查看控制器“拥有“的二级资源
在 Kubernetes 控制器中,通常会同时管理 主资源 和 次资源。主资源 是控制器负责的主要资源,而 次资源 是由控制器创建和管理,以支持 主资源。
在本节中,我们将解释如何管理由控制器“拥有“的 二级资源。这个例子将展示如何:
- 在主要资源(
Busybox
)和次要资源(Deployment
)之间设置所有者引用,以确保正确的生命周期管理。 - 将控制器配置为在
SetupWithManager()
中使用Owns()
监视次要资源。可以看到Deployment
由Busybox
控制器拥有,因为它将由该控制器创建和管理。
设置拥有者引用
要将次级资源(Deployment
)的生命周期与主资源(Busybox
)连接起来,我们需要在次级资源上设置一个 所有者引用。这确保了 Kubernetes 会自动处理层叠删除:如果主资源被删除,次级资源也会被删除。
Controller-runtime 提供了 controllerutil.SetControllerReference 函数,您可以使用它来设置资源之间的关系。
设置拥有者引用
下面,我们创建 Deployment
并使用 controllerutil.SetControllerReference()
在 Busybox
自定义资源和 Deployment
之间设置 Owner 引用。
// deploymentForBusybox 返回一个 Busybox 的 Deployment 对象
func (r *BusyboxReconciler) deploymentForBusybox(busybox *examplecomv1alpha1.Busybox) *appsv1.Deployment {
replicas := busybox.Spec.Size
dep := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: busybox.Name,
Namespace: busybox.Namespace,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": busybox.Name},
},
Template: metav1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": busybox.Name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "busybox",
Image: "busybox:latest",
},
},
},
},
},
}
// 设置 Deployment 的 ownerRef,确保在删除 Busybox CR 时,Deployment 也会被删除。 controllerutil.SetControllerReference(busybox, dep, r.Scheme)
return dep
}
Explanation
通过设置 OwnerReference
,如果 Busybox
资源被删除,Kubernetes 会自动删除 Deployment
。这还允许控制器监视 Deployment
的变化,并确保维护所需的状态(例如副本数)。
例如,如果有人修改了 Deployment
,将副本数更改为 3,而 Busybox
CR 定义的期望状态为 1 个副本,控制器将进行调整,确保 Deployment
缩减回 1 个副本。
对账函数示例
// Reconcile 处理 Busybox 和 Deployment 的主要调整循环。func (r *BusyboxReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := logf.FromContext(ctx)
// 获取 Busybox 实例 busybox := &examplecomv1alpha1.Busybox{}
if err := r.Get(ctx, req.NamespacedName, busybox); err != nil {
if apierrors.IsNotFound(err) {
log.Info("Busybox resource not found. Ignoring since it must be deleted")
return ctrl.Result{}, nil
}
log.Error(err, "Failed to get Busybox")
return ctrl.Result{}, err
}
// 检查部署是否已经存在,如果不存在则创建一个新的。 found := &appsv1.Deployment{}
err := r.Get(ctx, types.NamespacedName{Name: busybox.Name, Namespace: busybox.Namespace}, found)
if err != nil && apierrors.IsNotFound(err) {
// 定义一个新的部署 dep := r.deploymentForBusybox(busybox)
log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
if err := r.Create(ctx, dep); err != nil {
log.Error(err, "无法创建新的部署", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name)
return ctrl.Result{}, err
}
// 重新排队请求以确保创建部署 return ctrl.Result{RequeueAfter: time.Minute}, nil
} else if err != nil {
log.Error(err, "Failed to get Deployment")
return ctrl.Result{}, err
}
// 确保部署大小与期望状态匹配
size := busybox.Spec.Size
if *found.Spec.Replicas != size {
found.Spec.Replicas = &size
if err := r.Update(ctx, found); err != nil {
log.Error(err, "Failed to update Deployment size", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name)
return ctrl.Result{}, err
}
// 重新排队请求以确保达到正确的状态
return ctrl.Result{Requeue: true}, nil
}
// 更新 Busybox 状态以反映该部署可用 busybox.Status.AvailableReplicas = found.Status.AvailableReplicas
if err := r.Status().Update(ctx, busybox); err != nil {
log.Error(err, "Failed to update Busybox status")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}
观看辅助资源
为了确保对次要资源(例如 Deployment
)的更改能够触发对主要资源(Busybox
)的对账,我们配置控制器以监视这两个资源。
Owns()
方法允许您指定控制器应该监控的辅助资源。这样,控制器将在辅助资源发生变化(例如,被更新或删除)时自动调整主资源。
示例:配置 SetupWithManager
以监视辅助资源
// SetupWithManager 使用 Manager 设置控制器。
// 控制器将同时监视 Busybox 主资源和 Deployment 次资源。func (r *BusyboxReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&examplecomv1alpha1.Busybox{}). // 观看主要资源 Owns(&appsv1.Deployment{}). // 监视次要资源(部署)
Complete(r)
}
确保正确的权限
Kubebuilder 使用 标记 来定义控制器所需的 RBAC 权限。为了使控制器能够正确监视和管理主资源(Busybox
)和次资源(Deployment
),必须授予其适当的权限;即对这些资源具有 watch
、get
、list
、create
、update
和 delete
权限。
示例:RBAC 标记
在 Reconcile
方法之前,我们需要定义适当的 RBAC 标记。这些标记将由 controller-gen 在您运行 make manifests
时,用于生成所需的角色和权限。
// +kubebuilder:rbac:groups=example.com,resources=busyboxes,verbs=获取;列表;观察;创建;更新;补丁;删除
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=获取;列表;观察;创建;更新;补丁;删除
- 第一个标记授予控制器管理
Busybox
自定义资源(主要资源)的权限。 - 第二个标记授予控制器管理
Deployment
资源(次要资源)的权限。
请注意,我们正在授予对资源的 watch
权限。