目录
1. Understand the Operator Pattern
2. Use Kubebuilder and controller-runtime
Install tools:
Create a new project:
3. Define Your Custom Resource
4. Implement the Reconciliation Logic
5. Add RBAC and Deploy
6. Best Practices
7. Testing
首页 后端开发 Golang 在GO中开发Kubernetes运营商

在GO中开发Kubernetes运营商

Jul 25, 2025 am 02:38 AM
go

编写Kubernetes Operator的最有效方式是使用Go语言结合Kubebuilder和controller-runtime。1. 理解Operator模式:通过CRD定义自定义资源,编写控制器监听资源变化并执行调和循环以维护期望状态。2. 使用Kubebuilder初始化项目并创建API,自动生成CRD、控制器和配置文件。3. 在api/v1/myapp_types.go中定义CRD的Spec和Status结构体,运行make manifests生成CRD YAML。4. 在控制器的Reconcile方法中实现业务逻辑,使用r.Create、r.Update等方法管理Kubernetes资源。5. 通过Go注解定义RBAC权限,使用make manifests和make docker-build构建镜像,并通过kubectl或make deploy部署。6. 遵循最佳实践:确保调和逻辑幂等,合理处理错误并使用RequeueAfter控制重试,添加日志与事件,必要时使用Finalizers和Webhooks。7. 使用envtest进行集成测试,fakeclient进行单元测试。最终,Operator开发的核心是定义CRD、编写调和逻辑、利用controller-runtime简化K8s交互,并通过成熟工具链完成测试与部署。

Developing Kubernetes Operators in Go

Writing Kubernetes Operators in Go is one of the most effective ways to extend the Kubernetes control plane for managing complex, stateful applications. An operator uses custom resources (CRs) and controllers to automate tasks that a human operator would otherwise perform—like backups, scaling, upgrades, and failover. Go is the natural choice because Kubernetes itself is written in Go, and the ecosystem (like client-go and controller-runtime) is mature and well-documented.

Developing Kubernetes Operators in Go

Here’s a practical guide to help you get started and understand the key components.


1. Understand the Operator Pattern

An Operator combines a Custom Resource Definition (CRD) with a controller that watches for changes to that resource and takes action to reconcile the desired state with the actual state of the cluster.

Developing Kubernetes Operators in Go
  • Custom Resource (CR): A YAML manifest defining your application’s desired state (e.g., MyAppDatabase).
  • Controller: A Go program that watches MyAppDatabase objects and manages Kubernetes resources (e.g., StatefulSets, Services) to match the spec.

This is based on the informer-pattern and reconciliation loop.


2. Use Kubebuilder and controller-runtime

The easiest way to build an operator in Go is using Kubebuilder, part of the Kubernetes SIGs, which scaffolds projects using controller-runtime—a library that handles low-level details like client setup, event handling, and reconciliation.

Developing Kubernetes Operators in Go

Install tools:

# Install kubebuilder
curl -L -O https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
tar -xzf kubebuilder_*_$(go env GOOS)_$(go  env GOARCH).tar.gz
sudo mv kubebuilder_*_$(go env GOOS)_$(go env GOARCH) /usr/local/kubebuilder
export PATH=$PATH:/usr/local/kubebuilder/bin

Create a new project:

mkdir myapp-operator
cd myapp-operator
kubebuilder init --domain example.com --repo example.com/myapp-operator
kubebuilder create api --group apps --version v1 --kind MyApp

This generates:

  • api/v1/myapp_types.go – Define your CRD schema.
  • controllers/myapp_controller.go – Where you write reconciliation logic.
  • config/ – Kustomize manifests for deploying CRD and RBAC.

3. Define Your Custom Resource

Edit api/v1/myapp_types.go:

type MyAppSpec struct {
    Replicas int32  `json:"replicas"`
    Image    string `json:"image"`
    Port     int32  `json:"port"`
}

type MyAppStatus struct {
    ReadyReplicas int32  `json:"readyReplicas"`
    Conditions    []metav1.Condition `json:"conditions,omitempty"`
}

Run make manifests to generate CRD YAML from Go annotations.


4. Implement the Reconciliation Logic

In controllers/myapp_controller.go, the Reconcile method is called whenever a MyApp resource changes.

func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    log := r.Log.WithValues("myapp", req.NamespacedName)

    var myapp MyApp
    if err := r.Get(ctx, req.NamespacedName, &myapp); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // Ensure a Deployment exists
    desiredDep := &appsv1.Deployment{
        ObjectMeta: metav1.ObjectMeta{
            Name:      myapp.Name,
            Namespace: myapp.Namespace,
        },
        Spec: appsv1.DeploymentSpec{
            Replicas: &myapp.Spec.Replicas,
            Selector: &metav1.LabelSelector{
                MatchLabels: map[string]string{"app": myapp.Name},
            },
            Template:corev1.PodTemplateSpec{
                ObjectMeta: metav1.ObjectMeta{
                    Labels: map[string]string{"app": myapp.Name},
                },
                Spec: corev1.PodSpec{
                    Containers: []corev1.Container{
                        {
                            Name:  "app",
                            Image: myapp.Spec.Image,
                            Ports: []corev1.ContainerPort{{ContainerPort: myapp.Spec.Port}},
                        },
                    },
                },
            },
        },
    }

    // Use controller-runtime's client to create or update
    if err := r.Create(ctx, desiredDep); err != nil {
        if !errors.IsAlreadyExists(err) {
            return ctrl.Result{}, err
        }
    }

    // Update status
    myapp.Status.ReadyReplicas = 0 // Update from actual deployment
    if err := r.Status().Update(ctx, &myapp); err != nil {
        return ctrl.Result{}, err
    }

    return ctrl.Result{}, nil
}

Use r.Create, r.Update, r.Patch, or r.Delete to manage objects.


5. Add RBAC and Deploy

Kubebuilder uses Go annotations to generate RBAC rules:

//  kubebuilder:rbac:groups=apps.example.com,resources=myapps,verbs=get;list;watch;create;update;patch;delete
//  kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//  kubebuilder:rbac:groups=core,resources=pods,verbs=list

Run:

make manifests
make docker-build IMG=myapp-operator:v0.0.1
kubectl apply -f config/crd/bases/apps.example.com_myapps.yaml
kubectl create deployment myapp-operator --image=myapp-operator:v0.0.1

Or use make deploy IMG=myapp-operator:v0.0.1 if using the default kustomize setup.


6. Best Practices

  • Idempotency: Reconcile loops may run multiple times—ensure operations are safe to repeat.
  • Error handling: Return errors to requeue; use ctrl.Result{RequeueAfter: time.Second} for periodic checks.
  • Logging & Events: Use r.Log and r.Recorder.Event() to emit Kubernetes events.
  • Finalizers: Use them when you need to perform cleanup before a CR is deleted.
  • Webhooks: Add validation (ValidatingAdmissionWebhook) or defaults (MutatingAdmissionWebhook) via kubebuilder create webhook.

7. Testing

  • Use envtest for integration tests that start etcd and kube-apiserver locally.
  • Write unit tests for your reconciliation logic using fakeclient.

Example test setup:

import (
    "sigs.k8s.io/controller-runtime/pkg/envtest"
)

var testEnv *envtest.Environment

Basically, building Kubernetes Operators in Go boils down to:

  • Defining a CRD with kubebuilder
  • Writing a controller that reconciles desired vs. actual state
  • Using controller-runtime to handle Kubernetes interactions
  • Testing with envtest and deploying with standard manifests

It’s not trivial, but the tooling has matured a lot—Kubebuilder and controller-runtime do most of the heavy lifting. Start small, automate one thing well, and expand from there.

以上是在GO中开发Kubernetes运营商的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

Rimworld Odyssey如何钓鱼
1 个月前 By Jack chen
Kimi K2:最强大的开源代理模型
1 个月前 By Jack chen
我可以有两个支付帐户吗?
1 个月前 By 下次还敢

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Laravel 教程
1602
29
PHP教程
1506
276
GO应用程序的标准项目布局是什么? GO应用程序的标准项目布局是什么? Aug 02, 2025 pm 02:31 PM

答案是:Go应用没有强制项目布局,但社区普遍采用一种标准结构以提升可维护性和扩展性。1.cmd/存放程序入口,每个子目录对应一个可执行文件,如cmd/myapp/main.go;2.internal/存放私有代码,不可被外部模块导入,用于封装业务逻辑和服务;3.pkg/存放可公开复用的库,供其他项目导入;4.api/可选,存放OpenAPI、Protobuf等API定义文件;5.config/、scripts/、web/分别存放配置文件、脚本和Web资源;6.根目录包含go.mod和go.sum

您如何在Go中逐行读取文件? 您如何在Go中逐行读取文件? Aug 02, 2025 am 05:17 AM

使用bufio.Scanner是Go中逐行读取文件最常见且高效的方法,适用于处理大文件、日志解析或配置文件等场景。1.使用os.Open打开文件并确保通过deferfile.Close()关闭文件。2.通过bufio.NewScanner创建扫描器实例。3.在for循环中调用scanner.Scan()逐行读取,直到返回false表示到达文件末尾或出错。4.使用scanner.Text()获取当前行内容(不含换行符)。5.循环结束后检查scanner.Err()以捕获可能的读取错误。此方法内存效

您如何使用诸如if-else in go中的条件语句? 您如何使用诸如if-else in go中的条件语句? Aug 02, 2025 pm 03:16 PM

Go中的if-else语句无需括号但必须使用花括号,支持在if中初始化变量以限制作用域,可通过elseif链式判断条件,常用于错误检查,且变量声明与条件结合可提升代码简洁性与安全性。

您如何在GO中解析命令行旗帜? 您如何在GO中解析命令行旗帜? Aug 02, 2025 pm 04:24 PM

Go的flag包可轻松解析命令行参数,1.使用flag.Type()定义字符串、整型、布尔等类型标志;2.可通过flag.TypeVar()将标志解析到变量避免指针操作;3.调用flag.Parse()后,用flag.Args()获取后续位置参数;4.实现flag.Value接口可支持自定义类型,满足多数简单CLI需求,复杂场景可用spf13/cobra库替代。

Go Run命令做什么? Go Run命令做什么? Aug 03, 2025 am 03:49 AM

gorun是一个用于快速编译并执行Go程序的命令,1.它在一步中完成编译和运行,生成临时可执行文件并在程序结束后删除;2.适用于包含main函数的独立程序,便于开发和测试;3.支持多文件运行,可通过gorun*.go或列出所有文件执行;4.自动处理依赖,利用模块系统解析外部包;5.不适用于库或包,且不生成持久化二进制文件,因此适合脚本、学习和频繁修改时的快速测试,是一种高效、简洁的即时运行方式。

您如何处理GO Web应用程序中的路由? 您如何处理GO Web应用程序中的路由? Aug 02, 2025 am 06:49 AM

Go应用中的路由选择取决于项目复杂度,1.使用标准库net/httpServeMux适合简单应用,无需外部依赖且轻量,但不支持URL参数和高级匹配;2.第三方路由器如Chi提供中间件、路径参数和嵌套路由,适合模块化设计;3.Gin性能优异,内置JSON处理和丰富功能,适合API和微服务。应根据是否需要灵活性、性能或功能集成来选择,小型项目用标准库,中大型项目推荐Chi或Gin,最终实现从简单到复杂的平滑扩展。

您如何在Go中宣布常数? 您如何在Go中宣布常数? Aug 02, 2025 pm 04:21 PM

在Go中,常量使用const关键字声明,且值不可更改,可为无类型或有类型;1.单个常量声明如constPi=3.14159;2.块内多个常量声明如const(Pi=3.14159;Language="Go";IsCool=true);3.显式类型常量如constSecondsInMinuteint=60;4.使用iota生成枚举值,如const(Sunday=iota;Monday;Tuesday)将依次赋值0、1、2,且iota可用于位运算等表达式;常量必须在编译时确定值,

如何在GO中连接到SQL数据库? 如何在GO中连接到SQL数据库? Aug 03, 2025 am 09:31 AM

要连接Go中的SQL数据库,需使用database/sql包和特定数据库驱动。1.导入database/sql包和驱动(如github.com/go-sql-driver/mysql),注意驱动前加下划线表示仅用于初始化;2.使用sql.Open("mysql","user:password@tcp(localhost:3306)/dbname")创建数据库句柄,并调用db.Ping()验证连接;3.使用db.Query()执行查询,db.Exec()执行

See all articles