Kubernetes中YAML文件编写


Kubernetes中YAML文件编写

1、YAML格式基本规范(复习)

YAML(YAML Ain't Markup Language)是一种用于数据序列化的格式,常用于配置文件、数据交换等场景。YAML的目标是易于阅读和书写,同时也易于与编程语言交互。YAML文件通常以.yaml或.yml作为文件扩展名。

YAML格式基本规范:

结构表示:

  • 使用缩进表示层级关系,通常使用两个或四个空格的缩进,但必须在同一文档中保持一致。
  • 不使用制表符(Tab)进行缩进。

键值对:

  • 使用冒号加空格: 来分隔键和值。
  • 键是唯一的,通常是字符串。

列表(数组):

  • 使用短横线加空格- 来表示列表项。
  • 列表项通常会缩进,表示属于上一级的列表。

字典(映射):

  • 字典是一组键值对的集合。
  • 字典的每个键值对都会缩进,表示属于上一级的字典。

数据类型:

  • 支持字符串、布尔值、整数、浮点数、null、时间、日期等数据类型。
  • 字符串通常不需要引号,但如果包含特殊字符,则需要用单引号或双引号括起来。
  • 使用true/false表示布尔值。
  • 使用null表示空值。

注释:

  • 使用井号 # 开头表示注释,注释内容不会被解析。

多文档支持:

  • 使用三个短横线---来分隔文件中的多个文档。

复杂结构:

  • 字典和列表可以嵌套使用,形成复杂的结构。

这是一个简单的YAML示例,展示了一些基本的格式:

# 这是一个注释
person:  # 字典的开始
  name: John Doe  # 字符串
  age: 30  # 整数
  married: true  # 布尔值
  children:  # 列表的开始
    - name: Jane Doe
      age: 10
    - name: Doe Junior
      age: 5

# 它对应的JSON文件如下:
{
  "person": {
    "name": "John Doe",
    "age": 30,
    "married": true,
    "children": [
      {
        "name": "Jane Doe",
        "age": 10
      },
      {
        "name": "Doe Junior",
        "age": 5
      }
    ]
  }
}

2、K8S中YAML文件编写

YAML文件通常用于配置管理系统、部署工具、持续集成和持续部署(CI/CD)等场景,它们易于阅读和编辑。在Kubernetes中,YAML文件被广泛用于定义资源对象,如Deployments、Services、Pods等。

通过定义Deployment资源对象的过程,看下YAML文件编写的思路。

YAML文件的组成

YAML文件由apiVersion、kind、metadata、spec、status五部分组成,前四部分较常用。

基本语法规则

在Kubernetes中,YAML文件遵循特定的结构:

---                      # YAML文件起始标志(可选)
apiVersion: v1           # API版本
kind: Pod                # 资源类型
metadata:                # 元数据
  name: myapp            # 资源名称
  labels:                # 标签
    app: webapp          # 标签键值对
spec:                    # 详细配置
  containers:            # 容器定义
  - name: web            # 容器名称
    image: nginx:1.17    # 容器镜像

关键字段解析

  • apiVersion: 指定使用的Kubernetes API版本,不同资源类型使用不同版本
  • kind: 定义资源类型,如Pod、Deployment、Service等
  • metadata: 包含资源的标识信息(名称、标签、注释等)
  • spec: 描述资源的期望状态,这是最复杂的部分
  • status: 记录资源的实际状态,由Kubernetes自动生成,使用清单时通常省略
# 查看K8S自带的资源管理帮助文档
root@k8s-master01:~# kubectl explain deployment
KIND:     Deployment
VERSION:  apps/v1

DESCRIPTION:
     Deployment enables declarative updates for Pods and ReplicaSets.

FIELDS:
   apiVersion  <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind  <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata  <Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   spec  <Object>
     Specification of the desired behavior of the Deployment.

   status  <Object>
     Most recently observed status of the Deployment.

--dry-run生成YAML文件框架

快速生成YAML模板

Kubernetes提供了强大的模板生成功能,无需手动编写YAML。

# 生成Pod模板
kubectl run myapp --image=nginx:1.17 --dry-run=client -o yaml > pod.yaml

# 生成Namespace模板
kubectl create namespace work --dry-run=client -o yaml > namespace.yaml

# 生成Deployment模板
kubectl create deployment myapp --image=dbimg:1.35 --dry-run=client -o yaml > deployment.yaml

实际生成的Deployment示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: myapp
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myapp
    spec:
      containers:
      - image: dbimg:1.35
        name: dbimg
        resources: {}
status: {}

案例:通过--dry-run生成YAML文件框架

root@k8s-master01:~# kubectl create deployment jumpoint-web --image=nginx:latest --port=80 --replicas=2 --namespace=jumpoint-ns --dry-run=client --output=yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: jumpoint-web
  name: jumpoint-web
  namespace: jumpoint-ns
spec:
  replicas: 2
  selector:
    matchLabels:
      app: jumpoint-web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: jumpoint-web
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
        resources: {}
status: {}

通过explain获取YAML文件字段含义

# 若要查看metadata.labels字段的含义:
root@k8s-master01:~# kubectl explain deployment.metadata.labels
KIND:     Deployment
VERSION:  apps/v1

FIELD:    labels <map[string]string>

DESCRIPTION:
     Map of string keys and values that can be used to organize and categorize
     (scope and select) objects. May match selectors of replication controllers
     and services. More info: http://kubernetes.io/docs/user-guide/labels

# 若要查看deployment.spec.template.spec.containers字段下还有哪些字段可用
root@k8s-master01:~# kubectl explain deployment.spec.template.spec.containers
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: containers <[]Object>

DESCRIPTION:
     List of containers belonging to the pod. Containers cannot currently be
     added or removed. There must be at least one container in a Pod. Cannot be
     updated.

     A single application container that you want to run within a pod.

FIELDS:
...
   imagePullPolicy  <string>
     Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always
     if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.
     More info:
     https://kubernetes.io/docs/concepts/containers/images#updating-images

     Possible enum values:
     - `"Always"` means that kubelet always attempts to pull the latest image.
     Container will fail If the pull fails.
     - `"IfNotPresent"` means that kubelet pulls if the image isn't present on
     disk. Container will fail if the image isn't present and the pull fails.
     - `"Never"` means that kubelet never pulls an image, but only uses a local
     image. Container will fail if the image isn't present
...

调整YAML文件内容

精简不用的字段、修改字段的内容、添加镜像的拉取策略等,将其保存到nginx-deployment.yaml文件中。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: jumpoint-web-deployment-label
  name: jumpoint-web
  namespace: jumpoint-ns
spec:
  replicas: 2
  selector:
    matchLabels:
      app: jumpoint-web-pod-label
  template:
    metadata:
      labels:
        app: jumpoint-web-pod-label
    spec:
      containers:
      - image: nginx:latest
        name: jumpoint-web-container-name
        imagePullPolicy: Always
        ports:
        - containerPort: 80
          protocol: TCP
          name: http

使用nginx-deployment.yaml文件创建Deployment资源对象。

root@k8s-master01:~/yaml-resources# kubectl create namespace jumpoint-ns
namespace/jumpoint-ns created

root@k8s-master01:~/yaml-resources# kubectl apply -f nginx-deployment.yaml
deployment.apps/jumpoint-web created

root@k8s-master01:~/yaml-resources# kubectl get deployments -n jumpoint-ns
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
jumpoint-web   2/2     2            2           95s

root@k8s-master01:~/yaml-resources# kubectl get pods -n jumpoint-ns -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP            NODE             NOMINATED NODE   READINESS GATES
jumpoint-web-66c66b4db4-f5dw4   1/1     Running   0          3m49s   10.200.2.14   k8s-node02-237   <none>           <none>
jumpoint-web-66c66b4db4-x8jqj   1/1     Running   0          3m49s   10.200.1.13   k8s-node01-236   <none>           <none>

root@k8s-master01-235:~/yaml-resources# kubectl describe deployment -n jumpoint-ns jumpoint-web
Name:                   jumpoint-web
Namespace:              jumpoint-ns
CreationTimestamp:      Tue, 30 Apr 2024 13:13:50 +0800
Labels:                 app=jumpoint-web-deployment-label
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=jumpoint-web-pod-label
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=jumpoint-web-pod-label
  Containers:
   jumpoint-web-container-name:
    Image:        nginx:latest
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   jumpoint-web-66c66b4db4 (2/2 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  3m19s  deployment-controller  Scaled up replica set jumpoint-web-66c66b4db4 to 2

3、资源操作命令详解

1.创建资源

# 从YAML文件创建资源
kubectl create -f myapp.yaml

# 创建多个资源
kubectl create -f directory/  # 目录下所有YAML文件
kubectl create -f file1.yaml -f file2.yaml

2.应用声明式配置

# 创建或更新某个资源(推荐方式)
kubectl apply -f myapp.yaml

# 查看将要应用的变更
kubectl apply -f myapp.yaml --dry-run=client

# 强制替换配置
kubectl replace --force -f myapp.yaml

3.删除资源

# 删除指定资源
kubectl delete -f myapp.yaml

# 删除多个资源
kubectl delete -f directory/

# 基于标签删除(可能的多个pod)
kubectl delete pod -l app=webapp

4、高级操作技巧

1. 部分更新资源(打补丁)

# 使用merge混合策略(默认是strategic策略性合并)更新标签,适用于简单字段更新
cat > patch.yaml << EOF
metadata:
  labels:
    key: myapp-value
EOF

kubectl patch pod myapp --type=merge --patch-file patch.yaml

# 使用JSON patch删除标签
cat > remove-label.yaml << EOF
- op: remove
  path: /metadata/labels/key
EOF

kubectl patch pod myapp --type=json --patch-file remove-label.yaml

2. 添加注解

# 添加或更新注解
kubectl annotate pod myapp webapp="nginx.1.17" description="前端Web服务器"

# 查看注解信息
kubectl describe pod myapp | grep Annotations

3. 实时编辑资源(对于改动不大的情况,使用edit更快速)

# 编辑运行中的资源
kubectl edit pod myapp

# 编辑Deployment配置(编辑时会打开默认文本编辑器,修改保存后会立即生效)
kubectl edit deployment/myapp

5、常见问题排查

1. YAML格式错误

# 常见的格式错误
error: error parsing pod.yaml: error converting YAML to JSON: yaml: line 10: did not find expected key

# 解决方法:使用YAML验证工具或在线校验器

2. 资源已存在错误

# 使用create时如果资源已存在会报错
Error from server (AlreadyExists): error when creating "myapp.yaml": pods "myapp" already exists

# 解决方法:使用apply代替create,或者先删除再创建

3. 字段验证错误

# API服务器会验证字段合法性
The Deployment "myapp" is invalid: spec.template.spec.containers[0].name: Required value

# 解决方法:使用kubectl explain查看字段要求

掌握Kubernetes资源清单文件的使用是容器编排的基础技能。记住,实践是最好的学习方式。尝试从简单的Pod开始,逐步扩展到复杂的Deployment和Service配置,慢慢你就会发现Kubernetes资源管理的强大之处。