penguin/monok8s

k8s image for Mono Gateway Dev Kit

commit 3c0df319d755118216c61087282b11abbb2e886e25905f203211cd49147690f4

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-04-02T17:04:40Z
subjectDraft for OSUpgrade Spec
commit 3c0df319d755118216c61087282b11abbb2e886e25905f203211cd49147690f4
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-04-02T17:04:40Z

    Draft for OSUpgrade Spec
---
 README.md                                          |  52 ++++++++--
 clitools/makefile                                  |  18 ++--
 clitools/pkg/apis/monok8s/v1alpha1/monoksconfig.go |  77 ++++++++++++++
 clitools/pkg/apis/monok8s/v1alpha1/osupgrade.go    | 109 ++++++++++++++++++++
 clitools/pkg/apis/monok8s/v1alpha1/types.go        | 114 ---------------------
 clitools/pkg/node/agent.go                         |   4 +-
 clitools/pkg/templates/templates.go                |  18 ++--
 7 files changed, 250 insertions(+), 142 deletions(-)

diff --git a/README.md b/README.md
index 86b3d31..fc4351c 100644
--- a/README.md
+++ b/README.md
@@ -90,29 +90,61 @@ We use a CRD with an agent to handle this. Our versions follows upstream's.
 
 kubectl apply -f upgrade.yaml
 ```yaml
-apiVersion: k8s.mono.si/v1alpha1
+apiVersion: monok8s.io/v1alpha1
 kind: OSUpgrade
 metadata:
-  name: "my-ugrade"
+  name: "my-ugrade-2"
 spec:
-  version: "v1.35.1" # Or just "latest"
+  version: "v1.35.3"
   imageURL: "https://updates.example.com/monok8s-1.2.3.img.zst"
   checksum: "sha256:..."
+  nodeSelector: {}
+status:
+  phase: Pending
+  resolvedVersion: "v1.35.3"
+  observedGeneration: 1
+  summary:
+    targetedNodes: 0
+    pendingNodes: 0
+    runningNodes: 0
+    succeededNodes: 0
+    failedNodes: 0
 ```
 
 kubectl get osugrades
 ```
-NAME           TARGET     STATUS      AGE
-my-upgrade-1   latest     pending     1m
-my-upgrade-2   v1.35.3    accepted    1m # latest gets realized into a version number
-their-upgrade  v1.33.2    succeeded   1m
+NAME             TARGET     STATUS      AGE
+my-upgrade-2     v1.35.3    accepted    1m # latest gets realized into a version number
+my-downgrade-1   v1.33.2    rejected    1m # Downgrade not supported
 ```
 
 kubectl get osupgradeprogress
 ```
-NODE        SOURCE         STATUS
-my-node     my-upgrade-2   active
-their-node  my-upgrade-2   completed
+NAME                NODE        SOURCE        CURRENT  TARGET   STATUS
+osupgrade-abc123f   node-1      my-upgrade-2  v1.34.1  v1.35.3  downloading
+osupgrade-cde456g   node-2      my-upgrade-2  v1.35.3  v1.35.3  completed
+```
+
+```yaml
+apiVersion: monok8s.io/v1alpha1
+kind: OSUpgradeProgress
+metadata:
+  name: "osupgrade-abc123f"
+spec:
+  sourceRef:
+    name: my-upgrade-2
+  nodeName: node-1
+status:
+  currentVersion: "v1.34.1"
+  targetVersion: "v1.35.3"
+  phase: Downloading
+  startedAt: null
+  completedAt: null
+  lastUpdatedAt: null
+  retryCount: 0
+  inactivePartition: "B"
+  failureReason: ""
+  message: ""
 ```
 
 ## NOTES
diff --git a/clitools/makefile b/clitools/makefile
index 98e1bc0..4564640 100644
--- a/clitools/makefile
+++ b/clitools/makefile
@@ -12,14 +12,16 @@ BUILDINFO_FILE := pkg/buildinfo/buildinfo_gen.go
 
 # Never cache this
 .buildinfo:
-	echo 'package buildinfo' > $(BUILDINFO_FILE)
-	echo 'const (' >> $(BUILDINFO_FILE)
-	echo '	Version = "$(VERSION)"' >> $(BUILDINFO_FILE)
-	echo '	KubeVersion = "$(KUBE_VERSION)"' >> $(BUILDINFO_FILE)
-	echo '	GitRevision = "$(GIT_REV)"' >> $(BUILDINFO_FILE)
-	echo '	Timestamp = "$(shell TZ=UTC date +%Y%m%d.%H%M%S)"' >> $(BUILDINFO_FILE)
-	echo ')' >> $(BUILDINFO_FILE)
-	echo ''
+	@printf '%s\n' \
+		'package buildinfo' \
+		'' \
+		'const (' \
+		'    Version     = "$(VERSION)"' \
+		'    KubeVersion = "$(KUBE_VERSION)"' \
+		'    GitRevision = "$(GIT_REV)"' \
+		'    Timestamp   = "'$$(TZ=UTC date +%Y%m%d.%H%M%S)'"' \
+		')' \
+	> $(BUILDINFO_FILE)
 
 build: .buildinfo
 	mkdir -p $(BIN_DIR)
diff --git a/clitools/pkg/apis/monok8s/v1alpha1/monoksconfig.go b/clitools/pkg/apis/monok8s/v1alpha1/monoksconfig.go
new file mode 100644
index 0000000..758af8e
--- /dev/null
+++ b/clitools/pkg/apis/monok8s/v1alpha1/monoksconfig.go
@@ -0,0 +1,77 @@
+package v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+type MonoKSConfig struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Spec              MonoKSConfigSpec    `json:"spec,omitempty" yaml:"spec,omitempty"`
+	Status            *MonoKSConfigStatus `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+type MonoKSConfigList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []MonoKSConfig `json:"items"`
+}
+
+type MonoKSConfigSpec struct {
+	KubernetesVersion             string            `json:"kubernetesVersion,omitempty" yaml:"kubernetesVersion,omitempty"`
+	NodeName                      string            `json:"nodeName,omitempty" yaml:"nodeName,omitempty"`
+	ClusterName                   string            `json:"clusterName,omitempty" yaml:"clusterName,omitempty"`
+	ClusterDomain                 string            `json:"clusterDomain,omitempty" yaml:"clusterDomain,omitempty"`
+	ClusterRole                   string            `json:"clusterRole,omitempty" yaml:"clusterRole,omitempty"`
+	InitControlPlane              bool              `json:"initControlPlane,omitempty" yaml:"initControlPlane,omitempty"`
+	EnableControlAgent            bool              `json:"enableControlAgent,omitempty" yaml:"enableControlAgent,omitempty"`
+	PodSubnet                     string            `json:"podSubnet,omitempty" yaml:"podSubnet,omitempty"`
+	ServiceSubnet                 string            `json:"serviceSubnet,omitempty" yaml:"serviceSubnet,omitempty"`
+	APIServerAdvertiseAddress     string            `json:"apiServerAdvertiseAddress,omitempty" yaml:"apiServerAdvertiseAddress,omitempty"`
+	APIServerEndpoint             string            `json:"apiServerEndpoint,omitempty" yaml:"apiServerEndpoint,omitempty"`
+	ContainerRuntimeEndpoint      string            `json:"containerRuntimeEndpoint,omitempty" yaml:"containerRuntimeEndpoint,omitempty"`
+	BootstrapToken                string            `json:"bootstrapToken,omitempty" yaml:"bootstrapToken,omitempty"`
+	DiscoveryTokenCACertHash      string            `json:"discoveryTokenCACertHash,omitempty" yaml:"discoveryTokenCACertHash,omitempty"`
+	ControlPlaneCertKey           string            `json:"controlPlaneCertKey,omitempty" yaml:"controlPlaneCertKey,omitempty"`
+	CNIPlugin                     string            `json:"cniPlugin,omitempty" yaml:"cniPlugin,omitempty"`
+	AllowSchedulingOnControlPlane bool              `json:"allowSchedulingOnControlPlane,omitempty" yaml:"allowSchedulingOnControlPlane,omitempty"`
+	SkipImageCheck                bool              `json:"skipImageCheck,omitempty" yaml:"skipImageCheck,omitempty"`
+	KubeProxyNodePortAddresses    []string          `json:"kubeProxyNodePortAddresses,omitempty" yaml:"kubeProxyNodePortAddresses,omitempty"`
+	SubjectAltNames               []string          `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"`
+	NodeLabels                    map[string]string `json:"nodeLabels,omitempty" yaml:"nodeLabels,omitempty"`
+	NodeAnnotations               map[string]string `json:"nodeAnnotations,omitempty" yaml:"nodeAnnotations,omitempty"`
+	Network                       NetworkSpec       `json:"network,omitempty" yaml:"network,omitempty"`
+}
+
+type NetworkSpec struct {
+	Hostname         string   `json:"hostname,omitempty" yaml:"hostname,omitempty"`
+	ManagementIface  string   `json:"managementIface,omitempty" yaml:"managementIface,omitempty"`
+	ManagementCIDR   string   `json:"managementCIDR,omitempty" yaml:"managementCIDR,omitempty"`
+	ManagementGW     string   `json:"managementGateway,omitempty" yaml:"managementGateway,omitempty"`
+	DNSNameservers   []string `json:"dnsNameservers,omitempty" yaml:"dnsNameservers,omitempty"`
+	DNSSearchDomains []string `json:"dnsSearchDomains,omitempty" yaml:"dnsSearchDomains,omitempty"`
+}
+
+type MonoKSConfigStatus struct {
+	Phase              string             `json:"phase,omitempty"`
+	ObservedGeneration int64              `json:"observedGeneration,omitempty"`
+	Conditions         []metav1.Condition `json:"conditions,omitempty"`
+	AppliedSteps       []string           `json:"appliedSteps,omitempty"`
+}
+
+func (in *MonoKSConfig) DeepCopyObject() runtime.Object {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	return &out
+}
+
+func (in *MonoKSConfigList) DeepCopyObject() runtime.Object {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	return &out
+}
diff --git a/clitools/pkg/apis/monok8s/v1alpha1/osupgrade.go b/clitools/pkg/apis/monok8s/v1alpha1/osupgrade.go
new file mode 100644
index 0000000..bd9329b
--- /dev/null
+++ b/clitools/pkg/apis/monok8s/v1alpha1/osupgrade.go
@@ -0,0 +1,109 @@
+package v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+type OSUpgrade struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Spec              OSUpgradeSpec    `json:"spec,omitempty" yaml:"spec,omitempty"`
+	Status            *OSUpgradeStatus `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+type OSUpgradeList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Items           []OSUpgrade `json:"items" yaml:"items"`
+}
+
+type OSUpgradeSpec struct {
+	Version      string                `json:"version,omitempty" yaml:"version,omitempty"`
+	ImageURL     string                `json:"imageURL,omitempty" yaml:"imageURL,omitempty"`
+	Checksum     string                `json:"checksum,omitempty" yaml:"checksum,omitempty"`
+	NodeSelector *metav1.LabelSelector `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
+}
+
+type OSUpgradeStatus struct {
+	Phase              string             `json:"phase,omitempty" yaml:"phase,omitempty"`
+	ResolvedVersion    string             `json:"resolvedVersion,omitempty" yaml:"resolvedVersion,omitempty"`
+	ObservedGeneration int64              `json:"observedGeneration,omitempty" yaml:"observedGeneration,omitempty"`
+	Summary            OSUpgradeSummary   `json:"summary,omitempty" yaml:"summary,omitempty"`
+	Conditions         []metav1.Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
+}
+
+type OSUpgradeSummary struct {
+	TargetedNodes  int32 `json:"targetedNodes,omitempty" yaml:"targetedNodes,omitempty"`
+	PendingNodes   int32 `json:"pendingNodes,omitempty" yaml:"pendingNodes,omitempty"`
+	RunningNodes   int32 `json:"runningNodes,omitempty" yaml:"runningNodes,omitempty"`
+	SucceededNodes int32 `json:"succeededNodes,omitempty" yaml:"succeededNodes,omitempty"`
+	FailedNodes    int32 `json:"failedNodes,omitempty" yaml:"failedNodes,omitempty"`
+}
+
+type OSUpgradeProgress struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Spec              OSUpgradeProgressSpec    `json:"spec,omitempty" yaml:"spec,omitempty"`
+	Status            *OSUpgradeProgressStatus `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+type OSUpgradeProgressList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Items           []OSUpgradeProgress `json:"items" yaml:"items"`
+}
+
+type OSUpgradeProgressSpec struct {
+	SourceRef OSUpgradeSourceRef `json:"sourceRef,omitempty" yaml:"sourceRef,omitempty"`
+	NodeName  string             `json:"nodeName,omitempty" yaml:"nodeName,omitempty"`
+}
+
+type OSUpgradeSourceRef struct {
+	Name string `json:"name,omitempty" yaml:"name,omitempty"`
+}
+
+type OSUpgradeProgressStatus struct {
+	CurrentVersion    string       `json:"currentVersion,omitempty" yaml:"currentVersion,omitempty"`
+	TargetVersion     string       `json:"targetVersion,omitempty" yaml:"targetVersion,omitempty"`
+	Phase             string       `json:"phase,omitempty" yaml:"phase,omitempty"`
+	StartedAt         *metav1.Time `json:"startedAt,omitempty" yaml:"startedAt,omitempty"`
+	CompletedAt       *metav1.Time `json:"completedAt,omitempty" yaml:"completedAt,omitempty"`
+	LastUpdatedAt     *metav1.Time `json:"lastUpdatedAt,omitempty" yaml:"lastUpdatedAt,omitempty"`
+	RetryCount        int32        `json:"retryCount,omitempty" yaml:"retryCount,omitempty"`
+	InactivePartition string       `json:"inactivePartition,omitempty" yaml:"inactivePartition,omitempty"`
+	FailureReason     string       `json:"failureReason,omitempty" yaml:"failureReason,omitempty"`
+	Message           string       `json:"message,omitempty" yaml:"message,omitempty"`
+}
+
+func (in *OSUpgrade) DeepCopyObject() runtime.Object {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	return &out
+}
+
+func (in *OSUpgradeList) DeepCopyObject() runtime.Object {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	return &out
+}
+
+func (in *OSUpgradeProgress) DeepCopyObject() runtime.Object {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	return &out
+}
+
+func (in *OSUpgradeProgressList) DeepCopyObject() runtime.Object {
+	if in == nil {
+		return nil
+	}
+	out := *in
+	return &out
+}
diff --git a/clitools/pkg/apis/monok8s/v1alpha1/types.go b/clitools/pkg/apis/monok8s/v1alpha1/types.go
index 9ee1a69..ec2e469 100644
--- a/clitools/pkg/apis/monok8s/v1alpha1/types.go
+++ b/clitools/pkg/apis/monok8s/v1alpha1/types.go
@@ -17,88 +17,6 @@ var (
 	AddToScheme        = SchemeBuilder.AddToScheme
 )
 
-type MonoKSConfig struct {
-	metav1.TypeMeta   `json:",inline" yaml:",inline"`
-	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
-	Spec              MonoKSConfigSpec    `json:"spec,omitempty" yaml:"spec,omitempty"`
-	Status            *MonoKSConfigStatus `json:"status,omitempty" yaml:"status,omitempty"`
-}
-
-type MonoKSConfigList struct {
-	metav1.TypeMeta `json:",inline"`
-	metav1.ListMeta `json:"metadata,omitempty"`
-	Items           []MonoKSConfig `json:"items"`
-}
-
-type MonoKSConfigSpec struct {
-	KubernetesVersion             string            `json:"kubernetesVersion,omitempty" yaml:"kubernetesVersion,omitempty"`
-	NodeName                      string            `json:"nodeName,omitempty" yaml:"nodeName,omitempty"`
-	ClusterName                   string            `json:"clusterName,omitempty" yaml:"clusterName,omitempty"`
-	ClusterDomain                 string            `json:"clusterDomain,omitempty" yaml:"clusterDomain,omitempty"`
-	ClusterRole                   string            `json:"clusterRole,omitempty" yaml:"clusterRole,omitempty"`
-	InitControlPlane              bool              `json:"initControlPlane,omitempty" yaml:"initControlPlane,omitempty"`
-	EnableControlAgent            bool              `json:"enableControlAgent,omitempty" yaml:"enableControlAgent,omitempty"`
-	PodSubnet                     string            `json:"podSubnet,omitempty" yaml:"podSubnet,omitempty"`
-	ServiceSubnet                 string            `json:"serviceSubnet,omitempty" yaml:"serviceSubnet,omitempty"`
-	APIServerAdvertiseAddress     string            `json:"apiServerAdvertiseAddress,omitempty" yaml:"apiServerAdvertiseAddress,omitempty"`
-	APIServerEndpoint             string            `json:"apiServerEndpoint,omitempty" yaml:"apiServerEndpoint,omitempty"`
-	ContainerRuntimeEndpoint      string            `json:"containerRuntimeEndpoint,omitempty" yaml:"containerRuntimeEndpoint,omitempty"`
-	BootstrapToken                string            `json:"bootstrapToken,omitempty" yaml:"bootstrapToken,omitempty"`
-	DiscoveryTokenCACertHash      string            `json:"discoveryTokenCACertHash,omitempty" yaml:"discoveryTokenCACertHash,omitempty"`
-	ControlPlaneCertKey           string            `json:"controlPlaneCertKey,omitempty" yaml:"controlPlaneCertKey,omitempty"`
-	CNIPlugin                     string            `json:"cniPlugin,omitempty" yaml:"cniPlugin,omitempty"`
-	AllowSchedulingOnControlPlane bool              `json:"allowSchedulingOnControlPlane,omitempty" yaml:"allowSchedulingOnControlPlane,omitempty"`
-	SkipImageCheck                bool              `json:"skipImageCheck,omitempty" yaml:"skipImageCheck,omitempty"`
-	KubeProxyNodePortAddresses    []string          `json:"kubeProxyNodePortAddresses,omitempty" yaml:"kubeProxyNodePortAddresses,omitempty"`
-	SubjectAltNames               []string          `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"`
-	NodeLabels                    map[string]string `json:"nodeLabels,omitempty" yaml:"nodeLabels,omitempty"`
-	NodeAnnotations               map[string]string `json:"nodeAnnotations,omitempty" yaml:"nodeAnnotations,omitempty"`
-	Network                       NetworkSpec       `json:"network,omitempty" yaml:"network,omitempty"`
-}
-
-type NetworkSpec struct {
-	Hostname         string   `json:"hostname,omitempty" yaml:"hostname,omitempty"`
-	ManagementIface  string   `json:"managementIface,omitempty" yaml:"managementIface,omitempty"`
-	ManagementCIDR   string   `json:"managementCIDR,omitempty" yaml:"managementCIDR,omitempty"`
-	ManagementGW     string   `json:"managementGateway,omitempty" yaml:"managementGateway,omitempty"`
-	DNSNameservers   []string `json:"dnsNameservers,omitempty" yaml:"dnsNameservers,omitempty"`
-	DNSSearchDomains []string `json:"dnsSearchDomains,omitempty" yaml:"dnsSearchDomains,omitempty"`
-}
-
-type MonoKSConfigStatus struct {
-	Phase              string             `json:"phase,omitempty"`
-	ObservedGeneration int64              `json:"observedGeneration,omitempty"`
-	Conditions         []metav1.Condition `json:"conditions,omitempty"`
-	AppliedSteps       []string           `json:"appliedSteps,omitempty"`
-}
-
-type OSUpgrade struct {
-	metav1.TypeMeta   `json:",inline" yaml:",inline"`
-	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
-	Spec              OSUpgradeSpec    `json:"spec,omitempty" yaml:"spec,omitempty"`
-	Status            *OSUpgradeStatus `json:"status,omitempty" yaml:"status,omitempty"`
-}
-
-type OSUpgradeList struct {
-	metav1.TypeMeta `json:",inline"`
-	metav1.ListMeta `json:"metadata,omitempty"`
-	Items           []OSUpgrade `json:"items"`
-}
-
-type OSUpgradeSpec struct {
-	Version         string   `json:"version,omitempty" yaml:"version,omitempty"`
-	ImageURL        string   `json:"imageURL,omitempty" yaml:"imageURL,omitempty"`
-	TargetPartition string   `json:"targetPartition,omitempty" yaml:"targetPartition,omitempty"`
-	NodeSelector    []string `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
-	Force           bool     `json:"force,omitempty" yaml:"force,omitempty"`
-}
-
-type OSUpgradeStatus struct {
-	Phase              string             `json:"phase,omitempty"`
-	ObservedGeneration int64              `json:"observedGeneration,omitempty"`
-	Conditions         []metav1.Condition `json:"conditions,omitempty"`
-}
-
 func addKnownTypes(scheme *runtime.Scheme) error {
 	scheme.AddKnownTypes(SchemeGroupVersion,
 		&MonoKSConfig{},
@@ -109,35 +27,3 @@ func addKnownTypes(scheme *runtime.Scheme) error {
 	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
 	return nil
 }
-
-func (in *MonoKSConfig) DeepCopyObject() runtime.Object {
-	if in == nil {
-		return nil
-	}
-	out := *in
-	return &out
-}
-
-func (in *MonoKSConfigList) DeepCopyObject() runtime.Object {
-	if in == nil {
-		return nil
-	}
-	out := *in
-	return &out
-}
-
-func (in *OSUpgrade) DeepCopyObject() runtime.Object {
-	if in == nil {
-		return nil
-	}
-	out := *in
-	return &out
-}
-
-func (in *OSUpgradeList) DeepCopyObject() runtime.Object {
-	if in == nil {
-		return nil
-	}
-	out := *in
-	return &out
-}
diff --git a/clitools/pkg/node/agent.go b/clitools/pkg/node/agent.go
index c875281..93a1b94 100644
--- a/clitools/pkg/node/agent.go
+++ b/clitools/pkg/node/agent.go
@@ -16,11 +16,11 @@ import (
 
 	"undecided.project/monok8s/pkg/crds"
 	"undecided.project/monok8s/pkg/kube"
+	templates "undecided.project/monok8s/pkg/templates"
 )
 
 const (
 	controlAgentName              = "control-agent"
-	controlAgentDefaultNamespace  = "kube-system"
 	controlAgentNodeSelectorKey   = "monok8s.io/control-agent"
 	controlAgentNodeSelectorValue = "true"
 	controlAgentImage             = "localhost/monok8s/control-agent:dev"
@@ -84,7 +84,7 @@ func ApplyControlAgentDaemonSetResources(ctx context.Context, n *NodeContext) er
 
 	namespace := strings.TrimSpace(n.Config.Namespace)
 	if namespace == "" {
-		namespace = controlAgentDefaultNamespace
+		namespace = templates.DefaultNamespace
 	}
 
 	clients, err := kube.NewClientsFromKubeconfig(kubeconfig)
diff --git a/clitools/pkg/templates/templates.go b/clitools/pkg/templates/templates.go
index 934a4da..b5ef898 100644
--- a/clitools/pkg/templates/templates.go
+++ b/clitools/pkg/templates/templates.go
@@ -7,6 +7,8 @@ import (
 	types "undecided.project/monok8s/pkg/apis/monok8s/v1alpha1"
 )
 
+const DefaultNamespace = "kube-system"
+
 func DefaultMonoKSConfig(v TemplateValues) types.MonoKSConfig {
 	return types.MonoKSConfig{
 		TypeMeta: metav1.TypeMeta{
@@ -15,7 +17,7 @@ func DefaultMonoKSConfig(v TemplateValues) types.MonoKSConfig {
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      "example",
-			Namespace: "kube-system",
+			Namespace: DefaultNamespace,
 		},
 		Spec: types.MonoKSConfigSpec{
 			KubernetesVersion: v.KubernetesVersion,
@@ -71,16 +73,16 @@ func DefaultOSUpgrade(v TemplateValues) types.OSUpgrade {
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      "example",
-			Namespace: "kube-system",
+			Namespace: DefaultNamespace,
 		},
 		Spec: types.OSUpgradeSpec{
-			Version:         "v0.0.1",
-			ImageURL:        "https://example.invalid/images/monok8s-v0.0.1.img.zst",
-			TargetPartition: "B",
-			NodeSelector: []string{
-				firstNonEmpty(v.NodeName, v.Hostname),
+			Version:  v.KubernetesVersion,
+			ImageURL: "https://example.invalid/images/monok8s-v0.0.1.img.zst",
+			NodeSelector: &metav1.LabelSelector{
+				MatchLabels: map[string]string{
+					"kubernetes.io/hostname": firstNonEmpty(v.NodeName, v.Hostname),
+				},
 			},
-			Force: false,
 		},
 	}
 }