Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Ansible tips & tricks

18,089 views

Published on

Unusual ways to use and abuse Ansible

Published in: Technology

Ansible tips & tricks

  1. 1. Tips & Tricks Not your usual usage Ansible Fest NYC 2015
  2. 2. #>whoami ● currently: ansible core team member (bcoca) ● helpdesk/application support ● programmer/analyst/software engineer ● QA, systems & network administrator ● release manager, DBA, information security, ● “Tech Janitor”
  3. 3. #>apropos ansible ● Configuration management ● Release management ● Automation framework ● Orchestration system ● Distributed batch executor ____________________ / It runs a TASK * x on a HOST * x / -------------------- ^__^ (oo)_______ (__) )/ ||----w | || ||
  4. 4. #LIVE>multiply_shell ● allows you to reuse your shell magic ● must be non interactive ● plays well with traditional unix tools ● just multiply by ### hosts ● requires some work for nicer outputs ● -t == json file database per host
  5. 5. #LIVE>ansible_shell #>ansible webs -m shell -a "awk '{print $9}' /var/log/nginx/access.log|sort |uniq -c |sort -k1,1nr 2>/dev/null|column -t" web1 | success | rc=0 >> 204417 200 48108 304 8550 302 6541 301 1696 404 269 206 web2 | success | rc=0 >> 205807 200 43762 304 ...
  6. 6. #LIVE>procmail -- procmail :0 #send back http code live report * ^From.*@example.com * ^Subject:.*500 report |ansible-playbook ~/plays/report.yml --- #report.yml … - shell: "awk '{print $9}' … register: report - mail: to={{lookup(‘env’,’FROM’)}} body={{report}} … ______________ < you got mail > -------------- , , /( )` ___ / | /- _ `-/ ' (// / / / | ` O O ) / | `-^--'`< ' (_.) _ ) / `.___/` / `-----' / <----. __ / __ <----|====O)))==) ) /==== <----' `--' `.__,' | | / ______( (_ / ______ ,' ,-----' | `--{__________) /
  7. 7. #UTIL>small_scripts ● tries not to be a programming language ● but … sometimes its very useful as such ● plays can wrap existing roles/task lists ● vars_prompt/pause allow for interactivity ● -e “var=val” for completely batch ● -e @file.json: you can use json data files
  8. 8. #UTIL>/sbin/departed #!/usr/bin/ansible-playbook --- - name: Ensure only valid users hosts: all gather_facts: False sudo: True vars_files: #departed: [ alan, bcoca, isaac, mathew, willy ] - /etc/departed_users.yml tasks: - name: Delete departed user and all it’s files user: name={{item}} state=absent remove=yes with_items: “{{departed}}”
  9. 9. #UTIL>/bin/release_apps #!/usr/bin/ansible-playbook - hosts: localhost vars_prompt: - name: app_name prompt: “Which app do you want to deploy?” - name: app_version prompt: “Choose version/tag (default HEAD)” default: ‘HEAD’ tasks: - git: repo=git@myreposerver/{{app_version}} version={{app_version}} ... ... - hosts: app_servers serial: 1 tasks: - pause: "are you sure you want to stop all services?" - name: shush nagios nagios: action=silence host={{inventory_hostname}} delegate_to: {{monitor}} - name: nginx graceful stop service: name=nginx state=stopped - name: stop uwsgi service name=uwsgi state=stopped … ... ______________________ / for reusability, use includes and roles / ---------------------- __ UooU.'@@@@@@`. __/(@@@@@@@@@@) (@@@@@@@@) `YY~~~~YY' || ||
  10. 10. #QA>verify ● The same way I do things , I can check them ● Gentle learning curve for your test creator ● Checks don’t normally need root ● check_mode and diff_mode ● assert/fail, no need to read the output!
  11. 11. #QA>check_server - hosts: app_server tasks: - users: name=appuser state=present name: verify that app user is present - file: path=/to/app/dir owner=appuser mode=0700 name: check that app dir has proper permissions - service: name={{item}} state=started name: check that services are running with_items: [‘nginx’, ‘uwsgi’] - postgres_user: name=dbapp1 password=secretrole_attr_flags=NOSUPERUSER name: check app user is accessible via app server ____________________________________ / or if your playbook is idempotent, just run it again Sam! / ------------------------------------ / ( ) .( o ).
  12. 12. #QA>check_app - hosts: app_servers tasks: - stat: path=/var/run/tomcat/webapps/myapp.jar register: jar - assert: that: - jar.checksum == lookup(‘consul_kv’,‘myapp_csum’) - stat: path=/var/run/app2.pid - wait_for: port=8080 - uri: return_content=’app1 OK’
  13. 13. #AUDIT>verify --- qa? ● The same way I do, I can check ● Gentle learning curve for your auditor ● Checks don’t normally need root ● check_mode and diff_mode
  14. 14. #AUDIT>check_firewall # verify firewall after manual config - wait_for: port: “{{item}}” host: prod.example.com delegate_to: outside.host.com with_items: [‘80, ‘443’] - wait_for: port={{item}} host=prod.example.com delegate_to: outside.host.com failed_when: not left_door_open|failed register: left_door_open when: item not in [‘80’, ‘443’] with_sequence: start=1 end=1024 ______________ < or call nmap > -------------- ___ {~._.~} ( Y ) ()~*~() (_)-(_)
  15. 15. #AUDIT>check_file_changes # from vars today_file: checks/{{inventory_hostname}}/{{today}}.txt - find: paths=/etc recurse=Y size=1 age=1d registered: fchanged - assert: that: - fchanged|length == 0 - assert: that: - item.checksum == lookup(‘pipe’, ‘grep ‘ + item + ‘ /checks/latest| cut -f2’) with_items: “{{fchanged}}” - local_action: template src=checksums.j2 dest={{today_file}} - local_action: file src={{today_file}} path=/checks/latest state=link ______________________ / Just until you setup aide|osiris|tripwire / ---------------------- /_)o< | | O . O| _____/
  16. 16. #AUDIT>facts_drift ● set fact caching to use jsonfile ● make git repo or checkout in cache dir ● set incron to commit when file changes ● now git log shows facts change over time ● filter out time facts (or not) ● … so ... tower will do this for me?
  17. 17. #AUDIT>file_changes_xattr ● {{ansible_managed}} (changed or lack info) ● use xattr to keep metadata with the file ● requires user_xattr on mount ● great ETL, can keep correct file transforms ● does not affect copy/template ‘changed’
  18. 18. #HACK>expand_ansible ● roles: as shared libraries ● plugins: there are more than modules ● callbacks: send events ● notification modules: specific events ● dynamic modules: if you crave abstraction
  19. 19. #HACK>tidy # tidy_expected: [‘conf1.cfg’, conf2.cfg’] - find: paths={{tidy_path}} #/etc/myapp register: existing - file: path={{item.path}} state=absent when: item.path|basename not in tidy_expected with_items: “{{existing.files|default([ ])}}” register: removed - mail: body=“{{removed}}”
  20. 20. #HACK>ansible_events syslog_json callback plugin def __init__(self): self.logger = logging.getLogger('ansible logger') self.logger.setLevel(logging.DEBUG) self.handler = logging.handlers.SysLogHandler( address = (os.getenv('SYSLOG_SERVER','locahost'), os.getenv('SYSLOG_PORT',514)), facility=logging.handlers.SysLogHandler.LOG_USER ) self.logger.addHandler(handler) .... def runner_on_ok(self, host, res): self.logger.info('RUNNER_ON_OK ' + host + ' ' + json.dumps(res, sort_keys=True)) def runner_on_skipped(self, host, item=None): self.logger.info('RUNNER_ON_SKIPPED ' + host)
  21. 21. #HACK>ansible_events osx_say callback plugin def say(msg, voice): subprocess.call([SAY_CMD, msg, "--voice=%s" % (voice)]) def __init__(self): # plugin disable itself if say is not present if not os.path.exists(SAY_CMD): self.disabled = True print "%s does not exist, plugin %s disabled" % (SAY_CMD, os.path.basename(__file__)) … def runner_on_failed(self, host, res, ignore_errors=False): say("Failure on host %s" % host, FAILED_VOICE) def runner_on_ok(self, host, res): say("pew", LASER_VOICE) ________________________________________________ / https://github.com/mpdehaan/ansible-and-juliet / ------------------------------------------------ ,;;;;;;;, ;;;;;;;;;;;, ;;;;;'_____;' ;;;(/))))|(( _;;((((((|)))) / |_ .--~( ~)))))))))))) / `-((((((((((( | | ` ) | /|) | | `. _/ _____/ | | , `~ / | / | `. `| / | ~- ` / ____~._/~ -_, ( |-----| ';; | | :;;;' | / | | | | |
  22. 22. #HACK>executing tasks - action: module: <module name> - action: <module name> - <module name>: ● optionally ‘local_action’ instead of ‘action’ ● module name as a variable {{mymodule}}
  23. 23. #HACK>abstract package - include_vars: “{{ansible_os_distribution|default (‘default’)}}.yml” - name: install apache action: “{{ansible_pkg_mgr}} name={{item}} state=present” with_items: “{{apache_pkgs}}” - template: src: “{{apache_config}}.j2” dest: /etc/{{apache_config}} owner: “{{apache_user}}” group: “{{apache_group}}” notify: “apache_restart”
  24. 24. #HACK>abstract package Redhat.yml --- apache_user: httpd apache_group: httpd apache_config: /etc/httpd/conf/httpd.conf apache_pkgs: - httpd - mod_ssl - php-fpm apache_service: httpd
  25. 25. #HACK>abstract package Debian.yml --- apache_user: www-data apache_group: www-data apache_config: /etc/apache2/httpd.conf apache_pkgs: - apache2-mpm - libapache2-mod-ssl - php5-fpm apache_service: apache2 __________________ / can break apachectl utils / ------------------ .--. |o_o | |:_/ | // (| | ) /'_ _/` ___)=(___/
  26. 26. #THE END>wait 6 && exit ● Ansible was born to play well with Unix ● Roles allow for reuse and sharing ● Plugins are where you code ● Plugins are useful to non programmers. ● callbacks, lookups, filters, etc are also plugins ● Many ways to make Ansible work for you __________ < goodbye! > ---------- ^__^ (oo)_______ (__) )/ ||----w | || ||

×