参考资料
前置:内核加载模块并修改内核参数配置
lsmod | \grep -E 'overlay|nf_nat|br_netfilter|xt_conntrack|aufs'- 查看需要的模块是否已加载
sysctl vm.swappiness net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv6.conf.all.accept_ra- 查看内核配置
vim /etc/modules-load.d/modules.conf
- 加载模块
vim /etc/sysctl.d/systcl.conf
sysctl --system- 重新加载内核参数配置
- 如果 ipv6 默认路由是通过路由器通告 (RA) 设置,需要
net.ipv6.conf.all.accept_ra=2
前置:移除交换分区,顺便调整磁盘空间
移除 swap 交换分区
- https://www.kernel.org/doc/html/latest/admin-guide/sysctl/vm.html
vm.swappiness = 0实际不代表无交换
swapoff -a- 卸载所有 swap 交换分区
DEV_SWAP=$(cat /etc/fstab | grep swap | awk '{print $1}')- 根据对应 swap 物理卷名称修改关键字
lvchange -a n $DEV_SWAP
lvremove $DEV_SWAP
lvdisplay | grep swap- 查看是否已移除
vim /etc/fstab- 注释对应部分,禁用开机自动挂载
可选:调整磁盘空间
- 以 VM 为例,分别挂载了两个逻辑组
vg-root和vg-home到/和/home - 如果需要缩容根目录需要进入救援模式
DEV_HOME=$(cat /etc/fstab | grep vg-home | awk '{print $1}')
DEV_ROOT=$(cat /etc/fstab | grep vg-root | awk '{print $1}')
umount /homelsof +D /home
- 缩小 vg-home 空间
e2fsck -f $DEV_HOMEresize2fs $DEV_HOME 5Glvreduce -L 5G $DEV_HOME
- 扩容至 vg-root
lvextend -l +100%FREE $DEV_ROOTresize2fs $DEV_ROOT
- 重新挂载并查看调整结果
mount /home && df -h | grep /dev
前置:安装了容器运行时和 kubeadm, kubelet
- 参考资料
安装 containerd 并启用 SystemdCgroup
安装 containerd 二进制文件
- 最新版本
CONTAINERD_VERSION=$(curl -s https://api.github.com/repos/containerd/containerd/releases/latest | jq -r '.tag_name' | sed 's/v//')echo $CONTAINERD_VERSION
wget https://github.com/containerd/containerd/releases/download/v$CRI_VERSION/containerd-$CONTAINERD_VERSION-linux-amd64.tar.gz
sudo tar Cxzvf /usr/local containerd-$CONTAINERD_VERSION-linux-amd64.tar.gz
containerd 生成默认配置文件并启用 SystemdCgroup
containerd config default | \ sed 's/SystemdCgroup = false/SystemdCgroup = true/' | \ sudo tee /etc/containerd/config.toml
安装 containerd systemd 服务文件并启用 containerd 服务
sudo mkdir -p /usr/local/lib/systemd/system
sudo curl -Lo /usr/local/lib/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo systemctl daemon-reload
sudo systemctl enable --now containerd
安装 kubeadm, kubelet
- 以 1.34 版本为例
K8S_VERSION=1.34
添加 Kubernetes 官方仓库
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v$K8S_VERSION/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v$K8S_VERSION/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
K8STOOL_VERSION=$(apt-cache madison kubectl | awk '{print $3}' | grep $K8S_VERSION | head -n 1)echo $K8STOOL_VERSION
sudo apt-get update
sudo apt-get install -y kubectl=$K8STOOL_VERSION \ kubelet=$K8STOOL_VERSION \ kubeadm=$K8STOOL_VERSION- 版本要尽量一致
sudo apt-mark hold kubelet kubeadm kubectl- 锁定当前版本
sudo systemctl enable --now kubelet- 可选,先启用 kubelet 服务,再运行 kubeadm
可选:安装 docker 运行时 (不推荐,Kubernetes 原生已移除 dockershim 兼容层)
docker 一键安装脚本
bash <(curl -sSL https://linuxmirrors.cn/docker.sh) \ --source "mirrors.huaweicloud.com/docker-ce" \ --source-registry "registry.cn-shanghai.aliyuncs.com" \ --install-latest true --use-intranet-source false \ --ignore-backup-tips- 选择华为云,否则容易出现解析错误
其他可选项
修改 docker daemon.json 开启 ipv6
ls -al /lib/systemd/system/docker.service
vim /etc/docker/daemon.json
- default-gateway-v6 不能与已有的地址一致
获取并安装 cri-dockerd 插件
- 最新版本
CRI_VERSION=$(curl -s https://api.github.com/repos/Mirantis/cri-dockerd/releases/latest | jq -r '.tag_name' | sed 's/v//')echo $CRI_VERSION
wget https://github.com/Mirantis/cri-dockerd/releases/download/v$CRI_VERSION/cri-dockerd-$CRI_VERSION.amd64.tgz
tar xzf cri-dockerd-$CRI_VERSION.amd64.tgz --strip-components=1 && \ sudo mv cri-dockerd /usr/local/bin/
cri-dockerd --version
docker info
docker network ls
docker inspect network bridge
- 可选:外部高可用的 etcd 集群
- 详见 etcd 对应内容
其他:安装常用的 CNI 插件
- kubeadm 安装没有提供 CNI 插件,自己选择一个安装即可
flannel:简单可靠的 Overlay 网络
- 如果使用 apply 安装的话需要注意是否自定义了 pod CIDR
calico:高性能、企业级网络与安全方案
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.2/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.31.2/manifests/custom-resources.yaml
cilium:基于 eBPF 的下一代云原生网络
ciliumprojectCilium Quick Installation — Cilium 1.18.4 documentation
Cilium Quick Installation — Cilium 1.18.4 documentation
This guide will walk you through the quick default installation. It will automatically detect and use the best configuration possible for the Kubernetes distribution you are using. All state is stored using Kubernetes custom resource definitions (CRDs).
Kubernetes 组件版本兼容性
- Kubernetes 遵循 "N-1" 兼容原则,即客户端版本可以比服务器版本高或低一个次要版本
- 以 kube-apiserver 为核心版本
- kubectl, kube-controller-manager 和 kube-scheduler 不能相差一个次要版本
- kubelet 和 kube-proxy 不能相差两个次要版本
kubeadm init 初始化一个 Kubernetes 控制平面节点
- kubeadm init phase 分阶段初始化控制平面节点
init 会执行以下阶段
常用选项
--apiserver-advertise-address string- API 服务器所公布的其正在监听的 IP 地址
--apiserver-bind-port int32- API 服务器绑定的端口,默认值:6443
--apiserver-cert-extra-sans strings- 用于 API Server 服务证书的可选附加主题备用名称(SAN)
- 可以是 IP 地址和 DNS 名称
--control-plane-endpoint string- 为控制平面指定一个稳定的 IP 地址或 DNS 名称
--pod-network-cidr string- 指明 Pod 网络可以使用的 IP 地址段
--service-cidr string- 为服务的虚拟 IP 地址另外指定 IP 地址段
--service-dns-domain string- 为服务另外指定域名,默认为
"cluster.local"
选项和参数
--configstring- kubeadm 配置文件位置
--node-name string- 指定节点的名称
--kubernetes-version string- 为控制平面选择一个特定的 Kubernetes 版本,默认为
"stable-1"
--image-repository string- 选择用于拉取控制平面镜像的容器仓库
--token string- 用于建立控制平面节点与工作节点间的双向通信的令牌
- token 格式为
[a-z0-9]{6}.[a-z0-9]{16} kubeadm token generate生成并打印一个引导令牌,但不要在服务器上创建它
--token-ttl duration- 令牌被自动删除之前的持续时间,默认为
"24h0m0s" - 设置为
'0',则令牌将永不过期
--cert-dir string- 保存和存储证书的路径,默认为
"/etc/kubernetes/pki"
--upload-certs- 将控制平面证书上传到 kubeadm-certs Secret
--certificate-key string- 用于加密 kubeadm-certs Secret 中的控制平面证书的密钥
- 证书密钥为十六进制编码的字符串,是大小为 32 字节的 AES 密钥
--feature-gates string- 用来描述各种特性门控的键值(key=value)对
- 可用选项
ControlPlaneKubeletLocalMode=true|false (ALPHA - 默认值=false)EtcdLearnerMode=true|false (默认值=true)NodeLocalCRISocket=true|false (ALPHA - 默认值=false)PublicKeysECDSA=true|false (DEPRECATED - 默认值=false)RootlessControlPlane=true|false (ALPHA - 默认值=false)WaitForAllControlPlaneComponents=true|false (ALPHA - 默认值=false)
--cri-socketstring- 要连接的 CRI 套接字的路径
- 如果为空,则 kubeadm 将尝试自动检测此值
- 仅当安装了多个 CRI 或存在非标准的 CRI 套接字时,才使用此选项
--skip-phases strings- 要跳过的阶段列表
kubeadm init 使用配置文件初始化一个 Kubernetes 控制平面节点
kubeadm config print 打印默认值
kubeadm config print init-defaults
kubeadm config print join-defaults
kubeadm config print reset-defaults
kubeadm config print upgrade-defaults
kubeadm init --config <配置文件> 的四种配置类型
- 至少需要提供
InitConfiguration或ClusterConfiguration中的一个
InitConfiguration- 用于控制
kubeadm init本身的运行行为
ClusterConfiguration- 用于定义整个集群的全局设置
KubeProxyConfiguration- 用于自定义 kube-proxy 的配置
KubeletConfiguration- 用于自定义所有节点上 kubelet 的默认配置
完整样例
kubeadm token 管理引导令牌
kubeadm token generate生成并打印一个引导令牌,但不要在服务器上创建它- token 形式为
[a-z0-9]{6}.[a-z0-9]{16} - 前 6 位为 token id
kubeadm token create [token]在服务器上创建引导令牌token可选,没有提供则 kubeadm 将生成一个随机令牌
kubeadm token list列出服务器上的引导令牌
kubeadm token delete [token-value]删除对应令牌token-value是完整令牌或者令牌 ID
kubeadm join 初始化一个 Kubernetes 节点加入已有集群
- 关键是建立当前节点和控制平面节点的双向信任
- 发现要信任的集群 CA(让待加入节点信任 Kubernetes 控制平面节点)
- 集群 CA TLS 引导(让 Kubernetes 控制平面节点信任待加入节点)
两种集群 CA 发现方案
使用共享令牌和 API 服务器的 IP 地址
kubeadm join 1.2.3.4:6443 \ --discovery-token <token> \ --discovery-token-ca-cert-hash sha256:<hex_encoded_hash>--control-plane作为控制平面加入节点--discovery-token-unsafe-skip-ca-verification不验证 CA 公钥- 和
--discovery-token-ca-cert-hash冲突
基于 HTTPS 或文件发现
kubeadm join 1.2.3.4:6443 \ --discovery-file <filepath>|<urlpath>- 可以是文本本地路径
path/to/file.conf也可以是文件 url 路径https://url/file.conf
join 工作流
- 工作节点加入流程:
- 从 API 服务器获取集群信息(默认通过引导令牌和 CA 哈希验证)。
- kubelet 使用共享令牌临时认证,发起 TLS 引导并提交证书签名请求(CSR)。
- 控制平面自动批准 CSR,完成身份认证。
- 配置 kubelet 使用唯一标识连接 API 服务器。
- 控制平面节点额外步骤:
- (可选)下载集群共享的控制平面证书。
- 生成本地控制平面组件的配置、证书和 kubeconfig。
- 将本地 etcd 实例作为新成员加入 etcd 集群
- kubeadm join phase 分阶段将节点加入集群
join 会执行以下阶段
选项和参数
--node-name string- 指定节点的名称
--discovery-file string- 对于基于文件的发现,给出用于加载集群信息的文件或者 URL
--discovery-token string- 对于基于令牌的发现,该令牌用于验证从 API 服务器获取的集群信息
--discovery-token-ca-cert-hash stringSlice- 对于基于令牌的发现,验证根 CA 公钥是否与此哈希匹配
--discovery-token-unsafe-skip-ca-verification- 对于基于令牌的发现,允许在未关联
--discovery-token-ca-cert-hash参数的情况下添加节点
--tls-bootstrap-token string- 指定在加入节点时用于临时通过 Kubernetes 控制平面进行身份验证的令牌
--certificate-key string- 使用此密钥可以解密由 init 上传的证书 Secret
--control-plane- 在此节点上创建一个新的控制平面实例
--apiserver-advertise-address string- 如果托管一个新的控制平面实例,则 API 服务器将公布其正在侦听的 IP 地址
--apiserver-bind-port int32- API 服务器绑定的端口,默认值:6443
--cri-socketstring- 要连接的 CRI 套接字的路径
- 如果为空,则 kubeadm 将尝试自动检测此值
- 仅当安装了多个 CRI 或存在非标准的 CRI 套接字时,才使用此选项
--configstring- kubeadm 配置文件位置
--skip-phases strings- 要跳过的阶段列表
kubeadm certs 管理证书
kubeadm 使用 TLS 证书详细一览
需要以下证书
默认 CN | 父级 CA | O(位于 Subject 中) | kind | 主机(SAN) |
kube-etcd | etcd-ca | ㅤ | server、client | <hostname>、<Host_IP>、localhost、127.0.0.1 |
kube-etcd-peer | etcd-ca | ㅤ | server、client | <hostname>、<Host_IP>、localhost、127.0.0.1 |
kube-etcd-healthcheck-client | etcd-ca | ㅤ | client | ㅤ |
kube-apiserver-etcd-client | etcd-ca | ㅤ | client | ㅤ |
kube-apiserver | kubernetes-ca | ㅤ | server | |
kube-apiserver-kubelet-client | kubernetes-ca | system:masters | client | ㅤ |
front-proxy-client | kubernetes-front-proxy-ca | ㅤ | client | ㅤ |
证书路径
默认 CN | 建议的密钥路径 | 建议的证书路径 | 命令 | 密钥参数 | 证书参数 |
etcd-ca | etcd/ca.key | etcd/ca.crt | kube-apiserver | ㅤ | --etcd-cafile |
kube-apiserver-etcd-client | apiserver-etcd-client.key | apiserver-etcd-client.crt | kube-apiserver | --etcd-keyfile | --etcd-certfile |
kubernetes-ca | ca.key | ca.crt | kube-apiserver | ㅤ | --client-ca-file |
kubernetes-ca | ca.key | ca.crt | kube-controller-manager | --cluster-signing-key-file | --client-ca-file, --root-ca-file, --cluster-signing-cert-file |
kube-apiserver | apiserver.key | apiserver.crt | kube-apiserver | --tls-private-key-file | --tls-cert-file |
kube-apiserver-kubelet-client | apiserver-kubelet-client.key | apiserver-kubelet-client.crt | kube-apiserver | --kubelet-client-key | --kubelet-client-certificate |
front-proxy-ca | front-proxy-ca.key | front-proxy-ca.crt | kube-apiserver | ㅤ | --requestheader-client-ca-file |
front-proxy-ca | front-proxy-ca.key | front-proxy-ca.crt | kube-controller-manager | ㅤ | --requestheader-client-ca-file |
front-proxy-client | front-proxy-client.key | front-proxy-client.crt | kube-apiserver | --proxy-client-key-file | --proxy-client-cert-file |
etcd-ca | etcd/ca.key | etcd/ca.crt | etcd | ㅤ | --trusted-ca-file, --peer-trusted-ca-file |
kube-etcd | etcd/server.key | etcd/server.crt | etcd | --key-file | --cert-file |
kube-etcd-peer | etcd/peer.key | etcd/peer.crt | etcd | --peer-key-file | --peer-cert-file |
etcd-ca | ㅤ | etcd/ca.crt | etcdctl | ㅤ | --cacert |
kube-etcd-healthcheck-client | etcd/healthcheck-client.key | etcd/healthcheck-client.crt | etcdctl | --key | --cert |

kubeadm certs check-expiration检查证书是否以及何时过期
kubeadm certs renew续订 Kubernetes 证书
kubeadm certs certificate-key生成一个新的控制面证书密钥
kubeadm certs generate-csr为所有控制面证书和 kubeconfig 文件生成密钥和 CSR
kubeadm reset 尽力还原由 kubeadm init 或 kubeadm join 所做的更改
reset 会执行以下阶段
选项和参数
--cri-socketstring- 要连接的 CRI 套接字的路径
- 如果为空,则 kubeadm 将尝试自动检测此值
- 仅当安装了多个 CRI 或存在非标准的 CRI 套接字时,才使用此选项
--cert-dirstring- 默认为
"/etc/kubernetes/pki"
--configstring- kubeadm 配置文件位置
--kubeconfigstring- kubeconfig 配置文件位置
- 如果未设置该标志, 则可以在一组标准位置中搜索现有的 kubeconfig 文件
- 默认为
"/etc/kubernetes/admin.conf"
--cleanup-tmp-dir- 清理
"/etc/kubernetes/tmp"目录
--skip-phases strings- 要跳过的阶段列表
kubeadm reset 不会删除的一些东西
- 如果使用了外部 etcd,
kubeadm reset将不会删除任何 etcd 中的数据
kubeadm reset命令不会清理 CNI 插件配置- CNI 插件使用
/etc/cni/net.d目录来存储其配置
kubeadm reset命令不会清理由 kube-proxy 应用到主机的任何 iptables、nftables 或 IPVS 规则
kubeadm reset命令不会清理$HOME/.kube目录中的任何内容
kubeadm upgrade 升级 Kubernetes 集群版本
- 建议按照次要版本一步步升级,且 kubeadm 本身也需要匹配对应版本
- 下文假设次要版本为 1.34
upgrade 会执行以下阶段
kubeadm upgrade apply phase <phase-name>执行某个特定升级阶段
ubuntu/debian 升级 kubeadm
apt update
apt-cache madison kubeadm- 查看可用版本,假设次要版本为 1.34
apt-mark unhold kubeadm && \ apt-get install -y kubeadm='1.34.x-*' && \ apt-mark hold kubeadm
kubeadm upgrade plan- 检查可用升级以及升级建议,并取回要升级的目标版本
- 还会自动对 kubeadm 在节点上所管理的证书执行续约操作
- CNI 驱动插件需要手动升级
升级首个控制平面需要执行 kubeadm upgrade apply v1.34.Z
kubeadm upgrade apply会执行以下操作- 检查您的集群是否处于可升级状态
- API 服务器可访问
- 所有节点均处于
Ready状态 - 控制平面运行正常
- 强制执行版本偏差策略
- 确保控制平面图像可用或可供拉取到机器
- 如果组件配置需要版本升级,则生成替换项和/或使用用户提供的覆盖项
- 升级控制平面组件,如果其中任何组件启动失败,则进行回滚
- 应用新的
CoreDNS和kube-proxy清单,并确保创建所有必要的 RBAC 规则 - 为 API 服务器创建新的证书和密钥文件,并备份即将在 180 天内过期的旧文件
后续其他控制平面只需要 kubeadm upgrade node
kubeadm upgrade node在其他控制平面会执行以下操作- 从集群中获取 kubeadm ClusterConfiguration
- (可选)备份 kube-apiserver 证书
- 升级控制平面组件的静态 Pod 清单
- 升级此节点的 kubelet 配置
kubectl drain <node-to-drain> --ignore-daemonsets- 腾空节点准备升级 kubelet
ubuntu/debian 升级 kubelet 和 kubectl
apt-mark unhold kubelet kubectl && \ apt-get install -y kubelet='1.34.x-*' kubectl='1.34.x-*' && \ apt-mark hold kubelet kubectl
systemctl daemon-reload
systemctl restart kubelet
kubectl uncordon <node-to-uncordon>- 工作节点恢复为可调度状态
如果升级失败可以再次执行 kubeadm upgrade apply --force
kubeadm upgrade指令是幂等(exactly once)的,并最终确保实际状态是声明的期望状态
- 在升级期间,kubeadm 会写入备份到 /etc/kubernetes/tmp 文件夹
kubeadm-backup-etcd-<date>-<time>- 仅当使用内部 etcd 时非空,包含当前控制平面节点本地 etcd 成员数据的备份
- 如果升级失败且自动回滚无法修复,可以复制到
/var/lib/etcd进行手工修复 kubeadm-backup-manifests-<date>-<time>- 包含当前控制平面节点的静态 Pod 清单文件的备份版本
- 如果升级失败且自动回滚无法修复,可以复制到
/etc/kubernetes/manifests目录实现手工恢复
- 升级后,备份目录
/etc/kubernetes/tmp将保留,需要手动清理
- Author:白鸟3
- URL:https://blog.kun2peng.top/operation/k8s_kubeadm
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
