Skip to content

K8s 入门:最小概念与排障 ​

K8s 的概念很多,但日常 90% 的操作只涉及 Pod / Deployment / Service / Ingress / ConfigMap 五个对象。

一、五个对象的关系 ​

text
Ingress(域名/路径 → Service)
   ↓
Service(稳定 VIP + 负载均衡)
   ↓
Deployment(副本数、滚动更新)
   ↓
ReplicaSet → Pod(真正运行的容器)
对象一句话
Pod最小调度单元,一个或多个容器共享网络
Deployment管副本数和滚动更新,不直接管 Pod
Service一组 Pod 的稳定入口(ClusterIP/NodePort/LoadBalancer)
Ingress七层路由,按域名/路径转发到 Service
ConfigMap / Secret配置与密钥,挂载或注入环境变量

二、最小可用清单 ​

yaml
# app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-api
  namespace: shop
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: order-api
    spec:
      containers:
        - name: app
          image: registry.internal:5000/shop/order-api:1.4.2
          ports:
            - containerPort: 8080
          envFrom:
            - configMapRef:
                name: order-api-config
          resources:
            requests:
              cpu: 500m
              memory: 1Gi
            limits:
              cpu: "2"
              memory: 2Gi
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 20
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
          lifecycle:
            preStop:
              exec:
                command: ["sh", "-c", "sleep 5"]
---
apiVersion: v1
kind: Service
metadata:
  name: order-api
  namespace: shop
spec:
  selector:
    app: order-api
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: order-api
  namespace: shop
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: order-api
                port:
                  number: 80
bash
kubectl apply -f app.yaml
kubectl -n shop rollout status deploy/order-api
text
deployment "order-api" successfully rolled out

关键点:

配置为什么重要
requests调度依据,不设会被塞到资源不足的节点
limits.memory超过就 OOMKilled
readinessProbe没通过就不接流量,滚动更新不中断的关键
livenessProbe失败会重启容器,不要配得太激进
maxUnavailable: 0滚动时先起新的再停旧的
preStop sleep 5给 Service 摘流量留时间,避免请求打到正在退出的 Pod

三、日常命令 ​

bash
kubectl get pods -n shop -o wide
kubectl describe pod order-api-7d9c8f6b5-x2k4m -n shop
kubectl logs -f order-api-7d9c8f6b5-x2k4m -n shop --tail 100
kubectl logs -n shop -l app=order-api --tail=20 --prefix
kubectl exec -it order-api-7d9c8f6b5-x2k4m -n shop -- sh
kubectl rollout history deploy/order-api -n shop
kubectl rollout undo deploy/order-api -n shop
kubectl rollout restart deploy/order-api -n shop
kubectl get events -n shop --sort-by=.lastTimestamp | tail -20
text
NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE
order-api-7d9c8f6b5-x2k4m    1/1     Running   0          12m   10.244.1.42  node-2
order-api-7d9c8f6b5-m8p7q    1/1     Running   0          12m   10.244.2.18  node-3
order-api-7d9c8f6b5-t5r9s    1/1     Running   0          12m   10.244.1.51  node-2

kubectl get events 是排查的第一现场:调度失败、拉镜像失败、探针失败都会在这里留记录。

四、四种常见异常状态 ​

Pending ​

bash
kubectl describe pod <pod> -n shop | tail -20
text
Events:
  Type     Reason             Age   From               Message
  ----     ------             ----  ----               -------
  Warning  FailedScheduling   2m    default-scheduler  0/3 nodes are available:
           2 Insufficient cpu, 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }

原因:资源不够、节点有污点、亲和性不满足、PVC 没绑定。

ImagePullBackOff ​

text
Warning  Failed  1m  kubelet  Failed to pull image "registry.internal:5000/shop/order-api:1.4.2":
rpc error: code = Unknown desc = Error response from daemon: manifest unknown

三种原因:

  1. 镜像 tag 不存在(最常见)。
  2. 私有仓库没配 imagePullSecrets。
  3. 节点到 registry 的网络不通 / 证书不受信。
bash
kubectl create secret docker-registry regcred \
  --docker-server=registry.internal:5000 \
  --docker-username=admin --docker-password='xxx' -n shop

CrashLoopBackOff ​

容器启动后立刻退出,K8s 指数退避重启(10s、20s、40s…最多 5 分钟)。

bash
kubectl logs <pod> -n shop --previous

--previous 看上一次崩溃前的日志,这是关键。

OOMKilled ​

bash
kubectl describe pod <pod> -n shop | grep -A2 'Last State'
text
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137

limits.memory 太小,或 JVM 没按容器限额调整(-XX:MaxRAMPercentage=70)。

五、探针的三个坑 ​

坑后果正确做法
liveness 用 /health 且依赖数据库数据库抖动 → 全部 Pod 被重启 → 雪崩liveness 只查自身存活
readiness 没配滚动更新时新 Pod 未就绪就接流量必配 readiness
initialDelaySeconds 太小Java 冷启动 40s,20s 就开始探测 → 反复重启或用 startupProbe
yaml
startupProbe:
  httpGet:
    path: /actuator/health
    port: 8080
  failureThreshold: 30
  periodSeconds: 5

startupProbe 成功前,liveness/readiness 都不生效——专门解决"启动慢"。

六、ConfigMap 与 Secret ​

bash
kubectl create configmap order-api-config -n shop \
  --from-file=application-prod.yml

kubectl create secret generic order-api-secret -n shop \
  --from-literal=DB_PASSWORD='xxx'
yaml
envFrom:
  - configMapRef:
      name: order-api-config
  - secretRef:
      name: order-api-secret

Secret 默认是 base64,不是加密

kubectl get secret -o yaml 直接能看到明文(base64 解码即可)。要真正保护:

  • 开启 etcd 静态加密。
  • 用外部密钥管理(Vault、云 KMS)。
  • 至少限制 RBAC,别让所有人能读 secret。

七、踩过的坑 ​

现象根因处置
Pod 一直 Pending资源/污点/亲和性describe 看 Events
ImagePullBackOfftag 错 / 没 secret查镜像名与 imagePullSecrets
CrashLoopBackOff应用启动失败logs --previous
OOMKilledlimit 太小或堆外超限调 limit,JVM 用 MaxRAMPercentage
滚动更新期间 502没配 readiness / 没 preStop补探针与优雅退出
Pod 重启但没日志启动就崩--previous + describe
Service 访问不通selector 不匹配kubectl get endpoints 看是否为空
改了 ConfigMap 不生效环境变量注入只在启动时读重启 Pod,或用 volume 挂载
kubectl exec 进不去distroless 无 shell用 kubectl debug 临时容器