• 使用 kubebuilder 创建并部署 k8s-operator


    一、准备

    本文中的示例运行环境及相关软件版本如下:

    • Kubernetes v1.16.3
    • Go 1.15.6
    • Kubebuilder 3.1.0
    • Docker 20.10.7

    安装kubebuilder:

    #下载kubebuilder 3.1.0,建议二进制版本:https://github.com/kubernetes-sigs/kubebuilder/releases
    #将二进制文件copy到/usr/local/bin下 
    % chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
    #验证 
    % kubebuilder version

    二、创建项目

    % mkdir guestbook 
    % cd guestbook %
    % go mod init guestbook //go mod管理包 
    % kubebuilder init --domain xiaohongshu.org --owner "luxiu"

    三、创建API

    % kubebuilder create api --group redis  --version v1 --kind RedisCluster
    Create Resource [y/n]
    y
    Create Controller [y/n]
    y
    Writing kustomize manifests for you to edit...
    Writing scaffold for you to edit...
    api/v1/rediscluster_types.go
    controllers/rediscluster_controller.go
    Update dependencies:
    $ go mod tidy
    Running make:
    $ make generate
    go: creating new go.mod: module tmp
    Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1
    go: found sigs.k8s.io/controller-tools/cmd/controller-gen in sigs.k8s.io/controller-tools v0.4.1
    /Users/luxiu/Desktop/luxiu/project/kubernetes/crd-test/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."

    API 创建完成后,在项目根目录下查看目录结构:

    四、安装 CRD

    这里安装CRD到指定的k8s集群里,需要修改Makefile里连接k8s配置:

    install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
            $(KUSTOMIZE) build config/crd | kubectl --context cls-j07gq3ud-context-default  apply -f -
    uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.
            $(KUSTOMIZE) build config/crd | kubectl --context cls-j07gq3ud-context-default  delete -f -
    deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
            cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
            $(KUSTOMIZE) build config/default | kubectl --context cls-j07gq3ud-context-default apply -f -
    undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.
            $(KUSTOMIZE) build config/default | kubectl --context cls-j07gq3ud-context-default delete -f -

    执行下面命令来安装CRD:

     % make install
    /Users/luxiu/Desktop/luxiu/project/kubernetes/crd-test/bin/controller-gen "crd:trivialVersions=true,preserveUnknownFields=false" rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
    /Users/luxiu/Desktop/luxiu/project/kubernetes/crd-test/bin/kustomize build config/crd | kubectl --context cls-j07gq3ud-context-default  apply -f -
    customresourcedefinition.apiextensions.k8s.io/redisclusters.redis.xiaohongshu.org created

    五、部署 Controller

    在开始部署 controller 之前,我们需要先检查 kubebuilder 自动生成的 YAML 文件。

    修改使用 gcr.io 镜像仓库的镜像地址

    对于中国大陆用户,可能无法访问 Google 镜像仓库 gcr.io,因此需要修改 config/default/manager_auth_proxy_patch.yaml 文件中的镜像地址,将其中 gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 修改为quay.io/brancz/kube-rbac-proxy:v0.8.0

    有两种方式运行 controller:

    • 本地运行,用于调试
    • 部署到 Kubernetes 上运行,作为生产使用

    本地运行 controller

    要想在本地运行 controller,只需要执行下面的命令,你将看到 controller 启动和运行时输出:

    $ make run

    将 Controller 部署到指定 Kubernetes集群

    这里有个问题,需要修改Dockerfile中 ,给go 设置proxy代理,这样go mod download时不至于超时连不上:

    RUN go mod download 这行的上面加如下一行:
    ENV GOPROXY="https://goproxy.cn"

    构建 controller 的镜像,并推送到公司docker harbor 上,然后在 Kubernetes 上部署 Deployment 资源,如下命令:

    $ make docker-build  IMG=docker-reg.devops.xiaohongshu.com/data-infra/rediscluster:v1
    $ make docker-push  IMG=docker-reg.devops.xiaohongshu.com/data-infra/rediscluster:v1
    $ make deploy  IMG=docker-reg.devops.xiaohongshu.com/data-infra/rediscluster:v1

    在初始化项目时,kubebuilder 会自动根据项目名称创建一个 Namespace,如本文中的guestbook-system ,查看 Deployment 对象和 Pod 资源。

    % k8sdev get deployment -n guestbook-system
    NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
    guestbook-controller-manager   1/1     1            1           25h
    % k8sdev get pod  -n guestbook-system
    NAME                                            READY   STATUS    RESTARTS   AGE
    guestbook-controller-manager-79fd58d674-fvm2m   2/2     Running   0          145m

    六、创建 CR

    该创建自定义资源对象CR了,如原生中的rc/deployment等对象

    % k8sdev apply -f config/samples/redis_v1_rediscluster.yaml
    rediscluster.redis.xiaohongshu.org/rediscluster-sample created
    % k8sdev get RedisCluster
    NAME                  AGE
    rediscluster-sample   38s

    至此一个基本的 Operator 框架已经创建完成,但这个 Operator 只是修改了 etcd 中的数据而已,实际上什么事情也没做,因为我们没有在 Operator 中的增加业务逻辑。

    七、开发业务逻辑

    下面我们将修改 CRD 的数据结构并在 controller 中增加一些日志输出。

    修改 CRD

    我们将修改api/v1/guestbook_types.go 文件的内容,在 CRD 中增加 FirstNameLastName 和 Status 字段。

    // GuestbookSpec defines the desired state of Guestbook
    type GuestbookSpec 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 Guestbook. Edit guestbook_types.go to remove/update
    	FirstName string `json:"firstname"`
    	LastName  string `json:"lastname"`
    }
    
    // GuestbookStatus defines the observed state of Guestbook
    type GuestbookStatus struct {
    	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
    	// Important: Run "make" to regenerate code after modifying this file
    	Status string `json:"Status"`
    }

    修改 Reconcile 函数

    Reconcile 函数是 Operator 的核心逻辑,Operator 的业务逻辑都位于 controllers/guestbook_controller.go 文件的 Reconcile 函数中

    func (r *GuestbookReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    	_ = log.FromContext(ctx)
    
    	// your logic here
    	// 获取当前的 CR,并打印
    	logger := log.FromContext(ctx)
    	obj := &webappv1.Guestbook{}
    	if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
    		logger.Error(err, "Unable to fetch object")
    		return ctrl.Result{}, nil
    	} else {
    		logger.Info("Greeting 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 {
    		logger.Error(err, "unable to update status")
    	}
    
    	return ctrl.Result{}, nil
    }
    
    

    运行测试

    • 安装CRD(同上)
    • 部署controller(同上)
    • 创建CR

     修改 config/samples/redis_v1_rediscluster.yaml 文件中的配置

    apiVersion: redis.xiaohongshu.org/v1
    kind: RedisCluster
    metadata:
      name: rediscluster-sample
    spec:
      # Add fields here
      firstname: Jimmy
      lastname: Song

    执行下面命令,创建CR:

    $ k8sdev apply -f  config/samples/redis_v1_rediscluster.yaml

    查看controller里的运行日志:

    % k8sdev get pod  -n guestbook-system
    NAME                                            READY   STATUS    RESTARTS   AGE
    guestbook-controller-manager-79fd58d674-fvm2m   2/2     Running   0          3h53m
    
    % k8sdev logs -f guestbook-controller-manager-79fd58d674-fvm2m -n guestbook-system -c manager
    2022-03-08T08:24:04.641Z	INFO	controller-runtime.manager.controller.guestbook	Greeting from Kubebuilder to	{"reconciler group": "webapp.my.domain", "reconciler kind": "Guestbook", "name": "guestbook-sample", "namespace": "default", "Jimmy": "Song"}
    2022-03-08T08:24:04.651Z	INFO	controller-runtime.manager.controller.guestbook	Greeting from Kubebuilder to	{"reconciler group": "webapp.my.domain", "reconciler kind": "Guestbook", "name": "guestbook-sample", "namespace": "default", "Jimmy": "Song"}

     

     

    参考:部署k8s operator

     

  • 相关阅读:
    基于java的航空机票订票系统的开发-计算机毕业设计
    【老生谈算法】基于Matlab的IIR数字低通滤波器的设计
    数据仓库之数据冗余规范
    碰瓷“一带一路”
    golang版本管理gvm
    CSS -- a:link 失效问题 及 属性选择器
    Java中的方法递归(套娃检索)
    smile——Java机器学习引擎
    河海大学李轶团队揭示河流交汇特性决定了汇流水动力区微生物群落对河网的影响
    git遇到的报错
  • 原文地址:https://www.cnblogs.com/mysql-dba/p/15982341.html