mirror of
https://gitee.com/devstar/devstar-devcontainer-operator
synced 2025-09-16 03:31:07 +00:00
优化 DevcontainerApp Reconciler 逻辑:
- 将 NodePort 调度结果放在 app.Status 域,避免修改 Spec 导致 NodePort Service 重复创建 - 将 namespace 修改成 devstar-studio-ns,防止后期整合 RBAC 遇到问题 - 增加 label devstar-resource-type=devstar-devcontainer
This commit is contained in:
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
devcontainer_v1 "devstar.cn/DevcontainerApp/api/v1"
|
||||
devcontainer_controller_utils "devstar.cn/DevcontainerApp/internal/controller/utils"
|
||||
app_v1 "k8s.io/api/apps/v1"
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
core_v1 "k8s.io/api/core/v1"
|
||||
k8s_sigs_controller_runtime_utils "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
)
|
||||
@@ -57,10 +57,11 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
logger := log.FromContext(ctx)
|
||||
var err error
|
||||
|
||||
// 1. 读取缓存中的 app
|
||||
// 1. 读取缓存中的 DevcontainerApp
|
||||
app := &devcontainer_v1.DevcontainerApp{}
|
||||
err = r.Get(ctx, req.NamespacedName, app)
|
||||
if err != nil {
|
||||
// 当 CRD 资源 “DevcontainerApp” 被删除后,直接返回空结果,跳过剩下步骤
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
}
|
||||
|
||||
// 2.2 查找 集群中同名称的 StatefulSet
|
||||
statefulSetInNamespace := &app_v1.StatefulSet{}
|
||||
statefulSetInNamespace := &apps_v1.StatefulSet{}
|
||||
err = r.Get(ctx, req.NamespacedName, statefulSetInNamespace)
|
||||
if err != nil {
|
||||
if !errors.IsNotFound(err) {
|
||||
@@ -84,14 +85,15 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
logger.Error(err, "Failed to create StatefulSet")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
}
|
||||
// 这里会反复触发更新
|
||||
// 原因:在 SetupWithManager方法中,监听了 StatefulSet ,所以只要更新 StatefulSet 就会触发
|
||||
// 此处更新和 controllerManager 更新 StatefulSet 都会触发更新事件,导致循环触发
|
||||
//修复方法:加上判断条件,仅在 app.Spec.StatefulSet.Image != statefulSet.Spec.Template.Spec.Containers[0].Image 时才更新 StatefulSet
|
||||
if app.Spec.StatefulSet.Image != statefulSet.Spec.Template.Spec.Containers[0].Image {
|
||||
if err := r.Update(ctx, statefulSet); err != nil {
|
||||
return ctrl.Result{}, err
|
||||
} else {
|
||||
// 这里会反复触发更新
|
||||
// 原因:在 SetupWithManager方法中,监听了 StatefulSet ,所以只要更新 StatefulSet 就会触发
|
||||
// 此处更新和 controllerManager 更新 StatefulSet 都会触发更新事件,导致循环触发
|
||||
//修复方法:加上判断条件,仅在 app.Spec.StatefulSet.Image != statefulSet.Spec.Template.Spec.Containers[0].Image 时才更新 StatefulSet
|
||||
if app.Spec.StatefulSet.Image != statefulSet.Spec.Template.Spec.Containers[0].Image {
|
||||
if err := r.Update(ctx, statefulSet); err != nil {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,19 +102,27 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
if err := k8s_sigs_controller_runtime_utils.SetControllerReference(app, service, r.Scheme); err != nil {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
serviceInNamespace := &core_v1.Service{}
|
||||
err = r.Get(ctx, types.NamespacedName{Name: app.Name, Namespace: app.Namespace}, serviceInNamespace)
|
||||
serviceInCluster := &core_v1.Service{}
|
||||
err = r.Get(ctx, types.NamespacedName{Name: app.Name, Namespace: app.Namespace}, serviceInCluster)
|
||||
if err != nil {
|
||||
if !errors.IsNotFound(err) {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
err = r.Create(ctx, service)
|
||||
if err != nil && !errors.IsAlreadyExists(err) {
|
||||
logger.Error(err, "create service failed")
|
||||
if err == nil {
|
||||
// 创建 NodePort Service 成功只执行一次 ==> 将NodePort 端口分配信息更新到 app.Status
|
||||
logger.Info("[DevStar][DevContainer] NodePort Assigned", "nodePortAssigned", service.Spec.Ports[0].NodePort)
|
||||
|
||||
app.Status.NodePortAssigned = uint16(service.Spec.Ports[0].NodePort)
|
||||
if err := r.Status().Update(ctx, app); err != nil {
|
||||
logger.Error(err, "Failed to update NodePort of DevcontainerApp", "nodePortAssigned", service.Spec.Ports[0].NodePort)
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
} else if !errors.IsAlreadyExists(err) {
|
||||
logger.Error(err, "Failed to create DevcontainerApp NodePort Service", "nodePortServiceName", service.Name)
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
@@ -120,7 +130,7 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
||||
func (r *DevcontainerAppReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
For(&devcontainer_v1.DevcontainerApp{}).
|
||||
Owns(&app_v1.StatefulSet{}).
|
||||
Owns(&apps_v1.StatefulSet{}).
|
||||
Owns(&core_v1.Service{}).
|
||||
Complete(r)
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ metadata:
|
||||
spec:
|
||||
selector:
|
||||
app: {{.ObjectMeta.Name}}
|
||||
devstar-resource-type: devstar-devcontainer
|
||||
sessionAffinity: None
|
||||
type: NodePort
|
||||
externalTrafficPolicy: Cluster
|
||||
|
@@ -5,16 +5,19 @@ metadata:
|
||||
namespace: {{.ObjectMeta.Namespace}}
|
||||
labels:
|
||||
app: {{.ObjectMeta.Name}}
|
||||
devstar-resource-type: devstar-devcontainer
|
||||
spec:
|
||||
podManagementPolicy: OrderedReady
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{.ObjectMeta.Name}}
|
||||
devstar-resource-type: devstar-devcontainer
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{.ObjectMeta.Name}}
|
||||
devstar-resource-type: devstar-devcontainer
|
||||
spec:
|
||||
containers:
|
||||
- name: {{.ObjectMeta.Name}}
|
||||
|
Reference in New Issue
Block a user