基于Kubeadm在Ubuntu 20.04上构建高可用Kubernetes集群
本文将详细介绍如何在Ubuntu 20.04操作系统上,利用kubeadm工具部署一个高可用的Kubernetes(K8s)集群。部署过程涵盖了从系统环境准备到集群初始化与节点加入的各个环节,旨在提供一个清晰、可操作的指南。
1. 集群架构与资源规划
在开始部署之前,明确集群的架构和资源分配至关重要。本次部署将搭建一个包含3个主控节点(Master)和3个工作节点(Node)的K8s高可用集群。
1.1 节点信息规划
| 名称 | IP 地址 | 角色 |
|---|---|---|
| k8s-master-01 | 172.1.2.11 | 主控节点 (Control Plane) |
| k8s-master-02 | 172.1.2.12 | 主控节点 (Control Plane) |
| k8s-master-03 | 172.1.2.13 | 主控节点 (Control Plane) |
| k8s-node-01 | 172.1.2.21 | 工作节点 (Worker) |
| k8s-node-02 | 172.1.2.22 | 工作节点 (Worker) |
| k8s-node-03 | 172.1.2.23 | 工作节点 (Worker) |
注意: 在进行IP地址规划时,请确保所选的IP地址适用于您的网络环境,并且所有节点可以相互访问。若集群后续需要对外提供服务或集成其他网络组件(如旁路网关),建议使用私有IP地址,并预留足够的地址空间。避免使用公网IP作为内部集群通信地址,这可能导致网络配置复杂性增加或潜在安全风险。
2. 环境准备与基础配置
所有参与Kubernetes集群的节点都需要进行以下基础环境配置。
2.1 操作系统初始化
所有节点均基于 Ubuntu 20.04 LTS 系统。
允许 Root 用户远程登录
为方便管理,配置 root 用户可远程登录:
# 创建并设置root用户密码(如果root用户不存在或密码未设置)
sudo passwd root
# 修改SSH服务配置以允许root登录
sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
sudo systemctl restart sshd
配置 APT 软件源
为加快软件包下载速度,配置阿里云的APT源和Kubernetes的APT源。
# 更新并安装必要的工具
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
# 备份原始 sources.list
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
# 配置阿里云 Ubuntu 源
cat <<EOF | sudo tee /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
EOF
# 配置 Kubernetes APT 源
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
# 更新软件包列表
sudo apt-get update
2.2 关闭防火墙
在集群部署初期,为避免不必要的网络问题,建议暂时关闭防火墙。生产环境部署时应配置允许K8s所需端口通过。
sudo ufw disable && sudo ufw status
2.3 禁用 Swap 分区
Kubernetes 要求禁用系统的 Swap 分区,以确保节点性能和稳定性。
# 临时禁用 swap
sudo swapoff -a
# 永久禁用 swap:编辑 /etc/fstab 文件,注释掉所有包含 swap 的行
# 例如,将 `/swap.img none swap sw 0 0` 修改为 `# /swap.img none swap sw 0 0`
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# 验证 swap 是否已禁用
sudo systemctl --type swap
# 预期输出应为 "0 loaded units listed."
2.4 配置时间同步
集群中所有节点的时间必须保持同步,这对于K8s的许多组件(如证书、日志)正常工作至关重要。我们使用 Chrony 进行时间同步。
sudo apt install chrony -y
sudo systemctl start chrony && sudo systemctl enable chrony
2.5 配置主机名解析
在所有节点上配置 /etc/hosts 文件,以便进行内部主机名解析。
cat <<EOF | sudo tee -a /etc/hosts
172.1.2.11 k8s-master-01 k8sapi.com
172.1.2.12 k8s-master-02
172.1.2.13 k8s-master-03
172.1.2.21 k8s-node-01
172.1.2.22 k8s-node-02
172.1.2.23 k8s-node-03
EOF
注意: k8sapi.com 是为高可用主控平面设置的虚拟域名,它将解析到实际的主控节点IP地址,或者在LVS/HAProxy等负载均衡器前置时解析到负载均衡器的IP。
2.6 安装 Docker 容器运行时
Kubernetes 需要一个容器运行时来执行容器。这里我们安装 Docker CE,并配置阿里云镜像加速和 cgroup 驱动为 systemd。
# 安装必要的系统工具
sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
# 添加 Docker 官方 GPG 密钥
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 添加 Docker APT 软件源
sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# 更新并安装 Docker CE
sudo apt-get -y update
sudo apt-get -y install docker-ce
# 配置 Docker 镜像加速和 cgroup 驱动
sudo mkdir -p /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://registry.docker-cn.com"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "5"
}
}
EOF
# 重启 Docker 服务以应用配置
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl enable docker
2.7 安装 Kubernetes 核心组件
安装 kubeadm、kubelet 和 kubectl。我们指定安装 v1.22.4 版本以保持与后续 kubeadm init 命令版本一致性。
# 安装特定版本的 Kubernetes 组件
sudo apt-get update
sudo apt-get install -y kubelet=1.22.4-00 kubeadm=1.22.4-00 kubectl=1.22.4-00
# 阻止这些包的自动更新
sudo apt-mark hold kubelet kubeadm kubectl
2.8 预拉取 K8s 组件镜像
由于国内网络环境访问 k8s.gcr.io 可能会遇到问题,建议从阿里云镜像仓库预先拉取所需的 K8s 组件镜像,并重新打标签。
#!/bin/bash
# 定义 Kubernetes 版本,与之前安装的kubeadm版本保持一致
K8S_VER="v1.22.4"
# pause镜像版本
PAUSE_VER="3.6" # 1.22.4 通常使用 pause 3.6
# coredns镜像版本
COREDNS_VER="v1.8.4" # 1.22.4 通常使用 coredns v1.8.4
# etcd镜像版本 (注意,kubeadm在1.22.4中通常使用3.5.0)
ETCD_VER="3.5.0-0" # 1.22.4 通常使用 etcd 3.5.0
# 阿里云Kubernetes镜像仓库前缀
ALIYUN_K8S_REGISTRY="registry.aliyuncs.com/google_containers"
IMAGES=(
kube-apiserver:${K8S_VER}
kube-controller-manager:${K8S_VER}
kube-scheduler:${K8S_VER}
kube-proxy:${K8S_VER}
pause:${PAUSE_VER}
etcd:${ETCD_VER}
coredns:${COREDNS_VER}
)
echo "--- 开始拉取并重命名 K8s 镜像 ---"
for IMAGE in "${IMAGES[@]}"; do
# 构建阿里云镜像地址
ALIYUN_IMAGE="${ALIYUN_K8S_REGISTRY}/${IMAGE}"
# 构建官方GCR镜像地址
GCR_IMAGE="k8s.gcr.io/${IMAGE}"
echo "正在拉取: ${ALIYUN_IMAGE}"
sudo docker pull "${ALIYUN_IMAGE}"
if [ $? -eq 0 ]; then
echo "拉取成功,正在重命名为: ${GCR_IMAGE}"
sudo docker tag "${ALIYUN_IMAGE}" "${GCR_IMAGE}"
sudo docker rmi "${ALIYUN_IMAGE}"
else
echo "拉取 ${ALIYUN_IMAGE} 失败,请检查网络或镜像地址。"
exit 1
fi
done
echo "--- 所有 K8s 镜像已准备就绪 ---"
sudo docker images | grep k8s.gcr.io
在每个节点上运行上述脚本,确保所有必要的镜像都已拉取并正确标记。
3. 初始化 Kubernetes 集群
3.1 初始化首个主控节点 (k8s-master-01)
在 k8s-master-01 上执行初始化命令。这里的 --control-plane-endpoint k8sapi.com 指定了控制平面的入口地址,方便后续添加其他主控节点和工作节点。
# 在 k8s-master-01 节点执行
sudo kubeadm init \
--control-plane-endpoint k8sapi.com:6443 \
--kubernetes-version=v1.22.4 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--upload-certs \
--token-ttl=0
参数说明:
--control-plane-endpoint k8sapi.com:6443: 指定 API Server 的负载均衡地址。--kubernetes-version=v1.22.4: 指定 Kubernetes 版本。--pod-network-cidr=10.244.0.0/16: Pod 网络范围,此范围由 Flannel 网络插件使用。--service-cidr=10.96.0.0/12: Service 网络范围。--upload-certs: 自动上传控制平面证书到集群以便其他主控节点加入。--token-ttl=0: 设置加入令牌永不过期,方便后续节点加入(生产环境应设置有效期)。
初始化成功后,会输出以下信息,其中包含加入工作节点和加入其他主控节点的命令。请务必保存这些命令。
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/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join k8sapi.com:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:79a78631165ad2563462f6b6900223019036a10065a7f5d60677a2884b256d01 \
--control-plane --certificate-key <CERTIFICATE_KEY>
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join k8sapi.com:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:79a78631165ad2563462f6b6900223019036a10065a7f5d60677a2884b256d01
请按提示,配置 kubectl 访问集群:
# 在 k8s-master-01 节点执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
或者,如果作为 root 用户操作:
# 在 k8s-master-01 节点执行
export KUBECONFIG=/etc/kubernetes/admin.conf
3.2 部署 Pod 网络插件 (Flannel)
在 k8s-master-01 上部署 Flannel 作为 Pod 网络插件,使 Pod 之间能够互相通信。
# 在 k8s-master-01 节点执行
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
部署成功后,稍等片刻,可以通过 kubectl get pods -n kube-system 命令查看 Pod 状态,等待所有 CoreDNS 和 Flannel Pods 运行正常。
3.3 工作节点加入集群
在所有工作节点(k8s-node-01, k8s-node-02, k8s-node-03)上执行 kubeadm join 命令,将它们加入集群。使用初始化主控节点时输出的 Worker Node 加入命令。
# 在 k8s-node-01, k8s-node-02, k8s-node-03 节点执行
# 将下方命令替换为 kubeadm init 实际输出的 worker join 命令
sudo kubeadm join k8sapi.com:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:79a78631165ad2563462f6b6900223019036a10065a7f5d60677a2884b256d01
3.4 其他主控节点加入控制平面
将 k8s-master-02 和 k8s-master-03 加入控制平面以实现高可用。
拷贝证书
首先,需要将 k8s-master-01 上的 Kubernetes 证书复制到其他主控节点。
# 在 k8s-master-01 节点执行,将证书复制到 k8s-master-02
# 注意:替换 master02 为 k8s-master-02 的实际IP或主机名
sudo scp -rp /etc/kubernetes/pki/ca* k8s-master-02:/etc/kubernetes/pki/
sudo scp -rp /etc/kubernetes/pki/sa* k8s-master-02:/etc/kubernetes/pki/
sudo scp -rp /etc/kubernetes/pki/front-proxy-ca* k8s-master-02:/etc/kubernetes/pki/
sudo scp -rp /etc/kubernetes/pki/etcd/ca.* k8s-master-02:/etc/kubernetes/pki/etcd/
# 同样操作复制到 k8s-master-03
sudo scp -rp /etc/kubernetes/pki/ca* k8s-master-03:/etc/kubernetes/pki/
sudo scp -rp /etc/kubernetes/pki/sa* k8s-master-03:/etc/kubernetes/pki/
sudo scp -rp /etc/kubernetes/pki/front-proxy-ca* k8s-master-03:/etc/kubernetes/pki/
sudo scp -rp /etc/kubernetes/pki/etcd/ca.* k8s-master-03:/etc/kubernetes/pki/etcd/
加入控制平面
在 k8s-master-02 和 k8s-master-03 上执行 kubeadm join 命令,添加 --control-plane 标志。
# 在 k8s-master-02 和 k8s-master-03 节点执行
# 将下方命令替换为 kubeadm init 实际输出的 control-plane join 命令
sudo kubeadm join k8sapi.com:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:79a78631165ad2563462f6b6900223019036a10065a7f5d60677a2884b256d01 \
--control-plane --certificate-key <CERTIFICATE_KEY>
注意替换 <CERTIFICATE_KEY> 为 kubeadm init 命令输出中的实际值。
4. 验证集群状态
在任意一个主控节点上执行以下命令,检查集群状态。
# 在任意主控节点执行
kubectl get nodes
预期输出应显示所有节点处于 Ready 状态:
NAME STATUS ROLES AGE VERSION
k8s-master-01 Ready control-plane,master 60m v1.22.4
k8s-master-02 Ready control-plane,master 30m v1.22.4
k8s-master-03 Ready control-plane,master 28m v1.22.4
k8s-node-01 Ready <none> 45m v1.22.4
k8s-node-02 Ready <none> 40m v1.22.4
k8s-node-03 Ready <none> 38m v1.22.4
查看 kube-system 命名空间下的所有 Pod 状态,确保所有核心组件均正常运行:
# 在任意主控节点执行
kubectl get pods -n kube-system
预期输出应显示所有 Pod 处于 Running 状态:
NAME READY STATUS RESTARTS AGE
coredns-78fcd69978-bshpd 1/1 Running 0 60m
coredns-78fcd69978-kj5rz 1/1 Running 0 60m
etcd-k8s-master-01 1/1 Running 0 60m
etcd-k8s-master-02 1/1 Running 0 30m
etcd-k8s-master-03 1/1 Running 0 28m
kube-apiserver-k8s-master-01 1/1 Running 0 60m
kube-apiserver-k8s-master-02 1/1 Running 0 30m
kube-apiserver-k8s-master-03 1/1 Running 0 28m
kube-controller-manager-k8s-master-01 1/1 Running 0 60m
kube-controller-manager-k8s-master-02 1/1 Running 0 30m
kube-controller-manager-k8s-master-03 1/1 Running 0 28m
kube-flannel-ds-8mgmv 1/1 Running 0 30m
kube-flannel-ds-9kh2l 1/1 Running 0 55m
kube-flannel-ds-kn9bs 1/1 Running 0 55m
kube-flannel-ds-m2pc9 1/1 Running 0 35m
kube-flannel-ds-r4v2w 1/1 Running 0 59m
kube-flannel-ds-sxzs9 1/1 Running 0 55m
kube-proxy-6pb85 1/1 Running 0 35m
kube-proxy-8q772 1/1 Running 0 33m
kube-proxy-f56d4 1/1 Running 0 56m
kube-proxy-gmz5d 1/1 Running 0 56m
kube-proxy-m9qnf 1/1 Running 0 56m
kube-proxy-qzzwf 1/1 Running 0 61m
kube-scheduler-k8s-master-01 1/1 Running 0 61m
kube-scheduler-k8s-master-02 1/1 Running 0 30m
kube-scheduler-k8s-master-03 1/1 Running 0 28m
至此,一个高可用的Kubernetes集群已成功部署。