kubebuilder 实战演练之deploy-image插件的使用
案例需求
我们期望开发一个Operator,能够实现如下效果:
- 定义一个名为 Memcached 的 CR
- 编写Controller具有调谐 Memcached 的能力
- Memcached Spec中有一个Size,Controller 将不允许创建的Memcached实例 超过Size
- Controller 还要负责更新资源的 Status
- 编写Controller具有调谐 Memcached 的能力
开发项目
创建一个项目Project
1
2
3
4
5
6
7
8
9
10
11[root@master memcached-operator]# mkdir $GOPATH/memcached-operator
[root@master memcached-operator]# cd $GOPATH/memcached-operator
[root@master memcached-operator]# kubebuilder init --domain=graham924.com --repo=graham924.com/memcached-operator
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.17.0
INFO Update dependencies:
$ go mod tidy
Next: define a resource with:
$ kubebuilder create api创建一个API
这里 kubebuilder create api时,使用 deploy-image等 参数,直接就完成了全部代码的生成
deploy-image插件
- 这里我们在使用 kubebuilder create api 时,将使用 deploy-image 的 plugin,帮我们自动生成一些代码。完整命令如下:参数解释:
1
kubebuilder create api --group cache --version v1alpha1 --kind Memcached --image=memcached:1.4.36-alpine --image-container-command="memcached,-m=64,-o,modern,-v" --image-container-port="11211" --run-as-user="1001" --plugins="deploy-image/v1-alpha" --make=false
- kubebuilder create api:这是 Kubebuilder 工具的命令,用于创建一个新的 API 资源。
- –group cache:指定新创建的 API 资源所属的 API 组,这里指定为 “cache”。
- –version v1alpha1:指定新创建的 API 资源的版本号,这里指定为 “v1alpha1”。
- –kind Memcached:指定新创建的资源的种类(Kind),这里指定为 “Memcached”,即自定义资源的类型为 Memcached。
- –image=memcached:1.4.36-alpine:指定用于部署的镜像名称及版本,这里指定为 “memcached:1.4.36-alpine”。
- –image-container-command=”memcached,-m=64,-o,modern,-v”:指定容器的启动命令,这里设置为在容器中运行 memcached 服务,并指定了一些参数如内存限制、存储模式等。
- –image-container-port=”11211”:指定容器监听的端口号,这里指定为 “11211”,通常是 memcached 服务的默认端口。
- –run-as-user=”1001”:指定容器运行时的用户 ID,这里指定为 “1001”。
- –plugins=”deploy-image/v1-alpha”:指定要使用的插件,这里指定为部署镜像的插件 “deploy-image/v1-alpha”,用于将镜像部署到目标环境中。
- –make=false:表示不立即构建二进制文件。当设置为 false 时,Kubebuilder 不会自动为你构建 Go 二进制文件,而是生成代码结构以供你自己构建。
kubebuilder create api 时,使用 deploy-image plugin,会帮我们额外生成什么? - controllers/*_controller.go (脚手架controller的reconcile调谐逻辑框架)
- controllers/*_controller_test.go (scaffold the tests for the controller)
- controllers/*_suite_test.go (scaffold/update the suite of tests)
- api//*_types.go (scaffold the specs for the new api)
- config/samples/*_.yaml (scaffold default values for its CR)
- main.go (update to add controller setup)
- config/manager/manager.yaml (update with envvar to store the image)
创建API实践演示
创建API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25[root@master memcached-operator]# kubebuilder create api --group cache --version v1alpha1 --kind Memcached --image=memcached:1.4.36-alpine --image-container-command="memcached,-m=64,-o,modern,-v" --image-container-port="11211" --run-as-user="1001" --plugins="deploy-image/v1-alpha" --make=false
INFO updating scaffold with deploy-image/v1alpha1 plugin...
INFO Writing scaffold for you to edit...
INFO Writing scaffold for you to edit...
INFO api/v1alpha1/memcached_types.go
INFO api/v1alpha1/groupversion_info.go
INFO internal/controller/suite_test.go
INFO internal/controller/memcached_controller.go
INFO internal/controller/memcached_controller_test.go
INFO Writing kustomize manifests for you to edit...
INFO api/v1alpha1/memcached_types.go
INFO config/samples/cache_v1alpha1_memcached.yaml
INFO internal/controller/memcached_controller.go
INFO creating import for % graham924.com/memcached-operator/api/v1alpha1
INFO internal/controller/memcached_controller_test.go
INFO creating import for % graham924.com/memcached-operator/api/v1alpha1
INFO Update dependencies:
$ go mod tidy
INFO Running make:
$ make manifests
mkdir -p /root/zgy/project/share-code-operator-study/memcached-operator/bin
Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0
/root/zgy/project/share-code-operator-study/memcached-operator/bin/controller-gen-v0.14.0 rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
Next: check the implementation of your new API and controller. If you do changes in the API run the manifests with:
$ make manifests生成后的目录如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63[root@master memcached-operator]# tree
.
├── api
│ └── v1alpha1
│ ├── groupversion_info.go
│ └── memcached_types.go
├── bin
│ └── controller-gen-v0.14.0
├── cmd
│ └── main.go
├── config
│ ├── crd
│ │ ├── bases
│ │ │ └── cache.graham924.com_memcacheds.yaml
│ │ ├── kustomization.yaml
│ │ └── kustomizeconfig.yaml
│ ├── default
│ │ ├── kustomization.yaml
│ │ ├── manager_auth_proxy_patch.yaml
│ │ └── manager_config_patch.yaml
│ ├── manager
│ │ ├── kustomization.yaml
│ │ └── manager.yaml
│ ├── prometheus
│ │ ├── kustomization.yaml
│ │ └── monitor.yaml
│ ├── rbac
│ │ ├── auth_proxy_client_clusterrole.yaml
│ │ ├── auth_proxy_role_binding.yaml
│ │ ├── auth_proxy_role.yaml
│ │ ├── auth_proxy_service.yaml
│ │ ├── kustomization.yaml
│ │ ├── leader_election_role_binding.yaml
│ │ ├── leader_election_role.yaml
│ │ ├── memcached_editor_role.yaml
│ │ ├── memcached_viewer_role.yaml
│ │ ├── role_binding.yaml
│ │ ├── role.yaml
│ │ └── service_account.yaml
│ └── samples
│ ├── cache_v1alpha1_memcached.yaml
│ └── kustomization.yaml
├── Dockerfile
├── go.mod
├── go.sum
├── hack
│ └── boilerplate.go.txt
├── internal
│ └── controller
│ ├── memcached_controller.go
│ ├── memcached_controller_test.go
│ └── suite_test.go
├── Makefile
├── PROJECT
├── README.md
└── test
├── e2e
│ ├── e2e_suite_test.go
│ └── e2e_test.go
└── utils
└── utils.go
18 directories, 41 files
查看CR的 types.go
因为我们使用了 deploy-image 插件,所以 api/v1alpha1/memcached_types.go 的 Spec、Status 中,会默认生成几个字段
- Spec 字段
- Size:使用 +kubebuilder:validation 标记 设置Size的值在1~3之间。
- ContainerPort:容器Port
- Status 字段
- Conditions:描述资源的状态信息kubebuilder的官方文档中,给出了各种用于配置/代码生成的标记:https://book.kubebuilder.io/reference/markers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32......
// MemcachedSpec defines the desired state of Memcached
type MemcachedSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Size defines the number of Memcached instances
// The following markers will use OpenAPI v3 schema to validate the value
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=3
// +kubebuilder:validation:ExclusiveMaximum=false
Size int32 `json:"size,omitempty"`
// Port defines the port that will be used to init the container with the image
ContainerPort int32 `json:"containerPort,omitempty"`
}
// MemcachedStatus defines the observed state of Memcached
type MemcachedStatus struct {
// Represents the observations of a Memcached's current state.
// Memcached.status.conditions.type are: "Available", "Progressing", and "Degraded"
// Memcached.status.conditions.status are one of True, False, Unknown.
// Memcached.status.conditions.reason the value should be a CamelCase string and producers of specific
// condition types may define expected values and meanings for this field, and whether the values
// are considered a guaranteed API.
// Memcached.status.conditions.Message is a human readable message indicating details about the transition.
// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
}
......
- Conditions:描述资源的状态信息
查看CR的资源定义文件CRD
1 | config/crd/bases/cache.example.com_memcacheds.yaml 文件 |
可以看出,+kubebuilder 标记的内容,会展示在CRD的定义文件中的,下面以Spec的内容为例,Status的内容也是一样的
1 | spec: |
查看CR yaml示例
- config/crd/bases/cache.example.com_memcacheds.yaml 文件
1
2
3
4
5
6
7
8
9
10
11apiVersion: cache.graham924.com/v1alpha1
kind: Memcached
metadata:
name: memcached-sample
spec:
# TODO(user): edit the following value to ensure the number
# of Pods/Instances your Operand must have on cluster
size: 1
# TODO(user): edit the following value to ensure the container has the right port to be initialized
containerPort: 11211
查看CR的 controller.go
因为我们使用了 deploy-image 插件,所以 internal/controller/memcached_controller.go 的 Reconcile 已经给生成了很多代码逻辑
1 | /* |
controller.go 中 SetupWithManager 方法
- SetupWithManager 方法中,已经为我们的CR创建ListWatch机制了
1
2
3
4
5
6
7
8
9// SetupWithManager sets up the controller with the Manager.
// Note that the Deployment will be also watched in order to ensure its
// desirable state on the cluster
func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&cachev1alpha1.Memcached{}).
Owns(&appsv1.Deployment{}).
Complete(r)
}
Manager 是controller-runtime提供的组件,用于监督和管理 Controller。SetupWithManager 方法就是将 当前Controller注册到 Manager 中
controller.go 中 设置deployment 的 ownerRef
- deploymentForMemcached 中,创建的deployment,ownerRef 已经给设置成了相应的Memcached资源
1
2
3
4
5
6
7
8
9
10
11
12
13// deploymentForMemcached returns a Memcached Deployment object
func (r *MemcachedReconciler) deploymentForMemcached(
memcached *cachev1alpha1.Memcached) (*appsv1.Deployment, error) {
ls := labelsForMemcached(memcached.Name)
replicas := memcached.Spec.Size
......
if err := ctrl.SetControllerReference(memcached, dep, r.Scheme); err != nil {
return nil, err
}
return dep, nil
}
controller.go 中 rbac 的 kubebuilder 标记
- Reconcile 方法上方,使用 rbac 的 kubebuilder 标记,标记了当前Operator的访问权限
- 当你修改 controller.go 里的rbac标记后,需要执行 make manifests 或 make generate 更新 config/rbac 目录下的rbac权限文件
1
2
3
4
5
6//+kubebuilder:rbac:groups=cache.graham924.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=cache.graham924.com,resources=memcacheds/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=cache.graham924.com,resources=memcacheds/finalizers,verbs=update
//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch
CRD 及 Controller 部署
安装CRD
1 | [root@master memcached-operator]# make install |
打包Controller并上传镜像
- cd 到 memcached-operator 的所在目录,修改 Dockerfile 文件,加上这么两句
1
2
3
4
5
6
7
8
9
10# Build the manager binary
FROM golang:1.21 AS builder
ARG TARGETOS
ARG TARGETARCH
# 就是加上这两句,设置一下go的国内代理加速
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.cn
...... - 然后 修改Makefile 文件,在docker-build命令中,添加 –network host ,这是让我们的机器使用主机网络,能够连接外网执行打包上传命令
1
2
3
4
5
6# If you wish to build the manager image targeting other platforms you can use the --platform flag.
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
.PHONY: docker-build
docker-build: ## Build docker image with the manager.
$(CONTAINER_TOOL) build --network host -t ${IMG} .1
make docker-build docker-push IMG=gesang321/memcached-operator:v1alpha1
部署Controller
- 部署Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[root@master memcached-operator]# make deploy IMG=gesang321/memcached-operator:v1alpha1
/root/zgy/project/share-code-operator-study/memcached-operator/bin/controller-gen-v0.14.0 rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
cd config/manager && /root/zgy/project/share-code-operator-study/memcached-operator/bin/kustomize-v5.3.0 edit set image controller=gesang321/memcached-operator:v1alpha1
/root/zgy/project/share-code-operator-study/memcached-operator/bin/kustomize-v5.3.0 build config/default | kubectl apply -f -
namespace/memcached-operator-system created
customresourcedefinition.apiextensions.k8s.io/memcacheds.cache.graham924.com created
serviceaccount/memcached-operator-controller-manager created
role.rbac.authorization.k8s.io/memcached-operator-leader-election-role created
clusterrole.rbac.authorization.k8s.io/memcached-operator-manager-role created
clusterrole.rbac.authorization.k8s.io/memcached-operator-metrics-reader created
clusterrole.rbac.authorization.k8s.io/memcached-operator-proxy-role created
rolebinding.rbac.authorization.k8s.io/memcached-operator-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/memcached-operator-manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/memcached-operator-proxy-rolebinding created
service/memcached-operator-controller-manager-metrics-service created
deployment.apps/memcached-operator-controller-manager created - 查看部署结果
1
2
3
4
5
6
7[root@master memcached-operator]# kubectl get deploy -n memcached-operator-system
NAME READY UP-TO-DATE AVAILABLE AGE
memcached-operator-controller-manager 1/1 1 1 37m
[root@master memcached-operator]# kubectl get pods -n memcached-operator-system
NAME READY STATUS RESTARTS AGE
memcached-operator-controller-manager-6fd6c7699b-42rg4 2/2 Running 0 38m
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Macolm's Blog!