一、准备

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

  • 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

使用 kubebuilder 创建并部署 k8s-operator的更多相关文章

  1. ansible一键部署k8s单机环境

    一.虚拟机准备 干净的Centsot7.4.4G内存.2个CPU 最小化安装,最好带虚拟化 二.执行初始化脚本 注意:脚本中配置静态网卡根据实际网卡名称配置,我用的是ens33 可以用 sed -i ...

  2. 二进制部署k8s

    一.二进制部署 k8s集群 1)参考文章 博客: https://blog.qikqiak.com 文章: https://www.qikqiak.com/post/manual-install-hi ...

  3. 【原】二进制部署 k8s 1.18.3

    二进制部署 k8s 1.18.3 1.相关前置信息 1.1 版本信息 kube_version: v1.18.3 etcd_version: v3.4.9 flannel: v0.12.0 cored ...

  4. centos7.8 安装部署 k8s 集群

    centos7.8 安装部署 k8s 集群 目录 centos7.8 安装部署 k8s 集群 环境说明 Docker 安装 k8s 安装准备工作 Master 节点安装 k8s 版本查看 安装 kub ...

  5. 在Azure Container Service创建Kubernetes(k8s)群集运行ASP.NET Core跨平台应用程序

    引子 在此前的一篇文章中,我介绍了如何在本地docker环境中运行ASP.NET Core跨平台应用程序(http://www.cnblogs.com/chenxizhang/p/7148657.ht ...

  6. 微服务架构 - 离线部署k8s平台并部署测试实例

    一般在公司部署或者真实环境部署k8s平台,很有可能是内网环境,也即意味着是无法连接互联网的环境,这时就需要离线部署k8s平台.在此整理离线部署k8s的步骤,分享给大家,有什么不足之处,欢迎指正. 1. ...

  7. 部署 k8s Cluster(上)[转]

    我们将部署三个节点的 Kubernetes Cluster. k8s-master 是 Master,k8s-node1 和 k8s-node2 是 Node. 所有节点的操作系统均为 Ubuntu ...

  8. ubuntu18.04使用kubeadm部署k8s单节点

    实验目的: 体验kubeadm部署k8s服务,全流程体验! 实验环境: ubuntu18.04 联网在线部署 kubeadm 01.系统检查 节点主机名唯一,建议写入/etc/hosts 禁止swap ...

  9. Kubeasz部署K8s基础测试环境简介

    下面介绍使用Kubeasz部署K8s集群环境. https://github.com/easzlab/kubeasz在需要使用kubeeasz项目安装的k8s时,需要将所有需要它来部署的节点上,都安装 ...

随机推荐

  1. 如何在pyqt中给无边框窗口添加DWM环绕阴影

    前言 在之前的博客<如何在pyqt中通过调用SetWindowCompositionAttribute实现Win10亚克力效果>中,我们实现了窗口的亚克力效果,同时也用SetWindowC ...

  2. 「JOISC 2014 Day1」巴士走读

    「JOISC 2014 Day1」巴士走读 将询问离线下来. 从终点出发到起点. 由于在每个点(除了终点)的时间被过来的边固定,因此如果一个点不被新的边更新,是不会发生变化的. 因此可以按照时间顺序, ...

  3. libcurl库openssl编译

    openssl编译 win32: perl Configure  no-shared VC-WIN32 --prefix=E:/lib/openssl-1.1.1 linux: ./config -f ...

  4. Mysql 返回JSON值属性的函数 (五)

    本节中的函数返回JSON值的属性. JSON_DEPTH(json_doc) 返回JSON文档的最大深度.NULL如果参数为,则 返回 NULL.如果参数不是有效的JSON文档,则会发生错误. 一个空 ...

  5. Linux开机显示模式切换

    修改vim /etc/inittab 默认为5-图形界面模式,改为3-多用户模式即可 # Default runlevel. The runlevels used are: # 0 - halt (D ...

  6. python-字符串操作分类小结

    切片 str[start:end:step] # 包括头,不包括尾巴.step为步长,意思是每隔step-1个元素,取一个字符 [::-1] #反向取字符串,实现字符串的反转 "abcde& ...

  7. [转]API性能测试基本性能指标及要求

    原文链接http://blog.csdn.net/strawbingo/article/details/46458959 指标的基本概念 1.事务(Transaction) 在web性能测试中,一个事 ...

  8. HTML笔记整理--上节

    一.认识WEB 「网页」主要是由文字.图像和超链接等元素构成,当然除了这些元素,网页中还可以包括音频.视频以及Flash等. 「浏览器」是网页显示.运行的平台. 「浏览器内核」(排版引擎.解释引擎.渲 ...

  9. 「codeforces - 1284G」Seollal

    给定 \(n\times m\) 的网格图,有些格子有障碍,无障碍且相邻的格子之间连边形成图.保证 \((1, 1)\) 无障碍,保证无障碍格子连通. 将网格图黑白染色,相邻格子颜色不同,\((1, ...

  10. 手写RPC框架(六)整合Netty

    手写RPC框架(六)整合Netty Netty简介: Netty是一个基于NIO的,提供异步,事件驱动的网络应用工具,具有高性能高可靠性等特点. 使用传统的Socket来进行网络通信,服务端每一个连接 ...