(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{
returnctrl.Result{},err
}
log.Info("createservicesuccess!")
applyOpts:=[]client.PatchOption{client.ForceOwnership,client.
FieldOwner("welcome_controller")}
err=r.Patch(ctx,&deployment,client.Apply,applyOpts...)
iferr!=nil{
returnctrl.Result{},err
}
err=r.Patch(ctx,&svc,client.Apply,applyOpts...)iferr!=nil{
returnctrl.Result{},err
}
在控制器部分需要完成 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"},
ObjectMeta:metav1.ObjectMeta{Name:welcome.Name,Namespace:welcome.Namespace,
},
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应用。