Docker 解决了"单个容器怎么跑",但几十上百个容器谁来管?挂了谁自动拉起来?流量怎么分给多副本?这就是 Kubernetes(K8s)干的事:它是容器集群的自动调度管家。这一页带你从 kubectl 命令到手写 Deployment/Service YAML,把最核心的四个对象练熟。
K8s 概念多,先抓主线:你声明"我要几个副本",K8s 负责凑齐。
kubectl create deployment 起一个 nginx。kubectl apply -f 起来。以前运维是命令式:你敲 docker run,起一个。挂了再手动起一个。K8s 反过来,是声明式:你写一份 YAML 说"我希望有 3 个 nginx Pod 在跑",交给 K8s,它负责让现实状态不断逼近这个期望状态。
关键洞察:Pod 是"一次性"的——它随时可能被销毁、重建、调度到别的机器,IP 每次都变。所以你永远不要直接连 Pod 的 IP。Service 就是那个固定不变的门牌号,背后自动跟着当前健康的 Pod。
自愈:某个 Pod 死了,Deployment 控制器发现"现在只有 2 个,期望 3 个",立刻在某处补一个新的。这就是"自愈",不用人管。
滚动更新:改了镜像版本,Deployment 会"起新 Pod、摘旧 Pod"交替进行,全程不中断流量。
app: web,Service 选 app: web,两者靠标签"相亲"关联。改标签就断联,这是最常踩的坑。| 命令 | 作用 |
|---|---|
kubectl get pods | 列出 Pod(-o wide 看节点/IP) |
kubectl get deploy,svc | 列出 Deployment 和 Service |
kubectl apply -f xxx.yaml | 声明式创建/更新对象 |
kubectl describe pod 名 | 看 Pod 详情和 events(排错关键) |
kubectl logs 名 -f | 看容器日志 |
kubectl exec -it 名 -- sh | 进容器 |
kubectl scale deploy/web --replicas=5 | 扩缩容 |
kubectl delete -f xxx.yaml | 删除对象 |
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
labels: {app: web}
spec:
replicas: 3 # 期望 3 个副本
selector:
matchLabels: {app: web} # 管哪些 Pod
template: # 下面是 Pod 模板
metadata:
labels: {app: web} # Pod 标签,必须和 selector 对上
spec:
containers:
- name: web
image: myapp:1.0
ports:
- containerPort: 8000
resources:
requests: {cpu: "100m", memory: "128Mi"}
limits: {cpu: "500m", memory: "256Mi"}
readinessProbe: # 就绪探针:不通就不接流量
httpGet: {path: /health, port: 8000}
initialDelaySeconds: 3
livenessProbe: # 存活探针:不通就重启容器
httpGet: {path: /health, port: 8000}
periodSeconds: 10
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
selector: {app: web} # 挑带 app=web 标签的 Pod
ports:
- port: 80 # Service 端口
targetPort: 8000 # 转发到容器端口
type: ClusterIP # 集群内访问;NodePort/LoadBalancer 对外
| 类型 | 用途 | 谁能访问 |
|---|---|---|
| ClusterIP | 默认,集群内部虚拟 IP | 集群内其他 Pod |
| NodePort | 在每个节点开一个固定端口 | 集群外部(IP:NodePort) |
| LoadBalancer | 对接云厂商负载均衡 | 公网用户 |
# 建配置 kubectl create configmap app-config --from-literal=LOG_LEVEL=info # YAML 里以环境变量注入 env: - name: LOG_LEVEL valueFrom: configMapKeyRef: name: app-config key: LOG_LEVEL
密钥(数据库密码)用 Secret,用法和 ConfigMap 一样,只是内容 base64 编码、更敏感。
kubectl create deployment nginx --image=nginx:1.25。kubectl scale deployment nginx --replicas=2。kubectl get pods 看到 2 个 Running。port: 80(别人访问 svc:80)。targetPort: 8000(转发到容器的 8000)。app: web,和 Pod 标签一致。http://web-svc(默认 80)→ 转发到 Pod 的 8000。kubectl set image deployment/web-deploy web=myapp:2.0。kubectl rollout status deployment/web-deploy 看进度。kubectl rollout undo deployment/web-deploy 回滚。kubectl describe pod 看 events → kubectl logs 名 --previous 看上一次崩溃的日志。常见原因:应用启动即报错、配置/环境变量缺失、监听端口配错。app: web,Pod 标签却是 app: www,一个都选不中。用 kubectl get endpoints web-svc 看后端列表,是空的就是标签没对上。| 考法 | 出题形式 | 应对 |
|---|---|---|
| 对象职责 | Pod/Deployment/Service 各管什么 | Pod=实例,Deployment=副本,Service=入口 |
| 声明式 | 对比命令式 | 写期望状态,控制器不断逼近 |
| 探针 | readiness vs liveness | 一个管接流量,一个管重启 |
| 排错 | CrashLoop/连不通 | describe + logs + endpoints |
真题基础1. Kubernetes 中最小的部署单位是?
真题中档2. Service 的 selector 与 Pod 标签不匹配,会发生什么?
真题中档3. readinessProbe 失败时,K8s 会怎么做?
真题拔高4. Pod 状态是 CrashLoopBackOff,第一步应该做什么?
kubectl create configmap app-config --from-literal=LOG_LEVEL=info,在 Deployment 里 env 注入。kubectl apply -f deploy.yaml -f svc.yaml。kubectl get pods 三个都 Running;kubectl get svc 看到 NodePort(如 31234);访问 节点IP:31234。kubectl delete pod 任意一个,几秒后 Deployment 自动补一个新 Pod,副本数回到 3。kubectl apply -f xxx.yaml。kubectl describe pod 名,最下面 Events 区。kubectl scale deploy/名 --replicas=6,或改 YAML replicas 再 apply。kubectl rollout undo deployment/名。| 天 | 任务 | 自检 |
|---|---|---|
| 第 1 天 | 读②③,起一个 nginx Deployment | get pods 看到 Running |
| 第 2 天 | 背命令卡 + 做基础 1-5 | 基础全对 |
| 第 3 天 | 手写 Deployment+Service YAML 并 apply | 访问通 |
| 第 4 天 | 做中档 6-10,演练滚动更新和回滚 | rollout 正常 |
| 第 5 天 | 做拔高 11-15 + 真题 4 题 | 会造故障会排 |
| 第 6-7 天 | 故意删一个 Pod 观察自愈,口述部署流程 | 不看资料全默对 |