From ec708aa8320cb37aad778c3fa955a22fb481fe35 Mon Sep 17 00:00:00 2001 From: Abhinav Date: Wed, 1 Feb 2023 16:34:23 -0800 Subject: [PATCH 25/34] Add support for configuring NTP servers on bottlerocket through CAPI Signed-off-by: Abhinav --- .../internal/bottlerocket/bootstrap.go | 10 ++++++++++ .../internal/bottlerocket/bootstrap_test.go | 19 ++++++++++++++++++- .../internal/bottlerocket/bottlerocket.go | 15 ++++++++++++--- .../controllers/kubeadmconfig_controller.go | 10 +++++++++- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/bootstrap/kubeadm/internal/bottlerocket/bootstrap.go b/bootstrap/kubeadm/internal/bottlerocket/bootstrap.go index 58f38ca34..cd70d69a8 100644 --- a/bootstrap/kubeadm/internal/bottlerocket/bootstrap.go +++ b/bootstrap/kubeadm/internal/bottlerocket/bootstrap.go @@ -96,6 +96,12 @@ password = "{{.RegistryMirrorPassword}}" [settings.kubernetes.node-taints] {{.Taints}} {{- end -}} +` + + ntpTemplate = `{{ define "ntpSettings" -}} +[settings.ntp] +time-servers = [{{stringsJoin .NTPServers ", " }}] +{{- end -}} ` bottlerocketNodeInitSettingsTemplate = `{{template "hostContainerSlice" .}} @@ -129,5 +135,9 @@ password = "{{.RegistryMirrorPassword}}" {{- if (ne .Taints "")}} {{template "taintsTemplate" .}} {{- end -}} + +{{- if .NTPServers}} +{{template "ntpSettings" .}} +{{- end -}} ` ) diff --git a/bootstrap/kubeadm/internal/bottlerocket/bootstrap_test.go b/bootstrap/kubeadm/internal/bottlerocket/bootstrap_test.go index 5ee1b0d45..223f49e5a 100644 --- a/bootstrap/kubeadm/internal/bottlerocket/bootstrap_test.go +++ b/bootstrap/kubeadm/internal/bottlerocket/bootstrap_test.go @@ -40,10 +40,20 @@ no-proxy = [] [settings.pki.registry-mirror-ca] data = "REGISTRYCA" trusted=true +[[settings.container-registry.credentials]] +registry = "public.ecr.aws" +username = "admin" +password = "pass" +[[settings.container-registry.credentials]] +registry = "REGISTRYENDPOINT" +username = "admin" +password = "pass" [settings.kubernetes.node-labels] KEY=VAR [settings.kubernetes.node-taints] -KEY=VAR` +KEY=VAR +[settings.ntp] +time-servers = ["1.2.3.4", "time-a.capi.com", "time-b.capi.com"]` const userDataNoAdminImage = ` [settings.host-containers.admin] @@ -99,6 +109,13 @@ func TestGenerateUserData(t *testing.T) { NodeLabels: "KEY=VAR", Taints: "KEY=VAR", ProviderId: "PROVIDERID", + RegistryMirrorUsername: "admin", + RegistryMirrorPassword: "pass", + NTPServers: []string{ + "\"1.2.3.4\"", + "\"time-a.capi.com\"", + "\"time-b.capi.com\"", + }, HostContainers: []bootstrapv1.BottlerocketHostContainer{ { Name: "admin", diff --git a/bootstrap/kubeadm/internal/bottlerocket/bottlerocket.go b/bootstrap/kubeadm/internal/bottlerocket/bottlerocket.go index c37713406..05e441723 100644 --- a/bootstrap/kubeadm/internal/bottlerocket/bottlerocket.go +++ b/bootstrap/kubeadm/internal/bottlerocket/bottlerocket.go @@ -33,6 +33,7 @@ type BottlerocketConfig struct { Taints []corev1.Taint BottlerocketCustomHostContainers []bootstrapv1.BottlerocketHostContainer BottlerocketCustomBootstrapContainers []bootstrapv1.BottlerocketBootstrapContainer + NTPServers []string RegistryMirrorCredentials } @@ -45,6 +46,7 @@ type BottlerocketSettingsInput struct { RegistryMirrorUsername string RegistryMirrorPassword string NodeLabels string + NTPServers []string Taints string ProviderId string HostContainers []bootstrapv1.BottlerocketHostContainer @@ -57,8 +59,8 @@ type HostPath struct { } type RegistryMirrorCredentials struct { - Username string - Password string + Username string + Password string } func generateBootstrapContainerUserData(kind string, tpl string, data interface{}) ([]byte, error) { @@ -141,6 +143,9 @@ func generateNodeUserData(kind string, tpl string, data interface{}) ([]byte, er if _, err := tm.Parse(taintsTemplate); err != nil { return nil, errors.Wrapf(err, "failed to parse taints %s template", kind) } + if _, err := tm.Parse(ntpTemplate); err != nil { + return nil, errors.Wrapf(err, "failed to parse NTP %s template", kind) + } t, err := tm.Parse(tpl) if err != nil { return nil, errors.Wrapf(err, "failed to parse %s template", kind) @@ -214,11 +219,15 @@ func getBottlerocketNodeUserData(bootstrapContainerUserData []byte, users []boot if config.RegistryMirrorConfiguration.CACert != "" { bottlerocketInput.RegistryMirrorCACert = base64.StdEncoding.EncodeToString([]byte(config.RegistryMirrorConfiguration.CACert)) } - if config.RegistryMirrorCredentials.Username != "" && config.RegistryMirrorCredentials.Password != "" { bottlerocketInput.RegistryMirrorUsername = config.RegistryMirrorCredentials.Username bottlerocketInput.RegistryMirrorPassword = config.RegistryMirrorCredentials.Password } + if len(config.NTPServers) > 0 { + for _, ntp := range config.NTPServers { + bottlerocketInput.NTPServers = append(bottlerocketInput.NTPServers, strconv.Quote(ntp)) + } + } bottlerocketNodeUserData, err := generateNodeUserData("InitBottlerocketNode", bottlerocketNodeInitSettingsTemplate, bottlerocketInput) if err != nil { diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go index afaab8a16..fbf7b634f 100644 --- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go +++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go @@ -496,6 +496,9 @@ func (r *KubeadmConfigReconciler) handleClusterNotInitialized(ctx context.Contex if len(scope.Config.Spec.InitConfiguration.NodeRegistration.Taints) > 0 { bottlerocketConfig.Taints = scope.Config.Spec.InitConfiguration.NodeRegistration.Taints } + if scope.Config.Spec.NTP != nil && scope.Config.Spec.NTP.Enabled != nil && *scope.Config.Spec.NTP.Enabled { + bottlerocketConfig.NTPServers = scope.Config.Spec.NTP.Servers + } } @@ -709,6 +712,9 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope) if len(scope.Config.Spec.JoinConfiguration.NodeRegistration.Taints) > 0 { bottlerocketConfig.Taints = scope.Config.Spec.JoinConfiguration.NodeRegistration.Taints } + if scope.Config.Spec.NTP != nil && scope.Config.Spec.NTP.Enabled != nil && *scope.Config.Spec.NTP.Enabled { + bottlerocketConfig.NTPServers = scope.Config.Spec.NTP.Servers + } bootstrapJoinData, err = bottlerocket.NewNode(nodeInput, bottlerocketConfig) if err != nil { scope.Error(err, "Failed to create a worker bottlerocket join configuration") @@ -845,6 +851,9 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S if len(scope.Config.Spec.JoinConfiguration.NodeRegistration.Taints) > 0 { bottlerocketConfig.Taints = scope.Config.Spec.JoinConfiguration.NodeRegistration.Taints } + if scope.Config.Spec.NTP != nil && scope.Config.Spec.NTP.Enabled != nil && *scope.Config.Spec.NTP.Enabled { + bottlerocketConfig.NTPServers = scope.Config.Spec.NTP.Servers + } bootstrapJoinData, err = bottlerocket.NewJoinControlPlane(controlPlaneJoinInput, bottlerocketConfig) if err != nil { scope.Error(err, "Failed to generate cloud init for bottlerocket bootstrap control plane") @@ -965,7 +974,6 @@ func (r *KubeadmConfigReconciler) resolveRegistryCredentials(ctx context.Context return username, password, nil } - // ClusterToKubeadmConfigs is a handler.ToRequestsFunc to be used to enqueue // requests for reconciliation of KubeadmConfigs. func (r *KubeadmConfigReconciler) ClusterToKubeadmConfigs(o client.Object) []ctrl.Request { -- 2.40.0