8b85faf7e6
As part of the minor update workflow and the update workflow, this changes the pacemaker haproxy bundle resource to add the needed mount for public TLS to work. This also handles the reloading of the container to fetch any new certificates and if needed, it will restart the pacemaker resource (for upgrades), since we would need pacemaker to re-create the resource. Change-Id: I850f4de17e7f7e3b46deb27119227ef76658dcb5 Closes-Bug: #1759797
415 lines
18 KiB
YAML
415 lines
18 KiB
YAML
heat_template_version: queens
|
|
|
|
description: >
|
|
OpenStack containerized HAproxy service for pacemaker
|
|
|
|
parameters:
|
|
DockerHAProxyImage:
|
|
description: image
|
|
type: string
|
|
DockerHAProxyConfigImage:
|
|
description: The container image to use for the haproxy config_volume
|
|
type: string
|
|
ServiceData:
|
|
default: {}
|
|
description: Dictionary packing service data
|
|
type: json
|
|
ServiceNetMap:
|
|
default: {}
|
|
description: Mapping of service_name -> network name. Typically set
|
|
via parameter_defaults in the resource registry. This
|
|
mapping overrides those in ServiceNetMapDefaults.
|
|
type: json
|
|
DefaultPasswords:
|
|
default: {}
|
|
type: json
|
|
EndpointMap:
|
|
default: {}
|
|
description: Mapping of service endpoint -> protocol. Typically set
|
|
via parameter_defaults in the resource registry.
|
|
type: json
|
|
SSLCertificate:
|
|
default: ''
|
|
description: >
|
|
The content of the SSL certificate (without Key) in PEM format.
|
|
type: string
|
|
PublicSSLCertificateAutogenerated:
|
|
default: false
|
|
description: >
|
|
Whether the public SSL certificate was autogenerated or not.
|
|
type: boolean
|
|
DeployedSSLCertificatePath:
|
|
default: '/etc/pki/tls/private/overcloud_endpoint.pem'
|
|
description: >
|
|
The filepath of the certificate as it will be stored in the controller.
|
|
type: string
|
|
RoleName:
|
|
default: ''
|
|
description: Role name on which the service is applied
|
|
type: string
|
|
RoleParameters:
|
|
default: {}
|
|
description: Parameters specific to the role
|
|
type: json
|
|
InternalTLSCAFile:
|
|
default: '/etc/ipa/ca.crt'
|
|
type: string
|
|
description: Specifies the default CA cert to use if TLS is used for
|
|
services in the internal network.
|
|
InternalTLSCRLPEMFile:
|
|
default: '/etc/pki/CA/crl/overcloud-crl.pem'
|
|
type: string
|
|
description: Specifies the default CRL PEM file to use for revocation if
|
|
TLS is used for services in the internal network.
|
|
HAProxyInternalTLSCertsDirectory:
|
|
default: '/etc/pki/tls/certs/haproxy'
|
|
type: string
|
|
HAProxyInternalTLSKeysDirectory:
|
|
default: '/etc/pki/tls/private/haproxy'
|
|
type: string
|
|
ConfigDebug:
|
|
default: false
|
|
description: Whether to run config management (e.g. Puppet) in debug mode.
|
|
type: boolean
|
|
|
|
conditions:
|
|
puppet_debug_enabled: {get_param: ConfigDebug}
|
|
public_tls_enabled:
|
|
or:
|
|
- not:
|
|
equals:
|
|
- {get_param: SSLCertificate}
|
|
- ""
|
|
- equals:
|
|
- {get_param: PublicSSLCertificateAutogenerated}
|
|
- true
|
|
|
|
resources:
|
|
|
|
ContainersCommon:
|
|
type: ../containers-common.yaml
|
|
|
|
HAProxyBase:
|
|
type: ../../../puppet/services/pacemaker/haproxy.yaml
|
|
properties:
|
|
EndpointMap: {get_param: EndpointMap}
|
|
ServiceData: {get_param: ServiceData}
|
|
ServiceNetMap: {get_param: ServiceNetMap}
|
|
DefaultPasswords: {get_param: DefaultPasswords}
|
|
RoleName: {get_param: RoleName}
|
|
RoleParameters: {get_param: RoleParameters}
|
|
|
|
outputs:
|
|
role_data:
|
|
description: Role data for the HAproxy role.
|
|
value:
|
|
service_name: {get_attr: [HAProxyBase, role_data, service_name]}
|
|
config_settings:
|
|
map_merge:
|
|
- get_attr: [HAProxyBase, role_data, config_settings]
|
|
- haproxy_docker: true
|
|
tripleo::profile::pacemaker::haproxy_bundle::haproxy_docker_image: &haproxy_image {get_param: DockerHAProxyImage}
|
|
# the list of directories that contain the certs to bind mount in the countainer
|
|
# bind-mounting the directories rather than all the cert, key and pem files ensures
|
|
# that docker won't create directories on the host when then pem files do not exist
|
|
tripleo::profile::pacemaker::haproxy_bundle::tls_mapping: &tls_mapping
|
|
- get_param: InternalTLSCAFile
|
|
- get_param: HAProxyInternalTLSKeysDirectory
|
|
- get_param: HAProxyInternalTLSCertsDirectory
|
|
- get_param: DeployedSSLCertificatePath
|
|
tripleo::profile::pacemaker::haproxy_bundle::internal_certs_directory: {get_param: HAProxyInternalTLSCertsDirectory}
|
|
tripleo::profile::pacemaker::haproxy_bundle::internal_keys_directory: {get_param: HAProxyInternalTLSKeysDirectory}
|
|
# disable the use CRL file until we can restart the container when the file expires
|
|
tripleo::haproxy::crl_file: null
|
|
tripleo::profile::pacemaker::haproxy_bundle::haproxy_docker_image: &haproxy_image_pcmklatest
|
|
list_join:
|
|
- ':'
|
|
- - yaql:
|
|
data: {get_param: DockerHAProxyImage}
|
|
expression: $.data.rightSplit(separator => ":", maxSplits => 1)[0]
|
|
- 'pcmklatest'
|
|
logging_source: {get_attr: [HAProxyBase, role_data, logging_source]}
|
|
logging_groups: {get_attr: [HAProxyBase, role_data, logging_groups]}
|
|
service_config_settings: {get_attr: [HAProxyBase, role_data, service_config_settings]}
|
|
# BEGIN DOCKER SETTINGS
|
|
puppet_config:
|
|
config_volume: haproxy
|
|
puppet_tags: haproxy_config
|
|
step_config:
|
|
list_join:
|
|
- "\n"
|
|
- - "exec {'wait-for-settle': command => '/bin/true' }"
|
|
- "class tripleo::firewall(){}; define tripleo::firewall::rule( $port = undef, $dport = undef, $sport = undef, $proto = undef, $action = undef, $state = undef, $source = undef, $iniface = undef, $chain = undef, $destination = undef, $extras = undef){}"
|
|
- "['pcmk_bundle', 'pcmk_resource', 'pcmk_property', 'pcmk_constraint', 'pcmk_resource_default'].each |String $val| { noop_resource($val) }"
|
|
- 'include ::tripleo::profile::pacemaker::haproxy_bundle'
|
|
config_image: {get_param: DockerHAProxyConfigImage}
|
|
volumes: &deployed_cert_mount
|
|
yaql:
|
|
expression: $.data.select($+":"+$+":ro")
|
|
data: *tls_mapping
|
|
kolla_config:
|
|
/var/lib/kolla/config_files/haproxy.json:
|
|
command: /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg
|
|
config_files:
|
|
- source: "/var/lib/kolla/config_files/src/*"
|
|
dest: "/"
|
|
merge: true
|
|
preserve_properties: true
|
|
optional: true
|
|
- source: "/var/lib/kolla/config_files/src-tls/*"
|
|
dest: "/"
|
|
merge: true
|
|
optional: true
|
|
preserve_properties: true
|
|
permissions:
|
|
- path: /var/lib/haproxy
|
|
owner: haproxy:haproxy
|
|
recurse: true
|
|
- path:
|
|
list_join:
|
|
- ''
|
|
- - {get_param: HAProxyInternalTLSCertsDirectory}
|
|
- '/*'
|
|
owner: haproxy:haproxy
|
|
perm: '0600'
|
|
optional: true
|
|
- path:
|
|
list_join:
|
|
- ''
|
|
- - {get_param: HAProxyInternalTLSKeysDirectory}
|
|
- '/*'
|
|
owner: haproxy:haproxy
|
|
perm: '0600'
|
|
optional: true
|
|
docker_config_scripts: {get_attr: [ContainersCommon, docker_config_scripts]}
|
|
docker_config:
|
|
step_1:
|
|
haproxy_image_tag:
|
|
start_order: 1
|
|
detach: false
|
|
net: host
|
|
user: root
|
|
command:
|
|
- '/bin/bash'
|
|
- '-c'
|
|
- str_replace:
|
|
template:
|
|
"/usr/bin/docker tag 'HAPROXY_IMAGE' 'HAPROXY_IMAGE_PCMKLATEST'"
|
|
params:
|
|
HAPROXY_IMAGE: {get_param: DockerHAProxyImage}
|
|
HAPROXY_IMAGE_PCMKLATEST: *haproxy_image_pcmklatest
|
|
image: {get_param: DockerHAProxyImage}
|
|
volumes:
|
|
- /etc/hosts:/etc/hosts:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
- /dev/shm:/dev/shm:rw
|
|
- /etc/sysconfig/docker:/etc/sysconfig/docker:ro
|
|
- /usr/bin:/usr/bin:ro
|
|
- /var/run/docker.sock:/var/run/docker.sock:rw
|
|
image: {get_param: DockerHAProxyImage}
|
|
step_2:
|
|
haproxy_init_bundle:
|
|
start_order: 3
|
|
detach: false
|
|
net: host
|
|
user: root
|
|
privileged: true
|
|
command: # '/docker_puppet_apply.sh "STEP" "TAGS" "CONFIG" "DEBUG"'
|
|
list_concat:
|
|
- - '/docker_puppet_apply.sh'
|
|
- '2'
|
|
- 'file,file_line,concat,augeas,tripleo::firewall::rule,pacemaker::resource::bundle,pacemaker::property,pacemaker::resource::ip,pacemaker::resource::ocf,pacemaker::constraint::order,pacemaker::constraint::colocation'
|
|
- 'include ::tripleo::profile::base::pacemaker; include ::tripleo::profile::pacemaker::haproxy_bundle'
|
|
- if:
|
|
- puppet_debug_enabled
|
|
- - '--debug'
|
|
- - ''
|
|
image: {get_param: DockerHAProxyImage}
|
|
volumes:
|
|
list_concat:
|
|
- {get_attr: [ContainersCommon, docker_puppet_apply_volumes]}
|
|
- *deployed_cert_mount
|
|
-
|
|
# puppet saves iptables rules in /etc/sysconfig
|
|
- /etc/sysconfig:/etc/sysconfig:rw
|
|
# saving rules require accessing /usr/libexec/iptables/iptables.init, just bind-mount
|
|
# the necessary bit and prevent systemd to try to reload the service in the container
|
|
- /usr/libexec/iptables:/usr/libexec/iptables:ro
|
|
- /usr/libexec/initscripts/legacy-actions:/usr/libexec/initscripts/legacy-actions:ro
|
|
- /etc/corosync/corosync.conf:/etc/corosync/corosync.conf:ro
|
|
- /dev/shm:/dev/shm:rw
|
|
host_prep_tasks:
|
|
- name: create persistent directories
|
|
file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
with_items:
|
|
- /var/lib/haproxy
|
|
metadata_settings:
|
|
get_attr: [HAProxyBase, role_data, metadata_settings]
|
|
update_tasks:
|
|
- name: Set HAProxy upgrade facts
|
|
block: &haproxy_update_upgrade_facts
|
|
- name: Check for haproxy Kolla configuration
|
|
stat:
|
|
path: /var/lib/config-data/puppet-generated/haproxy
|
|
register: haproxy_kolla_config
|
|
- name: Check if haproxy is already containerized
|
|
set_fact:
|
|
haproxy_containerized: "{{haproxy_kolla_config.stat.isdir | default(false)}}"
|
|
- name: get bootstrap nodeid
|
|
tags: common
|
|
command: hiera -c /etc/puppet/hiera.yaml bootstrap_nodeid
|
|
register: bootstrap_node
|
|
- name: set is_bootstrap_node fact
|
|
tags: common
|
|
set_fact: is_bootstrap_node={{bootstrap_node.stdout|lower == ansible_hostname|lower}}
|
|
- name: Mount TLS cert if needed
|
|
when:
|
|
- step|int == 1
|
|
- haproxy_containerized|bool
|
|
- is_bootstrap_node
|
|
block:
|
|
- name: Check haproxy public certificate configuration in pacemaker
|
|
command: cibadmin --query --xpath "//storage-mapping[@id='haproxy-cert']"
|
|
ignore_errors: true
|
|
register: haproxy_cert_mounted
|
|
- name: Disable the haproxy cluster resource
|
|
pacemaker_resource:
|
|
resource: haproxy-bundle
|
|
state: disable
|
|
wait_for_resource: true
|
|
register: output
|
|
retries: 5
|
|
until: output.rc == 0
|
|
# rc == 6 means the configuration doesn't exist in the CIB
|
|
when: haproxy_cert_mounted.rc == 6
|
|
- name: Set HAProxy public cert volume mount fact
|
|
set_fact:
|
|
haproxy_public_cert_path: {get_param: DeployedSSLCertificatePath}
|
|
haproxy_public_tls_enabled: {if: [public_tls_enabled, true, false]}
|
|
- name: Add a bind mount for public certificate in the haproxy bundle
|
|
command: pcs resource bundle update haproxy-bundle storage-map add id=haproxy-cert source-dir={{ haproxy_public_cert_path }} target-dir=/var/lib/kolla/config_files/src-tls/{{ haproxy_public_cert_path }} options=ro
|
|
when: haproxy_cert_mounted.rc == 6 and haproxy_public_tls_enabled|bool
|
|
- name: Enable the haproxy cluster resource
|
|
pacemaker_resource:
|
|
resource: haproxy-bundle
|
|
state: enable
|
|
wait_for_resource: true
|
|
register: output
|
|
retries: 5
|
|
until: output.rc == 0
|
|
when: haproxy_cert_mounted.rc == 6
|
|
- name: Haproxy fetch and retag container image for pacemaker
|
|
when: step|int == 2
|
|
block: &haproxy_fetch_retag_container_tasks
|
|
- name: Get docker Haproxy image
|
|
set_fact:
|
|
docker_image: {get_param: DockerHAProxyImage}
|
|
docker_image_latest: *haproxy_image_pcmklatest
|
|
- name: Get previous Haproxy image id
|
|
shell: "docker images | awk '/haproxy.* pcmklatest/{print $3}'"
|
|
register: haproxy_image_id
|
|
- block:
|
|
- name: Get a list of container using Haproxy image
|
|
shell: "docker ps -a -q -f 'ancestor={{haproxy_image_id.stdout}}'"
|
|
register: haproxy_containers_to_destroy
|
|
# It will be recreated with the delpoy step.
|
|
- name: Remove any container using the same Haproxy image
|
|
shell: "docker rm -fv {{item}}"
|
|
with_items: "{{ haproxy_containers_to_destroy.stdout_lines }}"
|
|
- name: Remove previous Haproxy images
|
|
shell: "docker rmi -f {{haproxy_image_id.stdout}}"
|
|
when:
|
|
- haproxy_image_id.stdout != ''
|
|
- name: Pull latest Haproxy images
|
|
command: "docker pull {{docker_image}}"
|
|
- name: Retag pcmklatest to latest Haproxy image
|
|
shell: "docker tag {{docker_image}} {{docker_image_latest}}"
|
|
# Got to check that pacemaker_is_active is working fine with bundle.
|
|
# TODO: pacemaker_is_active resource doesn't support bundle.
|
|
upgrade_tasks:
|
|
- name: Get docker haproxy image
|
|
set_fact:
|
|
docker_image_latest: *haproxy_image_pcmklatest
|
|
- name: Set HAProxy upgrade facts
|
|
block: *haproxy_update_upgrade_facts
|
|
- name: haproxy baremetal to container upgrade tasks
|
|
when:
|
|
- step|int == 1
|
|
- not haproxy_containerized|bool
|
|
block:
|
|
- name: Check cluster resource status
|
|
pacemaker_resource:
|
|
resource: {get_attr: [HAProxyBase, role_data, service_name]}
|
|
state: started
|
|
check_mode: true
|
|
ignore_errors: true
|
|
register: haproxy_res
|
|
- when: (is_bootstrap_node) and (haproxy_res|succeeded)
|
|
block:
|
|
- name: Disable the haproxy cluster resource.
|
|
pacemaker_resource:
|
|
resource: {get_attr: [HAProxyBase, role_data, service_name]}
|
|
state: disable
|
|
wait_for_resource: true
|
|
register: output
|
|
retries: 5
|
|
until: output.rc == 0
|
|
- name: Delete the stopped haproxy cluster resource.
|
|
pacemaker_resource:
|
|
resource: {get_attr: [HAProxyBase, role_data, service_name]}
|
|
state: delete
|
|
wait_for_resource: true
|
|
register: output
|
|
retries: 5
|
|
until: output.rc == 0
|
|
- name: Expose HAProxy stats socket on the host and mount TLS cert if needed
|
|
when:
|
|
- step|int == 1
|
|
- haproxy_containerized|bool
|
|
- is_bootstrap_node
|
|
block:
|
|
- name: Check haproxy stats socket configuration in pacemaker
|
|
command: cibadmin --query --xpath "//storage-mapping[@id='haproxy-var-lib']"
|
|
ignore_errors: true
|
|
register: haproxy_stats_exposed
|
|
- name: Check haproxy public certificate configuration in pacemaker
|
|
command: cibadmin --query --xpath "//storage-mapping[@id='haproxy-cert']"
|
|
ignore_errors: true
|
|
register: haproxy_cert_mounted
|
|
- name: Disable the haproxy cluster resource
|
|
pacemaker_resource:
|
|
resource: haproxy-bundle
|
|
state: disable
|
|
wait_for_resource: true
|
|
register: output
|
|
retries: 5
|
|
until: output.rc == 0
|
|
# rc == 6 means the configuration doesn't exist in the CIB
|
|
when: haproxy_stats_exposed.rc == 6 or haproxy_cert_mounted.rc == 6
|
|
- name: Add a bind mount for stats socket in the haproxy bundle
|
|
command: pcs resource bundle update haproxy-bundle storage-map add id=haproxy-var-lib source-dir=/var/lib/haproxy target-dir=/var/lib/haproxy options=rw
|
|
when: haproxy_stats_exposed.rc == 6
|
|
- name: Set HAProxy public cert volume mount fact
|
|
set_fact:
|
|
haproxy_public_cert_path: {get_param: DeployedSSLCertificatePath}
|
|
haproxy_public_tls_enabled: {if: [public_tls_enabled, true, false]}
|
|
- name: Add a bind mount for public certificate in the haproxy bundle
|
|
command: pcs resource bundle update haproxy-bundle storage-map add id=haproxy-cert source-dir={{ haproxy_public_cert_path }} target-dir=/var/lib/kolla/config_files/src-tls/{{ haproxy_public_cert_path }} options=ro
|
|
when: haproxy_cert_mounted.rc == 6 and haproxy_public_tls_enabled|bool
|
|
- name: Enable the haproxy cluster resource
|
|
pacemaker_resource:
|
|
resource: haproxy-bundle
|
|
state: enable
|
|
wait_for_resource: true
|
|
register: output
|
|
retries: 5
|
|
until: output.rc == 0
|
|
when: haproxy_stats_exposed.rc == 6 or haproxy_cert_mounted.rc == 6
|
|
- name: Retag the pacemaker image if containerized
|
|
when:
|
|
- step|int == 3
|
|
- haproxy_containerized|bool
|
|
block: *haproxy_fetch_retag_container_tasks
|