Linux 安装 K8S 之 kubeadm

摘要

安装前设置(所有节点)

修正系统的时间

1
2
3
4
5
6
7
8
# 安装chrony
sudo dnf install chrony -y
# 启动服务
sudo systemctl enable --now chronyd
# 修正时间
sudo chronyc makestep
# 查看时间
date

安装 docker(可选)

  • k8s 使用docker作为容器运行时才需要安装,安装方法参见 Linux 安装 Docker

创建用户

  • 避免使用root用户,这里创建一个 centos 用户,要求该用户具有sudo权限,如果使用docker运行时,则需要将该用户添加到docker用户组

1
2
3
4
5
6
7
8
9
# 1.创建用户
$ sudo useradd -m -s /bin/bash centos
# 2.添加到docker用户组
$ sudo usermod -aG docker centos
# 3.将用户添加到 sudo(管理员)组,说明:wheel 是 CentOS 中允许使用 sudo 权限的用户组。具体可以通过 visudo 命令查看
$ sudo usermod -aG wheel centos
## 这种添加方式使用sudo时需要输入密码,如果不希望输入密码,可以通过 visudo 命令修改,将 wheel 组改为 %wheel ALL=(ALL) NOPASSWD: ALL 的形式
# 4.切换用户,以下操作均在该用户下进行
$ su - centos

升级内核

  • 由 kubeadm 创建的 Kubernetes 集群依赖于使用内核特性的相关软件。

  • Kubernetes 集群的节点对于使用 Linux 内核版本要求参加Linux 内核版本要求

  • kubeadm 项目支持 LTS 内核。参阅 LTS 内核列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 查看当前内核版本,可以看到当前内核版本为 4.18.0
$ uname -r
4.18.0-553.el8_10.x86_64
#查看 yum 中可升级的内核版本
$ sudo yum list kernel --showduplicates
#如果list中有需要的版本可以直接执行 update 升级,多数是没有的,所以要按以下步骤操作

#导入ELRepo软件仓库的公共秘钥
$ sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

#Centos7系统安装ELRepo
# $sudo yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
#Centos8系统安装ELRepo
$ sudo yum install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm

#查看ELRepo提供的内核版本
$ sudo yum --disablerepo="*" --enablerepo="elrepo-kernel" list available


#kernel-lt:表示longterm,即长期支持的内核,当前lt内核版本为 5.4.295
#kernel-ml:表示mainline,即当前主线的内核,当前ml内核版本为 6.15.4,笔者测试安装该版本内核最后创建集群时会失败
#安装lt内核
$ sudo yum --enablerepo=elrepo-kernel install kernel-lt.x86_64

# 查看已安装的内核版本,可以看到 刚刚安装的 5.4.295 内核版本的两个文件
$ ls -lh /boot/vmlinuz-* /boot/initramfs-* | grep "5.4"
-rw------- 1 root root 29M 6月 29 17:15 /boot/initramfs-5.4.295-1.el8.elrepo.x86_64.img
-rwxr-xr-x 1 root root 9.5M 6月 28 01:21 /boot/vmlinuz-5.4.295-1.el8.elrepo.x86_64

# 查看可以使用的内核
$ sudo grubby --info=ALL | grep ^kernel
kernel="/boot/vmlinuz-5.4.295-1.el8.elrepo.x86_64"
kernel="/boot/vmlinuz-4.18.0-553.el8_10.x86_64"
kernel="/boot/vmlinuz-0-rescue-88f75739047993488aacc30b9cd25ca0"


# 查看默认内核,默认情况下,系统会自动将新安装的内核设置为默认启动内核
$ sudo grubby --default-kernel
/boot/vmlinuz-5.4.295-1.el8.elrepo.x86_64

# 如果没有自动启用,则通过该命令设置默认内核
$ sudo grubby --set-default /boot/vmlinuz-5.4.295-1.el8.elrepo.x86_64

# 重启系统
$ sudo reboot

# 重启登录后验证内核版本
$ uname -r
5.4.295-1.el8.elrepo.x86_64

将 SELinux 设置为 permissive 模式(相当于将其禁用)

1
2
$ sudo setenforce 0
$ sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

禁用Firewalld

1
2
3
# 为了方便,这里可以禁用 firewalld
sudo systemctl stop firewalld
sudo systemctl disable firewalld

不关 Firewalld 应该开放哪些端口?(实测还是会遇到各种各样的问题)

  • Master 节点需要开放的端口

端口 协议 说明
6443 TCP kube-apiserver,用于 kubectl 与集群通信
2379-2380 TCP etcd 集群通信(仅在你自己部署 etcd 时)
10250 TCP kubelet 监听端口,供 apiserver 与节点通信
10259 TCP kube-scheduler
10257 TCP kube-controller-manager
  • Worker 节点需要开放的端口

端口 协议 说明
10250 TCP kubelet 与 apiserver 通信
30000-32767 TCP NodePort 服务默认端口范围
10255 TCP kubelet 只读端口(默认关闭,可不开放)
  • 如果你使用的是 Calico 网络插件

端口 协议 说明
179 TCP BGP 通信端口,用于 Calico 节点间路由(若使用 BGP 模式)
  • 如果你使用的是 Flannel(VXLAN 模式)

端口 协议 说明
8472 UDP VXLAN 数据通信
  • Ingress 控制器(比如 NGINX Ingress)

端口 协议 说明
80 / 443 TCP 提供 HTTP/HTTPS 服务访问(Ingress 服务)
  • 示例命令:使用 firewall-cmd 开放端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 启动 firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld

# 示例:开放常用端口
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --permanent --add-port=2379-2380/tcp
sudo firewall-cmd --permanent --add-port=10250/tcp
sudo firewall-cmd --permanent --add-port=10259/tcp
sudo firewall-cmd --permanent --add-port=10257/tcp
sudo firewall-cmd --permanent --add-port=30000-32767/tcp
sudo firewall-cmd --permanent --add-port=179/tcp # 如果用 Calico
sudo firewall-cmd --permanent --add-port=8472/udp # 如果用 Flannel
sudo firewall-cmd --permanent --add-port=80/tcp # Ingress
sudo firewall-cmd --permanent --add-port=443/tcp # Ingress

# 允许 Calico 的封装协议 IPIP ,允许 IPIP 协议(协议号 4)
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p 4 -j ACCEPT
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -p 4 -j ACCEPT

# 如果 Calico 使用 VXLAN 模式,则需要开放 4789 端口
sudo firewall-cmd --permanent --add-port=4789/udp
# Calico Typha 网络
sudo firewall-cmd --permanent --add-port=5473/tcp

# Calico WireGuard(IPv4 和 IPv6)
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --permanent --add-port=51821/udp

# 应用更改
sudo firewall-cmd --reload

# 查看开放的端口
$ sudo firewall-cmd --list-ports
80/tcp 179/tcp 443/tcp 2377/tcp 2379-2380/tcp 6443/tcp 7946/tcp 10250/tcp 10257/tcp 10259/tcp 30000-32767/tcp 4789/udp 7946/udp 8472/udp

# 查看开放的直接规则
$ sudo firewall-cmd --direct --get-all-rules
ipv4 filter INPUT 0 -p 4 -j ACCEPT

关闭swap

1
2
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

加载内核模块

1
2
sudo modprobe overlay
sudo modprobe br_netfilter

设置内核参数

1
2
3
4
5
6
7
cat <<EOF | sudo tee /etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

安装containerd

1
2
3
4
5
6
7
8
9
10
11
12
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y containerd.io

sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml

# 设置Systemd为cgroup driver
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# 启动并设置开机启动
sudo systemctl enable --now containerd

安装cri-dockerd(可选)

  • 如果使用 containerd,则不需要安装 cri-dockerd

  • Kubernetes 1.24+ 默认移除了 dockershim,所以你必须安装 cri-dockerd 才能继续使用 Docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 下载并安装 cri-dockerd RPM,目前最新版是 0.3.19,fc35: Fedora 35 构建,适配 RHEL/CentOS 8 系统的 glibc 和 libstdc++
$ curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.19/cri-dockerd-0.3.19-3.fc35.x86_64.rpm
# 安装时报错:cri-dockerd-0.3.19-3.fc35.x86_64.rpm 依赖 GLIBC ≥ 2.32 和 2.34,但 CentOS 8 系统只提供 GLIBC 2.28。
$ sudo dnf install -y ./cri-dockerd-0.3.19-3.fc35.x86_64.rpm

# 重新下载一个兼容的版本即可,这里选择:cri-dockerd-0.3.14-3.el8.x86_64.rpm
$ curl -LO https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.14/cri-dockerd-0.3.14-3.el8.x86_64.rpm
$ sudo dnf install -y ./cri-dockerd-0.3.14-3.el8.x86_64.rpm

# 重新加载服务
$ sudo systemctl daemon-reload
# 加入开机启动并立刻启动
$ sudo systemctl enable --now cri-docker

# 后面的 kubeadm 命令 都要加上 --cri-socket unix:///var/run/cri-dockerd.sock

安装 kubelet, kubeadm, kubectl

  • 添加 Kubernetes YUM 源,k8s 的版本从官网获取

1
2
3
4
5
6
7
8
9
10
11
12
$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key
EOF

# 清理yum缓存并重新建立缓存
$ sudo yum clean all && sudo yum makecache
  • 安装 kubelet, kubeadm, kubectl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查看kubeadm有什么版本
$ sudo yum list --showduplicates kubeadm
# 不指定版本默认那种最新版
$ sudo yum install -y kubelet kubeadm kubectl

# 启用kubelet
$ sudo systemctl enable --now kubelet

# 指定容器运行时为containerd,这里通过 crictl 指定容器运行时为 containerd
# 配置文件:/etc/crictl.yaml
$ sudo crictl config runtime-endpoint /run/containerd/containerd.sock

# 检查
$ kubeadm version
$ kubelet --version
$ kubectl version --client
  • 启用 shell 自动补全功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1.安装 bash-completion
# 1.1 检查bash-completion是否已安装,有输出说明已经安装
$ type _init_completion
# 1.2 安装bash-completion,安装后会创建文件 /usr/share/bash-completion/bash_completion
$ dnf install bash-completion

# 2.安装 kubectl 的自动补全功能
# 2.1 当前用户
$ echo 'source <(kubectl completion bash)' >> ~/.bashrc
# 2.2 所有用户
$ kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
$ sudo chmod a+r /etc/bash_completion.d/kubectl

# 3 如果 kubectl 有关联的别名,你可以扩展 Shell 补全来适配此别名
$ echo 'alias k=kubectl' >>~/.bashrc
$ echo 'complete -o default -F __start_kubectl k' >>~/.bashrc

# 4.刷新配置文件
$ source ~/.bashrc

创建集群(master节点)

  • master节点: [hostname: k8s-master, IP: 10.211.55.11]

  • 初始化master节点的控制面板,容器运行时基于 containerd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# kubeadm init --help可以查看命令的具体参数用法

#在master节点执行初始化(node节点不用执行)
# --apiserver-advertise-address 指定apiserver的IP,即master节点的IP
# --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers 设置镜像仓库为国内镜像仓库
# --kubernetes-version 设置k8s的版本,跟kubeadm版本一致
# --service-cidr 这是设置node节点的网络的,暂时这样设置
# --pod-network-cidr 这是设置node节点的网络的,暂时这样设置
# --cri-socket unix:///var/run/cri-dockerd.sock 设置cri使用cri-dockerd
# --ignore-preflight-errors=all 忽略所有预检错误(Preflight Errors)。这会跳过对系统状态的某些检查,例如是否启用了 swap、CPU 核心数、系统配置等。不推荐用于生产,只用于调试或测试环境。

$ sudo kubeadm init \
--apiserver-advertise-address=10.211.55.11 \
--kubernetes-version v1.33.2 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16
## 安装成功会打印如下信息
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

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/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.211.55.11:6443 --token sqwk6v.lxlnf0ibtbgr4i27 \
--discovery-token-ca-cert-hash sha256:c43f8b6d0e7081a76ab1d8ca8d3c5fb1ef3b21afcd81874566d7840167809412

  • 查看集群状态

1
2
3
4
5
6
$ k get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy ok
  • 为当前用户授予连接集群的权限

1
2
3
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 安装calico前查看pod,-A 查看所有命名空间
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-674b8bbfcf-8xllc 0/1 Pending 0 116m
kube-system coredns-674b8bbfcf-w2sxz 0/1 Pending 0 116m
kube-system etcd-k8s 1/1 Running 2 (74m ago) 116m
kube-system kube-apiserver-k8s 1/1 Running 2 (74m ago) 116m
kube-system kube-controller-manager-k8s 1/1 Running 2 (74m ago) 116m
kube-system kube-proxy-94zqw 1/1 Running 1 (74m ago) 116m
kube-system kube-scheduler-k8s 1/1 Running 2 (74m ago) 116m

# 下载yaml文件,目前最新版为 v3.30.2
$ curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.30.2/manifests/calico.yaml

# 创建
$ kubectl apply -f calico.yaml

# 安装calico后查看pod,在安装 Calico 之前 CoreDNS 是 Pending 状态,现在已经变成 Running
# -o wide: 显示pod的详细信息
$ kubectl get pods -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system calico-kube-controllers-7bfdc5b57c-9qv9m 1/1 Running 0 6m23s 10.244.77.1 k8s <none> <none>
kube-system calico-node-m7wc5 1/1 Running 0 6m23s 10.211.55.11 k8s <none> <none>
kube-system coredns-674b8bbfcf-8xllc 1/1 Running 0 123m 10.244.77.3 k8s <none> <none>
kube-system coredns-674b8bbfcf-w2sxz 1/1 Running 0 123m 10.244.77.2 k8s <none> <none>
kube-system etcd-k8s 1/1 Running 2 (82m ago) 123m 10.211.55.11 k8s <none> <none>
kube-system kube-apiserver-k8s 1/1 Running 2 (82m ago) 123m 10.211.55.11 k8s <none> <none>
kube-system kube-controller-manager-k8s 1/1 Running 2 (82m ago) 123m 10.211.55.11 k8s <none> <none>
kube-system kube-proxy-94zqw 1/1 Running 1 (82m ago) 123m 10.211.55.11 k8s <none> <none>
kube-system kube-scheduler-k8s 1/1 Running 2 (82m ago) 123m 10.211.55.11 k8s <none> <none>

calica 安装后可能出现不正常的情况,比如 calico-node-xxx 的pod始终无法正常运行,此时可以尝试重新安装 calica

1
2
3
4
5
6
7
8
# 删除 calico
$ kubectl delete -f calico.yaml
#如果是重装calico,需要先清除旧的配置
$ sudo rm -rf /etc/cni/net.d/
$ sudo rm -rf /var/lib/calico

# 重新安装 calico
$ kubectl apply -f calico.yaml

添加节点(worker节点)

  • worker节点: [hostname: k8s-worker1, IP: 10.211.55.15]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 在待加入的节点上执行如下命令,如果忘记token,则使用下文的命令重新获取
$ sudo kubeadm join 10.211.55.11:6443 --token sqwk6v.lxlnf0ibtbgr4i27 --discovery-token-ca-cert-hash sha256:c43f8b6d0e7081a76ab1d8ca8d3c5fb1ef3b21afcd81874566d7840167809412
## 输出
[preflight] Running pre-flight checks
[WARNING SystemVerification]: cgroups v1 support is in maintenance mode, please migrate to cgroups v2
[preflight] Reading configuration from the "kubeadm-config" ConfigMap in namespace "kube-system"...
[preflight] Use 'kubeadm init phase upload-config --config your-config-file' to re-upload it.
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is healthy after 1.004135788s
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
  • 如果上面的令牌忘记了,或者新的 worker 节点加入,在 master 上执行下面的命令,生成新的令牌

1
2
3
$ kubeadm token create --print-join-command
## 输出
kubeadm join 10.211.55.11:6443 --token 5o3p2i.gj95aopph0xbrcig --discovery-token-ca-cert-hash sha256:c43f8b6d0e7081a76ab1d8ca8d3c5fb1ef3b21afcd81874566d7840167809412
  • 在 master 节点上查看新创建的资源,默认情况下 work 节点不支持管理 k8s

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查看节点
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s Ready control-plane 3h33m v1.33.2
k8s-worker1 Ready <none> 115s v1.33.2

# 查看pod list
$ kubectl get pods -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system calico-kube-controllers-7bfdc5b57c-q5xwp 1/1 Running 0 37m 10.244.235.193 k8s-master <none> <none>
kube-system calico-node-7pbbq 1/1 Running 0 4m51s 10.211.55.15 k8s-worker1 <none> <none>
kube-system calico-node-w47qq 1/1 Running 0 37m 10.211.55.11 k8s-master <none> <none>
kube-system coredns-674b8bbfcf-2tvld 1/1 Running 0 37m 10.244.235.195 k8s-master <none> <none>
kube-system coredns-674b8bbfcf-h6kx7 1/1 Running 0 37m 10.244.235.194 k8s-master <none> <none>
kube-system etcd-k8s-master 1/1 Running 2 37m 10.211.55.11 k8s-master <none> <none>
kube-system kube-apiserver-k8s-master 1/1 Running 4 37m 10.211.55.11 k8s-master <none> <none>
kube-system kube-controller-manager-k8s-master 1/1 Running 4 37m 10.211.55.11 k8s-master <none> <none>
kube-system kube-proxy-nkbns 1/1 Running 0 4m51s 10.211.55.15 k8s-worker1 <none> <none>
kube-system kube-proxy-plqw8 1/1 Running 0 37m 10.211.55.11 k8s-master <none> <none>
kube-system kube-scheduler-k8s-master 1/1 Running 4 38m 10.211.55.11 k8s-master <none> <none>
  • 使 work 节点支持管理 k8s(可选):远程管理

1
2
3
4
5
6
7
# 将 master 节点中的 ~/.kube/config 复制到 work 节点的 ~/.kube/config 即可
# 在 master 节点执行
scp ~/.kube/config k8s-work1:/tmp

# 在 work 节点执行
mkdir -p ~/.kube
mv /tmp/config ~/.kube/config
  • 删除work节点

1
2
3
4
5
6
7
8
# worker节点上执行如下命令
## 在移除节点之前,请重置 kubeadm 安装的状态
$ sudo kubeadm reset
## 重置过程不会重置或清除 iptables 规则或 IPVS 表。如果你希望重置 iptables,则必须手动进行
$ iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

# master 节点上删除节点
$ kubectl delete node k8s-worker1

测试:用K8S部署Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建deployment
kubectl create deployment nginx --image=nginx
# 创建service,--type指定为NodePort,其含义为将deployment的80端口映射到Node的随机端口
kubectl expose deployment nginx --type=NodePort --port=80

# 查看pod和service,不加 -n 参数,默认查看的是default命名空间
$ kubectl get pod,svc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-5869d7778c-95z74 1/1 Running 0 19m 10.244.194.65 k8s-worker1 <none> <none>

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 61m <none>
service/nginx NodePort 10.96.48.156 <none> 80:30291/TCP 14m app=nginx

# 浏览器访问任意nodeIP:30291

# 删除测试资源
## 删除deployment
kubectl delete deployment nginx
## 删除service
kubectl delete service nginx

通过 kubeadm 卸载 Kubernetes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 停止 kubelet 相关组件,删除 /etc/kubernetes 配置,清除证书、状态目录等,取消 iptables 规则,清除容器运行时中的 Pod、镜像信息等
$ sudo kubeadm reset
# 虽然 kubeadm reset 已经会清除大部分内容,但以下文件和配置可能依然存在,建议一并手动清理
## 删除 kubeconfig 文件(本地 kubectl 配置)
rm -rf $HOME/.kube
## 清理 etcd 数据(如你启用了本地 etcd)
sudo rm -rf /var/lib/etcd
## 清理 CNI 网络配置和状态
sudo rm -rf /etc/cni/net.d
sudo rm -rf /var/lib/cni/
sudo rm -rf /var/lib/kubelet/*
# 清理 Calico
sudo rm -rf /var/lib/calico

# 清理 iptables
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

停止和禁用 kubelet 服务

1
2
sudo systemctl stop kubelet
sudo systemctl disable kubelet

升级 kubeadm 集群

  • 将 kubeadm 创建的 Kubernetes 集群从 1.32.x 版本 升级到 1.33.x 版本以及从 1.33.x 升级到 1.33.y(其中 y > x),略过次版本号的升级是 不被支持的。

升级步骤

升级 master 节点

  • 升级 master 节点

  • 如果要从 v1.33 升级到 v1.34,则需要先修改 Kubernetes YUM 源,因为我上面配置 yum 源时配置的是 v1.33

  • 如果只是从 v1.33.2 升级到 v1.33.3,则不需要修改 Kubernetes YUM 源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看 kubeadm 可以升级的版本
$ sudo yum list --showduplicates kubeadm

# 指定要升级的版本,比如这里要升级到 1.33.3
sudo yum install -y kubeadm-1.33.3
# 查看升级后的版本
kubeadm version

# 验证升级计划: 此命令检查你的集群是否可被升级,并取回你要升级的目标版本。 命令也会显示一个包含组件配置版本状态的表格。
$ sudo kubeadm upgrade plan

# 升级 master 节点: 这一步会升级 kube-apiserver、controller-manager、scheduler 等静态 Pod。
$ sudo kubeadm upgrade apply v1.33.3
## 一旦该命令结束,你应该会看到:
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.33.3". Enjoy!

[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
  • 手动升级你的 CNI 驱动插件,比如 Calico

  • 升级 kubelet 和 kubectl

1
2
3
4
5
# 安装指定的版本
sudo yum install -y kubelet-1.33.3 kubectl-1.33.3
# 重启 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet

升级 worker 节点

  • 升级 worker 节点

  • 如果要从 v1.33 升级到 v1.34,则需要先修改 Kubernetes YUM 源,因为我上面配置 yum 源时配置的是 v1.33

  • 如果只是从 v1.33.2 升级到 v1.33.3,则不需要修改 Kubernetes YUM 源

1
2
3
4
5
6
7
# 查看 kubeadm 可以升级的版本
$ sudo yum list --showduplicates kubeadm

# 指定要升级的版本,比如这里要升级到 1.33.3
$ sudo yum install -y kubeadm-1.33.3
# 查看升级后的版本
$ kubeadm version
  • 腾空节点:如果有多个 worker 节点,可以选择先腾空节点。如果只有一个 worker 节点,则不需要。

drain 是为了在升级期间 避免该节点上正在运行的业务容器受到影响

1
2
3
# 在控制平面节点上执行此命令
# 将 <node-to-drain> 替换为你正腾空的节点的名称
$ kubectl drain <node-to-drain> --ignore-daemonsets
  • 升级 node 节点

1
$ sudo kubeadm upgrade node
  • 升级 kubelet 和 kubectl

1
2
3
4
5
# 安装指定的版本
$ sudo yum install -y kubelet-1.33.3 kubectl-1.33.3
# 重启 kubelet
$ sudo systemctl daemon-reload
$ sudo systemctl restart kubelet
  • 如果前面对节点做了 腾空节点 操作,则需要取消对节点的保护,将节点标记为可调度,让节点重新上线

1
2
3
# 在控制平面节点上执行此命令
# 将 <node-to-uncordon> 替换为你的节点名称
$ kubectl uncordon <node-to-uncordon>

更新证书

  • kubeadm 创建的证书存放在 /etc/kubernetes/pki/ 下,默认客户端证书有效期为 1 年

  • 可以通过如下命令查看证书信息

1
2
kubectl -n kube-system get cm kubeadm-config -o yaml
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text
  • 查看证书到期时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sudo kubeadm certs check-expiration
## 输出结果
## 可以看到 客户端 的证书的过期时间,默认值为 1 年
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
admin.conf Jun 29, 2026 14:41 UTC 363d ca no
apiserver Jun 29, 2026 14:41 UTC 363d ca no
apiserver-etcd-client Jun 29, 2026 14:41 UTC 363d etcd-ca no
apiserver-kubelet-client Jun 29, 2026 14:41 UTC 363d ca no
controller-manager.conf Jun 29, 2026 14:41 UTC 363d ca no
etcd-healthcheck-client Jun 29, 2026 14:41 UTC 363d etcd-ca no
etcd-peer Jun 29, 2026 14:41 UTC 363d etcd-ca no
etcd-server Jun 29, 2026 14:41 UTC 363d etcd-ca no
front-proxy-client Jun 29, 2026 14:41 UTC 363d front-proxy-ca no
scheduler.conf Jun 29, 2026 14:41 UTC 363d ca no
super-admin.conf Jun 29, 2026 14:41 UTC 363d ca no

# 根证书默认有效期为 10 年
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
ca Jun 27, 2035 14:41 UTC 9y no
etcd-ca Jun 27, 2035 14:41 UTC 9y no
front-proxy-ca Jun 27, 2035 14:41 UTC 9y no
  • 更新客户端证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 更新前备份
sudo cp -rf /etc/kubernetes/ /etc/kubernetes.bak
sudo cp -rf /var/lib/etcd/ /var/lib/etcd.bak

# 可以更新单个客户端证书
# sudo kubeadm certs renew admin.conf
# sudo kubeadm certs renew apiserver

# 升级全部客户端证书,也只能续期1年
sudo kubeadm certs renew all
## 输出
[renew] Reading configuration from the "kubeadm-config" ConfigMap in namespace "kube-system"...
[renew] Use 'kubeadm init phase upload-config --config your-config-file' to re-upload it.

certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
certificate for serving the Kubernetes API renewed
certificate the apiserver uses to access etcd renewed
certificate for the API server to connect to kubelet renewed
certificate embedded in the kubeconfig file for the controller manager to use renewed
certificate for liveness probes to healthcheck etcd renewed
certificate for etcd nodes to communicate with each other renewed
certificate for serving etcd renewed
certificate for the front proxy client renewed
certificate embedded in the kubeconfig file for the scheduler manager to use renewed
certificate embedded in the kubeconfig file for the super-admin renewed

Done renewing certificates. You must restart the kube-apiserver, kube-controller-manager, kube-scheduler and etcd, so that they can use the new certificates.

# 需要根据输出提示重启 kube-apiserver, kube-controller-manager, kube-scheduler 和 etcd
# 这几个组件是通过pod 启动的,可以通过 kubectl get pod -n kube-system 查看
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-7bfdc5b57c-q5xwp 1/1 Running 3 (5h37m ago) 41h
calico-node-7pbbq 1/1 Running 3 (5h36m ago) 41h
calico-node-v4hzr 1/1 Running 2 (5h37m ago) 19h
calico-node-w47qq 1/1 Running 3 (5h37m ago) 41h
coredns-674b8bbfcf-2tvld 1/1 Running 3 (5h37m ago) 41h
coredns-674b8bbfcf-h6kx7 1/1 Running 3 (5h37m ago) 41h
etcd-k8s-master 1/1 Running 5 (5h37m ago) 41h
kube-apiserver-k8s-master 1/1 Running 7 (5h37m ago) 41h
kube-controller-manager-k8s-master 1/1 Running 7 (5h37m ago) 41h
kube-proxy-nkbns 1/1 Running 3 (5h36m ago) 41h
kube-proxy-plqw8 1/1 Running 3 (5h37m ago) 41h
kube-proxy-sbgh6 1/1 Running 2 (5h37m ago) 19h
kube-scheduler-k8s-master 1/1 Running 7 (5h37m ago) 41h

# 删除指定的pod就会自动重启
kubectl delete pod -n kube-system kube-apiserver-k8s-master kube-controller-manager-k8s-master kube-scheduler-k8s-master etcd-k8s-master

# 重启成功后再次查看证书信息,就会看到更新后的到期时间为1年
sudo kubeadm certs check-expiration

Kubernetes 节点组件

角色 组件名 说明
Master Node kube-apiserver Kubernetes 的 API 请求入口,处理所有 REST 请求,协调各组件。
kube-scheduler 调度器,决定将 Pod 调度到哪个合适的 Node。
kube-controller-manager 包含多个控制器(如 NodeController、ReplicationController、DeploymentController 等),用于控制和调整集群状态。
etcd 分布式 KV 存储系统,存储 Kubernetes 所有状态数据。只有 API Server 能直接访问。
Worker Node kubelet 负责与 Master 通信,执行其下发的 Pod 管理任务,控制容器生命周期。
kube-proxy 负责维护 Node 上的网络规则,支持服务负载均衡和网络通信。
container runtime 容器运行时,比如 Docker、containerd、CRI-O,负责实际运行容器。

crictl 命令

  • crictl 是k8s官方出品的一个命令行工具,用于与 containerd 进行通信。

  • crictl 命令的使用方式比较类似docker命令

操作 docker 命令 crictl 命令 说明
查看正在运行的容器 docker ps crictl ps
查看所有容器(包括已停止) docker ps -a crictl ps -a
查看镜像 docker images crictl images
查看容器日志 docker logs <container_id> crictl logs <container_id>
进入容器交互 docker exec -it <id> sh crictl exec -it <id> sh
查看容器详细信息 docker inspect <container_id> crictl inspect <container_id>
查看 Pod 详细信息 ❌(不支持) crictl inspectp <pod_id> K8s 专属
删除容器 docker rm <container_id> crictl rm <container_id>
删除镜像 docker rmi <image_id> crictl rmi <image_id>
拉取镜像 docker pull nginx crictl pull nginx
运行容器(非 K8s 场景) docker run -it nginx ❌(不支持) crictl 不运行容器,仅调试现有容器
列出容器运行时信息 docker info crictl info
查看容器运行状态 docker stats crictl stats 简要版
设置配置文件 ~/.docker/config.json /etc/crictl.yaml 如设置 endpoint