Share
Embed
Ansible
Lightning talk on Ansible, given at the Amsterdam Python meetup group on Oct 2nd, 2013
Nick Groenen
October 02, 2013
Transcript
62 slides
-
Ansible Radically simple* IT orchestration * If you believe the
ads http://bit.ly/1hiL9Xl -
24 years old Loves spicy food Developer @ TravelBird Python
user since 2009 Linux user since around 2003 Big fan of Open Source Nick Groenen Twitter: @NickGroenen Web: https://zoni.nl Email: [email protected] -
Python WSGI app on 2 application servers (web1 & web2)
behind 1 loadbalancer (lb1) Explore through example -
Vagrantfile Vagrant.configure("2") do |config| config.vm.define :lb1 do |lb1| lb1.vm.box =
"raring-server-cloudimg-amd64-vagrant" lb1.vm.network :private_network, ip: "192.168.99.10" end config.vm.define :web1 do |web1| web1.vm.box = "raring-server-cloudimg-amd64-vagrant" web1.vm.network :private_network, ip: "192.168.99.11" end config.vm.define :web2 do |web2| web2.vm.box = "raring-server-cloudimg-amd64-vagrant" web2.vm.network :private_network, ip: "192.168.99.12" end end -
Vagrantfile Vagrant.configure("2") do |config| config.vm.define :lb1 do |lb1| lb1.vm.box =
"raring-server-cloudimg-amd64-vagrant" lb1.vm.network :private_network, ip: "192.168.99.10" end config.vm.define :web1 do |web1| web1.vm.box = "raring-server-cloudimg-amd64-vagrant" web1.vm.network :private_network, ip: "192.168.99.11" end config.vm.define :web2 do |web2| web2.vm.box = "raring-server-cloudimg-amd64-vagrant" web2.vm.network :private_network, ip: "192.168.99.12" end end -
$ vagrant up Bringing machine 'lb1' up with 'virtualbox' provider...
Bringing machine 'web1' up with 'virtualbox' provider… Bringing machine 'web2' up with 'virtualbox' provider... -
Ansible leverages SSH. No daemons to setup, no (extra) permissions
to manage, we're ready to roll! pip install ansible or aptitude install ansible or yum install ansible or emerge ansible -
/etc/ansible/hosts [loadbalancers] lb1 ansible_ssh_host=192.168.99.10 [webservers] web1 ansible_ssh_host=192.168.99.11 web2 ansible_ssh_host=192.168.99.12 ansible_ssh_host
is only necessary because Vagrant VM's aren't in DNS -
playbook.yml - hosts: loadbalancers user: vagrant sudo: true tasks: -
name: Install nginx apt: name=nginx state=present - name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 -
playbook.yml - hosts: loadbalancers user: vagrant sudo: true tasks: -
name: Install nginx apt: name=nginx state=present - name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 -
playbook.yml - hosts: loadbalancers user: vagrant sudo: true tasks: -
name: Install nginx apt: name=nginx state=present - name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 -
playbook.yml - hosts: loadbalancers user: vagrant sudo: true tasks: -
name: Install nginx apt: name=nginx state=present - name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 -
playbook.yml # Some stuff omitted to save space tasks: -
name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 notify: - restart nginx handlers: - name: restart nginx service: name=nginx state=restarted -
playbook.yml # Some stuff omitted to save space tasks: -
name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 notify: - restart nginx handlers: - name: restart nginx service: name=nginx state=restarted -
playbook.yml # Some stuff omitted to save space tasks: -
name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 validate="nginx -t -c %s" notify: - restart nginx handlers: - name: restart nginx service: name=nginx state=restarted -
playbook.yml # Some stuff omitted to save space tasks: -
name: Install nginx config template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=644 validate="nginx -t -c %s" notify: - restart nginx handlers: - name: restart nginx service: name=nginx state=restarted -
failed: [lb1] => {"failed": true} msg: failed to validate: rc:1
error:nginx: [emerg] directive "pid" is not terminated by ";" in /home/vagrant/. ansible/tmp/ansible-1380702362.41-73682544006063/source:5 nginx: configuration file /home/vagrant/.ansible/tmp/ansible- 1380702362.41-73682544006063/source test failed FATAL: all hosts have already failed -- aborting If you screwed up -
nginx.conf.j2 {{ ansible_managed }} user www-data; worker_processes {{ ansible_processor_cores }};
pid /run/nginx.pid; events { worker_connections {{ nginx_worker_connections }}; } -
nginx.conf.j2 {{ ansible_managed }} user www-data; worker_processes {{ ansible_processor_cores }};
pid /run/nginx.pid; events { worker_connections {{ nginx_worker_connections }}; } -
nginx.conf.j2 {{ ansible_managed }} user www-data; worker_processes {{ ansible_processor_cores }};
pid /run/nginx.pid; events { worker_connections {{ nginx_worker_connections }}; } -
nginx.conf.j2 {{ ansible_managed }} user www-data; worker_processes {{ ansible_processor_cores }};
pid /run/nginx.pid; events { worker_connections {{ nginx_worker_connections }}; } -
Which kernels am I running? $ ansible --module-name shell --args
"uname -srv" --user vagrant all -
lb1 | success | rc=0 >> Linux 3.8.0-30-generic #44-Ubuntu SMP
Thu Aug 22 20:52:24 UTC 2013 web1 | success | rc=0 >> Linux 3.8.0-30-generic #44-Ubuntu SMP Thu Aug 22 20:52:24 UTC 2013 web2 | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue -
nginx.conf.j2 (continued) upstream exampleapp { {% for host in groups['webservers']
%} server {{ hostvars[host]['ansible_ssh_host'] }}:9001; {% endfor %} } server { listen 80; server_name example.vagrant; location / { uwsgi_pass exampleapp; } } -
nginx.conf.j2 (continued) upstream exampleapp { {% for host in groups['webservers']
%} server {{ hostvars[host]['ansible_ssh_host'] }}:9001; {% endfor %} } server { listen 80; server_name example.vagrant; location / { uwsgi_pass exampleapp; } } -
playbook.yml - hosts: webservers user: vagrant sudo: true tasks: -
name: Install dependencies apt: name={{ item }} state=present with_items: - python-virtualenv - python-pip - git -
playbook.yml - hosts: webservers user: vagrant sudo: true tasks: -
name: Install dependencies apt: name={{ item }} state=present with_items: - python-virtualenv - python-pip - git -
playbook.yml - hosts: webservers user: vagrant sudo: true tasks: -
name: Install dependencies apt: name={{ item }} state=present with_items: - python-virtualenv - python-pip - git -
playbook.yml - hosts: webservers user: vagrant sudo: true tasks: -
name: Install dependencies apt: name={{ item }} state=present with_items: - python-virtualenv - python-pip - git -
- name: Checkout application code git: repo=https://gist.github.com/6164386.git dest=/srv/exampleapp version=HEAD update=yes
notify: - reload uwsgi instance - name: Install requirements pip: state=present virtualenv=/srv/exampleapp requirements=/srv/exampleapp/requirements.txt playbook.yml -
- name: Checkout application code git: repo=https://gist.github.com/6164386.git dest=/srv/exampleapp version=HEAD update=yes
notify: - reload uwsgi instance - name: Install requirements pip: state=present virtualenv=/srv/exampleapp requirements=/srv/exampleapp/requirements.txt playbook.yml -
ansible-playbook playbook.yml lb1 : ok=3 changed=0 unreachable=0 failed=0 web1 :
ok=4 changed=3 unreachable=0 failed=0 web2 : ok=4 changed=3 unreachable=0 failed=0 -
Python WSGI app on 2 application servers (web1 & web2)
behind 1 loadbalancer (lb1) Deployed! -
Delegating actions - hosts: webservers serial: 2 tasks: - name:
Remove from loadbalancer shell: remove_from_lb_command delegate_to: lb1 - do_stuff_here - name: Add to loadbalancer shell: add_to_lb_command delegate_to: lb1 -
Tags tasks: - apt: name={{ item }} state=installed with_items: -
nginx - memcached tags: - packages - template: src=templates/src.j2 dest=/etc/foo.conf tags: - configuration -
Tags Run with: $ ansible-playbook example.yml --tags "packages" $ ansible-playbook
example.yml --tags "configuration" $ ansible-playbook example.yml \ --tags "configuration,packages" -
Prompting for input vars_prompt: - name: "some_password" prompt: "Enter password"
private: yes - name: "release_version" prompt: "Product release version" private: no -
Looking up data - hosts: localhost tasks: - name: Print
result of DNS lookup shell: echo {{ lookup('dnstxt', 'example.com') }} - name: Print file contents debug: msg="Motd content: {{ lookup('file', '/etc/motd') }}" -
• External inventory scripts • Python API • Custom modules
• Custom Jinja2 filters • Moar! And more... -
Closing words • Ignored all best practices for demonstration (use
roles!) • Made many assumptions http://www.ansibleworks.com/quickstart-video/ http://www.ansibleworks.com/docs