在裸机内网环境中部署 Kubernetes 时,最容易卡住的通常不是 Pod 本身,而是入口流量、LoadBalancer 地址分配、证书、Service 与 Gateway 之间的关系。本文记录一套两节点开发环境的完整落地路径:从 kubeadm 初始化集群,到安装 Calico、MetalLB、Envoy Gateway,再到通过独立域名暴露 Kite 管理界面。
适用环境
本文示例基于以下环境:
- Ubuntu Server 26.04
- Kubernetes v1.36.x
- kubeadm
- containerd
- Calico CNI
- Envoy Gateway
- MetalLB Layer 2
- Harbor
- Kite Kubernetes Web UI
- 1 个控制平面节点和 1 个工作节点
- 裸机内网,节点位于同一个二层网段
示例拓扑如下:
| 角色 |
主机名 |
IP |
| 控制平面 |
k8s-master-1 |
192.168.110.200 |
| 工作节点 |
k8s-node-1 |
192.168.110.201 |
| 工作节点 |
k8s-node-2 |
192.168.110.202 |
MetalLB 地址池建议预留:
1
| 192.168.110.230-192.168.110.240
|
这些 IP 必须满足以下条件:
- 不与任何主机冲突
- 不在 DHCP 地址池内
- 与 Kubernetes 节点处于同一个 VLAN 或二层网络
- 已经和网络管理员确认可以使用
总体架构
开发环境推荐链路如下:
1 2 3 4 5 6 7 8 9 10 11
| Calico | MetalLB Layer 2 | Envoy Gateway | HTTPRoute / TLSRoute | Kubernetes Service | Deployment
|
组件选择:
- Gateway API 使用标准 CRD 通道。
- Gateway Controller 使用 Envoy Gateway。
- 裸机 LoadBalancer 使用 MetalLB Layer 2。
- TLS 在开发环境使用自签名证书,测试和生产环境使用 cert-manager 或企业 CA。
- Kite 使用单独域名访问,不建议挂在
/kite 子路径下。
当前场景不建议仅为了 Gateway API 更换 Calico。只有当项目计划同时引入 eBPF、Cilium NetworkPolicy、Cilium Service LB 和 Cilium Gateway API 时,再考虑整体迁移到 Cilium。
Harbor 前置要求
在 Harbor 中创建项目:
建议将项目设为 Public,但通过防火墙、路由或访问控制限制 Harbor 仅允许内网访问。 这是为了让 kubeadm 启动的静态 Pod 能在节点重启后自动拉取核心镜像,不依赖 Kubernetes 内的 imagePullSecrets。
先在三台节点确认 Harbor 证书、DNS 和网络正常:
1 2
| curl -sS -o /dev/null -w '%{http_code}\n' \ https://harbor.meatball.org.cn/v2/
|
返回 200 或 401 都说明 TLS 与网络正常。
若返回 x509: certificate signed by unknown authority,说明节点本身尚未信任 Harbor CA。将 CA 根证书安装到三台节点:
1 2 3 4 5
| install -Dm0644 /path/to/harbor-ca.crt \ /usr/local/share/ca-certificates/harbor-meatball.crt
update-ca-certificates systemctl restart containerd
|
不要配置 insecure_skip_verify。
节点规划
| 主机名 |
IP |
角色 |
k8s-master-1 |
192.168.110.200 |
控制平面 |
k8s-node-1 |
192.168.110.201 |
工作节点 |
k8s-node-2 |
192.168.110.202 |
工作节点 |
分别在对应节点设置变量:
1 2 3
| export NODE_NAME=k8s-master-1 export NODE_IP=192.168.110.200
|
1 2 3
| export NODE_NAME=k8s-node-1 export NODE_IP=192.168.110.201
|
1 2 3
| export NODE_NAME=k8s-node-2 export NODE_IP=192.168.110.202
|
三台节点初始化
三台节点都执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| set -euo pipefail
hostnamectl set-hostname "${NODE_NAME}"
grep -qF '192.168.110.200 k8s-master-1' /etc/hosts || \ echo '192.168.110.200 k8s-master-1' >> /etc/hosts
grep -qF '192.168.110.201 k8s-node-1' /etc/hosts || \ echo '192.168.110.201 k8s-node-1' >> /etc/hosts
grep -qF '192.168.110.202 k8s-node-2' /etc/hosts || \ echo '192.168.110.202 k8s-node-2' >> /etc/hosts
timedatectl set-ntp true
swapoff -a sed -ri '/\sswap\s/s/^/#/' /etc/fstab
systemctl disable --now ufw 2>/dev/null || true
modprobe overlay modprobe br_netfilter
cat >/etc/modules-load.d/kubernetes.conf <<'EOF' overlay br_netfilter EOF
cat >/etc/sysctl.d/99-kubernetes.conf <<'EOF' net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 net.ipv4.conf.all.rp_filter = 0 net.ipv4.conf.default.rp_filter = 0 EOF
sysctl --system
|
验证:
1 2 3 4 5
| hostnamectl --static swapon --show lsmod | grep -E 'overlay|br_netfilter' sysctl net.ipv4.ip_forward ip -4 addr show ens18
|
swapon --show 必须没有输出。
安装并配置 containerd
三台节点执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| apt-get update
apt-get install -y \ ca-certificates \ curl \ gpg \ apt-transport-https \ containerd \ conntrack \ socat \ ipset \ iptables \ iproute2 \ ethtool \ ebtables \ ipvsadm \ cri-tools
mkdir -p /etc/containerd
containerd config default >/etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' \ /etc/containerd/config.toml
systemctl enable --now containerd systemctl restart containerd
|
确认:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| containerd --version
grep -n -A5 -B2 'SystemdCgroup' \ /etc/containerd/config.toml
grep -n 'disabled_plugins' /etc/containerd/config.toml
systemctl is-active containerd
cat >/etc/crictl.yaml <<'EOF' runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false EOF
crictl info >/dev/null && echo 'containerd CRI 正常'
|
SystemdCgroup = true 是必须项;同时确认 disabled_plugins 中不包含 cri。(kubernetes.io)
安装 Kubernetes v1.36.3
三台节点执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| export K8S_VERSION=v1.36.3
mkdir -p -m 0755 /etc/apt/keyrings
curl -fsSL \ https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key \ | gpg --dearmor -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/ /' \ >/etc/apt/sources.list.d/kubernetes.list
apt-get update
K8S_DEB_VERSION="$(apt-cache madison kubeadm \ | awk '$3 ~ /^1\.36\.3-/ {print $3; exit}')"
test -n "${K8S_DEB_VERSION}"
echo "安装 Debian 包版本:${K8S_DEB_VERSION}"
apt-get install -y \ kubelet="${K8S_DEB_VERSION}" \ kubeadm="${K8S_DEB_VERSION}" \ kubectl="${K8S_DEB_VERSION}"
apt-mark hold kubelet kubeadm kubectl
systemctl enable kubelet
|
验证:
1 2 3 4
| kubeadm version kubelet --version kubectl version --client apt-mark showhold
|
同步 Kubernetes 与 Calico 镜像到 Harbor
只需在一台可访问外网和 Harbor 的机器执行,建议使用 k8s-master-1。
1 2 3 4 5 6 7 8 9 10 11
| export HARBOR=harbor.meatball.org.cn export HARBOR_PROJECT=k8s export K8S_VERSION=v1.36.3 export K8S_REPO="${HARBOR}/${HARBOR_PROJECT}/kubernetes" export CALICO_REPO="${HARBOR}/${HARBOR_PROJECT}" export SOURCE_REPO="registry.aliyuncs.com/google_containers" export TARGET_REPO="harbor.meatball.org.cn/k8s"
apt-get install -y skopeo
skopeo login "${HARBOR}"
|
输入 Harbor 账号或 Robot Account 的用户名和 Token。
Kubernetes 核心镜像
1 2 3 4 5 6 7 8
| mkdir -p /root/kubeadm
kubeadm config images list \ --kubernetes-version "${K8S_VERSION}" \ --image-repository "${SOURCE_REPO}" \ | tee /root/kubeadm/kubernetes-images.txt
cat /root/kubeadm/kubernetes-images.txt
|
同步:
1 2 3 4 5 6 7 8 9 10 11
| while read -r SOURCE_IMAGE; do RELATIVE_IMAGE="${SOURCE_IMAGE#${SOURCE_REPO}/}" TARGET_IMAGE="${K8S_REPO}/${RELATIVE_IMAGE}"
echo "同步:${SOURCE_IMAGE} -> ${TARGET_IMAGE}" skopeo copy --all \ "docker://${SOURCE_IMAGE}" \ "docker://${TARGET_IMAGE}" done </root/kubeadm/kubernetes-images.txt
|
Calico 镜像
Calico 官方的 v3.32.1 私有仓库清单包含以下镜像;本文会只启用基础网络组件,但建议全部同步,便于后续启用 Calico API、Whisker 或网关功能。(docs.tigera.io)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| cat >/root/kubeadm/calico-images.txt <<'EOF' quay.io/tigera/operator:v1.42.3 quay.io/calico/node:v3.32.1 quay.io/calico/cni:v3.32.1 quay.io/calico/typha:v3.32.1 quay.io/calico/csi:v3.32.1 quay.io/calico/node-driver-registrar:v3.32.1 quay.io/calico/apiserver:v3.32.1 quay.io/calico/kube-controllers:v3.32.1 quay.io/calico/envoy-gateway:v3.32.1 quay.io/calico/envoy-proxy:v3.32.1 quay.io/calico/envoy-ratelimit:v3.32.1 quay.io/calico/dikastes:v3.32.1 quay.io/calico/pod2daemon-flexvol:v3.32.1 quay.io/calico/key-cert-provisioner:v3.32.1 quay.io/calico/goldmane:v3.32.1 quay.io/calico/whisker:v3.32.1 quay.io/calico/whisker-backend:v3.32.1 EOF
|
1 2 3 4 5 6 7 8 9 10
| while read -r SOURCE_IMAGE; do RELATIVE_IMAGE="${SOURCE_IMAGE#quay.io/}" TARGET_IMAGE="${CALICO_REPO}/${RELATIVE_IMAGE}"
echo "同步:${SOURCE_IMAGE} -> ${TARGET_IMAGE}"
skopeo copy --all \ "docker://${SOURCE_IMAGE}" \ "docker://${TARGET_IMAGE}" done </root/kubeadm/calico-images.txt
|
验证 Harbor 镜像:
1 2 3 4 5 6 7
| skopeo inspect \ "docker://${K8S_REPO}/kube-apiserver:$(kubeadm config images list --kubernetes-version "${K8S_VERSION}" | awk -F: '/kube-apiserver/ {print $NF}')" \ --format '{{.Name}}:{{.Tag}}'
skopeo inspect \ "docker://${CALICO_REPO}/calico/node:v3.32.1" \ --format '{{.Name}}:{{.Tag}}'
|
在三台节点分别验证 containerd 能从 Harbor 拉取:
1 2 3 4 5 6 7 8 9 10
| export HARBOR=harbor.meatball.org.cn export K8S_REPO="${HARBOR}/k8s/kubernetes" export K8S_VERSION=v1.36.3
crictl pull "$( kubeadm config images list \ --kubernetes-version "${K8S_VERSION}" \ --image-repository "${K8S_REPO}" \ | head -n 1 )"
|
初始化控制平面
只在 k8s-master-1 执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| export HARBOR=harbor.meatball.org.cn export K8S_VERSION=v1.36.3 export K8S_REPO="${HARBOR}/k8s/kubernetes"
mkdir -p /root/kubeadm
cat >/root/kubeadm/kubeadm-config.yaml <<EOF apiVersion: kubeadm.k8s.io/v1beta4 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.110.200 bindPort: 6443 nodeRegistration: name: k8s-master-1 criSocket: unix:///run/containerd/containerd.sock kubeletExtraArgs: - name: node-ip value: 192.168.110.200 --- apiVersion: kubeadm.k8s.io/v1beta4 kind: ClusterConfiguration kubernetesVersion: ${K8S_VERSION} imageRepository: ${K8S_REPO} controlPlaneEndpoint: 192.168.110.200:6443 networking: podSubnet: 192.168.0.0/16 serviceSubnet: 10.96.0.0/12 dnsDomain: cluster.local apiServer: certSANs: - 192.168.110.200 - k8s-master-1 --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd EOF
|
修改 sandbox_image 为 Harbor 地址
编辑 /etc/containerd/config.toml,找到 sandbox_image 字段,改为:
1 2
| [plugins.'io.containerd.cri.v1.images'.pinned_images] sandbox = 'harbor.meatball.org.cn/k8s/kubernetes/pause:3.10.2'
|
重启 containerd
1 2
| systemctl daemon-reload systemctl restart containerd
|
验证配置是否生效
1
| containerd config dump | grep -A5 pinned_images
|
应显示 Harbor 地址。
验证配置与 Harbor 镜像地址:
1 2 3 4 5
| kubeadm config validate \ --config /root/kubeadm/kubeadm-config.yaml
kubeadm config images list \ --config /root/kubeadm/kubeadm-config.yaml
|
预拉镜像:
1 2 3 4
| kubeadm config images pull \ --config /root/kubeadm/kubeadm-config.yaml
crictl images | grep harbor.meatball.org.cn
|
初始化:
1 2 3 4
| kubeadm init \ --config /root/kubeadm/kubeadm-config.yaml \ --upload-certs \ | tee /root/kubeadm/kubeadm-init.log
|
配置 kubectl:
1 2 3 4 5 6 7 8 9 10
| mkdir -p "${HOME}/.kube"
cp -f /etc/kubernetes/admin.conf "${HOME}/.kube/config"
chown "$(id -u):$(id -g)" "${HOME}/.kube/config"
export KUBECONFIG="${HOME}/.kube/config"
kubectl get nodes kubectl get pods -n kube-system
|
此时 k8s-master-1 处于 NotReady 是正常的,因为尚未安装 CNI。
加入两个工作节点
在 master 生成加入命令:
1 2 3 4 5 6 7 8 9 10 11 12
| kubeadm token create \ --ttl 24h \ --print-join-command \ | tee /root/kubeadm/join-worker.sh
sed -i \ 's#$# --cri-socket unix:///run/containerd/containerd.sock#' \ /root/kubeadm/join-worker.sh
chmod 700 /root/kubeadm/join-worker.sh
cat /root/kubeadm/join-worker.sh
|
将输出的完整命令分别在 k8s-node-1 与 k8s-node-2 执行。
回到 master 验证:
1
| kubectl get nodes -o wide
|
安装 Calico
Calico 要使用私有仓库,必须:
- 将 Operator Manifest 中的
quay.io 改为 Harbor;
- 在
Installation.spec.registry 配置 Harbor 镜像前缀。(docs.tigera.io)
只在 master 执行:
1 2 3 4 5 6 7 8 9 10
| cd /root/kubeadm
curl -fsSLo tigera-operator.yaml \ https://raw.githubusercontent.com/projectcalico/calico/v3.32.1/manifests/tigera-operator.yaml
sed -i \ 's#quay.io/#harbor.meatball.org.cn/k8s/#g' \ tigera-operator.yaml
grep -n 'image:' tigera-operator.yaml
|
输出必须包含:
1
| harbor.meatball.org.cn/k8s/tigera/operator:v1.42.3
|
创建 Calico 网络配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cat >/root/kubeadm/calico-installation.yaml <<'EOF' apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: variant: Calico registry: harbor.meatball.org.cn/k8s calicoNetwork: ipPools: - name: default-ipv4-ippool blockSize: 26 cidr: 192.168.0.0/16 encapsulation: VXLAN natOutgoing: Enabled nodeSelector: all() EOF
|
安装:
1 2 3 4 5 6 7
| kubectl apply -f /root/kubeadm/tigera-operator.yaml
kubectl rollout status deployment/tigera-operator \ -n tigera-operator \ --timeout=5m
kubectl apply -f /root/kubeadm/calico-installation.yaml
|
观察状态:
另开一个终端执行:
1 2 3 4 5 6 7 8
| kubectl get tigerastatus
kubectl get nodes -o wide
kubectl get pods -n calico-system
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.spec.containers[*].image}{"\n"}{end}' \ | grep harbor.meatball.org.cn
|
最终三台节点应为 Ready。
集群网络验证
同步测试镜像到 Harbor:
1 2 3 4 5 6 7 8 9 10 11
| skopeo copy --all \ docker://swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 \ docker://harbor.meatball.org.cn/k8s/test/dnsutils:1.3
skopeo copy --all \ docker://swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.26.3-alpine \ docker://harbor.meatball.org.cn/k8s/library/nginx:1.26.3-alpine
skopeo copy --all \ docker://swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/curlimages/curl:8.21.0 \ docker://harbor.meatball.org.cn/k8s/curlimages/curl:8.21.0
|
DNS 验证:
1 2 3 4 5
| kubectl run dns-test \ --image=harbor.meatball.org.cn/k8s/test/dnsutils:1.3 \ --restart=Never \ --rm -it \ -- nslookup kubernetes.default
|
跨工作节点的服务验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| cat >/root/kubeadm/network-test.yaml <<'EOF' apiVersion: apps/v1 kind: Deployment metadata: name: nginx-test spec: replicas: 2 selector: matchLabels: app: nginx-test template: metadata: labels: app: nginx-test spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app: nginx-test topologyKey: kubernetes.io/hostname containers: - name: nginx image: harbor.meatball.org.cn/k8s/library/nginx:1.26.3-alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-test spec: selector: app: nginx-test ports: - port: 80 targetPort: 80 EOF
kubectl apply -f /root/kubeadm/network-test.yaml
kubectl rollout status deployment/nginx-test --timeout=5m
kubectl get pods -l app=nginx-test -o wide
kubectl run curl-test \ --image=harbor.meatball.org.cn/k8s/curlimages/curl:8.21.0 \ --restart=Never \ --rm -it \ -- curl -fsS http://nginx-test.default.svc.cluster.local
|
清理测试资源:
1
| kubectl delete -f /root/kubeadm/network-test.yaml
|
1 2 3 4
| export POD_NAME=$(kubectl get pods --namespace kube-system -l "app.kubernetes.io/name=kite,app.kubernetes.io/instance=kite" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace kube-system $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace kube-system port-forward $POD_NAME 8080:$CONTAINER_PORT --address 0.0.0.0
|
集群环境:k8s v1.36,containerd‑2.x,Calico;Harbor 项目k8s;helm>=3.8;使用 FRR‑K8s(helm chart 默认模式,官方推荐)。
MetalLB 组件镜像来源:quay.io/metallb/*,helm chart 是 helm repo 类型,先下载 chart 包,再同步业务镜像到私有 harbor。
🔴前置条件(必须先做,IPVS 模式必开 strictARP)
你的 k8s 集群 kube‑proxy 如果是 ipvs 模式,必须开启 strictARP=true,否则 MetalLB L2 模式 ARP 异常,LoadBalancer 无法正常工作。
1 2 3 4 5 6 7 8 9 10 11 12 13
| kubectl get configmap kube-proxy -n kube-system -o yaml | \ sed -e "s/strictARP: false/strictARP: true/" | \ kubectl diff -f - -n kube-system
kubectl get configmap kube-proxy -n kube-system -o yaml | \ sed -e "s/strictARP: false/strictARP: true/" | \ kubectl apply -f - -n kube-system
kubectl rollout restart daemonset kube-proxy -n kube-system kubectl get pods -n kube-system -l k8s-app=kube-proxy -w
|
iptables 模式集群可以跳过上面 strictARP 步骤。
1 2 3 4 5 6
| helm repo add metallb https://metallb.github.io/metallb helm repo update
helm pull metallb/metallb --version 0.16.1 --untar=false ls -lh metallb-0.16.1.tgz
|
查看 chart 需要哪些容器镜像
1
| helm show values metallb-0.16.1.tgz
|
v0.16.1 FRR‑K8s 模式用到镜像清单:
- quay.io/metallb/controller:v0.16.1
- quay.io/metallb/speaker:v0.16.1
- quay.io/frrouting/frr:9.1.0
使用 skopeo 同步全部业务镜像到你的 harbor:
使用 DaoCloud quay 代理规避 quay.io 匿名限流报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| skopeo copy --all \ docker://quay.m.daocloud.io/metallb/controller:v0.16.1 \ docker://harbor.meatball.org.cn/k8s/metallb/controller:v0.16.1
skopeo copy --all \ docker://quay.m.daocloud.io/metallb/speaker:v0.16.1 \ docker://harbor.meatball.org.cn/k8s/metallb/speaker:v0.16.1
skopeo copy --all \ docker://quay.m.daocloud.io/frrouting/frr:10.4.3 \ docker://harbor.meatball.org.cn/k8s/frrouting/frr:10.4.3
skopeo copy --all \ docker://quay.m.daocloud.io/metallb/frr-k8s:v0.0.25 \ docker://harbor.meatball.org.cn/k8s/metallb/frr-k8s:v0.0.25
|
校验镜像同步完成:
1 2 3
| skopeo inspect docker://harbor.meatball.org.cn/k8s/metallb/controller:v0.16.1 skopeo inspect docker://harbor.meatball.org.cn/k8s/metallb/speaker:v0.16.1 skopeo inspect docker://harbor.meatball.org.cn/k8s/frrouting/frr:9.1.0
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| cat >/root/kubeadm/values-metallb.yaml <<'EOF' controller: image: repository: harbor.meatball.org.cn/k8s/metallb/controller tag: v0.16.1 speaker: image: repository: harbor.meatball.org.cn/k8s/metallb/speaker tag: v0.16.1 frrk8s: image: repository: harbor.meatball.org.cn/k8s/frrouting/frr tag: 10.4.3 reloaderImage: repository: harbor.meatball.org.cn/k8s/metallb/frr-k8s tag: v0.0.25
namespaceLabels: podSecurityContext: runAsNonRoot: true runAsUser: 65534 fsGroup: 65534 namespaceLabels: pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/warn: privileged EOF
|
–create‑namespace 自动创建metallb‑system命名空间
1 2 3 4
| helm install metallb ./metallb-0.16.1.tgz \ -n metallb-system \ --create-namespace \ -f values-metallb.yaml
|
校验 pod 启动状态
1
| kubectl get pods -n metallb-system -w
|
预期 pod:
- metallb‑controller‑xxxx (1/1 Running)
- metallb‑speaker‑xxxx(每个节点一个 pod,1/1 Running)
- frrk8s‑frr‑xxxx(每个节点一个 frr pod,1/1 Running)
简单验证 LoadBalancer 功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| kubectl apply -f - <<'EOF' apiVersion: v1 kind: Service metadata: name: lb-demo spec: type: LoadBalancer selector: app: nginx-test ports: - port: 80 targetPort: 80 EOF
kubectl get svc lb-demo
|
如果 EXTERNAL‑IP 拿到192.168.110.21x地址,代表 MetalLB 工作正常。
卸载命令(后续清理)
1 2
| helm uninstall metallb -n metallb-system kubectl delete ns metallb-system
|
前置:同步 Kite OCI‑Helm Chart 到私有 Harbor
1 2 3 4 5 6 7 8
| helm pull oci://ghcr.io/kite-org/charts/kite --untar=false
helm registry login harbor.meatball.org.cn
helm push kite-*.tgz oci://harbor.meatball.org.cn/k8s
|
skopeo 同步 kite 镜像到 harbor
1 2 3
| skopeo copy --all \ docker://swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/kite-org/kite:v0.15.0 \ docker://harbor.meatball.org.cn/k8s/kite:v0.15.0
|
更新 helm release,替换镜像仓库
- 当前镜像:ghcr.io/kite‑org/kite:v0.15.0
- 目标镜像:harbor.meatball.org.cn/k8s/kite:v0.15.0
helm upgrade(直接覆盖 image.repository)
1 2 3
| helm install kite oci://harbor.meatball.org.cn/k8s/kite \ -n kube-system \ --set image.repository=harbor.meatball.org.cn/k8s/kite
|
部署校验
1 2 3 4 5 6 7 8
| helm list -n kube-system
kubectl get deploy kite -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}'
kubectl get pods -n kube-system -w
|
前提:metallb 的 speaker/controller 全部 Pod 处于 Running,IPAddressPool、L2Advertisement CR 已经部署完成
1 2 3 4 5
| kubectl patch svc kite -n kube-system -p '{"spec":{"type":"LoadBalancer","ports":[{"port":8080,"targetPort":"http"}]}}'
kubectl get svc kite -n kube-system -w
|
拿到EXTERNAL‑IP例如192.168.110.210,局域网浏览器直接访问:http://192.168.110.210:8080。
注意:MetalLB L2 只能分配内网网段 IP;互联网外网访问需要路由器做 DNAT 端口转发。
💡实验环境完成后,测试/生产环境建议升级为至少 3 个控制平面节点并使用负载均衡 VIP;同时增加 etcd 快照备份、监控、Ingress、存储和镜像漏洞扫描。
Nacos 版本:v3.2.3(官方稳定版)
用到镜像:
- docker.io/nacos/nacos-server:v3.2.3 主服务镜像
- docker.io/nacos/nacos‑peer‑finder‑plugin:1.1 集群选主插件镜像
两种部署方式:①helm chart 方式(推荐,同 kite 操作逻辑);②原生 yaml 方式。
克隆官方 nacos‑k8s 仓库
1 2 3 4 5
| git clone https://github.com/nacos-group/nacos-k8s.git cd nacos-k8s/helm
helm package . ls -lh nacos-*.tgz
|
推送到 harbor OCI 仓库
1 2
| helm registry login harbor.meatball.org.cn helm push nacos-*.tgz oci://harbor.meatball.org.cn/k8s
|
skopeo 同步 2 个容器镜像(之前命令不变)
1 2 3 4 5 6 7
| skopeo copy --all \ docker://docker.m.daocloud.io/nacos/nacos-server:v3.2.3 \ docker://harbor.meatball.org.cn/k8s/nacos/nacos-server:v3.2.3
skopeo copy --all \ docker://docker.m.daocloud.io/nacos/nacos-peer-finder-plugin:1.1 \ docker://harbor.meatball.org.cn/k8s/nacos/nacos-peer-finder-plugin:1.1
|
生成values-nacos.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| cat >/root/kubeadm/values-nacos.yaml <<'EOF' global: mode: standalone
nacos: replicaCount: 1 image: repository: harbor.meatball.org.cn/k8s/nacos/nacos-server tag: v3.2.3 pullPolicy: IfNotPresent plugin: enable: true image: repository: harbor.meatball.org.cn/k8s/nacos/nacos-peer-finder-plugin tag: 1.1 pullPolicy: IfNotPresent
authEnable: true authToken: "TXlTdXBlclNlY3JldE5hY29zS2V5MjAyNmFiY2RlZmdoaWprbG1ub3BxcnN0dXY=" authIdentityKey: "nacos" authIdentityValue: "nacos" admin: username: nacos password: "nacos123456"
service: type: LoadBalancer loadBalancerIP: 192.168.110.230 ports: http: port: 8848 targetPort: 8848 EOF
|
从私有 harbor OCI 安装 nacos
1 2 3
| helm install nacos oci://harbor.meatball.org.cn/k8s/nacos \ -n nacos --create-namespace \ -f values.yaml
|
校验:
1 2 3
| helm list -n nacos kubectl get statefulset nacos -n nacos -o jsonpath='{.spec.template.spec.containers[0].image}' kubectl get pods -n nacos -w
|
查看分配的IP
1
| kubectl get svc nacos -n nacos
|