kubernetes CRD介绍及用kubebuilder编写自己的CRD及Controller |
您所在的位置:网站首页 › 什么是crd › kubernetes CRD介绍及用kubebuilder编写自己的CRD及Controller |
文章目录
1.CRDCRD简介CRD使用场景Kubebuilder
2.项目搭建2.1 背景2.2 环境准备2.3 大体流程2.4 创建项目2.4.1 初始化2.4.2 创建CRD api2.4.3 安装CRD2.4.4 部署controller方法1:本地运行 controller方法2:将 controller 部署到 Kubernetes构建docker镜像并发布到仓库中部署镜像到集群
2.4.5 创建 CR
2.5 增加业务逻辑2.5.1 修改 CRD2.5.2 修改 Reconcile 函数2.5.3 部署测试部署CRD和controller部署 CR获取当前的 CR删除 CR删除CRD
2.6 注意
错误错误提示:tcp :8080: bind: address already in use错误 no new variable on left side构建镜像错误错误1:curl: (35) Network file descriptor is not connected错误2:The command '/bin/sh -c go mod download' returned a non-zero code: 1
部署镜像到集群错误错误:/bin/sh: kustomize: 未找到命令错误:ImagePullBackOffer错误:have() want(context.Context)
参考资料
1.CRD
CRD简介
CRD官方文档 kubernetes 有两种机制供用户扩展API 第一种:CRD,复用Kubernetes的API Server,无须编写额外的APIServer。用户只需要定义CRD,并且提供一个CRD控制器,就能通过Kubernetes的API管理自定义资源对象了,同时要求用户的CRD对象符合API Server的管理规范。 该方法更易用、不需要编码。但是缺乏灵活性。第二种:使用API聚合机制 ,用户需要编写额外的API Server,可以对资源进行更细粒度的控制(例如,如何在各API版本之间切换),要求用户自行处理对多个API版本的支持。 该方法需要编码,允许通过聚合层的方式提供更加定制化的实现。CRD CRD, 全称是 Custom Resource Definition,即用户自定义资源类型。顾名思义,它指的就是,允许用户在 Kubernetes 中添加一个跟 Pod、Node 类似的、新的 API 资源类型,即:自定义 API 资源。在 Kubernetes 中一切都可视为资源,Kubernetes在1.7版本后增加了CRD,使得开发人员可以不修改Kubernetes的原有代码,而是通过扩展形式,来管理自定义资源对象,该功能大大提高了 Kubernetes 的扩展能力。Custom resources 是对K8S API的扩展,代表了一个特定的kubetnetes的定制化安装。在一个运行中的集群中,自定义资源可以动态注册到集群中。注册完毕以后,用户可以通过kubelet创建和访问这个自定义的对象,类似于操作pod一样。Custom controllers 自定义控制器 Custom resources可以让用户简单的存储和获取结构化数据。只有结合控制器才能变成一个真正的declarative API(被声明过的API)。控制器可以把资源更新成用户想要的状态,并且通过一系列操作维护和变更状态。定制化控制器是用户可以在运行中的集群内部署和更新的一个控制器,它独立于集群本身的生命周期。 定制化控制器可以和任何一种资源一起工作,当和定制化资源结合使用时尤其有效。Operator模式 是一个customer controllers和Custom resources结合的例子。它可以允许开发者将特殊应用编码至kubernetes的扩展API内。通俗理解:CR即创建一个自定义资源,CRD是对资源的描述,CC是提供CRD对象的管理。 CRD本身只是一段声明,用于定义用户自定义的资源对象。但仅有CRD的定义并没有实际作用,用户还需要提供管理CRD对象的CRD控制器(CRD Controller),才能实现对CRD对象的管理。CRD控制器通常可以通过Go语言进行开发,并需要遵循Kubernetes的控制器开发规范,基于客户端库client-go进行开发,需要实现Informer、ResourceEventHandler、Workqueue等组件具体的功能处理逻辑。 CRD使用场景crd在很多k8s周边开源项目中有使用,比如ingress-controller 、istio 、hpa和众多的operator。 KubebuilderKubebuilder Kubebuilder 是一个基于 CRD 来构建 Kubernetes API 的框架,可以使用 CRD 来构建 API、Controller 和 Admission Webhook。 2.项目搭建 2.1 背景从零开始写一个 CRD 及其Controller ,它的开发方式经历过不同的阶段,从最早的参考 K8S 官方的控制器代码并手动复制,到用 client-gen 生成框架代码,到现在使用 kubebuilder ,已经非常方便我们完成 CRD/Controller,甚至 Operator 的开发(当然 Operator 的开发也有专用的 operator-sdk开源框架)。 2.2 环境准备Centos中安装golang、kubebuilder、kustomize环境 kubernetes集群部署 golang 1.15.5 kubebuilder 2.3.1 (推荐使用二进制方式安装) kustomize kubernetes集群 1.20.1 go中推荐打开 export GO111MODULE=on 以强制启用 Go module,它是目前最新的 Golang 包依赖管理工具,也是官方推荐,govender,godep 等工具已经不建议继续使用执行 go env -w GOPROXY=goproxy.cn,direct 开启代理,配置默认从 goproxy.cn 拉去 Go Module 的依赖包,如果不存在走默认的方式,goproxy.cn 是七牛云维护的一个 golang 包代理库,测试下来性能是最好的,可以拉取很多被墙掉的包 go version #查看go的版本 kubebuilder version kubectl get nodes # 查看k8s集群的版本 2.3 大体流程 go mod init my.domain ## 这两个复杂的命令可以通过kubebuilder --help查看 # 初始化 kubebuilder init --domain example.com --license apache2 --owner "The Kubernetes authors" # 创建CRD api kubebuilder create api --group webapp --version v1 --kind Frigate # 安装CRD make install # 启动controller(本地) make run 2.4 创建项目我们首先将使用自动配置创建一个项目,该项目在创建 CR 时不会触发任何资源生成。 2.4.1 初始化创建的项目路径位于 $GOPATH/kubebuilder-example。 go mod init:初始化go mod, 生成go.mod文件,后可接参数指定 module 名 ![]() 在项目路径下使用下面的命令初始化项目。 kubebuilder init --domain example.com --license apache2 --owner "The Kubernetes authors"
注意:此处如果出现端口被占用的情况,参考文末
执行上面的命令之后,KubeBuilder 就帮我们创建了两个文件 api/v1/frigate_types.go和controllers/frigate_controller.go, 前者是这个 CRD 需要定义哪些属性,而后者是对 CRD 的 Reconcile 的处理逻辑(也就是增删改 CRD 的逻辑), 我们后面再讲这两个文件。 我们看一下这两个文件的树状结构 先来 make install 一下, 将其安装到 K8S cluster 中 make install kubectl get crd
有两种方式运行 controller: 本地运行,用于调试部署到 Kubernetes 上运行,作为生产使用 方法1:本地运行 controller要想在本地运行 controller,需要执行: make run按照其他相关博客 提示: 请修改DockerFile中: a. 将FROM golang:1.12.5 as builder 替换成 FROM golang:1.13 as builder b. 在COPY go.sum 下加上ENV GOPROXY=https://goproxy.cn,direct c. 将FROM gcr.io/distroless/static:nonroot 替换成 FROM golang:1.13 d. 删除USER nonroot:nonroot 修改了相关部分:如下
注意:这个仓库是自己在阿里云建的仓库,可以使用自己的仓库名 对于中国大陆用户,可能无法访问 Google 镜像仓库 gcr.io,因此需要修改 config/default/manager_auth_proxy_patch.yaml 文件中的镜像地址: vim config/default/manager_auth_proxy_patch.yaml 替换成: image: registry.cn-hangzhou.aliyuncs.com/kubenode/kube-rbac-proxy:v0.4.0 make deploy IMG=registry.cn-beijing.aliyuncs.com/anan_java/go_project_01:v1.0
注意:此处如果出现问题,参考文末 2.4.5 创建 CRKubebuilder 在初始化项目的时候已生成了示例 CR。 可以在源码目录下看到config文件下有个sample文件夹,里面有例子:
执行下面的命令查看新创建的 CR kubectl get frigate.webapp.example.com frigate-sample -o yaml
下面我们将修改 CRD 的数据结构并在 controller 中增加一些日志输出。 2.5.1 修改 CRD我们将修改上文中使用 kubebuilder 命令生成的默认 CRD 配置,在 CRD 中增加 FirstName、LastName 和 Status 字段。 修改 api/v1/frigate_types.go FirstName string `json:"firstname"` LastName string `json:"lastname"` Status string `json:"Status"`修改 controllers/frigate_controller.go # 添加log包 # 添加如下代码 _ = r.Log.WithValues("apiexamplea", req.NamespacedName) // 获取当前的 CR,并打印 obj := &webappv1.Frigate{} if err := r.Get(ctx, req.NamespacedName, obj); err != nil { log.Println(err, "Unable to fetch object") } else { log.Println("Geeting from Kubebuilder to", obj.Spec.FirstName, obj.Spec.LastName) } // 初始化 CR 的 Status 为 Running obj.Status.Status = "Running" if err := r.Status().Update(ctx, obj); err != nil { log.Println(err, "unable to update status") }![]() 这段代码的业务逻辑是当发现有 CR 变更时,在控制台中输出日志。 2.5.3 部署测试修改好 业务逻辑后,再测试一下新的逻辑是否可以正常运行 部署CRD和controller make install # 部署CRD make run # 本地运行controller 也可以将其部署到 Kubernetes 上运行
修改 config/samples/webapp_v1_frigate.yaml 文件中的配置。 ![]() 将其应用到 Kubernetes。 kubectl apply -f config/samples/webapp_v1_frigate.yaml此时转到上文中运行 controller 的窗口,将在命令行前台中看到如下输出。 ![]() 这正是我们在 CRD 里定义的字段。 删除 CR使用下面的命令删除 CR。 kubectl delete frigate.webapp.example.com frigate-sample
注意: 创建项目时,部署controller的两种方法都可以正常完成相关步骤增加业务逻辑时,如果通过将controller部署到集群中实现,没有前台的界面,所以看不到前台的输出,而且,最后没有Status:running,不知道这样正不正常。unable to start manager {“error”: “error listening on :8080: listen tcp :8080: bind: address already in use”} 解决方法: 找到占用8080端口的进程,kill掉即可 netstat -tnlp | grep 80 kill -9 进程号
注意:如果make run时出现如下错误,说明改行变量声明有问题,将 ctx :=... 删掉即可 curl: (35) Network file descriptor is not connected make: *** [test] 错误 35 可是自己通过源码安装,没有二进制文件 go: github.com/go-logr/[email protected]: Get https://proxy.golang.org/github.com/go-logr/logr/@v/v0.1.0.mod: dial tcp 172.217.160.113:443: connect: connection refused The command ‘/bin/sh -c go mod download’ returned a non-zero code: 1 make: *** [docker-build] 错误 1
请修改DockerFile中: a. 将FROM golang:1.12.5 as builder 替换成 FROM golang:1.13 as builder b. 在COPY go.sum 下加上ENV GOPROXY=https://goproxy.cn,direct c. 将FROM gcr.io/distroless/static:nonroot 替换成 FROM golang:1.13 d. 删除USER nonroot:nonroot 修改了相关部分:如下
然后删除系统创建的资源,重新构建镜像并发布,从make docker build那部分开始 注意:第一次从这个部分开始出现了错误,删除CRD重头开始了 第二次从这个部分开始就正确了 # 自己删除了 镜像,命名空间,还有仓库里的镜像 docker rmi 镜像号 kubectl delete ns 命名空间 手动删除仓库里的镜像 错误:have() want(context.Context)构建镜像时出现:
CRD介绍: Kubernetes中CRD的介绍和使用 kubernetes1.9管中窥豹-CRD概念、使用场景及实例 Kuberneters(K8s)CRD资源详解 kubernetes CRD CRD及Controller创建: K8S中编写自己的CRD及Controller简明指南 主参考 Kind: Frigate 使用 kubebuilder 创建 operator 示例 主参考 --kind Guestbook kubernetes CRD开发指南 --kind VirtulMachine 云计算虚拟化:k8s进阶-CRD项目部署 Kubebuilder: Kubernetes CRD 开发实践 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |