Kubernetes v1.35 云原生平台实战:MetalLB、Prometheus、GitLab CI/CD 与 HPA
1. 项目目标与当前架构
目标不是只部署一个 Nginx,而是打通一条可验证的交付链路:源码提交后由流水线构建镜像、推送镜像仓库、更新 Kubernetes 工作负载;同时为应用提供统一入口、指标采集、告警与 HPA 扩缩容能力。
Gitee master │ ▼ GitLab CI:fetch → build → deploy │ │ │ ├─ Kaniko 构建 Commit SHA 镜像 │ └─ 阿里云 ACR ▼ Kubernetes apps/frontend-static ├─ Deployment + RollingUpdate + Probe ├─ Service + Ingress-NGINX ├─ HPA(CPU 指标) └─ Prometheus / Grafana / Alertmanager
1.1 实验拓扑
| 角色 | 主机名 | 地址 | 关键组件 |
|---|---|---|---|
| 控制平面 | k8s-master-1 | 192.168.117.138 | kube-apiserver、etcd、scheduler、controller-manager |
| Worker | k8s-node-1 | 192.168.117.139 | containerd、Calico、Ingress 后端、应用 Pod |
| Worker | k8s-node-2 | 192.168.117.140 | containerd、Calico、应用 Pod |
| NFS(历史存储) | NFS | 192.168.117.147 | /web/html 迁移目标 |
| MetalLB VIP | - | 192.168.117.188 | ingress-nginx-controller 的 LoadBalancer 地址 |
1.2 版本与验收快照
| 项目 | 当前状态 |
|---|---|
| OS | CentOS Stream 10 |
| Kubernetes | v1.35.0 |
| 容器运行时 | containerd 2.2.1 |
| CNI | Calico v3.28.0 |
| kube-proxy | IPVS,strictARP: true |
| 节点/Pod | 3/3 Ready、47/47 Running |
| GitLab | GitLab CE 18.11.9 / Helm Chart 9.11.10 |
| 监控 | kube-prometheus-stack 82.16.0 / Prometheus Operator v0.89.0 |
常用验收命令:
kubectl get nodes -o wide
kubectl get pods -A
kubectl -n kube-system get configmap kube-proxy -o yaml
2. 集群基础:containerd、Calico 与 IPVS
集群使用 kubeadm 初始化,所有节点统一使用 containerd,并将 kubelet 的 cgroup 驱动配置为 systemd。网络层选择 Calico,Pod CIDR 与 kubeadm init 的 --pod-network-cidr 保持一致。
# 仅示例:版本和镜像源应按实际环境确认
dnf install -y kubelet-1.35.0 kubeadm-1.35.0 kubectl-1.35.0 \
--disableexcludes=kubernetes
systemctl enable --now kubelet
# containerd 必须使用 systemd cgroup
grep -n 'SystemdCgroup' /etc/containerd/config.toml
systemctl restart containerd
Service 转发使用 IPVS。MetalLB L2 模式需要 kube-proxy 的 strictARP 为 true,否则 VIP 的 ARP 宣告可能异常:
kubectl -n kube-system get configmap kube-proxy -o jsonpath='{.data.config\.conf}' \
| grep -E 'mode:|strictARP:'
# 预期:mode: "ipvs"、strictARP: true
3. MetalLB + Ingress-NGINX:裸金属 VIP 与七层路由
公有云可由云厂商分配 LoadBalancer 地址;裸金属实验集群使用 MetalLB 管理地址池。当前仅配置一个 VIP,因此将它分配给 ingress-nginx-controller,由 Ingress 根据域名和路径转发到 ClusterIP Service。
MetalLB 的 IPAddressPool 负责可分配地址,L2Advertisement 负责 L2/ARP 宣告;官方说明见 MetalLB Configuration。
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 192.168.117.188/32 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: example namespace: metallb-system spec: ipAddressPools: - first-pool
kubectl -n metallb-system get ipaddresspool,l2advertisement
kubectl -n ingress-nginx get svc ingress-nginx-controller
# 当前 Service:LoadBalancer,EXTERNAL-IP=192.168.117.188,端口 80/443
现役前端使用独立域名 frontend.192.168.117.188.nip.io,对应 apps/frontend-static 的 Ingress。根 VIP 返回 503 并不等于 MetalLB 故障:当前遗留的 default/web-ingress 没有 Endpoint;应通过目标域名验证现役路由。
curl --noproxy '*' -I http://frontend.192.168.117.188.nip.io
kubectl -n apps get ingress,service,pods
当前控制器镜像为 Ingress-NGINX v1.8.1,仅作为现役状态记录。Ingress-NGINX 项目已在 2026 年 3 月后结束常规维护,后续生产方案应评估 Gateway API 或其他受维护的实现;不要将本文环境直接宣传为可直接用于生产的入口方案。官方公告
4. 存储演进:NFS 故障恢复与 local-path 边界
早期静态站点通过 NFS 的 /web/html 目录挂载到 Nginx 容器。排障中发现旧 PV 指向过期端点 192.168.117.134,因此采用“新建并切换、旧资源保留”的方式创建 nfs-pv-html-v2 / nfs-pvc-html-v2,指向 192.168.117.147:/web/html,避免直接删除仍可回滚的旧 PV/PVC。
kubectl get pv nfs-pv-html nfs-pv-html-v2 \
-o custom-columns=NAME:.metadata.name,SERVER:.spec.nfs.server,PATH:.spec.nfs.path,STATUS:.status.phase
现役 apps/frontend-static 不再依赖 NFS:流水线将 index.html 封装入 Nginx 镜像,运行时只从 ACR 拉取版本化镜像。NFS 章节保留为一次存储迁移与回滚策略案例,不作为当前前端的依赖说明。
GitLab 的 PostgreSQL、Redis、Gitaly、MinIO 则使用 local-path:分别为 8Gi、2Gi、20Gi、10Gi。这种方式适合实验环境,卷与节点绑定,不具备复制存储或跨节点故障切换能力。
5. 可观测:Prometheus、Alertmanager 与 Grafana
监控采用 Helm 部署的 kube-prometheus-stack,包含 Prometheus、Alertmanager、Grafana、Prometheus Operator、Node Exporter 和 kube-state-metrics。当前已有 13 个 ServiceMonitor 与 35 个 PrometheusRule,用于采集节点、Kubernetes 对象和服务指标,并将规则结果交给 Alertmanager。
helm -n monitoring list
kubectl -n monitoring get pods
kubectl get servicemonitors.monitoring.coreos.com -A
kubectl get prometheusrules.monitoring.coreos.com -A
Grafana 和 Prometheus 当前通过 NodePort 暴露,而非第二个 MetalLB VIP:
kubectl -n monitoring get svc prometheus-grafana prometheus-kube-prometheus-prometheus
# Grafana NodePort:31356
# Prometheus NodePort:30090
文章不记录默认账号、密码或从 Secret 解码出的值。应通过 Kubernetes Secret、受控访问入口和独立凭据管理 Grafana、ACR 与 GitLab 的敏感信息。
6. GitLab CI/CD:从 Gitee 到 Kubernetes
GitLab 通过 Helm 部署,版本为 CE 18.11.9;Runner 使用 Kubernetes Executor。镜像仓库复用阿里云 ACR,GitLab 内置 Registry 保持关闭。流水线的目标是:从 Gitee master 获取静态资源,用 Kaniko 无特权构建 Nginx 镜像,以 Commit SHA 标记版本,并将 Deployment、Service、Ingress、HPA 应用到 apps 命名空间。
Gitee master → fetch-source:克隆源码并保存 GITEE_COMMIT、INDEX_SHA256 → build-image:Kaniko 构建并推送 <registry>/<namespace>/frontend-static:<commit> → deploy-app:apply 清单,替换镜像,等待 rollout status
关键变量只在 GitLab 的 CI/CD Variables 中维护,不进入仓库:
GITEE_REPO_URL GITEE_USERNAME / GITEE_TOKEN(私有仓库时需要) ACR_REGISTRY ACR_NAMESPACE ACR_USERNAME ACR_PASSWORD GIT_CLIENT_IMAGE KANIKO_IMAGE
.gitlab-ci.yml 的核心行为如下,密码仅在运行时写入 Kaniko 的 Docker 配置:
variables:
GITEE_BRANCH: master
K8S_NAMESPACE: apps
IMAGE_NAME: ${ACR_REGISTRY}/${ACR_NAMESPACE}/frontend-static
# fetch:git clone --depth 1 --branch "${GITEE_BRANCH}" "${GITEE_REPO_URL}" source
# build:/kaniko/executor --destination "${IMAGE_NAME}:${GITEE_COMMIT}"
# deploy:kubectl apply ... && kubectl rollout status deployment/frontend-static
6.1 导入仓库不是自动同步
GitLab CE 的“按 URL 导入”只在导入时复制代码,后续不会持续从 Gitee 拉取。GitLab 项目自身的 master 必须包含最新 .gitlab-ci.yml;运行时的 fetch-source 再负责克隆 Gitee master。因此当日志出现 git clone --branch main 时,应同时检查:
-
GitLab 项目当前提交中的
GITEE_BRANCH; -
项目/组变量是否覆盖了 YAML 变量;
-
Gitee 的实际默认分支。
6.2 三个已遇到的排障点
-
Windows Git 自签名证书报错: 应将 GitLab CA 导入 Windows 受信任根证书;临时排查可对单次命令使用
git -c http.sslVerify=false,不要设置全局关闭校验。 -
GitLab 分支与 Gitee 历史分叉: 先
git fetch gitlab和git log --left-right master...gitlab/master;确认 GitLab 无独立提交后,才使用git push --force-with-lease gitlab master:master。受保护分支需临时授权强推,完成后立即关闭。 -
Kaniko 推送 ACR 返回 UNAUTHORIZED:
podman login成功只说明账号可登录,不代表流水线镜像路径正确。重点检查ACR_NAMESPACE是否注入;正确镜像路径必须是<registry>/<namespace>/frontend-static:<commit>。
7. 现役应用:滚动更新、探针与 HPA
当前 apps/frontend-static 的镜像由 Commit SHA 标记。Deployment 固定双副本起步,使用 maxUnavailable: 0、maxSurge: 1 进行滚动发布,并以 HTTP 探针控制就绪和存活判断。
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
spec:
containers:
- name: frontend
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
readinessProbe:
httpGet: { path: /, port: http }
livenessProbe:
httpGet: { path: /, port: http }
HPA 使用 autoscaling/v2,CPU 平均利用率目标为 60%。资源 requests 是 CPU 利用率计算的前提;behavior 用于限制每次副本变化并避免频繁缩容。HPA 行为字段的含义可参考 Kubernetes 官方文档。
本次验收中,frontend-static 为 2/2 Ready、2/2 Available,两个实例分布在不同 Worker,重启次数为 0;镜像标签与 Gitee Commit 157d90ca9e61ff1a5d11b461e04087b84a3592af 对应。早期 Nginx HPA 压测场景曾将稳定并发上限从 1000 提升至 1800、最大 QPS 提升约 12%;该压测参数与当前前端 2—6 副本配置不同,应分别理解。
8. 发布后的验收清单
# 集群基础
kubectl get nodes
kubectl get pods -A
# VIP 与入口
kubectl -n ingress-nginx get svc ingress-nginx-controller
curl --noproxy '*' -I http://frontend.192.168.117.188.nip.io
# 应用与 HPA
kubectl -n apps get deploy,pod,svc,ingress,hpa
kubectl -n apps rollout status deployment/frontend-static --timeout=300s
# 监控
kubectl -n monitoring get pods
kubectl get servicemonitors.monitoring.coreos.com -A
kubectl get prometheusrules.monitoring.coreos.com -A
验收应同时检查控制面、Pod、Endpoint、HPA 条件和 HTTP 响应,而不是仅看到 Pipeline 成功就判定发布完成。
总结
这套平台的核心价值不在于单独安装某个组件,而在于把基础设施、流量、监控、镜像交付和弹性伸缩接成一条可验证的闭环:代码变更可追溯到镜像标签,镜像可追溯到 Kubernetes Deployment,应用状态可通过探针、HPA、Prometheus 和 HTTP 验收共同确认。
更多推荐


所有评论(0)