diff --git a/ansible/roles/keystone/defaults/main.yml b/ansible/roles/keystone/defaults/main.yml
index b6d148b2bd..d0710e308d 100644
--- a/ansible/roles/keystone/defaults/main.yml
+++ b/ansible/roles/keystone/defaults/main.yml
@@ -195,14 +195,19 @@ keystone_enabled_notification_topics: "{{ keystone_notification_topics | selecta
 ####################
 # Keystone
 ####################
+keystone_service_endpoints:
+  - {'interface': 'internal', 'url': '{{ keystone_internal_url }}'}
+  - {'interface': 'public', 'url': '{{ keystone_public_url }}'}
+
+# TODO(yoctozepto): Remove admin_endpoint leftovers in Antelope (2023.1).
+keystone_service_admin_endpoint: {'interface': 'admin', 'url': '{{ keystone_internal_url }}'}
+keystone_create_admin_endpoint: false
+
 keystone_ks_services:
   - name: "keystone"
     type: "identity"
     description: "Openstack Identity Service"
-    endpoints:
-      - {'interface': 'admin', 'url': '{{ keystone_internal_url }}'}
-      - {'interface': 'internal', 'url': '{{ keystone_internal_url }}'}
-      - {'interface': 'public', 'url': '{{ keystone_public_url }}'}
+    endpoints: "{{ keystone_service_endpoints + ([keystone_service_admin_endpoint] if kolla_action == 'upgrade' or keystone_create_admin_endpoint | bool else []) }}"
 
 ####################
 # TLS
diff --git a/ansible/roles/keystone/tasks/register.yml b/ansible/roles/keystone/tasks/register.yml
index 1afb3fce71..90b0457795 100644
--- a/ansible/roles/keystone/tasks/register.yml
+++ b/ansible/roles/keystone/tasks/register.yml
@@ -4,7 +4,7 @@
   command: >
     docker exec keystone kolla_keystone_bootstrap
     {{ openstack_auth.username }} {{ openstack_auth.password }} {{ keystone_admin_project }}
-    admin {{ keystone_internal_url }} {{ keystone_internal_url }} {{ keystone_public_url }} {{ item }}
+    admin {{ keystone_internal_url }} {{ keystone_public_url }} {{ item }}
   register: keystone_bootstrap
   changed_when: (keystone_bootstrap.stdout | from_json).changed
   failed_when: (keystone_bootstrap.stdout | from_json).failed
diff --git a/ansible/roles/keystone/tasks/upgrade.yml b/ansible/roles/keystone/tasks/upgrade.yml
index a9260131e2..cd387b787a 100644
--- a/ansible/roles/keystone/tasks/upgrade.yml
+++ b/ansible/roles/keystone/tasks/upgrade.yml
@@ -46,3 +46,14 @@
   run_once: True
   when:
     - not use_preconfigured_databases | bool
+
+# TODO(yoctozepto): Remove after Zed (in AA).
+# This is needed to update the admin endpoint as the port has
+# changed in the same release (Zed), i.e., the admin endpoint uses the
+# same port as the other ones (public, internal).
+- import_role:
+    name: service-ks-register
+  vars:
+    service_ks_register_auth: "{{ openstack_keystone_auth }}"
+    service_ks_register_services: "{{ keystone_ks_services }}"
+  run_once: True
diff --git a/releasenotes/notes/keystone-admin-endpoint-optional-8eb8c9a18085d64e.yaml b/releasenotes/notes/keystone-admin-endpoint-optional-8eb8c9a18085d64e.yaml
new file mode 100644
index 0000000000..15833be612
--- /dev/null
+++ b/releasenotes/notes/keystone-admin-endpoint-optional-8eb8c9a18085d64e.yaml
@@ -0,0 +1,9 @@
+---
+upgrade:
+  - |
+    The Keystone's admin endpoint is no longer created by default. Operators
+    of existing deployments may wish to remove it after the upgrade
+    completes. Operators having external services relying on the availability
+    of the Keystone's admin endpoint may set ``keystone_create_admin_endpoint``
+    to ``true`` to keep creating the admin endpoint but such support will
+    be removed after Zed.