Repository: linkerd/linkerd2
Pull request #4885 (2020-08-17 02:30:40)

cli/cmd/inject_test: add os.RemoveAll err verification
Add error judgment of return value to os.RemoveAll in TestWalk function.


Signed-off-by: Zhou Hao <zhouhao@cn.fujitsu.com>

<!--  Thanks for sending a pull request!

If you already have a well-structured git commit message, chances are GitHub
set the title and description of this PR to the git commit message subject and
body, respectively. If so, you may delete these instructions and submit your PR.

If this is your first time, please read our contributor guide:
https://github.com/linkerd/linkerd2/blob/main/CONTRIBUTING.md

The title and description of your Pull Request should match the git commit
subject and body, respectively. Git commit messages are structured as follows:

```
Subject

Problem

Solution

Validation

Fixes #[GitHub issue ID]

DCO Sign off
```

Example git commit message:

```
Introduce Pull Request Template

GitHub's community guidelines recommend a pull request template, the repo was
lacking one.

Introduce a `PULL_REQUEST_TEMPLATE.md` file.

Once merged, the
[Community profile checklist](https://github.com/linkerd/linkerd2/community)
should indicate the repo now provides a pull request template.

Fixes #3321

Signed-off-by: Jane Smith <jane.smith@example.com>
```

Note the git commit message subject becomes the pull request title.

For more details around git commits, see the section on Committing in our
contributor guide:
https://github.com/linkerd/linkerd2/blob/main/CONTRIBUTING.md#committing
-->



Patch:
diff --git a/.github/workflows/cloud_integration.yml b/.github/workflows/cloud_integration.yml
index 7dc835aef..7fd057a83 100644
--- a/.github/workflows/cloud_integration.yml
+++ b/.github/workflows/cloud_integration.yml
@@ -77,7 +77,6 @@ jobs:
         restore-keys: |
           ${{ runner.os }}-go-
     - name: Install linkerd CLI
-      id: install_cli
       run: |
         TAG="$(CI_FORCE_CLEAN=1 bin/root-tag)"
         CMD="$PWD/target/release/linkerd2-cli-$TAG-linux-amd64"
@@ -100,11 +99,7 @@ jobs:
         name: testing-${{ env.TAG }}-${{ github.run_id }}
         num_nodes: 2
     - name: Run integration tests
-      env:
-        GITCOOKIE_SH: ${{ secrets.GITCOOKIE_SH }}
-      run: |
-        echo "$GITCOOKIE_SH" | bash
-        bin/tests --skip-kind-create "$CMD"
+      run: bin/tests --skip-kind-create "$CMD"
     - name: CNI tests
       run: |
         export TAG="$($CMD version --client --short)"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c8e191012..29cdd9c70 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -160,7 +160,6 @@ jobs:
         restore-keys: |
           ${{ runner.os }}-go-
     - name: Install linkerd CLI
-      id: install_cli
       run: |
         TAG="$(CI_FORCE_CLEAN=1 bin/root-tag)"
         CMD="$PWD/target/release/linkerd2-cli-$TAG-linux-amd64"
@@ -170,7 +169,7 @@ jobs:
         [[ "$TAG" == "$($CMD version --short --client)" ]]
         echo "Installed Linkerd CLI version: $TAG"
         echo "::set-env name=CMD::$CMD"
-        echo "::set-output name=tag::$TAG"
+        echo "::set-env name=TAG::$TAG"
     - name: Create GKE cluster
       # linkerd/linkerd2-action-gcloud@v1.0.1
       uses: linkerd/linkerd2-action-gcloud@308c4df
@@ -180,23 +179,62 @@ jobs:
         gcp_zone: ${{ secrets.GCP_ZONE }}
         preemptible: false
         create: true
-        name: testing-${{ steps.install_cli.outputs.tag }}-${{ github.run_id }}
+        name: testing-${{ env.TAG }}-${{ github.run_id }}
         num_nodes: 2
     - name: Run integration tests
-      env:
-        GITCOOKIE_SH: ${{ secrets.GITCOOKIE_SH }}
+      run: bin/tests --skip-kind-create "$CMD"
+    - name: CNI tests
+      run: |
+        export TAG="$($CMD version --client --short)"
+        go test -cover -race -v -mod=readonly ./cni-plugin/test -integration-tests
+  arm64_integration_tests:
+    name: ARM64 integration tests
+    runs-on: ubuntu-18.04
+    needs: [docker_build]
+    steps:
+    - name: Checkout code
+      # actions/checkout@v2
+      uses: actions/checkout@722adc6
+    - name: Try to load cached Go modules
+      # actions/cache@v1.1.2
+      uses: actions/cache@70655ec
+      with:
+        path: ~/go/pkg/mod
+        key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+        restore-keys: |
+          ${{ runner.os }}-go-
+    - name: Install linkerd CLI
+      run: |
+        TAG="$(CI_FORCE_CLEAN=1 bin/root-tag)"
+        CMD="$PWD/target/release/linkerd2-cli-$TAG-linux-amd64"
+        bin/docker-pull-binaries $TAG
+        $CMD version --client
+        # validate CLI version matches the repo
+        [[ "$TAG" == "$($CMD version --short --client)" ]]
+        echo "Installed Linkerd CLI version: $TAG"
+        echo "::set-env name=CMD::$CMD"
+    - name: Set KUBECONFIG environment variables
       run: |
-        echo "$GITCOOKIE_SH" | bash
-        bin/tests --skip-kind-create "$CMD"
+        mkdir -p $HOME/.kube
+        echo "${{ secrets.ARM64_KUBECONFIG }}" > $HOME/.kube/config
+        echo ::set-env name=KUBECONFIG::$HOME/.kube/config
+        kubectl cluster-info
+    - name: Run integration tests
+      env:
+        RUN_ARM_TEST: 1
+      run: bin/tests --skip-kind-create "$CMD"
     - name: CNI tests
       run: |
         export TAG="$($CMD version --client --short)"
         go test -cover -race -v -mod=readonly ./cni-plugin/test -integration-tests
+    - name: Test cleanup
+      if: ${{ always() }}
+      run: bin/test-cleanup
   choco_pack:
     # only runs for stable tags. The conditionals are at each step level instead of the job level
     # otherwise the jobs below that depend on this one won't run
     name: Pack Chocolatey release
-    needs: [kind_integration_tests, cloud_integration_tests]
+    needs: [kind_integration_tests, cloud_integration_tests, arm64_integration_tests]
     runs-on: windows-2019
     steps:
     - name: Checkout code
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml
index f4867b521..1bfc23277 100644
--- a/.github/workflows/static_checks.yml
+++ b/.github/workflows/static_checks.yml
@@ -18,11 +18,7 @@ jobs:
       # actions/checkout@v2
       uses: actions/checkout@722adc6
     - name: Go lint
-      env:
-        GITCOOKIE_SH: ${{ secrets.GITCOOKIE_SH }}
-      run: |
-        echo "$GITCOOKIE_SH" | bash
-        bin/lint --verbose
+      run: bin/lint --verbose
   go_format:
     name: Go format
     runs-on: ubuntu-18.04
@@ -33,11 +29,18 @@ jobs:
       # actions/checkout@v2
       uses: actions/checkout@722adc6
     - name: Format
-      env:
-        GITCOOKIE_SH: ${{ secrets.GITCOOKIE_SH }}
-      run: |
-        echo "$GITCOOKIE_SH" | bash
-        bin/fmt
+      run: bin/fmt
+  proto_diff:
+    name: Proto diff
+    runs-on: ubuntu-18.04
+    container:
+      image: golang:1.13.4
+    steps:
+      - name: Checkout code
+        # actions/checkout@v2
+        uses: actions/checkout@722adc6
+      - name: Diff proto files
+        run: bin/protoc-diff
   shellcheck:
     name: shellcheck
     runs-on: ubuntu-18.04
diff --git a/.proxy-version b/.proxy-version
index 8c95cd04f..5868b8749 100644
--- a/.proxy-version
+++ b/.proxy-version
@@ -1,1 +1,1 @@
-v2.106.0
+v2.108.0
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 124ec645c..23a493c93 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -34,6 +34,7 @@
 - [Vernacular.ai](https://vernacular.ai/)
 - [xCloud](https://www.xbox.com/en-US/xbox-game-streaming/project-xcloud)
 - [YouMail](https://www.youmail.com)
+- [OLX Brasil](https://www.olx.com.br)
 
 If you're using Linkerd 2.x and aren't on this list, please [submit a pull
 request](https://github.com/linkerd/linkerd2/edit/main/ADOPTERS.md)!
diff --git a/CHANGES.md b/CHANGES.md
index 6e25e2492..227cfde40 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,34 @@
 # Changes
 
+## edge-20.8.4
+
+* Fixed a problem causing the `enable-endpoint-slices` flag to not be persisted
+  when set via `linkerd upgrade` (thanks @Matei207!)
+* Removed SMI-Metrics templates and experimental sub-commands
+* Use `--frozen-lockfile` to avoid accidental update of dashboard JS
+  dependencies in CI (thanks @tharun208!)
+
+## edge-20.8.3
+
+This edge release adds support for [topology-aware service routing][topology] to
+the Destination controller. When providing service discovery updates to proxies,
+the Destination controller will now filter endpoints based on the service's
+topology preferences. Additionally, this release includes bug fixes for the
+`linkerd check` CLI command and web dashboard.
+
+* CLI
+  * `linkerd check` will no longer warn about a looser webhook failure policy in
+    HA mode
+* Controller
+  * Added support for [topology-aware service routing][topology] to the Destination
+    controller (thanks @Matei207)
+  * Changed the Destination controller to always return destination overrides
+    for service profiles when no traffic split is present
+* Web UI
+  * Fixed Tap `Authority` dropdown not being populated (thanks to @tharun208!)
+  
+[topology]: https://kubernetes.io/docs/concepts/services-networking/service-topology/
+
 ## edge-20.8.2
 
 This edge release adds an internationalization framework to the dashboard,
diff --git a/bin/protoc-diff b/bin/protoc-diff
new file mode 100755
index 000000000..e75a0a8e0
--- /dev/null
+++ b/bin/protoc-diff
@@ -0,0 +1,22 @@
+#!/usr/bin/env sh
+
+set -eu
+
+# Install unzip if not already installed (Linux only)
+system=$(uname -s)
+if [ "$system" = Linux ] && ! [ -x "$(command -v unzip)" ]; then
+  apt-get update
+  apt-get install unzip
+fi
+
+bin/protoc-go.sh
+
+dir_dirty=$(git diff HEAD)
+if [ -z "$dir_dirty" ]; then
+  echo "Protobuf definitions match generated code"
+  exit 0
+else
+  echo "Protobuf definitions diverge from generated code:"
+  echo "$(git status)"
+  exit 64
+fi
diff --git a/charts/linkerd2/README.md b/charts/linkerd2/README.md
index 78d2f9f67..31ed97a38 100644
--- a/charts/linkerd2/README.md
+++ b/charts/linkerd2/README.md
@@ -166,14 +166,6 @@ their default values.
 | `profileValidator.caBundle`                 | Bundle of CA certificates for service profile validator. If not provided then Helm will use the certificate generated  for `profileValidator.crtPEM`. If `profileValidator.externalSecret` is set to true, this value must be set, as no certificate will be generated.         |  |
 | `publicAPIResources`                        | CPU and Memory resources required by controllers publicAPI (see `global.proxy.resources` for sub-fields)             |   |
 | `publicAPIProxyResources`                   | CPU and Memory resources required by proxy injected into controllers public API pod (see `global.proxy.resources` for sub-fields)             |  values  `global.proxy.resources`   |
-| `smiMetrics.enabled`                        | Enable collection of SMI metrics by setting to `true`. Default is `false`
-| `smiMetrics.externalSecret`                 | Do not create a secret resource for the SMI metrics component.  If this is set to `true`, the value `smiMetrics.caBundle` must be set (see below).                                           | false |
-| `smiMetrics.image`                          | The image and tag to use for the SMI metrics component.    | `deislabs/smi-metrics:v0.2.1` |
-| `smiMetrics.crtPEM`                         | Certificate for the SMI metrics component. If not provided then Helm will generate one.                                                                                                                                 ||
-| `smiMetrics.keyPEM`                         | Certificate key for the SMI metrics component. If not provided then Helm will generate one.                                                                                                                             ||
-| `smiMetrics.caBundle`                       | Bundle of CA certificates for the SMI metrics component. If not provided then Helm will use the certificate generated  for `smiMetrics.crtPEM`. If `smiMetrics.externalSecret` is set to true, this value must be set, as no certificate will be generated.                       ||
-| `smiMetricsResources`                       | CPU and Memory resources required by SMI metrics (see `global.proxy.resources` for sub-fields)             |   |
-| `smiMetricsProxyResources`                  | CPU and Memory resources required by proxy injected into SMI metrics pod (see `global.proxy.resources` for sub-fields)             | values in `global.proxy.resources`   |
 | `spValidatorResources`                      | CPU and Memory resources required by the SP validator (see `global.proxy.resources` for sub-fields)             |   |
 | `spValidatorProxyResources`                 | CPU and Memory resources required by proxy injected into the SP validator pod (see `global.proxy.resources` for sub-fields)             | values in `global.proxy.resources`   |
 | `tap.externalSecret`                        | Do not create a secret resource for the Tap component. If this is set to `true`, the value `tap.caBundle` must be set (see below).                                                  | false                                |
diff --git a/charts/linkerd2/smi-metrics-config.yaml b/charts/linkerd2/smi-metrics-config.yaml
deleted file mode 100644
index 8035eb955..000000000
--- a/charts/linkerd2/smi-metrics-config.yaml
+++ /dev/null
@@ -1,169 +0,0 @@
-mesh: linkerd
-linkerd:
-  // TODO: update to use `global.prometheusUrl` field, before falling back to the default value
-  prometheusUrl: http://linkerd-prometheus.linkerd.svc.cluster.local:9090
-  resourceQueries:
-    p99_response_latency : |-
-      histogram_quantile(
-                        0.99,
-                        sum(
-                          irate(
-                            response_latency_ms_bucket{
-                              namespace=~"{{default ".+" .namespace }}",
-                              {{lower .kind}}=~"{{default ".+" .name }}"
-                            }[{{.window}}]
-                          )
-                        ) by (
-                          {{lower .kind}},
-                          namespace,
-                          le
-                        )
-                      )
-    p90_response_latency : |-
-      histogram_quantile(
-                        0.90,
-                        sum(
-                          irate(
-                            response_latency_ms_bucket{
-                              namespace=~"{{default ".+" .namespace }}",
-                              {{lower .kind}}=~"{{default ".+" .name }}"
-                            }[{{.window}}]
-                          )
-                        ) by (
-                          {{lower .kind}},
-                          namespace,
-                          le
-                        )
-                      )
-    p50_response_latency : |-
-      histogram_quantile(
-                        0.50,
-                        sum(
-                          irate(
-                            response_latency_ms_bucket{
-                              namespace=~"{{default ".+" .namespace }}",
-                              {{lower .kind}}=~"{{default ".+" .name }}"
-                            }[{{.window}}]
-                          )
-                        ) by (
-                          {{lower .kind}},
-                          namespace,
-                          le
-                        )
-                      )
-    success_count : |-
-      sum(
-                increase(
-                  response_total{
-                    classification="success",
-                    namespace=~"{{default ".+" .namespace }}",
-                    {{lower .kind}}=~"{{default ".+" .name }}"
-                  }[{{.window}}]
-                )
-              ) by (
-                {{lower .kind}},
-                namespace
-              )
-    failure_count : |-
-      sum(
-                increase(
-                  response_total{
-                    classification="failure",
-                    namespace=~"{{default ".+" .namespace }}",
-                    {{lower .kind}}=~"{{default ".+" .name }}"
-                  }[{{.window}}]
-                )
-              ) by (
-                {{lower .kind}},
-                namespace
-              )
-  edgeQueries:
-    p99_response_latency : |-
-      histogram_quantile(
-                        0.99,
-                        sum(
-                          irate(
-                            response_latency_ms_bucket{
-                              namespace=~"{{.namespace}}",
-                              {{lower .kind}}=~"{{default ".+" .fromName}}",
-                              dst_{{lower .kind}}=~"{{default ".+" .toName}}"
-                            }[{{.window}}]
-                          )
-                        ) by (
-                          {{lower .kind}},
-                          dst_{{lower .kind}},
-                          namespace,
-                          dst_namespace,
-                          le
-                        )
-                      )
-    p90_response_latency : |-
-      histogram_quantile(
-                        0.90,
-                        sum(
-                          irate(
-                            response_latency_ms_bucket{
-                              namespace=~"{{.namespace}}",
-                              {{lower .kind}}=~"{{default ".+" .fromName}}",
-                              dst_{{lower .kind}}=~"{{default ".+" .toName}}"
-                            }[{{.window}}]
-                          )
-                        ) by (
-                          {{lower .kind}},
-                          dst_{{lower .kind}},
-                          namespace,
-                          dst_namespace,
-                          le
-                        )
-                      )
-    p50_response_latency : |-
-      histogram_quantile(
-                        0.50,
-                        sum(
-                          irate(
-                            response_latency_ms_bucket{
-                              namespace=~"{{.namespace}}",
-                              {{lower .kind}}=~"{{default ".+" .fromName}}",
-                              dst_{{lower .kind}}=~"{{default ".+" .toName}}"
-                            }[{{.window}}]
-                          )
-                        ) by (
-                          {{lower .kind}},
-                          dst_{{lower .kind}},
-                          namespace,
-                          dst_namespace,
-                          le
-                        )
-                      )
-    success_count : |-
-      sum(
-                increase(
-                  response_total{
-                    classification="success",
-                    namespace=~"{{.namespace}}",
-                    {{lower .kind}}=~"{{default ".+" .fromName}}",
-                    dst_{{lower .kind}}=~"{{default ".+" .toName}}"
-                  }[{{.window}}]
-                )
-              ) by (
-                {{lower .kind}},
-                dst_{{lower .kind}},
-                namespace,
-                dst_namespace
-              )
-    failure_count : |-
-      sum(
-                increase(
-                  response_total{
-                    classification="failure",
-                    namespace=~"{{.namespace}}",
-                    {{lower .kind}}=~"{{default ".+" .fromName}}",
-                    dst_{{lower .kind}}=~"{{default ".+" .toName}}"
-                  }[{{.window}}]
-                )
-              ) by (
-                {{lower .kind}},
-                dst_{{lower .kind}},
-                namespace,
-                dst_namespace
-              )
diff --git a/charts/linkerd2/templates/_config.tpl b/charts/linkerd2/templates/_config.tpl
index bcac0a960..39f3ce805 100644
--- a/charts/linkerd2/templates/_config.tpl
+++ b/charts/linkerd2/templates/_config.tpl
@@ -12,8 +12,7 @@
   },
   "autoInjectContext": null,
   "omitWebhookSideEffects": {{.Values.omitWebhookSideEffects}},
-  "clusterDomain": "{{.Values.global.clusterDomain}}",
-  "enableEndpointSlices": "{{.Values.global.enableEndpointSlices}}"
+  "clusterDomain": "{{.Values.global.clusterDomain}}"
 }
 {{- end -}}
 
diff --git a/charts/linkerd2/templates/destination-rbac.yaml b/charts/linkerd2/templates/destination-rbac.yaml
index 3bab38e49..817488123 100644
--- a/charts/linkerd2/templates/destination-rbac.yaml
+++ b/charts/linkerd2/templates/destination-rbac.yaml
@@ -18,7 +18,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
diff --git a/charts/linkerd2/templates/destination.yaml b/charts/linkerd2/templates/destination.yaml
index f418318cc..d39415452 100644
--- a/charts/linkerd2/templates/destination.yaml
+++ b/charts/linkerd2/templates/destination.yaml
@@ -76,6 +76,7 @@ spec:
         - -controller-namespace={{.Values.global.namespace}}
         - -enable-h2-upgrade={{.Values.enableH2Upgrade}}
         - -log-level={{.Values.global.controllerLogLevel}}
+        - -enable-endpoint-slices={{.Values.global.enableEndpointSlices}}
         {{- include "partials.linkerd.trace" . | nindent 8 -}}
         image: {{.Values.controllerImage}}:{{default .Values.global.linkerdVersion .Values.global.controllerImageVersion}}
         imagePullPolicy: {{.Values.global.imagePullPolicy}}
@@ -103,7 +104,7 @@ spec:
         volumeMounts:
         - mountPath: /var/run/linkerd/config
           name: config
-      {{- $tree := deepCopy . }}      
+      {{- $tree := deepCopy . }}
       {{- if not (empty .Values.destinationProxyResources) }}
       {{- $r := merge .Values.destinationProxyResources .Values.global.proxy.resources }}
       {{- $_ := set $tree.Values.global.proxy "resources" $r }}
diff --git a/charts/linkerd2/templates/psp.yaml b/charts/linkerd2/templates/psp.yaml
index 423cddc25..6cfa17b1b 100644
--- a/charts/linkerd2/templates/psp.yaml
+++ b/charts/linkerd2/templates/psp.yaml
@@ -120,8 +120,3 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: {{.Values.global.namespace}}
-{{- if .Values.smiMetrics.enabled }}
-- kind: ServiceAccount
-  name: linkerd-smi-metrics
-  namespace: {{.Values.global.namespace}}
-{{- end }}
diff --git a/charts/linkerd2/templates/smi-metrics-rbac.yaml b/charts/linkerd2/templates/smi-metrics-rbac.yaml
deleted file mode 100644
index a1a20840f..000000000
--- a/charts/linkerd2/templates/smi-metrics-rbac.yaml
+++ /dev/null
@@ -1,72 +0,0 @@
-{{- if .Values.smiMetrics.enabled }}
----
-###
-### SMI-Metrics RBAC
-###
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-  name: linkerd-smi-metrics
-  namespace: {{.Values.global.namespace}}
----
-apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
-metadata:
-  name: linkerd-smi-metrics
-  labels:
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-  namespace: kube-system
-roleRef:
-  apiGroup: rbac.authorization.k8s.io
-  kind: Role
-  name: extension-apiserver-authentication-reader
-subjects:
-- kind: ServiceAccount
-  name: linkerd-smi-metrics
-  namespace: {{.Values.global.namespace}}
----
-{{- $cn := printf "linkerd-smi-metrics.%s.svc" .Values.global.namespace }}
-{{- $cert := genCA $cn 365 }}
-{{- if (not .Values.smiMetrics.externalSecret) }}
-kind: Secret
-apiVersion: v1
-metadata:
-  name: linkerd-smi-metrics-tls
-  namespace: {{ .Values.global.namespace }}
-  labels:
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-  annotations:
-    {{.Values.global.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.global.linkerdVersion) .Values.global.cliVersion}}
-type: kubernetes.io/tls
-data:
-  tls.crt: {{ ternary (b64enc (trim $cert.Cert)) (b64enc (trim .Values.smiMetrics.crtPEM)) (empty .Values.smiMetrics.crtPEM) }}
-  tls.key: {{ ternary (b64enc (trim $cert.Key)) (b64enc (trim .Values.smiMetrics.keyPEM)) (empty .Values.smiMetrics.keyPEM) }}
----
-{{- end }}
-apiVersion: apiregistration.k8s.io/v1
-kind: APIService
-metadata:
-  name: v1alpha1.metrics.smi-spec.io
-  labels:
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-spec:
-  group: metrics.smi-spec.io
-  version: v1alpha1
-  insecureSkipTLSVerify: false
-  groupPriorityMinimum: 100
-  versionPriority: 100
-  service:
-    name: linkerd-smi-metrics
-    namespace: {{.Values.global.namespace}}
-{{- if and (.Values.smiMetrics.externalSecret) (empty .Values.smiMetrics.caBundle) }}
-  {{- fail "If smiMetrics.externalSecret is true then you need to provide smiMetrics.caBundle" }}
-{{- end }}
-  caBundle: {{ ternary (b64enc (trim $cert.Cert)) (b64enc (trim .Values.smiMetrics.caBundle)) (empty .Values.smiMetrics.caBundle) }}
-{{- end }}
diff --git a/charts/linkerd2/templates/smi-metrics.yaml b/charts/linkerd2/templates/smi-metrics.yaml
deleted file mode 100644
index 137f73c81..000000000
--- a/charts/linkerd2/templates/smi-metrics.yaml
+++ /dev/null
@@ -1,132 +0,0 @@
-{{- if .Values.smiMetrics.enabled }}
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
-  labels:
-    app.kubernetes.io/name: smi-metrics
-    app.kubernetes.io/part-of: Linkerd
-    app.kubernetes.io/version: {{default .Values.global.linkerdVersion .Values.global.controllerImageVersion}}
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-  name: linkerd-smi-metrics
-  namespace: {{.Values.global.namespace}}
-data:
-  config.yml: |
-    {{- $files := .Files }}
-    {{- $files.Get "smi-metrics-config.yaml" | nindent 4 }}
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: linkerd-smi-metrics
-  namespace: {{.Values.global.namespace}}
-  labels:
-    app.kubernetes.io/name: smi-metrics
-    app.kubernetes.io/part-of: Linkerd
-    app.kubernetes.io/version: {{default .Values.global.linkerdVersion .Values.global.controllerImageVersion}}
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-spec:
-  replicas: 1
-  selector:
-    matchLabels:
-      {{.Values.global.controllerComponentLabel}}: smi-metrics
-      {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-      {{- include "partials.proxy.labels" .Values.global.proxy | nindent 6}}
-  template:
-    metadata:
-      annotations:
-        {{- if empty .Values.global.cliVersion }}
-        checksum/config: {{ include (print $.Template.BasePath "/smi-metrics-rbac.yaml") . | sha256sum }}
-        {{- end }}
-        {{.Values.global.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.global.linkerdVersion) .Values.global.cliVersion}}
-        {{- include "partials.proxy.annotations" .Values.global.proxy| nindent 8}}
-      labels:
-        {{.Values.global.controllerComponentLabel}}: smi-metrics
-        {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-        {{.Values.global.workloadNamespaceLabel}}: {{.Values.global.namespace}}
-        {{- include "partials.proxy.labels" .Values.global.proxy | nindent 8}}
-    spec:
-      {{- if .Values.tolerations -}}
-      {{- include "linkerd.tolerations" . | nindent 6 }}
-      {{- end -}}
-      {{- include "linkerd.node-selector" . | nindent 6 }}
-      {{- if .Values.enablePodAntiAffinity -}}
-      {{- $local := dict "component" "smi-metrics" "label" .Values.global.controllerComponentLabel -}}
-      {{- include "linkerd.pod-affinity" $local | nindent 6 -}}
-      {{- end }}
-      serviceAccountName: linkerd-smi-metrics
-      containers:
-      - name: shim
-        image: {{ .Values.smiMetrics.image }}
-        imagePullPolicy: {{.Values.global.imagePullPolicy}}
-
-        command:
-        - /smi-metrics
-        - --config=/config.yml
-
-        ports:
-        - containerPort: 8080
-          name: api
-          protocol: TCP
-        - containerPort: 8081
-          name: admin
-          protocol: TCP
-
-        volumeMounts:
-        - name: config
-          mountPath: /config.yml
-          subPath: config.yml
-        - mountPath: /var/run/smi-metrics
-          name: tls
-          readOnly: true
-
-        {{- if .Values.smiMetricsResources -}}
-        {{- include "partials.resources" .Values.smiMetricsResources | nindent 8 }}
-        {{- end }}
-
-      {{- $tree := deepCopy . }}      
-      {{- if not (empty .Values.smiMetricsProxyResources) }}
-      {{- $r := merge .Values.smiMetricsProxyResources .Values.global.proxy.resources }}
-      {{- $_ := set $tree.Values.global.proxy "resources" $r }}
-      {{- end }}
-      - {{- include "partials.proxy" $tree | indent 8 | trimPrefix (repeat 7 " ") }}
-      {{ if not .Values.global.cniEnabled -}}
-      initContainers:
-      - {{- include "partials.proxy-init" . | indent 8 | trimPrefix (repeat 7 " ") }}
-      {{ end -}}
-
-      volumes:
-      {{ if .Values.global.controlPlaneTracing -}}
-      - {{- include "partials.proxy.volumes.labels" . | indent 8 | trimPrefix (repeat 7 " ") }}
-      {{ end -}}
-      {{ if not .Values.global.cniEnabled -}}
-      - {{- include "partials.proxyInit.volumes.xtables" . | indent 8 | trimPrefix (repeat 7 " ") }}
-      {{ end -}}
-      - name: config
-        configMap:
-          name: linkerd-smi-metrics
-      - {{- include "partials.proxy.volumes.identity" . | indent 8 | trimPrefix (repeat 7 " ") }}
-      - name: tls
-        secret:
-          secretName: linkerd-smi-metrics-tls
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: linkerd-smi-metrics
-  namespace: {{.Values.global.namespace}}
-  labels:
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-    {{.Values.global.controllerNamespaceLabel}}: {{.Values.global.namespace}}
-  annotations:
-    {{.Values.global.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.global.linkerdVersion) .Values.global.cliVersion}}
-spec:
-  ports:
-    - port: 443
-      targetPort: api
-      protocol: TCP
-  selector:
-    {{.Values.global.controllerComponentLabel}}: smi-metrics
-{{- end }}
diff --git a/charts/linkerd2/values.yaml b/charts/linkerd2/values.yaml
index 26d6f4b1e..5faad6354 100644
--- a/charts/linkerd2/values.yaml
+++ b/charts/linkerd2/values.yaml
@@ -236,23 +236,6 @@ nodeSelector:
 # https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
 #tolerations:
 
-smiMetrics:
-  enabled: false
-  externalSecret: false
-  image: deislabs/smi-metrics:v0.2.1
-  # if empty, Helm will auto-generate these fields
-  crtPEM: |
-
-  keyPEM: |
-
-  # if empty, Helm will auto-generate this field, unless externalSecret is set to true.
-  caBundle: |
-
-# set resources for smi-metrics and its linkerd proxy respectively
-# see global.proxy.resources for details.
-#smiMetricsResources:
-#smiMetricsProxyResources:
-
 # Configuration for Add-ons
 # Full configuration fields https://github.com/linkerd/linkerd2/tree/master/charts/linkerd2#add-ons-configuration
 
diff --git a/cli/cmd/alpha.go b/cli/cmd/alpha.go
index db8d867cb..90ad4e8c7 100644
--- a/cli/cmd/alpha.go
+++ b/cli/cmd/alpha.go
@@ -12,8 +12,5 @@ func newCmdAlpha() *cobra.Command {
 		Args:  cobra.NoArgs,
 	}
 
-	alphaCmd.AddCommand(newCmdAlphaStat())
-	alphaCmd.AddCommand(newCmdAlphaClients())
-
 	return alphaCmd
 }
diff --git a/cli/cmd/alpha_clients.go b/cli/cmd/alpha_clients.go
deleted file mode 100644
index 9c35ec918..000000000
--- a/cli/cmd/alpha_clients.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package cmd
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/linkerd/linkerd2/controller/api/util"
-	"github.com/linkerd/linkerd2/pkg/k8s"
-	"github.com/linkerd/linkerd2/pkg/smimetrics"
-	"github.com/spf13/cobra"
-
-	corev1 "k8s.io/api/core/v1"
-)
-
-// alphaClientsOptions holds values for command line flags that apply to the alpha
-// clients command. All fields in this struct should have corresponding flags added in
-// the newCmdAlphaClients func later in this file.
-type alphaClientsOptions struct {
-	namespace string
-}
-
-// newCmdAlphaClients creates a new cobra command for the `alpha clients` subcommand which
-// display client-side traffic stats to a resource. [Experimental]
-func newCmdAlphaClients() *cobra.Command {
-	options := alphaClientsOptions{
-		namespace: corev1.NamespaceDefault,
-	}
-
-	clientsCmd := &cobra.Command{
-		Use:   "clients [flags] (RESOURCE)",
-		Short: "Display client-side traffic stats to a resource.",
-		Long: `Display client-side traffic stats to a resource.
-		
-(RESOURCE) is a named resource of one these kinds:
-  * cronjobs
-  * daemonsets
-  * deployments
-  * jobs
-  * namespaces
-  * pods
-  * replicasets
-  * replicationcontrollers
-  * statefulsets
-
-linkerd alpha clients will return a table of the requested resource's clients
-showing traffic metrics to the requested resource such as request rate, success
-rate, and latency percentiles.  These values are measured on the client side
-and, for example, include network latency.
-
-Examples:
-  linkerd alpha clients -n emojivoto deploy/web`,
-		Args: cobra.ExactArgs(1),
-		RunE: func(cmd *cobra.Command, args []string) error {
-			k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
-			if err != nil {
-				return err
-			}
-
-			target, err := util.BuildResource(options.namespace, args[0])
-			if err != nil {
-				return err
-			}
-			if _, ok := allowedKinds[target.GetType()]; !ok {
-				return fmt.Errorf("%s is not a supported resource type", target.GetType())
-			}
-			if target.GetName() == "" {
-				return errors.New("You must specify a resource name")
-			}
-			kind, err := k8s.PluralResourceNameFromFriendlyName(target.GetType())
-			if err != nil {
-				return err
-			}
-
-			metrics, err := smimetrics.GetTrafficMetricsEdgesList(k8sAPI, options.namespace, kind, target.GetName(), nil)
-			if err != nil {
-				return err
-			}
-			renderTrafficMetricsEdgesList(metrics, stdout, nil, "from")
-
-			return nil
-		},
-	}
-
-	clientsCmd.PersistentFlags().StringVarP(&options.namespace, "namespace", "n", options.namespace, "Namespace of the specified resource")
-	return clientsCmd
-}
diff --git a/cli/cmd/alpha_stat.go b/cli/cmd/alpha_stat.go
deleted file mode 100644
index 7d043ca51..000000000
--- a/cli/cmd/alpha_stat.go
+++ /dev/null
@@ -1,312 +0,0 @@
-package cmd
-
-import (
-	"errors"
-	"fmt"
-	"io"
-
-	"github.com/linkerd/linkerd2/cli/table"
-	"github.com/linkerd/linkerd2/controller/api/util"
-	"github.com/linkerd/linkerd2/controller/gen/public"
-	"github.com/linkerd/linkerd2/pkg/k8s"
-	"github.com/linkerd/linkerd2/pkg/smimetrics"
-	log "github.com/sirupsen/logrus"
-	"github.com/spf13/cobra"
-
-	"github.com/servicemeshinterface/smi-sdk-go/pkg/apis/metrics/v1alpha1"
-	corev1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/api/resource"
-)
-
-var allowedKinds = map[string]struct{}{
-	k8s.CronJob:               struct{}{},
-	k8s.DaemonSet:             struct{}{},
-	k8s.Deployment:            struct{}{},
-	k8s.Job:                   struct{}{},
-	k8s.Namespace:             struct{}{},
-	k8s.Pod:                   struct{}{},
-	k8s.ReplicaSet:            struct{}{},
-	k8s.ReplicationController: struct{}{},
-	k8s.StatefulSet:           struct{}{},
-}
-
-// alphaStatOptions holds values for command line flags that apply to the alpha
-// stat command. All fields in this struct should have corresponding flags added in
-// the newCmdAlphaStat func later in this file.
-type alphaStatOptions struct {
-	namespace     string
-	toResource    string
-	allNamespaces bool
-}
-
-// newCmdAlphaStat creates a new cobra command for the `alpha stat` subcommand which
-// display traffic stats about one or many resources. [Experimental]
-func newCmdAlphaStat() *cobra.Command {
-	options := alphaStatOptions{
-		namespace: "default",
-	}
-
-	statCmd := &cobra.Command{
-		Use:   "stat [flags] (RESOURCE)",
-		Short: "Display traffic stats about one or many resources",
-		Long: `Display traffic stats about one or many resources
-
-(RESOURCE) can be a resource kind; one of:
-  * cronjobs
-  * daemonsets
-  * deployments
-  * jobs
-  * namespaces
-  * pods
-  * replicasets
-  * replicationcontrollers
-  * statefulsets
-or it may be a specific named resource of one of the above kinds.
-
-linkerd alpha stat will return a table of the requested resource or resources
-showing the top-line metrics for those resources such as request rate, success
-rate, and latency percentiles.  These values are measured on the server-side
-unless the --to flag is specified.
-
-The --to flag accepts a resource kind or a specific resource and instead
-displays the metrics measured on the client side from the root resource to
-the to-resource.  The root resource must be a specific named resource.
-
-Examples:
-  # Topline Resource Metrics
-  linkerd alpha stat -n emojivoto deploy/web
-
-  # Topline Resource Metrics for a whole Kind
-  linkerd alpha stat -n emojivoto deploy
-
-  # Outbound edges
-  linkerd alpha stat -n emojivoto deploy/web --to=deploy
-
-  # Outbound to a specific destination
-  linkerd alpha stat -n emojivoto deploy/web --to=deploy/emoji`,
-		Args: cobra.ExactArgs(1),
-		RunE: func(cmd *cobra.Command, args []string) error {
-			k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
-			if err != nil {
-				return err
-			}
-
-			namespace := options.namespace
-			if options.allNamespaces {
-				namespace = corev1.NamespaceAll
-			}
-			target, err := util.BuildResource(namespace, args[0])
-			if err != nil {
-				return err
-			}
-			if target.GetName() != "" && options.allNamespaces {
-				// Getting a named resource from all-namespaces is not supported.
-				return errors.New("cannot use --all-namespaces flag with a named target resource")
-			}
-
-			if _, ok := allowedKinds[target.GetType()]; !ok {
-				return fmt.Errorf("%s is not a supported resource type", target.GetType())
-			}
-			kind, err := k8s.PluralResourceNameFromFriendlyName(target.GetType())
-			if err != nil {
-				return err
-			}
-			name := target.GetName()
-			toResource := buildToResource("", options.toResource)
-			// TODO: Lift this requirement once the API supports it.
-			if toResource != nil && toResource.GetType() != target.GetType() {
-				return errors.New("the --to resource must have the same kind as the target resource")
-			}
-
-			if name != "" {
-				if toResource != nil {
-					metrics, err := smimetrics.GetTrafficMetricsEdgesList(k8sAPI, target.GetNamespace(), kind, name, nil)
-					if err != nil {
-						return err
-					}
-					renderTrafficMetricsEdgesList(metrics, stdout, toResource, "to")
-				} else {
-					metrics, err := smimetrics.GetTrafficMetrics(k8sAPI, target.GetNamespace(), kind, name, nil)
-					if err != nil {
-						return err
-					}
-					renderTrafficMetrics(metrics, options.allNamespaces, stdout)
-				}
-			} else {
-				if toResource != nil {
-					return errors.New("the --to flag requires that the target resource name be specified")
-				}
-				metrics, err := smimetrics.GetTrafficMetricsList(k8sAPI, target.GetNamespace(), kind, nil)
-				if err != nil {
-					return err
-				}
-				renderTrafficMetricsList(metrics, options.allNamespaces, stdout)
-			}
-
-			return nil
-		},
-	}
-
-	statCmd.PersistentFlags().StringVarP(&options.namespace, "namespace", "n", options.namespace, "Namespace of the specified resource")
-	statCmd.PersistentFlags().StringVar(&options.toResource, "to", options.toResource, "If present, restricts outbound stats to the specified resource name")
-	statCmd.PersistentFlags().BoolVarP(&options.allNamespaces, "all-namespaces", "A", options.allNamespaces, "Ignore the --namespace flag and fetches data from all namespaces")
-
-	return statCmd
-}
-
-func buildToResource(namespace, to string) *public.Resource {
-	toResource, err := util.BuildResource(namespace, to)
-	if err != nil {
-		log.Debugf("Invalid to resource: %s", err)
-		return nil
-
-	}
-	log.Debugf("Using to resource: %v", toResource)
-	return toResource
-}
-
-func renderTrafficMetrics(metrics *v1alpha1.TrafficMetrics, allNamespaces bool, w io.Writer) {
-	t := buildTable(false, allNamespaces)
-	t.Data = []table.Row{metricsToRow(metrics, "")}
-	t.Render(w)
-}
-
-func renderTrafficMetricsList(metrics *v1alpha1.TrafficMetricsList, allNamespaces bool, w io.Writer) {
-	t := buildTable(false, allNamespaces)
-	t.Data = []table.Row{}
-	for _, row := range metrics.Items {
-		row := row // Copy to satisfy golint.
-		t.Data = append(t.Data, metricsToRow(row, ""))
-	}
-	t.Render(w)
-}
-
-// renderTrafficMetricsEdgesList will render a table to the given Writer.
-// Rows will be filtered to make sure that only traffic directed to the resource requested by the `--to` flag is shown
-func renderTrafficMetricsEdgesList(metrics *v1alpha1.TrafficMetricsList, w io.Writer, toResource *public.Resource, direction string) {
-	t := buildTable(true, false)
-	t.Data = []table.Row{}
-	for _, row := range metrics.Items {
-		row := row // Copy to satisfy golint.
-		if string(row.Edge.Direction) != direction {
-			continue
-		}
-		if toResource != nil {
-			if toResource.GetName() != "" && row.Edge.Resource.Name != toResource.GetName() {
-				log.Debugf("Skipping edge %v", row.Edge.Resource)
-				continue
-			}
-		}
-		t.Data = append(t.Data, metricsToRow(row, direction))
-	}
-	t.Render(w)
-}
-
-func getNumericMetric(metrics *v1alpha1.TrafficMetrics, name string) *resource.Quantity {
-	for _, m := range metrics.Metrics {
-		if m.Name == name {
-			return m.Value
-		}
-	}
-	return resource.NewQuantity(0, resource.DecimalSI)
-}
-
-func getNumericMetricWithUnit(metrics *v1alpha1.TrafficMetrics, name string) string {
-	for _, m := range metrics.Metrics {
-		if m.Name == name {
-			value := m.Value.Value()
-			return fmt.Sprintf("%d%s", value, m.Unit)
-		}
-	}
-	return ""
-}
-
-func metricsToRow(metrics *v1alpha1.TrafficMetrics, direction string) []string {
-	success := getNumericMetric(metrics, "success_count").MilliValue()
-	failure := getNumericMetric(metrics, "failure_count").MilliValue()
-	sr := "-"
-	if success+failure > 0 {
-		rate := float32(success) / float32(success+failure) * 100
-		sr = fmt.Sprintf("%.2f%%", rate)
-	}
-	rate := float64(success+failure) / 1000.0 / metrics.Window.Seconds()
-	rps := fmt.Sprintf("%.1frps", rate)
-
-	var to string
-	var from string
-	if direction == "to" {
-		to = metrics.Edge.Resource.String()
-		from = metrics.Resource.Name
-	} else if direction == "from" {
-		to = metrics.Resource.Name
-		from = metrics.Edge.Resource.String()
-	}
-
-	return []string{
-		metrics.Resource.Namespace,
-		metrics.Resource.Name,
-		from,
-		to,
-		sr,
-		rps,
-		getNumericMetricWithUnit(metrics, "p50_response_latency"),
-		getNumericMetricWithUnit(metrics, "p90_response_latency"),
-		getNumericMetricWithUnit(metrics, "p99_response_latency"),
-	}
-}
-
-func buildTable(outbound, allNamespaces bool) table.Table {
-	columns := []table.Column{
-		table.Column{
-			Header:    "NAMESPACE",
-			Width:     9,
-			Hide:      !allNamespaces,
-			Flexible:  true,
-			LeftAlign: true,
-		},
-		table.Column{
-			Header:    "NAME",
-			Width:     4,
-			Hide:      outbound,
-			Flexible:  true,
-			LeftAlign: true,
-		},
-		table.Column{
-			Header:    "FROM",
-			Width:     4,
-			Hide:      !outbound,
-			Flexible:  true,
-			LeftAlign: true,
-		},
-		table.Column{
-			Header:    "TO",
-			Width:     2,
-			Hide:      !outbound,
-			Flexible:  true,
-			LeftAlign: true,
-		},
-		table.Column{
-			Header: "SUCCESS",
-			Width:  7,
-		},
-		table.Column{
-			Header: "RPS",
-			Width:  9,
-		},
-		table.Column{
-			Header: "LATENCY_P50",
-			Width:  11,
-		},
-		table.Column{
-			Header: "LATENCY_P90",
-			Width:  11,
-		},
-		table.Column{
-			Header: "LATENCY_P99",
-			Width:  11,
-		},
-	}
-	t := table.NewTable(columns, []table.Row{})
-	t.Sort = []int{0, 1} // Sort by namespace, then name.
-	return t
-}
diff --git a/cli/cmd/install.go b/cli/cmd/install.go
index 605bacda3..59b942b4b 100644
--- a/cli/cmd/install.go
+++ b/cli/cmd/install.go
@@ -54,8 +54,6 @@ type (
 		restrictDashboardPrivileges bool
 		controlPlaneTracing         bool
 		identityOptions             *installIdentityOptions
-		smiMetricsEnabled           bool
-		smiMetricsImage             string
 		*proxyConfigOptions
 
 		recordedFlags []*pb.Install_Flag
@@ -132,7 +130,6 @@ var (
 		"templates/sp-validator-rbac.yaml",
 		"templates/tap-rbac.yaml",
 		"templates/psp.yaml",
-		"templates/smi-metrics-rbac.yaml",
 	}
 
 	templatesControlPlaneStage = []string{
@@ -147,7 +144,6 @@ var (
 		"templates/proxy-injector.yaml",
 		"templates/sp-validator.yaml",
 		"templates/tap.yaml",
-		"templates/smi-metrics.yaml",
 		"templates/linkerd-config-addons.yaml",
 	}
 )
@@ -189,8 +185,6 @@ func newInstallOptionsWithDefaults() (*installOptions, error) {
 		omitWebhookSideEffects:      defaults.OmitWebhookSideEffects,
 		restrictDashboardPrivileges: defaults.RestrictDashboardPrivileges,
 		controlPlaneTracing:         defaults.Global.ControlPlaneTracing,
-		smiMetricsEnabled:           defaults.SMIMetrics.Enabled,
-		smiMetricsImage:             defaults.SMIMetrics.Image,
 		proxyConfigOptions: &proxyConfigOptions{
 			proxyVersion:           version.Version,
 			ignoreCluster:          false,
@@ -515,16 +509,10 @@ func (options *installOptions) recordableFlagSet() *pflag.FlagSet {
 		"A path to a PEM-encoded file containing Linkerd Identity trust anchors (generated by default)",
 	)
 
-	flags.BoolVar(
-		&options.smiMetricsEnabled, "smi-metrics", options.smiMetricsEnabled,
-		"Enables installing the SMI-Metrics controller",
-	)
-
 	flags.BoolVar(&options.enableEndpointSlices, "enable-endpoint-slices", options.enableEndpointSlices,
 		"Enables the usage of EndpointSlice informers and resources for destination service")
 
 	flags.StringVarP(&options.controlPlaneVersion, "control-plane-version", "", options.controlPlaneVersion, "Tag to be used for the control plane component images")
-	flags.StringVar(&options.smiMetricsImage, "smi-metrics-image", options.smiMetricsImage, "SMI Metrics image")
 
 	// Hide developer focused flags in release builds.
 	release, err := version.IsReleaseChannel(version.Version)
@@ -541,9 +529,6 @@ func (options *installOptions) recordableFlagSet() *pflag.FlagSet {
 	}
 
 	flags.MarkHidden("control-plane-tracing")
-	flags.MarkHidden("smi-metrics")
-	flags.MarkHidden("smi-metrics-image")
-
 	return flags
 }
 
@@ -801,8 +786,6 @@ func (options *installOptions) buildValuesWithoutIdentity(configs *pb.All) (*l5d
 		}
 		installValues.Grafana["image"].(map[string]interface{})["name"] = fmt.Sprintf("%s/grafana", options.dockerRegistry)
 	}
-	installValues.SMIMetrics.Image = options.smiMetricsImage
-	installValues.SMIMetrics.Enabled = options.smiMetricsEnabled
 
 	installValues.Global.Proxy = &l5dcharts.Proxy{
 		DestinationGetNetworks: strings.Join(options.destinationGetNetworks, ","),
@@ -902,7 +885,6 @@ func render(w io.Writer, values *l5dcharts.Values) error {
 	}
 
 	if values.Stage == "" || values.Stage == controlPlaneStage {
-		files = append(files, &chartutil.BufferedFile{Name: "smi-metrics-config.yaml"})
 		for _, template := range templatesControlPlaneStage {
 			files = append(files,
 				&chartutil.BufferedFile{Name: template},
@@ -956,7 +938,6 @@ func (options *installOptions) globalConfig(identity *pb.IdentityContext) *pb.Gl
 	return &pb.Global{
 		LinkerdNamespace:       controlPlaneNamespace,
 		CniEnabled:             options.cniEnabled,
-		EndpointSliceEnabled:   options.enableEndpointSlices,
 		Version:                options.controlPlaneVersion,
 		IdentityContext:        identity,
 		OmitWebhookSideEffects: options.omitWebhookSideEffects,
diff --git a/cli/cmd/upgrade.go b/cli/cmd/upgrade.go
index b771d6b1c..11508c474 100644
--- a/cli/cmd/upgrade.go
+++ b/cli/cmd/upgrade.go
@@ -242,11 +242,19 @@ func (options *upgradeOptions) validateAndBuild(stage string, k *k8s.KubernetesA
 	// The overrideConfigs() is used to override proxy configs only.
 	options.overrideConfigs(configs, map[string]string{})
 
+	if options.enableEndpointSlices {
+		if err = validateEndpointSlicesFeature(); err != nil {
+			return nil, fmt.Errorf("--enableEndpointSlice=true not supported: %s", err)
+		}
+	}
+
 	// Override configs with upgrade CLI options.
 	if options.controlPlaneVersion != "" {
 		configs.GetGlobal().Version = options.controlPlaneVersion
 	}
+
 	configs.GetInstall().Flags = options.recordedFlags
+
 	configs.GetGlobal().OmitWebhookSideEffects = options.omitWebhookSideEffects
 	if configs.GetGlobal().GetClusterDomain() == "" {
 		configs.GetGlobal().ClusterDomain = defaultClusterDomain
@@ -339,15 +347,6 @@ func (options *upgradeOptions) validateAndBuild(stage string, k *k8s.KubernetesA
 	}
 	values.Tap = &charts.Tap{TLS: tapTLS}
 
-	smiMetricsTLS, err := fetchK8sTLSSecret(k, k8s.SmiMetricsServiceName, options)
-	if err != nil {
-		if !kerrors.IsNotFound(err) {
-			return nil, fmt.Errorf("could not fetch existing SMI metrics secret: %s", err)
-		}
-		smiMetricsTLS = &charts.TLS{}
-	}
-	values.SMIMetrics.TLS = smiMetricsTLS
-
 	values.Stage = stage
 
 	if !options.addOnOverwrite {
@@ -389,7 +388,6 @@ func (options *upgradeOptions) validateAndBuild(stage string, k *k8s.KubernetesA
 func setFlagsFromInstall(flags *pflag.FlagSet, installFlags []*pb.Install_Flag) {
 	for _, i := range installFlags {
 		if f := flags.Lookup(i.GetName()); f != nil && !f.Changed {
-
 			// The function recordFlags() stores the string representation of flags in the ConfigMap
 			// so a stringSlice is stored e.g. as [a,b].
 			// To avoid having f.Value.Set() interpreting that as a string we need to remove
@@ -439,8 +437,6 @@ func injectCABundle(k *k8s.KubernetesAPI, webhook string, value *charts.TLS) err
 		err = injectCABundleFromValidatingWebhook(k, k8s.SPValidatorWebhookConfigName, value)
 	case k8s.TapServiceName:
 		err = injectCABundleFromAPIService(k, k8s.TapAPIRegistrationServiceName, value)
-	case k8s.SmiMetricsServiceName:
-		err = injectCABundleFromAPIService(k, k8s.SmiMetricsAPIRegistrationServiceName, value)
 	default:
 		err = fmt.Errorf("unknown webhook for retrieving CA bundle: %s", webhook)
 	}
@@ -511,30 +507,6 @@ func fetchTLSSecret(k *k8s.KubernetesAPI, webhook string, options *upgradeOption
 	return value, nil
 }
 
-func fetchK8sTLSSecret(k *k8s.KubernetesAPI, webhook string, options *upgradeOptions) (*charts.TLS, error) {
-	secret, err := k.CoreV1().
-		Secrets(controlPlaneNamespace).
-		Get(webhookSecretName(webhook), metav1.GetOptions{})
-	if err != nil {
-		return nil, err
-	}
-
-	value := &charts.TLS{
-		KeyPEM: string(secret.Data["tls.key"]),
-		CrtPEM: string(secret.Data["tls.crt"]),
-	}
-
-	if err := injectCABundle(k, webhook, value); err != nil {
-		return nil, err
-	}
-
-	if err := options.verifyTLS(value, webhook); err != nil {
-		return nil, err
-	}
-
-	return value, nil
-}
-
 func ensureIssuerCertWorksWithAllProxies(k kubernetes.Interface, cred *tls.Cred) error {
 	meshedPods, err := healthcheck.GetMeshedPodsIdentityData(k, "")
 	var problematicPods []string
diff --git a/controller/api/destination/endpoint_translator.go b/controller/api/destination/endpoint_translator.go
index 7a1811699..a25682da8 100644
--- a/controller/api/destination/endpoint_translator.go
+++ b/controller/api/destination/endpoint_translator.go
@@ -9,6 +9,9 @@ import (
 	"github.com/linkerd/linkerd2/pkg/addr"
 	"github.com/linkerd/linkerd2/pkg/k8s"
 	logging "github.com/sirupsen/logrus"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/client-go/kubernetes"
 )
 
 const defaultWeight uint32 = 10000
@@ -19,8 +22,12 @@ type endpointTranslator struct {
 	controllerNS        string
 	identityTrustDomain string
 	enableH2Upgrade     bool
-	stream              pb.Destination_GetServer
-	log                 *logging.Entry
+	nodeTopologyLabels  map[string]string
+
+	availableEndpoints watcher.AddressSet
+	filteredSnapshot   watcher.AddressSet
+	stream             pb.Destination_GetServer
+	log                *logging.Entry
 }
 
 func newEndpointTranslator(
@@ -28,6 +35,8 @@ func newEndpointTranslator(
 	identityTrustDomain string,
 	enableH2Upgrade bool,
 	service string,
+	srcNodeName string,
+	k8sClient kubernetes.Interface,
 	stream pb.Destination_GetServer,
 	log *logging.Entry,
 ) *endpointTranslator {
@@ -36,10 +45,158 @@ func newEndpointTranslator(
 		"service":   service,
 	})
 
-	return &endpointTranslator{controllerNS, identityTrustDomain, enableH2Upgrade, stream, log}
+	nodeTopologyLabels, err := getK8sNodeTopology(k8sClient, srcNodeName)
+	if err != nil {
+		log.Errorf("Failed to get node topology for node %s: %s", srcNodeName, err)
+	}
+	availableEndpoints := newEmptyAddressSet()
+
+	filteredSnapshot := newEmptyAddressSet()
+
+	return &endpointTranslator{
+		controllerNS,
+		identityTrustDomain,
+		enableH2Upgrade,
+		nodeTopologyLabels,
+		availableEndpoints,
+		filteredSnapshot,
+		stream,
+		log,
+	}
 }
 
 func (et *endpointTranslator) Add(set watcher.AddressSet) {
+	for id, address := range set.Addresses {
+		et.availableEndpoints.Addresses[id] = address
+	}
+
+	et.sendFilteredUpdate(set)
+}
+
+func (et *endpointTranslator) Remove(set watcher.AddressSet) {
+	for id := range set.Addresses {
+		delete(et.availableEndpoints.Addresses, id)
+	}
+
+	et.sendFilteredUpdate(set)
+}
+
+func (et *endpointTranslator) sendFilteredUpdate(set watcher.AddressSet) {
+	et.availableEndpoints = watcher.AddressSet{
+		Addresses:       et.availableEndpoints.Addresses,
+		Labels:          set.Labels,
+		TopologicalPref: set.TopologicalPref,
+	}
+
+	filtered := et.filterAddresses()
+	diffAdd, diffRemove := et.diffEndpoints(filtered)
+
+	if len(diffAdd.Addresses) > 0 {
+		et.sendClientAdd(diffAdd)
+	}
+	if len(diffRemove.Addresses) > 0 {
+		et.sendClientRemove(diffRemove)
+	}
+
+	et.filteredSnapshot = filtered
+}
+
+// filterAddresses is responsible for filtering endpoints based on service topology preference.
+// The client will receive only endpoints with the same topology label value as the source node,
+// the order of labels is based on the topological preference elicited from the K8s service.
+func (et *endpointTranslator) filterAddresses() watcher.AddressSet {
+	if len(et.availableEndpoints.TopologicalPref) == 0 {
+		allAvailEndpoints := make(map[watcher.ID]watcher.Address)
+		for k, v := range et.availableEndpoints.Addresses {
+			allAvailEndpoints[k] = v
+		}
+		return watcher.AddressSet{
+			Addresses: allAvailEndpoints,
+			Labels:    et.availableEndpoints.Labels,
+		}
+	}
+
+	et.log.Debugf("Filtering through address set with preference %v", et.availableEndpoints.TopologicalPref)
+	filtered := make(map[watcher.ID]watcher.Address)
+	for _, pref := range et.availableEndpoints.TopologicalPref {
+		// '*' as a topology preference means all endpoints
+		if pref == "*" {
+			return et.availableEndpoints
+		}
+
+		srcLocality, ok := et.nodeTopologyLabels[pref]
+		if !ok {
+			continue
+		}
+
+		for id, address := range et.availableEndpoints.Addresses {
+			addrLocality := address.TopologyLabels[pref]
+			if addrLocality == srcLocality {
+				filtered[id] = address
+			}
+		}
+
+		// if we filtered at least one endpoint, it means that preference has been satisfied
+		if len(filtered) > 0 {
+			et.log.Debugf("Filtered %d from a total of %d", len(filtered), len(et.availableEndpoints.Addresses))
+			return watcher.AddressSet{
+				Addresses: filtered,
+				Labels:    et.availableEndpoints.Labels,
+			}
+		}
+	}
+
+	// if we have no filtered endpoints or the '*' preference then no topology pref is satisfied
+	return newEmptyAddressSet()
+}
+
+// diffEndpoints calculates the difference between the filtered set of endpoints in the current (Add/Remove) operation
+// and the snapshot of previously filtered endpoints. This diff allows the client to receive only the endpoints that
+// satisfy the topological preference, by adding new endpoints and removing stale ones.
+func (et *endpointTranslator) diffEndpoints(filtered watcher.AddressSet) (watcher.AddressSet, watcher.AddressSet) {
+	add := make(map[watcher.ID]watcher.Address)
+	remove := make(map[watcher.ID]watcher.Address)
+
+	for id, address := range filtered.Addresses {
+		if _, ok := et.filteredSnapshot.Addresses[id]; !ok {
+			add[id] = address
+		}
+	}
+
+	for id, address := range et.filteredSnapshot.Addresses {
+		if _, ok := filtered.Addresses[id]; !ok {
+			remove[id] = address
+		}
+	}
+
+	return watcher.AddressSet{
+			Addresses: add,
+			Labels:    filtered.Labels,
+		},
+		watcher.AddressSet{
+			Addresses: remove,
+			Labels:    filtered.Labels,
+		}
+}
+
+func (et *endpointTranslator) NoEndpoints(exists bool) {
+	et.log.Debugf("NoEndpoints(%+v)", exists)
+
+	u := &pb.Update{
+		Update: &pb.Update_NoEndpoints{
+			NoEndpoints: &pb.NoEndpoints{
+				Exists: exists,
+			},
+		},
+	}
+
+	et.log.Debugf("Sending destination no endpoints: %+v", u)
+	if err := et.stream.Send(u); err != nil {
+		et.log.Errorf("Failed to send address update: %s", err)
+	}
+}
+
+func (et *endpointTranslator) sendClientAdd(set watcher.AddressSet) {
 	addrs := []*pb.WeightedAddr{}
 	for _, address := range set.Addresses {
 		var (
@@ -103,7 +260,7 @@ func (et *endpointTranslator) Add(set watcher.AddressSet) {
 	}
 }
 
-func (et *endpointTranslator) Remove(set watcher.AddressSet) {
+func (et *endpointTranslator) sendClientRemove(set watcher.AddressSet) {
 	addrs := []*net.TcpAddress{}
 	for _, address := range set.Addresses {
 		tcpAddr, err := et.toAddr(address)
@@ -126,23 +283,6 @@ func (et *endpointTranslator) Remove(set watcher.AddressSet) {
 	}
 }
 
-func (et *endpointTranslator) NoEndpoints(exists bool) {
-	et.log.Debugf("NoEndpoints(%+v)", exists)
-
-	u := &pb.Update{
-		Update: &pb.Update_NoEndpoints{
-			NoEndpoints: &pb.NoEndpoints{
-				Exists: exists,
-			},
-		},
-	}
-
-	et.log.Debugf("Sending destination no endpoints: %+v", u)
-	if err := et.stream.Send(u); err != nil {
-		et.log.Errorf("Failed to send address update: %s", err)
-	}
-}
-
 func (et *endpointTranslator) toAddr(address watcher.Address) (*net.TcpAddress, error) {
 	ip, err := addr.ParseProxyIPV4(address.IP)
 	if err != nil {
@@ -203,3 +343,29 @@ func (et *endpointTranslator) toWeightedAddr(address watcher.Address) (*pb.Weigh
 		ProtocolHint: hint,
 	}, nil
 }
+
+func getK8sNodeTopology(k8sClient kubernetes.Interface, srcNode string) (map[string]string, error) {
+	nodeTopology := make(map[string]string)
+	node, err := k8sClient.CoreV1().Nodes().Get(srcNode, metav1.GetOptions{})
+	if err != nil {
+		return nodeTopology, err
+	}
+
+	for k, v := range node.Labels {
+		if k == corev1.LabelHostname ||
+			k == corev1.LabelZoneFailureDomainStable ||
+			k == corev1.LabelZoneRegionStable {
+			nodeTopology[k] = v
+		}
+	}
+
+	return nodeTopology, nil
+}
+
+func newEmptyAddressSet() watcher.AddressSet {
+	return watcher.AddressSet{
+		Addresses:       make(map[watcher.ID]watcher.Address),
+		Labels:          make(map[string]string),
+		TopologicalPref: []string{},
+	}
+}
diff --git a/controller/api/destination/server.go b/controller/api/destination/server.go
index 1896b4ced..0b789896d 100644
--- a/controller/api/destination/server.go
+++ b/controller/api/destination/server.go
@@ -30,6 +30,7 @@ type (
 		identityTrustDomain string
 		clusterDomain       string
 
+		k8sAPI   *k8s.API
 		log      *logging.Entry
 		shutdown <-chan struct{}
 	}
@@ -75,6 +76,7 @@ func NewServer(
 		controllerNS,
 		identityTrustDomain,
 		clusterDomain,
+		k8sAPI,
 		log,
 		shutdown,
 	}
@@ -93,11 +95,19 @@ func (s *server) Get(dest *pb.GetDestination, stream pb.Destination_GetServer) e
 	}
 	log.Debugf("Get %s", dest.GetPath())
 
+	var token contextToken
+	if dest.GetContextToken() != "" {
+		token = s.parseContextToken(dest.GetContextToken())
+		log.Debugf("Dest token: %v", token)
+	}
+
 	translator := newEndpointTranslator(
 		s.controllerNS,
 		s.identityTrustDomain,
 		s.enableH2Upgrade,
 		dest.GetPath(),
+		token.NodeName,
+		s.k8sAPI.Client,
 		stream,
 		log,
 	)
diff --git a/controller/api/destination/traffic_split_adaptor.go b/controller/api/destination/traffic_split_adaptor.go
index aa6ab240e..88456d2eb 100644
--- a/controller/api/destination/traffic_split_adaptor.go
+++ b/controller/api/destination/traffic_split_adaptor.go
@@ -6,6 +6,7 @@ import (
 	"github.com/linkerd/linkerd2/controller/api/destination/watcher"
 	sp "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
 	ts "github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
+	"k8s.io/apimachinery/pkg/api/resource"
 )
 
 // trafficSplitAdaptor merges traffic splits into service profiles, encoding
@@ -64,11 +65,15 @@ func (tsa *trafficSplitAdaptor) publish() {
 			overrides = append(overrides, dst)
 		}
 		merged.Spec.DstOverrides = overrides
-	}
-
-	if tsa.profile == nil && tsa.split == nil {
-		tsa.listener.Update(nil)
 	} else {
-		tsa.listener.Update(&merged)
+		// If there is no traffic split, always return a destination override
+		// so that it's known the host is a service.
+		dst := &sp.WeightedDst{
+			Authority: fmt.Sprintf("%s.%s.svc.%s.:%d", tsa.id.Name, tsa.id.Namespace, tsa.clusterDomain, tsa.port),
+			Weight:    resource.MustParse("1"),
+		}
+		merged.Spec.DstOverrides = []*sp.WeightedDst{dst}
 	}
+
+	tsa.listener.Update(&merged)
 }
diff --git a/controller/api/destination/watcher/endpoints_watcher.go b/controller/api/destination/watcher/endpoints_watcher.go
index 225aff435..90db0c044 100644
--- a/controller/api/destination/watcher/endpoints_watcher.go
+++ b/controller/api/destination/watcher/endpoints_watcher.go
@@ -47,12 +47,14 @@ type (
 		OwnerKind         string
 		Identity          string
 		AuthorityOverride string
+		TopologyLabels    map[string]string
 	}
 
 	// AddressSet is a set of Address, indexed by ID.
 	AddressSet struct {
-		Addresses map[ID]Address
-		Labels    map[string]string
+		Addresses       map[ID]Address
+		Labels          map[string]string
+		TopologicalPref []string
 	}
 
 	portAndHostname struct {
@@ -88,7 +90,8 @@ type (
 		k8sAPI               *k8s.API
 		enableEndpointSlices bool
 
-		ports map[portAndHostname]*portPublisher
+		TopologyPref []string
+		ports        map[portAndHostname]*portPublisher
 		// All access to the servicePublisher and its portPublishers is explicitly synchronized by
 		// this mutex.
 		sync.Mutex
@@ -107,6 +110,7 @@ type (
 		log                  *logging.Entry
 		k8sAPI               *k8s.API
 		enableEndpointSlices bool
+		TopologyPref         []string
 
 		exists    bool
 		addresses AddressSet
@@ -393,6 +397,7 @@ func (ew *EndpointsWatcher) getOrNewServicePublisher(id ServiceID) *servicePubli
 				"svc":       id.Name,
 			}),
 			k8sAPI:               ew.k8sAPI,
+			TopologyPref:         make([]string, 0),
 			ports:                make(map[portAndHostname]*portPublisher),
 			enableEndpointSlices: ew.enableEndpointSlices,
 		}
@@ -462,12 +467,23 @@ func (sp *servicePublisher) updateService(newService *corev1.Service) {
 	defer sp.Unlock()
 	sp.log.Debugf("Updating service for %s", sp.id)
 
+	if sp.enableEndpointSlices {
+		sp.TopologyPref = make([]string, len(newService.Spec.TopologyKeys))
+		copy(sp.TopologyPref, newService.Spec.TopologyKeys)
+	}
+
 	for key, port := range sp.ports {
+		if sp.enableEndpointSlices {
+			port.TopologyPref = sp.TopologyPref
+			port.updateTopologyPreference()
+		}
+
 		newTargetPort := getTargetPort(newService, key.port)
 		if newTargetPort != port.targetPort {
 			port.updatePort(newTargetPort)
 		}
 	}
+
 }
 
 func (sp *servicePublisher) subscribe(srcPort Port, hostname string, listener EndpointUpdateListener) {
@@ -528,6 +544,7 @@ func (sp *servicePublisher) newPortPublisher(srcPort Port, hostname string) *por
 		log:                  log,
 		metrics:              endpointsVecs.newEndpointsMetrics(sp.metricsLabels(srcPort, hostname)),
 		enableEndpointSlices: sp.enableEndpointSlices,
+		TopologyPref:         sp.TopologyPref,
 	}
 
 	if port.enableEndpointSlices {
@@ -614,8 +631,9 @@ func (pp *portPublisher) addEndpointSlice(slice *discovery.EndpointSlice) {
 
 func (pp *portPublisher) updateEndpointSlice(oldSlice *discovery.EndpointSlice, newSlice *discovery.EndpointSlice) {
 	updatedAddressSet := AddressSet{
-		Addresses: make(map[ID]Address),
-		Labels:    pp.addresses.Labels,
+		Addresses:       make(map[ID]Address),
+		Labels:          pp.addresses.Labels,
+		TopologicalPref: pp.TopologyPref,
 	}
 
 	for id, address := range pp.addresses.Addresses {
@@ -715,6 +733,11 @@ func (pp *portPublisher) endpointSliceToAddresses(es *discovery.EndpointSlice) A
 				identity := es.Annotations[consts.RemoteGatewayIdentity]
 				address, id := pp.newServiceRefAddress(resolvedPort, IPAddr, serviceID.Name, es.Namespace)
 				address.Identity, address.AuthorityOverride = authorityOverride, identity
+
+				for k, v := range endpoint.Topology {
+					address.TopologyLabels[k] = v
+				}
+
 				addresses[id] = address
 			}
 
@@ -728,14 +751,21 @@ func (pp *portPublisher) endpointSliceToAddresses(es *discovery.EndpointSlice) A
 					pp.log.Errorf("Unable to create new address:%v", err)
 					continue
 				}
+
+				for k, v := range endpoint.Topology {
+					address.TopologyLabels[k] = v
+				}
+
 				addresses[id] = address
 			}
 		}
 
 	}
+
 	return AddressSet{
-		Addresses: addresses,
-		Labels:    metricLabels(es),
+		Addresses:       addresses,
+		Labels:          metricLabels(es),
+		TopologicalPref: pp.TopologyPref,
 	}
 }
 
@@ -773,8 +803,9 @@ func (pp *portPublisher) endpointsToAddresses(endpoints *corev1.Endpoints) Addre
 		}
 	}
 	return AddressSet{
-		Addresses: addresses,
-		Labels:    metricLabels(endpoints),
+		Addresses:       addresses,
+		Labels:          metricLabels(endpoints),
+		TopologicalPref: []string{},
 	}
 }
 
@@ -788,7 +819,7 @@ func (pp *portPublisher) newServiceRefAddress(endpointPort Port, endpointIP, ser
 		Namespace: serviceNamespace,
 	}
 
-	return Address{IP: endpointIP, Port: endpointPort}, id
+	return Address{IP: endpointIP, Port: endpointPort, TopologyLabels: make(map[string]string)}, id
 }
 
 func (pp *portPublisher) newPodRefAddress(endpointPort Port, endpointIP, podName, podNamespace string) (Address, PodID, error) {
@@ -802,11 +833,12 @@ func (pp *portPublisher) newPodRefAddress(endpointPort Port, endpointIP, podName
 	}
 	ownerKind, ownerName := pp.k8sAPI.GetOwnerKindAndName(pod, false)
 	addr := Address{
-		IP:        endpointIP,
-		Port:      endpointPort,
-		Pod:       pod,
-		OwnerName: ownerName,
-		OwnerKind: ownerKind,
+		IP:             endpointIP,
+		Port:           endpointPort,
+		Pod:            pod,
+		TopologyLabels: make(map[string]string),
+		OwnerName:      ownerName,
+		OwnerKind:      ownerKind,
 	}
 
 	return addr, id, nil
@@ -870,6 +902,22 @@ func (pp *portPublisher) updatePort(targetPort namedPort) {
 	}
 }
 
+// updateTopologyPreference is used when a service's topology preference changes. This method
+// propagates the changes to the portPublisher, the portPublisher's AddressSet and triggers
+// an (empty) update for all of its listeners to reflect the new preference changes.
+func (pp *portPublisher) updateTopologyPreference() {
+	pp.addresses.TopologicalPref = pp.TopologyPref
+
+	updatedAddrSet := AddressSet{
+		Addresses:       make(map[ID]Address),
+		Labels:          make(map[string]string),
+		TopologicalPref: pp.TopologyPref,
+	}
+	for _, listener := range pp.listeners {
+		listener.Add(updatedAddrSet)
+	}
+}
+
 func (pp *portPublisher) deleteEndpointSlice(es *discovery.EndpointSlice) {
 	addrSet := pp.endpointSliceToAddresses(es)
 	for id := range addrSet.Addresses {
@@ -993,13 +1041,15 @@ func diffAddresses(oldAddresses, newAddresses AddressSet) (add, remove AddressSe
 		}
 	}
 	add = AddressSet{
-		Addresses: addAddresses,
-		Labels:    newAddresses.Labels,
+		Addresses:       addAddresses,
+		Labels:          newAddresses.Labels,
+		TopologicalPref: newAddresses.TopologicalPref,
 	}
 	remove = AddressSet{
-		Addresses: removeAddresses,
+		Addresses:       removeAddresses,
+		TopologicalPref: newAddresses.TopologicalPref,
 	}
-	return
+	return add, remove
 }
 
 func getEndpointSliceServiceID(es *discovery.EndpointSlice) (ServiceID, error) {
diff --git a/controller/cmd/destination/main.go b/controller/cmd/destination/main.go
index 25e638bcf..13366bf27 100644
--- a/controller/cmd/destination/main.go
+++ b/controller/cmd/destination/main.go
@@ -27,6 +27,7 @@ func Main(args []string) {
 	enableH2Upgrade := cmd.Bool("enable-h2-upgrade", true, "Enable transparently upgraded HTTP2 connections among pods in the service mesh")
 	disableIdentity := cmd.Bool("disable-identity", false, "Disable identity configuration")
 	controllerNamespace := cmd.String("controller-namespace", "linkerd", "namespace in which Linkerd is installed")
+	enableEndpointSlices := cmd.Bool("enable-endpoint-slices", false, "Enable the usage of EndpointSlice informers and resources")
 
 	traceCollector := flags.AddTraceFlags(cmd)
 
@@ -73,14 +74,14 @@ func Main(args []string) {
 	if err != nil {
 		log.Fatalf("Failed to initialize K8s API Client: %s", err)
 	}
-	enableEndpointSlices := global.GetEndpointSliceEnabled()
+
 	err = pkgK8s.EndpointSliceAccess(k8Client)
-	if enableEndpointSlices && err != nil {
+	if *enableEndpointSlices && err != nil {
 		log.Fatalf("Failed to start with EndpointSlices enabled: %s", err)
 	}
 
 	var k8sAPI *k8s.API
-	if enableEndpointSlices {
+	if *enableEndpointSlices {
 		k8sAPI, err = k8s.InitializeAPI(
 			*kubeConfigPath, true,
 			k8s.Endpoint, k8s.ES, k8s.Pod, k8s.RS, k8s.Svc, k8s.SP, k8s.TS, k8s.Job,
@@ -100,7 +101,7 @@ func Main(args []string) {
 		*controllerNamespace,
 		trustDomain,
 		*enableH2Upgrade,
-		enableEndpointSlices,
+		*enableEndpointSlices,
 		k8sAPI,
 		clusterDomain,
 		done,
diff --git a/controller/cmd/service-mirror/main.go b/controller/cmd/service-mirror/main.go
index c4a4a078a..b9717223f 100644
--- a/controller/cmd/service-mirror/main.go
+++ b/controller/cmd/service-mirror/main.go
@@ -14,17 +14,18 @@ import (
 	"k8s.io/client-go/tools/clientcmd"
 
 	controllerK8s "github.com/linkerd/linkerd2/controller/k8s"
+	servicemirror "github.com/linkerd/linkerd2/controller/service-mirror"
 	"github.com/linkerd/linkerd2/pkg/admin"
 	"github.com/linkerd/linkerd2/pkg/flags"
 	"github.com/linkerd/linkerd2/pkg/k8s"
 	"github.com/linkerd/linkerd2/pkg/multicluster"
-	"github.com/linkerd/linkerd2/pkg/servicemirror"
+	sm "github.com/linkerd/linkerd2/pkg/servicemirror"
 	log "github.com/sirupsen/logrus"
 )
 
 var (
-	clusterWatcher *RemoteClusterServiceWatcher
-	probeWorker    *ProbeWorker
+	clusterWatcher *servicemirror.RemoteClusterServiceWatcher
+	probeWorker    *servicemirror.ProbeWorker
 )
 
 // Main executes the service-mirror controller
@@ -66,7 +67,7 @@ func Main(args []string) {
 
 	linkClient := k8sAPI.DynamicClient.Resource(multicluster.LinkGVR).Namespace(*namespace)
 
-	metrics := newProbeMetricVecs()
+	metrics := servicemirror.NewProbeMetricVecs()
 	go admin.StartServer(*metricsAddr)
 
 	controllerK8sAPI.Sync(nil)
@@ -136,7 +137,7 @@ func loadCredentials(link multicluster.Link, namespace string, k8sAPI *k8s.Kuber
 	if err != nil {
 		return nil, fmt.Errorf("Failed to load credentials secret %s: %s", link.ClusterCredentialsSecret, err)
 	}
-	return servicemirror.ParseRemoteClusterSecret(secret)
+	return sm.ParseRemoteClusterSecret(secret)
 }
 
 func restartClusterWatcher(
@@ -146,7 +147,7 @@ func restartClusterWatcher(
 	controllerK8sAPI *controllerK8s.API,
 	requeueLimit int,
 	repairPeriod time.Duration,
-	metrics probeMetricVecs,
+	metrics servicemirror.ProbeMetricVecs,
 ) {
 	if clusterWatcher != nil {
 		clusterWatcher.Stop(false)
@@ -161,7 +162,7 @@ func restartClusterWatcher(
 		return
 	}
 
-	clusterWatcher, err = NewRemoteClusterServiceWatcher(
+	clusterWatcher, err = servicemirror.NewRemoteClusterServiceWatcher(
 		namespace,
 		controllerK8sAPI,
 		cfg,
@@ -180,10 +181,10 @@ func restartClusterWatcher(
 		return
 	}
 
-	workerMetrics, err := metrics.newWorkerMetrics(link.TargetClusterName)
+	workerMetrics, err := metrics.NewWorkerMetrics(link.TargetClusterName)
 	if err != nil {
 		log.Errorf("Failed to create metrics for cluster watcher: %s", err)
 	}
-	probeWorker = NewProbeWorker(fmt.Sprintf("probe-gateway-%s", link.TargetClusterName), &link.ProbeSpec, workerMetrics, link.TargetClusterName)
-	go probeWorker.run()
+	probeWorker = servicemirror.NewProbeWorker(fmt.Sprintf("probe-gateway-%s", link.TargetClusterName), &link.ProbeSpec, workerMetrics, link.TargetClusterName)
+	probeWorker.Start()
 }
diff --git a/controller/gen/config/config.pb.go b/controller/gen/config/config.pb.go
index 6eb8d41b9..c12657d1e 100644
--- a/controller/gen/config/config.pb.go
+++ b/controller/gen/config/config.pb.go
@@ -104,8 +104,7 @@ type Global struct {
 	AutoInjectContext      *AutoInjectContext `protobuf:"bytes,6,opt,name=auto_inject_context,json=autoInjectContext,proto3" json:"auto_inject_context,omitempty"`
 	OmitWebhookSideEffects bool               `protobuf:"varint,7,opt,name=omitWebhookSideEffects,proto3" json:"omitWebhookSideEffects,omitempty"`
 	// Override default `cluster.local`
-	ClusterDomain        string `protobuf:"bytes,8,opt,name=cluster_domain,json=clusterDomain,proto3" json:"cluster_domain,omitempty"`
-	EndpointSliceEnabled bool   `protobuf:"varint,9,opt,name=endpoint_slice_enabled,json=endpointSliceEnabled,proto3" json:"endpoint_slice_enabled,omitempty"`
+	ClusterDomain string `protobuf:"bytes,8,opt,name=cluster_domain,json=clusterDomain,proto3" json:"cluster_domain,omitempty"`
 }
 
 func (x *Global) Reset() {
@@ -190,13 +189,6 @@ func (x *Global) GetClusterDomain() string {
 	return ""
 }
 
-func (x *Global) GetEndpointSliceEnabled() bool {
-	if x != nil {
-		return x.EndpointSliceEnabled
-	}
-	return false
-}
-
 type Proxy struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -914,7 +906,7 @@ var file_config_config_proto_rawDesc = []byte{
 	0x07, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18,
 	0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
 	0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x52, 0x07, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c,
-	0x6c, 0x22, 0xaa, 0x03, 0x0a, 0x06, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x11,
+	0x6c, 0x22, 0xf4, 0x02, 0x0a, 0x06, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x11,
 	0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
 	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64,
 	0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6e, 0x69,
@@ -937,135 +929,131 @@ var file_config_config_proto_rawDesc = []byte{
 	0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x53, 0x69, 0x64, 0x65, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74,
 	0x73, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x6d,
 	0x61, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74,
-	0x65, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x65, 0x6e, 0x64, 0x70,
-	0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c,
-	0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
-	0x6e, 0x74, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xec,
-	0x08, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x37, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x78,
-	0x79, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e,
-	0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-	0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6d, 0x61, 0x67,
-	0x65, 0x12, 0x40, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x5f,
-	0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x69,
-	0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6d,
-	0x61, 0x67, 0x65, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x69, 0x74, 0x49, 0x6d,
-	0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70,
-	0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x6e, 0x6b,
-	0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74,
-	0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x4c, 0x0a,
-	0x14, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f,
-	0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x69,
+	0x65, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0xec, 0x08, 0x0a, 0x05, 0x50, 0x72, 0x6f,
+	0x78, 0x79, 0x12, 0x37, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x6d, 0x61, 0x67,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72,
+	0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52,
+	0x0a, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x40, 0x0a, 0x10, 0x70,
+	0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32,
+	0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x0e, 0x70,
+	0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x69, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a,
+	0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74,
+	0x72, 0x6f, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x4c, 0x0a, 0x14, 0x69, 0x67, 0x6e, 0x6f, 0x72,
+	0x65, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18,
+	0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32,
+	0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67,
+	0x65, 0x52, 0x12, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+	0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x15, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f,
+	0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x05,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e,
+	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65,
+	0x52, 0x13, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+	0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+	0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69,
 	0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f,
-	0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x49,
-	0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x4e, 0x0a, 0x15, 0x69,
-	0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70,
-	0x6f, 0x72, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x69, 0x6e,
-	0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72,
-	0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x13, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4f, 0x75,
-	0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x38, 0x0a, 0x0c, 0x69,
-	0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
-	0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x34, 0x0a, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70,
-	0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x6e, 0x6b,
-	0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74,
-	0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x3a, 0x0a, 0x0d, 0x6f,
-	0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f,
-	0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f,
-	0x75, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x41, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75,
-	0x72, 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6c, 0x69, 0x6e, 0x6b,
-	0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
-	0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72,
-	0x6f, 0x78, 0x79, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70,
-	0x72, 0x6f, 0x78, 0x79, 0x55, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x6c,
-	0x65, 0x76, 0x65, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x69, 0x6e,
-	0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x67,
-	0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12,
-	0x3a, 0x0a, 0x19, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72,
-	0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01,
-	0x28, 0x08, 0x52, 0x17, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72,
-	0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70,
-	0x72, 0x6f, 0x78, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
-	0x12, 0x37, 0x0a, 0x18, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x69,
-	0x6d, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x49, 0x6e, 0x69, 0x74, 0x49, 0x6d, 0x61,
-	0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x65, 0x62,
-	0x75, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16,
-	0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6d, 0x61,
-	0x67, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67,
-	0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x11, 0x64, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x11,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x1d, 0x0a, 0x0a,
-	0x6c, 0x6f, 0x67, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x09, 0x6c, 0x6f, 0x67, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x6f,
-	0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f,
-	0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x6f,
-	0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69,
-	0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
-	0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
-	0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43,
-	0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x47, 0x0a,
-	0x05, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f,
-	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67,
-	0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x75, 0x6c, 0x6c, 0x5f, 0x70, 0x6f,
-	0x6c, 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x75, 0x6c, 0x6c,
-	0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x1a, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12,
-	0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f,
-	0x72, 0x74, 0x22, 0x2a, 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
-	0x1d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x9e,
-	0x01, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x69,
-	0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65,
-	0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x70, 0x75, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x0d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12,
-	0x1b, 0x0a, 0x09, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x08, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x43, 0x70, 0x75, 0x12, 0x21, 0x0a, 0x0c,
-	0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0b, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x22,
-	0x17, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e,
-	0x74, 0x65, 0x78, 0x74, 0x3a, 0x02, 0x18, 0x01, 0x22, 0x8d, 0x02, 0x0a, 0x0f, 0x49, 0x64, 0x65,
-	0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c,
-	0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12,
-	0x2a, 0x0a, 0x11, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73,
-	0x5f, 0x70, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x72, 0x75, 0x73,
-	0x74, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x50, 0x65, 0x6d, 0x12, 0x46, 0x0a, 0x11, 0x69,
-	0x73, 0x73, 0x75, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65,
-	0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x52, 0x10, 0x69, 0x73, 0x73, 0x75, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x74,
-	0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x14, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x6b, 0x65,
-	0x77, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x12, 0x63, 0x6c,
-	0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65, 0x77, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x61, 0x6e, 0x63, 0x65,
-	0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x22, 0x20, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c,
-	0x65, 0x76, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x97, 0x01, 0x0a, 0x07, 0x49,
-	0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x5f, 0x76, 0x65,
-	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69,
-	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x33, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73,
-	0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64,
-	0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
-	0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x1a, 0x30, 0x0a, 0x04,
-	0x46, 0x6c, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
-	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04,
-	0x08, 0x01, 0x10, 0x02, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
-	0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
-	0x72, 0x64, 0x32, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x67,
-	0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x33,
+	0x72, 0x74, 0x52, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12,
+	0x34, 0x0a, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69,
+	0x6e, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x3a, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
+	0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c,
+	0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50,
+	0x6f, 0x72, 0x74, 0x52, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x6f, 0x72,
+	0x74, 0x12, 0x41, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x09, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x69,
+	0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x69,
+	0x64, 0x12, 0x36, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x0b,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e,
+	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52,
+	0x08, 0x6c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x3a, 0x0a, 0x19, 0x64, 0x69, 0x73,
+	0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72,
+	0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x64, 0x69,
+	0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x72, 0x6f,
+	0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x76,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72,
+	0x6f, 0x78, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x18, 0x70, 0x72,
+	0x6f, 0x78, 0x79, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x76,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x70, 0x72,
+	0x6f, 0x78, 0x79, 0x49, 0x6e, 0x69, 0x74, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69, 0x6d, 0x61,
+	0x67, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
+	0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65,
+	0x52, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x13,
+	0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73,
+	0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x62, 0x75, 0x67,
+	0x49, 0x6d, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x18,
+	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x5f,
+	0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16,
+	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x65, 0x74, 0x4e, 0x65,
+	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x5f, 0x66, 0x6f,
+	0x72, 0x6d, 0x61, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x46,
+	0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
+	0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
+	0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
+	0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12,
+	0x36, 0x0a, 0x17, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+	0x63, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
+	0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x22, 0x47, 0x0a, 0x05, 0x49, 0x6d, 0x61, 0x67, 0x65,
+	0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+	0x1f, 0x0a, 0x0b, 0x70, 0x75, 0x6c, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x75, 0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79,
+	0x22, 0x1a, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x2a, 0x0a, 0x09,
+	0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x6f, 0x72,
+	0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70,
+	0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x9e, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x73,
+	0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+	0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x70, 0x75,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43,
+	0x70, 0x75, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x65,
+	0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x69, 0x6d,
+	0x69, 0x74, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x69,
+	0x6d, 0x69, 0x74, 0x43, 0x70, 0x75, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f,
+	0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x69,
+	0x6d, 0x69, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x22, 0x17, 0x0a, 0x11, 0x41, 0x75, 0x74,
+	0x6f, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x3a, 0x02,
+	0x18, 0x01, 0x22, 0x8d, 0x02, 0x0a, 0x0f, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43,
+	0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x5f,
+	0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72,
+	0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x72, 0x75,
+	0x73, 0x74, 0x5f, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x5f, 0x70, 0x65, 0x6d, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x41, 0x6e, 0x63, 0x68, 0x6f,
+	0x72, 0x73, 0x50, 0x65, 0x6d, 0x12, 0x46, 0x0a, 0x11, 0x69, 0x73, 0x73, 0x75, 0x61, 0x6e, 0x63,
+	0x65, 0x5f, 0x6c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x73, 0x73,
+	0x75, 0x61, 0x6e, 0x63, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a,
+	0x14, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x6b, 0x65, 0x77, 0x5f, 0x61, 0x6c, 0x6c, 0x6f,
+	0x77, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f,
+	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x12, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6b, 0x65,
+	0x77, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63,
+	0x68, 0x65, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65,
+	0x6d, 0x65, 0x22, 0x20, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x14,
+	0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c,
+	0x65, 0x76, 0x65, 0x6c, 0x22, 0x97, 0x01, 0x0a, 0x07, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+	0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+	0x6e, 0x12, 0x33, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x1d, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x66,
+	0x69, 0x67, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x52,
+	0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x1a, 0x30, 0x0a, 0x04, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x12,
+	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, 0x33,
+	0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x6e,
+	0x6b, 0x65, 0x72, 0x64, 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x32, 0x2f, 0x63, 0x6f,
+	0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e,
+	0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/controller/cmd/service-mirror/cluster_watcher.go b/controller/service-mirror/cluster_watcher.go
similarity index 100%
rename from controller/cmd/service-mirror/cluster_watcher.go
rename to controller/service-mirror/cluster_watcher.go
diff --git a/controller/cmd/service-mirror/cluster_watcher_mirroring_test.go b/controller/service-mirror/cluster_watcher_mirroring_test.go
similarity index 100%
rename from controller/cmd/service-mirror/cluster_watcher_mirroring_test.go
rename to controller/service-mirror/cluster_watcher_mirroring_test.go
diff --git a/controller/cmd/service-mirror/cluster_watcher_test_util.go b/controller/service-mirror/cluster_watcher_test_util.go
similarity index 100%
rename from controller/cmd/service-mirror/cluster_watcher_test_util.go
rename to controller/service-mirror/cluster_watcher_test_util.go
diff --git a/controller/cmd/service-mirror/events_formatting.go b/controller/service-mirror/events_formatting.go
similarity index 100%
rename from controller/cmd/service-mirror/events_formatting.go
rename to controller/service-mirror/events_formatting.go
diff --git a/controller/cmd/service-mirror/jittered_ticker.go b/controller/service-mirror/jittered_ticker.go
similarity index 100%
rename from controller/cmd/service-mirror/jittered_ticker.go
rename to controller/service-mirror/jittered_ticker.go
diff --git a/controller/cmd/service-mirror/metrics.go b/controller/service-mirror/metrics.go
similarity index 82%
rename from controller/cmd/service-mirror/metrics.go
rename to controller/service-mirror/metrics.go
index 6f6f087aa..ba14732a0 100644
--- a/controller/cmd/service-mirror/metrics.go
+++ b/controller/service-mirror/metrics.go
@@ -12,7 +12,9 @@ const (
 	probeSuccessfulLabel = "probe_successful"
 )
 
-type probeMetricVecs struct {
+// ProbeMetricVecs stores metrics about about gateways collected by probe
+// workers.
+type ProbeMetricVecs struct {
 	alive     *prometheus.GaugeVec
 	latencies *prometheus.HistogramVec
 	enqueues  *prometheus.CounterVec
@@ -20,7 +22,9 @@ type probeMetricVecs struct {
 	probes    *prometheus.CounterVec
 }
 
-type probeMetrics struct {
+// ProbeMetrics stores metrics about about a specific gateway collected by a
+// probe worker.
+type ProbeMetrics struct {
 	alive      prometheus.Gauge
 	latencies  prometheus.Observer
 	probes     *prometheus.CounterVec
@@ -39,7 +43,8 @@ func init() {
 	)
 }
 
-func newProbeMetricVecs() probeMetricVecs {
+// NewProbeMetricVecs creates a new ProbeMetricVecs.
+func NewProbeMetricVecs() ProbeMetricVecs {
 	labelNames := []string{gatewayClusterName}
 
 	probes := promauto.NewCounterVec(
@@ -88,7 +93,7 @@ func newProbeMetricVecs() probeMetricVecs {
 		},
 		labelNames)
 
-	return probeMetricVecs{
+	return ProbeMetricVecs{
 		alive:     alive,
 		latencies: latencies,
 		enqueues:  enqueues,
@@ -96,7 +101,10 @@ func newProbeMetricVecs() probeMetricVecs {
 		probes:    probes,
 	}
 }
-func (mv probeMetricVecs) newWorkerMetrics(remoteClusterName string) (*probeMetrics, error) {
+
+// NewWorkerMetrics creates a new ProbeMetrics by scoping to a specific target
+// cluster.
+func (mv ProbeMetricVecs) NewWorkerMetrics(remoteClusterName string) (*ProbeMetrics, error) {
 
 	labels := prometheus.Labels{
 		gatewayClusterName: remoteClusterName,
@@ -106,7 +114,7 @@ func (mv probeMetricVecs) newWorkerMetrics(remoteClusterName string) (*probeMetr
 	if err != nil {
 		return nil, err
 	}
-	return &probeMetrics{
+	return &ProbeMetrics{
 		alive:     mv.alive.With(labels),
 		latencies: mv.latencies.With(labels),
 		probes:    curriedProbes,
@@ -116,7 +124,7 @@ func (mv probeMetricVecs) newWorkerMetrics(remoteClusterName string) (*probeMetr
 	}, nil
 }
 
-func (mv probeMetricVecs) unregister(remoteClusterName string) {
+func (mv ProbeMetricVecs) unregister(remoteClusterName string) {
 	labels := prometheus.Labels{
 		gatewayClusterName: remoteClusterName,
 	}
diff --git a/controller/cmd/service-mirror/probe_worker.go b/controller/service-mirror/probe_worker.go
similarity index 97%
rename from controller/cmd/service-mirror/probe_worker.go
rename to controller/service-mirror/probe_worker.go
index ed349c434..e2d42f8a8 100644
--- a/controller/cmd/service-mirror/probe_worker.go
+++ b/controller/service-mirror/probe_worker.go
@@ -19,12 +19,12 @@ type ProbeWorker struct {
 	*sync.RWMutex
 	probeSpec *multicluster.ProbeSpec
 	stopCh    chan struct{}
-	metrics   *probeMetrics
+	metrics   *ProbeMetrics
 	log       *logging.Entry
 }
 
 // NewProbeWorker creates a new probe worker associated with a particular gateway
-func NewProbeWorker(localGatewayName string, spec *multicluster.ProbeSpec, metrics *probeMetrics, probekey string) *ProbeWorker {
+func NewProbeWorker(localGatewayName string, spec *multicluster.ProbeSpec, metrics *ProbeMetrics, probekey string) *ProbeWorker {
 	return &ProbeWorker{
 		localGatewayName: localGatewayName,
 		RWMutex:          &sync.RWMutex{},
diff --git a/pkg/charts/cni/values.go b/pkg/charts/cni/values.go
index 75c259ff4..1c8851198 100644
--- a/pkg/charts/cni/values.go
+++ b/pkg/charts/cni/values.go
@@ -49,7 +49,7 @@ func NewValues() (*Values, error) {
 	return v, nil
 }
 
-// readDefaults read all the default variables from the values.yaml file.
+// readDefaults reads all the default variables from the values.yaml file.
 // chartDir is the root directory of the Helm chart where values.yaml is.
 func readDefaults(chartDir string) (*Values, error) {
 	file := &chartutil.BufferedFile{
diff --git a/pkg/charts/linkerd2/values.go b/pkg/charts/linkerd2/values.go
index e910529dd..517e6b786 100644
--- a/pkg/charts/linkerd2/values.go
+++ b/pkg/charts/linkerd2/values.go
@@ -43,14 +43,12 @@ type (
 		Tap                         *Tap              `json:"tap"`
 		NodeSelector                map[string]string `json:"nodeSelector"`
 		Tolerations                 []interface{}     `json:"tolerations"`
-		SMIMetrics                  *SMIMetrics       `json:"smiMetrics"`
 
 		DestinationResources   *Resources `json:"destinationResources"`
 		HeartbeatResources     *Resources `json:"heartbeatResources"`
 		IdentityResources      *Resources `json:"identityResources"`
 		ProxyInjectorResources *Resources `json:"proxyInjectorResources"`
 		PublicAPIResources     *Resources `json:"publicAPIResources"`
-		SMIMetricsResources    *Resources `json:"smiMetricsResources"`
 		SPValidatorResources   *Resources `json:"spValidatorResources"`
 		TapResources           *Resources `json:"tapResources"`
 		WebResources           *Resources `json:"webResources"`
@@ -59,7 +57,6 @@ type (
 		IdentityProxyResources      *Resources `json:"identityProxyResources"`
 		ProxyInjectorProxyResources *Resources `json:"proxyInjectorProxyResources"`
 		PublicAPIProxyResources     *Resources `json:"publicAPIProxyResources"`
-		SMIMetricsProxyResources    *Resources `json:"smiMetricsProxyResources"`
 		SPValidatorProxyResources   *Resources `json:"spValidatorProxyResources"`
 		TapProxyResources           *Resources `json:"tapProxyResources"`
 		WebProxyResources           *Resources `json:"webProxyResources"`
@@ -223,13 +220,6 @@ type (
 		*TLS
 	}
 
-	// SMIMetrics has all the SMIMetrics's Helm variables
-	SMIMetrics struct {
-		*TLS
-		Enabled bool   `json:"enabled"`
-		Image   string `json:"image"`
-	}
-
 	// TLS has a pair of PEM-encoded key and certificate variables used in the
 	// Helm templates
 	TLS struct {
diff --git a/pkg/healthcheck/healthcheck.go b/pkg/healthcheck/healthcheck.go
index 02f2b3280..ae362f65c 100644
--- a/pkg/healthcheck/healthcheck.go
+++ b/pkg/healthcheck/healthcheck.go
@@ -23,6 +23,7 @@ import (
 	"github.com/linkerd/linkerd2/pkg/tls"
 	"github.com/linkerd/linkerd2/pkg/version"
 	log "github.com/sirupsen/logrus"
+	admissionRegistration "k8s.io/api/admissionregistration/v1beta1"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
@@ -1208,7 +1209,11 @@ func (hc *HealthChecker) allCategories() []category {
 					hintAnchor:  "l5d-injection-disabled",
 					warning:     true,
 					check: func(context.Context) error {
-						if hc.isHA() {
+						policy, err := hc.getMutatingWebhookFailurePolicy()
+						if err != nil {
+							return err
+						}
+						if policy != nil && *policy == admissionRegistration.Fail {
 							return hc.checkHAMetadataPresentOnKubeSystemNamespace()
 						}
 						return &SkipError{Reason: "not run for non HA installs"}
@@ -1667,6 +1672,17 @@ func (hc *HealthChecker) checkCustomResourceDefinitions(shouldExist bool) error
 	return checkResources("CustomResourceDefinitions", objects, []string{"serviceprofiles.linkerd.io"}, shouldExist)
 }
 
+func (hc *HealthChecker) getMutatingWebhookFailurePolicy() (*admissionRegistration.FailurePolicyType, error) {
+	mwc, err := hc.kubeAPI.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(k8s.ProxyInjectorWebhookConfigName, metav1.GetOptions{})
+	if err != nil {
+		return nil, err
+	}
+	if len(mwc.Webhooks) != 1 {
+		return nil, fmt.Errorf("expected 1 webhooks, found %d", len(mwc.Webhooks))
+	}
+	return mwc.Webhooks[0].FailurePolicy, nil
+}
+
 func (hc *HealthChecker) checkMutatingWebhookConfigurations(shouldExist bool) error {
 	options := metav1.ListOptions{
 		LabelSelector: hc.controlPlaneComponentsSelector(),
@@ -1885,7 +1901,7 @@ func (hc *HealthChecker) checkHAMetadataPresentOnKubeSystemNamespace() error {
 
 	val, ok := ns.Labels[k8s.AdmissionWebhookLabel]
 	if !ok || val != "disabled" {
-		return fmt.Errorf("kube-system namespace needs to have the label %s: disabled if HA mode is enabled", k8s.AdmissionWebhookLabel)
+		return fmt.Errorf("kube-system namespace needs to have the label %s: disabled if injector webhook failure policy is Fail", k8s.AdmissionWebhookLabel)
 	}
 
 	return nil
diff --git a/pkg/healthcheck/healthcheck_multicluster.go b/pkg/healthcheck/healthcheck_multicluster.go
index f5b9aa0a2..86290f3ce 100644
--- a/pkg/healthcheck/healthcheck_multicluster.go
+++ b/pkg/healthcheck/healthcheck_multicluster.go
@@ -23,7 +23,7 @@ const (
 	// multicluster setup.
 	LinkerdMulticlusterChecks CategoryID = "linkerd-multicluster"
 
-	linkerdServiceMirrorComponentName      = "linkerd-service-mirror"
+	linkerdServiceMirrorComponentName      = "service-mirror"
 	linkerdServiceMirrorServiceAccountName = "linkerd-service-mirror-%s"
 	linkerdServiceMirrorClusterRoleName    = "linkerd-service-mirror-access-local-resources-%s"
 	linkerdServiceMirrorRoleName           = "linkerd-service-mirror-read-remote-creds-%s"
diff --git a/pkg/k8s/labels.go b/pkg/k8s/labels.go
index 312a39e5e..cb825205a 100644
--- a/pkg/k8s/labels.go
+++ b/pkg/k8s/labels.go
@@ -323,12 +323,6 @@ const (
 	// TapAPIRegistrationServiceName is the name of the tap APIService registration resource
 	TapAPIRegistrationServiceName = "v1alpha1.tap.linkerd.io"
 
-	// SmiMetricsServiceName is the name of the SMI metrics APIService
-	SmiMetricsServiceName = "linkerd-smi-metrics"
-
-	// SmiMetricsAPIRegistrationServiceName is the name of the SMI metrics APIService registration resource
-	SmiMetricsAPIRegistrationServiceName = "v1alpha1.metrics.smi-spec.io"
-
 	// AdmissionWebhookLabel indicates whether admission webhooks are enabled for a namespace
 	AdmissionWebhookLabel = ProxyConfigAnnotationsPrefix + "/admission-webhooks"
 
diff --git a/pkg/smimetrics/client.go b/pkg/smimetrics/client.go
deleted file mode 100644
index 7ee5cd922..000000000
--- a/pkg/smimetrics/client.go
+++ /dev/null
@@ -1,153 +0,0 @@
-package smimetrics
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-
-	"github.com/linkerd/linkerd2/pkg/k8s"
-	"github.com/servicemeshinterface/smi-sdk-go/pkg/apis/metrics/v1alpha1"
-	log "github.com/sirupsen/logrus"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-)
-
-const apiBase = "/apis/metrics.smi-spec.io/v1alpha1"
-
-// GetTrafficMetrics returns the inbound traffic metrics for a specific named
-// resource.
-func GetTrafficMetrics(k8sAPI *k8s.KubernetesAPI, namespace, kind, name string, params map[string]string) (*v1alpha1.TrafficMetrics, error) {
-	ns := ""
-	if namespace != "" {
-		ns = "/namespaces/" + namespace
-	}
-	path := fmt.Sprintf("%s%s/%s/%s", apiBase, ns, kind, name)
-
-	bytes, err := getMetricsResponse(k8sAPI, path, params)
-	if err != nil {
-		return nil, err
-	}
-
-	return parseTrafficMetrics(bytes)
-}
-
-// GetTrafficMetricsList returns the inbound traffic metrics for all resources
-// of a given kind.
-func GetTrafficMetricsList(k8sAPI *k8s.KubernetesAPI, namespace, kind string, params map[string]string) (*v1alpha1.TrafficMetricsList, error) {
-	ns := ""
-	if namespace != "" {
-		ns = "/namespaces/" + namespace
-	}
-	path := fmt.Sprintf("%s%s/%s", apiBase, ns, kind)
-
-	bytes, err := getMetricsResponse(k8sAPI, path, params)
-	if err != nil {
-		return nil, err
-	}
-
-	return parseTrafficMetricsList(bytes)
-}
-
-// GetTrafficMetricsEdgesList returns the edge traffic metrics for a specific
-// named resource.
-func GetTrafficMetricsEdgesList(k8sAPI *k8s.KubernetesAPI, namespace, kind, name string, params map[string]string) (*v1alpha1.TrafficMetricsList, error) {
-	ns := ""
-	if namespace != "" {
-		ns = "/namespaces/" + namespace
-	}
-	path := fmt.Sprintf("%s%s/%s/%s/edges", apiBase, ns, kind, name)
-
-	bytes, err := getMetricsResponse(k8sAPI, path, params)
-	if err != nil {
-		return nil, err
-	}
-
-	return parseTrafficMetricsList(bytes)
-}
-
-func getMetricsResponse(k8sAPI *k8s.KubernetesAPI, path string, params map[string]string) ([]byte, error) {
-	client, err := k8sAPI.NewClient()
-	if err != nil {
-		return nil, err
-	}
-
-	url, err := url.Parse(k8sAPI.Host)
-	if err != nil {
-		return nil, err
-	}
-
-	url.Path = path
-
-	for k, v := range params {
-		url.Query().Add(k, v)
-	}
-
-	log.Debugf("Requesting %s", url)
-
-	httpReq, err := http.NewRequest(
-		http.MethodGet,
-		url.String(),
-		nil,
-	)
-	if err != nil {
-		return nil, err
-	}
-
-	httpRsp, err := client.Do(httpReq)
-	if err != nil {
-		log.Debugf("Error invoking [%s]: %v", url, err)
-		return nil, err
-	}
-	defer httpRsp.Body.Close()
-
-	log.Debugf("Response from [%s] had headers: %v", url, httpRsp.Header)
-
-	return ioutil.ReadAll(httpRsp.Body)
-}
-
-func handleStatusResponse(bytes []byte) error {
-	var status metav1.Status
-	json.Unmarshal(bytes, &status)
-	if status.Kind == "Status" {
-		return errors.New(status.Message)
-	}
-	return nil
-}
-
-func parseTrafficMetrics(bytes []byte) (*v1alpha1.TrafficMetrics, error) {
-	err := handleStatusResponse(bytes)
-	if err != nil {
-		return nil, err
-	}
-
-	var metrics v1alpha1.TrafficMetrics
-	err = json.Unmarshal(bytes, &metrics)
-	if err != nil {
-		log.Errorf("Failed to decode response as TrafficMetrics [%s]: %v", string(bytes), err)
-		return nil, errors.New(string(bytes))
-	}
-
-	log.Debugf("Parsed TrafficMetrics: %+v", metrics)
-
-	return &metrics, nil
-}
-
-func parseTrafficMetricsList(bytes []byte) (*v1alpha1.TrafficMetricsList, error) {
-	err := handleStatusResponse(bytes)
-	if err != nil {
-		return nil, err
-	}
-
-	var metrics v1alpha1.TrafficMetricsList
-	err = json.Unmarshal(bytes, &metrics)
-	if err != nil {
-		log.Errorf("Failed to decode response as TrafficMetricsList [%s]: %v", string(bytes), err)
-		return nil, errors.New(string(bytes))
-	}
-
-	log.Debugf("Parsed TrafficMetricsList: %+v", metrics)
-
-	return &metrics, nil
-}
diff --git a/proto/config/config.proto b/proto/config/config.proto
index 63777abcb..db64e3c6e 100644
--- a/proto/config/config.proto
+++ b/proto/config/config.proto
@@ -28,7 +28,6 @@ message Global {
 
   // Override default `cluster.local`
   string cluster_domain = 8;
-  bool endpoint_slice_enabled = 9;
 }
 
 message Proxy {
diff --git a/web/app/js/components/Tap.jsx b/web/app/js/components/Tap.jsx
index 15ccee807..b9cbbc30b 100644
--- a/web/app/js/components/Tap.jsx
+++ b/web/app/js/components/Tap.jsx
@@ -262,11 +262,12 @@ class Tap extends React.Component {
     });
 
     const url = this.api.urlsForResourceNoStats('all');
-    this.api.setCurrentRequests([this.api.fetchMetrics(url)]);
+    const authorityUrl = this.api.urlsForResource('authority');
+    this.api.setCurrentRequests([this.api.fetchMetrics(url), this.api.fetchMetrics(authorityUrl)]);
     this.serverPromise = Promise.all(this.api.getCurrentPromises())
-      .then(([rsp]) => {
-        const { resourcesByNs, authoritiesByNs } = groupResourcesByNs(rsp);
-
+      .then(rsp => {
+        const { resourcesByNs } = groupResourcesByNs(rsp[0]);
+        const { authoritiesByNs } = groupResourcesByNs(rsp[1]);
         this.setState({
           resourcesByNs,
           authoritiesByNs,


Test patch:
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index f8049d22d..d16de49db 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -18,10 +18,7 @@ jobs:
       # actions/checkout@v2
       uses: actions/checkout@722adc6
     - name: Go unit tests
-      env:
-        GITCOOKIE_SH: ${{ secrets.GITCOOKIE_SH }}
       run: |
-        echo "$GITCOOKIE_SH" | bash
         go get gotest.tools/gotestsum@v0.4.2
         # TODO: validate bin/protoc-go.sh does not dirty the repo
         gotestsum -- -cover -race -v -mod=readonly ./...
@@ -40,5 +37,5 @@ jobs:
       run: |
         export PATH="$HOME/.yarn/bin:$PATH"
         export NODE_ENV=test
-        bin/web
+        bin/web --frozen-lockfile
         bin/web test --reporters="jest-dot-reporter" --reporters="./gh_ann_reporter.js"
diff --git a/bin/_test-helpers.sh b/bin/_test-helpers.sh
index a688f90ea..2e66fcf66 100644
--- a/bin/_test-helpers.sh
+++ b/bin/_test-helpers.sh
@@ -284,6 +284,11 @@ run_upgrade-edge_test() {
 # Run the upgrade-stable test by upgrading the most-recent stable release to the
 # HEAD of this branch.
 run_upgrade-stable_test() {
+  if [ -n "$RUN_ARM_TEST" ]; then
+    echo "Skipped. Linkerd stable version does not support ARM yet"
+    exit 0
+  fi
+
   stable_install_url="https://run.linkerd.io/install"
   upgrade_test "stable" "$stable_install_url"
 }
@@ -313,6 +318,11 @@ helm_cleanup() {
 }
 
 run_helm-upgrade_test() {
+  if [ -n "$RUN_ARM_TEST" ]; then
+    echo "Skipped. Linkerd stable version does not support ARM yet"
+    exit 0
+  fi
+
   local stable_version
   stable_version=$(latest_release_channel "stable")
 
diff --git a/cli/cmd/inject_test.go b/cli/cmd/inject_test.go
index 3eaca72a3..b3242b7f8 100644
--- a/cli/cmd/inject_test.go
+++ b/cli/cmd/inject_test.go
@@ -575,7 +575,12 @@ func TestWalk(t *testing.T) {
 	if err := os.MkdirAll(tmpFolderData, os.ModeDir|os.ModePerm); err != nil {
 		t.Fatal("Unexpected error: ", err)
 	}
-	defer os.RemoveAll(tmpFolderRoot)
+	defer func() {
+		err := os.RemoveAll(tmpFolderRoot)
+		if err != nil {
+			t.Errorf("failed to remove temp dir %q: %v", tmpFolderRoot, err)
+		}
+	}()
 
 	var (
 		data  = []byte(readTestdata(t, "inject_gettest_deployment.bad.input.yml"))
diff --git a/cli/cmd/install_helm_test.go b/cli/cmd/install_helm_test.go
index dc248acfc..2ef697d93 100644
--- a/cli/cmd/install_helm_test.go
+++ b/cli/cmd/install_helm_test.go
@@ -99,11 +99,6 @@ func testRenderHelm(t *testing.T, chart *pb.Chart, goldenFileName string) {
     "keyPEM":"test-tap-key-pem",
     "crtPEM":"test-tap-crt-pem",
 	"caBundle":"test-tap-ca-bundle"
-  },
-  "smiMetrics":{
-	  "keyPEM":"test-smi-metrics-key-pem",
-	  "crtPEM":"test-smi-metrics-crt-pem",
-	  "caBundle":"test-smi-metrics-ca-bundle"
   }
 }`
 
diff --git a/cli/cmd/install_test.go b/cli/cmd/install_test.go
index 891d4783e..0ea0f4225 100644
--- a/cli/cmd/install_test.go
+++ b/cli/cmd/install_test.go
@@ -136,7 +136,6 @@ func TestRender(t *testing.T) {
 		ProxyInjector:      defaultValues.ProxyInjector,
 		ProfileValidator:   defaultValues.ProfileValidator,
 		Tap:                defaultValues.Tap,
-		SMIMetrics:         defaultValues.SMIMetrics,
 		Dashboard: &charts.Dashboard{
 			Replicas: 1,
 		},
@@ -526,7 +525,4 @@ func addFakeTLSSecrets(values *charts.Values) {
 	values.Tap.CrtPEM = "tap crt"
 	values.Tap.KeyPEM = "tap key"
 	values.Tap.CaBundle = "tap CA bundle"
-	values.SMIMetrics.CrtPEM = "smi metrics crt"
-	values.SMIMetrics.KeyPEM = "smi metrics key"
-	values.SMIMetrics.CaBundle = "smi metrics CA bundle"
 }
diff --git a/cli/cmd/testdata/inject_emojivoto_already_injected.golden.yml b/cli/cmd/testdata/inject_emojivoto_already_injected.golden.yml
index 4c815f4f3..bb3e58462 100644
--- a/cli/cmd/testdata/inject_emojivoto_already_injected.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_already_injected.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -204,7 +204,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -378,7 +378,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -552,7 +552,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_already_injected.input.yml b/cli/cmd/testdata/inject_emojivoto_already_injected.input.yml
index b9e15e36f..0dc98c12e 100644
--- a/cli/cmd/testdata/inject_emojivoto_already_injected.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_already_injected.input.yml
@@ -27,7 +27,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -65,7 +65,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -102,7 +102,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -141,7 +141,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment.golden.yml
index 59cd0bf6d..affcfde19 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment.input.yml
index 786b093ef..cf20c6963 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment.input.yml
@@ -23,7 +23,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.golden.yml
index a06dd700d..7e627e1c6 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.input.yml
index 4557615a9..e9f12bcd8 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_capabilities.input.yml
@@ -26,7 +26,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.golden.yml
index c752776a9..776e2f8c7 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.golden.yml
@@ -39,7 +39,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.input.yml
index f1da22b6d..f3dcc150a 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_config_overrides.input.yml
@@ -33,7 +33,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.golden.yml
index 0d7b85f26..b203a9e61 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -204,7 +204,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.input.yml
index 775df48bd..03ecfd7b0 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_controller_name.input.yml
@@ -23,7 +23,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
@@ -54,7 +54,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_debug.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_debug.golden.yml
index 3ccded89c..d75b6ba21 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_debug.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_debug.golden.yml
@@ -31,7 +31,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_empty_proxy_version_config.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_empty_proxy_version_config.golden.yml
index 9922a353d..a9b1d472d 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_empty_proxy_version_config.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_empty_proxy_version_config.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.golden.yml
index a7415c56c..e74cb73a6 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.input.yml
index 7da36a4f1..28d20393b 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_empty_resources.input.yml
@@ -27,7 +27,7 @@ spec:
               value: voting-svc.emojivoto:8080
             - name: INDEX_BUNDLE
               value: dist/index_bundle.js
-          image: buoyantio/emojivoto-web:v3
+          image: buoyantio/emojivoto-web:v10
           name: web-svc
           ports:
             - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_empty_version_config.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_empty_version_config.golden.yml
index 5bb391376..833364b62 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_empty_version_config.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_empty_version_config.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.golden.yml
index e9680468e..b643ae3ed 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 9100
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.input.yml
index eea28aaaf..ba2399ef1 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_false.input.yml
@@ -26,7 +26,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 9100
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_true.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_true.input.yml
index c70fb9c1d..7aa61739a 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_true.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_hostNetwork_true.input.yml
@@ -23,7 +23,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 9100
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_injectDisabled.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_injectDisabled.input.yml
index e7786b133..3ae825304 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_injectDisabled.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_injectDisabled.input.yml
@@ -25,7 +25,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 9100
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_no_init_container.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_no_init_container.golden.yml
index a57eef80b..ee6a11778 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_no_init_container.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_no_init_container.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_overridden.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_overridden.golden.yml
index 0dd41b51b..d5a38cbd9 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_overridden.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_overridden.golden.yml
@@ -31,7 +31,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_overridden_noinject.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_overridden_noinject.golden.yml
index 517843615..1d46e31c4 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_overridden_noinject.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_overridden_noinject.golden.yml
@@ -26,7 +26,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_proxyignores.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_proxyignores.golden.yml
index f655c0333..ef69f0176 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_proxyignores.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_proxyignores.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_trace.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_trace.golden.yml
index 270fb6a1d..13c4eb611 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_trace.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_trace.golden.yml
@@ -32,7 +32,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_udp.golden.yml b/cli/cmd/testdata/inject_emojivoto_deployment_udp.golden.yml
index 47242003a..cdd9fd198 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_udp.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_udp.golden.yml
@@ -30,7 +30,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 9100
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_udp.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_udp.input.yml
index 7caae4c13..85aa443f2 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_udp.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_udp.input.yml
@@ -23,7 +23,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 9100
diff --git a/cli/cmd/testdata/inject_emojivoto_deployment_uninjected.input.yml b/cli/cmd/testdata/inject_emojivoto_deployment_uninjected.input.yml
index 0a23466fa..f603ccdc5 100644
--- a/cli/cmd/testdata/inject_emojivoto_deployment_uninjected.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_deployment_uninjected.input.yml
@@ -25,7 +25,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_istio.input.yml b/cli/cmd/testdata/inject_emojivoto_istio.input.yml
index 4f1ca8622..dcbd65a88 100644
--- a/cli/cmd/testdata/inject_emojivoto_istio.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_istio.input.yml
@@ -23,7 +23,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_list.golden.yml b/cli/cmd/testdata/inject_emojivoto_list.golden.yml
index 1ef8fa2df..52166b323 100644
--- a/cli/cmd/testdata/inject_emojivoto_list.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_list.golden.yml
@@ -32,7 +32,7 @@ items:
             value: voting-svc.emojivoto:8080
           - name: INDEX_BUNDLE
             value: dist/index_bundle.js
-          image: buoyantio/emojivoto-web:v3
+          image: buoyantio/emojivoto-web:v10
           name: web-svc
           ports:
           - containerPort: 80
@@ -199,7 +199,7 @@ items:
         - env:
           - name: GRPC_PORT
             value: "8080"
-          image: buoyantio/emojivoto-emoji-svc:v3
+          image: buoyantio/emojivoto-emoji-svc:v10
           name: emoji-svc
           ports:
           - containerPort: 8080
diff --git a/cli/cmd/testdata/inject_emojivoto_list.input.yml b/cli/cmd/testdata/inject_emojivoto_list.input.yml
index 11f4a2365..dceed514a 100644
--- a/cli/cmd/testdata/inject_emojivoto_list.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_list.input.yml
@@ -25,7 +25,7 @@ items:
             value: voting-svc.emojivoto:8080
           - name: INDEX_BUNDLE
             value: dist/index_bundle.js
-          image: buoyantio/emojivoto-web:v3
+          image: buoyantio/emojivoto-web:v10
           name: web-svc
           ports:
           - containerPort: 80
@@ -49,7 +49,7 @@ items:
         - env:
           - name: GRPC_PORT
             value: "8080"
-          image: buoyantio/emojivoto-emoji-svc:v3
+          image: buoyantio/emojivoto-emoji-svc:v10
           name: emoji-svc
           ports:
           - containerPort: 8080
diff --git a/cli/cmd/testdata/inject_emojivoto_list_empty_resources.golden.yml b/cli/cmd/testdata/inject_emojivoto_list_empty_resources.golden.yml
index f7e8960ff..e25b726f4 100644
--- a/cli/cmd/testdata/inject_emojivoto_list_empty_resources.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_list_empty_resources.golden.yml
@@ -32,7 +32,7 @@ items:
             value: voting-svc.emojivoto:8080
           - name: INDEX_BUNDLE
             value: dist/index_bundle.js
-          image: buoyantio/emojivoto-web:v3
+          image: buoyantio/emojivoto-web:v10
           name: web-svc
           ports:
           - containerPort: 80
@@ -199,7 +199,7 @@ items:
         - env:
           - name: GRPC_PORT
             value: "8080"
-          image: buoyantio/emojivoto-emoji-svc:v3
+          image: buoyantio/emojivoto-emoji-svc:v10
           name: emoji-svc
           ports:
           - containerPort: 8080
diff --git a/cli/cmd/testdata/inject_emojivoto_list_empty_resources.input.yml b/cli/cmd/testdata/inject_emojivoto_list_empty_resources.input.yml
index 238828f42..1ccb5e2fc 100644
--- a/cli/cmd/testdata/inject_emojivoto_list_empty_resources.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_list_empty_resources.input.yml
@@ -29,7 +29,7 @@ items:
                   value: voting-svc.emojivoto:8080
                 - name: INDEX_BUNDLE
                   value: dist/index_bundle.js
-              image: buoyantio/emojivoto-web:v3
+              image: buoyantio/emojivoto-web:v10
               name: web-svc
               ports:
                 - containerPort: 80
@@ -58,7 +58,7 @@ items:
             - env:
                 - name: GRPC_PORT
                   value: "8080"
-              image: buoyantio/emojivoto-emoji-svc:v3
+              image: buoyantio/emojivoto-emoji-svc:v10
               name: emoji-svc
               ports:
                 - containerPort: 8080
diff --git a/cli/cmd/testdata/inject_emojivoto_pod.golden.yml b/cli/cmd/testdata/inject_emojivoto_pod.golden.yml
index 7f8a933c2..0487a0822 100644
--- a/cli/cmd/testdata/inject_emojivoto_pod.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_pod.golden.yml
@@ -18,7 +18,7 @@ spec:
     env:
     - name: WEB_HOST
       value: web-svc.emojivoto:80
-    image: buoyantio/emojivoto-web:v3
+    image: buoyantio/emojivoto-web:v10
     name: vote-bot
   - env:
     - name: LINKERD2_PROXY_LOG
diff --git a/cli/cmd/testdata/inject_emojivoto_pod.input.yml b/cli/cmd/testdata/inject_emojivoto_pod.input.yml
index 4f6cd73b3..a75101701 100644
--- a/cli/cmd/testdata/inject_emojivoto_pod.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_pod.input.yml
@@ -12,6 +12,6 @@ spec:
     env:
     - name: WEB_HOST
       value: web-svc.emojivoto:80
-    image: buoyantio/emojivoto-web:v3
+    image: buoyantio/emojivoto-web:v10
     name: vote-bot
 ---
diff --git a/cli/cmd/testdata/inject_emojivoto_pod_proxyignores.golden.yml b/cli/cmd/testdata/inject_emojivoto_pod_proxyignores.golden.yml
index f511dc61d..89c9752cb 100644
--- a/cli/cmd/testdata/inject_emojivoto_pod_proxyignores.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_pod_proxyignores.golden.yml
@@ -18,7 +18,7 @@ spec:
     env:
     - name: WEB_HOST
       value: web-svc.emojivoto:80
-    image: buoyantio/emojivoto-web:v3
+    image: buoyantio/emojivoto-web:v10
     name: vote-bot
   - env:
     - name: LINKERD2_PROXY_LOG
diff --git a/cli/cmd/testdata/inject_emojivoto_pod_with_requests.golden.yml b/cli/cmd/testdata/inject_emojivoto_pod_with_requests.golden.yml
index 624e9014c..bb04261b6 100644
--- a/cli/cmd/testdata/inject_emojivoto_pod_with_requests.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_pod_with_requests.golden.yml
@@ -18,7 +18,7 @@ spec:
     env:
     - name: WEB_HOST
       value: web-svc.emojivoto:80
-    image: buoyantio/emojivoto-web:v3
+    image: buoyantio/emojivoto-web:v10
     name: vote-bot
   - env:
     - name: LINKERD2_PROXY_LOG
diff --git a/cli/cmd/testdata/inject_emojivoto_pod_with_requests.input.yml b/cli/cmd/testdata/inject_emojivoto_pod_with_requests.input.yml
index 4f6cd73b3..a75101701 100644
--- a/cli/cmd/testdata/inject_emojivoto_pod_with_requests.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_pod_with_requests.input.yml
@@ -12,6 +12,6 @@ spec:
     env:
     - name: WEB_HOST
       value: web-svc.emojivoto:80
-    image: buoyantio/emojivoto-web:v3
+    image: buoyantio/emojivoto-web:v10
     name: vote-bot
 ---
diff --git a/cli/cmd/testdata/inject_emojivoto_statefulset.golden.yml b/cli/cmd/testdata/inject_emojivoto_statefulset.golden.yml
index d39c3c079..ca171bf7c 100644
--- a/cli/cmd/testdata/inject_emojivoto_statefulset.golden.yml
+++ b/cli/cmd/testdata/inject_emojivoto_statefulset.golden.yml
@@ -31,7 +31,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_emojivoto_statefulset.input.yml b/cli/cmd/testdata/inject_emojivoto_statefulset.input.yml
index e8af3d34c..d2598fb1d 100644
--- a/cli/cmd/testdata/inject_emojivoto_statefulset.input.yml
+++ b/cli/cmd/testdata/inject_emojivoto_statefulset.input.yml
@@ -24,7 +24,7 @@ spec:
           value: voting-svc.emojivoto:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v3
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 80
diff --git a/cli/cmd/testdata/inject_gettest_deployment.bad.input.yml b/cli/cmd/testdata/inject_gettest_deployment.bad.input.yml
index 310dbbd14..6d70c9f69 100644
--- a/cli/cmd/testdata/inject_gettest_deployment.bad.input.yml
+++ b/cli/cmd/testdata/inject_gettest_deployment.bad.input.yml
@@ -9,12 +9,12 @@ spec:
     spec:
       containers:
       - name: http-to-grpc-two-replicas-c1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "c1"]
         ports:
         - containerPort: 9090
       - name: http-to-grpc-two-replicas-c2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "8080", "--response-text", "c2"]
         ports:
         - containerPort: 9090
@@ -36,12 +36,12 @@ spec:
     spec:
       containers:
       - name: http-to-grpc-one-replica-c1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "c1"]
         ports:
         - containerPort: 9090
       - name: http-to-grpc-one-replica-c2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "8080", "--response-text", "c2"]
         ports:
         - containerPort: 9090
diff --git a/cli/cmd/testdata/inject_gettest_deployment.good.golden.yml b/cli/cmd/testdata/inject_gettest_deployment.good.golden.yml
index 05998d515..b7d97ee81 100644
--- a/cli/cmd/testdata/inject_gettest_deployment.good.golden.yml
+++ b/cli/cmd/testdata/inject_gettest_deployment.good.golden.yml
@@ -23,7 +23,7 @@ spec:
         - "9090"
         - --response-text
         - c1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         name: http-to-grpc-two-replicas-c1
         ports:
         - containerPort: 9090
@@ -33,7 +33,7 @@ spec:
         - "8080"
         - --response-text
         - c2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         name: http-to-grpc-two-replicas-c2
         ports:
         - containerPort: 9090
@@ -199,7 +199,7 @@ spec:
         - "9090"
         - --response-text
         - c1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         name: http-to-grpc-one-replica-c1
         ports:
         - containerPort: 9090
@@ -209,7 +209,7 @@ spec:
         - "8080"
         - --response-text
         - c2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         name: http-to-grpc-one-replica-c2
         ports:
         - containerPort: 9090
diff --git a/cli/cmd/testdata/inject_gettest_deployment.good.input.yml b/cli/cmd/testdata/inject_gettest_deployment.good.input.yml
index 2070a962b..a7537f252 100644
--- a/cli/cmd/testdata/inject_gettest_deployment.good.input.yml
+++ b/cli/cmd/testdata/inject_gettest_deployment.good.input.yml
@@ -11,12 +11,12 @@ spec:
     spec:
       containers:
       - name: http-to-grpc-two-replicas-c1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "c1"]
         ports:
         - containerPort: 9090
       - name: http-to-grpc-two-replicas-c2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "8080", "--response-text", "c2"]
         ports:
         - containerPort: 9090
@@ -33,12 +33,12 @@ spec:
     spec:
       containers:
       - name: http-to-grpc-one-replica-c1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "c1"]
         ports:
         - containerPort: 9090
       - name: http-to-grpc-one-replica-c2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "8080", "--response-text", "c2"]
         ports:
         - containerPort: 9090
diff --git a/cli/cmd/testdata/install_addon_config.golden b/cli/cmd/testdata/install_addon_config.golden
index b3ab9c306..e236fd7e4 100644
--- a/cli/cmd/testdata/install_addon_config.golden
+++ b/cli/cmd/testdata/install_addon_config.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 ###
 ### Grafana RBAC
diff --git a/cli/cmd/testdata/install_addon_control-plane.golden b/cli/cmd/testdata/install_addon_control-plane.golden
index a0361be1f..fa049ff85 100644
--- a/cli/cmd/testdata/install_addon_control-plane.golden
+++ b/cli/cmd/testdata/install_addon_control-plane.golden
@@ -11,7 +11,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -568,6 +568,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -1734,7 +1735,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_config.golden b/cli/cmd/testdata/install_config.golden
index 47661e50d..7729b1938 100644
--- a/cli/cmd/testdata/install_config.golden
+++ b/cli/cmd/testdata/install_config.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 ###
 ### Grafana RBAC
diff --git a/cli/cmd/testdata/install_control-plane.golden b/cli/cmd/testdata/install_control-plane.golden
index 594bf1dcb..def50e78c 100644
--- a/cli/cmd/testdata/install_control-plane.golden
+++ b/cli/cmd/testdata/install_control-plane.golden
@@ -11,7 +11,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -568,6 +568,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -1733,7 +1734,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_controlplane_tracing_output.golden b/cli/cmd/testdata/install_controlplane_tracing_output.golden
index ac510bd24..ca81576c5 100644
--- a/cli/cmd/testdata/install_controlplane_tracing_output.golden
+++ b/cli/cmd/testdata/install_controlplane_tracing_output.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1387,6 +1386,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         - -trace-collector=linkerd-collector.linkerd.svc.cluster.local:55678
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
@@ -2625,7 +2625,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_custom_registry.golden b/cli/cmd/testdata/install_custom_registry.golden
index c6f9d9d21..78f16eede 100644
--- a/cli/cmd/testdata/install_custom_registry.golden
+++ b/cli/cmd/testdata/install_custom_registry.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"my.custom.registry/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"my.custom.registry/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"my.custom.registry/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: my.custom.registry/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2522,7 +2522,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_default.golden b/cli/cmd/testdata/install_default.golden
index 707a4327c..ff38cd386 100644
--- a/cli/cmd/testdata/install_default.golden
+++ b/cli/cmd/testdata/install_default.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2522,7 +2522,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_default_override_dst_get_nets.golden b/cli/cmd/testdata/install_default_override_dst_get_nets.golden
index a9d300087..3e5b10c48 100644
--- a/cli/cmd/testdata/install_default_override_dst_get_nets.golden
+++ b/cli/cmd/testdata/install_default_override_dst_get_nets.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.0.0.0/8","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2522,7 +2522,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_grafana_existing.golden b/cli/cmd/testdata/install_grafana_existing.golden
index 2e1b49a88..43af02c1e 100644
--- a/cli/cmd/testdata/install_grafana_existing.golden
+++ b/cli/cmd/testdata/install_grafana_existing.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -783,7 +783,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -797,7 +796,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1354,6 +1353,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2519,7 +2519,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_ha_output.golden b/cli/cmd/testdata/install_ha_output.golden
index 7bb9e5583..d419d6f4c 100644
--- a/cli/cmd/testdata/install_ha_output.golden
+++ b/cli/cmd/testdata/install_ha_output.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"100m","requestMemory":"20Mi","limitCpu":"1","limitMemory":"250Mi"},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1452,6 +1451,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2758,7 +2758,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_ha_with_overrides_output.golden b/cli/cmd/testdata/install_ha_with_overrides_output.golden
index 4c2346194..6e819e3cc 100644
--- a/cli/cmd/testdata/install_ha_with_overrides_output.golden
+++ b/cli/cmd/testdata/install_ha_with_overrides_output.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"400m","requestMemory":"300Mi","limitCpu":"1","limitMemory":"250Mi"},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1452,6 +1451,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2758,7 +2758,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_heartbeat_disabled_output.golden b/cli/cmd/testdata/install_heartbeat_disabled_output.golden
index 8bd72dd20..9c93672da 100644
--- a/cli/cmd/testdata/install_heartbeat_disabled_output.golden
+++ b/cli/cmd/testdata/install_heartbeat_disabled_output.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -742,7 +742,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -756,7 +755,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1313,6 +1312,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2433,7 +2433,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_helm_output.golden b/cli/cmd/testdata/install_helm_output.golden
index eab5f7c95..443d65f1e 100644
--- a/cli/cmd/testdata/install_helm_output.golden
+++ b/cli/cmd/testdata/install_helm_output.golden
@@ -141,7 +141,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -810,9 +810,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
----
-# Source: linkerd2/templates/smi-metrics-rbac.yaml
-
 ---
 # Source: linkerd2/templates/config.yaml
 ---
@@ -841,8 +838,7 @@ data:
       },
       "autoInjectContext": null,
       "omitWebhookSideEffects": false,
-      "clusterDomain": "cluster.local",
-      "enableEndpointSlices": "false"
+      "clusterDomain": "cluster.local"
     }
   proxy: |
     {
@@ -1436,6 +1432,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:linkerd-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2569,9 +2566,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
----
-# Source: linkerd2/templates/smi-metrics.yaml
-
 ---
 # Source: linkerd2/templates/linkerd-config-addons.yaml
 ---
diff --git a/cli/cmd/testdata/install_helm_output_addons.golden b/cli/cmd/testdata/install_helm_output_addons.golden
index 1e1e67f58..0edf89b78 100644
--- a/cli/cmd/testdata/install_helm_output_addons.golden
+++ b/cli/cmd/testdata/install_helm_output_addons.golden
@@ -141,7 +141,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -810,9 +810,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
----
-# Source: linkerd2/templates/smi-metrics-rbac.yaml
-
 ---
 # Source: linkerd2/templates/config.yaml
 ---
@@ -841,8 +838,7 @@ data:
       },
       "autoInjectContext": null,
       "omitWebhookSideEffects": false,
-      "clusterDomain": "cluster.local",
-      "enableEndpointSlices": "false"
+      "clusterDomain": "cluster.local"
     }
   proxy: |
     {
@@ -1436,6 +1432,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:linkerd-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2570,9 +2567,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
----
-# Source: linkerd2/templates/smi-metrics.yaml
-
 ---
 # Source: linkerd2/templates/linkerd-config-addons.yaml
 ---
diff --git a/cli/cmd/testdata/install_helm_output_ha.golden b/cli/cmd/testdata/install_helm_output_ha.golden
index d3dadd5a3..e5d1d40db 100644
--- a/cli/cmd/testdata/install_helm_output_ha.golden
+++ b/cli/cmd/testdata/install_helm_output_ha.golden
@@ -141,7 +141,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -810,9 +810,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
----
-# Source: linkerd2/templates/smi-metrics-rbac.yaml
-
 ---
 # Source: linkerd2/templates/config.yaml
 ---
@@ -841,8 +838,7 @@ data:
       },
       "autoInjectContext": null,
       "omitWebhookSideEffects": false,
-      "clusterDomain": "cluster.local",
-      "enableEndpointSlices": "false"
+      "clusterDomain": "cluster.local"
     }
   proxy: |
     {
@@ -1531,6 +1527,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:linkerd-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2805,9 +2802,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
----
-# Source: linkerd2/templates/smi-metrics.yaml
-
 ---
 # Source: linkerd2/templates/linkerd-config-addons.yaml
 ---
diff --git a/cli/cmd/testdata/install_no_init_container.golden b/cli/cmd/testdata/install_no_init_container.golden
index 8ed1fc04e..2169bc1ff 100644
--- a/cli/cmd/testdata/install_no_init_container.golden
+++ b/cli/cmd/testdata/install_no_init_container.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -783,7 +783,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -797,7 +796,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":true,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":true,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1278,6 +1277,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2253,7 +2253,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_output.golden b/cli/cmd/testdata/install_output.golden
index 970839f68..310590ba5 100644
--- a/cli/cmd/testdata/install_output.golden
+++ b/cli/cmd/testdata/install_output.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: Namespace
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -1347,6 +1346,7 @@ spec:
         - -controller-namespace=Namespace
         - -enable-h2-upgrade=true
         - -log-level=ControllerLogLevel
+        - -enable-endpoint-slices=false
         image: ControllerImage:ControllerImageVersion
         imagePullPolicy: ImagePullPolicy
         livenessProbe:
@@ -2487,7 +2487,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_prometheus_overwrite.golden b/cli/cmd/testdata/install_prometheus_overwrite.golden
index 169e0cea4..4f43c859f 100644
--- a/cli/cmd/testdata/install_prometheus_overwrite.golden
+++ b/cli/cmd/testdata/install_prometheus_overwrite.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2522,7 +2522,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_proxy_ignores.golden b/cli/cmd/testdata/install_proxy_ignores.golden
index 0be71ad9b..743bb2669 100644
--- a/cli/cmd/testdata/install_proxy_ignores.golden
+++ b/cli/cmd/testdata/install_proxy_ignores.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[{"portRange":"22"},{"portRange":"8100-8102"}],"ignoreOutboundPorts":[{"portRange":"5432"}],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2522,7 +2522,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_restricted_dashboard.golden b/cli/cmd/testdata/install_restricted_dashboard.golden
index 91c82964d..1104e0f34 100644
--- a/cli/cmd/testdata/install_restricted_dashboard.golden
+++ b/cli/cmd/testdata/install_restricted_dashboard.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -718,7 +718,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -732,7 +731,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1289,6 +1288,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2454,7 +2454,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_tracing.golden b/cli/cmd/testdata/install_tracing.golden
index f4bf34a9f..493112289 100644
--- a/cli/cmd/testdata/install_tracing.golden
+++ b/cli/cmd/testdata/install_tracing.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2523,7 +2523,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/cli/cmd/testdata/install_tracing_overwrite.golden b/cli/cmd/testdata/install_tracing_overwrite.golden
index af33fc7cf..c38bf9194 100644
--- a/cli/cmd/testdata/install_tracing_overwrite.golden
+++ b/cli/cmd/testdata/install_tracing_overwrite.golden
@@ -133,7 +133,7 @@ rules:
   resources: ["jobs"]
   verbs: ["list", "get", "watch"]
 - apiGroups: [""]
-  resources: ["pods", "endpoints", "services"]
+  resources: ["pods", "endpoints", "services", "nodes"]
   verbs: ["list", "get", "watch"]
 - apiGroups: ["linkerd.io"]
   resources: ["serviceprofiles"]
@@ -786,7 +786,6 @@ subjects:
 - kind: ServiceAccount
   name: linkerd-web
   namespace: linkerd
-
 ---
 kind: ConfigMap
 apiVersion: v1
@@ -800,7 +799,7 @@ metadata:
     linkerd.io/created-by: linkerd/cli dev-undefined
 data:
   global: |
-    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local","endpointSliceEnabled":false}
+    {"linkerdNamespace":"linkerd","cniEnabled":false,"version":"install-control-plane-version","identityContext":{"trustDomain":"cluster.local","trustAnchorsPem":"-----BEGIN CERTIFICATE-----\nMIIBYDCCAQegAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1jbHVzdGVy\nLmxvY2FsMB4XDTE5MDMwMzAxNTk1MloXDTI5MDIyODAyMDM1MlowGDEWMBQGA1UE\nAxMNY2x1c3Rlci5sb2NhbDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAChpAt0\nxtgO9qbVtEtDK80N6iCL2Htyf2kIv2m5QkJ1y0TFQi5hTVe3wtspJ8YpZF0pl364\n6TiYeXB8tOOhIACjQjBAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHSUEFjAUBggrBgEF\nBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBQ/AAwF8kG8VOmRSUTPakSSa/N4mqK2HsZuhQXCmiZHwIgZEzI5DCkpU7w3SIv\nOLO4Zsk1XrGZHGsmyiEyvYF9lpY=\n-----END CERTIFICATE-----\n","issuanceLifetime":"86400s","clockSkewAllowance":"20s","scheme":"linkerd.io/tls"},"autoInjectContext":null,"omitWebhookSideEffects":false,"clusterDomain":"cluster.local"}
   proxy: |
     {"proxyImage":{"imageName":"gcr.io/linkerd-io/proxy","pullPolicy":"IfNotPresent"},"proxyInitImage":{"imageName":"gcr.io/linkerd-io/proxy-init","pullPolicy":"IfNotPresent"},"controlPort":{"port":4190},"ignoreInboundPorts":[],"ignoreOutboundPorts":[],"inboundPort":{"port":4143},"adminPort":{"port":4191},"outboundPort":{"port":4140},"resource":{"requestCpu":"","requestMemory":"","limitCpu":"","limitMemory":""},"proxyUid":"2102","logLevel":{"level":"warn,linkerd=info"},"disableExternalProfiles":true,"proxyVersion":"install-proxy-version","proxyInitImageVersion":"v1.3.6","debugImage":{"imageName":"gcr.io/linkerd-io/debug","pullPolicy":"IfNotPresent"},"debugImageVersion":"install-debug-version","destinationGetNetworks":"10.0.0.0/8,172.16.0.0/12,192.168.0.0/16","logFormat":"plain","outboundConnectTimeout":"","inboundConnectTimeout":""}
   install: |
@@ -1357,6 +1356,7 @@ spec:
         - -controller-namespace=linkerd
         - -enable-h2-upgrade=true
         - -log-level=info
+        - -enable-endpoint-slices=false
         image: gcr.io/linkerd-io/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -2523,7 +2523,6 @@ spec:
       - name: tls
         secret:
           secretName: linkerd-tap-tls
-
 ---
 ###
 ### linkerd add-ons configuration
diff --git a/controller/api/destination/endpoint_translator_test.go b/controller/api/destination/endpoint_translator_test.go
index 0ec60d527..d032942c2 100644
--- a/controller/api/destination/endpoint_translator_test.go
+++ b/controller/api/destination/endpoint_translator_test.go
@@ -10,6 +10,7 @@ import (
 	pb "github.com/linkerd/linkerd2-proxy-api/go/destination"
 	"github.com/linkerd/linkerd2-proxy-api/go/net"
 	"github.com/linkerd/linkerd2/controller/api/destination/watcher"
+	pkgk8s "github.com/linkerd/linkerd2/controller/k8s"
 	"github.com/linkerd/linkerd2/pkg/addr"
 	"github.com/linkerd/linkerd2/pkg/k8s"
 	logging "github.com/sirupsen/logrus"
@@ -115,12 +116,37 @@ var (
 )
 
 func makeEndpointTranslator(t *testing.T) (*mockDestinationGetServer, *endpointTranslator) {
+	k8sAPI, err := pkgk8s.NewFakeAPI(`
+apiVersion: v1
+kind: Node
+metadata:
+  annotations:
+    kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
+    node.alpha.kubernetes.io/ttl: "0"
+  labels:
+    beta.kubernetes.io/arch: amd64
+    beta.kubernetes.io/os: linux
+    kubernetes.io/arch: amd64
+    kubernetes.io/hostname: kind-worker
+    kubernetes.io/os: linux
+    topology.kubernetes.io/region: west
+    topology.kubernetes.io/zone: west-1a
+  name: test-123
+`,
+	)
+	if err != nil {
+		t.Fatalf("NewFakeAPI returned an error: %s", err)
+	}
+	k8sAPI.Sync(nil)
+
 	mockGetServer := &mockDestinationGetServer{updatesReceived: []*pb.Update{}}
 	translator := newEndpointTranslator(
 		"linkerd",
 		"trust.domain",
 		true,
 		"service-name.service-ns",
+		"test-123",
+		k8sAPI.Client,
 		mockGetServer,
 		logging.WithField("test", t.Name()),
 	)
@@ -131,7 +157,7 @@ func TestEndpointTranslatorForRemoteGateways(t *testing.T) {
 	t.Run("Sends one update for add and another for remove", func(t *testing.T) {
 		mockGetServer, translator := makeEndpointTranslator(t)
 
-		translator.Add(mkAddressSetForServices(remoteGatewayWithNoTLS))
+		translator.Add(mkAddressSetForServices(remoteGatewayWithNoTLS, remoteGatewayWithTLS))
 		translator.Remove(mkAddressSetForServices(remoteGatewayWithTLS))
 
 		expectedNumUpdates := 2
@@ -236,7 +262,7 @@ func TestEndpointTranslatorForPods(t *testing.T) {
 	t.Run("Sends one update for add and another for remove", func(t *testing.T) {
 		mockGetServer, translator := makeEndpointTranslator(t)
 
-		translator.Add(mkAddressSetForPods(normalPod))
+		translator.Add(mkAddressSetForPods(normalPod, tlsOptionalPod))
 		translator.Remove(mkAddressSetForPods(tlsOptionalPod))
 
 		expectedNumUpdates := 2
@@ -249,12 +275,12 @@ func TestEndpointTranslatorForPods(t *testing.T) {
 	t.Run("Sends addresses as removed or added", func(t *testing.T) {
 		mockGetServer, translator := makeEndpointTranslator(t)
 
-		translator.Add(mkAddressSetForPods(normalPod, tlsOptionalPod))
+		translator.Add(mkAddressSetForPods(normalPod, tlsOptionalPod, tlsDisabledPod))
 		translator.Remove(mkAddressSetForPods(tlsDisabledPod))
 
 		addressesAdded := mockGetServer.updatesReceived[0].GetAdd().Addrs
 		actualNumberOfAdded := len(addressesAdded)
-		expectedNumberOfAdded := 2
+		expectedNumberOfAdded := 3
 		if actualNumberOfAdded != expectedNumberOfAdded {
 			t.Fatalf("Expecting [%d] addresses to be added, got [%d]: %v", expectedNumberOfAdded, actualNumberOfAdded, addressesAdded)
 		}
@@ -365,8 +391,9 @@ func TestEndpointTranslatorForPods(t *testing.T) {
 
 func mkAddressSetForServices(gatewayAddresses ...watcher.Address) watcher.AddressSet {
 	set := watcher.AddressSet{
-		Addresses: make(map[watcher.ServiceID]watcher.Address),
-		Labels:    map[string]string{"service": "service-name", "namespace": "service-ns"},
+		Addresses:       make(map[watcher.ServiceID]watcher.Address),
+		Labels:          map[string]string{"service": "service-name", "namespace": "service-ns"},
+		TopologicalPref: []string{},
 	}
 	for _, a := range gatewayAddresses {
 		a := a // pin
@@ -384,8 +411,9 @@ func mkAddressSetForServices(gatewayAddresses ...watcher.Address) watcher.Addres
 
 func mkAddressSetForPods(podAddresses ...watcher.Address) watcher.AddressSet {
 	set := watcher.AddressSet{
-		Addresses: make(map[watcher.PodID]watcher.Address),
-		Labels:    map[string]string{"service": "service-name", "namespace": "service-ns"},
+		Addresses:       make(map[watcher.PodID]watcher.Address),
+		Labels:          map[string]string{"service": "service-name", "namespace": "service-ns"},
+		TopologicalPref: []string{},
 	}
 	for _, p := range podAddresses {
 		id := watcher.PodID{Name: p.Pod.Name, Namespace: p.Pod.Namespace}
diff --git a/controller/api/destination/server_test.go b/controller/api/destination/server_test.go
index 9caffde05..f93e5f767 100644
--- a/controller/api/destination/server_test.go
+++ b/controller/api/destination/server_test.go
@@ -115,6 +115,7 @@ spec:
 		"linkerd",
 		"trust.domain",
 		"mycluster.local",
+		k8sAPI,
 		log,
 		make(<-chan struct{}),
 	}
diff --git a/controller/api/destination/traffic_split_adaptor_test.go b/controller/api/destination/traffic_split_adaptor_test.go
index f1e743767..7e24178bb 100644
--- a/controller/api/destination/traffic_split_adaptor_test.go
+++ b/controller/api/destination/traffic_split_adaptor_test.go
@@ -22,8 +22,8 @@ func TestTrafficSplitAdaptor(t *testing.T) {
 			},
 			DstOverrides: []*sp.WeightedDst{
 				{
-					Authority: "foo",
-					Weight:    resource.MustParse("500m"),
+					Authority: "foo.ns.svc.cluster.local.:80",
+					Weight:    resource.MustParse("1"),
 				},
 			},
 		},
diff --git a/controller/api/public/stat_summary_test.go b/controller/api/public/stat_summary_test.go
index c5e015506..753873fc3 100644
--- a/controller/api/public/stat_summary_test.go
+++ b/controller/api/public/stat_summary_test.go
@@ -308,7 +308,7 @@ spec:
   template:
     spec:
       containers:
-      - image: buoyantio/emojivoto-emoji-svc:v3
+      - image: buoyantio/emojivoto-emoji-svc:v10
 `, `
 apiVersion: apps/v1
 kind: ReplicaSet
@@ -416,7 +416,7 @@ spec:
   template:
     spec:
       containers:
-      - image: buoyantio/emojivoto-emoji-svc:v3
+      - image: buoyantio/emojivoto-emoji-svc:v10
 `, `
 apiVersion: v1
 kind: Pod
@@ -492,7 +492,7 @@ spec:
   template:
     spec:
       containers:
-      - image: buoyantio/emojivoto-emoji-svc:v3
+      - image: buoyantio/emojivoto-emoji-svc:v10
 `, `
 apiVersion: v1
 kind: Pod
@@ -1137,7 +1137,7 @@ spec:
   template:
     spec:
       containers:
-      - image: buoyantio/emojivoto-emoji-svc:v3
+      - image: buoyantio/emojivoto-emoji-svc:v10
 `, `
 apiVersion: apps/v1
 kind: ReplicaSet
@@ -1609,7 +1609,7 @@ spec:
   template:
     spec:
       containers:
-      - image: buoyantio/emojivoto-emoji-svc:v3
+      - image: buoyantio/emojivoto-emoji-svc:v10
 `, `
 apiVersion: apps/v1
 kind: ReplicaSet
diff --git a/pkg/addr/addr_test.go b/pkg/addr/addr_test.go
index bbe75ed27..771ae44c9 100644
--- a/pkg/addr/addr_test.go
+++ b/pkg/addr/addr_test.go
@@ -198,3 +198,114 @@ func TestNetToPublic(t *testing.T) {
 		})
 	}
 }
+
+func TestParseProxyIPV4(t *testing.T) {
+	var testCases = []struct {
+		ip      string
+		expAddr *pb.IPAddress
+		expErr  bool
+	}{
+		{
+			ip:      "10.0",
+			expAddr: nil,
+			expErr:  true,
+		},
+		{
+			ip:      "x.x.x.x",
+			expAddr: nil,
+			expErr:  true,
+		},
+		{
+			ip: "10.10.10.10",
+			expAddr: &pb.IPAddress{
+				Ip: &pb.IPAddress_Ipv4{Ipv4: 168430090},
+			},
+			expErr: false,
+		},
+	}
+
+	for _, testCase := range testCases {
+		res, err := ParseProxyIPV4(testCase.ip)
+		if testCase.expErr && err == nil {
+			t.Fatalf("expected get err, but get nil")
+		}
+		if !testCase.expErr {
+			if err != nil {
+				t.Fatalf("Unexpected err %v", err)
+			}
+			if !proto.Equal(res, testCase.expAddr) {
+				t.Fatalf("Unexpected TCP Address: [%+v] expected: [%+v]", res, testCase.expAddr)
+			}
+		}
+	}
+}
+
+func TestParsePublicIPV4(t *testing.T) {
+	var testCases = []struct {
+		ip      string
+		expAddr *public.IPAddress
+		expErr  bool
+	}{
+		{
+			ip:      "10.0",
+			expAddr: nil,
+			expErr:  true,
+		},
+		{
+			ip:      "x.x.x.x",
+			expAddr: nil,
+			expErr:  true,
+		},
+		{
+			ip: "10.10.10.11",
+			expAddr: &public.IPAddress{
+				Ip: &public.IPAddress_Ipv4{Ipv4: 168430091},
+			},
+			expErr: false,
+		},
+	}
+
+	for _, testCase := range testCases {
+		res, err := ParsePublicIPV4(testCase.ip)
+		if testCase.expErr && err == nil {
+			t.Fatalf("expected get err, but get nil")
+		}
+		if !testCase.expErr {
+			if err != nil {
+				t.Fatalf("Unexpected err %v", err)
+			}
+			if !proto.Equal(res, testCase.expAddr) {
+				t.Fatalf("Unexpected TCP Address: [%+v] expected: [%+v]", res, testCase.expAddr)
+			}
+		}
+	}
+}
+
+func TestProxyAddressToString(t *testing.T) {
+	var testCases = []struct {
+		addr   *pb.TcpAddress
+		expStr string
+	}{
+		{
+			addr: &pb.TcpAddress{
+				Ip:   &pb.IPAddress{Ip: &pb.IPAddress_Ipv4{Ipv4: 1}},
+				Port: 1234,
+			},
+			expStr: "0.0.0.1:1234",
+		},
+		{
+			addr: &pb.TcpAddress{
+				Ip:   &pb.IPAddress{Ip: &pb.IPAddress_Ipv4{Ipv4: 65535}},
+				Port: 5678,
+			},
+			expStr: "0.0.255.255:5678",
+		},
+	}
+
+	for _, testCase := range testCases {
+		res := ProxyAddressToString(testCase.addr)
+		if !(res == testCase.expStr) {
+			t.Fatalf("Unexpected string: %s expected: %s", res, testCase.expStr)
+		}
+	}
+}
diff --git a/pkg/charts/linkerd2/values_test.go b/pkg/charts/linkerd2/values_test.go
index 4a983ac66..217af986f 100644
--- a/pkg/charts/linkerd2/values_test.go
+++ b/pkg/charts/linkerd2/values_test.go
@@ -132,10 +132,6 @@ func TestNewValues(t *testing.T) {
 		ProxyInjector:    &ProxyInjector{TLS: &TLS{}},
 		ProfileValidator: &ProfileValidator{TLS: &TLS{}},
 		Tap:              &Tap{TLS: &TLS{}},
-		SMIMetrics: &SMIMetrics{
-			Image: "deislabs/smi-metrics:v0.2.1",
-			TLS:   &TLS{},
-		},
 		Grafana: Grafana{
 			"enabled": true,
 		},
diff --git a/pkg/healthcheck/healthcheck_test.go b/pkg/healthcheck/healthcheck_test.go
index a44226cc4..b563de3ea 100644
--- a/pkg/healthcheck/healthcheck_test.go
+++ b/pkg/healthcheck/healthcheck_test.go
@@ -786,15 +786,6 @@ metadata:
 				`
 kind: ServiceAccount
 apiVersion: v1
-metadata:
-  name: linkerd-smi-metrics
-  namespace: test-ns
-  labels:
-    linkerd.io/control-plane-ns: test-ns
-`,
-				`
-kind: ServiceAccount
-apiVersion: v1
 metadata:
   name: linkerd-sp-validator
   namespace: test-ns
@@ -997,15 +988,6 @@ metadata:
 				`
 kind: ServiceAccount
 apiVersion: v1
-metadata:
-  name: linkerd-smi-metrics
-  namespace: test-ns
-  labels:
-    linkerd.io/control-plane-ns: test-ns
-`,
-				`
-kind: ServiceAccount
-apiVersion: v1
 metadata:
   name: linkerd-sp-validator
   namespace: test-ns
@@ -1217,15 +1199,6 @@ metadata:
 				`
 kind: ServiceAccount
 apiVersion: v1
-metadata:
-  name: linkerd-smi-metrics
-  namespace: test-ns
-  labels:
-    linkerd.io/control-plane-ns: test-ns
-`,
-				`
-kind: ServiceAccount
-apiVersion: v1
 metadata:
   name: linkerd-sp-validator
   namespace: test-ns
@@ -1446,15 +1419,6 @@ metadata:
 				`
 kind: ServiceAccount
 apiVersion: v1
-metadata:
-  name: linkerd-smi-metrics
-  namespace: test-ns
-  labels:
-    linkerd.io/control-plane-ns: test-ns
-`,
-				`
-kind: ServiceAccount
-apiVersion: v1
 metadata:
   name: linkerd-sp-validator
   namespace: test-ns
@@ -1684,15 +1648,6 @@ metadata:
 				`
 kind: ServiceAccount
 apiVersion: v1
-metadata:
-  name: linkerd-smi-metrics
-  namespace: test-ns
-  labels:
-    linkerd.io/control-plane-ns: test-ns
-`,
-				`
-kind: ServiceAccount
-apiVersion: v1
 metadata:
   name: linkerd-sp-validator
   namespace: test-ns
@@ -2335,17 +2290,8 @@ metadata:
 	})
 }
 
-func getConfigAndKubeSystemNamespace(ha bool, nsLabel string) []string {
+func getWebhookAndKubeSystemNamespace(nsLabel string, failurePolicy string) []string {
 	return []string{fmt.Sprintf(`
-kind: ConfigMap
-apiVersion: v1
-metadata:
-  name: linkerd-config
-  namespace: linkerd
-data:
-  install: |
-    {"cliVersion":"dev-undefined","flags":[{"name":"ha","value":"%v"}]}`, ha),
-		fmt.Sprintf(`
 apiVersion: v1
 kind: Namespace
 metadata:
@@ -2353,6 +2299,35 @@ metadata:
   labels:
     %s
   name: kube-system`, nsLabel),
+		fmt.Sprintf(`
+apiVersion: admissionregistration.k8s.io/v1beta1
+kind: MutatingWebhookConfiguration
+metadata:
+  name: linkerd-proxy-injector-webhook-config
+  labels:
+    linkerd.io/control-plane-component: proxy-injector
+    linkerd.io/control-plane-ns: linkerd
+webhooks:
+- name: linkerd-proxy-injector.linkerd.io
+  namespaceSelector:
+    matchExpressions:
+    - key: config.linkerd.io/admission-webhooks
+      operator: NotIn
+      values:
+      - disabled
+  clientConfig:
+    service:
+      name: linkerd-proxy-injector
+      namespace: linkerd
+      path: "/"
+    caBundle: cHJveHkgaW5qZWN0b3IgQ0EgYnVuZGxl
+  failurePolicy: %s
+  rules:
+  - operations: [ "CREATE" ]
+    apiGroups: [""]
+    apiVersions: ["v1"]
+    resources: ["pods"]
+  sideEffects: None`, failurePolicy),
 	}
 }
 
@@ -2363,24 +2338,24 @@ func TestKubeSystemNamespaceInHA(t *testing.T) {
 		expectedOutput  string
 	}{
 		{
-			"passes when HA is not enabled",
-			getConfigAndKubeSystemNamespace(false, ""),
+			"passes when webhook policy is Ignore is not enabled",
+			getWebhookAndKubeSystemNamespace("", "Ignore"),
 			"",
 		},
 		{
-			"passes when HA is enabled and namespace has required metadata",
-			getConfigAndKubeSystemNamespace(true, "config.linkerd.io/admission-webhooks: disabled"),
+			"passes when webhook policy is Fail and namespace has required metadata",
+			getWebhookAndKubeSystemNamespace("config.linkerd.io/admission-webhooks: disabled", "Fail"),
 			"l5d-injection-disabled pod injection disabled on kube-system",
 		},
 		{
-			"fails when HA and admission hooks are enabled",
-			getConfigAndKubeSystemNamespace(true, "config.linkerd.io/admission-webhooks: enabled"),
-			"l5d-injection-disabled pod injection disabled on kube-system: kube-system namespace needs to have the label config.linkerd.io/admission-webhooks: disabled if HA mode is enabled",
+			"fails when webhook policy is Fail and admission hooks are enabled",
+			getWebhookAndKubeSystemNamespace("config.linkerd.io/admission-webhooks: enabled", "Fail"),
+			"l5d-injection-disabled pod injection disabled on kube-system: kube-system namespace needs to have the label config.linkerd.io/admission-webhooks: disabled if injector webhook failure policy is Fail",
 		},
 		{
-			"fails when HA is enabled and metadata is missing",
-			getConfigAndKubeSystemNamespace(true, ""),
-			"l5d-injection-disabled pod injection disabled on kube-system: kube-system namespace needs to have the label config.linkerd.io/admission-webhooks: disabled if HA mode is enabled",
+			"fails when webhook policy is Fail and metadata is missing",
+			getWebhookAndKubeSystemNamespace("", "Fail"),
+			"l5d-injection-disabled pod injection disabled on kube-system: kube-system namespace needs to have the label config.linkerd.io/admission-webhooks: disabled if injector webhook failure policy is Fail",
 		},
 	}
 
@@ -2391,13 +2366,7 @@ func TestKubeSystemNamespaceInHA(t *testing.T) {
 			hc := NewHealthChecker([]CategoryID{}, &Options{})
 			hc.ControlPlaneNamespace = "linkerd"
 
-			var err error
 			hc.kubeAPI, _ = k8s.NewFakeAPI(tc.k8sConfigs...)
-			_, hc.linkerdConfig, err = hc.checkLinkerdConfigConfigMap()
-			if err != nil {
-				t.Fatalf("Unexpected error: %q", err)
-			}
-
 			hc.addCheckAsCategory("l5d-injection-disabled", LinkerdHAChecks, "pod injection disabled on kube-system")
 
 			obs := newObserver()
diff --git a/test/integration/edges/testdata/slow-cooker.yaml b/test/integration/edges/testdata/slow-cooker.yaml
index 4ed8ac548..e152d6c9f 100644
--- a/test/integration/edges/testdata/slow-cooker.yaml
+++ b/test/integration/edges/testdata/slow-cooker.yaml
@@ -15,13 +15,13 @@ spec:
     spec:
       containers:
       - name: slow-cooker
-        image: buoyantio/slow_cooker:1.1.1
+        image: buoyantio/slow_cooker:1.3.0
         command:
         - "/bin/sh"
         args:
         - "-c"
         - |
           sleep 15 # wait for pods to start
-          slow_cooker -metric-addr 0.0.0.0:9999 http://___TERMINUS_POD_IP___:8080
+          /slow_cooker/slow_cooker -metric-addr 0.0.0.0:9999 http://___TERMINUS_POD_IP___:8080
         ports:
         - containerPort: 9999
diff --git a/test/integration/edges/testdata/terminus.yaml b/test/integration/edges/testdata/terminus.yaml
index b6ef83552..d05a24f66 100644
--- a/test/integration/edges/testdata/terminus.yaml
+++ b/test/integration/edges/testdata/terminus.yaml
@@ -15,7 +15,7 @@ spec:
     spec:
       containers:
       - name: terminus
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
diff --git a/test/integration/egress/testdata/proxy.yaml b/test/integration/egress/testdata/proxy.yaml
index e7c134873..eae122f03 100644
--- a/test/integration/egress/testdata/proxy.yaml
+++ b/test/integration/egress/testdata/proxy.yaml
@@ -15,4 +15,4 @@ spec:
     spec:
       containers:
       - name: http-egress
-        image: gcr.io/linkerd-io/debug:stable-2.6.1
+        image: gcr.io/linkerd-io/debug:edge-20.8.1
diff --git a/test/integration/externalissuer/testdata/external_issuer_application.yaml b/test/integration/externalissuer/testdata/external_issuer_application.yaml
index fc1052f35..6a5aa293c 100644
--- a/test/integration/externalissuer/testdata/external_issuer_application.yaml
+++ b/test/integration/externalissuer/testdata/external_issuer_application.yaml
@@ -15,7 +15,7 @@ spec:
     spec:
       containers:
       - name: backend
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
@@ -51,14 +51,14 @@ spec:
     spec:
       containers:
       - name: slow-cooker
-        image: buoyantio/slow_cooker:1.1.1
+        image: buoyantio/slow_cooker:1.3.0
         command:
         - "/bin/sh"
         args:
         - "-c"
         - |
           sleep 5 # wait for pods to start
-          slow_cooker http://backend-svc:8080
+          /slow_cooker/slow_cooker http://backend-svc:8080
         ports:
         - containerPort: 9999
 ---
diff --git a/test/integration/get/testdata/not_to_be_injected_application.yaml b/test/integration/get/testdata/not_to_be_injected_application.yaml
index b16f92cad..c63482630 100644
--- a/test/integration/get/testdata/not_to_be_injected_application.yaml
+++ b/test/integration/get/testdata/not_to_be_injected_application.yaml
@@ -15,12 +15,12 @@ spec:
     spec:
       containers:
       - name: http-to-grpc
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"]
         ports:
         - containerPort: 9090
       - name: http-to-grpc-2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"]
         ports:
         - containerPort: 90
@@ -41,7 +41,7 @@ spec:
     spec:
       containers:
       - name: http-to-grpc
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"]
         ports:
         - containerPort: 90
diff --git a/test/integration/get/testdata/to_be_injected_application.yaml b/test/integration/get/testdata/to_be_injected_application.yaml
index f37a5e62c..79fcde82e 100644
--- a/test/integration/get/testdata/to_be_injected_application.yaml
+++ b/test/integration/get/testdata/to_be_injected_application.yaml
@@ -15,12 +15,12 @@ spec:
     spec:
       containers:
       - name: http-to-grpc
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"]
         ports:
         - containerPort: 9090
       - name: http-to-grpc-2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"]
         ports:
         - containerPort: 90
@@ -41,7 +41,7 @@ spec:
     spec:
       containers:
       - name: http-to-grpc
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "90", "--response-text", "BANANA"]
         ports:
         - containerPort: 90
diff --git a/test/integration/inject/testdata/inject_test.yaml b/test/integration/inject/testdata/inject_test.yaml
index 46df41251..be175757f 100644
--- a/test/integration/inject/testdata/inject_test.yaml
+++ b/test/integration/inject/testdata/inject_test.yaml
@@ -14,7 +14,7 @@ spec:
     spec:
       containers:
       - name: bb-terminus
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"]
         ports:
         - containerPort: 9090
diff --git a/test/integration/inject/testdata/injected_default.golden b/test/integration/inject/testdata/injected_default.golden
index dcd522346..9e42050ce 100644
--- a/test/integration/inject/testdata/injected_default.golden
+++ b/test/integration/inject/testdata/injected_default.golden
@@ -29,7 +29,7 @@ spec:
         - "9090"
         - --response-text
         - BANANA
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         name: bb-terminus
         ports:
         - containerPort: 9090
diff --git a/test/integration/inject/testdata/injected_params.golden b/test/integration/inject/testdata/injected_params.golden
index ccf45659e..d1f1fee1e 100644
--- a/test/integration/inject/testdata/injected_params.golden
+++ b/test/integration/inject/testdata/injected_params.golden
@@ -44,7 +44,7 @@ spec:
         - "9090"
         - --response-text
         - BANANA
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         name: bb-terminus
         ports:
         - containerPort: 9090
diff --git a/test/integration/inject/testdata/pod.yaml b/test/integration/inject/testdata/pod.yaml
index 83ba51409..132efaa09 100644
--- a/test/integration/inject/testdata/pod.yaml
+++ b/test/integration/inject/testdata/pod.yaml
@@ -7,7 +7,7 @@ metadata:
 spec:
   containers:
   - name: bb-terminus
-    image: buoyantio/bb:v0.0.5
+    image: buoyantio/bb:v0.0.6
     args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"]
     ports:
     - containerPort: 9090
diff --git a/test/integration/install_test.go b/test/integration/install_test.go
index 8745348cb..1afb9fad0 100644
--- a/test/integration/install_test.go
+++ b/test/integration/install_test.go
@@ -430,8 +430,6 @@ func TestUpgradeHelm(t *testing.T) {
 		"--set", "prometheus.proxy.resources.memory.request=105Mi",
 		"--set", "proxyInjectorProxyResources.cpu.limit=1060m",
 		"--set", "proxyInjectorProxyResources.memory.request=106Mi",
-		"--set", "smiMetricsProxyResources.cpu.limit=1070m",
-		"--set", "smiMetricsProxyResources.memory.request=107Mi",
 		"--set", "spValidatorProxyResources.cpu.limit=1080m",
 		"--set", "spValidatorProxyResources.memory.request=108Mi",
 		"--set", "tapProxyResources.cpu.limit=1090m",
@@ -515,15 +513,6 @@ var expectedResources = []expectedData{
 		memLimit:   "200Mi",
 		memRequest: "106Mi",
 	},
-	/*	 not used in default case
-	{
-		pod:        "linkerd-smi-metrics",
-		cpuLimit:   "1070m",
-		cpuRequest: "20m",
-		memLimit:   "200Mi",
-		memRequest: "1007i",
-	},
-	*/
 	{
 		pod:        "linkerd-sp-validator",
 		cpuLimit:   "1080m",
diff --git a/test/integration/serviceprofiles/testdata/hello_world.yaml b/test/integration/serviceprofiles/testdata/hello_world.yaml
index 09359cf9f..20d27b04d 100644
--- a/test/integration/serviceprofiles/testdata/hello_world.yaml
+++ b/test/integration/serviceprofiles/testdata/hello_world.yaml
@@ -14,7 +14,7 @@ spec:
     spec:
       containers:
       - name: hello
-        image: buoyantio/helloworld:0.1.6
+        image: buoyantio/helloworld:0.1.7
         args:
         - "-addr=:8888"
         - "-text=Hello"
@@ -51,7 +51,7 @@ spec:
     spec:
       containers:
       - name: world
-        image: buoyantio/helloworld:0.1.6
+        image: buoyantio/helloworld:0.1.7
         args:
         - "-addr=:8889"
         - "-text=World"
@@ -84,12 +84,12 @@ spec:
     spec:
       containers:
       - name: hello-slow-cooker
-        image: buoyantio/slow_cooker:1.1.1
+        image: buoyantio/slow_cooker:1.3.0
         command:
         - "/bin/sh"
         args:
         - "-c"
         - |
           sleep 15 # wait for pods to start
-          slow_cooker -metric-addr 0.0.0.0:9998 http://hello-svc:8888/testpath
+          /slow_cooker/slow_cooker -metric-addr 0.0.0.0:9998 http://hello-svc:8888/testpath
       restartPolicy: OnFailure
diff --git a/test/integration/serviceprofiles/testdata/tap_application.yaml b/test/integration/serviceprofiles/testdata/tap_application.yaml
index 977d8a430..688c29766 100644
--- a/test/integration/serviceprofiles/testdata/tap_application.yaml
+++ b/test/integration/serviceprofiles/testdata/tap_application.yaml
@@ -1,4 +1,4 @@
-# slow_cooker --http-> gateway --grpc-> t1
+# /slow_cooker/slow_cooker --http-> gateway --grpc-> t1
 #                              --grpc-> t2 always-error
 #                              --http-> t3
 #
@@ -21,7 +21,7 @@ spec:
     spec:
       containers:
       - name: t1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--grpc-server-port=9090"
@@ -59,7 +59,7 @@ spec:
     spec:
       containers:
       - name: t2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--grpc-server-port=9090"
@@ -98,7 +98,7 @@ spec:
     spec:
       containers:
       - name: t3
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
@@ -137,7 +137,7 @@ spec:
     spec:
       containers:
       - name: gateway
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - broadcast-channel
         - "--h1-server-port=8080"
@@ -173,14 +173,14 @@ spec:
     spec:
       containers:
       - name: slow-cooker
-        image: buoyantio/slow_cooker:1.1.1
+        image: buoyantio/slow_cooker:1.3.0
         command:
         - "/bin/sh"
         args:
         - "-c"
         - |
           sleep 15 # wait for pods to start
-          slow_cooker -metric-addr 0.0.0.0:9999 http://gateway-svc:8080
+          /slow_cooker/slow_cooker -metric-addr 0.0.0.0:9999 http://gateway-svc:8080
         ports:
         - containerPort: 9999
       restartPolicy: OnFailure
diff --git a/test/integration/tap/testdata/tap_application.yaml b/test/integration/tap/testdata/tap_application.yaml
index 0e13caab7..953922078 100644
--- a/test/integration/tap/testdata/tap_application.yaml
+++ b/test/integration/tap/testdata/tap_application.yaml
@@ -1,4 +1,4 @@
-# slow_cooker --http-> gateway --grpc-> t1
+# /slow_cooker/slow_cooker --http-> gateway --grpc-> t1
 #                              --grpc-> t2 always-error
 #                              --http-> t3
 #                              --http-> t4 tap-disabled
@@ -22,7 +22,7 @@ spec:
     spec:
       containers:
       - name: t1
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--grpc-server-port=9090"
@@ -60,7 +60,7 @@ spec:
     spec:
       containers:
       - name: t2
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--grpc-server-port=9090"
@@ -99,7 +99,7 @@ spec:
     spec:
       containers:
       - name: t3
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
@@ -139,7 +139,7 @@ spec:
     spec:
       containers:
       - name: t4
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
@@ -177,7 +177,7 @@ spec:
     spec:
       containers:
       - name: gateway
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - broadcast-channel
         - "--h1-server-port=8080"
@@ -214,14 +214,14 @@ spec:
     spec:
       containers:
       - name: slow-cooker
-        image: buoyantio/slow_cooker:1.1.1
+        image: buoyantio/slow_cooker:1.3.0
         command:
         - "/bin/sh"
         args:
         - "-c"
         - |
           sleep 15 # wait for pods to start
-          slow_cooker -metric-addr 0.0.0.0:9999 http://gateway-svc:8080
+          /slow_cooker/slow_cooker -metric-addr 0.0.0.0:9999 http://gateway-svc:8080
         ports:
         - containerPort: 9999
       restartPolicy: OnFailure
diff --git a/test/integration/testdata/smoke_test.yaml b/test/integration/testdata/smoke_test.yaml
index b78b7ac2c..fd9e1d9ea 100644
--- a/test/integration/testdata/smoke_test.yaml
+++ b/test/integration/testdata/smoke_test.yaml
@@ -15,7 +15,7 @@ spec:
     spec:
       containers:
       - name: http-to-grpc
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["terminus", "--grpc-server-port", "9090", "--response-text", "BANANA"]
         ports:
         - containerPort: 9090
@@ -48,7 +48,7 @@ spec:
     spec:
       containers:
       - name: http-to-grpc
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args: ["point-to-point-channel", "--grpc-downstream-server", "smoke-test-terminus-svc:9090", "--h1-server-port", "8080"]
         ports:
         - containerPort: 8080
diff --git a/test/integration/testdata/upgrade_test.yaml b/test/integration/testdata/upgrade_test.yaml
index 0ae9222dd..eefad5156 100644
--- a/test/integration/testdata/upgrade_test.yaml
+++ b/test/integration/testdata/upgrade_test.yaml
@@ -36,7 +36,7 @@ spec:
       - env:
         - name: GRPC_PORT
           value: "8080"
-        image: buoyantio/emojivoto-emoji-svc:v8
+        image: buoyantio/emojivoto-emoji-svc:v10
         name: emoji-svc
         ports:
         - containerPort: 8080
@@ -81,7 +81,7 @@ spec:
       - env:
         - name: GRPC_PORT
           value: "8080"
-        image: buoyantio/emojivoto-voting-svc:v8
+        image: buoyantio/emojivoto-voting-svc:v10
         name: voting-svc
         ports:
         - containerPort: 8080
@@ -132,7 +132,7 @@ spec:
           value: voting-svc:8080
         - name: INDEX_BUNDLE
           value: dist/index_bundle.js
-        image: buoyantio/emojivoto-web:v8
+        image: buoyantio/emojivoto-web:v10
         name: web-svc
         ports:
         - containerPort: 8080
diff --git a/test/integration/tracing/testdata/emojivoto.yaml b/test/integration/tracing/testdata/emojivoto.yaml
index 04049f180..4c023ba3f 100644
--- a/test/integration/tracing/testdata/emojivoto.yaml
+++ b/test/integration/tracing/testdata/emojivoto.yaml
@@ -192,7 +192,7 @@ spec:
         env:
         - name: WEB_HOST
           value: nginx-ingress:80
-        image: buoyantio/emojivoto-web:v8
+        image: buoyantio/emojivoto-web:v10
         name: vote-bot
         resources:
           requests:
diff --git a/test/integration/tracing/testdata/ingress.yaml b/test/integration/tracing/testdata/ingress.yaml
index f61261d8c..b9b3de5f0 100644
--- a/test/integration/tracing/testdata/ingress.yaml
+++ b/test/integration/tracing/testdata/ingress.yaml
@@ -92,7 +92,7 @@ kind: ConfigMap
 metadata:
   name: nginx-ingress-controller
   labels:
-    app: nginx-ingress  
+    app: nginx-ingress
 data:
   ssl-redirect: "false"
   enable-opentracing: "true"
diff --git a/test/integration/tracing/tracing_test.go b/test/integration/tracing/tracing_test.go
index 40c7149ef..5c82ef569 100644
--- a/test/integration/tracing/tracing_test.go
+++ b/test/integration/tracing/tracing_test.go
@@ -41,6 +41,9 @@ func TestMain(m *testing.M) {
 //////////////////////
 
 func TestTracing(t *testing.T) {
+	if os.Getenv("RUN_ARM_TEST") != "" {
+		t.Skip("Skipped. Jaeger & Open Census images does not support ARM yet")
+	}
 
 	// Tracing Components
 	out, stderr, err := TestHelper.LinkerdRun("inject", "testdata/tracing.yaml")
diff --git a/test/integration/trafficsplit/testdata/traffic_split_application.yaml b/test/integration/trafficsplit/testdata/traffic_split_application.yaml
index c3827305f..cfa1050dd 100644
--- a/test/integration/trafficsplit/testdata/traffic_split_application.yaml
+++ b/test/integration/trafficsplit/testdata/traffic_split_application.yaml
@@ -19,7 +19,7 @@ spec:
     spec:
       containers:
       - name: backend
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
@@ -55,7 +55,7 @@ spec:
     spec:
       containers:
       - name: failing
-        image: buoyantio/bb:v0.0.5
+        image: buoyantio/bb:v0.0.6
         args:
         - terminus
         - "--h1-server-port=8080"
@@ -92,14 +92,14 @@ spec:
     spec:
       containers:
       - name: slow-cooker
-        image: buoyantio/slow_cooker:1.1.1
+        image: buoyantio/slow_cooker:1.3.0
         command:
         - "/bin/sh"
         args:
         - "-c"
         - |
           sleep 5 # wait for pods to start
-          slow_cooker http://backend-svc:8080
+          /slow_cooker/slow_cooker http://backend-svc:8080
         ports:
         - containerPort: 9999
 ---