安裝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: nginxname: application-samplenamespace: default
spec:replicas: 3template:spec:containers:- name: nginximage: nginx:1.14.2ports:- 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 controllerimport ("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-operatordappsv1 "github.com/daniel-hutao/application-operator/api/v1"
)// ApplicationReconciler reconciles a Application object
type ApplicationReconciler struct {client.ClientScheme *runtime.Scheme
}func (r *ApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {l := log.FromContext(ctx)//聲明一個*Application類型的實例app用了接收我們的crapp := &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等 這時候需要打印錯誤信息,然后返回這個錯誤以及一分鐘后重試的resultl.Error(err, "failed to get the Application")return ctrl.Result{RequeueAfter: 1 * time.Minute}, err}//create podsfor 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/perks@v1.0.1: 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