作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.K8S集群部署之各节点环境准备
1.虚拟机操作系统环境准备
参考链接:
https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
2.关闭swap分区
1. 临时关闭
swapoff -a && sysctl -w vm.swappiness=0
2 基于配置文件关闭
sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
3.确保硬件设备会拥有唯一的地址
[root@master241 ~]# ifconfig ens33 | grep ether | awk '{print $2}'
00:0c:29:8b:5d:15
[root@master241 ~]# cat /sys/class/dmi/id/product_uuid
cfd44d56-7951-e670-48e0-bead0c8b5d15
[root@master241 ~]#
[root@worker242 ~]# ifconfig ens33 | grep ether | awk '{print $2}'
00:0c:29:61:a1:78
[root@worker242 ~]# cat /sys/class/dmi/id/product_uuid
d8404d56-9099-eb9b-f0de-d3772361a178
[root@worker242 ~]#
[root@worker243 ~]# ifconfig ens33 | grep ether | awk '{print $2}'
00:0c:29:08:3c:1e
[root@worker243 ~]# cat /sys/class/dmi/id/product_uuid
30f14d56-fdea-adfa-2f4c-b274e5083c1e
[root@worker243 ~]#
温馨提示:
一般来讲,硬件设备会拥有唯一的地址,但是有些虚拟机的地址可能会重复。 因此要确保各个节点MAC地址或product_uuid唯一。
Kubernetes使用这些值来唯一确定集群中的节点。 如果这些值在每个节点上不唯一,可能会导致安装失败。
4.检查网络节点是否互通
简而言之,就是检查你的k8s集群各节点是否互通,可以使用ping命令来测试。
cat >> /etc/hosts <<EOF
10.0.0.241 master241
10.0.0.242 worker242
10.0.0.243 worker243
10.0.0.250 harbor.yinzhengjie.com
EOF
5.允许iptable检查桥接流量
1.创建配置文件
cat <<EOF | tee /etc/modules-load.d/k8s.conf
br_netfilter
bridge
EOF
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
2.临时生效,需要加载模块,所有节点均要操作
[root@master241 ~]# modprobe br_netfilter bridge
[root@master241 ~]#
[root@master241 ~]# lsmod | grep bridge
bridge 176128 1 br_netfilter
stp 16384 1 bridge
llc 16384 2 bridge,stp
[root@master241 ~]#
[root@master241 ~]# sysctl -f /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
[root@master241 ~]#
6.检查端口是否被占用
参考链接:
https://kubernetes.io/zh-cn/docs/reference/networking/ports-and-protocols/
7.禁用防火墙
systemctl disable --now ufw
温馨提示:
ubuntu的ufw类似于Centos的firewalld
8.禁用apparmor
systemctl disable --now apparmor
温馨提示:
ubuntu的apparmor类似于Centos的selinux
9.安装containerd服务
本教材并不打算采用docker作为容器运行时,而是使用containerd作为底层的容器运行时。
需要自行安装containerd,线下的VIP同学可以直接使用我写好的一键部署脚本即可。
线上的同学可以参考我之前整理的blog,里面也有具体的二进制部署教程,您也可以自行编写一键部署脚本。
参考链接:
https://www.cnblogs.com/yinzhengjie/p/18030527
温馨提示:
如果不修改cgroup的管理驱动为systemd,则默认值为cgroupfs,在初始化master节点时会失败哟!
二.K8S集群部署之所有节点安装kubeadm,kubelet,kubectl
1.软件包说明
你需要在每台机器上安装以下的软件包:
kubeadm:
用来初始化集群的指令。
kubelet:
在集群中的每个节点上用来启动Pod和容器等。
kubectl:
用来与集群通信的命令行工具。
kubeadm不能帮你安装或者管理kubelet或kubectl,所以你需要确保它们与通过kubeadm安装的控制平面(master)的版本相匹配。 如果不这样做,则存在发生版本偏差的风险,可能会导致一些预料之外的错误和问题。
然而,控制平面与kubelet间的相差一个次要版本不一致是支持的,但kubelet的版本不可以超过"API SERVER"的版本。 例如,1.7.0版本的kubelet可以完全兼容1.8.0版本的"API SERVER",反之则不可以。
2.配置软件源
新版kubernetes源使用方法和之前有一定区别,请求按照如下配置方法配置使用。
其中新版kubernetes源按照安装版本区分不同仓库,该文档示例为配置1.24版本,如需其他版本请在对应位置字符串替换即可。
比如需要安装1.29版本,则需要将如下配置中的v1.24替换成v1.29。目前该源支持v1.24 - v1.29版本,后续版本会持续更新。
实操案例
1.更新"apt"包索引并安装使用Kubernetes apt仓库所需要的包
apt-get update && apt-get install -y apt-transport-https ca-certificates curl gpg
2.下载用于 Kubernetes 软件包仓库的公共签名密钥。所有仓库都使用相同的签名密钥,因此你可以忽略URL中的版本
mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.24/deb/Release.key |
gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
3.添加Kubernetes apt仓库
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.24/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
3.查看kubeadm的版本
1.更新apt包索引
[root@master241 ~]# apt-get update
2.查看支持的kubeadm版本号
[root@master241 ~]# apt-cache madison kubeadm | awk '{ print $3 }'
1.24.17-1.1
1.24.16-1.1
1.24.15-1.1
1.24.14-1.1
1.24.13-1.1
1.24.12-1.1
1.24.11-1.1
1.24.10-1.1
1.24.9-1.1
1.24.8-1.1
1.24.7-1.1
1.24.6-1.1
1.24.5-1.1
1.24.4-1.1
1.24.3-1.1
1.24.2-1.1
1.24.1-1.1
1.24.0-2.1
[root@master241 ~]#
温馨提示:
将来你要安装的K8S时请所有组件版本均保持一致!
4 安装kubeadm,kubelet,kubectl软件包
1.安装 kubelet、kubeadm 和 kubectl
apt-get -y install kubelet=1.24.17-1.1 kubeadm=1.24.17-1.1 kubectl=1.24.17-1.1
2.查看安装的版本
[root@master241 ~]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.17", GitCommit:"22a9682c8fe855c321be75c5faacde343f909b04", GitTreeState:"clean", BuildDate:"2023-08-23T23:43:11Z", GoVersion:"go1.20.7", Compiler:"gc", Platform:"linux/amd64"}
[root@master241 ~]#
[root@master241 ~]# kubelet --version
Kubernetes v1.24.17
[root@master241 ~]#
3.锁定其版本
apt-mark hold kubelet kubeadm kubectl
温馨提示:
kubelet现在每隔几秒就会重启,因为它陷入了一个等待kubeadm指令的死循环。
参考链接:
https://kubernetes.io/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl
三.K8S集群部署之初始化master节点
1.使用kubeadm初始化master节点
1.初始化master节点
[root@master241 ~]# kubeadm init --kubernetes-version=v1.24.17 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.100.0.0/16 --service-cidr=10.200.0.0/16 --service-dns-domain=yinzhengjie.com
相关参数说明:
--kubernetes-version:
指定K8S master组件的版本号。
--image-repository:
指定下载k8s master组件的镜像仓库地址。
--pod-network-cidr:
指定Pod的网段地址。
--service-cidr:
指定SVC的网段
--service-dns-domain:
指定service的域名。若不指定,默认为"cluster.local"。
使用kubeadm初始化集群时,可能会出现如下的输出信息:
[init]
使用初始化的K8S版本。
[preflight]
主要是做安装K8S集群的前置工作,比如下载镜像,这个时间取决于你的网速。
[certs]
生成证书文件,默认存储在"/etc/kubernetes/pki"目录哟。
[kubeconfig]
生成K8S集群的默认配置文件,默认存储在"/etc/kubernetes"目录哟。
[kubelet-start]
启动kubelet,
环境变量默认写入:"/var/lib/kubelet/kubeadm-flags.env"
配置文件默认写入:"/var/lib/kubelet/config.yaml"
[control-plane]
使用静态的目录,默认的资源清单存放在:"/etc/kubernetes/manifests"。
此过程会创建静态Pod,包括"kube-apiserver","kube-controller-manager"和"kube-scheduler"
[etcd]
创建etcd的静态Pod,默认的资源清单存放在:""/etc/kubernetes/manifests"
[wait-control-plane]
等待kubelet从资源清单目录"/etc/kubernetes/manifests"启动静态Pod。
[apiclient]
等待所有的master组件正常运行。
[upload-config]
创建名为"kubeadm-config"的ConfigMap在"kube-system"名称空间中。
[kubelet]
创建名为"kubelet-config-1.22"的ConfigMap在"kube-system"名称空间中,其中包含集群中kubelet的配置
[upload-certs]
跳过此节点,详情请参考”--upload-certs"
[mark-control-plane]
标记控制面板,包括打标签和污点,目的是为了标记master节点。
[bootstrap-token]
创建token口令,例如:"kbkgsa.fc97518diw8bdqid"。
如下图所示,这个口令将来在加入集群节点时很有用,而且对于RBAC控制也很有用处哟。
[kubelet-finalize]
更新kubelet的证书文件信息
[addons]
添加附加组件,例如:"CoreDNS"和"kube-proxy”
2.拷贝kubeconfig文件到家目录
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
温馨提示:
1.也可以添加环境变量"export KUBECONFIG=/etc/kubernetes/admin.conf";
2.后续课程我们也会讲到自定义用户及授权相关的内容哟;
3.查看集群节点
[root@master241 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health":"true","reason":""}
[root@master241 ~]#
[root@master241 ~]#
[root@master241 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master241 NotReady control-plane 10m v1.24.17
[root@master241 ~]#
四.K8S集群部署之配置worker节点加入集群
1.worker节点加入集群
[root@worker242 ~]# kubeadm join 10.0.0.241:6443 --token eapq0k.erthrm6oksihzd9h --discovery-token-ca-cert-hash sha256:5357c608da3b5ea26e4162725eff17989ac6590dca8356eb6107ad3bd430a319
[root@worker243 ~]# kubeadm join 10.0.0.241:6443 --token eapq0k.erthrm6oksihzd9h --discovery-token-ca-cert-hash sha256:5357c608da3b5ea26e4162725eff17989ac6590dca8356eb6107ad3bd430a319
温馨提示:
注意,你的环境和我的不一样,需要拷贝你上一步产生的输出信息。
2.查看集群现有的worker节点
[root@master241 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master241 NotReady control-plane 13m v1.24.17
worker242 NotReady <none> 42s v1.24.17
worker243 NotReady <none> 8s v1.24.17
[root@master241 ~]#
五.k8s部署CNI组件之flannel案例
1.下载flannel的资源清单
[root@master241 ~]# wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
2.修改flannel的资源清单配置文件
[root@master241 ~]# vim kube-flannel.yml
[root@master241 ~]#
[root@master241 ~]# grep 16 kube-flannel.yml
"Network": "10.100.0.0/16",
[root@master241 ~]#
温馨提示:
修改和咱们Pod网络相同的网段即可。
3.部署flannel组件
[root@master241 ~]# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
[root@master241 ~]#
4.查看是否部署成功
[root@master241 ~]# kubectl get pods -o wide -n kube-flannel
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-5gsst 1/1 Running 0 115s 10.0.0.243 worker243 <none> <none>
kube-flannel-ds-mwpj6 1/1 Running 0 115s 10.0.0.241 master241 <none> <none>
kube-flannel-ds-zfftm 1/1 Running 0 115s 10.0.0.242 worker242 <none> <none>
[root@master241 ~]#
5.查看集群的信息
[root@master241 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master241 Ready control-plane 68m v1.24.17
worker242 Ready <none> 55m v1.24.17
worker243 Ready <none> 55m v1.24.17
[root@master241 ~]#
6.校验网络插件是否部署成功
[root@master241 ~]# cat deploy-apps.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: oldboyedu-app01
spec:
replicas: 1
selector:
matchLabels:
apps: v1
template:
metadata:
labels:
apps: v1
spec:
nodeName: worker242
containers:
- name: c1
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: oldboyedu-app02
spec:
replicas: 1
selector:
matchLabels:
apps: v2
template:
metadata:
labels:
apps: v2
spec:
nodeName: worker243
containers:
- name: c2
image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
[root@master241 ~]#
[root@master241 ~]# kubectl apply -f deploy-apps.yaml
deployment.apps/oldboyedu-app01 created
deployment.apps/oldboyedu-app02 created
[root@master241 ~]#
7.访问测试Pod
[root@master241 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
oldboyedu-app01-67fcb64b-pj75r 1/1 Running 0 40s 10.100.1.2 worker242 <none> <none>
oldboyedu-app02-546c76bbd4-ws2wt 1/1 Running 0 40s 10.100.2.2 worker243 <none> <none>
[root@master241 ~]#
[root@master241 ~]# curl 10.100.1.2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>yinzhengjie apps v1</title>
<style>
div img {
width: 900px;
height: 600px;
margin: 0;
}
</style>
</head>
<body>
<h1 style="color: green">凡人修仙传 v1 </h1>
<div>
<img src="1.jpg">
<div>
</body>
</html>
[root@master241 ~]#
[root@master241 ~]# curl 10.100.2.2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>yinzhengjie apps v2</title>
<style>
div img {
width: 900px;
height: 600px;
margin: 0;
}
</style>
</head>
<body>
<h1 style="color: red">凡人修仙传 v2 </h1>
<div>
<img src="2.jpg">
<div>
</body>
</html>
[root@master241 ~]#
8.删除资源
[root@master241 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
oldboyedu-app01-67fcb64b-pj75r 1/1 Running 0 5m17s 10.100.1.2 worker242 <none> <none>
oldboyedu-app02-546c76bbd4-ws2wt 1/1 Running 0 5m17s 10.100.2.2 worker243 <none> <none>
[root@master241 ~]#
[root@master241 ~]# kubectl delete -f deploy-apps.yaml
deployment.apps "oldboyedu-app01" deleted
deployment.apps "oldboyedu-app02" deleted
[root@master241 ~]#
[root@master241 ~]# kubectl get pods -o wide
No resources found in default namespace.
[root@master241 ~]#
六.K8S新手注意事项
1.配置自动补全功能
apt -y install bash-completion
kubectl completion bash > ~/.kube/completion.bash.inc
echo "source '$HOME/.kube/completion.bash.inc'" >> $HOME/.bash_profile
source $HOME/.bash_profile
2.集群搭建完毕后拍快照
一定要拍快照,一定要拍快照,一定要拍快照,重要的事情说三遍。
拍快照的目的是为了避免同学们上课不小心把K8S环境搞崩了,便与你恢复到K8S集群搭建完毕的状态。
七.可能会遇到的报错
1. /proc/sys/net/bridge/bridge-nf-call-iptables does not exist
问题原因:
没有加载"br_netfilter"和"bridge"模块。
解决方案:
[root@master241 ~]# modprobe br_netfilter bridge
[root@master241 ~]#
[root@master241 ~]# lsmod | grep bridge
bridge 176128 1 br_netfilter
stp 16384 1 bridge
llc 16384 2 bridge,stp
[root@master241 ~]#
[root@master241 ~]# sysctl -f /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
[root@master241 ~]#
2.The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
问题原因:
很明显,这个报错是由于被禁用了"cgroups"导致的报错哟。
解决方案:(请确保"SystemdCgroup"是被启用的)
[root@master241 ~]# grep SystemdCgroup /etc/containerd/config.toml
SystemdCgroup = true
[root@master241 ~]#
温馨提示:
参考我的blog或者我给大家的脚本来安装containerd就已经避免了这个问题了哟~
3.Failed to create pod sandbox: rpc error: code = Unknown desc = failed to create containerd task: failed to start shim: exec: "containerd-shim": executable file not found in $PATH: unknown
问题原因:
如上图所示,kubelet调用containerd创建容器时会用到"containerd-shim"工具,因此我们需要确保你的主机上是有这个命令的。
如下图所示,如果有containerd-shim相关的工具,但名称不一致,只需要创建一个软连接即可。
解决方案:
[root@worker242 ~]# which containerd-shim
[root@worker242 ~]#
[root@worker242 ~]# ln -svf /usr/bin/containerd-shim-runc-v2 /usr/bin/containerd-shim
'/usr/bin/containerd-shim' -> '/usr/bin/containerd-shim-runc-v2'
[root@worker242 ~]#
[root@worker242 ~]# which containerd-shim
/usr/bin/containerd-shim
[root@worker242 ~]#
[root@worker242 ~]# ll /usr/bin/containerd-shim
lrwxrwxrwx 1 root root 32 Mar 9 17:37 /usr/bin/containerd-shim -> /usr/bin/containerd-shim-runc-v2*
[root@worker242 ~]#
4.Failed to create pod sandbox: rpc error: code = Unknown desc = failed to create containerd task: ttrpc: closed: unknown
问题原因:
sandbox为基础架构的容器镜像,或者是缺少ttrpc的相关配置。
解决方案:
重新生成containerd相关的配置并重启服务测试。
5.Error: failed to run Kubelet: running with swap on is not supported, please disable swap! or...
问题原因:
没禁用swap分区,导致kubelet无法正常启动。
这个问题不太好发觉,尤其是在刚刚搭建集群的时候,重启K8S后发现你的swap分区没有禁用导致kubelet无法正常启动。
解决方案:
禁用swap分区,或者是启动kubelet时忽略swap的警告信息,这要求你的K8S版本必须大于1.22才支持,目前也属于测试版。
生产环境中还是建议大家禁用swap分区,因为会影响其使用的性能。
[root@master241 ~]# swapoff -a
[root@master241 ~]#
[root@master241 ~]# free -h
total used free shared buff/cache available
Mem: 3.8Gi 339Mi 2.7Gi 1.0Mi 798Mi 3.2Gi
Swap: 0B 0B 0B
[root@master241 ~]#
[root@master241 ~]# sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab
[root@master241 ~]#