发现并使用自定义资源

KubernetesBeginner
立即练习

介绍

Kubernetes 可以通过新的资源类型进行扩展。自定义资源定义(CustomResourceDefinition,简称 CRD)用于向 Kubernetes API 服务器注册新的 API 资源。注册完成后,你就可以使用熟悉的 kubectl 命令来创建、获取、描述、标记和修补(patch)这些新类型的对象。

在本实验中,你将创建一个名为 AppProfile 的小型命名空间级 CRD,通过 Kubernetes API 发现命令来识别它,从 YAML 文件创建自定义资源,并像操作常规 Kubernetes 对象一样更新它们。本实验不需要控制器;重点在于理解自定义资源类型是如何呈现的,以及如何操作这些对象。

准备自定义资源命名空间

在此步骤中,你将准备一个干净的命名空间,用于自定义资源的练习。

从 /home/labex/project 开始。你将在该目录下编写 CRD 和自定义资源清单。

mkdir -p /home/labex/project
cd /home/labex/project

检查 Kubernetes API 服务器是否可访问。如果虚拟机刚启动且节点尚未就绪,请等待几秒钟后再运行该命令。

kubectl get nodes --request-timeout=5s

预期输出包括:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

在创建应用程序对象之前,请等待集群网络 Pod 处于就绪(Ready)状态。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

预期输出:

pod/calico-node-... condition met

创建一个名为 ckad-prep-customresources 的命名空间:

kubectl create namespace ckad-prep-customresources

将此命名空间设置为当前上下文的命名空间:

kubectl config set-context --current --namespace=ckad-prep-customresources

确认当前命名空间:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

预期输出:

ckad-prep-customresources

使用 CRD 注册新的资源类型

在此步骤中,你将创建一个名为 AppProfile 的自定义资源定义(CRD)。

CRD 有两个重要的命名层级。metadata.name 是复数资源名称加上 API 组,例如 appprofiles.training.labex.io。spec.names 部分定义了用户如何引用该资源:kind: AppProfile、plural: appprofiles、singular: appprofile 以及简写名称 appprof。

创建 app-profile-crd.yaml:

cat > app-profile-crd.yaml <<'EOF'
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: appprofiles.training.labex.io
spec:
  group: training.labex.io
  scope: Namespaced
  names:
    plural: appprofiles
    singular: appprofile
    kind: AppProfile
    shortNames:
    - appprof
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            required:
            - image
            - replicas
            properties:
              image:
                type: string
              replicas:
                type: integer
                minimum: 1
              tier:
                type: string
EOF

应用 CRD:

kubectl apply -f app-profile-crd.yaml

预期输出:

customresourcedefinition.apiextensions.k8s.io/appprofiles.training.labex.io created

等待 API 服务器报告 CRD 已建立(Established):

kubectl wait --for=condition=Established crd/appprofiles.training.labex.io --timeout=120s

预期输出:

customresourcedefinition.apiextensions.k8s.io/appprofiles.training.labex.io condition met

检查 CRD 的名称和作用域:

kubectl get crd appprofiles.training.labex.io -o 'jsonpath={.spec.names.kind}{" "}{.spec.names.plural}{" "}{.spec.scope}{"\n"}'

预期输出:

AppProfile appprofiles Namespaced

发现并创建自定义资源

在此步骤中,你将发现新的资源类型并创建你的第一个 AppProfile。

kubectl api-resources 会列出 API 服务器已知的资源类型。CRD 建立后,它会出现在此发现输出中,与内置资源类型并列。

kubectl api-resources --api-group=training.labex.io

预期输出包括:

NAME          SHORTNAMES   APIVERSION              NAMESPACED   KIND
appprofiles   appprof      training.labex.io/v1    true         AppProfile

使用 kubectl explain 读取 Kubernetes 从 CRD 中学习到的模式。spec 字段是存放应用程序特定设置的地方。

kubectl explain appprofile.spec

预期输出包括:

GROUP:      training.labex.io
KIND:       AppProfile
VERSION:    v1

FIELD: spec <Object>

创建 frontend-profile.yaml:

cat > frontend-profile.yaml <<'EOF'
apiVersion: training.labex.io/v1
kind: AppProfile
metadata:
  name: frontend
  labels:
    app.kubernetes.io/part-of: storefront
    tier: web
spec:
  image: nginx:1.27
  replicas: 2
  tier: web
EOF

应用自定义资源:

kubectl apply -f frontend-profile.yaml

预期输出:

appprofile.training.labex.io/frontend created

使用复数名称列出自定义资源:

kubectl get appprofiles

预期输出包括:

NAME       AGE
frontend   ...

使用 jsonpath 读取自定义资源中的字段:

kubectl get appprofile frontend -o 'jsonpath={.spec.image}{" "}{.spec.replicas}{" "}{.spec.tier}{"\n"}'

预期输出:

nginx:1.27 2 web

更新并筛选自定义资源

在此步骤中,你将使用与内置对象相同的 kubectl 模式来管理自定义资源。

修补(Patch)frontend 自定义资源以更改其所需的副本数。--type=merge 选项告诉 Kubernetes 将你的 JSON 对象合并到现有对象中,而不是替换整个资源。

kubectl patch appprofile frontend --type=merge -p '{"spec":{"replicas":3}}'

预期输出:

appprofile.training.labex.io/frontend patched

确认更新后的值:

kubectl get appprofile frontend -o 'jsonpath={.spec.replicas}{"\n"}'

预期输出:

3

创建第二个名为 worker 的自定义资源:

cat > worker-profile.yaml <<'EOF'
apiVersion: training.labex.io/v1
kind: AppProfile
metadata:
  name: worker
  labels:
    app.kubernetes.io/part-of: storefront
    tier: worker
spec:
  image: busybox:1.36
  replicas: 1
  tier: worker
EOF
kubectl apply -f worker-profile.yaml

预期输出:

appprofile.training.labex.io/worker created

仅列出属于 storefront 应用程序的自定义资源。由于自定义资源支持标准的 Kubernetes 标签,因此该操作有效。

kubectl get appprofiles -l app.kubernetes.io/part-of=storefront

预期输出包括:

NAME       AGE
frontend   ...
worker     ...

使用简写名称 appprof 打印每个资源的名称和副本数:

kubectl get appprof -o 'jsonpath={range .items[*]}{.metadata.name}{"="}{.spec.replicas}{"\n"}{end}'

预期输出包括:

frontend=3
worker=1

总结

你创建了一个 CRD,等待其建立,通过 kubectl api-resources 和 kubectl explain 发现了新的 API 资源,创建了自定义资源,修补了自定义资源,按标签进行了筛选,并使用了简写名称。这些操作技能与你在 CKAD 任务中处理由 Operator、控制器或平台扩展安装的资源时所使用的技能完全一致。