一、整体思路与部署原理说明
在开始动手之前,先梳理一下Kubernetes集群部署的整体思路。K8s集群本质上是由一组节点组成的分布式系统,其中master节点负责集群的调度、控制和管理,worker节点负责实际运行业务容器。整个部署过程可以拆解为四个关键环节:镜像仓库准备、基础环境配置、集群初始化、网络插件安装。
为什么需要先搭建Harbor镜像仓库?因为 Kubernetes 集群中的各个组件(如 kube-apiserver、kube-controller-manager、kube-scheduler 等)都是以容器镜像的形式运行的。在国内网络环境下,直接从官方源拉取镜像往往不稳定,因此我们先把所需镜像同步到本地 Harbor 仓库,后续所有节点都从内网仓库拉取,既保证了速度,也保证了版本的一致性。
部署方式上,这里采用 kubeadm工具进行集群初始化。kubeadm是Kubernetes官方提供的集群部署工具,它把复杂的证书生成、组件配置、节点注册等过程封装成了标准化的命令,大大降低了部署门槛。整个部署链路可以概括为:Harbor仓库提供镜像 → 各节点安装容器运行时(Docker + cri-dockerd)→ kubeadm 初始化 master → 工作节点加入集群 → 安装网络插件打通 Pod 通信。
二、构建Harbor镜像仓库
1. 部署Docker本地仓库
Harbor本身以容器方式运行,因此需要先准备Docker环境。这里先在Harbor节点上搭建一个内网 Yum 仓库,用于后续向集群各节点分发Docker安装包,避免每台机器都从外网下载。
bash
[root@harbor ~]# cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name = docker
baseurl = https://mirrors.aliyun.com/docker-ce/linux/rhel/9.6/x86_64/stable/
gpgcheck = 0
EOF
[root@harbor ~]# dnf install httpd createrepo-y
[root@harbor ~]# mkdir /var/www/html/docker/ -p
[root@harbor ~]# vim /etc/httpd/conf/httpd.conf
Listen 4444
[root@harbor ~]# systemctl enable --now httpd
[root@harbor ~]# dnf install docker-ce -downloadonly --destdir /mnt/ -y
[root@harbor ~]# mv /mnt/*.rpm /var/www/html/docker/
[root@harbor ~]# createrepo -v /var/www/html/docker/
[root@harbor ~]# cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name = docker
baseurl = http://172.25.254.254:4444/docker
gpgcheck = 0
EOF
[root@harbor ~]# dnf install docker-ce -y
这里用 Apache 的4444端口提 RPM包下载服务,createrepo生成仓库元数据,这样集群内其他节点就能通过 Yum 源直接安装 Docker。
2. 安装Docker并配置内核参数
bash
[root@harbor ~]# dnf install docker-ce -y
[root@harbor ~]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
[root@harbor ~]# modprobe -a br_netfilter
[root@harbor ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
[root@harbor ~]# systemctl restart systemd-modules-load.service
[root@harbor ~]# sysctl --system
[root@harbor ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@harbor ~]# systemctl daemon-reload
[root@harbor ~]# systemctl enable --now docker
这里有一个关键点需要说明:br_netfilter 模块和 bridge-nf-call-iptables参数是 Kubernetes 网络通信的基础。K8s 的 Service 和网络策略依赖 iptables 规则,而这些规则需要能穿透 Linux 网桥,所以必须显式开启这些内核参数,否则集群内部Pod之间的通信会出现异常。
3. 生成HTTPS证书
bash
[root@harbor ~]# mkdir /data/certs -p
[root@harbor ~]# openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout /data/certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \
-x509 -days 365 -out /data/certs/timinglee.org.crt
Harbor 默认要求HTTPS访问,因此需要为域名 reg.timinglee.org 生成自签名证书。证书生成后,后续所有节点都要信任这个CA,Docker 才能从 Harbor 正常拉取镜像。
4. 编辑Harbor配置文件并启动
bash
[root@harbor ~]# tar zxf harbor-offline-installer-v2.5.4.tgz -C /opt/
[root@harbor ~]# cd /opt/harbor/
[root@harbor harbor]# cp harbor.yml.tmpl harbor.yml
[root@harbor harbor]# vim harbor.yml
hostname: reg.timinglee.org
certificate: /data/certs/timinglee.org.crt
private_key: /data/certs/timinglee.org.key
harbor_admin_password: lee
[root@harbor harbor]# ./install.sh --with-chartmuseum
Harbor 的配置文件核心是 hostname 和证书路径,hostname 必须与证书中的域名一致,否则客户端校验会失败。安装完成后,为了方便管理,把 Harbor 注册为 systemd 服务,这样开机就能自动启动。
5. 验证Harbor仓库可用性
bash
[root@harbor harbor]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
[root@harbor harbor]# cp /data/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
[root@harbor harbor]# vim /etc/hosts
172.25.254.200 harbor reg.timinglee.org
[root@harbor harbor]# systemctl restart docker
[root@harbor harbor]# docker compose up -d
[root@harbor harbor]# docker login reg.timinglee.org -u admin
Password:
Login Succeeded
验证的关键在于把 Harbor 的证书放到 Docker 的证书信任目录中,这样 Docker 客户端才会信任这个自签名仓库。登录成功说明 Harbor 仓库已经可以正常使用了。
三、构建部署Kubernetes所需主机
集群规划如下,共四台主机,分别承担镜像仓库、控制节点和工作节点的角色:
| 主机名 | IP | 配置 | 角色 |
|---|---|---|---|
| harbor.timinglee.org | 172.25.254.254 | CPU 1核、内存 1G | Harbor 仓库 |
| master-node | 172.25.254.100 | CPU 4核、内存 4G以上 | Master,K8s 集群控制节点 |
| node1 | 172.25.254.10 | CPU 2核、内存 2G | Worker,K8s 集群工作节点 |
| node2 | 172.25.254.20 | CPU 2核、内存 2G | Worker,K8s 集群工作节点 |
1. 所有主机基础配置
所有节点都需要执行以下基础配置,包括关闭 swap、安装 Docker、配置 Harbor 仓库信任、配置镜像加速器以及主机名解析。
bash
# 关闭swap
systemctl disable --now swap.target
systemctl mask swap.target
sed '/swap/s/^/#/g' -i /etc/fstab
配置可以使用harbor仓库
mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
在harbor主机中分发证书到所有主机
[root@harbor ~]# for i in 100 10 20
> do
> scp /data/certs/timinglee.org.crt root@172.25.254.$i:/etc/docker/certs.d/reg.timinglee.org/ca.crt
> done
systemctl enable docker
systemctl restart docker
所有主机配置docker加速器
cat >/etc/docker/daemon.json <<EOF
{
"registry-mirrors":["https://reg.timinglee.org"]
}
EOF
systemctl restart docker
所有主机彼此建立解析
vim /etc/hosts
172.25.254.100 master
172.25.254.10 node1
172.25.254.20 node2
172.25.254.200 reg.timinglee.org
所有主机配置kubernetes安装源
vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name = kubernetes
baseurl = https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.35/rpm/
gpgcheck = 0
检测
dnf list kubelet
这里说明一下为什么必须关闭 swap:Kubernetes 的调度器在分配 Pod 时基于节点的可用内存做决策,如果系统启用了 swap,kubelet 的内存判断就会失真,可能导致节点上运行了超出实际内存能力的 Pod,引发 OOM 甚至节点不稳定。因此 K8s 官方要求所有节点必须关闭 swap。
四、Kubernetes集群部署
1. 安装cri-dockerd(所有主机)
Kubernetes 从 1.24 版本开始移除了对 Docker 的直接支持,需要通过 cri-dockerd 这个适配层,把 Docker 的容器运行时接口转换成 Kubernetes 的 CRI 标准接口。这里提供两种安装方式:RPM 包方式和二进制包方式。
bash
# 方式一:RPM包部署
[root@master ~]# rpm -ivh cri-dockerd-0.3.14-3.el8.x86_64.rpm libcgroup-0.41-19.el8.x86_64.rpm
vim /lib/systemd/system/cri-docker.service
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1
方式二:二进制包部署
[root@docker-node1 ~]# wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.4/cri-dockerd-0.4.4.amd64.tgz
[root@docker-node1 ~]# tar zxf cri-dockerd-0.4.4.amd64.tgz
[root@docker-node1 cri-dockerd]# install -o root -g root -m 0755 cri-dockerd /usr/local/bin/cri-dockerd
[root@docker-node1 cri-dockerd]# cp cri-docker.s* /lib/systemd/system
[root@docker-node1 cri-dockerd]# vim /lib/systemd/system/cri-docker.service
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1 --container-runtime-endpoint fd://
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
[root@docker-node1 cri-dockerd]# systemctl daemon-reload
[root@docker-node1 cri-dockerd]# systemctl enable --now cri-docker.service
这里有一个细节值得注意:cri-dockerd 启动参数中指定了 pause 镜像地址为 reg.timinglee.org/k8s/pause:3.10.1。pause 镜像是每个 Pod 的基础容器,负责持有 Pod 的网络命名空间,所有业务容器共享这个命名空间。把它指向本地 Harbor,可以避免节点从外网拉取。
2. 安装Kubernetes集群所需软件
bash
# master节点
dnf install kubelet kubeadm kubectl -y
systemctl enable --now kubelet.service
node节点
dnf install kubelet kubeadm -y
systemctl enable --now kubelet.service
master节点中 kubectl 和kubeadm 补齐
[root@master ~]# echo "source <(kubectl completion bash)" >> ~/.bashrc
[root@master ~]# echo "source <(kubeadm completion bash)" >> ~/.bashrc
[root@master ~]# source ~/.bashrc
三个组件的分工需要说明一下:kubelet 是运行在每个节点上的代理,负责管理 Pod 的生命周期;kubeadm 是集群初始化工具,只在部署阶段使用;kubectl 是命令行管理工具,在 master 节点上用来查看和控制集群状态。
3. 下载Kubernetes集群所需镜像并上传到Harbor
bash
# 查看所需镜像列表
[root@k8s-master ~]# kubeadm config images list
registry.k8s.io/kube-apiserver:v1.35.7
registry.k8s.io/kube-controller-manager:v1.35.7
registry.k8s.io/kube-scheduler:v1.35.7
registry.k8s.io/kube-proxy:v1.35.7
registry.k8s.io/coredns/coredns:v1.13.1
registry.k8s.io/pause:3.10.1
registry.k8s.io/etcd:3.6.6-0
从阿里云镜像源拉取
[root@master ~]# kubeadm config images pull
--image-repository registry.aliyuncs.com/google_containers
--kubernetes-version v1.35.7
--cri-socket=unix:///var/run/cri-dockerd.sock
上传镜像到本地harbor
[root@master ~]# docker login reg.timinglee.org -u admin
[root@master ~]# docker images --format "{{.Repository}}:{{.Tag}}" | awk -F "/" '/google/{system("docker tag "$0" reg.timinglee.org/k8s/"$3)}'
[root@master ~]# docker images --format "{{.Repository}}:{{.Tag}}" | awk -F "/" '/timinglee/{system("docker push "$0)}'
这一步是整个部署中比较关键的一环。kubeadm 初始化集群时,需要从镜像仓库拉取 apiserver、etcd、coredns 等组件镜像。由于这些镜像默认从 registry.k8s.io 拉取,在国内网络环境下基本不可用,所以先通过阿里云镜像源拉取,再重新打标签上传到本地 Harbor。这样集群初始化时就能从内网快速拉取,同时保证所有节点使用的镜像版本完全一致。
4. 在Master中初始化Kubernetes集群
bash
[root@master ~]# kubeadm init --pod-network-cidr=10.244.0.0/16 \
--image-repository reg.timinglee.org/k8s \
--kubernetes-version v1.35.7 \
--cri-socket=unix:///var/run/cri-dockerd.sock
初始化成功后,其他主机加入本集群的凭证
kubeadm join 172.25.254.100:6443 --token tdwjoc.8d1yw3wl4r4tm6c4
--discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927
如果忘记join命令
[root@master ~]# kubeadm token create --print-join-command
如果初始化出问题,可以重置集群设定
[root@master ~]# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
添加kubernets环境变量到本机
[root@master ~]# echo "export KUBECONFIG=/etc/kubernetes/admin.conf" > ~/.bash_profile
[root@master ~]# source ~/.bash_profile
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 102s v1.35.3
这里对几个关键参数做一下说明。--pod-network-cidr 指定了 Pod 网络的地址段,这里使用 10.244.0.0/16,这是 flannel 网络插件的默认网段,两者必须保持一致,否则网络插件无法正常工作。--image-repository 指定从本地 Harbor 拉取镜像。--cri-socket 指定 cri-dockerd 的 socket 路径,告诉 kubeadm 使用哪个容器运行时接口。
初始化完成后,需要把 KUBECONFIG 环境变量指向 admin.conf,这样 kubectl 才能找到集群的认证信息。此时节点状态是 NotReady,这是正常的,因为还没有安装网络插件。
5. 添加Node节点到集群
bash
[root@node1 ~]# kubeadm join 172.25.254.100:6443 --token jl4ztx.cax3iysvu7onsh5s --discovery-token-ca-cert-hash sha256:6b5950ef2cdba85d6dfdb564ee90d4187fa3d341767dc9852cbdd5c9dee4f927 --cri-socket=unix:///var/run/cri-dockerd.sock
测试
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane 5m16s v1.35.3
node1 NotReady <none> 66s v1.35.3
node2 NotReady <none> 58s v1.35.3
工作节点通过 kubeadm join 命令加入集群,token 和证书哈希是 master 初始化时生成的凭证。加入后节点状态同样是 NotReady,原因和 master 一样,等待网络插件就绪后才会变为 Ready。
6. 安装Flannel网络插件
bash
[root@k8s-master ~]# tar zxf kube-flannel-v0.28.9.tar.gz
[root@k8s-master ~]# cd flannel/
[root@k8s-master flannel]# docker load -i kube-flannel-v0.28.9.tar
上传flannel镜像到本地harbor
[root@master ~]# docker tag ghcr.io/flannel-io/flannel-cni-plugin:v1.9.0-flannel1 reg.timinglee.org/flannel-io/flannel-cni-plugin:v1.9.0-flannel1
[root@master ~]# docker push reg.timinglee.org/flannel-io/flannel-cni-plugin:v1.9.0-flannel1
[root@master ~]# docker tag ghcr.io/flannel-io/flannel:v0.28.1 reg.timinglee.org/flannel-io/flannel:v0.28.1
[root@master ~]# docker push reg.timinglee.org/flannel-io/flannel:v0.28.1
修改kube-flannel.yml中的镜像地址为本地harbor
[root@master ~]# vim kube-flannel.yml
image: flannel-io/flannel:v0.28.1
image: flannel-io/flannel-cni-plugin:v1.9.0-flannel1
[root@master ~]# kubectl apply -f kube-flannel.yml
测试
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane 13m v1.35.3
node1 Ready <none> 9m44s v1.35.3
node2 Ready <none> 9m36s v1.35.3
Flannel 是 Kubernetes 的容器网络接口(CNI)插件,负责为每个 Pod 分配 IP 地址,并在节点之间建立 Overlay 网络。它的工作原理是:每个节点上的 flanneld 进程从 10.244.0.0/16 网段中划分一个子网,通过 VXLAN 隧道把不同节点上的 Pod 网络打通。安装完成后,所有节点状态变为 Ready,说明集群已经可以正常工作了。
五、附加:利用Ansible自动化部署Kubernetes运行环境
手动部署虽然能帮助理解原理,但步骤繁琐且容易出错。这里补充一种自动化方式,利用 Ansible 把前面所有的基础环境配置、Docker 安装、cri-dockerd 部署和 K8s 软件安装固化成剧本,实现一键部署。
1. 安装Ansible并配置运行环境
bash
[root@harbor ~]# vim /etc/yum.repos.d/epel.repo
[epel]
name = epel
baseurl = https://mirrors.aliyun.com/epel/9/Everything/x86_64/
gpgcheck = 0
[root@harbor ~]# dnf install ansible-core.x86_64 ansible.noarch -y
[root@harbor ~]# useradd devops
[root@harbor ~]# echo lee | passwd --stdin devops
[root@harbor ~]# su - devops
[devops@harbor ~]$ mkdir ansible
[devops@harbor ~]$ cd ansible/
生成inventory主机清单
[devops@harbor ansible]$ vim inventory
[servers]
172.25.254.100
172.25.254.20
172.25.254.10
生成ansible.cfg配置文件
[devops@harbor ansible]$ vim ansible.cfg
[defaults]
inventory = /home/devops/ansible/inventory
remote_user = root
ask_pass = false
host_key_checking = false
测试连通性
[devops@harbor ansible]$ ansible all -m ping
Ansible 采用无代理架构,通过 SSH 协议管理远程主机,控制端只需要安装 Ansible 本身,被管理节点无需安装任何额外软件。inventory 文件定义了要管理的主机列表,ansible.cfg 配置了连接参数。
2. 利用Ansible剧本部署Docker
bash
[devops@harbor ansible]$ vim kubernetes-devops.yml
- name: devops k8s from ansible
hosts: all
tasks:
- name: setup docker repo
yum_repository:
name: docker
description: docker
baseurl: http://172.25.254.254:4444/docker
file: docker
gpgcheck: no
name: install docker
dnf:
name: docker-ce
state: present
name: setup docker.service
replace:
path: /lib/systemd/system/docker.service
regexp: "ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock"
replace: "ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true"
name: setup docker registry
copy:
content: |
{
"registry-mirrors":["https://reg.timinglee.org"]
}
dest: /etc/docker/daemon.json
name: setup docker certs
file:
path: /etc/docker/certs.d/reg.timinglee.org
state: directory
name: cp certs file
copy:
src: "{{item.src}}"
dest: "{{item.dest}}"
loop:
src: /etc/docker/certs.d/reg.timinglee.org/ca.crt
dest: /etc/docker/certs.d/reg.timinglee.org/ca.crt
src: /etc/docker/certs.d/reg.timinglee.org/ca.crt
dest: /etc/pki/ca-trust/source/anchors/ca.crt
name: load module
copy:
dest: "{{item.dest}}"
content: "{{item.value}}"
loop:
dest: /etc/modules-load.d/docker_mod.conf
value: br_netfilter
dest: /etc/sysctl.d/docker.conf
value: |
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
name: update ca cert
shell: "update-ca-trust extract;sysctl --system"
name: start services
service:
name: "{{item}}"
state: restarted
enabled: yes
loop:
docker
systemd-modules-load.service
[devops@harbor ansible]$ ansible-playbook kubernetes-devops.yml
这个剧本把前面手动执行的 Docker 安装、内核参数配置、证书分发、镜像加速器配置等步骤全部封装成了 Ansible 任务。yum_repository 模块配置 Yum 源,dnf 模块安装软件包,copy 模块分发证书和配置文件,service 模块管理服务状态。通过循环和变量,一份剧本可以同时作用于所有节点。
3. 利用Ansible安装cri-dockerd
bash
[devops@harbor ansible]$ tar zxf cri-dockerd-0.4.4.amd64.tgz
[devops@harbor ansible]$ cd cri-dockerd/
[devops@harbor cri-dockerd]$ vim cri-docker.service
[Service]
Type=notify
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=reg.timinglee.org/k8s/pause:3.10.1
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
[devops@harbor ansible]$ vim kubernetes-devops.yml
name: devops k8s from ansible
hosts: all
tasks:
name: stup cri-dockerd
copy:
src: "{{item.src}}"
dest: "{{item.dest}}"
mode: '0755'
loop:
src: ./cri-dockerd/cri-dockerd
dest: /usr/bin/cri-dockerd
src: "./cri-dockerd/cri-docker.service"
dest: "/lib/systemd/system/cri-docker.service"
src: "./cri-dockerd/cri-docker.socket"
dest: "/lib/systemd/system/cri-docker.socket"
name: update ca cert
shell: "update-ca-trust extract;sysctl --system;systemctl daemon-reload"
name: start services
service:
name: "{{item}}"
state: restarted
enabled: yes
loop:
docker
systemd-modules-load.service
cri-docker
[devops@harbor ansible]$ ansible-playbook kubernetes-devops.yml
cri-dockerd 的部署同样通过 copy 模块把二进制文件和 systemd 服务文件分发到所有节点,然后启动服务。这里把 cri-docker 加入服务管理列表,确保开机自启。
4. 利用Ansible部署K8s软件
bash
[devops@harbor ansible]$ vim kubernetes-devops.yml
- name: install kubernetes from ansible
hosts: all
tasks:
- name: setup k8s repo
yum_repository:
name: kubernetes
description: kubernetes
baseurl: https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.35/rpm
file: kubernetes
gpgcheck: no
name: install software in master
dnf:
name: "{{item}}"
state: present
loop:
kubeadm-1.35.7-150500.1.1
kubelet-1.35.7-150500.1.1
kubectl-1.35.7-150500.1.1
when: inventory_hostname == "172.25.254.100"
name: install software in work node
dnf:
name: "{{item}}"
state: present
loop:
kubeadm-1.35.7-150500.1.1
kubelet-1.35.7-150500.1.1
when: inventory_hostname == "172.25.254.10" or inventory_hostname == "172.25.254.20"
name: setup kubectl kubeadm complication
lineinfile:
path: /root/.bashrc
line: |
source <(kubectl completion bash)
source <(kubeadm completion bash)
when: inventory_hostname == "172.25.254.100"
name: start kubelet
service:
name: kubelet
state: started
enabled: yes
[devops@harbor ansible]$ ansible-playbook kubernetes-devops.yml
这个剧本利用 when 条件判断,区分 master 和 worker 节点安装不同的软件包。master 节点额外安装 kubectl 并配置命令补齐,worker 节点只安装 kubelet 和 kubeadm。通过 Ansible 的幂等特性,重复执行剧本不会产生副作用,这比手动操作更可靠。
六、总结
整个 K8s 集群部署的核心链路可以概括为:先搭建 Harbor 镜像仓库解决镜像分发问题,再统一配置所有节点的 Docker 环境和内核参数,然后通过 cri-dockerd 让 Kubernetes 能够使用 Docker 作为容器运行时,最后用 kubeadm 初始化集群并安装 flannel 网络插件打通 Pod 网络。
手动部署的价值在于理解每个组件的作用和它们之间的依赖关系,而 Ansible 自动化部署的价值在于把成熟的部署流程固化下来,实现可重复、可维护的集群交付。建议先手动完整走一遍流程,再尝试用 Ansible 脚本化,这样既能理解原理,又能提升效率。