天天看點

帶你讀《雲原生應用開發 Operator原理與實踐》第一章引言1.2Operator 介紹(五)

(4)  修改 Controller邏輯

在 Controller中需要通過Reconcile方法完成 Deployment和 Service 部署,并最終達到期望的狀态。

Controller中的代碼見代碼清單 1-11,我們需要在其中加入業務邏輯。

// +kubebuilder:rbac:groups=webapp.demo.welcome.domain,resources=welcomes,ver-bs=get;list;watch;create;update;patch;delete

//+kubebuilder:rbac:groups=webapp.demo.welcome.domain,resources=welcomes/status,verbs=get;update;patch

//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=list;watch;get;patch;create;update

//+kubebuilder:rbac:groups=core,resources=services,verbs=list;watch;get;patch;create;update

func(r*WelcomeReconciler)Reconcile(reqctrl.Request)(ctrl.Result,error){

ctx:=context.Background()

log:=r.Log.WithValues("welcome",req.NamespacedName)log.Info("reconcilingwelcome")

此處有兩組“+”辨別,第一組用于Operator更新Welcome資源對象,第二組用于建立Deployment和 Service。接下來完成 Welcome類型控制器的部分代碼的實作(見代碼清單1-12)。

deployment,err:=r.createWelcomeDeployment(welcome)iferr!=nil{

returnctrl.Result{},err

}

log.Info("createdeploymentsuccess!")

svc,err:=r.createService(welcome)iferr!=nil{

log.Info("createservicesuccess!")

applyOpts:=[]client.PatchOption{client.ForceOwnership,client.

FieldOwner("welcome_controller")}

err=r.Patch(ctx,&deployment,client.Apply,applyOpts...)

iferr!=nil{

err=r.Patch(ctx,&svc,client.Apply,applyOpts...)iferr!=nil{

在控制器部分需要完成 Deployment和 Service 的建立,并完成兩者的關聯,在上述代碼中,我們分别通過調用createWelcomeDeployment和 createService方法完成對象的建立,接下來我們完成上述方法的具體實作(見代碼清單1-13)。

func(r*WelcomeReconciler)createWelcomeDeployment(welcomewebappv1.Welcome)(appsv1.Deployment,error){

defOne:=int32(1)

name:=welcome.Spec.Nameifname==""{

name="world"

depl:=appsv1.Deployment{

TypeMeta:metav1.TypeMeta{APIVersion:appsv1.SchemeGroupVersion.

String(),Kind:"Deployment"},

ObjectMeta:metav1.ObjectMeta{Name:welcome.Name,Namespace:welcome.Namespace,

},

Spec:appsv1.DeploymentSpec{Replicas:&defOne,

Selector:&metav1.LabelSelector{

MatchLabels:map[string]string{"welcome":welcome.Name},

Template:corev1.PodTemplateSpec{ObjectMeta:metav1.ObjectMeta{

Labels:map[string]string{"welcome":welcome.Name},

Spec:corev1.PodSpec{

Containers:[]corev1.Container{

{

Name:"welcome",

Env:[]corev1.EnvVar{

{Name:"NAME",Value:name},

Protocol:"TCP"},

Ports:[]corev1.ContainerPort{

{ContainerPort:8080,Name:"http",

Image:"sdfcdwefe/operatordemo:v1",Resources:corev1.ResourceRequirements{

Requests:corev1.ResourceList{corev1.ResourceCPU:   *resource.

NewMilliQuantity(100, resource.DecimalSI),NewMilliQuantity(100000,resource.BinarySI),

corev1.ResourceMemory:*resource.

在上述代碼中,我們在 Deployment使用了之前制作的 Docker鏡像,将 Types中獲得的 NAME字段作為環境變量傳入鏡像中,在鏡像執行 main函數時,即可獲得 NAME字段并修改 index檔案,在檔案中插入 NAME,并預設開啟 8080監聽端口,使用者通過Web通路時即可獲得最終的期望值。

接下來,我們完成Service部分代碼的實作(見代碼清單1-14)。

func(r*WelcomeReconciler)createService(welcomewebappv1.Welcome)(corev1.Service,error){

svc:=corev1.Service{

TypeMeta:metav1.TypeMeta{APIVersion:corev1.SchemeGroupVersion.

String(),Kind:"Service"},

Spec:corev1.ServiceSpec{

Ports:[]corev1.ServicePort{

{Name:"http",Port:8080,Protocol:"TCP",TargetPort:

intstr.FromString("http")},

Selector:map[string]string{"welcome":welcome.Name},Type:        corev1.ServiceTypeLoadBalancer,

在本例中,我們建立了 LoadBalancer類型的 Service。通過kubectlgetsvc指令可以擷取 URL位址,也可以通路 Web應用。