Files

119 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: devops.k8s.core-objects
title: Kubernetes 基础:Pod / Deployment / Service / Ingress、配置与密钥、探针、滚动更新和扩缩容
type: lesson
domain: devops
stack: [k8s]
tags: [Kubernetes, Pod, Deployment, Service, Ingress, ConfigMap, Secret, 探针, 滚动更新, HPA, PDB, kubectl]
level: basic
prerequisites: [devops.docker.image-dockerfile]
est_hours: 3
related: [devops.k8s.scenario.agent-rollout, devops.nginx.scenario.ai-gateway-sse-canary, devops.k8s.interview]
week: [14]
order: 1
---
# Kubernetes 基础:Pod / Deployment / Service / Ingress、配置与密钥、探针、滚动更新和扩缩容
> 定位:**能读懂和修改清单、能用 kubectl 排查**,集群搭建和运维不在范围内。BOSS直聘 2026-10-23 的调研中有岗位把 K8s 列为要求或加分项。示例清单通过 kubeconform 结构校验(6 个资源全部有效)和团队规范测试(5 个测试通过),**没有在真实集群中部署**。以官方文档为准:https://kubernetes.io/zh-cn/docs/home/ 。
## 解释说明
### 核心对象
| 对象 | 作用 | 类比 |
| --- | --- | --- |
| **Pod** | 最小调度单位,一个或几个容器共享网络和存储 | 一组 `docker run` |
| **Deployment** | 声明“要几个什么样的 Pod”,负责滚动更新和回滚 | Compose 的 service + 副本数 |
| **Service** | 给一组 Pod 一个稳定的虚拟 IP / DNS 名,做负载均衡 | 内部的负载均衡器 |
| **Ingress** | 集群入口的 HTTP 路由(域名、路径、TLS) | Nginx 反向代理配置 |
| **ConfigMap / Secret** | 配置 / 敏感信息,以环境变量或文件注入 | `.env` |
| **HPA** | 按指标自动调整副本数 | — |
| **PDB** | 主动驱逐(节点维护)时至少保留多少可用 Pod | — |
| Namespace | 资源隔离和配额 | — |
**声明式**:你提交“期望状态”(YAML),控制器不断把“实际状态”调整为期望状态。Pod 挂了会被重建,而不是由你手动重启。
**标签和选择器**:Deployment、Service 通过标签选择 Pod,标签不一致是新手最常见的问题(Service 没有后端)。
### 三种探针
| 探针 | 失败的后果 | 检查什么 |
| --- | --- | --- |
| startupProbe | 启动阶段超时则重启 | 启动是否完成(给慢启动的应用留时间) |
| readinessProbe | 从 Service 的后端中摘除,不重启 | 能否处理请求(可检查关键依赖) |
| livenessProbe | 重启容器 | 进程是否卡死(**不要检查外部依赖**) |
### 滚动更新和优雅退出
- `maxSurge` / `maxUnavailable` 控制更新节奏;`kubectl rollout undo` 回滚。
- Pod 终止流程:从 Service 端点中移除 + 执行 `preStop` → 发送 SIGTERM → 等待 `terminationGracePeriodSeconds` → SIGKILL。应用要处理 SIGTERM:停止接收新请求、完成进行中的请求(AI 流式回答可能持续几十秒)。
### 常用排查命令
```bash
kubectl get pods -l app.kubernetes.io/name=agent-api -o wide
kubectl describe pod <pod> # 看事件:拉取镜像失败、探针失败、OOMKilled、调度失败
kubectl logs <pod> --previous # 看上一次崩溃前的日志
kubectl get endpoints agent-api # Service 是否有后端
kubectl rollout status deploy/agent-api
kubectl rollout undo deploy/agent-api
```
## 案例
把 AI Agent API 部署到公司的 K8s 集群:3 副本、零不可用的滚动更新、启动慢时用 startupProbe 保护、密钥由 Secret 注入、Ingress 关闭缓冲以支持 SSE、HPA 按负载扩到 10 个、PDB 保证节点维护时至少 2 个可用。
## 代码示例
清单:[examples/agent-api](examples/agent-api/)(`deployment.yaml`、`service.yaml`、`ingress.yaml`、`configmap.yaml`、`hpa.yaml`),校验结果:
```text
$ kubeconform -strict -summary *.yaml
Summary: 6 resources found in 5 files - Valid: 6, Invalid: 0, Errors: 0, Skipped: 0
$ pytest -q test_manifests.py
5 passed
```
Deployment 关键部分:
```yaml
strategy:
type: RollingUpdate
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
template:
spec:
terminationGracePeriodSeconds: 90
containers:
- name: api
image: registry.example.com/agent-api:1.4.2
env:
- name: LLM_API_KEY
valueFrom: { secretKeyRef: { name: agent-api-secrets, key: llm-api-key } }
resources:
requests: { cpu: "250m", memory: "256Mi" }
limits: { memory: "512Mi" }
startupProbe: { httpGet: { path: /healthz, port: http }, periodSeconds: 5, failureThreshold: 24 }
readinessProbe: { httpGet: { path: /readyz, port: http }, periodSeconds: 5 }
livenessProbe: { httpGet: { path: /healthz, port: http }, periodSeconds: 10 }
```
团队规范测试([test_manifests.py](examples/agent-api/test_manifests.py))检查:选择器与标签一致、镜像固定版本、有资源和探针、密钥不明文、PDB 小于最小副本数、仓库中没有 Secret 对象。
## 易错点
- Service 选择器和 Pod 标签不一致。
- 存活探针检查数据库,数据库抖动时所有 Pod 被重启,雪上加霜。
- 没有 startupProbe,慢启动的应用被存活探针反复杀掉(CrashLoopBackOff)。
- 镜像用 `latest`,无法确定线上跑的是哪个版本,回滚也不可靠。
- 内存没有限制或限制过小(OOMKilled)。
- 应用不处理 SIGTERM,滚动更新时正在进行的流式回答被切断。
- 把 Secret 的 YAML(只是 base64,不是加密)提交到仓库。
## 面试常问
- Pod、Deployment、Service 的关系?
- 三种探针的区别?
- 滚动更新怎么做到不中断服务?
- Pod 一直 CrashLoopBackOff 怎么排查?