一、引言
Kubernetes YAML配置文件是定义和管理K8s资源的核心方式。编写规范、正确的YAML文件是K8s运维的基本功。本文将深入剖析K8s YAML的核心结构,讲解每个字段的作用,分享生产环境中的配置最佳实践。
二、SCQA分析框架
情境(Situation)
- YAML是K8s资源定义的标准格式
- 配置错误会导致资源创建失败或运行异常
- 需要统一的配置规范和最佳实践
冲突(Complication)
- API版本众多,选择困难
- 字段复杂,容易遗漏必需字段
- 配置不规范导致维护困难
问题(Question)
- K8s YAML的核心结构是什么?
- 各字段的作用和使用场景是什么?
- 如何编写规范的YAML配置?
- 常见的配置错误有哪些?
答案(Answer)
- YAML由apiVersion、kind、metadata、spec四个核心部分组成
- apiVersion指定API版本,kind指定资源类型
- metadata包含资源元数据,spec定义资源规格
- 遵循规范的配置可以提高可维护性和可靠性
三、YAML核心结构详解
3.1 整体结构
# 核心四要素
apiVersion: <version> # API版本
kind: <resource-type> # 资源类型
metadata: # 元数据
name: <resource-name> # 资源名称
spec: # 规格定义
# 资源特定配置
3.2 apiVersion(API版本)
API版本分类:
| 版本类型 | 稳定性 | 示例 |
|---|---|---|
| v1 | 稳定版 | core/v1(Pod、Service) |
| v1beta1/v1beta2 | 测试版 | 功能开发中 |
| v1alpha1 | 实验版 | 功能不稳定 |
常见资源的API版本:
# 核心资源
apiVersion: v1 # Pod、Service、ConfigMap、Secret、Namespace
# 应用资源
apiVersion: apps/v1 # Deployment、StatefulSet、ReplicaSet、DaemonSet
# 网络资源
apiVersion: networking.k8s.io/v1 # Ingress、NetworkPolicy
# 批处理资源
apiVersion: batch/v1 # Job、CronJob
# RBAC资源
apiVersion: rbac.authorization.k8s.io/v1 # Role、ClusterRole、RoleBinding
# 存储资源
apiVersion: storage.k8s.io/v1 # StorageClass、CSIDriver
选择原则:
- 优先使用v1稳定版
- 避免使用alpha版本
- 根据K8s集群版本选择兼容的API版本
3.3 kind(资源类型)
资源类型分类:
| 类别 | 资源类型 | 主要用途 |
|---|---|---|
| 工作负载 | Pod、Deployment、StatefulSet、ReplicaSet、DaemonSet、Job、CronJob | 运行应用 |
| 服务发现 | Service、Ingress | 服务访问 |
| 配置管理 | ConfigMap、Secret | 配置和敏感信息 |
| 存储 | PersistentVolume、PersistentVolumeClaim、StorageClass | 持久化存储 |
| 网络 | NetworkPolicy、IngressClass | 网络策略 |
| RBAC | Role、ClusterRole、RoleBinding、ClusterRoleBinding | 权限管理 |
| 命名空间 | Namespace | 资源隔离 |
3.4 metadata(元数据)
核心字段:
metadata:
name: my-app # 资源名称(必需)
namespace: production # 命名空间(默认default)
labels: # 标签(用于选择器和分组)
app: my-app
tier: frontend
version: v1.0.0
environment: production
annotations: # 注解(用于存储额外信息)
description: "Frontend web application"
author: "dev-team@example.com"
contact: "ops-team@example.com"
finalizers: # 终结器(资源删除前的钩子)
- kubernetes.io/pvc-protection
labels vs annotations:
| 特性 | labels | annotations |
|---|---|---|
| 用途 | 资源选择和分组 | 存储额外元数据 |
| 查询 | 可用于selector | 不可用于selector |
| 大小限制 | 较小,用于标识 | 可以较大,用于描述 |
| 示例 | app=web, version=v1 | author=john, build-time=xxx |
3.5 spec(规格定义)
Pod spec:
spec:
containers: # 容器列表(必需)
- name: main-container # 容器名称(必需)
image: nginx:1.25.0 # 镜像地址(必需)
imagePullPolicy: Always # 镜像拉取策略:Always、Never、IfNotPresent
ports: # 端口配置
- containerPort: 80
name: http
protocol: TCP
resources: # 资源配置
requests: # 资源请求(调度时使用)
cpu: "100m" # 0.1 CPU核心
memory: "128Mi"
limits: # 资源限制(运行时上限)
cpu: "200m"
memory: "256Mi"
env: # 环境变量
- name: NODE_ENV
value: production
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db-host
volumeMounts: # 卷挂载
- name: data
mountPath: /data
readOnly: false
livenessProbe: # 存活探针
httpGet:
path: /health
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe: # 就绪探针
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 3
volumes: # 卷定义
- name: data
emptyDir: {}
nodeSelector: # 节点选择器
disktype: ssd
affinity: # 亲和性配置
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: node-type
operator: In
values: ["high-performance"]
Deployment spec:
spec:
replicas: 3 # 副本数(默认1)
selector: # Pod选择器(必需)
matchLabels:
app: my-app
strategy: # 更新策略
type: RollingUpdate # RollingUpdate(滚动更新)或 Recreate(重建)
rollingUpdate:
maxSurge: 25% # 更新时最大额外副本数
maxUnavailable: 0 # 更新时最大不可用副本数
minReadySeconds: 5 # Pod就绪后最小等待时间
revisionHistoryLimit: 10 # 保留的历史版本数
paused: false # 是否暂停部署
progressDeadlineSeconds: 600 # 部署超时时间
template: # Pod模板(必需)
metadata:
labels:
app: my-app
spec:
containers:
- name: main
image: my-app:latest
3.6 status(状态信息)
status字段由K8s自动生成,不可手动修改:
status:
phase: Running # Pod状态:Pending、Running、Succeeded、Failed、Unknown
conditions: # 状态条件
- type: Ready
status: "True"
lastProbeTime: "2024-01-01T10:00:00Z"
lastTransitionTime: "2024-01-01T10:00:05Z"
reason: "PodReady"
message: "Pod is ready"
podIP: 10.244.0.10 # Pod IP地址
hostIP: 192.168.1.100 # 节点IP地址
startTime: "2024-01-01T10:00:00Z"
四、常见资源YAML模板
4.1 Pod
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: my-app
spec:
containers:
- name: main
image: nginx:latest
ports:
- containerPort: 80
4.2 Service
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: ClusterIP
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
4.3 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: main
image: my-app:latest
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
4.4 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# 键值对形式
database: mysql
host: db-service
port: "3306"
# 文件形式
application.yml: |
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://${host}:${port}/mydb
4.5 Secret
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: dXNlcjE= # echo -n "user1" | base64
password: cGFzc3dvcmQxMjM= # echo -n "password123" | base64
4.6 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
4.7 PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard
五、生产环境最佳实践
5.1 API版本选择
使用稳定版API:
# 正确:使用稳定版
apiVersion: apps/v1
kind: Deployment
# 错误:使用beta版
apiVersion: apps/v1beta2
kind: Deployment
5.2 标签规范
使用标准标签:
| 标签名 | 说明 | 示例值 |
|---|---|---|
| app | 应用名称 | my-app |
| tier | 层级 | frontend、backend、database |
| version | 版本 | v1.0.0 |
| environment | 环境 | dev、test、staging、prod |
| component | 组件 | api、worker、scheduler |
配置示例:
metadata:
labels:
app: my-app
tier: backend
version: v1.2.0
environment: production
component: api
5.3 资源限制配置
为所有容器配置资源请求和限制:
spec:
containers:
- name: app
image: my-app:latest
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
资源配置原则:
- requests <= limits
- 根据应用实际需求配置
- 避免设置过大的资源限制
5.4 健康检查配置
配置完整的探针:
spec:
containers:
- name: app
image: my-app:latest
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
successThreshold: 2
5.5 配置分离
使用ConfigMap管理配置:
# 创建ConfigMap
kubectl create configmap app-config --from-file=application.yml
# 在Pod中使用
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: config
mountPath: /app/config
volumes:
- name: config
configMap:
name: app-config
使用Secret管理敏感信息:
# 创建Secret
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=secret123
# 在Pod中使用
spec:
containers:
- name: app
image: my-app:latest
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
5.6 更新策略配置
配置滚动更新策略:
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
minReadySeconds: 10
progressDeadlineSeconds: 600
5.7 YAML格式化
使用标准缩进和格式:
# 正确
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
# 错误(缩进不一致)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment # 缺少缩进
spec:
replicas:3 # 缺少空格
使用kubectl validate检查:
kubectl apply --dry-run=client -f my-app.yaml
六、常见配置错误与解决方案
错误一:API版本错误
现象:
kubectl apply -f deployment.yaml
# error: unable to recognize "deployment.yaml": no matches for kind "Deployment" in version "apps/v1beta1"
原因:使用了已废弃的API版本
解决方案:
# 查看支持的API版本
kubectl api-versions | grep apps
# 使用正确的版本
apiVersion: apps/v1 # 而非 apps/v1beta1
错误二:缺少必需字段
现象:
kubectl apply -f pod.yaml
# error: error validating "pod.yaml": error validating data: ValidationError(Pod.spec.containers[0]): missing required field "image" in io.k8s.api.core.v1.Container
原因:缺少container的image字段
解决方案:
spec:
containers:
- name: app
image: my-app:latest # 添加image字段
错误三:标签不匹配
现象:
kubectl get endpoints my-service
# NAME ENDPOINTS AGE
# my-service <none> 5m
原因:Service selector与Pod标签不匹配
解决方案:
# Service配置
spec:
selector:
app: my-app # 确保与Pod标签一致
# Pod配置
metadata:
labels:
app: my-app # 与Service selector匹配
错误四:镜像拉取失败
现象:
kubectl describe pod my-pod
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Normal Scheduled 5s default-scheduler Successfully assigned default/my-pod to node-01
# Warning Failed 3s kubelet Failed to pull image "my-app:latest": rpc error: code = Unknown desc = Error response from daemon: pull access denied for my-app, repository does not exist or may require 'docker login'
原因:镜像地址错误或权限不足
解决方案:
# 使用正确的镜像地址
spec:
containers:
- name: app
image: registry.example.com/my-app:latest # 使用完整镜像地址
# 配置镜像拉取凭证
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass
spec:
imagePullSecrets:
- name: regcred
错误五:资源不足
现象:
kubectl describe pod my-pod
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Warning FailedScheduling 5s (x3 over 10s) default-scheduler 0/3 nodes are available: 3 Insufficient cpu.
原因:Pod资源请求超过节点可用资源
解决方案:
# 降低资源请求
spec:
containers:
- name: app
image: my-app:latest
resources:
requests:
cpu: "50m" # 降低CPU请求
memory: "64Mi" # 降低内存请求
七、YAML工具推荐
7.1 验证工具
| 工具 | 用途 |
|---|---|
| kubectl apply –dry-run | 验证YAML语法 |
| kubeval | YAML验证工具 |
| kubescape | 安全合规检查 |
7.2 格式化工具
| 工具 | 用途 |
|---|---|
| yamllint | YAML语法检查和格式化 |
| prettier | 代码格式化工具 |
| kubectl neat | 清理YAML输出 |
7.3 IDE插件
| 插件 | 适用IDE | 功能 |
|---|---|---|
| Kubernetes | VS Code | YAML语法高亮、自动补全 |
| YAML | VS Code | YAML语法检查 |
| Cloud Code | JetBrains | K8s资源管理 |
八、总结
核心要点
- YAML四要素:apiVersion、kind、metadata、spec
- 必需字段:name、containers[].name、containers[].image
- 标签规范:使用标准标签便于资源管理
- 资源配置:为所有容器配置requests和limits
- 健康检查:配置liveness和readiness探针
- 配置分离:使用ConfigMap和Secret管理配置
最佳实践清单
- ✅ 使用稳定版API(v1)
- ✅ 添加有意义的标签和注解
- ✅ 配置资源请求和限制
- ✅ 配置健康检查探针
- ✅ 使用ConfigMap管理配置
- ✅ 使用Secret管理敏感信息
- ✅ 配置合理的更新策略
- ✅ 使用工具验证YAML语法
本文对应的面试题:K8s YAML必含核心字段有哪些?
附录:常用kubectl命令
# 验证YAML
kubectl apply --dry-run=client -f my-app.yaml
# 查看资源YAML
kubectl get deployment my-deployment -o yaml
# 编辑资源
kubectl edit deployment my-deployment
# 查看API版本
kubectl api-versions
# 查看资源文档
kubectl explain deployment.spec
# 格式化输出
kubectl get pod my-pod -o yaml | kubectl neat
文档信息
- 本文作者:soveran zhong
- 本文链接:https://blog.clockwingsoar.cn/2026/06/24/k8s-yaml-best-practices/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)