diff options
Diffstat (limited to 'roles')
-rw-r--r-- | roles/dns-records/tasks/main.yml | 112 | ||||
-rw-r--r-- | roles/dns-views/defaults/main.yml | 4 | ||||
-rw-r--r-- | roles/dns-views/tasks/main.yml | 30 | ||||
-rw-r--r-- | roles/openstack-stack/defaults/main.yml | 7 | ||||
-rw-r--r-- | roles/openstack-stack/tasks/main.yml | 9 | ||||
-rw-r--r-- | roles/openstack-stack/tasks/subnet_update_dns_servers.yaml | 1 | ||||
-rw-r--r-- | roles/openstack-stack/templates/heat_stack.yaml.j2 | 193 | ||||
-rw-r--r-- | roles/openstack-stack/templates/heat_stack_server.yaml.j2 | 15 | ||||
-rw-r--r-- | roles/openstack-stack/templates/heat_stack_server_nofloating.yaml.j2 | 152 | ||||
-rw-r--r-- | roles/static_inventory/defaults/main.yml | 21 | ||||
-rw-r--r-- | roles/static_inventory/tasks/main.yml | 11 | ||||
-rw-r--r-- | roles/static_inventory/tasks/openstack.yml | 67 | ||||
-rw-r--r-- | roles/static_inventory/tasks/sshconfig.yml | 13 | ||||
-rw-r--r-- | roles/static_inventory/tasks/sshtun.yml | 15 | ||||
-rw-r--r-- | roles/static_inventory/templates/inventory.j2 | 10 | ||||
-rw-r--r-- | roles/static_inventory/templates/openstack_ssh_config.j2 | 21 | ||||
-rw-r--r-- | roles/static_inventory/templates/ssh-tunnel.service.j2 | 20 |
17 files changed, 638 insertions, 63 deletions
diff --git a/roles/dns-records/tasks/main.yml b/roles/dns-records/tasks/main.yml new file mode 100644 index 000000000..305a55195 --- /dev/null +++ b/roles/dns-records/tasks/main.yml @@ -0,0 +1,112 @@ +--- +- name: "Generate list of private A records" + set_fact: + private_records: "{{ private_records | default([]) + [ { 'type': 'A', 'hostname': hostvars[item]['ansible_hostname'], 'ip': hostvars[item]['private_v4'] } ] }}" + with_items: "{{ groups['cluster_hosts'] }}" + +- name: "Add wildcard records to the private A records for infrahosts" + set_fact: + private_records: "{{ private_records | default([]) + [ { 'type': 'A', 'hostname': '*.' + openshift_app_domain, 'ip': hostvars[item]['private_v4'] } ] }}" + with_items: "{{ groups['infra_hosts'] }}" + +- name: "Add public master cluster hostname records to the private A records (single master)" + set_fact: + private_records: "{{ private_records | default([]) + [ { 'type': 'A', 'hostname': (hostvars[groups.masters[0]].openshift_master_cluster_public_hostname | replace(full_dns_domain, ''))[:-1], 'ip': hostvars[groups.masters[0]].private_v4 } ] }}" + when: + - hostvars[groups.masters[0]].openshift_master_cluster_public_hostname is defined + - openstack_num_masters == 1 + +- name: "Add public master cluster hostname records to the private A records (multi-master)" + set_fact: + private_records: "{{ private_records | default([]) + [ { 'type': 'A', 'hostname': (hostvars[groups.masters[0]].openshift_master_cluster_public_hostname | replace(full_dns_domain, ''))[:-1], 'ip': hostvars[groups.lb[0]].private_v4 } ] }}" + when: + - hostvars[groups.masters[0]].openshift_master_cluster_public_hostname is defined + - openstack_num_masters > 1 + +- name: "Set the private DNS server to use the external value (if provided)" + set_fact: + nsupdate_server_private: "{{ external_nsupdate_keys['private']['server'] }}" + nsupdate_key_secret_private: "{{ external_nsupdate_keys['private']['key_secret'] }}" + nsupdate_key_algorithm_private: "{{ external_nsupdate_keys['private']['key_algorithm'] }}" + nsupdate_private_key_name: "{{ external_nsupdate_keys['private']['key_name']|default('private-' + full_dns_domain) }}" + when: + - external_nsupdate_keys is defined + - external_nsupdate_keys['private'] is defined + +- name: "Set the private DNS server to use the provisioned value" + set_fact: + nsupdate_server_private: "{{ hostvars[groups['dns'][0]].public_v4 }}" + nsupdate_key_secret_private: "{{ hostvars[groups['dns'][0]].nsupdate_keys['private-' + full_dns_domain].key_secret }}" + nsupdate_key_algorithm_private: "{{ hostvars[groups['dns'][0]].nsupdate_keys['private-' + full_dns_domain].key_algorithm }}" + when: + - nsupdate_server_private is undefined + +- name: "Generate the private Add section for DNS" + set_fact: + private_named_records: + - view: "private" + zone: "{{ full_dns_domain }}" + server: "{{ nsupdate_server_private }}" + key_name: "{{ nsupdate_private_key_name|default('private-' + full_dns_domain) }}" + key_secret: "{{ nsupdate_key_secret_private }}" + key_algorithm: "{{ nsupdate_key_algorithm_private | lower }}" + entries: "{{ private_records }}" + +- name: "Generate list of public A records" + set_fact: + public_records: "{{ public_records | default([]) + [ { 'type': 'A', 'hostname': hostvars[item]['ansible_hostname'], 'ip': hostvars[item]['public_v4'] } ] }}" + with_items: "{{ groups['cluster_hosts'] }}" + when: hostvars[item]['public_v4'] is defined + +- name: "Add wildcard records to the public A records" + set_fact: + public_records: "{{ public_records | default([]) + [ { 'type': 'A', 'hostname': '*.' + openshift_app_domain, 'ip': hostvars[item]['public_v4'] } ] }}" + with_items: "{{ groups['infra_hosts'] }}" + when: hostvars[item]['public_v4'] is defined + +- name: "Add public master cluster hostname records to the public A records (single master)" + set_fact: + public_records: "{{ public_records | default([]) + [ { 'type': 'A', 'hostname': (hostvars[groups.masters[0]].openshift_master_cluster_public_hostname | replace(full_dns_domain, ''))[:-1], 'ip': hostvars[groups.masters[0]].public_v4 } ] }}" + when: + - hostvars[groups.masters[0]].openshift_master_cluster_public_hostname is defined + - openstack_num_masters == 1 + +- name: "Add public master cluster hostname records to the public A records (multi-master)" + set_fact: + public_records: "{{ public_records | default([]) + [ { 'type': 'A', 'hostname': (hostvars[groups.masters[0]].openshift_master_cluster_public_hostname | replace(full_dns_domain, ''))[:-1], 'ip': hostvars[groups.lb[0]].public_v4 } ] }}" + when: + - hostvars[groups.masters[0]].openshift_master_cluster_public_hostname is defined + - openstack_num_masters > 1 + +- name: "Set the public DNS server details to use the external value (if provided)" + set_fact: + nsupdate_server_public: "{{ external_nsupdate_keys['public']['server'] }}" + nsupdate_key_secret_public: "{{ external_nsupdate_keys['public']['key_secret'] }}" + nsupdate_key_algorithm_public: "{{ external_nsupdate_keys['public']['key_algorithm'] }}" + nsupdate_public_key_name: "{{ external_nsupdate_keys['public']['key_name']|default('public-' + full_dns_domain) }}" + when: + - external_nsupdate_keys is defined + - external_nsupdate_keys['public'] is defined + +- name: "Set the public DNS server details to use the provisioned value" + set_fact: + nsupdate_server_public: "{{ hostvars[groups['dns'][0]].public_v4 }}" + nsupdate_key_secret_public: "{{ hostvars[groups['dns'][0]].nsupdate_keys['public-' + full_dns_domain].key_secret }}" + nsupdate_key_algorithm_public: "{{ hostvars[groups['dns'][0]].nsupdate_keys['public-' + full_dns_domain].key_algorithm }}" + when: + - nsupdate_server_public is undefined + +- name: "Generate the public Add section for DNS" + set_fact: + public_named_records: + - view: "public" + zone: "{{ full_dns_domain }}" + server: "{{ nsupdate_server_public }}" + key_name: "{{ nsupdate_public_key_name|default('public-' + full_dns_domain) }}" + key_secret: "{{ nsupdate_key_secret_public }}" + key_algorithm: "{{ nsupdate_key_algorithm_public | lower }}" + entries: "{{ public_records }}" + +- name: "Generate the final dns_records_add" + set_fact: + dns_records_add: "{{ private_named_records + public_named_records }}" diff --git a/roles/dns-views/defaults/main.yml b/roles/dns-views/defaults/main.yml new file mode 100644 index 000000000..c9f8248af --- /dev/null +++ b/roles/dns-views/defaults/main.yml @@ -0,0 +1,4 @@ +--- +external_nsupdate_keys: {} +named_private_recursion: 'yes' +named_public_recursion: 'no' diff --git a/roles/dns-views/tasks/main.yml b/roles/dns-views/tasks/main.yml new file mode 100644 index 000000000..ffbad2e3f --- /dev/null +++ b/roles/dns-views/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: "Generate ACL list for DNS server" + set_fact: + acl_list: "{{ acl_list | default([]) + [ (hostvars[item]['private_v4'] + '/32') ] }}" + with_items: "{{ groups['cluster_hosts'] }}" + +- name: "Generate the private view" + set_fact: + private_named_view: + - name: "private" + recursion: "{{ named_private_recursion }}" + acl_entry: "{{ acl_list }}" + zone: + - dns_domain: "{{ full_dns_domain }}" + forwarder: "{{ public_dns_nameservers }}" + when: external_nsupdate_keys['private'] is undefined + +- name: "Generate the public view" + set_fact: + public_named_view: + - name: "public" + recursion: "{{ named_public_recursion }}" + zone: + - dns_domain: "{{ full_dns_domain }}" + forwarder: "{{ public_dns_nameservers }}" + when: external_nsupdate_keys['public'] is undefined + +- name: "Generate the final named_config_views" + set_fact: + named_config_views: "{{ private_named_view|default([]) + public_named_view|default([]) }}" diff --git a/roles/openstack-stack/defaults/main.yml b/roles/openstack-stack/defaults/main.yml index 4831d6bc4..c16b5dc00 100644 --- a/roles/openstack-stack/defaults/main.yml +++ b/roles/openstack-stack/defaults/main.yml @@ -1,9 +1,9 @@ --- -dns_volume_size: 1 ssh_ingress_cidr: 0.0.0.0/0 node_ingress_cidr: 0.0.0.0/0 master_ingress_cidr: 0.0.0.0/0 lb_ingress_cidr: 0.0.0.0/0 +bastion_ingress_cidr: 0.0.0.0/0 num_etcd: 0 num_masters: 1 num_nodes: 1 @@ -11,3 +11,8 @@ num_dns: 1 num_infra: 1 nodes_to_remove: [] etcd_volume_size: 2 +dns_volume_size: 1 +lb_volume_size: 5 +use_bastion: False +ui_ssh_tunnel: False +provider_network: None diff --git a/roles/openstack-stack/tasks/main.yml b/roles/openstack-stack/tasks/main.yml index a53e6350b..9b4855294 100644 --- a/roles/openstack-stack/tasks/main.yml +++ b/roles/openstack-stack/tasks/main.yml @@ -8,7 +8,6 @@ - name: set template paths set_fact: stack_template_path: "{{ stack_template_pre.path }}/stack.yaml" - server_template_path: "{{ stack_template_pre.path }}/server.yaml" user_data_template_path: "{{ stack_template_pre.path }}/user-data" - name: generate HOT stack template from jinja2 template @@ -19,7 +18,13 @@ - name: generate HOT server template from jinja2 template template: src: heat_stack_server.yaml.j2 - dest: "{{ server_template_path }}" + dest: "{{ stack_template_pre.path }}/server.yaml" + +- name: generate HOT server w/o floating IPs template from jinja2 template + template: + src: heat_stack_server_nofloating.yaml.j2 + dest: "{{ stack_template_pre.path }}/server_nofloating.yaml" + when: use_bastion|bool - name: generate user_data from jinja2 template template: diff --git a/roles/openstack-stack/tasks/subnet_update_dns_servers.yaml b/roles/openstack-stack/tasks/subnet_update_dns_servers.yaml index be4f07b97..af28fc98f 100644 --- a/roles/openstack-stack/tasks/subnet_update_dns_servers.yaml +++ b/roles/openstack-stack/tasks/subnet_update_dns_servers.yaml @@ -6,3 +6,4 @@ state: present use_default_subnetpool: yes dns_nameservers: "{{ [private_dns_server|default(public_dns_nameservers[0])]|union(public_dns_nameservers)|unique }}" + when: not provider_network diff --git a/roles/openstack-stack/templates/heat_stack.yaml.j2 b/roles/openstack-stack/templates/heat_stack.yaml.j2 index 54941db06..b6b5e3613 100644 --- a/roles/openstack-stack/templates/heat_stack.yaml.j2 +++ b/roles/openstack-stack/templates/heat_stack.yaml.j2 @@ -54,6 +54,7 @@ outputs: description: Floating IPs of the nodes value: { get_attr: [ infra_nodes, floating_ip ] } +{% if num_dns|int > 0 %} dns_name: description: Name of the DNS value: @@ -68,9 +69,11 @@ outputs: dns_private_ips: description: Private IPs of the DNS value: { get_attr: [ dns, private_ip ] } +{% endif %} resources: +{% if not provider_network %} net: type: OS::Neutron::Net properties: @@ -127,6 +130,8 @@ resources: router_id: { get_resource: router } subnet_id: { get_resource: subnet } +{% endif %} + # keypair: # type: OS::Nova::KeyPair # properties: @@ -156,6 +161,13 @@ resources: port_range_min: 22 port_range_max: 22 remote_ip_prefix: {{ ssh_ingress_cidr }} +{% if use_bastion|bool %} + - direction: ingress + protocol: tcp + port_range_min: 22 + port_range_max: 22 + remote_ip_prefix: {{ bastion_ingress_cidr }} +{% endif %} - direction: ingress protocol: icmp remote_ip_prefix: {{ ssh_ingress_cidr }} @@ -398,6 +410,7 @@ resources: port_range_min: 443 port_range_max: 443 +{% if num_dns|int > 0 %} dns-secgrp: type: OS::Neutron::SecurityGroup properties: @@ -432,7 +445,9 @@ resources: port_range_min: 53 port_range_max: 53 remote_ip_prefix: "{{ openstack_subnet_prefix }}.0/24" -{% if num_masters > 1 %} +{% endif %} + +{% if num_masters|int > 1 or ui_ssh_tunnel|bool %} lb-secgrp: type: OS::Neutron::SecurityGroup properties: @@ -443,14 +458,21 @@ resources: protocol: tcp port_range_min: {{ openshift_master_api_port | default(8443) }} port_range_max: {{ openshift_master_api_port | default(8443) }} - remote_ip_prefix: {{ lb_ingress_cidr }} - {% if openshift_master_console_port is defined and openshift_master_console_port != openshift_master_api_port %} + remote_ip_prefix: {{ lb_ingress_cidr | default(bastion_ingress_cidr) }} +{% if ui_ssh_tunnel|bool %} + - direction: ingress + protocol: tcp + port_range_min: {{ openshift_master_api_port | default(8443) }} + port_range_max: {{ openshift_master_api_port | default(8443) }} + remote_ip_prefix: {{ ssh_ingress_cidr }} +{% endif %} +{% if openshift_master_console_port is defined and openshift_master_console_port != openshift_master_api_port %} - direction: ingress protocol: tcp port_range_min: {{ openshift_master_console_port | default(8443) }} port_range_max: {{ openshift_master_console_port | default(8443) }} - remote_ip_prefix: {{ lb_ingress_cidr }} - {% endif %} + remote_ip_prefix: {{ lb_ingress_cidr | default(bastion_ingress_cidr) }} +{% endif %} {% endif %} etcd: @@ -458,14 +480,18 @@ resources: properties: count: {{ num_etcd }} resource_def: +{% if use_bastion|bool %} + type: server_nofloating.yaml +{% else %} type: server.yaml +{% endif %} properties: name: str_replace: template: k8s_type-%index%.cluster_id params: cluster_id: {{ stack_name }} - k8s_type: etcd + k8s_type: {{ etcd_hostname }} cluster_env: {{ public_dns_domain }} cluster_id: {{ stack_name }} group: @@ -475,25 +501,34 @@ resources: k8s_type: etcds cluster_id: {{ stack_name }} type: etcd - image: {{ openstack_image }} + image: {{ openstack_etcd_image }} flavor: {{ etcd_flavor }} key_name: {{ ssh_public_key }} +{% if provider_network %} + net: {{ provider_network }} + net_name: {{ provider_network }} +{% else %} net: { get_resource: net } subnet: { get_resource: subnet } - secgrp: - - { get_resource: {% if openstack_flat_secgrp|default(False)|bool %}flat-secgrp{% else %}etcd-secgrp{% endif %} } - - { get_resource: common-secgrp } - floating_network: {{ external_network }} net_name: str_replace: template: openshift-ansible-cluster_id-net params: cluster_id: {{ stack_name }} +{% endif %} + secgrp: + - { get_resource: {% if openstack_flat_secgrp|default(False)|bool %}flat-secgrp{% else %}etcd-secgrp{% endif %} } + - { get_resource: common-secgrp } +{% if not use_bastion|bool and not provider_network %} + floating_network: {{ external_network }} +{% endif %} volume_size: {{ etcd_volume_size }} +{% if not provider_network %} depends_on: - interface +{% endif %} -{% if num_masters > 1 %} +{% if num_masters|int > 1 %} loadbalancer: type: OS::Heat::ResourceGroup properties: @@ -506,7 +541,7 @@ resources: template: k8s_type-%index%.cluster_id params: cluster_id: {{ stack_name }} - k8s_type: lb + k8s_type: {{ lb_hostname }} cluster_env: {{ public_dns_domain }} cluster_id: {{ stack_name }} group: @@ -516,23 +551,32 @@ resources: k8s_type: lb cluster_id: {{ stack_name }} type: lb - image: {{ openstack_image }} + image: {{ openstack_lb_image }} flavor: {{ lb_flavor }} key_name: {{ ssh_public_key }} +{% if provider_network %} + net: {{ provider_network }} + net_name: {{ provider_network }} +{% else %} net: { get_resource: net } subnet: { get_resource: subnet } - secgrp: - - { get_resource: lb-secgrp } - - { get_resource: common-secgrp } - floating_network: {{ external_network }} net_name: str_replace: template: openshift-ansible-cluster_id-net params: cluster_id: {{ stack_name }} - volume_size: 5 +{% endif %} + secgrp: + - { get_resource: lb-secgrp } + - { get_resource: common-secgrp } + {% if not provider_network %} + floating_network: {{ external_network }} + {% endif %} + volume_size: {{ lb_volume_size }} + {% if not provider_network %} depends_on: - interface + {% endif %} {% endif %} masters: @@ -540,14 +584,18 @@ resources: properties: count: {{ num_masters }} resource_def: +{% if use_bastion|bool %} + type: server_nofloating.yaml +{% else %} type: server.yaml +{% endif %} properties: name: str_replace: template: k8s_type-%index%.cluster_id params: cluster_id: {{ stack_name }} - k8s_type: master + k8s_type: {{ master_hostname }} cluster_env: {{ public_dns_domain }} cluster_id: {{ stack_name }} group: @@ -557,31 +605,40 @@ resources: k8s_type: masters cluster_id: {{ stack_name }} type: master - image: {{ openstack_image }} + image: {{ openstack_master_image }} flavor: {{ master_flavor }} key_name: {{ ssh_public_key }} +{% if provider_network %} + net: {{ provider_network }} + net_name: {{ provider_network }} +{% else %} net: { get_resource: net } subnet: { get_resource: subnet } + net_name: + str_replace: + template: openshift-ansible-cluster_id-net + params: + cluster_id: {{ stack_name }} +{% endif %} secgrp: {% if openstack_flat_secgrp|default(False)|bool %} - { get_resource: flat-secgrp } {% else %} - { get_resource: master-secgrp } - { get_resource: node-secgrp } -{% if num_etcd == 0 %} +{% if num_etcd|int == 0 %} - { get_resource: etcd-secgrp } {% endif %} {% endif %} - { get_resource: common-secgrp } +{% if not use_bastion|bool and not provider_network %} floating_network: {{ external_network }} - net_name: - str_replace: - template: openshift-ansible-cluster_id-net - params: - cluster_id: {{ stack_name }} +{% endif %} volume_size: {{ master_volume_size }} +{% if not provider_network %} depends_on: - interface +{% endif %} compute_nodes: type: OS::Heat::ResourceGroup @@ -590,15 +647,18 @@ resources: removal_policies: - resource_list: {{ nodes_to_remove }} resource_def: +{% if use_bastion|bool %} + type: server_nofloating.yaml +{% else %} type: server.yaml +{% endif %} properties: name: str_replace: - template: subtype-k8s_type-%index%.cluster_id + template: sub_type_k8s_type-%index%.cluster_id params: cluster_id: {{ stack_name }} - k8s_type: node - subtype: app + sub_type_k8s_type: {{ node_hostname }} cluster_env: {{ public_dns_domain }} cluster_id: {{ stack_name }} group: @@ -613,23 +673,32 @@ resources: {% for k, v in openshift_cluster_node_labels.app.iteritems() %} {{ k|e }}: {{ v|e }} {% endfor %} - image: {{ openstack_image }} + image: {{ openstack_node_image }} flavor: {{ node_flavor }} key_name: {{ ssh_public_key }} +{% if provider_network %} + net: {{ provider_network }} + net_name: {{ provider_network }} +{% else %} net: { get_resource: net } subnet: { get_resource: subnet } - secgrp: - - { get_resource: {% if openstack_flat_secgrp|default(False)|bool %}flat-secgrp{% else %}node-secgrp{% endif %} } - - { get_resource: common-secgrp } - floating_network: {{ external_network }} net_name: str_replace: template: openshift-ansible-cluster_id-net params: cluster_id: {{ stack_name }} - volume_size: {{ app_volume_size }} +{% endif %} + secgrp: + - { get_resource: {% if openstack_flat_secgrp|default(False)|bool %}flat-secgrp{% else %}node-secgrp{% endif %} } + - { get_resource: common-secgrp } +{% if not use_bastion|bool and not provider_network %} + floating_network: {{ external_network }} +{% endif %} + volume_size: {{ node_volume_size }} +{% if not provider_network %} depends_on: - interface +{% endif %} infra_nodes: type: OS::Heat::ResourceGroup @@ -640,11 +709,10 @@ resources: properties: name: str_replace: - template: subtypek8s_type-%index%.cluster_id + template: sub_type_k8s_type-%index%.cluster_id params: cluster_id: {{ stack_name }} - k8s_type: node - subtype: infra + sub_type_k8s_type: {{ infra_hostname }} cluster_env: {{ public_dns_domain }} cluster_id: {{ stack_name }} group: @@ -659,11 +727,21 @@ resources: {% for k, v in openshift_cluster_node_labels.infra.iteritems() %} {{ k|e }}: {{ v|e }} {% endfor %} - image: {{ openstack_image }} + image: {{ openstack_infra_image }} flavor: {{ infra_flavor }} key_name: {{ ssh_public_key }} +{% if provider_network %} + net: {{ provider_network }} + net_name: {{ provider_network }} +{% else %} net: { get_resource: net } subnet: { get_resource: subnet } + net_name: + str_replace: + template: openshift-ansible-cluster_id-net + params: + cluster_id: {{ stack_name }} +{% endif %} secgrp: # TODO(bogdando) filter only required node rules into infra-secgrp {% if openstack_flat_secgrp|default(False)|bool %} @@ -671,18 +749,21 @@ resources: {% else %} - { get_resource: node-secgrp } {% endif %} +{% if ui_ssh_tunnel|bool and num_masters|int < 2 %} + - { get_resource: lb-secgrp } +{% endif %} - { get_resource: infra-secgrp } - { get_resource: common-secgrp } +{% if not provider_network %} floating_network: {{ external_network }} - net_name: - str_replace: - template: openshift-ansible-cluster_id-net - params: - cluster_id: {{ stack_name }} +{% endif %} volume_size: {{ infra_volume_size }} +{% if not provider_network %} depends_on: - interface +{% endif %} +{% if num_dns|int > 0 %} dns: type: OS::Heat::ResourceGroup properties: @@ -695,7 +776,7 @@ resources: template: k8s_type-%index%.cluster_id params: cluster_id: {{ stack_name }} - k8s_type: dns + k8s_type: {{ dns_hostname }} cluster_env: {{ public_dns_domain }} cluster_id: {{ stack_name }} group: @@ -705,20 +786,30 @@ resources: k8s_type: dns cluster_id: {{ stack_name }} type: dns - image: {{ openstack_image }} + image: {{ openstack_dns_image }} flavor: {{ dns_flavor }} key_name: {{ ssh_public_key }} +{% if provider_network %} + net: {{ provider_network }} + net_name: {{ provider_network }} +{% else %} net: { get_resource: net } subnet: { get_resource: subnet } - secgrp: - - { get_resource: dns-secgrp } - - { get_resource: common-secgrp } - floating_network: {{ external_network }} net_name: str_replace: template: openshift-ansible-cluster_id-net params: cluster_id: {{ stack_name }} +{% endif %} + secgrp: + - { get_resource: dns-secgrp } + - { get_resource: common-secgrp } +{% if not provider_network %} + floating_network: {{ external_network }} +{% endif %} volume_size: {{ dns_volume_size }} +{% if not provider_network %} depends_on: - interface +{% endif %} +{% endif %} diff --git a/roles/openstack-stack/templates/heat_stack_server.yaml.j2 b/roles/openstack-stack/templates/heat_stack_server.yaml.j2 index 5851d3b9b..a520a8fe2 100644 --- a/roles/openstack-stack/templates/heat_stack_server.yaml.j2 +++ b/roles/openstack-stack/templates/heat_stack_server.yaml.j2 @@ -61,20 +61,24 @@ parameters: label: Net name description: Net name +{% if not provider_network %} subnet: type: string label: Subnet ID description: Subnet resource +{% endif %} secgrp: type: comma_delimited_list label: Security groups description: Security group resources +{% if not provider_network %} floating_network: type: string label: Floating network description: Network to allocate floating IP from +{% endif %} availability_zone: type: string @@ -117,7 +121,11 @@ outputs: - server - addresses - { get_param: net_name } +{% if provider_network %} + - 0 +{% else %} - 1 +{% endif %} - addr resources: @@ -134,6 +142,7 @@ resources: user_data: get_file: user-data user_data_format: RAW + user_data_update_policy: IGNORE metadata: group: { get_param: group } environment: { get_param: cluster_env } @@ -146,16 +155,21 @@ resources: type: OS::Neutron::Port properties: network: { get_param: net } +{% if not provider_network %} fixed_ips: - subnet: { get_param: subnet } +{% endif %} security_groups: { get_param: secgrp } +{% if not provider_network %} floating-ip: type: OS::Neutron::FloatingIP properties: floating_network: { get_param: floating_network } port_id: { get_resource: port } +{% endif %} +{% if not ephemeral_volumes|default(false)|bool %} cinder_volume: type: OS::Cinder::Volume properties: @@ -168,3 +182,4 @@ resources: volume_id: { get_resource: cinder_volume } instance_uuid: { get_resource: server } mountpoint: /dev/sdb +{% endif %} diff --git a/roles/openstack-stack/templates/heat_stack_server_nofloating.yaml.j2 b/roles/openstack-stack/templates/heat_stack_server_nofloating.yaml.j2 new file mode 100644 index 000000000..638fc8b45 --- /dev/null +++ b/roles/openstack-stack/templates/heat_stack_server_nofloating.yaml.j2 @@ -0,0 +1,152 @@ +heat_template_version: 2016-10-14 + +description: OpenShift cluster server w/o floating IP + +parameters: + + name: + type: string + label: Name + description: Name + + group: + type: string + label: Host Group + description: The Primary Ansible Host Group + default: host + + cluster_env: + type: string + label: Cluster environment + description: Environment of the cluster + + cluster_id: + type: string + label: Cluster ID + description: Identifier of the cluster + + type: + type: string + label: Type + description: Type master or node + + subtype: + type: string + label: Sub-type + description: Sub-type compute or infra for nodes, default otherwise + default: default + + key_name: + type: string + label: Key name + description: Key name of keypair + + image: + type: string + label: Image + description: Name of the image + + flavor: + type: string + label: Flavor + description: Name of the flavor + + net: + type: string + label: Net ID + description: Net resource + + net_name: + type: string + label: Net name + description: Net name + + subnet: + type: string + label: Subnet ID + description: Subnet resource + + secgrp: + type: comma_delimited_list + label: Security groups + description: Security group resources + + availability_zone: + type: string + description: The Availability Zone to launch the instance. + default: nova + + volume_size: + type: number + description: Size of the volume to be created. + default: 1 + constraints: + - range: { min: 1, max: 1024 } + description: must be between 1 and 1024 Gb. + + node_labels: + type: json + description: OpenShift Node Labels + default: {"region": "default" } + +outputs: + + name: + description: Name of the server + value: { get_attr: [ server_nofloating, name ] } + + private_ip: + description: Private IP of the server + value: + get_attr: + - server_nofloating + - addresses + - { get_param: net_name } + - 0 + - addr + +resources: + + server_nofloating: + type: OS::Nova::Server + properties: + name: { get_param: name } + key_name: { get_param: key_name } + image: { get_param: image } + flavor: { get_param: flavor } + networks: + - port: { get_resource: port } + user_data: + get_file: user-data + user_data_format: RAW + user_data_update_policy: IGNORE + metadata: + group: { get_param: group } + environment: { get_param: cluster_env } + clusterid: { get_param: cluster_id } + host-type: { get_param: type } + sub-host-type: { get_param: subtype } + node_labels: { get_param: node_labels } + + port: + type: OS::Neutron::Port + properties: + network: { get_param: net } + fixed_ips: + - subnet: { get_param: subnet } + security_groups: { get_param: secgrp } + +{% if not ephemeral_volumes|default(false)|bool %} + cinder_volume: + type: OS::Cinder::Volume + properties: + size: { get_param: volume_size } + availability_zone: { get_param: availability_zone } + + volume_attachment: + type: OS::Cinder::VolumeAttachment + properties: + volume_id: { get_resource: cinder_volume } + instance_uuid: { get_resource: server_nofloating } + mountpoint: /dev/sdb +{% endif %} diff --git a/roles/static_inventory/defaults/main.yml b/roles/static_inventory/defaults/main.yml index 315965cde..871700f8c 100644 --- a/roles/static_inventory/defaults/main.yml +++ b/roles/static_inventory/defaults/main.yml @@ -4,5 +4,26 @@ refresh_inventory: True inventory: static inventory_path: ~/openstack-inventory +# Either to configure bastion +use_bastion: true + +# SSH user/key/options to access hosts via bastion +ssh_user: openshift +ssh_options: >- + -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no + -o ConnectTimeout=90 -o ControlMaster=auto -o ControlPersist=270s + -o ServerAliveInterval=30 -o GSSAPIAuthentication=no + # SSH key to access nodes private_ssh_key: ~/.ssh/openshift + +# The patch to store the generated config to access bastion/hosts +ssh_config_path: /tmp/ssh.config.ansible + +# The IP:port to make an SSH tunnel to access UI on the 1st master +# via bastion node (requires sudo on the ansible control node) +ui_ssh_tunnel: False +ui_port: "{{ openshift_master_api_port | default(8443) }}" +target_ip: "{{ hostvars[groups['masters.' + stack_name|quote][0]].private_v4 }}" + +openstack_private_network: private diff --git a/roles/static_inventory/tasks/main.yml b/roles/static_inventory/tasks/main.yml index 15c81690e..24e11beb6 100644 --- a/roles/static_inventory/tasks/main.yml +++ b/roles/static_inventory/tasks/main.yml @@ -4,3 +4,14 @@ - name: Checkpoint in-memory data into a static inventory include: checkpoint.yml + +- name: Generate SSH config for accessing hosts via bastion + include: sshconfig.yml + when: use_bastion|bool + +- name: Configure SSH tunneling to access UI + include: sshtun.yml + become: true + when: + - use_bastion|bool + - ui_ssh_tunnel|bool diff --git a/roles/static_inventory/tasks/openstack.yml b/roles/static_inventory/tasks/openstack.yml index a25502835..e36974d93 100644 --- a/roles/static_inventory/tasks/openstack.yml +++ b/roles/static_inventory/tasks/openstack.yml @@ -16,6 +16,7 @@ - name: set_fact for openstack inventory nodes set_fact: + registered_bastion_nodes: "{{ (registered_nodes_output.stdout | from_json) | json_query(q) }}" registered_nodes_floating: "{{ (registered_nodes_output.stdout | from_json) | json_query(q2) }}" vars: q: "[] | [?metadata.group=='infra.{{stack_name}}']" @@ -23,25 +24,75 @@ when: - refresh_inventory|bool + - name: set_fact for openstack inventory nodes with provider network + set_fact: + registered_nodes_floating: "{{ (registered_nodes_output.stdout | from_json) | json_query(q) }}" + vars: + q: "[] | [?metadata.clusterid=='{{stack_name}}'] | [?public_v4=='']" + when: + - refresh_inventory|bool + - openstack_provider_network_name|default(None) + - name: Add cluster nodes w/o floating IPs to inventory - with_items: "{{ registered_nodes }}" - when: not item in registered_nodes_floating + with_items: "{{ registered_nodes|difference(registered_nodes_floating) }}" add_host: name: '{{ item.name }}' groups: '{{ item.metadata.group }}' - ansible_host: '{{ item.private_v4 }}' + ansible_host: >- + {% if use_bastion|bool -%} + {{ item.name }} + {%- else -%} + {%- set node = registered_nodes | json_query("[?name=='" + item.name + "']") -%} + {{ node[0].addresses[openstack_private_network|quote][0].addr }} + {%- endif %} ansible_fqdn: '{{ item.name }}' + ansible_user: '{{ ssh_user }}' ansible_private_key_file: '{{ private_ssh_key }}' - private_v4: '{{ item.private_v4 }}' + ansible_ssh_extra_args: '-F {{ ssh_config_path }}' + private_v4: >- + {% set node = registered_nodes | json_query("[?name=='" + item.name + "']") -%} + {{ node[0].addresses[openstack_private_network|quote][0].addr }} - name: Add cluster nodes with floating IPs to inventory with_items: "{{ registered_nodes_floating }}" - when: item in registered_nodes_floating add_host: name: '{{ item.name }}' groups: '{{ item.metadata.group }}' - ansible_host: '{{ item.public_v4 }}' + ansible_host: >- + {% if use_bastion|bool -%} + {{ item.name }} + {%- elif openstack_provider_network_name|default(None) -%} + {{ item.private_v4 }} + {%- else -%} + {{ item.public_v4 }} + {%- endif %} ansible_fqdn: '{{ item.name }}' + ansible_user: '{{ ssh_user }}' ansible_private_key_file: '{{ private_ssh_key }}' - private_v4: '{{ item.private_v4 }}' - public_v4: '{{ item.public_v4 }}' + ansible_ssh_extra_args: '-F {{ ssh_config_path }}' + private_v4: >- + {% set node = registered_nodes | json_query("[?name=='" + item.name + "']") -%} + {{ node[0].addresses[openstack_private_network|quote][0].addr }} + public_v4: >- + {% if openstack_provider_network_name|default(None) -%} + {{ item.private_v4 }} + {%- else -%} + {{ item.public_v4 }} + {%- endif %} + + - name: Add bastion node to inventory + add_host: + name: bastion + groups: bastions + ansible_host: '{{ registered_bastion_nodes[0].public_v4 }}' + ansible_fqdn: '{{ registered_bastion_nodes[0].name }}' + ansible_user: '{{ ssh_user }}' + ansible_private_key_file: '{{ private_ssh_key }}' + ansible_ssh_extra_args: '-F {{ ssh_config_path }}' + private_v4: >- + {% set node = registered_nodes | json_query("[?name=='" + registered_bastion_nodes[0].name + "']") -%} + {{ node[0].addresses[openstack_private_network|quote][0].addr }} + public_v4: '{{ registered_bastion_nodes[0].public_v4 }}' + when: + - registered_bastion_nodes is defined + - use_bastion|bool diff --git a/roles/static_inventory/tasks/sshconfig.yml b/roles/static_inventory/tasks/sshconfig.yml new file mode 100644 index 000000000..7119fe6ff --- /dev/null +++ b/roles/static_inventory/tasks/sshconfig.yml @@ -0,0 +1,13 @@ +--- +- name: set ssh proxy command prefix for accessing nodes via bastion + set_fact: + ssh_proxy_command: >- + ssh {{ ssh_options }} + -i {{ private_ssh_key }} + {{ ssh_user }}@{{ hostvars['bastion'].ansible_host }} + +- name: regenerate ssh config + template: + src: openstack_ssh_config.j2 + dest: "{{ ssh_config_path }}" + mode: 0644 diff --git a/roles/static_inventory/tasks/sshtun.yml b/roles/static_inventory/tasks/sshtun.yml new file mode 100644 index 000000000..b0e4c832c --- /dev/null +++ b/roles/static_inventory/tasks/sshtun.yml @@ -0,0 +1,15 @@ +--- +- name: Create ssh tunnel systemd service + template: + src: ssh-tunnel.service.j2 + dest: /etc/systemd/system/ssh-tunnel.service + mode: 0644 + +- name: reload the systemctl daemon after file update + command: systemctl daemon-reload + +- name: Enable ssh tunnel service + service: + name: ssh-tunnel + enabled: true + state: restarted diff --git a/roles/static_inventory/templates/inventory.j2 b/roles/static_inventory/templates/inventory.j2 index 464726a0b..987c98ec6 100644 --- a/roles/static_inventory/templates/inventory.j2 +++ b/roles/static_inventory/templates/inventory.j2 @@ -10,9 +10,12 @@ %} private_v4={{ hostvars[host]['private_v4'] }}{% endif %} {% if 'public_v4' in hostvars[host] %} public_v4={{ hostvars[host]['public_v4'] }}{% endif %} +{% if 'ansible_user' in hostvars[host] +%} ansible_user={{ hostvars[host]['ansible_user'] }}{% endif %} {% if 'ansible_private_key_file' in hostvars[host] %} ansible_private_key_file={{ hostvars[host]['ansible_private_key_file'] }}{% endif %} - openshift_hostname={{ host }} +{% if use_bastion|bool and 'ansible_ssh_extra_args' in hostvars[host] +%} ansible_ssh_extra_args={{ hostvars[host]['ansible_ssh_extra_args']|quote }}{% endif %} openshift_hostname={{ host }} {% endif %} {% endfor %} @@ -36,6 +39,7 @@ dns [OSEv3:children] nodes etcd +lb # Set variables common for all OSEv3 hosts #[OSEv3:vars] @@ -65,6 +69,9 @@ nodes.{{ stack_name }} [dns:children] dns.{{ stack_name }} +[lb:children] +lb.{{ stack_name }} + # Empty placeholders for all groups of the cluster nodes [masters.{{ stack_name }}] [etcd.{{ stack_name }}] @@ -72,6 +79,7 @@ dns.{{ stack_name }} [nodes.{{ stack_name }}] [app.{{ stack_name }}] [dns.{{ stack_name }}] +[lb.{{ stack_name }}] # BEGIN Autogenerated groups {% for group in groups %} diff --git a/roles/static_inventory/templates/openstack_ssh_config.j2 b/roles/static_inventory/templates/openstack_ssh_config.j2 new file mode 100644 index 000000000..ad5d1253a --- /dev/null +++ b/roles/static_inventory/templates/openstack_ssh_config.j2 @@ -0,0 +1,21 @@ +Host * + IdentitiesOnly yes + +Host bastion + Hostname {{ hostvars['bastion'].ansible_host }} + IdentityFile {{ hostvars['bastion'].ansible_private_key_file }} + User {{ ssh_user }} + StrictHostKeyChecking no + UserKnownHostsFile=/dev/null + +{% for host in groups['all'] | difference(groups['bastions'][0]) %} + +Host {{ host }} + Hostname {{ hostvars[host].ansible_host }} + ProxyCommand {{ ssh_proxy_command }} -W {{ hostvars[host].private_v4 }}:22 + IdentityFile {{ hostvars[host].ansible_private_key_file }} + User {{ ssh_user }} + StrictHostKeyChecking no + UserKnownHostsFile=/dev/null + +{% endfor %} diff --git a/roles/static_inventory/templates/ssh-tunnel.service.j2 b/roles/static_inventory/templates/ssh-tunnel.service.j2 new file mode 100644 index 000000000..0d1cf8f79 --- /dev/null +++ b/roles/static_inventory/templates/ssh-tunnel.service.j2 @@ -0,0 +1,20 @@ +[Unit] +Description=Set up ssh tunneling for OpenShift cluster UI +After=network.target + +[Service] +ExecStart=/usr/bin/ssh -NT -o \ + ServerAliveInterval=60 -o \ + UserKnownHostsFile=/dev/null -o \ + StrictHostKeyChecking=no -o \ + ExitOnForwardFailure=no -i \ + {{ private_ssh_key }} {{ ssh_user }}@{{ hostvars['bastion'].ansible_host }} \ + -L 0.0.0.0:{{ ui_port }}:{{ target_ip }}:{{ ui_port }} + + +# Restart every >2 seconds to avoid StartLimitInterval failure +RestartSec=5 +Restart=always + +[Install] +WantedBy=multi-user.target |