Repository: aquasecurity/starboard
Pull request #639 (2021-07-16 20:29:17)

Introduce resource request/limit parameters for trivy pod 
This PR solves the problem reported in #572: with for new configuration values the resource/limit requirements of the trivy pod can be adjusted.

Defaults are added to the Helm charts and k8s resources:

```
#k8s resource requests and limits
  resources:
    request:
      cpu: 100m
      memory: 100M
    limit:
      cpu: 500m
      memory: 500M
```

But configmap of existing custom instances should be updated to use limits as before.  

codecov[bot]: # [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) Report
> Merging [#639](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) (7529efd) into [main](https://codecov.io/gh/aquasecurity/starboard/commit/cc32bbb31bfd310fd1abc375034add08aaf8a037?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) (cc32bbb) will **decrease** coverage by `29.62%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/aquasecurity/starboard/pull/639/graphs/tree.svg?width=650&height=150&src=pr&token=qqTGKAJ0Wb&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity)](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity)

```diff
@@             Coverage Diff             @@
##             main     #639       +/-   ##
===========================================
- Coverage   68.41%   38.78%   -29.63%     
===========================================
  Files          58       12       -46     
  Lines        4454     1302     -3152     
===========================================
- Hits         3047      505     -2542     
+ Misses       1054      726      -328     
+ Partials      353       71      -282     
```


| [Impacted Files](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) | Coverage Δ | |
|---|---|---|
| [pkg/configauditreport/scanner.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NvbmZpZ2F1ZGl0cmVwb3J0L3NjYW5uZXIuZ28=) | `0.00% <0.00%> (-70.77%)` | :arrow_down: |
| [pkg/operator/controller/vulnerabilityreport.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL29wZXJhdG9yL2NvbnRyb2xsZXIvdnVsbmVyYWJpbGl0eXJlcG9ydC5nbw==) | `0.00% <0.00%> (-68.04%)` | :arrow_down: |
| [pkg/operator/controller/ciskubebenchreport.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL29wZXJhdG9yL2NvbnRyb2xsZXIvY2lza3ViZWJlbmNocmVwb3J0Lmdv) | `0.00% <0.00%> (-62.77%)` | :arrow_down: |
| [pkg/operator/predicate/predicate.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL29wZXJhdG9yL3ByZWRpY2F0ZS9wcmVkaWNhdGUuZ28=) | `62.06% <0.00%> (-29.32%)` | :arrow_down: |
| [pkg/plugin/factory.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL3BsdWdpbi9mYWN0b3J5Lmdv) | `51.21% <0.00%> (-29.27%)` | :arrow_down: |
| [pkg/operator/operator.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL29wZXJhdG9yL29wZXJhdG9yLmdv) | `38.68% <0.00%> (-24.09%)` | :arrow_down: |
| [pkg/configauditreport/io.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NvbmZpZ2F1ZGl0cmVwb3J0L2lvLmdv) | `43.90% <0.00%> (-12.20%)` | :arrow_down: |
| [pkg/operator/controller/configauditreport.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL29wZXJhdG9yL2NvbnRyb2xsZXIvY29uZmlnYXVkaXRyZXBvcnQuZ28=) | `57.87% <0.00%> (-6.95%)` | :arrow_down: |
| [pkg/plugin/conftest/plugin.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL3BsdWdpbi9jb25mdGVzdC9wbHVnaW4uZ28=) | `85.09% <0.00%> (-1.87%)` | :arrow_down: |
| [pkg/cmd/root.go](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity#diff-cGtnL2NtZC9yb290Lmdv) | | |
| ... and [44 more](https://codecov.io/gh/aquasecurity/starboard/pull/639/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity). Last update [cc32bbb...7529efd](https://codecov.io/gh/aquasecurity/starboard/pull/639?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=aquasecurity).

elek: Thanks the suggestion @danielpacak. I improved the error handling and defaults handling.

Still, one test is failing locally:

```
• Failure [6.160 seconds]
Starboard CLI
/home/elek/s/starboard/itest/starboard/starboard_cli_test.go:34
  Command init
  /home/elek/s/starboard/itest/starboard/starboard_cli_test.go:44
    should initialize Starboard [It]
    /home/elek/s/starboard/itest/starboard/starboard_cli_test.go:46
```

But the same test is also failing (locally) on my `origin/main`. As all the other tests are passing, I think it can be tested on the CI while I am debugging my local environments...

Patch:
diff --git a/deploy/helm/templates/config.yaml b/deploy/helm/templates/config.yaml
index aa168d3..8a0abee 100644
--- a/deploy/helm/templates/config.yaml
+++ b/deploy/helm/templates/config.yaml
@@ -35,6 +35,25 @@ data:
   {{- if eq .Values.trivy.mode "ClientServer" }}
   trivy.serverURL: "{{ .Values.trivy.serverURL }}"
   {{- end }}
+  {{- with .Values.trivy.resources }}
+    {{- with .request }}
+      {{- if .cpu }}
+  trivy.resources.request.cpu: {{ .cpu }}
+      {{- end }}
+      {{- if hasKey . "memory" }}
+  trivy.resources.request.memory: {{ .memory }}
+      {{- end }}
+    {{- end }}
+    {{- with .limit }}
+      {{- if .cpu }}
+  trivy.resources.limit.cpu: {{ .cpu }}
+      {{- end }}
+      {{- if .memory }}
+  trivy.resources.limit.memory: {{ .memory }}
+      {{- end }}
+    {{- end }}
+  {{- end }}
+
 ---
 apiVersion: v1
 kind: Secret
diff --git a/deploy/helm/values.yaml b/deploy/helm/values.yaml
index 02f0733..abeabd6 100644
--- a/deploy/helm/values.yaml
+++ b/deploy/helm/values.yaml
@@ -92,6 +92,14 @@ trivy:
   httpsProxy:
   noProxy:
   severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
+#k8s resource requests and limits
+  resources:
+    request:
+      cpu: 100m
+      memory: 100M
+    limit:
+      cpu: 500m
+      memory: 500M
 
 kubeBench:
   imageRef: docker.io/aquasec/kube-bench:0.6.3
diff --git a/deploy/static/05-starboard-operator.config.yaml b/deploy/static/05-starboard-operator.config.yaml
index d83a79f..02f04f9 100644
--- a/deploy/static/05-starboard-operator.config.yaml
+++ b/deploy/static/05-starboard-operator.config.yaml
@@ -18,6 +18,10 @@ data:
   trivy.severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
   trivy.imageRef: docker.io/aquasec/trivy:0.16.0
   trivy.mode: Standalone
+  trivy.resources.request.cpu: 100m
+  trivy.resources.request.memory: 100M
+  trivy.resources.limit.cpu: 500m
+  trivy.resources.limit.memory: 500M
 ---
 apiVersion: v1
 kind: ConfigMap
diff --git a/pkg/plugin/trivy/plugin.go b/pkg/plugin/trivy/plugin.go
index 3e03b57..7ed87b6 100644
--- a/pkg/plugin/trivy/plugin.go
+++ b/pkg/plugin/trivy/plugin.go
@@ -19,19 +19,6 @@ import (
 	"k8s.io/utils/pointer"
 )
 
-var (
-	defaultResourceRequirements = corev1.ResourceRequirements{
-		Requests: corev1.ResourceList{
-			corev1.ResourceCPU:    resource.MustParse("100m"),
-			corev1.ResourceMemory: resource.MustParse("100M"),
-		},
-		Limits: corev1.ResourceList{
-			corev1.ResourceCPU:    resource.MustParse("500m"),
-			corev1.ResourceMemory: resource.MustParse("500M"),
-		},
-	}
-)
-
 const (
 	// Plugin the name of this plugin.
 	Plugin = "Trivy"
@@ -60,6 +47,11 @@ const (
 	keyTrivyServerTokenHeader   = "trivy.serverTokenHeader"
 	keyTrivyServerToken         = "trivy.serverToken"
 	keyTrivyServerCustomHeaders = "trivy.serverCustomHeaders"
+
+	keyTrivyResourcesRequestsCPU    = "trivy.resources.request.cpu"
+	keyTrivyResourcesRequestsMemory = "trivy.resources.request.memory"
+	keyTrivyResourcesLimitCPU       = "trivy.resources.limit.cpu"
+	keyTrivyResourcesLimitMemory    = "trivy.resources.limit.memory"
 )
 
 // Mode describes mode in which Trivy client operates.
@@ -117,6 +109,48 @@ func (c Config) GetInsecureRegistries() map[string]bool {
 	return insecureRegistries
 }
 
+//GetResourceRequirements creates k8s requires/limit fragments from the config
+func (c Config) GetResourceRequirements() (corev1.ResourceRequirements, error) {
+	defaultResourceRequirements := corev1.ResourceRequirements{
+		Requests: corev1.ResourceList{},
+		Limits:   corev1.ResourceList{},
+	}
+
+	err := c.setResourceLimit(keyTrivyResourcesRequestsCPU, &defaultResourceRequirements.Requests, corev1.ResourceCPU)
+	if err != nil {
+		return defaultResourceRequirements, err
+	}
+
+	err = c.setResourceLimit(keyTrivyResourcesRequestsMemory, &defaultResourceRequirements.Requests, corev1.ResourceMemory)
+	if err != nil {
+		return defaultResourceRequirements, err
+	}
+
+	err = c.setResourceLimit(keyTrivyResourcesLimitCPU, &defaultResourceRequirements.Limits, corev1.ResourceCPU)
+	if err != nil {
+		return defaultResourceRequirements, err
+	}
+
+	err = c.setResourceLimit(keyTrivyResourcesLimitMemory, &defaultResourceRequirements.Limits, corev1.ResourceMemory)
+	if err != nil {
+		return defaultResourceRequirements, err
+	}
+
+	return defaultResourceRequirements, nil
+}
+
+func (c Config) setResourceLimit(configKey string, k8sResourceList *corev1.ResourceList, k8sResourceName corev1.ResourceName) error {
+	if value, found := c.Data[configKey]; found {
+		quantity, err := resource.ParseQuantity(value)
+		if err != nil {
+			return fmt.Errorf("parsing resource definition %s: %s %v", configKey, value, err)
+		}
+
+		(*k8sResourceList)[k8sResourceName] = quantity
+	}
+	return nil
+}
+
 // NewPlugin constructs a new vulnerabilityreport.Plugin, which is using an
 // upstream Trivy container image to scan Kubernetes workloads.
 //
@@ -139,6 +173,11 @@ func (p *plugin) Init(ctx starboard.PluginContext) error {
 			keyTrivyImageRef: "docker.io/aquasec/trivy:0.16.0",
 			keyTrivySeverity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL",
 			keyTrivyMode:     string(Standalone),
+
+			keyTrivyResourcesRequestsCPU:    "100m",
+			keyTrivyResourcesRequestsMemory: "100M",
+			keyTrivyResourcesLimitCPU:       "500m",
+			keyTrivyResourcesLimitMemory:    "500M",
 		},
 	})
 }
@@ -210,6 +249,11 @@ func (p *plugin) getPodSpecForStandaloneMode(config Config, spec corev1.PodSpec,
 
 	trivyConfigName := starboard.GetPluginConfigMapName(Plugin)
 
+	requirements, err := config.GetResourceRequirements()
+	if err != nil {
+		return corev1.PodSpec{}, nil, err
+	}
+
 	initContainer := corev1.Container{
 		Name:                     p.idGenerator.GenerateID(),
 		Image:                    trivyImageRef,
@@ -273,7 +317,7 @@ func (p *plugin) getPodSpecForStandaloneMode(config Config, spec corev1.PodSpec,
 			"--cache-dir",
 			"/var/lib/trivy",
 		},
-		Resources: defaultResourceRequirements,
+		Resources: requirements,
 		VolumeMounts: []corev1.VolumeMount{
 			{
 				Name:      sharedVolumeName,
@@ -456,6 +500,11 @@ func (p *plugin) getPodSpecForStandaloneMode(config Config, spec corev1.PodSpec,
 			return corev1.PodSpec{}, nil, err
 		}
 
+		resourceRequirements, err := config.GetResourceRequirements()
+		if err != nil {
+			return corev1.PodSpec{}, nil, err
+		}
+
 		containers = append(containers, corev1.Container{
 			Name:                     c.Name,
 			Image:                    trivyImageRef,
@@ -474,7 +523,7 @@ func (p *plugin) getPodSpecForStandaloneMode(config Config, spec corev1.PodSpec,
 				"json",
 				c.Image,
 			},
-			Resources:    defaultResourceRequirements,
+			Resources:    resourceRequirements,
 			VolumeMounts: volumeMounts,
 			SecurityContext: &corev1.SecurityContext{
 				Privileged:               pointer.BoolPtr(false),
@@ -721,6 +770,11 @@ func (p *plugin) getPodSpecForClientServerMode(config Config, spec corev1.PodSpe
 			})
 		}
 
+		requirements, err := config.GetResourceRequirements()
+		if err != nil {
+			return corev1.PodSpec{}, nil, err
+		}
+
 		containers = append(containers, corev1.Container{
 			Name:                     container.Name,
 			Image:                    trivyImageRef,
@@ -740,7 +794,7 @@ func (p *plugin) getPodSpecForClientServerMode(config Config, spec corev1.PodSpe
 				container.Image,
 			},
 			VolumeMounts: volumeMounts,
-			Resources:    defaultResourceRequirements,
+			Resources:    requirements,
 		})
 	}
 


Test patch:
diff --git a/pkg/plugin/trivy/plugin_test.go b/pkg/plugin/trivy/plugin_test.go
index 87e9c90..969569f 100644
--- a/pkg/plugin/trivy/plugin_test.go
+++ b/pkg/plugin/trivy/plugin_test.go
@@ -114,6 +114,81 @@ func TestConfig_GetMode(t *testing.T) {
 	}
 }
 
+func TestConfig_GetResourceRequirements(t *testing.T) {
+	testCases := []struct {
+		name                 string
+		configData           trivy.Config
+		expectedError        string
+		expectedRequirements corev1.ResourceRequirements
+	}{
+		{
+			name:          "Should return empty requirements by default",
+			configData:    trivy.Config{PluginConfig: starboard.PluginConfig{}},
+			expectedError: "",
+			expectedRequirements: corev1.ResourceRequirements{
+				Requests: corev1.ResourceList{},
+				Limits:   corev1.ResourceList{},
+			},
+		},
+		{
+			name: "Should return configured resource requirement",
+			configData: trivy.Config{PluginConfig: starboard.PluginConfig{
+				Data: map[string]string{
+					"trivy.resources.request.cpu":    "800m",
+					"trivy.resources.request.memory": "200M",
+					"trivy.resources.limit.cpu":      "600m",
+					"trivy.resources.limit.memory":   "700M",
+				},
+			}},
+			expectedError: "",
+			expectedRequirements: corev1.ResourceRequirements{
+				Requests: corev1.ResourceList{
+					corev1.ResourceCPU:    resource.MustParse("800m"),
+					corev1.ResourceMemory: resource.MustParse("200M"),
+				},
+				Limits: corev1.ResourceList{
+					corev1.ResourceCPU:    resource.MustParse("600m"),
+					corev1.ResourceMemory: resource.MustParse("700M"),
+				},
+			},
+		},
+		{
+			name: "Should return error if resource is not parseable",
+			configData: trivy.Config{PluginConfig: starboard.PluginConfig{
+				Data: map[string]string{
+					"trivy.resources.request.cpu":    "roughly 100",
+					"trivy.resources.request.memory": "200M",
+					"trivy.resources.limit.cpu":      "600m",
+					"trivy.resources.limit.memory":   "700M",
+				},
+			}},
+			expectedError: "parsing resource definition trivy.resources.request.cpu: roughly 100 quantities must match the regular expression '^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$'",
+			expectedRequirements: corev1.ResourceRequirements{
+				Requests: corev1.ResourceList{
+					corev1.ResourceCPU:    resource.MustParse("800m"),
+					corev1.ResourceMemory: resource.MustParse("200M"),
+				},
+				Limits: corev1.ResourceList{
+					corev1.ResourceCPU:    resource.MustParse("600m"),
+					corev1.ResourceMemory: resource.MustParse("700M"),
+				},
+			},
+		},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			resourceRequirement, err := tc.configData.GetResourceRequirements()
+			if tc.expectedError != "" {
+				require.EqualError(t, err, tc.expectedError)
+			} else {
+				require.NoError(t, err)
+				require.Equal(t, tc.expectedRequirements, resourceRequirement, tc.name)
+			}
+
+		})
+	}
+}
+
 func TestConfig_IgnoreFileExists(t *testing.T) {
 	testCases := []struct {
 		name           string
@@ -208,6 +283,11 @@ func TestScanner_GetScanJobSpec(t *testing.T) {
 			config: map[string]string{
 				"trivy.imageRef": "docker.io/aquasec/trivy:0.14.0",
 				"trivy.mode":     string(trivy.Standalone),
+
+				"trivy.resources.request.cpu":    "100m",
+				"trivy.resources.request.memory": "100M",
+				"trivy.resources.limit.cpu":      "500m",
+				"trivy.resources.limit.memory":   "500M",
 			},
 			workloadSpec: corev1.PodSpec{
 				Containers: []corev1.Container{
@@ -452,6 +532,11 @@ func TestScanner_GetScanJobSpec(t *testing.T) {
 				"trivy.imageRef":                     "docker.io/aquasec/trivy:0.14.0",
 				"trivy.mode":                         string(trivy.Standalone),
 				"trivy.insecureRegistry.pocRegistry": "poc.myregistry.harbor.com.pl",
+
+				"trivy.resources.request.cpu":    "100m",
+				"trivy.resources.request.memory": "100M",
+				"trivy.resources.limit.cpu":      "500m",
+				"trivy.resources.limit.memory":   "500M",
 			},
 			workloadSpec: corev1.PodSpec{
 				Containers: []corev1.Container{
@@ -703,6 +788,10 @@ CVE-2018-14618
 
 # No impact in our settings
 CVE-2019-1543`,
+				"trivy.resources.request.cpu":    "100m",
+				"trivy.resources.request.memory": "100M",
+				"trivy.resources.limit.cpu":      "500m",
+				"trivy.resources.limit.memory":   "500M",
 			},
 			workloadSpec: corev1.PodSpec{
 				Containers: []corev1.Container{
@@ -972,6 +1061,10 @@ CVE-2019-1543`,
 				"trivy.imageRef":  "docker.io/aquasec/trivy:0.14.0",
 				"trivy.mode":      string(trivy.ClientServer),
 				"trivy.serverURL": "http://trivy.trivy:4954",
+				"trivy.resources.request.cpu":    "100m",
+				"trivy.resources.request.memory": "100M",
+				"trivy.resources.limit.cpu":      "500m",
+				"trivy.resources.limit.memory":   "500M",
 			},
 			workloadSpec: corev1.PodSpec{
 				Containers: []corev1.Container{
@@ -1145,6 +1238,10 @@ CVE-2019-1543`,
 				"trivy.mode":                         string(trivy.ClientServer),
 				"trivy.serverURL":                    "http://trivy.trivy:4954",
 				"trivy.insecureRegistry.pocRegistry": "poc.myregistry.harbor.com.pl",
+				"trivy.resources.request.cpu":    "100m",
+				"trivy.resources.request.memory": "100M",
+				"trivy.resources.limit.cpu":      "500m",
+				"trivy.resources.limit.memory":   "500M",
 			},
 			workloadSpec: corev1.PodSpec{
 				Containers: []corev1.Container{
@@ -1326,6 +1423,10 @@ CVE-2018-14618
 
 # No impact in our settings
 CVE-2019-1543`,
+				"trivy.resources.request.cpu":    "100m",
+				"trivy.resources.request.memory": "100M",
+				"trivy.resources.limit.cpu":      "500m",
+				"trivy.resources.limit.memory":   "500M",
 			},
 			workloadSpec: corev1.PodSpec{
 				Containers: []corev1.Container{