当前位置:首页 > 技术 > 正文内容

基于Kubeadm在Ubuntu 20.04上构建高可用Kubernetes集群

访客 技术 2026年10月3日 1

本文将详细介绍如何在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集群已成功部署。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。