Kubernetes Operator

Operator理论知识

1)Operator是什么

你可以理解成Operator就是CRD+自定义Controller的实践应用。

Kubernetes Operator由CoreOS公司开发,它是一种自定义控制器,它扩展了 Kubernetes API 的功能,用于管理和自动化应用程序、服务或资源的生命周期。Operator 可以将复杂的操作封装到 Kubernetes 中,以便在集群中创建、配置、部署和管理特定类型的应用程序或服务。

Operator 的核心思想是将应用程序的专业知识嵌入到自定义控制器中,以便控制器能够理解和管理特定类型的应用程序。这样一来,Operator 可以根据自定义资源的规范和状态,自动执行与应用程序相关的任务,如创建、更新、伸缩、备份和恢复等。Operator 还可以响应集群事件,自动修复故障和应用程序状态的健康性。

通过使用 Operator,开发人员和管理员可以更轻松地在 Kubernetes 上管理复杂的应用程序和服务,减少手动操作的工作量,提高可靠性和可重复性。同时,Operator 的开放性设计使得可以创建适用于各种不同类型应用程序的自定义操作符,从数据库、消息队列到机器学习模型等各种类型的应用程序都可以通过 Operator 进行管理。

2)Operator用来做什么

使用 Operator 有很多理由。通常情况下,要么是开发团队为他们的产品创建 Operator,要么是 DevOps 团队希望对第三方软件管理进行自动化。无论哪种方式,都应该从确定 Operator 应该负责哪些东西开始。

最基本的 Operator 用于部署,使用 kubectl apply 就可以创建一个用于响应 API 资源的数据库,但这比内置的 Kubernetes 资源(如 StatefulSets 或 Deployments)好不了多少。复杂的 Operator 将提供更大的价值。如果你想要对数据库进行伸缩该怎么办?

如果是 StatefulSet,你可以执行 kubectl scale statefulset my-db --replicas 3,这样就可以得到 3 个实例。但如果这些实例需要不同的配置呢?是否需要指定一个实例为主实例,其他实例为副本?如果在添加新副本之前需要执行设置步骤,那该怎么办?在这种情况下,可以使用 Operator。

更高级的 Operator 可以处理其他一些特性,如响应负载的自动伸缩、备份和恢复、与 Prometheus 等度量系统的集成,甚至可以进行故障检测和自动调优。任何具有传统“运行手册”文档的操作都可以被自动化、测试和依赖,并自动做出响应。

被管理的系统甚至不需要部署在 Kubernetes 上也能从 Operator 中获益。例如,主要的云服务提供商(如 Amazon Web Services、微软 Azure 和谷歌云)提供 Kubenretes Operator 来管理其他云资源,如对象存储。用户可以通过配置 Kubernetes 应用程序的方式来配置云资源。运维团队可能对其他资源也采取同样的方法,使用 Operator 来管理任何东西——从第三方软件服务到硬件。

下面总结了一些常见的场景:

  • 按需部署一个应用程序,并自动配置,比如Prometheus
  • 需要备份和恢复应用程序的状态,如MySQL数据库
  • 处理应用程序代码的升级以及相关更改,例如数据库架构或额外的配置设置
  • 发布一个服务,要让不支持Kubernetes API的应用程序能够发现
  • 模拟整个或部分集群中的故障以测试其弹性
  • 在没有内部成员选举程序的情况下为分布式应用程序选择领导者

Operator初次上手

说明:需要大家有一点go的开发能力

目前主流的Operator开发框架有两个:kubebuilder和Operator-sdk, 两者实际上并没有本质的区别,它们的核心都是使用官方的 controller-tools 和 controller-runtime。不过细节上稍有不同,比如 kubebuilder 有着更为完善的测试与部署以及代码生成的脚手架等;而 operator-sdk 对 ansible operator 这类上层操作的支持更好一些。

下面基于kubebuilder,讲解如何开发Operator

1. 环境准备

Kubebuilder工作依赖go环境,所以需要安装go,理应单独拿一台机器来安装Kubebuilder,但我们为了节省资源,就拿tanglinux03来安装。

1)安装go

Rocky8使用yum安装

yum install -y golang.x86_64

检测版本

go version

设置国内代理

go env -w GOPROXY=https://goproxy.cn,direct

设置环境变量

go env GOPATH  #会有一个目录,,然后把这个目录写入到/etc/profile
vi /etc/profile   
export GOPATH=/root/go/   #最后一行添加

2)安装docker

开发过程中会用到docker环境,由于我们部署k8s时,安装过containerd,当时配置过yum仓库,所以可以直接通过yum来安装docker

yum install -y docker-ce

启动服务

systemctl start docker

3)安装kubectl 以及配置直接访问k8s集群

由于是tanglinux03,已经安装过kubectl,如果没有安装请参考部署k8s集群的步骤来安装。而默认tanglinux03是无法直接访问k8s集群的,需要将tanglinux01下面的/root/.kube目录拷贝到tanglinux03才可以

##以下操作在tanglinux01上操作
scp -r /root/.kube  tanglinux03:/root/

测试

##在tanglinux03上执行
kubectl get node

4)安装kubebuilder

curl -k -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
chmod +x kubebuilder && mv kubebuilder /usr/local/bin/

测试

kubebuilder version
2. 创建Helloworld项目

1)初始化项目

export GOPATH=`go env GOPATH`
mkdir -p $GOPATH/src/helloworld 
cd $GOPATH/src/helloworld 
kubebuilder init --domain tanglinux.com

初始化完成后,目录结构是:

|-- cmd
|   `-- main.go
|-- config
|   |-- 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.yaml
|       |-- auth_proxy_role_binding.yaml
|       |-- auth_proxy_service.yaml
|       |-- kustomization.yaml
|       |-- leader_election_role.yaml
|       |-- leader_election_role_binding.yaml
|       |-- role.yaml
|       |-- role_binding.yaml
|       `-- service_account.yaml
|-- go.mod
|-- go.sum
`-- hack
    `-- boilerplate.go.txt

2)创建API(CRD + Controller)

先安装make,如果没有make会出问题

yum install -y make

创建API

kubebuilder create api --group webapp --version v1 --kind Guestbook  ##打两次y
Create Resource [y/n]
y
Create Controller [y/n]
y

3)构建和部署CRD

make install

这个过程会将CRD部署到k8s集群里

我们可以查看CRD

kubectl get crd |grep tanglinux.com

我们可以通过下面命令查看该CRD对应的yaml

$GOPATH/src/helloworld/bin/kustomize build config/crd

4)编辑Controller对应的源码,并编译

如果是生产环境,此时就要去编辑Controller对应的go程序啦,由于我们是体验过程,所以只做简单改动

源码文件路径为:$GOPATH/src/helloworld/internal/controller/guestbook_controller.go

vi $GOPATH/src/helloworld/internal/controller/guestbook_controller.go

改动1:

增加一个依赖包fmt

kubernetes生产化实践 pdf_linux

改动2:

找到// TODO(user): your logic here,在下面增加一行代码,用来打印堆栈信息

fmt.Println("Helloworld.")

kubernetes生产化实践 pdf_linux_02

改完后,执行

make run

这样就可以将该Controller运行起来了。会显示如下信息

test -s /root/go/src/helloworld/bin/controller-gen && /root/go/src/helloworld/bin/controller-gen --version | grep -q v0.13.0 || \
GOBIN=/root/go/src/helloworld/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.13.0
/root/go/src/helloworld/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
/root/go/src/helloworld/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
go fmt ./...
internal/controller/guestbook_controller.go
go vet ./...
go run ./cmd/main.go
2023-12-19T09:41:15-05:00       INFO    setup   starting manager
2023-12-19T09:41:15-05:00       INFO    controller-runtime.metrics      Starting metrics server
2023-12-19T09:41:15-05:00       INFO    starting server {"kind": "health probe", "addr": "[::]:8081"}
2023-12-19T09:41:15-05:00       INFO    controller-runtime.metrics      Serving metrics server  {"bindAddress": ":8080", "secure": false}
2023-12-19T09:41:15-05:00       INFO    Starting EventSource    {"controller": "guestbook", "controllerGroup": "webapp.tanglinux.com", "controllerKind": "Guestbook", "source": "kind source: *v1.Guestbook"}
2023-12-19T09:41:15-05:00       INFO    Starting Controller     {"controller": "guestbook", "controllerGroup": "webapp.tanglinux.com", "controllerKind": "Guestbook"}
2023-12-19T09:41:15-05:00       INFO    Starting workers        {"controller": "guestbook", "controllerGroup": "webapp.tanglinux.com", "controllerKind": "Guestbook", "worker count": 1}

说明:

不要按ctrc c中断,此时需要我们到k8s那边去

5)到k8s创建Guestbook资源的实例

现在kubernetes已经部署了Guestbook类型的CRD,而且对应的controller也已正在运行中,可以尝试创建Guestbook类型的实例了(相当于有了pod的定义后,才可以创建pod);

kubebuilder已经自动创建了一个类型的部署文件:$GOPATH/src/helloworld/config/samples/webapp_v1_guestbook.yaml ,内容如下,很简单,接下来咱们就用这个文件来创建Guestbook实例:

cat > guestbook.yaml <<EOF
apiVersion: webapp.tanglinux.com/v1
kind: Guestbook
metadata:
  labels:
    app.kubernetes.io/name: guestbook
    app.kubernetes.io/instance: guestbook-sample
    app.kubernetes.io/part-of: helloworld
    app.kubernetes.io/managed-by: kustomize
    app.kubernetes.io/created-by: helloworld
  name: guestbook-sample
spec:
  # TODO(user): Add fields here
  foo: bar
EOF

应用此yaml

kubectl apply -f guestbook.yaml

回到tanglinux03的终端,可以看到多了一行输出

kubernetes生产化实践 pdf_容器_03

6)将Controller制作成镜像,并上传到远程仓库

首先需要有一个私有镜像仓库,用来存储编译好的镜像。如果有harbor直接使用harbor最好,如果没有,就是用docker的镜像仓库hub.docker.com,假设你已经有账号了。

在编译镜像之前还需要登录到docker的镜像仓库

docker login https://hub.docker.com

我在这里使用的是harbor

docker login https://harbor.jiangrou.top

给Dockerfile里增加GOPROXY设置

vi Dockerfile #在go mod download上面增加一行

RUN go env -w GOPROXY=https://goproxy.cn

kubernetes生产化实践 pdf_kubernetes生产化实践 pdf_04

Harbor这里,我已经创建项目tang,然后编译镜像

make docker-build docker-push IMG=harbor.jiangrou.top/tang/guestbook:v1

如果编译不过去,那就是网络问题,下载镜像有问题,此时就要做一个代理

按如下方法做代理

mkdir -p /etc/systemd/system/docker.service.d
cat > /etc/systemd/system/docker.service.d/proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://t.lishiming.net:38089/"
Environment="HTTPS_PROXY=http://t.lishiming.net:38089/"
Environment="NO_PROXY=localhost,127.0.0.1,.jiangrou.top"
EOF
##注意,上面的地址要换成你自己的,这个代理是我自己设置的,如果你没有自己的代理,可以用我这个,但不保证一直能使用
systemclt daemon-reload
systemctl restart docerk

harbor那边已经成功上传镜像

kubernetes生产化实践 pdf_kubernetes_05

7)在k8s里部署该镜像

部署之前,需要把之前设置的代理取消,否则会出错

unset http_proxy
unset https_proxy

修改kube-rbac-proxy镜像地址,因为自带的镜像下载不到

sed -i 's/gcr.io/gcr.lank8s.cn/' ./config/default/manager_auth_proxy_patch.yaml

将harbor项目改为公开,方便下载

kubernetes生产化实践 pdf_linux_06

在三个k8s node上手动将镜像下载下来

ctr -n k8s.io i pull harbor.jiangrou.top/tang/guestbook:v1

部署,这是在tanglinux03上执行的,当前目录还是在$GOPATH/src/helloworld

make deploy IMG=harbor.jiangrou.top/tang/guestbook:v1

查看pod

kubectl get po -n helloworld-system

kubernetes生产化实践 pdf_kubernetes生产化实践 pdf_07

此时,我们再次到k8s里去apply guestbook.yaml

kubectl delete -f guestbook.yaml
kubectl apply -f guestbook.yaml

再去查看helloworld-controller-manager-694854949d-wjkk5的log

kubectl -n helloworld-system logs helloworld-controller-manager-694854949d-wjkk5

就能看到最后面的 Helloworld 输出了。

8)清理

到tanglinux03,进入到$GOPATH/src/helloworld,执行

make uninstall

注意,它清理的是CRD资源,Controller并不会清理,要想删除Controller,直接删除对应ns即可

kubectl delete ns helloworld-system