跳转至

RUNBOOK — server 命名空间运行手册

面向对象:接手本集群日常运维与值班的人(假定你不熟悉这些服务,可能需要凌晨照着做) 命名空间:server(2026-09-18 由 traefik / gitlab / gitlab-pg / gitlab-redis / gitlab-minio 统一而来) 本手册只写「命名空间级」的共性与速查;各服务的细节操作在各自的专用 RUNBOOK 中,本手册用链接指向 最近更新:2026-09-19

目录

1. 服务概览

server 是本集群的业务命名空间,承载入口代理、代码托管平台、目录服务与一个业务数据库。

组件 版本 形态 专用 RUNBOOK
Traefik(HTTP/HTTPS/TCP 入口代理) v3.7.13 Deployment ×1,固定 k8s-master-01 traefik_deploy/RUNBOOK.md
GitLab(含 webservice / sidekiq / gitaly / shell / kas / registry / toolbox) v19.3.2 多 Deployment + StatefulSet gitlab-deploy-v2/RUNBOOK.md
MinIO(GitLab 对象存储) RELEASE.2025-04-22 StatefulSet ×1,NFS 卷 见 GitLab RUNBOOK
PostgreSQL(CNPG 单实例) 17.6 Cluster gitlab-pg,local SSD 见 GitLab RUNBOOK
Redis 7.4 StatefulSet ×1,local SSD 见 GitLab RUNBOOK
OpenLDAP 2.6.10 StatefulSet ×1,NFS 卷 ldap-deploy/RUNBOOK.md
phpLDAPadmin(LDAP 管理界面) — Deployment ×1 见 LDAP RUNBOOK
MariaDB 12.3.3 StatefulSet ×1,NFS 卷 mariadb-deploy/(无独立 RUNBOOK)
Envoy Gateway(GitLab 的入口数据面) v1.9.0 Deployment + Gateway 见 GitLab RUNBOOK

依赖关系(自下而上):

Traefik  ← 集群外客户端(80/443/389/636/3306)
  └─ 路由到 → phpLDAPadmin / Traefik Dashboard / (monitoring 内的 grafana、prometheus)
  └─ TCP 路由 → OpenLDAP(389/636)、MariaDB(3306)

Envoy Gateway ← gitlab.rainchen.top / registry / kas  (GitLab 不经 Traefik)
  └─ 转发到 → GitLab webservice / registry / kas
GitLab → PostgreSQL + Redis + MinIO(三者均在 server 内)

重要性等级:

  • Traefik:核心。它宕机则所有 HTTP/HTTPS 与 TCP(LDAP/MariaDB)入口全部中断。
  • GitLab:重要。宕机影响代码托管、CI、镜像仓库;不影响 LDAP 与数据库服务本身。
  • OpenLDAP:重要。宕机影响依赖其认证的系统登录。
  • MariaDB / phpLDAPadmin:一般。

2. 接入与凭据

业务域名 入口 后端(命名空间/服务) 说明
gitlab.rainchen.top Envoy Gateway(不走 Traefik) server/gitlab-webservice-default:8080 GitLab 主页
registry.rainchen.top Envoy Gateway server/gitlab-registry:5000 容器镜像仓库
kas.rainchen.top Envoy Gateway server/gitlab-kas:8154 GitLab Agent 服务
ldapadmin.rainchen.top Traefik (443) server/phpldapadmin:80 LDAP 管理界面
traefik.rainchen.top Traefik (443) Traefik Dashboard 需 BasicAuth
grafana.rainchen.top Traefik (443) monitoring/grafana 监控面板(跨命名空间)
prometheus.rainchen.top Traefik (443) monitoring/prometheus 指标查询
192.168.31.10:389 / :636 Traefik (TCP) server/openldap:389/636 LDAP 明文 / LDAPS
192.168.31.10:3306 Traefik (TCP) server/mariadb:3306 业务数据库

域名解析不在集群内维护(本机 /etc/hosts 无相关条目),客户端需自行解析到 192.168.31.10。

凭据只写位置,不写内容:

# Traefik Dashboard 口令(明文,权限 600)
cat traefik_deploy/secrets/dashboard-basic-auth.txt
# GitLab root 初始口令
kubectl -n server get secret gitlab-gitlab-initial-root-password -o jsonpath='{.data.password}' | base64 -d
# GitLab 依赖(PG/Redis/MinIO)口令
cat ns_migration/secrets/gitlab-credentials.env      # 权限 600
# LDAP 管理员口令(见 LDAP RUNBOOK 第 2 章,存在集群 Secret 与工作目录两处)
# MariaDB 口令:kubectl -n server get secret | grep -i mariadb

3. 日常速查表

# 1) 一眼看全 `server` 的工作负载是否健康(最常用)
kubectl -n server get pods -o wide | grep -vE 'Completed' | awk '$3!="Running" {print}'
# 预期:无输出(全部 Running)。有输出即为异常 Pod,转到第 8 章对应场景

# 2) 入口是否可用(404 正常,表示 Traefik 在且无匹配路由)
curl -s -o /dev/null -w '%{http_code}\n' http://192.168.31.10/            # 预期 404

# 3) 各业务域名连通性(返回 200/302/401 均属"入口可达")
for h in gitlab.rainchen.top ldapadmin.rainchen.top traefik.rainchen.top; do
  printf '%-26s ' "$h"
  curl -sk -o /dev/null -w '%{http_code}\n' --resolve "$h:443:192.168.31.10" "https://$h/"
done

# 4) helm release 状态(应是 deployed)
helm list -n server

# 5) 存储是否都 Bound
kubectl -n server get pvc | grep -v Bound        # 预期:无输出

# 6) 节点资源水位
kubectl top nodes

# 7) 最近 5 条事件(排查异常的第一现场)
kubectl -n server get events --sort-by=.lastTimestamp | tail -5

# 8) 取任意组件的日志(近 100 行)
kubectl -n server logs deploy/<组件名> --tail=100

4. 日常操作

# 查看某组件全部 Pod 与其所在节点
kubectl -n server get pods -o wide -l app.kubernetes.io/instance=<release>   # 例:-l app=redis

# 重启单个组件(滚动重启,逐个替换 Pod)
kubectl -n server rollout restart deploy/<名称>
kubectl -n server rollout status  deploy/<名称> --timeout=180s   # 预期:successfully rolled out

# 【高危】重启 Traefik:单副本 + hostPort,重启期间所有入口中断数秒
#   执行前确认无重要业务在跑;详见 traefik_deploy/RUNBOOK.md
kubectl -n server rollout restart deploy/traefik

# 进入容器排障
kubectl -n server exec -it deploy/gitlab-toolbox -- bash      # GitLab 运维工具箱
kubectl -n server exec -it sts/openldap -- sh                 # LDAP

# 临时把集群内服务暴露到本机(排查用;勿长期驻留)
kubectl -n server port-forward svc/gitlab-webservice-default 8080:8080
# 注意:不要 port-forward 到 envoy-gateway(那是控制面 18000/19001,连不上业务)

5. 配置管理

组件 配置载体 修改方式 生效方式
Traefik traefik_deploy/values.yaml 改后 helm upgrade(见其 SOP 第 5 章) Pod 滚动重建
GitLab gitlab-deploy-v2/values-gitlab.yaml 改后 helm upgrade 对应组件滚动重建
MinIO / PostgreSQL / Redis / MariaDB / OpenLDAP 各自清单或 values(见各交付目录) 重新 kubectl apply 或 helm upgrade 视组件而定
路由(HTTP) IngressRoute 自定义资源 kubectl apply 后热加载 无需重启 Traefik
路由(TCP) IngressRouteTCP 自定义资源 同上 同上

易错点:Traefik 的 entrypoint(端口)配置在 values 里,改端口需 helm upgrade 并会重建 Pod;而路由规则改的是 IngressRoute,与 helm 无关。两者不要混。

6. 备份与恢复

对象 备份方式 位置
GitLab 应用数据 chart 的备份机制(toolbox)+ 对象存储 gitlab-backups 桶 见 GitLab RUNBOOK
OpenLDAP 数据 slapcat 导出 LDIF + 备份 CronJob 见 LDAP RUNBOOK
MariaDB 见 mariadb-deploy/ —
local PV 数据 节点本地目录(k8s-node-01:/mnt/ssd/k8s/{gitaly,postgres,redis}) 由各组件自管
集群资源定义 kubectl get all,pvc,secret -n server -o yaml > backup/server-resources-<日期>.yaml 建议纳入 ns_migration/backup/

命名空间级快速快照(变更前必做):

kubectl -n server get all,pvc,ingressroute,ingressroutetcp,middleware -o yaml \
  > ns_migration/backup/server-resources-$(date +%Y%m%d-%H%M%S).yaml
# 生成后请到 ns_migration/backup/README.md 登记:备份文件、原路径、产生时间、因何产生、何时可删

恢复原则:先恢复定义(YAML),再恢复数据。数据恢复必须在对应组件停写状态下进行。

7. 监控与告警

  • 监控栈:kube-prometheus-stack(在 monitoring 命名空间),Grafana grafana.rainchen.top、Prometheus prometheus.rainchen.top。
  • 现有采集范围:仅监控栈自身组件的 ServiceMonitor(alertmanager / apiserver / coredns / grafana / kube-state-metrics / kubelet / operator / prometheus)。
  • server 命名空间的指标尚未接入:Traefik 已暴露 metrics entrypoint(容器端口 9100),GitLab 有 gitlab-gitlab-exporter:9168,但都没有对应的 ServiceMonitor —— 这是当前最大的可观测性缺口,建议后续补 ServiceMonitor(属变更,需走变更流程)。
  • 当前告警:依赖监控栈默认规则(集群级:节点不可用、Pod 重启、磁盘压力等),没有针对 server 内业务服务的告警。
  • 值班建议的替代手段(无告警时的兜底巡检):
# 每班一次:异常 Pod + 入口连通性
kubectl -n server get pods -o wide | grep -vE 'Completed' | awk '$3!="Running" {print "异常: " $0}'
for h in gitlab.rainchen.top traefik.rainchen.top ldapadmin.rainchen.top; do
  printf '%-26s ' "$h"; curl -sk -o /dev/null -w '%{http_code}\n' --resolve "$h:443:192.168.31.10" "https://$h/"
done

8. 故障处置

场景 1:某个域名打不开(其他域名正常)

症状:单个域名无响应或返回 404/502,其余域名正常。

诊断

# 1) 是入口问题还是后端问题?先用 IP+Host 头直连 Traefik
curl -sk -o /dev/null -w '%{http_code}\n' -H 'Host: <域名>' https://192.168.31.10/    # 404=无路由; 502=后端不可达; 200/302=正常
# 2) 路由是否存在
kubectl get ingressroute,ingressroutetcp -A | grep <域名关键字>      # 预期:能看到对应 IngressRoute
# 3) 后端 Pod 是否就绪
kubectl -n server get pods | grep <后端组件名>                       # 预期:1/1 或 2/2 Running
# 4) 后端 Service 是否有端点
kubectl -n server get endpoints <服务名>                             # 预期:有 IP:端口,而不是 <none>

处置:404 → 路由缺失,重新 kubectl apply 对应 IngressRoute(文件在各交付目录);502 → 后端未就绪,转场景 2;endpoints 为 <none> → 后端 Pod 未就绪或标签不匹配,检查 Pod 与 Service selector。

验证:重跑诊断第 1 步,预期返回 200/302;再用真实域名 curl 一次。

场景 2:Pod 一直 Pending

症状:kubectl -n server get pods 中某 Pod 长期 Pending。

诊断

kubectl -n server describe pod <pod> | grep -A5 Events      # 关键看 Events
# 判读:
#   "didn't match Pod's node affinity/selector" + local PV 相关 → 存储绑定在别的节点(场景 3)
#   "Insufficient cpu/memory"                                   → 资源不足,见第 10 章
#   "didn't have free ports for the requested pod ports"        → hostPort 冲突(Traefik 常见)

处置:资源不足 → 扩容节点或调整 requests;hostPort 冲突 → 同一节点上不允许两个 Pod 抢同一 hostPort,Traefik 只应有一个副本,若出现多副本请确认是否误改 replicas;亲和性/存储冲突 → 转场景 3。

验证:kubectl -n server get pod <pod> -o wide 预期 Running 且 NODE 与 PV 所在节点一致。

场景 3:PVC 绑定到了错误的 PV(或长期 Pending)

症状:PVC 卡 Pending;或 PVC 已 Bound 但 VOLUME 指向与用途不符的 PV(例如 PG 用上了 redis 卷)。

诊断

kubectl -n server get pvc -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,VOLUME:.spec.volumeName   # 核对绑定关系
kubectl get pv | grep -E 'Available|Released'                                        # 看是否有闲置 PV
# 本集群的既定对应关系(2026-09-18 起):
#   gitlab-pg-1 → pv-postgres-ssd ;redis-data → pv-redis-ssd ;repo-data-gitlab-gitaly-0 → pv-gitaly-ssd

处置:原因通常是「同容量 PV 被先到先得随机分配」。正确做法是用 claimRef 预绑定锁定关系:

# 1) 停用该 PVC 的负载(避免写入错卷)
kubectl -n server scale deploy/<负载> --replicas=0        # 或 delete cluster(CNPG)
# 2) 删除错绑的 PVC(PV 回收策略为 Retain,数据不会丢)
kubectl -n server delete pvc <pvc 名>
# 3) 清空 claimRef 使其回到 Available(必须去掉 uid,只留 4 个字段的预绑定是 Available)
kubectl patch pv <pv 名> -p '{"spec":{"claimRef":null}}'
kubectl patch pv <pv 名> --type=merge -p '{"spec":{"claimRef":{"apiVersion":"v1","kind":"PersistentVolumeClaim","namespace":"server","name":"<目标 pvc 名>"}}}'
# 4) 重建负载,让它自行创建 PVC(CNPG 必须自建,禁止预建 —— 否则卡 BootstrapPending)

验证:kubectl -n server get pvc 中目标 PVC 的 VOLUME 与预期 PV 一致。

场景 4:server 内服务访问 monitoring 或集群外服务失败

症状:跨命名空间调用报 connection refused / no such host / 超时。

诊断

# 1) DNS 是否可解析(用一次性 Pod)
kubectl -n server run dns-test --rm -i --restart=Never --image=busybox:1.36 --quiet -- \
  nslookup kubernetes.default.svc.cluster.local        # 预期能解析出 IP
# 2) 目标服务的 FQDN 格式:<svc>.<ns>.svc.cluster.local
kubectl get svc -n <目标 ns>
# 3) 目标端点是否就绪
kubectl -n <目标 ns> get endpoints <svc>

处置:DNS 失败 → 检查 CoreDNS(kubectl -n kube-system get pods -l k8s-app=kube-dns);端点为空 → 目标服务无就绪 Pod;跨命名空间引用被 Traefik 拒绝 → 该场景需在 Traefik values 中开启 allowCrossNamespace(属变更)。

验证:同一条 nslookup / curl 命令返回预期结果。

9. 安全与权限

  • 命名空间内 Secret 清单(只列用途):Traefik(TLS 自签证书、Dashboard 口令)、GitLab(gitlab-rails-secret 等 20 个,含数据库/对象存储/组件密钥)、PG/Redis/MinIO 凭据、OpenLDAP(管理员口令、TLS)、MariaDB 口令。
  • TLS:
  • Traefik 使用内部 CA 自签证书(traefik_deploy/certs/,有效期至 2036-09-13),为默认 TLSStore 证书。
  • GitLab 经 Envoy Gateway 暴露,证书由 chart 自管(gitlab-gitlab-tls 类 Secret)。
  • 轮换:替换 Secret 内容后 kubectl -n server rollout restart deploy/traefik(Traefik 会重载)。
  • RBAC:本命名空间的工作负载多数使用各自 chart 创建的 ServiceAccount;集群级权限集中在 gitlab-* ClusterRole 与 Traefik 的 ClusterRole(只读 CRD 与 endpoints)。
  • 访问控制:Traefik Dashboard 用 BasicAuth 中间件(server/middleware/dashboard-auth);GitLab 自身有账号体系;phpLDAPadmin 走 LDAP 管理员认证。

10. 容量与性能

当前基线(2026-09-19 实测):

项 数值
server 命名空间 CPU requests 合计 3.73 核
server 命名空间内存 requests 合计 6.7 GiB
server 命名空间存储(PVC 合计) 117 GiB
节点分配:k8s-master-01 4 核 / 7.4 GiB
节点分配:k8s-node-01/02/03 各 8 核 / 15.3 GiB
实际水位(全节点) CPU 5–15%,内存 25–33%

主要 Pod 落点:k8s-node-01 聚集了 Gitaly、PostgreSQL、MinIO、Redis 及多数 GitLab 组件(因 local PV 与存储亲和);k8s-node-03 有 Envoy 数据面、KAS、MariaDB、phpLDAPadmin。

扩容触发条件:

  • 任一节点内存长期超过 70% → 优先排查 GitLab sidekiq / registry 的内存增长(kubectl top pod -n server --sort-by=memory)。
  • k8s-node-01 因聚集存储组件最先吃紧:若该节点 CPU/内存超 70%,应把无状态组件(sidekiq、registry 副本)通过节点亲和迁往 node-02/03。
  • 存储:pv-gitaly-ssd(20Gi)随仓库增长而增长,接近 80% 时需规划扩容(local PV 扩容需重建 PV 并迁移数据,属变更)。

已知瓶颈:k8s-node-01 单点承载全部 local PV 数据(Gitaly/PG/Redis),该节点故障会导致 GitLab 不可用且需人工介入恢复。

11. 附录

术语表

术语 含义
entrypoint Traefik 的监听端口定义(如 web=80、websecure=443、ldap=389)
IngressRoute / IngressRouteTCP Traefik CRD 的 HTTP / TCP 路由资源(与 helm 无关,可热加载)
Gateway API K8s 新一代入口标准(GitLab 用它 + Envoy Gateway,不经 Traefik)
local PV 节点本地盘上的静态 PV(local-ssd),与节点强绑定
claimRef 预绑定 在 PV 上预设目标 PVC 名(不写 uid),使绑定关系确定而非随机

相关文档

文档 位置
本次命名空间统一变更档案 ns_migration/SOP.md
本次变更中的两次阻塞故障 ns_migration/INCIDENT-20260918-gitlab-ns-migration.md
Traefik 运行手册 / 部署 SOP traefik_deploy/RUNBOOK.md、traefik_deploy/SOP.md
GitLab 运行手册 / 部署 SOP gitlab-deploy-v2/RUNBOOK.md、gitlab-deploy-v2/SOP.md
LDAP 运行手册 / 部署 SOP ldap-deploy/RUNBOOK.md、ldap-deploy/SOP.md
数据非空场景的 GitLab 迁移方案 ns_migration/GitLab迁移到server-方案与风险.md

修订记录

日期 修改人 变更内容
2026-09-19 运维 首版:基于 2026-09-18 命名空间统一后的实际状态编写

来源:/home/rain/Documents/k8s_ins/ns_migration/RUNBOOK.md | 最后更新:2026-09-19 16:50(由 build/sync.py 同步,请勿在站点侧修改)