Controller to not touch osup if possible

This commit is contained in:
2026-04-23 19:05:07 +08:00
parent 9eba55e7ee
commit 4549b9d167
6 changed files with 25 additions and 107 deletions

View File

@@ -14,4 +14,4 @@ else
-addext "subjectAltName=IP:127.0.0.1,DNS:localhost" -addext "subjectAltName=IP:127.0.0.1,DNS:localhost"
fi fi
go run "$PROJ_ROOT"/cmd/ctl controller --tls-cert-file "$OUT_DIR"/tls.crt --tls-private-key-file "$OUT_DIR"/tls.key --namespace default go run "$PROJ_ROOT"/cmd/ctl controller --tls-cert-file "$OUT_DIR"/tls.crt --tls-private-key-file "$OUT_DIR"/tls.key

View File

@@ -14,7 +14,6 @@ import (
"k8s.io/klog/v2" "k8s.io/klog/v2"
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1" monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
"example.com/monok8s/pkg/buildinfo"
"example.com/monok8s/pkg/kube" "example.com/monok8s/pkg/kube"
) )
@@ -39,34 +38,7 @@ func EnsureOSUpgradeProgressForNode(
return fmt.Errorf("osupgrade is nil") return fmt.Errorf("osupgrade is nil")
} }
// Keep using your existing helper if it already encapsulates
// selector matching / parent linkage / create-or-update semantics.
osup, err := ensureProgressHeartbeat(ctx, clients, namespace, nodeName, osu)
if err != nil {
return err
}
klog.InfoS("ensured OSUpgradeProgress from admission",
"osupgrade", osu.Name,
"osupgradeProgress", osup.Name,
"node", nodeName,
)
return nil
}
func ensureProgressHeartbeat(ctx context.Context, clients *kube.Clients,
namespace string, nodeName string,
osu *monov1alpha1.OSUpgrade,
) (*monov1alpha1.OSUpgradeProgress, error) {
name := fmt.Sprintf("%s-%s", osu.Name, nodeName) name := fmt.Sprintf("%s-%s", osu.Name, nodeName)
now := metav1.Now()
currentVersion := buildinfo.KubeVersion
targetVersion := ""
if osu.Status != nil {
targetVersion = osu.Status.ResolvedVersion
}
progress := &monov1alpha1.OSUpgradeProgress{ progress := &monov1alpha1.OSUpgradeProgress{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
@@ -83,84 +55,35 @@ func ensureProgressHeartbeat(ctx context.Context, clients *kube.Clients,
Name: osu.Name, Name: osu.Name,
}, },
}, },
Status: &monov1alpha1.OSUpgradeProgressStatus{
CurrentVersion: currentVersion,
TargetVersion: targetVersion,
Phase: monov1alpha1.OSUpgradeProgressPhasePending,
LastUpdatedAt: &now,
Message: "acknowledged",
},
} }
created, err := createProgress(ctx, clients, osup_gvr, progress) created, err := createProgress(ctx, clients, osup_gvr, progress)
if err == nil { if err == nil {
klog.InfoS("created osupgradeprogress", "name", created.Name, "namespace", created.Namespace) klog.InfoS("created osupgradeprogress", "name", created.Name, "namespace", created.Namespace)
return created, nil return nil
} }
if !apierrors.IsAlreadyExists(err) { if !apierrors.IsAlreadyExists(err) {
return nil, fmt.Errorf("create OSUpgradeProgress %s/%s: %w", namespace, name, err) return fmt.Errorf("create OSUpgradeProgress %s/%s: %w", namespace, name, err)
} }
var out *monov1alpha1.OSUpgradeProgress
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
existing, err := getProgress(ctx, clients, osup_gvr, namespace, name) existing, err := getProgress(ctx, clients, osup_gvr, namespace, name)
if err != nil { if err != nil {
return fmt.Errorf("get existing OSUpgradeProgress %s/%s: %w", namespace, name, err) return fmt.Errorf("get existing OSUpgradeProgress %s/%s: %w", namespace, name, err)
} }
// Keep spec aligned with source and node. if existing.Spec.NodeName != nodeName || existing.Spec.SourceRef.Name != osu.Name {
existing.Spec.NodeName = nodeName return fmt.Errorf(
existing.Spec.SourceRef.Name = osu.Name "conflicting OSUpgradeProgress %s/%s already exists: got spec.nodeName=%q spec.sourceRef.name=%q, want nodeName=%q sourceRef.name=%q",
namespace,
existing, err = updateProgressSpec(ctx, clients, osup_gvr, existing) name,
if err != nil { existing.Spec.NodeName,
if isUnknownUpdateResult(err) { existing.Spec.SourceRef.Name,
latest, getErr := getProgress(ctx, clients, osup_gvr, namespace, name) nodeName,
if getErr == nil { osu.Name,
out = latest )
}
}
return fmt.Errorf("update OSUpgradeProgress spec %s/%s: %w", namespace, name, err)
} }
if existing.Status == nil {
existing.Status = &monov1alpha1.OSUpgradeProgressStatus{}
}
existing.Status.CurrentVersion = currentVersion
existing.Status.TargetVersion = targetVersion
existing.Status.LastUpdatedAt = &now
if existing.Status.Phase == "" {
existing.Status.Phase = monov1alpha1.OSUpgradeProgressPhasePending
}
if existing.Status.Message == "" {
existing.Status.Message = "acknowledged"
}
existing, err = updateProgressStatus(ctx, clients, osup_gvr, existing)
if err != nil {
if isUnknownUpdateResult(err) {
latest, getErr := getProgress(ctx, clients, osup_gvr, namespace, name)
if getErr == nil {
out = latest
}
}
return fmt.Errorf("update OSUpgradeProgress status %s/%s: %w", namespace, name, err)
}
out = existing
return nil return nil
})
if err != nil {
if out != nil {
return out, nil
}
return nil, err
}
klog.InfoS("updated osupgradeprogress", "name", out.Name, "namespace", out.Namespace)
return out, nil
} }
func updateProgressRobust( func updateProgressRobust(

View File

@@ -276,13 +276,7 @@ func listTargetNodeNames(
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid nodeSelector: %w", err) return nil, fmt.Errorf("invalid nodeSelector: %w", err)
} }
selector = sel
reqs, selectable := sel.Requirements()
if !selectable {
return nil, fmt.Errorf("nodeSelector is not selectable")
}
selector = selector.Add(reqs...)
} }
list, err := clients.Kubernetes.CoreV1(). list, err := clients.Kubernetes.CoreV1().
@@ -306,7 +300,6 @@ func listTargetNodeNames(
} }
func shouldUseNode(node *corev1.Node) bool { func shouldUseNode(node *corev1.Node) bool {
// Keep this conservative for now. Tighten if you want only Ready nodes.
return node != nil && node.Name != "" return node != nil && node.Name != ""
} }

View File

@@ -73,13 +73,13 @@ func (s *Server) Initialize() {
ws.Consumes(restful.MIME_JSON) ws.Consumes(restful.MIME_JSON)
ws.Produces(restful.MIME_JSON) ws.Produces(restful.MIME_JSON)
ws.Route(ws.GET("/status").To(s.queryStatus). ws.Route(ws.GET("/healthz").To(s.queryHealthz).
Doc("Return basic controller status")) Doc("Return basic controller status"))
s.restfulCont.Add(ws) s.restfulCont.Add(ws)
} }
func (s *Server) queryStatus(request *restful.Request, response *restful.Response) { func (s *Server) queryHealthz(request *restful.Request, response *restful.Response) {
resp := StatusResponse{ resp := StatusResponse{
OK: true, OK: true,
Service: "monok8s-controller", Service: "monok8s-controller",

View File

@@ -8,7 +8,7 @@ set -e
BASE_URL="http://localhost:8000" BASE_URL="http://localhost:8000"
TARGET_VERSION="v1.34.6" TARGET_VERSION="v1.34.6"
STABLE_VERSION="v1.34.6" STABLE_VERSION="v1.34.6"
NAME="my-upgrade-2" NAME="my-upgrade-1"
echo "apiVersion: monok8s.io/v1alpha1" echo "apiVersion: monok8s.io/v1alpha1"
echo "kind: OSUpgrade" echo "kind: OSUpgrade"

View File

@@ -2,7 +2,9 @@
set -eu set -eu
### User-configurable vars ### User-configurable vars
IMG_DIR="./out" SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
OUT_DIR="$( realpath "$SCRIPT_DIR"/../out/ )"
IMG_DIR="$OUT_DIR"
CONFIG_PART_SUFFIX="s1" # config partition after flashing CONFIG_PART_SUFFIX="s1" # config partition after flashing
ENV_SEARCH_DIR="./out" # optional; leave empty to use selected image dir ENV_SEARCH_DIR="./out" # optional; leave empty to use selected image dir