第1章 k8s系统架构
从系统架构来看,k8s分为2个节点
Master 控制节点 指挥官
Node 工作节点 干活的
1.Master节点组成
API Server :提供k8s API接口
主要处理Rest操作以及更新Etcd中的对象
是所有资源增删改查的唯一入口。
Scheduler:资源调度器
根据etcd里的节点资源状态决定将Pod绑定到哪个Node上
Controller Manager
负责保障pod的健康存在
资源对象的自动化控制中心,Kubernetes集群有很多控制器。
Etcd
这个是Kubernetes集群的数据库
所有持久化的状态信息存储在Etcd中
kubectl
kubectl是管理k8s集群的客户端⼯具,管理员通过kubectl命令对API Server进⾏操作
API Server 响应并返回对应的命令结果,从⽽达到对 Kubernetes 集群的管理
2.Node节点的组成
容器运⾏时(Container Runtime)
容器运⾏时是负责容器运⾏的软件。
默认情况下,Kubernetes 使⽤ 容器运⾏时接⼝(Container Runtime Interface,CRI) 来与你所选择的容器运⾏时交互
如果同时检测到 Docker 和 containerd,则优先选择 Docker。 这是必然的,因为 Docker 18.09 附带了containerd 并且两者都是可以检测到的, 即使你仅安装了 Docker。 如果检测到其他两个或多个运⾏时,kubeadm 输出错误信息并退出
kubelet 通过内置的 dockershim CRI 实现与 Docker 集成。
Docker Engine
负责节点容器的管理工作,最终创建出来的是一个Docker容器。
kubelet
安装在Node上的代理服务,用来管理Pods以及容器/镜像/Volume等,实现对集群对节点的管理。
kube-proxy
安装在Node上的网络代理服务,提供网络代理以及负载均衡,实现与Service通讯。
第2章 k8s核心资源
从逻辑架构上看,k8s分为
Pod
Controller
Service
1.POD
POD是k8s的最小单位
POD的IP地址是随机的,删除POD会改变IP
POD都有一个根容器
一个POD内可以由一个或多个容器组成
一个POD内的容器共享根容器的网络命名空间
一个POD的内的网络地址由根容器提供
创建Pod流程图:
⽂字说明:
创建Pod的清单 --> API Server
API Server --> etcd
etcd --> API Server
kube-scheduler --> API Server --> etcd
etcd --> API server --> kubelet --> Docker
kubelet --> API Server --> etcd
管理员清单提交给了 APIServer
API Server 接收到请求后把资源清单信息存⼊到 etcd 数据库中
etcd 存好后更新状态给 API Server
API Server通过相应的接⼝更新事件
kube-scheduler 组件发现这个时候有⼀个 Pod 还没有绑定到节点上,就会对这个 Pod 进⾏⼀系列的调度,把它调度到⼀个最合适的节点上
然后把这个节点和 Pod 绑定到⼀起的信息告诉 API Server
API Server将调度消息更新到etcd⾥,etcd更新好后返回状态给API Server
节点上的 kubelet 组件这个时候 watch 到有⼀个 Pod 被分配过来了,就去把这个 Pod 的信息拉取下来,
然后根据描述通过容器运⾏时把容器创建出来,最后当然同样把 Pod 状态汇报给API Server 再写回到 etcd中去,这样就完成了⼀整个的创建流程。
容器运⾏状态:
Waiting(等待)
如果容器并不处在Running或Terminated状态之⼀,它就处在Waiting状态。 处于Waiting状态的容器仍在运⾏它完成启动所需要的操作:例如,从某个容器镜像 仓库拉取容器镜像,或者向容器应⽤数据等等。 当你使⽤kubectl 来查询包含 Waiting状态的容器的 Pod 时,你也会看到⼀个 Reason 字段,其中给出了容器处于等待状态的原因。
Running(运⾏中)
Running状态表明容器正在执⾏状态并且没有问题发⽣。
如果你使⽤ kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到 关于容器进⼊Running状态的信息。
Terminated(已终⽌)
处于Terminated状态的容器已经开始执⾏并且或者正常结束或者因为某些原因失败。 如果你使⽤kubectl来查询包含Terminated状态的容器的 Pod 时,你会看到 容器进⼊此状态的原因、退出代码以及容器执⾏期间的起⽌时间。
2.Label
label标签是kubernetes中⾮常重要的⼀个属性,label标签就像身份证⼀样,可以⽤来识别k8s的对象。
我们在传统架构⾥不同组件之间查找都是通过IP地址,但是在k8s⾥,很多的匹配关系都是通过标签来查找的。
3.Namespace
Namespace(命令空间)是k8s⾥另⼀个⾮常重要的概念,Namespace通过将集群内部的资源对象划分为不同的。Namespace⾥,形成逻辑上的不同项⽬组或⽤户组。
常⻅的pod,service,Deployment等资源如果没有指定命令空间,则默认创建在名为default的默认命名空间。
4.Controller
用来管理POD,控制器的种类有很多
- RC Replication Controller 控制POD有多个副本
- RS ReplicaSet RC控制的升级版
- Deployment 推荐使用,功能更强大,包含了RS控制器
- DaemonSet 保证所有的Node上有且只有一个Pod在运行
- StatefulSet 有状态的应用,为Pod提供唯一的标识,它可以保证部署和scale的顺序
5.Service
Service服务也是k8s的核⼼资源之⼀,Service定义了服务的⼊⼝地址,⽤来将后端的Pod服务暴露给外部⽤户访问。
我们知道Pod会随时被销毁和创建,⽽新创的Pod的IP地址并不是固定的,那么Service资源是如何找到后⾯不确定IP的Pod呢?
为了解决这个问题,k8s在PodIP之上⼜设计了⼀层IP,名为ClusterIP,这个ClusterIP在创建后就不会再变化,除⾮被删除重新创建。
通过这样的设计,我们只需要创建Cluster类型的Service资源,再通过标签和后端的Pod绑定在⼀起,这样只要访问ClusterIP就可以将请求转发到了后端的Pod,⽽且如果后端有多个Pod,ClusterIP还会将流量⾃动负载均衡到后⾯的Pod
通过ClusterIP我们可以访问对应的Pod,但是这个ClusterIP是⼀个虚拟IP,只能在k8s集群内部使⽤。外部⽤户是访问不到的,那么我们如何让外⾯的⽤户也可以访问到我们的服务呢?
我们的k8s运⾏在物理服务器上,那么必然会有物理⽹卡和真实的IP地址,也就是说所有k8s集群之外的节点想访问k8s集群内的某个节点,都必须通过物理⽹卡和IP
所以我们可以通过将物理⽹卡的IP地址的端⼝和Cluster做端⼝映射来实现外部流量对内部Pod的访问。
这种IP在k8s⾥称为NodeIP,暴露的端⼝称为NodePort。
#总结
NodeIP 对外提供用户访问
CluterIP 集群内部IP,可以动态感知后面的POD IP
POD IP POD的IP
Service三种⽹络图:
Service和Pod和RS的关系:
第3章 k8s实验环境准备
1.配置信息
主机名 IP地址 推荐配置 勉强配置
master 10.0.0.10 1C4G40G 1C2G
node1 10.0.0.11 1C2G40G 1C1G
node2 10.0.0.12 1C2G40G 1C1G
----------------------------------------
初始化操作:
干净环境
配置主机名
配置host解析
关闭防火墙
关闭SELinux
配置时间同步
更新好阿里源
确保网络通畅
关闭SWAP分区
2.系统环境准备
配置主机名
主机名 IP地址
master 10.0.0.10
node1 10.0.0.11
node2 10.0.0.12
3.配置host解析
cat >> /etc/hosts << EOF
10.0.0.10 master
10.0.0.11 node1
10.0.0.12 node2
EOF
4.关闭防火墙
systemctl stop firewalld NetworkManager
systemctl disable firewalld NetworkManager
5.关闭SELinux
setenforce 0
sed -i 's#SELINUX=disabled#SELINUX=disabled#g' /etc/selinux/config
getenforce
6.更新好阿里源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sed -i '/aliyuncs/d' /etc/yum.repos.d/*.repo
7.确保网络通畅
ping -c 1 www.baidu.com
ping -c 1 master
ping -c 1 node1
ping -c 1 node2
8.配置时间同步
yum install chrony -y
systemctl start chronyd
systemctl enable chronyd
date
9.关闭SWAP分区
swapoff -a
sed -i '/swap/d' /etc/fstab
free -h
第4章安装部署kubeadm
k8s安装部署⽅式
k8s的安装⽅式有很多种,常⻅的安装⽅式主要有以下⼏种:
1.⼆进制安装 ⽣产推荐
2.kubeadm安装 学习和实验
3.⽹友写的ansible⼆进制安装 ⾮常⽜叉
4.第三⽅安装⼯具⽐如rancher
5.云服务的k8s ⽐如阿⾥云的ACK
这⾥我们应该把学习使⽤k8s作为⾸要任务,所以先选择安装最简单的kubeadm来部署⼀套k8s集群。
0.kubeadm介绍
kubeadm是google推出的⼀种部署k8s集群的套件,他将k8s的组件打包封装成了容器,然后通过kubeadm进⾏集群的初始化。
kubeadm的好处是安装部署⽅便,缺点是不容易看到每个组件的配置,出了问题不好排查。但是我们现在的重点是学习k8s的使⽤,所以这些优先选择简单的安装⽅式,最后会介绍⼆进制安装部署。
1.安装指定版本的docker
注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!!
1.配置阿里源
cd /etc/yum.repos.d/
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
2.下载指定版本的docker
#yum list docker-ce --showduplicates
yum -y install docker-ce-19.03.15 docker-ce-cli-19.03.15
3.配置docker镜像加速
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://ig2l319y.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
4.启动
systemctl enable docker && systemctl start docker
5.检查版本
docker -v
2.部署kubeadm和kubelet
注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!!
1.设置k8s禁止使用swap
cat > /etc/sysconfig/kubelet<<EOF
KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
EOF
2.设置内核参数
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
3.设置k8s国内yum仓库
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
4.安装kubeadm
#yum list kubeadm --showduplicates
yum install -y kubelet-1.19.3 kubeadm-1.19.3 kubectl-1.19.3 ipvsadm
5.设置kubelet开机启动
systemctl enable kubelet
6.加载IPVS模块
cat >/etc/sysconfig/modules/ipvs.modules<<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
chmod +x /etc/sysconfig/modules/ipvs.modules
source /etc/sysconfig/modules/ipvs.modules
lsmod | grep -e ip_vs -e nf_conntrack_ipv
3.初始化集群部署Master
0.安装规划
节点规划
master master节点 API Server,controlle,scheduler,kube-proxy,kubelet,etcd
node1 node节点 Dokcer kubelet kube-proxy
node2 node节点 Dokcer kubelet kube-proxy
IP规划
POD IP 10.2.0.0
Cluster IP 10.1.0.0
Node IP 10.0.0.0
1.初始化命令
注意!只在master节点运行!!!--主节点 注意!只在master节点运行!!!--主节点 注意!只在master节点运行!!!--主节点
官网地址:
https://v1-16.docs.kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/
初始化命令:
kubeadm init \
--apiserver-advertise-address=10.0.0.10 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.19.3 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.2.0.0/16 \
--service-dns-domain=cluster.local \
--ignore-preflight-errors=Swap \
--ignore-preflight-errors=NumCPU
执行完成后会有输出,这是node节点加入k8s集群的命令
kubeadm join 10.0.0.10:6443 --token fsteby.4pz9czptzvxhzrg2 \
--discovery-token-ca-cert-hash sha256:8466da60f808479cf39c78fbbfc7c80b397ac95ed23164253abe05a9c8c619b4
2.为kubectl准备kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
3.获取node节点信息
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady master 2m37s v1.19.3
4.支持命令补全
yum install bash-completion -y
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
kubectl completion bash >/etc/bash_completion.d/kubectl
5.设置kube-proxy使用ipvs模式
执行命令,然后将mode: ""修改为mode: "ipvs"然后保存退出
kubectl edit cm kube-proxy -n kube-system
重启kube-proxy
kubectl -n kube-system get pod|grep kube-proxy|awk '{print "kubectl -n kube-system delete pod "$1}'|bash
查看pod信息
kubectl get -n kube-system pod|grep "kube-proxy"
检查日志,如果出现IPVS rr就表示成功
[root@master ~]kubectl -n kube-system logs -f kube-proxy-7cdbn
I0225 08:03:57.736191 1 node.go:135] Successfully retrieved node IP: 10.0.0.10
I0225 08:03:57.736249 1 server_others.go:176] Using ipvs Proxier.
W0225 08:03:57.736841 1 proxier.go:420] IPVS scheduler not specified, use rr by default
检查IPVS规则
[root@master ~]ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.1.0.1:443 rr
-> 10.0.0.10:6443 Masq 1 0 0
TCP 10.1.0.10:53 rr
TCP 10.1.0.10:9153 rr
UDP 10.1.0.10:53 rr
4.部署网络插件
注意!只在master节点上安装部署!!! 注意!只在master节点上安装部署!!! 注意!只在master节点上安装部署!!!
1.部署Flannel网络插件3
git clone --depth 1 https://github.com/coreos/flannel.git
2.修改资源配置清单
cd flannel/Documentation/
vim kube-flannel.yml
egrep -n "10.2.0.0|mirror|eth0" kube-flannel.yml
128: "Network": "10.2.0.0/16",
189: - --iface=eth0
3.应用资源配置清单
kubectl create -f kube-flannel.yml
4.检查pod运行状态,等一会应该全是running
[root@master ~]kubectl -n kube-system get pod
NAME READY STATUS RESTARTS AGE
coredns-6d56c8448f-ckwhg 1/1 Running 0 6m43s
coredns-6d56c8448f-rvmdf 1/1 Running 0 6m43s
etcd-master 1/1 Running 0 6m55s
kube-apiserver-master 1/1 Running 0 6m55s
kube-controller-manager-master 1/1 Running 0 6m55s
kube-flannel-ds-gzmxp 1/1 Running 0 15s
kube-flannel-ds-q4xtg 1/1 Running 0 2m42s
kube-flannel-ds-z6w27 1/1 Running 0 2m42s
kube-proxy-2zwxm 1/1 Running 0 4m15s
kube-proxy-9q8n6 1/1 Running 0 4m23s
kube-proxy-w295q 1/1 Running 0 4m25s
kube-scheduler-master 1/1 Running 0 6m55s
5.部署Node节点
1.master节点输出增加节点的命令
kubeadm token create --print-join-command
2.node节点执行加入集群命令
kubeadm join 10.0.0.10:6443 --token uqf018.mia8v3i1zcai19sj --discovery-token-ca-cert-hash sha256:e7d36e1fb53e59b12f0193f4733edb465d924321bcfc055f801cf1ea59d90aae
3.在master节点上查看状态
kubectl get nodes
4.给节点打标签
[root@master ~]kubectl label nodes node1 node-role.kubernetes.io/node=
[root@master ~]kubectl label nodes node2 node-role.kubernetes.io/node=
5.再次查看节点状态
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 171m v1.19.3
node1 Ready node 27m v1.19.3
node2 Ready node 27m v1.19.3