Repository: linkerd/linkerd2
Pull request #5765 (2021-02-17 15:56:19)

Add Tarun to Maintainers
@pothulapati has been an active participant in the Linkerd community,
contributing over 100 changes over the past two years. In recognition of
Tarun's track record, I'd like to propose that we add him to the project
maintainers group.

This change adds Tarun to the list of maintainers and moves the
_Emeriti_ section below the _Steering Committee_ section.

<!--  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/MAINTAINERS.md b/MAINTAINERS.md
index c4f6683f9..a5270fe33 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -7,16 +7,7 @@ The Linkerd maintainers are:
 * Alex Leong <alex@buoyant.io> @adleong
 * Eliza Weisman <eliza@buoyant.io> @hawkw
 * Kevin Leimkuhler <kevinl@buoyant.io> @kleimkuhler
-
-## Emeritus
-
-Former maintainers include:
-
-* Andrew Seigner <siggy@buoyant.io> @siggy
-* Kevin Ingleman <ki@buoyant.io> @klingerf
-* Risha Mars <mars@buoyant.io> @rmars
-* Hema Lee <Hemalekha.Lee@nordstrom.com> @hemakl
-* Zahari Dichev <zahari@buoyant.io> @zaharidichev
+* Tarun Pothulapati <tarun@buoyant.io> @pothulapati
 
 ## Steering Committee
 
@@ -27,11 +18,20 @@ The Linkerd Steering Committee members are:
 * Justin Turner @justin-turner-heb
 * William King @quentusrex
 
+## Emeriti
+
+Former maintainers include:
+
+* Andrew Seigner <siggy@buoyant.io> @siggy
+* Kevin Ingleman <ki@buoyant.io> @klingerf
+* Risha Mars <mars@buoyant.io> @rmars
+* Hema Lee <Hemalekha.Lee@nordstrom.com> @hemakl
+* Zahari Dichev <zahari@buoyant.io> @zaharidichev
+
 <!--
 # Adding a new maintainer
 
 * Submit a PR modifying this file
-* Add maintainer to .github/CODEOWNERS
 * Obtain approvals per GOVERNANCE.md
 * Invite maintainer to
   https://github.com/orgs/linkerd/teams/maintainers/members
diff --git a/charts/linkerd2/README.md b/charts/linkerd2/README.md
index 111fb9359..5b4d85e01 100644
--- a/charts/linkerd2/README.md
+++ b/charts/linkerd2/README.md
@@ -140,8 +140,8 @@ Kubernetes: `>=1.16.0-0`
 | controllerUID | int | `2103` | User ID for the control plane components |
 | createdByAnnotation | string | `"linkerd.io/created-by"` | Annotation label for the proxy create. Do not edit. |
 | debugContainer.image.name | string | `"ghcr.io/linkerd/debug"` | Docker image for the debug container |
-| debugContainer.image.pullPolicy | string | `"IfNotPresent"` | Pull policy for the debug container Docker image |
-| debugContainer.image.version | string | `"linkerdVersionValue"` | Tag for the debug container Docker image |
+| debugContainer.image.pullPolicy | string | imagePullPolicy | Pull policy for the debug container Docker image |
+| debugContainer.image.version | string | linkerdVersion | Tag for the debug container Docker image |
 | disableHeartBeat | bool | `false` | Set to true to not start the heartbeat cronjob |
 | enableEndpointSlices | bool | `false` | enables the use of EndpointSlice informers for the destination service; enableEndpointSlices should be set to true only if EndpointSlice K8s feature gate is on; the feature is still experimental. |
 | enableH2Upgrade | bool | `true` | Allow proxies to perform transparent HTTP/2 upgrading |
@@ -155,7 +155,7 @@ Kubernetes: `>=1.16.0-0`
 | identity.issuer.tls.crtPEM | string | `""` | Issuer certificate (ECDSA). It must be provided during install. |
 | identity.issuer.tls.keyPEM | string | `""` | Key for the issuer certificate (ECDSA). It must be provided during install |
 | identityTrustAnchorsPEM | string | `""` | Trust root certificate (ECDSA). It must be provided during install. |
-| identityTrustDomain | string | `"cluster.local"` | Trust domain used for identity |
+| identityTrustDomain | string | clusterDomain | Trust domain used for identity |
 | imagePullPolicy | string | `"IfNotPresent"` | Docker image pull policy |
 | imagePullSecrets | list | `[]` | For Private docker registries, authentication is needed.  Registry secrets are applied to the respective service accounts |
 | installNamespace | bool | `true` | Set to false when installing Linkerd in a custom namespace. See the [Linkerd documentation](https://linkerd.io/2/tasks/install-helmcustomizing-the-namespace) for more information. |
@@ -174,8 +174,8 @@ Kubernetes: `>=1.16.0-0`
 | proxy.cores | int | `0` | The `cpu.limit` and `cores` should be kept in sync. The value of `cores` must be an integer and should typically be set by rounding up from the limit. E.g. if cpu.limit is '1500m', cores should be 2. |
 | proxy.enableExternalProfiles | bool | `false` | Enable service profiles for non-Kubernetes services |
 | proxy.image.name | string | `"ghcr.io/linkerd/proxy"` | Docker image for the proxy |
-| proxy.image.pullPolicy | string | `"IfNotPresent"` | Pull policy for the proxy container Docker image |
-| proxy.image.version | string | `"linkerdVersionValue"` | Tag for the proxy container Docker image |
+| proxy.image.pullPolicy | string | imagePullPolicy | Pull policy for the proxy container Docker image |
+| proxy.image.version | string | linkerdVersion | Tag for the proxy container Docker image |
 | proxy.inboundConnectTimeout | string | `"100ms"` | Maximum time allowed for the proxy to establish an inbound TCP connection |
 | proxy.logFormat | string | `"plain"` | Log format (`plain` or `json`) for the proxy |
 | proxy.logLevel | string | `"warn,linkerd=info"` | Log level for the proxy |
@@ -195,7 +195,7 @@ Kubernetes: `>=1.16.0-0`
 | proxyInit.ignoreInboundPorts | string | `"25,443,587,3306,11211"` | Default set of ports to skip via itpables: - SMTP (25,587) server-first - HTTPS (443) opaque TLS - MYSQL (3306) server-first - Memcached (11211) clients do not issue any preamble, which breaks detection |
 | proxyInit.ignoreOutboundPorts | string | `"25,443,587,3306,11211"` | Default set of ports to skip via itpables, same defaults as InboudPorts |
 | proxyInit.image.name | string | `"ghcr.io/linkerd/proxy-init"` | Docker image for the proxy-init container |
-| proxyInit.image.pullPolicy | string | `"IfNotPresent"` | Pull policy for the proxy-init container Docker image |
+| proxyInit.image.pullPolicy | string | imagePullPolicy | Pull policy for the proxy-init container Docker image |
 | proxyInit.image.version | string | `"v1.3.9"` | Tag for the proxy-init container Docker image |
 | proxyInit.resources.cpu.limit | string | `"100m"` | Maximum amount of CPU units that the proxy-init container can use |
 | proxyInit.resources.cpu.request | string | `"10m"` | Amount of CPU units that the proxy-init container requests |
diff --git a/charts/linkerd2/templates/config.yaml b/charts/linkerd2/templates/config.yaml
index fbedb84ef..cef6d638c 100644
--- a/charts/linkerd2/templates/config.yaml
+++ b/charts/linkerd2/templates/config.yaml
@@ -25,6 +25,9 @@ data:
   {{- if kindIs "map" $values.proxyInjector -}}
     {{- $_ := unset $values.proxyInjector "keyPEM"}}
   {{- end -}}
+  {{- if (empty $values.identityTrustDomain) -}}
+  {{- $_ := set $values "identityTrustDomain" $values.clusterDomain}}
+  {{- end -}}
   {{- $_ := unset $values "partials"}}
   {{- $_ := unset $values "configs"}}
   {{- $_ := unset $values "stage"}}
diff --git a/charts/linkerd2/templates/destination.yaml b/charts/linkerd2/templates/destination.yaml
index 4dd49811e..0b7da4f5b 100644
--- a/charts/linkerd2/templates/destination.yaml
+++ b/charts/linkerd2/templates/destination.yaml
@@ -118,7 +118,7 @@ spec:
         - -log-format={{.Values.controllerLogFormat}}
         - -enable-endpoint-slices={{.Values.enableEndpointSlices}}
         - -cluster-domain={{.Values.clusterDomain}}
-        - -identity-trust-domain={{.Values.identityTrustDomain}}
+        - -identity-trust-domain={{.Values.identityTrustDomain | default .Values.clusterDomain}}
         {{- include "partials.linkerd.trace" . | nindent 8 -}}
         image: {{.Values.controllerImage}}:{{default .Values.linkerdVersion .Values.controllerImageVersion}}
         imagePullPolicy: {{.Values.imagePullPolicy}}
diff --git a/charts/linkerd2/templates/identity.yaml b/charts/linkerd2/templates/identity.yaml
index fe9ae8823..0e4c1bc3d 100644
--- a/charts/linkerd2/templates/identity.yaml
+++ b/charts/linkerd2/templates/identity.yaml
@@ -135,7 +135,7 @@ spec:
         - -log-level={{.Values.controllerLogLevel}}
         - -log-format={{.Values.controllerLogFormat}}
         - -controller-namespace={{.Values.namespace}}
-        - -identity-trust-domain={{.Values.identityTrustDomain}}
+        - -identity-trust-domain={{.Values.identityTrustDomain | default .Values.clusterDomain}}
         - -identity-issuance-lifetime={{.Values.identity.issuer.issuanceLifetime}}
         - -identity-clock-skew-allowance={{.Values.identity.issuer.clockSkewAllowance}}
         - -identity-trust-anchors-pem={{b64enc .Values.identityTrustAnchorsPEM}}
diff --git a/charts/linkerd2/values.yaml b/charts/linkerd2/values.yaml
index 97ff6e58c..8189c34d6 100644
--- a/charts/linkerd2/values.yaml
+++ b/charts/linkerd2/values.yaml
@@ -3,7 +3,7 @@
 # Declare variables to be passed into your templates.
 
 # -- Kubernetes DNS Domain name to use
-clusterDomain: &cluster_domain cluster.local
+clusterDomain: cluster.local
 
 # -- The cluster networks for which service discovery is performed. This should
 # include the pod network but need not include the node network.
@@ -12,9 +12,9 @@ clusterDomain: &cluster_domain cluster.local
 # typical Kubernetes environments.
 clusterNetworks: "10.0.0.0/8,100.64.0.0/10,172.16.0.0/12,192.168.0.0/16"
 # -- Docker image pull policy
-imagePullPolicy: &image_pull_policy IfNotPresent
+imagePullPolicy: IfNotPresent
 # -- Log level for the control plane components
-controllerLogLevel: &controller_log_level info
+controllerLogLevel: info
 # -- Log format for the control plane components
 controllerLogFormat: plain
 # -- enables control plane tracing
@@ -22,7 +22,7 @@ controlPlaneTracing: false
 # -- namespace to send control plane traces to
 controlPlaneTracingNamespace: linkerd-jaeger
 # -- control plane version. See Proxy section for proxy version
-linkerdVersion: &linkerd_version linkerdVersionValue
+linkerdVersion: linkerdVersionValue
 # -- Control plane namespace
 namespace: linkerd
 # -- enables the use of EndpointSlice informers for the destination service;
@@ -36,7 +36,8 @@ cniEnabled: false
 # -- Trust root certificate (ECDSA). It must be provided during install.
 identityTrustAnchorsPEM: |
 # -- Trust domain used for identity
-identityTrustDomain: *cluster_domain
+# @default -- clusterDomain
+identityTrustDomain: ""
 # -- Additional annotations to add to all pods
 podAnnotations: {}
 # -- Additional labels to add to all pods
@@ -55,9 +56,11 @@ proxy:
     # -- Docker image for the proxy
     name: ghcr.io/linkerd/proxy
     # -- Pull policy for the proxy container Docker image
-    pullPolicy: *image_pull_policy
+    # @default -- imagePullPolicy
+    pullPolicy: ""
     # -- Tag for the proxy container Docker image
-    version: *linkerd_version
+    # @default -- linkerdVersion
+    version: ""
   # -- Log level for the proxy
   logLevel: warn,linkerd=info
   # -- Log format (`plain` or `json`) for the proxy
@@ -109,7 +112,8 @@ proxyInit:
     # -- Docker image for the proxy-init container
     name: ghcr.io/linkerd/proxy-init
     # -- Pull policy for the proxy-init container Docker image
-    pullPolicy: *image_pull_policy
+    # @default -- imagePullPolicy
+    pullPolicy: ""
     # -- Tag for the proxy-init container Docker image
     version: v1.3.9
   resources:
@@ -178,9 +182,11 @@ debugContainer:
     # -- Docker image for the debug container
     name: ghcr.io/linkerd/debug
     # -- Pull policy for the debug container Docker image
-    pullPolicy: *image_pull_policy
+    # @default -- imagePullPolicy
+    pullPolicy: ""
     # -- Tag for the debug container Docker image
-    version: *linkerd_version
+    # @default -- linkerdVersion
+    version: ""
 
 identity:
   issuer:
diff --git a/charts/partials/templates/_debug.tpl b/charts/partials/templates/_debug.tpl
index d842f53c2..cf0eb1417 100644
--- a/charts/partials/templates/_debug.tpl
+++ b/charts/partials/templates/_debug.tpl
@@ -1,6 +1,6 @@
 {{- define "partials.debug" -}}
-image: {{.image.name}}:{{.image.version}}
-imagePullPolicy: {{.image.pullPolicy}}
+image: {{.Values.debugContainer.image.name}}:{{.Values.debugContainer.image.version | default .Values.linkerdVersion}}
+imagePullPolicy: {{.Values.debugContainer.image.pullPolicy | default .Values.imagePullPolicy}}
 name: linkerd-debug
 terminationMessagePolicy: FallbackToLogsOnError
 {{- end -}}
diff --git a/charts/partials/templates/_proxy-init.tpl b/charts/partials/templates/_proxy-init.tpl
index 49942d6a4..ae2e78730 100644
--- a/charts/partials/templates/_proxy-init.tpl
+++ b/charts/partials/templates/_proxy-init.tpl
@@ -17,7 +17,7 @@ args:
 - {{ .Values.proxyInit.closeWaitTimeoutSecs | quote}}
 {{- end }}
 image: {{.Values.proxyInit.image.name}}:{{.Values.proxyInit.image.version}}
-imagePullPolicy: {{.Values.proxyInit.image.pullPolicy}}
+imagePullPolicy: {{.Values.proxyInit.image.pullPolicy | default .Values.imagePullPolicy}}
 name: linkerd-init
 {{ include "partials.resources" .Values.proxyInit.resources }}
 securityContext:
diff --git a/charts/partials/templates/_proxy.tpl b/charts/partials/templates/_proxy.tpl
index 3074d754a..0022d5163 100644
--- a/charts/partials/templates/_proxy.tpl
+++ b/charts/partials/templates/_proxy.tpl
@@ -82,7 +82,7 @@ env:
 - name: _l5d_ns
   value: {{.Values.namespace}}
 - name: _l5d_trustdomain
-  value: {{.Values.identityTrustDomain}}
+  value: {{.Values.identityTrustDomain | default .Values.clusterDomain}}
 - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
   value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
 - name: LINKERD2_PROXY_IDENTITY_SVC_NAME
@@ -90,8 +90,8 @@ env:
 - name: LINKERD2_PROXY_DESTINATION_SVC_NAME
   value: linkerd-destination.$(_l5d_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
 {{ end -}}
-image: {{.Values.proxy.image.name}}:{{.Values.proxy.image.version}}
-imagePullPolicy: {{.Values.proxy.image.pullPolicy}}
+image: {{.Values.proxy.image.name}}:{{.Values.proxy.image.version | default .Values.linkerdVersion}}
+imagePullPolicy: {{.Values.proxy.image.pullPolicy | default .Values.imagePullPolicy}}
 livenessProbe:
   httpGet:
     path: /live
diff --git a/charts/patch/templates/patch.json b/charts/patch/templates/patch.json
index c28fb6169..d088b8b96 100644
--- a/charts/patch/templates/patch.json
+++ b/charts/patch/templates/patch.json
@@ -67,7 +67,7 @@
       {{- include "partials.proxy-init" . | fromYaml | toPrettyJson | nindent 6 }}
   },
   {{- end }}
-  {{- with .Values.debugContainer }}
+  {{- if .Values.debugContainer }}
   {
     "op": "add",
     "path": "{{$prefix}}/spec/containers/-",
diff --git a/cli/cmd/options.go b/cli/cmd/options.go
index f88ae8afb..0db8b3b4c 100644
--- a/cli/cmd/options.go
+++ b/cli/cmd/options.go
@@ -503,8 +503,11 @@ func validateValues(ctx context.Context, k *k8s.KubernetesAPI, values *l5dcharts
 		}
 	}
 
-	if errs := validation.IsDNS1123Subdomain(values.IdentityTrustDomain); len(errs) > 0 {
-		return fmt.Errorf("invalid trust domain '%s': %s", values.IdentityTrustDomain, errs[0])
+	// Validate only if its not empty
+	if values.IdentityTrustDomain != "" {
+		if errs := validation.IsDNS1123Subdomain(values.IdentityTrustDomain); len(errs) > 0 {
+			return fmt.Errorf("invalid trust domain '%s': %s", values.IdentityTrustDomain, errs[0])
+		}
 	}
 
 	err := validateProxyValues(values)
diff --git a/multicluster/charts/linkerd-multicluster/templates/gateway.yaml b/multicluster/charts/linkerd-multicluster/templates/gateway.yaml
index 4ecef8d4a..310d00cf0 100644
--- a/multicluster/charts/linkerd-multicluster/templates/gateway.yaml
+++ b/multicluster/charts/linkerd-multicluster/templates/gateway.yaml
@@ -6,6 +6,7 @@ metadata:
   name: {{.Values.gatewayName}}-config
   labels:
     {{.Values.controllerComponentLabel}}: gateway
+    linkerd.io/extension: linkerd-multicluster
   annotations:
     {{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
   namespace: {{.Values.namespace}}
@@ -58,6 +59,7 @@ metadata:
     app.kubernetes.io/version: {{.Values.linkerdVersion}}
     {{.Values.controllerComponentLabel}}: gateway
     app: {{.Values.gatewayName}}
+    linkerd.io/extension: linkerd-multicluster
   name: {{.Values.gatewayName}}
   namespace: {{.Values.namespace}}
 spec:
@@ -115,6 +117,8 @@ kind: Service
 metadata:
   name: {{.Values.gatewayName}}
   namespace: {{.Values.namespace}}
+  labels:
+    linkerd.io/extension: linkerd-multicluster
   annotations:
     mirror.linkerd.io/gateway-identity: {{.Values.gatewayName}}.{{.Values.namespace}}.serviceaccount.identity.{{.Values.linkerdNamespace}}.{{.Values.identityTrustDomain}}
     mirror.linkerd.io/probe-period: "{{.Values.gatewayProbeSeconds}}"
@@ -143,4 +147,6 @@ apiVersion: v1
 metadata:
   name: {{.Values.gatewayName}}
   namespace: {{.Values.namespace}}
+  labels:
+    linkerd.io/extension: linkerd-multicluster
 {{end -}}
diff --git a/multicluster/charts/linkerd-multicluster/templates/link-crd.yaml b/multicluster/charts/linkerd-multicluster/templates/link-crd.yaml
index 1199edcc3..1447b8c8d 100644
--- a/multicluster/charts/linkerd-multicluster/templates/link-crd.yaml
+++ b/multicluster/charts/linkerd-multicluster/templates/link-crd.yaml
@@ -6,6 +6,8 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   name: links.multicluster.linkerd.io
+  labels:
+    linkerd.io/extension: linkerd-multicluster
   annotations:
     {{.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" .Values.linkerdVersion) .Values.cliVersion}}
 spec:
diff --git a/multicluster/charts/linkerd-multicluster/templates/remote-access-service-mirror-rbac.yaml b/multicluster/charts/linkerd-multicluster/templates/remote-access-service-mirror-rbac.yaml
index e19326b9d..54a6391fd 100644
--- a/multicluster/charts/linkerd-multicluster/templates/remote-access-service-mirror-rbac.yaml
+++ b/multicluster/charts/linkerd-multicluster/templates/remote-access-service-mirror-rbac.yaml
@@ -10,6 +10,8 @@ kind: ClusterRole
 metadata:
   name: {{.}}
   namespace: {{$.Values.namespace}}
+  labels:
+    linkerd.io/extension: linkerd-multicluster
   annotations:
     {{$.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" $.Values.linkerdVersion) $.Values.cliVersion}}
 rules:
@@ -26,6 +28,8 @@ kind: ServiceAccount
 metadata:
   name: {{.}}
   namespace: {{$.Values.namespace}}
+  labels:
+    linkerd.io/extension: linkerd-multicluster
   annotations:
     {{$.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" $.Values.linkerdVersion) $.Values.cliVersion}}
 ---
@@ -34,6 +38,8 @@ kind: ClusterRoleBinding
 metadata:
   name: {{.}}
   namespace: {{$.Values.namespace}}
+  labels:
+    linkerd.io/extension: linkerd-multicluster
   annotations:
     {{$.Values.createdByAnnotation}}: {{default (printf "linkerd/helm %s" $.Values.linkerdVersion) $.Values.cliVersion}}
 roleRef:
diff --git a/multicluster/cmd/uninstall.go b/multicluster/cmd/uninstall.go
index 8783671db..18da3f423 100644
--- a/multicluster/cmd/uninstall.go
+++ b/multicluster/cmd/uninstall.go
@@ -1,20 +1,19 @@
 package cmd
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"os"
 	"strings"
 
-	"github.com/linkerd/linkerd2/multicluster/static"
-	"github.com/linkerd/linkerd2/pkg/charts"
 	"github.com/linkerd/linkerd2/pkg/k8s"
+	"github.com/linkerd/linkerd2/pkg/k8s/resource"
 	mc "github.com/linkerd/linkerd2/pkg/multicluster"
 	"github.com/spf13/cobra"
-	chartloader "helm.sh/helm/v3/pkg/chart/loader"
-	"helm.sh/helm/v3/pkg/chartutil"
+
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/tools/clientcmd"
-	"sigs.k8s.io/yaml"
 )
 
 func newMulticlusterUninstallCommand() *cobra.Command {
@@ -42,12 +41,12 @@ func newMulticlusterUninstallCommand() *cobra.Command {
 				config.CurrentContext = kubeContext
 			}
 
-			k, err := k8s.NewAPI(kubeconfigPath, config.CurrentContext, impersonate, impersonateGroup, 0)
+			k8sAPI, err := k8s.NewAPI(kubeconfigPath, config.CurrentContext, impersonate, impersonateGroup, 0)
 			if err != nil {
 				return err
 			}
 
-			links, err := mc.GetLinks(cmd.Context(), k.DynamicClient)
+			links, err := mc.GetLinks(cmd.Context(), k8sAPI.DynamicClient)
 			if err != nil {
 				return err
 			}
@@ -60,42 +59,7 @@ func newMulticlusterUninstallCommand() *cobra.Command {
 				return errors.New(strings.Join(err, "\n"))
 			}
 
-			values, err := buildMulticlusterInstallValues(cmd.Context(), options)
-
-			if err != nil {
-				return err
-			}
-
-			// Render raw values and create chart config
-			rawValues, err := yaml.Marshal(values)
-			if err != nil {
-				return err
-			}
-
-			files := []*chartloader.BufferedFile{
-				{Name: chartutil.ChartfileName},
-				{Name: "templates/namespace.yaml"},
-				{Name: "templates/gateway.yaml"},
-				{Name: "templates/remote-access-service-mirror-rbac.yaml"},
-				{Name: "templates/link-crd.yaml"},
-			}
-
-			chart := &charts.Chart{
-				Name:      helmMulticlusterDefaultChartName,
-				Dir:       helmMulticlusterDefaultChartName,
-				Namespace: controlPlaneNamespace,
-				RawValues: rawValues,
-				Files:     files,
-				Fs:        static.Templates,
-			}
-			buf, err := chart.RenderNoPartials()
-			if err != nil {
-				return err
-			}
-			stdout.Write(buf.Bytes())
-			stdout.Write([]byte("---\n"))
-
-			return nil
+			return uninstallRunE(cmd.Context(), k8sAPI)
 		},
 	}
 
@@ -103,3 +67,20 @@ func newMulticlusterUninstallCommand() *cobra.Command {
 
 	return cmd
 }
+
+func uninstallRunE(ctx context.Context, k8sAPI *k8s.KubernetesAPI) error {
+
+	resources, err := resource.FetchKubernetesResources(ctx, k8sAPI,
+		metav1.ListOptions{LabelSelector: "linkerd.io/extension=linkerd-multicluster"},
+	)
+	if err != nil {
+		return err
+	}
+
+	for _, r := range resources {
+		if err := r.RenderResource(os.Stdout); err != nil {
+			return fmt.Errorf("error rendering Kubernetes resource: %v", err)
+		}
+	}
+	return nil
+}
diff --git a/viz/charts/linkerd-viz/README.md b/viz/charts/linkerd-viz/README.md
index 55ec3cf2b..ea9866637 100644
--- a/viz/charts/linkerd-viz/README.md
+++ b/viz/charts/linkerd-viz/README.md
@@ -73,12 +73,13 @@ Kubernetes: `>=1.16.0-0`
 |-----|------|---------|-------------|
 | clusterDomain | string | `"cluster.local"` | Kubernetes DNS Domain name to use |
 | createdByAnnotation | string | `"linkerd.io/created-by"` |  |
-| dashboard.UID | int | `2103` |  |
+| dashboard.UID | string | `nil` | UID for the dashboard resource |
 | dashboard.enforcedHostRegexp | string | `""` | Host header validation regex for the dashboard. See the [Linkerd documentation](https://linkerd.io/2/tasks/exposing-dashboard) for more information |
 | dashboard.image.name | string | `"web"` | Docker image name for the web instance |
-| dashboard.image.registry | string | `"ghcr.io/linkerd"` | Docker registry for the web instance |
-| dashboard.image.tag | string | `"linkerdVersionValue"` | Docker image tag for the web instance |
-| dashboard.logLevel | string | `"info"` | log level of the dashboard component |
+| dashboard.image.pullPolicy | string | defaultImagePullPolicy | Pull policy for the  web component |
+| dashboard.image.registry | string | defaultRegistry | Docker registry for the web instance |
+| dashboard.image.tag | string | linkerdVersion | Docker image tag for the web instance |
+| dashboard.logLevel | string | defaultLogLevel | log level of the dashboard component |
 | dashboard.proxy | string | `nil` |  |
 | dashboard.replicas | int | `1` | Number of replicas of dashboard |
 | dashboard.resources.cpu.limit | string | `nil` | Maximum amount of CPU units that the web container can use |
@@ -86,6 +87,7 @@ Kubernetes: `>=1.16.0-0`
 | dashboard.resources.memory.limit | string | `nil` | Maximum amount of memory that web container can use |
 | dashboard.resources.memory.request | string | `nil` | Amount of memory that the web container requests |
 | dashboard.restrictPrivileges | bool | `false` | Restrict the Linkerd Dashboard's default privileges to disallow Tap and Check |
+| defaultImagePullPolicy | string | `"IfNotPresent"` | Docker imagePullPolicy for all viz components |
 | defaultLogLevel | string | `"info"` | Log level for all the viz components |
 | defaultRegistry | string | `"ghcr.io/linkerd"` | Docker registry for all viz components |
 | defaultUID | int | `2103` | UID for all the viz components |
@@ -93,26 +95,27 @@ Kubernetes: `>=1.16.0-0`
 | extensionAnnotation | string | `"linkerd.io/extension"` |  |
 | grafana.enabled | bool | `true` | toggle field to enable or disable grafana |
 | grafana.image.name | string | `"grafana"` | Docker image name for the grafana instance |
-| grafana.image.registry | string | `"ghcr.io/linkerd"` | Docker registry for the grafana instance |
-| grafana.image.tag | string | `"linkerdVersionValue"` | Docker image tag for the grafana instance |
+| grafana.image.pullPolicy | string | defaultImagePullPolicy | Pull policy for the grafana instance |
+| grafana.image.registry | string | defaultRegistry | Docker registry for the grafana instance |
+| grafana.image.tag | string | linkerdVersion | Docker image tag for the grafana instance |
 | grafana.proxy | string | `nil` |  |
 | grafana.resources.cpu.limit | string | `nil` | Maximum amount of CPU units that the grafana container can use |
 | grafana.resources.cpu.request | string | `nil` | Amount of CPU units that the grafana container requests |
 | grafana.resources.memory.limit | string | `nil` | Maximum amount of memory that grafana container can use |
 | grafana.resources.memory.request | string | `nil` | Amount of memory that the grafana container requests |
 | grafanaUrl | string | `""` | url of external grafana instance with reverse proxy configured. |
-| identityTrustDomain | string | `"cluster.local"` | Trust domain used for identity |
+| identityTrustDomain | string | clusterDomain | Trust domain used for identity |
 | imagePullSecrets | list | `[]` | For Private docker registries, authentication is needed.  Registry secrets are applied to the respective service accounts |
 | installNamespace | bool | `true` | Set to false when installing in a custom namespace. |
 | jaegerUrl | string | `""` | url of external jaeger instance Set this to `jaeger.linkerd-jaeger.svc.<clusterDomain>` if you plan to use jaeger extension |
 | linkerdNamespace | string | `"linkerd"` | Namespace of the Linkerd core control-plane install |
 | linkerdVersion | string | `"linkerdVersionValue"` | control plane version. See Proxy section for proxy version |
-| metricsAPI.UID | int | `2103` |  |
+| metricsAPI.UID | string | `nil` | UID for the metrics-api resource |
 | metricsAPI.image.name | string | `"metrics-api"` | Docker image name for the metrics-api component |
-| metricsAPI.image.pullPolicy | string | `"Always"` | Pull policy for the metrics-api component |
-| metricsAPI.image.registry | string | `"ghcr.io/linkerd"` | Docker registry for the metrics-api component |
-| metricsAPI.image.tag | string | `"linkerdVersionValue"` | Docker image tag for the metrics-api component |
-| metricsAPI.logLevel | string | `"info"` | log level of the metrics-api component |
+| metricsAPI.image.pullPolicy | string | defaultImagePullPolicy | Pull policy for the metrics-api component |
+| metricsAPI.image.registry | string | defaultRegistry | Docker registry for the metrics-api component |
+| metricsAPI.image.tag | string | linkerdVersion | Docker image tag for the metrics-api component |
+| metricsAPI.logLevel | string | defaultLogLevel | log level of the metrics-api component |
 | metricsAPI.proxy | string | `nil` |  |
 | metricsAPI.replicas | int | `1` | number of replicas of the metrics-api component |
 | metricsAPI.resources.cpu.limit | string | `nil` | Maximum amount of CPU units that the metrics-api container can use |
@@ -123,13 +126,14 @@ Kubernetes: `>=1.16.0-0`
 | nodeSelector | object | `{"beta.kubernetes.io/os":"linux"}` | NodeSelector section, See the [K8S documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) for more information |
 | prometheus.alertRelabelConfigs | string | `nil` | Alert relabeling is applied to alerts before they are sent to the Alertmanager. |
 | prometheus.alertmanagers | string | `nil` | Alertmanager instances the Prometheus server sends alerts to configured via the static_configs parameter. |
-| prometheus.args | object | `{"config.file":"/etc/prometheus/prometheus.yml","log.level":"info","storage.tsdb.path":"/data","storage.tsdb.retention.time":"6h"}` | Command line options for Prometheus binary |
+| prometheus.args | object | `{"config.file":"/etc/prometheus/prometheus.yml","storage.tsdb.path":"/data","storage.tsdb.retention.time":"6h"}` | Command line options for Prometheus binary |
 | prometheus.enabled | bool | `true` | toggle field to enable or disable prometheus |
 | prometheus.globalConfig | object | `{"evaluation_interval":"10s","scrape_interval":"10s","scrape_timeout":"10s"}` | The global configuration specifies parameters that are valid in all other configuration contexts. |
 | prometheus.image.name | string | `"prometheus"` | Docker image name for the prometheus instance |
-| prometheus.image.pullPolicy | string | `"Always"` | Pull policy for the prometheus instance |
+| prometheus.image.pullPolicy | string | defaultImagePullPolicy | Pull policy for the prometheus instance |
 | prometheus.image.registry | string | `"prom"` | Docker registry for the prometheus instance |
 | prometheus.image.tag | string | `"v2.19.3"` | Docker image tag for the prometheus instance |
+| prometheus.logLevel | string | defaultLogLevel | log level of the prometheus instance |
 | prometheus.proxy | string | `nil` |  |
 | prometheus.remoteWrite | string | `nil` | Allows transparently sending samples to an endpoint. Mostly used for long term storage. |
 | prometheus.resources.cpu.limit | string | `nil` | Maximum amount of CPU units that the prometheus container can use |
@@ -141,29 +145,31 @@ Kubernetes: `>=1.16.0-0`
 | prometheus.sidecarContainers | string | `nil` | A sidecarContainers section specifies a list of secondary containers to run in the prometheus pod e.g. to export data to non-prometheus systems |
 | prometheusUrl | string | `""` | url of external prometheus instance |
 | proxyInjectAnnotation | string | `"linkerd.io/inject"` |  |
-| tap.UID | int | `2103` |  |
+| tap.UID | string | `nil` | UID for the dashboard resource |
 | tap.caBundle | string | `""` | Bundle of CA certificates for Tap component. If not provided then Helm will use the certificate generated  for `tap.crtPEM`. If `tap.externalSecret` is set to true, this value must be set, as no certificate will be generated. |
 | tap.crtPEM | string | `""` | Certificate for the Tap component. If not provided then Helm will generate one. |
 | tap.externalSecret | bool | `false` | 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). |
 | tap.image.name | string | `"tap"` | Docker image name for the tap instance |
-| tap.image.registry | string | `"ghcr.io/linkerd"` | Docker registry for the tap instance |
-| tap.image.tag | string | `"linkerdVersionValue"` | Docker image tag for the tap instance |
+| tap.image.pullPolicy | string | defaultImagePullPolicy | Pull policy for the tap component |
+| tap.image.registry | string | defaultRegistry | Docker registry for the tap instance |
+| tap.image.tag | string | linkerdVersion | Docker image tag for the tap instance |
 | tap.keyPEM | string | `""` | Certificate key for Tap component. If not provided then Helm will generate one. |
-| tap.logLevel | string | `"info"` | log level of the tap component |
+| tap.logLevel | string | defaultLogLevel | log level of the tap component |
 | tap.proxy | string | `nil` |  |
 | tap.replicas | int | `1` | Number of tap component replicas |
 | tap.resources.cpu.limit | string | `nil` | Maximum amount of CPU units that the tap container can use |
 | tap.resources.cpu.request | string | `nil` | Amount of CPU units that the tap container requests |
 | tap.resources.memory.limit | string | `nil` | Maximum amount of memory that tap container can use |
 | tap.resources.memory.request | string | `nil` | Amount of memory that the tap container requests |
-| tapInjector.UID | int | `2103` |  |
+| tapInjector.UID | string | `nil` |  |
 | tapInjector.caBundle | string | `""` | Bundle of CA certificates for the tapInjector. If not provided then Helm will use the certificate generated  for `tapInjector.crtPEM`. If `tapInjector.externalSecret` is set to true, this value must be set, as no certificate will be generated. |
 | tapInjector.crtPEM | string | `""` | Certificate for the tapInjector. If not provided then Helm will generate one. |
 | tapInjector.externalSecret | bool | `false` | Do not create a secret resource for the tapInjector webhook. If this is set to `true`, the value `tapInjector.caBundle` must be set (see below) |
 | tapInjector.failurePolicy | string | `"Ignore"` |  |
 | tapInjector.image.name | string | `"tap"` | Docker image name for the tapInjector instance |
-| tapInjector.image.registry | string | `"ghcr.io/linkerd"` | Docker registry for the tapInjector instance |
-| tapInjector.image.tag | string | `"linkerdVersionValue"` | Docker image tag for the tapInjector instance |
+| tapInjector.image.pullPolicy | string | defaultImagePullPolicy | Pull policy for the tapInjector component |
+| tapInjector.image.registry | string | defaultRegistry | Docker registry for the tapInjector instance |
+| tapInjector.image.tag | string | linkerdVersion | Docker image tag for the tapInjector instance |
 | tapInjector.keyPEM | string | `""` | Certificate key for the tapInjector. If not provided then Helm will generate one. |
 | tapInjector.logLevel | string | defaultLogLevel | log level of the tapInjector |
 | tapInjector.namespaceSelector | string | `nil` |  |
diff --git a/viz/charts/linkerd-viz/templates/grafana.yaml b/viz/charts/linkerd-viz/templates/grafana.yaml
index b5fe3af4c..459966407 100644
--- a/viz/charts/linkerd-viz/templates/grafana.yaml
+++ b/viz/charts/linkerd-viz/templates/grafana.yaml
@@ -129,8 +129,8 @@ spec:
         # see https://github.com/grafana/grafana/issues/20096
         - name: GODEBUG
           value: netdns=go
-        image: {{.Values.grafana.image.registry}}/{{.Values.grafana.image.name}}:{{.Values.grafana.image.tag}}
-        imagePullPolicy: {{.Values.imagePullPolicy}}
+        image: {{.Values.grafana.image.registry | default .Values.defaultRegistry}}/{{.Values.grafana.image.name}}:{{.Values.grafana.image.tag | default .Values.linkerdVersion}}
+        imagePullPolicy: {{.Values.grafana.image.pullPolicy | default .Values.defaultImagePullPolicy}}
         livenessProbe:
           httpGet:
             path: /api/health
diff --git a/viz/charts/linkerd-viz/templates/metrics-api.yaml b/viz/charts/linkerd-viz/templates/metrics-api.yaml
index 5d70980d5..214f72d91 100644
--- a/viz/charts/linkerd-viz/templates/metrics-api.yaml
+++ b/viz/charts/linkerd-viz/templates/metrics-api.yaml
@@ -68,7 +68,7 @@ spec:
       containers:
       - args:
         - -controller-namespace={{.Values.linkerdNamespace}}
-        - -log-level={{.Values.metricsAPI.logLevel}}
+        - -log-level={{.Values.metricsAPI.logLevel | default .Values.defaultLogLevel}}
         - -cluster-domain={{.Values.clusterDomain}}
         {{- if .Values.prometheusUrl }}
         - -prometheus-url={{.Values.prometheusUrl}}
@@ -77,8 +77,8 @@ spec:
         {{- else }}
         {{ fail "Please enable `linkerd-prometheus` or provide `prometheusUrl` for the viz extension to function properly"}}
         {{- end }}
-        image: {{.Values.metricsAPI.image.registry}}/{{.Values.metricsAPI.image.name}}:{{.Values.metricsAPI.image.tag}}
-        imagePullPolicy: {{.Values.metricsAPI.pullPolicy}}
+        image: {{.Values.metricsAPI.image.registry | default .Values.defaultRegistry}}/{{.Values.metricsAPI.image.name}}:{{.Values.metricsAPI.image.tag | default .Values.linkerdVersion}}
+        imagePullPolicy: {{.Values.metricsAPI.image.pullPolicy | default .Values.defaultImagePullPolicy}}
         livenessProbe:
           httpGet:
             path: /ping
@@ -99,5 +99,5 @@ spec:
         {{- include "partials.resources" .Values.metricsAPI.resources | nindent 8 }}
         {{- end }}
         securityContext:
-          runAsUser: {{.Values.metricsAPI.UID}}
+          runAsUser: {{.Values.metricsAPI.UID | default .Values.defaultUID}}
       serviceAccountName: linkerd-metrics-api
diff --git a/viz/charts/linkerd-viz/templates/prometheus.yaml b/viz/charts/linkerd-viz/templates/prometheus.yaml
index 4f885fed7..b5142dfc4 100644
--- a/viz/charts/linkerd-viz/templates/prometheus.yaml
+++ b/viz/charts/linkerd-viz/templates/prometheus.yaml
@@ -242,11 +242,12 @@ spec:
       {{- toYaml .Values.prometheus.sidecarContainers | trim | nindent 6 }}
       {{- end}}
       - args:
+        - --log.level={{.Values.prometheus.logLevel | default .Values.defaultLogLevel}}
         {{- range $key, $value := .Values.prometheus.args}}
         - --{{ $key }}{{ if $value }}={{ $value }}{{ end }}
         {{- end }}
         image: {{.Values.prometheus.image.registry}}/{{.Values.prometheus.image.name}}:{{.Values.prometheus.image.tag}}
-        imagePullPolicy: {{.Values.prometheus.imagepullPolicy}}
+        imagePullPolicy: {{.Values.prometheus.image.pullPolicy | default .Values.defaultImagePullPolicy}}
         livenessProbe:
           httpGet:
             path: /-/healthy
diff --git a/viz/charts/linkerd-viz/templates/tap-injector.yaml b/viz/charts/linkerd-viz/templates/tap-injector.yaml
index 21a1cfa1f..73300f703 100644
--- a/viz/charts/linkerd-viz/templates/tap-injector.yaml
+++ b/viz/charts/linkerd-viz/templates/tap-injector.yaml
@@ -72,8 +72,8 @@ spec:
         - injector
         - -tap-service-name=linkerd-tap.{{.Values.namespace}}.serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - -log-level={{.Values.tapInjector.logLevel | default .Values.defaultLogLevel}}
-        image: {{.Values.tapInjector.image.registry}}/{{.Values.tapInjector.image.name}}:{{.Values.tapInjector.image.tag}}
-        imagePullPolicy: {{.Values.tapInjector.image.pullPolicy}}
+        image: {{.Values.tapInjector.image.registry | default .Values.defaultRegistry}}/{{.Values.tapInjector.image.name}}:{{.Values.tapInjector.image.tag | default .Values.linkerdVersion}}
+        imagePullPolicy: {{.Values.tapInjector.image.pullPolicy | default .Values.defaultImagePullPolicy}}
         livenessProbe:
           httpGet:
             path: /ping
@@ -94,7 +94,7 @@ spec:
         {{- include "partials.resources" .Values.tapInjector.resources | nindent 8 }}
         {{- end }}
         securityContext:
-          runAsUser: {{.Values.tapInjector.UID}}
+          runAsUser: {{.Values.tapInjector.UID | default .Values.defaultUID}}
         volumeMounts:
         - mountPath: /var/run/linkerd/tls
           name: tls
diff --git a/viz/charts/linkerd-viz/templates/tap.yaml b/viz/charts/linkerd-viz/templates/tap.yaml
index 903e262ee..b107d9aa9 100644
--- a/viz/charts/linkerd-viz/templates/tap.yaml
+++ b/viz/charts/linkerd-viz/templates/tap.yaml
@@ -81,10 +81,10 @@ spec:
       - args:
         - api
         - -api-namespace={{.Values.linkerdNamespace}}
-        - -log-level={{.Values.tap.logLevel}}
-        - -identity-trust-domain={{.Values.identityTrustDomain}}
-        image: {{.Values.tap.image.registry}}/{{.Values.tap.image.name}}:{{.Values.tap.image.tag}}
-        imagePullPolicy: {{.Values.tap.image.pullPolicy}}
+        - -log-level={{.Values.tap.logLevel | default .Values.defaultLogLevel}}
+        - -identity-trust-domain={{.Values.identityTrustDomain | default .Values.clusterDomain}}
+        image: {{.Values.tap.image.registry | default .Values.defaultRegistry}}/{{.Values.tap.image.name}}:{{.Values.tap.image.tag | default .Values.linkerdVersion}}
+        imagePullPolicy: {{.Values.tap.image.pullPolicy | default .Values.defaultImagePullPolicy}}
         livenessProbe:
           httpGet:
             path: /ping
@@ -107,7 +107,7 @@ spec:
         {{- include "partials.resources" .Values.tap.resources | nindent 8 }}
         {{- end }}
         securityContext:
-          runAsUser: {{.Values.tap.UID}}
+          runAsUser: {{.Values.tap.UID | default .Values.defaultUID}}
         volumeMounts:
         - mountPath: /var/run/linkerd/tls
           name: tls
diff --git a/viz/charts/linkerd-viz/templates/web.yaml b/viz/charts/linkerd-viz/templates/web.yaml
index c34054f7c..89901271b 100644
--- a/viz/charts/linkerd-viz/templates/web.yaml
+++ b/viz/charts/linkerd-viz/templates/web.yaml
@@ -80,7 +80,7 @@ spec:
         {{- end}}
         - -controller-namespace={{.Values.linkerdNamespace}}
         - -viz-namespace={{.Values.namespace}}
-        - -log-level={{.Values.dashboard.logLevel}}
+        - -log-level={{.Values.dashboard.logLevel | default .Values.defaultLogLevel}}
         {{- if .Values.dashboard.enforcedHostRegexp }}
         - -enforced-host={{.Values.dashboard.enforcedHostRegexp}}
         {{- else -}}
@@ -88,8 +88,8 @@ spec:
         {{- $hostAbbrev := replace "." "\\." (printf "linkerd-web.%s.svc" .Values.namespace) }}
         - -enforced-host=^(localhost|127\.0\.0\.1|{{ $hostFull }}|{{ $hostAbbrev }}|\[::1\])(:\d+)?$
         {{- end}}
-        image: {{.Values.dashboard.image.registry}}/{{.Values.dashboard.image.name}}:{{.Values.dashboard.image.tag}}
-        imagePullPolicy: {{.Values.dashboard.image.pullPolicy}}
+        image: {{.Values.dashboard.image.registry | default .Values.defaultRegistry}}/{{.Values.dashboard.image.name}}:{{.Values.dashboard.image.tag | default .Values.linkerdVersion}}
+        imagePullPolicy: {{.Values.dashboard.image.pullPolicy | default .Values.defaultImagePullPolicy}}
         livenessProbe:
           httpGet:
             path: /ping
@@ -110,5 +110,5 @@ spec:
         {{- include "partials.resources" .Values.dashboard.resources | nindent 8 }}
         {{- end }}
         securityContext:
-          runAsUser: {{.Values.dashboard.UID}}
+          runAsUser: {{.Values.dashboard.UID | default .Values.defaultUID}}
       serviceAccountName: linkerd-web
diff --git a/viz/charts/linkerd-viz/values.yaml b/viz/charts/linkerd-viz/values.yaml
index a8b8eb99e..7edde4289 100644
--- a/viz/charts/linkerd-viz/values.yaml
+++ b/viz/charts/linkerd-viz/values.yaml
@@ -5,22 +5,25 @@
 # Fields that should be common with the core control plane
 
 # -- control plane version. See Proxy section for proxy version
-linkerdVersion: &linkerd_version linkerdVersionValue
+linkerdVersion: linkerdVersionValue
 # -- Kubernetes DNS Domain name to use
-clusterDomain: &cluster_domain cluster.local
+clusterDomain: cluster.local
 # -- Trust domain used for identity
-identityTrustDomain: *cluster_domain
+# @default -- clusterDomain
+identityTrustDomain: ""
 #  Annotation labels. Do not edit.
 createdByAnnotation: linkerd.io/created-by
 proxyInjectAnnotation: linkerd.io/inject
 extensionAnnotation: linkerd.io/extension
 
 # -- Docker registry for all viz components
-defaultRegistry: &registry ghcr.io/linkerd
+defaultRegistry: ghcr.io/linkerd
+# -- Docker imagePullPolicy for all viz components
+defaultImagePullPolicy: IfNotPresent
 # -- Log level for all the viz components
-defaultLogLevel: &log_level info
+defaultLogLevel: info
 # -- UID for all the viz components
-defaultUID: &uid 2103
+defaultUID: 2103
 
 # -- Namespace of the Linkerd core control-plane install
 linkerdNamespace: linkerd
@@ -64,16 +67,20 @@ metricsAPI:
   # -- number of replicas of the metrics-api component
   replicas: 1
   # -- log level of the metrics-api component
-  logLevel: *log_level
+  # @default -- defaultLogLevel
+  logLevel: ""
   image:
     # -- Docker registry for the metrics-api component
-    registry: ghcr.io/linkerd
+    # @default -- defaultRegistry
+    registry: ""
     # -- Docker image name for the metrics-api component
     name: metrics-api
     # -- Docker image tag for the metrics-api component
-    tag: *linkerd_version
+    # @default -- linkerdVersion
+    tag: ""
     # -- Pull policy for the metrics-api component
-    pullPolicy: Always
+    # @default -- defaultImagePullPolicy
+    pullPolicy: ""
 
   resources:
     cpu:
@@ -92,21 +99,28 @@ metricsAPI:
     # into the metrics-api component
     # resources:
 
-  UID: *uid
+  # -- UID for the metrics-api resource
+  UID:
 
 # tap configuration
 tap:
     # -- Number of tap component replicas
   replicas: 1
   # -- log level of the tap component
-  logLevel: *log_level
+  # @default -- defaultLogLevel
+  logLevel: ""
   image:
     # -- Docker registry for the tap instance
-    registry: *registry
+    # @default -- defaultRegistry
+    registry: ""
     # -- Docker image name for the tap instance
     name: tap
     # -- Docker image tag for the tap instance
-    tag: *linkerd_version
+    # @default -- linkerdVersion
+    tag: ""
+    # -- Pull policy for the tap component
+    # @default -- defaultImagePullPolicy
+    pullPolicy: ""
   # -- 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).
   externalSecret: false
@@ -141,8 +155,8 @@ tap:
     # into the tap component
     # resources:
 
-  # UID for the dashboard resource
-  UID: *uid
+  # -- UID for the dashboard resource
+  UID:
 
 # tapInjector configuration
 tapInjector:
@@ -153,11 +167,17 @@ tapInjector:
   logLevel: ""
   image:
     # -- Docker registry for the tapInjector instance
-    registry: *registry
+    # @default -- defaultRegistry
+    registry: ""
     # -- Docker image name for the tapInjector instance
     name: tap
     # -- Docker image tag for the tapInjector instance
-    tag: *linkerd_version
+    # @default -- linkerdVersion
+    tag: ""
+    # -- Pull policy for the tapInjector component
+    # @default -- defaultImagePullPolicy
+    pullPolicy: ""
+
   namespaceSelector:
     # matchExpressions:
     # - key: runlevel
@@ -166,7 +186,8 @@ tapInjector:
   objectSelector:
     # matchLabels:
     #   foo: bar
-  UID: *uid
+  # -- UID for the tapInjector resource
+  UID: 
   failurePolicy: Ignore
   resources:
     cpu:
@@ -206,17 +227,23 @@ dashboard:
   # -- Number of replicas of dashboard
   replicas: 1
   # -- log level of the dashboard component
-  logLevel: *log_level
+  # @default -- defaultLogLevel
+  logLevel: ""
   image:
     # -- Docker registry for the web instance
-    registry: *registry
+    # @default -- defaultRegistry
+    registry: ""
     # -- Docker image name for the web instance
     name: web
     # -- Docker image tag for the web instance
-    tag: *linkerd_version
+    # @default -- linkerdVersion
+    tag: ""
+    # -- Pull policy for the  web component
+    # @default -- defaultImagePullPolicy
+    pullPolicy: ""
 
-  # UID for the dashboard resource
-  UID: *uid
+  # -- UID for the dashboard resource
+  UID:
 
   # -- Restrict the Linkerd Dashboard's default privileges to disallow Tap and Check
   restrictPrivileges: false
@@ -247,11 +274,16 @@ grafana:
   enabled: true
   image:
     # -- Docker registry for the grafana instance
-    registry: *registry
+    # @default -- defaultRegistry
+    registry: ""
     # -- Docker image name for the grafana instance
     name: grafana
     # -- Docker image tag for the grafana instance
-    tag: *linkerd_version
+    # @default -- linkerdVersion
+    tag: ""
+    # -- Pull policy for the grafana instance
+    # @default -- defaultImagePullPolicy
+    pullPolicy: ""
 
   resources:
     cpu:
@@ -281,14 +313,17 @@ prometheus:
     # -- Docker image tag for the prometheus instance
     tag: v2.19.3
     # -- Pull policy for the prometheus instance
-    pullPolicy: Always
+    # @default -- defaultImagePullPolicy
+    pullPolicy: ""
 
+  # -- log level of the prometheus instance
+  # @default -- defaultLogLevel
+  logLevel: ""
   # -- Command line options for Prometheus binary
   args:
     storage.tsdb.path: /data
     storage.tsdb.retention.time: 6h
     config.file: /etc/prometheus/prometheus.yml
-    log.level: *log_level
   # -- The global configuration specifies parameters that are valid in all other
   # configuration contexts.
   globalConfig:
diff --git a/web/app/package.json b/web/app/package.json
index 3601f807c..43eb0f8fa 100644
--- a/web/app/package.json
+++ b/web/app/package.json
@@ -10,7 +10,7 @@
     "@fortawesome/react-fontawesome": "0.1.9",
     "@lingui/macro": "2.9.2",
     "@lingui/react": "2.9.2",
-    "@material-ui/core": "4.9.11",
+    "@material-ui/core": "4.11.3",
     "@material-ui/icons": "4.9.1",
     "@material-ui/lab": "^4.0.0-alpha.50",
     "classnames": "2.2.6",
diff --git a/web/app/yarn.lock b/web/app/yarn.lock
index 8ece898af..99efe41e4 100644
--- a/web/app/yarn.lock
+++ b/web/app/yarn.lock
@@ -1288,24 +1288,23 @@
     hoist-non-react-statics "3.3.0"
     prop-types "^15.7.2"
 
-"@material-ui/core@4.9.11":
-  version "4.9.11"
-  resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.11.tgz#02f45f4dbea6db191fdc0d993323d64cfae613fd"
-  integrity sha512-S2Ha9GpTxzl29XMeMc8dQX2pj97yApNzuhe/23If53fMdg5Fmd3SgbE1bMbyXeKhxwtXZjOFxd0vU+W/sez8Ew==
+"@material-ui/core@4.11.3":
+  version "4.11.3"
+  resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.3.tgz#f22e41775b0bd075e36a7a093d43951bf7f63850"
+  integrity sha512-Adt40rGW6Uds+cAyk3pVgcErpzU/qxc7KBR94jFHBYretU4AtWZltYcNsbeMn9tXL86jjVL1kuGcIHsgLgFGRw==
   dependencies:
     "@babel/runtime" "^7.4.4"
-    "@material-ui/react-transition-group" "^4.2.0"
-    "@material-ui/styles" "^4.9.10"
-    "@material-ui/system" "^4.9.10"
-    "@material-ui/types" "^5.0.1"
-    "@material-ui/utils" "^4.9.6"
+    "@material-ui/styles" "^4.11.3"
+    "@material-ui/system" "^4.11.3"
+    "@material-ui/types" "^5.1.0"
+    "@material-ui/utils" "^4.11.2"
     "@types/react-transition-group" "^4.2.0"
     clsx "^1.0.4"
     hoist-non-react-statics "^3.3.2"
-    popper.js "^1.16.1-lts"
+    popper.js "1.16.1-lts"
     prop-types "^15.7.2"
-    react-is "^16.8.0"
-    react-transition-group "^4.3.0"
+    react-is "^16.8.0 || ^17.0.0"
+    react-transition-group "^4.4.0"
 
 "@material-ui/icons@4.9.1":
   version "4.9.1"
@@ -1325,20 +1324,10 @@
     prop-types "^15.7.2"
     react-is "^16.8.0 || ^17.0.0"
 
-"@material-ui/react-transition-group@^4.2.0":
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/@material-ui/react-transition-group/-/react-transition-group-4.3.0.tgz#92529142addb5cc179dbf42d246c7e3fe4d6104b"
-  integrity sha512-CwQ0aXrlUynUTY6sh3UvKuvye1o92en20VGAs6TORnSxUYeRmkX8YeTUN3lAkGiBX1z222FxLFO36WWh6q73rQ==
-  dependencies:
-    "@babel/runtime" "^7.5.5"
-    dom-helpers "^5.0.1"
-    loose-envify "^1.4.0"
-    prop-types "^15.6.2"
-
-"@material-ui/styles@^4.9.10":
-  version "4.11.2"
-  resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.2.tgz#e70558be3f41719e8c0d63c7a3c9ae163fdc84cb"
-  integrity sha512-xbItf8zkfD3FuGoD9f2vlcyPf9jTEtj9YTJoNNV+NMWaSAHXgrW6geqRoo/IwBuMjqpwqsZhct13e2nUyU9Ljw==
+"@material-ui/styles@^4.11.3":
+  version "4.11.3"
+  resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.11.3.tgz#1b8d97775a4a643b53478c895e3f2a464e8916f2"
+  integrity sha512-HzVzCG+PpgUGMUYEJ2rTEmQYeonGh41BYfILNFb/1ueqma+p1meSdu4RX6NjxYBMhf7k+jgfHFTTz+L1SXL/Zg==
   dependencies:
     "@babel/runtime" "^7.4.4"
     "@emotion/hash" "^0.8.0"
@@ -1347,32 +1336,32 @@
     clsx "^1.0.4"
     csstype "^2.5.2"
     hoist-non-react-statics "^3.3.2"
-    jss "^10.0.3"
-    jss-plugin-camel-case "^10.0.3"
-    jss-plugin-default-unit "^10.0.3"
-    jss-plugin-global "^10.0.3"
-    jss-plugin-nested "^10.0.3"
-    jss-plugin-props-sort "^10.0.3"
-    jss-plugin-rule-value-function "^10.0.3"
-    jss-plugin-vendor-prefixer "^10.0.3"
+    jss "^10.5.1"
+    jss-plugin-camel-case "^10.5.1"
+    jss-plugin-default-unit "^10.5.1"
+    jss-plugin-global "^10.5.1"
+    jss-plugin-nested "^10.5.1"
+    jss-plugin-props-sort "^10.5.1"
+    jss-plugin-rule-value-function "^10.5.1"
+    jss-plugin-vendor-prefixer "^10.5.1"
     prop-types "^15.7.2"
 
-"@material-ui/system@^4.9.10":
-  version "4.11.2"
-  resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.2.tgz#7f0a754bba3673ed5fdbfa02fe438096c104b1f6"
-  integrity sha512-BELFJEel5E+5DMiZb6XXT3peWRn6UixRvBtKwSxqntmD0+zwbbfCij6jtGwwdJhN1qX/aXrKu10zX31GBaeR7A==
+"@material-ui/system@^4.11.3":
+  version "4.11.3"
+  resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.11.3.tgz#466bc14c9986798fd325665927c963eb47cc4143"
+  integrity sha512-SY7otguNGol41Mu2Sg6KbBP1ZRFIbFLHGK81y4KYbsV2yIcaEPOmsCK6zwWlp+2yTV3J/VwT6oSBARtGIVdXPw==
   dependencies:
     "@babel/runtime" "^7.4.4"
     "@material-ui/utils" "^4.11.2"
     csstype "^2.5.2"
     prop-types "^15.7.2"
 
-"@material-ui/types@^5.0.1", "@material-ui/types@^5.1.0":
+"@material-ui/types@^5.1.0":
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2"
   integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==
 
-"@material-ui/utils@^4.11.2", "@material-ui/utils@^4.9.6":
+"@material-ui/utils@^4.11.2":
   version "4.11.2"
   resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.11.2.tgz#f1aefa7e7dff2ebcb97d31de51aecab1bb57540a"
   integrity sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==
@@ -7317,70 +7306,70 @@ jsprim@^1.2.2:
     json-schema "0.2.3"
     verror "1.10.0"
 
-jss-plugin-camel-case@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.0.tgz#4b0a9c85e65e5eb72cbfba59373686c604d88f72"
-  integrity sha512-GSjPL0adGAkuoqeYiXTgO7PlIrmjv5v8lA6TTBdfxbNYpxADOdGKJgIEkffhlyuIZHlPuuiFYTwUreLUmSn7rg==
+jss-plugin-camel-case@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.1.tgz#427b24a9951b4c2eaa7e3d5267acd2e00b0934f9"
+  integrity sha512-9+oymA7wPtswm+zxVti1qiowC5q7bRdCJNORtns2JUj/QHp2QPXYwSNRD8+D2Cy3/CEMtdJzlNnt5aXmpS6NAg==
   dependencies:
     "@babel/runtime" "^7.3.1"
     hyphenate-style-name "^1.0.3"
-    jss "10.5.0"
+    jss "10.5.1"
 
-jss-plugin-default-unit@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.0.tgz#e9f2e89741b0118ba15d52b4c13bda2b27262373"
-  integrity sha512-rsbTtZGCMrbcb9beiDd+TwL991NGmsAgVYH0hATrYJtue9e+LH/Gn4yFD1ENwE+3JzF3A+rPnM2JuD9L/SIIWw==
+jss-plugin-default-unit@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.1.tgz#2be385d71d50aee2ee81c2a9ac70e00592ed861b"
+  integrity sha512-D48hJBc9Tj3PusvlillHW8Fz0y/QqA7MNmTYDQaSB/7mTrCZjt7AVRROExoOHEtd2qIYKOYJW3Jc2agnvsXRlQ==
   dependencies:
     "@babel/runtime" "^7.3.1"
-    jss "10.5.0"
+    jss "10.5.1"
 
-jss-plugin-global@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.5.0.tgz#eb357ccd35cb4894277fb2117a78d1e498668ad6"
-  integrity sha512-FZd9+JE/3D7HMefEG54fEC0XiQ9rhGtDHAT/ols24y8sKQ1D5KIw6OyXEmIdKFmACgxZV2ARQ5pAUypxkk2IFQ==
+jss-plugin-global@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.5.1.tgz#0e1793dea86c298360a7e2004721351653c7e764"
+  integrity sha512-jX4XpNgoaB8yPWw/gA1aPXJEoX0LNpvsROPvxlnYe+SE0JOhuvF7mA6dCkgpXBxfTWKJsno7cDSCgzHTocRjCQ==
   dependencies:
     "@babel/runtime" "^7.3.1"
-    jss "10.5.0"
+    jss "10.5.1"
 
-jss-plugin-nested@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.5.0.tgz#790c506432a23a63c71ceb5044e2ac85f0958702"
-  integrity sha512-ejPlCLNlEGgx8jmMiDk/zarsCZk+DV0YqXfddpgzbO9Toamo0HweCFuwJ3ZO40UFOfqKwfpKMVH/3HUXgxkTMg==
+jss-plugin-nested@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.5.1.tgz#8753a80ad31190fb6ac6fdd39f57352dcf1295bb"
+  integrity sha512-xXkWKOCljuwHNjSYcXrCxBnjd8eJp90KVFW1rlhvKKRXnEKVD6vdKXYezk2a89uKAHckSvBvBoDGsfZrldWqqQ==
   dependencies:
     "@babel/runtime" "^7.3.1"
-    jss "10.5.0"
+    jss "10.5.1"
     tiny-warning "^1.0.2"
 
-jss-plugin-props-sort@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.0.tgz#5bcc3bd8e68cd3e2dafb47d67db28fd5a4fcf102"
-  integrity sha512-kTLRvrOetFKz5vM88FAhLNeJIxfjhCepnvq65G7xsAQ/Wgy7HwO1BS/2wE5mx8iLaAWC6Rj5h16mhMk9sKdZxg==
+jss-plugin-props-sort@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.1.tgz#ab1c167fd2d4506fb6a1c1d66c5f3ef545ff1cd8"
+  integrity sha512-t+2vcevNmMg4U/jAuxlfjKt46D/jHzCPEjsjLRj/J56CvP7Iy03scsUP58Iw8mVnaV36xAUZH2CmAmAdo8994g==
   dependencies:
     "@babel/runtime" "^7.3.1"
-    jss "10.5.0"
+    jss "10.5.1"
 
-jss-plugin-rule-value-function@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.0.tgz#60ee8240dfe60418e1ba4729adee893cbe9be7a3"
-  integrity sha512-jXINGr8BSsB13JVuK274oEtk0LoooYSJqTBCGeBu2cG/VJ3+4FPs1gwLgsq24xTgKshtZ+WEQMVL34OprLidRA==
+jss-plugin-rule-value-function@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.1.tgz#37f4030523fb3032c8801fab48c36c373004de7e"
+  integrity sha512-3gjrSxsy4ka/lGQsTDY8oYYtkt2esBvQiceGBB4PykXxHoGRz14tbCK31Zc6DHEnIeqsjMUGbq+wEly5UViStQ==
   dependencies:
     "@babel/runtime" "^7.3.1"
-    jss "10.5.0"
+    jss "10.5.1"
     tiny-warning "^1.0.2"
 
-jss-plugin-vendor-prefixer@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.0.tgz#01f04cfff31f43f153f5d71972f5800b10a2eb84"
-  integrity sha512-rux3gmfwDdOKCLDx0IQjTwTm03IfBa+Rm/hs747cOw5Q7O3RaTUIMPKjtVfc31Xr/XI9Abz2XEupk1/oMQ7zRA==
+jss-plugin-vendor-prefixer@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.1.tgz#45a183a3a0eb097bdfab0986b858d99920c0bbd8"
+  integrity sha512-cLkH6RaPZWHa1TqSfd2vszNNgxT1W0omlSjAd6hCFHp3KIocSrW21gaHjlMU26JpTHwkc+tJTCQOmE/O1A4FKQ==
   dependencies:
     "@babel/runtime" "^7.3.1"
     css-vendor "^2.0.8"
-    jss "10.5.0"
+    jss "10.5.1"
 
-jss@10.5.0, jss@^10.0.3:
-  version "10.5.0"
-  resolved "https://registry.yarnpkg.com/jss/-/jss-10.5.0.tgz#0c2de8a29874b2dc8162ab7f34ef6573a87d9dd3"
-  integrity sha512-B6151NvG+thUg3murLNHRPLxTLwQ13ep4SH5brj4d8qKtogOx/jupnpfkPGSHPqvcwKJaCLctpj2lEk+5yGwMw==
+jss@10.5.1, jss@^10.5.1:
+  version "10.5.1"
+  resolved "https://registry.yarnpkg.com/jss/-/jss-10.5.1.tgz#93e6b2428c840408372d8b548c3f3c60fa601c40"
+  integrity sha512-hbbO3+FOTqVdd7ZUoTiwpHzKXIo5vGpMNbuXH1a0wubRSWLWSBvwvaq4CiHH/U42CmjOnp6lVNNs/l+Z7ZdDmg==
   dependencies:
     "@babel/runtime" "^7.3.1"
     csstype "^3.0.2"
@@ -9040,10 +9029,10 @@ pofile@^1.0.11:
   resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.1.0.tgz#9ce84bbef5043ceb4f19bdc3520d85778fad4f94"
   integrity sha512-6XYcNkXWGiJ2CVXogTP7uJ6ZXQCldYLZc16wgRp8tqRaBTTyIfF+TUT3EQJPXTLAT7OTPpTAoaFdoXKfaTRU1w==
 
-popper.js@^1.16.1-lts:
-  version "1.16.1"
-  resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
-  integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
+popper.js@1.16.1-lts:
+  version "1.16.1-lts"
+  resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05"
+  integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==
 
 portfinder@^1.0.26:
   version "1.0.28"
@@ -9407,7 +9396,7 @@ react-dom@16.13.1:
     prop-types "^15.6.2"
     scheduler "^0.19.1"
 
-react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
+react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -9489,7 +9478,7 @@ react-test-renderer@^16.0.0-0:
     react-is "^16.8.6"
     scheduler "^0.19.1"
 
-react-transition-group@^4.3.0:
+react-transition-group@^4.4.0:
   version "4.4.1"
   resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
   integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==


Test patch:
diff --git a/cli/cmd/testdata/install_controlplane_tracing_output.golden b/cli/cmd/testdata/install_controlplane_tracing_output.golden
index efc4ee173..4593fe870 100644
--- a/cli/cmd/testdata/install_controlplane_tracing_output.golden
+++ b/cli/cmd/testdata/install_controlplane_tracing_output.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -935,7 +935,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -968,7 +968,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_custom_domain.golden b/cli/cmd/testdata/install_custom_domain.golden
index f65ff6117..426192b1e 100644
--- a/cli/cmd/testdata/install_custom_domain.golden
+++ b/cli/cmd/testdata/install_custom_domain.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -935,7 +935,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -968,7 +968,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_custom_registry.golden b/cli/cmd/testdata/install_custom_registry.golden
index 642490991..b68a356ed 100644
--- a/cli/cmd/testdata/install_custom_registry.golden
+++ b/cli/cmd/testdata/install_custom_registry.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: my.custom.registry/linkerd-io/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -935,7 +935,7 @@ data:
       enableExternalProfiles: false
       image:
         name: my.custom.registry/linkerd-io/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -968,7 +968,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: my.custom.registry/linkerd-io/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_default.golden b/cli/cmd/testdata/install_default.golden
index f69773f4e..51799b2c2 100644
--- a/cli/cmd/testdata/install_default.golden
+++ b/cli/cmd/testdata/install_default.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -935,7 +935,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -968,7 +968,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
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 bea2a7a7a..3daf5488e 100644
--- a/cli/cmd/testdata/install_default_override_dst_get_nets.golden
+++ b/cli/cmd/testdata/install_default_override_dst_get_nets.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -935,7 +935,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -968,7 +968,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_ha_output.golden b/cli/cmd/testdata/install_ha_output.golden
index 03484c214..803fa3f03 100644
--- a/cli/cmd/testdata/install_ha_output.golden
+++ b/cli/cmd/testdata/install_ha_output.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources:
@@ -953,7 +953,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -986,7 +986,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_ha_with_overrides_output.golden b/cli/cmd/testdata/install_ha_with_overrides_output.golden
index ae541bfd7..9fdfb9952 100644
--- a/cli/cmd/testdata/install_ha_with_overrides_output.golden
+++ b/cli/cmd/testdata/install_ha_with_overrides_output.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources:
@@ -953,7 +953,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -986,7 +986,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_heartbeat_disabled_output.golden b/cli/cmd/testdata/install_heartbeat_disabled_output.golden
index ce8c7d82a..6c91755b6 100644
--- a/cli/cmd/testdata/install_heartbeat_disabled_output.golden
+++ b/cli/cmd/testdata/install_heartbeat_disabled_output.golden
@@ -815,7 +815,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -892,7 +892,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -925,7 +925,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_helm_output.golden b/cli/cmd/testdata/install_helm_output.golden
index 56f60fbc9..9c758e907 100644
--- a/cli/cmd/testdata/install_helm_output.golden
+++ b/cli/cmd/testdata/install_helm_output.golden
@@ -880,7 +880,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -933,7 +933,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -966,7 +966,7 @@ data:
       ignoreOutboundPorts: "111"
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-init-version
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_helm_output_ha.golden b/cli/cmd/testdata/install_helm_output_ha.golden
index 3d5359e09..a7774ff59 100644
--- a/cli/cmd/testdata/install_helm_output_ha.golden
+++ b/cli/cmd/testdata/install_helm_output_ha.golden
@@ -880,7 +880,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-debug-version
     destinationProxyResources: null
     destinationResources:
@@ -951,7 +951,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -984,7 +984,7 @@ data:
       ignoreOutboundPorts: "111"
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-init-version
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_helm_output_ha_labels.golden b/cli/cmd/testdata/install_helm_output_ha_labels.golden
index bdace70e7..a7f8b8f25 100644
--- a/cli/cmd/testdata/install_helm_output_ha_labels.golden
+++ b/cli/cmd/testdata/install_helm_output_ha_labels.golden
@@ -880,7 +880,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-debug-version
     destinationProxyResources: null
     destinationResources:
@@ -955,7 +955,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -988,7 +988,7 @@ data:
       ignoreOutboundPorts: "333"
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-init-version
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_helm_output_ha_namespace_selector.golden b/cli/cmd/testdata/install_helm_output_ha_namespace_selector.golden
index 328acf087..cd71b031d 100644
--- a/cli/cmd/testdata/install_helm_output_ha_namespace_selector.golden
+++ b/cli/cmd/testdata/install_helm_output_ha_namespace_selector.golden
@@ -880,7 +880,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-debug-version
     destinationProxyResources: null
     destinationResources:
@@ -951,7 +951,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -984,7 +984,7 @@ data:
       ignoreOutboundPorts: "111"
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: test-proxy-init-version
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_no_init_container.golden b/cli/cmd/testdata/install_no_init_container.golden
index 2721583d5..a2458fdc3 100644
--- a/cli/cmd/testdata/install_no_init_container.golden
+++ b/cli/cmd/testdata/install_no_init_container.golden
@@ -855,7 +855,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -932,7 +932,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -965,7 +965,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_proxy_ignores.golden b/cli/cmd/testdata/install_proxy_ignores.golden
index ad1b8d60e..c3568b2f2 100644
--- a/cli/cmd/testdata/install_proxy_ignores.golden
+++ b/cli/cmd/testdata/install_proxy_ignores.golden
@@ -858,7 +858,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -935,7 +935,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -968,7 +968,7 @@ data:
       ignoreOutboundPorts: "5432"
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
diff --git a/cli/cmd/testdata/install_values_file.golden b/cli/cmd/testdata/install_values_file.golden
index 3556c71b3..3f98f7299 100644
--- a/cli/cmd/testdata/install_values_file.golden
+++ b/cli/cmd/testdata/install_values_file.golden
@@ -844,7 +844,7 @@ data:
     debugContainer:
       image:
         name: ghcr.io/linkerd/debug
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-debug-version
     destinationProxyResources: null
     destinationResources: null
@@ -892,7 +892,7 @@ data:
       IQCN7lBFLDDvjx6V0+XkjpKERRsJYf5adMvnloFl48ilJgIhANtxhndcr+QJPuC8
       vgUC0d2/9FMueIVMb+46WTCOjsqr
       -----END CERTIFICATE-----
-    identityTrustDomain: cluster.local
+    identityTrustDomain: example.com
     imagePullPolicy: IfNotPresent
     imagePullSecrets: []
     installNamespace: false
@@ -921,7 +921,7 @@ data:
       enableExternalProfiles: false
       image:
         name: ghcr.io/linkerd/proxy
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: install-proxy-version
       inboundConnectTimeout: 100ms
       isGateway: false
@@ -954,7 +954,7 @@ data:
       ignoreOutboundPorts: 25,443,587,3306,11211
       image:
         name: ghcr.io/linkerd/proxy-init
-        pullPolicy: IfNotPresent
+        pullPolicy: ""
         version: v1.3.9
       resources:
         cpu:
@@ -1087,7 +1087,7 @@ spec:
         - -log-level=info
         - -log-format=plain
         - -controller-namespace=l5d
-        - -identity-trust-domain=cluster.local
+        - -identity-trust-domain=example.com
         - -identity-issuance-lifetime=24h0m0s
         - -identity-clock-skew-allowance=20s
         - -identity-trust-anchors-pem=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJ3VENDQVdhZ0F3SUJBZ0lRZURacDVsRGFJeWdRNVVmTUtackZBVEFLQmdncWhrak9QUVFEQWpBcE1TY3cKSlFZRFZRUURFeDVwWkdWdWRHbDBlUzVzYVc1clpYSmtMbU5zZFhOMFpYSXViRzlqWVd3d0hoY05NakF3T0RJNApNRGN4TWpRM1doY05NekF3T0RJMk1EY3hNalEzV2pBcE1TY3dKUVlEVlFRREV4NXBaR1Z1ZEdsMGVTNXNhVzVyClpYSmtMbU5zZFhOMFpYSXViRzlqWVd3d1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFScWM3MFoKbDF2Z3c3OXJqQjV1U0lUSUNVQTZHeWZ2U0ZmY3VJaXM3Qi9YRlNra3dBSFU1Uy9zMUFBUCtSMFRYN0hCV1VDNAp1YUc0V1dzaXdKS05uN21nbzNBd2JqQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VnWURWUjBUQVFIL0JBZ3dCZ0VCCi93SUJBVEFkQmdOVkhRNEVGZ1FVNVl0alZWUGZkN0k3TkxIc24yQzI2RUJ5R1Ywd0tRWURWUjBSQkNJd0lJSWUKYVdSbGJuUnBkSGt1YkdsdWEyVnlaQzVqYkhWemRHVnlMbXh2WTJGc01Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQwpJUUNON2xCRkxERHZqeDZWMCtYa2pwS0VSUnNKWWY1YWRNdm5sb0ZsNDhpbEpnSWhBTnR4aG5kY3IrUUpQdUM4CnZnVUMwZDIvOUZNdWVJVk1iKzQ2V1RDT2pzcXIKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
@@ -1180,7 +1180,7 @@ spec:
         - name: _l5d_ns
           value: l5d
         - name: _l5d_trustdomain
-          value: cluster.local
+          value: example.com
         - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
           value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - name: LINKERD2_PROXY_IDENTITY_SVC_NAME
@@ -1410,7 +1410,7 @@ spec:
         - name: _l5d_ns
           value: l5d
         - name: _l5d_trustdomain
-          value: cluster.local
+          value: example.com
         - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
           value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - name: LINKERD2_PROXY_IDENTITY_SVC_NAME
@@ -1573,7 +1573,7 @@ spec:
         - -log-format=plain
         - -enable-endpoint-slices=false
         - -cluster-domain=example.com
-        - -identity-trust-domain=cluster.local
+        - -identity-trust-domain=example.com
         image: ghcr.io/linkerd/controller:install-control-plane-version
         imagePullPolicy: IfNotPresent
         livenessProbe:
@@ -1659,7 +1659,7 @@ spec:
         - name: _l5d_ns
           value: l5d
         - name: _l5d_trustdomain
-          value: cluster.local
+          value: example.com
         - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
           value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - name: LINKERD2_PROXY_IDENTITY_SVC_NAME
@@ -1915,7 +1915,7 @@ spec:
         - name: _l5d_ns
           value: l5d
         - name: _l5d_trustdomain
-          value: cluster.local
+          value: example.com
         - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
           value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - name: LINKERD2_PROXY_IDENTITY_SVC_NAME
@@ -2167,7 +2167,7 @@ spec:
         - name: _l5d_ns
           value: l5d
         - name: _l5d_trustdomain
-          value: cluster.local
+          value: example.com
         - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
           value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - name: LINKERD2_PROXY_IDENTITY_SVC_NAME
diff --git a/pkg/charts/linkerd2/values_test.go b/pkg/charts/linkerd2/values_test.go
index 94ace45dc..490aad59a 100644
--- a/pkg/charts/linkerd2/values_test.go
+++ b/pkg/charts/linkerd2/values_test.go
@@ -59,15 +59,13 @@ func TestNewValues(t *testing.T) {
 		ControlPlaneTracing:          false,
 		ControlPlaneTracingNamespace: "linkerd-jaeger",
 		HighAvailability:             false,
-		IdentityTrustDomain:          "cluster.local",
 		PodAnnotations:               map[string]string{},
 		PodLabels:                    map[string]string{},
 		Proxy: &Proxy{
 			EnableExternalProfiles: false,
 			Image: &Image{
-				Name:       "ghcr.io/linkerd/proxy",
-				PullPolicy: "IfNotPresent",
-				Version:    testVersion,
+				Name:    "ghcr.io/linkerd/proxy",
+				Version: "dev-undefined",
 			},
 			LogLevel:  "warn,linkerd=info",
 			LogFormat: "plain",
@@ -96,9 +94,8 @@ func TestNewValues(t *testing.T) {
 			IgnoreInboundPorts:  "25,443,587,3306,11211",
 			IgnoreOutboundPorts: "25,443,587,3306,11211",
 			Image: &Image{
-				Name:       "ghcr.io/linkerd/proxy-init",
-				PullPolicy: "IfNotPresent",
-				Version:    testVersion,
+				Name:    "ghcr.io/linkerd/proxy-init",
+				Version: testVersion,
 			},
 			Resources: &Resources{
 				CPU: Constraints{
@@ -129,9 +126,8 @@ func TestNewValues(t *testing.T) {
 		},
 		DebugContainer: &DebugContainer{
 			Image: &Image{
-				Name:       "ghcr.io/linkerd/debug",
-				PullPolicy: "IfNotPresent",
-				Version:    testVersion,
+				Name:    "ghcr.io/linkerd/debug",
+				Version: "dev-undefined",
 			},
 		},
 
@@ -143,9 +139,7 @@ func TestNewValues(t *testing.T) {
 	// in non-test environment, the default versions are read from the
 	// values.yaml.
 	actual.ControllerImageVersion = testVersion
-	actual.Proxy.Image.Version = testVersion
 	actual.ProxyInit.Image.Version = testVersion
-	actual.DebugContainer.Image.Version = testVersion
 
 	// Make Add-On Values nil to not have to check for their defaults
 	actual.ImagePullSecrets = nil
@@ -206,9 +200,7 @@ func TestNewValues(t *testing.T) {
 		// in non-test environment, the default versions are read from the
 		// values.yaml.
 		actual.ControllerImageVersion = testVersion
-		actual.Proxy.Image.Version = testVersion
 		actual.ProxyInit.Image.Version = testVersion
-		actual.DebugContainer.Image.Version = testVersion
 
 		if !reflect.DeepEqual(expected, actual) {
 			t.Errorf("Mismatch Helm HA defaults.\nExpected: %+v\nActual: %+v", expected, actual)
diff --git a/pkg/healthcheck/healthcheck_test.go b/pkg/healthcheck/healthcheck_test.go
index 1369d3682..ee84ff7b0 100644
--- a/pkg/healthcheck/healthcheck_test.go
+++ b/pkg/healthcheck/healthcheck_test.go
@@ -2275,7 +2275,6 @@ data:
     enableEndpointSlices: false
     grafanaUrl: ""
     highAvailability: false
-    identityTrustDomain: cluster.local
     imagePullPolicy: ImagePullPolicy
     imagePullSecrets: null
     linkerdNamespaceLabel: LinkerdNamespaceLabel
@@ -2378,7 +2377,6 @@ data:
 				LinkerdNamespaceLabel:    "LinkerdNamespaceLabel",
 				ProxyContainerName:       "ProxyContainerName",
 				CNIEnabled:               false,
-				IdentityTrustDomain:      defaultValues.IdentityTrustDomain,
 				Proxy: &linkerd2.Proxy{
 					Image: &linkerd2.Image{
 						Name:       "ProxyImageName",
@@ -2458,7 +2456,6 @@ data:
       enableEndpointSlices: false
       grafanaUrl: ""
       highAvailability: false
-      identityTrustDomain: cluster.local
       imagePullPolicy: ImagePullPolicy
       imagePullSecrets: null
       linkerdNamespaceLabel: LinkerdNamespaceLabel
@@ -2561,7 +2558,6 @@ data:
 				LinkerdNamespaceLabel:    "LinkerdNamespaceLabel",
 				ProxyContainerName:       "ProxyContainerName",
 				CNIEnabled:               false,
-				IdentityTrustDomain:      defaultValues.IdentityTrustDomain,
 				Proxy: &linkerd2.Proxy{
 					Image: &linkerd2.Image{
 						Name:       "ProxyImageName",
diff --git a/viz/cmd/install_test.go b/viz/cmd/install_test.go
index aa6c3933c..6641390e7 100644
--- a/viz/cmd/install_test.go
+++ b/viz/cmd/install_test.go
@@ -63,6 +63,22 @@ func TestRender(t *testing.T) {
 			},
 			"install_proxy_resources.golden",
 		},
+		{
+			map[string]interface{}{
+				"defaultLogLevel": "debug",
+				"defaultUID":      1234,
+				"defaultRegistry": "gcr.io/linkerd",
+				"tap": map[string]interface{}{
+					"logLevel": "info",
+					"UID":      5678,
+					"image": map[string]interface{}{
+						"registry": "ghcr.io/linkerd",
+						"tag":      "stable-9.2",
+					},
+				},
+			},
+			"install_default_overrides.golden",
+		},
 		{
 			map[string]interface{}{
 				"grafana":    map[string]interface{}{"enabled": false},
diff --git a/viz/cmd/testdata/install_default.golden b/viz/cmd/testdata/install_default.golden
index 09965eaa5..e27cae75b 100644
--- a/viz/cmd/testdata/install_default.golden
+++ b/viz/cmd/testdata/install_default.golden
@@ -471,7 +471,7 @@ spec:
         - -cluster-domain=cluster.local
         - -prometheus-url=http://linkerd-prometheus.linkerd-viz.svc.cluster.local:9090
         image: ghcr.io/linkerd/metrics-api:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -612,7 +612,7 @@ spec:
         - name: GODEBUG
           value: netdns=go
         image: ghcr.io/linkerd/grafana:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /api/health
@@ -855,12 +855,12 @@ spec:
         fsGroup: 65534
       containers:
       - args:
-        - --config.file=/etc/prometheus/prometheus.yml
         - --log.level=info
+        - --config.file=/etc/prometheus/prometheus.yml
         - --storage.tsdb.path=/data
         - --storage.tsdb.retention.time=6h
         image: prom/prometheus:v2.19.3
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /-/healthy
@@ -964,7 +964,7 @@ spec:
         - -log-level=info
         - -identity-trust-domain=cluster.local
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -1124,7 +1124,7 @@ spec:
         - -tap-service-name=linkerd-tap.linkerd-viz.serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - -log-level=info
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -1224,7 +1224,7 @@ spec:
         - -log-level=info
         - -enforced-host=^(localhost|127\.0\.0\.1|linkerd-web\.linkerd-viz\.svc\.cluster\.local|linkerd-web\.linkerd-viz\.svc|\[::1\])(:\d+)?$
         image: ghcr.io/linkerd/web:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
diff --git a/viz/cmd/testdata/install_default_overrides.golden b/viz/cmd/testdata/install_default_overrides.golden
new file mode 100644
index 000000000..416fd7114
--- /dev/null
+++ b/viz/cmd/testdata/install_default_overrides.golden
@@ -0,0 +1,1247 @@
+---
+###
+### Linkerd Viz Extension Namespace
+###
+kind: Namespace
+apiVersion: v1
+metadata:
+  name: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+  annotations:
+    linkerd.io/inject: enabled
+---
+###
+### Metrics API RBAC
+###
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-metrics-api
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: metrics-api
+rules:
+- apiGroups: ["extensions", "apps"]
+  resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
+  verbs: ["list", "get", "watch"]
+- apiGroups: ["extensions", "batch"]
+  resources: ["cronjobs", "jobs"]
+  verbs: ["list" , "get", "watch"]
+- apiGroups: [""]
+  resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
+  verbs: ["list", "get", "watch"]
+- apiGroups: ["linkerd.io"]
+  resources: ["serviceprofiles"]
+  verbs: ["list", "get", "watch"]
+- apiGroups: ["split.smi-spec.io"]
+  resources: ["trafficsplits"]
+  verbs: ["list", "get", "watch"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-metrics-api
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: metrics-api
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: linkerd-linkerd-viz-metrics-api
+subjects:
+- kind: ServiceAccount
+  name: linkerd-metrics-api
+  namespace: linkerd-viz
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: linkerd-metrics-api
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: metrics-api
+---
+###
+### Grafana RBAC
+###
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: linkerd-grafana
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: grafana
+    namespace: linkerd-viz
+---
+###
+### Prometheus RBAC
+###
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-prometheus
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: prometheus
+rules:
+- apiGroups: [""]
+  resources: ["nodes", "nodes/proxy", "pods"]
+  verbs: ["get", "list", "watch"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-prometheus
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: prometheus
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: linkerd-linkerd-viz-prometheus
+subjects:
+- kind: ServiceAccount
+  name: linkerd-prometheus
+  namespace: linkerd-viz
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: linkerd-prometheus
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: prometheus
+    namespace: linkerd-viz
+---
+###
+### Tap RBAC
+###
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-tap
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+rules:
+- apiGroups: [""]
+  resources: ["pods", "services", "replicationcontrollers", "namespaces", "nodes"]
+  verbs: ["list", "get", "watch"]
+- apiGroups: ["extensions", "apps"]
+  resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
+  verbs: ["list", "get", "watch"]
+- apiGroups: ["extensions", "batch"]
+  resources: ["cronjobs", "jobs"]
+  verbs: ["list" , "get", "watch"]
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-tap-admin
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+rules:
+- apiGroups: ["tap.linkerd.io"]
+  resources: ["*"]
+  verbs: ["watch"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-tap
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: linkerd-linkerd-viz-tap
+subjects:
+- kind: ServiceAccount
+  name: linkerd-tap
+  namespace: linkerd-viz
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: linkerd-linkerd-viz-tap-auth-delegator
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: system:auth-delegator
+subjects:
+- kind: ServiceAccount
+  name: linkerd-tap
+  namespace: linkerd-viz
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: linkerd-tap
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+    namespace: linkerd-viz
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: linkerd-linkerd-viz-tap-auth-reader
+  namespace: kube-system
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+    namespace: linkerd-viz
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: extension-apiserver-authentication-reader
+subjects:
+- kind: ServiceAccount
+  name: linkerd-tap
+  namespace: linkerd-viz
+---
+kind: Secret
+apiVersion: v1
+metadata:
+  name: linkerd-tap-k8s-tls
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+type: kubernetes.io/tls
+data:
+  tls.crt: dGVzdC10YXAtY3J0LXBlbQ==
+  tls.key: dGVzdC10YXAta2V5LXBlbQ==
+---
+apiVersion: apiregistration.k8s.io/v1
+kind: APIService
+metadata:
+  name: v1alpha1.tap.linkerd.io
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+spec:
+  group: tap.linkerd.io
+  version: v1alpha1
+  groupPriorityMinimum: 1000
+  versionPriority: 100
+  service:
+    name: linkerd-tap
+    namespace: linkerd-viz
+  caBundle: dGVzdC10YXAtY2EtYnVuZGxl
+---
+###
+### Web RBAC
+###
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: linkerd-web
+  namespace: linkerd
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+    namespace: linkerd
+rules:
+- apiGroups: [""]
+  resources: ["configmaps"]
+  verbs: ["get"]
+  resourceNames: ["linkerd-config"]
+- apiGroups: [""]
+  resources: ["namespaces", "configmaps"]
+  verbs: ["get"]
+- apiGroups: [""]
+  resources: ["serviceaccounts", "pods"]
+  verbs: ["list"]
+- apiGroups: ["apps"]
+  resources: ["replicasets"]
+  verbs: ["list"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: linkerd-web
+  namespace: linkerd
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+    namespace: linkerd
+roleRef:
+  kind: Role
+  name: linkerd-web
+  apiGroup: rbac.authorization.k8s.io
+subjects:
+- kind: ServiceAccount
+  name: linkerd-web
+  namespace: linkerd-viz
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: linkerd-linkerd-viz-web-check
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+rules:
+- apiGroups: ["rbac.authorization.k8s.io"]
+  resources: ["clusterroles", "clusterrolebindings"]
+  verbs: ["list"]
+- apiGroups: ["apiextensions.k8s.io"]
+  resources: ["customresourcedefinitions"]
+  verbs: ["list"]
+- apiGroups: ["admissionregistration.k8s.io"]
+  resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
+  verbs: ["list"]
+- apiGroups: ["policy"]
+  resources: ["podsecuritypolicies"]
+  verbs: ["list"]
+- apiGroups: ["linkerd.io"]
+  resources: ["serviceprofiles"]
+  verbs: ["list"]
+- apiGroups: ["apiregistration.k8s.io"]
+  resources: ["apiservices"]
+  verbs: ["get"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: linkerd-linkerd-viz-web-check
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+roleRef:
+  kind: ClusterRole
+  name: linkerd-linkerd-viz-web-check
+  apiGroup: rbac.authorization.k8s.io
+subjects:
+- kind: ServiceAccount
+  name: linkerd-web
+  namespace: linkerd-viz
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-linkerd-viz-web-admin
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: linkerd-linkerd-viz-tap-admin
+subjects:
+- kind: ServiceAccount
+  name: linkerd-web
+  namespace: linkerd-viz
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: linkerd-linkerd-viz-web-api
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+rules:
+- apiGroups: [""]
+  resources: ["namespaces"]
+  verbs: ["list"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: linkerd-linkerd-viz-web-api
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+roleRef:
+  kind: ClusterRole
+  name: linkerd-linkerd-viz-web-api
+  apiGroup: rbac.authorization.k8s.io
+subjects:
+- kind: ServiceAccount
+  name: linkerd-web
+  namespace: linkerd-viz
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: linkerd-web
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+    namespace: linkerd-viz
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: linkerd-viz-psp
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    namespace: linkerd-viz
+roleRef:
+  kind: Role
+  name: linkerd-psp
+  apiGroup: rbac.authorization.k8s.io
+subjects:
+- kind: ServiceAccount
+  name: linkerd-tap
+  namespace: linkerd-viz
+- kind: ServiceAccount
+  name: linkerd-web
+  namespace: linkerd-viz
+- kind: ServiceAccount
+  name: linkerd-grafana
+  namespace: linkerd-viz
+- kind: ServiceAccount
+  name: linkerd-prometheus
+  namespace: linkerd-viz
+---
+###
+### Metrics API
+###
+kind: Service
+apiVersion: v1
+metadata:
+  name: linkerd-metrics-api
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: metrics-api
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+spec:
+  type: ClusterIP
+  selector:
+    linkerd.io/extension: linkerd-viz
+    component: metrics-api
+  ports:
+  - name: http
+    port: 8085
+    targetPort: 8085
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+  labels:
+    linkerd.io/extension: linkerd-viz
+    app.kubernetes.io/name: metrics-api
+    app.kubernetes.io/part-of: Linkerd
+    app.kubernetes.io/version: dev-undefined
+    component: metrics-api
+  name: linkerd-metrics-api
+  namespace: linkerd-viz
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      linkerd.io/extension: linkerd-viz
+      component: metrics-api
+  template:
+    metadata:
+      annotations:
+        checksum/config: 6827b2203b1cd90692d9dd6a973a2162e574dc9fd7b5b9e346ceac7e287204a6
+        linkerd.io/created-by: linkerd/helm dev-undefined
+      labels:
+        linkerd.io/extension: linkerd-viz
+        component: metrics-api
+    spec:
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      containers:
+      - args:
+        - -controller-namespace=linkerd
+        - -log-level=debug
+        - -cluster-domain=cluster.local
+        - -prometheus-url=http://linkerd-prometheus.linkerd-viz.svc.cluster.local:9090
+        image: gcr.io/linkerd/metrics-api:dev-undefined
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /ping
+            port: 9995
+          initialDelaySeconds: 10
+        name: metrics-api
+        ports:
+        - containerPort: 8085
+          name: http
+        - containerPort: 9995
+          name: admin-http
+        readinessProbe:
+          failureThreshold: 7
+          httpGet:
+            path: /ready
+            port: 9995
+        resources:
+        securityContext:
+          runAsUser: 1234
+      serviceAccountName: linkerd-metrics-api
+---
+###
+### Grafana
+###
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: linkerd-grafana-config
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: grafana
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+data:
+  grafana.ini: |-
+    instance_name = linkerd-grafana
+    [server]
+    root_url = %(protocol)s://%(domain)s:/grafana/
+    [auth]
+    disable_login_form = true
+    [auth.anonymous]
+    enabled = true
+    org_role = Editor
+    [auth.basic]
+    enabled = false
+    [analytics]
+    check_for_updates = false
+    [panels]
+    disable_sanitize_html = true
+  datasources.yaml: |-
+    apiVersion: 1
+    datasources:
+    - name: prometheus
+      type: prometheus
+      access: proxy
+      orgId: 1
+      url: http://linkerd-prometheus.linkerd-viz.svc.cluster.local:9090
+      isDefault: true
+      jsonData:
+        timeInterval: "5s"
+      version: 1
+      editable: true
+
+  dashboards.yaml: |-
+    apiVersion: 1
+    providers:
+    - name: 'default'
+      orgId: 1
+      folder: ''
+      type: file
+      disableDeletion: true
+      editable: true
+      options:
+        path: /var/lib/grafana/dashboards
+        homeDashboardId: linkerd-top-line
+---
+kind: Service
+apiVersion: v1
+metadata:
+  name: linkerd-grafana
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: grafana
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+spec:
+  type: ClusterIP
+  selector:
+    linkerd.io/extension: linkerd-viz
+    component: grafana
+  ports:
+  - name: http
+    port: 3000
+    targetPort: 3000
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+  labels:
+    linkerd.io/extension: linkerd-viz
+    app.kubernetes.io/name: grafana
+    app.kubernetes.io/part-of: Linkerd
+    app.kubernetes.io/version: dev-undefined
+    component: grafana
+    namespace: linkerd-viz
+  name: linkerd-grafana
+  namespace: linkerd-viz
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      linkerd.io/extension: linkerd-viz
+      component: grafana
+      namespace: linkerd-viz
+  template:
+    metadata:
+      annotations:
+        linkerd.io/created-by: linkerd/helm dev-undefined
+      labels:
+        linkerd.io/extension: linkerd-viz
+        component: grafana
+        namespace: linkerd-viz
+    spec:
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      containers:
+      - env:
+        - name: GF_PATHS_DATA
+          value: /data
+        # Force using the go-based DNS resolver instead of the OS' to avoid failures in some environments
+        # see https://github.com/grafana/grafana/issues/20096
+        - name: GODEBUG
+          value: netdns=go
+        image: gcr.io/linkerd/grafana:dev-undefined
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /api/health
+            port: 3000
+          initialDelaySeconds: 30
+        name: grafana
+        ports:
+        - containerPort: 3000
+          name: http
+        readinessProbe:
+          httpGet:
+            path: /api/health
+            port: 3000
+        resources:
+        securityContext:
+          runAsUser: 472
+        volumeMounts:
+        - mountPath: /data
+          name: data
+        - mountPath: /etc/grafana
+          name: grafana-config
+          readOnly: true
+      serviceAccountName: linkerd-grafana
+      volumes:
+      - emptyDir: {}
+        name: data
+      - configMap:
+          items:
+          - key: grafana.ini
+            path: grafana.ini
+          - key: datasources.yaml
+            path: provisioning/datasources/datasources.yaml
+          - key: dashboards.yaml
+            path: provisioning/dashboards/dashboards.yaml
+          name: linkerd-grafana-config
+        name: grafana-config
+---
+###
+### Prometheus
+###
+kind: ConfigMap
+apiVersion: v1
+metadata:
+  name: linkerd-prometheus-config
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: prometheus
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+data:
+  prometheus.yml: |-
+    global:
+      evaluation_interval: 10s
+      scrape_interval: 10s
+      scrape_timeout: 10s
+
+    rule_files:
+    - /etc/prometheus/*_rules.yml
+    - /etc/prometheus/*_rules.yaml
+
+    scrape_configs:
+    - job_name: 'prometheus'
+      static_configs:
+      - targets: ['localhost:9090']
+
+    - job_name: 'grafana'
+      kubernetes_sd_configs:
+      - role: pod
+        namespaces:
+          names: ['linkerd-viz']
+      relabel_configs:
+      - source_labels:
+        - __meta_kubernetes_pod_container_name
+        action: keep
+        regex: ^grafana$
+
+    #  Required for: https://grafana.com/grafana/dashboards/315
+    - job_name: 'kubernetes-nodes-cadvisor'
+      scheme: https
+      tls_config:
+        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+        insecure_skip_verify: true
+      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+      kubernetes_sd_configs:
+      - role: node
+      relabel_configs:
+      - action: labelmap
+        regex: __meta_kubernetes_node_label_(.+)
+      - target_label: __address__
+        replacement: kubernetes.default.svc:443
+      - source_labels: [__meta_kubernetes_node_name]
+        regex: (.+)
+        target_label: __metrics_path__
+        replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor
+      metric_relabel_configs:
+      - source_labels: [__name__]
+        regex: '(container|machine)_(cpu|memory|network|fs)_(.+)'
+        action: keep
+      - source_labels: [__name__]
+        regex: 'container_memory_failures_total' # unneeded large metric
+        action: drop
+
+    - job_name: 'linkerd-controller'
+      kubernetes_sd_configs:
+      - role: pod
+        namespaces:
+          names:
+          - 'linkerd'
+          - 'linkerd-viz'
+      relabel_configs:
+      - source_labels:
+        - __meta_kubernetes_pod_container_port_name
+        action: keep
+        regex: admin-http
+      - source_labels: [__meta_kubernetes_pod_container_name]
+        action: replace
+        target_label: component
+
+    - job_name: 'linkerd-service-mirror'
+      kubernetes_sd_configs:
+      - role: pod
+      relabel_configs:
+      - source_labels:
+        - __meta_kubernetes_pod_label_linkerd_io_control_plane_component
+        - __meta_kubernetes_pod_container_port_name
+        action: keep
+        regex: linkerd-service-mirror;admin-http$
+      - source_labels: [__meta_kubernetes_pod_container_name]
+        action: replace
+        target_label: component
+
+    - job_name: 'linkerd-proxy'
+      kubernetes_sd_configs:
+      - role: pod
+      relabel_configs:
+      - source_labels:
+        - __meta_kubernetes_pod_container_name
+        - __meta_kubernetes_pod_container_port_name
+        - __meta_kubernetes_pod_label_linkerd_io_control_plane_ns
+        action: keep
+        regex: ^linkerd-proxy;linkerd-admin;linkerd$
+      - source_labels: [__meta_kubernetes_namespace]
+        action: replace
+        target_label: namespace
+      - source_labels: [__meta_kubernetes_pod_name]
+        action: replace
+        target_label: pod
+      # special case k8s' "job" label, to not interfere with prometheus' "job"
+      # label
+      # __meta_kubernetes_pod_label_linkerd_io_proxy_job=foo =>
+      # k8s_job=foo
+      - source_labels: [__meta_kubernetes_pod_label_linkerd_io_proxy_job]
+        action: replace
+        target_label: k8s_job
+      # drop __meta_kubernetes_pod_label_linkerd_io_proxy_job
+      - action: labeldrop
+        regex: __meta_kubernetes_pod_label_linkerd_io_proxy_job
+      # __meta_kubernetes_pod_label_linkerd_io_proxy_deployment=foo =>
+      # deployment=foo
+      - action: labelmap
+        regex: __meta_kubernetes_pod_label_linkerd_io_proxy_(.+)
+      # drop all labels that we just made copies of in the previous labelmap
+      - action: labeldrop
+        regex: __meta_kubernetes_pod_label_linkerd_io_proxy_(.+)
+      # __meta_kubernetes_pod_label_linkerd_io_foo=bar =>
+      # foo=bar
+      - action: labelmap
+        regex: __meta_kubernetes_pod_label_linkerd_io_(.+)
+      # Copy all pod labels to tmp labels
+      - action: labelmap
+        regex: __meta_kubernetes_pod_label_(.+)
+        replacement: __tmp_pod_label_$1
+      # Take `linkerd_io_` prefixed labels and copy them without the prefix
+      - action: labelmap
+        regex: __tmp_pod_label_linkerd_io_(.+)
+        replacement:  __tmp_pod_label_$1
+      # Drop the `linkerd_io_` originals
+      - action: labeldrop
+        regex: __tmp_pod_label_linkerd_io_(.+)
+      # Copy tmp labels into real labels
+      - action: labelmap
+        regex: __tmp_pod_label_(.+)
+---
+kind: Service
+apiVersion: v1
+metadata:
+  name: linkerd-prometheus
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: prometheus
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+spec:
+  type: ClusterIP
+  selector:
+    linkerd.io/extension: linkerd-viz
+    component: prometheus
+  ports:
+  - name: admin-http
+    port: 9090
+    targetPort: 9090
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+  labels:
+    linkerd.io/extension: linkerd-viz
+    app.kubernetes.io/name: prometheus
+    app.kubernetes.io/part-of: Linkerd
+    app.kubernetes.io/version: dev-undefined
+    component: prometheus
+    namespace: linkerd-viz
+  name: linkerd-prometheus
+  namespace: linkerd-viz
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      linkerd.io/extension: linkerd-viz
+      component: prometheus
+      namespace: linkerd-viz
+  template:
+    metadata:
+      annotations:
+        linkerd.io/created-by: linkerd/helm dev-undefined
+      labels:
+        linkerd.io/extension: linkerd-viz
+        component: prometheus
+        namespace: linkerd-viz
+    spec:
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      securityContext:
+        fsGroup: 65534
+      containers:
+      - args:
+        - --log.level=debug
+        - --config.file=/etc/prometheus/prometheus.yml
+        - --storage.tsdb.path=/data
+        - --storage.tsdb.retention.time=6h
+        image: prom/prometheus:v2.19.3
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /-/healthy
+            port: 9090
+          initialDelaySeconds: 30
+          timeoutSeconds: 30
+        name: prometheus
+        ports:
+        - containerPort: 9090
+          name: admin-http
+        readinessProbe:
+          httpGet:
+            path: /-/ready
+            port: 9090
+          initialDelaySeconds: 30
+          timeoutSeconds: 30
+        resources:
+        securityContext:
+          runAsNonRoot: true
+          runAsUser: 65534
+          runAsGroup: 65534
+        volumeMounts:
+        - mountPath: /data
+          name: data
+        - mountPath: /etc/prometheus/prometheus.yml
+          name: prometheus-config
+          subPath: prometheus.yml
+          readOnly: true
+      serviceAccountName: linkerd-prometheus
+      volumes:
+      - name: data
+        emptyDir: {}
+      - configMap:
+          name: linkerd-prometheus-config
+        name: prometheus-config
+---
+###
+### Tap
+###
+kind: Service
+apiVersion: v1
+metadata:
+  name: linkerd-tap
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+spec:
+  type: ClusterIP
+  selector:
+    linkerd.io/extension: linkerd-viz
+    component: tap
+  ports:
+  - name: grpc
+    port: 8088
+    targetPort: 8088
+  - name: apiserver
+    port: 443
+    targetPort: apiserver
+---
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+  labels:
+    linkerd.io/extension: linkerd-viz
+    app.kubernetes.io/name: tap
+    app.kubernetes.io/part-of: Linkerd
+    app.kubernetes.io/version: dev-undefined
+    component: tap
+    namespace: linkerd-viz
+  name: linkerd-tap
+  namespace: linkerd-viz
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      linkerd.io/extension: linkerd-viz
+      component: tap
+      namespace: linkerd-viz
+  template:
+    metadata:
+      annotations:
+        checksum/config: bbc82b03e8c9fdc549e1ef5d3f795c07c21fb3b4c089351186f170b722689d86
+        linkerd.io/created-by: linkerd/helm dev-undefined
+      labels:
+        linkerd.io/extension: linkerd-viz
+        component: tap
+        namespace: linkerd-viz
+    spec:
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      containers:
+      - args:
+        - api
+        - -api-namespace=linkerd
+        - -log-level=info
+        - -identity-trust-domain=cluster.local
+        image: ghcr.io/linkerd/tap:stable-9.2
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /ping
+            port: 9998
+          initialDelaySeconds: 10
+        name: tap
+        ports:
+        - containerPort: 8088
+          name: grpc
+        - containerPort: 8089
+          name: apiserver
+        - containerPort: 9998
+          name: admin-http
+        readinessProbe:
+          failureThreshold: 7
+          httpGet:
+            path: /ready
+            port: 9998
+        resources:
+        securityContext:
+          runAsUser: 5678
+        volumeMounts:
+        - mountPath: /var/run/linkerd/tls
+          name: tls
+          readOnly: true
+      serviceAccountName: linkerd-tap
+      volumes:
+      - name: tls
+        secret:
+          secretName: linkerd-tap-k8s-tls
+
+---
+###
+### Tap Injector RBAC
+###
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-tap-injector
+  labels:
+    linkerd.io/extension: linkerd-viz
+rules:
+- apiGroups: [""]
+  resources: ["namespaces"]
+  verbs: ["get", "list", "watch"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: linkerd-tap-injector
+  labels:
+    linkerd.io/extension: linkerd-viz
+subjects:
+- kind: ServiceAccount
+  name: tap-injector
+  namespace: linkerd-viz
+roleRef:
+  kind: ClusterRole
+  name: linkerd-tap-injector
+  apiGroup: rbac.authorization.k8s.io
+---
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: tap-injector
+  namespace: linkerd-viz
+---
+kind: Secret
+apiVersion: v1
+metadata:
+  name: tap-injector-k8s-tls
+  namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+type: kubernetes.io/tls
+data:
+  tls.crt: dGVzdC10YXAtY3J0LXBlbQ==
+  tls.key: dGVzdC10YXAta2V5LXBlbQ==
+---
+apiVersion: admissionregistration.k8s.io/v1
+kind: MutatingWebhookConfiguration
+metadata:
+  name: linkerd-tap-injector-webhook-config
+  labels:
+    linkerd.io/extension: linkerd-viz
+webhooks:
+- name: tap-injector.linkerd.io
+  clientConfig:
+    service:
+      name: tap-injector
+      namespace: linkerd-viz
+      path: "/"
+    caBundle: dGVzdC10YXAtY2EtYnVuZGxl
+  failurePolicy: Ignore
+  admissionReviewVersions: ["v1", "v1beta1"]
+  reinvocationPolicy: IfNeeded
+  rules:
+  - operations: [ "CREATE" ]
+    apiGroups: [""]
+    apiVersions: ["v1"]
+    resources: ["pods"]
+  sideEffects: None
+---
+###
+### Tap Injector
+###
+kind: Service
+apiVersion: v1
+metadata:
+  name: tap-injector
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: tap-injector
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+spec:
+  type: ClusterIP
+  selector:
+    component: tap-injector
+  ports:
+  - name: tap-injector
+    port: 443
+    targetPort: tap-injector
+---
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+  labels:
+    linkerd.io/extension: linkerd-viz
+    app.kubernetes.io/name: tap-injector
+    app.kubernetes.io/part-of: Linkerd
+    component: tap-injector
+  name: tap-injector
+  namespace: linkerd-viz
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      component: tap-injector
+  template:
+    metadata:
+      annotations:
+        checksum/config: 0120b5feafdef04a057ab39fd63ed315ebbcc2bfc0b0657e3007fa34ffb8b7e2
+        linkerd.io/created-by: linkerd/helm dev-undefined
+      labels:
+        linkerd.io/extension: linkerd-viz
+        component: tap-injector
+    spec:
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      containers:
+      - args:
+        - injector
+        - -tap-service-name=linkerd-tap.linkerd-viz.serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
+        - -log-level=debug
+        image: gcr.io/linkerd/tap:dev-undefined
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /ping
+            port: 9995
+          initialDelaySeconds: 10
+        name: tap-injector
+        ports:
+        - containerPort: 8443
+          name: tap-injector
+        - containerPort: 9995
+          name: admin-http
+        readinessProbe:
+          failureThreshold: 7
+          httpGet:
+            path: /ready
+            port: 9995
+        resources:
+        securityContext:
+          runAsUser: 1234
+        volumeMounts:
+        - mountPath: /var/run/linkerd/tls
+          name: tls
+          readOnly: true
+      serviceAccountName: tap-injector
+      volumes:
+      - name: tls
+        secret:
+          secretName: tap-injector-k8s-tls
+---
+###
+### Web
+###
+kind: Service
+apiVersion: v1
+metadata:
+  name: linkerd-web
+  namespace: linkerd-viz
+  labels:
+    linkerd.io/extension: linkerd-viz
+    component: web
+    namespace: linkerd-viz
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+spec:
+  type: ClusterIP
+  selector:
+    linkerd.io/extension: linkerd-viz
+    component: web
+  ports:
+  - name: http
+    port: 8084
+    targetPort: 8084
+  - name: admin-http
+    port: 9994
+    targetPort: 9994
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  annotations:
+    linkerd.io/created-by: linkerd/helm dev-undefined
+  labels:
+    linkerd.io/extension: linkerd-viz
+    app.kubernetes.io/name: web
+    app.kubernetes.io/part-of: Linkerd
+    app.kubernetes.io/version: dev-undefined
+    component: web
+    namespace: linkerd-viz
+  name: linkerd-web
+  namespace: linkerd-viz
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      linkerd.io/extension: linkerd-viz
+      component: web
+      namespace: linkerd-viz
+  template:
+    metadata:
+      annotations:
+        linkerd.io/created-by: linkerd/helm dev-undefined
+      labels:
+        linkerd.io/extension: linkerd-viz
+        component: web
+        namespace: linkerd-viz
+    spec:
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      containers:
+      - args:
+        - -linkerd-controller-api-addr=linkerd-controller-api.linkerd.svc.cluster.local:8085
+        - -linkerd-metrics-api-addr=linkerd-metrics-api.linkerd-viz.svc.cluster.local:8085
+        - -cluster-domain=cluster.local
+        - -grafana-addr=linkerd-grafana.linkerd-viz.svc.cluster.local:3000
+        - -controller-namespace=linkerd
+        - -viz-namespace=linkerd-viz
+        - -log-level=debug
+        - -enforced-host=^(localhost|127\.0\.0\.1|linkerd-web\.linkerd-viz\.svc\.cluster\.local|linkerd-web\.linkerd-viz\.svc|\[::1\])(:\d+)?$
+        image: gcr.io/linkerd/web:dev-undefined
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /ping
+            port: 9994
+          initialDelaySeconds: 10
+        name: web
+        ports:
+        - containerPort: 8084
+          name: http
+        - containerPort: 9994
+          name: admin-http
+        readinessProbe:
+          failureThreshold: 7
+          httpGet:
+            path: /ready
+            port: 9994
+        resources:
+        securityContext:
+          runAsUser: 1234
+      serviceAccountName: linkerd-web
diff --git a/viz/cmd/testdata/install_grafana_disabled.golden b/viz/cmd/testdata/install_grafana_disabled.golden
index 933aa5141..a070106fb 100644
--- a/viz/cmd/testdata/install_grafana_disabled.golden
+++ b/viz/cmd/testdata/install_grafana_disabled.golden
@@ -455,7 +455,7 @@ spec:
         - -cluster-domain=cluster.local
         - -prometheus-url=http://linkerd-prometheus.linkerd-viz.svc.cluster.local:9090
         image: ghcr.io/linkerd/metrics-api:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -673,12 +673,12 @@ spec:
         fsGroup: 65534
       containers:
       - args:
-        - --config.file=/etc/prometheus/prometheus.yml
         - --log.level=info
+        - --config.file=/etc/prometheus/prometheus.yml
         - --storage.tsdb.path=/data
         - --storage.tsdb.retention.time=6h
         image: prom/prometheus:v2.19.3
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /-/healthy
@@ -782,7 +782,7 @@ spec:
         - -log-level=info
         - -identity-trust-domain=cluster.local
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -942,7 +942,7 @@ spec:
         - -tap-service-name=linkerd-tap.linkerd-viz.serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - -log-level=info
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -1042,7 +1042,7 @@ spec:
         - -log-level=info
         - -enforced-host=^(localhost|127\.0\.0\.1|linkerd-web\.linkerd-viz\.svc\.cluster\.local|linkerd-web\.linkerd-viz\.svc|\[::1\])(:\d+)?$
         image: ghcr.io/linkerd/web:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
diff --git a/viz/cmd/testdata/install_prometheus_disabled.golden b/viz/cmd/testdata/install_prometheus_disabled.golden
index a644bc67f..2cab9a4de 100644
--- a/viz/cmd/testdata/install_prometheus_disabled.golden
+++ b/viz/cmd/testdata/install_prometheus_disabled.golden
@@ -428,7 +428,7 @@ spec:
         - -cluster-domain=cluster.local
         - -prometheus-url=external-prom.com
         image: ghcr.io/linkerd/metrics-api:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -569,7 +569,7 @@ spec:
         - name: GODEBUG
           value: netdns=go
         image: ghcr.io/linkerd/grafana:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /api/health
@@ -674,7 +674,7 @@ spec:
         - -log-level=info
         - -identity-trust-domain=cluster.local
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -834,7 +834,7 @@ spec:
         - -tap-service-name=linkerd-tap.linkerd-viz.serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - -log-level=info
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -934,7 +934,7 @@ spec:
         - -log-level=info
         - -enforced-host=^(localhost|127\.0\.0\.1|linkerd-web\.linkerd-viz\.svc\.cluster\.local|linkerd-web\.linkerd-viz\.svc|\[::1\])(:\d+)?$
         image: ghcr.io/linkerd/web:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
diff --git a/viz/cmd/testdata/install_proxy_resources.golden b/viz/cmd/testdata/install_proxy_resources.golden
index d2ed26563..b2ed0efbe 100644
--- a/viz/cmd/testdata/install_proxy_resources.golden
+++ b/viz/cmd/testdata/install_proxy_resources.golden
@@ -471,7 +471,7 @@ spec:
         - -cluster-domain=cluster.local
         - -prometheus-url=http://linkerd-prometheus.linkerd-viz.svc.cluster.local:9090
         image: ghcr.io/linkerd/metrics-api:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -616,7 +616,7 @@ spec:
         - name: GODEBUG
           value: netdns=go
         image: ghcr.io/linkerd/grafana:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /api/health
@@ -863,12 +863,12 @@ spec:
         fsGroup: 65534
       containers:
       - args:
-        - --config.file=/etc/prometheus/prometheus.yml
         - --log.level=info
+        - --config.file=/etc/prometheus/prometheus.yml
         - --storage.tsdb.path=/data
         - --storage.tsdb.retention.time=6h
         image: prom/prometheus:v2.19.3
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /-/healthy
@@ -976,7 +976,7 @@ spec:
         - -log-level=info
         - -identity-trust-domain=cluster.local
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -1136,7 +1136,7 @@ spec:
         - -tap-service-name=linkerd-tap.linkerd-viz.serviceaccount.identity.$(_l5d_ns).$(_l5d_trustdomain)
         - -log-level=info
         image: ghcr.io/linkerd/tap:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping
@@ -1240,7 +1240,7 @@ spec:
         - -log-level=info
         - -enforced-host=^(localhost|127\.0\.0\.1|linkerd-web\.linkerd-viz\.svc\.cluster\.local|linkerd-web\.linkerd-viz\.svc|\[::1\])(:\d+)?$
         image: ghcr.io/linkerd/web:dev-undefined
-        imagePullPolicy: 
+        imagePullPolicy: IfNotPresent
         livenessProbe:
           httpGet:
             path: /ping