Repository: knative/serving
Pull request #8105 (2020-05-28 00:42:21)

Split Active/Ready for PA types
<!--
Request Prow to automatically lint any go code in this PR:

/lint
-->

Issue #8004

<!-- Please include the 'why' behind your changes if no issue exists -->
## Proposed Changes

* Instead of using Ready/Active interchangeably, take ObservedGeneration into account for Ready and ensure the reconciler is looking at Active internally.
    * External callers and clients should use Readiness to see that the resource is ready with the latest gen.

**Note**
This change is required for https://github.com/knative/serving/pull/8155 to work properly. The automatic logic in preprocess resets ready to unknown upon observing a new generation (expecting the reconciler to overwrite it with something), but the scaler logic here: https://github.com/knative/serving/blob/224721105fb411d354d07a77fb322939696a42ac/pkg/reconciler/autoscaling/kpa/scaler.go#L193 mixes the ready and active conditions and assumes they are interchangable.


**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

```


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

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/8105#" title="Author self-approved">whaught</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **markusthoemmes**
You can assign the PR to them by writing `/assign @markusthoemmes` 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:

- **[OWNERS](https://github.com/knative/serving/blob/master/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":["markusthoemmes"]} -->
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265805691369558017/artifacts/line-cov.html#file0) | Do not exist | 100.0% | 

knative-prow-robot: @whaught: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-integration-tests | 73908ac20e2d0f8c5c0e89370b5e230889cdb848 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265805691369558016) | `/test pull-knative-serving-integration-tests`

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

<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 -->
knative-test-reporter-robot: <!--[AUTOMATED-FLAKY-RETRYER]73908ac20e2d0f8c5c0e89370b5e230889cdb848[AUTOMATED-FLAKY-RETRYER]-->
The following jobs failed:

Test name | Triggers | Retries
--- | --- | ---
pull-knative-serving-integration-tests | [pull-knative-serving-integration-tests](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265805691369558016) | 1/3

Automatically retrying due to test flakiness...
/test pull-knative-serving-integration-tests
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265822676774031360/artifacts/line-cov.html#file1) | Do not exist | 100.0% | 
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265822676774031360/artifacts/line-cov.html#file3) | 91.8% | 93.0% | 1.2

knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-integration-tests | 73908ac20e2d0f8c5c0e89370b5e230889cdb848 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265805691369558016) | `/test pull-knative-serving-integration-tests`
pull-knative-serving-unit-tests | 675592adcdbf59c8a3a66614fa1a2a0a51846e2b | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265822676774031362) | `/test pull-knative-serving-unit-tests`

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

<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 -->
knative-test-reporter-robot: <!--[AUTOMATED-FLAKY-RETRYER]675592adcdbf59c8a3a66614fa1a2a0a51846e2b[AUTOMATED-FLAKY-RETRYER]-->
The following jobs failed:

Test name | Triggers | Retries
--- | --- | ---
pull-knative-serving-unit-tests |  | 0/3

Failed non-flaky tests preventing automatic retry of pull-knative-serving-unit-tests:

```
pkg/apis/autoscaling/v1alpha1.TestTypicalFlow
pkg/reconciler/autoscaling/kpa.TestReconcile
pkg/reconciler/autoscaling/kpa.TestReconcile/sks_does_not_exist
pkg/reconciler/autoscaling/kpa.TestReconcile/want=-1,_underscaled,_PA_inactive
pkg/reconciler/autoscaling/kpa.TestReconcile/scaled-to-0-no-scale-data
```
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265825948222099456/artifacts/line-cov.html#file1) | Do not exist | 100.0% | 
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265825948222099456/artifacts/line-cov.html#file3) | 91.8% | 93.9% | 2.1

knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265827333177085952/artifacts/line-cov.html#file1) | Do not exist | 100.0% | 
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265827333177085952/artifacts/line-cov.html#file3) | 91.8% | 93.0% | 1.2

knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-integration-tests | 73908ac20e2d0f8c5c0e89370b5e230889cdb848 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265805691369558016) | `/test pull-knative-serving-integration-tests`
pull-knative-serving-unit-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265828968225837058) | `/test pull-knative-serving-unit-tests`

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

<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 -->
knative-test-reporter-robot: <!--[AUTOMATED-FLAKY-RETRYER]d860c8814192a1bd8fc5ed4b02046c53ad5550f4[AUTOMATED-FLAKY-RETRYER]-->
The following jobs failed:

Test name | Triggers | Retries
--- | --- | ---
pull-knative-serving-unit-tests |  | 0/3

Failed non-flaky tests preventing automatic retry of pull-knative-serving-unit-tests:

```
pkg/apis/autoscaling/v1alpha1.TestTypicalFlow
pkg/reconciler/autoscaling/kpa.TestReconcile
pkg/reconciler/autoscaling/kpa.TestReconcile/sks_does_not_exist
pkg/reconciler/autoscaling/kpa.TestReconcile/want=-1,_underscaled,_PA_inactive
pkg/reconciler/autoscaling/kpa.TestReconcile/scaled-to-0-no-scale-data
```
knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-integration-tests | 73908ac20e2d0f8c5c0e89370b5e230889cdb848 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265805691369558016) | `/test pull-knative-serving-integration-tests`
pull-knative-serving-unit-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265828968225837058) | `/test pull-knative-serving-unit-tests`
pull-knative-serving-build-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-build-tests/1265828968230031361) | `/test pull-knative-serving-build-tests`

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

<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 -->
knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-unit-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265828968225837058) | `/test pull-knative-serving-unit-tests`
pull-knative-serving-build-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-build-tests/1265828968230031361) | `/test pull-knative-serving-build-tests`
pull-knative-serving-integration-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265828968230031362) | `/test pull-knative-serving-integration-tests`

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

<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 -->
knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-unit-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265828968225837058) | `/test pull-knative-serving-unit-tests`
pull-knative-serving-build-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-build-tests/1265828968230031361) | `/test pull-knative-serving-build-tests`
pull-knative-serving-integration-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265828968230031362) | `/test pull-knative-serving-integration-tests`
pull-knative-serving-autotls-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-autotls-tests/1265828968225837057) | `/test pull-knative-serving-autotls-tests`

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

<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 -->
knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-unit-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265828968225837058) | `/test pull-knative-serving-unit-tests`
pull-knative-serving-build-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-build-tests/1265828968230031361) | `/test pull-knative-serving-build-tests`
pull-knative-serving-integration-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265828968230031362) | `/test pull-knative-serving-integration-tests`
pull-knative-serving-autotls-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-autotls-tests/1265828968225837057) | `/test pull-knative-serving-autotls-tests`
pull-knative-serving-upgrade-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-upgrade-tests/1265828968225837056) | `/test pull-knative-serving-upgrade-tests`

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

<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 -->
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265836643693105158/artifacts/line-cov.html#file1) | 91.8% | 93.0% | 1.2

knative-prow-robot: @whaught: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-build-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-build-tests/1265828968230031361) | `/test pull-knative-serving-build-tests`
pull-knative-serving-integration-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-integration-tests/1265828968230031362) | `/test pull-knative-serving-integration-tests`
pull-knative-serving-autotls-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-autotls-tests/1265828968225837057) | `/test pull-knative-serving-autotls-tests`
pull-knative-serving-upgrade-tests | d860c8814192a1bd8fc5ed4b02046c53ad5550f4 | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-upgrade-tests/1265828968225837056) | `/test pull-knative-serving-upgrade-tests`
pull-knative-serving-unit-tests | 3f6106d004dd196e0c28ab496111c359eb35591e | [link](https://prow.knative.dev/view/gcs/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-unit-tests/1265836643693105154) | `/test pull-knative-serving-unit-tests`

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

<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 -->
knative-test-reporter-robot: <!--[AUTOMATED-FLAKY-RETRYER]3f6106d004dd196e0c28ab496111c359eb35591e[AUTOMATED-FLAKY-RETRYER]-->
The following jobs failed:

Test name | Triggers | Retries
--- | --- | ---
pull-knative-serving-unit-tests |  | 0/3

Failed non-flaky tests preventing automatic retry of pull-knative-serving-unit-tests:

```
pkg/apis/autoscaling/v1alpha1.TestTypicalFlow
pkg/reconciler/autoscaling/kpa.TestReconcile
pkg/reconciler/autoscaling/kpa.TestReconcile/sks_does_not_exist
pkg/reconciler/autoscaling/kpa.TestReconcile/want=-1,_underscaled,_PA_inactive
pkg/reconciler/autoscaling/kpa.TestReconcile/scaled-to-0-no-scale-data
```
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265839790561955841/artifacts/line-cov.html#file1) | Do not exist | 100.0% | 
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265839790561955841/artifacts/line-cov.html#file3) | 91.8% | 93.9% | 2.1

knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265858915963244544/artifacts/line-cov.html#file1) | Do not exist | 100.0% | 
[pkg/reconciler/autoscaling/hpa/hpa.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265858915963244544/artifacts/line-cov.html#file2) | 97.2% | 97.1% | -0.1
[pkg/reconciler/autoscaling/kpa/kpa.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265858915963244544/artifacts/line-cov.html#file3) | 93.8% | 93.7% | -0.1
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265858915963244544/artifacts/line-cov.html#file4) | 91.8% | 93.0% | 1.2

knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/autoscaling/v1alpha1/pa_types.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265868729279844355/artifacts/line-cov.html#file1) | Do not exist | 100.0% | 
[pkg/reconciler/autoscaling/hpa/hpa.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265868729279844355/artifacts/line-cov.html#file2) | 97.2% | 97.1% | -0.1
[pkg/reconciler/autoscaling/kpa/kpa.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265868729279844355/artifacts/line-cov.html#file3) | 93.8% | 93.7% | -0.1
[pkg/reconciler/autoscaling/kpa/scaler.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/8105/pull-knative-serving-go-coverage/1265868729279844355/artifacts/line-cov.html#file4) | 91.8% | 91.4% | -0.4


Patch:
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 662e1c14d..cc54fcdb4 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -76,6 +76,7 @@ aliases:
   - vagababov
   - ZhiminXiang
   networking-reviewers:
+  - andrew-su
   - JRBANCEL
   - markusthoemmes
   - mdemirhan
diff --git a/cmd/activator/main.go b/cmd/activator/main.go
index b5b25400c..a2d0a1681 100644
--- a/cmd/activator/main.go
+++ b/cmd/activator/main.go
@@ -56,9 +56,12 @@ import (
 	activatorconfig "knative.dev/serving/pkg/activator/config"
 	activatorhandler "knative.dev/serving/pkg/activator/handler"
 	activatornet "knative.dev/serving/pkg/activator/net"
+	"knative.dev/serving/pkg/activator/util"
+	apiconfig "knative.dev/serving/pkg/apis/config"
 	"knative.dev/serving/pkg/apis/networking"
 	asmetrics "knative.dev/serving/pkg/autoscaler/metrics"
 	pkghttp "knative.dev/serving/pkg/http"
+	"knative.dev/serving/pkg/http/handler"
 	"knative.dev/serving/pkg/logging"
 	"knative.dev/serving/pkg/network"
 )
@@ -203,6 +206,12 @@ func main() {
 	// Create activation handler chain
 	// Note: innermost handlers are specified first, ie. the last handler in the chain will be executed first
 	var ah http.Handler = activatorhandler.New(ctx, throttler)
+	ah = handler.NewTimeToFirstByteTimeoutHandler(ah, "activator request timeout", func(r *http.Request) time.Duration {
+		if rev := util.RevisionFrom(r.Context()); rev != nil {
+			return time.Duration(*rev.Spec.TimeoutSeconds) * time.Second
+		}
+		return apiconfig.DefaultRevisionTimeoutSeconds * time.Second
+	})
 	ah = activatorhandler.NewRequestEventHandler(reqCh, ah)
 	ah = tracing.HTTPSpanMiddleware(ah)
 	ah = configStore.HTTPMiddleware(ah)
diff --git a/cmd/queue/main.go b/cmd/queue/main.go
index 3e547bb5a..57d06206a 100644
--- a/cmd/queue/main.go
+++ b/cmd/queue/main.go
@@ -51,6 +51,7 @@ import (
 	activatorutil "knative.dev/serving/pkg/activator/util"
 	"knative.dev/serving/pkg/apis/networking"
 	pkghttp "knative.dev/serving/pkg/http"
+	"knative.dev/serving/pkg/http/handler"
 	"knative.dev/serving/pkg/logging"
 	"knative.dev/serving/pkg/network"
 	"knative.dev/serving/pkg/queue"
@@ -62,7 +63,7 @@ const (
 	badProbeTemplate   = "unexpected probe header value: %s"
 	failingHealthcheck = "failing healthcheck"
 
-	healthURLTemplate = "http://127.0.0.1:%d"
+	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.
@@ -77,6 +78,13 @@ var (
 	readinessProbeTimeout = flag.Int("probe-period", -1, "run readiness probe with given timeout")
 )
 
+// Scaled down config to use during exec probing.
+type probeConfig struct {
+	QueueServingPort int `split_words:"true" required:"true"`
+	// DownwardAPI configuration for pod labels
+	DownwardAPILabelsPath string `split_words:"true"`
+}
+
 type config struct {
 	ContainerConcurrency   int    `split_words:"true" required:"true"`
 	QueueServingPort       int    `split_words:"true" required:"true"`
@@ -236,40 +244,35 @@ func knativeProbeHandler(healthState *health.State, prober func() bool, isAggres
 	}
 }
 
-func probeQueueHealthPath(port, timeoutSeconds int, env config) error {
-	if port <= 0 {
-		return fmt.Errorf("port must be a positive value, got %d", port)
+func probeQueueHealthPath(timeoutSeconds int, env probeConfig) error {
+	if env.QueueServingPort <= 0 {
+		return fmt.Errorf("port must be a positive value, got %d", env.QueueServingPort)
 	}
 
-	url := fmt.Sprintf(healthURLTemplate, port)
+	url := healthURLPrefix + strconv.Itoa(env.QueueServingPort)
 	timeoutDuration := readiness.PollTimeout
 	if timeoutSeconds != 0 {
 		timeoutDuration = time.Duration(timeoutSeconds) * time.Second
 	}
+
+	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{
-		Transport: &http.Transport{
-			// Do not use the cached connection
-			DisableKeepAlives: true,
-		},
 		Timeout: timeoutDuration,
 	}
 	ctx, cancel := context.WithTimeout(context.Background(), timeoutDuration)
 	defer cancel()
-	stopCh := ctx.Done()
 
 	var lastErr error
 	// 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) {
-		var req *http.Request
-		req, lastErr = http.NewRequest(http.MethodGet, url, nil)
-		if lastErr != nil {
-			// Return nil error for retrying
-			return false, nil
-		}
-		// Add the header to indicate this is a probe request.
-		req.Header.Add(network.ProbeHeaderName, queue.Name)
-		req.Header.Add(network.UserAgentKey, network.QueueProxyUserAgent)
 		res, lastErr := httpClient.Do(req)
 		if lastErr != nil {
 			// Return nil error for retrying
@@ -277,6 +280,7 @@ func probeQueueHealthPath(port, timeoutSeconds int, env config) error {
 		}
 		defer res.Body.Close()
 		success := health.IsHTTPProbeReady(res)
+
 		// The check for preferForScaledown() fails readiness faster
 		// in the presence of the label
 		if preferScaleDown, err := preferPodForScaledown(env.DownwardAPILabelsPath); err != nil {
@@ -285,7 +289,7 @@ func probeQueueHealthPath(port, timeoutSeconds int, env config) error {
 			return false, errors.New("failing probe deliberately for pod scaledown")
 		}
 		return success, nil
-	}, stopCh)
+	}, ctx.Done())
 
 	if lastErr != nil {
 		return fmt.Errorf("failed to probe: %w", lastErr)
@@ -302,16 +306,15 @@ func probeQueueHealthPath(port, timeoutSeconds int, env config) error {
 func main() {
 	flag.Parse()
 
-	// Parse the environment.
-	var env config
-	if err := envconfig.Process("", &env); err != nil {
-		fmt.Fprintln(os.Stderr, err)
-		os.Exit(1)
-	}
-
 	// If this is set, we run as a standalone binary to probe the queue-proxy.
 	if *readinessProbeTimeout >= 0 {
-		if err := probeQueueHealthPath(env.QueueServingPort, *readinessProbeTimeout, env); err != nil {
+		// Parse the environment.
+		var env probeConfig
+		if err := envconfig.Process("", &env); err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		}
+		if err := probeQueueHealthPath(*readinessProbeTimeout, env); err != nil {
 			// used instead of the logger to produce a concise event message
 			fmt.Fprintln(os.Stderr, err)
 			os.Exit(1)
@@ -319,6 +322,13 @@ func main() {
 		os.Exit(0)
 	}
 
+	// Parse the environment.
+	var env config
+	if err := envconfig.Process("", &env); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+
 	// Setup the logger.
 	logger, _ = pkglogging.NewLogger(env.ServingLoggingConfig, env.ServingLoggingLevel)
 	logger = logger.Named("queueproxy")
@@ -350,7 +360,11 @@ func main() {
 	defer reportTicker.Stop()
 
 	stats := network.NewRequestStats(time.Now())
-	go queue.ReportStats(time.Now(), stats, reportTicker.C, promStatReporter.Report)
+	go func() {
+		for now := range reportTicker.C {
+			promStatReporter.Report(stats.Report(now))
+		}
+	}()
 
 	// Setup probe to run for checking user-application healthiness.
 	probe := buildProbe(env.ServingReadinessProbe)
@@ -440,6 +454,7 @@ func buildServer(env config, healthState *health.State, rp *readiness.Probe, sta
 	breaker := buildBreaker(env)
 	metricsSupported := supportsMetrics(env, logger)
 	tracingEnabled := env.TracingConfigBackend != tracingconfig.None
+	timeout := time.Duration(env.RevisionTimeoutSeconds) * time.Second
 
 	// Create queue handler chain.
 	// Note: innermost handlers are specified first, ie. the last handler in the chain will be executed first.
@@ -449,9 +464,9 @@ func buildServer(env config, healthState *health.State, rp *readiness.Probe, sta
 	}
 	composedHandler = proxyHandler(breaker, stats, tracingEnabled, composedHandler)
 	composedHandler = queue.ForwardedShimHandler(composedHandler)
-	composedHandler = queue.TimeToFirstByteTimeoutHandler(composedHandler,
-		time.Duration(env.RevisionTimeoutSeconds)*time.Second, "request timeout")
-	composedHandler = pushRequestLogHandler(composedHandler, env)
+	composedHandler = handler.NewTimeToFirstByteTimeoutHandler(composedHandler, "request timeout", func(*http.Request) time.Duration {
+		return timeout
+	})
 
 	if metricsSupported {
 		composedHandler = requestMetricsHandler(composedHandler, env)
@@ -460,6 +475,9 @@ func buildServer(env config, healthState *health.State, rp *readiness.Probe, sta
 
 	composedHandler = knativeProbeHandler(healthState, rp.ProbeContainer, rp.IsAggressive(), tracingEnabled, composedHandler, env, logger)
 	composedHandler = network.NewProbeHandler(composedHandler)
+	// We might want sometimes capture the probes/healthchecks in the request
+	// logs. Hence we need to have RequestLogHandler to be the first one.
+	composedHandler = pushRequestLogHandler(composedHandler, env)
 
 	return pkgnet.NewServer(":"+strconv.Itoa(env.QueueServingPort), composedHandler)
 }
@@ -549,7 +567,6 @@ func pushRequestLogHandler(currentHandler http.Handler, env config) http.Handler
 	}
 	handler, err := pkghttp.NewRequestLogHandler(currentHandler, logging.NewSyncFileWriter(os.Stdout), env.ServingRequestLogTemplate,
 		pkghttp.RequestLogTemplateInputGetterFromRevision(revInfo), env.ServingEnableProbeRequestLog)
-
 	if err != nil {
 		logger.Errorw("Error setting up request logger. Request logs will be unavailable.", zap.Error(err))
 		return currentHandler
diff --git a/config/config-features.yaml b/config/config-features.yaml
new file mode 120000
index 000000000..864ceb031
--- /dev/null
+++ b/config/config-features.yaml
@@ -0,0 +1,1 @@
+core/configmaps/features.yaml
\ No newline at end of file
diff --git a/config/core/configmaps/autoscaler.yaml b/config/core/configmaps/autoscaler.yaml
index c6df8d70d..aba6995d6 100644
--- a/config/core/configmaps/autoscaler.yaml
+++ b/config/core/configmaps/autoscaler.yaml
@@ -106,8 +106,9 @@ data:
     # enters panic mode. When operating in panic mode, the autoscaler
     # scales on the average concurrency over the panic window which is
     # panic-window-percentage of the stable-window.
+    # Must be in the [1, 100] range.
     # When computing the panic window it will be rounded to the closest
-    # whole second.
+    # whole second, at least 1s.
     panic-window-percentage: "10.0"
 
     # The percentage of the container concurrency target at which to
diff --git a/config/core/configmaps/defaults.yaml b/config/core/configmaps/defaults.yaml
index 21dd61bb2..41af44219 100644
--- a/config/core/configmaps/defaults.yaml
+++ b/config/core/configmaps/defaults.yaml
@@ -58,6 +58,11 @@ data:
     # and the system default is used.
     revision-memory-request: "100M"  # 100 megabytes of memory
 
+    # revision-ephemeral-storage-request contains the ephemeral storage
+    # allocation to assign to revisions by default.  If omitted, no value is
+    # specified and the system default is used.
+    revision-ephemeral-storage-request: "500M"  # 500 megabytes of storage
+
     # revision-cpu-limit contains the cpu allocation to limit
     # revisions to by default.  If omitted, no value is specified
     # and the system default is used.
@@ -68,6 +73,11 @@ data:
     # and the system default is used.
     revision-memory-limit: "200M"  # 200 megabytes of memory
 
+    # revision-ephemeral-storage-limit contains the ephemeral storage
+    # allocation to limit revisions to by default.  If omitted, no value is
+    # specified and the system default is used.
+    revision-ephemeral-storage-limit: "750M"  # 750 megabytes of storage
+
     # container-name-template contains a template for the default
     # container name, if none is specified.  This field supports
     # Go templating and is supplied with the ObjectMeta of the
diff --git a/go.mod b/go.mod
index 01bcda4f4..f4d3a070d 100644
--- a/go.mod
+++ b/go.mod
@@ -30,6 +30,7 @@ require (
 	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 	golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a
+	golang.org/x/time v0.0.0-20191024005414-555d28b269f0
 	google.golang.org/api v0.20.0
 	google.golang.org/grpc v1.28.0
 	istio.io/api v0.0.0-20191115173247-e1a1952e5b81
@@ -42,8 +43,8 @@ require (
 	k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
 	k8s.io/metrics v0.17.6
 	knative.dev/caching v0.0.0-20200521155757-e78d17bc250e
-	knative.dev/pkg v0.0.0-20200527173759-2d1a04d1ff82
-	knative.dev/test-infra v0.0.0-20200527185659-fc87694eb879
+	knative.dev/pkg v0.0.0-20200528190300-08a86da47d28
+	knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e
 )
 
 // pin the older grpc - see: https://github.com/grpc/grpc-go/issues/3180
diff --git a/go.sum b/go.sum
index fcb33da85..4feb2f05d 100644
--- a/go.sum
+++ b/go.sum
@@ -1321,8 +1321,8 @@ knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7/go.mod h1:QgNZTxnwpB/oSpNcfnL
 knative.dev/pkg v0.0.0-20200520073958-94316e20e860/go.mod h1:QgNZTxnwpB/oSpNcfnLVlw+WpEwwyKAvJlvR3hgeltA=
 knative.dev/pkg v0.0.0-20200527024749-495174c96651 h1:/LhCktTMhJrCDXGg3KCWeSQTLLGy3Ms4AaqM9O/05dI=
 knative.dev/pkg v0.0.0-20200527024749-495174c96651/go.mod h1:4ipprwHqpqiyYHbrEjSf1kNwL+sJOqHhj1ujO2WxvpE=
-knative.dev/pkg v0.0.0-20200527173759-2d1a04d1ff82 h1:uC65bOUmC5UsVJgUI28QWis/oiqnZrU49wLM828ioJM=
-knative.dev/pkg v0.0.0-20200527173759-2d1a04d1ff82/go.mod h1:ywZfX/0D8hoOf4uJVgeEvJpSmsOauQvr1IuAWld9UjM=
+knative.dev/pkg v0.0.0-20200528190300-08a86da47d28 h1:tLWWfrpGYT8vs/QLWYc7s0pqaw+ISz4UmM9AhrWBc8o=
+knative.dev/pkg v0.0.0-20200528190300-08a86da47d28/go.mod h1:ywZfX/0D8hoOf4uJVgeEvJpSmsOauQvr1IuAWld9UjM=
 knative.dev/test-infra v0.0.0-20200407185800-1b88cb3b45a5/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ=
 knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxPZ20keR2zCNtiQA1MP9ZB4BH4HuI+SIU=
 knative.dev/test-infra v0.0.0-20200513011557-d03429a76034 h1:JxqONCZVS7or+Fv3ebVQoipuIBH7Ig3Qbx170hgIF+A=
@@ -1333,8 +1333,8 @@ knative.dev/test-infra v0.0.0-20200519161858-554a95a37986 h1:ZDy43jkWPQ75d4l4DGy
 knative.dev/test-infra v0.0.0-20200519161858-554a95a37986/go.mod h1:LeNa1Wvn47efeQUkpkn3XG7Fx9Ga+rhAP13SZyjaEGg=
 knative.dev/test-infra v0.0.0-20200522180958-6a0a9b9d893a h1:c0qTABRcNoxZVu5gsryLWPZtGa/s4zsvovz0nGefuzg=
 knative.dev/test-infra v0.0.0-20200522180958-6a0a9b9d893a/go.mod h1:n9eQkzmSNj8BiqNFl1lzoz68D09uMeJfyOjc132Gbik=
-knative.dev/test-infra v0.0.0-20200527185659-fc87694eb879 h1:3spi67ya78+ofPZLHpJkZlBSj6pBowXa8/1Zdha6MCY=
-knative.dev/test-infra v0.0.0-20200527185659-fc87694eb879/go.mod h1:7JtOmoYiYxh2oFO23nwGanuJ6qT6mFrRlZV1LL6gomY=
+knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e h1:ZzmzPgCKdrFg2MA2sGtd9HrlIQ7XidnmMJB8RDEduO0=
+knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e/go.mod h1:7JtOmoYiYxh2oFO23nwGanuJ6qT6mFrRlZV1LL6gomY=
 modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
diff --git a/hack/update-deps.sh b/hack/update-deps.sh
index b277dd3ff..5e5001b3f 100755
--- a/hack/update-deps.sh
+++ b/hack/update-deps.sh
@@ -62,8 +62,8 @@ go mod vendor
 echo "Applying patches"
 git apply ${REPO_ROOT_DIR}/hack/patches/*.patch
 
-rm -rf $(find vendor/ -name 'OWNERS')
-rm -rf $(find vendor/ -name '*_test.go')
+# Remove unwanted vendor files
+find vendor/ \( -name "OWNERS" -o -name "*_test.go" \) -print0 | xargs -0 rm -f
 
 export GOFLAGS=-mod=vendor
 
diff --git a/hack/update-k8s-deps.sh b/hack/update-k8s-deps.sh
index 2190eb56a..698f80a4a 100755
--- a/hack/update-k8s-deps.sh
+++ b/hack/update-k8s-deps.sh
@@ -57,6 +57,7 @@ OPENAPI_SHA=$(curl -L "https://api.github.com/repos/kubernetes/kube-openapi/git/
 
 update_module "k8s.io/kube-openapi" "${OPENAPI_SHA}"
 
+# See: https://github.com/kubernetes-sigs/custom-metrics-apiserver/issues/67
 echo "YOU MANUALLY NEED TO BUMP github.com/kubernetes-incubator/custom-metrics-apiserver"
 
 ./hack/update-deps.sh
diff --git a/pkg/activator/net/lb_policy.go b/pkg/activator/net/lb_policy.go
new file mode 100644
index 000000000..3c6025b74
--- /dev/null
+++ b/pkg/activator/net/lb_policy.go
@@ -0,0 +1,48 @@
+/*
+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.
+*/
+
+// This file contains the load load balancing policies for Activator load balancing.
+
+package net
+
+import (
+	"context"
+	"math/rand"
+)
+
+// lbPolicy is a functor that selects a target pod from the list, or (noop, nil) if
+// no such target can be currently acquired.
+// Policies will presume that `targets` list is appropriately guarded by the caller,
+// that is while podTrackers themselves can change during this call, the list
+// and pointers therein are immutable.
+type lbPolicy func(ctx context.Context, targets []*podTracker) (func(), *podTracker)
+
+// randomLBPolicy is a load balancer policy that picks a random target.
+// This approximates the LB policy done by K8s Service (IPTables based).
+func randomLBPolicy(_ context.Context, targets []*podTracker) (func(), *podTracker) {
+	return noop, targets[rand.Intn(len(targets))]
+}
+
+// firstAvailableLBPolicy is a load balancer policy, that picks the first target
+// that has capacity to serve the request right now.
+func firstAvailableLBPolicy(ctx context.Context, targets []*podTracker) (func(), *podTracker) {
+	for _, t := range targets {
+		if cb, ok := t.Reserve(ctx); ok {
+			return cb, t
+		}
+	}
+	return noop, nil
+}
diff --git a/pkg/activator/net/throttler.go b/pkg/activator/net/throttler.go
index d572d2df6..f3dd23fc9 100644
--- a/pkg/activator/net/throttler.go
+++ b/pkg/activator/net/throttler.go
@@ -107,6 +107,7 @@ type breaker interface {
 type revisionThrottler struct {
 	revID                types.NamespacedName
 	containerConcurrency int
+	lbPolicy             lbPolicy
 
 	// These are used in slicing to infer which pods to assign
 	// to this activator.
@@ -148,11 +149,16 @@ func newRevisionThrottler(revID types.NamespacedName,
 	breakerParams queue.BreakerParams,
 	logger *zap.SugaredLogger) *revisionThrottler {
 	logger = logger.With(zap.Object(logkey.Key, logging.NamespacedName(revID)))
-	var revBreaker breaker
+	var (
+		revBreaker breaker
+		lbp        lbPolicy
+	)
 	if containerConcurrency == 0 {
 		revBreaker = newInfiniteBreaker(logger)
+		lbp = randomLBPolicy
 	} else {
 		revBreaker = queue.NewBreaker(breakerParams)
+		lbp = firstAvailableLBPolicy
 	}
 	return &revisionThrottler{
 		revID:                revID,
@@ -161,29 +167,12 @@ func newRevisionThrottler(revID types.NamespacedName,
 		logger:               logger,
 		protocol:             proto,
 		activatorIndex:       -1, // Start with unknown.
+		lbPolicy:             lbp,
 	}
 }
 
 func noop() {}
 
-// pickPod picks the first tracker that has open capacity if container concurrency
-// if limited, random pod otherwise.
-func pickPod(ctx context.Context, tgs []*podTracker, cc int) (func(), *podTracker) {
-	// Infinite capacity, pick random. We have to do this
-	// otherwise _all_ the requests will go to the first pod
-	// since it has unlimited capacity.
-	if cc == 0 {
-		return noop, tgs[rand.Intn(len(tgs))]
-	}
-
-	for _, t := range tgs {
-		if cb, ok := t.Reserve(ctx); ok {
-			return cb, t
-		}
-	}
-	return noop, nil
-}
-
 // Returns a dest that at the moment of choosing had an open slot
 // for request.
 func (rt *revisionThrottler) acquireDest(ctx context.Context) (func(), *podTracker) {
@@ -193,7 +182,7 @@ func (rt *revisionThrottler) acquireDest(ctx context.Context) (func(), *podTrack
 	if rt.clusterIPTracker != nil {
 		return noop, rt.clusterIPTracker
 	}
-	return pickPod(ctx, rt.assignedTrackers, rt.containerConcurrency)
+	return rt.lbPolicy(ctx, rt.assignedTrackers)
 }
 
 func (rt *revisionThrottler) try(ctx context.Context, function func(string) error) error {
diff --git a/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go b/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go
index 327d06612..c0f48dfa4 100644
--- a/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go
+++ b/pkg/apis/autoscaling/v1alpha1/pa_lifecycle.go
@@ -146,23 +146,27 @@ func (pa *PodAutoscaler) PanicThresholdPercentage() (percentage float64, ok bool
 	return pa.annotationFloat64(autoscaling.PanicThresholdPercentageAnnotationKey)
 }
 
-// IsReady looks at the conditions and if the Status has a condition
-// PodAutoscalerConditionReady returns true if ConditionStatus is True
-func (pas *PodAutoscalerStatus) IsReady() bool {
-	return podCondSet.Manage(pas).IsHappy()
+// IsReady returns true if the Status condition PodAutoscalerConditionReady
+// is true and the latest spec has been observed.
+func (pa *PodAutoscaler) IsReady() bool {
+	pas := pa.Status
+	return pa.Generation == pas.ObservedGeneration && podCondSet.Manage(&pas).IsHappy()
+}
+
+// IsActive returns true if the pod autoscaler is finished scaling.
+func (pas *PodAutoscalerStatus) IsActive() bool {
+	return pas.GetCondition(PodAutoscalerConditionActive).IsTrue()
 }
 
 // IsActivating returns true if the pod autoscaler is Activating if it is neither
-// Active nor Inactive
+// Active nor Inactive.
 func (pas *PodAutoscalerStatus) IsActivating() bool {
-	cond := pas.GetCondition(PodAutoscalerConditionActive)
-	return cond != nil && cond.Status == corev1.ConditionUnknown
+	return pas.GetCondition(PodAutoscalerConditionActive).IsUnknown()
 }
 
 // IsInactive returns true if the pod autoscaler is Inactive.
 func (pas *PodAutoscalerStatus) IsInactive() bool {
-	cond := pas.GetCondition(PodAutoscalerConditionActive)
-	return cond != nil && cond.Status == corev1.ConditionFalse
+	return pas.GetCondition(PodAutoscalerConditionActive).IsFalse()
 }
 
 // GetCondition gets the condition `t`.
diff --git a/pkg/apis/config/defaults.go b/pkg/apis/config/defaults.go
index a458e71fd..214e73641 100644
--- a/pkg/apis/config/defaults.go
+++ b/pkg/apis/config/defaults.go
@@ -83,10 +83,12 @@ func NewDefaultsConfigFromMap(data map[string]string) (*Defaults, error) {
 		cm.AsInt64("container-concurrency", &nc.ContainerConcurrency),
 		cm.AsInt64("container-concurrency-max-limit", &nc.ContainerConcurrencyMaxLimit),
 
-		asQuantity("revision-cpu-request", &nc.RevisionCPURequest),
-		asQuantity("revision-memory-request", &nc.RevisionMemoryRequest),
-		asQuantity("revision-cpu-limit", &nc.RevisionCPULimit),
-		asQuantity("revision-memory-limit", &nc.RevisionMemoryLimit),
+		cm.AsQuantity("revision-cpu-request", &nc.RevisionCPURequest),
+		cm.AsQuantity("revision-memory-request", &nc.RevisionMemoryRequest),
+		cm.AsQuantity("revision-ephemeral-storage-request", &nc.RevisionEphemeralStorageRequest),
+		cm.AsQuantity("revision-cpu-limit", &nc.RevisionCPULimit),
+		cm.AsQuantity("revision-memory-limit", &nc.RevisionMemoryLimit),
+		cm.AsQuantity("revision-ephemeral-storage-limit", &nc.RevisionEphemeralStorageLimit),
 	); err != nil {
 		return nil, err
 	}
@@ -139,10 +141,12 @@ type Defaults struct {
 	// a containerConcurrency of 0 (i.e. unbounded).
 	AllowContainerConcurrencyZero bool
 
-	RevisionCPURequest    *resource.Quantity
-	RevisionCPULimit      *resource.Quantity
-	RevisionMemoryRequest *resource.Quantity
-	RevisionMemoryLimit   *resource.Quantity
+	RevisionCPURequest              *resource.Quantity
+	RevisionCPULimit                *resource.Quantity
+	RevisionMemoryRequest           *resource.Quantity
+	RevisionMemoryLimit             *resource.Quantity
+	RevisionEphemeralStorageRequest *resource.Quantity
+	RevisionEphemeralStorageLimit   *resource.Quantity
 }
 
 // UserContainerName returns the name of the user container based on the context.
@@ -155,17 +159,3 @@ func (d *Defaults) UserContainerName(ctx context.Context) string {
 	}
 	return buf.String()
 }
-
-// asQuantity parses the value at key as a *resource.Quantity into the target, if it exists.
-func asQuantity(key string, target **resource.Quantity) cm.ParseFunc {
-	return func(data map[string]string) error {
-		if raw, ok := data[key]; !ok {
-			*target = nil
-		} else if val, err := resource.ParseQuantity(raw); err != nil {
-			return err
-		} else {
-			*target = &val
-		}
-		return nil
-	}
-}
diff --git a/pkg/apis/config/zz_generated.deepcopy.go b/pkg/apis/config/zz_generated.deepcopy.go
index 484d01ca3..bc124553d 100644
--- a/pkg/apis/config/zz_generated.deepcopy.go
+++ b/pkg/apis/config/zz_generated.deepcopy.go
@@ -43,6 +43,16 @@ func (in *Defaults) DeepCopyInto(out *Defaults) {
 		x := (*in).DeepCopy()
 		*out = &x
 	}
+	if in.RevisionEphemeralStorageRequest != nil {
+		in, out := &in.RevisionEphemeralStorageRequest, &out.RevisionEphemeralStorageRequest
+		x := (*in).DeepCopy()
+		*out = &x
+	}
+	if in.RevisionEphemeralStorageLimit != nil {
+		in, out := &in.RevisionEphemeralStorageLimit, &out.RevisionEphemeralStorageLimit
+		x := (*in).DeepCopy()
+		*out = &x
+	}
 	return
 }
 
diff --git a/pkg/apis/networking/v1alpha1/ingress_types.go b/pkg/apis/networking/v1alpha1/ingress_types.go
index 607249fd4..c004cb095 100644
--- a/pkg/apis/networking/v1alpha1/ingress_types.go
+++ b/pkg/apis/networking/v1alpha1/ingress_types.go
@@ -221,6 +221,14 @@ type HTTPIngressPath struct {
 	// If RewriteHost is specified, Splits must not be.
 	RewriteHost string `json:"rewriteHost,omitempty"`
 
+	// Headers defines header matching rules which is a map from a header name
+	// to HeaderMatch which specify a matching condition.
+	// When a request matched with all the header matching rules,
+	// the request is routed by the corresponding ingress rule.
+	// If it is empty, the headers are not used for matching
+	// +optional
+	Headers map[string]HeaderMatch `json:"headers,omitempty"`
+
 	// Splits defines the referenced service endpoints to which the traffic
 	// will be forwarded to.
 	//
@@ -361,3 +369,9 @@ const (
 func (t *Ingress) GetStatus() *duckv1.Status {
 	return &t.Status.Status
 }
+
+// HeaderMatch represents a matching value of Headers in HTTPIngressPath.
+// Currently, only the exact matching is supported.
+type HeaderMatch struct {
+	Exact string `json:"exact"`
+}
diff --git a/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go
index 0f4641d8b..bd179bb46 100644
--- a/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/networking/v1alpha1/zz_generated.deepcopy.go
@@ -161,6 +161,13 @@ func (in *HTTP01Challenge) DeepCopy() *HTTP01Challenge {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *HTTPIngressPath) DeepCopyInto(out *HTTPIngressPath) {
 	*out = *in
+	if in.Headers != nil {
+		in, out := &in.Headers, &out.Headers
+		*out = make(map[string]HeaderMatch, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
 	if in.Splits != nil {
 		in, out := &in.Splits, &out.Splits
 		*out = make([]IngressBackendSplit, len(*in))
@@ -242,6 +249,22 @@ func (in *HTTPRetry) DeepCopy() *HTTPRetry {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HeaderMatch) DeepCopyInto(out *HeaderMatch) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HeaderMatch.
+func (in *HeaderMatch) DeepCopy() *HeaderMatch {
+	if in == nil {
+		return nil
+	}
+	out := new(HeaderMatch)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Ingress) DeepCopyInto(out *Ingress) {
 	*out = *in
diff --git a/pkg/apis/serving/v1/revision_defaults.go b/pkg/apis/serving/v1/revision_defaults.go
index 0849af374..224288f61 100644
--- a/pkg/apis/serving/v1/revision_defaults.go
+++ b/pkg/apis/serving/v1/revision_defaults.go
@@ -22,6 +22,7 @@ import (
 	"github.com/google/uuid"
 
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/resource"
 	"knative.dev/pkg/apis"
 	"knative.dev/pkg/kmeta"
 	"knative.dev/pkg/ptr"
@@ -69,28 +70,33 @@ func (rs *RevisionSpec) applyDefault(container *corev1.Container, cfg *config.Co
 	if container.Resources.Requests == nil {
 		container.Resources.Requests = corev1.ResourceList{}
 	}
-	if _, ok := container.Resources.Requests[corev1.ResourceCPU]; !ok {
-		if rc := cfg.Defaults.RevisionCPURequest; rc != nil {
-			container.Resources.Requests[corev1.ResourceCPU] = *rc
-		}
-	}
-	if _, ok := container.Resources.Requests[corev1.ResourceMemory]; !ok {
-		if rm := cfg.Defaults.RevisionMemoryRequest; rm != nil {
-			container.Resources.Requests[corev1.ResourceMemory] = *rm
-		}
-	}
 
 	if container.Resources.Limits == nil {
 		container.Resources.Limits = corev1.ResourceList{}
 	}
-	if _, ok := container.Resources.Limits[corev1.ResourceCPU]; !ok {
-		if rc := cfg.Defaults.RevisionCPULimit; rc != nil {
-			container.Resources.Limits[corev1.ResourceCPU] = *rc
+
+	for _, r := range []struct {
+		Name    corev1.ResourceName
+		Request *resource.Quantity
+		Limit   *resource.Quantity
+	}{{
+		Name:    corev1.ResourceCPU,
+		Request: cfg.Defaults.RevisionCPURequest,
+		Limit:   cfg.Defaults.RevisionCPULimit,
+	}, {
+		Name:    corev1.ResourceMemory,
+		Request: cfg.Defaults.RevisionMemoryRequest,
+		Limit:   cfg.Defaults.RevisionMemoryLimit,
+	}, {
+		Name:    corev1.ResourceEphemeralStorage,
+		Request: cfg.Defaults.RevisionEphemeralStorageRequest,
+		Limit:   cfg.Defaults.RevisionEphemeralStorageLimit,
+	}} {
+		if _, ok := container.Resources.Requests[r.Name]; !ok && r.Request != nil {
+			container.Resources.Requests[r.Name] = *r.Request
 		}
-	}
-	if _, ok := container.Resources.Limits[corev1.ResourceMemory]; !ok {
-		if rm := cfg.Defaults.RevisionMemoryLimit; rm != nil {
-			container.Resources.Limits[corev1.ResourceMemory] = *rm
+		if _, ok := container.Resources.Limits[r.Name]; !ok && r.Limit != nil {
+			container.Resources.Limits[r.Name] = *r.Limit
 		}
 	}
 
diff --git a/pkg/autoscaler/config/config.go b/pkg/autoscaler/config/config.go
index 9ba594278..288286ab9 100644
--- a/pkg/autoscaler/config/config.go
+++ b/pkg/autoscaler/config/config.go
@@ -200,9 +200,12 @@ func validate(lc *Config) (*Config, error) {
 		return nil, fmt.Errorf("stable-window = %v, must be specified with at most second precision", lc.StableWindow)
 	}
 
-	effPW := time.Duration(lc.PanicWindowPercentage / 100 * float64(lc.StableWindow))
-	if effPW < BucketSize || effPW > lc.StableWindow {
-		return nil, fmt.Errorf("panic-window-percentage = %v, must be in [%v, 100] interval", lc.PanicWindowPercentage, 100*float64(BucketSize)/float64(lc.StableWindow))
+	// We ensure BucketSize in the `MakeMetric`, so just ensure percentage is in the correct region.
+	if lc.PanicWindowPercentage < autoscaling.PanicWindowPercentageMin ||
+		lc.PanicWindowPercentage > autoscaling.PanicWindowPercentageMax {
+		return nil, fmt.Errorf("panic-window-percentage = %v, must be in [%v, %v] interval",
+			lc.PanicWindowPercentage, autoscaling.PanicWindowPercentageMin, autoscaling.PanicWindowPercentageMax)
+
 	}
 
 	if lc.InitialScale < 0 || (lc.InitialScale == 0 && !lc.AllowZeroInitialScale) {
diff --git a/pkg/autoscaler/fake/fake_metric_client.go b/pkg/autoscaler/fake/fake_metric_client.go
index 17ffe5037..9454fa2af 100644
--- a/pkg/autoscaler/fake/fake_metric_client.go
+++ b/pkg/autoscaler/fake/fake_metric_client.go
@@ -67,32 +67,29 @@ func (mtp *ManualTickProvider) NewTicker(time.Duration) *time.Ticker {
 	}
 }
 
+// SetStableAndPanicConcurrency sets the stable and panic concurrencies.
+func (mc *MetricClient) SetStableAndPanicConcurrency(s, p float64) {
+	mc.StableConcurrency, mc.PanicConcurrency = s, p
+}
+
 // StableAndPanicConcurrency returns stable/panic concurrency stored in the object
 // and the result of Errf as the error.
-func (t *MetricClient) StableAndPanicConcurrency(key types.NamespacedName, now time.Time) (float64, float64, error) {
+func (mc *MetricClient) StableAndPanicConcurrency(key types.NamespacedName, now time.Time) (float64, float64, error) {
 	var err error
-	if t.ErrF != nil {
-		err = t.ErrF(key, now)
+	if mc.ErrF != nil {
+		err = mc.ErrF(key, now)
 	}
-	return t.StableConcurrency, t.PanicConcurrency, err
+	return mc.StableConcurrency, mc.PanicConcurrency, err
 }
 
 // StableAndPanicRPS returns stable/panic RPS stored in the object
 // and the result of Errf as the error.
-func (t *MetricClient) StableAndPanicRPS(key types.NamespacedName, now time.Time) (float64, float64, error) {
+func (mc *MetricClient) StableAndPanicRPS(key types.NamespacedName, now time.Time) (float64, float64, error) {
 	var err error
-	if t.ErrF != nil {
-		err = t.ErrF(key, now)
+	if mc.ErrF != nil {
+		err = mc.ErrF(key, now)
 	}
-	return t.StableRPS, t.PanicRPS, err
-}
-
-// StaticMetricClient returns stable/panic concurrency and RPS with static value, i.e. 10.
-var StaticMetricClient = MetricClient{
-	StableConcurrency: 10.0,
-	PanicConcurrency:  10.0,
-	StableRPS:         10.0,
-	PanicRPS:          10.0,
+	return mc.StableRPS, mc.PanicRPS, err
 }
 
 // Endpoints is used to create endpoints.
diff --git a/pkg/autoscaler/scaling/autoscaler.go b/pkg/autoscaler/scaling/autoscaler.go
index a6c013375..31eb7ed90 100644
--- a/pkg/autoscaler/scaling/autoscaler.go
+++ b/pkg/autoscaler/scaling/autoscaler.go
@@ -200,6 +200,9 @@ func (a *Autoscaler) Scale(ctx context.Context, now time.Time) ScaleResult {
 		logger.Info("PANICKING.")
 		a.panicTime = now
 		pkgmetrics.Record(a.reporterCtx, panicM.M(1))
+	} else if isOverPanicThreshold {
+		// If we're still over panic threshold right now — extend the panic window.
+		a.panicTime = now
 	} else if !a.panicTime.IsZero() && !isOverPanicThreshold && a.panicTime.Add(spec.StableWindow).Before(now) {
 		// Stop panicking after the surge has made its way into the stable metric.
 		logger.Info("Un-panicking.")
@@ -210,14 +213,19 @@ func (a *Autoscaler) Scale(ctx context.Context, now time.Time) ScaleResult {
 
 	desiredPodCount := desiredStablePodCount
 	if !a.panicTime.IsZero() {
+		// In some edgecases stable window metric might be larger
+		// than panic one. And we should provision for stable as for panic,
+		// so pick the larger of the two.
+		if desiredPodCount < desiredPanicPodCount {
+			desiredPodCount = desiredPanicPodCount
+		}
 		logger.Debug("Operating in panic mode.")
 		// We do not scale down while in panic mode. Only increases will be applied.
-		if desiredPanicPodCount > a.maxPanicPods {
-			logger.Infof("Increasing pods from %d to %d.", originalReadyPodsCount, desiredPanicPodCount)
-			a.panicTime = now
-			a.maxPanicPods = desiredPanicPodCount
-		} else if desiredPanicPodCount < a.maxPanicPods {
-			logger.Infof("Skipping decrease from %d to %d.", a.maxPanicPods, desiredPanicPodCount)
+		if desiredPodCount > a.maxPanicPods {
+			logger.Infof("Increasing pods from %d to %d.", originalReadyPodsCount, desiredPodCount)
+			a.maxPanicPods = desiredPodCount
+		} else if desiredPodCount < a.maxPanicPods {
+			logger.Infof("Skipping decrease from %d to %d.", a.maxPanicPods, desiredPodCount)
 		}
 		desiredPodCount = a.maxPanicPods
 	} else {
diff --git a/pkg/queue/timeout.go b/pkg/http/handler/timeout.go
similarity index 83%
rename from pkg/queue/timeout.go
rename to pkg/http/handler/timeout.go
index de5274fe2..09efbeb52 100644
--- a/pkg/queue/timeout.go
+++ b/pkg/http/handler/timeout.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2018 The Knative Authors
+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.
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package queue
+package handler
 
 import (
 	"bufio"
@@ -28,8 +28,18 @@ import (
 	"knative.dev/pkg/websocket"
 )
 
-// TimeToFirstByteTimeoutHandler returns a Handler that runs `h` with the
-// given time limit in which the first byte of the response must be written.
+// TimeoutFunc returns the timeout duration to be used by the timeout handler.
+type TimeoutFunc func(req *http.Request) time.Duration
+
+type timeToFirstByteTimeoutHandler struct {
+	handler     http.Handler
+	timeoutFunc TimeoutFunc
+	body        string
+}
+
+// NewTimeToFirstByteTimeoutHandler returns a Handler that runs `h` with the
+// given time limit from the timeout function in which the first byte of
+// the response must be written.
 //
 // The new Handler calls h.ServeHTTP to handle each request, but if a
 // call runs for longer than its time limit, the handler responds with
@@ -43,28 +53,21 @@ import (
 // https://golang.org/pkg/net/http/#Handler.
 //
 // The implementation is largely inspired by http.TimeoutHandler.
-func TimeToFirstByteTimeoutHandler(h http.Handler, dt time.Duration, msg string) http.Handler {
-	return &timeoutHandler{
-		handler: h,
-		body:    msg,
-		timeout: dt,
+func NewTimeToFirstByteTimeoutHandler(h http.Handler, msg string, timeoutFunc TimeoutFunc) http.Handler {
+	return &timeToFirstByteTimeoutHandler{
+		handler:     h,
+		body:        msg,
+		timeoutFunc: timeoutFunc,
 	}
 }
 
-type timeoutHandler struct {
-	handler http.Handler
-	body    string
-	timeout time.Duration
-}
-
-func (h *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+func (h *timeToFirstByteTimeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	ctx, cancel := context.WithCancel(r.Context())
 	defer cancel()
 
 	// done is closed when h.handler.ServeHTTP completes and contains
 	// the panic from h.handler.ServeHTTP if h.handler.ServeHTTP panics.
 	done := make(chan interface{})
-
 	tw := &timeoutWriter{w: w}
 	go func() {
 		defer func() {
@@ -76,7 +79,7 @@ func (h *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		h.handler.ServeHTTP(tw, r.WithContext(ctx))
 	}()
 
-	timeout := time.NewTimer(h.timeout)
+	timeout := time.NewTimer(h.timeoutFunc(r))
 	defer timeout.Stop()
 	for {
 		select {
@@ -151,7 +154,6 @@ func (tw *timeoutWriter) WriteHeader(code int) {
 	if tw.timedOut {
 		return
 	}
-
 	tw.wroteOnce = true
 	tw.w.WriteHeader(code)
 }
diff --git a/pkg/http/request_log.go b/pkg/http/request_log.go
index ddb945000..c146d0085 100644
--- a/pkg/http/request_log.go
+++ b/pkg/http/request_log.go
@@ -137,7 +137,7 @@ func (h *RequestLogHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
 	defer func() {
 		// Filter probe requests for request logs if disabled.
-		if network.IsProbe(r) && !h.enableProbeRequestLog {
+		if !h.enableProbeRequestLog && network.IsProbe(r) {
 			return
 		}
 
@@ -167,8 +167,8 @@ func (h *RequestLogHandler) write(t *template.Template, in *RequestLogTemplateIn
 	// Use a local buffer to store the whole template expansion first. If h.writer
 	// is used directly, parallel template executions may result in interleaved
 	// output.
-	w := &bytes.Buffer{}
-	if err := t.Execute(w, in); err != nil {
+	w := bytes.Buffer{}
+	if err := t.Execute(&w, in); err != nil {
 		// Template execution failed. Write an error message with some basic information about the request.
 		fmt.Fprintf(h.writer, "Invalid request log template: method: %v, response code: %v, latency: %v, url: %v\n",
 			in.Request.Method, in.Response.Code, in.Response.Latency, in.Request.URL)
diff --git a/pkg/network/network.go b/pkg/network/network.go
index 7eef7a361..89400e881 100644
--- a/pkg/network/network.go
+++ b/pkg/network/network.go
@@ -137,6 +137,19 @@ const (
 	// AutoscalingUserAgent is the user-agent header value set in probe
 	// requests sent by autoscaling implementations.
 	AutoscalingUserAgent = "Knative-Autoscaling-Probe"
+
+	// TagHeaderName is the name of the header entry which has a tag name as value.
+	// The tag name specifies which route was expected to be chosen by Ingress.
+	TagHeaderName = "Knative-Serving-Tag"
+
+	// DefaultRouteHeaderName is the name of the header entry
+	// identifying whether a request is routed via the default route or not.
+	// It has one of the string value "true" or "false".
+	DefaultRouteHeaderName = "Knative-Serving-Default-Route"
+
+	// TagHeaderBasedRoutingKey is the name of the configuration entry
+	// that specifies enabling tag header based routing or not.
+	TagHeaderBasedRoutingKey = "tagHeaderBasedRouting"
 )
 
 // DomainTemplateValues are the available properties people can choose from
@@ -195,6 +208,9 @@ type Config struct {
 
 	// DefaultCertificateClass specifies the default Certificate class.
 	DefaultCertificateClass string
+
+	// TagHeaderBasedRouting specifies if TagHeaderBasedRouting is enabled or not.
+	TagHeaderBasedRouting bool
 }
 
 // HTTPProtocol indicates a type of HTTP endpoint behavior
@@ -270,6 +286,7 @@ func NewConfigFromMap(data map[string]string) (*Config, error) {
 	templateCache.Add(nc.TagTemplate, t)
 
 	nc.AutoTLS = strings.EqualFold(data[AutoTLSKey], "enabled")
+	nc.TagHeaderBasedRouting = strings.EqualFold(data[TagHeaderBasedRoutingKey], "enabled")
 
 	switch strings.ToLower(data[HTTPProtocolKey]) {
 	case "", string(HTTPEnabled):
diff --git a/pkg/network/status/status.go b/pkg/network/status/status.go
index cda7dbd80..4d1e527ea 100644
--- a/pkg/network/status/status.go
+++ b/pkg/network/status/status.go
@@ -30,6 +30,7 @@ import (
 	"time"
 
 	"go.uber.org/zap"
+	"golang.org/x/time/rate"
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/util/sets"
@@ -47,6 +48,9 @@ const (
 	// probeTimeout defines the maximum amount of time a request will wait
 	probeTimeout = 1 * time.Second
 	probePath    = "/healthz"
+	// initialDelay defines the delay before enqueuing a probing request the first time.
+	// It gives times for the change to propagate and prevents unnecessary retries.
+	initialDelay = 200 * time.Millisecond
 )
 
 var dialContext = (&net.Dialer{Timeout: probeTimeout}).DialContext
@@ -134,7 +138,12 @@ func NewProber(
 		ingressStates: make(map[string]*ingressState),
 		podContexts:   make(map[string]cancelContext),
 		workQueue: workqueue.NewNamedRateLimitingQueue(
-			workqueue.DefaultControllerRateLimiter(),
+			workqueue.NewMaxOfRateLimiter(
+				// Per item exponential backoff
+				workqueue.NewItemExponentialFailureRateLimiter(50*time.Millisecond, 30*time.Second),
+				// Global rate limiter
+				&workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(50), 100)},
+			),
 			"ProbingQueue"),
 		targetLister:     targetLister,
 		readyCallback:    readyCallback,
@@ -252,7 +261,7 @@ func (m *Prober) IsReady(ctx context.Context, ing *v1alpha1.Ingress) (bool, erro
 		for _, wi := range ipWorkItems {
 			wi.podState = podState
 			wi.context = podCtx
-			m.workQueue.AddRateLimited(wi)
+			m.workQueue.AddAfter(wi, initialDelay)
 			m.logger.Infof("Queuing probe for %s, IP: %s:%s (depth: %d)",
 				wi.url, wi.podIP, wi.podPort, m.workQueue.Len())
 		}
diff --git a/pkg/queue/prometheus_stats_reporter.go b/pkg/queue/prometheus_stats_reporter.go
index eb301245b..95bb7de16 100644
--- a/pkg/queue/prometheus_stats_reporter.go
+++ b/pkg/queue/prometheus_stats_reporter.go
@@ -24,6 +24,7 @@ import (
 
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
+	"knative.dev/serving/pkg/network"
 )
 
 const (
@@ -125,13 +126,13 @@ func NewPrometheusStatsReporter(namespace, config, revision, pod string, reporti
 }
 
 // Report captures request metrics.
-func (r *PrometheusStatsReporter) Report(acr float64, apcr float64, rc float64, prc float64) {
+func (r *PrometheusStatsReporter) Report(stats network.RequestStatsReport) {
 	// Requests per second is a rate over time while concurrency is not.
 	rp := r.reportingPeriod.Seconds()
-	r.requestsPerSecond.Set(rc / rp)
-	r.proxiedRequestsPerSecond.Set(prc / rp)
-	r.averageConcurrentRequests.Set(acr)
-	r.averageProxiedConcurrentRequests.Set(apcr)
+	r.requestsPerSecond.Set(stats.RequestCount / rp)
+	r.proxiedRequestsPerSecond.Set(stats.ProxiedRequestCount / rp)
+	r.averageConcurrentRequests.Set(stats.AverageConcurrency)
+	r.averageProxiedConcurrentRequests.Set(stats.AverageProxiedConcurrency)
 	r.processUptime.Set(time.Since(r.startTime).Seconds())
 }
 
diff --git a/pkg/queue/stats.go b/pkg/queue/stats.go
deleted file mode 100644
index 0c7216463..000000000
--- a/pkg/queue/stats.go
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-Copyright 2018 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 queue
-
-import (
-	"time"
-
-	"knative.dev/serving/pkg/network"
-)
-
-// ReportStats continually processes network events from reqCh and reports
-// aggregated stats via the `report` function whenever reportCh ticks.
-func ReportStats(startedAt time.Time, stats *network.RequestStats, reportCh <-chan time.Time, report func(float64, float64, float64, float64)) {
-	for {
-		select {
-		case now := <-reportCh:
-			stat := stats.Report(now)
-			report(
-				stat.AverageConcurrency,
-				stat.AverageProxiedConcurrency,
-				stat.RequestCount,
-				stat.ProxiedRequestCount,
-			)
-		}
-	}
-}
diff --git a/pkg/reconciler/autoscaling/kpa/kpa.go b/pkg/reconciler/autoscaling/kpa/kpa.go
index 1f9b6616d..818cdc2f5 100644
--- a/pkg/reconciler/autoscaling/kpa/kpa.go
+++ b/pkg/reconciler/autoscaling/kpa/kpa.go
@@ -122,7 +122,7 @@ func (c *Reconciler) ReconcileKind(ctx context.Context, pa *pav1alpha1.PodAutosc
 	//			this revision, e.g. after a restart) but PA status is inactive (it was
 	//			already scaled to 0).
 	// 2. The excess burst capacity is negative.
-	if want == 0 || decider.Status.ExcessBurstCapacity < 0 || want == -1 && pa.Status.IsInactive() {
+	if want == 0 || decider.Status.ExcessBurstCapacity < 0 || want == scaleUnknown && pa.Status.IsInactive() {
 		logger.Infof("SKS should be in proxy mode: want = %d, ebc = %d, #act's = %d PA Inactive? = %v",
 			want, decider.Status.ExcessBurstCapacity, decider.Status.NumActivators,
 			pa.Status.IsInactive())
diff --git a/pkg/reconciler/autoscaling/kpa/scaler.go b/pkg/reconciler/autoscaling/kpa/scaler.go
index 71a4d72c4..55cd6b731 100644
--- a/pkg/reconciler/autoscaling/kpa/scaler.go
+++ b/pkg/reconciler/autoscaling/kpa/scaler.go
@@ -190,7 +190,7 @@ func (ks *scaler) handleScaleToZero(ctx context.Context, pa *pav1alpha1.PodAutos
 		}
 		ks.enqueueCB(pa, activationTimeout)
 		return scaleUnknown, false
-	case pa.Status.IsReady(): // Active=True
+	case pa.Status.IsActive(): // Active=True
 		// Don't scale-to-zero if the PA is active
 		// but return `(0, false)` to mark PA inactive, instead.
 		sw := aresources.StableWindow(pa, cfgAS)
diff --git a/pkg/reconciler/revision/resources/queue.go b/pkg/reconciler/revision/resources/queue.go
index 40ed65db9..18094b400 100644
--- a/pkg/reconciler/revision/resources/queue.go
+++ b/pkg/reconciler/revision/resources/queue.go
@@ -148,11 +148,19 @@ func makeQueueProbe(in *corev1.Probe) *corev1.Probe {
 					Command: []string{"/ko-app/queue", "-probe-period", "0"},
 				},
 			},
-			// We want to mark the service as not ready as soon as the
-			// PreStop handler is called, so we need to check a little
-			// bit more often than the default.  It is a small
-			// sacrifice for a low rate of 503s.
-			PeriodSeconds: 1,
+			// The exec probe enables us to retry failed probes quickly to get sub-second
+			// resolution and achieve faster cold-starts.  However, for draining pods as
+			// part of the K8s lifecycle this period will bound the tail of how quickly
+			// we can remove a Pod's endpoint from the K8s service.
+			//
+			// The trade-off here is that exec probes cost CPU to run, and for idle pods
+			// (e.g. due to minScale) we see ~50m/{period} of idle CPU usage in the
+			// queue-proxy.  So while setting this to 1s results in slightly faster drains
+			// it also means that in the steady state the queue-proxy is consuming 10x
+			// more CPU due to probes than with a period of 10s.
+			//
+			// See also: https://github.com/knative/serving/issues/8147
+			PeriodSeconds: 10,
 			// We keep the connection open for a while because we're
 			// actively probing the user-container on that endpoint and
 			// thus don't want to be limited by K8s granularity here.
diff --git a/pkg/reconciler/route/resources/ingress.go b/pkg/reconciler/route/resources/ingress.go
index fa4e7956b..9f143e846 100644
--- a/pkg/reconciler/route/resources/ingress.go
+++ b/pkg/reconciler/route/resources/ingress.go
@@ -30,6 +30,8 @@ import (
 	netv1alpha1 "knative.dev/serving/pkg/apis/networking/v1alpha1"
 	"knative.dev/serving/pkg/apis/serving"
 	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
+	"knative.dev/serving/pkg/network"
+	"knative.dev/serving/pkg/reconciler/route/config"
 	"knative.dev/serving/pkg/reconciler/route/domains"
 	"knative.dev/serving/pkg/reconciler/route/resources/labels"
 	"knative.dev/serving/pkg/reconciler/route/resources/names"
@@ -99,6 +101,8 @@ func MakeIngressSpec(
 	rules := make([]netv1alpha1.IngressRule, 0, len(names))
 	challengeHosts := getChallengeHosts(acmeChallenges)
 
+	networkConfig := config.FromContext(ctx).Network
+
 	for _, name := range names {
 		visibilities := []netv1alpha1.IngressVisibility{netv1alpha1.IngressVisibilityClusterLocal}
 		// If this is a public target (or not being marked as cluster-local), we also make public rule.
@@ -111,6 +115,33 @@ func MakeIngressSpec(
 				return netv1alpha1.IngressSpec{}, err
 			}
 			rule := *makeIngressRule([]string{domain}, r.Namespace, visibility, targets[name])
+			if networkConfig.TagHeaderBasedRouting {
+				if rule.HTTP.Paths[0].AppendHeaders == nil {
+					rule.HTTP.Paths[0].AppendHeaders = make(map[string]string)
+				}
+
+				if name == traffic.DefaultTarget {
+					// To provide a information if a request is routed via the "default route" or not,
+					// the header "Knative-Serving-Default-Route: true" is appended here.
+					// If the header has "true" and there is a "Knative-Serving-Tag" header,
+					// then the request is having the undefined tag header, which will be observed in queue-proxy.
+					rule.HTTP.Paths[0].AppendHeaders[network.DefaultRouteHeaderName] = "true"
+					// Add ingress paths for a request with the tag header.
+					// If a request has one of the `names`(tag name) except the default path,
+					// the request will be routed via one of the ingress paths, corresponding to the tag name.
+					rule.HTTP.Paths = append(
+						makeTagBasedRoutingIngressPaths(r.Namespace, targets, names), rule.HTTP.Paths...)
+				} else {
+					// If a request is routed by a tag-attached hostname instead of the tag header,
+					// the request may not have the tag header "Knative-Serving-Tag",
+					// even though the ingress path used in the case is also originated
+					// from the same Knative route with the ingress path for the tag based routing.
+					//
+					// To prevent such inconsistency,
+					// the tag header is appended with the tag corresponding to the tag-attached hostname
+					rule.HTTP.Paths[0].AppendHeaders[network.TagHeaderName] = name
+				}
+			}
 			// If this is a public rule, we need to configure ACME challenge paths.
 			if visibility == netv1alpha1.IngressVisibilityExternalIP {
 				rule.HTTP.Paths = append(
@@ -173,6 +204,32 @@ func makeACMEIngressPaths(challenges map[string]netv1alpha1.HTTP01Challenge, dom
 }
 
 func makeIngressRule(domains []string, ns string, visibility netv1alpha1.IngressVisibility, targets traffic.RevisionTargets) *netv1alpha1.IngressRule {
+	return &netv1alpha1.IngressRule{
+		Hosts:      domains,
+		Visibility: visibility,
+		HTTP: &netv1alpha1.HTTPIngressRuleValue{
+			Paths: []netv1alpha1.HTTPIngressPath{
+				*makeBaseIngressPath(ns, targets),
+			},
+		},
+	}
+}
+
+func makeTagBasedRoutingIngressPaths(ns string, targets map[string]traffic.RevisionTargets, names []string) []netv1alpha1.HTTPIngressPath {
+	paths := make([]netv1alpha1.HTTPIngressPath, 0, len(names))
+
+	for _, name := range names {
+		if name != traffic.DefaultTarget {
+			path := makeBaseIngressPath(ns, targets[name])
+			path.Headers = map[string]netv1alpha1.HeaderMatch{network.TagHeaderName: {Exact: name}}
+			paths = append(paths, *path)
+		}
+	}
+
+	return paths
+}
+
+func makeBaseIngressPath(ns string, targets traffic.RevisionTargets) *netv1alpha1.HTTPIngressPath {
 	// Optimistically allocate |targets| elements.
 	splits := make([]netv1alpha1.IngressBackendSplit, 0, len(targets))
 	for _, t := range targets {
@@ -196,14 +253,8 @@ func makeIngressRule(domains []string, ns string, visibility netv1alpha1.Ingress
 		})
 	}
 
-	return &netv1alpha1.IngressRule{
-		Hosts:      domains,
-		Visibility: visibility,
-		HTTP: &netv1alpha1.HTTPIngressRuleValue{
-			Paths: []netv1alpha1.HTTPIngressPath{{
-				Splits: splits,
-				// TODO(lichuqiang): #2201, plumbing to config timeout and retries.
-			}},
-		},
+	return &netv1alpha1.HTTPIngressPath{
+		Splits: splits,
+		// TODO(lichuqiang): #2201, plumbing to config timeout and retries.
 	}
 }
diff --git a/third_party/cert-manager-0.12.0/net-certmanager.yaml b/third_party/cert-manager-0.12.0/net-certmanager.yaml
index 281d85256..43678c648 100644
--- a/third_party/cert-manager-0.12.0/net-certmanager.yaml
+++ b/third_party/cert-manager-0.12.0/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: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
     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: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
 webhooks:
 - admissionReviewVersions:
   - v1beta1
@@ -86,7 +86,7 @@ metadata:
   name: net-certmanager-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -109,7 +109,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
     networking.knative.dev/certificate-provider: cert-manager
 data:
   _example: |
@@ -156,7 +156,7 @@ metadata:
   name: networking-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
     networking.knative.dev/certificate-provider: cert-manager
 spec:
   selector:
@@ -168,7 +168,7 @@ spec:
         cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
       labels:
         app: networking-certmanager
-        serving.knative.dev/release: "v20200527-9146236"
+        serving.knative.dev/release: "v20200602-9146236"
     spec:
       serviceAccountName: controller
       containers:
@@ -208,7 +208,7 @@ kind: Service
 metadata:
   labels:
     app: networking-certmanager
-    serving.knative.dev/release: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
     networking.knative.dev/certificate-provider: cert-manager
   name: networking-certmanager
   namespace: knative-serving
@@ -245,7 +245,7 @@ metadata:
   name: net-certmanager-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
 spec:
   selector:
     matchLabels:
@@ -258,7 +258,7 @@ spec:
       labels:
         app: net-certmanager-webhook
         role: net-certmanager-webhook
-        serving.knative.dev/release: "v20200527-9146236"
+        serving.knative.dev/release: "v20200602-9146236"
     spec:
       serviceAccountName: controller
       containers:
@@ -319,7 +319,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20200527-9146236"
+    serving.knative.dev/release: "v20200602-9146236"
 spec:
   ports:
   - # Define metrics and profiling for them to be accessible within service meshes.
diff --git a/third_party/net-istio.yaml b/third_party/net-istio.yaml
index d3ba63e49..662d06706 100644
--- a/third_party/net-istio.yaml
+++ b/third_party/net-istio.yaml
@@ -18,7 +18,7 @@ metadata:
   # These are the permissions needed by the Istio Ingress implementation.
   name: knative-serving-istio
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     serving.knative.dev/controller: "true"
     networking.knative.dev/ingress-provider: istio
 rules:
@@ -48,7 +48,7 @@ metadata:
   name: knative-ingress-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -85,7 +85,7 @@ metadata:
   name: cluster-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -118,7 +118,7 @@ kind: MutatingWebhookConfiguration
 metadata:
   name: webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 webhooks:
 - admissionReviewVersions:
@@ -154,7 +154,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 webhooks:
 - admissionReviewVersions:
@@ -192,7 +192,7 @@ metadata:
   name: istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 
 ---
@@ -216,7 +216,7 @@ metadata:
   name: config-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -286,7 +286,7 @@ metadata:
   name: networking-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -302,14 +302,14 @@ spec:
         sidecar.istio.io/inject: "false"
       labels:
         app: networking-istio
-        serving.knative.dev/release: "v20200527-e824460"
+        serving.knative.dev/release: "v20200602-a31bec3"
     spec:
       serviceAccountName: controller
       containers:
       - name: networking-istio
         # 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:3be0005c07a7681d2f122833835f277e8441246d3fd66d2ae91b1ea66ddef080
+        image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:b1c48789552132a835c7eb8629eaf88f834defcf11cec4019c2ed1533780dffc
         resources:
           requests:
             cpu: 30m
@@ -361,7 +361,7 @@ metadata:
   name: istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -375,14 +375,14 @@ spec:
       labels:
         app: istio-webhook
         role: istio-webhook
-        serving.knative.dev/release: "v20200527-e824460"
+        serving.knative.dev/release: "v20200602-a31bec3"
     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:d7230116a940946f12aef40a13c0f127e7c30eba165f88e58f4a425744fa8bfd
+        image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:f251f007aff42aacfbc648ebd06728458b10a128456130561ed1e8ac69cf65bd
         resources:
           requests:
             cpu: 20m
@@ -436,7 +436,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: istio-webhook
-    serving.knative.dev/release: "v20200527-e824460"
+    serving.knative.dev/release: "v20200602-a31bec3"
     networking.knative.dev/ingress-provider: istio
 spec:
   ports:
diff --git a/vendor/knative.dev/pkg/apis/duck/v1/status_types.go b/vendor/knative.dev/pkg/apis/duck/v1/status_types.go
index 53006708f..aab246b1f 100644
--- a/vendor/knative.dev/pkg/apis/duck/v1/status_types.go
+++ b/vendor/knative.dev/pkg/apis/duck/v1/status_types.go
@@ -96,7 +96,7 @@ func (source *Status) ConvertTo(ctx context.Context, sink *Status, predicates ..
 	sink.ObservedGeneration = source.ObservedGeneration
 	if source.Annotations != nil {
 		// This will deep copy the map.
-		sink.Annotations = kmeta.UnionMaps(source.Annotations, nil)
+		sink.Annotations = kmeta.UnionMaps(source.Annotations)
 	}
 
 	conditions := make(apis.Conditions, 0, len(source.Conditions))
diff --git a/vendor/knative.dev/pkg/apis/duck/v1beta1/status_types.go b/vendor/knative.dev/pkg/apis/duck/v1beta1/status_types.go
index d90e7dc69..107592e85 100644
--- a/vendor/knative.dev/pkg/apis/duck/v1beta1/status_types.go
+++ b/vendor/knative.dev/pkg/apis/duck/v1beta1/status_types.go
@@ -109,7 +109,8 @@ func (s *Status) GetCondition(t apis.ConditionType) *apis.Condition {
 func (source *Status) ConvertTo(ctx context.Context, sink *Status) {
 	sink.ObservedGeneration = source.ObservedGeneration
 	if source.Annotations != nil {
-		sink.Annotations = kmeta.UnionMaps(source.Annotations, nil)
+		// This will deep copy the map.
+		sink.Annotations = kmeta.UnionMaps(source.Annotations)
 	}
 	for _, c := range source.Conditions {
 		switch c.Type {
diff --git a/vendor/knative.dev/pkg/configmap/parse.go b/vendor/knative.dev/pkg/configmap/parse.go
index 6479598b7..210d2114e 100644
--- a/vendor/knative.dev/pkg/configmap/parse.go
+++ b/vendor/knative.dev/pkg/configmap/parse.go
@@ -22,6 +22,7 @@ import (
 	"strings"
 	"time"
 
+	"k8s.io/apimachinery/pkg/api/resource"
 	"k8s.io/apimachinery/pkg/util/sets"
 )
 
@@ -114,6 +115,21 @@ func AsStringSet(key string, target *sets.String) ParseFunc {
 	}
 }
 
+// AsQuantity parses the value at key as a *resource.Quantity into the target, if it exists
+func AsQuantity(key string, target **resource.Quantity) ParseFunc {
+	return func(data map[string]string) error {
+		if raw, ok := data[key]; ok {
+			val, err := resource.ParseQuantity(raw)
+			if err != nil {
+				return fmt.Errorf("failed to parse %q: %w", key, err)
+			}
+
+			*target = &val
+		}
+		return nil
+	}
+}
+
 // Parse parses the given map using the parser functions passed in.
 func Parse(data map[string]string, parsers ...ParseFunc) error {
 	for _, parse := range parsers {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 41b59cddf..0bdbfa660 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -453,6 +453,7 @@ golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
 golang.org/x/text/width
 # golang.org/x/time v0.0.0-20191024005414-555d28b269f0
+## explicit
 golang.org/x/time/rate
 # golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65
 golang.org/x/tools/cmd/goimports
@@ -1196,7 +1197,7 @@ knative.dev/caching/pkg/client/injection/informers/caching/v1alpha1/image/fake
 knative.dev/caching/pkg/client/injection/informers/factory
 knative.dev/caching/pkg/client/injection/informers/factory/fake
 knative.dev/caching/pkg/client/listers/caching/v1alpha1
-# knative.dev/pkg v0.0.0-20200527173759-2d1a04d1ff82
+# knative.dev/pkg v0.0.0-20200528190300-08a86da47d28
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate
@@ -1312,7 +1313,7 @@ knative.dev/pkg/webhook/resourcesemantics/conversion
 knative.dev/pkg/webhook/resourcesemantics/defaulting
 knative.dev/pkg/webhook/resourcesemantics/validation
 knative.dev/pkg/websocket
-# knative.dev/test-infra v0.0.0-20200527185659-fc87694eb879
+# knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e
 ## explicit
 knative.dev/test-infra/scripts
 # sigs.k8s.io/structured-merge-diff/v2 v2.0.1


Test patch:
diff --git a/cmd/autoscaler/main_test.go b/cmd/autoscaler/main_test.go
index fbbf16393..cfcbb28c0 100644
--- a/cmd/autoscaler/main_test.go
+++ b/cmd/autoscaler/main_test.go
@@ -21,7 +21,6 @@ import (
 	"strings"
 	"testing"
 
-	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	kubeinformers "k8s.io/client-go/informers"
 	fakek8s "k8s.io/client-go/kubernetes/fake"
@@ -30,11 +29,6 @@ import (
 	"knative.dev/serving/pkg/autoscaler/scaling"
 )
 
-const (
-	testNamespace = "test-namespace"
-	testRevision  = "test-Revision"
-)
-
 var (
 	kubeClient   = fakek8s.NewSimpleClientset()
 	kubeInformer = kubeinformers.NewSharedInformerFactory(kubeClient, 0)
@@ -66,11 +60,11 @@ func TestUniscalerFactoryFailures(t *testing.T) {
 		}, "max length must be 255 characters",
 	}}
 
-	uniScalerFactory := getTestUniScalerFactory()
+	uniScalerFactory := testUniScalerFactory()
 	decider := &scaling.Decider{
 		ObjectMeta: metav1.ObjectMeta{
-			Namespace: testNamespace,
-			Name:      testRevision,
+			Namespace: autoscalerfake.TestNamespace,
+			Name:      autoscalerfake.TestRevision,
 		},
 		Spec: scaling.DeciderSpec{
 			ServiceName: "wholesome-service",
@@ -94,7 +88,7 @@ func TestUniscalerFactoryFailures(t *testing.T) {
 	// Now blank out service name and give correct labels.
 	decider.Spec.ServiceName = ""
 	decider.Labels = map[string]string{
-		serving.RevisionLabelKey:      testRevision,
+		serving.RevisionLabelKey:      autoscalerfake.TestRevision,
 		serving.ServiceLabelKey:       "some-nice-service",
 		serving.ConfigurationLabelKey: "test-config",
 	}
@@ -108,28 +102,16 @@ func TestUniscalerFactoryFailures(t *testing.T) {
 	}
 }
 
-func endpoints(ns, n string) {
-	ep := &corev1.Endpoints{
-		ObjectMeta: metav1.ObjectMeta{
-			Namespace: ns,
-			Name:      n,
-		},
-		Subsets: []corev1.EndpointSubset{{}},
-	}
-	kubeClient.CoreV1().Endpoints(ns).Create(ep)
-	kubeInformer.Core().V1().Endpoints().Informer().GetIndexer().Add(ep)
-}
-
 func TestUniScalerFactoryFunc(t *testing.T) {
-	endpoints(testNamespace, "magic-services-offered")
-	uniScalerFactory := getTestUniScalerFactory()
+	autoscalerfake.Endpoints(1, "magic-services-offered")
+	uniScalerFactory := testUniScalerFactory()
 	for _, srv := range []string{"some", ""} {
 		decider := &scaling.Decider{
 			ObjectMeta: metav1.ObjectMeta{
-				Namespace: testNamespace,
-				Name:      testRevision,
+				Namespace: autoscalerfake.TestNamespace,
+				Name:      autoscalerfake.TestRevision,
 				Labels: map[string]string{
-					serving.RevisionLabelKey:      testRevision,
+					serving.RevisionLabelKey:      autoscalerfake.TestRevision,
 					serving.ServiceLabelKey:       srv,
 					serving.ConfigurationLabelKey: "test-config",
 				},
@@ -145,6 +127,6 @@ func TestUniScalerFactoryFunc(t *testing.T) {
 	}
 }
 
-func getTestUniScalerFactory() func(decider *scaling.Decider) (scaling.UniScaler, error) {
-	return uniScalerFactoryFunc(kubeInformer.Core().V1().Endpoints(), &autoscalerfake.StaticMetricClient)
+func testUniScalerFactory() func(decider *scaling.Decider) (scaling.UniScaler, error) {
+	return uniScalerFactoryFunc(kubeInformer.Core().V1().Endpoints(), &autoscalerfake.MetricClient{})
 }
diff --git a/cmd/queue/main_test.go b/cmd/queue/main_test.go
index 50f66b638..25664ccbb 100644
--- a/cmd/queue/main_test.go
+++ b/cmd/queue/main_test.go
@@ -169,9 +169,7 @@ func TestProbeHandler(t *testing.T) {
 }
 
 func TestProbeQueueInvalidPort(t *testing.T) {
-	const port = 0 // invalid port
-
-	if err := probeQueueHealthPath(port, 1, config{}); err == nil {
+	if err := probeQueueHealthPath(1, probeConfig{QueueServingPort: 0}); err == nil {
 		t.Error("Expected error, got nil")
 	} else if diff := cmp.Diff(err.Error(), "port must be a positive value, got 0"); diff != "" {
 		t.Errorf("Unexpected not ready message: %s", diff)
@@ -179,9 +177,7 @@ func TestProbeQueueInvalidPort(t *testing.T) {
 }
 
 func TestProbeQueueConnectionFailure(t *testing.T) {
-	port := 12345 // some random port (that's not listening)
-
-	if err := probeQueueHealthPath(port, 1, config{}); err == nil {
+	if err := probeQueueHealthPath(1, probeConfig{QueueServingPort: 12345}); err == nil {
 		t.Error("Expected error, got nil")
 	}
 }
@@ -205,7 +201,7 @@ func TestProbeQueueNotReady(t *testing.T) {
 		t.Fatalf("Failed to convert port(%s) to int: %v", u.Port(), err)
 	}
 
-	err = probeQueueHealthPath(port, 1, config{})
+	err = probeQueueHealthPath(1, probeConfig{QueueServingPort: port})
 
 	if diff := cmp.Diff(err.Error(), "probe returned not ready"); diff != "" {
 		t.Errorf("Unexpected not ready message: %s", diff)
@@ -235,7 +231,7 @@ func TestProbeQueueReady(t *testing.T) {
 		t.Fatalf("Failed to convert port(%s) to int: %v", u.Port(), err)
 	}
 
-	if err = probeQueueHealthPath(port, 1, config{}); err != nil {
+	if err = probeQueueHealthPath(1, probeConfig{QueueServingPort: port}); err != nil {
 		t.Errorf("probeQueueHealthPath(%d, 1s) = %s", port, err)
 	}
 
@@ -276,7 +272,10 @@ func TestProbeFailFast(t *testing.T) {
 	f.Close()
 
 	start := time.Now()
-	if err = probeQueueHealthPath(port, 1 /*seconds*/, config{DownwardAPILabelsPath: f.Name()}); err == nil {
+	if err = probeQueueHealthPath(1 /*seconds*/, probeConfig{
+		QueueServingPort:      port,
+		DownwardAPILabelsPath: f.Name(),
+	}); err == nil {
 		t.Error("probeQueueHealthPath did not fail")
 	}
 
@@ -307,7 +306,7 @@ func TestProbeQueueTimeout(t *testing.T) {
 	}
 
 	timeout := 1
-	if err = probeQueueHealthPath(port, timeout, config{}); err == nil {
+	if err = probeQueueHealthPath(timeout, probeConfig{QueueServingPort: port}); err == nil {
 		t.Errorf("Expected probeQueueHealthPath(%d, %v) to return timeout error", port, timeout)
 	}
 
@@ -341,7 +340,7 @@ func TestProbeQueueDelayedReady(t *testing.T) {
 	}
 
 	timeout := 0
-	if err := probeQueueHealthPath(port, timeout, config{}); err != nil {
+	if err := probeQueueHealthPath(timeout, probeConfig{QueueServingPort: port}); err != nil {
 		t.Errorf("probeQueueHealthPath(%d) = %s", port, err)
 	}
 }
@@ -510,7 +509,11 @@ func BenchmarkProxyHandler(b *testing.B) {
 	if err != nil {
 		b.Fatal("Failed to create stats reporter:", err)
 	}
-	go queue.ReportStats(time.Now(), stats, reportTicker.C, promStatReporter.Report)
+	go func() {
+		for now := range reportTicker.C {
+			promStatReporter.Report(stats.Report(now))
+		}
+	}()
 	req := httptest.NewRequest(http.MethodPost, "http://example.com", nil)
 	req.Header.Set(network.OriginalHostHeader, wantHost)
 
diff --git a/pkg/activator/net/lb_policy_test.go b/pkg/activator/net/lb_policy_test.go
new file mode 100644
index 000000000..638dd3bd4
--- /dev/null
+++ b/pkg/activator/net/lb_policy_test.go
@@ -0,0 +1,88 @@
+/*
+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 net
+
+import (
+	"context"
+	"testing"
+	"time"
+
+	"knative.dev/serving/pkg/queue"
+)
+
+func TestFirstAvailable(t *testing.T) {
+	t.Run("1 tracker, 1 slot", func(t *testing.T) {
+		podTrackers := []*podTracker{{
+			dest: "this-is-nowhere",
+			b: queue.NewBreaker(queue.BreakerParams{
+				QueueDepth:      1,
+				MaxConcurrency:  1,
+				InitialCapacity: 1,
+			}),
+		}}
+
+		ctx := context.Background()
+		cb, tracker := firstAvailableLBPolicy(ctx, podTrackers)
+		defer cb()
+		if tracker == nil {
+			t.Fatal("Tracker was nil")
+		}
+
+		ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond)
+		defer cancel()
+
+		cb, tracker = firstAvailableLBPolicy(ctx, podTrackers)
+		defer cb()
+		if tracker != nil {
+			t.Fatal("Tracker was not nil")
+		}
+	})
+	t.Run("2 trackers, 1 slot", func(t *testing.T) {
+		podTrackers := []*podTracker{{
+			dest: "down-by-the-river",
+			b: queue.NewBreaker(queue.BreakerParams{
+				QueueDepth:      1,
+				MaxConcurrency:  1,
+				InitialCapacity: 1,
+			}),
+		}, {
+			dest: "heart-of-gold",
+			b: queue.NewBreaker(queue.BreakerParams{
+				QueueDepth:      1,
+				MaxConcurrency:  1,
+				InitialCapacity: 1,
+			}),
+		}}
+
+		ctx := context.Background()
+		cb, tracker := firstAvailableLBPolicy(ctx, podTrackers)
+		defer cb()
+		if tracker == nil {
+			t.Fatal("Tracker was nil")
+		} else if got, want := tracker.dest, podTrackers[0].dest; got != want {
+			t.Errorf("Tracker = %s, want: %s", got, want)
+		}
+
+		cb, tracker = firstAvailableLBPolicy(ctx, podTrackers)
+		defer cb()
+		if tracker == nil {
+			t.Fatal("Tracker was nil")
+		} else if got, want := tracker.dest, podTrackers[1].dest; got != want {
+			t.Errorf("Tracker = %s, want: %s", got, want)
+		}
+	})
+}
diff --git a/pkg/apis/autoscaling/v1alpha1/pa_lifecycle_test.go b/pkg/apis/autoscaling/v1alpha1/pa_lifecycle_test.go
index 24635dd3c..353c46d9c 100644
--- a/pkg/apis/autoscaling/v1alpha1/pa_lifecycle_test.go
+++ b/pkg/apis/autoscaling/v1alpha1/pa_lifecycle_test.go
@@ -424,7 +424,7 @@ func TestIsActivating(t *testing.T) {
 	}{{
 		name:         "empty status",
 		status:       PodAutoscalerStatus{},
-		isActivating: false,
+		isActivating: true,
 	}, {
 		name: "active=unknown",
 		status: PodAutoscalerStatus{
@@ -564,7 +564,8 @@ func TestIsReady(t *testing.T) {
 
 	for _, tc := range cases {
 		t.Run(tc.name, func(t *testing.T) {
-			if got, want := tc.status.IsReady(), tc.isReady; got != want {
+			pa := PodAutoscaler{Status: tc.status}
+			if got, want := pa.IsReady(), tc.isReady; got != want {
 				t.Errorf("IsReady = %v, want: %v", got, want)
 			}
 		})
@@ -1010,7 +1011,9 @@ func TestTypicalFlow(t *testing.T) {
 	// When the activator successfully forwards traffic to the deployment,
 	// we mark ourselves as active once more.
 	r.MarkActive()
-	apistest.CheckConditionSucceeded(r, PodAutoscalerConditionActive, t)
+	if !r.IsActive() {
+		t.Error("Active was not set.")
+	}
 	apistest.CheckConditionSucceeded(r, PodAutoscalerConditionReady, t)
 }
 
diff --git a/pkg/apis/config/defaults_test.go b/pkg/apis/config/defaults_test.go
index 1115f649c..5fdaf9207 100644
--- a/pkg/apis/config/defaults_test.go
+++ b/pkg/apis/config/defaults_test.go
@@ -48,6 +48,7 @@ func TestDefaultsConfigurationFromFile(t *testing.T) {
 	// So for this test we ignore those, but verify the other fields.
 	got.RevisionCPULimit, got.RevisionCPURequest = nil, nil
 	got.RevisionMemoryLimit, got.RevisionMemoryRequest = nil, nil
+	got.RevisionEphemeralStorageLimit, got.RevisionEphemeralStorageRequest = nil, nil
 	want := defaultDefaultsConfig()
 	if diff := cmp.Diff(want, got); diff != "" {
 		t.Error("Example does not represent default config: diff(-want,+got)\n", diff)
diff --git a/pkg/apis/serving/k8s_validation_test.go b/pkg/apis/serving/k8s_validation_test.go
index e78a74a2d..20ed14685 100644
--- a/pkg/apis/serving/k8s_validation_test.go
+++ b/pkg/apis/serving/k8s_validation_test.go
@@ -386,10 +386,10 @@ func TestContainerValidation(t *testing.T) {
 			Image: "foo",
 			Resources: corev1.ResourceRequirements{
 				Limits: corev1.ResourceList{
-					corev1.ResourceName("memory"): resource.MustParse("250M"),
+					corev1.ResourceMemory: resource.MustParse("250M"),
 				},
 				Requests: corev1.ResourceList{
-					corev1.ResourceName("cpu"): resource.MustParse("25m"),
+					corev1.ResourceCPU: resource.MustParse("25m"),
 				},
 			},
 		},
diff --git a/pkg/apis/serving/v1/revision_defaults_test.go b/pkg/apis/serving/v1/revision_defaults_test.go
index f327de9ee..c4f97fe6e 100644
--- a/pkg/apis/serving/v1/revision_defaults_test.go
+++ b/pkg/apis/serving/v1/revision_defaults_test.go
@@ -269,10 +269,12 @@ func TestRevisionDefaulting(t *testing.T) {
 					Name: config.DefaultsConfigName,
 				},
 				Data: map[string]string{
-					"revision-cpu-request":    "100m",
-					"revision-memory-request": "200M",
-					"revision-cpu-limit":      "300m",
-					"revision-memory-limit":   "400M",
+					"revision-cpu-request":               "100m",
+					"revision-memory-request":            "200M",
+					"revision-ephemeral-storage-request": "300m",
+					"revision-cpu-limit":                 "400M",
+					"revision-memory-limit":              "500m",
+					"revision-ephemeral-storage-limit":   "600M",
 				},
 			})
 
@@ -287,12 +289,14 @@ func TestRevisionDefaulting(t *testing.T) {
 						Name: config.DefaultUserContainerName,
 						Resources: corev1.ResourceRequirements{
 							Requests: corev1.ResourceList{
-								corev1.ResourceCPU:    resource.MustParse("100m"),
-								corev1.ResourceMemory: resource.MustParse("200M"),
+								corev1.ResourceCPU:              resource.MustParse("100m"),
+								corev1.ResourceMemory:           resource.MustParse("200M"),
+								corev1.ResourceEphemeralStorage: resource.MustParse("300m"),
 							},
 							Limits: corev1.ResourceList{
-								corev1.ResourceCPU:    resource.MustParse("300m"),
-								corev1.ResourceMemory: resource.MustParse("400M"),
+								corev1.ResourceCPU:              resource.MustParse("400M"),
+								corev1.ResourceMemory:           resource.MustParse("500m"),
+								corev1.ResourceEphemeralStorage: resource.MustParse("600M"),
 							},
 						},
 						ReadinessProbe: defaultProbe,
diff --git a/pkg/apis/serving/v1/revision_validation_test.go b/pkg/apis/serving/v1/revision_validation_test.go
index 20dc82e9e..da6ab75ef 100644
--- a/pkg/apis/serving/v1/revision_validation_test.go
+++ b/pkg/apis/serving/v1/revision_validation_test.go
@@ -542,7 +542,7 @@ func TestImmutableFields(t *testing.T) {
 					Containers: []corev1.Container{{
 						Resources: corev1.ResourceRequirements{
 							Requests: corev1.ResourceList{
-								corev1.ResourceName("cpu"): resource.MustParse("50m"),
+								corev1.ResourceCPU: resource.MustParse("50m"),
 							},
 						},
 					}},
@@ -558,7 +558,7 @@ func TestImmutableFields(t *testing.T) {
 					Containers: []corev1.Container{{
 						Resources: corev1.ResourceRequirements{
 							Requests: corev1.ResourceList{
-								corev1.ResourceName("cpu"): resource.MustParse("100m"),
+								corev1.ResourceCPU: resource.MustParse("100m"),
 							},
 						},
 					}},
diff --git a/pkg/apis/serving/v1alpha1/revision_validation_test.go b/pkg/apis/serving/v1alpha1/revision_validation_test.go
index 2c81f043c..080db721b 100644
--- a/pkg/apis/serving/v1alpha1/revision_validation_test.go
+++ b/pkg/apis/serving/v1alpha1/revision_validation_test.go
@@ -669,7 +669,7 @@ func TestImmutableFields(t *testing.T) {
 					Image: "busybox",
 					Resources: corev1.ResourceRequirements{
 						Requests: corev1.ResourceList{
-							corev1.ResourceName("cpu"): resource.MustParse("50m"),
+							corev1.ResourceCPU: resource.MustParse("50m"),
 						},
 					},
 				},
@@ -684,7 +684,7 @@ func TestImmutableFields(t *testing.T) {
 					Image: "busybox",
 					Resources: corev1.ResourceRequirements{
 						Requests: corev1.ResourceList{
-							corev1.ResourceName("cpu"): resource.MustParse("100m"),
+							corev1.ResourceCPU: resource.MustParse("100m"),
 						},
 					},
 				},
diff --git a/pkg/apis/serving/v1beta1/revision_validation_test.go b/pkg/apis/serving/v1beta1/revision_validation_test.go
index 3ee08493b..1b6a36a98 100644
--- a/pkg/apis/serving/v1beta1/revision_validation_test.go
+++ b/pkg/apis/serving/v1beta1/revision_validation_test.go
@@ -543,7 +543,7 @@ func TestImmutableFields(t *testing.T) {
 					Containers: []corev1.Container{{
 						Resources: corev1.ResourceRequirements{
 							Requests: corev1.ResourceList{
-								corev1.ResourceName("cpu"): resource.MustParse("50m"),
+								corev1.ResourceCPU: resource.MustParse("50m"),
 							},
 						},
 					}},
@@ -559,7 +559,7 @@ func TestImmutableFields(t *testing.T) {
 					Containers: []corev1.Container{{
 						Resources: corev1.ResourceRequirements{
 							Requests: corev1.ResourceList{
-								corev1.ResourceName("cpu"): resource.MustParse("100m"),
+								corev1.ResourceCPU: resource.MustParse("100m"),
 							},
 						},
 					}},
diff --git a/pkg/autoscaler/config/config_test.go b/pkg/autoscaler/config/config_test.go
index faa289915..30c13cdaa 100644
--- a/pkg/autoscaler/config/config_test.go
+++ b/pkg/autoscaler/config/config_test.go
@@ -230,8 +230,7 @@ func TestNewConfig(t *testing.T) {
 	}, {
 		name: "panic window percentage too small",
 		input: map[string]string{
-			"stable-window":           "12s",
-			"panic-window-percentage": "5", // 0.6s < BucketSize
+			"panic-window-percentage": "0.1",
 		},
 		wantErr: true,
 	}, {
diff --git a/pkg/autoscaler/scaling/autoscaler_test.go b/pkg/autoscaler/scaling/autoscaler_test.go
index 31951542b..1fd8452fc 100644
--- a/pkg/autoscaler/scaling/autoscaler_test.go
+++ b/pkg/autoscaler/scaling/autoscaler_test.go
@@ -183,6 +183,70 @@ func TestAutoscalerStableModeIncreaseWithRPS(t *testing.T) {
 	expectScale(t, a, time.Now(), ScaleResult{10, expectedEBC(10, 101, 99, 1), na, true})
 }
 
+func TestAutoscalerUnpanicAfterSlowIncrease(t *testing.T) {
+	// Do initial jump from 10 to 25 pods.
+	metrics := &fake.MetricClient{StableConcurrency: 11, PanicConcurrency: 25}
+	a := newTestAutoscaler(t, 1, 98, metrics)
+	fake.Endpoints(10, fake.TestService)
+
+	na := expectedNA(a, 10)
+	start := time.Now()
+	tm := start
+	expectScale(t, a, tm, ScaleResult{25, expectedEBC(1, 98, 25, 10), na, true})
+	if a.panicTime != tm {
+		t.Errorf("PanicTime = %v, want: %v", a.panicTime, tm)
+	}
+	// Now the half of the stable window has passed, and we've been adding 1 pod per cycle.
+	// For window of 60s, that's +15 pods.
+	fake.Endpoints(25+15, fake.TestService)
+
+	metrics.SetStableAndPanicConcurrency(30, 41)
+	tm = tm.Add(stableWindow / 2)
+
+	na = expectedNA(a, 40)
+	expectScale(t, a, tm, ScaleResult{41, expectedEBC(1, 98, 41, 40), na, true})
+	if a.panicTime != start {
+		t.Error("Panic Time should not have moved")
+	}
+
+	// Now at the end. Panic must end. And +30 pods.
+	fake.Endpoints(25+30, fake.TestService)
+	metrics.SetStableAndPanicConcurrency(50, 56)
+	tm = tm.Add(stableWindow/2 + tickInterval)
+
+	na = expectedNA(a, 55)
+	expectScale(t, a, tm, ScaleResult{50 /* no longer in panic*/, expectedEBC(1, 98, 56, 55), na, true})
+	if !a.panicTime.IsZero() {
+		t.Errorf("PanicTime = %v, want: 0", a.panicTime)
+	}
+}
+
+func TestAutoscalerExtendPanicWindow(t *testing.T) {
+	// Do initial jump from 10 to 25 pods.
+	metrics := &fake.MetricClient{StableConcurrency: 11, PanicConcurrency: 25}
+	a := newTestAutoscaler(t, 1, 98, metrics)
+	fake.Endpoints(10, fake.TestService)
+
+	na := expectedNA(a, 10)
+	start := time.Now()
+	tm := start
+	expectScale(t, a, tm, ScaleResult{25, expectedEBC(1, 98, 25, 10), na, true})
+	if a.panicTime != tm {
+		t.Errorf("PanicTime = %v, want: %v", a.panicTime, tm)
+	}
+	// Now the half of the stable window has passed, and we're still surging.
+	fake.Endpoints(25+15, fake.TestService)
+
+	metrics.SetStableAndPanicConcurrency(30, 80)
+	tm = tm.Add(stableWindow / 2)
+
+	na = expectedNA(a, 40)
+	expectScale(t, a, tm, ScaleResult{80, expectedEBC(1, 98, 80, 40), na, true})
+	if a.panicTime != tm {
+		t.Errorf("PanicTime = %v, want: %v", a.panicTime, tm)
+	}
+}
+
 func TestAutoscalerStableModeDecrease(t *testing.T) {
 	metrics := &fake.MetricClient{StableConcurrency: 100.0, PanicConcurrency: 100}
 	a := newTestAutoscaler(t, 10, 98, metrics)
@@ -190,8 +254,7 @@ func TestAutoscalerStableModeDecrease(t *testing.T) {
 	na := expectedNA(a, 8)
 	expectScale(t, a, time.Now(), ScaleResult{10, expectedEBC(10, 98, 100, 8), na, true})
 
-	metrics.StableConcurrency = 50
-	metrics.PanicConcurrency = 50
+	metrics.SetStableAndPanicConcurrency(50, 50)
 	expectScale(t, a, time.Now(), ScaleResult{5, expectedEBC(10, 98, 50, 8), na, true})
 }
 
@@ -214,23 +277,36 @@ func TestAutoscalerPanicModeExponentialTrackAndStablize(t *testing.T) {
 	na := expectedNA(a, 1)
 	expectScale(t, a, time.Now(), ScaleResult{6, expectedEBC(1, 101, 6, 1), na, true})
 
+	tm := time.Now()
 	fake.Endpoints(6, fake.TestService)
 	na = expectedNA(a, 6)
-	metrics.PanicConcurrency, metrics.StableConcurrency = 36, 36
-	expectScale(t, a, time.Now(), ScaleResult{36, expectedEBC(1, 101, 36, 6), na, true})
+	metrics.SetStableAndPanicConcurrency(36, 36)
+	expectScale(t, a, tm, ScaleResult{36, expectedEBC(1, 101, 36, 6), na, true})
+	if got, want := a.panicTime, tm; got != tm {
+		t.Errorf("PanicTime = %v, want: %v", got, want)
+	}
 
 	fake.Endpoints(36, fake.TestService)
 	na = expectedNA(a, 36)
-	metrics.PanicConcurrency, metrics.StableConcurrency = 216, 216
-	expectScale(t, a, time.Now(), ScaleResult{216, expectedEBC(1, 101, 216, 36), na, true})
+	metrics.SetStableAndPanicConcurrency(216, 216)
+	tm = tm.Add(time.Second)
+	expectScale(t, a, tm, ScaleResult{216, expectedEBC(1, 101, 216, 36), na, true})
+	if got, want := a.panicTime, tm; got != tm {
+		t.Errorf("PanicTime = %v, want: %v", got, want)
+	}
 
 	fake.Endpoints(216, fake.TestService)
 	na = expectedNA(a, 216)
-	metrics.PanicConcurrency, metrics.StableConcurrency = 1296, 1296
-	expectScale(t, a, time.Now(), ScaleResult{1296, expectedEBC(1, 101, 1296, 216), na, true})
+	metrics.SetStableAndPanicConcurrency(1296, 1296)
+	expectScale(t, a, tm, ScaleResult{1296, expectedEBC(1, 101, 1296, 216), na, true})
+	if got, want := a.panicTime, tm; got != tm {
+		t.Errorf("PanicTime = %v, want: %v", got, want)
+	}
+
 	fake.Endpoints(1296, fake.TestService)
 	na = expectedNA(a, 1296)
-	expectScale(t, a, time.Now(), ScaleResult{1296, expectedEBC(1, 101, 1296, 1296), na, true})
+	tm = tm.Add(time.Second)
+	expectScale(t, a, tm, ScaleResult{1296, expectedEBC(1, 101, 1296, 1296), na, true})
 }
 
 func TestAutoscalerScale(t *testing.T) {
@@ -272,6 +348,26 @@ func TestAutoscalerScale(t *testing.T) {
 		baseScale: 1,
 		wantScale: 5,
 		wantEBC:   expectedEBC(10, 100, 50, 1),
+	}, {
+		label: "AutoscalerPanicStableLargerThanPanic",
+		as:    newTestAutoscaler(t, 1, 100, &fake.MetricClient{StableConcurrency: 50, PanicConcurrency: 30}),
+		prepFunc: func(a *Autoscaler) {
+			a.panicTime = time.Now().Add(-5 * time.Second)
+			a.maxPanicPods = 5
+		},
+		baseScale: 5,
+		wantScale: 50, // Note that we use stable concurrency value for desired scale.
+		wantEBC:   expectedEBC(1, 100, 30, 5),
+	}, {
+		label: "AutoscalerPanicStableLessThanPanic",
+		as:    newTestAutoscaler(t, 1, 100, &fake.MetricClient{StableConcurrency: 20, PanicConcurrency: 30}),
+		prepFunc: func(a *Autoscaler) {
+			a.panicTime = time.Now().Add(-5 * time.Second)
+			a.maxPanicPods = 5
+		},
+		baseScale: 5,
+		wantScale: 30, // And here we use panic, since it's larger.
+		wantEBC:   expectedEBC(1, 100, 30, 5),
 	}, {
 		label:     "AutoscalerStableModeNoChangeAlreadyScaled",
 		as:        newTestAutoscaler(t, 10, 100, &fake.MetricClient{StableConcurrency: 50.0, PanicConcurrency: 50}),
@@ -333,8 +429,7 @@ func TestAutoscalerPanicThenUnPanicScaleDown(t *testing.T) {
 	expectScale(t, a, panicTime, ScaleResult{100, expectedEBC(10, 93, 1000, 10), na, true})
 
 	// Traffic dropped off, scale stays as we're still in panic.
-	metrics.PanicConcurrency = 1
-	metrics.StableConcurrency = 1
+	metrics.SetStableAndPanicConcurrency(1, 1)
 	expectScale(t, a, panicTime.Add(30*time.Second), ScaleResult{100, expectedEBC(10, 93, 1, 10), na, true})
 
 	// Scale down after the StableWindow
@@ -461,7 +556,7 @@ func expectScale(t *testing.T, a UniScaler, now time.Time, want ScaleResult) {
 }
 
 func TestStartInPanicMode(t *testing.T) {
-	metrics := &fake.StaticMetricClient
+	metrics := &staticMetricClient
 	deciderSpec := &DeciderSpec{
 		TargetValue:         100,
 		TotalValue:          120,
@@ -504,7 +599,7 @@ func TestStartInPanicMode(t *testing.T) {
 
 func TestNewFail(t *testing.T) {
 	eraseEndpoints()
-	metrics := &fake.StaticMetricClient
+	metrics := &staticMetricClient
 	deciderSpec := &DeciderSpec{
 		TargetValue:         100,
 		TotalValue:          120,
@@ -535,3 +630,11 @@ func reset() {
 		targetRPSM.Name(), panicM.Name())
 	register()
 }
+
+// staticMetricClient returns stable/panic concurrency and RPS with static value, i.e. 10.
+var staticMetricClient = fake.MetricClient{
+	StableConcurrency: 10.0,
+	PanicConcurrency:  10.0,
+	StableRPS:         10.0,
+	PanicRPS:          10.0,
+}
diff --git a/pkg/queue/timeout_test.go b/pkg/http/handler/timeout_test.go
similarity index 75%
rename from pkg/queue/timeout_test.go
rename to pkg/http/handler/timeout_test.go
index 04fa2e1d1..248e986b2 100644
--- a/pkg/queue/timeout_test.go
+++ b/pkg/http/handler/timeout_test.go
@@ -1,5 +1,5 @@
 /*
-Copyright 2018 The Knative Authors
+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.
@@ -13,7 +13,8 @@ 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 queue
+
+package handler
 
 import (
 	"io"
@@ -24,15 +25,68 @@ import (
 	"time"
 )
 
+func TestTimeoutWriterAllowsForAdditionalWrites(t *testing.T) {
+	recorder := httptest.NewRecorder()
+	handler := &timeoutWriter{w: recorder}
+	handler.WriteHeader(http.StatusOK)
+	handler.TimeoutAndWriteError("error")
+	if _, err := io.WriteString(handler, "test"); err != nil {
+		t.Fatalf("handler.Write() = %v, want no error", err)
+	}
+
+	if got, want := recorder.Code, http.StatusOK; got != want {
+		t.Errorf("recorder.Status = %d, want %d", got, want)
+	}
+	if got, want := recorder.Body.String(), "test"; got != want {
+		t.Errorf("recorder.Body = %s, want %s", got, want)
+	}
+}
+
+func TestTimeoutWriterDoesntFlushAfterTimeout(t *testing.T) {
+	recorder := httptest.NewRecorder()
+	handler := &timeoutWriter{w: recorder}
+	handler.TimeoutAndWriteError("error")
+	handler.Flush()
+
+	if got, want := recorder.Flushed, false; got != want {
+		t.Errorf("recorder.Flushed = %t, want %t", got, want)
+	}
+}
+
+func TestTimeoutWriterFlushesAfterTimeout(t *testing.T) {
+	recorder := httptest.NewRecorder()
+	handler := &timeoutWriter{w: recorder}
+	handler.Flush()
+
+	if got, want := recorder.Flushed, true; got != want {
+		t.Errorf("recorder.Flushed = %t, want %t", got, want)
+	}
+}
+
+func TestTimeoutWriterErrorsWriteAfterTimeout(t *testing.T) {
+	recorder := httptest.NewRecorder()
+	handler := &timeoutWriter{w: recorder}
+	handler.TimeoutAndWriteError("error")
+	if _, err := handler.Write([]byte("hello")); err != http.ErrHandlerTimeout {
+		t.Errorf("ErrHandlerTimeout got %v, want: %s", err, http.ErrHandlerTimeout)
+	}
+}
+
 func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 	const (
-		failingTimeout = 0 * time.Millisecond
-		longTimeout    = 10 * time.Second
+		longTimeout = 10 * time.Second
 	)
 
+	longTimeoutFunc := func(*http.Request) time.Duration {
+		return longTimeout
+	}
+	failingTimeoutFunc := func(*http.Request) time.Duration {
+		return 0 * time.Millisecond
+	}
+
 	tests := []struct {
 		name               string
-		timeout            time.Duration
+		timeoutFunc        TimeoutFunc
 		handler            func(mux *sync.Mutex, writeErrors chan error) http.Handler
 		timeoutMessage     string
 		wantStatus         int
@@ -41,8 +95,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantPanic          bool
 		sleepBeforeExiting time.Duration
 	}{{
-		name:    "all good",
-		timeout: longTimeout,
+		name:        "all good",
+		timeoutFunc: longTimeoutFunc,
 		handler: func(*sync.Mutex, chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				w.Write([]byte("hi"))
@@ -51,8 +105,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantStatus: http.StatusOK,
 		wantBody:   "hi",
 	}, {
-		name:    "custom timeout message",
-		timeout: failingTimeout,
+		name:        "custom timeout message",
+		timeoutFunc: failingTimeoutFunc,
 		handler: func(mux *sync.Mutex, writeErrors chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				mux.Lock()
@@ -66,8 +120,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantBody:       "request timeout",
 		wantWriteError: true,
 	}, {
-		name:    "propagate panic",
-		timeout: longTimeout,
+		name:        "propagate panic",
+		timeoutFunc: longTimeoutFunc,
 		handler: func(*sync.Mutex, chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				panic(http.ErrAbortHandler)
@@ -77,8 +131,8 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		wantBody:   "request timeout",
 		wantPanic:  true,
 	}, {
-		name:    "timeout before panic",
-		timeout: failingTimeout,
+		name:        "timeout before panic",
+		timeoutFunc: failingTimeoutFunc,
 		handler: func(*sync.Mutex, chan error) http.Handler {
 			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				time.Sleep(1 * time.Second)
@@ -101,7 +155,7 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 			var reqMux sync.Mutex
 			writeErrors := make(chan error, 1)
 			rr := httptest.NewRecorder()
-			handler := TimeToFirstByteTimeoutHandler(test.handler(&reqMux, writeErrors), test.timeout, test.timeoutMessage)
+			handler := NewTimeToFirstByteTimeoutHandler(test.handler(&reqMux, writeErrors), test.timeoutMessage, test.timeoutFunc)
 
 			defer func() {
 				if test.wantPanic {
@@ -133,36 +187,3 @@ func TestTimeToFirstByteTimeoutHandler(t *testing.T) {
 		})
 	}
 }
-
-func TestTimeoutWriterAllowsForAdditionalWrites(t *testing.T) {
-	recorder := httptest.NewRecorder()
-	handler := &timeoutWriter{
-		w: recorder,
-	}
-
-	handler.WriteHeader(http.StatusOK)
-	handler.TimeoutAndWriteError("error")
-	if _, err := io.WriteString(handler, "test"); err != nil {
-		t.Fatalf("handler.Write() = %v, want no error", err)
-	}
-
-	if got, want := recorder.Code, http.StatusOK; got != want {
-		t.Errorf("recorder.Status = %d, want %d", got, want)
-	}
-	if got, want := recorder.Body.String(), "test"; got != want {
-		t.Errorf("recorder.Body = %s, want %s", got, want)
-	}
-}
-
-func TestTimeoutWriterDoesntFlushAfterTimeout(t *testing.T) {
-	recorder := httptest.NewRecorder()
-	handler := &timeoutWriter{
-		w: recorder,
-	}
-
-	handler.TimeoutAndWriteError("error")
-	handler.Flush()
-	if got, want := recorder.Flushed, false; got != want {
-		t.Errorf("recorder.Flushed = %t, want %t", got, want)
-	}
-}
diff --git a/pkg/queue/prometheus_stats_reporter_test.go b/pkg/queue/prometheus_stats_reporter_test.go
index e32ed4f0c..0f24bef2e 100644
--- a/pkg/queue/prometheus_stats_reporter_test.go
+++ b/pkg/queue/prometheus_stats_reporter_test.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"github.com/prometheus/client_golang/prometheus"
+	"knative.dev/serving/pkg/network"
 
 	dto "github.com/prometheus/client_model/go"
 )
@@ -42,44 +43,39 @@ func TestNewPrometheusStatsReporter_negative(t *testing.T) {
 		config    string
 		revision  string
 		pod       string
-	}{
-		{
-			"Empty_Namespace_Value",
-			"Expected namespace empty error",
-			errors.New("namespace must not be empty"),
-			"",
-			config,
-			revision,
-			pod,
-		},
-		{
-			"Empty_Config_Value",
-			"Expected config empty error",
-			errors.New("config must not be empty"),
-			namespace,
-			"",
-			revision,
-			pod,
-		},
-		{
-			"Empty_Revision_Value",
-			"Expected revision empty error",
-			errors.New("revision must not be empty"),
-			namespace,
-			config,
-			"",
-			pod,
-		},
-		{
-			"Empty_Pod_Value",
-			"Expected pod empty error",
-			errors.New("pod must not be empty"),
-			namespace,
-			config,
-			revision,
-			"",
-		},
-	}
+	}{{
+		"Empty_Namespace_Value",
+		"Expected namespace empty error",
+		errors.New("namespace must not be empty"),
+		"",
+		config,
+		revision,
+		pod,
+	}, {
+		"Empty_Config_Value",
+		"Expected config empty error",
+		errors.New("config must not be empty"),
+		namespace,
+		"",
+		revision,
+		pod,
+	}, {
+		"Empty_Revision_Value",
+		"Expected revision empty error",
+		errors.New("revision must not be empty"),
+		namespace,
+		config,
+		"",
+		pod,
+	}, {
+		"Empty_Pod_Value",
+		"Expected pod empty error",
+		errors.New("pod must not be empty"),
+		namespace,
+		config,
+		revision,
+		"",
+	}}
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
@@ -154,8 +150,7 @@ func TestReporterReport(t *testing.T) {
 		expectedConcurrency:         3,
 		expectedProxiedRequestCount: 15,
 		expectedProxiedConcurrency:  2,
-	},
-	}
+	}}
 
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
@@ -165,7 +160,12 @@ func TestReporterReport(t *testing.T) {
 			}
 			// Make the value slightly more interesting, rather than microseconds.
 			reporter.startTime = reporter.startTime.Add(-5 * time.Second)
-			reporter.Report(test.concurrency, test.proxiedConcurrency, test.reqCount, test.proxiedReqCount)
+			reporter.Report(network.RequestStatsReport{
+				AverageConcurrency:        test.concurrency,
+				AverageProxiedConcurrency: test.proxiedConcurrency,
+				RequestCount:              test.reqCount,
+				ProxiedRequestCount:       test.proxiedReqCount,
+			})
 			checkData(t, requestsPerSecondGV, test.expectedReqCount)
 			checkData(t, averageConcurrentRequestsGV, test.expectedConcurrency)
 			checkData(t, proxiedRequestsPerSecondGV, test.expectedProxiedRequestCount)
diff --git a/pkg/queue/stats_test.go b/pkg/queue/stats_test.go
deleted file mode 100644
index a5b272d00..000000000
--- a/pkg/queue/stats_test.go
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
-Copyright 2018 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 queue
-
-import (
-	"testing"
-	"time"
-
-	"github.com/google/go-cmp/cmp"
-	"knative.dev/serving/pkg/network"
-)
-
-type reportedStat struct {
-	Concurrency         float64
-	ProxiedConcurrency  float64
-	RequestCount        float64
-	ProxiedRequestCount float64
-}
-
-func TestNoData(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	got := s.report(now)
-	want := reportedStat{
-		Concurrency:  0.0,
-		RequestCount: 0,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestSingleRequestWholeTime(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	s.requestStart(now)
-	now = now.Add(1 * time.Second)
-	s.requestEnd(now)
-
-	got := s.report(now)
-
-	want := reportedStat{
-		Concurrency:  1.0,
-		RequestCount: 1,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestSingleRequestHalfTime(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	s.requestStart(now)
-	now = now.Add(1 * time.Second)
-	s.requestEnd(now)
-	now = now.Add(1 * time.Second)
-	got := s.report(now)
-
-	want := reportedStat{
-		Concurrency:  0.5,
-		RequestCount: 1,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestVeryShortLivedRequest(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	s.requestStart(now)
-	now = now.Add(10 * time.Millisecond)
-	s.requestEnd(now)
-
-	now = now.Add(990 * time.Millisecond) // make the second full
-	got := s.report(now)
-
-	want := reportedStat{
-		Concurrency:  float64(10) / float64(1000),
-		RequestCount: 1,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestMultipleRequestsWholeTime(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	s.requestStart(now)
-	now = now.Add(300 * time.Millisecond)
-	s.requestEnd(now)
-
-	s.requestStart(now)
-	now = now.Add(300 * time.Millisecond)
-	s.requestEnd(now)
-
-	s.requestStart(now)
-	now = now.Add(400 * time.Millisecond)
-	s.requestEnd(now)
-
-	got := s.report(now)
-
-	want := reportedStat{
-		Concurrency:  1.0,
-		RequestCount: 3,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestMultipleRequestsInterleaved(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	s.requestStart(now)
-	now = now.Add(100 * time.Millisecond)
-	s.requestStart(now)
-	now = now.Add(500 * time.Millisecond)
-	s.requestEnd(now)
-	now = now.Add(400 * time.Millisecond)
-	s.requestEnd(now)
-
-	got := s.report(now)
-
-	want := reportedStat{
-		Concurrency:  1.5,
-		RequestCount: 2,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestOneRequestAcrossReportings(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-
-	s.requestStart(now)
-	now = now.Add(1 * time.Second)
-	got1 := s.report(now)
-	want1 := reportedStat{
-		Concurrency:  1.0,
-		RequestCount: 1,
-	}
-
-	now = now.Add(500 * time.Millisecond)
-	s.requestEnd(now)
-	now = now.Add(500 * time.Millisecond)
-	got2 := s.report(now)
-	want2 := reportedStat{
-		Concurrency:  0.5,
-		RequestCount: 0,
-	}
-
-	if diff := cmp.Diff(want1, got1); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-	if diff := cmp.Diff(want2, got2); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestOneProxiedRequest(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-	s.proxiedStart(now)
-	now = now.Add(1 * time.Second)
-	got := s.report(now)
-	want := reportedStat{
-		Concurrency:         1.0,
-		ProxiedConcurrency:  1.0,
-		RequestCount:        1,
-		ProxiedRequestCount: 1,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestOneEndedProxiedRequest(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-	s.proxiedStart(now)
-	now = now.Add(500 * time.Millisecond)
-	s.proxiedEnd(now)
-	now = now.Add(500 * time.Millisecond)
-	got := s.report(now)
-	want := reportedStat{
-		Concurrency:         0.5,
-		ProxiedConcurrency:  0.5,
-		RequestCount:        1,
-		ProxiedRequestCount: 1,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-func TestTwoRequestsOneProxied(t *testing.T) {
-	now := time.Now()
-	s := newTestStats(t, now)
-	s.proxiedStart(now)
-	now = now.Add(500 * time.Millisecond)
-	s.proxiedEnd(now)
-	s.requestStart(now)
-	now = now.Add(500 * time.Millisecond)
-	got := s.report(now)
-	want := reportedStat{
-		Concurrency:         1.0,
-		ProxiedConcurrency:  0.5,
-		RequestCount:        2,
-		ProxiedRequestCount: 1,
-	}
-	if diff := cmp.Diff(want, got); diff != "" {
-		t.Errorf("Unexpected stat (-want +got): %v", diff)
-	}
-}
-
-// Test type to hold the bi-directional time channels
-type testStats struct {
-	stats        *network.RequestStats
-	reportBiChan chan time.Time
-	statChan     chan reportedStat
-}
-
-func newTestStats(t *testing.T, now time.Time) *testStats {
-	stats := network.NewRequestStats(now)
-	reportBiChan := make(chan time.Time)
-	statChan := make(chan reportedStat)
-	report := func(acr float64, apcr float64, rc float64, prc float64) {
-		statChan <- reportedStat{
-			Concurrency:         acr,
-			ProxiedConcurrency:  apcr,
-			RequestCount:        rc,
-			ProxiedRequestCount: prc,
-		}
-	}
-	go ReportStats(now, stats, reportBiChan, report)
-	return &testStats{
-		stats:        stats,
-		reportBiChan: reportBiChan,
-		statChan:     statChan,
-	}
-}
-
-func (s *testStats) requestStart(now time.Time) {
-	s.stats.HandleEvent(network.ReqEvent{Time: now, Type: network.ReqIn})
-}
-
-func (s *testStats) requestEnd(now time.Time) {
-	s.stats.HandleEvent(network.ReqEvent{Time: now, Type: network.ReqOut})
-}
-
-func (s *testStats) proxiedStart(now time.Time) {
-	s.stats.HandleEvent(network.ReqEvent{Time: now, Type: network.ProxiedIn})
-}
-
-func (s *testStats) proxiedEnd(now time.Time) {
-	s.stats.HandleEvent(network.ReqEvent{Time: now, Type: network.ProxiedOut})
-}
-
-func (s *testStats) report(now time.Time) reportedStat {
-	s.reportBiChan <- now
-	return <-s.statChan
-}
diff --git a/pkg/reconciler/autoscaling/kpa/kpa_test.go b/pkg/reconciler/autoscaling/kpa/kpa_test.go
index e5a0fb29a..21707e4dd 100644
--- a/pkg/reconciler/autoscaling/kpa/kpa_test.go
+++ b/pkg/reconciler/autoscaling/kpa/kpa_test.go
@@ -1196,7 +1196,7 @@ func TestControllerSynchronizesCreatesAndDeletes(t *testing.T) {
 		if err != nil {
 			return true, err
 		}
-		return newKPA.Status.IsReady(), nil
+		return newKPA.IsReady(), nil
 	}); err != nil {
 		t.Fatal("PA failed to become ready:", err)
 	}
diff --git a/pkg/reconciler/revision/resources/deploy_test.go b/pkg/reconciler/revision/resources/deploy_test.go
index 933ed2cab..6a97ef2be 100644
--- a/pkg/reconciler/revision/resources/deploy_test.go
+++ b/pkg/reconciler/revision/resources/deploy_test.go
@@ -87,7 +87,7 @@ var (
 					Command: []string{"/ko-app/queue", "-probe-period", "0"},
 				},
 			},
-			PeriodSeconds:  1,
+			PeriodSeconds:  10,
 			TimeoutSeconds: 10,
 		},
 		SecurityContext: queueSecurityContext,
@@ -203,7 +203,7 @@ var (
 					serving.RevisionUID: "1234",
 				},
 			},
-			ProgressDeadlineSeconds: ptr.Int32(int32(deployment.ProgressDeadlineDefault.Seconds())),
+			ProgressDeadlineSeconds: ptr.Int32(0),
 			Template: corev1.PodTemplateSpec{
 				ObjectMeta: metav1.ObjectMeta{
 					Labels: map[string]string{
@@ -341,7 +341,7 @@ func withAppendedVolumes(volumes ...corev1.Volume) podSpecOption {
 	}
 }
 
-func makeDeployment(opts ...deploymentOption) *appsv1.Deployment {
+func appsv1deployment(opts ...deploymentOption) *appsv1.Deployment {
 	deploy := defaultDeployment.DeepCopy()
 	for _, option := range opts {
 		option(deploy)
@@ -541,14 +541,7 @@ func TestMakePodSpec(t *testing.T) {
 	}, {
 		name: "with tcp readiness probe",
 		rev: revision("bar", "foo", func(revision *v1.Revision) {
-			container(revision.Spec.GetContainer(),
-				withReadinessProbe(corev1.Handler{
-					TCPSocket: &corev1.TCPSocketAction{
-						Host: "127.0.0.1",
-						Port: intstr.FromInt(12345),
-					},
-				}),
-			)
+			container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 		}),
 		want: podSpec(
 			[]corev1.Container{
@@ -741,59 +734,48 @@ func TestMakeDeployment(t *testing.T) {
 		name string
 		rev  *v1.Revision
 		want *appsv1.Deployment
+		dc   deployment.Config
 	}{{
 		name: "with concurrency=1",
 		rev: revision("bar", "foo",
 			withoutLabels,
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				container(revision.Spec.GetContainer(),
-					withReadinessProbe(corev1.Handler{
-						TCPSocket: &corev1.TCPSocketAction{
-							Host: "127.0.0.1",
-							Port: intstr.FromInt(12345),
-						},
-					}),
-				)
-			},
-		),
-		want: makeDeployment(),
+				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
+			}),
+		want: appsv1deployment(),
 	}, {
 		name: "with owner",
 		rev: revision("bar", "foo",
 			withoutLabels,
 			withOwnerReference("parent-config"),
 			func(revision *v1.Revision) {
-				container(revision.Spec.GetContainer(),
-					withReadinessProbe(corev1.Handler{
-						TCPSocket: &corev1.TCPSocketAction{
-							Host: "127.0.0.1",
-							Port: intstr.FromInt(12345),
-						},
-					}),
-				)
-			},
-		),
-		want: makeDeployment(),
+				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
+			}),
+		want: appsv1deployment(),
 	}, {
 		name: "with sidecar annotation override",
 		rev: revision("bar", "foo", withoutLabels, func(revision *v1.Revision) {
 			revision.ObjectMeta.Annotations = map[string]string{
 				sidecarIstioInjectAnnotation: "false",
 			}
-			container(revision.Spec.GetContainer(),
-				withReadinessProbe(corev1.Handler{
-					TCPSocket: &corev1.TCPSocketAction{
-						Host: "127.0.0.1",
-						Port: intstr.FromInt(12345),
-					},
-				}),
-			)
+			container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 		}),
-		want: makeDeployment(func(deploy *appsv1.Deployment) {
+		want: appsv1deployment(func(deploy *appsv1.Deployment) {
 			deploy.ObjectMeta.Annotations[sidecarIstioInjectAnnotation] = "false"
 			deploy.Spec.Template.ObjectMeta.Annotations[sidecarIstioInjectAnnotation] = "false"
 		}),
+	}, {
+		name: "with ProgressDeadline override",
+		dc: deployment.Config{
+			ProgressDeadline: 42 * time.Second,
+		},
+		rev: revision("bar", "foo", withoutLabels, func(revision *v1.Revision) {
+			container(revision.Spec.GetContainer(), withTCPReadinessProbe())
+		}),
+		want: appsv1deployment(func(deploy *appsv1.Deployment) {
+			deploy.Spec.ProgressDeadlineSeconds = ptr.Int32(42)
+		}),
 	}}
 
 	for _, test := range tests {
@@ -806,7 +788,7 @@ func TestMakeDeployment(t *testing.T) {
 			}
 			test.want.Spec.Template.Spec = *podSpec
 			got, err := MakeDeployment(test.rev, &logConfig, &traceConfig,
-				&network.Config{}, &obsConfig, &asConfig, &deploymentConfig)
+				&network.Config{}, &obsConfig, &asConfig, &test.dc)
 			if err != nil {
 				t.Fatal("got unexpected error:", err)
 			}
@@ -816,39 +798,3 @@ func TestMakeDeployment(t *testing.T) {
 		})
 	}
 }
-
-func TestProgressDeadlineOverride(t *testing.T) {
-	rev := revision("bar", "foo",
-		withoutLabels,
-		func(revision *v1.Revision) {
-			container(revision.Spec.GetContainer(),
-				withReadinessProbe(corev1.Handler{
-					TCPSocket: &corev1.TCPSocketAction{
-						Host: "127.0.0.1",
-						Port: intstr.FromInt(12345),
-					},
-				}),
-			)
-		},
-	)
-	want := makeDeployment(func(d *appsv1.Deployment) {
-		d.Spec.ProgressDeadlineSeconds = ptr.Int32(42)
-	})
-
-	dc := &deployment.Config{
-		ProgressDeadline: 42 * time.Second,
-	}
-	podSpec, err := makePodSpec(rev, &logConfig, &traceConfig, &obsConfig, &asConfig, dc)
-	if err != nil {
-		t.Fatal("makePodSpec returned error:", err)
-	}
-	want.Spec.Template.Spec = *podSpec
-	got, err := MakeDeployment(rev, &logConfig, &traceConfig,
-		&network.Config{}, &obsConfig, &asConfig, dc)
-	if err != nil {
-		t.Fatal("MakeDeployment returned error:", err)
-	}
-	if !cmp.Equal(want, got, cmp.AllowUnexported(resource.Quantity{})) {
-		t.Error("MakeDeployment (-want, +got) =", cmp.Diff(want, got, cmp.AllowUnexported(resource.Quantity{})))
-	}
-}
diff --git a/pkg/reconciler/revision/resources/queue_test.go b/pkg/reconciler/revision/resources/queue_test.go
index 901fdd3ad..6d421c6c6 100644
--- a/pkg/reconciler/revision/resources/queue_test.go
+++ b/pkg/reconciler/revision/resources/queue_test.go
@@ -61,9 +61,7 @@ var (
 	traceConfig      tracingconfig.Config
 	obsConfig        metrics.ObservabilityConfig
 	asConfig         autoscalerconfig.Config
-	deploymentConfig = deployment.Config{
-		ProgressDeadline: deployment.ProgressDeadlineDefault,
-	}
+	deploymentConfig deployment.Config
 )
 
 const testProbeJSONTemplate = `{"tcpSocket":{"port":%d,"host":"127.0.0.1"}}`
@@ -81,7 +79,6 @@ func TestMakeQueueContainer(t *testing.T) {
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
 		want: queueContainer(func(c *corev1.Container) {
@@ -90,11 +87,10 @@ func TestMakeQueueContainer(t *testing.T) {
 			})
 		}),
 	}, {
-		name: "no owner no autoscaler single",
+		name: "custom sidecar image, container port, protocol",
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				revision.Spec.PodSpec = corev1.PodSpec{
 					Containers: []corev1.Container{{
 						Name:           containerName,
@@ -117,35 +113,27 @@ func TestMakeQueueContainer(t *testing.T) {
 				"QUEUE_SERVING_PORT":    "8013",
 				"CONTAINER_CONCURRENCY": "1",
 			})
-		},
-		),
+		}),
 	}, {
 		name: "service name in labels",
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				revision.ObjectMeta.Labels = map[string]string{
 					serving.ServiceLabelKey: "svc",
 				}
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
-		cc: deployment.Config{
-			QueueSidecarImage: "alpine",
-		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{
 				"SERVING_SERVICE": "svc",
 			})
-			c.Image = "alpine"
-			c.Ports = append(queueNonServingPorts, queueHTTPPort)
 		}),
 	}, {
 		name: "config owner as env var, zero concurrency",
 		rev: revision("blah", "baz",
 			withContainerConcurrency(0),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				revision.ObjectMeta.OwnerReferences = []metav1.OwnerReference{{
 					APIVersion:         v1.SchemeGroupVersion.String(),
 					Kind:               "Configuration",
@@ -162,14 +150,12 @@ func TestMakeQueueContainer(t *testing.T) {
 				"SERVING_NAMESPACE":     "baz",
 				"SERVING_REVISION":      "blah",
 			})
-			c.Ports = append(queueNonServingPorts, queueHTTPPort)
 		}),
 	}, {
 		name: "logging configuration as env var",
 		rev: revision("this", "log",
-			withContainerConcurrency(0),
+			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
 		lc: logging.Config{
@@ -180,34 +166,29 @@ func TestMakeQueueContainer(t *testing.T) {
 		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{
-				"CONTAINER_CONCURRENCY":  "0",
 				"SERVING_LOGGING_CONFIG": "The logging configuration goes here",
 				"SERVING_LOGGING_LEVEL":  "error",
 				"SERVING_NAMESPACE":      "log",
 				"SERVING_REVISION":       "this",
 			})
-			c.Ports = append(queueNonServingPorts, queueHTTPPort)
 		}),
 	}, {
 		name: "container concurrency 10",
 		rev: revision("bar", "foo",
 			withContainerConcurrency(10),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{
 				"CONTAINER_CONCURRENCY": "10",
 			})
-			c.Ports = append(queueNonServingPorts, queueHTTPPort)
 		}),
 	}, {
 		name: "request log configuration as env var",
 		rev: revision("bar", "foo",
-			withContainerConcurrency(0),
+			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
 		oc: metrics.ObservabilityConfig{
@@ -216,18 +197,15 @@ func TestMakeQueueContainer(t *testing.T) {
 		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{
-				"CONTAINER_CONCURRENCY":            "0",
 				"SERVING_REQUEST_LOG_TEMPLATE":     "test template",
 				"SERVING_ENABLE_PROBE_REQUEST_LOG": "true",
 			})
-			c.Ports = append(queueNonServingPorts, queueHTTPPort)
 		}),
 	}, {
 		name: "request metrics backend as env var",
 		rev: revision("bar", "foo",
-			withContainerConcurrency(0),
+			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
 		oc: metrics.ObservabilityConfig{
@@ -235,27 +213,36 @@ func TestMakeQueueContainer(t *testing.T) {
 		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{
-				"CONTAINER_CONCURRENCY":           "0",
 				"SERVING_REQUEST_METRICS_BACKEND": "prometheus",
 			})
-			c.Ports = append(queueNonServingPorts, queueHTTPPort)
 		}),
 	}, {
 		name: "enable profiling",
 		rev: revision("bar", "foo",
-			withContainerConcurrency(0),
+			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
 				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
 			}),
 		oc: metrics.ObservabilityConfig{EnableProfiling: true},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{
-				"CONTAINER_CONCURRENCY": "0",
-				"ENABLE_PROFILING":      "true",
+				"ENABLE_PROFILING": "true",
 			})
 			c.Ports = append(queueNonServingPorts, profilingPort, queueHTTPPort)
 		}),
+	}, {
+		name: "custom TimeoutSeconds",
+		rev: revision("bar", "foo",
+			withContainerConcurrency(1),
+			func(revision *v1.Revision) {
+				container(revision.Spec.GetContainer(), withTCPReadinessProbe())
+				revision.Spec.TimeoutSeconds = ptr.Int64(99)
+			}),
+		want: queueContainer(func(c *corev1.Container) {
+			c.Env = env(map[string]string{
+				"REVISION_TIMEOUT_SECONDS": "99",
+			})
+		}),
 	}}
 
 	for _, test := range tests {
@@ -296,8 +283,6 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
-				revision.ObjectMeta.Labels = map[string]string{}
 				revision.ObjectMeta.Annotations = map[string]string{
 					serving.QueueSideCarResourcePercentageAnnotation: "20",
 				}
@@ -306,8 +291,8 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 					ReadinessProbe: testProbe,
 					Resources: corev1.ResourceRequirements{
 						Limits: corev1.ResourceList{
-							corev1.ResourceName("memory"): resource.MustParse("2Gi"),
-							corev1.ResourceName("cpu"):    resource.MustParse("2"),
+							corev1.ResourceMemory: resource.MustParse("2Gi"),
+							corev1.ResourceCPU:    resource.MustParse("2"),
 						},
 					}},
 				}
@@ -315,18 +300,15 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{})
 			c.Resources.Limits = corev1.ResourceList{
-				corev1.ResourceName("memory"): *resource.NewMilliQuantity(429496729600, resource.BinarySI),
-				corev1.ResourceName("cpu"):    *resource.NewMilliQuantity(400, resource.BinarySI),
+				corev1.ResourceMemory: resource.MustParse("0.4Gi"),
+				corev1.ResourceCPU:    resource.MustParse("0.4"),
 			}
-			c.Image = "alpine"
 		}),
 	}, {
-		name: "resources percentage in annotations small than min allowed",
+		name: "resources percentage in annotations smaller than min allowed",
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
-				revision.ObjectMeta.Labels = map[string]string{}
 				revision.ObjectMeta.Annotations = map[string]string{
 					serving.QueueSideCarResourcePercentageAnnotation: "0.2",
 				}
@@ -335,8 +317,8 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 					ReadinessProbe: testProbe,
 					Resources: corev1.ResourceRequirements{
 						Requests: corev1.ResourceList{
-							corev1.ResourceName("cpu"):    resource.MustParse("50m"),
-							corev1.ResourceName("memory"): resource.MustParse("128Mi"),
+							corev1.ResourceCPU:    resource.MustParse("50m"),
+							corev1.ResourceMemory: resource.MustParse("128Mi"),
 						},
 					},
 				}}
@@ -344,18 +326,15 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{})
 			c.Resources.Requests = corev1.ResourceList{
-				corev1.ResourceName("cpu"):    resource.MustParse("25m"),
-				corev1.ResourceName("memory"): resource.MustParse("50Mi"),
+				corev1.ResourceCPU:    resource.MustParse("25m"), // clamped to boundary in resourceboundary.go
+				corev1.ResourceMemory: resource.MustParse("50Mi"),
 			}
-			c.Image = "alpine"
 		}),
 	}, {
-		name: "Invalid resources percentage in annotations",
+		name: "invalid resources percentage in annotations",
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
-				revision.ObjectMeta.Labels = map[string]string{}
 				revision.ObjectMeta.Annotations = map[string]string{
 					serving.QueueSideCarResourcePercentageAnnotation: "foo",
 				}
@@ -364,8 +343,8 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 					ReadinessProbe: testProbe,
 					Resources: corev1.ResourceRequirements{
 						Requests: corev1.ResourceList{
-							corev1.ResourceName("cpu"):    resource.MustParse("50m"),
-							corev1.ResourceName("memory"): resource.MustParse("128Mi"),
+							corev1.ResourceCPU:    resource.MustParse("50m"),
+							corev1.ResourceMemory: resource.MustParse("128Mi"),
 						},
 					},
 				}}
@@ -373,17 +352,14 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{})
 			c.Resources.Requests = corev1.ResourceList{
-				corev1.ResourceName("cpu"): resource.MustParse("25m"),
+				corev1.ResourceCPU: resource.MustParse("25m"),
 			}
-			c.Image = "alpine"
 		}),
 	}, {
 		name: "resources percentage in annotations bigger than than math.MaxInt64",
 		rev: revision("bar", "foo",
 			withContainerConcurrency(1),
 			func(revision *v1.Revision) {
-				revision.Spec.TimeoutSeconds = ptr.Int64(45)
-				revision.ObjectMeta.Labels = map[string]string{}
 				revision.ObjectMeta.Annotations = map[string]string{
 					serving.QueueSideCarResourcePercentageAnnotation: "100",
 				}
@@ -392,7 +368,7 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 					ReadinessProbe: testProbe,
 					Resources: corev1.ResourceRequirements{
 						Requests: corev1.ResourceList{
-							corev1.ResourceName("memory"): resource.MustParse("900000Pi"),
+							corev1.ResourceMemory: resource.MustParse("900000Pi"),
 						},
 					},
 				}}
@@ -400,17 +376,15 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 		want: queueContainer(func(c *corev1.Container) {
 			c.Env = env(map[string]string{})
 			c.Resources.Requests = corev1.ResourceList{
-				corev1.ResourceName("cpu"):    resource.MustParse("25m"),
-				corev1.ResourceName("memory"): resource.MustParse("200Mi"),
+				corev1.ResourceCPU:    resource.MustParse("25m"),
+				corev1.ResourceMemory: resource.MustParse("200Mi"),
 			}
-			c.Image = "alpine"
 		}),
 	}}
 
-	cc := deployment.Config{QueueSidecarImage: "alpine"}
 	for _, test := range tests {
 		t.Run(test.name, func(t *testing.T) {
-			got, err := makeQueueContainer(test.rev, &logConfig, &traceConfig, &obsConfig, &asConfig, &cc)
+			got, err := makeQueueContainer(test.rev, &logConfig, &traceConfig, &obsConfig, &asConfig, &deploymentConfig)
 			if err != nil {
 				t.Fatal("makeQueueContainer returned error:", err)
 			}
@@ -421,19 +395,7 @@ func TestMakeQueueContainerWithPercentageAnnotation(t *testing.T) {
 			sortEnv(got.Env)
 			sortEnv(test.want.Env)
 			if diff := cmp.Diff(test.want, *got, cmp.AllowUnexported(resource.Quantity{})); diff != "" {
-				t.Error("makeQueueContainerWithPercentageAnnotation (-want, +got) =", diff)
-			}
-			if test.want.Resources.Limits.Memory().Cmp(*got.Resources.Limits.Memory()) != 0 {
-				t.Errorf("Resources.Limits.Memory = %v, want: %v", got.Resources.Limits.Memory(), test.want.Resources.Limits.Memory())
-			}
-			if test.want.Resources.Requests.Cpu().Cmp(*got.Resources.Requests.Cpu()) != 0 {
-				t.Errorf("Resources.Request.CPU = %v, want: %v", got.Resources.Requests.Cpu(), test.want.Resources.Requests.Cpu())
-			}
-			if test.want.Resources.Requests.Memory().Cmp(*got.Resources.Requests.Memory()) != 0 {
-				t.Errorf("Resources.Requests.Memory = %v, want: %v", got.Resources.Requests.Memory(), test.want.Resources.Requests.Memory())
-			}
-			if test.want.Resources.Limits.Cpu().Cmp(*got.Resources.Limits.Cpu()) != 0 {
-				t.Errorf("Resources.Limits.CPU  = %v, want: %v", got.Resources.Limits.Cpu(), test.want.Resources.Limits.Cpu())
+				t.Error("makeQueueContainer (-want, +got) =", diff)
 			}
 		})
 	}
@@ -443,8 +405,6 @@ func TestProbeGenerationHTTPDefaults(t *testing.T) {
 	rev := revision("bar", "foo",
 		withContainerConcurrency(1),
 		func(revision *v1.Revision) {
-			revision.Spec.TimeoutSeconds = ptr.Int64(45)
-			revision.ObjectMeta.Labels = map[string]string{}
 			revision.Spec.PodSpec.Containers = []corev1.Container{{
 				Name: containerName,
 				ReadinessProbe: &corev1.Probe{
@@ -486,7 +446,7 @@ func TestProbeGenerationHTTPDefaults(t *testing.T) {
 			"SERVING_READINESS_PROBE": string(wantProbeJSON),
 		})
 		c.Resources.Requests = corev1.ResourceList{
-			corev1.ResourceName("cpu"): resource.MustParse("25m"),
+			corev1.ResourceCPU: resource.MustParse("25m"),
 		}
 		c.ReadinessProbe = &corev1.Probe{
 			Handler: corev1.Handler{
@@ -497,8 +457,7 @@ func TestProbeGenerationHTTPDefaults(t *testing.T) {
 			PeriodSeconds:  1,
 			TimeoutSeconds: 10,
 		}
-	},
-	)
+	})
 
 	got, err := makeQueueContainer(rev, &logConfig, &traceConfig, &obsConfig, &asConfig, &deploymentConfig)
 	if err != nil {
@@ -517,8 +476,6 @@ func TestProbeGenerationHTTP(t *testing.T) {
 	rev := revision("bar", "foo",
 		withContainerConcurrency(1),
 		func(revision *v1.Revision) {
-			revision.Spec.TimeoutSeconds = ptr.Int64(45)
-			revision.ObjectMeta.Labels = map[string]string{}
 			revision.Spec.PodSpec.Containers = []corev1.Container{{
 				Name: containerName,
 				Ports: []corev1.ContainerPort{{
@@ -572,8 +529,7 @@ func TestProbeGenerationHTTP(t *testing.T) {
 			PeriodSeconds:  2,
 			TimeoutSeconds: 10,
 		}
-	},
-	)
+	})
 
 	got, err := makeQueueContainer(rev, &logConfig, &traceConfig, &obsConfig, &asConfig, &deploymentConfig)
 	if err != nil {
@@ -625,7 +581,7 @@ func TestTCPProbeGeneration(t *testing.T) {
 		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Resources.Requests = corev1.ResourceList{
-				corev1.ResourceName("cpu"): resource.MustParse("25m"),
+				corev1.ResourceCPU: resource.MustParse("25m"),
 			}
 			c.ReadinessProbe = &corev1.Probe{
 				Handler: corev1.Handler{
@@ -633,7 +589,7 @@ func TestTCPProbeGeneration(t *testing.T) {
 						Command: []string{"/ko-app/queue", "-probe-period", "0"},
 					},
 				},
-				PeriodSeconds:  1,
+				PeriodSeconds:  10,
 				TimeoutSeconds: 10,
 			}
 			c.Env = env(map[string]string{"USER_PORT": strconv.Itoa(userPort)})
@@ -667,7 +623,7 @@ func TestTCPProbeGeneration(t *testing.T) {
 		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Resources.Requests = corev1.ResourceList{
-				corev1.ResourceName("cpu"): resource.MustParse("25m"),
+				corev1.ResourceCPU: resource.MustParse("25m"),
 			}
 			c.ReadinessProbe = &corev1.Probe{
 				Handler: corev1.Handler{
@@ -719,7 +675,7 @@ func TestTCPProbeGeneration(t *testing.T) {
 		},
 		want: queueContainer(func(c *corev1.Container) {
 			c.Resources.Requests = corev1.ResourceList{
-				corev1.ResourceName("cpu"): resource.MustParse("25m"),
+				corev1.ResourceCPU: resource.MustParse("25m"),
 			}
 			c.ReadinessProbe = &corev1.Probe{
 				Handler: corev1.Handler{
diff --git a/pkg/reconciler/route/resources/ingress_test.go b/pkg/reconciler/route/resources/ingress_test.go
index 88fe7003e..d94dc057c 100644
--- a/pkg/reconciler/route/resources/ingress_test.go
+++ b/pkg/reconciler/route/resources/ingress_test.go
@@ -306,6 +306,178 @@ func TestMakeIngressSpec_CorrectRuleVisibility(t *testing.T) {
 	}
 }
 
+func TestMakeIngressSpec_CorrectRulesWithTagBasedRouting(t *testing.T) {
+	targets := map[string]traffic.RevisionTargets{
+		traffic.DefaultTarget: {{
+			TrafficTarget: v1.TrafficTarget{
+				ConfigurationName: "config",
+				RevisionName:      "v2",
+				Percent:           ptr.Int64(100),
+			},
+			ServiceName: "gilberto",
+			Active:      true,
+		}},
+		"v1": {{
+			TrafficTarget: v1.TrafficTarget{
+				ConfigurationName: "config",
+				RevisionName:      "v1",
+				Percent:           ptr.Int64(100),
+			},
+			ServiceName: "jobim",
+			Active:      true,
+		}},
+	}
+
+	r := Route(ns, "test-route", WithURL)
+
+	expected := []netv1alpha1.IngressRule{{
+		Hosts: []string{
+			"test-route." + ns + ".svc.cluster.local",
+		},
+		HTTP: &netv1alpha1.HTTPIngressRuleValue{
+			Paths: []netv1alpha1.HTTPIngressPath{{
+				Headers: map[string]netv1alpha1.HeaderMatch{
+					network.TagHeaderName: {
+						Exact: "v1",
+					},
+				},
+				Splits: []netv1alpha1.IngressBackendSplit{{
+					IngressBackend: netv1alpha1.IngressBackend{
+						ServiceNamespace: ns,
+						ServiceName:      "jobim",
+						ServicePort:      intstr.FromInt(80),
+					},
+					Percent: 100,
+					AppendHeaders: map[string]string{
+						"Knative-Serving-Revision":  "v1",
+						"Knative-Serving-Namespace": ns,
+					},
+				}},
+			}, {
+				AppendHeaders: map[string]string{
+					network.DefaultRouteHeaderName: "true",
+				},
+				Splits: []netv1alpha1.IngressBackendSplit{{
+					IngressBackend: netv1alpha1.IngressBackend{
+						ServiceNamespace: ns,
+						ServiceName:      "gilberto",
+						ServicePort:      intstr.FromInt(80),
+					},
+					Percent: 100,
+					AppendHeaders: map[string]string{
+						"Knative-Serving-Revision":  "v2",
+						"Knative-Serving-Namespace": ns,
+					},
+				}},
+			}},
+		},
+		Visibility: netv1alpha1.IngressVisibilityClusterLocal,
+	}, {
+		Hosts: []string{
+			"test-route." + ns + ".example.com",
+		},
+		HTTP: &netv1alpha1.HTTPIngressRuleValue{
+			Paths: []netv1alpha1.HTTPIngressPath{{
+				Headers: map[string]netv1alpha1.HeaderMatch{
+					network.TagHeaderName: {
+						Exact: "v1",
+					},
+				},
+				Splits: []netv1alpha1.IngressBackendSplit{{
+					IngressBackend: netv1alpha1.IngressBackend{
+						ServiceNamespace: ns,
+						ServiceName:      "jobim",
+						ServicePort:      intstr.FromInt(80),
+					},
+					Percent: 100,
+					AppendHeaders: map[string]string{
+						"Knative-Serving-Revision":  "v1",
+						"Knative-Serving-Namespace": ns,
+					},
+				}},
+			}, {
+				AppendHeaders: map[string]string{
+					network.DefaultRouteHeaderName: "true",
+				},
+				Splits: []netv1alpha1.IngressBackendSplit{{
+					IngressBackend: netv1alpha1.IngressBackend{
+						ServiceNamespace: ns,
+						ServiceName:      "gilberto",
+						ServicePort:      intstr.FromInt(80),
+					},
+					Percent: 100,
+					AppendHeaders: map[string]string{
+						"Knative-Serving-Revision":  "v2",
+						"Knative-Serving-Namespace": ns,
+					},
+				}},
+			}},
+		},
+		Visibility: netv1alpha1.IngressVisibilityExternalIP,
+	}, {
+		Hosts: []string{
+			"v1-test-route." + ns + ".svc.cluster.local",
+		},
+		HTTP: &netv1alpha1.HTTPIngressRuleValue{
+			Paths: []netv1alpha1.HTTPIngressPath{{
+				AppendHeaders: map[string]string{
+					network.TagHeaderName: "v1",
+				},
+				Splits: []netv1alpha1.IngressBackendSplit{{
+					IngressBackend: netv1alpha1.IngressBackend{
+						ServiceNamespace: ns,
+						ServiceName:      "jobim",
+						ServicePort:      intstr.FromInt(80),
+					},
+					Percent: 100,
+					AppendHeaders: map[string]string{
+						"Knative-Serving-Revision":  "v1",
+						"Knative-Serving-Namespace": ns,
+					},
+				}},
+			}},
+		},
+		Visibility: netv1alpha1.IngressVisibilityClusterLocal,
+	}, {
+		Hosts: []string{
+			"v1-test-route." + ns + ".example.com",
+		},
+		HTTP: &netv1alpha1.HTTPIngressRuleValue{
+			Paths: []netv1alpha1.HTTPIngressPath{{
+				AppendHeaders: map[string]string{
+					network.TagHeaderName: "v1",
+				},
+				Splits: []netv1alpha1.IngressBackendSplit{{
+					IngressBackend: netv1alpha1.IngressBackend{
+						ServiceNamespace: ns,
+						ServiceName:      "jobim",
+						ServicePort:      intstr.FromInt(80),
+					},
+					Percent: 100,
+					AppendHeaders: map[string]string{
+						"Knative-Serving-Revision":  "v1",
+						"Knative-Serving-Namespace": ns,
+					},
+				}},
+			}},
+		},
+		Visibility: netv1alpha1.IngressVisibilityExternalIP,
+	}}
+
+	cfg := testConfig()
+	cfg.Network.TagHeaderBasedRouting = true
+	ctx := config.ToContext(context.Background(), cfg)
+
+	ci, err := MakeIngressSpec(ctx, r, nil, targets, nil /* visibility */)
+	if err != nil {
+		t.Errorf("Unexpected error %v", err)
+	}
+
+	if !cmp.Equal(expected, ci.Rules) {
+		t.Errorf("Unexpected rules (-want, +got): %s", cmp.Diff(expected, ci.Rules))
+	}
+}
+
 // One active target.
 func TestMakeIngressRule_Vanilla(t *testing.T) {
 	targets := []traffic.RevisionTarget{{
diff --git a/pkg/reconciler/route/route_test.go b/pkg/reconciler/route/route_test.go
index 585da1d18..3e19d4e5a 100644
--- a/pkg/reconciler/route/route_test.go
+++ b/pkg/reconciler/route/route_test.go
@@ -51,6 +51,7 @@ import (
 	"knative.dev/pkg/controller"
 	"knative.dev/pkg/ptr"
 	"knative.dev/pkg/system"
+	"knative.dev/serving/pkg/apis/networking/v1alpha1"
 	netv1alpha1 "knative.dev/serving/pkg/apis/networking/v1alpha1"
 	"knative.dev/serving/pkg/apis/serving"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
@@ -989,6 +990,314 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 	}
 }
 
+func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
+	ctx, _, ctl, watcher, cf := newTestSetup(t)
+	defer cf()
+
+	watcher.OnChange(&corev1.ConfigMap{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      network.ConfigName,
+			Namespace: system.Namespace(),
+		},
+		Data: map[string]string{
+			network.TagHeaderBasedRoutingKey: "enabled",
+		},
+	})
+	// A standalone revision
+	rev := getTestRevision("test-rev")
+	fakeservingclient.Get(ctx).ServingV1().Revisions(testNamespace).Create(rev)
+	fakerevisioninformer.Get(ctx).Informer().GetIndexer().Add(rev)
+
+	// A configuration and associated revision. Normally the revision would be
+	// created by the configuration reconciler.
+	config := getTestConfiguration()
+	cfgrev := getTestRevisionForConfig(config)
+	config.Status.SetLatestCreatedRevisionName(cfgrev.Name)
+	config.Status.SetLatestReadyRevisionName(cfgrev.Name)
+	fakeservingclient.Get(ctx).ServingV1().Configurations(testNamespace).Create(config)
+	// Since Reconcile looks in the lister, we need to add it to the informer
+	fakecfginformer.Get(ctx).Informer().GetIndexer().Add(config)
+	fakeservingclient.Get(ctx).ServingV1().Revisions(testNamespace).Create(cfgrev)
+	fakerevisioninformer.Get(ctx).Informer().GetIndexer().Add(cfgrev)
+
+	// A route targeting both the config and standalone revision with named
+	// targets
+	route := getTestRouteWithTrafficTargets(WithSpecTraffic(
+		v1.TrafficTarget{
+			Tag:          "foo",
+			RevisionName: "test-rev",
+			Percent:      ptr.Int64(50),
+		}, v1.TrafficTarget{
+			Tag:               "bar",
+			ConfigurationName: "test-config",
+			Percent:           ptr.Int64(50),
+		}))
+
+	fakeservingclient.Get(ctx).ServingV1().Routes(testNamespace).Create(route)
+	// Since Reconcile looks in the lister, we need to add it to the informer
+	fakerouteinformer.Get(ctx).Informer().GetIndexer().Add(route)
+
+	ctl.Reconciler.Reconcile(context.Background(), KeyOrDie(route))
+
+	ci := getRouteIngressFromClient(ctx, t, route)
+	domain := strings.Join([]string{route.Name, route.Namespace, defaultDomainSuffix}, ".")
+	expectedSpec := netv1alpha1.IngressSpec{
+		TLS: []netv1alpha1.IngressTLS{},
+		Rules: []netv1alpha1.IngressRule{{
+			Hosts: []string{
+				"test-route.test.svc.cluster.local",
+			},
+			HTTP: &netv1alpha1.HTTPIngressRuleValue{
+				Paths: []netv1alpha1.HTTPIngressPath{{
+					Headers: map[string]netv1alpha1.HeaderMatch{
+						network.TagHeaderName: {
+							Exact: "bar",
+						},
+					},
+					Splits: []v1alpha1.IngressBackendSplit{
+						{
+							IngressBackend: v1alpha1.IngressBackend{
+								ServiceNamespace: "test",
+								ServiceName:      "p-deadbeef",
+								ServicePort:      intstr.IntOrString{IntVal: 80},
+							},
+							Percent: 100,
+							AppendHeaders: map[string]string{
+								"Knative-Serving-Namespace": "test",
+								"Knative-Serving-Revision":  "p-deadbeef",
+							},
+						},
+					},
+				}, {
+					Headers: map[string]netv1alpha1.HeaderMatch{
+						network.TagHeaderName: {
+							Exact: "foo",
+						},
+					},
+					Splits: []v1alpha1.IngressBackendSplit{
+						{
+							IngressBackend: v1alpha1.IngressBackend{
+								ServiceNamespace: "test",
+								ServiceName:      "test-rev",
+								ServicePort:      intstr.IntOrString{IntVal: 80},
+							},
+							Percent: 100,
+							AppendHeaders: map[string]string{
+								"Knative-Serving-Namespace": "test",
+								"Knative-Serving-Revision":  "test-rev",
+							},
+						},
+					},
+				}, {
+					AppendHeaders: map[string]string{
+						network.DefaultRouteHeaderName: "true",
+					},
+					Splits: []netv1alpha1.IngressBackendSplit{{
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      rev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 50,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  rev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}, {
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      cfgrev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 50,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  cfgrev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}},
+				}},
+			},
+			Visibility: netv1alpha1.IngressVisibilityClusterLocal,
+		}, {
+			Hosts: []string{
+				domain,
+			},
+			HTTP: &netv1alpha1.HTTPIngressRuleValue{
+				Paths: []netv1alpha1.HTTPIngressPath{{
+					Headers: map[string]netv1alpha1.HeaderMatch{
+						network.TagHeaderName: {
+							Exact: "bar",
+						},
+					},
+					Splits: []v1alpha1.IngressBackendSplit{
+						{
+							IngressBackend: v1alpha1.IngressBackend{
+								ServiceNamespace: "test",
+								ServiceName:      "p-deadbeef",
+								ServicePort:      intstr.IntOrString{IntVal: 80},
+							},
+							Percent: 100,
+							AppendHeaders: map[string]string{
+								"Knative-Serving-Namespace": "test",
+								"Knative-Serving-Revision":  "p-deadbeef",
+							},
+						},
+					},
+				}, {
+					Headers: map[string]netv1alpha1.HeaderMatch{
+						network.TagHeaderName: {
+							Exact: "foo",
+						},
+					},
+					Splits: []v1alpha1.IngressBackendSplit{
+						{
+							IngressBackend: v1alpha1.IngressBackend{
+								ServiceNamespace: "test",
+								ServiceName:      "test-rev",
+								ServicePort:      intstr.IntOrString{IntVal: 80},
+							},
+							Percent: 100,
+							AppendHeaders: map[string]string{
+								"Knative-Serving-Namespace": "test",
+								"Knative-Serving-Revision":  "test-rev",
+							},
+						},
+					},
+				}, {
+					AppendHeaders: map[string]string{
+						network.DefaultRouteHeaderName: "true",
+					},
+					Splits: []netv1alpha1.IngressBackendSplit{{
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      rev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 50,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  rev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}, {
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      cfgrev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 50,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  cfgrev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}},
+				}},
+			},
+			Visibility: netv1alpha1.IngressVisibilityExternalIP,
+		}, {
+			Hosts: []string{
+				"bar-test-route.test.svc.cluster.local",
+			},
+			HTTP: &netv1alpha1.HTTPIngressRuleValue{
+				Paths: []netv1alpha1.HTTPIngressPath{{
+					Splits: []netv1alpha1.IngressBackendSplit{{
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      cfgrev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 100,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  cfgrev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}},
+					AppendHeaders: map[string]string{
+						network.TagHeaderName: "bar",
+					},
+				}},
+			},
+			Visibility: netv1alpha1.IngressVisibilityClusterLocal,
+		}, {
+			Hosts: []string{
+				"bar-test-route.test.test-domain.dev",
+			},
+			HTTP: &netv1alpha1.HTTPIngressRuleValue{
+				Paths: []netv1alpha1.HTTPIngressPath{{
+					Splits: []netv1alpha1.IngressBackendSplit{{
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      cfgrev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 100,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  cfgrev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}},
+					AppendHeaders: map[string]string{
+						network.TagHeaderName: "bar",
+					},
+				}},
+			},
+			Visibility: netv1alpha1.IngressVisibilityExternalIP,
+		}, {
+			Hosts: []string{
+				"foo-test-route.test.svc.cluster.local",
+			},
+			HTTP: &netv1alpha1.HTTPIngressRuleValue{
+				Paths: []netv1alpha1.HTTPIngressPath{{
+					Splits: []netv1alpha1.IngressBackendSplit{{
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      rev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 100,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  rev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}},
+					AppendHeaders: map[string]string{
+						network.TagHeaderName: "foo",
+					},
+				}},
+			},
+			Visibility: netv1alpha1.IngressVisibilityClusterLocal,
+		}, {
+			Hosts: []string{
+				"foo-test-route.test.test-domain.dev",
+			},
+			HTTP: &netv1alpha1.HTTPIngressRuleValue{
+				Paths: []netv1alpha1.HTTPIngressPath{{
+					Splits: []netv1alpha1.IngressBackendSplit{{
+						IngressBackend: netv1alpha1.IngressBackend{
+							ServiceNamespace: testNamespace,
+							ServiceName:      rev.Name,
+							ServicePort:      intstr.FromInt(80),
+						},
+						Percent: 100,
+						AppendHeaders: map[string]string{
+							"Knative-Serving-Revision":  rev.Name,
+							"Knative-Serving-Namespace": testNamespace,
+						},
+					}},
+					AppendHeaders: map[string]string{
+						network.TagHeaderName: "foo",
+					},
+				}},
+			},
+			Visibility: netv1alpha1.IngressVisibilityExternalIP,
+		}},
+	}
+
+	if diff := cmp.Diff(expectedSpec, ci.Spec); diff != "" {
+		fmt.Printf("%+v\n", ci.Spec)
+		t.Errorf("Unexpected rule spec diff (-want +got): %v", diff)
+	}
+}
+
 func TestUpdateDomainConfigMap(t *testing.T) {
 	templateCM := corev1.ConfigMap{
 		ObjectMeta: metav1.ObjectMeta{
diff --git a/test/conformance/api/v1/revision_timeout_test.go b/test/conformance/api/v1/revision_timeout_test.go
index 183ceba92..22a834013 100644
--- a/test/conformance/api/v1/revision_timeout_test.go
+++ b/test/conformance/api/v1/revision_timeout_test.go
@@ -19,21 +19,18 @@ limitations under the License.
 package v1
 
 import (
-	"encoding/json"
 	"fmt"
 	"net/http"
 	"net/url"
 	"testing"
 	"time"
 
-	"github.com/mattbaird/jsonpatch"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/types"
-	"knative.dev/pkg/ptr"
 	pkgTest "knative.dev/pkg/test"
 	v1 "knative.dev/serving/pkg/apis/serving/v1"
-	serviceresourcenames "knative.dev/serving/pkg/reconciler/service/resources/names"
+	revisionresourcenames "knative.dev/serving/pkg/reconciler/revision/resources/names"
 	"knative.dev/serving/test"
+	"knative.dev/serving/test/e2e"
 	v1test "knative.dev/serving/test/v1"
 
 	. "knative.dev/serving/pkg/testing/v1"
@@ -47,20 +44,6 @@ func createService(t *testing.T, clients *test.Clients, names test.ResourceNames
 	return clients.ServingClient.Services.Create(service)
 }
 
-func updateServiceWithTimeout(clients *test.Clients, names test.ResourceNames, revisionTimeoutSeconds int64) error {
-	patches := []jsonpatch.JsonPatchOperation{{
-		Operation: "replace",
-		Path:      "/spec/template/spec/timeoutSeconds",
-		Value:     revisionTimeoutSeconds,
-	}}
-	patchBytes, err := json.Marshal(patches)
-	if err != nil {
-		return err
-	}
-	_, err = clients.ServingClient.Services.Patch(names.Service, types.JSONPatchType, patchBytes, "")
-	return err
-}
-
 // sendRequests send a request to "endpoint", returns error if unexpected response code, nil otherwise.
 func sendRequest(t *testing.T, clients *test.Clients, endpoint *url.URL,
 	initialSleep, sleep time.Duration, expectedResponseCode int) error {
@@ -100,134 +83,119 @@ func TestRevisionTimeout(t *testing.T) {
 	t.Parallel()
 	clients := test.Setup(t)
 
-	var rev2s, rev5s test.ResourceNames
-	names := test.ResourceNames{
-		Service: test.ObjectNameForTest(t),
-		Image:   test.Timeout,
-	}
-
-	test.CleanupOnInterrupt(func() { test.TearDown(clients, names) })
-	defer test.TearDown(clients, names)
-
-	t.Log("Creating a new Service ")
-	svc, err := createService(t, clients, names, 2)
-	if err != nil {
-		t.Fatal("Failed to create Service:", err)
-	}
-	names.Route = serviceresourcenames.Route(svc)
-	names.Config = serviceresourcenames.Configuration(svc)
-
-	t.Log("The Service will be updated with the name of the Revision once it is created")
-	revisionName, err := v1test.WaitForServiceLatestRevision(clients, names)
-	if err != nil {
-		t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err)
-	}
-	rev2s.Revision = revisionName
-
-	t.Log("When the Service reports as Ready, everything should be ready")
-	if err := v1test.WaitForServiceState(clients.ServingClient, names.Service, v1test.IsServiceReady, "ServiceIsReady"); err != nil {
-		t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err)
-	}
-
-	t.Log("Updating the Service to use a different revision timeout")
-	err = updateServiceWithTimeout(clients, names, 5)
-	if err != nil {
-		t.Fatalf("Patch update for Service %s with new timeout 5s failed: %v", names.Service, err)
-	}
-
-	// getNextRevisionName waits for names.Revision to change, so we set it to the rev2s revision and wait for the (new) rev5s revision.
-	names.Revision = rev2s.Revision
-
-	t.Log("Since the Service was updated a new Revision will be created and the Service will be updated")
-	rev5s.Revision, err = v1test.WaitForServiceLatestRevision(clients, names)
-	if err != nil {
-		t.Fatalf("Service %s was not updated with the Revision with timeout 5s: %v", names.Service, err)
-	}
-
-	t.Logf("Waiting for revision %q to be ready", rev2s.Revision)
-	if err := v1test.WaitForRevisionState(clients.ServingClient, rev2s.Revision, v1test.IsRevisionReady, "RevisionIsReady"); err != nil {
-		t.Fatalf("The Revision %q still can't serve traffic: %v", rev2s.Revision, err)
-	}
-	t.Logf("Waiting for revision %q to be ready", rev5s.Revision)
-	if err := v1test.WaitForRevisionState(clients.ServingClient, rev5s.Revision, v1test.IsRevisionReady, "RevisionIsReady"); err != nil {
-		t.Fatalf("The Revision %q still can't serve traffic: %v", rev5s.Revision, err)
-	}
-
-	// Set names for traffic targets to make them directly routable.
-	rev2s.TrafficTarget = "rev2s"
-	rev5s.TrafficTarget = "rev5s"
-
-	t.Log("Updating RouteSpec")
-	if _, err := v1test.UpdateServiceRouteSpec(t, clients, names, v1.RouteSpec{
-		Traffic: []v1.TrafficTarget{{
-			Tag:          rev2s.TrafficTarget,
-			RevisionName: rev2s.Revision,
-			Percent:      ptr.Int64(50),
-		}, {
-			Tag:          rev5s.TrafficTarget,
-			RevisionName: rev5s.Revision,
-			Percent:      ptr.Int64(50),
-		}},
-	}); err != nil {
-		t.Fatal("Failed to update Service:", err)
-	}
-
-	t.Log("Wait for the service domains to be ready")
-	if err := v1test.WaitForServiceState(clients.ServingClient, names.Service, v1test.IsServiceReady, "ServiceIsReady"); err != nil {
-		t.Fatalf("The Service %s was not marked as Ready to serve traffic: %v", names.Service, err)
-	}
-
-	service, err := clients.ServingClient.Services.Get(names.Service, metav1.GetOptions{})
-	if err != nil {
-		t.Fatalf("Error fetching Service %s: %v", names.Service, err)
-	}
-
-	var rev2sURL, rev5sURL *url.URL
-	for _, tt := range service.Status.Traffic {
-		if tt.Tag == rev2s.TrafficTarget {
-			rev2sURL = tt.URL.URL()
-		}
-		if tt.Tag == rev5s.TrafficTarget {
-			rev5sURL = tt.URL.URL()
-		}
-	}
-	if rev2sURL == nil || rev5sURL == nil {
-		t.Fatalf("Unable to fetch URLs from traffic targets: %#v", service.Status.Traffic)
-	}
-
-	t.Log("Probing", rev5sURL)
-	if _, err := pkgTest.WaitForEndpointState(
-		clients.KubeClient,
-		t.Logf,
-		rev5sURL,
-		v1test.RetryingRouteInconsistency(pkgTest.IsStatusOK),
-		"WaitForSuccessfulResponse",
-		test.ServingFlags.ResolvableDomain,
-		test.AddRootCAtoTransport(t.Logf, clients, test.ServingFlags.Https)); err != nil {
-		t.Fatalf("Error probing %s: %v", rev5sURL, err)
-	}
-
-	// Quick sanity check
-	if err := sendRequest(t, clients, rev2sURL, 0, 0, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 0s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 0, 0, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 0s with revision timeout 5s: %v", err)
-	}
-
-	// Fail by surpassing the initial timeout.
-	if err := sendRequest(t, clients, rev2sURL, 5*time.Second, 0, http.StatusGatewayTimeout); err != nil {
-		t.Errorf("Did not fail request with sleep 5s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 7*time.Second, 0, http.StatusGatewayTimeout); err != nil {
-		t.Errorf("Did not fail request with sleep 7s with revision timeout 5s: %v", err)
-	}
+	testCases := []struct {
+		name           string
+		shouldScaleTo0 bool
+		timeoutSeconds int64
+		expectedStatus int
+		initialSleep   int
+		sleep          int
+	}{{
+		name:           "when scaling up from 0 and does not exceed timeout seconds",
+		shouldScaleTo0: true,
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          0,
+	}, {
+		name:           "when scaling up from 0 and it writes first byte before timeout",
+		shouldScaleTo0: true,
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          15,
+	}, {
+		name:           "when scaling up from 0 and it does exceed timeout seconds",
+		shouldScaleTo0: true,
+		timeoutSeconds: 1, // If the pods come up faster than 1s, this test might fail.
+		expectedStatus: http.StatusGatewayTimeout,
+	}, {
+		name:           "when pods already exist, and it does not exceed timeout seconds",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   2,
+		sleep:          0,
+	}, {
+		name:           "when pods already exist, and it does exceed timeout seconds",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusGatewayTimeout,
+		initialSleep:   12,
+		sleep:          0,
+	}, {
+		name:           "when pods already exist, and it writes first byte before timeout",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          15,
+	}}
 
-	// Not fail by not surpassing in the initial timeout, but in the overall request duration.
-	if err := sendRequest(t, clients, rev2sURL, time.Second, 3*time.Second, http.StatusOK); err != nil {
-		t.Errorf("Did not fail request with sleep 1s/3s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 3*time.Second, 3*time.Second, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 3s/3s with revision timeout 5s: %v", err)
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			names := test.ResourceNames{
+				Service: test.ObjectNameForTest(t),
+				Image:   test.Timeout,
+			}
+
+			test.CleanupOnInterrupt(func() { test.TearDown(clients, names) })
+			defer test.TearDown(clients, names)
+
+			t.Log("Creating a new Service ")
+			_, err := createService(t, clients, names, tc.timeoutSeconds)
+			if err != nil {
+				t.Fatal("Failed to create Service:", err)
+			}
+
+			t.Log("The Service will be updated with the name of the Revision once it is created")
+			revisionName, err := v1test.WaitForServiceLatestRevision(clients, names)
+			if err != nil {
+				t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err)
+			}
+			names.Revision = revisionName
+
+			t.Log("When the Service reports as Ready, everything should be ready")
+			if err := v1test.WaitForServiceState(clients.ServingClient, names.Service, v1test.IsServiceReady, "ServiceIsReady"); err != nil {
+				t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err)
+			}
+
+			service, err := clients.ServingClient.Services.Get(names.Service, metav1.GetOptions{})
+			if err != nil {
+				t.Fatalf("Error fetching Service %s: %v", names.Service, err)
+			}
+
+			if service.Status.URL == nil {
+				t.Fatalf("Unable to fetch URLs from service: %#v", service.Status)
+			}
+
+			serviceURL := url.URL(*service.Status.URL)
+
+			if tc.shouldScaleTo0 {
+				t.Log("Waiting to scale down to 0")
+				revision, err := clients.ServingClient.Revisions.Get(names.Revision, metav1.GetOptions{})
+				if err != nil {
+					t.Fatalf("Error fetching Service %s: %v", names.Service, err)
+				}
+
+				if err := e2e.WaitForScaleToZero(t, revisionresourcenames.Deployment(revision), clients); err != nil {
+					t.Fatal("Could not scale to zero:", err)
+				}
+			} else {
+				t.Log("Probing to force at least one pod", serviceURL.String())
+				if _, err := pkgTest.WaitForEndpointState(
+					clients.KubeClient,
+					t.Logf,
+					&serviceURL,
+					v1test.RetryingRouteInconsistency(pkgTest.IsOneOfStatusCodes(http.StatusOK, http.StatusGatewayTimeout)),
+					"WaitForSuccessfulResponse",
+					test.ServingFlags.ResolvableDomain,
+					test.AddRootCAtoTransport(t.Logf, clients, test.ServingFlags.Https)); err != nil {
+					t.Fatalf("Error probing %s: %v", &serviceURL, err)
+				}
+			}
+
+			if err := sendRequest(t, clients, &serviceURL, time.Duration(tc.initialSleep)*time.Second, time.Duration(tc.sleep)*time.Second, tc.expectedStatus); err != nil {
+				t.Errorf("Failed request with intialSleep %ds, sleep %ds, with revision timeout %ds and expecting status %v: %v",
+					tc.initialSleep, tc.sleep, tc.timeoutSeconds, tc.expectedStatus, err)
+			}
+		})
 	}
 }
diff --git a/test/conformance/api/v1alpha1/revision_timeout_test.go b/test/conformance/api/v1alpha1/revision_timeout_test.go
index c1713fc6f..65763f079 100644
--- a/test/conformance/api/v1alpha1/revision_timeout_test.go
+++ b/test/conformance/api/v1alpha1/revision_timeout_test.go
@@ -19,22 +19,18 @@ limitations under the License.
 package v1alpha1
 
 import (
-	"encoding/json"
 	"fmt"
 	"net/http"
 	"net/url"
 	"testing"
 	"time"
 
-	"github.com/mattbaird/jsonpatch"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/types"
-	"knative.dev/pkg/ptr"
 	pkgTest "knative.dev/pkg/test"
-	v1 "knative.dev/serving/pkg/apis/serving/v1"
 	"knative.dev/serving/pkg/apis/serving/v1alpha1"
-	serviceresourcenames "knative.dev/serving/pkg/reconciler/service/resources/names"
+	revisionresourcenames "knative.dev/serving/pkg/reconciler/revision/resources/names"
 	"knative.dev/serving/test"
+	"knative.dev/serving/test/e2e"
 	v1a1test "knative.dev/serving/test/v1alpha1"
 
 	. "knative.dev/serving/pkg/testing/v1alpha1"
@@ -48,20 +44,6 @@ func createLatestService(t *testing.T, clients *test.Clients, names test.Resourc
 	return clients.ServingAlphaClient.Services.Create(service)
 }
 
-func updateServiceWithTimeout(clients *test.Clients, names test.ResourceNames, revisionTimeoutSeconds int64) error {
-	patches := []jsonpatch.JsonPatchOperation{{
-		Operation: "replace",
-		Path:      "/spec/template/spec/timeoutSeconds",
-		Value:     revisionTimeoutSeconds,
-	}}
-	patchBytes, err := json.Marshal(patches)
-	if err != nil {
-		return err
-	}
-	_, err = clients.ServingAlphaClient.Services.Patch(names.Service, types.JSONPatchType, patchBytes, "")
-	return err
-}
-
 // sendRequests send a request to "endpoint", returns error if unexpected response code, nil otherwise.
 func sendRequest(t *testing.T, clients *test.Clients, endpoint *url.URL,
 	initialSleep, sleep time.Duration, expectedResponseCode int) error {
@@ -101,138 +83,119 @@ func TestRevisionTimeout(t *testing.T) {
 	t.Parallel()
 	clients := test.Setup(t)
 
-	var rev2s, rev5s test.ResourceNames
-	names := test.ResourceNames{
-		Service: test.ObjectNameForTest(t),
-		Image:   test.Timeout,
-	}
-
-	test.CleanupOnInterrupt(func() { test.TearDown(clients, names) })
-	defer test.TearDown(clients, names)
-
-	t.Log("Creating a new Service in runLatest")
-	svc, err := createLatestService(t, clients, names, 2)
-	if err != nil {
-		t.Fatal("Failed to create Service:", err)
-	}
-	names.Route = serviceresourcenames.Route(svc)
-	names.Config = serviceresourcenames.Configuration(svc)
-
-	t.Log("The Service will be updated with the name of the Revision once it is created")
-	revisionName, err := v1a1test.WaitForServiceLatestRevision(clients, names)
-	if err != nil {
-		t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err)
-	}
-	rev2s.Revision = revisionName
-
-	t.Log("When the Service reports as Ready, everything should be ready")
-	if err := v1a1test.WaitForServiceState(clients.ServingAlphaClient, names.Service, v1a1test.IsServiceReady, "ServiceIsReady"); err != nil {
-		t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err)
-	}
-
-	t.Log("Updating the Service to use a different revision timeout")
-	err = updateServiceWithTimeout(clients, names, 5)
-	if err != nil {
-		t.Fatalf("Patch update for Service %s with new timeout 5s failed: %v", names.Service, err)
-	}
-
-	// getNextRevisionName waits for names.Revision to change, so we set it to the rev2s revision and wait for the (new) rev5s revision.
-	names.Revision = rev2s.Revision
-
-	t.Log("Since the Service was updated a new Revision will be created and the Service will be updated")
-	rev5s.Revision, err = v1a1test.WaitForServiceLatestRevision(clients, names)
-	if err != nil {
-		t.Fatalf("Service %s was not updated with the Revision with timeout 5s: %v", names.Service, err)
-	}
-
-	t.Logf("Waiting for revision %q to be ready", rev2s.Revision)
-	if err := v1a1test.WaitForRevisionState(clients.ServingAlphaClient, rev2s.Revision, v1a1test.IsRevisionReady, "RevisionIsReady"); err != nil {
-		t.Fatalf("The Revision %q still can't serve traffic: %v", rev2s.Revision, err)
-	}
-	t.Logf("Waiting for revision %q to be ready", rev5s.Revision)
-	if err := v1a1test.WaitForRevisionState(clients.ServingAlphaClient, rev5s.Revision, v1a1test.IsRevisionReady, "RevisionIsReady"); err != nil {
-		t.Fatalf("The Revision %q still can't serve traffic: %v", rev5s.Revision, err)
-	}
-
-	// Set names for traffic targets to make them directly routable.
-	rev2s.TrafficTarget = "rev2s"
-	rev5s.TrafficTarget = "rev5s"
-
-	t.Log("Updating RouteSpec")
-	if _, err := v1a1test.UpdateServiceRouteSpec(t, clients, names, v1alpha1.RouteSpec{
-		Traffic: []v1alpha1.TrafficTarget{{
-			TrafficTarget: v1.TrafficTarget{
-				Tag:          rev2s.TrafficTarget,
-				RevisionName: rev2s.Revision,
-				Percent:      ptr.Int64(50),
-			},
-		}, {
-			TrafficTarget: v1.TrafficTarget{
-				Tag:          rev5s.TrafficTarget,
-				RevisionName: rev5s.Revision,
-				Percent:      ptr.Int64(50),
-			},
-		}},
-	}); err != nil {
-		t.Fatal("Failed to update Service:", err)
-	}
-
-	t.Log("Wait for the service to be ready")
-	if err := v1a1test.WaitForServiceState(clients.ServingAlphaClient, names.Service, v1a1test.IsServiceReady, "ServiceIsReady"); err != nil {
-		t.Fatalf("The Service %s was not marked as Ready to serve traffic: %v", names.Service, err)
-	}
-
-	service, err := clients.ServingAlphaClient.Services.Get(names.Service, metav1.GetOptions{})
-	if err != nil {
-		t.Fatalf("Error fetching Service %s: %v", names.Service, err)
-	}
-
-	var rev2sURL, rev5sURL *url.URL
-	for _, tt := range service.Status.Traffic {
-		if tt.Tag == rev2s.TrafficTarget {
-			rev2sURL = tt.URL.URL()
-		}
-		if tt.Tag == rev5s.TrafficTarget {
-			rev5sURL = tt.URL.URL()
-		}
-	}
-	if rev2sURL == nil || rev5sURL == nil {
-		t.Fatalf("Unable to fetch URLs from traffic targets: %#v", service.Status.Traffic)
-	}
-
-	t.Log("Probing", rev5sURL)
-	if _, err := pkgTest.WaitForEndpointState(
-		clients.KubeClient,
-		t.Logf,
-		rev5sURL,
-		v1a1test.RetryingRouteInconsistency(pkgTest.IsStatusOK),
-		"WaitForSuccessfulResponse",
-		test.ServingFlags.ResolvableDomain,
-		test.AddRootCAtoTransport(t.Logf, clients, test.ServingFlags.Https)); err != nil {
-		t.Fatalf("Error probing %s: %v", rev5sURL, err)
-	}
-
-	// Quick sanity check
-	if err := sendRequest(t, clients, rev2sURL, 0, 0, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 0s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 0, 0, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 0s with revision timeout 5s: %v", err)
-	}
-
-	// Fail by surpassing the initial timeout.
-	if err := sendRequest(t, clients, rev2sURL, 5*time.Second, 0, http.StatusGatewayTimeout); err != nil {
-		t.Errorf("Did not fail request with sleep 5s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 7*time.Second, 0, http.StatusGatewayTimeout); err != nil {
-		t.Errorf("Did not fail request with sleep 7s with revision timeout 5s: %v", err)
-	}
+	testCases := []struct {
+		name           string
+		shouldScaleTo0 bool
+		timeoutSeconds int64
+		expectedStatus int
+		initialSleep   int
+		sleep          int
+	}{{
+		name:           "when scaling up from 0 and does not exceed timeout seconds",
+		shouldScaleTo0: true,
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          0,
+	}, {
+		name:           "when scaling up from 0 and it writes first byte before timeout",
+		shouldScaleTo0: true,
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          15,
+	}, {
+		name:           "when scaling up from 0 and it does exceed timeout seconds",
+		shouldScaleTo0: true,
+		timeoutSeconds: 1, // If the pods come up faster than 1s, this test might fail.
+		expectedStatus: http.StatusGatewayTimeout,
+	}, {
+		name:           "when pods already exist, and it does not exceed timeout seconds",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   2,
+		sleep:          0,
+	}, {
+		name:           "when pods already exist, and it does exceed timeout seconds",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusGatewayTimeout,
+		initialSleep:   12,
+		sleep:          0,
+	}, {
+		name:           "when pods already exist, and it writes first byte before timeout",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          15,
+	}}
 
-	// Not fail by not surpassing in the initial timeout, but in the overall request duration.
-	if err := sendRequest(t, clients, rev2sURL, time.Second, 3*time.Second, http.StatusOK); err != nil {
-		t.Errorf("Did not fail request with sleep 1s/3s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 3*time.Second, 3*time.Second, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 3s/3s with revision timeout 5s: %v", err)
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			names := test.ResourceNames{
+				Service: test.ObjectNameForTest(t),
+				Image:   test.Timeout,
+			}
+
+			test.CleanupOnInterrupt(func() { test.TearDown(clients, names) })
+			defer test.TearDown(clients, names)
+
+			t.Log("Creating a new Service ")
+			_, err := createLatestService(t, clients, names, tc.timeoutSeconds)
+			if err != nil {
+				t.Fatal("Failed to create Service:", err)
+			}
+
+			t.Log("The Service will be updated with the name of the Revision once it is created")
+			revisionName, err := v1a1test.WaitForServiceLatestRevision(clients, names)
+			if err != nil {
+				t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err)
+			}
+			names.Revision = revisionName
+
+			t.Log("When the Service reports as Ready, everything should be ready")
+			if err := v1a1test.WaitForServiceState(clients.ServingAlphaClient, names.Service, v1a1test.IsServiceReady, "ServiceIsReady"); err != nil {
+				t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err)
+			}
+
+			service, err := clients.ServingAlphaClient.Services.Get(names.Service, metav1.GetOptions{})
+			if err != nil {
+				t.Fatalf("Error fetching Service %s: %v", names.Service, err)
+			}
+
+			if service.Status.URL == nil {
+				t.Fatalf("Unable to fetch URLs from service: %#v", service.Status)
+			}
+
+			serviceURL := url.URL(*service.Status.URL)
+
+			if tc.shouldScaleTo0 {
+				t.Log("Waiting to scale down to 0")
+				revision, err := clients.ServingBetaClient.Revisions.Get(names.Revision, metav1.GetOptions{})
+				if err != nil {
+					t.Fatalf("Error fetching Service %s: %v", names.Service, err)
+				}
+
+				if err := e2e.WaitForScaleToZero(t, revisionresourcenames.Deployment(revision), clients); err != nil {
+					t.Fatal("Could not scale to zero:", err)
+				}
+			} else {
+				t.Log("Probing to force at least one pod", serviceURL.String())
+				if _, err := pkgTest.WaitForEndpointState(
+					clients.KubeClient,
+					t.Logf,
+					&serviceURL,
+					v1a1test.RetryingRouteInconsistency(pkgTest.IsOneOfStatusCodes(http.StatusOK, http.StatusGatewayTimeout)),
+					"WaitForSuccessfulResponse",
+					test.ServingFlags.ResolvableDomain,
+					test.AddRootCAtoTransport(t.Logf, clients, test.ServingFlags.Https)); err != nil {
+					t.Fatalf("Error probing %s: %v", &serviceURL, err)
+				}
+			}
+
+			if err := sendRequest(t, clients, &serviceURL, time.Duration(tc.initialSleep)*time.Second, time.Duration(tc.sleep)*time.Second, tc.expectedStatus); err != nil {
+				t.Errorf("Failed request with intialSleep %ds, sleep %ds, with revision timeout %ds and expecting status %v: %v",
+					tc.initialSleep, tc.sleep, tc.timeoutSeconds, tc.expectedStatus, err)
+			}
+		})
 	}
 }
diff --git a/test/conformance/api/v1beta1/revision_timeout_test.go b/test/conformance/api/v1beta1/revision_timeout_test.go
index 3cbacaa6d..2b1900fd0 100644
--- a/test/conformance/api/v1beta1/revision_timeout_test.go
+++ b/test/conformance/api/v1beta1/revision_timeout_test.go
@@ -19,22 +19,18 @@ limitations under the License.
 package v1beta1
 
 import (
-	"encoding/json"
 	"fmt"
 	"net/http"
 	"net/url"
 	"testing"
 	"time"
 
-	"github.com/mattbaird/jsonpatch"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/types"
-	"knative.dev/pkg/ptr"
 	pkgTest "knative.dev/pkg/test"
-	v1 "knative.dev/serving/pkg/apis/serving/v1"
 	"knative.dev/serving/pkg/apis/serving/v1beta1"
-	serviceresourcenames "knative.dev/serving/pkg/reconciler/service/resources/names"
+	revisionresourcenames "knative.dev/serving/pkg/reconciler/revision/resources/names"
 	"knative.dev/serving/test"
+	"knative.dev/serving/test/e2e"
 	v1b1test "knative.dev/serving/test/v1beta1"
 
 	. "knative.dev/serving/pkg/testing/v1beta1"
@@ -48,20 +44,6 @@ func createService(t *testing.T, clients *test.Clients, names test.ResourceNames
 	return clients.ServingBetaClient.Services.Create(service)
 }
 
-func updateServiceWithTimeout(clients *test.Clients, names test.ResourceNames, revisionTimeoutSeconds int64) error {
-	patches := []jsonpatch.JsonPatchOperation{{
-		Operation: "replace",
-		Path:      "/spec/template/spec/timeoutSeconds",
-		Value:     revisionTimeoutSeconds,
-	}}
-	patchBytes, err := json.Marshal(patches)
-	if err != nil {
-		return err
-	}
-	_, err = clients.ServingBetaClient.Services.Patch(names.Service, types.JSONPatchType, patchBytes, "")
-	return err
-}
-
 // sendRequests send a request to "endpoint", returns error if unexpected response code, nil otherwise.
 func sendRequest(t *testing.T, clients *test.Clients, endpoint *url.URL,
 	initialSleep, sleep time.Duration, expectedResponseCode int) error {
@@ -101,134 +83,119 @@ func TestRevisionTimeout(t *testing.T) {
 	t.Parallel()
 	clients := test.Setup(t)
 
-	var rev2s, rev5s test.ResourceNames
-	names := test.ResourceNames{
-		Service: test.ObjectNameForTest(t),
-		Image:   test.Timeout,
-	}
-
-	test.CleanupOnInterrupt(func() { test.TearDown(clients, names) })
-	defer test.TearDown(clients, names)
-
-	t.Log("Creating a new Service ")
-	svc, err := createService(t, clients, names, 2)
-	if err != nil {
-		t.Fatal("Failed to create Service:", err)
-	}
-	names.Route = serviceresourcenames.Route(svc)
-	names.Config = serviceresourcenames.Configuration(svc)
-
-	t.Log("The Service will be updated with the name of the Revision once it is created")
-	revisionName, err := v1b1test.WaitForServiceLatestRevision(clients, names)
-	if err != nil {
-		t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err)
-	}
-	rev2s.Revision = revisionName
-
-	t.Log("When the Service reports as Ready, everything should be ready")
-	if err := v1b1test.WaitForServiceState(clients.ServingBetaClient, names.Service, v1b1test.IsServiceReady, "ServiceIsReady"); err != nil {
-		t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err)
-	}
-
-	t.Log("Updating the Service to use a different revision timeout")
-	err = updateServiceWithTimeout(clients, names, 5)
-	if err != nil {
-		t.Fatalf("Patch update for Service %s with new timeout 5s failed: %v", names.Service, err)
-	}
-
-	// getNextRevisionName waits for names.Revision to change, so we set it to the rev2s revision and wait for the (new) rev5s revision.
-	names.Revision = rev2s.Revision
-
-	t.Log("Since the Service was updated a new Revision will be created and the Service will be updated")
-	rev5s.Revision, err = v1b1test.WaitForServiceLatestRevision(clients, names)
-	if err != nil {
-		t.Fatalf("Service %s was not updated with the Revision with timeout 5s: %v", names.Service, err)
-	}
-
-	t.Logf("Waiting for revision %q to be ready", rev2s.Revision)
-	if err := v1b1test.WaitForRevisionState(clients.ServingBetaClient, rev2s.Revision, v1b1test.IsRevisionReady, "RevisionIsReady"); err != nil {
-		t.Fatalf("The Revision %q still can't serve traffic: %v", rev2s.Revision, err)
-	}
-	t.Logf("Waiting for revision %q to be ready", rev5s.Revision)
-	if err := v1b1test.WaitForRevisionState(clients.ServingBetaClient, rev5s.Revision, v1b1test.IsRevisionReady, "RevisionIsReady"); err != nil {
-		t.Fatalf("The Revision %q still can't serve traffic: %v", rev5s.Revision, err)
-	}
-
-	// Set names for traffic targets to make them directly routable.
-	rev2s.TrafficTarget = "rev2s"
-	rev5s.TrafficTarget = "rev5s"
-
-	t.Log("Updating RouteSpec")
-	if _, err := v1b1test.UpdateServiceRouteSpec(t, clients, names, v1.RouteSpec{
-		Traffic: []v1.TrafficTarget{{
-			Tag:          rev2s.TrafficTarget,
-			RevisionName: rev2s.Revision,
-			Percent:      ptr.Int64(50),
-		}, {
-			Tag:          rev5s.TrafficTarget,
-			RevisionName: rev5s.Revision,
-			Percent:      ptr.Int64(50),
-		}},
-	}); err != nil {
-		t.Fatal("Failed to update Service:", err)
-	}
-
-	t.Log("Wait for the service domains to be ready")
-	if err := v1b1test.WaitForServiceState(clients.ServingBetaClient, names.Service, v1b1test.IsServiceReady, "ServiceIsReady"); err != nil {
-		t.Fatalf("The Service %s was not marked as Ready to serve traffic: %v", names.Service, err)
-	}
-
-	service, err := clients.ServingBetaClient.Services.Get(names.Service, metav1.GetOptions{})
-	if err != nil {
-		t.Fatalf("Error fetching Service %s: %v", names.Service, err)
-	}
-
-	var rev2sURL, rev5sURL *url.URL
-	for _, tt := range service.Status.Traffic {
-		if tt.Tag == rev2s.TrafficTarget {
-			rev2sURL = tt.URL.URL()
-		}
-		if tt.Tag == rev5s.TrafficTarget {
-			rev5sURL = tt.URL.URL()
-		}
-	}
-	if rev2sURL == nil || rev5sURL == nil {
-		t.Fatalf("Unable to fetch URLs from traffic targets: %#v", service.Status.Traffic)
-	}
-
-	t.Log("Probing", rev5sURL)
-	if _, err := pkgTest.WaitForEndpointState(
-		clients.KubeClient,
-		t.Logf,
-		rev5sURL,
-		v1b1test.RetryingRouteInconsistency(pkgTest.IsStatusOK),
-		"WaitForSuccessfulResponse",
-		test.ServingFlags.ResolvableDomain,
-		test.AddRootCAtoTransport(t.Logf, clients, test.ServingFlags.Https)); err != nil {
-		t.Fatalf("Error probing %s: %v", rev5sURL, err)
-	}
-
-	// Quick sanity check
-	if err := sendRequest(t, clients, rev2sURL, 0, 0, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 0s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 0, 0, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 0s with revision timeout 5s: %v", err)
-	}
-
-	// Fail by surpassing the initial timeout.
-	if err := sendRequest(t, clients, rev2sURL, 5*time.Second, 0, http.StatusGatewayTimeout); err != nil {
-		t.Errorf("Did not fail request with sleep 5s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 7*time.Second, 0, http.StatusGatewayTimeout); err != nil {
-		t.Errorf("Did not fail request with sleep 7s with revision timeout 5s: %v", err)
-	}
+	testCases := []struct {
+		name           string
+		shouldScaleTo0 bool
+		timeoutSeconds int64
+		expectedStatus int
+		initialSleep   int
+		sleep          int
+	}{{
+		name:           "when scaling up from 0 and does not exceed timeout seconds",
+		shouldScaleTo0: true,
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          0,
+	}, {
+		name:           "when scaling up from 0 and it writes first byte before timeout",
+		shouldScaleTo0: true,
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          15,
+	}, {
+		name:           "when scaling up from 0 and it does exceed timeout seconds",
+		shouldScaleTo0: true,
+		timeoutSeconds: 1, // If the pods come up faster than 1s, this test might fail.
+		expectedStatus: http.StatusGatewayTimeout,
+	}, {
+		name:           "when pods already exist, and it does not exceed timeout seconds",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   2,
+		sleep:          0,
+	}, {
+		name:           "when pods already exist, and it does exceed timeout seconds",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusGatewayTimeout,
+		initialSleep:   12,
+		sleep:          0,
+	}, {
+		name:           "when pods already exist, and it writes first byte before timeout",
+		timeoutSeconds: 10,
+		expectedStatus: http.StatusOK,
+		initialSleep:   0,
+		sleep:          15,
+	}}
 
-	// Not fail by not surpassing in the initial timeout, but in the overall request duration.
-	if err := sendRequest(t, clients, rev2sURL, time.Second, 3*time.Second, http.StatusOK); err != nil {
-		t.Errorf("Did not fail request with sleep 1s/3s with revision timeout 2s: %v", err)
-	}
-	if err := sendRequest(t, clients, rev5sURL, 3*time.Second, 3*time.Second, http.StatusOK); err != nil {
-		t.Errorf("Failed request with sleep 3s/3s with revision timeout 5s: %v", err)
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			names := test.ResourceNames{
+				Service: test.ObjectNameForTest(t),
+				Image:   test.Timeout,
+			}
+
+			test.CleanupOnInterrupt(func() { test.TearDown(clients, names) })
+			defer test.TearDown(clients, names)
+
+			t.Log("Creating a new Service ")
+			_, err := createService(t, clients, names, tc.timeoutSeconds)
+			if err != nil {
+				t.Fatal("Failed to create Service:", err)
+			}
+
+			t.Log("The Service will be updated with the name of the Revision once it is created")
+			revisionName, err := v1b1test.WaitForServiceLatestRevision(clients, names)
+			if err != nil {
+				t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err)
+			}
+			names.Revision = revisionName
+
+			t.Log("When the Service reports as Ready, everything should be ready")
+			if err := v1b1test.WaitForServiceState(clients.ServingBetaClient, names.Service, v1b1test.IsServiceReady, "ServiceIsReady"); err != nil {
+				t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err)
+			}
+
+			service, err := clients.ServingClient.Services.Get(names.Service, metav1.GetOptions{})
+			if err != nil {
+				t.Fatalf("Error fetching Service %s: %v", names.Service, err)
+			}
+
+			if service.Status.URL == nil {
+				t.Fatalf("Unable to fetch URLs from service: %#v", service.Status)
+			}
+
+			serviceURL := url.URL(*service.Status.URL)
+
+			if tc.shouldScaleTo0 {
+				t.Log("Waiting to scale down to 0")
+				revision, err := clients.ServingBetaClient.Revisions.Get(names.Revision, metav1.GetOptions{})
+				if err != nil {
+					t.Fatalf("Error fetching Service %s: %v", names.Service, err)
+				}
+
+				if err := e2e.WaitForScaleToZero(t, revisionresourcenames.Deployment(revision), clients); err != nil {
+					t.Fatal("Could not scale to zero:", err)
+				}
+			} else {
+				t.Log("Probing to force at least one pod", serviceURL.String())
+				if _, err := pkgTest.WaitForEndpointState(
+					clients.KubeClient,
+					t.Logf,
+					&serviceURL,
+					v1b1test.RetryingRouteInconsistency(pkgTest.IsOneOfStatusCodes(http.StatusOK, http.StatusGatewayTimeout)),
+					"WaitForSuccessfulResponse",
+					test.ServingFlags.ResolvableDomain,
+					test.AddRootCAtoTransport(t.Logf, clients, test.ServingFlags.Https)); err != nil {
+					t.Fatalf("Error probing %s: %v", &serviceURL, err)
+				}
+			}
+
+			if err := sendRequest(t, clients, &serviceURL, time.Duration(tc.initialSleep)*time.Second, time.Duration(tc.sleep)*time.Second, tc.expectedStatus); err != nil {
+				t.Errorf("Failed request with intialSleep %ds, sleep %ds, with revision timeout %ds and expecting status %v: %v",
+					tc.initialSleep, tc.sleep, tc.timeoutSeconds, tc.expectedStatus, err)
+			}
+		})
 	}
 }
diff --git a/test/conformance/certificate/http01/certificate_test.go b/test/conformance/certificate/http01/certificate.go
similarity index 99%
rename from test/conformance/certificate/http01/certificate_test.go
rename to test/conformance/certificate/http01/certificate.go
index 39bc27ba1..e63cefa11 100644
--- a/test/conformance/certificate/http01/certificate_test.go
+++ b/test/conformance/certificate/http01/certificate.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2020 The Knative Authors
 
diff --git a/test/conformance/certificate/http01/run.go b/test/conformance/certificate/http01/run.go
new file mode 100644
index 000000000..e57440166
--- /dev/null
+++ b/test/conformance/certificate/http01/run.go
@@ -0,0 +1,23 @@
+/*
+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 http01
+
+import "testing"
+
+func RunConformance(t *testing.T) {
+	t.Run("http01", TestHTTP01Challenge)
+}
diff --git a/test/conformance/certificate/http01/run_test.go b/test/conformance/certificate/http01/run_test.go
new file mode 100644
index 000000000..18bf81315
--- /dev/null
+++ b/test/conformance/certificate/http01/run_test.go
@@ -0,0 +1,25 @@
+// +build e2e
+
+/*
+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 http01
+
+import "testing"
+
+func TestCertificateConformance(t *testing.T) {
+	RunConformance(t)
+}
diff --git a/test/conformance/certificate/nonhttp01/certificate_test.go b/test/conformance/certificate/nonhttp01/certificate.go
similarity index 98%
rename from test/conformance/certificate/nonhttp01/certificate_test.go
rename to test/conformance/certificate/nonhttp01/certificate.go
index fda9a605e..90ac256f3 100644
--- a/test/conformance/certificate/nonhttp01/certificate_test.go
+++ b/test/conformance/certificate/nonhttp01/certificate.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2020 The Knative Authors
 
diff --git a/test/conformance/certificate/nonhttp01/run.go b/test/conformance/certificate/nonhttp01/run.go
new file mode 100644
index 000000000..60e4c7879
--- /dev/null
+++ b/test/conformance/certificate/nonhttp01/run.go
@@ -0,0 +1,23 @@
+/*
+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 nonhttp01
+
+import "testing"
+
+func RunConformance(t *testing.T) {
+	t.Run("secret", TestSecret)
+}
diff --git a/test/conformance/certificate/nonhttp01/run_test.go b/test/conformance/certificate/nonhttp01/run_test.go
new file mode 100644
index 000000000..64db2b152
--- /dev/null
+++ b/test/conformance/certificate/nonhttp01/run_test.go
@@ -0,0 +1,25 @@
+// +build e2e
+
+/*
+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 nonhttp01
+
+import "testing"
+
+func TestCertificateConformance(t *testing.T) {
+	RunConformance(t)
+}
diff --git a/test/conformance/ingress/basic_test.go b/test/conformance/ingress/basic.go
similarity index 99%
rename from test/conformance/ingress/basic_test.go
rename to test/conformance/ingress/basic.go
index 278e0af14..95bbc275d 100644
--- a/test/conformance/ingress/basic_test.go
+++ b/test/conformance/ingress/basic.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/grpc_test.go b/test/conformance/ingress/grpc.go
similarity index 99%
rename from test/conformance/ingress/grpc_test.go
rename to test/conformance/ingress/grpc.go
index 39dd33c2f..58e731273 100644
--- a/test/conformance/ingress/grpc_test.go
+++ b/test/conformance/ingress/grpc.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/headers_test.go b/test/conformance/ingress/headers.go
similarity index 99%
rename from test/conformance/ingress/headers_test.go
rename to test/conformance/ingress/headers.go
index f452abec4..e68e17f57 100644
--- a/test/conformance/ingress/headers_test.go
+++ b/test/conformance/ingress/headers.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/hosts_test.go b/test/conformance/ingress/hosts.go
similarity index 99%
rename from test/conformance/ingress/hosts_test.go
rename to test/conformance/ingress/hosts.go
index 5ccaebfc9..65359c19e 100644
--- a/test/conformance/ingress/hosts_test.go
+++ b/test/conformance/ingress/hosts.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/path_test.go b/test/conformance/ingress/path.go
similarity index 99%
rename from test/conformance/ingress/path_test.go
rename to test/conformance/ingress/path.go
index 25a8cb270..6c5951f96 100644
--- a/test/conformance/ingress/path_test.go
+++ b/test/conformance/ingress/path.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/percentage_test.go b/test/conformance/ingress/percentage.go
similarity index 99%
rename from test/conformance/ingress/percentage_test.go
rename to test/conformance/ingress/percentage.go
index cd67ad954..dd01ba03e 100644
--- a/test/conformance/ingress/percentage_test.go
+++ b/test/conformance/ingress/percentage.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/retry_test.go b/test/conformance/ingress/retry.go
similarity index 99%
rename from test/conformance/ingress/retry_test.go
rename to test/conformance/ingress/retry.go
index 3fd563b8d..22cf44d87 100644
--- a/test/conformance/ingress/retry_test.go
+++ b/test/conformance/ingress/retry.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/run.go b/test/conformance/ingress/run.go
new file mode 100644
index 000000000..50a0eb016
--- /dev/null
+++ b/test/conformance/ingress/run.go
@@ -0,0 +1,49 @@
+/*
+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 ingress
+
+import "testing"
+
+func RunConformance(t *testing.T) {
+	t.Run("basics", TestBasics)
+	t.Run("basics/http2", TestBasicsHTTP2)
+
+	t.Run("grpc", TestGRPC)
+	t.Run("grpc/split", TestGRPCSplit)
+
+	t.Run("headers/pre-split", TestPreSplitSetHeaders)
+	t.Run("headers/post-split", TestPostSplitSetHeaders)
+
+	t.Run("hosts/multiple", TestMultipleHosts)
+
+	t.Run("dispatch/path", TestPath)
+	t.Run("dispatch/percentage", TestPercentage)
+	t.Run("dispatch/path_and_percentage", TestPathAndPercentageSplit)
+
+	t.Run("retry", TestRetry)
+	t.Run("timeout", TestTimeout)
+
+	t.Run("tls", TestIngressTLS)
+	t.Run("update", TestUpdate)
+
+	t.Run("visibility", TestVisibility)
+	t.Run("visibility/split", TestVisibilitySplit)
+	t.Run("visibility/path", TestVisibilityPath)
+
+	t.Run("websocket", TestWebsocket)
+	t.Run("websocket/split", TestWebsocketSplit)
+}
diff --git a/test/conformance/ingress/run_test.go b/test/conformance/ingress/run_test.go
new file mode 100644
index 000000000..0ebadcce5
--- /dev/null
+++ b/test/conformance/ingress/run_test.go
@@ -0,0 +1,25 @@
+// +build e2e
+
+/*
+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 ingress
+
+import "testing"
+
+func TestIngressConformance(t *testing.T) {
+	RunConformance(t)
+}
diff --git a/test/conformance/ingress/timeout_test.go b/test/conformance/ingress/timeout.go
similarity index 99%
rename from test/conformance/ingress/timeout_test.go
rename to test/conformance/ingress/timeout.go
index 9cecd261c..f0f3d9f15 100644
--- a/test/conformance/ingress/timeout_test.go
+++ b/test/conformance/ingress/timeout.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/tls_test.go b/test/conformance/ingress/tls.go
similarity index 99%
rename from test/conformance/ingress/tls_test.go
rename to test/conformance/ingress/tls.go
index 14a1908e9..028f642e9 100644
--- a/test/conformance/ingress/tls_test.go
+++ b/test/conformance/ingress/tls.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/update_test.go b/test/conformance/ingress/update.go
similarity index 99%
rename from test/conformance/ingress/update_test.go
rename to test/conformance/ingress/update.go
index c015d11c2..2ba6c73c0 100644
--- a/test/conformance/ingress/update_test.go
+++ b/test/conformance/ingress/update.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/conformance/ingress/visibility_test.go b/test/conformance/ingress/visibility.go
similarity index 99%
rename from test/conformance/ingress/visibility_test.go
rename to test/conformance/ingress/visibility.go
index 5b94af791..d98c99f4f 100644
--- a/test/conformance/ingress/visibility_test.go
+++ b/test/conformance/ingress/visibility.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2020 The Knative Authors
 
diff --git a/test/conformance/ingress/websocket_test.go b/test/conformance/ingress/websocket.go
similarity index 99%
rename from test/conformance/ingress/websocket_test.go
rename to test/conformance/ingress/websocket.go
index bac98c8bb..2053e13d1 100644
--- a/test/conformance/ingress/websocket_test.go
+++ b/test/conformance/ingress/websocket.go
@@ -1,5 +1,3 @@
-// +build e2e
-
 /*
 Copyright 2019 The Knative Authors
 
diff --git a/test/e2e-common.sh b/test/e2e-common.sh
index 1c79523eb..cb084ba5b 100644
--- a/test/e2e-common.sh
+++ b/test/e2e-common.sh
@@ -153,11 +153,12 @@ function build_knative_from_source() {
 # Installs Knative Serving in the current cluster, and waits for it to be ready.
 # If no parameters are passed, installs the current source-based build, unless custom
 # YAML files were passed using the --custom-yamls flag.
-# Parameters: $1 - Knative Serving YAML file
+# Parameters: $1 - Knative Serving version "HEAD" or "latest-release". Default is "HEAD".
 #             $2 - Knative Monitoring YAML file (optional)
 function install_knative_serving() {
+  local version=${1:-"HEAD"}
   if [[ -z "${INSTALL_CUSTOM_YAMLS}" ]]; then
-    install_knative_serving_standard "$1" "$2"
+    install_knative_serving_standard "$version" "$2"
     return
   fi
   echo ">> Installing Knative serving from custom YAMLs"
@@ -202,11 +203,10 @@ function install_istio() {
   if [[ -n "$1" ]]; then
     echo ">> Installing Istio Ingress"
     echo "Istio Ingress YAML: ${1}"
-    # We apply a filter here because when we're installing from a pre-built
-    # bundle then the whole bundle it passed here.  We use ko because it has
-    # better filtering support for CRDs.
-    local YAML_NAME=${TMP_DIR}/${1##*/}
+    # Create temp copy in which we replace knative-serving by the test's system namespace.
+    local YAML_NAME=$(mktemp -p $TMP_DIR --suffix=.$(basename "$1"))
     sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${1} > ${YAML_NAME}
+    echo "Istio Ingress YAML: $YAML_NAME"
     ko apply -f "${YAML_NAME}" --selector=networking.knative.dev/ingress-provider=istio || return 1
     UNINSTALL_LIST+=( "${YAML_NAME}" )
   fi
@@ -282,7 +282,7 @@ function install_contour() {
 
 # Installs Knative Serving in the current cluster, and waits for it to be ready.
 # If no parameters are passed, installs the current source-based build.
-# Parameters: $1 - Knative Serving YAML file
+# Parameters: $1 - Knative Serving version "HEAD" or "latest-release".
 #             $2 - Knative Monitoring YAML file (optional)
 function install_knative_serving_standard() {
   echo ">> Creating ${SYSTEM_NAMESPACE} namespace if it does not exist"
@@ -294,7 +294,8 @@ function install_knative_serving_standard() {
   add_trap "kubectl delete namespace ${SYSTEM_NAMESPACE} --ignore-not-found=true" SIGKILL SIGTERM SIGQUIT
 
   echo ">> Installing Knative CRD"
-  if [[ -z "$1" ]]; then
+  SERVING_RELEASE_YAML=""
+  if [[ "$1" == "HEAD" ]]; then
     # If we need to build from source, then kick that off first.
     build_knative_from_source
 
@@ -302,11 +303,19 @@ function install_knative_serving_standard() {
     kubectl apply -f "${SERVING_CRD_YAML}" || return 1
     UNINSTALL_LIST+=( "${SERVING_CRD_YAML}" )
   else
-    local YAML_NAME=${TMP_DIR}/${1##*/}
-    sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${1} > ${YAML_NAME}
-    echo "Knative YAML: ${YAML_NAME}"
-    ko apply -f "${YAML_NAME}" --selector=knative.dev/crd-install=true || return 1
-    UNINSTALL_LIST+=( "${YAML_NAME}" )
+    # Download the latest release of Knative Serving.
+    local url="https://github.com/knative/serving/releases/download/${LATEST_SERVING_RELEASE_VERSION}"
+    local yaml="serving.yaml"
+
+    local SERVING_RELEASE_YAML=${TMP_DIR}/"serving-${LATEST_SERVING_RELEASE_VERSION}.yaml"
+    wget "${url}/${yaml}" -O "${SERVING_RELEASE_YAML}" \
+      || fail_test "Unable to download latest knative/serving release."
+
+    # Replace the default system namespace with the test's system namespace.
+    sed -i "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${SERVING_RELEASE_YAML}
+
+    echo "Knative YAML: ${SERVING_RELEASE_YAML}"
+    ko apply -f "${SERVING_RELEASE_YAML}" --selector=knative.dev/crd-install=true || return 1
   fi
 
   echo ">> Installing Ingress"
@@ -319,7 +328,18 @@ function install_knative_serving_standard() {
   elif [[ -n "${CONTOUR_VERSION}" ]]; then
     install_contour || return 1
   else
-    install_istio "./third_party/net-istio.yaml" || return 1
+    if [[ "$1" == "HEAD" ]]; then
+      install_istio "./third_party/net-istio.yaml" || return 1
+    else
+      # Download the latest release of net-istio.
+      local url="https://github.com/knative/net-istio/releases/download/${LATEST_NET_ISTIO_RELEASE_VERSION}"
+      local yaml="net-istio.yaml"
+      local YAML_NAME=${TMP_DIR}/"net-istio-${LATEST_NET_ISTIO_RELEASE_VERSION}.yaml"
+      wget "${url}/${yaml}" -O "${YAML_NAME}" \
+        || fail_test "Unable to download latest knative/net-istio release."
+      echo "net-istio YAML: ${YAML_NAME}"
+      install_istio $YAML_NAME || return 1
+    fi
   fi
 
   echo ">> Installing Cert-Manager"
@@ -336,7 +356,7 @@ function install_knative_serving_standard() {
   UNINSTALL_LIST+=( "${CERT_YAML_NAME}" )
 
   echo ">> Installing Knative serving"
-  if [[ -z "$1" ]]; then
+  if [[ "$1" == "HEAD" ]]; then
     local CORE_YAML_NAME=${TMP_DIR}/${SERVING_CORE_YAML##*/}
     sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${SERVING_CORE_YAML} > ${CORE_YAML_NAME}
     local HPA_YAML_NAME=${TMP_DIR}/${SERVING_HPA_YAML##*/}
@@ -354,14 +374,12 @@ function install_knative_serving_standard() {
 	UNINSTALL_LIST+=( "${MONITORING_YAML}" )
     fi
   else
-    echo "Knative YAML: ${1}"
+    echo "Knative YAML: ${SERVING_RELEASE_YAML}"
     # If we are installing from provided yaml, then only install non-istio bits here,
     # and if we choose to install istio below, then pass the whole file as the rest.
     # We use ko because it has better filtering support for CRDs.
-    local YAML_NAME=${TMP_DIR}/${1##*/}
-    sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${1} > ${YAML_NAME}
-    ko apply -f "${YAML_NAME}" --selector=networking.knative.dev/ingress-provider!=istio || return 1
-    UNINSTALL_LIST+=( "${YAML_NAME}" )
+    ko apply -f "${SERVING_RELEASE_YAML}" --selector=networking.knative.dev/ingress-provider!=istio || return 1
+    UNINSTALL_LIST+=( "${SERVING_RELEASE_YAML}" )
 
     if (( INSTALL_MONITORING )); then
       echo ">> Installing Monitoring"
diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh
index bad8b0370..29fb0eecc 100755
--- a/test/e2e-tests.sh
+++ b/test/e2e-tests.sh
@@ -97,7 +97,7 @@ go_test_e2e -timeout=30m \
 # We run KIngress conformance ingress separately, to make it easier to skip some tests.
 go_test_e2e -timeout=20m ./test/conformance/ingress ${parallelism}  \
   `# Skip TestUpdate due to excessive flaking https://github.com/knative/serving/issues/8032` \
-  -run="Test[^U]" \
+  -run="TestIngressConformance/^[^u]" \
   "--resolvabledomain=$(use_resolvable_domain)" "${use_https}" "$(ingress_class)" || failed=1
 
 if (( HTTPS )); then
diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh
index 9eef0c543..e33124e82 100755
--- a/test/e2e-upgrade-tests.sh
+++ b/test/e2e-upgrade-tests.sh
@@ -35,16 +35,15 @@ source $(dirname $0)/e2e-common.sh
 # tagged release on the current branch will be used.
 LATEST_SERVING_RELEASE_VERSION=$(git describe --match "v[0-9]*" --abbrev=0)
 
+# Latest net-istio release.
+LATEST_NET_ISTIO_RELEASE_VERSION=$(
+  curl --silent "https://api.github.com/repos/knative/net-istio/releases" | grep '"tag_name"' \
+    | cut -f2 -d: | sed "s/[^v0-9.]//g" | sort | tail -n1)
+
 function install_latest_release() {
   header "Installing Knative latest public release"
-  local url="https://github.com/knative/serving/releases/download/${LATEST_SERVING_RELEASE_VERSION}"
-  local yaml="serving.yaml"
-
-  local RELEASE_YAML="$(mktemp)"
-  wget "${url}/${yaml}" -O "${RELEASE_YAML}" \
-      || fail_test "Unable to download latest Knative release."
 
-  install_knative_serving "${RELEASE_YAML}" \
+  install_knative_serving latest-release \
       || fail_test "Knative latest release installation failed"
   wait_until_pods_running ${SYSTEM_NAMESPACE}
 }
diff --git a/test/e2e/activator_test.go b/test/e2e/activator_test.go
index 5769c5769..f8468144a 100644
--- a/test/e2e/activator_test.go
+++ b/test/e2e/activator_test.go
@@ -7,7 +7,7 @@ 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
+    https://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,
diff --git a/test/e2e/helloworld_test.go b/test/e2e/helloworld_test.go
index 3d7b2bb1f..4495719e7 100644
--- a/test/e2e/helloworld_test.go
+++ b/test/e2e/helloworld_test.go
@@ -105,12 +105,12 @@ func TestQueueSideCarResourceLimit(t *testing.T) {
 	resources, err := v1test.CreateServiceReady(t, clients, &names,
 		rtesting.WithResourceRequirements(corev1.ResourceRequirements{
 			Requests: corev1.ResourceList{
-				corev1.ResourceName("cpu"):    resource.MustParse("50m"),
-				corev1.ResourceName("memory"): resource.MustParse("128Mi"),
+				corev1.ResourceCPU:    resource.MustParse("50m"),
+				corev1.ResourceMemory: resource.MustParse("128Mi"),
 			},
 			Limits: corev1.ResourceList{
-				corev1.ResourceName("cpu"):    resource.MustParse("100m"),
-				corev1.ResourceName("memory"): resource.MustParse("258Mi"),
+				corev1.ResourceCPU:    resource.MustParse("100m"),
+				corev1.ResourceMemory: resource.MustParse("258Mi"),
 			},
 		}), rtesting.WithConfigAnnotations(map[string]string{
 			serving.QueueSideCarResourcePercentageAnnotation: "0.2",
diff --git a/test/test_images/httpproxy/service.yaml b/test/test_images/httpproxy/service.yaml
index b4bac824c..d9ee2b608 100644
--- a/test/test_images/httpproxy/service.yaml
+++ b/test/test_images/httpproxy/service.yaml
@@ -1,16 +1,5 @@
 apiVersion: serving.knative.dev/v1
 kind: Service
-metadata:
-  name: helloworld-test-image
-  namespace: default
-spec:
-  template:
-    spec:
-      containers:
-      - image: ko://knative.dev/serving/test/test_images/helloworld
----
-apiVersion: serving.knative.dev/v1
-kind: Service
 metadata:
   name: httpproxy-test-image
   namespace: default
@@ -22,4 +11,3 @@ spec:
         env:
         - name: TARGET_HOST
           value: "helloworld-test-image.default.svc.cluster.local"
-
diff --git a/third_party/contour-latest/contour.yaml b/third_party/contour-latest/contour.yaml
index c890192f0..898c622f7 100644
--- a/third_party/contour-latest/contour.yaml
+++ b/third_party/contour-latest/contour.yaml
@@ -1432,7 +1432,7 @@ spec:
         # if we change this on each version, you can no longer upgrade
         # just by applying the deployment YAML.
         # See #2423, #2395, #2150, and #2030 for earlier questions about this.
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         command:
         - contour
@@ -1672,7 +1672,7 @@ spec:
         - --contour-key-file=/certs/tls.key
         - --config-path=/config/contour.yaml
         command: ["contour"]
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         name: contour
         ports:
@@ -1764,7 +1764,7 @@ spec:
         args:
         - envoy
         - shutdown-manager
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         lifecycle:
           preStop:
@@ -1840,7 +1840,7 @@ spec:
         - --envoy-key-file=/certs/tls.key
         command:
         - contour
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         name: envoy-initconfig
         volumeMounts:
@@ -3305,7 +3305,7 @@ spec:
         # if we change this on each version, you can no longer upgrade
         # just by applying the deployment YAML.
         # See #2423, #2395, #2150, and #2030 for earlier questions about this.
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         command:
         - contour
@@ -3545,7 +3545,7 @@ spec:
         - --contour-key-file=/certs/tls.key
         - --config-path=/config/contour.yaml
         command: ["contour"]
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         name: contour
         ports:
@@ -3637,7 +3637,7 @@ spec:
         args:
         - envoy
         - shutdown-manager
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         lifecycle:
           preStop:
@@ -3713,7 +3713,7 @@ spec:
         - --envoy-key-file=/certs/tls.key
         command:
         - contour
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:25776cd920a8961746503d4bf923774a5b312a793e13ef4bcd01ae948ef0b748
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:69f3a2d31b2a14e8cabea4ed38ac83845ff7920c31a0d836a494383307737926
         imagePullPolicy: Always
         name: envoy-initconfig
         volumeMounts:
diff --git a/third_party/contour-latest/net-contour.yaml b/third_party/contour-latest/net-contour.yaml
index 282116932..f2ae8a3e1 100644
--- a/third_party/contour-latest/net-contour.yaml
+++ b/third_party/contour-latest/net-contour.yaml
@@ -35,7 +35,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: contour
-    serving.knative.dev/release: "v20200527-d62309d"
+    serving.knative.dev/release: "v20200601-b5d9707"
 data:
   _example: |
     ################################
@@ -94,7 +94,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:e6228f84f06f950240e6cc236f18cabcad890386ce2ba358d40c4f9b69652bfa
+        image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:a00111f41edd33143e10295aa5423fa28a38006262f20a58586ed1eddb161f63
         resources:
           requests:
             cpu: 40m
diff --git a/third_party/kourier-latest/kourier.yaml b/third_party/kourier-latest/kourier.yaml
index 102a71942..fa1115bc9 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -166,7 +166,7 @@ spec:
         app: 3scale-kourier-control
     spec:
       containers:
-      - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:32dc25a012cf385ede0e40eabd797966e230751f521ffcb0689814994ed599f3
+      - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:50c4153c679f98e89a4d302c9ed4710d88cb8e342df7c6174beaa442f28b14a4
         imagePullPolicy: Always
         name: kourier-control
         env: