Update ctl init to support env file

This commit is contained in:
2026-03-30 19:33:44 +08:00
parent 60a9ffeaf6
commit d9ffd1b446
12 changed files with 450 additions and 1191 deletions

View File

@@ -1,26 +1,13 @@
package templates
import (
"os"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "undecided.project/monok8s/pkg/apis/monok8s/v1alpha1"
buildinfo "undecided.project/monok8s/pkg/buildinfo"
)
var ValAPIServerEndPoint string = "10.0.0.10:6443"
var ValHostname string = "monoks-master-1"
var ValBootstrapToken string = "abcd12.ef3456789abcdef0"
var ValDiscoveryTokenCACertHash string = "sha256:9f1c2b3a4d5e6f7890abc1234567890abcdef1234567890abcdef1234567890ab"
func init() {
ValBootstrapToken = os.Getenv("HOSTNAME")
ValBootstrapToken = os.Getenv("BOOTSTRAP_TOKEN")
ValDiscoveryTokenCACertHash = os.Getenv("TOKEN_CACERT_HASH")
ValAPIServerEndPoint = os.Getenv("API_SERVER_ENDPOINT")
}
func DefaultMonoKSConfig() types.MonoKSConfig {
func DefaultMonoKSConfig(v TemplateValues) types.MonoKSConfig {
return types.MonoKSConfig{
TypeMeta: metav1.TypeMeta{
APIVersion: "monok8s.io/v1alpha1",
@@ -31,66 +18,51 @@ func DefaultMonoKSConfig() types.MonoKSConfig {
Namespace: "kube-system",
},
Spec: types.MonoKSConfigSpec{
KubernetesVersion: buildinfo.Version,
NodeName: ValHostname,
KubernetesVersion: v.KubernetesVersion,
NodeName: firstNonEmpty(v.NodeName, v.Hostname),
ClusterRole: "control-plane",
InitControlPlane: true,
ClusterRole: clusterRoleFromTemplateValues(v),
InitControlPlane: initControlPlaneFromTemplateValues(v),
ClusterName: "monok8s",
ClusterDomain: "cluster.local",
ClusterName: v.ClusterName,
ClusterDomain: v.ClusterDomain,
PodSubnet: "10.244.0.0/16",
ServiceSubnet: "10.96.0.0/12",
PodSubnet: v.PodSubnet,
ServiceSubnet: v.ServiceSubnet,
APIServerAdvertiseAddress: "10.0.0.10",
APIServerEndpoint: ValAPIServerEndPoint,
APIServerAdvertiseAddress: v.APIServerAdvertiseAddress,
APIServerEndpoint: v.APIServerEndpoint,
// Fake token and hash for placeholder purpose
BootstrapToken: ValBootstrapToken,
DiscoveryTokenCACertHash: ValDiscoveryTokenCACertHash,
BootstrapToken: v.BootstrapToken,
DiscoveryTokenCACertHash: v.DiscoveryTokenCACertHash,
ContainerRuntimeEndpoint: "unix:///var/run/crio/crio.sock",
ContainerRuntimeEndpoint: v.ContainerRuntimeEndpoint,
CNIPlugin: v.CNIPlugin,
CNIPlugin: "default",
AllowSchedulingOnControlPlane: true,
SkipImageCheck: false,
AllowSchedulingOnControlPlane: v.AllowSchedulingOnControlPlane,
SkipImageCheck: v.SkipImageCheck,
KubeProxyNodePortAddresses: []string{
"primary",
},
SubjectAltNames: []string{
"10.0.0.10", "localhost", ValHostname,
},
NodeLabels: map[string]string{
"monok8s.io/label": "value",
},
NodeAnnotations: map[string]string{
"monok8s.io/annotation": "value",
},
SubjectAltNames: copyStringSlice(v.SubjectAltNames),
NodeLabels: copyStringMap(v.NodeLabels),
NodeAnnotations: copyStringMap(v.NodeAnnotations),
Network: types.NetworkSpec{
Hostname: "monok8s-worker-1",
ManagementIface: "eth1",
ManagementCIDR: "10.0.0.10/24",
ManagementGW: "10.0.0.1",
DNSNameservers: []string{
"1.1.1.1",
"8.8.8.8",
},
DNSSearchDomains: []string{
"lan",
},
Hostname: firstNonEmpty(v.Hostname, v.NodeName),
ManagementIface: v.MgmtIface,
ManagementCIDR: v.MgmtAddress,
ManagementGW: v.MgmtGateway,
DNSNameservers: copyStringSlice(v.DNSNameservers),
DNSSearchDomains: copyStringSlice(v.DNSSearchDomains),
},
},
}
}
func DefaultOSUpgrade() types.OSUpgrade {
func DefaultOSUpgrade(v TemplateValues) types.OSUpgrade {
return types.OSUpgrade{
TypeMeta: metav1.TypeMeta{
APIVersion: "monok8s.io/v1alpha1",
@@ -105,9 +77,56 @@ func DefaultOSUpgrade() types.OSUpgrade {
ImageURL: "https://example.invalid/images/monok8s-v0.0.1.img.zst",
TargetPartition: "B",
NodeSelector: []string{
ValHostname,
firstNonEmpty(v.NodeName, v.Hostname),
},
Force: false,
},
}
}
func clusterRoleFromTemplateValues(v TemplateValues) string {
switch strings.ToLower(strings.TrimSpace(v.BootstrapMode)) {
case "init":
return "control-plane"
case "join":
if strings.EqualFold(strings.TrimSpace(v.JoinKind), "control-plane") {
return "control-plane"
}
return "worker"
default:
return "control-plane"
}
}
func initControlPlaneFromTemplateValues(v TemplateValues) bool {
return strings.EqualFold(strings.TrimSpace(v.BootstrapMode), "init")
}
func firstNonEmpty(xs ...string) string {
for _, x := range xs {
if strings.TrimSpace(x) != "" {
return strings.TrimSpace(x)
}
}
return ""
}
func copyStringSlice(in []string) []string {
if len(in) == 0 {
return nil
}
out := make([]string, len(in))
copy(out, in)
return out
}
func copyStringMap(in map[string]string) map[string]string {
if len(in) == 0 {
return nil
}
out := make(map[string]string, len(in))
for k, v := range in {
out[k] = v
}
return out
}

View File

@@ -0,0 +1,204 @@
package templates
import (
"os"
"strings"
buildinfo "undecided.project/monok8s/pkg/buildinfo"
)
type TemplateValues struct {
Hostname string
NodeName string
KubernetesVersion string
ClusterName string
ClusterDomain string
PodSubnet string
ServiceSubnet string
APIServerAdvertiseAddress string
APIServerEndpoint string
BootstrapToken string
DiscoveryTokenCACertHash string
ControlPlaneCertKey string
ContainerRuntimeEndpoint string
CNIPlugin string
BootstrapMode string // init, join
JoinKind string // worker, control-plane
AllowSchedulingOnControlPlane bool
SkipImageCheck bool
MgmtIface string
MgmtAddress string
MgmtGateway string
DNSNameservers []string
DNSSearchDomains []string
SubjectAltNames []string
NodeLabels map[string]string
NodeAnnotations map[string]string
}
func defaultTemplateValues() TemplateValues {
return TemplateValues{
Hostname: "monok8s-master-1",
NodeName: "monok8s-master-1",
KubernetesVersion: buildinfo.Version,
ClusterName: "monok8s",
ClusterDomain: "cluster.local",
PodSubnet: "10.244.0.0/16",
ServiceSubnet: "10.96.0.0/12",
APIServerAdvertiseAddress: "10.0.0.10",
APIServerEndpoint: "10.0.0.10:6443",
BootstrapToken: "abcd12.ef3456789abcdef0",
DiscoveryTokenCACertHash: "sha256:9f1c2b3a4d5e6f7890abc1234567890abcdef1234567890abcdef1234567890ab",
ControlPlaneCertKey: "",
ContainerRuntimeEndpoint: "unix:///var/run/crio/crio.sock",
CNIPlugin: "default",
BootstrapMode: "init",
JoinKind: "worker",
AllowSchedulingOnControlPlane: true,
SkipImageCheck: false,
MgmtIface: "eth1",
MgmtAddress: "10.0.0.10/24",
MgmtGateway: "10.0.0.1",
DNSNameservers: []string{"1.1.1.1", "8.8.8.8"},
DNSSearchDomains: []string{"lan"},
SubjectAltNames: []string{"10.0.0.10", "localhost", "monok8s-master-1"},
NodeLabels: map[string]string{
"monok8s.io/label": "value",
},
NodeAnnotations: map[string]string{
"monok8s.io/annotation": "value",
},
}
}
func LoadTemplateValuesFromEnv() TemplateValues {
v := defaultTemplateValues()
v.Hostname = getenvDefault("MKS_HOSTNAME", v.Hostname)
v.NodeName = getenvDefault("MKS_NODE_NAME", v.Hostname)
v.KubernetesVersion = getenvDefault("MKS_KUBERNETES_VERSION", v.KubernetesVersion)
v.ClusterName = getenvDefault("MKS_CLUSTER_NAME", v.ClusterName)
v.ClusterDomain = getenvDefault("MKS_CLUSTER_DOMAIN", v.ClusterDomain)
v.PodSubnet = getenvDefault("MKS_POD_SUBNET", v.PodSubnet)
v.ServiceSubnet = getenvDefault("MKS_SERVICE_SUBNET", v.ServiceSubnet)
v.APIServerAdvertiseAddress = getenvDefault("MKS_APISERVER_ADVERTISE_ADDRESS", v.APIServerAdvertiseAddress)
v.APIServerEndpoint = getenvDefault("MKS_API_SERVER_ENDPOINT", v.APIServerEndpoint)
v.BootstrapToken = getenvDefault("MKS_BOOTSTRAP_TOKEN", v.BootstrapToken)
v.DiscoveryTokenCACertHash = getenvDefault("MKS_DISCOVERY_TOKEN_CA_CERT_HASH", v.DiscoveryTokenCACertHash)
v.ControlPlaneCertKey = getenvDefault("MKS_CONTROL_PLANE_CERT_KEY", v.ControlPlaneCertKey)
v.ContainerRuntimeEndpoint = getenvDefault("MKS_CONTAINER_RUNTIME_ENDPOINT", v.ContainerRuntimeEndpoint)
v.CNIPlugin = getenvDefault("MKS_CNI_PLUGIN", v.CNIPlugin)
v.BootstrapMode = getenvDefault("MKS_BOOTSTRAP_MODE", v.BootstrapMode)
v.JoinKind = getenvDefault("MKS_JOIN_KIND", v.JoinKind)
v.AllowSchedulingOnControlPlane = getenvBoolDefault("MKS_ALLOW_SCHEDULING_ON_CONTROL_PLANE", v.AllowSchedulingOnControlPlane)
v.SkipImageCheck = getenvBoolDefault("MKS_SKIP_IMAGE_CHECK", v.SkipImageCheck)
v.MgmtIface = getenvDefault("MKS_MGMT_IFACE", v.MgmtIface)
v.MgmtAddress = getenvDefault("MKS_MGMT_ADDRESS", v.MgmtAddress)
v.MgmtGateway = getenvDefault("MKS_MGMT_GATEWAY", v.MgmtGateway)
if xs := splitWhitespaceList(os.Getenv("MKS_DNS_NAMESERVERS")); len(xs) > 0 {
v.DNSNameservers = xs
}
if xs := splitWhitespaceList(os.Getenv("MKS_DNS_SEARCH_DOMAINS")); len(xs) > 0 {
v.DNSSearchDomains = xs
}
if xs := splitCommaList(os.Getenv("MKS_SANS")); len(xs) > 0 {
v.SubjectAltNames = xs
}
if m := parseKeyValueMap(os.Getenv("MKS_NODE_LABELS")); len(m) > 0 {
v.NodeLabels = m
}
if m := parseKeyValueMap(os.Getenv("MKS_NODE_ANNOTATIONS")); len(m) > 0 {
v.NodeAnnotations = m
}
return v
}
func getenvDefault(key, def string) string {
s := strings.TrimSpace(os.Getenv(key))
if s == "" {
return def
}
return s
}
func getenvBoolDefault(key string, def bool) bool {
s := strings.TrimSpace(strings.ToLower(os.Getenv(key)))
if s == "" {
return def
}
switch s {
case "1", "true", "yes", "y", "on":
return true
case "0", "false", "no", "n", "off":
return false
default:
return def
}
}
func splitCommaList(s string) []string {
if strings.TrimSpace(s) == "" {
return nil
}
parts := strings.Split(s, ",")
out := make([]string, 0, len(parts))
for _, p := range parts {
p = strings.TrimSpace(p)
if p != "" {
out = append(out, p)
}
}
return out
}
func splitWhitespaceList(s string) []string {
if strings.TrimSpace(s) == "" {
return nil
}
return strings.Fields(s)
}
func parseKeyValueMap(s string) map[string]string {
out := map[string]string{}
if strings.TrimSpace(s) == "" {
return out
}
for _, item := range strings.Split(s, ",") {
item = strings.TrimSpace(item)
if item == "" {
continue
}
k, val, ok := strings.Cut(item, "=")
if !ok {
continue
}
k = strings.TrimSpace(k)
val = strings.TrimSpace(val)
if k == "" {
continue
}
out[k] = val
}
return out
}