kubebuilder开发operator

安装kubebuilder前 需要有kubernetes环境和golang环境
官网:https://go.kubebuilder.io/
安装kubebuilder

#下载
wget https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH) 
#改名kubebuilder后加权限
chmod +x kubebuilder
#放到环境变量里
mv kubebuilder /usr/local/bin/
#查看版本
kubebuilder version

创建operator项目

#先创建go mod 项目
go mod init application
#始化 repo 指定的是 module path, 如果项目目录不在 GOPATH 中, 是必须的 
kubebuilder init --domain=danielhu.cn --repo=github.com/daniel-hutao/application-operator --owner Daniel.Hu
#或者不加--repo直接初始化 模块名以go mod init application 的名字为当前module path
kubebuilder init --domain=my.operator.cn
#创建api资源注意:--kind Application 首字母必须大写 否则创建失败
kubebuilder create api --group apps --version v1 --kind Application
#修改玩相关配置代码后进行安装构建
#生成和更新
make manifests
#安装构建 直接部署的k8s集群中
make install
#查看crd
kubectl get crd
#查看资源
kubectl get application -A
#创建资源示例 application.samples.yaml
apiVersion: apps.danielhu.cn/v1
kind: Application
metadata:
  labels:
    app: nginx
  name: application-sample
  namespace: default
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: nginx
          image: nginx:1.14.2
          ports:
            - containerPort: 80
#创建
kubectl apply -f application.samples.yaml           
#查看 此时还没有对应controller来处理 所以只有资源 没有对应的pod
kubectl get application -A 

controller实现
此版本的(KubeBuilderVersion:“3.13.0”)kubebuilder controller文件夹在:internal/controller 之前版本直接在:controller

#修改controller/application_controller.go文件
package controller

import (
	"context"
	"fmt"
	"time"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	"k8s.io/apimachinery/pkg/runtime"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/log"

	//对应kubebuilder init --repo=github.com/daniel-hutao/application-operator
	dappsv1 "github.com/daniel-hutao/application-operator/api/v1"
)

// ApplicationReconciler reconciles a Application object
type ApplicationReconciler struct {
	client.Client
	Scheme *runtime.Scheme
}


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

	//声明一个*Application类型的实例app用了接收我们的cr
	app := &dappsv1.Application{}
	if err := r.Get(ctx, req.NamespacedName, app); err != nil {
		//err分很多种情况,如果找不到,一般不需要处理 只说明这个cr被删除了
		if errors.IsNotFound(err) {
			l.Info("the Application is not fount")
			//直接返回,不带错误,结束本次调谐
			return ctrl.Result{}, nil
		}
		//除了NotFound之外的错误,比如连不上apiserver等 这时候需要打印错误信息,然后返回这个错误以及一分钟后重试的result
		l.Error(err, "failed to get the Application")
		return ctrl.Result{RequeueAfter: 1 * time.Minute}, err
	}
	//create pods
	for i := 0; i < int(app.Spec.Replicas); i++ {
		pod := &corev1.Pod{
			ObjectMeta: metav1.ObjectMeta{
				Name:      fmt.Sprintf("%s-%d", app.Name, i),
				Namespace: app.Namespace,
				Labels:    app.Labels,
			},
			Spec: app.Spec.Template.Spec,
		}
		if err := r.Create(ctx, pod); err != nil {
			l.Error(err, "failed to create Pod")
			return ctrl.Result{RequeueAfter: 1 * time.Minute}, err
		}
		l.Info(fmt.Sprintf("the Pod (%s) has created", pod.Name))
	}
	l.Info("all pods has created")
	return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *ApplicationReconciler) SetupWithManager(mgr ctrl.Manager) error {
	return ctrl.NewControllerManagedBy(mgr).
		For(&dappsv1.Application{}).
		Complete(r)
}

运行

#直接运行
make run
#查看pod是否创建
kubectl get pod 

把controller打包后容器化方式部署到kubectlnetes集群中

#构建镜像 如果是golang的镜像 建议先在dockerfile内增加ENV GOPROXY=https://goproxy.io 否则会下载镜像失败
#注意 在master构建镜像 还需要把镜像安装到节点上 因为不知道会调度到那个节点 所以部署的时候 看调度到那个节点 就需要把镜像传到对应节点 否则部署失败
make docker-build IMG=application-operator:v0.0.1
#部署控制器
make deploy IMG=application-operator:v0.0.1
#查看
kubectl get pod -n application-operator-system
#卸载controller
make undeploy
#卸载crd
make uninstall

构建是出现的问题:

#1.依赖下载失败的问题:
339.1 go: github.com/beorn7/[email protected]: Get "https://proxy.golang.org/github.com/beorn7/perks/@v/v1.0.1.mod": dial tcp 142.251.43.17:443: connect: connection refused
#Dockerfile内增加如下代理
ENV GOPROXY=https://goproxy.io
#2.base镜像下载失败 报错:
ERROR: failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: failed to do request: Head "https://gcr.io/v2/distroless/static/manifests/nonroot": dial tcp 74.125.23.82:443: connect: connection refused
#处理:我们可以在国内镜像下载 然后换tag
docker pull kubeimages/distroless-static
docker tag kubeimages/distroless-static:latest gcr.io/distroless/static:nonroot 
#问题3 创建pod提示下载镜像错误 原因是此pod调度单node节点 节点上没有刚才构建的镜像 
#解决方法 把镜像下载 在传到节点上
#master下载镜像
docker save -o operator.tar application-operator:v0.0.1
#node节点载入镜像
docker load -i operator.tar 

你可能感兴趣的:(kubernetes,云原生)