[第13章]使用 kubebuilder 创建 Operator
在前面的章节中,你已经看到了如何使用自定义资源定义(CRD)来定义由 API 服务器提供的新资源,以及如何使用 controller-runtime 库来构建操作器。
Kubebuilder SDK 致力于帮助你创建新的资源和相关的 Operators。它提供的命令可以启动一个定义管理器的项目,并将资源和它们相关的控制器添加到项目中。
一旦生成了新的自定义资源和控制器的源代码,你将需要根据资源的业务领域来实现缺少的部分。然后,Kubebuilder SDK 提供工具来构建和部署自定义资源定义和管理器到集群上。
安装Kubebuilder
Kubebuilder 是以一个单一的二进制文件提供的。你可以从项目的发布页面下载二进制文件,并将其安装到你的PATH中。二进制文件被提供给 Linux 和 MacOS 系统。
创建项目
第一步是创建项目。该项目最初将包含:
-
定义管理器的Go源代码(目前没有任何控制器)
-
Docker文件,用于构建包含管理器二进制文件的镜像,以部署到集群上
-
Kubernetes 清单,以帮助将管理器部署到集群中。
-
一个定义命令的Makefile,以帮助你测试、构建和部署管理器。
要创建项目,首先创建一个空目录, cd 进入这个目录,然后执行以下 kubebuilder init
命令:
$ mkdir myresource-kb
$ cd myresource-kb
$ kubebuilder init
--domain myid.dev ❶
--repo github.com/myid/myresource ❷
-
❶ 域名,作为 GVK 分组名称的后缀使用。在这个项目中定义的自定义资源可以属于不同的分组,但所有分组将属于同一个域。例如,
mygroup1.myid.dev
和mygroup2.myid.dev
-
❷ 用于生成管理器 Go 代码的 Go 模块的名称
你可以通过运行以下命令检查 Makefile 中的可用命令:
$ make help
你可以用以下命令为管理器构建二进制文件:
$ make build
然后,你可以在本地运行管理器:
$ make run
或者
$ ./bin/manager
在这一点上,启动一个源码控制项目(例如,一个git项目),并使用生成的文件创建第一个修订版是很有意思的。这样,你将能够检查接下来执行的 kubebuilder 命令所做的修改。例如,如果你使用git:
$ git init
$ git commit -am 'kubebuilder init --domain myid.dev --repo github.com/myid/myresource'
在项目中添加自定义资源
就目前而言,管理器并不管理任何控制器。即使你能构建和运行它,你也不能对它做任何事情。
下一个要执行的 kubebuilder 命令是 kubebuilder create api,以添加一个自定义资源和它相关的控制器到项目中。该命令会问你是否要创建资源和控制器。对每个问题回答Y。
$ kubebuilder create api
--group mygroup ❶
--version v1alpha1 ❷
--kind MyResource ❸
Create Resource [y/n]
y
Create Controller [y/n]
y
-
❶ 自定义资源的分组。它将以域名为后缀,形成完整的 GVK 分组。
-
❷ 该资源的版本
-
❸ 资源的种类/kind
你可以通过运行下面的 git 命令看到该命令所做的修改:
$ git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: PROJECT
modified: go.mod
modified: go.sum
modified: main.go
Untracked files:
(use "git add <file>..." to include in what will be committed)
api/
config/crd/
config/rbac/myresource_editor_role.yaml
config/rbac/myresource_viewer_role.yaml
config/samples/
controllers/
no changes added to commit (use "git add" and/or "git commit -a")
PROJECT 文件包含项目的定义。它最初包含了作为标志提供给 init 命令的域名和 repo。现在它也包含了第一个资源的定义。main.go 文件和 controllers 目录为自定义资源定义了一个控制器。
api/v1alpha1
目录已经创建,包含了使用 Go 结构体的自定义资源的定义,以及由 deepcopy-gen(见第8章 “运行deepcopy-gen” 部分)在 controller-gen 工具的帮助下生成的代码。它还包含了 AddToScheme 函数的定义,对于将这种新的自定义资源添加到 Scheme 中非常有用。
config/samples
目录包含一个新文件,定义了 YAML 格式的自定义资源的实例。config/rbac
目录包含两个新文件,定义了两个新的 ClusterRole 资源,一个用于查看,一个用于编辑 MyResource 实例。config/crd
目录包含用于构建 CRD 的 kustomize 文件。
添加RBAC注解
在本地运行 operator 时,operator 会使用您的 kubeconfig 文件,以及该 kubeconfig 的特定授权。如果您使用集群管理员账户进行连接,操作员就会拥有集群上的所有授权,并能进行任何操作。
然而,当 operator 被部署在集群上时,它是用一个特定的 Kubernetes Service Account 运行的,并被赋予有限的授权。这些授权是由 kubebuilder 构建和部署的 ClusterRole 中定义的。
为了帮助 Kubebuilder 构建这个 ClusterRole,在 Reconcile 函数的生成注释中出现了注解(为了清晰起见,加入了换行符):
//+kubebuilder:rbac:
groups=mygroup.myid.dev,
resources=myresources,
verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:
groups=mygroup.myid.dev,
resources=myresources/status,
verbs=get;update;patch
//+kubebuilder:rbac:
groups=mygroup.myid.dev,
resources=myresources/finalizers,
verbs=update
这些规则将给予对 MyResource 资源的完全访问权,但没有对其他资源的访问权。
Reconcile 函数需要在观察 deployment 资源时拥有对它的读写权限;为此,你需要添加这个新的注解(已添加换行符):
//+kubebuilder:rbac:
groups=apps,
resources=deployments,
verbs=get;list;watch;create;update;patch;delete
在群集上部署 operator
为了能够将 operator 部署到集群中,您需要构建容器镜像,并将其部署到容器镜像登记处(如DockerHub、Quay.io或其他许多地方)。
第一步是在您喜欢的容器镜像登记处创建一个新的存储库,包含 operator 容器的镜像。假设您在 quay.io/myid
中创建了一个名为 myresource 的存储库,镜像的全名将是 quay.io/myid/myresource
。
在每次构建时,你都需要为镜像使用不同的标签,这样才能正确地更新容器。要在本地构建镜像,你需要运行以下命令(注意标签 v1alpha1-1):
$ make docker-build
IMG=quay.io/myid/myresource:v1alpha1-1
要将其部署到注册表,必须执行以下命令:
$ make docker-push
IMG=quay.io/myid/myresource:v1alpha1-1
最后,将 Operator 部署到集群中:
$ make deploy
IMG=quay.io/myid/myresource:v1alpha1-1
这将创建一个新的命名空间,myresource-kb-system,其中包含一个新的 deployment,将执行 Operator。您可以用以下命令检查 Operator 的日志: