基于Kubebuilder开发Operator(入门使用)
原文地址:使用kubebuilder 理解k8s crd - 知乎理解k8s的crd需要先理解k8s的controller模式比如kube-controller-manager中的deployment控制器,在初始化的时候就会传入要监听Deployments、ReplicaSet和pod的三个informer对象首先list一下对象到本地缓存,同时watch对象的变更,等于增量更新func sta
·
原文地址:使用kubebuilder 理解k8s crd - 知乎
理解k8s的crd需要先理解k8s的controller模式
- 比如kube-controller-manager中的deployment控制器,在初始化的时候就会传入要监听Deployments、ReplicaSet和pod的三个informer对象
- 首先list一下对象到本地缓存,同时watch对象的变更,等于增量更新
func startDeploymentController(ctx ControllerContext) (controller.Interface, bool, error) {
dc, err := deployment.NewDeploymentController(
ctx.InformerFactory.Apps().V1().Deployments(),
ctx.InformerFactory.Apps().V1().ReplicaSets(),
ctx.InformerFactory.Core().V1().Pods(),
ctx.ClientBuilder.ClientOrDie("deployment-controller"),
)
if err != nil {
return nil, true, fmt.Errorf("error creating Deployment controller: %v", err)
}
go dc.Run(int(ctx.ComponentConfig.DeploymentController.ConcurrentDeploymentSyncs), ctx.Stop)
return nil, true, nil
}
- 然后内部会做sync其实就是Reconcile loop, 即调谐循环——说白了就是对比对象的actualState和expectState的差异,执行对应的增删操作 比如deployment中扩缩容操作
- 计算差值,可以创建出的 pod 数减去所有活跃 rs的副本数之和
- 如果差值为正,说明需要扩容,并且从ReplicaSetsBySizeNewer排序看是按照从新到旧扩容
- 如果差值为负,说明需要缩容,并且从ReplicaSetsBySizeOlder排序看是按照从旧到新缩容
-
算差值如下
deploymentReplicasToAdd := allowedSize - allRSsReplicas
var scalingOperation string
switch {
case deploymentReplicasToAdd > 0:
sort.Sort(controller.ReplicaSetsBySizeNewer(allRSs))
scalingOperation = "up"
case deploymentReplicasToAdd < 0:
sort.Sort(controller.ReplicaSetsBySizeOlder(allRSs))
scalingOperation = "down"
}
理解了k8s的controller模式后,crd就是你自己写的controller
- 监听并处理你自己定义的资源,
- 下面这张图很形象
安装 Kubebuilder
wget https://github.com/kubernetes-sigs/kubebuilder/releases/download/v3.1.0/kubebuilder_linux_amd64
mv kubebuilder_linux_amd64 /usr/local/bin/kubebuilder
创建脚手架工程
- 创建一个目录,并且指定这个目录为代码仓库
mkdir -p ~/projects/guestbook
cd ~/projects/guestbook
kubebuilder init --domain my.domain --repo my.domain/guestbook
- 查看这个目录下的文件结果
[root@k8s-node01 guestbook]# tree
.
├── config
│ ├── default
│ │ ├── kustomization.yaml
│ │ ├── manager_auth_proxy_patch.yaml
│ │ └── manager_config_patch.yaml
│ ├── manager
│ │ ├── controller_manager_config.yaml
│ │ ├── 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
│ ├── role_binding.yaml
│ └── service_account.yaml
├── Dockerfile
├── go.mod
├── go.sum
├── hack
│ └── boilerplate.go.txt
├── main.go
├── Makefile
└── PROJECT
6 directories, 24 files
创建api
- 创建一个名为 webapp/v1的 API (group/version)
- 创建新的类型 Guestbook
kubebuilder create api --group webapp --version v1 --kind Guestbook
- 追踪结果,发现又多了很多文件 ,其中api/v1/guestbook_types.go代表定义API的地方 ,controllers/guestbook_controller.go代表调谐的逻辑
[root@k8s-master01 guestbook]# tree
.
├── api
│ └── v1
│ ├── groupversion_info.go
│ ├── guestbook_types.go
│ └── zz_generated.deepcopy.go
├── bin
│ └── controller-gen
├── config
│ ├── crd
│ │ ├── kustomization.yaml
│ │ ├── kustomizeconfig.yaml
│ │ └── patches
│ │ ├── cainjection_in_guestbooks.yaml
│ │ └── webhook_in_guestbooks.yaml
│ ├── default
│ │ ├── kustomization.yaml
│ │ ├── manager_auth_proxy_patch.yaml
│ │ └── manager_config_patch.yaml
│ ├── manager
│ │ ├── controller_manager_config.yaml
│ │ ├── 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
│ │ ├── guestbook_editor_role.yaml
│ │ ├── guestbook_viewer_role.yaml
│ │ ├── kustomization.yaml
│ │ ├── leader_election_role_binding.yaml
│ │ ├── leader_election_role.yaml
│ │ ├── role_binding.yaml
│ │ └── service_account.yaml
│ └── samples
│ └── webapp_v1_guestbook.yaml
├── controllers
│ ├── guestbook_controller.go
│ └── suite_test.go
├── Dockerfile
├── go.mod
├── go.sum
├── hack
│ └── boilerplate.go.txt
├── main.go
├── Makefile
└── PROJECT
13 directories, 37 files
- 在调谐函数中添加打印日志,位于 controller/guestbook_controller.go
func (r *GuestbookReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = log.FromContext(ctx)
// your logic here
log.FromContext(ctx).Info("print_req", "req", req.String())
return ctrl.Result{}, nil
}
部署到k8s集群中
- 编译打镜像
make docker-build IMG=guestbook:v1.0 # 实际执行 docker build -t guestbook:v1.0 .
- 一般我们需要修改项目里的 dockerfile,给 go 设置proxy代理,这样 go mod download时不至于超时连不上
- 然后需要将镜像手动推送到本地仓库中,如果底层的runtime是ctr的话 需要docker save出来并导入
docker save guestbook:v1.0 > a.tar
ctr --namespace k8s.io images import a.tar
- 因为项目中用到了 kube-rbac-proxy,这个镜像也可能出现下载不到的问题,需要自己手动处理一下,如下:
- 现在部署crd
make deploy IMG=guestbook:v1.0 #实际执行 kustomize build config/default | kubectl apply -f -
- 检查在guestbook-system ns 下部署的对象
- 检查api-resources
- 部署guestbook
kubectl apply -f config/samples/webapp_v1_guestbook.yaml
# guestbook.webapp.my.domain/guestbook-cxy created
- 查看crd中的日志可以看到调谐函数中打印
更多推荐
已为社区贡献7条内容
所有评论(0)