Ansible Workshop

Created by Viktor Farcic for Technology Conversations

@vfarcic

Viktor Farcic

Configuration Management in the Docker World

Environments

  • Master server
  • Cluster
  • Ubuntu

Environments

Create VMs


cd ansible-workshop

cat Vagrantfile

vagrant up

vagrant ssh cd
						

The Project

Deploy Docker Swarm to the Cluster

  • Common packages
  • Consul
  • Docker
  • Docker Swarm

The Project

Structure


tree /vagrant/ansible/roles

cat /vagrant/ansible/hosts/prod

cat /vagrant/ansible/swarm.yml
						

Common Role

Task: JQ

Install the jq package

Tip: http://docs.ansible.com/ansible/apt_module.html

Common Role

Solution: JQ


# roles/common/tasks/main.yml
- apt:
    name: jq
						

Common Role

Task: Run the playbook

Run the Ansible Playbook


ansible-playbook /vagrant/ansible/swarm.yml \
    -i /vagrant/ansible/hosts/prod
						

Common Role

Test


curl https://api.github.com/repos/vfarcic/\
ansible-workshop/commits?per_page=5 \
    | jq '.'
						

Consul Role

Task: Directories

Create the following directories:

  • /data/consul/logs
  • /data/consul/data
  • /data/consul/config

Tip: http://docs.ansible.com/ansible/file_module.html

Consul Role

Solution: Directories


# roles/consul/tasks/main.yml

- file:
    path: "{{ item }}"
    state: directory
  with_items:
    - /data/consul/logs
    - /data/consul/data
    - /data/consul/config
						

Consul Role

Task: Files

Copy the following files:

  • consul > /usr/local/bin/consul (mode 0755)
  • ui > /data/consul (mode 0644)

Tips:

Consul Role

Solution: Files


# roles/consul/tasks/main.yml

- copy:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    mode: "{{ item.mode }}"
  with_items:
    - { src: "consul", dest: "/usr/local/bin/consul", mode: "0755" }
    - { src: "ui", dest: "/data/consul", mode: "0644" }
						

Consul Role

Task: Run the Agent (1/2)

Run the following command:


nohup consul agent [EXTRA] \
    -ui-dir /data/consul/ui \
    -data-dir /data/consul/data \
    -config-dir /data/consul/config \
    -node=[HOST_NAME] \
    -bind=[IP] \
    -client=0.0.0.0 \
    >/data/consul/logs/consul.log 2>&1 &
						

Consul Role

Task: Run the Agent (2/2)

  • [EXTRA] should be replaced with -server -bootstrap-expect 1 on the main server and be empty on all others.
  • [HOST_NAME] should be replaced with the name of the host.
  • [IP] should be replaced with the IP of the host

Tips:

Consul Role

Solution: Run the Agent


# hosts/prod
[swarm]
10.100.192.200 consul_extra="-server -bootstrap-expect 1"
10.100.192.20[1:2] consul_extra=""

# roles/consul/tasks/main.yml
- shell: nohup consul agent {{ consul_extra }} \
      -ui-dir /data/consul/ui \
      -data-dir /data/consul/data \
      -config-dir /data/consul/config \
      -node={{ ansible_hostname }} \
      -bind={{ facter_ipaddress_eth1 }} \
      -client=0.0.0.0 \
      >/data/consul/logs/consul.log 2>&1 &
						

Consul Role

Task: Join the Cluster

Run the following command only if NOT the main server.


consul join [IP_OF_THE_MAIN_SERVER]
						
  • [IP_OF_THE_MAIN_SERVER] should be replaced with the IP of the main server (10.100.192.200)

Tips:

Consul Role

Solution: Join the Cluster


# hosts/prod

[swarm]
10.100.192.200
10.100.192.20[1:2] main_server_ip=10.100.192.200

# roles/consul/tasks/main.yml

- shell: consul join {{ main_server_ip }}
  when: main_server_ip is defined
						

Common Role

Test


curl 10.100.192.200:8500/v1/catalog/nodes \
    | jq '.'
						
Open http://10.100.192.200:8500/

Docker Role

Task: Add Repository

Add Docker repository deb https://apt.dockerproject.org/repo ubuntu-trusty main and update cache.

Tips:

Docker Role

Solution: Add Repository


# roles/docker/tasks/main.yml

- apt_repository:
    repo: deb https://apt.dockerproject.org/repo ubuntu-trusty main
    update_cache: yes
						

Docker Role

Task: Install Debian Packages

Install the following Debian packages:

  • docker-engine
  • python-pip

Tips:

Docker Role

Solution: Install Debian Packages


# roles/docker/tasks/main.yml

- apt:
    name: "{{ item }}"
    force: yes
  with_items:
    - docker-engine
    - python-pip
						

Docker Role

Task: Install PIP Package

Install the docker-py PIP package version 0.4.0

Tips:

Docker Role

Solution: Install PIP Package


# roles/docker/tasks/main.yml

- pip:
    name: docker-py
    version: 0.4.0
						

Common Role

Test


sudo docker --version
						

Swarm Role

Task: Reconfigure Docker

  • Copy the configuration file docker.cfg to /etc/default/docker (only if NOT the main server)
  • Restart the docker service if the configuration file has changed

Tips:

Swarm Role

Solution: Reconfigure Docker

# hosts/prod
[swarm]
10.100.192.200 main_server=true
10.100.192.20[1:2]

# roles/swarm/tasks/main.yml
- copy:
    src: docker.cfg
    dest: /etc/default/docker
  when: not main_server is defined
  register: result

- service:
    name: docker
    state: restarted
  when: result|changed

Swarm Role

Task: Deploy Swarm

Run the Docker container called swarm

  • If main server, command should be manage consul://[IP]:8500/swarm
  • If NOT main server, command should be join --advertise=[IP]:2375 consul://[IP]:8500/swarm
  • Replace [IP] with the IP of the server

Tips:

Swarm Role

Solution: Deploy Swarm


# roles/swarm/tasks/main.yml

- docker:
    name: swarm
    image: swarm
    ports: 2375:2375
    command: manage consul://{{ facter_ipaddress_eth1 }}:8500/swarm
  when: main_server is defined

- docker:
    name: swarm
    image: swarm
    command: join --advertise={{ facter_ipaddress_eth1 }}:2375 consul://{{ facter_ipaddress_eth1 }}:8500/swarm
  when: not main_server is defined
						

The Playbook

Test


ansible-playbook /vagrant/ansible/swarm.yml \
    -i /vagrant/ansible/hosts/prod

export DOCKER_HOST=tcp://10.100.192.200:2375

docker info

docker run -d --name hello-world-1 \
    ubuntu /bin/sh -c "while true; do echo hello world; sleep 5; done"

docker ps

docker logs -f hello-world-1

docker run -d --name hello-world-2 \
    ubuntu /bin/sh -c "while true; do echo hello world; sleep 5; done"

docker ps

docker logs -f hello-world-2
						

Viktor Farcic

@vfarcic

technology conversations.com