-
Notifications
You must be signed in to change notification settings - Fork 152
Add skupper for BKL and keystone to SKMO job #3836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
openshift-merge-bot
merged 1 commit into
openstack-k8s-operators:main
from
vakwetu:skmo-skupper-keystone
Apr 23, 2026
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
160 changes: 160 additions & 0 deletions
160
hooks/playbooks/skmo/configure-leaf-keystone-internal.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| --- | ||
| # Patch the leaf/workload region OpenStackControlPlane to use the Skupper | ||
| # Listener virtual endpoint for internal Keystone authentication traffic. | ||
| # | ||
| # The public endpoint override is left unchanged so that end-user traffic and | ||
| # the Keystone service catalog continue to reference the central region's | ||
| # external (public) URL. Only the *internal* override — used for all | ||
| # service-to-service communication inside the workload namespace — is updated | ||
| # to point at the Skupper Listener. | ||
| # | ||
| # After the OSCP is updated, this playbook also ensures that EDPM compute | ||
| # nodes can resolve the Skupper Keystone virtual service name. The Skupper | ||
| # Listener creates a ClusterIP-only Service (keystone-regionone) that is not | ||
| # reachable from outside the OCP cluster. EDPM nodes use the dnsmasq | ||
| # LoadBalancer Service (in the leaf namespace) as their DNS server and require | ||
| # a resolvable hostname for the Keystone auth_url configured in nova.conf. | ||
| # To bridge this gap, the playbook: | ||
| # 1. Creates a dedicated MetalLB LoadBalancer Service that selects the | ||
| # Skupper router pod and exposes port 5000 on the leaf internalapi network. | ||
| # 2. Creates a DNSData CR so dnsmasq resolves both the short (.svc) and | ||
| # fully-qualified (.svc.cluster.local) names to the LoadBalancer IP. | ||
| # | ||
| # This playbook is a no-op when cifmw_skupper_keystone_enabled is false. In | ||
| # that case, skupper-keystone-connector.yaml (pre_stage hook) has already | ||
| # written the public Keystone URL into skmo-values.yaml so the leaf OSCP is | ||
| # created with the public endpoint — no Skupper tunnel is used and there is no | ||
| # matching Connector for the Skupper Listener, so the OSCP must not be patched | ||
| # to point at the Skupper virtual Service. | ||
| # | ||
| # Run skupper-keystone-connector.yaml and skupper-keystone-listener.yaml | ||
| # before this playbook so that the Skupper virtual service is in place. | ||
| # | ||
| # Variables: | ||
| # cifmw_skupper_keystone_enabled (default: true) | ||
| # When false, all tasks in this playbook are skipped. | ||
| # cifmw_skupper_leaf_namespace (default: openstack2) | ||
| # cifmw_skupper_keystone_listener_host (default: keystone-regionone) | ||
| # cifmw_skupper_keystone_port (default: 5000) | ||
| # cifmw_skupper_keystone_metallb_pool (default: internalapi2) | ||
| # MetalLB address-pool name for the leaf internalapi network. An IP is | ||
| # auto-assigned from this pool; no static address is required. | ||
| - name: Configure leaf region to use Skupper Keystone internal endpoint | ||
| hosts: "{{ cifmw_target_hook_host | default('localhost') }}" | ||
| gather_facts: false | ||
| vars: | ||
| cifmw_skupper_keystone_enabled: true | ||
| cifmw_skupper_leaf_namespace: openstack2 | ||
| cifmw_skupper_keystone_listener_host: keystone-regionone | ||
| cifmw_skupper_keystone_port: 5000 | ||
| cifmw_skupper_keystone_metallb_pool: internalapi2 | ||
| tasks: | ||
| - name: Skip all tasks when Skupper Keystone routing is disabled | ||
| ansible.builtin.meta: end_play | ||
| when: not cifmw_skupper_keystone_enabled | bool | ||
|
|
||
| - name: Build the Skupper Keystone internal URL | ||
| ansible.builtin.set_fact: | ||
| _skupper_keystone_internal_url: >- | ||
| https://{{ cifmw_skupper_keystone_listener_host }}.{{ cifmw_skupper_leaf_namespace }}.svc.cluster.local:{{ cifmw_skupper_keystone_port }} | ||
|
|
||
| - name: Patch leaf OSCP internal Keystone override to use Skupper endpoint | ||
| # This switches the internal keystone endpoint URL from the central | ||
| # region's public URL to the Skupper Listener virtual service. The | ||
| # public endpoint override is not touched. | ||
| kubernetes.core.k8s: | ||
| state: patched | ||
| api_version: core.openstack.org/v1beta1 | ||
| kind: OpenStackControlPlane | ||
| name: controlplane | ||
| namespace: "{{ cifmw_skupper_leaf_namespace }}" | ||
| definition: | ||
| spec: | ||
| keystone: | ||
| template: | ||
| override: | ||
| service: | ||
| internal: | ||
| endpointURL: "{{ _skupper_keystone_internal_url }}" | ||
|
|
||
| - name: Wait for leaf OSCP to reconcile after Keystone endpoint change | ||
| kubernetes.core.k8s_info: | ||
| api_version: core.openstack.org/v1beta1 | ||
| kind: OpenStackControlPlane | ||
| name: controlplane | ||
| namespace: "{{ cifmw_skupper_leaf_namespace }}" | ||
| register: _leaf_oscp | ||
| retries: 60 | ||
| delay: 30 | ||
| until: | ||
| - _leaf_oscp.resources | length > 0 | ||
| - _leaf_oscp.resources[0].status is defined | ||
| - _leaf_oscp.resources[0].status.conditions is defined | ||
| - _leaf_oscp.resources[0].status.conditions | | ||
| selectattr('type', 'equalto', 'Ready') | | ||
| selectattr('status', 'equalto', 'True') | list | length > 0 | ||
|
|
||
| - name: Create LoadBalancer service to expose Skupper Keystone for EDPM nodes | ||
| # The Skupper Listener creates a ClusterIP-only Service that EDPM nodes | ||
| # outside the OCP cluster cannot reach. This LoadBalancer Service selects | ||
| # the same Skupper router pod and obtains a MetalLB IP on the leaf | ||
| # internalapi network, making port 5000 reachable from EDPM compute nodes. | ||
| kubernetes.core.k8s: | ||
| state: present | ||
| definition: | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: "{{ cifmw_skupper_keystone_listener_host }}-lb" | ||
| namespace: "{{ cifmw_skupper_leaf_namespace }}" | ||
| annotations: | ||
| metallb.universe.tf/address-pool: "{{ cifmw_skupper_keystone_metallb_pool }}" | ||
| spec: | ||
| type: LoadBalancer | ||
| selector: | ||
| application: skupper-router | ||
| skupper.io/component: router | ||
| ports: | ||
| - name: keystone-internal | ||
| port: "{{ cifmw_skupper_keystone_port | int }}" | ||
| protocol: TCP | ||
| targetPort: 1024 | ||
|
|
||
| - name: Wait for MetalLB to assign an external IP to the keystone LoadBalancer | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Service | ||
| name: "{{ cifmw_skupper_keystone_listener_host }}-lb" | ||
| namespace: "{{ cifmw_skupper_leaf_namespace }}" | ||
| register: _keystone_lb_svc | ||
| retries: 12 | ||
| delay: 10 | ||
| until: | ||
| - _keystone_lb_svc.resources | length > 0 | ||
| - _keystone_lb_svc.resources[0].status.loadBalancer.ingress is defined | ||
| - _keystone_lb_svc.resources[0].status.loadBalancer.ingress | length > 0 | ||
|
|
||
| - name: Set keystone LoadBalancer IP fact | ||
| ansible.builtin.set_fact: | ||
| _keystone_lb_ip: >- | ||
| {{ _keystone_lb_svc.resources[0].status.loadBalancer.ingress[0].ip }} | ||
|
|
||
| - name: Create DNSData entry for Skupper Keystone endpoint | ||
| # Adds both the short (.svc) and fully-qualified (.svc.cluster.local) | ||
| # names to the dnsmasq instance serving EDPM nodes, so that nova-compute | ||
| # auth_url lookups resolve to the LoadBalancer IP above. | ||
| kubernetes.core.k8s: | ||
| state: present | ||
| definition: | ||
| apiVersion: network.openstack.org/v1beta1 | ||
| kind: DNSData | ||
| metadata: | ||
| name: keystone-skupper | ||
| namespace: "{{ cifmw_skupper_leaf_namespace }}" | ||
| spec: | ||
| dnsDataLabelSelectorValue: dnsdata | ||
| hosts: | ||
| - hostnames: | ||
| - "{{ cifmw_skupper_keystone_listener_host }}.{{ cifmw_skupper_leaf_namespace }}.svc" | ||
| - "{{ cifmw_skupper_keystone_listener_host }}.{{ cifmw_skupper_leaf_namespace }}.svc.cluster.local" | ||
| ip: "{{ _keystone_lb_ip }}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,64 @@ | ||
| --- | ||
| - name: Patch leaf control plane with barbican-keystone-listener transport URL | ||
| hosts: localhost | ||
| # Configure the leaf barbican-keystone-listener to use the Skupper | ||
| # application network for cross-region RabbitMQ access. | ||
| # | ||
| # In the leaf region: | ||
| # - Read the RabbitMQ credentials from the dedicated user credentials secret | ||
| # created by the RabbitMQ operator when the TransportURL CR is reconciled. | ||
| # - Patch barbicanKeystoneListener to connect to the central RabbitMQ via the | ||
| # Skupper Listener endpoint using those credentials and its own pool_name. | ||
| # | ||
| # Variables: | ||
| # cifmw_skupper_central_namespace (default: openstack) | ||
| # cifmw_skupper_leaf_namespace (default: openstack2) | ||
| # cifmw_skupper_listener_host (default: rabbitmq-regionone) | ||
| # Must match the host set in skupper-listener.yaml. | ||
| # cifmw_skupper_rabbitmq_port (default: 5671) | ||
| # cifmw_skupper_transport_url_name (default: barbican-keystone-listener-regiontwo) | ||
| # Name of the TransportURL CR created in prepare-leaf.yaml. The operator | ||
| # creates a user credentials secret named: | ||
| # rabbitmq-user-<name>-<username>-user | ||
| # cifmw_skupper_transport_url_username (default: barbican-keystone-listener-regiontwo) | ||
| # Must match the username field set on the TransportURL CR in prepare-leaf.yaml. | ||
| - name: Configure barbican-keystone-listener to use Skupper for cross-region RabbitMQ | ||
| hosts: "{{ cifmw_target_hook_host | default('localhost') }}" | ||
| gather_facts: false | ||
| vars: | ||
| central_namespace: openstack | ||
| leaf_namespace: openstack2 | ||
| leaf_transport_url_name: rabbitmq-transport-url-barbican-keystone-listener-regiontwo | ||
| cifmw_skupper_central_namespace: openstack | ||
| cifmw_skupper_leaf_namespace: openstack2 | ||
| cifmw_skupper_listener_host: rabbitmq-regionone | ||
| cifmw_skupper_rabbitmq_port: 5671 | ||
| cifmw_skupper_transport_url_name: barbican-keystone-listener-regiontwo | ||
| cifmw_skupper_transport_url_username: barbican-keystone-listener-regiontwo | ||
| tasks: | ||
| - name: Get transport URL secret from central namespace | ||
| - name: Get RabbitMQ user credentials secret for leaf listener | ||
| # The RabbitMQ operator creates a secret named | ||
| # rabbitmq-user-<transport-url-name>-<username>-user that contains | ||
| # the username and password fields for the dedicated RabbitMQ user. | ||
| kubernetes.core.k8s_info: | ||
| api_version: v1 | ||
| kind: Secret | ||
| namespace: "{{ central_namespace }}" | ||
| name: "{{ leaf_transport_url_name }}" | ||
| register: _transport_secret | ||
| namespace: "{{ cifmw_skupper_central_namespace }}" | ||
| name: "rabbitmq-user-{{ cifmw_skupper_transport_url_name }}-{{ cifmw_skupper_transport_url_username }}-user" | ||
| register: _rabbitmq_user_secret | ||
|
|
||
| - name: Patch OpenStackControlPlane in leaf region with notifications transport_url | ||
| - name: Patch leaf barbicanKeystoneListener to use Skupper RabbitMQ endpoint | ||
| vars: | ||
| _transport_url: "{{ _transport_secret.resources[0].data['transport_url'] | b64decode }}" | ||
| _username: "{{ _rabbitmq_user_secret.resources[0].data['username'] | b64decode }}" | ||
| _password: "{{ _rabbitmq_user_secret.resources[0].data['password'] | b64decode }}" | ||
| kubernetes.core.k8s: | ||
| state: patched | ||
| api_version: core.openstack.org/v1beta1 | ||
| kind: OpenStackControlPlane | ||
| name: controlplane | ||
| namespace: "{{ leaf_namespace }}" | ||
| namespace: "{{ cifmw_skupper_leaf_namespace }}" | ||
| definition: | ||
| spec: | ||
| barbican: | ||
| template: | ||
| barbicanKeystoneListener: | ||
| customServiceConfig: | | ||
| [DEFAULT] | ||
| transport_url = {{ _transport_url }} | ||
| transport_url = rabbit://{{ _username }}:{{ _password }}@{{ cifmw_skupper_listener_host }}:{{ cifmw_skupper_rabbitmq_port }}/?ssl=1 | ||
| [keystone_notifications] | ||
| pool_name = barbican-listener-regionTwo | ||
| pool_name = barbican-listener-regiontwo | ||
|
danpawlik marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| --- | ||
| # Shared task file: Create a Skupper Connector CR and wait for it to be | ||
| # Configured. Include this from service-specific connector playbooks after | ||
| # the TLS credentials have been discovered and stored in the variables below. | ||
| # | ||
| # Expected variables (set via include_tasks vars: block): | ||
| # _cifmw_connector_name Skupper Connector CR name | ||
| # _cifmw_connector_namespace Namespace for the Connector | ||
| # _cifmw_connector_routing_key Skupper routing key (must match Listener) | ||
| # _cifmw_connector_host Backend service hostname | ||
| # _cifmw_connector_port Backend service port | ||
| # _cifmw_connector_tls_credentials Name of the TLS Secret for the backend | ||
| # _cifmw_connector_verify_hostname Whether Skupper verifies the backend cert hostname | ||
| # _cifmw_connector_ignore_wait_errors Whether to ignore wait failures | ||
|
|
||
| - name: Create Skupper Connector | ||
| kubernetes.core.k8s: | ||
| state: present | ||
| definition: | ||
| apiVersion: skupper.io/v2alpha1 | ||
| kind: Connector | ||
| metadata: | ||
| name: "{{ _cifmw_connector_name }}" | ||
| namespace: "{{ _cifmw_connector_namespace }}" | ||
| spec: | ||
| routingKey: "{{ _cifmw_connector_routing_key }}" | ||
| host: "{{ _cifmw_connector_host }}" | ||
| port: "{{ _cifmw_connector_port }}" | ||
| type: tcp | ||
| tlsCredentials: "{{ _cifmw_connector_tls_credentials }}" | ||
| verifyHostname: "{{ _cifmw_connector_verify_hostname }}" | ||
|
|
||
| - name: Wait for Skupper Connector to be configured | ||
| # A Connector shows "Ready" only after a matching Listener is deployed in | ||
| # the remote namespace. Waiting for "Configured" is sufficient here. | ||
| ignore_errors: "{{ _cifmw_connector_ignore_wait_errors | bool }}" | ||
| kubernetes.core.k8s_info: | ||
| api_version: skupper.io/v2alpha1 | ||
| kind: Connector | ||
| name: "{{ _cifmw_connector_name }}" | ||
| namespace: "{{ _cifmw_connector_namespace }}" | ||
| register: _connector | ||
| retries: 30 | ||
| delay: 10 | ||
| until: | ||
| - _connector.resources | length > 0 | ||
| - _connector.resources[0].status is defined | ||
| - _connector.resources[0].status.conditions is defined | ||
| - _connector.resources[0].status.conditions | | ||
| selectattr('type', 'equalto', 'Configured') | | ||
| selectattr('status', 'equalto', 'True') | list | length > 0 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.