mirror of
https://gitee.com/devstar/devstar-devcontainer-operator
synced 2025-04-21 09:42:22 +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:
parent
75919d52ca
commit
7aa665a314
@ -94,6 +94,10 @@ type DevcontainerAppStatus struct {
|
|||||||
// Information when was the last time the job was successfully scheduled.
|
// Information when was the last time the job was successfully scheduled.
|
||||||
// +optional
|
// +optional
|
||||||
LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"`
|
LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"`
|
||||||
|
|
||||||
|
// NodePortAssigned 存储 DevcontainerApp CRD调度后集群分配的 NodePort
|
||||||
|
// +optional
|
||||||
|
NodePortAssigned uint16 `json:"nodePortAssigned"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
|
@ -150,6 +150,9 @@ spec:
|
|||||||
scheduled.
|
scheduled.
|
||||||
format: date-time
|
format: date-time
|
||||||
type: string
|
type: string
|
||||||
|
nodePortAssigned:
|
||||||
|
description: NodePortAssigned 存储 DevcontainerApp CRD调度后集群分配的 NodePort
|
||||||
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
|
@ -2,7 +2,7 @@ apiVersion: devcontainer.devstar.cn/v1
|
|||||||
kind: DevcontainerApp
|
kind: DevcontainerApp
|
||||||
metadata:
|
metadata:
|
||||||
name: daimingchen-devstar-beef092a69c011ef9c00000c2952a362
|
name: daimingchen-devstar-beef092a69c011ef9c00000c2952a362
|
||||||
namespace: devstar-devcontainer-ns
|
namespace: devstar-studio-ns
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/name: devstar-devcontainer-kubebuilder-scaffold
|
app.kubernetes.io/name: devstar-devcontainer-kubebuilder-scaffold
|
||||||
app.kubernetes.io/managed-by: kustomize
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
@ -29,7 +29,7 @@ import (
|
|||||||
|
|
||||||
devcontainer_v1 "devstar.cn/DevcontainerApp/api/v1"
|
devcontainer_v1 "devstar.cn/DevcontainerApp/api/v1"
|
||||||
devcontainer_controller_utils "devstar.cn/DevcontainerApp/internal/controller/utils"
|
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"
|
core_v1 "k8s.io/api/core/v1"
|
||||||
k8s_sigs_controller_runtime_utils "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
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)
|
logger := log.FromContext(ctx)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// 1. 读取缓存中的 app
|
// 1. 读取缓存中的 DevcontainerApp
|
||||||
app := &devcontainer_v1.DevcontainerApp{}
|
app := &devcontainer_v1.DevcontainerApp{}
|
||||||
err = r.Get(ctx, req.NamespacedName, app)
|
err = r.Get(ctx, req.NamespacedName, app)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 当 CRD 资源 “DevcontainerApp” 被删除后,直接返回空结果,跳过剩下步骤
|
||||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ func (r *DevcontainerAppReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2.2 查找 集群中同名称的 StatefulSet
|
// 2.2 查找 集群中同名称的 StatefulSet
|
||||||
statefulSetInNamespace := &app_v1.StatefulSet{}
|
statefulSetInNamespace := &apps_v1.StatefulSet{}
|
||||||
err = r.Get(ctx, req.NamespacedName, statefulSetInNamespace)
|
err = r.Get(ctx, req.NamespacedName, statefulSetInNamespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.IsNotFound(err) {
|
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")
|
logger.Error(err, "Failed to create StatefulSet")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// 这里会反复触发更新
|
// 这里会反复触发更新
|
||||||
// 原因:在 SetupWithManager方法中,监听了 StatefulSet ,所以只要更新 StatefulSet 就会触发
|
// 原因:在 SetupWithManager方法中,监听了 StatefulSet ,所以只要更新 StatefulSet 就会触发
|
||||||
// 此处更新和 controllerManager 更新 StatefulSet 都会触发更新事件,导致循环触发
|
// 此处更新和 controllerManager 更新 StatefulSet 都会触发更新事件,导致循环触发
|
||||||
//修复方法:加上判断条件,仅在 app.Spec.StatefulSet.Image != statefulSet.Spec.Template.Spec.Containers[0].Image 时才更新 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 app.Spec.StatefulSet.Image != statefulSet.Spec.Template.Spec.Containers[0].Image {
|
||||||
if err := r.Update(ctx, statefulSet); err != nil {
|
if err := r.Update(ctx, statefulSet); err != nil {
|
||||||
return ctrl.Result{}, err
|
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 {
|
if err := k8s_sigs_controller_runtime_utils.SetControllerReference(app, service, r.Scheme); err != nil {
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
serviceInNamespace := &core_v1.Service{}
|
serviceInCluster := &core_v1.Service{}
|
||||||
err = r.Get(ctx, types.NamespacedName{Name: app.Name, Namespace: app.Namespace}, serviceInNamespace)
|
err = r.Get(ctx, types.NamespacedName{Name: app.Name, Namespace: app.Namespace}, serviceInCluster)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.IsNotFound(err) {
|
if !errors.IsNotFound(err) {
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
err = r.Create(ctx, service)
|
err = r.Create(ctx, service)
|
||||||
if err != nil && !errors.IsAlreadyExists(err) {
|
if err == nil {
|
||||||
logger.Error(err, "create service failed")
|
// 创建 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{}, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctrl.Result{}, nil
|
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 {
|
func (r *DevcontainerAppReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
return ctrl.NewControllerManagedBy(mgr).
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
For(&devcontainer_v1.DevcontainerApp{}).
|
For(&devcontainer_v1.DevcontainerApp{}).
|
||||||
Owns(&app_v1.StatefulSet{}).
|
Owns(&apps_v1.StatefulSet{}).
|
||||||
Owns(&core_v1.Service{}).
|
Owns(&core_v1.Service{}).
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
app: {{.ObjectMeta.Name}}
|
app: {{.ObjectMeta.Name}}
|
||||||
|
devstar-resource-type: devstar-devcontainer
|
||||||
sessionAffinity: None
|
sessionAffinity: None
|
||||||
type: NodePort
|
type: NodePort
|
||||||
externalTrafficPolicy: Cluster
|
externalTrafficPolicy: Cluster
|
||||||
|
@ -5,16 +5,19 @@ metadata:
|
|||||||
namespace: {{.ObjectMeta.Namespace}}
|
namespace: {{.ObjectMeta.Namespace}}
|
||||||
labels:
|
labels:
|
||||||
app: {{.ObjectMeta.Name}}
|
app: {{.ObjectMeta.Name}}
|
||||||
|
devstar-resource-type: devstar-devcontainer
|
||||||
spec:
|
spec:
|
||||||
podManagementPolicy: OrderedReady
|
podManagementPolicy: OrderedReady
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: {{.ObjectMeta.Name}}
|
app: {{.ObjectMeta.Name}}
|
||||||
|
devstar-resource-type: devstar-devcontainer
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: {{.ObjectMeta.Name}}
|
app: {{.ObjectMeta.Name}}
|
||||||
|
devstar-resource-type: devstar-devcontainer
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: {{.ObjectMeta.Name}}
|
- name: {{.ObjectMeta.Name}}
|
||||||
|
Loading…
Reference in New Issue
Block a user