Repository: linkerd/linkerd2
Pull request #12870 (2024-07-22 03:21:42)

build(deps): bump openssl from 0.10.64 to 0.10.66
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.64 to 0.10.66.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/sfackler/rust-openssl/releases">openssl's releases</a>.</em></p>
<blockquote>
<h2>openssl-v0.10.66</h2>
<h2>What's Changed</h2>
<ul>
<li>Fixed invariant violation in <code>MemBio::get_buf</code> with empty results by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2266">sfackler/rust-openssl#2266</a></li>
<li>Release openssl v0.10.66 by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2267">sfackler/rust-openssl#2267</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.65...openssl-v0.10.66">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.65...openssl-v0.10.66</a></p>
<h2>openssl-v0.10.65</h2>
<h2>What's Changed</h2>
<ul>
<li>don't emit rerun-if-changed when vendoring by <a href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2177">sfackler/rust-openssl#2177</a></li>
<li>Prepare for openssl-sys 0.9.101 release by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2182">sfackler/rust-openssl#2182</a></li>
<li>don't emit rerun-if-changed unless the path exists and is readable by <a href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2187">sfackler/rust-openssl#2187</a></li>
<li>Added support for LibreSSL 3.9.0 by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2202">sfackler/rust-openssl#2202</a></li>
<li>Support stable LibreSSL 3.9.x by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2209">sfackler/rust-openssl#2209</a></li>
<li>openssl-sys 0.9.102 release by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2210">sfackler/rust-openssl#2210</a></li>
<li>Add repository field to openssl-macros crate by <a href="https://github.com/paolobarbolini"><code>@​paolobarbolini</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2211">sfackler/rust-openssl#2211</a></li>
<li>Add missing openssl-sys dependency by <a href="https://github.com/pieterdd"><code>@​pieterdd</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2212">sfackler/rust-openssl#2212</a></li>
<li>Test OpenSSL 3.3.0-beta1 by <a href="https://github.com/sfackler"><code>@​sfackler</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2216">sfackler/rust-openssl#2216</a></li>
<li>test against 3.3.0 final by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2218">sfackler/rust-openssl#2218</a></li>
<li>fix min-versions in CI by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2228">sfackler/rust-openssl#2228</a></li>
<li>Make X509_VAL opaque for LibreSSL 4.0.0 by <a href="https://github.com/botovq"><code>@​botovq</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2227">sfackler/rust-openssl#2227</a></li>
<li>Use the newer names for STACK_OF(T) functions with BoringSSL by <a href="https://github.com/davidben"><code>@​davidben</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2231">sfackler/rust-openssl#2231</a></li>
<li>Only declare OpensslCallbacks in bindgen builds by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2234">sfackler/rust-openssl#2234</a></li>
<li>Fix building with latest BoringSSL by <a href="https://github.com/davidben"><code>@​davidben</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2230">sfackler/rust-openssl#2230</a></li>
<li>Emit rustc-check-cfg for nightly by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2235">sfackler/rust-openssl#2235</a></li>
<li>Configure OpenSSL data dir on vendored builds. by <a href="https://github.com/DanielSidhion"><code>@​DanielSidhion</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2122">sfackler/rust-openssl#2122</a></li>
<li>Add boringssl keylog callback support by <a href="https://github.com/mspublic"><code>@​mspublic</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2237">sfackler/rust-openssl#2237</a></li>
<li>Correct the name of the <code>pkgconf</code> package on some distros  by <a href="https://github.com/JonathanBrouwer"><code>@​JonathanBrouwer</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2253">sfackler/rust-openssl#2253</a></li>
<li>Add some OpenSSL 3 QUIC raw bindings by <a href="https://github.com/bdbai"><code>@​bdbai</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2257">sfackler/rust-openssl#2257</a></li>
<li>Initialize OpenSSL in MD constructors by <a href="https://github.com/sfackler"><code>@​sfackler</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2258">sfackler/rust-openssl#2258</a></li>
<li>Switch Pkey::from_ to use set1 functions by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2262">sfackler/rust-openssl#2262</a></li>
<li>Release openssl v0.10.65 and openssl-sys v0.9.103 by <a href="https://github.com/alex"><code>@​alex</code></a> in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2265">sfackler/rust-openssl#2265</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/paolobarbolini"><code>@​paolobarbolini</code></a> made their first contribution in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2211">sfackler/rust-openssl#2211</a></li>
<li><a href="https://github.com/pieterdd"><code>@​pieterdd</code></a> made their first contribution in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2212">sfackler/rust-openssl#2212</a></li>
<li><a href="https://github.com/DanielSidhion"><code>@​DanielSidhion</code></a> made their first contribution in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2122">sfackler/rust-openssl#2122</a></li>
<li><a href="https://github.com/mspublic"><code>@​mspublic</code></a> made their first contribution in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2237">sfackler/rust-openssl#2237</a></li>
<li><a href="https://github.com/JonathanBrouwer"><code>@​JonathanBrouwer</code></a> made their first contribution in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2253">sfackler/rust-openssl#2253</a></li>
<li><a href="https://github.com/bdbai"><code>@​bdbai</code></a> made their first contribution in <a href="https://redirect.github.com/sfackler/rust-openssl/pull/2257">sfackler/rust-openssl#2257</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.65">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.65</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/sfackler/rust-openssl/commit/ad70a0bea581e53fc5086afffa5bdfe6eb1b5f49"><code>ad70a0b</code></a> Merge pull request <a href="https://redirect.github.com/sfackler/rust-openssl/issues/2267">#2267</a> from alex/bump-for-release</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/5ce473b4e56e8c68e11428d2e9fdb0abf984aa59"><code>5ce473b</code></a> Release openssl v0.10.66</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/aef36e0f3950653148d6644309ee41ccf16e02bb"><code>aef36e0</code></a> Merge pull request <a href="https://redirect.github.com/sfackler/rust-openssl/issues/2266">#2266</a> from alex/mem-bio-invariant</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/142deef717bad843fc04c5afb925bfd9e7dc4305"><code>142deef</code></a> Fixed invariant violation in <code>MemBio::get_buf</code> with empty results</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/32f150b05a8996a14561741bceab66a95043cd57"><code>32f150b</code></a> Merge pull request <a href="https://redirect.github.com/sfackler/rust-openssl/issues/2265">#2265</a> from alex/bump-for-release</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/98addd271ec1edf3cd598ed093c1c82a081b91eb"><code>98addd2</code></a> Release openssl v0.10.65 and openssl-sys v0.9.103</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/7c7958d436cec622c5af39063db8541b4641e73e"><code>7c7958d</code></a> Merge pull request <a href="https://redirect.github.com/sfackler/rust-openssl/issues/2262">#2262</a> from alex/pkey-api</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/d7b12ccf1f6864f99ba24080567b38bbd82f39ab"><code>d7b12cc</code></a> Switch Pkey::from_ to use set1 functions</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/22ffa9add64d962782d993fae0cd9b348d3b43cd"><code>22ffa9a</code></a> Merge pull request <a href="https://redirect.github.com/sfackler/rust-openssl/issues/2258">#2258</a> from sfackler/init-md</li>
<li><a href="https://github.com/sfackler/rust-openssl/commit/9de3794474d8440e80d362531f82d0d9ce07c22a"><code>9de3794</code></a> Initialize OpenSSL in MD constructors</li>
<li>Additional commits viewable in <a href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.66">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=openssl&package-manager=cargo&previous-version=0.10.64&new-version=0.10.66)](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/go.yml b/.github/workflows/go.yml
index fe42bda5c..7d2131da2 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-22.04
     steps:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
-      - uses: tj-actions/changed-files@cc733854b1f224978ef800d29e4709d5ee2883e4
+      - uses: tj-actions/changed-files@6b2903bdce6310cfbddd87c418f253cf29b2dec9
         id: changed
         with:
           files: |
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index 022948e02..b00b3fbd7 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -28,7 +28,7 @@ jobs:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
       - id: tag
         run: echo "tag=$(CI_FORCE_CLEAN=1 bin/root-tag)" >> "$GITHUB_OUTPUT"
-      - uses: tj-actions/changed-files@cc733854b1f224978ef800d29e4709d5ee2883e4
+      - uses: tj-actions/changed-files@6b2903bdce6310cfbddd87c418f253cf29b2dec9
         id: core
         with:
           files: |
diff --git a/Cargo.lock b/Cargo.lock
index 223aeead6..cf4bef84c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1454,9 +1454,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "openssl"
-version = "0.10.64"
+version = "0.10.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
+checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
 dependencies = [
  "bitflags 2.5.0",
  "cfg-if",
@@ -1495,9 +1495,9 @@ dependencies = [
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.102"
+version = "0.9.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
+checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
 dependencies = [
  "cc",
  "libc",
diff --git a/charts/linkerd-crds/templates/policy/server.yaml b/charts/linkerd-crds/templates/policy/server.yaml
index ac3215c02..0af41224a 100644
--- a/charts/linkerd-crds/templates/policy/server.yaml
+++ b/charts/linkerd-crds/templates/policy/server.yaml
@@ -74,7 +74,7 @@ spec:
       served: true
       storage: false
       deprecated: true
-      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta2 Server"
+      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta3 Server"
       schema:
         openAPIV3Schema:
           type: object
@@ -133,6 +133,94 @@ spec:
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
     - name: v1beta2
+      served: true
+      storage: false
+      schema:
+        openAPIV3Schema:
+          type: object
+          required: [spec]
+          properties:
+            spec:
+              type: object
+              required:
+                - port
+              oneOf:
+                - required: [podSelector]
+                - required: [externalWorkloadSelector]
+              properties:
+                podSelector:
+                  type: object
+                  description: >-
+                    Selects pods in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                externalWorkloadSelector:
+                  type: object
+                  description: >-
+                    Selects ExternalWorkloads in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                port:
+                  description: >-
+                    A port name or number. Must exist in a pod spec.
+                  x-kubernetes-int-or-string: true
+                proxyProtocol:
+                  description: >-
+                    Configures protocol discovery for inbound connections.
+
+                    Supersedes the `config.linkerd.io/opaque-ports` annotation.
+                  type: string
+                  default: unknown
+      additionalPrinterColumns:
+      - name: Port
+        type: string
+        description: The port the server is listening on
+        jsonPath: .spec.port
+      - name: Protocol
+        type: string
+        description: The protocol of the server
+        jsonPath: .spec.proxyProtocol
+    - name: v1beta3
       served: true
       storage: true
       schema:
@@ -148,6 +236,11 @@ spec:
                 - required: [podSelector]
                 - required: [externalWorkloadSelector]
               properties:
+                accessPolicy:
+                  type: string
+                  default: deny
+                  description: >-
+                    Default access policy to apply when the traffic doesn't match any of the policy rules.
                 podSelector:
                   type: object
                   description: >-
@@ -220,3 +313,7 @@ spec:
         type: string
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
+      - name: Access Policy
+        type: string
+        description: The default access policy applied when the traffic doesn't match any of the policy rules
+        jsonPath: .spec.accessPolicy
diff --git a/controller/api/destination/watcher/endpoints_watcher.go b/controller/api/destination/watcher/endpoints_watcher.go
index 6bc0be848..800035bea 100644
--- a/controller/api/destination/watcher/endpoints_watcher.go
+++ b/controller/api/destination/watcher/endpoints_watcher.go
@@ -11,7 +11,7 @@ import (
 	"time"
 
 	ewv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/externalworkload/v1beta1"
-	"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	"github.com/linkerd/linkerd2/controller/k8s"
 	consts "github.com/linkerd/linkerd2/pkg/k8s"
 	"github.com/prometheus/client_golang/prometheus"
@@ -536,7 +536,7 @@ func (ew *EndpointsWatcher) getServicePublisher(id ServiceID) (sp *servicePublis
 func (ew *EndpointsWatcher) addServer(obj interface{}) {
 	ew.Lock()
 	defer ew.Unlock()
-	server := obj.(*v1beta2.Server)
+	server := obj.(*v1beta3.Server)
 	for _, sp := range ew.publishers {
 		sp.updateServer(nil, server)
 	}
@@ -546,8 +546,8 @@ func (ew *EndpointsWatcher) updateServer(oldObj interface{}, newObj interface{})
 	ew.Lock()
 	defer ew.Unlock()
 
-	oldServer := oldObj.(*v1beta2.Server)
-	newServer := newObj.(*v1beta2.Server)
+	oldServer := oldObj.(*v1beta3.Server)
+	newServer := newObj.(*v1beta3.Server)
 	if oldServer != nil && newServer != nil {
 		oldUpdated := latestUpdated(oldServer.ManagedFields)
 		updated := latestUpdated(newServer.ManagedFields)
@@ -576,7 +576,7 @@ func (ew *EndpointsWatcher) updateServer(oldObj interface{}, newObj interface{})
 func (ew *EndpointsWatcher) deleteServer(obj interface{}) {
 	ew.Lock()
 	defer ew.Unlock()
-	server := obj.(*v1beta2.Server)
+	server := obj.(*v1beta3.Server)
 	for _, sp := range ew.publishers {
 		sp.updateServer(server, nil)
 	}
@@ -751,7 +751,7 @@ func (sp *servicePublisher) metricsLabels(port Port, hostname string) prometheus
 	return endpointsLabels(sp.cluster, sp.id.Namespace, sp.id.Name, strconv.Itoa(int(port)), hostname)
 }
 
-func (sp *servicePublisher) updateServer(oldServer, newServer *v1beta2.Server) {
+func (sp *servicePublisher) updateServer(oldServer, newServer *v1beta3.Server) {
 	sp.Lock()
 	defer sp.Unlock()
 
@@ -1311,7 +1311,7 @@ func (pp *portPublisher) unsubscribe(listener EndpointUpdateListener) {
 
 	pp.metrics.setSubscribers(len(pp.listeners))
 }
-func (pp *portPublisher) updateServer(oldServer, newServer *v1beta2.Server) {
+func (pp *portPublisher) updateServer(oldServer, newServer *v1beta3.Server) {
 	updated := false
 	for id, address := range pp.addresses.Addresses {
 
@@ -1335,7 +1335,7 @@ func (pp *portPublisher) updateServer(oldServer, newServer *v1beta2.Server) {
 	}
 }
 
-func (pp *portPublisher) isAddressSelected(address Address, server *v1beta2.Server) bool {
+func (pp *portPublisher) isAddressSelected(address Address, server *v1beta3.Server) bool {
 	if server == nil {
 		return false
 	}
diff --git a/controller/api/destination/watcher/workload_watcher.go b/controller/api/destination/watcher/workload_watcher.go
index 45529b680..d9d2ca109 100644
--- a/controller/api/destination/watcher/workload_watcher.go
+++ b/controller/api/destination/watcher/workload_watcher.go
@@ -10,7 +10,7 @@ import (
 	"time"
 
 	ext "github.com/linkerd/linkerd2/controller/gen/apis/externalworkload/v1beta1"
-	"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	"github.com/linkerd/linkerd2/controller/k8s"
 	consts "github.com/linkerd/linkerd2/pkg/k8s"
 	"github.com/linkerd/linkerd2/pkg/util"
@@ -299,8 +299,8 @@ func (ww *WorkloadWatcher) submitExternalWorkloadUpdate(externalWorkload *ext.Ex
 }
 
 func (ww *WorkloadWatcher) updateServer(oldObj interface{}, newObj interface{}) {
-	oldServer := oldObj.(*v1beta2.Server)
-	newServer := newObj.(*v1beta2.Server)
+	oldServer := oldObj.(*v1beta3.Server)
+	newServer := newObj.(*v1beta3.Server)
 
 	oldUpdated := latestUpdated(oldServer.ManagedFields)
 	updated := latestUpdated(newServer.ManagedFields)
@@ -314,14 +314,14 @@ func (ww *WorkloadWatcher) updateServer(oldObj interface{}, newObj interface{})
 }
 
 func (ww *WorkloadWatcher) addOrDeleteServer(obj interface{}) {
-	server, ok := obj.(*v1beta2.Server)
+	server, ok := obj.(*v1beta3.Server)
 	if !ok {
 		tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
 		if !ok {
 			ww.log.Errorf("Couldn't get object from DeletedFinalStateUnknown %#v", obj)
 			return
 		}
-		server, ok = tombstone.Obj.(*v1beta2.Server)
+		server, ok = tombstone.Obj.(*v1beta3.Server)
 		if !ok {
 			ww.log.Errorf("DeletedFinalStateUnknown contained object that is not a Server %#v", obj)
 			return
@@ -334,7 +334,7 @@ func (ww *WorkloadWatcher) addOrDeleteServer(obj interface{}) {
 // whose pod matches the any of the Servers' podSelector or whose
 // externalworkload matches any of the Servers' externalworkload selection. This
 // function is an event handler so it cannot block.
-func (ww *WorkloadWatcher) updateServers(servers ...*v1beta2.Server) {
+func (ww *WorkloadWatcher) updateServers(servers ...*v1beta3.Server) {
 	ww.mu.RLock()
 	defer ww.mu.RUnlock()
 
@@ -390,7 +390,7 @@ func (ww *WorkloadWatcher) updateServers(servers ...*v1beta2.Server) {
 	}
 }
 
-func (ww *WorkloadWatcher) isPodSelectedByAny(pod *corev1.Pod, servers ...*v1beta2.Server) bool {
+func (ww *WorkloadWatcher) isPodSelectedByAny(pod *corev1.Pod, servers ...*v1beta3.Server) bool {
 	for _, s := range servers {
 		selector, err := metav1.LabelSelectorAsSelector(s.Spec.PodSelector)
 		if err != nil {
@@ -404,7 +404,7 @@ func (ww *WorkloadWatcher) isPodSelectedByAny(pod *corev1.Pod, servers ...*v1bet
 	return false
 }
 
-func (ww *WorkloadWatcher) isExternalWorkloadSelectedByAny(ew *ext.ExternalWorkload, servers ...*v1beta2.Server) bool {
+func (ww *WorkloadWatcher) isExternalWorkloadSelectedByAny(ew *ext.ExternalWorkload, servers ...*v1beta3.Server) bool {
 	for _, s := range servers {
 		selector, err := metav1.LabelSelectorAsSelector(s.Spec.ExternalWorkloadSelector)
 		if err != nil {
diff --git a/controller/gen/apis/server/v1beta3/doc.go b/controller/gen/apis/server/v1beta3/doc.go
new file mode 100644
index 000000000..0eecc56c2
--- /dev/null
+++ b/controller/gen/apis/server/v1beta3/doc.go
@@ -0,0 +1,3 @@
+// +k8s:deepcopy-gen=package
+
+package v1beta3
diff --git a/controller/gen/apis/server/v1beta3/register.go b/controller/gen/apis/server/v1beta3/register.go
new file mode 100644
index 000000000..82b647289
--- /dev/null
+++ b/controller/gen/apis/server/v1beta3/register.go
@@ -0,0 +1,49 @@
+package v1beta3
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+
+	"github.com/linkerd/linkerd2/controller/gen/apis/server"
+)
+
+var (
+	// SchemeGroupVersion is the identifier for the API which includes the name
+	// of the group and the version of the API.
+	SchemeGroupVersion = schema.GroupVersion{
+		Group:   server.GroupName,
+		Version: "v1beta3",
+	}
+
+	// SchemeBuilder collects functions that add things to a scheme. It's to
+	// allow code to compile without explicitly referencing generated types.
+	// You should declare one in each package that will have generated deep
+	// copy or conversion functions.
+	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
+
+	// AddToScheme applies all the stored functions to the scheme. A non-nil error
+	// indicates that one function failed and the attempt was abandoned.
+	AddToScheme = SchemeBuilder.AddToScheme
+)
+
+// Kind takes an unqualified kind and returns back a Group qualified GroupKind
+func Kind(kind string) schema.GroupKind {
+	return SchemeGroupVersion.WithKind(kind).GroupKind()
+}
+
+// Resource takes an unqualified resource and returns a Group qualified
+// GroupResource
+func Resource(resource string) schema.GroupResource {
+	return SchemeGroupVersion.WithResource(resource).GroupResource()
+}
+
+// Adds the list of known types to Scheme.
+func addKnownTypes(scheme *runtime.Scheme) error {
+	scheme.AddKnownTypes(SchemeGroupVersion,
+		&Server{},
+		&ServerList{},
+	)
+	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
+	return nil
+}
diff --git a/controller/gen/apis/server/v1beta3/types.go b/controller/gen/apis/server/v1beta3/types.go
new file mode 100644
index 000000000..221671b7e
--- /dev/null
+++ b/controller/gen/apis/server/v1beta3/types.go
@@ -0,0 +1,47 @@
+package v1beta3
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/intstr"
+)
+
+// +genclient
+// +genclient:noStatus
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +groupName=policy.linkerd.io
+
+type Server struct {
+	// TypeMeta is the metadata for the resource, like kind and apiversion
+	metav1.TypeMeta `json:",inline"`
+
+	// ObjectMeta contains the metadata for the particular object, including
+	// things like...
+	//  - name
+	//  - namespace
+	//  - self link
+	//  - labels
+	//  - ... etc ...
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	// Spec is the custom resource spec
+	Spec ServerSpec `json:"spec"`
+}
+
+// ServerSpec specifies a Server resource.
+type ServerSpec struct {
+	AccessPolicy             string                `json:"accessPolicy,omitempty"`
+	PodSelector              *metav1.LabelSelector `json:"podSelector,omitempty"`
+	ExternalWorkloadSelector *metav1.LabelSelector `json:"externalWorkloadSelector,omitempty"`
+	Port                     intstr.IntOrString    `json:"port,omitempty"`
+	ProxyProtocol            string                `json:"proxyProtocol,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ServerList is a list of Server resources.
+type ServerList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata"`
+
+	Items []Server `json:"items"`
+}
diff --git a/controller/gen/apis/server/v1beta3/zz_generated.deepcopy.go b/controller/gen/apis/server/v1beta3/zz_generated.deepcopy.go
new file mode 100644
index 000000000..42df854b3
--- /dev/null
+++ b/controller/gen/apis/server/v1beta3/zz_generated.deepcopy.go
@@ -0,0 +1,114 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by deepcopy-gen. DO NOT EDIT.
+
+package v1beta3
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Server) DeepCopyInto(out *Server) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Server.
+func (in *Server) DeepCopy() *Server {
+	if in == nil {
+		return nil
+	}
+	out := new(Server)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Server) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ServerList) DeepCopyInto(out *ServerList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Server, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerList.
+func (in *ServerList) DeepCopy() *ServerList {
+	if in == nil {
+		return nil
+	}
+	out := new(ServerList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ServerList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ServerSpec) DeepCopyInto(out *ServerSpec) {
+	*out = *in
+	if in.PodSelector != nil {
+		in, out := &in.PodSelector, &out.PodSelector
+		*out = new(v1.LabelSelector)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.ExternalWorkloadSelector != nil {
+		in, out := &in.ExternalWorkloadSelector, &out.ExternalWorkloadSelector
+		*out = new(v1.LabelSelector)
+		(*in).DeepCopyInto(*out)
+	}
+	out.Port = in.Port
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServerSpec.
+func (in *ServerSpec) DeepCopy() *ServerSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ServerSpec)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/controller/gen/client/clientset/versioned/clientset.go b/controller/gen/client/clientset/versioned/clientset.go
index dad7724bf..370588464 100644
--- a/controller/gen/client/clientset/versioned/clientset.go
+++ b/controller/gen/client/clientset/versioned/clientset.go
@@ -28,6 +28,7 @@ import (
 	policyv1beta3 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/policy/v1beta3"
 	serverv1beta1 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta1"
 	serverv1beta2 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta2"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta3"
 	serverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/serverauthorization/v1beta1"
 	linkerdv1alpha2 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/serviceprofile/v1alpha2"
 	discovery "k8s.io/client-go/discovery"
@@ -43,6 +44,7 @@ type Interface interface {
 	PolicyV1beta3() policyv1beta3.PolicyV1beta3Interface
 	ServerV1beta1() serverv1beta1.ServerV1beta1Interface
 	ServerV1beta2() serverv1beta2.ServerV1beta2Interface
+	ServerV1beta3() serverv1beta3.ServerV1beta3Interface
 	ServerauthorizationV1beta1() serverauthorizationv1beta1.ServerauthorizationV1beta1Interface
 	LinkerdV1alpha2() linkerdv1alpha2.LinkerdV1alpha2Interface
 }
@@ -56,6 +58,7 @@ type Clientset struct {
 	policyV1beta3              *policyv1beta3.PolicyV1beta3Client
 	serverV1beta1              *serverv1beta1.ServerV1beta1Client
 	serverV1beta2              *serverv1beta2.ServerV1beta2Client
+	serverV1beta3              *serverv1beta3.ServerV1beta3Client
 	serverauthorizationV1beta1 *serverauthorizationv1beta1.ServerauthorizationV1beta1Client
 	linkerdV1alpha2            *linkerdv1alpha2.LinkerdV1alpha2Client
 }
@@ -90,6 +93,11 @@ func (c *Clientset) ServerV1beta2() serverv1beta2.ServerV1beta2Interface {
 	return c.serverV1beta2
 }
 
+// ServerV1beta3 retrieves the ServerV1beta3Client
+func (c *Clientset) ServerV1beta3() serverv1beta3.ServerV1beta3Interface {
+	return c.serverV1beta3
+}
+
 // ServerauthorizationV1beta1 retrieves the ServerauthorizationV1beta1Client
 func (c *Clientset) ServerauthorizationV1beta1() serverauthorizationv1beta1.ServerauthorizationV1beta1Interface {
 	return c.serverauthorizationV1beta1
@@ -168,6 +176,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset,
 	if err != nil {
 		return nil, err
 	}
+	cs.serverV1beta3, err = serverv1beta3.NewForConfigAndClient(&configShallowCopy, httpClient)
+	if err != nil {
+		return nil, err
+	}
 	cs.serverauthorizationV1beta1, err = serverauthorizationv1beta1.NewForConfigAndClient(&configShallowCopy, httpClient)
 	if err != nil {
 		return nil, err
@@ -203,6 +215,7 @@ func New(c rest.Interface) *Clientset {
 	cs.policyV1beta3 = policyv1beta3.New(c)
 	cs.serverV1beta1 = serverv1beta1.New(c)
 	cs.serverV1beta2 = serverv1beta2.New(c)
+	cs.serverV1beta3 = serverv1beta3.New(c)
 	cs.serverauthorizationV1beta1 = serverauthorizationv1beta1.New(c)
 	cs.linkerdV1alpha2 = linkerdv1alpha2.New(c)
 
diff --git a/controller/gen/client/clientset/versioned/fake/clientset_generated.go b/controller/gen/client/clientset/versioned/fake/clientset_generated.go
index 07b93877a..a0c6afd60 100644
--- a/controller/gen/client/clientset/versioned/fake/clientset_generated.go
+++ b/controller/gen/client/clientset/versioned/fake/clientset_generated.go
@@ -32,6 +32,8 @@ import (
 	fakeserverv1beta1 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta1/fake"
 	serverv1beta2 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta2"
 	fakeserverv1beta2 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta2/fake"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta3"
+	fakeserverv1beta3 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake"
 	serverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/serverauthorization/v1beta1"
 	fakeserverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/serverauthorization/v1beta1/fake"
 	linkerdv1alpha2 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/serviceprofile/v1alpha2"
@@ -123,6 +125,11 @@ func (c *Clientset) ServerV1beta2() serverv1beta2.ServerV1beta2Interface {
 	return &fakeserverv1beta2.FakeServerV1beta2{Fake: &c.Fake}
 }
 
+// ServerV1beta3 retrieves the ServerV1beta3Client
+func (c *Clientset) ServerV1beta3() serverv1beta3.ServerV1beta3Interface {
+	return &fakeserverv1beta3.FakeServerV1beta3{Fake: &c.Fake}
+}
+
 // ServerauthorizationV1beta1 retrieves the ServerauthorizationV1beta1Client
 func (c *Clientset) ServerauthorizationV1beta1() serverauthorizationv1beta1.ServerauthorizationV1beta1Interface {
 	return &fakeserverauthorizationv1beta1.FakeServerauthorizationV1beta1{Fake: &c.Fake}
diff --git a/controller/gen/client/clientset/versioned/fake/register.go b/controller/gen/client/clientset/versioned/fake/register.go
index 8ebba89fb..13a59e01c 100644
--- a/controller/gen/client/clientset/versioned/fake/register.go
+++ b/controller/gen/client/clientset/versioned/fake/register.go
@@ -25,6 +25,7 @@ import (
 	policyv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/policy/v1beta3"
 	serverv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta1"
 	serverv1beta2 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	serverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
 	linkerdv1alpha2 "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -44,6 +45,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
 	policyv1beta3.AddToScheme,
 	serverv1beta1.AddToScheme,
 	serverv1beta2.AddToScheme,
+	serverv1beta3.AddToScheme,
 	serverauthorizationv1beta1.AddToScheme,
 	linkerdv1alpha2.AddToScheme,
 }
diff --git a/controller/gen/client/clientset/versioned/scheme/register.go b/controller/gen/client/clientset/versioned/scheme/register.go
index 0da750f79..28c8441d1 100644
--- a/controller/gen/client/clientset/versioned/scheme/register.go
+++ b/controller/gen/client/clientset/versioned/scheme/register.go
@@ -25,6 +25,7 @@ import (
 	policyv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/policy/v1beta3"
 	serverv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta1"
 	serverv1beta2 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	serverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
 	linkerdv1alpha2 "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -44,6 +45,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{
 	policyv1beta3.AddToScheme,
 	serverv1beta1.AddToScheme,
 	serverv1beta2.AddToScheme,
+	serverv1beta3.AddToScheme,
 	serverauthorizationv1beta1.AddToScheme,
 	linkerdv1alpha2.AddToScheme,
 }
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/doc.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/doc.go
new file mode 100644
index 000000000..09b1d25b0
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated typed clients.
+package v1beta3
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/doc.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/doc.go
new file mode 100644
index 000000000..16f443990
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/fake_server.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/fake_server.go
new file mode 100644
index 000000000..1c95745f3
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/fake_server.go
@@ -0,0 +1,129 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeServers implements ServerInterface
+type FakeServers struct {
+	Fake *FakeServerV1beta3
+	ns   string
+}
+
+var serversResource = v1beta3.SchemeGroupVersion.WithResource("servers")
+
+var serversKind = v1beta3.SchemeGroupVersion.WithKind("Server")
+
+// Get takes name of the server, and returns the corresponding server object, and an error if there is any.
+func (c *FakeServers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta3.Server, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(serversResource, c.ns, name), &v1beta3.Server{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta3.Server), err
+}
+
+// List takes label and field selectors, and returns the list of Servers that match those selectors.
+func (c *FakeServers) List(ctx context.Context, opts v1.ListOptions) (result *v1beta3.ServerList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(serversResource, serversKind, c.ns, opts), &v1beta3.ServerList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1beta3.ServerList{ListMeta: obj.(*v1beta3.ServerList).ListMeta}
+	for _, item := range obj.(*v1beta3.ServerList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested servers.
+func (c *FakeServers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(serversResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a server and creates it.  Returns the server's representation of the server, and an error, if there is any.
+func (c *FakeServers) Create(ctx context.Context, server *v1beta3.Server, opts v1.CreateOptions) (result *v1beta3.Server, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(serversResource, c.ns, server), &v1beta3.Server{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta3.Server), err
+}
+
+// Update takes the representation of a server and updates it. Returns the server's representation of the server, and an error, if there is any.
+func (c *FakeServers) Update(ctx context.Context, server *v1beta3.Server, opts v1.UpdateOptions) (result *v1beta3.Server, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(serversResource, c.ns, server), &v1beta3.Server{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta3.Server), err
+}
+
+// Delete takes name of the server and deletes it. Returns an error if one occurs.
+func (c *FakeServers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteActionWithOptions(serversResource, c.ns, name, opts), &v1beta3.Server{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeServers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(serversResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v1beta3.ServerList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched server.
+func (c *FakeServers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta3.Server, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(serversResource, c.ns, name, pt, data, subresources...), &v1beta3.Server{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta3.Server), err
+}
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/fake_server_client.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/fake_server_client.go
new file mode 100644
index 000000000..27b852b26
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/fake/fake_server_client.go
@@ -0,0 +1,40 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/typed/server/v1beta3"
+	rest "k8s.io/client-go/rest"
+	testing "k8s.io/client-go/testing"
+)
+
+type FakeServerV1beta3 struct {
+	*testing.Fake
+}
+
+func (c *FakeServerV1beta3) Servers(namespace string) v1beta3.ServerInterface {
+	return &FakeServers{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeServerV1beta3) RESTClient() rest.Interface {
+	var ret *rest.RESTClient
+	return ret
+}
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/generated_expansion.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/generated_expansion.go
new file mode 100644
index 000000000..ec1dcf591
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/generated_expansion.go
@@ -0,0 +1,21 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta3
+
+type ServerExpansion interface{}
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/server.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/server.go
new file mode 100644
index 000000000..19d5dee01
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/server.go
@@ -0,0 +1,178 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta3
+
+import (
+	"context"
+	"time"
+
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
+	scheme "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ServersGetter has a method to return a ServerInterface.
+// A group's client should implement this interface.
+type ServersGetter interface {
+	Servers(namespace string) ServerInterface
+}
+
+// ServerInterface has methods to work with Server resources.
+type ServerInterface interface {
+	Create(ctx context.Context, server *v1beta3.Server, opts v1.CreateOptions) (*v1beta3.Server, error)
+	Update(ctx context.Context, server *v1beta3.Server, opts v1.UpdateOptions) (*v1beta3.Server, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta3.Server, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v1beta3.ServerList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta3.Server, err error)
+	ServerExpansion
+}
+
+// servers implements ServerInterface
+type servers struct {
+	client rest.Interface
+	ns     string
+}
+
+// newServers returns a Servers
+func newServers(c *ServerV1beta3Client, namespace string) *servers {
+	return &servers{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the server, and returns the corresponding server object, and an error if there is any.
+func (c *servers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta3.Server, err error) {
+	result = &v1beta3.Server{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("servers").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of Servers that match those selectors.
+func (c *servers) List(ctx context.Context, opts v1.ListOptions) (result *v1beta3.ServerList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v1beta3.ServerList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("servers").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested servers.
+func (c *servers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("servers").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a server and creates it.  Returns the server's representation of the server, and an error, if there is any.
+func (c *servers) Create(ctx context.Context, server *v1beta3.Server, opts v1.CreateOptions) (result *v1beta3.Server, err error) {
+	result = &v1beta3.Server{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("servers").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(server).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a server and updates it. Returns the server's representation of the server, and an error, if there is any.
+func (c *servers) Update(ctx context.Context, server *v1beta3.Server, opts v1.UpdateOptions) (result *v1beta3.Server, err error) {
+	result = &v1beta3.Server{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("servers").
+		Name(server.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(server).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the server and deletes it. Returns an error if one occurs.
+func (c *servers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("servers").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *servers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("servers").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched server.
+func (c *servers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta3.Server, err error) {
+	result = &v1beta3.Server{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("servers").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/controller/gen/client/clientset/versioned/typed/server/v1beta3/server_client.go b/controller/gen/client/clientset/versioned/typed/server/v1beta3/server_client.go
new file mode 100644
index 000000000..4cb4e684e
--- /dev/null
+++ b/controller/gen/client/clientset/versioned/typed/server/v1beta3/server_client.go
@@ -0,0 +1,107 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1beta3
+
+import (
+	"net/http"
+
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
+	"github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned/scheme"
+	rest "k8s.io/client-go/rest"
+)
+
+type ServerV1beta3Interface interface {
+	RESTClient() rest.Interface
+	ServersGetter
+}
+
+// ServerV1beta3Client is used to interact with features provided by the server group.
+type ServerV1beta3Client struct {
+	restClient rest.Interface
+}
+
+func (c *ServerV1beta3Client) Servers(namespace string) ServerInterface {
+	return newServers(c, namespace)
+}
+
+// NewForConfig creates a new ServerV1beta3Client for the given config.
+// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
+// where httpClient was generated with rest.HTTPClientFor(c).
+func NewForConfig(c *rest.Config) (*ServerV1beta3Client, error) {
+	config := *c
+	if err := setConfigDefaults(&config); err != nil {
+		return nil, err
+	}
+	httpClient, err := rest.HTTPClientFor(&config)
+	if err != nil {
+		return nil, err
+	}
+	return NewForConfigAndClient(&config, httpClient)
+}
+
+// NewForConfigAndClient creates a new ServerV1beta3Client for the given config and http client.
+// Note the http client provided takes precedence over the configured transport values.
+func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ServerV1beta3Client, error) {
+	config := *c
+	if err := setConfigDefaults(&config); err != nil {
+		return nil, err
+	}
+	client, err := rest.RESTClientForConfigAndClient(&config, h)
+	if err != nil {
+		return nil, err
+	}
+	return &ServerV1beta3Client{client}, nil
+}
+
+// NewForConfigOrDie creates a new ServerV1beta3Client for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *ServerV1beta3Client {
+	client, err := NewForConfig(c)
+	if err != nil {
+		panic(err)
+	}
+	return client
+}
+
+// New creates a new ServerV1beta3Client for the given RESTClient.
+func New(c rest.Interface) *ServerV1beta3Client {
+	return &ServerV1beta3Client{c}
+}
+
+func setConfigDefaults(config *rest.Config) error {
+	gv := v1beta3.SchemeGroupVersion
+	config.GroupVersion = &gv
+	config.APIPath = "/apis"
+	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
+
+	if config.UserAgent == "" {
+		config.UserAgent = rest.DefaultKubernetesUserAgent()
+	}
+
+	return nil
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *ServerV1beta3Client) RESTClient() rest.Interface {
+	if c == nil {
+		return nil
+	}
+	return c.restClient
+}
diff --git a/controller/gen/client/informers/externalversions/generic.go b/controller/gen/client/informers/externalversions/generic.go
index 0a5bff745..d9a60362b 100644
--- a/controller/gen/client/informers/externalversions/generic.go
+++ b/controller/gen/client/informers/externalversions/generic.go
@@ -27,6 +27,7 @@ import (
 	v1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/policy/v1beta3"
 	serverv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta1"
 	v1beta2 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	serverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
 	v1alpha2 "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
 	schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -93,6 +94,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
 	case v1beta2.SchemeGroupVersion.WithResource("servers"):
 		return &genericInformer{resource: resource.GroupResource(), informer: f.Server().V1beta2().Servers().Informer()}, nil
 
+		// Group=server, Version=v1beta3
+	case serverv1beta3.SchemeGroupVersion.WithResource("servers"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Server().V1beta3().Servers().Informer()}, nil
+
 		// Group=serverauthorization, Version=v1beta1
 	case serverauthorizationv1beta1.SchemeGroupVersion.WithResource("serverauthorizations"):
 		return &genericInformer{resource: resource.GroupResource(), informer: f.Serverauthorization().V1beta1().ServerAuthorizations().Informer()}, nil
diff --git a/controller/gen/client/informers/externalversions/server/interface.go b/controller/gen/client/informers/externalversions/server/interface.go
index 9e78a70b0..ccc393e03 100644
--- a/controller/gen/client/informers/externalversions/server/interface.go
+++ b/controller/gen/client/informers/externalversions/server/interface.go
@@ -22,6 +22,7 @@ import (
 	internalinterfaces "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/internalinterfaces"
 	v1beta1 "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/server/v1beta1"
 	v1beta2 "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/server/v1beta2"
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/server/v1beta3"
 )
 
 // Interface provides access to each of this group's versions.
@@ -30,6 +31,8 @@ type Interface interface {
 	V1beta1() v1beta1.Interface
 	// V1beta2 provides access to shared informers for resources in V1beta2.
 	V1beta2() v1beta2.Interface
+	// V1beta3 provides access to shared informers for resources in V1beta3.
+	V1beta3() v1beta3.Interface
 }
 
 type group struct {
@@ -52,3 +55,8 @@ func (g *group) V1beta1() v1beta1.Interface {
 func (g *group) V1beta2() v1beta2.Interface {
 	return v1beta2.New(g.factory, g.namespace, g.tweakListOptions)
 }
+
+// V1beta3 returns a new v1beta3.Interface.
+func (g *group) V1beta3() v1beta3.Interface {
+	return v1beta3.New(g.factory, g.namespace, g.tweakListOptions)
+}
diff --git a/controller/gen/client/informers/externalversions/server/v1beta3/interface.go b/controller/gen/client/informers/externalversions/server/v1beta3/interface.go
new file mode 100644
index 000000000..042209931
--- /dev/null
+++ b/controller/gen/client/informers/externalversions/server/v1beta3/interface.go
@@ -0,0 +1,45 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1beta3
+
+import (
+	internalinterfaces "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/internalinterfaces"
+)
+
+// Interface provides access to all the informers in this group version.
+type Interface interface {
+	// Servers returns a ServerInformer.
+	Servers() ServerInformer
+}
+
+type version struct {
+	factory          internalinterfaces.SharedInformerFactory
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// New returns a new Interface.
+func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
+	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
+}
+
+// Servers returns a ServerInformer.
+func (v *version) Servers() ServerInformer {
+	return &serverInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
diff --git a/controller/gen/client/informers/externalversions/server/v1beta3/server.go b/controller/gen/client/informers/externalversions/server/v1beta3/server.go
new file mode 100644
index 000000000..b722d04ea
--- /dev/null
+++ b/controller/gen/client/informers/externalversions/server/v1beta3/server.go
@@ -0,0 +1,90 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1beta3
+
+import (
+	"context"
+	time "time"
+
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
+	versioned "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
+	internalinterfaces "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/internalinterfaces"
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/client/listers/server/v1beta3"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ServerInformer provides access to a shared informer and lister for
+// Servers.
+type ServerInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v1beta3.ServerLister
+}
+
+type serverInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewServerInformer constructs a new informer for Server type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewServerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredServerInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredServerInformer constructs a new informer for Server type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredServerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ServerV1beta3().Servers(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ServerV1beta3().Servers(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&serverv1beta3.Server{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *serverInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredServerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *serverInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&serverv1beta3.Server{}, f.defaultInformer)
+}
+
+func (f *serverInformer) Lister() v1beta3.ServerLister {
+	return v1beta3.NewServerLister(f.Informer().GetIndexer())
+}
diff --git a/controller/gen/client/listers/server/v1beta3/expansion_generated.go b/controller/gen/client/listers/server/v1beta3/expansion_generated.go
new file mode 100644
index 000000000..62873d13e
--- /dev/null
+++ b/controller/gen/client/listers/server/v1beta3/expansion_generated.go
@@ -0,0 +1,27 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1beta3
+
+// ServerListerExpansion allows custom methods to be added to
+// ServerLister.
+type ServerListerExpansion interface{}
+
+// ServerNamespaceListerExpansion allows custom methods to be added to
+// ServerNamespaceLister.
+type ServerNamespaceListerExpansion interface{}
diff --git a/controller/gen/client/listers/server/v1beta3/server.go b/controller/gen/client/listers/server/v1beta3/server.go
new file mode 100644
index 000000000..a794c4d19
--- /dev/null
+++ b/controller/gen/client/listers/server/v1beta3/server.go
@@ -0,0 +1,99 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1beta3
+
+import (
+	v1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ServerLister helps list Servers.
+// All objects returned here must be treated as read-only.
+type ServerLister interface {
+	// List lists all Servers in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v1beta3.Server, err error)
+	// Servers returns an object that can list and get Servers.
+	Servers(namespace string) ServerNamespaceLister
+	ServerListerExpansion
+}
+
+// serverLister implements the ServerLister interface.
+type serverLister struct {
+	indexer cache.Indexer
+}
+
+// NewServerLister returns a new ServerLister.
+func NewServerLister(indexer cache.Indexer) ServerLister {
+	return &serverLister{indexer: indexer}
+}
+
+// List lists all Servers in the indexer.
+func (s *serverLister) List(selector labels.Selector) (ret []*v1beta3.Server, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1beta3.Server))
+	})
+	return ret, err
+}
+
+// Servers returns an object that can list and get Servers.
+func (s *serverLister) Servers(namespace string) ServerNamespaceLister {
+	return serverNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ServerNamespaceLister helps list and get Servers.
+// All objects returned here must be treated as read-only.
+type ServerNamespaceLister interface {
+	// List lists all Servers in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v1beta3.Server, err error)
+	// Get retrieves the Server from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v1beta3.Server, error)
+	ServerNamespaceListerExpansion
+}
+
+// serverNamespaceLister implements the ServerNamespaceLister
+// interface.
+type serverNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all Servers in the indexer for a given namespace.
+func (s serverNamespaceLister) List(selector labels.Selector) (ret []*v1beta3.Server, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1beta3.Server))
+	})
+	return ret, err
+}
+
+// Get retrieves the Server from the indexer for a given namespace and name.
+func (s serverNamespaceLister) Get(name string) (*v1beta3.Server, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v1beta3.Resource("server"), name)
+	}
+	return obj.(*v1beta3.Server), nil
+}
diff --git a/controller/k8s/api.go b/controller/k8s/api.go
index f6be6e24c..e3e90fb02 100644
--- a/controller/k8s/api.go
+++ b/controller/k8s/api.go
@@ -12,7 +12,7 @@ import (
 	l5dcrdclient "github.com/linkerd/linkerd2/controller/gen/client/clientset/versioned"
 	l5dcrdinformer "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions"
 	ewinformers "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/externalworkload/v1beta1"
-	srvinformers "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/server/v1beta2"
+	srvinformers "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/server/v1beta3"
 	spinformers "github.com/linkerd/linkerd2/controller/gen/client/informers/externalversions/serviceprofile/v1alpha2"
 	"github.com/linkerd/linkerd2/pkg/k8s"
 	"github.com/prometheus/client_golang/prometheus"
@@ -279,7 +279,7 @@ func newAPI(
 			if l5dCrdSharedInformers == nil {
 				panic("Linkerd CRD shared informer not configured")
 			}
-			api.srv = l5dCrdSharedInformers.Server().V1beta2().Servers()
+			api.srv = l5dCrdSharedInformers.Server().V1beta3().Servers()
 			api.syncChecks = append(api.syncChecks, api.srv.Informer().HasSynced)
 			api.promGauges.addInformerSize(k8s.Server, informerLabels, api.srv.Informer())
 		case SS:
diff --git a/controller/k8s/api_resource.go b/controller/k8s/api_resource.go
index 45a86a067..ee4ef760a 100644
--- a/controller/k8s/api_resource.go
+++ b/controller/k8s/api_resource.go
@@ -3,7 +3,7 @@ package k8s
 import (
 	"strings"
 
-	serverv1beta2 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	sazv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
 	spv1alpha2 "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
 	"github.com/linkerd/linkerd2/pkg/k8s"
@@ -84,7 +84,7 @@ func (res APIResource) GVK() (schema.GroupVersionKind, error) {
 	case SS:
 		return appsv1.SchemeGroupVersion.WithKind("StatefulSet"), nil
 	case Srv:
-		return serverv1beta2.SchemeGroupVersion.WithKind("Server"), nil
+		return serverv1beta3.SchemeGroupVersion.WithKind("Server"), nil
 	case Svc:
 		return v1.SchemeGroupVersion.WithKind("Service"), nil
 	default:
diff --git a/controller/script/policy-client/main.go b/controller/script/policy-client/main.go
index 089b66dba..2b1912e82 100644
--- a/controller/script/policy-client/main.go
+++ b/controller/script/policy-client/main.go
@@ -24,7 +24,7 @@ func main() {
 	}
 	client := versioned.NewForConfigOrDie(config)
 
-	srvWatch, err := client.ServerV1beta2().Servers(*namespace).Watch(context.Background(), metav1.ListOptions{})
+	srvWatch, err := client.ServerV1beta3().Servers(*namespace).Watch(context.Background(), metav1.ListOptions{})
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "failed to watch Servers: %s", err)
 		os.Exit(1)
diff --git a/go.mod b/go.mod
index cefe6cad0..014196888 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
 	github.com/julienschmidt/httprouter v1.3.0
 	github.com/linkerd/linkerd2-proxy-api v0.13.1
 	github.com/mattn/go-isatty v0.0.20
-	github.com/mattn/go-runewidth v0.0.15
+	github.com/mattn/go-runewidth v0.0.16
 	github.com/nsf/termbox-go v1.1.1
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/browser v0.0.0-20170505125900-c90ca0c84f15
diff --git a/go.sum b/go.sum
index ac98e54a6..76c7f9e80 100644
--- a/go.sum
+++ b/go.sum
@@ -302,8 +302,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
-github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg=
 github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
diff --git a/jaeger/charts/linkerd-jaeger/templates/jaeger-injector-policy.yaml b/jaeger/charts/linkerd-jaeger/templates/jaeger-injector-policy.yaml
index 77bd1f645..fc5805372 100644
--- a/jaeger/charts/linkerd-jaeger/templates/jaeger-injector-policy.yaml
+++ b/jaeger/charts/linkerd-jaeger/templates/jaeger-injector-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/jaeger/charts/linkerd-jaeger/templates/tracing-policy.yaml b/jaeger/charts/linkerd-jaeger/templates/tracing-policy.yaml
index 7d9049bd0..d23d40bb8 100644
--- a/jaeger/charts/linkerd-jaeger/templates/tracing-policy.yaml
+++ b/jaeger/charts/linkerd-jaeger/templates/tracing-policy.yaml
@@ -1,6 +1,6 @@
 {{ if .Values.collector.enabled -}}
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -18,7 +18,7 @@ spec:
   port: 4317
   proxyProtocol: gRPC
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -35,7 +35,7 @@ spec:
   port: 4318
   proxyProtocol: HTTP/1
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -53,7 +53,7 @@ spec:
   port: 55678
   proxyProtocol: gRPC
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -70,7 +70,7 @@ spec:
       component: collector
   port: 9411
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -87,7 +87,7 @@ spec:
       component: collector
   port: 14268
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -104,7 +104,7 @@ spec:
       component: collector
   port: 14250
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -236,7 +236,7 @@ spec:
   # allow connections from any pod (meshed or not) sending trace data
   requiredAuthenticationRefs: []
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -275,7 +275,7 @@ spec:
       name: collector
       namespace: {{.Release.Namespace}}
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
@@ -315,7 +315,7 @@ spec:
       name: prometheus
       namespace: linkerd-viz
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/multicluster/charts/linkerd-multicluster/templates/gateway-policy.yaml b/multicluster/charts/linkerd-multicluster/templates/gateway-policy.yaml
index d81f31fc6..b6a3fe3f1 100644
--- a/multicluster/charts/linkerd-multicluster/templates/gateway-policy.yaml
+++ b/multicluster/charts/linkerd-multicluster/templates/gateway-policy.yaml
@@ -1,6 +1,6 @@
 {{if .Values.gateway.enabled -}}
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/multicluster/charts/linkerd-multicluster/templates/service-mirror-policy.yaml b/multicluster/charts/linkerd-multicluster/templates/service-mirror-policy.yaml
index b87a4c751..ff40e1c85 100644
--- a/multicluster/charts/linkerd-multicluster/templates/service-mirror-policy.yaml
+++ b/multicluster/charts/linkerd-multicluster/templates/service-mirror-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/pkg/k8s/k8s.go b/pkg/k8s/k8s.go
index 7d3d52f1d..13ac1dfbf 100644
--- a/pkg/k8s/k8s.go
+++ b/pkg/k8s/k8s.go
@@ -39,7 +39,7 @@ const (
 	HTTPRoute             = "httproute"
 
 	PolicyAPIGroup         = "policy.linkerd.io"
-	PolicyServerCRDVersion = "v1beta2"
+	PolicyServerCRDVersion = "v1beta3"
 
 	ServiceProfileAPIVersion = "linkerd.io/v1alpha2"
 	ServiceProfileKind       = "ServiceProfile"
diff --git a/pkg/k8s/policy.go b/pkg/k8s/policy.go
index aedf7d071..aaab050b9 100644
--- a/pkg/k8s/policy.go
+++ b/pkg/k8s/policy.go
@@ -9,7 +9,7 @@ import (
 	"k8s.io/apimachinery/pkg/labels"
 
 	policyv1 "github.com/linkerd/linkerd2/controller/gen/apis/policy/v1alpha1"
-	serverv1beta2 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	serverv1beta3 "github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	serverauthorizationv1beta1 "github.com/linkerd/linkerd2/controller/gen/apis/serverauthorization/v1beta1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -34,7 +34,7 @@ var HTTPRouteGVR = policyv1.SchemeGroupVersion.WithResource("httproutes")
 var SazGVR = serverauthorizationv1beta1.SchemeGroupVersion.WithResource("serverauthorizations")
 
 // ServerGVR is the GroupVersionResource for the Server resource.
-var ServerGVR = serverv1beta2.SchemeGroupVersion.WithResource("servers")
+var ServerGVR = serverv1beta3.SchemeGroupVersion.WithResource("servers")
 
 // AuthorizationsForResource returns a list of ServerAuthorizations and
 // AuthorizationPolicies which apply to any Server or HttpRoute which select
@@ -54,22 +54,22 @@ func AuthorizationsForResource(ctx context.Context, k8sAPI *KubernetesAPI, names
 	}
 
 	for _, saz := range sazs.Items {
-		var servers []serverv1beta2.Server
+		var servers []serverv1beta3.Server
 
 		if saz.Spec.Server.Name != "" {
-			server, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(saz.GetNamespace()).Get(ctx, saz.Spec.Server.Name, metav1.GetOptions{})
+			server, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(saz.GetNamespace()).Get(ctx, saz.Spec.Server.Name, metav1.GetOptions{})
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "ServerAuthorization/%s targets Server/%s but we failed to get it: %s\n", saz.Name, saz.Spec.Server.Name, err)
 				continue
 			}
-			servers = []serverv1beta2.Server{*server}
+			servers = []serverv1beta3.Server{*server}
 		} else if saz.Spec.Server.Selector != nil {
 			selector, err := metav1.LabelSelectorAsSelector(saz.Spec.Server.Selector)
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "Failed to parse Server selector for ServerAuthorization/%s: %s\n", saz.Name, err)
 				continue
 			}
-			serverList, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(saz.GetNamespace()).List(ctx, metav1.ListOptions{LabelSelector: selector.String()})
+			serverList, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(saz.GetNamespace()).List(ctx, metav1.ListOptions{LabelSelector: selector.String()})
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "Failed to get Servers for ServerAuthorization/%s: %s\n", saz.Name, err)
 				continue
@@ -95,14 +95,14 @@ func AuthorizationsForResource(ctx context.Context, k8sAPI *KubernetesAPI, names
 		os.Exit(1)
 	}
 
-	allServersInNamespace := map[string]*serverv1beta2.ServerList{}
+	allServersInNamespace := map[string]*serverv1beta3.ServerList{}
 
 	for _, p := range policies.Items {
 		target := p.Spec.TargetRef
 		if target.Kind == NamespaceKind && target.Group == K8sCoreAPIGroup {
 			serverList, ok := allServersInNamespace[p.Namespace]
 			if !ok {
-				serverList, err = k8sAPI.L5dCrdClient.ServerV1beta2().Servers(p.Namespace).List(ctx, metav1.ListOptions{})
+				serverList, err = k8sAPI.L5dCrdClient.ServerV1beta3().Servers(p.Namespace).List(ctx, metav1.ListOptions{})
 				if err != nil {
 					fmt.Fprintf(os.Stderr, "Failed to get Servers for Namespace/%s: %s\n", p.Namespace, err)
 					continue
@@ -122,7 +122,7 @@ func AuthorizationsForResource(ctx context.Context, k8sAPI *KubernetesAPI, names
 				}
 			}
 		} else if target.Kind == ServerKind && target.Group == PolicyAPIGroup {
-			server, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(p.Namespace).Get(ctx, string(target.Name), metav1.GetOptions{})
+			server, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(p.Namespace).Get(ctx, string(target.Name), metav1.GetOptions{})
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "AuthorizationPolicy/%s targets Server/%s but we failed to get it: %s\n", p.Name, target.Name, err)
 				continue
@@ -144,7 +144,7 @@ func AuthorizationsForResource(ctx context.Context, k8sAPI *KubernetesAPI, names
 			for _, parent := range route.Spec.ParentRefs {
 				if parent.Kind != nil && *parent.Kind == ServerKind &&
 					parent.Group != nil && *parent.Group == PolicyAPIGroup {
-					server, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(p.Namespace).Get(ctx, string(parent.Name), metav1.GetOptions{})
+					server, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(p.Namespace).Get(ctx, string(parent.Name), metav1.GetOptions{})
 					if err != nil {
 						fmt.Fprintf(os.Stderr, "HTTPRoute/%s belongs to Server/%s but we failed to get it: %s\n", target.Name, parent.Name, err)
 						continue
@@ -175,7 +175,7 @@ func ServersForResource(ctx context.Context, k8sAPI *KubernetesAPI, namespace st
 
 	results := make([]string, 0)
 
-	servers, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(namespace).List(ctx, metav1.ListOptions{})
+	servers, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(namespace).List(ctx, metav1.ListOptions{})
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "Failed to get serverauthorization resources: %s\n", err)
 		os.Exit(1)
@@ -216,7 +216,7 @@ func ServerAuthorizationsForServer(ctx context.Context, k8sAPI *KubernetesAPI, n
 				fmt.Fprintf(os.Stderr, "Failed to get servers: %s\n", err)
 				os.Exit(1)
 			}
-			serverList, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(saz.GetNamespace()).List(ctx, metav1.ListOptions{LabelSelector: selector.String()})
+			serverList, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(saz.GetNamespace()).List(ctx, metav1.ListOptions{LabelSelector: selector.String()})
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "Failed to get servers: %s\n", err)
 				os.Exit(1)
@@ -234,7 +234,7 @@ func ServerAuthorizationsForServer(ctx context.Context, k8sAPI *KubernetesAPI, n
 
 // serverIncludesPod returns true the given server selects any of the given pods
 // and that pod uses the server's port.
-func serverIncludesPod(server serverv1beta2.Server, pods []corev1.Pod) bool {
+func serverIncludesPod(server serverv1beta3.Server, pods []corev1.Pod) bool {
 	if server.Spec.PodSelector == nil {
 		return false
 	}
diff --git a/policy-controller/Cargo.toml b/policy-controller/Cargo.toml
index 0ea2fa8c5..e7e565e34 100644
--- a/policy-controller/Cargo.toml
+++ b/policy-controller/Cargo.toml
@@ -23,7 +23,7 @@ ipnet = { version = "2", default-features = false }
 linkerd-policy-controller-core = { path = "./core" }
 linkerd-policy-controller-grpc = { path = "./grpc" }
 linkerd-policy-controller-k8s-api = { path = "./k8s/api" }
-openssl = { version = "0.10.64", optional = true }
+openssl = { version = "0.10.66", optional = true }
 linkerd-policy-controller-k8s-index = { path = "./k8s/index" }
 linkerd-policy-controller-k8s-status = { path = "./k8s/status" }
 parking_lot = "0.12"
diff --git a/policy-controller/k8s/api/src/policy/server.rs b/policy-controller/k8s/api/src/policy/server.rs
index 82a68ec75..ff42ad893 100644
--- a/policy-controller/k8s/api/src/policy/server.rs
+++ b/policy-controller/k8s/api/src/policy/server.rs
@@ -8,7 +8,7 @@ use std::{fmt, num::NonZeroU16};
 #[derive(Clone, Debug, PartialEq, Eq, CustomResource, Deserialize, Serialize, JsonSchema)]
 #[kube(
     group = "policy.linkerd.io",
-    version = "v1beta2",
+    version = "v1beta3",
     kind = "Server",
     namespaced
 )]
diff --git a/viz/charts/linkerd-viz/templates/metrics-api-policy.yaml b/viz/charts/linkerd-viz/templates/metrics-api-policy.yaml
index 46bbac246..c2ce5f923 100644
--- a/viz/charts/linkerd-viz/templates/metrics-api-policy.yaml
+++ b/viz/charts/linkerd-viz/templates/metrics-api-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/viz/charts/linkerd-viz/templates/prometheus-policy.yaml b/viz/charts/linkerd-viz/templates/prometheus-policy.yaml
index fd7e539a6..68ded0c16 100644
--- a/viz/charts/linkerd-viz/templates/prometheus-policy.yaml
+++ b/viz/charts/linkerd-viz/templates/prometheus-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/viz/charts/linkerd-viz/templates/tap-injector-policy.yaml b/viz/charts/linkerd-viz/templates/tap-injector-policy.yaml
index 8a3fe157f..b8d8bad37 100644
--- a/viz/charts/linkerd-viz/templates/tap-injector-policy.yaml
+++ b/viz/charts/linkerd-viz/templates/tap-injector-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/viz/charts/linkerd-viz/templates/tap-policy.yaml b/viz/charts/linkerd-viz/templates/tap-policy.yaml
index 268a7ea6b..d40b90e39 100644
--- a/viz/charts/linkerd-viz/templates/tap-policy.yaml
+++ b/viz/charts/linkerd-viz/templates/tap-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: {{ .Release.Namespace }}
diff --git a/viz/cmd/allow-scrapes.go b/viz/cmd/allow-scrapes.go
index 0e114536c..54a8d408e 100644
--- a/viz/cmd/allow-scrapes.go
+++ b/viz/cmd/allow-scrapes.go
@@ -11,7 +11,7 @@ import (
 
 const (
 	allowScrapePolicy = `---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: proxy-admin
diff --git a/viz/cmd/uninstall.go b/viz/cmd/uninstall.go
index 36ae0da9a..3f3209a5d 100644
--- a/viz/cmd/uninstall.go
+++ b/viz/cmd/uninstall.go
@@ -83,7 +83,7 @@ func uninstallRunE(ctx context.Context, format string) error {
 		}
 	}
 
-	srvs, err := k8sAPI.L5dCrdClient.ServerV1beta2().Servers(v1.NamespaceAll).List(ctx, metav1.ListOptions{LabelSelector: selector})
+	srvs, err := k8sAPI.L5dCrdClient.ServerV1beta3().Servers(v1.NamespaceAll).List(ctx, metav1.ListOptions{LabelSelector: selector})
 	if err != nil {
 		return err
 	}


Test patch:
diff --git a/cli/cmd/testdata/install_crds.golden b/cli/cmd/testdata/install_crds.golden
index a9d0ffb06..44cc2101b 100644
--- a/cli/cmd/testdata/install_crds.golden
+++ b/cli/cmd/testdata/install_crds.golden
@@ -5907,7 +5907,7 @@ spec:
       served: true
       storage: false
       deprecated: true
-      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta2 Server"
+      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta3 Server"
       schema:
         openAPIV3Schema:
           type: object
@@ -5966,6 +5966,94 @@ spec:
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
     - name: v1beta2
+      served: true
+      storage: false
+      schema:
+        openAPIV3Schema:
+          type: object
+          required: [spec]
+          properties:
+            spec:
+              type: object
+              required:
+                - port
+              oneOf:
+                - required: [podSelector]
+                - required: [externalWorkloadSelector]
+              properties:
+                podSelector:
+                  type: object
+                  description: >-
+                    Selects pods in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                externalWorkloadSelector:
+                  type: object
+                  description: >-
+                    Selects ExternalWorkloads in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                port:
+                  description: >-
+                    A port name or number. Must exist in a pod spec.
+                  x-kubernetes-int-or-string: true
+                proxyProtocol:
+                  description: >-
+                    Configures protocol discovery for inbound connections.
+
+                    Supersedes the `config.linkerd.io/opaque-ports` annotation.
+                  type: string
+                  default: unknown
+      additionalPrinterColumns:
+      - name: Port
+        type: string
+        description: The port the server is listening on
+        jsonPath: .spec.port
+      - name: Protocol
+        type: string
+        description: The protocol of the server
+        jsonPath: .spec.proxyProtocol
+    - name: v1beta3
       served: true
       storage: true
       schema:
@@ -5981,6 +6069,11 @@ spec:
                 - required: [podSelector]
                 - required: [externalWorkloadSelector]
               properties:
+                accessPolicy:
+                  type: string
+                  default: deny
+                  description: >-
+                    Default access policy to apply when the traffic doesn't match any of the policy rules.
                 podSelector:
                   type: object
                   description: >-
@@ -6053,6 +6146,10 @@ spec:
         type: string
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
+      - name: Access Policy
+        type: string
+        description: The default access policy applied when the traffic doesn't match any of the policy rules
+        jsonPath: .spec.accessPolicy
 ---
 ###
 ### Service Profile CRD
diff --git a/cli/cmd/testdata/install_helm_crds_output.golden b/cli/cmd/testdata/install_helm_crds_output.golden
index 5f0a2d89a..9d4a7df19 100644
--- a/cli/cmd/testdata/install_helm_crds_output.golden
+++ b/cli/cmd/testdata/install_helm_crds_output.golden
@@ -5919,7 +5919,7 @@ spec:
       served: true
       storage: false
       deprecated: true
-      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta2 Server"
+      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta3 Server"
       schema:
         openAPIV3Schema:
           type: object
@@ -5978,6 +5978,94 @@ spec:
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
     - name: v1beta2
+      served: true
+      storage: false
+      schema:
+        openAPIV3Schema:
+          type: object
+          required: [spec]
+          properties:
+            spec:
+              type: object
+              required:
+                - port
+              oneOf:
+                - required: [podSelector]
+                - required: [externalWorkloadSelector]
+              properties:
+                podSelector:
+                  type: object
+                  description: >-
+                    Selects pods in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                externalWorkloadSelector:
+                  type: object
+                  description: >-
+                    Selects ExternalWorkloads in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                port:
+                  description: >-
+                    A port name or number. Must exist in a pod spec.
+                  x-kubernetes-int-or-string: true
+                proxyProtocol:
+                  description: >-
+                    Configures protocol discovery for inbound connections.
+
+                    Supersedes the `config.linkerd.io/opaque-ports` annotation.
+                  type: string
+                  default: unknown
+      additionalPrinterColumns:
+      - name: Port
+        type: string
+        description: The port the server is listening on
+        jsonPath: .spec.port
+      - name: Protocol
+        type: string
+        description: The protocol of the server
+        jsonPath: .spec.proxyProtocol
+    - name: v1beta3
       served: true
       storage: true
       schema:
@@ -5993,6 +6081,11 @@ spec:
                 - required: [podSelector]
                 - required: [externalWorkloadSelector]
               properties:
+                accessPolicy:
+                  type: string
+                  default: deny
+                  description: >-
+                    Default access policy to apply when the traffic doesn't match any of the policy rules.
                 podSelector:
                   type: object
                   description: >-
@@ -6065,6 +6158,10 @@ spec:
         type: string
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
+      - name: Access Policy
+        type: string
+        description: The default access policy applied when the traffic doesn't match any of the policy rules
+        jsonPath: .spec.accessPolicy
 ---
 # Source: linkerd-crds/templates/serviceprofile.yaml
 ---
diff --git a/cli/cmd/testdata/install_helm_crds_output_ha.golden b/cli/cmd/testdata/install_helm_crds_output_ha.golden
index 5f0a2d89a..9d4a7df19 100644
--- a/cli/cmd/testdata/install_helm_crds_output_ha.golden
+++ b/cli/cmd/testdata/install_helm_crds_output_ha.golden
@@ -5919,7 +5919,7 @@ spec:
       served: true
       storage: false
       deprecated: true
-      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta2 Server"
+      deprecationWarning: "policy.linkerd.io/v1alpha1 Server is deprecated; use policy.linkerd.io/v1beta3 Server"
       schema:
         openAPIV3Schema:
           type: object
@@ -5978,6 +5978,94 @@ spec:
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
     - name: v1beta2
+      served: true
+      storage: false
+      schema:
+        openAPIV3Schema:
+          type: object
+          required: [spec]
+          properties:
+            spec:
+              type: object
+              required:
+                - port
+              oneOf:
+                - required: [podSelector]
+                - required: [externalWorkloadSelector]
+              properties:
+                podSelector:
+                  type: object
+                  description: >-
+                    Selects pods in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                externalWorkloadSelector:
+                  type: object
+                  description: >-
+                    Selects ExternalWorkloads in the same namespace.
+
+                    The result of matchLabels and matchExpressions are ANDed.
+                    Selects all if empty.
+                  properties:
+                    matchLabels:
+                      type: object
+                      x-kubernetes-preserve-unknown-fields: true
+                    matchExpressions:
+                      type: array
+                      items:
+                        type: object
+                        required: [key, operator]
+                        properties:
+                          key:
+                            type: string
+                          operator:
+                            type: string
+                            enum: [In, NotIn, Exists, DoesNotExist]
+                          values:
+                            type: array
+                            items:
+                              type: string
+                port:
+                  description: >-
+                    A port name or number. Must exist in a pod spec.
+                  x-kubernetes-int-or-string: true
+                proxyProtocol:
+                  description: >-
+                    Configures protocol discovery for inbound connections.
+
+                    Supersedes the `config.linkerd.io/opaque-ports` annotation.
+                  type: string
+                  default: unknown
+      additionalPrinterColumns:
+      - name: Port
+        type: string
+        description: The port the server is listening on
+        jsonPath: .spec.port
+      - name: Protocol
+        type: string
+        description: The protocol of the server
+        jsonPath: .spec.proxyProtocol
+    - name: v1beta3
       served: true
       storage: true
       schema:
@@ -5993,6 +6081,11 @@ spec:
                 - required: [podSelector]
                 - required: [externalWorkloadSelector]
               properties:
+                accessPolicy:
+                  type: string
+                  default: deny
+                  description: >-
+                    Default access policy to apply when the traffic doesn't match any of the policy rules.
                 podSelector:
                   type: object
                   description: >-
@@ -6065,6 +6158,10 @@ spec:
         type: string
         description: The protocol of the server
         jsonPath: .spec.proxyProtocol
+      - name: Access Policy
+        type: string
+        description: The default access policy applied when the traffic doesn't match any of the policy rules
+        jsonPath: .spec.accessPolicy
 ---
 # Source: linkerd-crds/templates/serviceprofile.yaml
 ---
diff --git a/controller/api/destination/server_test.go b/controller/api/destination/server_test.go
index e7a1c8d66..0e7ead1af 100644
--- a/controller/api/destination/server_test.go
+++ b/controller/api/destination/server_test.go
@@ -14,7 +14,7 @@ import (
 	"github.com/linkerd/linkerd2-proxy-api/go/net"
 	"github.com/linkerd/linkerd2/controller/api/destination/watcher"
 	"github.com/linkerd/linkerd2/controller/api/util"
-	"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta2"
+	"github.com/linkerd/linkerd2/controller/gen/apis/server/v1beta3"
 	"github.com/linkerd/linkerd2/controller/k8s"
 	"github.com/linkerd/linkerd2/pkg/addr"
 	pkgk8s "github.com/linkerd/linkerd2/pkg/k8s"
@@ -315,13 +315,13 @@ func testOpaque(t *testing.T, name string) {
 	// Update the Server's pod selector so that it no longer selects the
 	// pod. This should result in the proxy protocol no longer being marked
 	// as opaque.
-	srv, err := client.ServerV1beta2().Servers("ns").Get(context.Background(), name, metav1.GetOptions{})
+	srv, err := client.ServerV1beta3().Servers("ns").Get(context.Background(), name, metav1.GetOptions{})
 	if err != nil {
 		t.Fatal(err)
 	}
 	// PodSelector is updated to NOT select the pod
 	srv.Spec.PodSelector.MatchLabels = map[string]string{"app": "FOOBAR"}
-	_, err = client.ServerV1beta2().Servers("ns").Update(context.Background(), srv, metav1.UpdateOptions{})
+	_, err = client.ServerV1beta3().Servers("ns").Update(context.Background(), srv, metav1.UpdateOptions{})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -345,7 +345,7 @@ func testOpaque(t *testing.T, name string) {
 	// as opaque.
 	srv.Spec.PodSelector.MatchLabels = map[string]string{"app": name}
 
-	_, err = client.ServerV1beta2().Servers("ns").Update(context.Background(), srv, metav1.UpdateOptions{})
+	_, err = client.ServerV1beta3().Servers("ns").Update(context.Background(), srv, metav1.UpdateOptions{})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1072,12 +1072,12 @@ func TestGetProfiles(t *testing.T) {
 		}
 
 		// Server is created, setting the port to opaque
-		l5dClient.ServerV1beta2().Servers("ns").Create(context.Background(), &v1beta2.Server{
+		l5dClient.ServerV1beta3().Servers("ns").Create(context.Background(), &v1beta3.Server{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:      "srv-hostport-mapping-2",
 				Namespace: "ns",
 			},
-			Spec: v1beta2.ServerSpec{
+			Spec: v1beta3.ServerSpec{
 				PodSelector: &metav1.LabelSelector{
 					MatchLabels: map[string]string{
 						"app": "hostport-mapping-2",
diff --git a/controller/api/destination/test_util.go b/controller/api/destination/test_util.go
index c7836e1b8..9783b4cf1 100644
--- a/controller/api/destination/test_util.go
+++ b/controller/api/destination/test_util.go
@@ -448,7 +448,7 @@ spec:
         name: http
         protocol: TCP`,
 		`
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: policy-test
@@ -460,7 +460,7 @@ spec:
   port: 80
   proxyProtocol: opaque`,
 		`
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: policy-test-external-workload
@@ -534,7 +534,7 @@ spec:
         name: http
         protocol: TCP`,
 		`
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: native
diff --git a/jaeger/cmd/testdata/install_collector_disabled.golden b/jaeger/cmd/testdata/install_collector_disabled.golden
index e05857997..ebc55d401 100644
--- a/jaeger/cmd/testdata/install_collector_disabled.golden
+++ b/jaeger/cmd/testdata/install_collector_disabled.golden
@@ -74,9 +74,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -111,7 +111,7 @@ spec:
     port: 443
     targetPort: jaeger-injector
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -321,9 +321,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
       dnsPolicy: ClusterFirst
diff --git a/jaeger/cmd/testdata/install_default.golden b/jaeger/cmd/testdata/install_default.golden
index 314976724..a49263a14 100644
--- a/jaeger/cmd/testdata/install_default.golden
+++ b/jaeger/cmd/testdata/install_default.golden
@@ -74,9 +74,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -111,7 +111,7 @@ spec:
     port: 443
     targetPort: jaeger-injector
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -501,9 +501,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -597,9 +597,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
       dnsPolicy: ClusterFirst
@@ -608,7 +608,7 @@ spec:
           type: RuntimeDefault
       serviceAccountName: jaeger
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -625,7 +625,7 @@ spec:
   port: 4317
   proxyProtocol: gRPC
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -642,7 +642,7 @@ spec:
   port: 4318
   proxyProtocol: HTTP/1
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -659,7 +659,7 @@ spec:
   port: 55678
   proxyProtocol: gRPC
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -675,7 +675,7 @@ spec:
       component: collector
   port: 9411
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -691,7 +691,7 @@ spec:
       component: collector
   port: 14268
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -707,7 +707,7 @@ spec:
       component: collector
   port: 14250
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -832,7 +832,7 @@ spec:
   # allow connections from any pod (meshed or not) sending trace data
   requiredAuthenticationRefs: []
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -869,7 +869,7 @@ spec:
       name: collector
       namespace: linkerd-jaeger
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -907,7 +907,7 @@ spec:
       name: prometheus
       namespace: linkerd-viz
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
diff --git a/jaeger/cmd/testdata/install_jaeger_disabled.golden b/jaeger/cmd/testdata/install_jaeger_disabled.golden
index 6bd032ecd..bb1f97a57 100644
--- a/jaeger/cmd/testdata/install_jaeger_disabled.golden
+++ b/jaeger/cmd/testdata/install_jaeger_disabled.golden
@@ -74,9 +74,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -111,7 +111,7 @@ spec:
     port: 443
     targetPort: jaeger-injector
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -490,9 +490,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -510,7 +510,7 @@ spec:
           name: collector-config
         name: collector-config-val
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -527,7 +527,7 @@ spec:
   port: 4317
   proxyProtocol: gRPC
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -544,7 +544,7 @@ spec:
   port: 4318
   proxyProtocol: HTTP/1
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -561,7 +561,7 @@ spec:
   port: 55678
   proxyProtocol: gRPC
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -577,7 +577,7 @@ spec:
       component: collector
   port: 9411
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -593,7 +593,7 @@ spec:
       component: collector
   port: 14268
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -609,7 +609,7 @@ spec:
       component: collector
   port: 14250
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -734,7 +734,7 @@ spec:
   # allow connections from any pod (meshed or not) sending trace data
   requiredAuthenticationRefs: []
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -771,7 +771,7 @@ spec:
       name: collector
       namespace: linkerd-jaeger
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
@@ -809,7 +809,7 @@ spec:
       name: prometheus
       namespace: linkerd-viz
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-jaeger
diff --git a/multicluster/cmd/testdata/install_default.golden b/multicluster/cmd/testdata/install_default.golden
index 000ee1bfb..5c9237d2c 100644
--- a/multicluster/cmd/testdata/install_default.golden
+++ b/multicluster/cmd/testdata/install_default.golden
@@ -49,9 +49,9 @@ spec:
               drop:
               - ALL
             readOnlyRootFilesystem: true
-            runAsGroup: 2103
             runAsNonRoot: true
             runAsUser: 2103
+            runAsGroup: 2103
             seccompProfile:
               type: RuntimeDefault
       securityContext:
@@ -93,7 +93,7 @@ metadata:
   labels:
     linkerd.io/extension: multicluster
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-multicluster
@@ -357,7 +357,7 @@ spec:
     singular: link
     kind: Link
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-multicluster
diff --git a/multicluster/cmd/testdata/install_ha.golden b/multicluster/cmd/testdata/install_ha.golden
index 128d937d2..939ab7a5d 100644
--- a/multicluster/cmd/testdata/install_ha.golden
+++ b/multicluster/cmd/testdata/install_ha.golden
@@ -71,9 +71,9 @@ spec:
               drop:
               - ALL
             readOnlyRootFilesystem: true
-            runAsGroup: 2103
             runAsNonRoot: true
             runAsUser: 2103
+            runAsGroup: 2103
             seccompProfile:
               type: RuntimeDefault
       securityContext:
@@ -131,7 +131,7 @@ metadata:
   labels:
     linkerd.io/extension: multicluster
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-multicluster
@@ -429,7 +429,7 @@ spec:
     singular: link
     kind: Link
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-multicluster
diff --git a/multicluster/cmd/testdata/install_psp.golden b/multicluster/cmd/testdata/install_psp.golden
index 92c62694f..74373d53d 100644
--- a/multicluster/cmd/testdata/install_psp.golden
+++ b/multicluster/cmd/testdata/install_psp.golden
@@ -49,9 +49,9 @@ spec:
               drop:
               - ALL
             readOnlyRootFilesystem: true
-            runAsGroup: 2103
             runAsNonRoot: true
             runAsUser: 2103
+            runAsGroup: 2103
             seccompProfile:
               type: RuntimeDefault
       securityContext:
@@ -93,7 +93,7 @@ metadata:
   labels:
     linkerd.io/extension: multicluster
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-multicluster
@@ -391,7 +391,7 @@ spec:
     singular: link
     kind: Link
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-multicluster
diff --git a/pkg/k8s/authz_test.go b/pkg/k8s/authz_test.go
index cf61603bd..a2c3a9388 100644
--- a/pkg/k8s/authz_test.go
+++ b/pkg/k8s/authz_test.go
@@ -126,7 +126,7 @@ spec:
 `, `
 kind: APIResourceList
 apiVersion: v1beta1
-groupVersion: policy.linkerd.io/v1beta2
+groupVersion: policy.linkerd.io/v1beta3
 resources:
 - name: servers
   singularName: server
@@ -187,7 +187,7 @@ resources:
   shortNames:
   - srv
 `},
-			expectedError: errors.New(`the server could not find the requested resource, GroupVersion "policy.linkerd.io/v1beta2" not found`),
+			expectedError: errors.New(`the server could not find the requested resource, GroupVersion "policy.linkerd.io/v1beta3" not found`),
 		},
 	}
 
diff --git a/test/integration/deep/dualstack/testdata/ipfamilies-policy.yml b/test/integration/deep/dualstack/testdata/ipfamilies-policy.yml
index 7aac13342..9af83d457 100644
--- a/test/integration/deep/dualstack/testdata/ipfamilies-policy.yml
+++ b/test/integration/deep/dualstack/testdata/ipfamilies-policy.yml
@@ -1,4 +1,4 @@
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: ipfamilies
diff --git a/test/integration/install/smoke/testdata/smoke_test.yaml b/test/integration/install/smoke/testdata/smoke_test.yaml
index 30af66dc6..100725165 100644
--- a/test/integration/install/smoke/testdata/smoke_test.yaml
+++ b/test/integration/install/smoke/testdata/smoke_test.yaml
@@ -32,7 +32,7 @@ spec:
     port: 9090
     targetPort: 9090
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: smoke-test-terminus
@@ -93,7 +93,7 @@ spec:
     port: 8080
     targetPort: 8080
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: smoke-test-proxy-admin
diff --git a/test/integration/install/testdata/smoke_test.yaml b/test/integration/install/testdata/smoke_test.yaml
index 30af66dc6..100725165 100644
--- a/test/integration/install/testdata/smoke_test.yaml
+++ b/test/integration/install/testdata/smoke_test.yaml
@@ -32,7 +32,7 @@ spec:
     port: 9090
     targetPort: 9090
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: smoke-test-terminus
@@ -93,7 +93,7 @@ spec:
     port: 8080
     targetPort: 8080
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: smoke-test-proxy-admin
diff --git a/test/integration/viz/policy/testdata/emoji-policy.yaml b/test/integration/viz/policy/testdata/emoji-policy.yaml
index 34e70a401..283d73d81 100644
--- a/test/integration/viz/policy/testdata/emoji-policy.yaml
+++ b/test/integration/viz/policy/testdata/emoji-policy.yaml
@@ -1,5 +1,5 @@
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: emoji-grpc
@@ -31,7 +31,7 @@ spec:
       identities:
         - "*.linkerd-stat-authz-test.serviceaccount.identity.linkerd.cluster.local"
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: voting-grpc
@@ -61,7 +61,7 @@ spec:
       serviceAccounts:
         - name: web
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   name: web-http
diff --git a/viz/cmd/testdata/install_default.golden b/viz/cmd/testdata/install_default.golden
index ce2f74973..b311b895d 100644
--- a/viz/cmd/testdata/install_default.golden
+++ b/viz/cmd/testdata/install_default.golden
@@ -463,7 +463,7 @@ spec:
           type: RuntimeDefault
       serviceAccountName: metrics-api
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -784,7 +784,7 @@ spec:
           name: prometheus-config
         name: prometheus-config
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -924,9 +924,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -942,7 +942,7 @@ spec:
         secret:
           secretName: tap-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1139,9 +1139,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -1157,7 +1157,7 @@ spec:
         secret:
           secretName: tap-injector-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1313,9 +1313,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
       securityContext:
diff --git a/viz/cmd/testdata/install_default_overrides.golden b/viz/cmd/testdata/install_default_overrides.golden
index 44851b4be..25d7e2a61 100644
--- a/viz/cmd/testdata/install_default_overrides.golden
+++ b/viz/cmd/testdata/install_default_overrides.golden
@@ -463,7 +463,7 @@ spec:
           type: RuntimeDefault
       serviceAccountName: metrics-api
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -784,7 +784,7 @@ spec:
           name: prometheus-config
         name: prometheus-config
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -924,9 +924,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 5678
           runAsNonRoot: true
           runAsUser: 5678
+          runAsGroup: 5678
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -942,7 +942,7 @@ spec:
         secret:
           secretName: tap-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1139,9 +1139,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 1234
           runAsNonRoot: true
           runAsUser: 1234
+          runAsGroup: 1234
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -1157,7 +1157,7 @@ spec:
         secret:
           secretName: tap-injector-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1314,9 +1314,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 1234
           runAsNonRoot: true
           runAsUser: 1234
+          runAsGroup: 1234
           seccompProfile:
             type: RuntimeDefault
       securityContext:
diff --git a/viz/cmd/testdata/install_prometheus_disabled.golden b/viz/cmd/testdata/install_prometheus_disabled.golden
index b045ff5a8..0ad7c83b8 100644
--- a/viz/cmd/testdata/install_prometheus_disabled.golden
+++ b/viz/cmd/testdata/install_prometheus_disabled.golden
@@ -423,7 +423,7 @@ spec:
           type: RuntimeDefault
       serviceAccountName: metrics-api
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -492,7 +492,7 @@ spec:
   - cidr: "0.0.0.0/0"
   - cidr: "::/0"
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -632,9 +632,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -650,7 +650,7 @@ spec:
         secret:
           secretName: tap-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -847,9 +847,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -865,7 +865,7 @@ spec:
         secret:
           secretName: tap-injector-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1021,9 +1021,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
       securityContext:
diff --git a/viz/cmd/testdata/install_prometheus_loglevel_from_args.golden b/viz/cmd/testdata/install_prometheus_loglevel_from_args.golden
index a9b8221a1..9755202a3 100644
--- a/viz/cmd/testdata/install_prometheus_loglevel_from_args.golden
+++ b/viz/cmd/testdata/install_prometheus_loglevel_from_args.golden
@@ -463,7 +463,7 @@ spec:
           type: RuntimeDefault
       serviceAccountName: metrics-api
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -784,7 +784,7 @@ spec:
           name: prometheus-config
         name: prometheus-config
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -924,9 +924,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -942,7 +942,7 @@ spec:
         secret:
           secretName: tap-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1139,9 +1139,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -1157,7 +1157,7 @@ spec:
         secret:
           secretName: tap-injector-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1313,9 +1313,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
       securityContext:
diff --git a/viz/cmd/testdata/install_proxy_resources.golden b/viz/cmd/testdata/install_proxy_resources.golden
index 777be4412..c4fe7adb0 100644
--- a/viz/cmd/testdata/install_proxy_resources.golden
+++ b/viz/cmd/testdata/install_proxy_resources.golden
@@ -463,7 +463,7 @@ spec:
           type: RuntimeDefault
       serviceAccountName: metrics-api
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -788,7 +788,7 @@ spec:
           name: prometheus-config
         name: prometheus-config
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -932,9 +932,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -950,7 +950,7 @@ spec:
         secret:
           secretName: tap-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1147,9 +1147,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
         volumeMounts:
@@ -1165,7 +1165,7 @@ spec:
         secret:
           secretName: tap-injector-k8s-tls
 ---
-apiVersion: policy.linkerd.io/v1beta2
+apiVersion: policy.linkerd.io/v1beta3
 kind: Server
 metadata:
   namespace: linkerd-viz
@@ -1325,9 +1325,9 @@ spec:
             drop:
             - ALL
           readOnlyRootFilesystem: true
-          runAsGroup: 2103
           runAsNonRoot: true
           runAsUser: 2103
+          runAsGroup: 2103
           seccompProfile:
             type: RuntimeDefault
       securityContext: