Skip to content

Kubernetes 清单:对象结构、身份与字段所有权 ​

Kubernetes 对象与 YAML 清单 ​

通用对象结构 ​

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 会变化。

标签与注解 ​

标签用于选择和组织,值应短小、稳定、低基数。注解用于不能被选择的元数据,如变更单、配置校验和、外部控制器参数。

推荐的应用标签:

yaml
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

查询:

bash
kubectl get pods -l 'app.kubernetes.io/name=checkout'
kubectl get pods -l 'environment in (staging,production),tier!=frontend'
kubectl get pods --show-labels

Service 和工作负载控制器依赖选择器。Deployment.spec.selector 必须匹配 Pod 模板标签,创建后不可随意修改;标签迁移应设计双标签过渡,避免 Service 瞬间无端点。

字段、标签与注解的选择 ​

数据放置位置原因
控制器期望配置spec有 Schema、版本和控制循环语义
可选择的业务维度label支持 selector
构建 URL、变更单、校验和annotation不参与选择,可保存较长字符串
当前运行结果status控制器拥有,不是用户期望状态
密钥材料Secret 或外部密钥系统不应放标签/注解/普通 ConfigMap

所有权与垃圾回收 ​

ReplicaSet 由 Deployment 拥有,Pod 又由 ReplicaSet 拥有。删除上级时,垃圾回收器依据 ownerReferences 处理下级。

bash
kubectl get pod <pod> -o jsonpath='{.metadata.ownerReferences}' | jq
kubectl describe deployment web

删除传播策略:

bash
# 前台:等待依赖对象删除后才完成
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。卡住时先检查负责的控制器,而不是直接清空:

bash
kubectl get <kind> <name> -o yaml
kubectl events --for <kind>/<name>

强制移除 Finalizer 可能泄漏云负载均衡器、磁盘、快照或 IP。必须确认外部资源已人工清理并有审批。

声明式应用与字段所有权 ​

bash
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 和控制器兼容。

生成清单草稿 ​

bash
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 文档拼成无法复用的巨大文件;保持依赖可读。

验证清单 ​

bash
# 客户端语法与类型检查
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 时:

  1. 用 kubectl explain 和 API Reference 确认语义。
  2. 设计新对象名称、双写/双路由或有序替换。
  3. 先创建并验证新对象。
  4. 切流后再删除旧对象。

不要默认用 kubectl replace --force;它本质上是删除再创建,会改变 UID、IP、调度和可用性。

Kubernetes 创建命名空间 YAML ​

kubernetes yaml ​

创建命名空间 ​

yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: games

继续阅读