2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

39
Docker & Ansible DevOps best friends Denis Nelubin 7bits

Transcript of 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Page 1: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Docker & AnsibleDevOps best friends

Denis Nelubin7bits

Page 2: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Docker● Blue whale● Good UI over (not only) Linux containers

○ And infrastructure

● Vanguard of containerization● Container != Virtual Machine

Page 3: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Containers & Images● Pull image● Run image as container● Save changes as image● Run image as container● …● Push image

Page 4: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Image Layers● Copy-on-Write● Diffs on filesystem

Page 5: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Dockerfile● Image build automation

FROM java:7-jreMAINTAINER Denis Nelubin <[email protected] >RUN apt-get update \&& DEBIAN_FRONTEND=noninteractive apt-get install -y \ curl \ postfix \ rsyslog \&& rm -rf /var/lib/apt/lists/*EXPOSE 25RUN curl -L https://github.com/kelseyhightower/confd/releases/download/v0.11.0/confd-0.11.0-linux-amd64 -o /usr/local/bin/confd \&& chmod 755 /usr/local/bin/confdCOPY etc/ /etc/WORKDIR /opt/coolappCOPY ./docker/docker-entrypoint.sh /CMD ["/bin/bash", "-e", "/docker-entrypoint.sh"]

Page 6: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Ports & Networks● Network between containers● Exposed ports

Page 7: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Volumes● Access to host filesystem● Put something changeable

to container● Extract something persistent

from container

Page 8: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Docker Compose● Bring multiple containers together

version: '2'services: app: image: openjdk:8-jre-alpine volumes: - ./coolapp/build/libs/coolapp-0.0.1-SNAPSHOT.jar:/app.jar command: java -jar /app.jar --spring.profiles.active=docker --server.port=8080 ports: - "8088:8080" environment: DATABASE_URL: jdbc:postgresql://db:5432/postgres DATABASE_USERNAME: postgres DATABASE_PASSWORD: links: - db depends_on: - db

Page 9: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Example

Page 10: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Databasedb: image: postgres:9.5 # https://hub.docker.com/_/postgres/ environment: TZ: "US/Central" volumes: - ./postgres:/docker-entrypoint-initdb.d:ro ports: - "54320:5432"

Page 11: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Applicationapp: image: openjdk:8-jre-alpine # https://hub.docker.com/_/openjdk/

volumes: - ./app/build/libs/app-0.0.1-SNAPSHOT.jar:/app.jar command: java -jar /app.jar --server.port=9001 ports: - "9001:9001"

environment: DATABASE_URL: jdbc:postgresql://db:5432/postgres DATABASE_USERNAME: postgres DATABASE_PASSWORD: TZ: "US/Central"

links: - db depends_on: - db

Page 12: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Proxyproxy: image: nginx:stable-alpine # https://hub.docker.com/_/nginx/

environment: TZ: "US/Central" volumes: - ./frontend/static:/usr/share/nginx/html:ro - ./proxy/etc/nginx.conf:/etc/nginx/nginx.conf:ro links: - app

Page 13: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Alpine Linuxhttps://alpinelinux.org/

● Lightweight Linux distribution

Docker Images:

● Alpine-based● Debian-based● Ubuntu-based

Page 14: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Development vs Production● Standard images● Code as volumes● Data in containers (temporary)● Configuration with environment● Docker network — OK

● All (debug) ports are exposed● Non-privileged ports are exposed

● Custom images (Dockerfiles)● Code "baked" to image● Data in volumes (persistent)● Configuration with environment● Docker network? Swarm?

Kubernetes? Expose ports?

● Public ports are exposed● Privileged ports are exposed

Page 15: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

EnvironmentSystem.getenv("DATABASE_URL");

spring: datasource: main_db: type: com.zaxxer.hikari.HikariDataSource jdbc-url: ${DATABASE_URL} username: ${DATABASE_USERNAME} password: ${DATABASE_PASSWORD}

Confd

relayhost = {{ getenv "RELAY" }}

/usr/local/bin/confd -onetime -backend env

Page 16: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

ConfdTemplate

relayhost = {{ getenv "RELAY" }}

Generate configs

/usr/local/bin/confd -onetime -backend env

Page 17: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

ORLY?

Page 18: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Docker in Production: A History of Failurehttps://thehftguy.com/2016/11/01/docker-in-production-an-history-of-failure/

● Breaking changes and regressions● Kernel support (or lack thereof)

○ The AUFS driver is unstable○ The AUFS filesystem was finally dropped in kernel version 4○ OverlayFS development was abandoned within 1 year of its initial release○ Then comes Overlay2

● Docker Registry can’t clean images● Docker MUST NOT run any databases in production, EVER

Page 19: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Ansible● Strange A● Good remote execution tool

○ Requires only SSH and Python 2

● Has tons of modules○ Try to avoid to write a custom module (v<2)

● Pretty configurable○ YAML

● Remote Execution != Configuration Management

Page 20: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Inventory● Hosts● Groups● Host Variables

[coolapp_servers]192.168.238.42 dns_name=cool.example.com

Page 21: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Playbook● What to do with the specified hosts● Apply roles!

- name: Init My Cool App hosts: coolapp_servers remote_user: root roles: - common - postgres - coolapp-postgres - java - nginx - coolapp-nginx

Page 22: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Roles● Tasks● Role Variables● Files● Templates● Handlers

● Can be taken from Ansible Galaxy○ https://galaxy.ansible.com/

Page 23: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Tasks● One action● Parameters● Verification before apply

○ Idempotence

● Standard/Built-in/Out-of-the-box

Page 24: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Handlers● Conditional actions● Applied after all tasks executed● Use them to restart a service when the config was changed

Page 25: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Ansible

Page 26: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Variables● Host Variables● Group Variables● Playbook Variables● Role Variables● Role Defaults● ...

Page 27: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Database# https://www.postgresql.org/download/linux/debian/- name: install apt key apt_key: url=https://www.postgresql.org/media/keys/ACCC4CF8.asc state=present- name: add apt repository apt_repository: repo='deb http://apt.postgresql.org/pub/repos/apt/

jessie-pgdg main' state=present filename='pgdg'

- name: install postgres apt: name='postgresql-{{ postgres_version }}'- name: install postgres contrib apt: name='postgresql-contrib-{{ postgres_version }}'- name: start postgres service: name=postgresql state=started

Page 28: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Database for app- name: create postgres user postgresql_user: name='{{ coolapp_db_user }}' password='{{ coolapp_db_password }}' become: true become_user: postgres- name: create postgres database postgresql_db: name='{{ coolapp_db_name }}' owner='{{ coolapp_db_user }}' become: true become_user: postgres- name: add postgres ltree extension postgresql_ext: name=ltree db='{{ coolapp_db_name }}' become: true become_user: postgres

Page 29: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Java- name: add backports repository apt_repository: repo: 'deb {{ java_debian_mirror }} jessie-backports main' state: present filename: 'jessie-backports'- name: install java apt: name: - '{{ java_package }}' - 'ca-certificates-java' default_release: 'jessie-backports'

Page 30: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Application- name: add user user: name='{{ coolapp_user }}' system=yes- name: create base dir file: path='{{ coolapp_basedir }}' owner='{{ coolapp_user }}' state=directory- name: copy jar file copy: src='{{ item }}' dest='{{ coolapp_basedir }}/app.jar' owner='{{ collapp_user }}' with_fileglob: - ../../../coolapp/build/libs/coolapp-*.jar notify: restart service

- name: create service config template: src=service dest='/etc/systemd/system/{{ coolapp_service_name }}.service' notify: reload systemd- name: enable service service: name='{{ coolapp_service_name }}' enabled=yes- name: start service service: name='{{ coolapp_service_name }}' state=started

Page 31: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Systemd Unit[Unit]Description={{ coolapp_service_description }}[Service]Type=simpleWorkingDirectory={{ coolapp_basedir }}ExecStart={{ collapp_java }} -jar app.jar --server.port={{ coolapp_port }}User={{ coolapp_user }}Environment=DATABASE_URL=jdbc:postgresql://{{ coolapp_db_host }}:5432/{{ coolapp_db_name }}

Environment=DATABASE_USERNAME={{ coolapp_db_user }}Environment=DATABASE_PASSWORD={{ coolapp_db_password }}[Install]WantedBy=multi-user.target

Page 32: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Nginx- name: add backports repository apt_repository: repo='deb {{ nginx_debian_mirror }} jessie-backports main' state=present filename='jessie-backports'

when: ansible_os_family == 'Debian'- name: install nginx apt: name=nginx default_release=jessie-backports state=latest when: ansible_os_family == 'Debian'- name: install nginx yum: name=nginx state=latest when: ansible_os_family == 'RedHat'- name: enable nginx service: name=nginx enabled=yes- name: start nginx service: name=nginx state=started

Page 33: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Nginx for app- name: generate DH params command: openssl dhparam -out /etc/nginx/dhparams.pem 2048 args: creates: /etc/nginx/dhparams.pem- name: copy nginx configuration template: src=config dest=/etc/nginx/sites-available/{{ coolapp_site_config }} notify: restart nginx- name: enable nginx configuration file: src=/etc/nginx/sites-available/{{ coolapp_site_config }} dest=/etc/nginx/sites-enabled/{{ coolapp_site_config }} state=link

notify: restart nginx

- name: validate nginx configuration command: /usr/sbin/nginx -t changed_when: false

Page 34: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Let's Encrypt# https://github.com/thefinn93/ansible-letsencrypt- role: letsencrypt letsencrypt_webroot_path: /var/www/html letsencrypt_email: [email protected] letsencrypt_cert_domains: - '{{ dns_name }}' letsencrypt_renewal_command_args: '--renew-hook "systemctl restart nginx"'

Page 35: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Docker → Ansible● Docker Service → Ansible Roles

○ Role for base image■ Take care on versions

○ Role for this project modifications

● Configuration by Environment○ Systemd Units

● Template config files● Take care on network

○ Open ports in firewall○ Define addresses of depending services

Page 36: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Ansible Notes● Variables hell● Don't use nested variables coolapp.basedir

○ Hard to override

● Roles are fragile○ Be ready to fix them on next deploy○ Ansible Galaxy is mostly useless

● Can you trust 3rd party roles?○ Read them carefully○ Do it yourself

● Never change anything on servers manually○ Modify roles and apply them

● Ansible Roles and Playbooks — the best deployment documentation

Page 37: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Docker vs Ansible● Run everything

on developer's machine● Official images from Hub● Environment variables

(via Docker Compose)● Config file templates

(via Confd)● docker-compose.yml, Dockerfile

● Run everything on production

● Official packages from repos● Environment variables

(via Systemd Units)● Config file templates

(via built-in Ansible templates)● Roles and everything

Anyway you may need Ansible to install Docker/Swarm/Kubernetes ;)

Page 38: 2017-03-11 02 Денис Нелюбин. Docker & Ansible - лучшие друзья DevOps

Girls vs DevOps