主题
第五部分 综合实战与故障排查手册
前四部分我们分别学习了 Kubernetes 核心概念、进阶实战、RKE2 从入门到精通、以及 K8s 辅助工具生态(含 K8sGPT)。本部分是"收口"章节:通过四个贴近生产的综合实战,把前面所有知识串成完整的工程闭环;再给出一本速查式故障排查手册和 20 道高频面试题,帮助你在真实环境与面试场景中都能游刃有余。
本部分大量引用本仓库中的真实素材:
rke2/目录:真实的安装脚本与配置(install-server.sh、install-agent.sh、server-config.yaml、registries.yaml)k8s-issues/目录:真实故障案例(quorum 丢失灾后恢复、master join 失败、iptables 防火墙拦截、镜像导入延迟等)
目录
- 1. 综合实战一:从零搭建生产级 RKE2 高可用集群
- 2. 综合实战二:部署完整可观测性栈并接入 K8sGPT
- 3. 综合实战三:GitOps 流水线(ArgoCD + Helm/Kustomize)
- 4. 综合实战四:备份与灾难恢复演练
- 5. 故障排查手册(速查式)
- 6. 常见面试题(20 题)
1. 综合实战一:从零搭建生产级 RKE2 高可用集群
1.1 目标架构
搭建一个 3 server(control-plane + etcd)+ 3 agent(worker)的高可用集群,使用 kube-vip 提供控制平面 VIP,对接私有镜像仓库,CNI 选用 Cilium(备选 canal)。
┌──────────────────────────────┐
│ VIP 192.168.122.200 (kube-vip)│ :6443 / :9345
└──────────────┬───────────────┘
┌────────────────────┼────────────────────┐
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ server-1 │◄─etcd─►│ server-2 │◄─etcd─►│ server-3 │
│ .190(init)│ │ .191 │ │ .192 │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
└────── CNI (Cilium) ─┼───────────────────┘
┌──────────▼───┐ ┌───────▼──────┐ ┌────────▼─────┐ ┌──────────────────┐
│ agent-1 .193 │ │ agent-2 .194 │ │ agent-3 .195 │ │ 私有仓库 │
└──────────────┘ └──────────────┘ └──────────────┘ │ .156:30000 │
└──────────────────┘节点规划表:
| 节点 | 主机名 | IP | 角色 | 配置建议 |
|---|---|---|---|---|
| server-1 | rocky9-vm-04 | 192.168.122.190 | control-plane + etcd(初始化节点) | 4C8G, 80G 盘 |
| server-2 | rocky9-vm-05 | 192.168.122.191 | control-plane + etcd | 4C8G |
| server-3 | rocky9-vm-06 | 192.168.122.192 | control-plane + etcd | 4C8G |
| agent-1 | rocky9-vm-07 | 192.168.122.193 | worker | 4C8G |
| agent-2 | rocky9-vm-08 | 192.168.122.194 | worker | 4C8G |
| agent-3 | rocky9-vm-09 | 192.168.122.195 | worker | 4C8G |
| VIP | — | 192.168.122.200 | kube-vip 漂移地址 | — |
注意事项:生产环境建议 agent 与 server 分离部署,etcd 数量保持奇数(3 或 5),且 etcd 节点使用 SSD。虚拟机场景下确认宿主机时间同步正常,否则证书与 etcd lease 会出现诡异问题。
1.2 Rocky Linux 9 系统准备(所有节点执行)
1.2.1 关闭 swap
bash
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab1.2.2 防火墙:二选一
方案 A:直接关闭(内网实验环境推荐,与本仓库 rke2/ 脚本一致):
bash
systemctl disable --now firewalld方案 B:放行 RKE2 所需端口(生产环境推荐):
bash
# server 节点(agent 节点只需 10250 / 8472 / NodePort)
firewall-cmd --permanent --add-port={6443,9345,10250,30000-32767}/tcp
firewall-cmd --permanent --add-port=2379-2380/tcp # etcd client/peer
firewall-cmd --permanent --add-port={8472,51820}/udp # VXLAN / WireGuard(可选)
firewall-cmd --reload真实案例:防火墙未放行 9345/10250 是 master join 失败的最常见原因之一,现象是 join 节点反复 TLS 超时。参见
k8s-issues/rke2-master-join-fails-iptables-firewall-blocking.md。
1.2.3 内核参数与模块
bash
cat > /etc/modules-load.d/rke2.conf <<EOF
overlay
br_netfilter
EOF
modprobe overlay && modprobe br_netfilter
cat > /etc/sysctl.d/90-rke2.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system1.2.4 时间同步(chrony)
bash
dnf install -y chrony
systemctl enable --now chronyd
# 内网环境指向内部 NTP
cat >> /etc/chrony.conf <<EOF
server 192.168.122.1 iburst
EOF
systemctl restart chronyd
chronyc sources -v1.2.5 其他准备
bash
# RKE2 支持 SELinux,保持 enforcing 即可;禁用 NetworkManager 管理 CNI 网卡
cat > /etc/NetworkManager/conf.d/rke2-canal.conf <<EOF
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:flannel*;interface-name:cilium*
EOF
systemctl reload NetworkManager
dnf install -y tar conntrack-tools socat iptables ipvsadm1.3 部署 kube-vip(控制平面 VIP)
在初始化第一个 server 之前先部署 kube-vip 静态 Pod,让 VIP 在 6443 可用:
bash
# 在 server-1 上执行
mkdir -p /var/lib/rancher/rke2/server/manifests
export VIP=192.168.122.200
export INTERFACE=eth0 # 按实际网卡名修改
export KVVERSION=v0.8.4
# 生成 kube-vip 静态 Pod 清单(ARP 模式,L2 同网段场景)
cat > /var/lib/rancher/rke2/server/manifests/kube-vip.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: kube-vip
namespace: kube-system
spec:
hostNetwork: true
containers:
- name: kube-vip
image: ghcr.io/kube-vip/kube-vip:${KVVERSION}
args: ["manager"]
env:
- {name: vip_arp, value: "true"}
- {name: vip_interface, value: "${INTERFACE}"}
- {name: address, value: "${VIP}"}
- {name: cp_enable, value: "true"}
- {name: cp_namespace, value: kube-system}
- {name: vip_leaderelection, value: "true"}
securityContext:
capabilities: {add: ["NET_ADMIN", "NET_RAW"]}
volumeMounts: [{mountPath: /etc/kubernetes/admin.conf, name: kubeconfig}]
volumes:
- name: kubeconfig
hostPath: {path: /etc/rancher/rke2/rke2.yaml}
EOF注意事项:
/var/lib/rancher/rke2/server/manifests/是 RKE2 的静态清单目录,rke2-server 启动时会自动 apply 其中的 YAML(即 HelmChart/AddOn 机制)。server-2/3 加入前也需放置同样的 kube-vip 清单。云环境或禁止 ARP 的网络应改用 BGP 模式。
1.4 初始化第一个 server 节点
参考本仓库 rke2/install-server.sh 的真实脚本,离线安装流程(在线环境直接 curl -sfL https://get.rke2.io | sh -):
bash
mkdir -p /opt/rke2-artifacts
curl -fsSL http://192.168.122.1:31000/repo/rke2/1.35.6/install.sh -o /tmp/install-rke2.sh
curl -fsSL http://192.168.122.1:31000/repo/rke2/rke2-1.35.6/rke2.linux-amd64.tar.gz -o /opt/rke2-artifacts/
curl -fsSL http://192.168.122.1:31000/repo/rke2/rke2-1.35.6/sha256sum-amd64.txt -o /opt/rke2-artifacts/
chmod +x /tmp/install-rke2.sh
INSTALL_RKE2_VERSION=v1.35.6+rke2r1 \
INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts \
INSTALL_RKE2_TYPE=server \
/tmp/install-rke2.sh写入配置 /etc/rancher/rke2/config.yaml(基于 rke2/server-config.yaml 改造为 HA 版):
yaml
node-name: rocky9-vm-04
node-ip: 192.168.122.190
advertise-address: 192.168.122.190
tls-san: [192.168.122.200, 192.168.122.190, rocky9-vm-04] # VIP 必配,否则走 VIP 报证书错误
cluster-cidr: 10.12.0.0/16
service-cidr: 10.13.0.0/16
kube-proxy-arg: ["proxy-mode=ipvs"]
system-default-registry: 192.168.122.156:30000
cni: cilium # 选 canal 则去掉此行(canal 是默认)
etcd-snapshot-retention: 5
etcd-snapshot-schedule-cron: "0 */6 * * *"
write-kubeconfig-mode: "0640"启动:
bash
systemctl enable --now rke2-server
journalctl -u rke2-server -f # 观察启动日志配置 kubectl 环境:
bash
mkdir -p ~/.kube
ln -sf /etc/rancher/rke2/rke2.yaml ~/.kube/config
export PATH=$PATH:/var/lib/rancher/rke2/bin
echo 'export PATH=$PATH:/var/lib/rancher/rke2/bin' >> ~/.bashrc
kubectl get nodes1.5 加入其余 server 节点(server-2 / server-3)
先在 server-2/3 上放置 kube-vip 静态清单(同 1.3),然后写配置 /etc/rancher/rke2/config.yaml(与首节点相同的项不再重复,仅列出差异项):
yaml
server: https://192.168.122.200:9345 # 指向 VIP(或首节点 IP)
token: <server-1 上 /var/lib/rancher/rke2/server/node-token 的内容>
node-name: rocky9-vm-05
node-ip: 192.168.122.191
advertise-address: 192.168.122.191
# 其余项(tls-san/cluster-cidr/service-cidr/kube-proxy-arg/system-default-registry/cni)与首节点保持一致bash
systemctl enable --now rke2-server验证 etcd 集群:
bash
kubectl get nodes
ETCDCTL_API=3 /var/lib/rancher/rke2/bin/etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
member list真实案例:server 加入时若 config.yaml 与首节点关键配置(cluster-cidr/service-cidr/cni 等)不一致,会出现 "critical configuration mismatch" 报错导致 join 失败。参见
k8s-issues/rke2-master-join-fails-critical-configuration-mismatch.md。真实案例:join 后节点长期 NotReady 但进程正常,可能是离线环境镜像 import 慢,containerd 还在解包。参见
k8s-issues/rke2-master-join-notready-image-import-delay.md。
1.6 加入 agent 节点
参考本仓库 rke2/install-agent.sh 与 rke2/agent-config.yaml:
bash
INSTALL_RKE2_VERSION=v1.35.6+rke2r1 INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts \
INSTALL_RKE2_TYPE=agent /tmp/install-rke2.sh
cat > /etc/rancher/rke2/config.yaml <<EOF
server: https://192.168.122.200:9345
token: <node-token>
node-name: rocky9-vm-07
node-ip: 192.168.122.193
kube-proxy-arg: ["proxy-mode=ipvs"]
system-default-registry: 192.168.122.156:30000
EOF
systemctl enable --now rke2-agent1.7 私有镜像仓库对接(registries.yaml)
所有节点创建 /etc/rancher/rke2/registries.yaml(内容与本仓库 rke2/registries.yaml 一致,并补充 mirror):
yaml
mirrors:
docker.io:
endpoint: ["http://192.168.122.156:30000"]
configs:
"192.168.122.156:30000":
tls: {insecure_skip_verify: true}
# 需要认证时追加:auth: {username: xxx password: xxx修改后需重启生效:
bash
systemctl restart rke2-server # agent 节点为 rke2-agent
# 验证
crictl pull 192.168.122.156:30000/library/nginx:latest注意事项:
registries.yaml的改动不会被 rke2 自动 reload(v1.35 起部分支持动态加载,生产仍建议重启)。system-default-registry会改写所有未带 registry 前缀的镜像引用,与mirrors.docker.io二选一规划清楚,混用容易踩坑。
1.8 Cilium 验证(或 canal)
bash
kubectl -n kube-system get pods -l k8s-app=cilium
# Cilium CLI 连通性测试
cilium status
cilium connectivity test若用 canal(默认):
bash
kubectl -n kube-system get pods -l k8s-app=canal
ip link show flannel.11.9 安装后验证清单
| 检查项 | 命令 | 预期结果 |
|---|---|---|
| 节点状态 | kubectl get nodes -o wide | 6 节点全部 Ready,角色正确 |
| VIP 可达 | curl -k https://192.168.122.200:6443/healthz | ok |
| VIP 漂移 | 停掉持有 VIP 节点的 rke2-server | VIP 漂移到其他 server,API 仍可用 |
| etcd 健康 | etcdctl endpoint health / member list | 3 成员均 healthy |
| 系统组件 | kubectl -n kube-system get pods | 全部 Running |
| DNS | kubectl run -it --rm dns --image=busybox:1.36 -- nslookup kubernetes.default | 解析成功 |
| 跨节点网络 | 部署 daemonset + ping 测试 | 跨节点 Pod IP 互通 |
| Service | 创建 ClusterIP/NodePort 服务并访问 | 通 |
| 镜像拉取 | 部署一个私有仓库镜像的 Pod | 拉取成功 |
| 快照 | rke2 etcd-snapshot save --name init-check | 快照生成于 /var/lib/rancher/rke2/server/db/snapshots/ |
| 时间同步 | chronyc tracking | 各节点偏差 < 10ms |
至此,一个生产级 RKE2 HA 集群搭建完成。
2. 综合实战二:部署完整可观测性栈并接入 K8sGPT
2.1 目标与架构
在实战一的集群上部署:Prometheus + Grafana(kube-prometheus-stack)、Loki 日志栈、NodeLocal DNSCache、metrics-server,并接入 K8sGPT(后端使用 Ollama 本地大模型),形成 "监控告警 → AI 诊断 → 修复建议" 闭环。
告警产生(Prometheus Alertmanager)
│
▼
运维人员/值班收到告警 ────────────┐
│ │
▼ ▼
Grafana 面板定位现象 k8sgpt analyze --backend ollama
(指标/日志/事件关联) (AI 扫描集群异常,给出根因与修复建议)
│ │
└──────────┬─────────────┘
▼
执行修复动作
│
▼
Prometheus 告警恢复(闭环)2.2 安装 metrics-server
bash
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 私有环境:set image 替换为 192.168.122.156:30000/library/metrics-server:v0.7.2
# 自签证书集群需加启动参数 --kubelet-insecure-tls
kubectl -n kube-system rollout status deploy/metrics-server && kubectl top nodes2.3 安装 NodeLocal DNSCache
bash
# 获取集群 DNS IP(通常是 service-cidr 第 10 个地址,如 10.13.0.10)
kubectl get svc -n kube-system kube-dns -o jsonpath='{.spec.clusterIP}'
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
# 替换模板变量后部署
sed -i 's/__PILLAR__LOCAL__DNS__/169.254.20.10/g; s/__PILLAR__DNS__SERVER__/10.13.0.10/g; s/__PILLAR__DNS__DOMAIN__/cluster.local/g' nodelocaldns.yaml
kubectl apply -f nodelocaldns.yaml && kubectl -n kube-system rollout status ds/node-local-dns注意事项:kube-proxy 为 IPVS 模式时(本集群正是),需要为 kubelet 配置
--cluster-dns=169.254.20.10,并在 IPVS 的 dummy 接口(kube-ipvs0)上绑定该地址,NodeLocal DNSCache 清单中localdns参数与 iptables NOTRACK 规则已处理大部分场景,但 IPVS 下建议同时验证dig @169.254.20.10 kubernetes.default.svc.cluster.local。深入原理可参见本仓库metaLB/coredns-nodelocaldncache-from-beginner-to-master.md。
2.4 安装 kube-prometheus-stack
bash
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
cat > prom-values.yaml <<'EOF'
prometheus:
prometheusSpec:
retention: 15d
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: longhorn # 按实际 SC 修改
accessModes: ["ReadWriteOnce"]
resources: {requests: {storage: 20Gi}}
grafana:
adminPassword: 'xxx'
persistence: {enabled: true, size: 5Gi}
service: {type: NodePort, nodePort: 30300}
alertmanager:
service: {type: NodePort, nodePort: 30903}
EOF
helm install kube-prom prometheus-community/kube-prometheus-stack \
-n monitoring --create-namespace -f prom-values.yaml
kubectl -n monitoring get pods
# 访问 Grafana: http://<任意节点IP>:30300 (admin / xxx)离线/私有仓库环境在 values 中统一替换镜像:
yaml
# prom-values.yaml 片段示例
grafana:
image:
repository: 192.168.122.156:30000/library/grafana
prometheus:
prometheusSpec:
image:
repository: 192.168.122.156:30000/library/prometheus2.5 安装 Loki 日志栈
bash
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
cat > loki-values.yaml <<'EOF'
loki:
commonConfig: {replication_factor: 1}
storage: {type: filesystem}
singleBinary: {replicas: 1}
promtail:
enabled: true
config:
clients: [{url: http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push}]
EOF
helm install loki grafana/loki-stack -n monitoring -f loki-values.yaml # 新版 chart 为 grafana/loki在 Grafana 中添加 Loki 数据源(http://loki.monitoring.svc.cluster.local:3100),即可在 Explore 中用 LogQL 查询日志:
logql
{namespace="default", pod=~"web-.*"} |= "error"2.6 部署 Ollama 本地模型
在与集群网络可达的一台 GPU/大内存机器上运行 Ollama(推荐独立部署,不占集群资源;有 GPU 节点时也可以 Deployment+Service(11434) 方式跑在集群内):
bash
curl -fsSL https://ollama.com/install.sh | sh
OLLAMA_HOST=0.0.0.0:11434 ollama serve &
ollama pull qwen2.5:7b # 或 llama3.1:8b 等2.7 接入 K8sGPT
安装(详见第四部分):
bash
# 以 operator 方式安装
helm repo add k8sgpt https://charts.k8sgpt.ai/
helm install k8sgpt-operator k8sgpt/k8sgpt-operator -n k8sgpt-operator-system --create-namespace
# 或 CLI 方式
curl -fsSL https://github.com/k8sgpt-ai/k8sgpt/releases/latest/download/k8sgpt_linux_amd64.tar.gz | tar xz -C /usr/local/binCLI 配置 Ollama 后端:
bash
k8sgpt auth add --backend ollama \
--model qwen2.5:7b \
--baseurl http://192.168.122.100:11434
k8sgpt auth list开启中文输出与扫描:
bash
k8sgpt analyze --explain --language chinese # 全量分析 + AI 中文解释
k8sgpt analyze --explain --filter Pod,Deployment --language chinese # 只看关键类型
k8sgpt analyze --explain --language chinese --output json > /tmp/diagnose.json
k8sgpt integration activate prometheus --namespace monitoring # 拉取 Prometheus 告警上下文Operator 方式则通过 CRD 配置:
yaml
apiVersion: core.k8sgpt.ai/v1alpha1
kind: K8sGPT
metadata: {name: k8sgpt-local, namespace: k8sgpt-operator-system}
spec:
ai:
enabled: true
backend: ollama
model: qwen2.5:7b
baseUrl: http://192.168.122.100:11434
language: chinese
noCache: false
repository: ghcr.io/k8sgpt-ai/k8sgpt
version: v0.4.12.8 闭环演练:制造一次故障并走通全流程
bash
# 1) 制造故障:引用不存在的镜像
kubectl create deployment broken-web --image=192.168.122.156:30000/library/nginx:notexist
# 2) 观察告警链路
kubectl get pods -w # ImagePullBackOff
kubectl -n monitoring get prometheusrules # 确认 KubePodCrashLooping 等规则
# 3) AI 诊断
k8sgpt analyze --explain --language chinese --filter Pod
# 输出示例:
# 0 default/broken-web-xxx(broken-web)
# - Error: Back-off pulling image "nginx:notexist"
# - 诊断:镜像 tag 不存在于私有仓库...
# - 解决方案:确认 tag 或推送镜像:docker push ...
# 4) 修复
kubectl set image deploy/broken-web broken-web=192.168.122.156:30000/library/nginx:latest
# 5) 验证闭环:Prometheus 告警恢复,Grafana 面板转绿
kubectl rollout status deploy/broken-web注意事项:K8sGPT 会把资源规格与事件发送给模型,使用公有云模型时注意脱敏;Ollama 本地模型可避免数据出域,是企业内网首选。AI 建议仅供参考,执行修复前人工确认。
3. 综合实战三:GitOps 流水线(ArgoCD + Helm/Kustomize)
3.1 架构与思路
开发者 push 代码/values 变更
│
▼
┌───────────────┐ Webhook / 轮询 ┌──────────────────┐
│ GitLab/GitHub │ ───────────────────────► │ ArgoCD │
│ (Git 仓库) │ │ (集群内运行) │
└───────────────┘ └────────┬─────────┘
│ 同步(sync)
┌─────────────────┼─────────────────┐
▼ ▼ ▼
Kustomize 应用 Helm Chart 应用 HelmChart CRD
(业务应用) (中间件/组件) (RKE2 系统组件)原则:Git 仓库是唯一事实来源(single source of truth),禁止直接 kubectl apply 修改生产对象;所有变更走 MR/PR 评审后由 ArgoCD 自动同步。
3.2 安装 ArgoCD
bash
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# NodePort 暴露(生产建议 Ingress + SSO)
kubectl -n argocd patch svc argocd-server -p '{"spec":{"type":"NodePort","ports":[{"port":443,"nodePort":30443,"name":"https"}]}}'
# 获取初始密码并登录
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d; echo
argocd login 192.168.122.193:30443 --username admin --insecure && argocd account update-password3.3 仓库结构设计
gitops-repo/
├── apps/ # ArgoCD Application 定义(App-of-Apps)
│ ├── infra.yaml
│ └── business-web.yaml
├── infra/ # 集群组件(ingress-nginx、cert-manager,Helm values 方式)
├── business/web/ # 业务应用(Kustomize 方式)
│ ├── base/ # deployment/service/kustomization.yaml
│ └── overlays/{staging,prod}/
└── rke2-components/ # RKE2 系统组件(HelmChart CRD)
└── metallb-config.yaml3.4 用 HelmChart CRD 管理 RKE2 组件
RKE2 内置 Helm 控制器,会把 /var/lib/rancher/rke2/server/manifests/ 中的 HelmChart CRD 渲染为系统组件。GitOps 场景下,我们用 ArgoCD 把 HelmChart CRD 同步进集群(或同步到 manifests 目录的 Git 托管流程)。
rke2-components/metallb-config.yaml:
yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata: {name: rke2-ingress-nginx, namespace: kube-system}
spec:
valuesContent: |-
controller:
service:
type: NodePort
nodePorts: {http: 30080, https: 30443}
metrics:
enabled: true
serviceMonitor: {enabled: true}
---
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata: {name: metallb, namespace: kube-system}
spec:
repo: https://metallb.github.io/metallb
chart: metallb
version: 0.14.8
targetNamespace: metallb-system
valuesContent: |-
controller:
image: {repository: 192.168.122.156:30000/library/metallb-controller}注意事项:
rke2-ingress-nginx、rke2-coredns、rke2-metrics-server等系统 Chart 必须用HelmChartConfig(而不是 HelmChart)来覆盖 values,名字与命名空间必须精确匹配,否则不生效。私有环境注意bootstrap与镜像仓库替换。
3.5 定义 ArgoCD Application
apps/infra.yaml:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: {name: infra, namespace: argocd}
spec:
project: default
source:
repoURL: http://192.168.122.1:31000/gitops-repo.git
targetRevision: main
path: infra
destination: {server: https://kubernetes.default.svc, namespace: kube-system}
syncPolicy:
automated: {prune: true, selfHeal: true} # 删除 Git 移除的资源;手工改动自动纠正
syncOptions: [CreateNamespace=true]apps/business-web.yaml(Kustomize 多环境):
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: {name: web-prod, namespace: argocd}
spec:
project: default
source:
repoURL: http://192.168.122.1:31000/gitops-repo.git
targetRevision: main
path: business/web/overlays/prod
destination: {server: https://kubernetes.default.svc, namespace: web}
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions: [CreateNamespace=true]对应的 business/web/overlays/prod/kustomization.yaml 通过 resources: [../../base] 引用 base,并用 images: 把 nginx 改写为 192.168.122.156:30000/library/nginx:1.27、replicas: 调整为 3,实现环境差异化。
应用并验证:
bash
kubectl apply -f apps/
argocd app list
argocd app sync web-prod
argocd app get web-prod
# 验证自愈:手工删掉一个 Deployment,观察 ArgoCD 自动拉回
kubectl -n web delete deploy web && argocd app get web-prod --refresh3.6 CI 侧配合(GitLab CI 示例)
yaml
# .gitlab-ci.yml —— CI 只负责构建镜像并回写 GitOps 仓库的 tag,不直接操作集群
build:
script:
- docker build -t 192.168.122.156:30000/app/web:$CI_COMMIT_SHORT_SHA .
- docker push 192.168.122.156:30000/app/web:$CI_COMMIT_SHORT_SHA
deploy-config:
script: # 回写 GitOps 仓库,ArgoCD 检测到变更后自动同步
- git clone http://gitlab.example.com/ops/gitops-repo.git && cd gitops-repo/business/web/overlays/prod
- kustomize edit set image nginx=192.168.122.156:30000/app/web:$CI_COMMIT_SHORT_SHA
- git commit -am "deploy web $CI_COMMIT_SHORT_SHA" && git push注意事项:CI 与 CD 分离是关键——CI 只推镜像、改 Git,ArgoCD 只从 Git 拉取并同步,集群凭据不出现在 CI 流水线里。
4. 综合实战四:备份与灾难恢复演练
4.1 双保险策略
| 层 | 工具 | 覆盖范围 | 恢复粒度 |
|---|---|---|---|
| 集群状态层 | RKE2 etcd 快照 | 全部集群状态(含证书、CRD、secret) | 整集群时间点恢复 |
| 应用数据层 | Velero | 选定的命名空间/资源 + PV 数据(restic/kopia) | 命名空间/单资源级 |
4.2 etcd 快照:配置与手工执行
集群已在 config.yaml 中配置自动快照:
yaml
etcd-snapshot-retention: 5
etcd-snapshot-schedule-cron: "0 */6 * * *" # 每 6 小时
etcd-snapshot-dir: /data/rke2/snapshots # 可选:挂到独立磁盘/NFS手工快照与查看:
bash
rke2 etcd-snapshot save --name pre-upgrade-$(date +%F)
rke2 etcd-snapshot list
# 快照位置:/var/lib/rancher/rke2/server/db/snapshots/
# 复制到集群外(重要!快照留在本机等于没备份)
rsync -avz /var/lib/rancher/rke2/server/db/snapshots/ backup-server:/backups/etcd/4.3 Velero 部署
bash
# 准备 S3 兼容存储(MinIO)
velero install \
--provider aws --plugins velero/velero-plugin-for-aws:v1.10.0 \
--bucket velero --secret-file ./credentials-velero \
--backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://192.168.122.100:9000 \
--use-volume-snapshots=false --default-volumes-to-fs-backup
# credentials-velero 内容:
# [default]
# aws_access_key_id=xxx
# aws_secret_access_key=xxx备份与恢复:
bash
# 定时备份
velero schedule create daily-backup --schedule="0 2 * * *" \
--include-namespaces web,monitoring --ttl 720h
# 手工备份
velero backup create web-backup-0719 --include-namespaces web
# 演练恢复(先模拟误删)
kubectl delete namespace web
velero restore create --from-backup web-backup-0719
velero restore describe web-backup-0719-20260719103000
kubectl -n web get all4.4 灾难恢复演练:场景一 —— 单 server 节点损坏
bash
# 1) 从剩余健康节点踢除损坏节点的 etcd 成员
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=... --cert=... --key=... member remove <损坏节点ID>
kubectl delete node rocky9-vm-06
# 2) 新机器按 1.5 节重新 join(同版本、同配置),验证 member list 恢复 3 成员4.5 灾难恢复演练:场景二 —— quorum 丢失(多数 etcd 节点同时宕机)
这是最严重的场景,本仓库 k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md 记录了真实恢复过程。核心流程:
bash
# 1) 选定一个节点作为"幸存节点",停掉所有 server 节点的 rke2-server
systemctl stop rke2-server
# 2) 在幸存节点上用最近快照恢复(cluster-reset)
rke2 server --cluster-reset \
--cluster-reset-restore-path=/var/lib/rancher/rke2/server/db/snapshots/<快照文件>
# 3) 恢复成功后正常启动,验证单节点集群 API 恢复
systemctl start rke2-server && kubectl get nodes
# 4) 其他 server 节点:清空数据目录后重新 join
rm -rf /var/lib/rancher/rke2/server/{db,tls,cred} # manifests 目录如有自定义清单注意备份
# 修改 config.yaml 指向幸存节点 server: https://192.168.122.78:9345
systemctl start rke2-server恢复流程示意:
[3 server 全挂, etcd quorum 丢失]
│
▼
选 1 台 + 最近快照 --cluster-reset ──► 单节点集群恢复 API
│
▼
其余节点清空 db/tls/cred 后重新 join ──► 重建 3 节点 etcd
│
▼
Velero 补齐快照时间点之后的应用变更(如有)真实案例要点(来自
k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md):
- 报错特征:
etcdserver: request timed out、authentication handshake failed: context deadline exceeded、本地 2379 connection refused。--cluster-reset用的快照必须来自健康时刻;恢复后 node-token 会变化,注意同步。- 加入节点前确认镜像已 import 完成,否则新节点长期 NotReady(参见
rke2-master-join-notready-image-import-delay.md)。
4.6 演练 checklist
| 步骤 | 验证标准 |
|---|---|
| 快照可恢复 | 每季度至少一次在隔离环境完成 --cluster-reset 演练 |
| 快照外送 | 快照文件在集群外有 ≥2 份副本 |
| Velero 恢复 | 能从备份恢复一个含 PV 的命名空间并验证数据 |
| RTO/RPO 记录 | 记录每次演练耗时与数据丢失窗口 |
| 文档更新 | 恢复手册与 token、证书位置保持最新 |
5. 故障排查手册(速查式)
使用方式:先按类别看"排查思维导图"定位大方向,再按条目执行命令。每条格式:现象 → 可能原因 → 排查命令 → 解决方案。
5.1 集群层
排查思维导图
集群异常
├─ kubectl 完全无响应? ──► 查 apiserver/VIP/证书(5.1.1 / 5.1.3)
├─ kubectl 慢/超时? ──► 查 etcd 性能与磁盘(5.1.2)
├─ 个别节点 NotReady? ──► 查 kubelet/容器运行时/网络(5.1.4)
└─ 控制平面负载高? ──► 查 apiserver/etcd 资源与大对象(5.1.5)5.1.1 apiserver 不可用
- 现象:
kubectl报The connection to the server <host>:6443 was refused或超时。 - 可能原因:rke2-server 进程挂掉;VIP 漂移异常;etcd quorum 丢失导致 apiserver 起不来;6443 端口被防火墙拦截。
- 排查命令:
bash
systemctl status rke2-server; journalctl -u rke2-server --since "10 min ago" | tail -100
ss -lntp | grep 6443; curl -k https://127.0.0.1:6443/healthz
ping <VIP>; arping -I eth0 <VIP> # 确认 VIP 在哪台机器- 解决方案:按日志修复后
systemctl restart rke2-server;quorum 丢失按 4.5 节 cluster-reset 流程(参见k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md);防火墙放行 6443(参见k8s-issues/rke2-master-join-fails-iptables-firewall-blocking.md)。
5.1.2 etcd 慢 / 空间不足
- 现象:apiserver 间歇超时;日志出现
etcdserver: request timed out、mvcc: database space exceeded。 - 可能原因:磁盘 IO 慢(非 SSD);DB 超配额(默认 2GiB,
--quota-backend-bytes);碎片过多;巨型 ConfigMap/secret 等大对象。 - 排查命令:
bash
# 建议将 --cacert/--cert/--key 三参数固化为别名,以下同
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
endpoint status --cluster -w table
ls -lh /var/lib/rancher/rke2/server/db/etcd/member/snap/db; iostat -x 1 5
kubectl get --raw /metrics | grep apiserver_storage_objects | sort -k2 -n | tail- 解决方案:
etcdctl compact <rev>→etcdctl defrag(先从节点后 leader);超配额先etcdctl alarm disarm再清理大对象并 defrag;长期措施:etcd 目录迁移 SSD、通过 config.yaml 的etcd-arg提升配额(如 4GiB)、确认自动快照(见 4.2)。
5.1.3 证书过期
- 现象:
x509: certificate has expired;节点 join 失败;日志大量 TLS handshake error。 - 可能原因:集群超 1 年未轮换证书;节点时间不同步;恢复旧快照导致证书链回退。
- 排查命令:
bash
for f in /var/lib/rancher/rke2/server/tls/{server-ca,client-ca}.crt \
/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt; do
echo "== $f"; openssl x509 -in $f -noout -enddate
done
curl -k --cert /var/lib/rancher/rke2/server/tls/client-admin.crt \
--key /var/lib/rancher/rke2/server/tls/client-admin.key https://127.0.0.1:6443/healthz
chronyc tracking- 解决方案:
bash
# RKE2 内置轮换(v1.23+)
rke2 certificate rotate
systemctl restart rke2-server
# agent 节点证书由 kubelet 自动轮换;失效时删除
# /var/lib/rancher/rke2/agent/client-kubelet.crt 后重启 rke2-agent注意事项:先校准时间再轮换证书;多 server 集群逐台轮换并验证。
5.1.4 节点 NotReady
- 现象:某节点
NotReady,其上 Pod 被驱逐。 - 可能原因:kubelet/containerd 停止;PID/磁盘压力;与 apiserver 网络不通;CNI 未就绪;镜像 import 延迟(离线 join 后常见)。
- 排查命令:
bash
kubectl describe node <node> # 看 Conditions 与 Events
ssh <node> 'systemctl status rke2-agent; journalctl -u rke2-agent --since "30 min ago" | tail -50'
crictl ps | head; df -h /var/lib; free -m
ls -lh /var/lib/rancher/rke2/agent/images/ # 离线 join:确认镜像是否还在导入- 解决方案:按 describe 的 Condition 对症下药(DiskPressure 清磁盘、NetworkUnavailable 查 CNI);镜像导入延迟耐心等待或提前
ctr -n k8s.io images import预热(参见k8s-issues/rke2-master-join-notready-image-import-delay.md)。
5.1.5 控制平面 CPU/内存高
- 现象:server 节点
top中 kube-apiserver / etcd 占用异常。 - 可能原因:失控客户端大量 LIST/WATCH;CrashLoop 事件风暴;大对象序列化开销;审计日志量过大。
- 排查命令:
bash
kubectl get events -A --sort-by=.lastTimestamp | tail -30
kubectl get --raw /metrics | grep -E 'apiserver_request_total|watch_events' | head
ss -ant | grep 6443 | wc -l # 连接数异常突增往往指向失控客户端- 解决方案:按 userAgent 聚合 metrics 找到异常客户端并修复;配置 apiserver 限流(
--max-requests-inflight);拆分大 ConfigMap;控制 events TTL。
5.2 网络层
排查思维导图
网络不通
├─ 访问 Service ClusterIP 不通? ──► Endpoints → kube-proxy(IPVS) → 节点选择器(5.2.1)
├─ 域名解析失败? ──► CoreDNS Pod → nodelocaldns → 上游 DNS(5.2.2)
├─ Ingress 返回 502/504? ──► controller → upstream Service → Pod 健康(5.2.3)
├─ 某些流量莫名被断? ──► NetworkPolicy 是否误伤(5.2.4)
└─ 跨节点 Pod 互 ping 不通? ──► CNI VXLAN/BGP、防火墙、MTU(5.2.5)5.2.1 Service 不通
- 现象:
curl http://svc:port超时或拒绝。 - 可能原因:Endpoints 为空(selector 不匹配/Pod 未 Ready);targetPort 写错;kube-proxy/IPVS 规则异常。
- 排查命令:
bash
kubectl get svc,ep <svc> # endpoints 是否有后端
kubectl get pods -l <selector> -o wide # Pod 是否 Ready
ipvsadm -Ln | grep -A5 <clusterIP> # IPVS 规则
kubectl run -it --rm debug --image=busybox:1.36 --restart=Never -- wget -qO- <clusterIP>:<port>- 解决方案:selector 与 Pod label 对齐;核对
port → targetPort → 容器监听端口链路(参见k8s-service/port-targetport-nodeport-explained.md);删除 kube-proxy Pod 让其重建。
5.2.2 DNS 解析失败
- 现象:Pod 内
nslookup超时或 NXDOMAIN。 - 可能原因:CoreDNS 异常;Corefile 配置错;nodelocaldns 与 kube-dns IP 不匹配;上游 DNS 不可达;iptables 拦截 53。
- 排查命令:
bash
kubectl -n kube-system get pods -l k8s-app=kube-dns -o wide
kubectl -n kube-system logs deploy/rke2-coredns-rke2-coredns | tail
kubectl -n kube-system get cm rke2-coredns-rke2-coredns -o yaml # Corefile
kubectl exec -it <pod> -- sh -c 'cat /etc/resolv.conf; nslookup kubernetes.default 10.13.0.10'- 解决方案:CoreDNS 异常重启;nodelocaldns 模板变量核对(见 2.3);上游 DNS 不通改 forward 配置;防火墙放行 UDP/TCP 53。
5.2.3 Ingress 502 / 504
- 现象:经 Ingress 访问返回 502/504。
- 可能原因:后端无可用 Endpoints;readiness 未配导致流量打到不健康 Pod;TLS 配置错;controller 跨节点网络异常;后端响应慢超 proxy timeout。
- 排查命令:
bash
kubectl -n ingress-nginx logs deploy/rke2-ingress-nginx-controller | grep -E '502|504|upstream'
kubectl get ing,ep -A; kubectl describe ing <name> # 看 backend 与注解
kubectl port-forward svc/<svc> 8080:<port> & # 绕过 Ingress 直连 Service 验证- 解决方案:502 先查 upstream(Service/Endpoints/Pod);504 调大注解
nginx.ingress.kubernetes.io/proxy-read-timeout;TLS 问题查tlssecret 与域名匹配。controller Pod 卡在 ContainerCreating 也会导致全站 503,参见k8s-issues/rke2-ingress-nginx-controller-ContainerCreating.md。
5.2.4 NetworkPolicy 误伤
- 现象:应用互访超时但各自 Pod 健康;新上线 policy 后故障出现。
- 可能原因:default-deny 漏配放行;selector 标签写错;忘记放行 DNS(kube-system:53)与 ingress 命名空间。
- 排查命令:
bash
kubectl get networkpolicy -A; kubectl describe networkpolicy <name>
cilium monitor --type drop; cilium policy get # Cilium 环境实时观察丢包- 解决方案:逐条禁用 policy 定位;补充 DNS egress 放行(模板见附录);上线前
--dry-run=server+ 灰度命名空间验证。
5.2.5 跨节点 Pod 不通
- 现象:同节点 Pod 互通,跨节点不通。
- 可能原因:VXLAN 端口(UDP 8472)被防火墙拦截;MTU 不匹配丢大包;节点路由缺失;CNI Pod 异常。
- 排查命令:
bash
kubectl -n kube-system get pods -o wide | grep -E 'cilium|canal'
ip link show | grep -E 'flannel|cilium|vxlan'; ip route | grep 10.12
ping -s 1400 <对端PodIP> # 测 MTU(小包通大包不通即 MTU 问题)
nc -uvz <对端节点IP> 8472 # VXLAN 端口连通性- 解决方案:防火墙放行 UDP 8472;统一 MTU(VXLAN 要求宿主机 ≥1500,隧道内 1450);重启异常 CNI Pod。
5.3 应用层
排查思维导图
Pod 异常(kubectl get pods 状态列)
├─ Pending ──► 资源不足/亲和性/PVC 未绑定(5.3.1)
├─ ContainerCreating ──► 拉镜像慢/挂载卷失败/CNI 问题
├─ ImagePullBackOff ──► 镜像名/tag/仓库认证/网络(5.3.3)
├─ CrashLoopBackOff ──► describe + logs 看退出原因(5.3.2)
├─ OOMKilled ──► limits 太小/内存泄漏(5.3.4)
├─ Running 但不健康 ──► Probe 失败(5.3.5)
└─ Deployment 更新卡住 ──► 新版本不 Ready / 配额 / PDB(5.3.6)通用三板斧(任何 Pod 问题先跑这三条):
bash
kubectl describe pod <pod> -n <ns> # 90% 的问题 Events 里写得很清楚
kubectl logs <pod> -n <ns> --previous # 崩溃前日志
kubectl get events -n <ns> --sort-by=.lastTimestamp | tail
k8sgpt analyze --explain --language chinese --filter Pod -n <ns> # AI 辅助5.3.1 Pod 一直 Pending
- 现象:Pending 无节点可调度。
- 可能原因:requests 超节点余量;nodeSelector/亲和性无匹配;污点未容忍;PVC 未绑定。
- 排查命令:
kubectl describe pod看FailedScheduling事件原文。 - 解决方案:调小 requests 或扩容;
kubectl get nodes --show-labels核对标签;补 tolerations;按 5.4.1 处理 PVC。
5.3.2 CrashLoopBackOff
- 现象:容器反复重启,
RESTARTS持续增长。 - 可能原因:应用报错退出(配置/依赖/端口占用);entrypoint 写错;探针太苛刻;挂载的 ConfigMap/secret 内容错误。
- 排查命令:
bash
kubectl logs <pod> --previous; kubectl describe pod <pod> | grep -A3 "Last State"
kubectl exec -it <pod> -- sh # 能起来的话进去手动跑命令复现- 解决方案:按日志修复应用/配置;探针放宽(initialDelaySeconds 调大);临时用
command: ["sleep","3600"]进容器排查。
5.3.3 ImagePullBackOff
- 现象:拉取镜像失败。
- 可能原因:镜像名/tag 不存在;未配
registries.yaml或缺 imagePullSecrets;到仓库网络不通;镜像太大超时。 - 排查命令:
bash
kubectl describe pod <pod> | grep -A5 Events
crictl pull <image> # 在节点上直接验证
cat /etc/rancher/rke2/registries.yaml; curl -s http://192.168.122.156:30000/v2/_catalog- 解决方案:修正镜像引用;配置 registries.yaml 并重启 rke2;创建
docker-registry类型 secret 并挂到 ServiceAccount。
5.3.4 OOMKilled
- 现象:容器被 OOM killer 终止,
Reason: OOMKilled。 - 可能原因:memory limits 过小;内存泄漏;JVM 未感知容器限制(老版本 JDK)。
- 排查命令:
bash
kubectl describe pod <pod> | grep -B2 -A5 OOMKilled; kubectl top pod <pod> --containers
dmesg | grep -i "killed process" # 节点层面确认- 解决方案:合理上调 limits(参考
kubectl top峰值 ×1.5);JVM 应用加-XX:MaxRAMPercentage=75.0;定位泄漏(heap dump/pprof)。
5.3.5 Probe(探针)失败
- 现象:Events 显示
Liveness probe failed反复重启;或 readiness 失败导致 Service 无后端。 - 可能原因:探针路径/端口错误;启动慢于 initialDelaySeconds;超时太短高峰期响应慢;探针依赖外部服务导致级联故障。
- 排查命令:
bash
kubectl describe pod <pod> | grep -A8 Probes
kubectl exec -it <pod> -- curl -v http://localhost:<port>/<path>; kubectl logs <pod> | tail- 解决方案:修正探针配置;慢启动应用配
startupProbe;liveness 探针只检查进程本身存活,外部依赖检查放 readiness。
5.3.6 滚动更新卡住
- 现象:
rollout status一直等待,新旧 Pod 并存。 - 可能原因:新版本 Pod 不 Ready;
maxUnavailable: 0且资源不足腾挪;PDB 阻止驱逐;HPA 与手写 replicas 冲突。 - 排查命令:
bash
kubectl rollout status deploy/<name>; kubectl describe deploy/<name> | grep -A10 Conditions
kubectl get pods -l app=<name> -o wide; kubectl get pdb- 解决方案:先修新版本 Pod 的就绪问题;
kubectl rollout undo deploy/<name>回滚止损;调整 strategy 或临时放宽 PDB。
5.4 存储层
排查思维导图
存储异常
├─ PVC 一直 Pending? ──► StorageClass/provisioner/容量(5.4.1)
├─ Pod 挂载超时? ──► 存储插件/挂载凭据/节点网络(5.4.2)
└─ 调度不到节点? ──► Local PV 节点亲和(5.4.3)5.4.1 PVC Pending
- 现象:PVC 一直
Pending,Pod 卡在 ContainerCreating。 - 可能原因:无匹配/默认 StorageClass;provisioner 异常;存储后端容量不足;
WaitForFirstConsumer模式下无 Pod 触发绑定。 - 排查命令:
bash
kubectl describe pvc <pvc> # 看 Events
kubectl get sc; kubectl -n <storage-ns> logs deploy/<provisioner> | tail- 解决方案:修正 storageClassName 或设默认 SC(注解
storageclass.kubernetes.io/is-default-class: "true");修复 provisioner;扩容存储后端。
5.4.2 挂载超时
- 现象:Events 报
MountVolume.SetUp failed: timed out waiting for the condition。 - 可能原因:NFS 不可达或 exports 配置错;挂载凭据错误;节点缺 nfs-common;Longhorn/Ceph 副本不健康。
- 排查命令:
bash
kubectl describe pod <pod>; journalctl -u rke2-agent | grep -i mount | tail
ssh <node> showmount -e <nfs-server>
ssh <node> mount -t nfs <nfs-server>:/export /tmp/test # 手动验证- 解决方案:修复 NFS/存储端点与网络;安装 nfs-common;检查存储系统自身健康度(如
kubectl -n longhorn-system get volumes)。
5.4.3 Local PV 节点亲和问题
- 现象:使用 local PV 的 Pod 调度失败或被调度到无数据的节点。
- 可能原因:PV 的
nodeAffinity与期望节点不一致;节点故障后数据不跟随无法迁移;误删 PV 后 PVC 残留。 - 排查命令:
bash
kubectl get pv <pv> -o yaml | grep -A10 nodeAffinity
kubectl describe pod <pod> | grep FailedScheduling- 解决方案:用 nodeSelector 把 Pod 固定到 PV 所在节点;节点故障按备份恢复重建;理解 local PV 语义是性能换可用性,关键业务慎用。
深入排查案例可继续参考本仓库
k8s-issues/目录各文档与k8s-service/service-full-chain-deep-dive.md、metaLB/k8s-full-chain-deep-dive.md的链路分析方法。
6. 常见面试题(20 题)
每题给出答案要点,适合自测与面试前速过。
1. 简述 Kubernetes 中 Pod 的创建流程(从 kubectl apply 到容器运行)。 要点:kubectl → apiserver(认证/鉴权/准入)→ 写 etcd → scheduler watch 到未绑定 Pod,打分选节点,写 binding → 目标节点 kubelet watch 到 → 调 CRI 拉镜像、CNI 配网络、CSI 挂卷 → 启动容器 → 上报状态。
2. Service 的 ClusterIP/NodePort/LoadBalancer 区别是什么? 要点:ClusterIP 仅集群内虚拟 IP(iptables/IPVS 转发);NodePort 在 ClusterIP 基础上每节点开端口;LoadBalancer 再叠加外部 LB(云厂商或 MetalLB)。引用 k8s-service/nodeip-vs-vip-nodeport.md。
3. Service 的 port、targetPort、nodePort、containerPort 分别是什么? 要点:port 是 Service 暴露端口;targetPort 转发到 Pod 的端口;nodePort 节点端口(30000-32767);containerPort 仅是声明性信息。引用 k8s-service/port-targetport-nodeport-explained.md。
4. iptables 模式与 IPVS 模式的 kube-proxy 有何差异? 要点:iptables 规则链式匹配 O(n),大规模下性能差、更新慢;IPVS 哈希表 O(1),支持多种调度算法,适合大规模集群。RKE2 可用 kube-proxy-arg: ["proxy-mode=ipvs"] 开启。
5. Deployment 滚动更新原理,maxSurge/maxUnavailable 含义? 要点:Deployment 管理 ReplicaSet,滚动时新建 RS 逐步扩容、旧 RS 缩容;maxSurge 允许超额的 Pod 数/比例;maxUnavailable 允许不可用数量。卡住时先查新 Pod 是否 Ready。
6. readinessProbe 与 livenessProbe 的区别? 要点:readiness 失败→从 Endpoints 摘除(不重启);liveness 失败→重启容器。startupProbe 用于慢启动应用兜底。
7. Pod 一直 Pending 怎么排查? 要点:describe 看 FailedScheduling:资源不足/亲和性/污点/PVC 未绑定四大类。
8. CrashLoopBackOff 的排查思路? 要点:logs --previous + describe 看退出码;区分应用错误、配置错误、探针误杀;必要时 sleep 容器进终端复现。
9. etcd 在 K8s 中的作用?为什么要求奇数节点? 要点:唯一持久化存储(所有集群状态);Raft 需要多数派(quorum = n/2+1),3 节点容忍 1 故障,4 节点同样只容忍 1 故障但多一台成本,故用奇数。
10. RKE2 与普通 K8s(kubeadm)的主要区别? 要点:单二进制、containerd 内置、静态 Pod 运行控制平面、默认安全加固(CIS)、内置 Helm 控制器(HelmChart CRD 管理组件)、自带 etcd 快照工具、FIPS 支持。
11. RKE2 高可用架构如何设计? 要点:≥3 server(内置 etcd)+ VIP/LB(kube-vip)暴露 6443/9345;tls-san 必须含 VIP;agent 通过 VIP join;配置一致(cluster-cidr/service-cidr/cni),否则 join 报 critical configuration mismatch。
12. 如何备份和恢复一个 RKE2 集群? 要点:定期 etcd 快照(cron 配置)+ 快照外送;灾难时在幸存节点 rke2 server --cluster-reset --cluster-reset-restore-path=<快照> 恢复单节点,其他节点清 db/tls/cred 后重新 join;应用层用 Velero 做增量补充。
13. etcd quorum 丢失怎么办? 要点:确认多数成员不可用→选一台用最近快照 cluster-reset→重建单节点集群→其余节点清空数据目录重新 join;全程参考 k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md 的真实流程。
14. CoreDNS 解析超时可能有哪些原因? 要点:CoreDNS Pod 异常/资源不足;上游 DNS 不通;nodelocaldns 与 kube-dns IP 配置错;conntrack 表满(UDP 丢包);NetworkPolicy 阻断 53。
15. Ingress 502 如何排查? 要点:controller 日志→upstream Service Endpoints→Pod 是否 Ready→readiness 配置→TLS 配置;区分 controller 自身异常与后端异常。
16. NetworkPolicy 生效的前提和常见坑? 要点:CNI 必须支持(Calico/Cilium 支持,纯 Flannel 不支持);策略是白名单叠加模型;常见坑:忘记放行 DNS egress、namespaceSelector 标签不对、default-deny 上线即断网。
17. HPA 的工作原理?为什么不能和 Deployment 的 replicas 同时手写? 要点:metrics-server 采集指标→HPA 控制器按 目标值/当前值×当前副本数 计算期望副本→改 scale 子资源;手写 replicas 会被 HPA 覆盖,GitOps 场景要从 manifest 中移除 replicas 字段。
18. GitOps 的核心原则?ArgoCD 的 selfHeal 解决什么问题? 要点:声明式、Git 为唯一事实来源、拉模式同步、持续 reconcile;selfHeal 解决集群状态被手工改动(配置漂移)后自动拉回 Git 定义。
19. K8sGPT 能做什么?生产使用注意什么? 要点:扫描集群异常资源(analyzer),结合 AI 给出根因解释与修复建议;支持 Ollama 等本地模型避免数据出域;AI 建议需人工复核,不直接自动执行变更。
20. 节点 NotReady 的可能原因有哪些? 要点:kubelet/containerd 停止;磁盘/PID 压力;CNI 未就绪;证书过期;节点时间漂移;镜像 import 延迟(离线 join);节点到 apiserver 网络中断。引用 k8s-issues/rke2-master-join-notready-image-import-delay.md。
本部分小结:四个实战串起了"建集群 → 可观测 → GitOps → 灾备"的生产闭环,故障手册与面试题用于日常速查与自测。建议把故障排查手册打印放在工位——真正出故障时,肌肉记忆比搜索引擎更可靠。