Ansible - Debian Based Gotchas - Part-1
As I am currently running through some Docker setups between Debian Jessie and Ubuntu Trusty using Ansible I ran into a few gotchas. Now I would have assumed that everything SHOULD be identical but not so much. With this being said, I figured I would begin to start putting some context around some gotchas that I run into from time to time. And hopefully this will help out others as well.
Docker
When using the following task which is part of this Ansible role for Docker. ansible-docker
---
- name: debian | updating apt-cache
apt:
update_cache: yes
cache_valid_time: 86400
become: true
- name: debian | installing pre-reqs
apt:
name: "{{ item }}"
state: present
become: true
with_items:
- 'apt-transport-https'
- 'ca-certificates'
- 'software-properties-common'
# We are removing the old Docker info
- name: debian | Removing Legacy Docker apt-key
apt_key:
keyserver: "hkp://p80.pool.sks-keyservers.net:80"
id: "58118E89F3A912897C070ADBF76221572C52609D"
state: "absent"
become: true
# We are removing the old Docker info
- name: debian | Removing Legacy Docker Repo
apt_repository:
repo: "deb https://apt.dockerproject.org/repo {{ ansible_distribution | lower }}-{{ ansible_distribution_release }} main"
state: "absent"
become: true
- name: debian | adding docker apt-key
apt_key:
url: "{{ docker_ubuntu_repo_info['url'] }}"
id: "{{ docker_ubuntu_repo_info['id'] }}"
state: "present"
become: true
- name: debian | adding docker repo
apt_repository:
repo: "{{ docker_ubuntu_repo_info['repo'] }}"
state: present
become: true
# We remove docker-engine as this is old package to install. The new package is
# docker-ce
- name: debian | uninstalling old docker package (if exists)
apt:
name: "{{ item }}"
state: "absent"
purge: yes
become: true
with_items:
- 'docker-engine'
- 'lxc-docker'
- name: debian | installing docker pre-reqs
apt:
name: "linux-image-extra-{{ ansible_kernel }}"
state: present
become: true
when: >
ansible_distribution == "Ubuntu" and
(ansible_distribution_version >= '14.04')
- name: debian | installing docker
apt:
name: "docker-ce={{ docker_version_debian }}"
state: "present"
become: true
- name: debian | setting grub memory limit (if set)
lineinfile:
dest: /etc/default/grub
regexp: "^GRUB_CMDLINE_LINUX_DEFAULT"
line: 'GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1"'
register: grub_updated
become: true
when: >
docker_set_grub_memory_limit is defined and
docker_set_grub_memory_limit
- name: debian | updating grub (if updated)
command: update-grub
become: true
when: grub_updated['changed']
- name: debian | installing additonal packages
apt:
name: "{{ item }}"
state: "present"
become: true
with_items:
- bridge-utils
First thing I found was that for some reason when installing python-pip
using APT it caused issues with Debian Jessie. It would throw and error
when executing PIP commands. This does not happen on Ubuntu Trusty. So
to get around this I had to add the following bit of logic to the
Ansible task(s). Notice the when: ansible_distribution == ""
. We use
this Ansible fact that is gathered to determine if we are running Debian
or Ubuntu, do not confuse this with ansible_os_family == "Debian"
as
both Debian and Ubuntu will report this.
Ubuntu:
when: ansible_distribution == "Ubuntu"
Debian:
when: ansible_distribution == "Debian"
Below is the code that is part of the task mentioned above.
- name: uninstall python-pip (If installed) - Debian
apt:
name: python-pip
state: absent
when: ansible_distribution == "Debian"
- name: debian | installing python packages
apt:
name: "{{ item }}"
state: present
with_items:
- python-pip
when: ansible_distribution == "Ubuntu"
- name: debian | installing python packages
easy_install:
name: "{{ item }}"
# state: present
with_items:
- pip
when: ansible_distribution == "Debian"
Now we could change both to use easy_install: as our module to use from an Ansible perspective but…
Another little cool fact that can be used when adding the Docker APT repositories for Debian and Ubuntu is to use the following Ansible facts gathered:
ansible_distribution
ansible_distribution_release
And we can use these as the following defined var in: (adding | lower will ensure that the ansible_distribution will be ubuntu/debian instead of Ubuntu/Debian so that it does not cause issues with adding the APT repositories)
defaults/main.yml
docker_ubuntu_repo_info: #defines docker ubuntu repo info for installing from
- id: 58118E89F3A912897C070ADBF76221572C52609D
keyserver: hkp://p80.pool.sks-keyservers.net:80
repo: "deb https://apt.dockerproject.org/repo {{ ansible_distribution | lower }}-{{ ansible_distribution_release }} main"
tasks/debian.yml
- name: debian | adding docker repo
apt_repository:
repo: "{{ item.repo }}"
state: present
with_items: docker_ubuntu_repo_info
Using these variables will yield the following based on OS.
Ubuntu
:
{{ ansible_distribution }} will be Ubuntu
{{ ansible_distribution_release }} will be trusty
Debian
:
{{ ansible_distribution }} will be Debian
{{ ansible_distribution_release }} will be jessie
UFW
When I began to configure the UFW (Uncomplicated Firewall) for some firewall rules to be used with Docker I ran into an issue on Debian Jessie stating that an invalid syntax error occurred when defining the routed default policy. Again, this works just fine on Ubuntu but not so much on Debian Jessie. After attempting a few different approaches to using the ufw Ansible module I finally pulled up the man page on UFW for Debian Jessie and Ubuntu. Well there is the issue right there. For some reason on Debian Jessie the UFW settings do not allow defining the default routed policy whereas on Ubuntu it does. Go figure. ansible-ufw
So how do we get around this one? It ended up being fairly simple but then again…Why do I need to do this?
Below is the bit of code that allows us to get around this (for now).
Again we will use the ansible_distribution fact to determine if we are
running Ubuntu or Debian when our policy direction is set to routed.
defaults/main.yml
ufw_policies: #defines default policy for incoming, outgoing and routed (forwarded) traffic...allow, deny or reject
- direction: incoming
policy: deny
- direction: outgoing
policy: allow
- direction: routed
policy: deny
tasks/configure_firewall.yml
- name: configure_firewall | setting default UFW policies (incoming, outgoing)
ufw:
direction: "{{ item.direction }}"
policy: "{{ item.policy }}"
with_items: ufw_policies
when: item.direction != "routed"
- name: configure_firewall | setting default UFW policies (routed)
ufw:
direction: "{{ item.direction }}"
policy: "{{ item.policy }}"
with_items: ufw_policies
when: item.direction == "routed" and ansible_distribution != "Debian"
And that is all for now. I will be returning to this post and updating from time to time as I find additional gotchas.
Enjoy!
Leave a comment