(一)master 和 slave 集群环境配置
集群使用环境为 Mac、UTM 虚拟机、Ubuntu 24.04 LTS ARM64 架构 镜像源、root 用户
- 本章出现的 IP 不得照抄,需要按实际 IP 进行填写
- Windows 用户,可以让 AI 重写此文件,以此达到配置集群的目的
master、slave 虚拟机 均开启了共享主机网络功能,并在主机使用脚本让虚拟机自动监听 梯子 开放的端口,以此达到拉取外网镜像源能力
- 脚本可以用 AI 生成,目的只有一个,那就是开放一个端口提供给虚拟机使其能访问外网
master 机器为控制平面,master 初始化后,root 的 kubectl 配置固定为 /root/.kube/config;kubeadm token 使用控制平面上的 /etc/kubernetes/admin.conf
下面配置 master、slave 双机 Kubernetes 集群
一 配置主机网段
master 主机
root@master:~# hostname
master
root@master:~# ip -4 -br addr
lo UNKNOWN 127.0.0.1/8
enp0s1 UP 192.168.64.2/24 metric 100
docker0 DOWN 172.17.0.1/16
root@master:~# ip route
default via 192.168.64.1 dev enp0s1 proto dhcp src 192.168.64.2 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.64.0/24 dev enp0s1 proto kernel scope link src 192.168.64.2 metric 100
192.168.64.1 dev enp0s1 proto dhcp scope link src 192.168.64.2 metric 100
root@master:~#
slave 主机
root@slave:~# hostname
slave
root@slave:~# ip -4 -br addr
lo UNKNOWN 127.0.0.1/8
enp0s1 UP 192.168.64.3/24 metric 100
docker0 DOWN 172.17.0.1/16
root@slave:~# ip route
default via 192.168.64.1 dev enp0s1 proto dhcp src 192.168.64.3 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.64.0/24 dev enp0s1 proto kernel scope link src 192.168.64.3 metric 100
192.168.64.1 dev enp0s1 proto dhcp scope link src 192.168.64.3 metric 100
root@slave:~#
分别在各自的 /etc/hosts 中加入双方的主机 ip master 主机
127.0.0.1 localhost
192.168.64.2 master
192.168.64.3 slave
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
slave 主机
127.0.0.1 localhost
192.168.64.2 master
192.168.64.3 slave
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
需要确保双方能够互相 ping 通(ping master、ping slave 不丢包)。
二 改造环境
以下命令应该在 master 与 slave 机器上执行
2.1 配置 UTM 宿主机代理
创建 root 专用的代理环境文件:
cat > /root/.utm-proxy-env <<'EOF'
export HTTP_PROXY='http://192.168.64.1:17897'
export HTTPS_PROXY='http://192.168.64.1:17897'
export http_proxy='http://192.168.64.1:17897'
export https_proxy='http://192.168.64.1:17897'
export NO_PROXY='127.0.0.1,localhost,::1,master,slave,192.168.64.0/24,10.96.0.0/12,10.244.0.0/16,.svc,.svc.cluster.local,.cluster.local'
export no_proxy="$NO_PROXY"
unset ALL_PROXY all_proxy
EOF
grep -qxF 'source /root/.utm-proxy-env' /root/.bashrc || \
echo 'source /root/.utm-proxy-env' >> /root/.bashrc
source /root/.utm-proxy-env
APT 使用独立配置,避免环境变量是否被继承造成差异:
cat > /etc/apt/apt.conf.d/99-utm-proxy <<'EOF'
Acquire::http::Proxy "http://192.168.64.1:17897";
Acquire::https::Proxy "http://192.168.64.1:17897";
EOF
nc -vz 192.168.64.1 17897
curl -fsSI https://pkgs.k8s.io | head
NO_PROXY 中包含节点网段、Service 网段和 Pod 网段,因此外网 HTTP/HTTPS 请求走代理,master:6443 和 Kubernetes 集群内部地址保持直连
2.2 准备 Linux 节点
# 更新系统并安装基础工具
apt-get update
apt-get install -y ca-certificates curl gpg bash-completion netcat-openbsd
dpkg --print-architecture
# 关闭 Swap
swapoff -a
sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
swapon --show
# 加载内核模块
tee /etc/modules-load.d/k8s.conf >/dev/null <<'EOF'
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# 配置内核网络参数
tee /etc/sysctl.d/k8s.conf >/dev/null <<'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
# 输出应为 1
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward
这些配置的目的,是把普通 Linux 主机调整为适合 Kubernetes 节点运行的环境:关闭 Swap 保证 kubelet 能准确进行内存资源管理;加载 overlay 支持容器镜像的分层文件系统;加载 br_netfilter 并开启 bridge-nf-call-iptables,让 Pod 经过 Linux Bridge 的流量能够被 iptables/netfilter 处理;开启 ip_forward,让节点具备转发 Pod 网络数据包的能力,从而支持跨 Pod、跨节点通信
三 安装并配置 containerd
以下命令应该在 master 与 slave 机器上执行
# 安装 containerd
apt-get install -y containerd
install -d -m 0755 /etc/containerd
containerd config default | tee /etc/containerd/config.toml >/dev/null
# 使用 systemd cgroup
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# containerd 是独立的 systemd 服务,必须单独配置代理才能拉取镜像
install -d -m 0755 /etc/systemd/system/containerd.service.d
cat > /etc/systemd/system/containerd.service.d/10-utm-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://192.168.64.1:17897"
Environment="HTTPS_PROXY=http://192.168.64.1:17897"
Environment="NO_PROXY=127.0.0.1,localhost,::1,master,slave,192.168.64.0/24,10.96.0.0/12,10.244.0.0/16,.svc,.svc.cluster.local,.cluster.local"
EOF
systemctl daemon-reload
systemctl enable --now containerd
systemctl restart containerd
# 检查服务
systemctl is-active containerd
ctr version
systemctl show containerd -p Environment --no-pager
grep -n 'SystemdCgroup = true' /etc/containerd/config.toml
应该输出 active ,以及 SystemdCgroup = true

目的是为 Kubernetes 安装并配置**容器运行时 containerd**。Kubernetes 本身不直接创建和运行容器,而是由 kubelet 通过 CRI 调用 containerd 来完成镜像拉取、容器创建、启动和停止等操作;生成 /etc/containerd/config.toml 是为了建立默认配置;设置 SystemdCgroup = true 是让 containerd 和 kubelet 统一使用 systemd` 管理 cgroup,避免资源管理方式不一致;最后启动并检查 containerd,确认容器运行时已经正常工作
四 安装 kubeadm、kubelet、kubectl
以下命令应该在 master 与 slave 机器上执行
# 添加 Kubernetes 1.36 软件仓库
install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key \
| gpg --dearmor --yes -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:/v1.36/deb/ /' \
| tee /etc/apt/sources.list.d/kubernetes.list >/dev/null
# 安装并锁定版本
apt-mark unhold kubelet kubeadm kubectl 2>/dev/null || true
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
systemctl enable --now kubelet
# 检查版本
kubeadm version -o short
kubelet --version
kubectl version --client
# 输出版本
v1.36.3
Kubernetes v1.36.3
Client Version: v1.36.2
Kustomize Version: v5.8.1
五 创建 kubeadm 配置文件
以下命令只在 master 机器上执行
# 创建配置文件
MASTER_IP="$(ip -4 route get 1.1.1.1 | awk '{for (i=1; i<=NF; i++) if ($i=="src") {print $(i+1); exit}}')"
K8S_VERSION="$(kubeadm version -o short)"
: "${MASTER_IP:?无法取得控制平面 IP}"
: "${K8S_VERSION:?无法取得 Kubernetes 版本}"
printf 'MASTER_IP=%s\nK8S_VERSION=%s\n' "$MASTER_IP" "$K8S_VERSION"
cat > kubeadm-config.yaml <<EOF
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "${MASTER_IP}"
bindPort: 6443
nodeRegistration:
name: master
criSocket: unix:///run/containerd/containerd.sock
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: "${K8S_VERSION}"
controlPlaneEndpoint: "master:6443"
networking:
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF
# 检查文件
cat kubeadm-config.yaml
kubeadm config validate --config kubeadm-config.yaml
六 初始化 master
以下命令只在 master 机器上执行
# 拉取镜像
kubeadm config images pull --config kubeadm-config.yaml
# 初始化集群并保存日志
set -o pipefail
kubeadm init --config kubeadm-config.yaml --upload-certs --v=5 \
| tee kubeadm-init.out
# 为 root 配置 kubectl
install -d -m 0700 /root/.kube
install -o root -g root -m 0600 \
/etc/kubernetes/admin.conf /root/.kube/config
# 验证 API Server
kubectl cluster-info
kubectl get nodes -o wide
# 确认直连 API Server
curl -k --noproxy '*' https://master:6443/livez
kubectl get nodes -o wide
第一条为 `ok`;第二条中 master 显示 `NotReady` 为正常。
保留 kubeadm join master:6443 --token xxxxx --discovery-token-ca-cert-hash xxxx !!!
七 安装 Calico 网络插件
以下命令只在 master 机器上执行
# 下载 Calico 清单
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/calico.yaml
# 使用清单
kubectl apply -f calico.yaml
# 观察 Pod 启动过程
# 当 calico-node、calico-kube-controllers、coredns 都进入 Running 即可退出
kubectl get pods -n kube-system -w
# 检查节点,master 从 NotReady 变为 Ready
kubectl get nodes -o wide
八 将 slave 加入集群
以下命令注意区分 master 与 slave 机器上执行
# 使用上述保留的 token;如果丢失,在 master 重新生成
# kubeadm token create --print-join-command
# 在 slave 中加入 token
kubeadm join master:6443 --token xxxx --discovery-token-ca-cert-hash xxxx
# 回到 master 机器检查
kubectl get nodes -o wide
kubectl get pods -A -o wide
master、slave 均存在且为 Ready
九 验证集群可用性
以下命令只在 master 机器上执行
# 创建 Deployment 和 Service
kubectl create deployment web --image=nginx:alpine
kubectl expose deployment web --port=80
kubectl rollout status deployment/web --timeout=120s
kubectl get pods -o wide
kubectl get service web
# 测试 Pod 访问 Service
kubectl run curl-test \
--image=curlimages/curl:latest \
--restart=Never --rm -it \
-- curl -s http://web
# 清理验证资源
kubectl delete deployment web
kubectl delete service web
能正常返回 Nginx HTML,则代表配置成功,可以清理验证资源了

安装 Dashboard
Dashboard 是管理 Kubernetes 集群的 Web UI,以下命令在 master 机器执行
# 检查 helm 版本
helm version
# 安装 Dashboard
DASHBOARD_CHART_URL='https://github.com/kubernetes-retired/dashboard/releases/download/kubernetes-dashboard-7.14.0/kubernetes-dashboard-7.14.0.tgz'
helm upgrade --install kubernetes-dashboard \
"$DASHBOARD_CHART_URL" \
--namespace kubernetes-dashboard \
--create-namespace \
--wait \
--timeout 10m
# 检查 Helm Release、Pod 和 Service
# helm list 中的状态应为 deployed
# Dashboard 的 API、Auth、Web、Metrics Scraper 和 Kong Pod 应为 Running
# Service kubernetes-dashboard-kong-proxy 应监听 443/TCP
helm list --namespace kubernetes-dashboard
kubectl --namespace kubernetes-dashboard wait \
--for=condition=Ready pod \
--all \
--timeout=600s
# Dashboard 会默认挂载到 slave 机器上
kubectl --namespace kubernetes-dashboard get pods,service -o wide
以下步骤非常重要,因为 Dashboard 需要使用 Token 进行校验登陆,所以此 Token 需保存
# 创建管理员 ServiceAccount
kubectl --namespace kubernetes-dashboard \
create serviceaccount dashboard-admin \
--dry-run=client -o yaml \
| kubectl apply -f -
# 授予 cluster-admin 权限
kubectl create clusterrolebinding dashboard-admin \
--clusterrole=cluster-admin \
--serviceaccount=kubernetes-dashboard:dashboard-admin \
--dry-run=client -o yaml \
| kubectl apply -f -
# 创建长期 Token
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Secret
metadata:
name: dashboard-admin-token
namespace: kubernetes-dashboard
annotations:
kubernetes.io/service-account.name: dashboard-admin
type: kubernetes.io/service-account-token
EOF
# 等待 master 把 Token 写入 Secret
kubectl --namespace kubernetes-dashboard wait \
--for=jsonpath='{.data.token}' \
secret/dashboard-admin-token \
--timeout=60s
# 每次登陆,执行此命令,将输出的 Token 粘贴到暴露的 URL 即可
kubectl --namespace kubernetes-dashboard \
get secret dashboard-admin-token \
--output=jsonpath='{.data.token}' \
| base64 --decode
printf '\n'
# 通过打印出的节点进入 DashBoard 界面
MASTER_IP="$(
ip -4 route get 1.1.1.1 \
| awk '{for (i=1; i<=NF; i++) if ($i=="src") {print $(i+1); exit}}'
)"
kubectl --namespace kubernetes-dashboard \
get service kubernetes-dashboard-kong-proxy
printf 'Dashboard 地址:https://%s:30443\n' "$MASTER_IP"
可以看到 Dashboard 也是非常好看的,

总结
本章实现了 master、slave 双机 k8s 集群,当然只是属于学习阶段,真实环境中需要配置的机器不只有一台,难度会往上增加
但核心是不变的,那就是 保持冷静,遇到问题,解决问题就好了
愿诸君顺遂