Kubernetes自定义资源(CRD)实战入门指南
在Kubernetes生态系统中,虽然内置资源如Deployment、Service等能满足大部分需求,但在实际应用中,我们经常需要定义自己的资源类型来管理特定的应用或服务。CustomResourceDefinition(CRD)正是为此而生,它允许我们扩展Kubernetes API,定义自己的资源类型。本文将通过一个完整的示例,带你从零开始掌握CRD的创建和使用。
一、CRD概述与应用场景
CustomResourceDefinition(CRD)是Kubernetes中一种强大的扩展机制,允许用户定义自己的资源类型,而无需修改Kubernetes核心代码。通过CRD,我们可以:
- 扩展Kubernetes API,添加自定义资源类型
- 与自定义控制器配合,实现自动化运维
- 构建Operator,管理复杂应用的生命周期
CRD的典型应用场景包括:
- 数据库管理:如MySQL、PostgreSQL等数据库的自动部署和管理
- 服务网格配置:如Istio中的VirtualService、DestinationRule等
- 监控系统配置:如Prometheus Operator中的ServiceMonitor
- CI/CD流水线:如Tekton中的PipelineRun、TaskRun等
二、CRD基础概念
在深入实践之前,我们需要了解几个核心概念:
1. CustomResourceDefinition (CRD)
CRD是Custom Resource Definition的缩写,它是自定义资源的定义模板,描述了自定义资源的结构和属性。
2. Custom Resource (CR)
CR是Custom Resource的缩写,它是CRD的具体实例,就像Pod是Deployment的具体实例一样。
3. Controller
控制器负责监听自定义资源的变化,并根据资源的期望状态执行相应的操作。
三、创建第一个CRD
让我们通过一个实际的例子来学习CRD的创建。我们将创建一个名为Website的自定义资源,用于管理网站部署。
1. 定义CRD
首先,创建一个名为website-crd.yaml的文件:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# 名称必须与下面的spec字段匹配,格式为<plural>.<group>
name: websites.web.example.com
spec:
# 组名,用于REST API: /apis/<group>/<version>
group: web.example.com
# CRD可以支持多个版本
versions:
- name: v1
# 每个版本都可以通过served标志来独立启用或禁止
served: true
# 其中一个且只有一个版本必须被标记为存储版本
storage: true
# 定义自定义资源的结构
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
domain:
type: string
description: 网站域名
image:
type: string
description: 网站使用的镜像
replicas:
type: integer
description: 网站副本数
minimum: 1
port:
type: integer
description: 网站服务端口
minimum: 1
maximum: 65535
status:
type: object
properties:
availableReplicas:
type: integer
description: 可用副本数
# 可以是Namespaced或Cluster
scope: Namespaced
names:
# 名称的复数形式,用于URL:/apis/<group>/<version>/<plural>
plural: websites
# 名称的单数形式,作为命令行使用时和显示时的别名
singular: website
# kind通常是单数形式的驼峰编码(CamelCased)形式
kind: Website
# CLI中使用的资源简称
shortNames:
- ws
2. 应用CRD
使用kubectl将CRD应用到集群中:
kubectl apply -f website-crd.yaml
验证CRD是否创建成功:
kubectl get crd websites.web.example.com
查看CRD详细信息:
kubectl describe crd websites.web.example.com
四、创建自定义资源实例
CRD创建成功后,我们就可以创建自定义资源实例了。
1. 定义自定义资源
创建一个名为my-website.yaml的文件:
apiVersion: web.example.com/v1
kind: Website
metadata:
name: my-website
namespace: default
spec:
domain: "mywebsite.example.com"
image: "nginx:1.20"
replicas: 3
port: 80
2. 应用自定义资源
kubectl apply -f my-website.yaml
3. 查看自定义资源
kubectl get websites
kubectl get ws # 使用简称
kubectl describe website my-website
五、CRD验证规则
为了确保自定义资源的数据质量,我们可以为CRD添加验证规则。
修改website-crd.yaml,添加验证规则:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: websites.web.example.com
spec:
group: web.example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
domain:
type: string
description: 网站域名
pattern: '^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$'
image:
type: string
description: 网站使用的镜像
replicas:
type: integer
description: 网站副本数
minimum: 1
maximum: 10
port:
type: integer
description: 网站服务端口
minimum: 1
maximum: 65535
required: ["domain", "image", "replicas", "port"]
status:
type: object
properties:
availableReplicas:
type: integer
# 添加验证规则
additionalPrinterColumns:
- name: Domain
type: string
description: 网站域名
jsonPath: .spec.domain
- name: Replicas
type: integer
description: 副本数
jsonPath: .spec.replicas
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
scope: Namespaced
names:
plural: websites
singular: website
kind: Website
shortNames:
- ws
重新应用CRD:
kubectl apply -f website-crd.yaml
现在当我们查看websites资源时,会显示额外的列:
kubectl get websites
六、CRD版本管理
随着应用的发展,我们可能需要升级CRD以支持新的字段或功能。Kubernetes支持CRD的多版本管理。
1. 添加新版本
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: websites.web.example.com
spec:
group: web.example.com
versions:
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
domain:
type: string
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 10
port:
type: integer
minimum: 1
maximum: 65535
status:
type: object
properties:
availableReplicas:
type: integer
- name: v2
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
domain:
type: string
image:
type: string
replicas:
type: integer
minimum: 1
maximum: 100
port:
type: integer
minimum: 1
maximum: 65535
# 新增字段
tls:
type: object
properties:
enabled:
type: boolean
secretName:
type: string
status:
type: object
properties:
availableReplicas:
type: integer
phase:
type: string
scope: Namespaced
names:
plural: websites
singular: website
kind: Website
shortNames:
- ws
七、实际应用示例
让我们通过一个完整的示例来展示CRD的实际应用。我们将创建一个简单的控制器,用于根据Website资源自动创建Deployment和Service。
1. 创建Website资源
apiVersion: web.example.com/v1
kind: Website
metadata:
name: nginx-website
namespace: default
spec:
domain: "nginx.example.com"
image: "nginx:1.20"
replicas: 2
port: 80
2. 控制器工作原理
虽然编写完整的控制器超出了本文的范围,但一个简单的控制器需要执行以下操作:
- 监听Website资源的变化
- 根据Website的spec创建Deployment
- 根据Website的spec创建Service
- 更新Website的status字段
3. 生成的Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-website
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx-website
template:
metadata:
labels:
app: nginx-website
spec:
containers:
- name: website
image: nginx:1.20
ports:
- containerPort: 80
4. 生成的Service
apiVersion: v1
kind: Service
metadata:
name: nginx-website
namespace: default
spec:
selector:
app: nginx-website
ports:
- port: 80
targetPort: 80
type: ClusterIP
八、最佳实践
在使用CRD时,应遵循以下最佳实践:
1. 命名规范
- Group名称应该是一个有效的域名(如web.example.com)
- 资源名称应该是复数形式(如websites)
- Kind名称应该是单数形式的驼峰命名(如Website)
2. 版本管理
- 为CRD提供多个版本支持
- 使用served标记启用版本
- 使用storage标记存储版本
- 提供版本转换机制
3. 验证规则
- 使用OpenAPI v3 schema定义资源结构
- 添加必要的字段验证规则
- 设置必填字段
4. 状态管理
- 在status子资源中维护资源状态
- 提供丰富的状态信息
- 定期更新状态
5. 打印列定义
- 定义additionalPrinterColumns以改善CLI体验
- 包含关键信息的列
- 使用合适的列类型
九、故障排除
在使用CRD时,可能会遇到以下常见问题:
1. CRD创建失败
检查YAML文件语法是否正确,字段是否符合要求。
2. 自定义资源验证失败
检查自定义资源是否符合CRD定义的schema。
3. 控制器无法识别新资源
确保控制器已正确配置并具有访问CRD的权限。
十、总结
CRD是Kubernetes生态系统中一个强大的扩展机制,它允许我们定义自己的资源类型,从而更好地管理复杂的应用和服务。通过本文的学习,你应该已经掌握了:
- CRD的基本概念和应用场景
- 如何定义和创建CRD
- 如何创建自定义资源实例
- 如何添加验证规则和打印列
- 如何管理CRD版本
- CRD的最佳实践
通过合理使用CRD,我们可以将复杂的业务逻辑封装成简单的Kubernetes资源,实现基础设施即代码和声明式API的理想状态。
评论区