YAML基础
概述
YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化语言,Kubernetes使用YAML作为其资源定义的标准格式。掌握YAML语法是使用Kubernetes的基础技能。
核心概念
YAML的特点
- 简洁易读:使用缩进表示层级关系
- 结构清晰:支持列表、字典等数据结构
- 可扩展:支持注释、多文档、引用等高级特性
- 兼容性强:可转换为JSON格式
Kubernetes中的YAML
- 所有K8S资源对象都使用YAML定义
- 声明式配置:描述期望状态而非操作步骤
- 版本控制友好:便于GitOps实践
- 模板化支持:结合Helm、Kustomize等工具
YAML语法基础
基本语法规则
yaml
# 1. 大小写敏感
Name: nginx
name: nginx
# 2. 使用缩进表示层级关系(空格,不用Tab)
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: default
# 3. 缩进空格数不重要,但同一层级必须对齐
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
# 4. 注释使用 # 符号
# 这是一个注释
key: value # 行尾注释数据类型
yaml
# 标量类型(Scalar)
string: "hello world"
integer: 42
float: 3.14
boolean: true
null_value: null
date: 2024-01-15
datetime: 2024-01-15T10:30:00Z
# 列表(List)- 使用短横线
fruits:
- apple
- banana
- orange
# 行内列表格式
fruits: [apple, banana, orange]
# 字典(Dictionary)- 使用键值对
person:
name: John
age: 30
city: Beijing
# 行内字典格式
person: {name: John, age: 30, city: Beijing}
# 嵌套结构
company:
name: TechCorp
employees:
- name: Alice
role: Developer
- name: Bob
role: Manager多行字符串
yaml
# 保留换行符(使用 |)
script: |
echo "Hello"
echo "World"
exit 0
# 折叠换行符(使用 >)
description: >
This is a long
description that
will be folded into
a single line.
# 保留换行并去除首尾空格(使用 |-)
clean_script: |-
echo "Hello"
echo "World"引用与锚点
yaml
# 定义锚点
defaults: &defaults
image: nginx:1.20
port: 80
# 引用锚点
service1:
<<: *defaults
name: web1
service2:
<<: *defaults
name: web2
port: 8080 # 覆盖默认值
# 合并多个锚点
base: &base
image: nginx
config: &config
replicas: 3
deployment:
<<: [*base, *config]
name: my-appKubernetes资源定义
资源清单结构
yaml
apiVersion: apps/v1 # API版本
kind: Deployment # 资源类型
metadata: # 元数据
name: nginx-deployment
namespace: default
labels:
app: nginx
annotations:
description: "Nginx deployment"
spec: # 规格定义
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
status: # 状态(由系统维护)
availableReplicas: 3常见资源类型及API版本
yaml
# 核心资源(apiVersion: v1)
- Pod
- Service
- ConfigMap
- Secret
- PersistentVolume
- PersistentVolumeClaim
- Namespace
- Node
# apps组(apiVersion: apps/v1)
- Deployment
- StatefulSet
- DaemonSet
- ReplicaSet
# batch组(apiVersion: batch/v1)
- Job
- CronJob
# networking.k8s.io组(apiVersion: networking.k8s.io/v1)
- Ingress
- NetworkPolicy
# rbac.authorization.k8s.io组(apiVersion: rbac.authorization.k8s.io/v1)
- Role
- RoleBinding
- ClusterRole
- ClusterRoleBinding必需字段
yaml
apiVersion: apps/v1 # 必需:API版本
kind: Deployment # 必需:资源类型
metadata: # 必需:元数据
name: my-app # 必需:资源名称
spec: # 必需:规格定义
# 根据资源类型不同而不同模板化配置
使用环境变量
yaml
apiVersion: v1
kind: Pod
metadata:
name: env-pod
spec:
containers:
- name: app
image: nginx:1.20
env:
- name: ENVIRONMENT
value: "production"
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database_host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: password使用ConfigMap
yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "mysql.default.svc.cluster.local"
database_port: "3306"
app.properties: |
server.port=8080
log.level=INFO
---
# 使用ConfigMap
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: app
image: nginx:1.20
envFrom:
- configMapRef:
name: app-config
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config使用Secret
yaml
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
username: YWRtaW4= # base64编码
password: MWYyZDFlMmU2N2Rm
stringData: # 明文形式(自动编码)
api-key: "my-api-key-123"
---
# 使用Secret
apiVersion: v1
kind: Pod
metadata:
name: secret-pod
spec:
containers:
- name: app
image: nginx:1.20
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: app-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: password实用kubectl操作命令
创建和管理资源
bash
# 创建资源
kubectl apply -f deployment.yaml
# 创建多个资源
kubectl apply -f ./configs/
# 从URL创建
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/nginx-deployment.yaml
# 查看资源
kubectl get pods
kubectl get deployments
kubectl get all
# 详细查看
kubectl describe pod nginx-pod
kubectl get pod nginx-pod -o yaml
kubectl get pod nginx-pod -o json
# 编辑资源
kubectl edit deployment nginx-deployment
# 删除资源
kubectl delete -f deployment.yaml
kubectl delete pod nginx-podYAML验证和调试
bash
# 验证YAML语法
kubectl apply -f deployment.yaml --dry-run=client
# 验证并查看生成的资源
kubectl apply -f deployment.yaml --dry-run=client -o yaml
# 查看资源差异
kubectl diff -f deployment.yaml
# 转换为YAML格式
kubectl get pod nginx-pod -o yaml > pod.yaml
# 从命令行生成YAML模板
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deployment.yaml
# 导出当前资源为YAML
kubectl get deployment nginx -o yaml --export > nginx-deployment.yaml高级操作
bash
# 使用标签选择器
kubectl get pods -l app=nginx
# 查看特定命名空间
kubectl get pods -n production
# 查看所有命名空间
kubectl get pods --all-namespaces
# 使用字段选择器
kubectl get pods --field-selector status.phase=Running
# 输出特定字段
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get pods -o custom-columns=NAME:.metadata.name,IMAGE:.spec.containers[0].image实践示例
示例1:多容器Pod配置
yaml
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
labels:
app: webapp
spec:
containers:
- name: app
image: nginx:1.20
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
- name: log-collector
image: busybox
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}应用场景:主容器运行应用,辅助容器收集日志或同步数据。
示例2:完整的应用栈配置
yaml
# 数据库配置
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
MYSQL_DATABASE: "myapp"
MYSQL_USER: "appuser"
---
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
stringData:
MYSQL_ROOT_PASSWORD: "rootpassword123"
MYSQL_PASSWORD: "userpassword123"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
envFrom:
- configMapRef:
name: mysql-config
- secretRef:
name: mysql-secret
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
---
# 应用配置
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
DB_HOST: "mysql-service"
DB_PORT: "3306"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: myapp:latest
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: mysql-secret
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
# 服务配置
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
---
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
selector:
app: webapp
ports:
- port: 80
targetPort: 8080
type: LoadBalancer应用场景:部署完整的三层应用架构(应用层、服务层、数据层)。
示例3:使用Kustomize进行配置管理
yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# 基础资源
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
# 命名空间
namespace: production
# 通用标签
commonLabels:
env: production
team: platform
# 通用注解
commonAnnotations:
contact: "platform-team@company.com"
# 配置补丁
patchesStrategicMerge:
- deployment-patch.yaml
# 环境变量替换
configMapGenerator:
- name: app-config
behavior: merge
literals:
- ENVIRONMENT=production
- LOG_LEVEL=INFO
# 镜像替换
images:
- name: myapp
newTag: v1.2.3
---
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: myapp:latest
ports:
- containerPort: 8080
---
# deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 5
template:
spec:
containers:
- name: webapp
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"应用场景:多环境配置管理,避免重复YAML文件。
bash
# 应用Kustomize配置
kubectl apply -k ./overlays/production/
# 查看生成的YAML
kubectl kustomize ./overlays/production/故障排查指南
常见YAML错误
1. 缩进错误
yaml
# ❌ 错误示例
spec:
containers:
- name: nginx
# ✅ 正确示例
spec:
containers:
- name: nginx排查方法:
bash
# 使用yamllint验证
yamllint deployment.yaml
# 使用kubectl验证
kubectl apply -f deployment.yaml --dry-run=client2. 字段名称错误
yaml
# ❌ 错误示例
apiVersion: apps/v1
kind: deployment # 应该是Deployment(首字母大写)
# ✅ 正确示例
apiVersion: apps/v1
kind: Deployment排查方法:
bash
# 查看API资源类型
kubectl api-resources
# 查看资源字段说明
kubectl explain deployment.spec
kubectl explain pod.spec.containers3. API版本错误
yaml
# ❌ 错误示例
apiVersion: extensions/v1beta1 # 已废弃
kind: Deployment
# ✅ 正确示例
apiVersion: apps/v1
kind: Deployment排查方法:
bash
# 查看支持的API版本
kubectl api-versions
# 查看资源支持的版本
kubectl explain deployment4. 必需字段缺失
yaml
# ❌ 错误示例
apiVersion: v1
kind: Pod
metadata:
name: my-pod
# 缺少spec字段
# ✅ 正确示例
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: nginx
image: nginx:1.20排查方法:
bash
# 查看资源结构
kubectl explain pod --recursive
# 使用dry-run验证
kubectl apply -f pod.yaml --dry-run=client5. 引号和特殊字符问题
yaml
# ❌ 错误示例
password: my@password#123 # 特殊字符未转义
# ✅ 正确示例
password: "my@password#123"
# 或使用单引号
password: 'my@password#123'调试技巧
bash
# 1. 查看资源定义模板
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml
# 2. 查看字段说明
kubectl explain deployment.spec.template.spec.containers
# 3. 验证YAML语法
cat deployment.yaml | python -m yaml
# 4. 比较资源差异
kubectl diff -f deployment.yaml
# 5. 查看事件日志
kubectl get events --sort-by='.lastTimestamp'
# 6. 查看资源状态
kubectl get pods -o wide
kubectl describe pod <pod-name>
# 7. 查看容器日志
kubectl logs <pod-name> -c <container-name>
# 8. 进入容器调试
kubectl exec -it <pod-name> -- /bin/sh常见错误信息
bash
# 错误1:资源已存在
Error from server (AlreadyExists): error when creating "deployment.yaml": deployments.apps "nginx" already exists
# 解决方案:
kubectl apply -f deployment.yaml # 使用apply而不是create
# 错误2:字段类型错误
Error from server (BadRequest): error when creating "deployment.yaml": Deployment in version "v1" cannot be handled as a Deployment: v1.Deployment: Spec: v1.DeploymentSpec: Replicas: readUint32: unexpected character: 错误
# 解决方案:检查字段类型,replicas应该是整数
replicas: 3 # 正确
replicas: "3" # 错误
# 错误3:验证失败
Error from server (Forbidden): error when creating "deployment.yaml": deployments.apps is forbidden: user cannot create resource "deployments" in API group "apps" in the namespace "default"
# 解决方案:检查RBAC权限
kubectl auth can-i create deployments最佳实践建议
1. YAML文件组织
bash
# 推荐的目录结构
project/
├── base/ # 基础配置
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/ # 环境覆盖
│ ├── dev/
│ │ ├── kustomization.yaml
│ │ └── patches/
│ ├── staging/
│ └── production/
└── manifests/ # 单独的资源文件
├── namespace.yaml
├── configmap.yaml
└── secret.yaml2. 命名规范
yaml
# 资源命名规范
metadata:
name: <app-name>-<resource-type>
# 例如:nginx-deployment, mysql-service, app-configmap
# 标签命名规范
labels:
app.kubernetes.io/name: nginx
app.kubernetes.io/instance: nginx-prod
app.kubernetes.io/version: "1.20"
app.kubernetes.io/component: web-server
app.kubernetes.io/part-of: webapp
app.kubernetes.io/managed-by: kubectl3. 注释和文档
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
annotations:
description: "Web application deployment"
owner: "platform-team"
documentation: "https://wiki.company.com/webapp"
spec:
replicas: 3 # 生产环境建议3个副本以上
selector:
matchLabels:
app: webapp
template:
spec:
containers:
- name: webapp
image: webapp:v1.2.3
resources:
requests:
memory: "256Mi" # 根据实际负载调整
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"4. 版本控制
yaml
# 使用Git管理YAML文件
# .gitignore
*.swp
*.tmp
secrets/ # 不要提交Secret到Git
*.key
*.pem
# 使用Sealed Secrets或External Secrets管理敏感信息5. 验证和测试
bash
# CI/CD流程中的验证步骤
# 1. 语法验证
yamllint manifests/
# 2. Schema验证
kubeval manifests/
# 3. 安全扫描
kubesec scan deployment.yaml
# 4. Dry-run测试
kubectl apply -f manifests/ --dry-run=client
# 5. 差异检查
kubectl diff -f manifests/6. 使用模板工具
yaml
# Helm模板示例
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}7. 安全配置
yaml
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: app
image: nginx:1.20
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}总结
核心要点
YAML语法基础
- 使用空格缩进,不用Tab
- 支持列表、字典、多行字符串等数据结构
- 使用锚点和引用减少重复
K8S资源定义
- 必需字段:apiVersion、kind、metadata、spec
- 使用kubectl explain查看资源结构
- 使用--dry-run验证配置
配置管理
- 使用ConfigMap管理配置
- 使用Secret管理敏感信息
- 使用Kustomize或Helm进行模板化
最佳实践
- 版本控制所有YAML文件
- 使用命名规范和标签规范
- 在CI/CD中集成验证步骤
常用命令速查
bash
# 创建资源
kubectl apply -f <file.yaml>
# 验证YAML
kubectl apply -f <file.yaml> --dry-run=client
# 查看资源
kubectl get <resource> -o yaml
# 编辑资源
kubectl edit <resource> <name>
# 删除资源
kubectl delete -f <file.yaml>
# 查看字段说明
kubectl explain <resource>.<field>
# 生成YAML模板
kubectl create <resource> <name> --dry-run=client -o yaml下一步学习
- 资源管理 - 学习K8S资源限制和配额管理
- Namespace - 了解命名空间和资源隔离
- 标签与选择器 - 掌握标签管理和应用分组
- ConfigMap和Secret - 深入学习配置和密钥管理
- Helm Charts - 学习使用Helm进行高级模板化