主机IP | 主机名称 | 角色 |
---|---|---|
192.168.32.200 | k8s-master01.org | master |
192.168.32.203 | k8s-node01.org | node01 |
192.168.32.204 | k8s-node02.org | node02 |
192.168.32.205 | k8s-node03.org | node03 |
# 修改192.168.32.200的主机名称为k8s-master01.org
# 修改192.168.32.203的主机名称为k8s-node01.org
# 修改192.168.32.204的主机名称为k8s-node02.org
# 修改192.168.32.205的主机名称为k8s-node03.org
在所有主机上安装 chrony
# 所有主机上执行
root@k8s-master01:~# apt install -y chrony
建议用户配置使用本地的的时间服务器,在节点数量众多时尤其如此。存在可用的本地时间服务器时,修改节点的/etc/chrony/chrony.conf配置文件,并将时间服务器指向相应的主机即可,配置格式如下:
server CHRONY-SERVER-NAME-OR-IP iburst
出于简化配置步骤的目的,本测试环境使用hosts文件进行各节点名称解析,文件内容如下所示。其中,我们使用kubeapi主机名作为API Server在高可用环境中的专用接入名称,也为控制平面的高可用配置留下便于配置的余地。
# 编辑/etc/hosts文件加入如下内容
root@k8s-master01:~# vim /etc/hosts
192.168.32.200 k8s-master01.org
192.168.32.203 k8s-node01.org
192.168.32.204 k8s-node02.org
192.168.32.205 k8s-node03.org
部署集群时,kubeadm默认会预先检查当前主机是否禁用了Swap设备,并在未禁用时强制终止部署过程。因此,在主机内存资源充裕的条件下,需要禁用所有的Swap设备,否则,就需要在后文的kubeadm init及kubeadm join命令执行时额外使用相关的选项忽略检查错误。
关闭Swap设备,需要分两步完成。首先是关闭当前已启用的所有Swap设备:
# 临时关闭,所有机器执行
root@k8s-master01:~# swapoff -a
而后编辑/etc/fstab配置文件,注释用于挂载Swap设备的所有行
# 所有机器执行
root@k8s-master01:~#vim /etc/fstab
# 注释如下一行
#/swap.img none swap sw 0 0
Ubuntu和Debian等Linux发行版默认使用ufw(Uncomplicated FireWall)作为前端来简化 iptables的使用,处于启用状态时,它默认会生成一些规则以加强系统安全。出于降低配置复杂度之目的,本文选择直接将其禁用。
root@k8s-master01:~# ufw disable
Firewall stopped and disabled on system startup
root@k8s-master01:~# ufw status
Status: inactive
root@k8s-master01:~#
提示:以下操作需要在本示例中的所有四台主机上分别进行。
首先,生成docker-ce相关程序包的仓库,这里以阿里云的镜像服务器为例进行说明:
docker-ce镜像_docker-ce下载地址_docker-ce安装教程-阿里巴巴开源镜像站 (aliyun.com)
# step 1: 安装必要的一些系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# step 2: 安装GPG证书
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# Step 3: 写入软件源信息
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# Step 4: 更新并安装Docker-CE
sudo apt-get -y update
sudo apt-get -y install docker-ce
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# apt-cache madison docker-ce
# docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
# Step 2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.1~ce-0~ubuntu-xenial)
# sudo apt-get -y install docker-ce=[VERSION]
本文以为20.10.10版本为例
root@k8s-node3:~# apt install docker-ce=5:20.10.10~3-0~ubuntu-focal docker-ce-cli=5:20.10.10~3-0~ubuntu-focal
kubelet需要让docker容器引擎使用systemd作为CGroup的驱动,其默认值为cgroupfs,因而,我们还需要编辑docker的配置文件/etc/docker/daemon.json,添加如下内容,其中的registry-mirrors用于指明使用的镜像加速服务。
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://ung2thfc.mirror.aliyuncs.com",
"https://mirror.ccs.tencentyun.com",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
systemctl daemon-reload && systemctl restart docker
Kubernetes自v1.24移除了对docker-shim的支持,而Docker Engine默认又不支持CRI规范,因而二者将无法直接完成整合。为此,Mirantis和Docker联合创建了cri-dockerd项目,用于为Docker Engine提供一个能够支持到CRI规范的垫片,从而能够让Kubernetes基于CRI控制Docker 。
项目地址:https://github.com/Mirantis/cri-dockerd
cri-dockerd项目提供了预制的二进制格式的程序包,用户按需下载相应的系统和对应平台的版本即可完成安装,这里以Ubuntu 2004 64bits系统环境,以及cri-dockerd目前最新的程序版本v0.3.0为例。
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.0/cri-dockerd_0.3.0.3-0.ubuntu-focal_amd64.deb
dpkg -i cri-dockerd_0.3.0.3-0.ubuntu-focal_amd64.deb
完成安装后,相应的服务cri-dockerd.service便会自动启动。我们也可以使用如下命令进行验证,若服务处于Running状态即可进行后续步骤 。
root@k8s-master01:~# systemctl status cri-docker.service
● cri-docker.service - CRI Interface for Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/cri-docker.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-03-21 10:59:57 CST; 1min 20s ago
TriggeredBy: ● cri-docker.socket
Docs: https://docs.mirantis.com
Main PID: 17591 (cri-dockerd)
Tasks: 7
Memory: 11.9M
CGroup: /system.slice/cri-docker.service
└─17591 /usr/bin/cri-dockerd --container-runtime-endpoint fd://
Mar 21 10:59:57 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Start docker client with request timeout 0s"
Mar 21 10:59:57 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Hairpin mode is set to none"
Mar 21 10:59:57 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Loaded network plugin cni"
Mar 21 10:59:57 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Docker cri networking managed by network plugin cni"
Mar 21 10:59:57 k8s-master01.org systemd[1]: Started CRI Interface for Docker Application Container Engine.
Mar 21 10:59:58 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Docker Info: &{ID:WQBA:P7R2:H6ZI:KWU3:FVFW:MHLC:QTT7:CJCX>
Mar 21 10:59:58 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Setting cgroupDriver cgroupfs"
Mar 21 10:59:58 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Docker cri received runtime config &RuntimeConfig{Network>
Mar 21 10:59:58 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Starting the GRPC backend for the Docker CRI interface."
Mar 21 10:59:58 k8s-master01.org cri-dockerd[17591]: time="2023-03-21T10:59:57+08:00" level=info msg="Start cri-dockerd grpc backend"
lines 1-21/21 (END)
首先,在各主机上生成kubelet和kubeadm等相关程序包的仓库,这里以阿里云的镜像服务为例:
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat </etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
安装完成后,要确保kubeadm等程序文件的版本,这将也是后面初始化Kubernetes集群时需要明确指定的版本号。
仅支持CRI规范的kubelet需要经由遵循该规范的cri-dockerd完成与docker-ce的整合。
配置cri-dockerd,确保其能够正确加载到CNI插件。编辑/usr/lib/systemd/system/cri-docker.service文件,确保其[Service]配置段中的ExecStart的值类似如下内容。
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.7 --cni-bin-dir=/opt/cni/bin --cni-cache-dir=/var/lib/cni/cache --cni-conf-dir=/etc/cni/net.d
需要添加的各配置参数(各参数的值要与系统部署的CNI插件的实际路径相对应):
配置完成后,重载并重启cri-docker.service服务。
root@k8s-master01:~# systemctl daemon-reload;systemctl restart cri-docker
配置kubelet,为其指定cri-dockerd在本地打开的Unix Sock文件的路径,该路径一般默认为“/run/cri-dockerd.sock“。编辑文件/etc/sysconfig/kubelet,为其添加 如下指定参数。
提示:若/etc/sysconfig目录不存在,则需要先创建该目录。
KUBELET_KUBEADM_ARGS="--container-runtime=remote --container-runtime-endpoint=/run/cri-dockerd.sock"
需要说明的是,该配置也可不进行,而是直接在后面的各kubeadm命令上使用“–cri-socket unix:///run/cri-dockerd.sock”选项。
该步骤开始尝试构建Kubernetes集群的master节点,配置完成后,各worker节点直接加入到集群中的即可。需要特别说明的是,由kubeadm部署的Kubernetes集群上,集群核心组件kube-apiserver、kube-controller-manager、kube-scheduler和etcd等均会以静态Pod的形式运行,它们所依赖的镜像文件默认来自于registry.k8s.io这一Registry服务之上。但我们无法直接访问该服务,常用的解决办法有如下两种
运行如下命令完成k8s-master01节点的初始化:
kubeadm init --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=v1.26.3 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 --token-ttl=0 --cri-socket unix:///run/cri-dockerd.sock
命令中的各选项简单说明如下:
对于Kubernetes系统的新用户来说,无论使用上述哪种方法,命令运行结束后,请记录最后的kubeadm join命令输出的最后提示的操作步骤。下面的内容是需要用户记录的一个命令输出示例,它提示了后续需要的操作步骤。
# 下面是成功完成第一个控制平面节点初始化的提示信息及后续需要完成的步骤
Your Kubernetes control-plane has initialized successfully!
# 为了完成初始化操作,管理员需要额外手动完成几个必要的步骤
To start using your cluster, you need to run the following as a regular user:
# 第1个步骤提示, Kubernetes集群管理员认证到Kubernetes集群时使用的kubeconfig配置文件
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 我们也可以不做上述设定,而使用环境变量KUBECONFIG为kubectl等指定默认使用的kubeconfig;
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
# 第2个步骤提示,为Kubernetes集群部署一个网络插件,具体选用的插件则取决于管理员;
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
# 第3个步骤提示,向集群添加额外的控制平面节点,但本文会略过该步骤,并将在其它文章介绍其实现方式。
You can now join any number of the control-plane node running the following command on each as root:
# 第4个步骤提示,向集群添加工作节点
Then you can join any number of worker nodes by running the following on each as root:
# 在部署好kubeadm等程序包的各工作节点上以root用户运行类似如下命令;
# 提示:与cri-dockerd结合使用docker-ce作为container runtime时,通常需要为下面的命令
# 额外附加“--cri-socket unix:///run/cri-dockerd.sock”选项;
kubeadm join 192.168.32.200:6443 --token ivu3t7.pogk70dd5pualoz2 \
--discovery-token-ca-cert-hash sha256:3edb3c8e3e6c944afe65b2616d46b49305c1420e6967c1fab966ddf8f149502d
kubectl是kube-apiserver的命令行客户端程序,实现了除系统部署之外的几乎全部的管理操作,是kubernetes管理员使用最多的命令之一。kubectl需经由API server认证及授权后方能执行相应的管理操作,kubeadm部署的集群为其生成了一个具有管理员权限的认证配置文件/etc/kubernetes/admin.conf,它可由kubectl通过默认的“$HOME/.kube/config”的路径进行加载。当然,用户也可在kubectl命令上使用–kubeconfig选项指定一个别的位置。
下面复制认证为Kubernetes系统管理员的配置文件至目标用户(例如当前用户root)的家目录下:
~# mkdir ~/.kube
~# cp /etc/kubernetes/admin.conf ~/.kube/config
Kubernetes系统上Pod网络的实现依赖于第三方插件进行,这类插件有近数十种之多,较为著名的有flannel、calico、canal和kube-router等,简单易用的实现是为CoreOS提供的flannel项目。下面的命令用于在线部署flannel至Kubernetes系统之上:
首先,下载适配系统及硬件平台环境的flanneld至每个节点,并放置于/opt/bin/目录下。我们这里选用flanneld-amd64,目前最新的版本为v0.21.3,因而,我们需要在集群的每个节点上执行如下命令:
~# mkdir /opt/cni/bin/
~# curl -L https://github.com/flannel-io/flannel/releases/download/v0.20.2/flanneld-amd64 -o /opt/cni/bin/flanneld
~# chmod +x /opt/cni/bin/flanneld
提示:下载flanneld的地址为 https://github.com/flannel-io/flannel/releases
随后,在初始化的第一个master节点k8s-master01上运行如下命令,向Kubernetes部署kube-flannel。
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.21.3/Documentation/kube-flannel.yml
而后使用如下命令确认其输出结果中Pod的状态为“Running”,类似如下命令及其输入的结果所示:
root@k8s-master01:~# kubectl get pods -n kube-flannel
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-jgkxd 1/1 Running 0 2m59s
root@k8s-master01:~#
kubectl get nodes
上述命令应该会得到类似如下输出,这表示k8s-master01节点已经就绪
root@k8s-master01:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master01.org Ready control-plane 62m v1.26.3
root@k8s-master01:~#
下面的两个步骤,需要分别在k8s-node01、k8s-node02和k8s-node03上各自完成。
1、若未禁用Swap设备,编辑kubelet的配置文件/etc/default/kubelet,设置其忽略Swap启用的状态错误,内容如下:KUBELET_EXTRA_ARGS=“–fail-swap-on=false”
2、将节点加入第二步中创建的master的集群中,要使用主节点初始化过程中记录的kubeadm join命令;
root@k8s-node01:/opt/cni/bin# kubeadm join 192.168.32.200:6443 --token ivu3t7.pogk70dd5pualoz2 --discovery-token-ca-cert-hash sha256:3edb3c8e3e6c944afe65b2616d46b49305c1420e6967c1fab966ddf8f149502d --cri-socket unix:///run/cri-dockerd.sock
在每个节点添加完成后,即可通过kubectl验证添加结果。下面的命令及其输出是在所有的三个节点均添加完成后运行的,其输出结果表明三个Worker Node已经准备就绪。
~# kubectl get nodes
root@k8s-master01:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master01.org Ready control-plane 80m v1.26.3
k8s-node01.org Ready 15m v1.26.3
k8s-node2.org Ready 114s v1.26.3
k8s-node3.org Ready 11m v1.26.3
root@k8s-master01:~#
到此为止,一个master,并附带有三个worker的kubernetes集群基础设施已经部署完成,用户随后即可测试其核心功能。
root@k8s-master01:~# kubectl create deployment test-nginx --image=nginx:latest --replicas=3
deployment.apps/test-nginx created
root@k8s-master01:~#
root@k8s-master01:~# kubectl create service nodeport test-nginx --tcp=80:80
service/test-nginx created
root@k8s-master01:~#
而后,使用如下命令了解Service对象test-nginx使用的NodePort,以便于在集群外部进行访问:
root@k8s-master01:~# kubectl get svc -l app=test-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test-nginx NodePort 10.100.229.239 80:31888/TCP 50s
root@k8s-master01:~#
因此,用户可以于集群外部通过“http://NodeIP:31888”这个URL访问web应用,例如于集群外通过浏览器访问“http://192.168.32.203:31888”。
本文给出了部署Kubernetes分布式集群的具体步骤,并在最后测试了将应用部署并运行于Kubernetes系统上的结果。在读者朋友们自行测试时,cri-dockerd、docker-ce、flannel、kubeadm、kubectl和kubelet的版本均可能存在版本上的不同,也因此可能会存在一定程度上的配置差异,具体调整方式请大家自行参考相关的文档进行。