每期一个小窍门: 使用kubebuilder 生成operator脚手架 并操作控制自定义CRD副本数 (下)

发布于:2024-08-08 ⋅ 阅读:(154) ⋅ 点赞:(0)
首先安装kubebuilder (我是mac电脑)
#下载
curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"

#+x
chmod +x kubebuilder && sudo mv kubebuilder /usr/local/bin/(这个目录随便 就是个可执行文件 放哪里都行)

# 方便使用
echo "export PATH=$PATH:/Users/haoxuanli/go/bin/kubebuilder(你kubebuilder位置)" >> 你的本地profile  比如~/.zshrc 
初始化kubebuilder 脚手架

初始化项目

 kubebuilder init --domain ksl.com  --repo operatorsky

开启多接口组支持

kubuilder edit --multigroup=true

创建api crd 我命名叫 “大car” dacar 也就是大卡车的意思 嗯

kubebuilder create api --group kslgroup01  --version v144 --kind Dacar     

目录生成结果如下
在这里插入图片描述

在这个文件中定义 dacar 这个crd的spec
api/v144/dacar_types.go
目前只初始化这两个属性就够了

type DacarSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// Foo is an example field of Dacar. Edit dacar_types.go to remove/update
	Replicas int32              `json:"replicas,omitempty"`
	Template v1.PodTemplateSpec `json:"template,omitempty"`
}

这是整个文件
api/v144/dacar_types.go

/*
Copyright 2024.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v144

import (
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// DacarSpec defines the desired state of Dacar
type DacarSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// Foo is an example field of Dacar. Edit dacar_types.go to remove/update
	Replicas int32              `json:"replicas,omitempty"`
	Template v1.PodTemplateSpec `json:"template,omitempty"`
}

// DacarStatus defines the observed state of Dacar
type DacarStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// Dacar is the Schema for the dacars API
type Dacar struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   DacarSpec   `json:"spec,omitempty"`
	Status DacarStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// DacarList contains a list of Dacar
type DacarList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Dacar `json:"items"`
}

func init() {
	SchemeBuilder.Register(&Dacar{}, &DacarList{})
}

写好这个文件后 直接通过自带的make命令 install 到k8s中

install 如果报错 我这还有个秘方
使用kubebuilder 遇到的 262144 bytes 超长问题

# 学习的话最好先用这2个
make manifest
make install

# 其实一条命令就可以搞定 install 自带make manifest
make install

以上命令需要本地 kubectl 可以操作目标k8s
kubeconf 配置到 ~/.kube/kubeconfig 即可

有了这个dacar类型之后 我们徒手制作一个这个类型的部署文件

apiVersion: kslgroup01.ksl.com/v144
kind: Dacar
metadata:
  labels:
    app: dacar-demo01
  name: dacar-demo01
  namespace: default
spec:
  replicas: 5
  template:
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

apply 这个文件后
我们发现可以查看到这个crd了

haoxuanli@HaoxuandeMacBook-Pro operatorsky % kubectl get dacars                 
NAME           AGE
dacar-demo01   12s

但是 还是看不到 pod
是因为我们没有写这个crd对应的operator

那就写个呗
注意这个operator的位置 dacar_controller.go 这里
在这里插入图片描述

主要实现这个reconcile方法就可以了
通过拿到的运行期状态 来跟部署文件的期望状态对比 然后进行不同业务响应就ok了

internal/controller/dacar_controller.go

func (r *DacarReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	logger := log.FromContext(ctx)

	// 通过 reconciler 拉取 dacar 状态
	// 1. 获取demo的api实例对象

	dacar := &kslgroup01v144.Dacar{}
	err := r.Get(ctx, req.NamespacedName, dacar)
	if err != nil {
		logger.Error(err, "unable to fetch Demo")
	}
	podList := &v1.PodList{}
	// 2. 获取当前api对象关联的运行pod
	err = r.List(ctx, podList, client.InNamespace(req.Namespace), client.MatchingLabels{"app": dacar.Name})

	if err != nil {
		logger.Error(err, "")
		return ctrl.Result{}, err
	}
	currentPodCount := len(podList.Items)
	// 比较dacar
	if int(dacar.Spec.Replicas) > currentPodCount {
		for i := 0; i < int(dacar.Spec.Replicas)-currentPodCount; i++ {
			pod := &v1.Pod{
				ObjectMeta: ctrl.ObjectMeta{
					Name:      dacar.Name + "-" + uuid.New().String()[0:5] + "666",
					Namespace: dacar.Namespace,
					Labels:    dacar.Labels,
				},
				Spec: dacar.Spec.Template.Spec,
			}
			err = ctrl.SetControllerReference(dacar, pod, r.Scheme)

			if err != nil {
				logger.Error(err, "unable to set ownerReference for Pod")
				return ctrl.Result{}, err
			}
			err = r.Create(ctx, pod)
		}
	} else {
		deleteCount := currentPodCount - int(dacar.Spec.Replicas)
		deletePods := podList.Items[:deleteCount]
		for _, pod := range deletePods {
			err = r.Delete(ctx, &pod)
			if err != nil {
				logger.Error(err, "unable to delete Pod for Demo")
				return ctrl.Result{}, err
			}
		}
	}

	return ctrl.Result{}, nil
}
运行operator

由于这个是demo 我们就不把operator部署到集群侧了
直接 make run 启动就可以了 日志不报错 就没啥问题

haoxuanli@HaoxuandeMacBook-Pro operatorsky % make run
/Users/haoxuanli/Documents/GitHub/operatorsky/bin/controller-gen rbac:roleName=manager-role crd=maxDescLen=0 webhook paths="./..." output:crd:artifacts:config=config/crd/bases
/Users/haoxuanli/Documents/GitHub/operatorsky/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
go vet ./...
go run ./cmd/main.go
2024-08-03T15:25:26+08:00       INFO    setup   starting manager
2024-08-03T15:25:26+08:00       INFO    starting server {"name": "health probe", "addr": "[::]:8081"}
2024-08-03T15:25:26+08:00       INFO    Starting EventSource    {"controller": "dacar", "controllerGroup": "kslgroup01.ksl.com", "controllerKind": "Dacar", "source": "kind source: *v144.Dacar"}
2024-08-03T15:25:26+08:00       INFO    Starting Controller     {"controller": "dacar", "controllerGroup": "kslgroup01.ksl.com", "controllerKind": "Dacar"}
2024-08-03T15:25:26+08:00       INFO    Starting workers        {"controller": "dacar", "controllerGroup": "kslgroup01.ksl.com", "controllerKind": "Dacar", "worker count": 1}

然后这边 kubectl get pod 可以看到如我们所愿 有5个启动的pod 对应了上方的部署文件

haoxuanli@HaoxuandeMacBook-Pro operatorsky % kubectl get po
NAME                    READY   STATUS              RESTARTS   AGE
dacar-demo01-2c116666   0/1     ContainerCreating   0          59s
dacar-demo01-2e1ca666   0/1     ContainerCreating   0          59s
dacar-demo01-a10ef666   0/1     ContainerCreating   0          59s
dacar-demo01-a41b5666   0/1     ContainerCreating   0          59s
dacar-demo01-def5b666   0/1     ContainerCreating   0          59s
haoxuanli@HaoxuandeMacBook-Pro operatorsky % 

好demo结束
## 停止operator 进程
停止那个刚才 make run的进程
## 删除crd
make uninstall

具体需要完整代码的话 可以下方评论找我要


网站公告

今日签到

点亮在社区的每一天
去签到