kubebuilder

一、环境准备

1、容器环境

docker run -itd --name go_dev -w /go/src -v /go_src:/go/src/ golang:1.17.6 bash
docker exec -it go_dev bash

2、安装kubebuilder

curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)
chmod +x kubebuilder && mv kubebuilder /usr/local/bin/

3、设置 goproxy

go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct

4、编译环境(可选)

FROM golang:1.17.6

ARG http_proxy=http://192.168.0.1:1080
ENV http_proxy=$http_proxy
ENV https_proxy=$http_proxy

WORKDIR /go/src

RUN curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH) && \
    chmod +x kubebuilder && mv kubebuilder /usr/local/bin/ && \
    go env -w GO111MODULE=on && go env -w GOPROXY=https://goproxy.cn,direct
docker build -t crd_dev_golang1.17.6:1.0.0 .
## 开发环境
docker run -itd --name crd_dev -w /go/src -v /crd_rtc:/go/src/ 192.168.0.90:3000/amd64/crd_dev_golang1.17.6:1.0.0
docker exec -it crd_dev bash

## 运行
make manifests
make install
make run

## 创建实例
kubectl apply -f rt.yaml

二、开发

1、初始化项目

go mod init rtcontainer
kubebuilder init --domain rtcontainer.io
kubebuilder create api --group rt --version v1 --kind RTContainer

2、添加类型

api/v1/rtcontainer_types.go

type RootAgent struct {
    IP   string `json:"ip,omitempty"`
    Port string `json:"port,omitempty"`
    NFS  string `json:"nfs,omitempty"`
}

type RTContainerSpec struct {
    RootAgent []RootAgent `json:"rootagent,omitempty"`
    Action    string      `json:"action,omitempty"`
    Image     string      `json:"image,omitempty"`
    Name      string      `json:"name,omitempty"`
    Replicas  *int32      `json:"replicas,omitempty"`
}

3、编写controller

delete ?

// +kubebuilder:rbac:groups=crd.crd.RTContainer.io,resources=RTContainers,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=crd.crd.RTContainer.io,resources=RTContainers/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=crd.crd.RTContainer.io,resources=RTContainers/finalizers,verbs=update

add

    appsv1 "k8s.io/api/apps/v1"
    corev1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    rtv1 "rtcontainer/api/v1"

func (r *RTContainerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    _ = log.FromContext(ctx)

    // TODO(user): your logic here

    RTContainer := &rtv1.RTContainer{}
    if err := r.Client.Get(ctx, req.NamespacedName, RTContainer); err != nil {
        if errors.IsNotFound(err) {
            log.Log.Info("RTContainer resource not found, skipping reconcile")
            return ctrl.Result{}, nil
        }
        return ctrl.Result{}, nil
    }

    //资源标记为删除
    if RTContainer.DeletionTimestamp != nil {
        log.Log.Info("RTContainer in deleting", "name", req.String())
        return ctrl.Result{}, nil
    }

    if err := r.CreateDeployRTContainer(ctx, RTContainer); err != nil {
        log.Log.Error(err, "failed to Create rtcontainer", "name", req.String())
        return ctrl.Result{}, nil
    }

    return ctrl.Result{}, nil
}

func (r *RTContainerReconciler) CreateDeployRTContainer(ctx context.Context, obj *rtv1.RTContainer) error {
    logger := log.FromContext(ctx)

    RTContainer := obj.DeepCopy()
    name := types.NamespacedName{
        Namespace: RTContainer.Namespace,
        Name:      RTContainer.Name,
    }
    // 构造owner
    owner := []metav1.OwnerReference{
        {
            APIVersion:         RTContainer.APIVersion,
            Kind:               RTContainer.Kind,
            Name:               RTContainer.Name,
            Controller:         pointer.BoolPtr(true),
            BlockOwnerDeletion: pointer.BoolPtr(true),
            UID:                RTContainer.UID,
        },
    }
    labels := map[string]string{"app": obj.Name}
    selector := &metav1.LabelSelector{MatchLabels: labels}

    meta := metav1.ObjectMeta{
        Name:            RTContainer.Name,
        Namespace:       RTContainer.Namespace,
        Labels:          labels,
        OwnerReferences: owner,
    }
    // 获取对应deployment, 如不存在则创建
    deploy := &appsv1.Deployment{}
    if err := r.Get(ctx, name, deploy); err != nil {
        if !errors.IsNotFound(err) {
            return err
        }

        deploy = &appsv1.Deployment{
            ObjectMeta: meta,
            Spec: appsv1.DeploymentSpec{
                Replicas: RTContainer.Spec.Replicas,
                Selector: selector,
                Template: corev1.PodTemplateSpec{
                    ObjectMeta: metav1.ObjectMeta{
                        Labels: labels,
                    },
                    Spec: corev1.PodSpec{
                        Containers: newContainers(RTContainer),
                    },
                },
            },
        }

        if err := r.Create(ctx, deploy); err != nil {
            return err
        }
        logger.Info("Create deployment successfully.", "name", name.String())
    }
    return nil
}

func newContainers(app *rtv1.RTContainer) []corev1.Container {
    return []corev1.Container{
        {
            Name:            app.Name,
            Image:           app.Spec.Image,
            ImagePullPolicy: corev1.PullIfNotPresent,
        },
    }
}

4、编译CRD,更新字段

make manifests

cat config/crd/bases/rt.rtcontainer.io_rtcontainers.yaml

5、安装kustomize

curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
mv kustomize bin/

6、安装、运行

make install
make run

7、运行实例

apiVersion: rt.rtcontainer.io/v1
kind: RTContainer
metadata:
  name: rt1
spec:
  rootagent:
  -  ip: "192.168.2.2"
     port: "8888"
     nfs: "/mount/fatfs_C/nfs_root"
  action: "Create"
  image: vm1:1.0
  replicas: 1

results matching ""

    No results matching ""