Kubernetes 清单:对象结构、身份与字段所有权
Kubernetes 对象与 YAML 清单
通用对象结构
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: demo
labels:
app.kubernetes.io/name: web
app.kubernetes.io/instance: web-demo
app.kubernetes.io/part-of: storefront
app.kubernetes.io/managed-by: gitops
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: web
template:
metadata:
labels:
app.kubernetes.io/name: web
spec:
containers:
- name: web
image: nginx:1.29.0
ports:
- name: http
containerPort: 80四个顶层字段最常见:apiVersion、kind、metadata 和 spec。status 由系统维护,不应复制进声明式清单。
名称与生成名称
- DNS 子域名称通常只允许小写字母、数字、
-、.,具体限制由资源决定。 metadata.name指定稳定名称。metadata.generateName: batch-让 API Server追加随机后缀,适合一次性对象。- 名称不是不可变身份;删除重建后 UID 会变化。
标签与注解
标签用于选择和组织,值应短小、稳定、低基数。注解用于不能被选择的元数据,如变更单、配置校验和、外部控制器参数。
推荐的应用标签:
metadata:
labels:
app.kubernetes.io/name: checkout
app.kubernetes.io/instance: checkout-prod
app.kubernetes.io/version: "2.4.1"
app.kubernetes.io/component: api
app.kubernetes.io/part-of: commerce
app.kubernetes.io/managed-by: helm查询:
kubectl get pods -l 'app.kubernetes.io/name=checkout'
kubectl get pods -l 'environment in (staging,production),tier!=frontend'
kubectl get pods --show-labelsService 和工作负载控制器依赖选择器。Deployment.spec.selector 必须匹配 Pod 模板标签,创建后不可随意修改;标签迁移应设计双标签过渡,避免 Service 瞬间无端点。
字段、标签与注解的选择
| 数据 | 放置位置 | 原因 |
|---|---|---|
| 控制器期望配置 | spec | 有 Schema、版本和控制循环语义 |
| 可选择的业务维度 | label | 支持 selector |
| 构建 URL、变更单、校验和 | annotation | 不参与选择,可保存较长字符串 |
| 当前运行结果 | status | 控制器拥有,不是用户期望状态 |
| 密钥材料 | Secret 或外部密钥系统 | 不应放标签/注解/普通 ConfigMap |
所有权与垃圾回收
ReplicaSet 由 Deployment 拥有,Pod 又由 ReplicaSet 拥有。删除上级时,垃圾回收器依据 ownerReferences 处理下级。
kubectl get pod <pod> -o jsonpath='{.metadata.ownerReferences}' | jq
kubectl describe deployment web删除传播策略:
# 前台:等待依赖对象删除后才完成
kubectl delete deployment web --cascade=foreground
# 后台:立即返回,垃圾回收器异步删除依赖
kubectl delete deployment web --cascade=background
# 孤儿:保留下级对象,必须明确知道后果
kubectl delete deployment web --cascade=orphan警告
--cascade=orphan 会留下失去管理者的 ReplicaSet/Pod,可能继续占用资源。只在恢复或迁移方案明确时使用。
Finalizer 与删除卡住
删除带 Finalizer 的对象时,API Server 设置 deletionTimestamp,控制器完成外部清理后移除 Finalizer。卡住时先检查负责的控制器,而不是直接清空:
kubectl get <kind> <name> -o yaml
kubectl events --for <kind>/<name>强制移除 Finalizer 可能泄漏云负载均衡器、磁盘、快照或 IP。必须确认外部资源已人工清理并有审批。
声明式应用与字段所有权
kubectl apply --server-side --dry-run=server -f manifests/
kubectl diff -f manifests/
kubectl apply --server-side --field-manager=teamdocs -f manifests/Server-Side Apply(SSA)在 managedFields 记录字段管理者。多个工具管理同一字段会产生冲突;不要用 --force-conflicts 掩盖职责不清,应先决定该字段由 GitOps、HPA、平台控制器还是人工拥有。
kubectl create --save-config 和客户端 Apply 的 last-applied annotation 是旧工作流。新系统优先 SSA,但要先验证 CRD Schema 和控制器兼容。
生成清单草稿
kubectl create deployment web --image=nginx:1.29.0 \
--replicas=3 --dry-run=client -o yaml > deployment.yaml
kubectl create service clusterip web --tcp=80:80 \
--dry-run=client -o yaml > service.yaml
kubectl create configmap web-config --from-file=app.conf \
--dry-run=client -o yaml > configmap.yaml生成后必须人工补齐资源约束、探针、安全上下文、标签和发布策略。--dry-run=client 不经过服务器准入;提交前再执行 --dry-run=server。
清单组织原则
- 一个目录表达一个可独立部署单元,明确环境覆盖方式。
- 不提交真实 Secret;使用受批准的外部密钥或密文方案。
- 固定镜像版本,生产推荐
image@sha256:<digest>。 metadata.namespace明确写出,或由受控的 Kustomize/Helm 层注入。- 不提交
status、resourceVersion、uid、creationTimestamp、managedFields。 - CRD 必须先于 CR,Namespace 必须先于其中的对象。
- 避免把多个 YAML 文档拼成无法复用的巨大文件;保持依赖可读。
验证清单
# 客户端语法与类型检查
kubectl apply --dry-run=client -f manifests/
# 目标集群的 Schema、准入和权限检查,不持久化
kubectl apply --server-side --dry-run=server -f manifests/
# 与集群当前对象比较
kubectl diff -f manifests/生产流水线还应加入 Schema 校验、策略校验、镜像扫描和冒烟测试。服务器 dry-run 仍可能调用具有副作用的错误 Webhook;Webhook 编写者必须正确处理 dryRun。
不可变字段与安全迁移
常见不可变或难以原地修改的字段包括 Service clusterIP、Deployment selector、StatefulSet 部分字段、PVC StorageClass 等。遇到 field is immutable 时:
- 用
kubectl explain和 API Reference 确认语义。 - 设计新对象名称、双写/双路由或有序替换。
- 先创建并验证新对象。
- 切流后再删除旧对象。
不要默认用 kubectl replace --force;它本质上是删除再创建,会改变 UID、IP、调度和可用性。
Kubernetes 创建命名空间 YAML
kubernetes yaml
创建命名空间
---
apiVersion: v1
kind: Namespace
metadata:
name: games继续阅读
- 命令
- 故障排查
- 故障排查