From d651ed70f4d2298ba1a372a6b9906e1942a871e8 Mon Sep 17 00:00:00 2001 From: Logan V Date: Sun, 3 Jul 2016 11:50:44 -0500 Subject: [PATCH] Unbound DNS resolution containers Optionally deploy unbound DNS caching resolvers in lieu of managing /etc/hosts across all hosts. This is an opt-in optimization providing centralized DNS resolution containers to allow intra-cluster name resolution identical to what openstack_hosts provides with its /etc/hosts management. Managing /etc/hosts is very inefficient and cumbersome in large environments with lots of hosts, so this change allows for a quicker and more consistent deployment using centralized resolvers. Change-Id: Ibbc1fc77aa42c1a530e2f52a5c3c4ed86d0fe8ea --- ansible-role-requirements.yml | 8 ++ etc/openstack_deploy/conf.d/unbound.conf.aio | 3 + .../conf.d/unbound.conf.example | 8 ++ playbooks/inventory/env.d/unbound.yml | 36 +++++++ playbooks/inventory/group_vars/all.yml | 4 + playbooks/inventory/group_vars/hosts.yml | 4 + playbooks/setup-infrastructure.yml | 1 + playbooks/unbound-install.yml | 94 +++++++++++++++++++ .../notes/unbound-dns-e0b591be4fa2b050.yaml | 6 ++ tests/test_inventory.py | 5 + 10 files changed, 169 insertions(+) create mode 100644 etc/openstack_deploy/conf.d/unbound.conf.aio create mode 100644 etc/openstack_deploy/conf.d/unbound.conf.example create mode 100644 playbooks/inventory/env.d/unbound.yml create mode 100644 playbooks/unbound-install.yml create mode 100644 releasenotes/notes/unbound-dns-e0b591be4fa2b050.yaml diff --git a/ansible-role-requirements.yml b/ansible-role-requirements.yml index 45d73afcbf..00ee6ea010 100644 --- a/ansible-role-requirements.yml +++ b/ansible-role-requirements.yml @@ -146,3 +146,11 @@ scm: git src: https://github.com/logan2211/ansible-etcd version: master +- name: unbound + scm: git + src: https://github.com/logan2211/ansible-unbound + version: master +- name: resolvconf + scm: git + src: https://github.com/logan2211/ansible-resolvconf + version: master diff --git a/etc/openstack_deploy/conf.d/unbound.conf.aio b/etc/openstack_deploy/conf.d/unbound.conf.aio new file mode 100644 index 0000000000..5e21cedc71 --- /dev/null +++ b/etc/openstack_deploy/conf.d/unbound.conf.aio @@ -0,0 +1,3 @@ +unbound_hosts: + aio1: + ip: 172.29.236.100 diff --git a/etc/openstack_deploy/conf.d/unbound.conf.example b/etc/openstack_deploy/conf.d/unbound.conf.example new file mode 100644 index 0000000000..48a8944e8f --- /dev/null +++ b/etc/openstack_deploy/conf.d/unbound.conf.example @@ -0,0 +1,8 @@ +# The infra nodes that will be running the Unbound DNS caching resolvers +unbound_hosts: + infra1: + ip: 172.20.236.111 + infra2: + ip: 172.20.236.112 + infra3: + ip: 172.20.236.113 diff --git a/playbooks/inventory/env.d/unbound.yml b/playbooks/inventory/env.d/unbound.yml new file mode 100644 index 0000000000..e2dc09d8c8 --- /dev/null +++ b/playbooks/inventory/env.d/unbound.yml @@ -0,0 +1,36 @@ +--- +# Copyright 2016, Logan Vig +# +# 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. + +component_skel: + unbound: + belongs_to: + - unbound_all + +container_skel: + unbound_container: + belongs_to: + - unbound_containers + contains: + - unbound + properties: + service_name: unbound + +physical_skel: + unbound_containers: + belongs_to: + - all_containers + unbound_hosts: + belongs_to: + - hosts diff --git a/playbooks/inventory/group_vars/all.yml b/playbooks/inventory/group_vars/all.yml index eb974a3068..c6d2b6044b 100644 --- a/playbooks/inventory/group_vars/all.yml +++ b/playbooks/inventory/group_vars/all.yml @@ -58,6 +58,10 @@ openstack_repo_git_url: "git://{{ internal_lb_vip_address }}" openstack_host_specific_kernel_modules: - { name: "ebtables", pattern: "CONFIG_BRIDGE_NF_EBTABLES", group: "network_hosts" } +## DNS resolution (resolvconf) options +#Group containing resolvers to configure +resolvconf_resolver_group: unbound_all + ## Memcached options memcached_port: 11211 memcached_servers: "{% for host in groups['memcached'] %}{{ hostvars[host]['ansible_ssh_host'] }}:{{ memcached_port }}{% if not loop.last %},{% endif %}{% endfor %}" diff --git a/playbooks/inventory/group_vars/hosts.yml b/playbooks/inventory/group_vars/hosts.yml index 986bdcf679..0360638ca9 100644 --- a/playbooks/inventory/group_vars/hosts.yml +++ b/playbooks/inventory/group_vars/hosts.yml @@ -17,3 +17,7 @@ lxc_hosts_package_state: "{{ package_state }}" openstack_hosts_package_state: "{{ package_state }}" security_package_state: "{{ package_state }}" + +#Disable /etc/hosts management if unbound DNS resolution containers exist +openstack_host_manage_hosts_file: > + "{{ groups['unbound_all'] is not defined or groups['unbound_all'] | length < 1 }}" diff --git a/playbooks/setup-infrastructure.yml b/playbooks/setup-infrastructure.yml index aaf1da2562..820f80d3b2 100644 --- a/playbooks/setup-infrastructure.yml +++ b/playbooks/setup-infrastructure.yml @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +- include: unbound-install.yml - include: repo-install.yml - include: haproxy-install.yml - include: memcached-install.yml diff --git a/playbooks/unbound-install.yml b/playbooks/unbound-install.yml new file mode 100644 index 0000000000..bee91f6a2b --- /dev/null +++ b/playbooks/unbound-install.yml @@ -0,0 +1,94 @@ +--- +# Copyright 2016, Logan Vig +# +# 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. + +- name: Install unbound DNS resolvers + hosts: + - unbound_all + gather_facts: "{{ gather_facts | default(True) }}" + user: root + roles: + - role: "unbound" + tags: + - unbound_server + - role: "system_crontab_coordination" + tags: + - "system-crontab-coordination" + vars: + is_metal: "{{ properties.is_metal|default(false) }}" + +- name: Install unbound DNS resolver client configurations + hosts: + - "!unbound_all" + - all + user: root + pre_tasks: + #gather a list of physical_hosts containing unbound containers + - name: Set unbound physical hosts fact + set_fact: + unbound_physical_hosts: > + {% set _var = [] -%} + {% for i in groups[resolvconf_resolver_group] -%} + {% if hostvars[i]['physical_host'] is defined -%} + {% if _var.append(hostvars[i]['physical_host']) -%}{% endif -%} + {% endif -%} + {% endfor -%} + {{ _var }} + when: resolvconf_enabled | bool + #create a sorted resolver list with affinity toward unbound container(s) + #on the same physical_host + - name: Apply resolver sorting + set_fact: + resolver_list: > + {% set _var = [] -%} + {% for i in groups[resolvconf_resolver_group] -%} + {% if physical_host is defined + and hostvars[i]['physical_host'] is defined + and physical_host == hostvars[i]['physical_host'] -%} + {% if _var.append(dict(host=hostvars[i]['ansible_ssh_host'], priority=100)) -%}{% endif -%} + {% else -%} + {% if _var.append(dict(host=hostvars[i]['ansible_ssh_host'], priority=50)) -%}{% endif -%} + {% endif -%} + {% endfor -%} + {{ _var }} + when: + - resolvconf_enabled | bool + - physical_host is defined + - physical_host in unbound_physical_hosts + - name: Set resolver IP list fact + set_fact: + resolvconf_resolver_ips: "{{ resolver_list | sort(reverse=true, attribute='priority') | map(attribute='host') | list }}" + resolvconf_options: + - 'timeout:1' + when: + - resolvconf_enabled | bool + - resolver_list is defined + - resolver_list | length > 0 + #rotate is only used when no physical_host affinity is defined + - name: Set resolver rotate when physical_host is not an unbound host + set_fact: + resolvconf_options: + - 'timeout:1' + - 'rotate' + when: + - resolvconf_enabled | bool + - resolver_list is not defined + roles: + - role: "resolvconf" + when: resolvconf_enabled | bool + tags: + - unbound_client + vars: + #Only run the resolvconf role when DNS containers are deployed to the env. + resolvconf_enabled: "{{ groups['unbound_all'] is defined and groups['unbound_all'] | length > 0 }}" diff --git a/releasenotes/notes/unbound-dns-e0b591be4fa2b050.yaml b/releasenotes/notes/unbound-dns-e0b591be4fa2b050.yaml new file mode 100644 index 0000000000..0755b0136e --- /dev/null +++ b/releasenotes/notes/unbound-dns-e0b591be4fa2b050.yaml @@ -0,0 +1,6 @@ +--- +features: + - Support for the deployment of Unbound caching DNS resolvers has been added + as an optional replacement for /etc/hosts management across all hosts in + the environment. To enable the Unbound DNS containers, add ``unbound_hosts`` + entries to the environment. diff --git a/tests/test_inventory.py b/tests/test_inventory.py index 34d28fd138..2f730adb7b 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -238,6 +238,11 @@ class TestAnsibleInventoryFormatConstraints(unittest.TestCase): 'swift_remote', 'swift_remote_all', 'swift_remote_container', + 'unbound', + 'unbound_container', + 'unbound_containers', + 'unbound_hosts', + 'unbound_all', 'utility', 'utility_all', 'utility_container',