前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >云原生|什么是K8s里的CRD(Custom Resource Definitions)?

云原生|什么是K8s里的CRD(Custom Resource Definitions)?

作者头像
琉璃康康
发布2024-01-22 15:07:13
6820
发布2024-01-22 15:07:13
举报
文章被收录于专栏:七禾页话七禾页话

@七禾页话

学习永无止境,记录相伴相随! —— 琉璃康康

最近给同事排错的时候,又遇到了CRD丢失导致微服务无法创建的问题。

那么什么是CRD?CRD到底是做什么的呢?

Kubernetes 自定义资源定义(Custom Resource Definition,简称 CRD)是一种强大的 Kubernetes API 扩展机制。它允许用户创建和管理自定义资源,这些资源不是 Kubernetes 标准 API 的一部分。CRD 使得 Kubernetes 不仅限于内建资源(如 Pod、Service 等),还可以支持用户定义的资源类型。

CRD 的核心思想是通过声明式的 API 来扩展 Kubernetes 的功能。你可以定义自己的资源结构,然后像操作 Kubernetes 内建资源一样操作这些自定义资源。

什么是Kubernetes内建资源呢?

一个Kubernetes集群建立后,为什么我们就可以创建POD、Config、Secret等资源呢?

这是因为集群建立起来后默认允许我们创建这些资源,这就是Kubernetes内建的可用API资源,可以通过命令kubectl api-resources查看,但是每个Kubernetes的版本由于默认安装的微服务不一样会导致其内建API资源会不一样,如下是一个例子,通过grep剔除掉crd创建的API资源,剩下的就是cluster内建的:

代码语言:javascript
复制
####左右滑动
crds=$(for i in `kubectl get crd --no-headers | awk -F"." '{print $1}'`;do echo -n "$i|";done | sed 's/|$//g')
kubectl api-resources | grep -vE ${crds}

@七禾页话

为什么需要CRD呢?

Kubernetes项目组并不知道不同公司业务都需要哪些API资源,所以Kubernetes发行版只包含项目开发的API资源,比如POD、ConfigMap等,但是对于不同公司,这些基础的内置API资源并不能满足业务需求,而且有些资源是所有业务共用的,就可以把这个共用的资源在自己的集群中统一定义,从而成为此集群的一种API被调用,这就是CRD——Custom Resource Definition。

具体来说,Custom Resource是 Kubernetes 开放了API的定义规则,是对 Kubernetes 内置API的扩展。现在,很多 Kubernetes 核心功能也都用Custom Resource来实现了,这使得 Kubernetes 更加模块化。

Custom Resource可以通过动态注册的方式在运行中的集群内或出现(create)或消失(delete),集群管理员可以独立于集群更新Custom Resource。一旦某Custom Resource被安装,用户可以使用 kubectl 来创建和访问其中的对象。

CRD可以通过kubectl get customresourcedefinitions.apiextensions.k8s.io或者缩写的kubectl get crd来查看:

如何查看CRD定义的API资源?

CRD的资源虽然是各个公司、或者不同的项目自己定制的,但是创建后也是作为 Kubernetes 资源而存在,所以可以通过kubectl api-resources查看,如下是一个例子,通过grep过滤由CRD定制的API资源,这些资源都是通过后期创建的:

代码语言:javascript
复制
####左右滑动
crds=$(for i in `kubectl get crd --no-headers | awk -F"." '{print $1}'`;do echo -n "$i|";done | sed 's/|$//g')
kubectl api-resources | grep -E ${crds}

@七禾页话

如何定义和使用CRD定义的API资源

Kubernetes里的所有东西都是通过创建实现的,CRD也不例外。我们也可以手动的apply一个CRD的yaml从而定义自己需要的API资源,编写 CRD YAML 的步骤包括定义 API 版本、Kind、以及资源的 schema。以下是一个简单的 CRD 示例,定义了一个名为 CronTab 的资源:

代码语言:javascript
复制
####左右滑动
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.stable.example.com
spec:
  group: stable.example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames:
      - ct

@七禾页话

在这个例子中,我们定义了一个新的资源类型 CronTab,它有三个字段:cronSpecimagereplicas

CRD创建后,就可以像操作 Kubernetes 内建资源一样操作自定义资源。比如,我们再创建一个 CronTab 实例,YAML如下所示:

代码语言:javascript
复制
####左右滑动
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-crontab
spec:
  cronSpec: "*/5 * * * *"
  image: my-cron-image
  replicas: 1

@七禾页话

再举个例子,MetalLB作为一种负载均衡器,其也有很多自己的Customer Resource,从官网拿到的MetalLB的yaml里有很多的CRD定义,当我们创建了MetaLLB的微服务后,可以看到MetalLB的定义资源也同步创建好,并且可以在api-resources列表里看到:

代码语言:javascript
复制
####左右滑动
kubectl get crd | grep -i metallb
kubectl api-resources | grep -i metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml
kubectl get crd | grep -i metallb
kubectl api-resources | grep -i metallb

@七禾页话

当定义的资源出现在了api-resources里,表明此资源可以在当前集群中使用了。

我们一般定义MetalLB的IP资源池是直接写到ConfigMap里,但是我们通过CRD可以看到有一个独立的API资源叫做ipaddresspools,因此我们可以直接通过ipaddresspools的API资源创建MetalLB的IP Pool实例:

代码语言:javascript
复制
####左右滑动
cat <<EOF | kubectl create -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.10.0/24
  - 192.168.9.1-192.168.9.5
  - fc00:f853:0ccd:e799::/124
EOF

@七禾页话

CRD创建的API资源会消失吗?

CRD创建的API资源会消失吗?答案是肯定会的。

可以看到我们查看CRD的命令是get,创建可以是create,那么对应的delete就可以删除CRD了,CRD删除后,对应的api-resources和相关的实例也就消失了,如果CRD通过helm等方式安装的,一旦helm里的instance被uninstall,其对应的CRD资源也会消失:

@七禾页话

这便是同事遇到的问题,其实提示很明显,一旦get或者创建中提示什么什么version没有,基本就是CRD定义的API资源没有了,比如下图:

@七禾页话

如何解决呢?必须要通过重新创建CRD将对应的API资源复原,CRD是通过yaml创建的,所以我们只要能写出来CRD的yaml,就可以复原其API资源,这个时候可以在其他集群中查看是否有我们需要的CRD,然后通过kubectl get crd <crd name> -o yaml打印后,删除会导致冲突的信息,比如创建时间、uuid、status等,剩下的就是CRD的yaml信息,另外把握住CRD的一些主要内容,如API 版本、Kind、以及资源的 schema 即可:

有了CRD的yaml后通过kubectl apply -f <crd yaml file>或者kubectl create -f <crd yaml file>使其生效即可。

后记

值得注意的是,CRD是集群级别的,跟内置API资源一样,不会被namespace隔离,一种CRD只需要在一个集群中创建一次,同名的CRD会被新版本的创建所覆盖,从而集群中保留的永远都是最新版的CRD,也就是最新版本的API资源类型。

因此在使用的时候需要特别注意CRD的问题,当多个微服务共用一个集群的时候,CRD是只需要安装最新版本的即可,因此每一个运维人员在安装CRD前都应该要先查看自己需要的CRD是否已经被安装,版本是否低于自己的需求:如果版本低,可以安装新的的CRD;如果集群里的CRD已经是自己需要的版本或者更高,那么不要再进行CRD的安装,否则会降低CRD的版本导致其他调用此CRD资源的微服务出问题。

CRD 作为 Kubernetes API的扩展机制,已经是 Kubernetes 集群中不可或缺的组成部分,为 Kubernetes 的扩展性和灵活性提供了基础。通过定义自己的资源类型,开发者可以创建完全定制的、高度适应特定需求的 Kubernetes 应用。不管是简单的配置管理,还是复杂的运维自动化,CRD 都为 Kubernetes 用户打开了一扇新的大门。

以上,欢迎留言来一起了解学习ICT的相关知识!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 七禾页话 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Kubernetes内建资源呢?
  • 为什么需要CRD呢?
  • 如何查看CRD定义的API资源?
  • 如何定义和使用CRD定义的API资源
  • CRD创建的API资源会消失吗?
  • 后记
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档