{"id":21540804,"url":"https://github.com/llleon/robot-operator","last_synced_at":"2025-03-17T21:46:34.841Z","repository":{"id":231030534,"uuid":"356005787","full_name":"LLLeon/robot-operator","owner":"LLLeon","description":"A Kubernetes Operator demo.","archived":false,"fork":false,"pushed_at":"2021-04-12T13:25:25.000Z","size":343,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-24T08:13:08.795Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LLLeon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-04-08T18:06:57.000Z","updated_at":"2021-04-12T13:25:27.000Z","dependencies_parsed_at":"2024-04-02T04:30:59.965Z","dependency_job_id":"9931ec36-0667-435f-b4a3-1886d0830a70","html_url":"https://github.com/LLLeon/robot-operator","commit_stats":null,"previous_names":["llleon/robot-operator"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLLeon%2Frobot-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLLeon%2Frobot-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLLeon%2Frobot-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LLLeon%2Frobot-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LLLeon","download_url":"https://codeload.github.com/LLLeon/robot-operator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244117224,"owners_count":20400741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T04:20:09.436Z","updated_at":"2025-03-17T21:46:34.818Z","avatar_url":"https://github.com/LLLeon.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# robot-operator\n\n## 0. 简介\n\nKubernetes Operator 通过 CRD + Controller 模式实现定制化需求，使得自定义资源可以像 Kubernetes 内置资源一样运行在集群中。\n\n架构图如下：\n\n![CustomController](https://github.com/LLLeon/robot-operator/blob/main/imgs/CustomController.png?raw=true)\n\n自定义控制器包括如下几个组件：\n\n- Client：与 API Server 进行通信的客户端，提供对 K8s 内置资源和自定义资源对象进行操作的方法（Get、List、Watch、Create 等）。\n- Informer：一个带有本地缓存和索引机制的、可以注册 EventHandler 的 client。它通过 Reflector 的 ListAndWatch 方法获取并监测对象实例的变化，具体做的是以下两个事情：\n  - 将事件类型（CRUD）及其对应的 API 对象（称为 Delta）放入 Delta FIFO 队列并缓存。Informer 还会不断从队列里面读取 Delta，根据其事件类型，创建或更新本地对象的缓存。\n  - 根据事件类型，触发 ResourceEventHandler，其实就是把 API 对象放入 WorkQueue。\n- WorkQueue：使得 Informer 和 Control Loop 两个逻辑可以解耦。\n- Control Loop：真正的业务逻辑，循环处理下面的事情：\n  - 从 WorkQueue 获取 API 对象（只有 key，形式为对象的 `\u003cnamespace\u003e/\u003cname\u003e`）。\n  - 根据 API 对象，通过各种资源的 Lister 方法从 Informer 维护的缓存拿到 API 对象。\n  - 将从缓存拿到的 API 对象（即期望状态）与集群中的实际状态进行对比，完成从实际状态向期望状态的转移。这在 K8s 中称为一次调谐（Reconcile）。\n\n对 client-go 和自定义控制器各组件的介绍还可以参考[这篇文档](https://github.com/kubernetes/sample-controller/blob/master/docs/controller-client-go.md)。\n\n这里使用 [code-generator](https://github.com/kubernetes/code-generator) 来为 CRD 资源生成代码，包括上面提到的：clientset、informers、listers 和自定义资源类型的 DeepCopy 方法。\n\n## 1. 初始化项目\n\n使用 go mod 初始化：\n\n```bash\n$ go mod init robot-operator\n$ go get k8s.io/apimachinery@v0.21.0\n$ go get k8s.io/client-go@v0.21.0\n$ go get k8s.io/code-generator@v0.21.0\n```\n\n## 2. 初始化 CRD 资源类型\n\n创建  `/pkg/api/robot/v1/doc.go`, `/pkg/api/robot/v1/types.go` 两个文件。\n\n## 3. 编写代码生成脚本\n\n创建 `/hack/tools.go`, `code-gen.sh` 两个文件。\n\n## 4. 生成代码\n\n```bash\n$ go mod vendor\n$ chmod -R 777 vendor\n$ cd hack \u0026\u0026 sh ./code-gen.sh\n```\n\n## 5. 注册资源类型\n\n创建 `/pkg/api/robot/v1/types.go` 文件，将自定义资源类型注册到 Scheme。\n\n\u003e 每一组 Controllers 都需要一个 Scheme，它解决 API 对象的序列化、反序列化与多版本 API 对象的兼容和转换问题，提供了 Kinds 与对应 Go types 的映射。\n\n## 6. Controller\n\n这里要编写控制循环的逻辑，先看一下 Controller 的结构：\n\n```go\ntype Controller struct {\n\tkubeClientset  kubernetes.Interface\n\trobotClientset clientset.Interface\n\n\tdeploymentsLister appslister.DeploymentLister\n\trobotsLister      robotlisters.RobotLister\n\n\tdeploymentsSynced cache.InformerSynced\n\trobotsSynced      cache.InformerSynced\n\n\tworkQueue workqueue.RateLimitingInterface\n\trecorder  record.EventRecorder\n}\n```\n\n基本上几个主要的组件都由 client-go 库实现了，简单说这里要实现的就是：\n\n- 向各种资源的 Informer 注册事件处理函数。\n- 不断从 workQueue 获取对象，将实际状态与期望状态做 diff，随后将实际状态向期望状态迁移。\n- 更新自定义资源的状态。\n\n## 7. 测试\n\n创建 CRD 和 CR：\n\n```bash\n$ kubectl apply -f ./artifacts/examples/crd.yaml\n$ kubectl apply -f ./artifacts/examples/robotone.yaml\n```\n\n此时可以成功获取到自定义的资源：\n\n```bash\n$ kubectl get crd\nNAME                     CREATED AT\nrobots.robot.llleon.io   2021-04-09T10:01:56Z\n\n$ kubectl get robot\nNAME        AGE\nrobot-one   3d3h\n```\n\n但由于还没有启动控制器，所以还未达到期望状态。\n\n编译好项目并启动：\n\n```bash\n$ ./robot-operator -kubeconfig=$HOME/.kube/config\n```\n\n此时再获取资源：\n\n```bash\n$ kubectl get deployment\nNAME        READY   UP-TO-DATE   AVAILABLE   AGE\nrobot-one   2/2     2            2           9m\n\n$ kubectl get pod\nNAME                         READY   STATUS    RESTARTS   AGE\nrobot-one-779b7cf75b-56q8f   1/1     Running   0          9m\nrobot-one-779b7cf75b-92wlq   1/1     Running   0          9m\n```\n\n可以看到达到了期望状态。\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllleon%2Frobot-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fllleon%2Frobot-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fllleon%2Frobot-operator/lists"}