diff --git a/.changelog/3531.txt b/.changelog/3531.txt new file mode 100644 index 0000000000..cd61ff3ce2 --- /dev/null +++ b/.changelog/3531.txt @@ -0,0 +1,3 @@ +```release-note:improvement +api-gateway: Apply `connectInject.initContainer.resources` to the init container for API gateway Pods. +``` diff --git a/control-plane/api-gateway/common/helm_config.go b/control-plane/api-gateway/common/helm_config.go index 7ce8e0778a..9b0ab1d7e8 100644 --- a/control-plane/api-gateway/common/helm_config.go +++ b/control-plane/api-gateway/common/helm_config.go @@ -6,6 +6,8 @@ package common import ( "strings" "time" + + v1 "k8s.io/api/core/v1" ) const componentAuthMethod = "k8s-component-auth-method" @@ -40,6 +42,8 @@ type HelmConfig struct { // MapPrivilegedServicePorts is the value which Consul will add to privileged container port values (ports < 1024) // defined on a Gateway. MapPrivilegedServicePorts int + + InitContainerResources *v1.ResourceRequirements } type ConsulConfig struct { diff --git a/control-plane/api-gateway/gatekeeper/gatekeeper_test.go b/control-plane/api-gateway/gatekeeper/gatekeeper_test.go index 72bf6aeabc..8e212344b5 100644 --- a/control-plane/api-gateway/gatekeeper/gatekeeper_test.go +++ b/control-plane/api-gateway/gatekeeper/gatekeeper_test.go @@ -15,6 +15,7 @@ import ( corev1 "k8s.io/api/core/v1" rbac "k8s.io/api/rbac/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -109,6 +110,16 @@ func TestUpsert(t *testing.T) { }, helmConfig: common.HelmConfig{ ImageDataplane: dataplaneImage, + InitContainerResources: &corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: requireQuantity(t, "100m"), + corev1.ResourceMemory: requireQuantity(t, "2Gi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: requireQuantity(t, "100m"), + corev1.ResourceMemory: requireQuantity(t, "2Gi"), + }, + }, }, initialResources: resources{}, finalResources: resources{ @@ -764,7 +775,7 @@ func TestUpsert(t *testing.T) { err := gatekeeper.Upsert(context.Background(), tc.gateway, tc.gatewayClassConfig, tc.helmConfig) require.NoError(t, err) - require.NoError(t, validateResourcesExist(t, client, tc.finalResources)) + require.NoError(t, validateResourcesExist(t, client, tc.helmConfig, tc.finalResources)) }) } } @@ -953,7 +964,7 @@ func TestDelete(t *testing.T) { Name: tc.gateway.Name, }) require.NoError(t, err) - require.NoError(t, validateResourcesExist(t, client, tc.finalResources)) + require.NoError(t, validateResourcesExist(t, client, tc.helmConfig, tc.finalResources)) require.NoError(t, validateResourcesAreDeleted(t, client, tc.initialResources)) }) } @@ -983,7 +994,7 @@ func joinResources(resources resources) (objs []client.Object) { return objs } -func validateResourcesExist(t *testing.T, client client.Client, resources resources) error { +func validateResourcesExist(t *testing.T, client client.Client, helmConfig common.HelmConfig, resources resources) error { t.Helper() for _, expected := range resources.deployments { @@ -1012,6 +1023,21 @@ func validateResourcesExist(t *testing.T, client client.Client, resources resour require.Equal(t, expected.Spec.Template.ObjectMeta.Annotations, actual.Spec.Template.ObjectMeta.Annotations) require.Equal(t, expected.Spec.Template.ObjectMeta.Labels, actual.Spec.Template.Labels) + // Ensure there is an init container + hasInitContainer := false + for _, container := range actual.Spec.Template.Spec.InitContainers { + if container.Name == injectInitContainerName { + hasInitContainer = true + + // If the Helm config specifies init container resources, verify they are set + if helmConfig.InitContainerResources != nil { + assert.Equal(t, helmConfig.InitContainerResources.Limits, container.Resources.Limits) + assert.Equal(t, helmConfig.InitContainerResources.Requests, container.Resources.Requests) + } + } + } + assert.True(t, hasInitContainer) + // Ensure there is a consul-dataplane container dropping ALL capabilities, adding // back the NET_BIND_SERVICE capability, and establishing a read-only root filesystem hasDataplaneContainer := false @@ -1349,3 +1375,9 @@ func configureServiceAccount(name, namespace string, labels map[string]string, r }, } } + +func requireQuantity(t *testing.T, v string) resource.Quantity { + quantity, err := resource.ParseQuantity(v) + require.NoError(t, err) + return quantity +} diff --git a/control-plane/api-gateway/gatekeeper/init.go b/control-plane/api-gateway/gatekeeper/init.go index f3d4ad1f95..1d57123fed 100644 --- a/control-plane/api-gateway/gatekeeper/init.go +++ b/control-plane/api-gateway/gatekeeper/init.go @@ -11,9 +11,10 @@ import ( corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" + "github.com/hashicorp/consul-k8s/control-plane/api-gateway/common" "github.com/hashicorp/consul-k8s/control-plane/namespaces" - "k8s.io/utils/pointer" ) const ( @@ -168,6 +169,10 @@ func initContainer(config common.HelmConfig, name, namespace string) (corev1.Con }) } + if config.InitContainerResources != nil { + container.Resources = *config.InitContainerResources + } + // Openshift Assigns the security context for us, do not enable if it is enabled. if !config.EnableOpenShift { container.SecurityContext = &corev1.SecurityContext{ diff --git a/control-plane/subcommand/inject-connect/v1controllers.go b/control-plane/subcommand/inject-connect/v1controllers.go index f717b873b0..0081935199 100644 --- a/control-plane/subcommand/inject-connect/v1controllers.go +++ b/control-plane/subcommand/inject-connect/v1controllers.go @@ -128,6 +128,7 @@ func (c *Command) configureV1Controllers(ctx context.Context, mgr manager.Manage ConsulTLSServerName: c.consul.TLSServerName, ConsulPartition: c.consul.Partition, ConsulCACert: string(c.caCertPem), + InitContainerResources: &c.initContainerResources, }, AllowK8sNamespacesSet: allowK8sNamespaces, DenyK8sNamespacesSet: denyK8sNamespaces,