Repository: knative/serving
Pull request #12036 (2021-09-23 09:11:26)

allow setting scheduler name in pod spec
I want to create knative pods that will use a specific scheduler, this is currently being actively blocked by the admission controller and this PR will allow it 

<!-- Please include the 'why' behind your changes if no issue exists -->
## Proposed Changes

* add podspec-schedulername flag and configuration option to allow setting the scheduler name in the pod spec
* update the field mask to use that configuration option

**Release Note**

<!-- Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". -->

```release-note
NONE
```


knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/12036#" title="Author self-approved">enoodle</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **rhuss** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @rhuss` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fserving).

<details open>
Needs approval from an approver in each of these files:

- **[pkg/apis/OWNERS](https://github.com/knative/serving/blob/main/pkg/apis/OWNERS)**
- **[pkg/reconciler/route/OWNERS](https://github.com/knative/serving/blob/main/pkg/reconciler/route/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["rhuss"]} -->
knative-prow-robot: Hi @enoodle. Thanks for your PR.

I'm waiting for a [knative](https://github.com/orgs/knative/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://github.com/orgs/knative/people) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=knative%2Fserving).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

knative-prow-robot: Welcome @enoodle! It looks like this is your first PR to knative/serving 🎉
markusthoemmes: /ok-to-test

Welcome to Knative! Implementation of this looks sound to me, summoning @dprotaso from the API group to gauge this further.

/assign @dprotaso 

knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/12036#" title="Author self-approved">enoodle</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please ask for approval from **dprotaso** after the PR has been reviewed.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fserving).

<details open>
Needs approval from an approver in each of these files:

- **[config/OWNERS](https://github.com/knative/serving/blob/main/config/OWNERS)**
- **[pkg/apis/OWNERS](https://github.com/knative/serving/blob/main/pkg/apis/OWNERS)**
- **[pkg/reconciler/route/OWNERS](https://github.com/knative/serving/blob/main/pkg/reconciler/route/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["dprotaso"]} -->
knative-prow-robot: @enoodle: The following tests **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-knative-serving-unit-tests | c04530527fe5af72d89a7efbc8596cc9262f6d64 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/12036/pull-knative-serving-unit-tests/1441023614777298944) | true | `/test pull-knative-serving-unit-tests`
pull-knative-serving-upgrade-tests | c04530527fe5af72d89a7efbc8596cc9262f6d64 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/12036/pull-knative-serving-upgrade-tests/1441023614810853376) | true | `/test pull-knative-serving-upgrade-tests`

[Full PR test history](https://gubernator.knative.dev/pr/knative_serving/12036). [Your PR dashboard](https://gubernator.knative.dev/pr/enoodle).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/config/core/configmaps/features.yaml b/config/core/configmaps/features.yaml
index b13066048..c0eeeba2c 100644
--- a/config/core/configmaps/features.yaml
+++ b/config/core/configmaps/features.yaml
@@ -22,7 +22,7 @@ metadata:
     app.kubernetes.io/version: devel
     app.kubernetes.io/part-of: knative-serving
   annotations:
-    knative.dev/example-checksum: "5b8c26fe"
+    knative.dev/example-checksum: "0b69357a"
 data:
   _example: |-
     ################################
@@ -106,6 +106,12 @@ data:
     # See: https://knative.dev/docs/serving/feature-flags/#kubernetes-priority-class-name
     kubernetes.podspec-priorityclassname: "disabled"
 
+    # Indicates whether Kubernetes SchedulerName support is enabled
+    #
+    # WARNING: Cannot safely be disabled once enabled.
+    # See: https://knative.dev/docs/serving/feature-flags/#kubernetes-scheduler-name
+    kubernetes.podspec-schedulername: "disabled"
+
     # This feature flag allows end-users to add a subset of capabilities on the Pod's SecurityContext.
     #
     # When set to "enabled" or "allowed" it allows capabilities to be added to the container.
diff --git a/pkg/apis/config/features.go b/pkg/apis/config/features.go
index cfdda32de..17e75fc07 100644
--- a/pkg/apis/config/features.go
+++ b/pkg/apis/config/features.go
@@ -50,6 +50,7 @@ func defaultFeaturesConfig() *Features {
 		PodSpecRuntimeClassName:      Disabled,
 		PodSpecSecurityContext:       Disabled,
 		PodSpecPriorityClassName:     Disabled,
+		PodSpecSchedulerName:         Disabled,
 		ContainerSpecAddCapabilities: Disabled,
 		PodSpecTolerations:           Disabled,
 		PodSpecVolumesEmptyDir:       Disabled,
@@ -72,6 +73,7 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) {
 		asFlag("kubernetes.podspec-runtimeclassname", &nc.PodSpecRuntimeClassName),
 		asFlag("kubernetes.podspec-securitycontext", &nc.PodSpecSecurityContext),
 		asFlag("kubernetes.podspec-priorityclassname", &nc.PodSpecPriorityClassName),
+		asFlag("kubernetes.podspec-schedulername", &nc.PodSpecSchedulerName),
 		asFlag("kubernetes.containerspec-addcapabilities", &nc.ContainerSpecAddCapabilities),
 		asFlag("kubernetes.podspec-tolerations", &nc.PodSpecTolerations),
 		asFlag("kubernetes.podspec-volumes-emptydir", &nc.PodSpecVolumesEmptyDir),
@@ -98,6 +100,7 @@ type Features struct {
 	PodSpecRuntimeClassName      Flag
 	PodSpecSecurityContext       Flag
 	PodSpecPriorityClassName     Flag
+	PodSpecSchedulerName         Flag
 	ContainerSpecAddCapabilities Flag
 	PodSpecTolerations           Flag
 	PodSpecVolumesEmptyDir       Flag
diff --git a/pkg/apis/serving/fieldmask.go b/pkg/apis/serving/fieldmask.go
index 30f349f68..aa6a86853 100644
--- a/pkg/apis/serving/fieldmask.go
+++ b/pkg/apis/serving/fieldmask.go
@@ -210,6 +210,9 @@ func PodSpecMask(ctx context.Context, in *corev1.PodSpec) *corev1.PodSpec {
 	if cfg.Features.PodSpecPriorityClassName != config.Disabled {
 		out.PriorityClassName = in.PriorityClassName
 	}
+	if cfg.Features.PodSpecSchedulerName != config.Disabled {
+		out.SchedulerName = in.SchedulerName
+	}
 
 	// Disallowed fields
 	// This list is unnecessary, but added here for clarity
@@ -225,7 +228,6 @@ func PodSpecMask(ctx context.Context, in *corev1.PodSpec) *corev1.PodSpec {
 	out.ShareProcessNamespace = nil
 	out.Hostname = ""
 	out.Subdomain = ""
-	out.SchedulerName = ""
 	out.Priority = nil
 	out.DNSConfig = nil
 	out.ReadinessGates = nil


Test patch:
diff --git a/pkg/apis/config/features_test.go b/pkg/apis/config/features_test.go
index 9db3d93b0..cc35f5b68 100644
--- a/pkg/apis/config/features_test.go
+++ b/pkg/apis/config/features_test.go
@@ -68,6 +68,7 @@ func TestFeaturesConfiguration(t *testing.T) {
 			PodSpecSecurityContext:   Enabled,
 			PodSpecTolerations:       Enabled,
 			PodSpecPriorityClassName: Enabled,
+			PodSpecSchedulerName:     Enabled,
 			TagHeaderBasedRouting:    Enabled,
 		}),
 		data: map[string]string{
@@ -80,6 +81,7 @@ func TestFeaturesConfiguration(t *testing.T) {
 			"kubernetes.podspec-securitycontext":   "Enabled",
 			"kubernetes.podspec-tolerations":       "Enabled",
 			"kubernetes.podspec-priorityclassname": "Enabled",
+			"kubernetes.podspec-schedulername":     "Enabled",
 			"tag-header-based-routing":             "Enabled",
 		},
 	}, {
@@ -379,6 +381,33 @@ func TestFeaturesConfiguration(t *testing.T) {
 		data: map[string]string{
 			"kubernetes.podspec-priorityclassname": "Disabled",
 		},
+	}, {
+		name:    "kubernetes.podspec-schedulername Allowed",
+		wantErr: false,
+		wantFeatures: defaultWith(&Features{
+			PodSpecSchedulerName: Allowed,
+		}),
+		data: map[string]string{
+			"kubernetes.podspec-schedulername": "Allowed",
+		},
+	}, {
+		name:    "kubernetes.podspec-schedulername Enabled",
+		wantErr: false,
+		wantFeatures: defaultWith(&Features{
+			PodSpecSchedulerName: Enabled,
+		}),
+		data: map[string]string{
+			"kubernetes.podspec-schedulername": "Enabled",
+		},
+	}, {
+		name:    "kubernetes.podspec-schedulername Disabled",
+		wantErr: false,
+		wantFeatures: defaultWith(&Features{
+			PodSpecSchedulerName: Disabled,
+		}),
+		data: map[string]string{
+			"kubernetes.podspec-schedulername": "Disabled",
+		},
 	}}
 
 	for _, tt := range configTests {
diff --git a/pkg/apis/serving/k8s_validation_test.go b/pkg/apis/serving/k8s_validation_test.go
index 7837469e1..836f2cbbe 100644
--- a/pkg/apis/serving/k8s_validation_test.go
+++ b/pkg/apis/serving/k8s_validation_test.go
@@ -112,6 +112,13 @@ func withPodSpecPriorityClassNameEnabled() configOption {
 	}
 }
 
+func withPodSpecSchedulerNameEnabled() configOption {
+	return func(cfg *config.Config) *config.Config {
+		cfg.Features.PodSpecSchedulerName = config.Enabled
+		return cfg
+	}
+}
+
 func TestPodSpecValidation(t *testing.T) {
 	tests := []struct {
 		name    string
@@ -696,6 +703,16 @@ func TestPodSpecFeatureValidation(t *testing.T) {
 			Paths:   []string{"priorityClassName"},
 		},
 		cfgOpts: []configOption{withPodSpecPriorityClassNameEnabled()},
+	}, {
+		name: "SchedulerName",
+		featureSpec: corev1.PodSpec{
+			SchedulerName: "foo",
+		},
+		err: &apis.FieldError{
+			Message: "must not set the field(s)",
+			Paths:   []string{"schedulerName"},
+		},
+		cfgOpts: []configOption{withPodSpecSchedulerNameEnabled()},
 	}}
 
 	featureTests := []struct {
diff --git a/pkg/reconciler/route/resources/service_test.go b/pkg/reconciler/route/resources/service_test.go
index 633ccddbd..6564f615f 100644
--- a/pkg/reconciler/route/resources/service_test.go
+++ b/pkg/reconciler/route/resources/service_test.go
@@ -430,6 +430,7 @@ func testConfig() *config.Config {
 			PodSpecTolerations:       apiConfig.Disabled,
 			PodSpecVolumesEmptyDir:   apiConfig.Disabled,
 			PodSpecPriorityClassName: apiConfig.Disabled,
+			PodSpecSchedulerName:     apiConfig.Disabled,
 			TagHeaderBasedRouting:    apiConfig.Disabled,
 		},
 	}
diff --git a/pkg/reconciler/route/table_test.go b/pkg/reconciler/route/table_test.go
index 44b8756da..e7a2d4f16 100644
--- a/pkg/reconciler/route/table_test.go
+++ b/pkg/reconciler/route/table_test.go
@@ -3280,6 +3280,7 @@ func reconcilerTestConfig() *config.Config {
 			PodSpecNodeSelector:      cfgmap.Disabled,
 			PodSpecTolerations:       cfgmap.Disabled,
 			PodSpecPriorityClassName: cfgmap.Disabled,
+			PodSpecSchedulerName:     cfgmap.Disabled,
 			TagHeaderBasedRouting:    cfgmap.Disabled,
 		},
 	}
diff --git a/test/conformance.go b/test/conformance.go
index 659158948..57782de5d 100644
--- a/test/conformance.go
+++ b/test/conformance.go
@@ -38,6 +38,8 @@ const (
 	Autoscale           = "autoscale"
 	EmptyDir            = "emptydir"
 	Failing             = "failing"
+	GRPCPing            = "grpc-ping"
+	HelloHTTP2          = "hellohttp2"
 	HelloVolume         = "hellovolume"
 	HelloWorld          = "helloworld"
 	HTTPProxy           = "httpproxy"
@@ -47,11 +49,11 @@ const (
 	Protocols           = "protocols"
 	Readiness           = "readiness"
 	Runtime             = "runtime"
+	ServingContainer    = "servingcontainer"
+	SidecarContainer    = "sidecarcontainer"
 	SingleThreadedImage = "singlethreaded"
 	Timeout             = "timeout"
 	WorkingDir          = "workingdir"
-	ServingContainer    = "servingcontainer"
-	SidecarContainer    = "sidecarcontainer"
 
 	// Constants for test image output.
 	PizzaPlanetText1 = "What a spaceport!"
diff --git a/test/conformance/api/v1/volumes_test.go b/test/conformance/api/v1/volumes_test.go
index f449f6514..14be006c5 100644
--- a/test/conformance/api/v1/volumes_test.go
+++ b/test/conformance/api/v1/volumes_test.go
@@ -120,7 +120,7 @@ func TestProjectedConfigMapVolume(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "hellovolume",
+		Image:   test.HelloVolume,
 	}
 
 	text := test.AppendRandomString("hello-volumes-")
@@ -258,7 +258,7 @@ func TestProjectedSecretVolume(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "hellovolume",
+		Image:   test.HelloVolume,
 	}
 
 	text := test.ObjectNameForTest(t)
@@ -328,7 +328,7 @@ func TestProjectedComplex(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "hellovolume",
+		Image:   test.HelloVolume,
 	}
 
 	text1 := test.ObjectNameForTest(t)
@@ -434,7 +434,7 @@ func TestProjectedServiceAccountToken(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "hellovolume",
+		Image:   test.HelloVolume,
 	}
 	test.EnsureTearDown(t, clients, &names)
 
diff --git a/test/e2e/activator_test.go b/test/e2e/activator_test.go
index 9683b9ad7..4869c2765 100644
--- a/test/e2e/activator_test.go
+++ b/test/e2e/activator_test.go
@@ -49,7 +49,7 @@ func TestActivatorOverload(t *testing.T) {
 	clients := Setup(t)
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "timeout",
+		Image:   test.Timeout,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/autotls/auto_tls_test.go b/test/e2e/autotls/auto_tls_test.go
index 7e7b883ba..277ca7d6d 100644
--- a/test/e2e/autotls/auto_tls_test.go
+++ b/test/e2e/autotls/auto_tls_test.go
@@ -62,7 +62,7 @@ func TestTLSDisabledWithAnnotation(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "runtime",
+		Image:   test.Runtime,
 	}
 	test.EnsureTearDown(t, clients, &names)
 
@@ -88,7 +88,7 @@ func testAutoTLS(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "runtime",
+		Image:   test.Runtime,
 	}
 	if len(env.TLSServiceName) != 0 {
 		names.Service = env.TLSServiceName
diff --git a/test/e2e/autotls/domain_mapping_test.go b/test/e2e/autotls/domain_mapping_test.go
index 629960a28..8542e62c4 100644
--- a/test/e2e/autotls/domain_mapping_test.go
+++ b/test/e2e/autotls/domain_mapping_test.go
@@ -61,7 +61,7 @@ func TestDomainMappingAutoTLS(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "runtime",
+		Image:   test.Runtime,
 	}
 
 	if len(env.TLSServiceName) != 0 {
diff --git a/test/e2e/destroypod_test.go b/test/e2e/destroypod_test.go
index ff9d1a1bc..76f98a812 100644
--- a/test/e2e/destroypod_test.go
+++ b/test/e2e/destroypod_test.go
@@ -56,7 +56,7 @@ func TestDestroyPodInflight(t *testing.T) {
 	names := test.ResourceNames{
 		Config: svcName,
 		Route:  svcName,
-		Image:  "timeout",
+		Image:  test.Timeout,
 	}
 	test.EnsureTearDown(t, clients, &names)
 
@@ -162,7 +162,7 @@ func TestDestroyPodTimely(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
@@ -247,7 +247,7 @@ func TestDestroyPodWithRequests(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "autoscale",
+		Image:   test.Autoscale,
 	}
 	test.EnsureTearDown(t, clients, &names)
 
diff --git a/test/e2e/egress_traffic_test.go b/test/e2e/egress_traffic_test.go
index 839285fb3..170fd9472 100644
--- a/test/e2e/egress_traffic_test.go
+++ b/test/e2e/egress_traffic_test.go
@@ -41,7 +41,7 @@ func TestEgressTraffic(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "httpproxy",
+		Image:   test.HTTPProxy,
 	}
 	test.EnsureTearDown(t, clients, &names)
 
diff --git a/test/e2e/gc/gc_test.go b/test/e2e/gc/gc_test.go
index ee3d596c1..d6dcf8e8f 100644
--- a/test/e2e/gc/gc_test.go
+++ b/test/e2e/gc/gc_test.go
@@ -44,7 +44,7 @@ func TestRevisionGC(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/grpc_test.go b/test/e2e/grpc_test.go
index 0f24479d6..cddc840f7 100644
--- a/test/e2e/grpc_test.go
+++ b/test/e2e/grpc_test.go
@@ -341,7 +341,7 @@ func testGRPC(t *testing.T, f grpcTest, fopts ...rtesting.ServiceOption) {
 
 	names := &test.ResourceNames{
 		Service: svcName,
-		Image:   "grpc-ping",
+		Image:   test.GRPCPing,
 	}
 
 	fopts = append(fopts, rtesting.WithNamedPort("h2c"))
diff --git a/test/e2e/helloworld_test.go b/test/e2e/helloworld_test.go
index b0451dee3..76ce66df7 100644
--- a/test/e2e/helloworld_test.go
+++ b/test/e2e/helloworld_test.go
@@ -43,7 +43,7 @@ func TestHelloWorld(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
@@ -85,7 +85,7 @@ func TestQueueSideCarResourceLimit(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/http2_test.go b/test/e2e/http2_test.go
index 132e66dc7..de0bf1ea7 100644
--- a/test/e2e/http2_test.go
+++ b/test/e2e/http2_test.go
@@ -41,7 +41,7 @@ func TestHelloHTTP2WithPortNameH2C(t *testing.T) {
 	// and behaves like helloworld if called with http/2.
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "hellohttp2",
+		Image:   test.HelloHTTP2,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
@@ -81,7 +81,7 @@ func TestHelloHTTP2WithEmptyPortName(t *testing.T) {
 	// and behaves like helloworld if called with http/2.
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "hellohttp2",
+		Image:   test.HelloHTTP2,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/initial_scale_test.go b/test/e2e/initial_scale_test.go
index 908068f86..3fca41bdd 100644
--- a/test/e2e/initial_scale_test.go
+++ b/test/e2e/initial_scale_test.go
@@ -38,7 +38,7 @@ func TestInitScalePositive(t *testing.T) {
 	clients := Setup(t)
 	names := test.ResourceNames{
 		Config: test.ObjectNameForTest(t),
-		Image:  "helloworld",
+		Image:  test.HelloWorld,
 	}
 	test.EnsureTearDown(t, clients, &names)
 
diff --git a/test/e2e/initscale/initial_scale_zero_test.go b/test/e2e/initscale/initial_scale_zero_test.go
index 6f1c595a8..512720d9d 100644
--- a/test/e2e/initscale/initial_scale_zero_test.go
+++ b/test/e2e/initscale/initial_scale_zero_test.go
@@ -34,7 +34,7 @@ func TestInitScaleZero(t *testing.T) {
 	clients := e2e.Setup(t)
 	names := test.ResourceNames{
 		Config: test.ObjectNameForTest(t),
-		Image:  "helloworld",
+		Image:  test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/logging_test.go b/test/e2e/logging_test.go
index 2cf72cd11..3558710f3 100644
--- a/test/e2e/logging_test.go
+++ b/test/e2e/logging_test.go
@@ -69,7 +69,7 @@ func TestRequestLogs(t *testing.T) {
 
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/minscale_readiness_test.go b/test/e2e/minscale_readiness_test.go
index 5b09240b8..51adb602a 100644
--- a/test/e2e/minscale_readiness_test.go
+++ b/test/e2e/minscale_readiness_test.go
@@ -49,7 +49,7 @@ func TestMinScale(t *testing.T) {
 		// Config and Route have different names to avoid false positives
 		Config: test.ObjectNameForTest(t),
 		Route:  test.ObjectNameForTest(t),
-		Image:  "helloworld",
+		Image:  test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/pod_schedule_error_test.go b/test/e2e/pod_schedule_error_test.go
index 6712b94f4..5186c7ded 100644
--- a/test/e2e/pod_schedule_error_test.go
+++ b/test/e2e/pod_schedule_error_test.go
@@ -45,7 +45,7 @@ func TestPodScheduleError(t *testing.T) {
 	)
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/rollback_byo_test.go b/test/e2e/rollback_byo_test.go
index dc7a97322..c93b8a0f0 100644
--- a/test/e2e/rollback_byo_test.go
+++ b/test/e2e/rollback_byo_test.go
@@ -38,7 +38,7 @@ func TestRollbackBYOName(t *testing.T) {
 	byoNameNew := serviceName + "-byo-foo-new"
 	names := test.ResourceNames{
 		Service: serviceName,
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/scale.go b/test/e2e/scale.go
index a334ba56e..1d3f595f8 100644
--- a/test/e2e/scale.go
+++ b/test/e2e/scale.go
@@ -95,7 +95,7 @@ func ScaleToWithin(t *testing.T, scale int, duration time.Duration, latencies La
 
 			names := test.ResourceNames{
 				Service: test.ObjectNameForTest(t),
-				Image:   "helloworld",
+				Image:   test.HelloWorld,
 			}
 
 			t.Cleanup(func() {
diff --git a/test/e2e/service_to_service_test.go b/test/e2e/service_to_service_test.go
index beb64f1b1..e1e161d7c 100644
--- a/test/e2e/service_to_service_test.go
+++ b/test/e2e/service_to_service_test.go
@@ -112,7 +112,7 @@ func testProxyToHelloworld(t *testing.T, clients *test.Clients, helloworldURL *u
 	t.Log("Creating a Service for the httpproxy test app.")
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "httpproxy",
+		Image:   test.HTTPProxy,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
@@ -177,7 +177,7 @@ func TestServiceToServiceCall(t *testing.T) {
 	t.Log("Creating a Service for the helloworld test app.")
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
@@ -225,7 +225,7 @@ func testSvcToSvcCallViaActivator(t *testing.T, clients *test.Clients, injectA b
 
 	testNames := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	withInternalVisibility := rtesting.WithServiceLabel(
@@ -287,7 +287,7 @@ func TestCallToPublicService(t *testing.T) {
 	t.Log("Creating a Service for the helloworld test app.")
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/test/e2e/subroutes_test.go b/test/e2e/subroutes_test.go
index ac7c62dd6..18f52f7db 100644
--- a/test/e2e/subroutes_test.go
+++ b/test/e2e/subroutes_test.go
@@ -95,7 +95,7 @@ func TestSubrouteVisibilityPublicToPrivate(t *testing.T) {
 	t.Log("Creating a Service for the helloworld test app.")
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
@@ -210,7 +210,7 @@ func TestSubrouteVisibilityPrivateToPublic(t *testing.T) {
 	t.Log("Creating a Service for the helloworld test app.")
 	names := test.ResourceNames{
 		Service: test.ObjectNameForTest(t),
-		Image:   "helloworld",
+		Image:   test.HelloWorld,
 	}
 
 	test.EnsureTearDown(t, clients, &names)
diff --git a/third_party/cert-manager-latest/net-certmanager.yaml b/third_party/cert-manager-latest/net-certmanager.yaml
index a9963541e..b592c87b7 100644
--- a/third_party/cert-manager-latest/net-certmanager.yaml
+++ b/third_party/cert-manager-latest/net-certmanager.yaml
@@ -18,7 +18,7 @@ metadata:
   # These are the permissions needed by the `cert-manager` `Certificate` implementation.
   name: knative-serving-certmanager
   labels:
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     serving.knative.dev/controller: "true"
     networking.knative.dev/certificate-provider: cert-manager
 rules:
@@ -49,7 +49,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.net-certmanager.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
 webhooks:
   - admissionReviewVersions:
@@ -88,7 +88,7 @@ metadata:
   name: net-certmanager-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
 
 ---
@@ -112,7 +112,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
 data:
   _example: |
@@ -159,7 +159,7 @@ metadata:
   name: net-certmanager-controller
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   selector:
@@ -171,14 +171,14 @@ spec:
         cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
       labels:
         app: net-certmanager-controller
-        serving.knative.dev/release: "v20210923-38e85872"
+        serving.knative.dev/release: "v20211004-3c78edd4"
     spec:
       serviceAccountName: controller
       containers:
         - name: controller
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:fa39217caaacafd23198851992c5e374d3b4e3a6835830c90a55a1542da9652e
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:e5677e2023a277d36ed50485ac01577a4e6125c33e81e3903f1b7b3e823ee395
           resources:
             requests:
               cpu: 30m
@@ -216,7 +216,7 @@ kind: Service
 metadata:
   labels:
     app: net-certmanager-controller
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
   name: net-certmanager-controller
   namespace: knative-serving
@@ -253,7 +253,7 @@ metadata:
   name: net-certmanager-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   selector:
@@ -267,14 +267,14 @@ spec:
       labels:
         app: net-certmanager-webhook
         role: net-certmanager-webhook
-        serving.knative.dev/release: "v20210923-38e85872"
+        serving.knative.dev/release: "v20211004-3c78edd4"
     spec:
       serviceAccountName: controller
       containers:
         - name: webhook
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:fc3e7467cb7f36e57bdb921b2c535cc2a620cf9eee04ab7dad83606f89900248
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:2660d7a701c88741ff094886080a7a465a6303377b4dcf116830ab5d44d20c06
           resources:
             requests:
               cpu: 20m
@@ -333,7 +333,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20210923-38e85872"
+    serving.knative.dev/release: "v20211004-3c78edd4"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   ports:
diff --git a/third_party/istio-latest/net-istio.yaml b/third_party/istio-latest/net-istio.yaml
index 6dd933c09..27a441a70 100644
--- a/third_party/istio-latest/net-istio.yaml
+++ b/third_party/istio-latest/net-istio.yaml
@@ -1,4 +1,4 @@
-# Generated when HEAD was 6e494b30d66b9bd566841f65c9e59f91e4790f11
+# Generated when HEAD was 60390217b31a8729e70070b4266936eff4e5ad23
 #
 # Copyright 2019 The Knative Authors
 #
@@ -20,7 +20,7 @@ metadata:
   # These are the permissions needed by the Istio Ingress implementation.
   name: knative-serving-istio
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     serving.knative.dev/controller: "true"
     networking.knative.dev/ingress-provider: istio
 rules:
@@ -50,7 +50,7 @@ metadata:
   name: knative-ingress-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -87,7 +87,7 @@ metadata:
   name: knative-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -106,7 +106,7 @@ metadata:
   name: knative-local-gateway
   namespace: istio-system
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
     experimental.istio.io/disable-gateway-port-translation: "true"
 spec:
@@ -139,7 +139,7 @@ metadata:
   name: config-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -200,7 +200,7 @@ metadata:
   name: "webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -216,7 +216,7 @@ metadata:
   name: "domainmapping-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -232,7 +232,7 @@ metadata:
   name: "net-istio-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -263,7 +263,7 @@ metadata:
   name: net-istio-controller
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -279,14 +279,14 @@ spec:
         sidecar.istio.io/inject: "false"
       labels:
         app: net-istio-controller
-        serving.knative.dev/release: "v20210923-6e494b30"
+        serving.knative.dev/release: "v20210929-60390217"
     spec:
       serviceAccountName: controller
       containers:
         - name: controller
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:f67450768015f75fc17f897cc50859980e10f15fb0a37daccf2c14111005d7cc
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:ed3e965f42abe47fc3eea86ace8bb7fa470988434e2f5560fdaf8d141f58e87a
           resources:
             requests:
               cpu: 30m
@@ -343,7 +343,7 @@ metadata:
   name: net-istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -357,14 +357,14 @@ spec:
       labels:
         app: net-istio-webhook
         role: net-istio-webhook
-        serving.knative.dev/release: "v20210923-6e494b30"
+        serving.knative.dev/release: "v20210929-60390217"
     spec:
       serviceAccountName: controller
       containers:
         - name: webhook
           # This is the Go import path for the binary that is containerized
           # and substituted here.
-          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:99fe90f43bb737754048a2faa1b1ecad7b71629cfb3448cdcf6aaddc5a203678
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:0751dca8c938339db1b840039ee6886d85b8b214525c7f55d04b8f2e2887aa7e
           resources:
             requests:
               cpu: 20m
@@ -417,7 +417,7 @@ metadata:
   name: net-istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 
 ---
@@ -442,7 +442,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-istio-webhook
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 spec:
   ports:
@@ -479,7 +479,7 @@ kind: MutatingWebhookConfiguration
 metadata:
   name: webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions:
@@ -516,7 +516,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20210923-6e494b30"
+    serving.knative.dev/release: "v20210929-60390217"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions: