答案是使用controller-runtime框架开发kubernetes operator能显著简化开发并确保遵循最佳实践。该框架由kubernetes官方维护,提供了manager、controller、reconciler、client和scheme等核心组件,封装了api交互、事件监听、缓存同步等底层细节,开发者只需专注于实现业务逻辑的reconcile方法,且其设计强制幂等性,保障了系统的可靠性与一致性,因此成为go语言下构建operator的事实标准。

用Golang编写Kubernetes Operator,并深入理解
controller-runtime
controller-runtime
Kubernetes Operator本质上是遵循控制器模式的应用程序,它通过扩展Kubernetes API来管理自定义资源(Custom Resources, CRs)。当我们谈论用Go语言编写Operator时,
controller-runtime
kubebuilder
一个Operator的核心工作流程是:
立即学习“go语言免费学习笔记(深入)”;
controller-runtime
controller.Builder
MyApplication
MyApplication
Deployment
Service
Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
controller-runtime
NamespacedName
ctrl.Request
controller-runtime
client.Client
Get
List
Create
Update
Delete
runtime.Scheme
编写一个Operator,我们通常会从定义CRD开始,然后用Go结构体表示这个CRD,接着实现Reconciler的逻辑,最后在
main
controller-runtime
选择
controller-runtime
首先,它极大地简化了开发复杂度。回想一下,如果没有这样的框架,你需要自己去处理Kubernetes API的连接、认证、事件监听、缓存同步、领导者选举(leader election),以及更细致的错误处理和重试机制。这些东西本身就是一套复杂的分布式系统编程挑战。
controller-runtime
其次,它是Kubernetes社区的“亲儿子”。
controller-runtime
再者,它的模块化和可扩展性做得很好。你可以轻松地添加多个控制器来管理不同的资源,也可以集成Webhook来实现准入控制或验证。这种设计使得大型Operator的开发和维护变得更加有序。比如,我常常会发现,一个复杂的Operator可能需要管理多种自定义资源,或者与多种内置资源交互,
controller-runtime
最后,它强制你思考“幂等性”。
controller-runtime
所以,与其说为什么选择它,不如说,在Go语言生态下开发Kubernetes Operator,
controller-runtime
要真正用好
controller-runtime
1. Manager (管理器)
Manager是整个Operator的“管家”。当你的Operator启动时,你首先会创建一个
Manager
client.Client
runtime.Scheme
2. Controller (控制器) 与 Reconciler (协调器)
这是Operator的核心执行单元。
controller.Builder
For(&v1alpha1.MyResource{})MyResource
Watches(&source.Kind{Type: &appsv1.Deployment{}}, &handler.EnqueueRequestForOwner{OwnerType: &v1alpha1.MyResource{}, Is </owner>Controller: true})MyResource
Deployment
Deployment
MyResource
Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
NamespacedName
ctrl.Request
Request
Reconcile
Reconcile
client.Get()
Request
Status
Reconcile
ctrl.Result
error
ctrl.Result{Requeue: true}Request
ctrl.Result{RequeueAfter: someDuration}Request
nil, err
controller-runtime
ctrl.Result{}, nil3. Client (客户端)
client.Client
Get
List
Create
Update
Delete
controller-runtime
client.Client
4. Scheme (类型注册)
runtime.Scheme
MyResource
Scheme
controller-runtime
5. Informer/Cache (信息器/缓存)
这是
controller-runtime
SharedInformer
Reconcile
client.Get()
理解这些组件如何协同工作,能帮助你更好地设计Operator的逻辑,优化性能,并有效地调试问题。当你遇到资源状态与预期不符时,你就会知道是Reconciler的逻辑问题,还是缓存同步延迟,或者更深层次的API通信问题。
我们来构建一个非常简单的Operator,它管理一个名为
MyApplication
MyApplication
Deployment
1. 定义CRD (Custom Resource Definition)
首先,我们需要定义
MyApplication
# config/crd/bases/example.com_myapplications.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myapplications.example.com
spec:
group: example.com
names:
kind: MyApplication
listKind: MyApplicationList
plural: myapplications
singular: myapplication
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
image:
type: string
description: The container image to deploy.
replicas:
type: integer
format: int32
description: Number of desired replicas.
minimum: 1
required:
- image
- replicas
status:
type: object
properties:
availableReplicas:
type: integer
format: int32
description: Total number of available pods (ready for at least minReadySeconds).
phase:
type: string
description: Current phase of the application (e.g., "Pending", "Running", "Failed").2. 定义Go类型
接下来,我们需要在Go代码中定义与CRD对应的结构体。
// api/v1alpha1/myapplication_types.go
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// MyApplicationSpec defines the desired state of MyApplication
type MyApplicationSpec struct {
Image string `json:"image"`
Replicas int32 `json:"replicas"`
}
// MyApplicationStatus defines the observed state of MyApplication
type MyApplicationStatus struct {
AvailableReplicas int32 `json:"availableReplicas"`
Phase string `json:"phase"`
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// MyApplication is the Schema for the myapplications API
type MyApplication struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MyApplicationSpec `json:"spec,omitempty"`
Status MyApplicationStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// MyApplicationList contains a list of MyApplication
type MyApplicationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []MyApplication `json:"items"`
}
func init() {
SchemeBuilder.Register(&MyApplication{}, &MyApplicationList{})
}+kubebuilder:object:root=true
+kubebuilder:subresource:status
kubebuilder
3. 实现Reconciler逻辑
这是Operator的核心。我们需要创建一个
MyApplicationReconciler
Reconcile
// internal/controller/myapplication_controller.go
package controller
import (
"context"
"fmt"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
examplev1alpha1 "your.domain/my-operator/api/v1alpha1" // 替换为你的模块路径
)
// MyApplicationReconciler reconciles a MyApplication object
type MyApplicationReconciler struct {
client.Client
Scheme *runtime.Scheme // 假设这里已经通过 Manager 传入了 Scheme
}
//+kubebuilder:rbac:groups=example.com,resources=myapplications,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=example.com,resources=myapplications/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=example.com,resources=myapplications/finalizers,verbs=update
//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
func (r *MyApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
// 1. 获取 MyApplication 实例
myApp := &examplev1alpha1.MyApplication{}
err := r.Get(ctx, req.NamespacedName, myApp)
if err != nil {
if errors.IsNotFound(err) {
// MyApplication 对象已被删除,忽略。
logger.Info("MyApplication resource not found. Ignoring since object must be deleted.")
return ctrl.Result{}, nil
}
// 获取资源时发生错误,重新排队。
logger.Error(err, "Failed to get MyApplication")
return ctrl.Result{}, err
}
// 2. 定义期望的 Deployment
desiredDeployment := r.newDeploymentForMyApplication(myApp)
// 3. 检查 Deployment 是否存在
foundDeployment := &以上就是如何用Golang编写Kubernetes Operator 详解controller-runtime框架的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号