Kubernetes Crash Course
Pods, Deployments, Services, Ingress and ConfigMaps — the mental model and the daily commands for running stateless services on K8s.
The object model in one screen
Kubernetes vocabulary feels huge, but for a stateless web service you only need five objects, wrapped in a strict hierarchy: Deployment manages ReplicaSets which manage Pods; Service gives them a stable address; Ingress routes HTTP from outside; ConfigMap/Secret injects config.
| Object | Purpose | Stability |
|---|---|---|
| Pod | 最小调度单元,1+ 共享网络/存储的容器 | IP 会变,随生死 |
| ReplicaSet | 维持指定数量的 Pod 副本 | 随滚动更新换代 |
| Deployment | 声明期望副本数与镜像版本,做滚动更新/回滚 | 长期存在 |
| Service | 为一组 Pod 提供稳定 ClusterIP + 负载均衡 | 长期存在 |
| Ingress | 七层路由:域名/路径 → Service | 长期存在 |
| ConfigMap/Secret | 配置与敏感数据,可挂载为文件或环境变量 | 独立于 Pod 生命周期 |
外部流量
│
▼
Ingress (backend-wiki.example.com → svc:api)
│
▼
Service api (ClusterIP 10.96.x.x, selectors app=api) ← 稳定入口
│ kube-proxy 在各节点做 DNAT
▼
Deployment api (replicas=3)
└─ ReplicaSet (镜像 v1.4.2)
├─ Pod api-7d8b9c-x2k4p ← 真正跑容器的地方
├─ Pod api-7d8b9c-mp1qz
└─ Pod api-7d8b9c-v9w3t
Your first Deployment + Service
apiVersion: apps/v1
kind: Deployment
metadata: {name: api}
spec:
replicas: 3
selector: {matchLabels: {app: api}}
template:
metadata: {labels: {app: api}}
spec:
containers:
- name: api
image: registry.example.com/api:1.4.2
ports: [{containerPort: 8080}]
resources:
requests: {cpu: 100m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
readinessProbe:
httpGet: {path: /health, port: 8080}
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata: {name: api}
spec:
selector: {app: api}
ports: [{port: 80, targetPort: 8080}]
- readinessProbe failures remove the Pod from the Service endpoints — it stays alive but receives no traffic
- Rolling update: Deployment creates a new ReplicaSet, scales it up and the old one down, respecting maxSurge/maxUnavailable
- rollout undo / rollout status are your undo and progress bar
kubectl apply -f api.yaml
kubectl get pods -l app=api -o wide
kubectl rollout status deployment/api
kubectl rollout undo deployment/api --to-revision=2
kubectl describe pod api-7d8b9c-x2k4p # 看 Events 排查为什么没起来
Config injection: ConfigMap & Secret
Twelve-factor style: config lives outside the image. ConfigMap and Secret can be consumed three ways: env vars (simple, but no live update), command args, or mounted files (supports dynamic reload).
apiVersion: v1
kind: ConfigMap
metadata: {name: api-conf}
data:
config.yaml: |
log_level: info
feature_flags:
new_search: true
---
# 在 Deployment spec.template.spec 里:
volumes:
- name: conf
configMap: {name: api-conf}
containers:
- name: api
volumeMounts:
- {name: conf, mountPath: /etc/api}
# 或用环境变量
env:
- {name: LOG_LEVEL, valueFrom: {configMapKeyRef: {name: api-conf, key: log_level}}}
- {name: DB_PASSWORD, valueFrom: {secretKeyRef: {name: api-secret, key: password}}}
The daily debugging loop
Ninety percent of K8s debugging is describe + logs + events, in that order. The Events section of describe tells you why the scheduler, kubelet or the probe controller is unhappy.
kubectl get events --sort-by='.lastTimestamp' -n prod # 全命名空间事件
kubectl top pod -n prod # 需要 metrics-server
kubectl logs -f api-7d8b9c-x2k4p --previous # 看崩之前的日志
kubectl exec -it api-7d8b9c-x2k4p -- sh
kubectl debug -it api-7d8b9c-x2k4p --image=nicolaka/netshoot # 带工具箱的临时容器
| Symptom | Look at |
|---|---|
| Pod 一直 Pending | describe Events:资源不足/调度约束/镜像拉不下来 |
| CrashLoopBackOff | logs --previous:应用启动失败的真实报错 |
| 就绪探针失败 | 应用日志 + endpoint 是否真的监听 |
| 503 时有时无 | get endpoints:Pod 是否被全数摘除 |
| 节点压力 | kubectl top node + describe node 的 Conditions |
一屏看懂对象模型
K8s 词汇看似庞大,但对无状态 Web 服务只需五个对象,且层级严格:Deployment 管理 ReplicaSet、ReplicaSet 管理 Pod;Service 提供稳定地址;Ingress 把外部 HTTP 流量路由进来;ConfigMap/Secret 注入配置。
| 对象 | 职责 | 稳定性 |
|---|---|---|
| Pod | 最小调度单元,1+ 共享网络/存储的容器 | IP 会变,随生死 |
| ReplicaSet | 维持指定数量的 Pod 副本 | 随滚动更新换代 |
| Deployment | 声明期望副本数与镜像版本,做滚动更新/回滚 | 长期存在 |
| Service | 为一组 Pod 提供稳定 ClusterIP + 负载均衡 | 长期存在 |
| Ingress | 七层路由:域名/路径 → Service | 长期存在 |
| ConfigMap/Secret | 配置与敏感数据,可挂载为文件或环境变量 | 独立于 Pod 生命周期 |
外部流量
│
▼
Ingress (backend-wiki.example.com → svc:api)
│
▼
Service api (ClusterIP 10.96.x.x, selectors app=api) ← 稳定入口
│ kube-proxy 在各节点做 DNAT
▼
Deployment api (replicas=3)
└─ ReplicaSet (镜像 v1.4.2)
├─ Pod api-7d8b9c-x2k4p ← 真正跑容器的地方
├─ Pod api-7d8b9c-mp1qz
└─ Pod api-7d8b9c-v9w3t
第一个 Deployment 与 Service
apiVersion: apps/v1
kind: Deployment
metadata: {name: api}
spec:
replicas: 3
selector: {matchLabels: {app: api}}
template:
metadata: {labels: {app: api}}
spec:
containers:
- name: api
image: registry.example.com/api:1.4.2
ports: [{containerPort: 8080}]
resources:
requests: {cpu: 100m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
readinessProbe:
httpGet: {path: /health, port: 8080}
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata: {name: api}
spec:
selector: {app: api}
ports: [{port: 80, targetPort: 8080}]
- readinessProbe 失败会把 Pod 从 Service 端点摘掉——Pod 还活着,但不再收到流量
- 滚动更新:Deployment 建新 ReplicaSet 逐步扩容、旧的同时缩容,由 maxSurge/maxUnavailable 控制节奏
- rollout undo / rollout status 就是你的回滚键和进度条
kubectl apply -f api.yaml
kubectl get pods -l app=api -o wide
kubectl rollout status deployment/api
kubectl rollout undo deployment/api --to-revision=2
kubectl describe pod api-7d8b9c-x2k4p # 看 Events 排查为什么没起来
配置注入:ConfigMap 与 Secret
十二要素风格:配置不进镜像。ConfigMap 与 Secret 有三种消费方式:环境变量(简单但不能热更新)、命令行参数、挂载为文件(可配合应用热更新)。
apiVersion: v1
kind: ConfigMap
metadata: {name: api-conf}
data:
config.yaml: |
log_level: info
feature_flags:
new_search: true
---
# 在 Deployment spec.template.spec 里:
volumes:
- name: conf
configMap: {name: api-conf}
containers:
- name: api
volumeMounts:
- {name: conf, mountPath: /etc/api}
# 或用环境变量
env:
- {name: LOG_LEVEL, valueFrom: {configMapKeyRef: {name: api-conf, key: log_level}}}
- {name: DB_PASSWORD, valueFrom: {secretKeyRef: {name: api-secret, key: password}}}
日常排障循环
九成的 K8s 排障就是 describe + logs + events 三步,按这个顺序。describe 里的 Events 会告诉你调度器、kubelet 或探针控制器究竟哪里不满意。
kubectl get events --sort-by='.lastTimestamp' -n prod # 全命名空间事件
kubectl top pod -n prod # 需要 metrics-server
kubectl logs -f api-7d8b9c-x2k4p --previous # 看崩之前的日志
kubectl exec -it api-7d8b9c-x2k4p -- sh
kubectl debug -it api-7d8b9c-x2k4p --image=nicolaka/netshoot # 带工具箱的临时容器
| 现象 | 去看哪 |
|---|---|
| Pod 一直 Pending | describe Events:资源不足/调度约束/镜像拉不下来 |
| CrashLoopBackOff | logs --previous:应用启动失败的真实报错 |
| 就绪探针失败 | 应用日志 + endpoint 是否真的监听 |
| 503 时有时无 | get endpoints:Pod 是否被全数摘除 |
| 节点压力 | kubectl top node + describe node 的 Conditions |