返回

自定义 Kubernetes 资源的完全指南

闲谈

引言

Kubernetes 是一个功能强大的容器编排平台,它使您可以轻松管理容器化应用程序。Kubernetes 的强大功能之一是其可扩展性。您可以使用自定义资源定义 (CRD) 来扩展 Kubernetes 以管理自定义资源。

本指南将向您展示如何使用 CRD 和 controller 来扩展 Kubernetes。我们将从创建一个简单的 CRD 开始,然后我们将创建一个 controller 来管理 CRD。

创建 CRD

要创建 CRD,您需要创建一个 YAML 文件。该文件应包含以下信息:

  • apiVersion: Kubernetes API 的版本
  • kind: CRD 的类型
  • metadata: CRD 的元数据
  • spec: CRD 的规范

以下是创建 CRD 的示例 YAML 文件:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: mycrds.example.com
spec:
  group: example.com
  names:
    kind: MyCRD
    plural: mycrds
  scope: Namespaced
  versions:
  - name: v1
    served: true
    storage: true

要创建 CRD,请使用以下命令:

kubectl apply -f mycrd.yaml

创建 controller

要创建 controller,您需要创建一个 Go 文件。该文件应包含以下信息:

  • 包: controller 的包
  • import: controller 的导入
  • 类型: controller 的类型
  • 方法: controller 的方法

以下是创建 controller 的示例 Go 文件:

package controller

import (
	"context"

	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/record"
)

// Controller is a controller for MyCRD resources.
type Controller struct {
	clientset kubernetes.Interface
	recorder  record.EventRecorder
}

// NewController returns a new controller.
func NewController(clientset kubernetes.Interface) *Controller {
	c := &Controller{
		clientset: clientset,
	}

	// Create an event recorder.
	eventBroadcaster := record.NewBroadcaster()
	c.recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "mycrd-controller"})

	return c
}

// Run starts the controller.
func (c *Controller) Run(ctx context.Context) {
	// Create a new informer for MyCRD resources.
	informer := cache.NewSharedIndexInformer(
		&cache.ListWatch{
			ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
				return c.clientset.ExampleV1().MyCRDs(metav1.NamespaceAll).List(ctx, options)
			},
			WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
				return c.clientset.ExampleV1().MyCRDs(metav1.NamespaceAll).Watch(ctx, options)
			},
		},
		&examplev1.MyCRD{},
		0, // resync period
		cache.Indexers{}, // indexers
	)

	// Register the informer with the controller.
	c.clientset.ExampleV1().RESTClient().Get().AbsPath("/apis/example.com/v1").Do(ctx).StatusCode()

	// Start the informer.
	go informer.Run(ctx.Done())

	// Handle add and update events.
	informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: c.handleAdd,
		UpdateFunc: c.handleUpdate,
	})

	// Handle delete events.
	informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		DeleteFunc: c.handleDelete,
	})

	// Wait for the context to be done.
	<-ctx.Done()
}

// handleAdd handles the addition of a MyCRD resource.
func (c *Controller) handleAdd(obj interface{}) {
	mycrd := obj.(*examplev1.MyCRD)

	// Do something with the MyCRD resource.

	// Record an event.
	c.recorder.Event(mycrd, corev1.EventTypeNormal, "Created", "MyCRD created")
}

// handleUpdate handles the update of a MyCRD resource.
func (c *Controller) handleUpdate(oldObj, newObj interface{}) {
	oldMycrd := oldObj.(*examplev1.MyCRD)
	newMycrd := newObj.(*examplev1.MyCRD)

	// Do something with the MyCRD resource.

	// Record an event.
	c.recorder.Event(newMycrd, corev1.EventTypeNormal, "Updated", "MyCRD updated")
}

// handleDelete handles the deletion of a MyCRD resource.
func (c *Controller) handleDelete(obj interface{}) {
	mycrd, ok := obj.(*examplev1.MyCRD)
	if !ok {
		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
		if !ok {
			fmt.Printf("error decoding object, invalid type")
			return
		}
		mycrd, ok = tombstone.Obj.(*examplev1.MyCRD)
		if !ok {
			fmt.Printf("error decoding object tombstone, invalid type")
			return
		}
	}

	// Do something with the MyCRD resource.

	// Record an event.
	c.recorder.Event(mycrd, corev1.EventTypeNormal, "Deleted", "MyCRD deleted")
}

要创建 controller,请使用以下命令:

go build -o mycrd-controller main.go

部署 controller

要部署 controller,请使用以下命令:

kubectl apply -f mycrd-controller.yaml

使用 CRD 和 controller

要使用 CRD 和 controller,请按照以下步骤操作:

  1. 创建一个 MyCRD 资源。
  2. 查看 MyCRD 资源。
  3. 更新 MyCRD 资源。
  4. 删除 MyCRD 资源。

结论

在本指南中,我们向您展示了如何使用 CRD 和 controller 来扩展 Kubernetes。我们希望本指南对您有所帮助。