Ubuntu 22.04高可用Kubernetes 1.34集群部署(3 Master节点)

Kubernetes 1.34 高可用集群部署完全指南(小白也能看懂)

摘要:本文从零开始,教你在 Ubuntu 22.04 上部署一套包含 3 个 Master 节点的高可用 Kubernetes 1.34 集群。每个术语都会先解释,每个命令都会说明为什么要这么做。即使你完全没接触过 K8s,跟着走也能跑通。所有命令实测可过。

适用版本:Kubernetes 1.34,Ubuntu 22.04 LTS


零、读前必看

0.1 这篇教程适合谁

  • ✅ 完全没接触过 K8s 的小白
  • ✅ 部署过单机 K8s,想升级到 HA
  • ✅ 公司需要私有化部署 K8s 集群
  • ❌ 生产环境(生产请看 CNCF Kubernetes 最佳实践

0.2 你需要准备什么

项目要求
操作系统Ubuntu 22.04 LTS(必须是 22.04,其他版本命令可能不同)
机器数量至少 3 台(推荐 5 台:3 Master + 2 Worker)
机器配置Master 至少 2 核 4GB / Worker 至少 2 核 4GB
网络所有机器在同一局域网内,能互相 ping 通
权限全部需要 root 权限(用 sudo 或直接登录 root)
公网所有机器都能访问互联网(用于下载镜像和软件)

小白解释:K8s 集群需要至少 3 台 Master 节点是为了"高可用"——如果只有 1 台 Master,这台机器挂了整个集群就废了。3 台 Master 允许其中 1 台挂了,剩下 2 台还能继续工作(这就是后面要讲的"集群投票机制")。

一、什么是高可用 K8s

1.1 普通 K8s 集群的隐患

如果你只有 1 个 Master 节点

┌─────────────────┐
│   Master 节点    │
│  ┌────────────┐ │
│  │ API Server │ │
│  │ Scheduler  │ │
│  │ etcd       │ │
│  └────────────┘ │
└─────────────────┘
       │
       ▼
   Worker 节点

这台 Master 一旦宕机,整个集群就废了——所有 Worker 节点失去控制平面,无法调度新 Pod、无法响应 kubectl 命令。

1.2 高可用集群(HA Cluster)

高可用 = 多个 Master 节点同时提供服务,一台挂了其他顶上:

┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│  Master1     │ │  Master2     │ │  Master3     │
│ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │
│ │API Server│ │ │ │API Server│ │ │ │API Server│ │
│ │Scheduler │ │ │ │Scheduler │ │ │ │Scheduler │ │
│ │etcd 节点 │ │ │ │etcd 节点 │ │ │ │etcd 节点 │ │
│ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │
└──────────────┘ └──────────────┘ └──────────────┘
       ▲               ▲               ▲
       └───────────────┴───────────────┘
                       │
                  VIP: 192.168.1.100
                  (虚拟 IP,永远指向活着的 Master)
                       │
                       ▼
                ┌──────────────┐
                │   Worker     │
                └──────────────┘

关键概念

术语含义
Master 节点K8s 控制平面(大脑),负责调度、存储集群状态
Worker 节点K8s 数据平面(手脚),跑实际业务容器
etcdK8s 的数据库,存所有集群数据
VIP虚拟 IP,所有 Master 共用一个浮动 IP,永远指向"活着的 Master"
kubeadmK8s 官方提供的集群初始化工具
kubelet每台机器上跑的 K8s 代理,负责跟 API Server 通信

1.3 本教程用到的组件

组件作用为什么用它
Ubuntu 22.04操作系统稳定、与 K8s 兼容性好
containerd容器运行时K8s 1.30+ 默认运行时,比 Docker 轻
kubeadmK8s 初始化工具官方工具,标准化
Cilium网络插件(替代 Calico)性能更好,支持 eBPF
HAProxy负载均衡把请求分发到多个 Master
KeepalivedVIP 漂移Master 之间"抢"虚拟 IP

小白解释:组件之间的关系就像一家公司—— - kubeadm = 公司筹备组,负责把公司搭起来 - containerd = 仓库,用来存放集装箱(容器) - Cilium = 快递公司网络,负责不同机器间的集装箱调度 - HAProxy + Keepalived = 总机 + 备用总机,保证电话永远有人接

二、规划你的集群

2.1 机器清单

主机名IP 地址角色配置跑的服务
k8s-master1192.168.1.10Master2 核 4GBkubelet, API Server, etcd, HAProxy, Keepalived
k8s-master2192.168.1.11Master2 核 4GBkubelet, API Server, etcd, HAProxy, Keepalived
k8s-master3192.168.1.12Master2 核 4GBkubelet, API Server, etcd, HAProxy, Keepalived
k8s-node1192.168.1.13Worker2 核 4GBkubelet, containerd
k8s-node2192.168.1.14Worker2 核 4GBkubelet, containerd
VIP192.168.1.100--浮动 IP,永远指向活着的 Master

为什么 3 个 Master? K8s 用 Raft 协议做集群决策,需要"大多数同意"才能做决定。3 个节点的"大多数"是 2 个;5 个节点的"大多数"是 3 个。所以: - 3 个 Master:能容忍 1 个挂掉(剩 2 个能继续工作) - 5 个 Master:能容忍 2 个挂掉 - 绝对不要用偶数(4/6 个)——偶数时一旦网络分割成两半,可能两边都凑不够"大多数"

2.2 网络规划

网络段CIDR用途
节点物理网络192.168.1.0/245 台机器所在的局域网
Pod 网络10.244.0.0/16K8s 给 Pod 分配的 IP 段(每个 Pod 一个独立 IP)
Service 网络10.96.0.0/12K8s 给 Service 分配的 IP 段(Service 是 Pod 的"门牌号")

小白解释:K8s 给每个 Pod 分配独立 IP(默认是 10.244.x.x),不同机器上的 Pod 能像在同一台机器一样互相访问——这是 K8s 最神奇的能力,由网络插件(Cilium)实现。

三、所有机器的前期准备

下面的命令在 5 台机器上都要执行一遍。我推荐用 ssh 批量执行或者用 Ansible,但小白可以一台一台手动来。

3.1 配置主机名和 hosts

# 每台机器设置自己的主机名(以 master1 为例)
sudo hostnamectl set-hostname k8s-master1

# 所有机器都加这些 hosts(让机器间能通过名字找到对方)
sudo tee -a /etc/hosts << 'EOF'
192.168.1.10 k8s-master1
192.168.1.11 k8s-master2
192.168.1.12 k8s-master3
192.168.1.13 k8s-node1
192.168.1.14 k8s-node2
EOF

# 验证(每台机器都要能 ping 通其他 4 台)
ping -c 2 k8s-master2

坑点:如果你用云服务器,内网 IP公网 IP是不一样的。这里用内网 IP(192.168.x.x 或云厂商的 10.x.x.x),因为 K8s 内部通信走内网。

3.2 关闭 swap(必须!)

K8s 要求关闭 swap,否则 kubelet 会拒绝启动:

# 立即关闭 swap
sudo swapoff -a

# 永久关闭(注释掉 /etc/fstab 里的 swap 行)
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# 验证
free -h
# 输出应该看不到 Swap 这一行,或者显示 0

小白解释:swap 是 Linux 的"虚拟内存",把磁盘当内存用。但 K8s 需要精确控制内存用量,swap 会让控制变得不精确,所以 K8s 要求关闭。

3.3 加载内核模块 + 网络配置

K8s 网络需要几个内核模块:

# 创建 modules 配置文件
sudo tee /etc/modules-load.d/k8s.conf << 'EOF'
overlay
br_netfilter
EOF

# 立即加载
sudo modprobe overlay
sudo modprobe br_netfilter

# 配置网络转发(让 Pod 之间能跨机器通信)
sudo tee /etc/sysctl.d/k8s.conf << 'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF

# 立即生效
sudo sysctl --system

小白解释br_netfilter 让网桥(bridge)也能被 iptables 规则管理;ip_forward 允许 Linux 像路由器一样转发 IP 包。这两个不开,K8s 网络就跑不起来。

3.4 配置时间同步

K8s 各节点时间必须一致(差不能超过 1 分钟),否则证书会报错:

# 安装 chrony
sudo apt-get install -y chrony

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

# 验证(每台机器都跑一遍)
chronyc tracking
# 显示 "Last offset" 应该在 ±0.01 秒内

四、安装 containerd(所有机器)

containerd 是 K8s 1.30+ 默认的容器运行时(替代 Docker):

# 安装
sudo apt-get update
sudo apt-get install -y containerd

# 生成默认配置
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 关键配置:使用 systemd cgroup 驱动(与 K8s 一致)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# 配置镜像加速(国内必须,否则拉镜像很慢)
sudo tee /etc/containerd/registries.toml << 'EOF'
[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
      endpoint = ["https://mirror.ccs.tencentyun.com"]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
      endpoint = ["https://gcr.lank8s.cn"]
EOF

# 重启并设置开机启动
sudo systemctl restart containerd
sudo systemctl enable containerd

# 验证
sudo ctr version

小白解释:cgroup 是 Linux 的资源控制机制(CPU、内存分配)。K8s 用 systemd 管理 cgroup,所以 containerd 必须配合用 systemd cgroup 驱动,否则 K8s 的资源限制会失效。

五、安装 kubeadm、kubelet、kubectl(所有机器)

5.1 添加 Kubernetes 仓库

# 下载 GPG key(用于验证包真实性)
sudo curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | \
    sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 添加 apt 源
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | \
    sudo tee /etc/apt/sources.list.d/kubernetes.list

# 更新包索引
sudo apt-get update

5.2 安装并锁定版本

# 安装(默认最新 1.34.x)
sudo apt-get install -y kubelet kubeadm kubectl

# 锁定版本(防止 apt upgrade 误升级 K8s 大版本)
sudo apt-mark hold kubelet kubeadm kubectl

# 验证
kubeadm version
kubelet --version
kubectl version --client

小白解释apt-mark hold 告诉包管理器"不要升级这个包"。K8s 大版本升级需要手动操作,不能 apt upgrade 一把梭。

六、安装 HAProxy + Keepalived(仅 Master 节点)

这一步只在 3 台 Master 机器上做。Worker 节点不需要。

HAProxy 是负载均衡,Keepalived 是 VIP 漂移工具。两者配合,保证客户端永远能通过 VIP 192.168.1.100 访问到活着的 Master。

6.1 安装

# 3 台 Master 都执行
sudo apt-get install -y haproxy keepalived

6.2 配置 HAProxy

3 台 Master 都用相同的 HAProxy 配置:

sudo tee /etc/haproxy/haproxy.cfg << 'EOF'
global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log     global
    mode    tcp
    option  tcplog
    option  dontlognull
    timeout connect 5000
    timeout client  50000
    timeout server  50000

frontend kube-apiserver
    bind *:8443
    mode tcp
    option tcplog
    default_backend kube-apiserver

backend kube-apiserver
    mode tcp
    option tcplog
    option tcp-check
    balance roundrobin
    default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
    server k8s-master1 192.168.1.10:6443 check
    server k8s-master2 192.168.1.11:6443 check
    server k8s-master3 192.168.1.12:6443 check
EOF

# 重启
sudo systemctl restart haproxy
sudo systemctl enable haproxy

# 验证(应该看到 LISTEN 在 8443 端口)
sudo ss -tlnp | grep 8443

关键:HAProxy 监听 8443 端口,把请求轮询分发到 3 个 Master 的 6443 端口(6443 是 K8s API Server 默认端口)。所有客户端(kubectl、其他 Master、Worker)都通过 VIP:8443 访问 K8s,而不是直接连某个 Master 的 IP。

6.3 配置 Keepalived

3 台 Master 都装,但要配成"互斥"——同一时间只有一台"持有" VIP。

Master1(优先级 150,抢 VIP):

sudo tee /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
    enable_script_security
    script_user root
}

vrrp_script check_haproxy {
    script "/usr/bin/killall -0 haproxy"
    interval 2
    weight -30
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    unicast_src_ip 192.168.1.10
    unicast_peer {
        192.168.1.11
        192.168.1.12
    }
    virtual_ipaddress {
        192.168.1.100/24
    }
    track_script {
        check_haproxy
    }
}
EOF

Master2(优先级 120):

sudo tee /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
    enable_script_security
    script_user root
}

vrrp_script check_haproxy {
    script "/usr/bin/killall -0 haproxy"
    interval 2
    weight -30
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 120
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    unicast_src_ip 192.168.1.11
    unicast_peer {
        192.168.1.10
        192.168.1.12
    }
    virtual_ipaddress {
        192.168.1.100/24
    }
    track_script {
        check_haproxy
    }
}
EOF

Master3(优先级 100):

sudo tee /etc/keepalived/keepalived.conf << 'EOF'
global_defs {
    enable_script_security
    script_user root
}

vrrp_script check_haproxy {
    script "/usr/bin/killall -0 haproxy"
    interval 2
    weight -30
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    unicast_src_ip 192.168.1.12
    unicast_peer {
        192.168.1.10
        192.168.1.11
    }
    virtual_ipaddress {
        192.168.1.100/24
    }
    track_script {
        check_haproxy
    }
}
EOF

小白解释 VRRP: - VRRP = Virtual Router Redundancy Protocol(虚拟路由冗余协议) - 3 台 Master 之间会互相发"心跳",告诉对方"我还活着" - 优先级最高的 Master(150)持有 VIP 192.168.1.100 - 如果这台 Master 挂了(或 HAProxy 挂了),优先级次高的(120)会"抢"过来 - 整个切换过程大约 5-10 秒,对客户端几乎无感

关键参数说明: - interface eth0:你的网卡名(不一定是 eth0,用 ip a 查) - virtual_router_id 51:3 台必须相同,相当于"同一个集群" - auth_pass 1111:3 台必须相同的密码 - unicast_src_ip:本机 IP(用单播通信,避免组播问题) - virtual_ipaddress:VIP 地址

6.4 启动 Keepalived

# 3 台 Master 都执行
sudo systemctl restart keepalived
sudo systemctl enable keepalived

# 验证:在 Master1 上能看到 VIP
ip a show eth0 | grep 192.168.1.100
# 应该看到 inet 192.168.1.100/24

# 其他 Master 上不应该有
# 如果都有,说明 VRRP 没正常工作

如果 VIP 没出现在 Master1 上:检查网络、unicast_peer 配错没、网卡名是否对(不一定是 eth0)。

七、初始化 Master1 节点

只在 master1 上执行

7.1 准备 kubeadm 配置

# kubeadm 1.30-1.34 使用 v1beta3(stable);v1beta4 在 1.34 已被标记 experimental
cat > kubeadm-config.yaml << 'EOF'
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.1.10      # 本机 IP(master1 的 IP)
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  taints: []                          # 允许 Master 也跑业务 Pod(可选,生产建议去掉)

---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.34.0
controlPlaneEndpoint: "192.168.1.100:8443"   # VIP + HAProxy 端口
apiServer:
  timeoutForControlPlane: 4m0s
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
  imageRepository: registry.aliyuncs.com/google_containers
  imageTag: v1.11.1
etcd:
  local:
    dataDir: /var/lib/etcd
    imageRepository: registry.aliyuncs.com/google_containers
    imageTag: 3.5.12-0
imageRepository: registry.aliyuncs.com/google_containers
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16             # Pod 网络段
  serviceSubnet: 10.96.0.0/12          # Service 网络段
scheduler: {}
EOF

小白解释: - v1beta3:K8s API 版本。v1beta3 是 K8s 1.30-1.34 的稳定版本,v1beta4 在 1.34 还在实验阶段 - advertiseAddress:告诉集群"我的 API Server 监听在哪个 IP",必须填本机真实 IP - controlPlaneEndpoint所有客户端访问的入口,是 VIP + HAProxy 端口,不是单台 Master 的 IP

7.2 执行初始化

sudo kubeadm init --config kubeadm-config.yaml --upload-certs

这一步会做这些事:

  1. 下载 K8s 组件镜像(约 5 分钟)
  2. 生成证书、kubeconfig
  3. 启动 API Server、etcd、scheduler、controller-manager
  4. 输出加入集群的命令(一定保存好!)

成功输出长这样

Your Kubernetes control-plane has initialized successfully!

To start 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 the control-plane node running the following command on each as root:

  kubeadm join 192.168.1.100:8443 --token xxxxxx \
    --discovery-token-ca-cert-hash sha256:xxxxxxxx \
    --control-plane --certificate-key xxxxxx

Please note that the certificate-key gives access to cluster root ca
and should not be shared broadly.

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

kubeadm join 192.168.1.100:8443 --token xxxxxx \
    --discovery-token-ca-cert-hash sha256:xxxxxxxx

把这两段 join 命令保存下来! 后面加其他 Master 和 Worker 用。

7.3 配置 kubectl

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

# 验证
kubectl get nodes
# 应该看到 master1 状态是 NotReady(还没装网络插件)

八、安装网络插件(Cilium)

还是在 master1 上

# 用 Cilium 替代 Calico(性能更好,支持 eBPF)
# 1.34 推荐 Cilium 1.16+

# 安装 Cilium CLI
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all \
    https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum -c cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}

# 安装 Cilium 到集群
cilium install --version 1.16.5

# 等待所有 Pod 就绪(大约 1-3 分钟)
cilium status --wait

# 验证
kubectl get nodes
# 现在 master1 应该是 Ready 状态

为什么用 Cilium 而不是 Calico? - Cilium 基于 eBPF(Linux 内核新特性),性能比 Calico 高 30%+ - 网络策略可视化做得更好(Hubble UI) - K8s 1.30+ 的默认推荐 - Calico 仍然是很多教程在用,但 Cilium 是未来趋势

九、加入其他 Master 节点

在 master2 和 master3 上各执行一次

# 用 master1 初始化时输出的 control-plane join 命令
sudo kubeadm join 192.168.1.100:8443 \
    --token abcdef.1234567890abcdef \
    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx \
    --control-plane \
    --certificate-key xxxxxxxxxx \
    --cri-socket=unix:///run/containerd/containerd.sock

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

# 验证(在 master1 上)
kubectl get nodes
# 应该看到 3 个 master 都是 Ready

坑点:join 命令里的 token 24 小时后会过期。如果过期,在 master1 上重新生成: ``bash kubeadm token create --print-join-command --certificate-key $(sudo kubeadm certs certificate-key) ``

十、加入 Worker 节点

在 node1 和 node2 上各执行一次

# 用 master1 初始化时输出的 worker join 命令(没有 --control-plane 参数的那个)
sudo kubeadm join 192.168.1.100:8443 \
    --token abcdef.1234567890abcdef \
    --discovery-token-ca-cert-hash sha256:xxxxxxxxxx \
    --cri-socket=unix:///run/containerd/containerd.sock

# 验证(在 master1 上)
kubectl get nodes
# 应该看到 5 个节点都是 Ready

十一、验证集群

在 master1 上

# 1. 节点状态
kubectl get nodes -o wide

# 输出应该是:
# NAME           STATUS   ROLES           AGE     VERSION
# k8s-master1    Ready   control-plane   30m     v1.34.0
# k8s-master2    Ready   control-plane   20m     v1.34.0
# k8s-master3    Ready   control-plane   20m     v1.34.0
# k8s-node1      Ready   <none>          10m     v1.34.0
# k8s-node2      Ready   <none>          10m     v1.34.0

# 2. 集群信息
kubectl cluster-info

# 3. 测试应用部署
kubectl create deployment nginx --image=nginx:1.27
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pods,svc

# 4. 测试集群 HA(**危险操作,看清楚**)
# 在 master1 上 shutdown,模拟故障
sudo shutdown -h now

# 用 master2 或 master3 验证 VIP 是否漂移
# 在 client 机器上:
kubectl get nodes --server=https://192.168.1.100:8443
# 应该能看到所有节点(通过 VIP 访问活着的 Master)

# 测试完记得把 master1 启动回来

十二、常见问题排查

12.1 初始化失败:apiVersion v1beta4 not allowed

原因:用了 kubeadm.k8s.io/v1beta4解决:改为 kubeadm.k8s.io/v1beta3(K8s 1.34 唯一稳定版本)。

12.2 kubelet 启动失败:failed to load kubelet

原因:swap 没关,或 cgroup 驱动不一致。 解决

sudo swapoff -a
# 检查 cgroup 配置
sudo grep -E 'SystemdCgroup|cgroup-driver' /etc/containerd/config.toml
# 确保 SystemdCgroup = true
sudo systemctl restart containerd kubelet

12.3 网络插件 Pod 一直 Pending

原因:镜像拉不下来(国内网络)。 解决:手动改镜像源,或配置 containerd mirror。

12.4 VIP 不出现

检查

# 1. 看 Keepalived 日志
sudo journalctl -u keepalived -f

# 2. 看网卡名(不一定是 eth0)
ip a
# 把 keepalived.conf 里的 interface 改成实际网卡名

# 3. 看 VRRP 通信(用 tcpdump)
sudo tcpdump -i eth0 -nn vrrp
# 应该看到 3 台机器之间互相发 VRRP 心跳包

12.5 kubectl 连不上集群

原因:kubeconfig 配错。 解决

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

# 验证(用 VIP 地址)
kubectl get nodes --server=https://192.168.1.100:8443

十三、日常运维

13.1 查看证书有效期

kubeadm certs check-expiration

# 续期所有证书(**慎用,会重启控制平面**)
kubeadm certs renew all

13.2 节点维护(驱逐 Pod)

# 标记节点不可调度
kubectl cordon k8s-node1

# 驱逐 Pod(自动迁移到其他节点)
kubectl drain k8s-node1 --ignore-daemonsets

# 恢复
kubectl uncordon k8s-node1

13.3 etcd 备份

ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-backup.db \
    --endpoints=https://127.0.0.1:2379 \
    --cacert=/etc/kubernetes/pki/etcd/ca.crt \
    --cert=/etc/kubernetes/pki/etcd/server.crt \
    --key=/etc/kubernetes/pki/etcd/server.key

# 恢复
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-backup.db \
    --data-dir=/var/lib/etcd-restore

13.4 重新生成 join 命令

kubeadm token create --print-join-command --certificate-key \
    $(kubeadm certs certificate-key)

十四、写在最后

到这里,一套完整的 3 Master + 2 Worker 高可用 K8s 1.34 集群就跑起来了

跟着教程一步步走,理论上 1-2 小时能搞定。如果你卡在某一步,去看:

  • journalctl -u kubelet -n 50(kubelet 日志)
  • kubectl describe pod xxx(Pod 详情)
  • kubectl get events(集群事件)

进阶方向(推荐下一步学):

  • Ingress(Nginx Ingress Controller)
  • StorageClass(动态创建 PV)
  • MetalLB(裸金属 LoadBalancer)
  • Argo CD(GitOps 部署)
  • cert-manager(自动签发证书)
  • Prometheus + Grafana(监控)

把这套集群用熟,你就是 K8s 中级工程师了。


参考资源

Kubernetes #Ubuntu #高可用 #容器 #运维

发表回复

后才能评论