前言:
学习下ansible的playbooks的状态配置管理,说来puppet saltstack都有类似的叫法,只是ansible的叫法更犀利,我当时一看playbook还以为是***的playboy。要使用ansible就要深入学习playbook配置及模板。
注:到底是playbook还是playbooks。。。。
请大家多关注下我的个人博客 , http://xiaorui.cc
先把官网的简单几个语法给说明下。
#这个是你选择的主机 - hosts: webservers #这个是变量 vars: http_port: 80 max_clients: 200 #远端的执行权限 remote_user: root tasks: #利用yum模块来操作 - 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 #这里的restart apache 和上面的触发是配对的。这就是handlers的作用。相当于tag handlers: - name: restart apache service: name=httpd state=restarted
如果有些系统做了相关的sudo限制,需要在playbooks里面开启sodu,或者直接偷懒,权限直接为root !
- hosts: web remote_user: xiaorui tasks: - service: name=nginx state=started sudo: yes
原文:http://rfyiamcool.blog.51cto.com/1030776/1413031
官网的基本完事了,这里就直接实战吧。先说一个简单的ansible playbook的例子。
- name: create user hosts: web user: root gather_facts: false vars: - user: "xiaorui" tasks: - name: create {{ user }} user: name="{{ user }}"
然后我们执行一下,Playbook 采用 YAML 语法结构,因此它们一般比较易于阅读并加以配置。 上面的意思已经很简单明了了,就是创建一个xiaorui的用户,里面引用了一个user的变量,用jinja2模板给赋值进去了。
下面的还用我说么? 多了一个service的调用,nginx的状态保持为启动。
- name: create user
hosts: web
user: root
gather_facts: false
vars:
- user: "xiaorui"
tasks:
- name: create {{ user }}
user: name="{{ user }}"
tasks:
- service: name=nginx state=started
使用copy传送文件的时候,经常出些问题,是ansible需要python-selinux包而已.
[root@67 ~]# ansible-playbook user.yaml PLAY [create user] ************************************************************ TASK: [Copy file to client] *************************************************** failed: [10.10.10.66] => {"failed": true, "md5sum": "1f18348f32c9a4694f16426798937ae2"} msg: Aborting, target uses selinux but python bindings (libselinux-python) aren't installed! FATAL: all hosts have already failed -- aborting PLAY RECAP ******************************************************************** to retry, use: --limit @/root/user.yaml.retry 10.10.10.66 : ok=0 changed=0 unreachable=0 failed=1
yum install -y libselinux-python 就可以行了
copy是传送文件用的。
- name: create user hosts: web user: root gather_facts: false remote_user: root vars: - user: "xiaorui" tasks: - name: create {{ user }} user: name="{{ user }}" tasks: - service: name=nginx state=started tasks: - name: Copy file to client copy: src=/root/rs.sh dest=/root/ccc
根据一些特殊的情况,可以做更多的模板,比如这样
vars: - user: "xiaorui" - say: "xiaorui" tasks: - name: create {{ user }} user: name="{{ user }}" tasks: - service: name=nginx state=started tasks: - name: Copy file to client # copy: src=/root/rs.sh dest=/root/ccc template: src=/root/testfile dest=/root/{{ say }}
不只是这样,我可以把刚才那个say变量传到文件里面。 爽吧? 其实和saltstack一样。。。。
再来一个和puppet exec一样执行外部命令的模块
tasks: - name: "cmd" action: command touch /root/1111
还有一种shell模块的使用方法 。
tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand || /bin/true
ansible在多任务下,推荐使用多进程模式的。其实就是用multiprocess做的多进程池 ! -f 10 就是limit 10个任务并发。
ansible-playbook user.yml -f 10
顺便讲解下,在ansible下,类似puppet的facter,saltstack grains的自定义变量。 -m setup 模块
咱们可以在模板文件中,引用这些setup系统变量的
#xiaorui.cc {{ ansible_devices.sda.model }} {{ ansible_hostname }} {{ ansible_machine }}
看看我测试机的setup是啥样子的。
[root@67 ~]# ansible web -m setup 10.10.10.66 | success >> { "ansible_facts": { "ansible_all_ipv4_addresses": [ "10.10.10.66" ], "ansible_all_ipv6_addresses": [ "fe80::20c:29ff:fe06:f2dc" ], "ansible_architecture": "i386", "ansible_bios_date": "06/02/2011", "ansible_bios_version": "6.00", "ansible_cmdline": { "KEYBOARDTYPE": "pc", "KEYTABLE": "us", "LANG": "zh_CN.UTF-8", "quiet": true, "rd_LVM_LV": "vg_65/lv_swap", "rd_NO_DM": true, "rd_NO_LUKS": true, "rd_NO_MD": true, "rhgb": true, "ro": true, "root": "/dev/mapper/vg_65-lv_root" }, "ansible_date_time": { "date": "2014-05-18", "day": "18", "epoch": "1400373954", "hour": "08", "iso8601": "2014-05-18T00:45:54Z", "iso8601_micro": "2014-05-18T00:45:54.840220Z", "minute": "45", "month": "05", "second": "54", "time": "08:45:54", "tz": "CST", "tz_offset": "+0800", "year": "2014" }, "ansible_default_ipv4": { "address": "10.10.10.66", "alias": "eth0", "gateway": "10.10.10.1", "interface": "eth0", "macaddress": "00:0c:29:06:f2:dc", "mtu": 1500, "netmask": "255.255.255.0", "network": "10.10.10.0", "type": "ether" }, "ansible_default_ipv6": {}, "ansible_devices": { "sda": { "holders": [], "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)", "model": "VMware Virtual S", "partitions": { "sda1": { "sectors": "1024000", "sectorsize": 512, "size": "500.00 MB", "start": "2048" }, "sda2": { "sectors": "418404352", "sectorsize": 512, "size": "199.51 GB", "start": "1026048" } }, "removable": "0", "rotational": "1", "scheduler_mode": "cfq", "sectors": "419430400", "sectorsize": "512", "size": "200.00 GB", "support_discard": "0", "vendor": "VMware," }, "sr0": { "holders": [], "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)", "model": "VMware IDE CDR10", "partitions": {}, "removable": "1", "rotational": "1", "scheduler_mode": "cfq", "sectors": "2097151", "sectorsize": "512", "size": "1024.00 MB", "support_discard": "0", "vendor": "NECVMWar" } }, "ansible_distribution": "CentOS", "ansible_distribution_release": "Final", "ansible_distribution_version": "6.4", "ansible_domain": "ruifengyun.com", "ansible_env": { "CVS_RSH": "ssh", "G_BROKEN_FILENAMES": "1", "HOME": "/root", "LANG": "C", "LESSOPEN": "|/usr/bin/lesspipe.sh %s", "LOGNAME": "root", "MAIL": "/var/mail/root", "PATH": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin", "PWD": "/root", "SELINUX_LEVEL_REQUESTED": "", "SELINUX_ROLE_REQUESTED": "", "SELINUX_USE_CURRENT_RANGE": "", "SHELL": "/bin/bash", "SHLVL": "2", "SSH_CLIENT": "10.10.10.67 50278 22", "SSH_CONNECTION": "10.10.10.67 50278 10.10.10.66 22", "USER": "root", "_": "/usr/bin/python" }, "ansible_eth0": { "active": true, "device": "eth0", "ipv4": { "address": "10.10.10.66", "netmask": "255.255.255.0", "network": "10.10.10.0" }, "ipv6": [ { "address": "fe80::20c:29ff:fe06:f2dc", "prefix": "64", "scope": "link" } ], "macaddress": "00:0c:29:06:f2:dc", "module": "pcnet32", "mtu": 1500, "promisc": false, "type": "ether" }, "ansible_form_factor": "Other", "ansible_fqdn": "66.ruifengyun.com", "ansible_hostname": "66", "ansible_interfaces": [ "lo", "eth0" ], "ansible_kernel": "2.6.32-358.el6.i686", "ansible_lo": { "active": true, "device": "lo", "ipv4": { "address": "127.0.0.1", "netmask": "255.0.0.0", "network": "127.0.0.0" }, "ipv6": [ { "address": "::1", "prefix": "128", "scope": "host" } ], "mtu": 16436, "promisc": false, "type": "loopback" }, "ansible_machine": "i686", "ansible_memfree_mb": 694, "ansible_memtotal_mb": 1006, "ansible_mounts": [ { "device": "/dev/mapper/vg_65-lv_root", "fstype": "ext4", "mount": "/", "options": "rw", "size_available": 47512358912, "size_total": 52844687360 }, { "device": "/dev/sda1", "fstype": "ext4", "mount": "/boot", "options": "rw", "size_available": 449800192, "size_total": 507744256 }, { "device": "/dev/mapper/vg_65-lv_home", "fstype": "ext4", "mount": "/home", "options": "rw", "size_available": 145807802368, "size_total": 153817976832 } ], "ansible_os_family": "RedHat", "ansible_pkg_mgr": "yum", "ansible_processor": [ "Intel(R) Core(TM) i5-2430M CPU @ 2.40GHz" ], "ansible_processor_cores": 1, "ansible_processor_count": 1, "ansible_processor_threads_per_core": 1, "ansible_processor_vcpus": 1, "ansible_product_name": "VMware Virtual Platform", "ansible_product_serial": "VMware-56 4d bf 2f b7 6c f2 9d-bb f1 a6 0b 1a 06 f2 dc", "ansible_product_uuid": "564DBF2F-B76C-F29D-BBF1-A60B1A06F2DC", "ansible_product_version": "None", "ansible_python_version": "2.6.6", "ansible_selinux": { "config_mode": "enforcing", "mode": "permissive", "policyvers": 24, "status": "enabled", "type": "targeted" }, "ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBAOjq8+laDLF6/ly/BezPQONwHrIhRmAwYIDysQEIWvvZ4eq/2MJO6GNleSqHd/e6VH1T3SWO4wbPcgTXVRqoQLlT46RQ3hxCCIQ1Q3vThB+QPstMslYFVrtupzSqrRDbtwakEsdp1VlW5RSyBJ7JgzlQn8yQgQwmuS7IXSl2yX5LAAAAFQD+tvRyt+h7lJngeQc0AXWnN/Ij4QAAAIEAtD9SU4ZGmRSX5Ms8W8oqaTED5b/0VqLgT7ear6NkH0zHi0pRGs2kgf0KLqRjuBKqwlYdBj309Oc+Rip23cqb725BWHlrI4mEvVl2FLSOnTi8zd4esYeRga5od26g9VDjIbE0MGB/hUukH5od4dXjnK1zowADyz7jJkrkT+dFpkcAAACAH/0s0vagsSWR4EsXyR0lQsc/lBT1xSCiRFZbPtqMXxmq/3cqM1bbmyK7puQiJDy3ay/vrV/fmLk5RlgbFJB7n/ZVJnEoGfwXSoHJLRC+7tBJIKUm2jskZ1rl3o3ZxWQsSHPGy3sBDE9R1czKf8p1T8gM/EQrHDtTOqmDgrc287M=", "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAABIwAAAQEAltE2aPOjHIF9Jh79LAm5Dc31VylZk15CqXwnwlQTOqAmFRoPwqnMn+F1oKOTVZ52BAQvitMF4XvNyE0sveSb5hFQkKBsJpEfBPNkQjty1Hgk03HpwHgspu9sk7HmwoPht+qTTm2764YYXiIbDJXva458eWBZsMTPX8frIeNzz1XbwveGbQt+jTYPdqzywp1UEJ4+EwGx9l3zR1WFDqA4Kz3clJJgtoGWasMmNXybr3tHn/csYllWdG0+03fxBM6d4QuR0WmgR7kIxxXnQcvWk0ZNUC3x9dVMeuGPsIvUh2bQOIv1rGWfB24mzIZIjV17RgNXrM8qy2FBZ96Mrvkd3w==", "ansible_swapfree_mb": 4063, "ansible_swaptotal_mb": 4063, "ansible_system": "Linux", "ansible_system_vendor": "VMware, Inc.", "ansible_user_id": "root", "ansible_userspace_architecture": "i386", "ansible_userspace_bits": "32", "ansible_virtualization_role": "guest", "ansible_virtualization_type": "VMware" }, "changed": false }
如果觉得信息太多,有些乱,可以用filter过滤下
[root@67 ~]# ansible web -m setup -a "filter=ansible_mounts" 10.10.10.66 | success >> { "ansible_facts": { "ansible_mounts": [ { "device": "/dev/mapper/vg_65-lv_root", "fstype": "ext4", "mount": "/", "options": "rw", "size_available": 47511494656, "size_total": 52844687360 }, { "device": "/dev/sda1", "fstype": "ext4", "mount": "/boot", "options": "rw", "size_available": 449800192, "size_total": 507744256 }, { "device": "/dev/mapper/vg_65-lv_home", "fstype": "ext4", "mount": "/home", "options": "rw", "size_available": 145807802368, "size_total": 153817976832 } ] }, "changed": false } [root@67 ~]#
如果想把这些 facts加入到template模板中,中途可能会遇到几处让人困扰的地方。
这边需要开启facts变量功能, gather_facts: no 或者是false是关闭,gather_facts:yes 或者是true都是开启。 当时没注意,找到了官方的实例,直接就干,结果sx了。咋都不行,总是提示define为定义。。。 原来facts没有开。。
{% for v in hostvars.iteritems() %} {{ v['ansible_hostname'] }} {% endfor %}
咱们在看看对端服务器的文件渲染情况。
用过puppet saltstack的朋友,知道Variables最后可以扩展什么东西,可以高度的定义每个配置文件。 可以根据ip地址,推送配置文件所需要的绑定的ip地址,根据内存大小,定义nginx缓存的内容大小,根据你的cpu核数,做nginx cpu的绑定,根据你的系统,我需要文件路径的判断等等。。。。。
虽然这些facts够多了,貌似很全,但是如果还不够你用,还不足以让你标识定位一台服务器,咋办? 赞一个 ansible不愧是比saltstack在国外更受欢迎的集群配置工具(据说。。。。 看了youtube的视频,几个老外说,他们热衷于去各种系统框架大会,ansible要比saltstack用的多点,其实我在有一篇文章说过,ansible为啥多? 有兴趣翻翻看看)。 说回来,saltstack的框架确实相当的优秀,但由于更新太频繁,自己不幸又是那是yum epel的人,结果中枪了。。。。
nima,扯远了,继续聊刚才的话题。如何自定义ansible facts变量,官方说的很明白, 在控制机创建一个文件就行了。。。
看懂了吧。 我刚才测试的时候,方法有些土,直接创建的,你可以参照一个例子,copy文件。
- hosts: web tasks: - name: create directory for ansible custom facts file: state=directory recurse=yes path=/etc/ansible/facts.d - name: install custom impi fact copy: src=ipmi.fact dest=/etc/ansible/facts.d - name: re-read facts after adding custom fact setup: filter=ansible_local
ansbile还有一个有意思的功能,可以判断上个tasks的值,根据这个值在做判断。
里面的when , foot_result。。。。 懂了吧
tasks: - shell: /usr/bin/foo register: foo_result ignore_errors: True - name: "cmd" action: command touch /root/kkkkk when: foo_result.rc == 127
这个是测试的过程
#http://xiaorui.cc [root@67 facts.d]# ansible web -m shell -a "ls /root/" 10.10.10.66 | success | rc=0 >> anaconda-ks.cfg date install.log install.log.syslog l.py nnn qpid-python-0.20 qpid-python-0.20.tar.gz testfile urllib-post.py [root@67 facts.d]# ansible-playbook cmd.yaml PLAY [web] ******************************************************************** GATHERING FACTS *************************************************************** ok: [10.10.10.66] TASK: [shell /usr/bin/foo] **************************************************** failed: [10.10.10.66] => {"changed": true, "cmd": "/usr/bin/foo ", "delta": "0:00:00.002429", "end": "2014-05-18 10:25:12.544151", "rc": 127, "start": "2014-05-18 10:25:12.541722"} stderr: /bin/sh: /usr/bin/foo: No such file or directory ...ignoring TASK: [cmd] ******************************************************************* changed: [10.10.10.66] PLAY RECAP ******************************************************************** 10.10.10.66 : ok=3 changed=2 unreachable=0 failed=0 [root@67 facts.d]# ansible web -m shell -a "ls /root/" 10.10.10.66 | success | rc=0 >> anaconda-ks.cfg date install.log install.log.syslog kkkkk l.py nnn qpid-python-0.20 qpid-python-0.20.tar.gz testfile urllib-post.py [root@67 facts.d]#
好了,先这么着吧。。。。 这两天再讲解下 用ansible如何多元配置nginx、lvs keepalived的环境。