O documento descreve como usar Ansible para automatizar a implantação de um ambiente WordPress simples usando Docker e Rancher. Ele explica como criar um playbook Ansible para instalar o Docker, configurar um servidor Rancher, registrar hosts e implantar containers MySQL e WordPress. O playbook usa várias roles para dividir as tarefas e variáveis de grupo para parametrizar a implantação.
1. Desde o ano passado eu tenho usado o Rancher com Ansible, e descobri que usar os dois
juntos pode ser incrivelmente útil. Se você não estiver familiariza-do com o Ansible, é uma
poderosa ferramenta de gerenciamento de configura-ção que pode ser usada para gerenciar
servidores remotamente sem um dae-mon ou agente rodando no host. Em vez disso, ele
usa SSH para se conectar com hosts, E aplica tarefas diretamente nas máquinas. Devido a
isso, se você tiver acesso SSH ao host, (e Python) em execução no host, Você poderá usar
o Ansible para gerenciar hosts remotamente. Você pode encontrar detalhes
na documentação do Ansible no site da empresa.
Neste post, vou usar o Ansible com Docker para automatizar a criação de um ambiente
wordpress simples em uma implantação do Rancher.
Especificamente, incluirei as seguintes etapas:
● Instalando Docker em meus hosts usando Ansible.
● Configurando uma nova instalação do Rancher usando Ansible.
● Registrando hosts com o Rancher usando Ansible.
● Implantando os containers de aplicativos nos Hosts.
Preparando o Playbook
Ansible Usa “playbooks’ Que são a linguagem de configuração e de orquestração do
Ansible, Estes playbooks são expressos em formato YAML, E descreve um conjunto de
tarefas que serão executadas em hosts remotos, veja em introdução a playbook para obter
mais informações sobre como usar os playbooks Ansible
No nosso caso o playbook Será executado em 3 servidores, um servidor para a plataforma
Rancher, O segundo servidor para o banco de dados MySQL e o último para o aplicativo
WordPress.
Os endereços e informações sobre os servidores anteriores estão listados no seguinte
arquivo de inventário Ansible, O inventário é o arquivo que contém nomes, endereços e
portas dos hosts remotos onde o playbook Ansible vai executar:
2. Arquivo de inventário:
[Rancher]
rancher ansible_ssh_port=22 ansible_ssh_host=x.x.x.x
[nodes:children]
application
database
[application]
node1 ansible_ssh_port=22 ansible_ssh_host=y.y.y.y
[database]
node2 ansible_ssh_port=22 ansible_ssh_host=z.z.z.z
Note que eu usei grupo no inventário para melhor descrever a lista de máquinas utilizadas
nesta implantação, O playbook em si será composto de cinco plays, O que resultará na
implantação do aplicativo WordPress:
● Play #1 Instalando e configurando o Docker
O primeiro play irá instalar e configurar o Docker em todas as máquinas, ele usa a role
"docker", que veremos na próxima seção.
● Play #2 Configurando o servidor Rancher
Este play irá instalar o servidor Rancher e certificando de que ele está funcionando, este
play só será executada num servidor que é considerado o servidor Rancher.
● Play #3 Registrando hosts do Rancher
Este play será executado em duas máquinas para registar cada um deles com o servidor
Rancher que deve estar funcionando partir do último play.
● Play #4 Implementar o container MySQL
Este é um play simples para implantar o contêiner MySQL no servidor de banco de dados.
● play #5 Implantar aplicativo WordPress
Este play irá instalar o aplicativo WordPress na segunda máquina e vinculá-lo ao contêiner
MySQL.
3. rancher.yml (the playbook file)
---
# play 1
- name: Instalando e configurando o Docker
hosts: all
sudo: yes
roles:
- { role: docker, tags: ["docker"] }
# play 2
- name: Configurando o Rancher Server
hosts: "rancher"
sudo: yes
roles:
- { role: rancher, tags: ["rancher"] }
# play 3
- name: Register Rancher Hosts
hosts: "nodes"
sudo: yes
roles:
- { role: rancher_reg, tags: ["rancher_reg"] }
# play 4
- name: Implementar o Container MySQL
hosts: 'database'
sudo: yes
roles:
- { role: mysql_docker, tags: ["mysql_docker"] }
# play 5
- name: Implantar o aplicativo WordPress
hosts: "application"
sudo: yes
roles:
- {role: wordpress_docker, tags: ["wordpress_docker"]}
4. Role(Função) Docker
Esta role irá instalar a versão mais recente do Docker em todos os servidores,a role assume
que você usará o Ubuntu 14.04, Porque algumas outras distribuições do Ubuntu requerem
algumas dependências para rodar Docker que não vamos discutir aqui, Veja a
documentação do Docker Para mais informações sobre Instalar Docker em diferentes
plataformas.
- name: Fail if OS distro is not Ubuntu 14.04
fail:
msg="The role is designed only for Ubuntu 14.04"
when: "{{ ansible_distribution_version | version_compare('14.04', '!=') }}"
O módulo Docker com Ansible requer biblioteca docker-py Para ser instalado no servidor
remoto, então primeiro usamos python-pip para instalar a biblioteca docker-py em todos os
servidores antes de instalar o Docker:
- name: Install dependencies
apt:
name={{ item }}
update_cache=yes
with_items:
- python-dev
- python-setuptools
- name: Install pip
easy_install:
name=pip
- name: Install docker-py
pip:
name=docker-py
state=present
version=1.1.0
As tarefas a seguir irão importar o Docker apt repo e instalar Docker:
- name: Add docker apt repo
apt_repository:
repo='deb https://apt.dockerproject.org/repo ubuntu-{{ ansible_distribution_release
}} main'
state=present
- name: Import the Docker repository key
apt_key:
url=https://apt.dockerproject.org/gpg
state=present
id=2C52609D
- name: Install Docker package
apt:
name=docker-engine
update_cache=yes
5. Finalmente, as três tarefas seguintes irá adicionar um grupo de sistemas para o Docker e
adicionar qualquer usuário definido na variável "Docker_users" a este grupo e ele copiará o
template para a configuração do Docker e reiniciará o Docker.
- name: Criar um grupo do Docker
group:
name=docker
state=present
- name: Adicionar usuário (s) ao grupo do Docker
user:
name={{ item }}
group=docker
state=present
with_items: docker_users
when: docker_users is defined
- name: Configurar o Docker
template:
src=default_docker.j2
dest=/etc/default/docker
mode=0644
owner=root
group=root
notify: restart docker
O template "default_docker.j2" verificará a variável "docker_opts" que não está definida por
padrão e se for definida, adicionará as opções definidas na variável ao arquivo:
# Docker Upstart and SysVinit configuration file
# Use DOCKER_OPTS para modificar as opções de inicialização do daemon.
{% if docker_opts is defined %}
DOCKER_OPTS="{{ docker_opts | join(' ')}}"
{% endif %}
6. Role Rancher
A role do Rancher é realmente simples, seu objetivo é baixar a imagem Docker do Rancher
do Docker hub,e aguardar o servidor Rancher iniciar e ouvir as conexões de entrada:
---
- name: Baixar e executar o contêiner Rancher/server
docker:
name: "{{ rancher_name }}"
image: rancher/server
restart_policy: always
ports:
- "{{ rancher_port }}:8080"
- name: Aguarde o início do servidor Rancher
action: command docker logs {{ rancher_name }}
register: rancher_logs
until: rancher_logs.stdout.find("Listening on") != -1
retries: 30
delay: 10
- name: Imprimir a URL do Rancher
debug: msg="You can connect to rancher server http://{{ ansible_default_ipv4.address
}}:{{ rancher_port }}"
7. Role de registro de agent do Rancher
A role do rancher_reg Irá baixar e executar a imagem Docker rancher_agent, Primeiro ele
usará a API do Rancher para retornar o token de registro para executar cada agente com a
URL de registro correto, este token é necessário para registrar hosts no ambiente do
Rancher:
---
- name: Install httplib2
apt:
name=python-httplib2
update_cache=yes
- name: Get the default project id
action: uri
method=GET
status_code=200
url="http://{{ rancher_server }}:{{ rancher_port }}/v1/projects" return_content=yes
register: project_id
- name: Return the registration token URL of Rancher server
action: uri
method=POST
status_code=201
url="http://{{ rancher_server }}:{{ rancher_port
}}/v1/registrationtokens?projectId={{ project_id.json['data'][0]['id'] }}"
return_content=yes
register: rancher_token_url
- name: Return the registration URL of Rancher server
action: uri
method=GET
url={{ rancher_token_url.json['links']['self'] }} return_content=yes
register: rancher_token
Em seguida, ele irá certificar-se de que nenhum outro agente está sendo executado no
servidor e ele executará o Agente Rancher:
- name: Verifique se o rancher-agente está em execução
command: docker ps -a
register: containers
- name: Register the Host machine with the Rancher server
docker:
image: rancher/agent:v{{ rancher_agent_version }}
privileged: yes
detach: True
volumes: /var/run/docker.sock:/var/run/docker.sock
command: "{{ rancher_token.json['registrationUrl'] }}"
state: started
when: "{{ 'rancher-agent' not in containers.stdout }}"
8. Roles MySQL e WordPress
As duas roles estão usando o módulo Ansible Docker para executar imagens Docker no
servidor, você notará que cada contêiner Docker começará com a variavel de Ambiente
RANCHER_NETWORK=true , O que fará com que o contêiner Docker use a rede
gerenciada do Rancher para que os contêineres possam se comunicar em diferentes hosts
na mesma rede privada.
Vou usar as imagens oficiais do MySQL e WordPress , A imagem do MySQL requer a
variavel de ambiente MYSQL_ROOT_PASSWORD para iniciar, Você também pode iniciá-lo
com banco de dados e usuário padrão que receberão permissões de superusuário neste
banco de dados.
- name: Create a mysql docker container
docker:
name: mysql
image: mysql:{{ mysql_version }}
detach: True
env: RANCHER_NETWORK=true,
MYSQL_ROOT_PASSWORD={{ mysql_root_password }}
- name: Aguarde alguns minutos para que os IPs sejam definidos no contêiner
wait_for: timeout=120
# As tarefas a seguir ajudam com a conexão dos contêiners em diferentes hosts no Rancher
- name: Fetch the MySQL Container IP
shell: docker exec mysql ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1 | sed
-n 2p
register: mysql_sec_ip
- name: print the mysql rancher's ip
debug: msg={{ mysql_sec_ip.stdout }}
Observe que a função aguardará por 2 minutos até se certificar de que o contêiner está
configurado com os IPs corretos e em seguida, ele buscará o ip secundário do container que
é o ip usado na rede do Rancher e salva-la na variavel mysql_sec_ip que irá continuar
ativa através do playbook, a imagem do WordPress por outro lado vai começar com a
variável WORDPRESS_DB_HOST definido para o ip do contêiner mysql que acabamos de
iniciar.
- name: Criar um container docker wordpress
docker:
name: wordpress
image: wordpress:{{ wordpress_version }}
detach: True
ports:
- 80:80
env: RANCHER_NETWORK=true,
WORDPRESS_DB_HOST={{ mysql_host }}:3306,
WORDPRESS_DB_PASSWORD={{ mysql_root_password }},
WORDPRESS_AUTH_KEY={{ wordpress_auth_key }},
WORDPRESS_SECURE_AUTH_KEY={{ wordpress_secure_auth_key }},
WORDPRESS_LOGGED_IN_KEY={{ wordpress_logged_in_key }},
WORDPRESS_NONCE_KEY={{ wordpress_nonce_key }},
WORDPRESS_AUTH_SALT={{ wordpress_auth_salt }},
WORDPRESS_SECURE_AUTH_SALT={{ wordpress_secure_auth_salt }},
WORDPRESS_NONCE_SALT={{ wordpress_nonce_salt }},
WORDPRESS_LOGGED_IN_SALT={{ wordpress_loggedin_salt }}
9. Gerenciando Variáveis
Ansible define variáveis nas diferentes camadas, algumas das camadas sobrepõem as
outras, então para o nosso caso eu adicionei um conjunto padrão de variáveis para cada role
a ser usada em diferentes playbooks mais tarde e adicionei as variáveis usadas no diretório
group_vars para substituí-las.
├── group_vars
│ ├── all.yml
│ ├── nodes.yml
│ └── Rancher.yml
├── hosts
├── rancher.yml
├── README.md
└── roles
├── docker
├── mysql_docker
├── rancher
├── rancher_reg
└── wordpress_docker
As variáveis nodes.yml serão aplicadas no grupo de nós definido no arquivo de inventário
que contém o banco de dados e os servidores de aplicativos, este arquivo contém
informações usadas pelos contêiners mysql e wordpress:
---
rancher_server: "{{ hostvars['rancher']['ansible_ssh_host'] }}"
# MySQL variables
mysql_root_password: "{{ lookup('password', mysql_passwd_tmpfile + ' length=20
chars=ascii_letters,digits') }}"
mysql_passwd_tmpfile: /tmp/mysqlpasswd.file
mysql_host: "{{ hostvars.node2.mysql_sec_ip.stdout }}"
mysql_port: 3306
mysql_version: 5.5
# WordPress variables
wordpress_version: latest
Você pode notar que eu usei senha de pesquisa para gerar uma senha aleatória para a
senha de root do mysql, uma boa alternativa para este método seria usar vault para
criptografar dados confidenciais como senhas ou chaves.
10. Executando o Playbook
Para executar o playbook, eu inicie as 3 máquinas com o Ubuntu 14.04 instalado e
adicionando seus IPs ao inventário que nós vimos mais cedo, e usando então o seguinte
comando para iniciar o playbook:
$ ansible-playbook -u root -i hosts rancher.yml
Após o playbook terminar seu trabalho, você pode acessar o servidor Rancher e você verá o
seguinte:
E ao acessar o IP do node1 na porta 80, você acessará o WordPress:
Conclusão
11. Ansible é uma ferramenta de automação muito poderosa e simples que pode ser usada para
gerenciar e configurar uma frota de servidores, usando o Ansible com Rancher pode ser um
método muito eficiente para iniciar seu ambiente e gerenciar seus containers Docker. Este
mês, estamos hospedando um meetup on-line no qual estaremos demonstrando como
executar microservices em containers Docker e upgrades de aplicativos de orquestração
usando o Rancher. Por favor junte-se a nós para este meetup para saber mais.