K8s 配置详解:如何编写和使用 YAML – wiki基地


K8s 配置详解:如何编写和使用 YAML 文件

引言:基础设施即代码与 Kubernetes

在现代云原生应用开发的浪潮中,Kubernetes (K8s) 已成为容器编排的事实标准。它提供了一个强大、灵活的平台来自动化部署、扩展和管理容器化应用。而要驯服 Kubernetes 这个强大的野兽,理解其配置方式至关重要。

传统的IT运维中,应用的部署和管理往往涉及大量的手动操作和脚本,这不仅效率低下,而且难以维护和复现。云原生时代倡导“基础设施即代码”(Infrastructure as Code, IaC)理念,这意味着基础设施的配置和管理应该像应用代码一样被处理:使用文本文件定义状态,通过版本控制进行管理,并通过自动化工具进行部署。

Kubernetes 完美契合了 IaC 的思想。在 K8s 中,我们不是直接告诉集群“运行一个 Nginx”,而是通过声明式 API 向 K8s 提交一个描述期望状态的配置清单,比如“我想要一个 Nginx Pod,它应该有 3 个副本,对外暴露 80 端口”。Kubernetes 控制平面会持续监控当前集群的状态,并努力使其达到你在配置清单中声明的期望状态。

那么,这些“配置清单”通常是什么格式呢?在 Kubernetes 中,最常用也是事实上的标准格式就是 YAML

本文将深入探讨 Kubernetes 配置的基石——YAML 文件,详细解释其结构、如何编写不同类型的 K8s 资源配置,以及如何使用 kubectl 工具来应用和管理这些配置。

第一部分:为什么选择 YAML?YAML 的基础语法

在了解 Kubernetes 配置之前,我们首先需要理解为什么 Kubernetes 青睐 YAML,以及 YAML 的基本语法。

1.1 YAML vs. JSON:可读性与互操作性

虽然 Kubernetes API 本质上可以使用 JSON 或 YAML 进行通信,但在编写和管理配置文件时,YAML 凭借其出色的可读性成为了首选。

  • JSON (JavaScript Object Notation): 是一种轻量级的数据交换格式,广泛用于网络传输。它的结构清晰,易于机器解析。
  • YAML (YAML Ain’t Markup Language / Yet Another Markup Language): 是一种人类友好的数据序列化标准,设计目标是易于阅读和编写。

对比两者的一个简单例子:

JSON:

json
{
"name": "my-app",
"ports": [
{"containerPort": 80},
{"containerPort": 443}
]
}

YAML:

yaml
name: my-app
ports:
- containerPort: 80
- containerPort: 443

显而易见,YAML 使用更少的符号(没有大括号、方括号、逗号和引号,在很多情况下)和更自然的缩进,使得配置文件看起来更像结构化的文本,而不是代码。这对于需要人工编写、阅读和维护大量配置文件的场景(比如 Kubernetes 应用部署)来说是一个巨大的优势。

尽管 YAML 更易读,但它在功能上与 JSON 基本等价,可以轻松地相互转换。Kubernetes API 内部也是 JSON 驱动的,但它提供了对 YAML 输入的良好支持。

1.2 YAML 的核心语法要素

掌握 Kubernetes 配置的第一步是掌握 YAML 的基础语法。YAML 主要基于以下几种结构:

1.2.1 键值对 (Key-Value Pairs)

这是 YAML 最基本的组成单元,表示一个属性及其对应的值。使用冒号 : 分隔键和值,冒号后面通常有一个空格,以增强可读性。

yaml
key1: value1
key2: value2

值可以是字符串、数字、布尔值等。字符串通常不需要引号,除非包含特殊字符或需要保留前导/后导空格。

yaml
name: my-container # 字符串
port: 80 # 数字
enabled: true # 布尔值
description: "This is a string with spaces and special characters: !" # 带引号的字符串

1.2.2 列表 (Lists / Sequences)

列表表示一组有序的项。列表的每一项都以短横线 - 开头,并且与父元素有相同的缩进。

yaml
fruits:
- Apple
- Banana
- Cherry
ports:
- protocol: TCP
number: 80
- protocol: UDP
number: 53

注意,列表中的项可以是简单的值,也可以是嵌套的键值对(即一个对象)。

1.2.3 对象 / 映射 (Objects / Maps / Dictionaries)

对象表示一组无序的键值对集合。在 YAML 中,通过缩进来表示一个键的值是一个嵌套的对象。

yaml
person:
name: Alice
age: 30
address:
street: 123 Main St
city: Anytown

这里的 person 的值是一个对象,包含 nameageaddress。而 address 的值又是一个嵌套的对象。

1.2.4 缩进 (Indentation)

缩进是 YAML 中最重要的语法元素,它定义了结构的层级关系。 YAML 不使用大括号或方括号来表示结构,而是完全依赖于一致的缩进。

  • 必须使用空格进行缩进,而不是 Tab 键。 不同的 Tab 宽度在不同的编辑器中可能导致解析错误。
  • 同一层级的元素必须具有相同的缩进量。
  • 通常使用 2 个或 4 个空格作为缩进单位。 推荐使用 2 个空格,这是 Kubernetes 文档中最常见的风格。

错误的缩进示例:

“`yaml

错误:name 和 age 缩进不一致

person:
name: Alice
age: 30

错误:list 项缩进与父元素不同

fruits:
– Apple
– Banana # Banana 缩进错误

错误:address 缩进错误

person:
name: Alice
address:
street: 123 Main St # street 缩进错误
“`

YAML 解析器对缩进非常敏感,即使一个空格的差异也可能导致解析失败或配置错误。务必确保缩进的正确性和一致性。

1.2.5 注释 (Comments)

使用井号 # 开头表示注释。注释可以出现在行尾或独立一行,它们会被解析器忽略,用于提高配置文件的可读性和解释性。

“`yaml

这是一个顶级注释

name: my-application # 应用程序名称

ports: # 定义端口列表
– containerPort: 80 # HTTP 端口
“`

1.2.6 多个文档在一个文件 (---)

YAML 支持在同一个文件中包含多个独立的 YAML 文档,使用 --- 分隔符。这在 Kubernetes 中非常常见,例如将一个应用的 Deployment 和 Service 定义放在同一个文件里。

“`yaml

— 表示第一个文档的开始或结束

apiVersion: apps/v1
kind: Deployment

… Deployment 配置 …

— # 分隔符

apiVersion: v1
kind: Service

… Service 配置 …

“`

1.3 YAML 小结

掌握了键值对、列表、对象、缩进和分隔符这几个基本概念,你就掌握了编写 Kubernetes YAML 配置所需的核心语法。记住:缩进是王道! 务必保持缩进的正确和一致。

第二部分:Kubernetes YAML 配置的解剖刀

一个典型的 Kubernetes 配置清单(无论是 Pod、Deployment、Service 还是其他资源)都遵循一个标准的顶层结构。理解这个结构是编写有效 K8s 配置的关键。

一个 Kubernetes 对象的 YAML 表示通常包含以下四个(或五个)顶层字段:

  1. apiVersion: 定义创建该对象所使用的 Kubernetes API 版本。
  2. kind: 定义对象的类型(例如 Pod, Deployment, Service, ConfigMap 等)。
  3. metadata: 定义对象的元数据,包括名称、命名空间、标签、注解等。
  4. spec: 定义对象的期望状态(Declaration of the desired state)。这是配置的核心部分,不同的对象类型有不同的 spec 字段。
  5. status: 定义对象的当前状态。这个字段通常由 Kubernetes 集群自动填充和管理,用户在编写配置文件时不会设置 status 字段。但在查看对象状态时,kubectl get <resource> -o yaml 会显示这个字段。

让我们逐一详细解释这些字段。

2.1 apiVersion

这个字段指定了用来创建或修改对象的 API 版本。Kubernetes 的 API 是不断演进的,不同的版本提供不同的功能和稳定性保证。API 版本通常由 API 组和版本号组成,例如 apps/v1v1networking.k8s.io/v1 等。

  • v1: 核心 API 组,包含 Pods, Services, Namespaces, PersistentVolumes 等基本对象。
  • apps/v1: 用于管理有状态应用的 API 组,包含 Deployments, ReplicaSets, StatefulSets, DaemonSets 等。
  • networking.k8s.io/v1: 用于网络策略相关的 API 组,包含 NetworkPolicy。
  • storage.k8s.io/v1: 用于存储相关的 API 组,包含 StorageClass, VolumeAttachment 等。

选择正确的 apiVersion 非常重要,因为它决定了后续 spec 字段的结构和可用的选项。通常,你应该使用最新且稳定的 API 版本。可以在 Kubernetes 官方文档中查找特定资源类型对应的 API 版本。

2.2 kind

这个字段指定了你想要创建的 Kubernetes 对象的类型。例如:

  • Pod: K8s 的最小可部署单元。
  • Deployment: 管理无状态 Pod 的部署和扩展。
  • Service: 定义访问 Pods 的策略,提供稳定的网络端点。
  • ConfigMap: 存储非敏感配置数据。
  • Secret: 存储敏感配置数据(如密码、密钥)。
  • Namespace: 隔离资源的分区。
  • Ingress: 暴露 HTTP 和 HTTPS 路由到集群内服务。
  • 等等。

kindapiVersion 共同确定了配置文件的类型和版本,从而决定了 spec 字段的结构。

2.3 metadata

metadata 字段是一个对象,用于包含对象的元数据,即描述对象自身的信息。这是 Kubernetes 中一个非常重要的部分,因为它提供了组织、识别和管理对象的机制。常见的元数据字段包括:

  • name (string, Required): 对象的名称,在同一类型的对象和同一命名空间下必须唯一。遵循 DNS 子域名的命名规范(小写字母、数字、中划线,必须以字母开头和结尾)。
  • namespace (string): 对象所在的命名空间。如果不指定,通常默认为 default 命名空间。命名空间提供了资源的逻辑隔离。
  • labels (map[string]string): 一组附加到对象上的键值对标签。标签用于组织和选择对象,是 Kubernetes 中进行资源分组和筛选的核心机制。例如,你可以使用 app: my-apptier: frontend 来标记属于某个应用前端部分的 Pods。
  • annotations (map[string]string): 一组附加到对象上的键值对注解。注解用于存储非标识性的元数据,通常用于工具或库的内部使用,不像标签那样用于选择对象。例如,部署工具可能会在这里记录部署信息。
  • uid (string): 由 Kubernetes 系统生成的唯一标识符,用于区分历史上的对象。
  • resourceVersion (string): 表示对象在内部数据库中的特定版本,用于实现乐观并发控制。

在编写配置时,name 是必需的(除了少数资源类型如 Namespace),namespace 是可选的(但强烈推荐使用),labels 是非常常用且重要的,annotations 则根据需要使用。

示例 metadata:

yaml
metadata:
name: my-nginx-deployment
namespace: default # 可选,通常省略或明确指定
labels:
app: my-app
tier: frontend
annotations:
description: "This is a sample nginx deployment"

2.4 spec

spec 字段是 Kubernetes 配置清单中最复杂、内容最丰富的部分,因为它包含了你想要创建的对象的期望状态的详细描述。spec 的结构完全取决于 kind 字段指定的对象类型。 不同的对象类型有完全不同的 spec 结构和字段。

例如:

  • Pod 的 spec 包含容器列表、卷、重启策略等。
  • Deployment 的 spec 包含 Pod 模板 (template)、副本数量 (replicas)、选择器 (selector) 等。
  • Service 的 spec 包含服务类型 (type)、端口映射 (ports)、选择器 (selector) 等。
  • ConfigMap 的 spec 包含要存储的数据 (databinaryData)。

理解各种 Kubernetes 资源的 spec 字段是掌握 Kubernetes 配置的关键。这需要查阅 Kubernetes 官方文档,或者使用 kubectl explain <resource_type> 命令来获取详细的字段说明。

示例 spec (以 Deployment 为例):

yaml
spec:
replicas: 3 # 期望运行的 Pod 副本数量
selector: # 选择器,用于确定哪些 Pod 由此 Deployment 管理
matchLabels:
app: my-app
tier: frontend
template: # Pod 模板,定义了 Deployment 将创建的 Pod 的 spec
metadata:
labels: # Pod 模板中的标签必须与 selector.matchLabels 匹配
app: my-app
tier: frontend
spec:
containers: # Pod 包含的容器列表
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

2.5 status (了解即可)

status 字段描述了对象的当前状态。这个字段是由 Kubernetes 系统和控制器自动更新的,用户在编写 YAML 文件时不需要(也不能)设置它。当你使用 kubectl get <resource> <name> -o yaml 命令查看一个正在运行或已经创建的对象时,你会看到 status 字段,它包含了诸如 Pod 的 IP 地址、Deployment 的当前副本数、Service 的 ClusterIP 等信息。

示例 status (以 Pod 为例):

yaml
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-10-26T10:00:00Z"
status: "True"
type: Initialized
# ... 其他条件 ...
containerStatuses:
- containerID: containerd://...
image: nginx:latest
imageID: docker.io/library/nginx@sha256:...
lastState: {}
name: nginx
ready: true # 容器是否就绪
restartCount: 0
started: true
state:
running: # 容器当前状态
startedAt: "2023-10-26T10:00:10Z"
hostIP: 192.168.1.100
podIP: 10.10.0.5
podIPs:
- ip: 10.10.0.5
phase: Running # Pod 当前阶段 (Pending, Running, Succeeded, Failed, Unknown)
qosClass: Burstable
startTime: "2023-10-26T10:00:00Z"

第三部分:编写常见的 Kubernetes 资源 YAML

现在我们来编写一些最常见和重要的 Kubernetes 资源的 YAML 配置。

3.1 Pod

Pod 是 Kubernetes 中最小的可部署计算单元。一个 Pod 包含一个或多个紧密相关的容器、存储卷、网络配置以及如何运行容器的规范。

基本 Pod YAML 示例 (运行一个 Nginx 容器):

“`yaml

pod-nginx.yaml

apiVersion: v1 # 使用核心 API v1
kind: Pod # 类型为 Pod
metadata:
name: nginx-pod # Pod 名称
labels: # 标签用于识别和分组
app: nginx
spec: # Pod 的期望状态
containers: # 容器列表
– name: nginx # 容器名称
image: nginx:latest # 使用的镜像
ports: # 暴露的端口
– containerPort: 80 # 容器内部监听的端口
“`

这个 Pod 定义非常简单,它告诉 Kubernetes 创建一个名为 nginx-pod 的 Pod,其中包含一个基于 nginx:latest 镜像的容器,该容器暴露 80 端口。

3.2 Deployment

Deployment 是 Kubernetes 中用于管理无状态应用的核心控制器。它可以定义 Pod 的模板、期望的副本数量,并提供滚动更新、回滚等功能。Deployment 会管理 ReplicaSet,而 ReplicaSet 则确保运行指定数量的 Pod 副本。

基本 Deployment YAML 示例 (运行 3 个 Nginx Pod 副本):

“`yaml

deployment-nginx.yaml

apiVersion: apps/v1 # 使用 apps API v1
kind: Deployment # 类型为 Deployment
metadata:
name: nginx-deployment # Deployment 名称
labels:
app: nginx
spec:
replicas: 3 # 期望的 Pod 副本数量
selector: # 选择器,用于匹配 Deployment 管理的 Pods
matchLabels:
app: nginx # 匹配带有 app: nginx 标签的 Pods
template: # Pod 模板
metadata:
labels: # Pod 模板的标签,必须与 selector 匹配
app: nginx
spec:
containers:
– name: nginx
image: nginx:latest
ports:
– containerPort: 80
“`

这个 Deployment 告诉 Kubernetes:
1. 创建一个名为 nginx-deployment 的 Deployment。
2. 始终保持 3 个带有 app: nginx 标签的 Pod 运行。
3. 这些 Pod 的创建基于 template 中定义的规范:一个名为 nginx-container 的容器,使用 nginx:latest 镜像,并暴露 80 端口。

注意 selector.matchLabelstemplate.metadata.labels 必须一致。这是 Deployment 知道哪些 Pod 属于它的关键。

3.3 Service

Pod 是有生命周期的,它们的 IP 地址不是固定的。Service 提供了一种抽象,为一组 Pods 提供一个稳定的网络端点(ClusterIP、DNS 名称等),并将请求负载均衡到这组 Pods 上。Service 通过 selector 字段来选择提供服务的 Pods。

基本 Service YAML 示例 (暴露 Nginx Deployment):

“`yaml

service-nginx.yaml

apiVersion: v1 # 使用核心 API v1
kind: Service # 类型为 Service
metadata:
name: nginx-service # Service 名称
spec:
selector: # 选择器,用于匹配 Service 服务的 Pods
app: nginx # 匹配带有 app: nginx 标签的 Pods
ports: # 定义服务的端口映射
– protocol: TCP
port: 80 # Service 监听的端口 (集群内访问)
targetPort: 80 # Pod 中容器监听的端口
type: ClusterIP # 服务类型 (ClusterIP, NodePort, LoadBalancer)
“`

这个 Service 告诉 Kubernetes:
1. 创建一个名为 nginx-service 的 Service。
2. 它将把流量路由到带有 app: nginx 标签的 Pods 上(这些 Pods 正是由上面定义的 Deployment 管理的)。
3. 服务在集群内部的 80 端口监听请求 (port: 80)。
4. 接收到的请求将被转发到被选中 Pods 的 80 端口 (targetPort: 80)。
5. 服务的类型是 ClusterIP,这意味着它只在集群内部可访问,分配一个集群内部 IP。

常见的 Service 类型:
* ClusterIP: 默认类型,分配一个集群内部 IP,只在集群内可访问。
* NodePort: 在集群中每个节点上开放一个静态端口,外部可以通过 <NodeIP>:<NodePort> 访问服务。用于开发或测试。
* LoadBalancer: 在支持的云提供商上,会自动创建一个外部负载均衡器,将流量导入服务。用于生产环境暴露服务。
* ExternalName: 将服务映射到外部的 DNS 名称,不做代理。

3.4 ConfigMap 和 Secret

ConfigMap 用于存储非敏感的配置数据,如配置文件、命令行参数、环境变量等。Secret 用于存储敏感数据,如密码、OAuth Token、SSH Key 等。它们都以键值对的形式存储数据,可以作为文件或环境变量注入到 Pod 中。

基本 ConfigMap YAML 示例:

“`yaml

configmap-app.yaml

apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data: # 非敏感数据
app.properties: | # 可以存储多行文本
database.url=jdbc:mysql://mysql:3306/mydb
database.username=myuser
config.json: |
{
“logLevel”: “INFO”,
“timeout”: 30
}
api_key: abcdef12345 # 也可以是单行键值对
“`

基本 Secret YAML 示例:

Secret 的 data 字段的值必须是 Base64 编码的。这是为了确保数据在传输和存储时是“可打印”的,但这不是加密。任何人都可以轻松解码 Base64。因此,Secret 只是为了管理敏感数据而设计的,而不是为了保护数据不被知道。真正的数据安全需要依赖于底层的 etcd 加密和 RBAC 访问控制。

“`yaml

secret-db-credentials.yaml

apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque # 默认类型,表示通用的用户定义 Secret
data:
# 数据库用户名 (Base64 编码的 ‘admin’)
username: YWRtaW4=
# 数据库密码 (Base64 编码的 ‘password123’)
password: cGFzc3dvcmQxMjM=
“`

你可以使用在线工具或命令行工具(如 echo -n 'your_string' | base64)来对字符串进行 Base64 编码。

第四部分:使用 kubectl 应用和管理 YAML 文件

编写好 YAML 文件后,就需要使用 Kubernetes 的命令行工具 kubectl 来与集群交互,创建、更新或删除资源。

4.1 创建资源 (kubectl applykubectl create)

有两种主要的方式使用 YAML 文件创建资源:

  • kubectl create -f <filename.yaml>: 基于 YAML 文件创建一个或多个资源。如果资源已经存在,会报错。
  • kubectl apply -f <filename.yaml>: 基于 YAML 文件创建或更新资源。这是更推荐的方式,尤其是用于持续部署。apply 命令是幂等的,你可以反复运行它,它只会根据 YAML 文件中的定义创建新资源或更新现有资源。

使用 apply 创建/更新资源:

“`bash
kubectl apply -f pod-nginx.yaml # 应用单个文件
kubectl apply -f deployment-nginx.yaml
kubectl apply -f service-nginx.yaml
kubectl apply -f configmap-app.yaml
kubectl apply -f secret-db-credentials.yaml

应用包含多个 YAML 文档的文件

kubectl apply -f app.yaml # app.yaml 可能包含 Deployment 和 Service

应用一个目录下的所有 YAML 文件

kubectl apply -f ./config/ # 应用 config 目录下的所有 .yaml, .yml, .json 文件
“`

kubectl apply 的工作原理是计算当前集群中对象的状态与 YAML 文件中定义的状态之间的差异,然后只发送必要的补丁请求来更新对象。

4.2 查看资源 (kubectl getkubectl describe)

创建资源后,可以使用 kubectl get 查看资源列表或特定资源的状态概要,使用 kubectl describe 查看资源的详细信息。

“`bash
kubectl get pods
kubectl get deployments
kubectl get services
kubectl get configmaps
kubectl get secrets

查看特定资源的 YAML 配置

kubectl get deployment nginx-deployment -o yaml

查看特定资源的详细信息

kubectl describe pod nginx-pod
kubectl describe service nginx-service
“`

kubectl get -o yaml 是一个非常有用的命令,可以用来查看 Kubernetes 为你的对象自动添加的字段(如 statusuidresourceVersion 等),以及验证你的配置是否被正确应用。

4.3 删除资源 (kubectl delete)

使用 kubectl delete 命令可以根据 YAML 文件或资源名称删除资源。

根据文件删除:

bash
kubectl delete -f pod-nginx.yaml
kubectl delete -f deployment-nginx.yaml
kubectl delete -f service-nginx.yaml
kubectl delete -f app.yaml # 删除 app.yaml 中定义的所有资源
kubectl delete -f ./config/ # 删除目录下的所有资源

根据类型和名称删除:

bash
kubectl delete pod nginx-pod
kubectl delete deployment nginx-deployment
kubectl delete service nginx-service

4.4 验证 YAML (kubectl apply --validate)

从 Kubernetes 1.20 版本开始,kubectl apply 默认启用客户端侧验证。这意味着在你将 YAML 发送给 API Server 之前,kubectl 会检查你的 YAML 文件结构和字段是否符合 Kubernetes 资源的模式定义。

如果想手动验证而不应用:

bash
kubectl apply -f app.yaml --dry-run=client --validate

--dry-run=client 表示只在客户端模拟操作,不实际发送请求到集群。结合 --validate 可以用来检查 YAML 的语法和结构有效性。

4.5 学习资源的 YAML 结构 (kubectl explain)

如果你不确定某个资源类型或字段的正确 YAML 结构,kubectl explain 命令是一个非常有用的工具。

bash
kubectl explain pod # 查看 Pod 的顶级字段说明
kubectl explain pod.spec # 查看 Pod spec 字段的说明
kubectl explain deployment.spec.template.spec.containers # 查看 Deployment Pod 模板中容器字段的说明
kubectl explain service.spec.ports # 查看 Service 端口字段的说明

这个命令会打印出字段的描述、类型以及是否必需,对于编写和调试 YAML 文件非常有帮助。

第五部分:编写 K8s YAML 的最佳实践和技巧

编写清晰、可维护的 Kubernetes YAML 配置需要遵循一些最佳实践。

  1. 保持文件小而专注: 将不同类型的资源(如 Deployment 和 Service)定义在不同的文件中,除非它们紧密相关且逻辑上属于同一单元(此时可以使用 --- 分隔符)。这样可以提高文件的可读性和可维护性。
  2. 使用有意义的名称和标签: 为资源选择清晰、描述性的名称。广泛使用标签来标记应用、组件、环境、版本等,这是 Kubernetes 中组织和选择资源的基石。标签的一致性对于 Service、Deployment、ConfigMap Volume 挂载等都非常重要。
  3. 利用命名空间: 使用命名空间来对不同环境(开发、测试、生产)或不同团队/应用进行逻辑隔离,避免资源名称冲突和提高安全性。在 metadata 中明确指定 namespace
  4. 添加注释: 使用注释解释复杂的配置段落、决策原因或注意事项,帮助自己和他人理解配置。
  5. 使用版本控制: 将你的 YAML 配置文件存储在 Git 等版本控制系统中。这使得你可以跟踪配置变更历史、回滚到早期版本,并进行团队协作。基础设施即代码的核心优势之一就是版本控制。
  6. 模板化和参数化: 对于需要在不同环境或不同部署中使用略有差异的配置(如镜像标签、副本数、配置值等),避免手动修改 YAML 文件。考虑使用模板工具,如 Helm 或 Kustomize。
    • Helm: 是 Kubernetes 的包管理器,使用 Chart 定义应用。Chart 中包含参数化的 YAML 模板,通过 values 文件注入具体值。
    • Kustomize: 是一个原生的 Kubernetes 配置管理工具,通过 overlay 的方式对基础 YAML 进行修改和定制,而无需修改原始文件。
      这些工具在管理复杂的应用或在多个环境中部署时非常有用。
  7. 定义资源请求和限制 (resources): 在 Pod 的容器定义中,为 CPU 和内存设置 resources.requestsresources.limits。这有助于调度器更合理地分配资源,并防止单个 Pod 耗尽节点资源影响其他 Pod。
  8. 配置健康检查 (livenessProbe, readinessProbe): 为容器配置存活探针 (livenessProbe) 和就绪探针 (readinessProbe)。这让 Kubernetes 知道何时重启不健康的容器,以及何时将流量路由到就绪的 Pod。
  9. 使用配置映射和秘密进行外部化配置: 将应用的配置数据从容器镜像中分离出来,存储在 ConfigMap 和 Secret 中。这样可以在不重建镜像的情况下修改应用配置,并且更安全地管理敏感信息。
  10. 从小处着手,逐步迭代: 从一个简单的 Pod 开始,然后是 Deployment 和 Service,再添加 ConfigMap、Secret、Ingress 等。逐步增加配置的复杂性,每次修改后都进行测试。

第六部分:常见的 YAML 编写错误和故障排除

即使有经验,编写 YAML 文件时也容易出错。以下是一些常见的错误及其排除方法:

  1. 缩进错误: 这是最常见也是最令人沮丧的错误。YAML 解析器对缩进非常敏感。
    • 错误信息: YAML 解析错误,通常指示缩进不一致或无效。
    • 排除方法: 使用支持 YAML 语法的代码编辑器(如 VS Code、Sublime Text 等),它们通常有缩进指南和语法高亮,能帮你发现问题。确保只使用空格,并且同一层级的元素缩进一致。可以使用在线 YAML 校验器或 kubectl apply --dry-run=client --validate 进行初步检查。
  2. 键名或值拼写错误: Kubernetes 的字段名称是固定的,拼写错误会导致字段无法识别。
    • 错误信息: 可能是 error: error validating... unknown field "<wrong_field>" in <object_type>.spec
    • 排除方法: 仔细检查字段名称。使用 kubectl explain <resource_type>.<field> 来查找正确的字段名和结构。
  3. API 版本或类型错误: 指定了错误的 apiVersionkind
    • 错误信息: error: unable to recognize "<filename.yaml>": no matches for kind "<kind>" in version "<api_version>".
    • 排除方法: 确认你使用的 Kubernetes 版本支持该 apiVersionkind 的组合。查阅 Kubernetes 文档或使用 kubectl api-versions 查看集群支持的 API 版本。
  4. 必需字段缺失: 某些字段是必需的,如果遗漏会导致创建失败。
    • 错误信息: error: error validating... missing required field "<required_field>" in <object_type>.spec
    • 排除方法: 查看错误信息,它会明确指出缺失的字段。使用 kubectl explain <resource_type>.<parent_field> 查看哪些字段是必需的。
  5. 选择器不匹配: Deployment 或 Service 的 selector 没有正确匹配 Pod 模板的标签。
    • 症状: Deployment 创建了 ReplicaSet 但没有 Pods 运行,或者 Service 没有 endpoints。
    • 排除方法: 检查 Deployment/Service 的 selector.matchLabels 是否与 Pod 模板 template.metadata.labels 完全一致。标签的键和值都必须匹配。
  6. 配置值不正确: 字段值格式错误或不在允许范围内。
    • 错误信息: 可能因字段而异,例如端口号超出范围,镜像名称格式错误等。
    • 排除方法: 查阅相关字段的文档说明。对于镜像问题,使用 docker pull <image> 在本地尝试拉取镜像,检查名称是否正确。
  7. 多个文档分隔符 (---) 使用错误: 如果在同一个文件中定义了多个资源但忘记使用 --- 分隔,解析器可能只会识别第一个文档。

排除 K8s 配置问题时,kubectl describe 命令是你的好朋友。它会提供资源的状态、事件以及相关的控制器信息,这些信息对于诊断问题非常有价值。例如,kubectl describe pod <pod-name> 可以看到 Pod 的调度情况、容器创建日志、错误事件等。

结论

Kubernetes 的配置是其强大能力的核心所在,而 YAML 文件则是承载这些配置的标准格式。通过本文的学习,你应该已经:

  • 理解了为什么 YAML 是 Kubernetes 配置的首选。
  • 掌握了 YAML 的基本语法:键值对、列表、对象、缩进和分隔符。
  • 了解了 Kubernetes YAML 对象的标准结构:apiVersion, kind, metadata, spec, status
  • 学会了编写常见的 Kubernetes 资源(Pod, Deployment, Service, ConfigMap, Secret)的 YAML 配置。
  • 掌握了使用 kubectl apply, get, describe, delete, explain 等命令来管理和调试配置。
  • 了解了编写高质量 K8s YAML 的最佳实践和常见错误排除方法。

编写和管理 Kubernetes 配置是一个不断学习和实践的过程。从简单的应用开始,逐步引入更复杂的资源和概念。善用 kubectl explain 和 Kubernetes 官方文档,它们是学习和解决问题的重要资源。将基础设施视为代码,将 YAML 文件纳入版本控制,采纳自动化工具和最佳实践,将极大地提高你在 Kubernetes 上管理应用的效率和可靠性。

继续练习,你会越来越熟练地运用 YAML 来构建和管理你的云原生应用世界!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部