diff --git a/charts/internal/gvisor/templates/psp-gvisor.yaml b/charts/internal/gvisor/templates/psp-gvisor.yaml index 7de61d1e..ab3853a6 100644 --- a/charts/internal/gvisor/templates/psp-gvisor.yaml +++ b/charts/internal/gvisor/templates/psp-gvisor.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.pspDisabled }} apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: @@ -21,4 +22,5 @@ spec: supplementalGroups: rule: 'RunAsAny' fsGroup: - rule: 'RunAsAny' \ No newline at end of file + rule: 'RunAsAny' +{{- end }} diff --git a/charts/internal/gvisor/templates/rbac-gvisor.yaml b/charts/internal/gvisor/templates/rbac-gvisor.yaml index b33504e0..f64a5c9c 100644 --- a/charts/internal/gvisor/templates/rbac-gvisor.yaml +++ b/charts/internal/gvisor/templates/rbac-gvisor.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.pspDisabled }} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: @@ -25,3 +26,4 @@ subjects: - kind: ServiceAccount name: gvisor namespace: kube-system +{{- end }} diff --git a/charts/internal/gvisor/values.yaml b/charts/internal/gvisor/values.yaml index 45f2c34e..68f27bd0 100644 --- a/charts/internal/gvisor/values.yaml +++ b/charts/internal/gvisor/values.yaml @@ -1,2 +1,4 @@ config: - kubernetesVersion: 1.16.1 \ No newline at end of file + kubernetesVersion: 1.16.1 + +pspDisabled: false diff --git a/pkg/charts/charts_test.go b/pkg/charts/charts_test.go index 787959e6..ec35e9b7 100644 --- a/pkg/charts/charts_test.go +++ b/pkg/charts/charts_test.go @@ -73,6 +73,7 @@ var _ = Describe("Chart package test", func() { "config": map[string]interface{}{ "kubernetesVersion": kubernetesVersion, }, + "pspDisabled": true, } mockChartRenderer.EXPECT().Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gomock.Eq(renderedValues)).Return(&chartrenderer.RenderedChart{ @@ -82,7 +83,7 @@ var _ = Describe("Chart package test", func() { }, }, nil) - _, err := charts.RenderGVisorChart(mockChartRenderer, kubernetesVersion) + _, err := charts.RenderGVisorChart(mockChartRenderer, kubernetesVersion, true) Expect(err).NotTo(HaveOccurred()) }) diff --git a/pkg/charts/values.go b/pkg/charts/values.go index dc666bb2..70fed743 100644 --- a/pkg/charts/values.go +++ b/pkg/charts/values.go @@ -57,13 +57,14 @@ func RenderGVisorInstallationChart(renderer chartrenderer.Interface, cr *extensi } // RenderGVisorChart renders the gVisor chart -func RenderGVisorChart(renderer chartrenderer.Interface, kubernetesVersion string) ([]byte, error) { +func RenderGVisorChart(renderer chartrenderer.Interface, kubernetesVersion string, pspDisabled bool) ([]byte, error) { configChartValues := map[string]interface{}{ "kubernetesVersion": kubernetesVersion, } gvisorChartValues := map[string]interface{}{ - "config": configChartValues, + "config": configChartValues, + "pspDisabled": pspDisabled, } release, err := renderer.Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gvisorChartValues) diff --git a/pkg/controller/actuator_reconcile.go b/pkg/controller/actuator_reconcile.go index b540748b..589cf5bd 100644 --- a/pkg/controller/actuator_reconcile.go +++ b/pkg/controller/actuator_reconcile.go @@ -22,12 +22,10 @@ import ( "github.com/go-logr/logr" extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" + gardencorev1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" - resourcesv1alpha1 "github.com/gardener/gardener/pkg/apis/resources/v1alpha1" - kutil "github.com/gardener/gardener/pkg/utils/kubernetes" "github.com/gardener/gardener/pkg/utils/managedresources/builder" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -49,48 +47,42 @@ func (a *actuator) Reconcile(ctx context.Context, log logr.Logger, cr *extension return fmt.Errorf("could not create chart renderer for shoot '%s', %w", cr.Namespace, err) } - // if the managed resource containing the prerequisites is not available yet, create it. - mr := &resourcesv1alpha1.ManagedResource{} - if err := a.client.Get(ctx, kutil.Key(cr.Namespace, GVisorManagedResourceName), mr); err != nil { - if !apierrors.IsNotFound(err) { - return err - } - log.Info("Preparing gVisor installation", "shoot", cluster.Shoot.Name, "shootNamespace", cluster.Shoot.Namespace) - // create MR containing the prerequisites for the installation DaemonSet - gVisorChart, err := charts.RenderGVisorChart(chartRenderer, cluster.Shoot.Spec.Kubernetes.Version) - if err != nil { - return err - } + log.Info("Preparing gVisor installation", "shoot", cluster.Shoot.Name, "shootNamespace", cluster.Shoot.Namespace) + // create MR containing the prerequisites for the installation DaemonSet + pspDisabled := gardencorev1beta1helper.IsPSPDisabled(cluster.Shoot) + gVisorChart, err := charts.RenderGVisorChart(chartRenderer, cluster.Shoot.Spec.Kubernetes.Version, pspDisabled) + if err != nil { + return err + } - secret, secretRefs := gvisorSecret(a.client, gVisorChart, cr.Namespace, GVisorSecretName) - if err := secret.Reconcile(ctx); err != nil { - return err - } + gvisorSecret, gvisorSecretRefs := buildSecret(a.client, gVisorChart, cr.Namespace, GVisorSecretName) + if err := gvisorSecret.Reconcile(ctx); err != nil { + return err + } - if err := builder. - NewManagedResource(a.client). - WithNamespacedName(cr.Namespace, GVisorManagedResourceName). - WithSecretRefs(secretRefs). - Reconcile(ctx); err != nil { - return fmt.Errorf("failed to create managed resource - prerequisite for the installation of gVisor, %w", err) - } + if err := builder. + NewManagedResource(a.client). + WithNamespacedName(cr.Namespace, GVisorManagedResourceName). + WithSecretRefs(gvisorSecretRefs). + Reconcile(ctx); err != nil { + return fmt.Errorf("failed to create managed resource - prerequisite for the installation of gVisor, %w", err) } log.Info("Installing gVisor", "shoot", cluster.Shoot.Name, "shootNamespace", cluster.Shoot.Namespace, "workerPoolName", cr.Spec.WorkerPool.Name) - gVisorChart, err := charts.RenderGVisorInstallationChart(chartRenderer, cr) + gVisorInstallationChart, err := charts.RenderGVisorInstallationChart(chartRenderer, cr) if err != nil { return err } - secret, secretRefs := gvisorSecret(a.client, gVisorChart, cr.Namespace, fmt.Sprintf("%s-%s", GVisorInstallationSecretName, cr.Spec.WorkerPool.Name)) - if err := secret.Reconcile(ctx); err != nil { + gVisorInstallationSecret, gVisorInstallationSecretRefs := buildSecret(a.client, gVisorInstallationChart, cr.Namespace, fmt.Sprintf("%s-%s", GVisorInstallationSecretName, cr.Spec.WorkerPool.Name)) + if err := gVisorInstallationSecret.Reconcile(ctx); err != nil { return err } return builder. NewManagedResource(a.client). WithNamespacedName(cr.Namespace, GetGVisorInstallationManagedResourceName(cr)). - WithSecretRefs(secretRefs). + WithSecretRefs(gVisorInstallationSecretRefs). Reconcile(ctx) } @@ -107,7 +99,7 @@ func withLocalObjectRefs(refs ...string) []corev1.LocalObjectReference { return localObjectRefs } -func gvisorSecret(cl client.Client, gVisorConfig []byte, namespace, secretName string) (*builder.Secret, []corev1.LocalObjectReference) { +func buildSecret(cl client.Client, gVisorConfig []byte, namespace, secretName string) (*builder.Secret, []corev1.LocalObjectReference) { return builder.NewSecret(cl). WithKeyValues(map[string][]byte{charts.GVisorConfigKey: gVisorConfig}). WithNamespacedName(namespace, secretName), withLocalObjectRefs(secretName) diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go index 51ecdfdb..3c365b55 100644 --- a/pkg/controller/controller_test.go +++ b/pkg/controller/controller_test.go @@ -114,8 +114,6 @@ var _ = Describe("Chart package test", func() { } // ---------- gVisor Preparation ------------------- - // mockClient retrieves extension-runtime-gvisor managed resource - not found - mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound) // chart renderer renders chart with path "gvisor" chartRenderer.EXPECT().Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gomock.Any()).Return(renderedChart, nil) // mockClient creates or update secret for managed resource "extension-runtime-gvisor" @@ -176,8 +174,27 @@ var _ = Describe("Chart package test", func() { Manifests: []manifest.Manifest{{Content: manifestContent}}, } - // mockClient retrieves extension-runtime-gvisor managed resource - already exists - mockClient.EXPECT().Get(context.TODO(), gomock.Any(), gomock.Any()).Return(nil) + // ---------- gVisor Preparation ------------------- + // chart renderer renders chart with path "gvisor" + mockChartRenderer.EXPECT().Render(gvisor.ChartPath, gvisor.ReleaseName, metav1.NamespaceSystem, gomock.Any()).Return(renderedChart, nil) + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{Name: controller.GVisorSecretName, Namespace: namespaceName}, + Data: map[string][]byte{charts.GVisorConfigKey: renderedChart.Manifest()}, + Type: corev1.SecretTypeOpaque, + } + mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound) + mockClient.EXPECT().Create(ctx, secret).Return(nil) + // Validate deployed managed resource "extension-runtime-gvisor" + managedResource := &resourcesv1alpha1.ManagedResource{ + ObjectMeta: metav1.ObjectMeta{Name: controller.GVisorManagedResourceName, Namespace: namespaceName}, + Spec: resourcesv1alpha1.ManagedResourceSpec{ + SecretRefs: []corev1.LocalObjectReference{ + {Name: controller.GVisorSecretName}, + }, + }, + } + mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound) + mockClient.EXPECT().Create(ctx, managedResource).Return(nil) // ---------- gVisor Installation ------------------- mockChartRenderer.EXPECT().Render(gvisor.InstallationChartPath, gvisor.InstallationReleaseName, metav1.NamespaceSystem, gomock.Any()).Return(renderedChart, nil) @@ -271,10 +288,7 @@ var _ = Describe("Chart package test", func() { obj.(*resourcesv1alpha1.ManagedResource).ObjectMeta.DeletionTimestamp = &now return nil } - mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable) - mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable) - mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable) - mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable) + mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(managedResourceStillAvailable).Times(4) mockClient.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(errNotFound) // Create mock mockClient