Date post: | 18-Jul-2015 |
Category: |
Technology |
Upload: | stephane-manciot |
View: | 529 times |
Download: | 4 times |
Ansible - Introduction
Main features
○ Automating remote system provisioning and applications deployment
○ With no agents to install on remote systems
○ Using existing SSHd on remote system
○ Native OpenSSH for remote communication on control machine
○ Parallel by default
○ Automation language that approaches plain english
Installation - requirements
○ Control machine requirements
● Python 2.6
● Any OS except Windows
○ Managed node requirements
● Python 2.4
Installation - control machine - source
○ From source ● $ git clone git://github.com/ansible/ansible.git
● $ cd ./ansible
● $ source ./hacking/env-setup
○ Additional python modules ● sudo easy_install pip
● sudo pip install paramiko PyYAML jinja2 httplib2
Installation - control machine - Yum
○ Latest release Via Yum ● $ sudo yum install ansible
● make rpm from source ○ $ git clone git://github.com/ansible/ansible.git
○ $ cd ./ansible
○ make rpm
○ sudo rpm -Uvh ~/rpmbuild/ansible-*.noarch.rpm
Installation - control machine - Apt
○ Latest release Via Apt ● $ sudo apt-get install software-properties-common
● $ sudo apt-add-repository ppa:ansible/ansible
● $ sudo apt-get update
● $ sudo apt-get install ansible
Installation - control machine - Pip
○ Latest release Via pip ● $ sudo easy_install pip
● $ sudo pip install ansible
Installation - control machine - Homebrew
○ Latest release Via Homebrew ● $ brew update
● $ brew install ansible
Inventory file
○ Define how ansible will interact with remote hosts
○ Define logical groups of managed nodes
○ Default location : /etc/ansible/hosts
○ INI format
Inventory file - communication variables
○ ansible_connection : local, ssh or paramiko
○ ansible_ssh_host : the name of the host to connect to
○ ansible_ssh_port : the ssh port number if not 22
○ ansible_ssh_user : the ssh user name to use
○ ansible_ssh_pass : the ssh password to use (insecure)
○ ansible_ssh_private_key_file : private key file used by ssh
Inventory file - hosts and groups
localhost ansible_connection=local
[webservers]
web[1:5].example.com ansible_connection=ssh ansible_ssh_user=webadmin
[dbservers]
db[1:2].example.com ansible_connection=ssh ansible_ssh_user=dbadmin
Inventory file - group variables
[webservers]
web[1:5].example.com ansible_connection=ssh ansible_ssh_user=webadmin
[webservers:vars]
http_port=80
Inventory file - groups of groups
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
Inventory file - splitting out specific data○ Define specific data using variables within YAML
files relative to the inventory file
[atlanta]
host1
host2
○ /etc/ansible/group_vars/atlanta, /etc/ansible/host_vars/host1
---
ntp_server: acme.example.org
database_server: storage.example.org
○ /etc/ansible/group_vars/atlanta/db_settings
Patterns
○ Decide which hosts to manage
● all hosts in the inventory (all or *)
● a specific host name or group name (host1, webservers)
● wildcard configuration (192.168.1.*)
● OR configuration (host1:host2, webservers:dbservers)
● NOT configuration (webservers:dbservers:!production)
● AND configuration (webservers:dbservers:&staging)
● REGEX configuration (~(web|db).*\.example\.com)
● exclude hosts using limit flag (ansible-playbook site.yml --limit datacenter2)
Vault
○ Allows keeping encrypted data in source control
○ Created encrypted files
$ ansible-vault create foo.yml
○ Editing encrypted files
$ ansible-vault edit foo.yml
○ Encrypting unencrypted files
$ ansible-vault encrypt foo.yml
○ Decrypting encrypted files
$ ansible-vault decrypt foo.yml
○ Running ad-hoc or playbook with vault
$ ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt
Vagrant integration
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network :private_network, ip: “192.168.33.10"
config.vm.provision :ansible do |ansible|
ansible.inventory_path = "vagrant-inventory.ini"
ansible.playbook = "dockers.yml"
ansible.extra_vars = { user: "vagrant" }
ansible.sudo = true
ansible.limit = 'all'
end
Ad-Hoc commands○ $ ansible {pattern} -m {module} -a “{options}” {flags}
● pattern : which hosts
● module : which ansible module (command by default)
● options : which module options
● flags : command flags
○ -u {username}: to run the command as a different user (user account by default)
○ -f {n}: to run the command in n parallel forks (5 by default)
○ --sudo: to run the command through sudo
○ -K: to interactively prompt you for the sudo password to use
○ -U {username}: to sudo to a user other than root
○ -i {file}: inventory file to use
○ --ask-vault-pass: to specify the vault-password interactively
○ --vault-password-file {file}: to specify the latter within a file
Ad-Hoc commands - samples
○ File transfer $ ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts"
○ Deploying from source control $ ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"
○ Managing services $ ansible webservers -m service -a "name=httpd state=started"
○ Gathering facts $ ansible all -m setup
Playbook
○ Expressed in YAML language
○ Composed of one or more “plays” in a list
○ Allowing multi-machine deployments orchestration
Playbook - play--- - hosts: webservers vars: http_port: 80 max_clients: 200 remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/srv/httpd.j2 dest=/etc/httpd.conf notify: - restart apache
- name: ensure apache is running service: name=httpd state=started handlers: - name: restart apache service: name=httpd state=restarted
Playbook - hosts and users
○ hosts : one or more groups or host patterns
○ remote_user : the name of the remote user account (per play or task)
○ sudo : run tasks using sudo (per play or task)
○ sudo_user : sudo to a different user than root
Playbook - tasks
○ Are executed in order against all machines matched by the host pattern
○ May be Included from other files tasks: - include: tasks/foo.yml
○ Hosts with failed tasks are taken out for the entire playbook
○ Each task executes a module with specific options
○ Modules are idempotent in order to bring the system to the desired state
tasks: - name: {task name} {module}: {options}
Playbook - handlers
○ Notifications may be triggered at the end of each block of tasks whenever a change has been made on the remote system
○ Handlers are referenced by name tasks:
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart apache
…
handlers:
- name: restart apache
service: name=apache state=restarted
Playbook - roles○ Based on a known file structure site.yml
webservers.yml
roles/
webservers/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
…
---
- hosts: webservers
roles:
- webservers
If roles/x/tasks/main.yml exists, tasks listed therein will be added to the playIf roles/x/handlers/main.yml exists, handlers listed therein will be added to the playIf roles/x/vars/main.yml exists, variables listed therein will be added to the playIf roles/x/meta/main.yml exists, any role dependencies listed therein will be added to the list of roles (1.3 and later)Any copy tasks can reference files in roles/x/files/ without having to path them relatively or absolutelyAny script tasks can reference scripts in roles/x/files/ without having to path them relatively or absolutelyAny template tasks can reference files in roles/x/templates/ without having to path them relatively or absolutelyAny include tasks can reference files in roles/x/tasks/ without having to path them relatively or absolutely
Playbook - roles○ May be applied conditionally ---
- hosts: webservers
roles:
- { role: some_role, when: "ansible_os_family == 'RedHat'" }
○ May be applied before or after other tasks ---
- hosts: webservers
pre_tasks:
- shell: echo 'hello'
roles:
- { role: some_role }
tasks:
- shell: echo 'still busy'
post_tasks:
- shell: echo 'goodbye'
Playbook - variables
○ Define directly inline - hosts: webservers
vars:
http_port: 80
○ Default role variables defined in {role}/defaults/main.yml file
○ Included variables --- - hosts: all remote_user: root vars: favcolor: blue vars_files: - /vars/external_vars.yml
Playbook - variables - Jinja2○ Within conditions
● failed, changed, success, skipped - shell: /usr/bin/foo
register: result
ignore_errors: True
- debug: msg="it failed"
when: result|failed
● mandatory {{ variable | mandatory }}
● version_compare
{{ ansible_distribution_version | version_compare('12.04', '>=') }}
● …
○ Within templates My amp goes to {{ max_amp_value }}
Playbook - variables - Facts
○ Information discovered from remote system
○ Frequently used in conditionals ---
- include: "Ubuntu.yml"
when: ansible_distribution == 'Ubuntu'
○ Local facts
● {file}.fact within /etc/ansible/facts.d [general]
foo=1
bar=2
● can be accessed in a template/playbook as {{ ansible_local.file.general.foo }}
Playbook - variables - Precedence
○ -e variables ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"
○ “most everything else”
○ variables defined in inventory
○ variables defined in facts
○ role defaults
Playbook - conditions
○ Execute task conditionally tasks:
- shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
when: foo is defined
○ Include tasks conditionally - include: tasks/sometasks.yml
when: "'reticulating splines' in output"
○ Execute role conditionally - hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family == 'Debian' }
Questions ?