Ansible

Generate systemd files to run Docker containers
Thomas Krag
Technical Lead Infrastructure at Wehkamp
# extrainfo.json
{
"Heritage": "Danish",
"I care about": [
"devops",
"automation",
"engineering and company culture",
"beer"
],
"Twitter": "@ildiroen",
"Slides": "https://slides.com/thomaskrag/ansible-docker-systemd"
}Wehkamp
Legacy
In-house datacenter
VMWare
Microsoft Server
.NET
MSSQL
Monolith
Blaze
Amazon Web Services
Mesos/Marathon
Docker
Scala/node.js
Cassandra
Microservices
Blaze Environment Stack
Mesos/Marathon
Scala/node.js
EC2
AWS
Cassandra
ElasticSearch
(simplified)
What do we use Ansible for?
Mesos/Marathon
Scala/node.js
EC2
AWS
Cassandra
ElasticSearch

Why systemd for Docker?
Why not Docker module for Ansible?
- We lose the benefits of systemd
- We can't define dependencies
An idea is born
Using Jinja2 templates with Ansible
Bas Tichelaar
What services?
- consul
- dnsmasq
- mesos
- prometheus
- haproxy
- zookeeper
- kibana
- grafana
- fluentd
- docker-gc
- and more...
[Service]
Restart=always
RestartSec=10
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill {{ name }}
ExecStartPre=-/usr/bin/docker rm {{ name }}
ExecStartPre=/usr/bin/docker pull {{ image }}
{%if execstartpost is defined %}{% for command in execstartpost %}ExecStartPost={{ command }}{% endfor %}{% endif %}
ExecStart=/usr/bin/docker run \
--name {{ name }} \
{% if team is defined %}
--label team={{ team }} \
{% else %}
--label team=purple \
{% endif %}
--label container_type=infrastructure \
{% for option, value in docker_opts.iteritems() %}
{% if value is string %}
--{{ option }} "{{ value }}" \
{% elif value == true %}
--{{ option }} \
{% elif value is mapping %}
{% for key, item in value.iteritems() %}
--{{ option }} "{{ key }}={{ item }}" \
{% endfor %}
{% else %}
{% for item in value %}
--{{ option }} "{{ item }}" \
{% endfor %}
{% endif %}
{% endfor %}
{{ image }} {% if command is defined %}{{ command }}{% endif %}
{% if execstop is defined %}{% for command in execstop %}ExecStop=-{{ command }}{% endfor %}{% endif %}
ExecStop=/usr/bin/docker stop -t 60 {{ name }}
[Install]
WantedBy=multi-user.target[Unit]
Description={{ name }} container
Requires=docker.service {% if requires is defined %}{% for item in requires %}{{ item }}.service {% endfor %}{% endif %}
{% if before is defined %}Before={% for item in before %}{{ item }}.service {% endfor %}{% endif %}
After=docker.service {% if after is defined %}{% for item in after %}{{ item }}.service {% endfor %}{% endif %}
{% if binds_to is defined %}BindsTo={% for item in binds_to %}{{ item }}.service {% endfor %}{% endif %}
{% if wants is defined %}Wants={% for item in wants %}{{ item }}.service {% endfor %}{% endif %}
---
- name: Run the Blaze-router container for .nl
include: ../../docker-systemd/tasks/main.yml
vars:
execstop:
- "/usr/local/bin/init_elb.sh deregister"
execstartpost:
- "/usr/local/bin/init_elb.sh register"
after:
- consul
- fluentd
name: blaze-router
image: "{{ container_router_nl }}"
docker_opts:
publish:
- "{{ inventory_hostname }}:80:80"
- "{{ inventory_hostname }}:81:81"
- "{{ inventory_hostname }}:443:443"
- "{{ inventory_hostname }}:9102:9101"
net: bridge
volume:
- /etc/ssl/certs:/etc/ssl/certs:ro
env:
SERVICE_443_NAME: blaze-router
SERVICE_81_CHECK_HTTP: /status
SERVICE_9101_NAME: prometheus-router-exporter
SERVICE_9101_TAGS: exposes-metrics
log-driver: fluentd
log-opt:
fluentd-tag: docker.blaze-router
tags:
- dockeronly
- haproxy
when: blaze_country == "nl"But does it work?
Moment of truth!
ansible-docker-systemd
By Thomas Krag
ansible-docker-systemd
This presentation shows how to leverage Ansible templating (jinja2) to create systemd files to manage Docker containers.
- 531