diff --git a/defaults/main.yml b/defaults/main.yml index 9b70084..d199ea5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -104,3 +104,7 @@ lxc_container_download_template_options: > lxc_container_allow_restarts: yes lxc_container_network_veth_pair: "{{ inventory_hostname[-8:].replace('-', '').replace('_', '') }}_{{ item.value.interface }}" + +# Enable fixed mac address generation for an lxc container +lxc_container_fixed_mac: false + diff --git a/releasenotes/notes/container-static-mac-addresses-9aae098fdc8a57cc.yaml b/releasenotes/notes/container-static-mac-addresses-9aae098fdc8a57cc.yaml new file mode 100644 index 0000000..6dcd7c8 --- /dev/null +++ b/releasenotes/notes/container-static-mac-addresses-9aae098fdc8a57cc.yaml @@ -0,0 +1,15 @@ +--- +features: + - LXC containers will now generate a fixed mac address on all + network interfaces when the option `lxc_container_fixed_mac` + is set to **true**. This feature was implemented to resolve + issues with dynamic mac addresses in containers generally + experienced at scale with network intensive services. +fixes: + - LXC containers will now have the ability to use a fixed mac + address on all network interfaces when the option + `lxc_container_fixed_mac` is set **true**. This change will + assist in resolving a long standing issue where network intensive + services, such as neutron and rabbitmq, can enter a confused state + for long periods of time and require rolling restarts or internal + system resets to recover. diff --git a/tasks/container_create.yml b/tasks/container_create.yml index 1beb8e4..51d23e6 100644 --- a/tasks/container_create.yml +++ b/tasks/container_create.yml @@ -172,6 +172,72 @@ tags: - lxc-container-config +# NOTE(cloudnull): Should a container already be up and running with a defined container interface +# the shell command will use the MAC address already set within the container as +# it's value. This allows the tasks to remain idempotent while ensuring that a +# container restart isn't required to set a static mac. +- name: Set define static mac address from an existing interface + shell: | + if lxc-attach -n {{ inventory_hostname }} -- cat /sys/class/net/{{ item.value.interface }}/address; then + lxc-attach -n {{ inventory_hostname }} -- cat /sys/class/net/{{ item.value.interface }}/address > /var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr + fi + args: + executable: /bin/bash + creates: "/var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr" + with_dict: "{{ container_networks | default({}) }}" + delegate_to: "{{ physical_host }}" + failed_when: false + when: + - lxc_container_fixed_mac | bool + tags: + - lxc-container-networks + +# NOTE(cloudnull): This task is being done to allow a container to have a static mac address. +# before this task a container had a dynamic mac address which would +# change when a container was restarted. This restart process causes terrible +# issues in several network intensive systems (RabbitMQ, Neutron, etc). To +# resolve the rotating mac address issue this task is setting the mac in a hwaddr +# file and a lookup is being used in the container-interface.ini template to render +# the static hardware address as expected. +- name: Set unique interface mac address + shell: | + hexchars="0123456789abcdef" + echo "00:16:3e$( + for i in {1..6}; do + echo -n ${hexchars:$(( $RANDOM % 16 )):1} + done | sed -e 's/\(..\)/:\1/g' + )" > /var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr + args: + executable: /bin/bash + creates: "/var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr" + with_dict: "{{ container_networks | default({}) }}" + delegate_to: "{{ physical_host }}" + when: + - lxc_container_fixed_mac | bool + tags: + - lxc-container-networks + +- name: Gather hardware addresses to be used as facts + command: cat /var/lib/lxc/{{ inventory_hostname }}/{{ item.value.interface }}.hwaddr + changed_when: false + register: macs + with_dict: "{{ container_networks | default({}) }}" + delegate_to: "{{ physical_host }}" + when: + - lxc_container_fixed_mac | bool + tags: + - lxc-container-networks + +# NOTE(cloudnull): To dynamically set the the mac address "facts" Ansible line format is being used +- name: Set fixed hardware address fact + set_fact: "{{item.item.value.interface }}_mac_address={{ item.stdout }}" + with_items: + - "{{ macs.results }}" + when: + - lxc_container_fixed_mac | bool + tags: + - lxc-container-networks + - name: LXC host config for container networks template: src: "container-interface.ini.j2" diff --git a/templates/container-interface.ini.j2 b/templates/container-interface.ini.j2 index 181f8f0..46d2eef 100644 --- a/templates/container-interface.ini.j2 +++ b/templates/container-interface.ini.j2 @@ -13,7 +13,11 @@ lxc.network.veth.pair = {{ lxc_container_network_veth_pair[-15:] }} # Host link to attach to, this should be a bridge if lxc.network.type = veth lxc.network.link = {{ item.value.bridge }} # Hardware Address +{% if lxc_container_fixed_mac | bool %} +lxc.network.hwaddr = {{ hostvars[inventory_hostname][item.value.interface + '_mac_address'] }} +{% else %} lxc.network.hwaddr = 00:16:3e:xx:xx:xx +{% endif %} # enable the device on boot lxc.network.flags = up # Set the container network MTU diff --git a/tests/host_vars/container2.yml b/tests/host_vars/container2.yml index 8ef14f9..9e170ec 100644 --- a/tests/host_vars/container2.yml +++ b/tests/host_vars/container2.yml @@ -6,3 +6,5 @@ lxc_container_bind_mounts: - host_directory: "/openstack/{{ inventory_hostname }}/test2" container_directory: "/opt/test2" +# TEST FOR FIXED MAC ADDRESS +lxc_container_fixed_mac: true