github.com/ironcore-dev/gardener-extension-provider-ironcore@v0.3.2-0.20240314231816-8336447fb9a0/pkg/webhook/controlplane/ensurer.go (about)

     1  // SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package controlplane
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/Masterminds/semver/v3"
    10  	"github.com/coreos/go-systemd/v22/unit"
    11  	extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook"
    12  	extensionscontextwebhook "github.com/gardener/gardener/extensions/pkg/webhook/context"
    13  	"github.com/gardener/gardener/extensions/pkg/webhook/controlplane/genericmutator"
    14  	extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
    15  	"github.com/gardener/gardener/pkg/component/machinecontrollermanager"
    16  	"github.com/go-logr/logr"
    17  	appsv1 "k8s.io/api/apps/v1"
    18  	corev1 "k8s.io/api/core/v1"
    19  	"k8s.io/apimachinery/pkg/api/resource"
    20  	vpaautoscalingv1 "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
    21  	kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
    22  
    23  	"github.com/ironcore-dev/gardener-extension-provider-ironcore/imagevector"
    24  	"github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/ironcore"
    25  )
    26  
    27  // NewEnsurer creates a new controlplane ensurer.
    28  func NewEnsurer(logger logr.Logger, gardenletManagesMCM bool) genericmutator.Ensurer {
    29  	return &ensurer{
    30  		logger: logger.WithName("ironcore-controlplane-ensurer"),
    31  	}
    32  }
    33  
    34  type ensurer struct {
    35  	genericmutator.NoopEnsurer
    36  	logger logr.Logger
    37  }
    38  
    39  // ImageVector is exposed for testing.
    40  var ImageVector = imagevector.ImageVector()
    41  
    42  // EnsureMachineControllerManagerDeployment ensures that the machine-controller-manager deployment conforms to the provider requirements.
    43  func (e *ensurer) EnsureMachineControllerManagerDeployment(_ context.Context, _ extensionscontextwebhook.GardenContext, newObj, _ *appsv1.Deployment) error {
    44  	image, err := ImageVector.FindImage(ironcore.MachineControllerManagerProviderIroncoreImageName)
    45  	if err != nil {
    46  		return err
    47  	}
    48  
    49  	template := &newObj.Spec.Template
    50  	ps := &template.Spec
    51  
    52  	ps.Containers = extensionswebhook.EnsureContainerWithName(
    53  		newObj.Spec.Template.Spec.Containers,
    54  		machinecontrollermanager.ProviderSidecarContainer(newObj.Namespace, ironcore.ProviderName, image.String()),
    55  	)
    56  
    57  	if c := extensionswebhook.ContainerWithName(ps.Containers, "machine-controller-manager-provider-ironcore"); c != nil {
    58  		ensureMCMCommandLineArgs(c)
    59  		c.VolumeMounts = extensionswebhook.EnsureVolumeMountWithName(c.VolumeMounts, corev1.VolumeMount{
    60  			Name:      "cloudprovider",
    61  			MountPath: "/etc/ironcore",
    62  			ReadOnly:  true,
    63  		})
    64  	}
    65  
    66  	ps.Volumes = extensionswebhook.EnsureVolumeWithName(ps.Volumes, corev1.Volume{
    67  		Name: "cloudprovider",
    68  		VolumeSource: corev1.VolumeSource{
    69  			Secret: &corev1.SecretVolumeSource{
    70  				SecretName: "cloudprovider",
    71  			},
    72  		},
    73  	})
    74  
    75  	return nil
    76  }
    77  
    78  // EnsureMachineControllerManagerVPA ensures that the machine-controller-manager VPA conforms to the provider requirements.
    79  func (e *ensurer) EnsureMachineControllerManagerVPA(_ context.Context, _ extensionscontextwebhook.GardenContext, newObj, _ *vpaautoscalingv1.VerticalPodAutoscaler) error {
    80  	var (
    81  		minAllowed = corev1.ResourceList{
    82  			corev1.ResourceCPU:    resource.MustParse("30m"),
    83  			corev1.ResourceMemory: resource.MustParse("64Mi"),
    84  		}
    85  		maxAllowed = corev1.ResourceList{
    86  			corev1.ResourceCPU:    resource.MustParse("2"),
    87  			corev1.ResourceMemory: resource.MustParse("5G"),
    88  		}
    89  	)
    90  
    91  	if newObj.Spec.ResourcePolicy == nil {
    92  		newObj.Spec.ResourcePolicy = &vpaautoscalingv1.PodResourcePolicy{}
    93  	}
    94  
    95  	newObj.Spec.ResourcePolicy.ContainerPolicies = extensionswebhook.EnsureVPAContainerResourcePolicyWithName(
    96  		newObj.Spec.ResourcePolicy.ContainerPolicies,
    97  		machinecontrollermanager.ProviderSidecarVPAContainerPolicy(ironcore.ProviderName, minAllowed, maxAllowed),
    98  	)
    99  	return nil
   100  }
   101  
   102  // EnsureKubeAPIServerDeployment ensures that the kube-apiserver deployment conforms to the provider requirements.
   103  func (e *ensurer) EnsureKubeAPIServerDeployment(_ context.Context, _ extensionscontextwebhook.GardenContext, new, _ *appsv1.Deployment) error {
   104  	template := &new.Spec.Template
   105  	ps := &template.Spec
   106  
   107  	if c := extensionswebhook.ContainerWithName(ps.Containers, "kube-apiserver"); c != nil {
   108  		ensureKubeAPIServerCommandLineArgs(c)
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  // EnsureKubeControllerManagerDeployment ensures that the kube-controller-manager deployment conforms to the provider requirements.
   115  func (e *ensurer) EnsureKubeControllerManagerDeployment(_ context.Context, _ extensionscontextwebhook.GardenContext, new, _ *appsv1.Deployment) error {
   116  	template := &new.Spec.Template
   117  	ps := &template.Spec
   118  
   119  	if c := extensionswebhook.ContainerWithName(ps.Containers, "kube-controller-manager"); c != nil {
   120  		ensureKubeControllerManagerCommandLineArgs(c)
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  // EnsureKubeSchedulerDeployment ensures that the kube-scheduler deployment conforms to the provider requirements.
   127  func (e *ensurer) EnsureKubeSchedulerDeployment(_ context.Context, _ extensionscontextwebhook.GardenContext, _, _ *appsv1.Deployment) error {
   128  	return nil
   129  }
   130  
   131  // EnsureClusterAutoscalerDeployment ensures that the cluster-autoscaler deployment conforms to the provider requirements.
   132  func (e *ensurer) EnsureClusterAutoscalerDeployment(_ context.Context, _ extensionscontextwebhook.GardenContext, _, _ *appsv1.Deployment) error {
   133  	return nil
   134  }
   135  
   136  func ensureMCMCommandLineArgs(c *corev1.Container) {
   137  	c.Command = extensionswebhook.EnsureStringWithPrefix(c.Command, "--ironcore-kubeconfig=", "/etc/ironcore/kubeconfig")
   138  }
   139  
   140  func ensureKubeAPIServerCommandLineArgs(c *corev1.Container) {
   141  	c.Command = extensionswebhook.EnsureNoStringWithPrefix(c.Command, "--cloud-provider=")
   142  	c.Command = extensionswebhook.EnsureNoStringWithPrefix(c.Command, "--cloud-config=")
   143  }
   144  
   145  func ensureKubeControllerManagerCommandLineArgs(c *corev1.Container) {
   146  	c.Command = extensionswebhook.EnsureStringWithPrefix(c.Command, "--cloud-provider=", "external")
   147  	c.Command = extensionswebhook.EnsureNoStringWithPrefix(c.Command, "--cloud-config=")
   148  }
   149  
   150  // EnsureKubeletServiceUnitOptions ensures that the kubelet.service unit options conform to the provider requirements.
   151  func (e *ensurer) EnsureKubeletServiceUnitOptions(_ context.Context, _ extensionscontextwebhook.GardenContext, _ *semver.Version, new, _ []*unit.UnitOption) ([]*unit.UnitOption, error) {
   152  	if opt := extensionswebhook.UnitOptionWithSectionAndName(new, "Service", "ExecStart"); opt != nil {
   153  		command := extensionswebhook.DeserializeCommandLine(opt.Value)
   154  		command = ensureKubeletCommandLineArgs(command)
   155  		opt.Value = extensionswebhook.SerializeCommandLine(command, 1, " \\\n    ")
   156  	}
   157  
   158  	new = extensionswebhook.EnsureUnitOption(new, &unit.UnitOption{
   159  		Section: "Service",
   160  		Name:    "ExecStartPre",
   161  		Value:   `/bin/sh -c 'hostnamectl set-hostname $(hostname -f)'`,
   162  	})
   163  
   164  	return new, nil
   165  }
   166  
   167  func ensureKubeletCommandLineArgs(command []string) []string {
   168  	command = extensionswebhook.EnsureStringWithPrefix(command, "--cloud-provider=", "external")
   169  	return command
   170  }
   171  
   172  // EnsureKubeletConfiguration ensures that the kubelet configuration conforms to the provider requirements.
   173  func (e *ensurer) EnsureKubeletConfiguration(_ context.Context, _ extensionscontextwebhook.GardenContext, _ *semver.Version, _, _ *kubeletconfigv1beta1.KubeletConfiguration) error {
   174  	return nil
   175  }
   176  
   177  // EnsureKubernetesGeneralConfiguration ensures that the kubernetes general configuration conforms to the provider requirements.
   178  func (e *ensurer) EnsureKubernetesGeneralConfiguration(_ context.Context, _ extensionscontextwebhook.GardenContext, _, _ *string) error {
   179  	return nil
   180  }
   181  
   182  // EnsureAdditionalUnits ensures that additional required system units are added.
   183  func (e *ensurer) EnsureAdditionalUnits(_ context.Context, _ extensionscontextwebhook.GardenContext, _, _ *[]extensionsv1alpha1.Unit) error {
   184  	return nil
   185  }
   186  
   187  // EnsureAdditionalFiles ensures that additional required system files are added.
   188  func (e *ensurer) EnsureAdditionalFiles(_ context.Context, _ extensionscontextwebhook.GardenContext, _, _ *[]extensionsv1alpha1.File) error {
   189  	return nil
   190  }