上个月我在 VMware 里准备一套学习用的 Kubernetes 实验环境,顺手把镜像仓库也一起规划进去了。当时选型没怎么纠结,直接定成 openEuler 22.03 LTS SP4 作为宿主机系统,集群用 kubeadm 方式部署 Kubernetes,镜像仓库用 Harbor。整套环境跑下来,从系统安装到集群初始化、Harbor 上线、再到工作负载从私有仓库拉镜像验证,一共花了两天时间。这篇文章把整个部署过程按我实际操作的顺序整理出来,包括版本选型的理由、VMware 虚拟机配置、openEuler 系统初始化、containerd 的安装和 CRI 调用原理、kubeadm 初始化集群、Calico 网络插件、Harbor 的 Helm 部署,以及集群从 Harbor 拉取镜像的完整链路验证。适合手里有测试机想完整复现一遍的运维工程师,也适合准备考 CKA 但缺一套干净环境练手的人。
1. 部署前准备:版本选型、VMware 虚拟机配置与 openEuler 系统初始化
1.1 为什么选 openEuler 22.03 LTS SP4 + Kubernetes 1.28 + Harbor 2.8?
先说版本选型。openEuler 我选了 22.03 LTS SP4,这是一个长期支持版本,x86_64 的 dvd.iso 镜像在官方镜像站直接下就行,文件名类似 openEuler-22.03-LTS-SP4-x86_64-dvd.iso。LTS 版本意味着生命周期长,不会出现刚装完系统就发现源已经不维护的情况。SP4 是 22.03 这个大版本下的第四个补丁版本,内核相对成熟,对 Kubernetes 和容器运行时这种对内核参数敏感的系统兼容性比较好。
Kubernetes 版本我选的是 1.28.x。为什么不追最新版?因为学习测试环境最重要的是生态兼容稳定。Harbor 的 Helm Chart、Calico 网络插件、Dashboard 都有各自的版本适配节奏,选一个发布半年以上的 Kubernetes 小版本,所有周边组件版本都能找到明确的兼容组合。1.28 的 kubeadm 初始化流程非常成熟,网上踩坑资料也最多,遇到问题容易查。
Harbor 我选的 2.8 以上版本,配合 Helm Chart 的 1.12 或 1.13 版本。Harbor 从 2.x 开始默认就是 OCI 分发规范,和 containerd 的对接非常顺滑。学习环境不需要用到镜像复制、漏洞扫描这些重量级功能,但自带的项目隔离、机器人账户、Webhook 这些功能足够让你理解生产环境里镜像仓库的基本模型。
另外一点是这套系统硬件配置不高也扛得住。Master 节点 4C8G、Worker 节点 2C4G 就能跑完整套环境,磁盘 50G 起步,Harbor 默认要跑 Postgres、Redis、Registry、Core、Portal 等多个容器,内存吃紧的话会频繁触发 OOM,这一点后面排障部分我会细说。
1.2 VMware 虚拟机配置与系统安装流程
虚拟机我用的是 VMware Workstation,如果是国产化环境或者公司统一用 FusionCompute,套路是一样的,关键是虚拟机的配置参数。
新建虚拟机的配置我直接参考下面的参数:
- 操作系统类型:Linux,内核版本选 Red Hat Enterprise Linux 8 64 位(openEuler 和 RHEL 系兼容)
- CPU:4 核
- 内存:8GB(实测在 4GB 下能跑但很紧张,Harbor 一起部署的话建议 8GB)
- 磁盘:60GB(系统装完大概占 10GB,镜像仓库数据会慢慢涨)
- 网络:NAT 模式或桥接模式,NAT 模式更省事,但一定要在 VMware 的虚拟网络编辑器里固定网段,避免宿主机 DHCP 动态分配导致 IP 漂移
安装过程里有两个容易踩坑的地方。第一个是分区,openEuler 的图形安装器默认分区方案是 LVM,如果你后续要调整磁盘或者扩容目录,LVM 是必要的;但学习环境建议直接把 / var 和 / 放一块,不要单独分 /home,避免后续镜像数据把根分区占满后一头雾水。第二个是安装源验证,如果镜像下载不完整,安装器会在读取软件包时报错,建议下完镜像后校验一下 sha256sum。
系统安装完成后,用 root 登录,第一件事就是配置 yum 源。openEuler 官方源一般可以直接用,但有时候在公司网络环境下访问速度很难受,我习惯用国内镜像源替换。先备份原有的 repo 文件:
bash复制cp -a /etc/yum.repos.d /etc/yum.repos.d.bak
rm -f /etc/yum.repos.d/*.repo
然后创建 openEuler 的镜像源配置,以 22.03 LTS SP4 x86_64 为例,核心配置是这样:
ini复制[openEuler-everything]
name=openEuler 22.03 LTS SP4 everything
baseurl=https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS-SP4/everything/x86_64/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-22.03-LTS-SP4/everything/x86_64/RPM-GPG-KEY-openEuler
执行 yum makecache 缓存元数据,随后用 yum install -y vim wget tar lrzsz bash-completion 装一批基础工具。
1.3 系统初始化:关闭防火墙、禁用 swap、配置内核参数
这一步是整个部署的基础,很多集群起不来或者网络异常,追根溯源都是系统初始化没做干净。我按照 kubeadm 官方文档的要求逐项配置。
第一项,关闭防火墙。openEuler 默认安装并启动 firewalld,Kubernetes 的 kube-proxy 用的是 iptables 或 ipvs 模式,和 firewalld 的 nftables 后端有时会冲突,而且测试环境什么端口都要通,直接禁用最省心:
bash复制systemctl stop firewalld
systemctl disable firewalld
第二项,禁用 swap。Kubernetes 从 1.28 开始虽然可以在开启 swap 的状态下运行 kubelet,但那是实验特性,学习环境不要自找麻烦。直接用注释掉 fstab 里的 swap 行:
bash复制sed -i '/swap/s/^/#/' /etc/fstab
swapoff -a
第三项,配置内核参数。这里有两个必须打开的参数,一个是 net.ipv4.ip_forward,这是 kube-proxy 和容器网络转发的基础;另一个是 net.bridge.bridge-nf-call-iptables,保证经过 Linux 网桥的流量能被 iptables 规则处理。先加载 br_netfilter 模块:
bash复制modprobe br_netfilter
echo 'modprobe br_netfilter' >> /etc/rc.local
chmod +x /etc/rc.local
echo "br_netfilter" > /etc/modules-load.d/k8s.conf
然后写入 sysctl 配置:
bash复制cat > /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
sysctl --system
如果你在初始化之后发现 Pod 网络跨节点不通,大概率是这两个内核参数没有生效。建议在这里先确认一下:
bash复制sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward
输出结果都应该是 1。
第四项,检查 SELinux。openEuler 默认安装的 SELinux 状态可能为开启,虽然 kubeadm 在 EL8 系的系统上会自动处理,但为了减少不确定性,我还是直接设置为 permissive 或 disabled。改 /etc/selinux/config,把 SELINUX=enforcing 改成 SELINUX=permissive,然后重启系统。生产环境你别这么干,但学习测试环境完全没有问题。
1.4 静态 IP、主机名与 hosts 解析规划
Kubernetes 集群的节点之间通信全靠主机名解析,这一步规划不好后面全是坑。
我在这套环境里规划了三台虚拟机:
- k8s-master:192.168.100.101,4C8G
- k8s-worker1:192.168.100.102,2C4G
- k8s-worker2:192.168.100.103,2C4G
三台机器全部安装 openEuler 22.03 LTS SP4。每台机器用 nmcli 配置静态 IP,以 master 为例:
bash复制nmcli connection modify ens160 ipv4.addresses 192.168.100.101/24
nmcli connection modify ens160 ipv4.gateway 192.168.100.2
nmcli connection modify ens160 ipv4.dns 192.168.100.2
nmc
