Repository: linkerd/linkerd2
Pull request #12085 (2024-02-15 03:23:50)

build(deps): bump helm.sh/helm/v3 from 3.14.0 to 3.14.1
Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.14.0 to 3.14.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/helm/helm/releases">helm.sh/helm/v3's releases</a>.</em></p>
<blockquote>
<p>Helm v3.14.1 is a security (patch) release. Users are strongly recommended to update to this release.</p>
<p>A Helm contributor discovered a path traversal vulnerability when Helm saves a chart including at download time.</p>
<p><a href="https://github.com/dominykas">Dominykas Blyžė</a> with <a href="https://www.nearform.com/">Nearform Ltd.</a> discovered the vulnerability.</p>
<h2>Installation and Upgrading</h2>
<p>Download Helm v3.14.1. The common platform binaries are here:</p>
<ul>
<li><a href="https://get.helm.sh/helm-v3.14.1-darwin-amd64.tar.gz">MacOS amd64</a> (<a href="https://get.helm.sh/helm-v3.14.1-darwin-amd64.tar.gz.sha256sum">checksum</a> / 67928236b37c4e780b9fb5e614fb3b9aece90d60f0b1b4cb7406ee292c2dae3b)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-darwin-arm64.tar.gz">MacOS arm64</a> (<a href="https://get.helm.sh/helm-v3.14.1-darwin-arm64.tar.gz.sha256sum">checksum</a> / 96468f927cc6efb4a2b92fd9419f40ed21d634af2f3e84fb8efa59526c7a003b)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-amd64.tar.gz">Linux amd64</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-amd64.tar.gz.sha256sum">checksum</a> / 75496ea824f92305ff7d28af37f4af57536bf5138399c824dff997b9d239dd42)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-arm.tar.gz">Linux arm</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-arm.tar.gz.sha256sum">checksum</a> / f50c00c262b74435530e677bcec07637aaeda1ed92ef809b49581a4e6182cbbe)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-arm64.tar.gz">Linux arm64</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-arm64.tar.gz.sha256sum">checksum</a> / f865b8ad4228fd0990bbc5b50615eb6cb9eb31c9a9ca7238401ed897bbbe9033)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-386.tar.gz">Linux i386</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-386.tar.gz.sha256sum">checksum</a> / 3c94ed0601e0e62c195a7e9b75262b18128c8284662aa0e080bb548dc6d47bcd)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-ppc64le.tar.gz">Linux ppc64le</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-ppc64le.tar.gz.sha256sum">checksum</a> / 4d853ab8fe3462287c7272fbadd5f73531ecdd6fa0db37d31630e41ae1ae21de)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-s390x.tar.gz">Linux s390x</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-s390x.tar.gz.sha256sum">checksum</a> / 19bf07999c7244bfeb0fd27152919b9faa1148cf43910edbb98efa9150058a98)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-linux-riscv64.tar.gz">Linux riscv64</a> (<a href="https://get.helm.sh/helm-v3.14.1-linux-riscv64.tar.gz.sha256sum">checksum</a> / 2660bd8eb37aafc071599b788a24bfe244e5d3ffa42da1599da5a5041dafa214)</li>
<li><a href="https://get.helm.sh/helm-v3.14.1-windows-amd64.zip">Windows amd64</a> (<a href="https://get.helm.sh/helm-v3.14.1-windows-amd64.zip.sha256sum">checksum</a> / 8a6c78a23a4e497ad8bd288138588adb3e5b49be8dbe82a3200fe7b297dac184)</li>
</ul>
<p>This release was signed with <code>672C 657B E06B 4B30 969C 4A57 4614 49C2 5E36 B98E </code> and can be found at <a href="https://github.com/mattfarina"><code>@​mattfarina</code></a> <a href="https://keybase.io/mattfarina">keybase account</a>. Please use the attached signatures for verifying this release using <code>gpg</code>.</p>
<p>The <a href="https://helm.sh/docs/intro/quickstart/">Quickstart Guide</a> will get you going from there. For <strong>upgrade instructions</strong> or detailed installation notes, check the <a href="https://helm.sh/docs/intro/install/">install guide</a>. You can also use a <a href="https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3">script to install</a> on any system with <code>bash</code>.</p>
<h2>What's Next</h2>
<ul>
<li>3.14.2 will contain only bug fixes and be released on March 13, 2024.</li>
<li>3.15.0 is the next feature release and will be on May 08, 2024.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/helm/helm/commit/e8858f8696b144ee7c533bd9d49a353ee6c4b98d"><code>e8858f8</code></a> validation fix</li>
<li>See full diff in <a href="https://github.com/helm/helm/compare/v3.14.0...v3.14.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=helm.sh/helm/v3&package-manager=go_modules&previous-version=3.14.0&new-version=3.14.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index e059762a0..5b5c9d964 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -36,7 +36,7 @@ jobs:
     continue-on-error: ${{ matrix.checks == 'advisories' }}
     steps:
     - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
-    - uses: EmbarkStudios/cargo-deny-action@5def368d93be6684ad20a0fdec5f23c8ea11e022
+    - uses: EmbarkStudios/cargo-deny-action@68cd9c5e3e16328a430a37c743167572e3243e7e
       with:
         command: check ${{ matrix.checks }}
 
diff --git a/Cargo.lock b/Cargo.lock
index 72b67e6f2..bdd1dd4c8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -62,9 +62,9 @@ dependencies = [
 
 [[package]]
 name = "anstyle"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
 
 [[package]]
 name = "anyhow"
@@ -441,9 +441,9 @@ checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d"
 
 [[package]]
 name = "either"
-version = "1.8.1"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
 
 [[package]]
 name = "equivalent"
@@ -1377,9 +1377,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
 
 [[package]]
 name = "memchr"
-version = "2.6.4"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 
 [[package]]
 name = "mime"
@@ -2114,9 +2114,9 @@ dependencies = [
 
 [[package]]
 name = "slab"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
 dependencies = [
  "autocfg",
 ]
diff --git a/charts/linkerd-control-plane/templates/destination.yaml b/charts/linkerd-control-plane/templates/destination.yaml
index 5be29aed3..b5800f9b7 100644
--- a/charts/linkerd-control-plane/templates/destination.yaml
+++ b/charts/linkerd-control-plane/templates/destination.yaml
@@ -205,13 +205,21 @@ spec:
         - -identity-trust-domain={{.Values.identityTrustDomain | default .Values.clusterDomain}}
         - -default-opaque-ports={{.Values.proxy.opaquePorts}}
         - -enable-pprof={{.Values.enablePprof | default false}}
+        {{- range (.Values.destinationController).additionalArgs }}
+        - {{ . }}
+        {{- end }}
         {{- range (.Values.destinationController).experimentalArgs }}
         - {{ . }}
         {{- end }}
-        {{- with (.Values.destinationController).experimentalEnv }}
+        {{- if or (.Values.destinationController).additionalEnv (.Values.destinationController).experimentalEnv }}
         env:
+        {{- with (.Values.destinationController).additionalEnv }}
         {{- toYaml . | nindent 8 -}}
         {{- end }}
+        {{- with (.Values.destinationController).experimentalEnv }}
+        {{- toYaml . | nindent 8 -}}
+        {{- end }}
+        {{- end }}
         {{- include "partials.linkerd.trace" . | nindent 8 -}}
         image: {{.Values.controllerImage}}:{{.Values.controllerImageVersion | default .Values.linkerdVersion}}
         imagePullPolicy: {{.Values.imagePullPolicy}}
@@ -249,10 +257,15 @@ spec:
         - -log-level={{.Values.controllerLogLevel}}
         - -log-format={{.Values.controllerLogFormat}}
         - -enable-pprof={{.Values.enablePprof | default false}}
-        {{- with (.Values.spValidator).experimentalEnv }}
+        {{- if or (.Values.spValidator).additionalEnv (.Values.spValidator).experimentalEnv }}
         env:
+        {{- with (.Values.spValidator).additionalEnv }}
+        {{- toYaml . | nindent 8 -}}
+        {{- end }}
+        {{- with (.Values.spValidator).experimentalEnv }}
         {{- toYaml . | nindent 8 -}}
         {{- end }}
+        {{- end }}
         image: {{.Values.controllerImage}}:{{.Values.controllerImageVersion | default .Values.linkerdVersion}}
         imagePullPolicy: {{.Values.imagePullPolicy}}
         livenessProbe:
@@ -305,6 +318,9 @@ spec:
         {{- if .Values.policyController.probeNetworks }}
         - --probe-networks={{.Values.policyController.probeNetworks | join ","}}
         {{- end}}
+        {{- range .Values.policyController.additionalArgs }}
+        - {{ . }}
+        {{- end }}
         {{- range .Values.policyController.experimentalArgs }}
         - {{ . }}
         {{- end }}
diff --git a/charts/linkerd-control-plane/templates/heartbeat.yaml b/charts/linkerd-control-plane/templates/heartbeat.yaml
index 8b3d1e1b9..d96318786 100644
--- a/charts/linkerd-control-plane/templates/heartbeat.yaml
+++ b/charts/linkerd-control-plane/templates/heartbeat.yaml
@@ -59,6 +59,9 @@ spec:
             env:
             - name: LINKERD_DISABLED
               value: "the heartbeat controller does not use the proxy"
+            {{- with (.Values.heartbeat).additionalEnv }}
+            {{- toYaml . | nindent 12 -}}
+            {{- end }}
             {{- with (.Values.heartbeat).experimentalEnv }}
             {{- toYaml . | nindent 12 -}}
             {{- end }}
diff --git a/charts/linkerd-control-plane/templates/identity.yaml b/charts/linkerd-control-plane/templates/identity.yaml
index ae375f200..83532c53d 100644
--- a/charts/linkerd-control-plane/templates/identity.yaml
+++ b/charts/linkerd-control-plane/templates/identity.yaml
@@ -165,6 +165,9 @@ spec:
         env:
         - name: LINKERD_DISABLED
           value: "linkerd-await cannot block the identity controller"
+        {{- with (.Values.identity).additionalEnv }}
+        {{- toYaml . | nindent 8 -}}
+        {{- end }}
         {{- with (.Values.identity).experimentalEnv }}
         {{- toYaml . | nindent 8 -}}
         {{- end }}
diff --git a/charts/linkerd-control-plane/templates/proxy-injector.yaml b/charts/linkerd-control-plane/templates/proxy-injector.yaml
index 8837af9bd..d3038df73 100644
--- a/charts/linkerd-control-plane/templates/proxy-injector.yaml
+++ b/charts/linkerd-control-plane/templates/proxy-injector.yaml
@@ -79,10 +79,15 @@ spec:
         - -log-format={{.Values.controllerLogFormat}}
         - -linkerd-namespace={{.Release.Namespace}}
         - -enable-pprof={{.Values.enablePprof | default false}}
-        {{- with (.Values.proxyInjector).experimentalEnv }}
+        {{- if or (.Values.proxyInjector).additionalEnv (.Values.proxyInjector).experimentalEnv }}
         env:
+        {{- with (.Values.proxyInjector).additionalEnv }}
         {{- toYaml . | nindent 8 -}}
         {{- end }}
+        {{- with (.Values.proxyInjector).experimentalEnv }}
+        {{- toYaml . | nindent 8 -}}
+        {{- end }}
+        {{- end }}
         image: {{.Values.controllerImage}}:{{.Values.controllerImageVersion | default .Values.linkerdVersion}}
         imagePullPolicy: {{.Values.imagePullPolicy}}
         livenessProbe:
diff --git a/charts/partials/templates/_proxy.tpl b/charts/partials/templates/_proxy.tpl
index d48f476ea..1db5c8779 100644
--- a/charts/partials/templates/_proxy.tpl
+++ b/charts/partials/templates/_proxy.tpl
@@ -160,6 +160,9 @@ be used in other contexts.
 - name: LINKERD2_PROXY_SHUTDOWN_GRACE_PERIOD
   value: {{.Values.proxy.shutdownGracePeriod | quote}}
 {{ end -}}
+{{ if .Values.proxy.additionalEnv -}}
+{{ toYaml .Values.proxy.additionalEnv }}
+{{ end -}}
 {{ if .Values.proxy.experimentalEnv -}}
 {{ toYaml .Values.proxy.experimentalEnv }}
 {{ end -}}
diff --git a/controller/api/destination/external-workload/endpoints_controller.go b/controller/api/destination/external-workload/endpoints_controller.go
index d669a2e36..94866f15a 100644
--- a/controller/api/destination/external-workload/endpoints_controller.go
+++ b/controller/api/destination/external-workload/endpoints_controller.go
@@ -62,6 +62,7 @@ type EndpointsController struct {
 
 	lec leaderelection.LeaderElectionConfig
 	informerHandlers
+	dropsMetric workqueue.CounterMetric
 }
 
 // informerHandlers holds handles to callbacks that have been registered with
@@ -93,11 +94,16 @@ type informerHandlers struct {
 // NewEndpointsController creates a new controller. The controller must be
 // started with its `Start()` method.
 func NewEndpointsController(k8sAPI *k8s.API, hostname, controllerNs string, stopCh chan struct{}, exportQueueMetrics bool) (*EndpointsController, error) {
+	queueName := "endpoints_controller_workqueue"
 	workQueueConfig := workqueue.RateLimitingQueueConfig{
-		Name: "endpoints_controller_workqueue",
+		Name: queueName,
 	}
+
+	var dropsMetric workqueue.CounterMetric = &noopCounterMetric{}
 	if exportQueueMetrics {
-		workQueueConfig.MetricsProvider = newWorkQueueMetricsProvider()
+		provider := newWorkQueueMetricsProvider()
+		workQueueConfig.MetricsProvider = provider
+		dropsMetric = provider.NewDropsMetric(queueName)
 	}
 
 	ec := &EndpointsController{
@@ -108,6 +114,7 @@ func NewEndpointsController(k8sAPI *k8s.API, hostname, controllerNs string, stop
 		log: logging.WithFields(logging.Fields{
 			"component": "external-endpoints-controller",
 		}),
+		dropsMetric: dropsMetric,
 	}
 
 	// Store configuration for leader elector client. The leader elector will
@@ -333,6 +340,7 @@ func (ec *EndpointsController) handleError(err error, key string) {
 	}
 
 	ec.queue.Forget(key)
+	ec.dropsMetric.Inc()
 	ec.log.Errorf("dropped Service %s out of update queue: %v", key, err)
 }
 
@@ -389,7 +397,7 @@ func (ec *EndpointsController) syncService(update string) error {
 
 	epSlices = dropEndpointSlicesPendingDeletion(epSlices)
 	if ec.reconciler.endpointTracker.StaleSlices(svc, epSlices) {
-		ec.log.Warnf("detected EndpointSlice informer cache is out of date when processing %s", svc)
+		ec.log.Warnf("detected EndpointSlice informer cache is out of date when processing %s", update)
 		return errors.New("EndpointSlice informer cache is out of date")
 	}
 	err = ec.reconciler.reconcile(svc, ews, epSlices)
diff --git a/controller/api/destination/external-workload/queue_metrics.go b/controller/api/destination/external-workload/queue_metrics.go
index b5a1a051b..ae512c2c4 100644
--- a/controller/api/destination/external-workload/queue_metrics.go
+++ b/controller/api/destination/external-workload/queue_metrics.go
@@ -23,6 +23,7 @@ const (
 	UnfinishedWorkKey          = "unfinished_work_seconds"
 	LongestRunningProcessorKey = "longest_running_processor_seconds"
 	RetriesKey                 = "retries_total"
+	DropsTotalKey              = "drops_total"
 )
 
 type queueMetricsProvider struct {
@@ -33,9 +34,10 @@ type queueMetricsProvider struct {
 	unfinished              *prometheus.GaugeVec
 	longestRunningProcessor *prometheus.GaugeVec
 	retries                 *prometheus.CounterVec
+	drops                   *prometheus.CounterVec
 }
 
-func newWorkQueueMetricsProvider() workqueue.MetricsProvider {
+func newWorkQueueMetricsProvider() *queueMetricsProvider {
 	return &queueMetricsProvider{
 		depth: promauto.NewGaugeVec(prometheus.GaugeOpts{
 			Subsystem: WorkQueueSubsystem,
@@ -84,6 +86,11 @@ func newWorkQueueMetricsProvider() workqueue.MetricsProvider {
 			Name:      RetriesKey,
 			Help:      "Total number of retries handled by workqueue",
 		}, []string{"name"}),
+		drops: promauto.NewCounterVec(prometheus.CounterOpts{
+			Subsystem: WorkQueueSubsystem,
+			Name:      DropsTotalKey,
+			Help:      "Total number of dropped items from the queue due to exceeding retry threshold",
+		}, []string{"name"}),
 	}
 }
 
@@ -114,3 +121,11 @@ func (p queueMetricsProvider) NewLongestRunningProcessorSecondsMetric(name strin
 func (p queueMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric {
 	return p.retries.WithLabelValues(name)
 }
+
+func (p queueMetricsProvider) NewDropsMetric(name string) workqueue.CounterMetric {
+	return p.drops.WithLabelValues(name)
+}
+
+type noopCounterMetric struct{}
+
+func (noopCounterMetric) Inc() {}
diff --git a/go.mod b/go.mod
index cc06fbe9d..401a9a61e 100644
--- a/go.mod
+++ b/go.mod
@@ -38,7 +38,7 @@ require (
 	google.golang.org/grpc v1.61.0
 	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
 	google.golang.org/protobuf v1.32.0
-	helm.sh/helm/v3 v3.14.0
+	helm.sh/helm/v3 v3.14.1
 	k8s.io/api v0.29.1
 	k8s.io/apiextensions-apiserver v0.29.1
 	k8s.io/apimachinery v0.29.1
diff --git a/go.sum b/go.sum
index d10b96d21..f8aa27035 100644
--- a/go.sum
+++ b/go.sum
@@ -750,8 +750,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
 gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
-helm.sh/helm/v3 v3.14.0 h1:TaZIH6uOchn7L27ptwnnuHJiFrT/BsD4dFdp/HLT2nM=
-helm.sh/helm/v3 v3.14.0/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
+helm.sh/helm/v3 v3.14.1 h1:4AwRLx+wfzlPtvrsbDmWP5PUokGmf9/nAmEdk21vae8=
+helm.sh/helm/v3 v3.14.1/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/multicluster/charts/linkerd-multicluster-link/templates/service-mirror.yaml b/multicluster/charts/linkerd-multicluster-link/templates/service-mirror.yaml
index 55b4a5564..33ecc1b8d 100644
--- a/multicluster/charts/linkerd-multicluster-link/templates/service-mirror.yaml
+++ b/multicluster/charts/linkerd-multicluster-link/templates/service-mirror.yaml
@@ -139,10 +139,15 @@ spec:
         {{- end }}
         - -enable-pprof={{.Values.enablePprof | default false}}
         - {{.Values.targetClusterName}}
-        {{- with .Values.serviceMirrorExperimentalEnv }}
+        {{- if or .Values.serviceMirrorAdditionalEnv .Values.serviceMirrorExperimentalEnv }}
         env:
+        {{- with .Values.serviceMirrorAdditionalEnv }}
         {{- toYaml . | nindent 8 -}}
         {{- end }}
+        {{- with .Values.serviceMirrorExperimentalEnv }}
+        {{- toYaml . | nindent 8 -}}
+        {{- end }}
+        {{- end }}
         image: {{.Values.controllerImage}}:{{.Values.controllerImageVersion}}
         name: service-mirror
         securityContext:
diff --git a/pkg/charts/linkerd2/values.go b/pkg/charts/linkerd2/values.go
index 001f91c21..d71bdb377 100644
--- a/pkg/charts/linkerd2/values.go
+++ b/pkg/charts/linkerd2/values.go
@@ -125,6 +125,7 @@ type (
 		LivenessProbe                        *Probe           `json:"livenessProbe"`
 		Control                              *ProxyControl    `json:"control"`
 
+		AdditionalEnv   []corev1.EnvVar `json:"additionalEnv"`
 		ExperimentalEnv []corev1.EnvVar `json:"experimentalEnv"`
 	}
 
diff --git a/pkg/k8s/api.go b/pkg/k8s/api.go
index 6ace4a1a9..b8f74ba51 100644
--- a/pkg/k8s/api.go
+++ b/pkg/k8s/api.go
@@ -306,6 +306,11 @@ func GetProxyReady(pod corev1.Pod) bool {
 func GetProxyVersion(pod corev1.Pod) string {
 	for _, container := range pod.Spec.Containers {
 		if container.Name == ProxyContainerName {
+			if strings.Contains(container.Image, "@") {
+				// Proxy container image is specified with digest instead of
+				// tag. We are unable to determine version.
+				return ""
+			}
 			parts := strings.Split(container.Image, ":")
 			return parts[len(parts)-1]
 		}


Test patch:
diff --git a/cli/cmd/testdata/install_controlplane_tracing_output.golden b/cli/cmd/testdata/install_controlplane_tracing_output.golden
index 09aa61c96..81bfa48ae 100644
--- a/cli/cmd/testdata/install_controlplane_tracing_output.golden
+++ b/cli/cmd/testdata/install_controlplane_tracing_output.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1051,7 +1052,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1388,7 +1388,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1825,7 +1824,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_custom_domain.golden b/cli/cmd/testdata/install_custom_domain.golden
index aa1419beb..70d0537f7 100644
--- a/cli/cmd/testdata/install_custom_domain.golden
+++ b/cli/cmd/testdata/install_custom_domain.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1387,7 +1387,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1823,7 +1822,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_custom_registry.golden b/cli/cmd/testdata/install_custom_registry.golden
index bc976390d..5af4971ed 100644
--- a/cli/cmd/testdata/install_custom_registry.golden
+++ b/cli/cmd/testdata/install_custom_registry.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1387,7 +1387,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1823,7 +1822,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_default.golden b/cli/cmd/testdata/install_default.golden
index aa1419beb..70d0537f7 100644
--- a/cli/cmd/testdata/install_default.golden
+++ b/cli/cmd/testdata/install_default.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1387,7 +1387,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1823,7 +1822,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
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 102310549..d9aa52d57 100644
--- a/cli/cmd/testdata/install_default_override_dst_get_nets.golden
+++ b/cli/cmd/testdata/install_default_override_dst_get_nets.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1387,7 +1387,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1823,7 +1822,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_default_token.golden b/cli/cmd/testdata/install_default_token.golden
index 660be38b5..29af9b70f 100644
--- a/cli/cmd/testdata/install_default_token.golden
+++ b/cli/cmd/testdata/install_default_token.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1378,7 +1378,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1805,7 +1804,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_ha_output.golden b/cli/cmd/testdata/install_ha_output.golden
index 017463aac..dd796905d 100644
--- a/cli/cmd/testdata/install_ha_output.golden
+++ b/cli/cmd/testdata/install_ha_output.golden
@@ -663,6 +663,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1127,7 +1128,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1504,7 +1504,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1976,7 +1975,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
diff --git a/cli/cmd/testdata/install_ha_with_overrides_output.golden b/cli/cmd/testdata/install_ha_with_overrides_output.golden
index 41700a1ab..4344954b4 100644
--- a/cli/cmd/testdata/install_ha_with_overrides_output.golden
+++ b/cli/cmd/testdata/install_ha_with_overrides_output.golden
@@ -663,6 +663,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1127,7 +1128,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1504,7 +1504,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1976,7 +1975,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
diff --git a/cli/cmd/testdata/install_heartbeat_disabled_output.golden b/cli/cmd/testdata/install_heartbeat_disabled_output.golden
index e1a0e8902..000089bae 100644
--- a/cli/cmd/testdata/install_heartbeat_disabled_output.golden
+++ b/cli/cmd/testdata/install_heartbeat_disabled_output.golden
@@ -567,6 +567,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -981,7 +982,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1318,7 +1318,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1694,7 +1693,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_helm_control_plane_output.golden b/cli/cmd/testdata/install_helm_control_plane_output.golden
index f8e4238b6..5ec38201c 100644
--- a/cli/cmd/testdata/install_helm_control_plane_output.golden
+++ b/cli/cmd/testdata/install_helm_control_plane_output.golden
@@ -613,6 +613,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1023,7 +1024,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1362,7 +1362,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1802,7 +1801,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_helm_control_plane_output_ha.golden b/cli/cmd/testdata/install_helm_control_plane_output_ha.golden
index b36f01cfa..28c32f2e0 100644
--- a/cli/cmd/testdata/install_helm_control_plane_output_ha.golden
+++ b/cli/cmd/testdata/install_helm_control_plane_output_ha.golden
@@ -640,6 +640,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1100,7 +1101,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1479,7 +1479,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1955,7 +1954,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
diff --git a/cli/cmd/testdata/install_helm_output_ha_labels.golden b/cli/cmd/testdata/install_helm_output_ha_labels.golden
index 6b5262f39..d6d4aa5b2 100644
--- a/cli/cmd/testdata/install_helm_output_ha_labels.golden
+++ b/cli/cmd/testdata/install_helm_output_ha_labels.golden
@@ -644,6 +644,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1108,7 +1109,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1491,7 +1491,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1975,7 +1974,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
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 e74dcb070..39be13d24 100644
--- a/cli/cmd/testdata/install_helm_output_ha_namespace_selector.golden
+++ b/cli/cmd/testdata/install_helm_output_ha_namespace_selector.golden
@@ -635,6 +635,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1090,7 +1091,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1469,7 +1469,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
@@ -1945,7 +1944,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             memory: "250Mi"
diff --git a/cli/cmd/testdata/install_no_init_container.golden b/cli/cmd/testdata/install_no_init_container.golden
index a02ffb86f..c112e8a7d 100644
--- a/cli/cmd/testdata/install_no_init_container.golden
+++ b/cli/cmd/testdata/install_no_init_container.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1381,7 +1381,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1811,7 +1810,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_output.golden b/cli/cmd/testdata/install_output.golden
index 99996d252..b3e78daba 100644
--- a/cli/cmd/testdata/install_output.golden
+++ b/cli/cmd/testdata/install_output.golden
@@ -616,6 +616,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control: null
@@ -1348,7 +1349,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             cpu: "cpu-limit"
@@ -1788,7 +1788,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
           limits:
             cpu: "cpu-limit"
diff --git a/cli/cmd/testdata/install_proxy_ignores.golden b/cli/cmd/testdata/install_proxy_ignores.golden
index 1d56deb06..9465393ab 100644
--- a/cli/cmd/testdata/install_proxy_ignores.golden
+++ b/cli/cmd/testdata/install_proxy_ignores.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1387,7 +1387,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1823,7 +1822,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/cli/cmd/testdata/install_values_file.golden b/cli/cmd/testdata/install_values_file.golden
index e4d7b0ed9..9e4559ac2 100644
--- a/cli/cmd/testdata/install_values_file.golden
+++ b/cli/cmd/testdata/install_values_file.golden
@@ -636,6 +636,7 @@ data:
     prometheusUrl: ""
     proxy:
       accessLog: ""
+      additionalEnv: null
       await: true
       capabilities: null
       control:
@@ -1050,7 +1051,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1387,7 +1387,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
@@ -1823,7 +1822,6 @@ spec:
             port: 4191
           initialDelaySeconds: 2
           timeoutSeconds: 1
-          initialDelaySeconds: 2
         resources:
         securityContext:
           allowPrivilegeEscalation: false
diff --git a/policy-test/src/lib.rs b/policy-test/src/lib.rs
index 1ca964591..71583df87 100644
--- a/policy-test/src/lib.rs
+++ b/policy-test/src/lib.rs
@@ -173,7 +173,12 @@ pub async fn await_route_status(
 // Wait for the endpoints controller to populate the Endpoints resource.
 pub fn endpoints_ready(obj: Option<&k8s::Endpoints>) -> bool {
     if let Some(ep) = obj {
-        return ep.subsets.iter().flatten().count() > 0;
+        return ep
+            .subsets
+            .iter()
+            .flatten()
+            .flat_map(|s| &s.addresses)
+            .any(|a| !a.is_empty());
     }
     false
 }