Repository: knative/serving
Pull request #11976 (2021-09-10 11:18:58)

Teach activator about mesh compatibility modes
This allows us to tell activator explicitly whether mesh is enabled or
disabled, allowing us to skip the heuristic fallbacks when we know mesh
is disabled, and skip the pod probing when we know it is enabled. The
default automatic fallback behaviour remains the default, and this
PR does not actually make this field configurable by a user, yet.

Part of #11895.


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

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/11976#" title="Author self-approved">julz</a>*

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

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

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

- ~~[pkg/activator/OWNERS](https://github.com/knative/serving/blob/main/pkg/activator/OWNERS)~~ [julz]
- ~~[pkg/autoscaler/OWNERS](https://github.com/knative/serving/blob/main/pkg/autoscaler/OWNERS)~~ [julz]

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":[]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/serving/pull/11976?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) Report
> Merging [#11976](https://codecov.io/gh/knative/serving/pull/11976?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (5fea6e1) into [main](https://codecov.io/gh/knative/serving/commit/3d2eec93955890d48b6306b8a663aabf4d041559?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (3d2eec9) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

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

```diff
@@           Coverage Diff           @@
##             main   #11976   +/-   ##
=======================================
  Coverage   87.66%   87.67%           
=======================================
  Files         197      197           
  Lines        9529     9532    +3     
=======================================
+ Hits         8354     8357    +3     
- Misses        908      909    +1     
+ Partials      267      266    -1     
```


| [Impacted Files](https://codecov.io/gh/knative/serving/pull/11976?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) | Coverage Δ | |
|---|---|---|
| [pkg/autoscaler/metrics/stats\_scraper.go](https://codecov.io/gh/knative/serving/pull/11976/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-cGtnL2F1dG9zY2FsZXIvbWV0cmljcy9zdGF0c19zY3JhcGVyLmdv) | `92.21% <ø> (ø)` | |
| [pkg/activator/net/revision\_backends.go](https://codecov.io/gh/knative/serving/pull/11976/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-cGtnL2FjdGl2YXRvci9uZXQvcmV2aXNpb25fYmFja2VuZHMuZ28=) | `91.62% <100.00%> (-0.79%)` | :arrow_down: |
| [pkg/reconciler/configuration/configuration.go](https://codecov.io/gh/knative/serving/pull/11976/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-cGtnL3JlY29uY2lsZXIvY29uZmlndXJhdGlvbi9jb25maWd1cmF0aW9uLmdv) | `86.15% <0.00%> (+1.53%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/serving/pull/11976?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).
> **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=knative)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/serving/pull/11976?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Last update [3d2eec9...5fea6e1](https://codecov.io/gh/knative/serving/pull/11976?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). 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=knative).

julz: /assign @markusthoemmes @psschwei 

Patch:
diff --git a/cmd/queue/execprobe.go b/cmd/queue/execprobe.go
deleted file mode 100644
index 116520264..000000000
--- a/cmd/queue/execprobe.go
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-Copyright 2020 The Knative Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"io"
-	"net/http"
-	"os"
-	"time"
-
-	"k8s.io/apimachinery/pkg/util/wait"
-	network "knative.dev/networking/pkg"
-	"knative.dev/serving/pkg/queue"
-	"knative.dev/serving/pkg/queue/health"
-)
-
-const (
-	healthURLPrefix = "http://127.0.0.1:"
-
-	// The 25 millisecond retry interval is an unscientific compromise between wanting to get
-	// started as early as possible while still wanting to give the container some breathing
-	// room to get up and running.
-	aggressivePollInterval = 25 * time.Millisecond
-
-	queuePortEnvVar = "QUEUE_SERVING_PORT"
-)
-
-// As well as running as a long-running proxy server, the Queue Proxy can be
-// run as an exec probe if the `--probe-timeout` flag is passed.
-//
-// In this mode, the exec probe (repeatedly) sends an HTTP request to the Queue
-// Proxy server with a Probe header. The handler for this probe request
-// (knativeProbeHandler) then performs the actual health check against the user
-// container. The exec probe binary exits 0 (success) if it eventually gets a
-// 200 status code back from the knativeProbeHandler, or 1 (fail) if it never
-// does.
-//
-// The reason we use an exec probe to hit an HTTP endpoint on the Queue
-// Proxy to then run the actual probe against the user container rather than
-// using an HTTP probe directly is because an exec probe can be launched
-// immediately after the container starts, whereas an HTTP probe would
-// initially race with the server starting up and fail. The minimum retry
-// period after this failure in upstream kubernetes is a second. The exec
-// probe, on the other hand, automatically polls on an aggressivePollInterval
-// until the HTTP endpoint responds with success. This allows us to get an
-// initial readiness result much faster than the effective upstream Kubernetes
-// minimum of 1 second.
-func standaloneProbeMain(timeout time.Duration, transport http.RoundTripper) (exitCode int) {
-	if err := probeQueueHealthPath(timeout, os.Getenv(queuePortEnvVar), transport); err != nil {
-		fmt.Fprintln(os.Stderr, err)
-		return 1
-	}
-
-	return 0
-}
-
-func probeQueueHealthPath(timeout time.Duration, queueServingPort string, transport http.RoundTripper) error {
-	url := healthURLPrefix + queueServingPort
-	req, err := http.NewRequest(http.MethodGet, url, nil)
-	if err != nil {
-		return fmt.Errorf("probe failed: error creating request: %w", err)
-	}
-
-	// Add the header to indicate this is a probe request.
-	req.Header.Add(network.ProbeHeaderName, queue.Name)
-	req.Header.Add(network.UserAgentKey, network.QueueProxyUserAgent)
-
-	httpClient := &http.Client{
-		Timeout:   timeout,
-		Transport: transport,
-	}
-
-	ctx, cancel := context.WithTimeout(context.Background(), timeout)
-	defer cancel()
-
-	var (
-		lastErr error
-		res     *http.Response
-	)
-	// Using PollImmediateUntil instead of PollImmediate because if timeout is reached while waiting for first
-	// invocation of conditionFunc, it exits immediately without trying for a second time.
-	timeoutErr := wait.PollImmediateUntil(aggressivePollInterval, func() (bool, error) {
-		res, lastErr = httpClient.Do(req)
-		if lastErr != nil {
-			// Return nil error for retrying.
-			return false, nil
-		}
-
-		defer func() {
-			// Ensure body is read and closed to ensure connection can be re-used via keep-alive.
-			// No point handling errors here, connection just won't be reused.
-			io.Copy(io.Discard, res.Body)
-			res.Body.Close()
-		}()
-
-		// Fail readiness immediately rather than retrying if we get a header indicating we're shutting down.
-		if health.IsHTTPProbeShuttingDown(res) {
-			lastErr = errors.New("failing probe deliberately for shutdown")
-			return false, lastErr
-		}
-		return health.IsHTTPProbeReady(res), nil
-	}, ctx.Done())
-
-	if lastErr != nil {
-		return fmt.Errorf("failed to probe: %w", lastErr)
-	}
-
-	// An http.StatusOK was never returned during probing.
-	if timeoutErr != nil {
-		return errors.New("probe returned not ready")
-	}
-
-	return nil
-}
diff --git a/cmd/queue/main.go b/cmd/queue/main.go
index d012a0c32..afffdbea9 100644
--- a/cmd/queue/main.go
+++ b/cmd/queue/main.go
@@ -117,14 +117,11 @@ func main() {
 
 	// If this is set, we run as a standalone binary to probe the queue-proxy.
 	if *startupProbeTimeout >= 0 {
-		// Use a unix socket rather than TCP to avoid going via entire TCP stack
-		// when we're actually in the same container.
-		transport := http.DefaultTransport.(*http.Transport).Clone()
-		transport.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) {
-			return net.Dial("unix", unixSocketPath)
-		}
-
-		os.Exit(standaloneProbeMain(*startupProbeTimeout, transport))
+		// This is kept as a compatibility layer to avoid an upgrade that updates the
+		// queue-proxy image before rolling out a new controller to fail.
+		//
+		// TODO: Delete me after 0.26 cuts
+		os.Exit(0)
 	}
 
 	// Otherwise, we run as the queue-proxy service.
diff --git a/go.mod b/go.mod
index bffa8b611..dfe9d3e11 100644
--- a/go.mod
+++ b/go.mod
@@ -45,9 +45,9 @@ require (
 	k8s.io/code-generator v0.21.4
 	k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7
 	k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 // indirect
-	knative.dev/caching v0.0.0-20210909065659-e5d224326175
+	knative.dev/caching v0.0.0-20210910063632-a51cf6760e00
 	knative.dev/hack v0.0.0-20210806075220-815cd312d65c
-	knative.dev/networking v0.0.0-20210909065659-060e46eeddbd
-	knative.dev/pkg v0.0.0-20210909102158-d569db39a812
+	knative.dev/networking v0.0.0-20210910120730-eb37d69eb87f
+	knative.dev/pkg v0.0.0-20210909165259-d4505c660535
 	sigs.k8s.io/yaml v1.2.0
 )
diff --git a/go.sum b/go.sum
index c4f5bd5e3..dd9fa56c8 100644
--- a/go.sum
+++ b/go.sum
@@ -1526,15 +1526,14 @@ k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAl
 k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ=
 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-knative.dev/caching v0.0.0-20210909065659-e5d224326175 h1:fJVzj33VnyLaQ41hKglWJbWX3R92UnnuMzK0FkP+ZnQ=
-knative.dev/caching v0.0.0-20210909065659-e5d224326175/go.mod h1:XWnA7pdlpf5b8h2PEQN0PhL/h+i9Iv4w10BLcS5Tz8A=
+knative.dev/caching v0.0.0-20210910063632-a51cf6760e00 h1:BObI5QX32nefcKWZlJATp0sWyj4LjDq596AlwCVpC7k=
+knative.dev/caching v0.0.0-20210910063632-a51cf6760e00/go.mod h1:PMt1PGfOsjGpIj0m6QWIfutn+5mY4WPGf3q4MP6oFf0=
 knative.dev/hack v0.0.0-20210806075220-815cd312d65c h1:nOXoDWAAItwr4o0dp3nHr6skgpVD4IvME/UX84YNl5k=
 knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/networking v0.0.0-20210909065659-060e46eeddbd h1:wQqcXHW9hAI8I9zKIzIjX3Vu1qCKcs7hT/AgcGwe6OA=
-knative.dev/networking v0.0.0-20210909065659-060e46eeddbd/go.mod h1:viMddr/gluqUQfSAvhJs0OxKBzh0Df5bELo8A/HS5qc=
-knative.dev/pkg v0.0.0-20210908202858-9a4b6128207c/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
-knative.dev/pkg v0.0.0-20210909102158-d569db39a812 h1:8EQzOnAxqP1inXNlfeFrjcRUbuwZ7HldgJLqNQnuOxY=
-knative.dev/pkg v0.0.0-20210909102158-d569db39a812/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
+knative.dev/networking v0.0.0-20210910120730-eb37d69eb87f h1:FHPmpIrUnJjoI2xBIpxTAvCoh9Y1nNHAOWRSJRJECww=
+knative.dev/networking v0.0.0-20210910120730-eb37d69eb87f/go.mod h1:Bq/n7aJlzPiieLpB/ndIgZXUJeGf50LXN7AQ/UaL6KA=
+knative.dev/pkg v0.0.0-20210909165259-d4505c660535 h1:1bbKs8NGGodV0LjOyn6s5lo+oAJ/9KtTURUZtpRxr60=
+knative.dev/pkg v0.0.0-20210909165259-d4505c660535/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
 pgregory.net/rapid v0.3.3 h1:jCjBsY4ln4Atz78QoBWxUEvAHaFyNDQg9+WU62aCn1U=
 pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/pkg/activator/net/revision_backends.go b/pkg/activator/net/revision_backends.go
index 5f0fca395..d39fdcce9 100644
--- a/pkg/activator/net/revision_backends.go
+++ b/pkg/activator/net/revision_backends.go
@@ -89,6 +89,24 @@ const (
 	defaultProbeFrequency time.Duration = 200 * time.Millisecond
 )
 
+// meshMode determines whether we should proxy directly to pods (most efficient), go via the
+// cluster IP (needed when mesh is enabled), or attempt to automatically detect.
+type meshMode int
+
+const (
+	// meshModeAuto first attempts direct pod IP proxying, and then falls back to
+	// cluster IP if this does not work.
+	meshModeAuto meshMode = iota
+	// meshModeEnabled causes us to always use ClusterIP (which means we do not
+	// need to probe, but deactivates activator load balancing)
+	meshModeEnabled
+	// meshModeDisabled causes us to always proxy directly to pods, which will
+	// not work when mesh is enabled, but allows us to intelligently load balance
+	// to pods with capacity, and enables the activator probe optimisation to
+	// start routing to pods before readiness has propagated.
+	meshModeDisabled
+)
+
 // revisionWatcher watches the podIPs and ClusterIP of the service for a revision. It implements the logic
 // to supply revisionDestsUpdate events on updateCh
 type revisionWatcher struct {
@@ -116,12 +134,16 @@ type revisionWatcher struct {
 	// usePassthroughLb makes the probing use the passthrough lb headers to enable
 	// pod addressability even in meshes.
 	usePassthroughLb bool
+
+	// meshMode configures whether we always directly probe pods,
+	// always use cluster IP, or attempt to autodetect
+	meshMode meshMode
 }
 
 func newRevisionWatcher(ctx context.Context, rev types.NamespacedName, protocol pkgnet.ProtocolType,
 	updateCh chan<- revisionDestsUpdate, destsCh chan dests,
 	transport http.RoundTripper, serviceLister corev1listers.ServiceLister,
-	usePassthroughLb bool,
+	usePassthroughLb bool, meshMode meshMode,
 	logger *zap.SugaredLogger) *revisionWatcher {
 	ctx, cancel := context.WithCancel(ctx)
 	return &revisionWatcher{
@@ -136,6 +158,7 @@ func newRevisionWatcher(ctx context.Context, rev types.NamespacedName, protocol
 		serviceLister:    serviceLister,
 		podsAddressable:  true, // By default we presume we can talk to pods directly.
 		usePassthroughLb: usePassthroughLb,
+		meshMode:         meshMode,
 		logger:           logger.With(zap.String(logkey.Key, rev.String())),
 	}
 }
@@ -287,9 +310,9 @@ func (rw *revisionWatcher) checkDests(curDests, prevDests dests) {
 		return
 	}
 
-	// If we have discovered that this revision cannot be probed directly
-	// do not spend time trying.
-	if rw.podsAddressable {
+	// If we have discovered (or have been told via meshMode) that this revision
+	// cannot be probed directly do not spend time trying.
+	if rw.podsAddressable && rw.meshMode != meshModeEnabled {
 		// reprobe set contains the targets that moved from ready to non-ready set.
 		// so they have to be re-probed.
 		reprobe := curDests.becameNonReady(prevDests)
@@ -337,6 +360,12 @@ func (rw *revisionWatcher) checkDests(curDests, prevDests dests) {
 		return
 	}
 
+	if rw.meshMode == meshModeDisabled {
+		// If mesh is disabled we always want to use direct pod addressing, and
+		// will not fall back to clusterIP.
+		return
+	}
+
 	// If we failed to probe even a single pod, check the clusterIP.
 	// NB: We can't cache the IP address, since user might go rogue
 	// and delete the K8s service. We'll fix it, but the cluster IP will be different.
@@ -499,7 +528,7 @@ func (rbm *revisionBackendsManager) getOrCreateRevisionWatcher(rev types.Namespa
 		}
 
 		destsCh := make(chan dests)
-		rw := newRevisionWatcher(rbm.ctx, rev, proto, rbm.updateCh, destsCh, rbm.transport, rbm.serviceLister, rbm.usePassthroughLb, rbm.logger)
+		rw := newRevisionWatcher(rbm.ctx, rev, proto, rbm.updateCh, destsCh, rbm.transport, rbm.serviceLister, rbm.usePassthroughLb, meshModeAuto, rbm.logger)
 		rbm.revisionWatchers[rev] = rw
 		go rw.run(rbm.probeFrequency)
 		return rw, nil
diff --git a/pkg/autoscaler/metrics/stats_scraper.go b/pkg/autoscaler/metrics/stats_scraper.go
index 4a0a95c6b..d108b0df9 100644
--- a/pkg/autoscaler/metrics/stats_scraper.go
+++ b/pkg/autoscaler/metrics/stats_scraper.go
@@ -137,7 +137,7 @@ var client = &http.Client{
 	Transport: keepAliveTransport,
 }
 
-// meshMode determines whethe we should attempt to sample for stats via the K8s
+// meshMode determines whether we should attempt to sample for stats via the K8s
 // service, or whether we should attempt to directly gather stats from pods
 // (which is more efficient, but not possible when mesh is enabled).
 type meshMode int
diff --git a/pkg/client/injection/reconciler/autoscaling/v1alpha1/metric/reconciler.go b/pkg/client/injection/reconciler/autoscaling/v1alpha1/metric/reconciler.go
index f7ed0efec..e2f113287 100644
--- a/pkg/client/injection/reconciler/autoscaling/v1alpha1/metric/reconciler.go
+++ b/pkg/client/injection/reconciler/autoscaling/v1alpha1/metric/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/autoscaling/v1alpha1/podautoscaler/reconciler.go b/pkg/client/injection/reconciler/autoscaling/v1alpha1/podautoscaler/reconciler.go
index f0fc1ff3d..be15f07ba 100644
--- a/pkg/client/injection/reconciler/autoscaling/v1alpha1/podautoscaler/reconciler.go
+++ b/pkg/client/injection/reconciler/autoscaling/v1alpha1/podautoscaler/reconciler.go
@@ -262,6 +262,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/serving/v1/configuration/reconciler.go b/pkg/client/injection/reconciler/serving/v1/configuration/reconciler.go
index db9565d25..ed47e6eaf 100644
--- a/pkg/client/injection/reconciler/serving/v1/configuration/reconciler.go
+++ b/pkg/client/injection/reconciler/serving/v1/configuration/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/serving/v1/revision/reconciler.go b/pkg/client/injection/reconciler/serving/v1/revision/reconciler.go
index e432ba3de..9b7c9e955 100644
--- a/pkg/client/injection/reconciler/serving/v1/revision/reconciler.go
+++ b/pkg/client/injection/reconciler/serving/v1/revision/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/serving/v1/route/reconciler.go b/pkg/client/injection/reconciler/serving/v1/route/reconciler.go
index 3d510d567..bf3bac9f3 100644
--- a/pkg/client/injection/reconciler/serving/v1/route/reconciler.go
+++ b/pkg/client/injection/reconciler/serving/v1/route/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/serving/v1/service/reconciler.go b/pkg/client/injection/reconciler/serving/v1/service/reconciler.go
index 84fc51d4e..a14342e12 100644
--- a/pkg/client/injection/reconciler/serving/v1/service/reconciler.go
+++ b/pkg/client/injection/reconciler/serving/v1/service/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/serving/v1alpha1/domainmapping/reconciler.go b/pkg/client/injection/reconciler/serving/v1alpha1/domainmapping/reconciler.go
index dc6ae8167..6fca16803 100644
--- a/pkg/client/injection/reconciler/serving/v1alpha1/domainmapping/reconciler.go
+++ b/pkg/client/injection/reconciler/serving/v1alpha1/domainmapping/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/client/injection/reconciler/serving/v1beta1/domainmapping/reconciler.go b/pkg/client/injection/reconciler/serving/v1beta1/domainmapping/reconciler.go
index 507976edf..cb256e549 100644
--- a/pkg/client/injection/reconciler/serving/v1beta1/domainmapping/reconciler.go
+++ b/pkg/client/injection/reconciler/serving/v1beta1/domainmapping/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/pkg/queue/concurrency_state.go b/pkg/queue/concurrency_state.go
index 9220c2924..53a47fc64 100644
--- a/pkg/queue/concurrency_state.go
+++ b/pkg/queue/concurrency_state.go
@@ -18,7 +18,9 @@ package queue
 
 import (
 	"net/http"
+	"sync"
 
+	"go.uber.org/atomic"
 	"go.uber.org/zap"
 )
 
@@ -38,50 +40,48 @@ func ConcurrencyStateHandler(logger *zap.SugaredLogger, h http.Handler, pause, r
 		resume = func() {}
 	}
 
-	type req struct {
-		w http.ResponseWriter
-		r *http.Request
+	var (
+		inFlight = atomic.NewInt64(0)
+		paused   = true
+		mux      sync.RWMutex
+	)
 
-		done chan struct{}
-	}
-
-	reqCh := make(chan req)
-	doneCh := make(chan struct{})
-	go func() {
-		inFlight := 0
-
-		// This loop is entirely synchronous, so there's no cleverness needed in
-		// ensuring open and close dont run at the same time etc. Only the
-		// delegated ServeHTTP is done in a goroutine.
-		for {
-			select {
-			case <-doneCh:
-				inFlight--
-				if inFlight == 0 {
-					logger.Info("Requests dropped to zero ...")
+	return func(w http.ResponseWriter, r *http.Request) {
+		defer func() {
+			if inFlight.Dec() == 0 {
+				mux.Lock()
+				defer mux.Unlock()
+				// We need to doublecheck this since another request can have reached the
+				// handler meanwhile. We don't want to do anything in that case.
+				if !paused && inFlight.Load() == 0 {
 					pause()
+					paused = true
 				}
+			}
+		}()
 
-			case r := <-reqCh:
-				inFlight++
-				if inFlight == 1 {
-					logger.Info("Requests increased from zero ...")
-					resume()
-				}
+		inFlight.Inc()
 
-				go func(r req) {
-					h.ServeHTTP(r.w, r.r)
-					close(r.done) // Return from ServeHTTP
-					doneCh <- struct{}{}
-				}(r)
-			}
+		mux.RLock()
+		if !paused {
+			// General stable-state case.
+			defer mux.RUnlock()
+			h.ServeHTTP(w, r)
+			return
+		}
+		mux.RUnlock()
+		mux.Lock()
+		if !paused { // doubly-checked locking
+			// Another request raced us and resumed already.
+			defer mux.Unlock()
+			h.ServeHTTP(w, r)
+			return
 		}
-	}()
 
-	return func(w http.ResponseWriter, r *http.Request) {
-		done := make(chan struct{})
-		reqCh <- req{w, r, done}
-		// Block till we've processed the request
-		<-done
+		resume()
+		paused = false
+		mux.Unlock()
+
+		h.ServeHTTP(w, r)
 	}
 }
diff --git a/pkg/queue/health/probe.go b/pkg/queue/health/probe.go
index c51a7a626..452ad123a 100644
--- a/pkg/queue/health/probe.go
+++ b/pkg/queue/health/probe.go
@@ -129,9 +129,9 @@ func http2UpgradeProbe(config HTTPProbeConfigOptions) (int, error) {
 
 	maxProto := 0
 
-	if IsHTTPProbeUpgradingToH2C(res) {
+	if isHTTPProbeUpgradingToH2C(res) {
 		maxProto = 2
-	} else if IsHTTPProbeReady(res) {
+	} else if isHTTPProbeReady(res) {
 		maxProto = 1
 	} else {
 		return maxProto, fmt.Errorf("HTTP probe did not respond Ready, got status code: %d", res.StatusCode)
@@ -185,26 +185,20 @@ func HTTPProbe(config HTTPProbeConfigOptions) error {
 		res.Body.Close()
 	}()
 
-	if !IsHTTPProbeReady(res) {
+	if !isHTTPProbeReady(res) {
 		return fmt.Errorf("HTTP probe did not respond Ready, got status code: %d", res.StatusCode)
 	}
 
 	return nil
 }
 
-// IsHTTPProbeUpgradingToH2C checks whether the server indicates it's switching to h2c protocol.
-func IsHTTPProbeUpgradingToH2C(res *http.Response) bool {
+// isHTTPProbeUpgradingToH2C checks whether the server indicates it's switching to h2c protocol.
+func isHTTPProbeUpgradingToH2C(res *http.Response) bool {
 	return res.StatusCode == http.StatusSwitchingProtocols && res.Header.Get("Upgrade") == "h2c"
 }
 
-// IsHTTPProbeReady checks whether we received a successful Response
-func IsHTTPProbeReady(res *http.Response) bool {
+// isHTTPProbeReady checks whether we received a successful Response
+func isHTTPProbeReady(res *http.Response) bool {
 	// response status code between 200-399 indicates success
 	return res.StatusCode >= 200 && res.StatusCode < 400
 }
-
-// IsHTTPProbeShuttingDown checks whether the Response indicates the prober is shutting down.
-func IsHTTPProbeShuttingDown(res *http.Response) bool {
-	// status 410 (Gone) indicates the probe returned a shutdown scenario.
-	return res.StatusCode == http.StatusGone
-}
diff --git a/pkg/reconciler/revision/resources/queue.go b/pkg/reconciler/revision/resources/queue.go
index e3331de66..5d4b78868 100644
--- a/pkg/reconciler/revision/resources/queue.go
+++ b/pkg/reconciler/revision/resources/queue.go
@@ -20,7 +20,6 @@ import (
 	"fmt"
 	"math"
 	"strconv"
-	"time"
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
@@ -172,37 +171,6 @@ func fractionFromPercentage(m map[string]string, k string) (float64, bool) {
 	return value / 100, err == nil
 }
 
-func makeStartupExecProbe(in *corev1.Probe, progressDeadline time.Duration) *corev1.Probe {
-	if in != nil && in.PeriodSeconds > 0 {
-		// If the user opted-out of the aggressive probing optimisation we don't
-		// need to run a startup probe at all.
-		return nil
-	}
-
-	out := &corev1.Probe{
-		Handler: corev1.Handler{
-			Exec: &corev1.ExecAction{
-				// The exec probe is run as a startup probe so the container will be killed
-				// and restarted if it fails. We use the ProgressDeadline as the timeout
-				// to match the time we'll wait before killing the revision if it
-				// fails to go ready on initial deployment.
-				Command: []string{"/ko-app/queue", "-probe-timeout", progressDeadline.String()},
-			},
-		},
-		// The exec probe itself retries aggressively so there's no point retrying via Kubernetes too.
-		TimeoutSeconds:   int32(progressDeadline.Seconds()),
-		FailureThreshold: 1,
-		SuccessThreshold: 1,
-		PeriodSeconds:    1,
-	}
-
-	if in != nil {
-		out.InitialDelaySeconds = in.InitialDelaySeconds
-	}
-
-	return out
-}
-
 // makeQueueContainer creates the container spec for the queue sidecar.
 func makeQueueContainer(rev *v1.Revision, cfg *config.Config) (*corev1.Container, error) {
 	configName := ""
@@ -245,7 +213,6 @@ func makeQueueContainer(rev *v1.Revision, cfg *config.Config) (*corev1.Container
 		// variable for this probe to use.
 		userProbe := container.ReadinessProbe.DeepCopy()
 		applyReadinessProbeDefaultsForExec(userProbe, userPort)
-		execProbe = makeStartupExecProbe(userProbe, cfg.Deployment.ProgressDeadline)
 
 		var err error
 		userProbeJSON, err = readiness.EncodeProbe(userProbe)
diff --git a/pkg/reconciler/route/route.go b/pkg/reconciler/route/route.go
index edf5675de..f522e5b49 100644
--- a/pkg/reconciler/route/route.go
+++ b/pkg/reconciler/route/route.go
@@ -24,6 +24,8 @@ import (
 	"strings"
 	"time"
 
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	kubelabels "k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/apimachinery/pkg/util/clock"
@@ -38,9 +40,11 @@ import (
 	networkinglisters "knative.dev/networking/pkg/client/listers/networking/v1alpha1"
 	"knative.dev/pkg/apis"
 	duckv1 "knative.dev/pkg/apis/duck/v1"
+	"knative.dev/pkg/controller"
 	"knative.dev/pkg/logging"
 	pkgreconciler "knative.dev/pkg/reconciler"
 	"knative.dev/pkg/tracker"
+	"knative.dev/serving/pkg/apis/serving"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
 	clientset "knative.dev/serving/pkg/client/clientset/versioned"
 	routereconciler "knative.dev/serving/pkg/client/injection/reconciler/serving/v1/route"
@@ -259,9 +263,55 @@ func (c *Reconciler) tls(ctx context.Context, host string, r *v1.Route, traffic
 	sort.Slice(acmeChallenges, func(i, j int) bool {
 		return acmeChallenges[i].URL.String() < acmeChallenges[j].URL.String()
 	})
+
+	orphanCerts, err := c.getOrphanRouteCerts(r, domainToTagMap)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	recorder := controller.GetEventRecorder(ctx)
+	for _, cert := range orphanCerts {
+		err = c.GetNetworkingClient().NetworkingV1alpha1().Certificates(cert.Namespace).Delete(ctx, cert.Name, metav1.DeleteOptions{})
+		if err != nil {
+			recorder.Eventf(cert, corev1.EventTypeNormal, "DeleteFailed",
+				"Failed to delete orphaned Knative Certificate %s/%s: %v", cert.Namespace, cert.Name, err)
+		} else {
+			recorder.Eventf(cert, corev1.EventTypeNormal, "Deleted",
+				"Deleted orphaned Knative Certificate %s/%s", cert.Namespace, cert.Name)
+		}
+	}
+
 	return tls, acmeChallenges, nil
 }
 
+// Returns a slice of certificates that used to belong route's old tags and are currently not in use.
+func (c *Reconciler) getOrphanRouteCerts(r *v1.Route, domainToTagMap map[string]string) ([]*netv1alpha1.Certificate, error) {
+	labelSelector := kubelabels.SelectorFromSet(kubelabels.Set{
+		serving.RouteLabelKey: r.Name,
+	})
+
+	certs, err := c.certificateLister.Certificates(r.Namespace).List(labelSelector)
+	if err != nil {
+		return nil, err
+	}
+
+	var unusedCerts []*netv1alpha1.Certificate
+	for _, cert := range certs {
+		var shouldKeepCert bool
+		for _, dn := range cert.Spec.DNSNames {
+			if _, used := domainToTagMap[dn]; used {
+				shouldKeepCert = true
+			}
+		}
+
+		if !shouldKeepCert {
+			unusedCerts = append(unusedCerts, cert)
+		}
+	}
+
+	return unusedCerts, nil
+}
+
 // configureTraffic attempts to configure traffic based on the RouteSpec.  If there are missing
 // targets (e.g. Configurations without a Ready Revision, or Revision that isn't Ready or Inactive),
 // no traffic will be configured.
diff --git a/vendor/knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go b/vendor/knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go
index 34e46dde5..a90410f7b 100644
--- a/vendor/knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go
+++ b/vendor/knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serverlessservice/reconciler.go
@@ -251,6 +251,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/vendor/knative.dev/pkg/apis/duck/ABOUT.md b/vendor/knative.dev/pkg/apis/duck/ABOUT.md
index b223412a0..989769220 100644
--- a/vendor/knative.dev/pkg/apis/duck/ABOUT.md
+++ b/vendor/knative.dev/pkg/apis/duck/ABOUT.md
@@ -302,7 +302,11 @@ is used with duck types:
                 ...
         }
         logger := c.Logger.Named("Revisions")
-        impl := controller.NewImpl(c, logger, "Revisions")
+        impl := controller.NewContext(
+          ctx,
+          c,
+          controller.ControllerOptions{WorkQueueName: "Revisions", Logger: logger},
+        )
 
         // Calls to Track create a 30 minute lease before they must be renewed.
         // Coordinate this value with controller resync periods.
diff --git a/vendor/knative.dev/pkg/apis/duck/v1/source_types.go b/vendor/knative.dev/pkg/apis/duck/v1/source_types.go
index 2f1afe246..00e699156 100644
--- a/vendor/knative.dev/pkg/apis/duck/v1/source_types.go
+++ b/vendor/knative.dev/pkg/apis/duck/v1/source_types.go
@@ -17,6 +17,7 @@ limitations under the License.
 package v1
 
 import (
+	"context"
 	"time"
 
 	corev1 "k8s.io/api/core/v1"
@@ -170,3 +171,45 @@ type SourceList struct {
 
 	Items []Source `json:"items"`
 }
+
+func (s *Source) Validate(ctx context.Context) *apis.FieldError {
+	if s == nil {
+		return nil
+	}
+	return s.Spec.Validate(ctx).ViaField("spec")
+}
+
+func (s *SourceSpec) Validate(ctx context.Context) *apis.FieldError {
+	return s.CloudEventOverrides.Validate(ctx).ViaField("ceOverrides")
+}
+
+func (ceOverrides *CloudEventOverrides) Validate(ctx context.Context) *apis.FieldError {
+	for key := range ceOverrides.Extensions {
+		if err := validateExtensionName(key); err != nil {
+			return err.ViaField("extensions")
+		}
+	}
+	return nil
+}
+
+func validateExtensionName(key string) *apis.FieldError {
+	if key == "" {
+		return apis.ErrInvalidKeyName(
+			key,
+			"",
+			"keys MUST NOT be empty",
+		)
+	}
+
+	for _, c := range key {
+		if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
+			return apis.ErrInvalidKeyName(
+				key,
+				"",
+				"keys are expected to be alphanumeric",
+			)
+		}
+	}
+
+	return nil
+}
diff --git a/vendor/knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace/reconciler.go b/vendor/knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace/reconciler.go
index 00747a699..d89572dc0 100644
--- a/vendor/knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace/reconciler.go
+++ b/vendor/knative.dev/pkg/client/injection/kube/reconciler/core/v1/namespace/reconciler.go
@@ -242,6 +242,10 @@ func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
 			return fmt.Errorf("failed to clear finalizers: %w", err)
 		}
 
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	// Synchronize the status.
diff --git a/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler.go b/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler.go
index 96e1edc25..e787096b3 100644
--- a/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler.go
+++ b/vendor/knative.dev/pkg/codegen/cmd/injection-gen/generators/reconciler_reconciler.go
@@ -465,6 +465,10 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro
 			return {{.fmtErrorf|raw}}("failed to clear finalizers: %w", err)
 		}
 
+	case {{.doObserveKind|raw}}:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
 	}
 
 	{{if .hasStatus}}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 30e03348f..34f634cf1 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1017,7 +1017,7 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20210909065659-e5d224326175
+# knative.dev/caching v0.0.0-20210910063632-a51cf6760e00
 ## explicit
 knative.dev/caching/config
 knative.dev/caching/pkg/apis/caching
@@ -1042,7 +1042,7 @@ knative.dev/caching/pkg/client/listers/caching/v1alpha1
 ## explicit
 knative.dev/hack
 knative.dev/hack/shell
-# knative.dev/networking v0.0.0-20210909065659-060e46eeddbd
+# knative.dev/networking v0.0.0-20210910120730-eb37d69eb87f
 ## explicit
 knative.dev/networking/config
 knative.dev/networking/pkg
@@ -1072,7 +1072,7 @@ knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serve
 knative.dev/networking/pkg/client/listers/networking/v1alpha1
 knative.dev/networking/pkg/ingress
 knative.dev/networking/pkg/prober
-# knative.dev/pkg v0.0.0-20210909102158-d569db39a812
+# knative.dev/pkg v0.0.0-20210909165259-d4505c660535
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate


Test patch:
diff --git a/.github/workflows/kind-e2e.yaml b/.github/workflows/kind-e2e.yaml
index d10aa0977..92c7be87c 100644
--- a/.github/workflows/kind-e2e.yaml
+++ b/.github/workflows/kind-e2e.yaml
@@ -21,6 +21,7 @@ jobs:
         - v1.19.11
         - v1.20.7
         - v1.21.1
+        - v1.22.0
 
         test-suite:
         - ./test/conformance/runtime
@@ -47,6 +48,11 @@ jobs:
           kind-image-sha: sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
           kingress: kourier
           cluster-suffix: c${{ github.run_id }}.local
+        - k8s-version: v1.22.0
+          kind-version: v0.11.1
+          kind-image-sha: sha256:f97edf7f7ed53c57762b24f90a34fad101386c5bd4d93baeb45449557148c717
+          kingress: kourier
+          cluster-suffix: c${{ github.run_id }}.local
 
           # The tests in api/v1alpha1 require the --enable-alpha flag to be set,
           # and alpha components to be deployed.
diff --git a/cmd/queue/execprobe_test.go b/cmd/queue/execprobe_test.go
deleted file mode 100644
index 16b59dde9..000000000
--- a/cmd/queue/execprobe_test.go
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-Copyright 2020 The Knative Authors
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"net/http"
-	"net/http/httptest"
-	"net/url"
-	"os"
-	"testing"
-	"time"
-
-	"go.uber.org/atomic"
-
-	network "knative.dev/networking/pkg"
-	"knative.dev/serving/pkg/queue/readiness"
-)
-
-func TestProbeQueueInvalidPort(t *testing.T) {
-	t.Cleanup(func() { os.Unsetenv(queuePortEnvVar) })
-	for _, port := range []string{"-1", "0", "66000"} {
-		os.Setenv(queuePortEnvVar, port)
-		if rv := standaloneProbeMain(1, http.DefaultTransport); rv != 1 {
-			t.Error("Unexpected return code", rv)
-		}
-	}
-}
-
-func TestProbeQueueConnectionFailure(t *testing.T) {
-	if err := probeQueueHealthPath(1, "12345", http.DefaultTransport); err == nil {
-		t.Error("Expected error, got nil")
-	}
-}
-
-func TestProbeQueueNotReady(t *testing.T) {
-	var probed atomic.Bool
-	port := newProbeTestServer(t, func(w http.ResponseWriter, _ *http.Request) {
-		probed.Store(true)
-		w.WriteHeader(http.StatusBadRequest)
-	})
-
-	err := probeQueueHealthPath(300*time.Millisecond, port, http.DefaultTransport)
-
-	if err == nil || err.Error() != "probe returned not ready" {
-		t.Error("Unexpected not ready error:", err)
-	}
-
-	if !probed.Load() {
-		t.Error("Expected the queue proxy server to be probed")
-	}
-}
-
-func TestProbeShuttingDown(t *testing.T) {
-	var probed atomic.Bool
-	port := newProbeTestServer(t, func(w http.ResponseWriter, _ *http.Request) {
-		probed.Store(true)
-		w.WriteHeader(http.StatusGone)
-	})
-
-	err := probeQueueHealthPath(time.Second, port, http.DefaultTransport)
-
-	if err == nil || err.Error() != "failed to probe: failing probe deliberately for shutdown" {
-		t.Error("Unexpected error:", err)
-	}
-
-	if !probed.Load() {
-		t.Error("Expected the queue proxy server to be probed")
-	}
-}
-
-func TestProbeQueueShuttingDownFailsFast(t *testing.T) {
-	port := newProbeTestServer(t, func(w http.ResponseWriter, _ *http.Request) {
-		w.WriteHeader(http.StatusGone)
-	})
-
-	start := time.Now()
-	if err := probeQueueHealthPath(1, port, http.DefaultTransport); err == nil {
-		t.Error("probeQueueHealthPath did not fail")
-	}
-
-	// if fails due to timeout and not cancelation, then it took too long.
-	if time.Since(start) >= 1*time.Second {
-		t.Error("took too long to fail")
-	}
-}
-
-func TestProbeQueueReady(t *testing.T) {
-	var probed atomic.Bool
-	port := newProbeTestServer(t, func(w http.ResponseWriter, _ *http.Request) {
-		probed.Store(true)
-		w.WriteHeader(http.StatusOK)
-	})
-
-	t.Cleanup(func() { os.Unsetenv(queuePortEnvVar) })
-	os.Setenv(queuePortEnvVar, port)
-
-	if rv := standaloneProbeMain(0 /*use default*/, nil); rv != 0 {
-		t.Error("Unexpected return value from standaloneProbeMain:", rv)
-	}
-
-	if !probed.Load() {
-		t.Error("Expected the queue proxy server to be probed")
-	}
-}
-
-func TestProbeQueueTimeout(t *testing.T) {
-	var probed atomic.Bool
-	port := newProbeTestServer(t, func(w http.ResponseWriter, r *http.Request) {
-		probed.Store(true)
-
-		select {
-		case <-time.After(time.Second):
-		case <-r.Context().Done():
-		}
-
-		w.WriteHeader(http.StatusOK)
-	})
-
-	t.Cleanup(func() { os.Unsetenv(queuePortEnvVar) })
-	os.Setenv(queuePortEnvVar, port)
-
-	if rv := standaloneProbeMain(300*time.Millisecond, nil); rv == 0 {
-		t.Error("Unexpected return value from standaloneProbeMain:", rv)
-	}
-
-	if !probed.Load() {
-		t.Error("Expected the queue proxy server to be probed")
-	}
-}
-
-func TestProbeQueueDelayedReady(t *testing.T) {
-	var count atomic.Int64
-	port := newProbeTestServer(t, func(w http.ResponseWriter, _ *http.Request) {
-		if count.Inc() < 3 {
-			w.WriteHeader(http.StatusBadRequest)
-			return
-		}
-		w.WriteHeader(http.StatusOK)
-	})
-
-	if err := probeQueueHealthPath(readiness.PollTimeout, port, http.DefaultTransport); err != nil {
-		t.Errorf("probeQueueHealthPath(%s) = %s", port, err)
-	}
-}
-
-func newProbeTestServer(t *testing.T, f func(w http.ResponseWriter, r *http.Request)) (port string) {
-	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		if r.Header.Get(network.UserAgentKey) == network.QueueProxyUserAgent {
-			f(w, r)
-		}
-	}))
-	t.Cleanup(ts.Close)
-
-	u, err := url.Parse(ts.URL)
-	if err != nil {
-		t.Fatalf("%s is not a valid URL: %v", ts.URL, err)
-	}
-
-	return u.Port()
-}
diff --git a/pkg/activator/net/revision_backends_test.go b/pkg/activator/net/revision_backends_test.go
index 751dc1a01..f241741f0 100644
--- a/pkg/activator/net/revision_backends_test.go
+++ b/pkg/activator/net/revision_backends_test.go
@@ -125,6 +125,7 @@ func TestRevisionWatcher(t *testing.T) {
 		initialClusterIPState bool
 		noPodAddressability   bool // This keeps the test defs shorter.
 		usePassthroughLb      bool
+		meshMode              meshMode
 	}{{
 		name:  "single healthy podIP",
 		dests: dests{ready: sets.NewString("128.0.0.1:1234")},
@@ -418,6 +419,58 @@ func TestRevisionWatcher(t *testing.T) {
 			}},
 		},
 		usePassthroughLb: true,
+	}, {
+		name:  "mesh mode enabled: pod ready but should still use cluster IP",
+		dests: dests{ready: sets.NewString("128.0.0.1:1234")},
+		clusterPort: corev1.ServicePort{
+			Name: "http",
+			Port: 1235,
+		},
+		noPodAddressability: true,
+		clusterIP:           "129.0.0.1",
+		expectUpdates: []revisionDestsUpdate{
+			{ClusterIPDest: "129.0.0.1:1235", Dests: sets.NewString("128.0.0.1:1234")},
+		},
+		meshMode: meshModeEnabled,
+		probeHostResponses: map[string][]activatortest.FakeResponse{
+			"128.0.0.1:1234": {{
+				// Pod is healthy, but should not be used since we're in mesh mode.
+				Code: http.StatusOK,
+				Body: queue.Name,
+			}},
+			"129.0.0.1:1234": {{
+				Code: http.StatusOK,
+				Body: queue.Name,
+			}},
+		},
+	}, {
+		name:  "mesh mode disabled: pod initially returns mesh-compatible error, but don't fallback",
+		dests: dests{ready: sets.NewString("128.0.0.1:1234")},
+		clusterPort: corev1.ServicePort{
+			Name: "http",
+			Port: 1235,
+		},
+		noPodAddressability: false,
+		clusterIP:           "129.0.0.1",
+		expectUpdates: []revisionDestsUpdate{
+			{Dests: sets.NewString("128.0.0.1:1234")},
+		},
+		meshMode: meshModeDisabled,
+		probeHostResponses: map[string][]activatortest.FakeResponse{
+			"129.0.0.1:1234": {{
+				// Cluster IP healthy, but should not be used.
+				Code: http.StatusOK,
+				Body: queue.Name,
+			}},
+			"128.0.0.1:1234": {{
+				// Mesh compatible error, but don't fall back (because mesh mode is disabled).
+				Code: meshErrorStatusCode,
+				Body: queue.Name,
+			}, {
+				Code: http.StatusOK,
+				Body: queue.Name,
+			}},
+		},
 	}} {
 		t.Run(tc.name, func(t *testing.T) {
 			fakeRT := activatortest.FakeRoundTripper{
@@ -467,6 +520,7 @@ func TestRevisionWatcher(t *testing.T) {
 				rt,
 				informer.Lister(),
 				tc.usePassthroughLb, // usePassthroughLb
+				tc.meshMode,
 				logger)
 			rw.clusterIPHealthy = tc.initialClusterIPState
 
diff --git a/pkg/queue/concurrency_state_test.go b/pkg/queue/concurrency_state_test.go
index 85a84f4db..e3d635fc0 100644
--- a/pkg/queue/concurrency_state_test.go
+++ b/pkg/queue/concurrency_state_test.go
@@ -23,7 +23,6 @@ import (
 	"time"
 
 	"go.uber.org/atomic"
-	"k8s.io/apimachinery/pkg/util/wait"
 	pkglogging "knative.dev/pkg/logging"
 	ltesting "knative.dev/pkg/logging/testing"
 
@@ -39,20 +38,20 @@ func TestConcurrencyStateHandler(t *testing.T) {
 	h := ConcurrencyStateHandler(logger, http.HandlerFunc(handler), func() { paused.Inc() }, func() { resumed.Inc() })
 
 	h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("GET", "http://target", nil))
-	if got, want := pollFor(paused, 1), int64(1); got != want {
+	if got, want := paused.Load(), int64(1); got != want {
 		t.Errorf("Pause was called %d times, want %d times", got, want)
 	}
 
-	if got, want := pollFor(resumed, 1), int64(1); got != want {
+	if got, want := resumed.Load(), int64(1); got != want {
 		t.Errorf("Resume was called %d times, want %d times", got, want)
 	}
 
 	h.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest("GET", "http://target", nil))
-	if got, want := pollFor(paused, 2), int64(2); got != want {
+	if got, want := paused.Load(), int64(2); got != want {
 		t.Errorf("Pause was called %d times, want %d times", got, want)
 	}
 
-	if got, want := pollFor(resumed, 2), int64(2); got != want {
+	if got, want := resumed.Load(), int64(2); got != want {
 		t.Errorf("Resume was called %d times, want %d times", got, want)
 	}
 }
@@ -84,11 +83,11 @@ func TestConcurrencyStateHandlerParallelSubsumed(t *testing.T) {
 	<-req1 // Allow req1 to pass.
 	<-req1 // Wait for req1 to finish.
 
-	if got, want := pollFor(paused, 1), int64(1); got != want {
+	if got, want := paused.Load(), int64(1); got != want {
 		t.Errorf("Pause was called %d times, want %d times", got, want)
 	}
 
-	if got, want := pollFor(resumed, 1), int64(1); got != want {
+	if got, want := resumed.Load(), int64(1); got != want {
 		t.Errorf("Resume was called %d times, want %d times", got, want)
 	}
 }
@@ -131,11 +130,11 @@ func TestConcurrencyStateHandlerParallelOverlapping(t *testing.T) {
 	<-req2 // Allow req2 to pass.
 	<-req2 // Wait for req2 to finish.
 
-	if got, want := pollFor(paused, 1), int64(1); got != want {
+	if got, want := paused.Load(), int64(1); got != want {
 		t.Errorf("Pause was called %d times, want %d times", got, want)
 	}
 
-	if got, want := pollFor(resumed, 1), int64(1); got != want {
+	if got, want := resumed.Load(), int64(1); got != want {
 		t.Errorf("Resume was called %d times, want %d times", got, want)
 	}
 }
@@ -205,12 +204,3 @@ func BenchmarkConcurrencyStateProxyHandler(b *testing.B) {
 		reportTicker.Stop()
 	}
 }
-
-func pollFor(val *atomic.Int64, want int64) int64 {
-	var lastVal int64
-	wait.PollImmediate(1*time.Millisecond, 1*time.Second, func() (bool, error) {
-		lastVal = val.Load()
-		return lastVal == want, nil
-	})
-	return lastVal
-}
diff --git a/pkg/queue/health/probe_test.go b/pkg/queue/health/probe_test.go
index 402d5c135..b795e5b8d 100644
--- a/pkg/queue/health/probe_test.go
+++ b/pkg/queue/health/probe_test.go
@@ -258,41 +258,6 @@ func TestHTTPProbeResponseErrorFailure(t *testing.T) {
 	}
 }
 
-func TestIsHTTPProbeShuttingDown(t *testing.T) {
-	tests := []struct {
-		name       string
-		statusCode int
-		wantResult bool
-	}{{
-		name:       "statusCode: 410",
-		statusCode: 410,
-		wantResult: true,
-	}, {
-		name:       "statusCode: 503",
-		statusCode: 503,
-		wantResult: false,
-	}, {
-		name:       "statusCode: 200",
-		statusCode: 200,
-		wantResult: false,
-	}, {
-		name:       "statusCode: 301",
-		statusCode: 301,
-		wantResult: false,
-	}}
-
-	for _, test := range tests {
-		t.Run(test.name, func(t *testing.T) {
-			response := http.Response{StatusCode: test.statusCode}
-			result := IsHTTPProbeShuttingDown(&response)
-			if result != test.wantResult {
-				t.Errorf("IsHTTPProbeShuttingDown returned unexpected result: got %v want %v",
-					result, test.wantResult)
-			}
-		})
-	}
-}
-
 func newH2cTestServer(t *testing.T, handler http.HandlerFunc) *httptest.Server {
 	h2s := &http2.Server{}
 	t.Helper()
diff --git a/pkg/reconciler/revision/resources/deploy_test.go b/pkg/reconciler/revision/resources/deploy_test.go
index 1de81e6f4..a5a999e8a 100644
--- a/pkg/reconciler/revision/resources/deploy_test.go
+++ b/pkg/reconciler/revision/resources/deploy_test.go
@@ -77,16 +77,6 @@ var (
 		Name:      QueueContainerName,
 		Resources: createQueueResources(&deploymentConfig, make(map[string]string), &corev1.Container{}),
 		Ports:     append(queueNonServingPorts, queueHTTPPort),
-		StartupProbe: &corev1.Probe{
-			Handler: corev1.Handler{
-				Exec: &corev1.ExecAction{
-					Command: []string{"/ko-app/queue", "-probe-timeout", "0s"},
-				},
-			},
-			PeriodSeconds:    1,
-			FailureThreshold: 1,
-			SuccessThreshold: 1,
-		},
 		ReadinessProbe: &corev1.Probe{
 			Handler: corev1.Handler{
 				HTTPGet: &corev1.HTTPGetAction{
@@ -1098,13 +1088,11 @@ func TestMakePodSpec(t *testing.T) {
 		want: podSpec(
 			[]corev1.Container{
 				servingContainer(func(container *corev1.Container) {
-					container.StartupProbe = nil
 					container.ReadinessProbe = nil
 				}),
 				queueContainer(
 					withEnvVar("SERVING_READINESS_PROBE", ""),
 					func(container *corev1.Container) {
-						container.StartupProbe = nil
 						container.ReadinessProbe = nil
 					}),
 			}),
diff --git a/pkg/reconciler/revision/resources/queue_test.go b/pkg/reconciler/revision/resources/queue_test.go
index ab09d78c1..72620ea81 100644
--- a/pkg/reconciler/revision/resources/queue_test.go
+++ b/pkg/reconciler/revision/resources/queue_test.go
@@ -340,29 +340,6 @@ func TestMakeQueueContainer(t *testing.T) {
 				"ENABLE_HTTP2_AUTO_DETECTION": "false",
 			})
 		}),
-	}, {
-		name: "set startup probe timeouts based on ProgressDeadline",
-		rev: revision("bar", "foo",
-			withContainers(containers)),
-		dc: deployment.Config{
-			ProgressDeadline: 1984 * time.Second,
-		},
-		want: queueContainer(func(c *corev1.Container) {
-			c.Env = env(map[string]string{})
-			c.StartupProbe = &corev1.Probe{
-				Handler: corev1.Handler{
-					Exec: &corev1.ExecAction{
-						Command: []string{"/ko-app/queue", "-probe-timeout", "33m4s"},
-					},
-				},
-				// The startup probe timeout seconds is set to the progress deadline to
-				// match the timeout on initial deployment.
-				TimeoutSeconds:   1984,
-				PeriodSeconds:    1,
-				SuccessThreshold: 1,
-				FailureThreshold: 1,
-			}
-		}),
 	}}
 
 	for _, test := range tests {
@@ -578,7 +555,6 @@ func TestProbeGenerationHTTPDefaults(t *testing.T) {
 		c.Env = env(map[string]string{
 			"SERVING_READINESS_PROBE": string(wantProbeJSON),
 		})
-		c.StartupProbe = nil // User overrode periodSeconds so no exec probe needed.
 		c.ReadinessProbe = &corev1.Probe{
 			Handler: corev1.Handler{
 				HTTPGet: &corev1.HTTPGetAction{
@@ -655,7 +631,6 @@ func TestProbeGenerationHTTP(t *testing.T) {
 			"USER_PORT":               strconv.Itoa(userPort),
 			"SERVING_READINESS_PROBE": string(wantProbeJSON),
 		})
-		c.StartupProbe = nil // User overrode periodSeconds so no execprobe needed.
 		c.ReadinessProbe = &corev1.Probe{
 			Handler: corev1.Handler{
 				HTTPGet: &corev1.HTTPGetAction{
@@ -723,21 +698,6 @@ func TestTCPProbeGeneration(t *testing.T) {
 			ProgressDeadline: 5678 * time.Second,
 		},
 		want: queueContainer(func(c *corev1.Container) {
-			c.StartupProbe = &corev1.Probe{
-				Handler: corev1.Handler{
-					Exec: &corev1.ExecAction{
-						Command: []string{"/ko-app/queue", "-probe-timeout", "1h34m38s"},
-					},
-				},
-				// StartupProbe overrides the user's parameters because the
-				// actual probing happens inside the execprobe.
-				// The timeout seconds is set to the progress deadline to match the
-				// timeout on initial deployment.
-				TimeoutSeconds:   5678,
-				PeriodSeconds:    1,
-				SuccessThreshold: 1,
-				FailureThreshold: 1,
-			}
 			c.ReadinessProbe = &corev1.Probe{
 				Handler: corev1.Handler{
 					HTTPGet: &corev1.HTTPGetAction{
@@ -781,7 +741,6 @@ func TestTCPProbeGeneration(t *testing.T) {
 			TimeoutSeconds: 1,
 		},
 		want: queueContainer(func(c *corev1.Container) {
-			c.StartupProbe = nil // User overrode periodSeconds, no exec probe needed.
 			c.ReadinessProbe = &corev1.Probe{
 				Handler: corev1.Handler{
 					HTTPGet: &corev1.HTTPGetAction{
@@ -835,7 +794,6 @@ func TestTCPProbeGeneration(t *testing.T) {
 			},
 		},
 		want: queueContainer(func(c *corev1.Container) {
-			c.StartupProbe = nil // User overrode periodSeconds, no exec probe needed.
 			c.ReadinessProbe = &corev1.Probe{
 				Handler: corev1.Handler{
 					HTTPGet: &corev1.HTTPGetAction{
diff --git a/pkg/reconciler/route/table_test.go b/pkg/reconciler/route/table_test.go
index 7b88f0873..44b8756da 100644
--- a/pkg/reconciler/route/table_test.go
+++ b/pkg/reconciler/route/table_test.go
@@ -2583,8 +2583,145 @@ func TestReconcileEnableAutoTLS(t *testing.T) {
 		WantEvents: []string{
 			Eventf(corev1.EventTypeNormal, "Created", "Created placeholder service %q", "becomes-ready"),
 			Eventf(corev1.EventTypeNormal, "Updated", "Updated Spec for Certificate %s/%s", "default", "route-12-34"),
+			Eventf(corev1.EventTypeNormal, "Deleted", "Deleted orphaned Knative Certificate %s/%s", "default", "route-12-34"),
 			Eventf(corev1.EventTypeNormal, "Created", "Created Ingress %q", "becomes-ready"),
 		},
+		WantDeletes: []clientgotesting.DeleteActionImpl{{
+			// This certificate's DNS name is not the host name needed by the input Route.
+			ActionImpl: clientgotesting.ActionImpl{
+				Namespace: "default",
+				Verb:      "delete",
+				Resource:  netv1alpha1.SchemeGroupVersion.WithResource("certificates"),
+			},
+			Name: "route-12-34",
+		}},
+		Key: "default/becomes-ready",
+	}, {
+		Name: "check that unused certificate removal works as intended",
+		Objects: []runtime.Object{
+			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34")),
+			cfg("default", "config",
+				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
+			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
+			&netv1alpha1.Certificate{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "route-12-34",
+					Namespace: "default",
+					OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(
+						Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34")))},
+					Labels: map[string]string{
+						serving.RouteLabelKey: "becomes-ready",
+					},
+					Annotations: map[string]string{
+						networking.CertificateClassAnnotationKey: network.CertManagerCertificateClassName,
+					},
+				},
+				Spec: netv1alpha1.CertificateSpec{
+					DNSNames: []string{"abc.test.example.com", "becomes-ready.default.example.com"},
+				},
+				Status: readyCertStatus(),
+			},
+			// This certificate is not required; the route will use the certificate named "route-12-34".
+			// This certificate has a different DNSNames order to test the unused certificate deletion.
+			&netv1alpha1.Certificate{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "route-12-34-keep",
+					Namespace: "default",
+					OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(
+						Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34")))},
+					Labels: map[string]string{
+						serving.RouteLabelKey: "becomes-ready",
+					},
+					Annotations: map[string]string{
+						networking.CertificateClassAnnotationKey: network.CertManagerCertificateClassName,
+					},
+				},
+				Spec: netv1alpha1.CertificateSpec{
+					DNSNames: []string{"becomes-ready.default.example.com", "abc.test.example.com"},
+				},
+				Status: readyCertStatus(),
+			},
+			// MakeCertificates will create a certificate with DNS name "abc.test.example.com" which is not the host name
+			// needed by the input Route.
+			&netv1alpha1.Certificate{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "route-12-34-unused",
+					Namespace: "default",
+					OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(
+						Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34")))},
+					Labels: map[string]string{
+						serving.RouteLabelKey: "becomes-ready",
+					},
+					Annotations: map[string]string{
+						networking.CertificateClassAnnotationKey: network.CertManagerCertificateClassName,
+					},
+				},
+				Spec: netv1alpha1.CertificateSpec{
+					DNSNames: []string{"abc.test.example.com"},
+				},
+				Status: readyCertStatus(),
+			},
+		},
+		WantCreates: []runtime.Object{
+			ingressWithTLS(
+				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL,
+					WithRouteUID("12-34")),
+				&traffic.Config{
+					Targets: map[string]traffic.RevisionTargets{
+						traffic.DefaultTarget: {{
+							TrafficTarget: v1.TrafficTarget{
+								ConfigurationName: "config",
+								LatestRevision:    ptr.Bool(true),
+								RevisionName:      "config-00001",
+								Percent:           ptr.Int64(100),
+							},
+						}},
+					},
+				},
+				[]netv1alpha1.IngressTLS{{
+					Hosts:           []string{"becomes-ready.default.example.com"},
+					SecretName:      "route-12-34",
+					SecretNamespace: "default",
+				}},
+				nil,
+			),
+			simpleK8sService(
+				Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34")),
+				WithExternalName("becomes-ready.default.example.com"),
+			),
+		},
+		WantUpdates: []clientgotesting.UpdateActionImpl{{
+			Object: certificateWithStatus(resources.MakeCertificates(Route("default", "becomes-ready", WithConfigTarget("config"), WithURL, WithRouteUID("12-34")),
+				map[string]string{"becomes-ready.default.example.com": ""}, network.CertManagerCertificateClassName)[0], readyCertStatus()),
+		}},
+		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
+			Object: Route("default", "becomes-ready", WithConfigTarget("config"),
+				WithRouteUID("12-34"),
+				WithAddress, WithInitRouteConditions,
+				MarkTrafficAssigned, MarkIngressNotConfigured, WithStatusTraffic(
+					v1.TrafficTarget{
+						RevisionName:   "config-00001",
+						Percent:        ptr.Int64(100),
+						LatestRevision: ptr.Bool(true),
+					}), MarkCertificateReady,
+				// The certificate is ready. So we want to have HTTPS URL.
+				WithHTTPSDomain),
+		}},
+		WantEvents: []string{
+			Eventf(corev1.EventTypeNormal, "Created", "Created placeholder service %q", "becomes-ready"),
+			Eventf(corev1.EventTypeNormal, "Updated", "Updated Spec for Certificate %s/%s", "default", "route-12-34"),
+			Eventf(corev1.EventTypeNormal, "Deleted", "Deleted orphaned Knative Certificate %s/%s", "default", "route-12-34-unused"),
+			Eventf(corev1.EventTypeNormal, "Created", "Created Ingress %q", "becomes-ready"),
+		},
+		WantDeletes: []clientgotesting.DeleteActionImpl{{
+			// This certificate's DNS name is not the host name needed by the input Route.
+			ActionImpl: clientgotesting.ActionImpl{
+				Namespace: "default",
+				Verb:      "delete",
+				Resource:  netv1alpha1.SchemeGroupVersion.WithResource("certificates"),
+			},
+			Name: "route-12-34-unused",
+		}},
 		Key: "default/becomes-ready",
 	}, {
 		Name: "verify ingress rules created for http01 challenges",
@@ -2796,8 +2933,18 @@ func TestReconcileEnableAutoTLS(t *testing.T) {
 		WantEvents: []string{
 			Eventf(corev1.EventTypeNormal, "Created", "Created placeholder service %q", "becomes-ready"),
 			Eventf(corev1.EventTypeNormal, "Updated", "Updated Spec for Certificate %s/%s", "default", "route-12-34"),
+			Eventf(corev1.EventTypeNormal, "Deleted", "Deleted orphaned Knative Certificate %s/%s", "default", "route-12-34"),
 			Eventf(corev1.EventTypeNormal, "Created", "Created Ingress %q", "becomes-ready"),
 		},
+		WantDeletes: []clientgotesting.DeleteActionImpl{{
+			// This certificate's DNS name is not the host name needed by the input Route.
+			ActionImpl: clientgotesting.ActionImpl{
+				Namespace: "default",
+				Verb:      "delete",
+				Resource:  netv1alpha1.SchemeGroupVersion.WithResource("certificates"),
+			},
+			Name: "route-12-34",
+		}},
 		Key: "default/becomes-ready",
 	}, {
 		// This test is a same with "public becomes cluster local" above, but confirm it does not create certs with autoTLS for cluster-local.
diff --git a/test/conformance/api/v1/resources_test.go b/test/conformance/api/v1/resources_test.go
index 7f35686c1..023730202 100644
--- a/test/conformance/api/v1/resources_test.go
+++ b/test/conformance/api/v1/resources_test.go
@@ -114,7 +114,12 @@ func TestCustomResourcesLimits(t *testing.T) {
 		t.Fatalf("Didn't get a response from bloating cow with %d MBs of Memory: %v", 200, err)
 	}
 
-	if err := pokeCowForMB(500); err == nil {
-		t.Fatalf("We shouldn't have got a response from bloating cow with %d MBs of Memory: %v", 500, err)
+	// ExceedingMemoryLimitSize defaults to 500.
+	// Allows override the memory usage to get a non-200 resposne because the serverless platform
+	// MAY automatically adjust the resource limits.
+	// See https://github.com/knative/specs/blob/main/specs/serving/runtime-contract.md#memory-and-cpu-limits
+	exceedingMemory := test.ServingFlags.ExceedingMemoryLimitSize
+	if err := pokeCowForMB(exceedingMemory); err == nil {
+		t.Fatalf("We shouldn't have got a response from bloating cow with %d MBs of Memory: %v", exceedingMemory, err)
 	}
 }
diff --git a/test/e2e/logging_test.go b/test/e2e/logging_test.go
index 6070a29b2..2cf72cd11 100644
--- a/test/e2e/logging_test.go
+++ b/test/e2e/logging_test.go
@@ -121,7 +121,7 @@ func TestRequestLogs(t *testing.T) {
 		// Health check requests are sent to / with a specific userAgent value periodically.
 		if err := waitForLog(t, clients, pod.Namespace, pod.Name, "queue-proxy", func(log logLine) bool {
 			return log.HTTPRequest.RequestURL == "/" &&
-				log.HTTPRequest.UserAgent == network.QueueProxyUserAgent
+				strings.HasPrefix(log.HTTPRequest.UserAgent, network.KubeProbeUAPrefix)
 		}); err != nil {
 			t.Fatal("Got error waiting for health check log:", err)
 		}
diff --git a/test/e2e_flags.go b/test/e2e_flags.go
index 69154d6ca..73214d7d8 100644
--- a/test/e2e_flags.go
+++ b/test/e2e_flags.go
@@ -31,18 +31,19 @@ var ServingFlags = initializeServingFlags()
 
 // ServingEnvironmentFlags holds the e2e flags needed only by the serving repo.
 type ServingEnvironmentFlags struct {
-	ResolvableDomain    bool   // Resolve Route controller's `domainSuffix`
-	CustomDomain        string // Indicates the `domainSuffix` for custom domain test.
-	HTTPS               bool   // Indicates where the test service will be created with https
-	Buckets             int    // The number of reconciler buckets configured.
-	Replicas            int    // The number of controlplane replicas being run.
-	EnableAlphaFeatures bool   // Indicates whether we run tests for alpha features
-	EnableBetaFeatures  bool   // Indicates whether we run tests for beta features
-	DisableLogStream    bool   // Indicates whether log streaming is disabled
-	DisableOptionalAPI  bool   // Indicates whether to skip conformance tests against optional API
-	TestNamespace       string // Default namespace for Serving E2E/Conformance tests
-	AltTestNamespace    string // Alternative namespace for running cross-namespace tests in
-	TLSTestNamespace    string // Namespace for Serving TLS tests
+	ResolvableDomain         bool   // Resolve Route controller's `domainSuffix`
+	CustomDomain             string // Indicates the `domainSuffix` for custom domain test.
+	HTTPS                    bool   // Indicates where the test service will be created with https
+	Buckets                  int    // The number of reconciler buckets configured.
+	Replicas                 int    // The number of controlplane replicas being run.
+	EnableAlphaFeatures      bool   // Indicates whether we run tests for alpha features
+	EnableBetaFeatures       bool   // Indicates whether we run tests for beta features
+	DisableLogStream         bool   // Indicates whether log streaming is disabled
+	DisableOptionalAPI       bool   // Indicates whether to skip conformance tests against optional API
+	TestNamespace            string // Default namespace for Serving E2E/Conformance tests
+	AltTestNamespace         string // Alternative namespace for running cross-namespace tests in
+	TLSTestNamespace         string // Namespace for Serving TLS tests
+	ExceedingMemoryLimitSize int    // Memory size used to trigger a non-200 response when the service is set with 300MB memory limit.
 }
 
 func initializeServingFlags() *ServingEnvironmentFlags {
@@ -84,5 +85,9 @@ func initializeServingFlags() *ServingEnvironmentFlags {
 	flag.StringVar(&f.TLSTestNamespace, "tls-test-namespace", "tls",
 		"Set this flag to change the namespace for running TLS tests.")
 
+	flag.IntVar(&f.ExceedingMemoryLimitSize, "exceeding-memory-limit-size", 500,
+		"Set this flag to the MB of memory consumed by your service in resource limit tests. "+
+			"You service is set with 300 MB memory limit and shoud return a non-200 response when consuming such amount of memory.")
+
 	return &f
 }
diff --git a/test/v1/service.go b/test/v1/service.go
index 65a761f57..2e615e408 100644
--- a/test/v1/service.go
+++ b/test/v1/service.go
@@ -224,9 +224,7 @@ func WaitForServiceLatestRevision(clients *test.Clients, names test.ResourceName
 	if err := WaitForServiceState(clients.ServingClient, names.Service, func(s *v1.Service) (bool, error) {
 		if s.Status.LatestCreatedRevisionName != names.Revision {
 			revisionName = s.Status.LatestCreatedRevisionName
-			// Without this it might happen that the latest created revision is later overridden by a newer one
-			// and the following check for LatestReadyRevisionName would fail.
-			return CheckRevisionState(clients.ServingClient, revisionName, IsRevisionRoutingActive) == nil, nil
+			return true, nil
 		}
 		return false, nil
 	}, "ServiceUpdatedWithRevision"); err != nil {
diff --git a/third_party/cert-manager-latest/net-certmanager.yaml b/third_party/cert-manager-latest/net-certmanager.yaml
index b88385828..2e1eb28b1 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: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     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: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     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: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     networking.knative.dev/certificate-provider: cert-manager
 
 ---
@@ -112,7 +112,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     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: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     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: "v20210909-e8ecf946"
+        serving.knative.dev/release: "v20210910-58d9cad4"
     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:263df033c5dfca39bb72f900ac3c48902d735a32ddf9f8641f6205929ed4a9e2
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:f127be0e080bf9b95b0c37ae10ea4b685a10ab87e98ee8d2abff7108b1f74f6b
           resources:
             requests:
               cpu: 30m
@@ -216,7 +216,7 @@ kind: Service
 metadata:
   labels:
     app: net-certmanager-controller
-    serving.knative.dev/release: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     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: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     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: "v20210909-e8ecf946"
+        serving.knative.dev/release: "v20210910-58d9cad4"
     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:311d176ab488e81ba0f0ecdd70eebe74f00600262890a6aab83bfee1b5d5168b
+          image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:97ce5cb8a8ecc800ed4135adf062c986298ae82afd34ed329a17fe8f526d88ce
           resources:
             requests:
               cpu: 20m
@@ -333,7 +333,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20210909-e8ecf946"
+    serving.knative.dev/release: "v20210910-58d9cad4"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   ports:
diff --git a/third_party/contour-latest/contour.yaml b/third_party/contour-latest/contour.yaml
index f181c8d27..bc2b9b283 100644
--- a/third_party/contour-latest/contour.yaml
+++ b/third_party/contour-latest/contour.yaml
@@ -1904,7 +1904,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           command:
             - contour
@@ -2155,7 +2155,7 @@ spec:
             - --config-path=/config/contour.yaml
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -2244,7 +2244,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -2326,7 +2326,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
@@ -2605,7 +2605,7 @@ spec:
     spec:
       containers:
         - name: contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           command:
             - contour
@@ -2717,7 +2717,7 @@ spec:
             - --config-path=/config/contour.yaml
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           name: contour
           ports:
@@ -2806,7 +2806,7 @@ spec:
           args:
             - envoy
             - shutdown-manager
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           lifecycle:
             preStop:
@@ -2888,7 +2888,7 @@ spec:
             - --envoy-key-file=/certs/tls.key
           command:
             - contour
-          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:80ba2608c8ec90354adb9c3e073759cf7572d425b9d77363930eecae6595eb30
+          image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:cfa94afa242cde3247bc2f5be0371e3043b6c06b1419799a3685b83fa696232b
           imagePullPolicy: IfNotPresent
           name: envoy-initconfig
           volumeMounts:
diff --git a/third_party/contour-latest/net-contour.yaml b/third_party/contour-latest/net-contour.yaml
index 2ef5fc7bd..bcc3abbee 100644
--- a/third_party/contour-latest/net-contour.yaml
+++ b/third_party/contour-latest/net-contour.yaml
@@ -33,7 +33,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: contour
-    serving.knative.dev/release: "v20210909-0343922c"
+    serving.knative.dev/release: "v20210910-5b0e8112"
 data:
   _example: |
     ################################
@@ -103,7 +103,7 @@ spec:
         - 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-contour/cmd/controller@sha256:3f8eb962bf682d0b1e90c0ff99a2dd6e06a6355b78a583a0516fc330eb18e44c
+          image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:55d192281ccfe727d19ea2b172364ca6b1e9cb0fce0145f93753a2989477da3c
           resources:
             requests:
               cpu: 40m
diff --git a/third_party/istio-latest/net-istio.yaml b/third_party/istio-latest/net-istio.yaml
index cb62ecfc2..806406225 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 94fc25274433b84c9277a5a6366dbdc862a426fa
+# Generated when HEAD was 2b9152729cc8cd2392e78f9a7f3a2b479f089a54
 #
 # 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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -200,7 +200,7 @@ metadata:
   name: "webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -216,7 +216,7 @@ metadata:
   name: "domainmapping-webhook"
   namespace: "knative-serving"
   labels:
-    serving.knative.dev/release: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+        serving.knative.dev/release: "v20210910-2b915272"
     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:740fb8c181be7f2b94c7a759a95d6faebd73a32ecb9af362e623df67ec1ac049
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:94cf24beb5aeafd3b9b691e94315b80a536623a10df631ce768e48a63e761e76
           resources:
             requests:
               cpu: 30m
@@ -343,7 +343,7 @@ metadata:
   name: net-istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+        serving.knative.dev/release: "v20210910-2b915272"
     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:1a503845bf10854c4443d559ce2cf47d4fa910bc94ede34a2db0e436e701834c
+          image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:c67d637dfa826600c99e8f455be189dc09ccc7789815d7763f215b8108496e0b
           resources:
             requests:
               cpu: 20m
@@ -417,7 +417,7 @@ metadata:
   name: net-istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     networking.knative.dev/ingress-provider: istio
 
 ---
@@ -442,7 +442,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-istio-webhook
-    serving.knative.dev/release: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     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: "v20210909-94fc2527"
+    serving.knative.dev/release: "v20210910-2b915272"
     networking.knative.dev/ingress-provider: istio
 webhooks:
   - admissionReviewVersions: