一、上集回顾
1、运维:
手动 --> 标准化 --> 工具化 --> 自动化 --> 智能化
2、工具化
OS Install:PXE ,Cobbler;Virutalization & Cloud Commputing
OS Config: ansible,fabric,puppet,saltstack,chef,cfengine,...
Deployment: fabric,ansible,...
Task Exec:fabric,ansible,func,...
3、Ansible:agentless(ssh),modules
Modules:
copy,file,fetch..
yum,easy_install,pip,
service,
group,user,
cron,at,..
command,shell
script,
ping,
template,...
Ad-Hoc,Playbook,...
$ ansible HOST-PATTERN -m MOD_NAME -a MOD_ARGS -C -f FORKS
二、Ansible Playbook
1、此前我们在命令行中直接运行的方式很难复用,比如我们管控十台主机都装上nginx并启动服务,我们使用ansible命令可直接使用,不过万一其中某几台主机出现故障我们需要重新部署这些命令我们需要记得住并且还需要重新来一遍。所以我们可以让每一台主机要执行的任务将其保存在文件中,这个文件组织成为YAML格式,必要的时候我们只需要使用ansible命令来执行这个指定的playbook,他会读取每一个指定的操作,将其在目标主机上完成。
2、YAML
a、定义
b、功能
c、语言的构成元素
c、基本数据结构
标量、数组、关联数组
维基百科:https:zh.wikipedia.org/wiki/YAML
3、playbook核心元素
a、Hosts:主机即关联到的主机,即哪些主机来执行这些任务
b、Tasks:任务列表,指要唱哪几出戏。
c、Variables:在唱戏的过程中如果有些数据我们需要重复使用可以使用此字段
d、Templates:生成文件时还可以基于模板来定义,这样对于不同的主机我们就可以使用不同的内容了。
e、Roles:我们可以将playbook分片以后构建成Roles。
f、Handlers:由特定条件触发的任务。
4、Playbook的基础组件
a、Hosts:运行指定任务的目标主机;
b、remoute_user:在远程主机上执行任务的用户;即目标主机上以哪个用户的身份来执行任务
sudo_user:如果以普通用户来执行任务有时候需要切换到管理员才能执行
c、tasks:任务列表,我们要执行管控任务时,我们的任务有哪些个?每一个任务的给定方法有两种,但是无论是哪种给法通常用来指明说调哪个模块传哪些参数从而让他完成哪个管理任务格式如下:
(1)、action:module arguments:动作和模块参数;action指你打算执行的是删除还是创建这种,调哪个模块,以及向这个模块传递什么参数。
(2)、module:arguments :模块名称和模块参数;即直接给定模块名称,以及要传递给模块的参数。
注意:shell 和command 模块后面直接跟命令,而非key=value类的参数列表;
某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
任务可以通过“tags”打标签,而后可在ansible-playbook命令上使用 -t 指定进行调用;
5、运行playbook的方式:
a、ansible-playbook --check :只检测可能会发生的改变,但不真正执行操作
b、ansible-playbook --list-hosts: 列出运行任务的主机;
c、运行
三、Playbook使用
1、定义Playbook
a、定义安装redis yaml文件
[root@node3 playbooks]# cat first.yaml - hosts: all #主机列表,这表示接下来由192.168.10.13来唱第一出戏 remote_user: root #任务由root执行 task: #执行什么任务,下面一共执行三个任务 - name: install redis yum: name=redis state=latest - name: start redis service: name=redis state=started #- hosts: all #表示所有主机都要唱戏 #- hosts: 192.168.10.14 #主机列表,表示由192.168.10.14来唱这出戏
b、检查语法,查看执行任务的主机和任务
[root@node3 playbooks]# ansible-playbook --syntax-check first.yaml
playbook: first.yaml
[root@node3 playbooks]# ansible-playbook --list-hosts --list-tasks first.yaml playbook: first.yaml play #1 (all): all TAGS: [] #第一出戏适用于all主机,标签没有定义,也就意味着all pattern: [u'all'] hosts (3): 192.168.10.14 192.168.10.15 192.168.10.13 tasks: install redis TAGS: [] #安装redis任务 start redis TAGS: [] #启动redis 任务
c、干跑一遍(不会真正的跑,只是预跑)。跑任务时是按照任务分发给所有主机,执行完第一个再执行第二个,再执行第三个再执行第四个。如果某一个任务卡住了所有主机上的所有任务都无法完成。
[root@node3 playbooks]# ansible-playbook -C first.yaml PLAY [all] ********************************************************************************************************************************************************************************** #收集主机上的环境信息,所有的戏都会添加进去 TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] ok: [192.168.10.15] ok: [192.168.10.14] TASK [install redis] ************************************************************************************************************************************************************************ changed: [192.168.10.15] changed: [192.168.10.14] changed: [192.168.10.13] TASK [start redis] ************************************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] changed: [192.168.10.15] #统计结果 PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.14 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.15 : ok=3 changed=2 unreachable=0 failed=0
d、真正执行任务
[root@node3 playbooks]# ansible-playbook first.yaml
查看redis是否安装上
[root@node3 playbooks]# ansible all -m shell -a "netstat -anpt|grep 6379" 192.168.10.15 | SUCCESS | rc=0 >> tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 15620/redis-server 192.168.10.13 | SUCCESS | rc=0 >> tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 10712/redis-server 192.168.10.14 | SUCCESS | rc=0 >> tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 10716/redis-server
e、将192.168.10.14的redis.conf配置文件复制到当前目录下
[root@node3 playbooks]# ansible 192.168.10.14 -m fetch -a "src=/etc/redis.conf dest=./" 192.168.10.14 | SUCCESS => { "changed": true, "checksum": "07eedef3014b6ed6d95b95b38577dff5ac3ecf12", "dest": "/root/playbooks/192.168.10.14/etc/redis.conf", "md5sum": "d98629fded012cd2a25b9db0599a9251", "remote_checksum": "07eedef3014b6ed6d95b95b38577dff5ac3ecf12", "remote_md5sum": null } [root@node3 playbooks]# ls 192.168.10.14/etc/ redis.conf [root@node3 playbooks]# cp 192.168.10.14/etc/redis.conf ./
修改配置文件两项参数。注意,参数后面不要加#注释,不然服务会起不来。被坑了一下午。
[root@node3 playbooks]# cat redis.conf |grep -E "^bind|^requ" bind 0.0.0.0 requirepass wohaoshuai
2、handlers关键字:任务在特定条件下触发。接收到其它任务的通知时被触发。notify: HANDLER TASK NAME
a、定义yaml文件替换redis.conf文件
[root@node3 playbooks]# cat first.yaml - hosts: all #主机列表,这表示接下来由192.168.10.13来唱第一出戏 remote_user: root #任务由root执行 tasks: #执行什么任务,下面一共执行三个任务 - name: install redis yum: name=redis state=latest - name: copy config file copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis - name: start redis service: name=redis state=started #- hosts: all #表示所有主机都要唱戏 #- hosts: 192.168.10.14 #主机列表,表示由192.168.10.14来唱这出戏 [root@node3 playbooks]# ansible-playbook --syntax-check first.yaml playbook: first.yaml [root@node3 playbooks]# ansible-playbook first.yaml PLAY [all] ********************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] ok: [192.168.10.15] ok: [192.168.10.13] TASK [install redis] ************************************************************************************************************************************************************************ ok: [192.168.10.15] ok: [192.168.10.14] ok: [192.168.10.13] TASK [copy config file] ********************************************************************************************************************************************************************* changed: [192.168.10.13] changed: [192.168.10.15] changed: [192.168.10.14] TASK [start redis] ************************************************************************************************************************************************************************** ok: [192.168.10.15] ok: [192.168.10.14] ok: [192.168.10.13] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=4 changed=1 unreachable=0 failed=0 192.168.10.14 : ok=4 changed=1 unreachable=0 failed=0 192.168.10.15 : ok=4 changed=1 unreachable=0 failed=0
b、定义某一任务只要发生改变另一个任务就要触发,即条件式触发
[root@node3 playbooks]# cat second.yaml - hosts: all #主机列表,这表示接下来由192.168.10.13来唱第一出戏 remote_user: root #任务由root执行 tasks: #执行什么任务,下面一共执行三个任务 - name: install redis yum: name=redis state=latest - name: copy config file copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis notify: restart redis #通知,通知给任务restart redis,即任务copy config file任务执行后只要redis.conf复制成功那么就执行 restart redis这个任务,不过只有redis.conf改变才会执行,若重复执行 该任务则restart redis任务不会重复执行。
- name: start redis service: name=redis state=started handlers: #处理器 - name: restart redis service: name=redis state=restarted
c、假如我们现在只想把redis.conf文件送到每一个节点而不启动其它任务,可以这样干,先把任务copy config file打上标签然后在执行的时候加上标签名称
[root@node3 playbooks]# cat second.yaml - hosts: all #主机列表,这表示接下来由192.168.10.13来唱第一出戏 remote_user: root #任务由root执行 tasks: #执行什么任务,下面一共执行三个任务 - name: install redis yum: name=redis state=latest - name: copy config file copy: src=/root/playbooks/redis.conf dest=/etc/redis.conf owner=redis notify: restart redis #通知,通知给任务restart redis,即任务copy config file任务执行后只要redis.conf复制成功那么就执行 restart redis这个任务,不过只有redis.conf改变才会执行,若重复执行 该任务则restart redis任务不会重复执行。
tags: configfile - name: start redis service: name=redis state=started handlers: #处理器 - name: restart redis service: name=redis state=restarted
[root@node3 playbooks]# ansible-playbook -t configfile second.yaml PLAY [all] ********************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] ok: [192.168.10.14] ok: [192.168.10.15] TASK [copy config file] ********************************************************************************************************************************************************************* changed: [192.168.10.15] changed: [192.168.10.14] changed: [192.168.10.13] RUNNING HANDLER [restart redis] ************************************************************************************************************************************************************* changed: [192.168.10.13] changed: [192.168.10.14] changed: [192.168.10.15] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.14 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.15 : ok=3 changed=2 unreachable=0 failed=0
如果两个任务标签都一样那么这两个任务都会执行
3、variables:变量
a、facts:因为通过ansible-playbook执行任务时会提前收集节点相应变量信息因此可直接调用,可使用setup模块直接获取目标主机的facters;
[root@node3 playbooks]# ansible 192.168.10.15 -m setup
[root@node3 playbooks]# cat third.yaml - hosts: 192.168.10.14 remote_user: root tasks: - name: copy file copy: content={{ ansible_env }} dest=/tmp/ansible.env [root@node3 playbooks]# ansible-playbook third.yaml PLAY [192.168.10.14] ************************************************************************************************************************************************************************ #此步骤为收集节点相应配置信息信息 TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] TASK [copy file] **************************************************************************************************************************************************************************** changed: [192.168.10.14] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.14 : ok=2 changed=1 unreachable=0 failed=0 [root@node3 playbooks]# ansible 192.168.10.14 -m shell -a "cat /tmp/ansible.env" 192.168.10.14 | SUCCESS | rc=0 >> {"LANG": "en_US.utf8", "TERM": "xterm", "SHELL": "/bin/bash", "XDG_RUNTIME_DIR": "/run/user/0", "MAIL": "/var/mail/root", "SHLVL": "2", "SSH_TTY": "/dev/pts/0", "SSH_CLIENT": "192.168.10.15 44546 22", "LESSOPEN": "||/usr/bin/lesspipe.sh %s", "PWD": "/root", "LOGNAME": "root", "USER": "root", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin", "HOME": "/root", "LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:", "XDG_SESSION_ID": "197", "_": "/usr/bin/python", "SSH_CONNECTION": "192.168.10.15 44546 192.168.10.14 22"}
b、用户自定义变量
1)、ansible-playbook命令的命令行中的自定义变量:-e VARS, --extra-vars=VARS
[root@node3 playbooks]# cat forth.yaml - hosts: all remote_user: root tasks: - name: install package yum: name={{ pkgname }} state=latest [root@node3 playbooks]# ansible-playbook -e pkgname=memcached -C forth.yaml PLAY [all] ********************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] ok: [192.168.10.14] ok: [192.168.10.15] TASK [install package] ********************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.15] changed: [192.168.10.13] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=2 changed=1 unreachable=0 failed=0 192.168.10.14 : ok=2 changed=1 unreachable=0 failed=0 192.168.10.15 : ok=2 changed=1 unreachable=0 failed=0
2)、在playbook中定义变量
c、通过roles传递变量
d、通过主机清单来传递变量(Host Inventory)
1)、向不同的主机传递不同的变量:
IP/HOSTNAME varaiable=value var2-=value2
2)、向组中的主机传递相同的变量;
[groupname:vars]
variable=value
3)、注意,invertory参数用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量。对于主机清单而言,我们ansible要管控哪些主机必须实现把其定义到主机清单中,否则是不能作为管控目标的,而定义在主机清单文件中的方式我们还可以尝试着把其定义为主机组,用角色来进行命名
[root@node3 ansible]# cat /etc/ansible/hosts |grep -Ev "^$|^#" [websrvs] 192.168.10.13 192.168.10.14 [dbsrvs] 192.168.10.15 192.168.10.14 #IP可以复用 [root@node3 ansible]# ansible websrvs --list-hosts hosts (2): 192.168.10.13 192.168.10.14
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass
ansible_sudo_pass
4)、放在中括号中叫做主机清单的组名,而这个组名在定义内部的主机时还可以使用通配符的方式进行定义。
[root@node3 ansible]# cat /etc/ansible/hosts |grep -Ev "^$|^#" [websrvs] node[1:7].wohaoshuai.com [dbsrvs] 192.168.10.15 192.168.10.14 #IP可以复用 [root@node3 ansible]# ansible websrvs --list-hosts hosts (7): node1.wohaoshuai.com node2.wohaoshuai.com node3.wohaoshuai.com node4.wohaoshuai.com node5.wohaoshuai.com node6.wohaoshuai.com node7.wohaoshuai.com
5)、还可以在主机清单中自定义参数
首先我们给每个主机创建一个用户
[root@node3 playbooks]# cat /etc/ansible/hosts |grep -Ev "^$|^#" [websrvs] 192.168.10.13 #ansible_ssh_port=22122 ansible_ssh_user=wohaoshuai ansible_ssh_password=wohaoshuai 192.168.10.14 [dbsrvs] 192.168.10.15 192.168.10.14 #IP可以复用 [root@node3 playbooks]# cat users.yaml - hosts: all remote_user: root tasks: - name: add_user user: name=wohaoshuai system=no state=present - name: set password shell: echo wohaoshuai |passwd --stdin wohaoshuai [root@node3 playbooks]# ansible-playbook users.yaml PLAY [all] ********************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] ok: [192.168.10.14] ok: [192.168.10.15] TASK [add_user] ***************************************************************************************************************************************************************************** changed: [192.168.10.15] changed: [192.168.10.13] changed: [192.168.10.14] TASK [set password] ************************************************************************************************************************************************************************* changed: [192.168.10.14] changed: [192.168.10.13] changed: [192.168.10.15] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.14 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.15 : ok=3 changed=2 unreachable=0 failed=0
接下来我们通过在主机清单中设置连接用户来连接管控的机器
[root@node3 playbooks]# cat /etc/ansible/hosts |grep -Ev "^$|^#" [websrvs] 192.168.10.13 ansible_ssh_user=wohaoshuai ansible_ssh_pass=wohaoshuai 192.168.10.14 ansible_ssh_user=wohaoshuai ansible_ssh_pass=wohaoshuai [dbsrvs] 192.168.10.15 192.168.10.14 #IP可以复用 [root@node3 playbooks]# ansible websrvs -m shell -a "whoami" 192.168.10.13 | SUCCESS | rc=0 >> wohaoshuai 192.168.10.14 | SUCCESS | rc=0 >> wohaoshuai
6)、我们在向主机传递参数时是可以直接传递变量的,接下来我们给组定义变量
[root@node3 playbooks]# cat /etc/ansible/hosts |grep -Ev "^$|^#" [websrvs] 192.168.10.13 192.168.10.14 [websrvs:vars] http_port=8080 #表示websrvs这个组有一个共同的所有主机都有的变量叫http_port且其值为8080 [dbsrvs] 192.168.10.15 192.168.10.14 #IP可以复用
e、关于变量的实例
包含命令行,主机清单,playbook的变量实例
[root@node3 playbooks]# cat /etc/ansible/hosts |grep -Ev "^$|^#" [websrvs] 192.168.10.13 http_port=8080 192.168.10.14 http_port=10080 [dbsrvs] 192.168.10.15 192.168.10.14 #IP可以复用 [root@node3 playbooks]# cat vars.yaml - hosts: websrvs remote_user: root vars: - pbvar: playbook variable testing tasks: - name: command line variables copy: content={{ cmdvar }} dest=/tmp/cmd.var - name: playbook variables copy: content={{ pbvar }} dest=/tmp/pb.var - name: host iventory variables copy: content={{ http_port }} dest=/tmp/hi.var [root@node3 playbooks]# ansible-playbook -e cmdvar="commandlinevariabletesting" vars.yaml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] ok: [192.168.10.13] TASK [command line variables] *************************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] TASK [playbook variables] ******************************************************************************************************************************************************************* changed: [192.168.10.13] changed: [192.168.10.14] TASK [host iventory variables] ************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.13] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=4 changed=3 unreachable=0 failed=0 192.168.10.14 : ok=4 changed=3 unreachable=0 failed=0
[root@node3 playbooks]# ansible websrvs -m shell -a "cat /tmp/cmd.var && cat /tmp/pb.var && cat /tmp/hi.var" 192.168.10.14 | SUCCESS | rc=0 >> commandlinevariabletestingplaybook variable testing10080 192.168.10.13 | SUCCESS | rc=0 >> commandlinevariabletestingplaybook variable testing8080
四、模板(Templates)
1、在说模板之前要先说一说模板模块。模板是指包含了模板语法的文本文件,而模板文件的生成要靠模板模块。
a、我们可以通过引用fector中的变量来定义配置文件
[root@node3 playbooks]# cat redis.conf.j2 |grep -E "^bind" bind {{ ansible_ens33.ipv4.address }} [root@node3 playbooks]# cat template.yaml - hosts: 192.168.10.13 remote_user: root tasks: - name: install config file template: src=/root/playbooks/redis.conf.j2 dest=/tmp/redis.conf [root@node3 playbooks]# ansible-playbook template.yaml PLAY [192.168.10.13] ************************************************************************************************************************************************************************ TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] TASK [install config file] ****************************************************************************************************************************************************************** changed: [192.168.10.13] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=2 changed=1 unreachable=0 failed=0 [root@node3 playbooks]# ansible 192.168.10.13 -m shell -a "cat /tmp/redis.conf|grep -E ^bind" 192.168.10.13 | SUCCESS | rc=0 >> bind 192.168.10.13
b、利用template安装httpd,让不同的主机拥有不同的配置项,这就需要主机清单中的变量了,如果是同样的配置项可以使用组变量来定义。
[root@node3 playbooks]# cat /root/playbooks/mylisten.conf Listen {{ http_port }} [root@node3 playbooks]# cat /root/playbooks/httpd.yaml - hosts: websrvs remote_user: root tasks: - name: install httpd yum: name=httpd state=latest - name: install config file template: src=/root/playbooks/mylisten.conf dest=/etc/httpd/conf.d/mylisten.conf - name: start httpd service: name=httpd state=started [root@node3 playbooks]# ansible-playbook --syntax-check httpd.yaml playbook: httpd.yaml [root@node3 playbooks]# ansible-playbook httpd.yaml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] ok: [192.168.10.14] TASK [install httpd] ************************************************************************************************************************************************************************ changed: [192.168.10.13] changed: [192.168.10.14] TASK [install config file] ****************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.13] TASK [start httpd] ************************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.13] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=4 changed=3 unreachable=0 failed=0 192.168.10.14 : ok=4 changed=3 unreachable=0 failed=0 [root@node3 playbooks]# ansible websrvs -m shell -a "cat /etc/httpd/conf.d/mylisten.conf && netstat -anpt|grep 80" 192.168.10.13 | SUCCESS | rc=0 >> Listen 8080 tcp6 0 0 :::8080 :::* LISTEN 17726/httpd tcp6 0 0 :::80 :::* LISTEN 17726/httpd 192.168.10.14 | SUCCESS | rc=0 >> Listen 10080 tcp 0 0 192.168.10.14:22 192.168.10.15:44820 ESTABLISHED 18061/sshd: root@pt tcp6 0 0 :::80 :::* LISTEN 18048/httpd tcp6 0 0 :::443 :::* LISTEN 18048/httpd tcp6 0 0 :::10080 :::* LISTEN 18048/httpd
五、Roles
1、在讲roles之前需要先介绍task中的其它高级使用方式,比如我们要安装nginx,tomcat,redis,mysql等构建一个简单的lnmp,同时还能基于redis做缓存或键值存储。任务相同但是包名不一样,此时我们可以在playbook的任务中可使用迭代功能或判断机制
a、when,条件判断
[root@node3 playbooks]# cat os.yaml - hosts: websrvs remote_user: root tasks: - name: install httpd yum: name=httpd state=latest when: ansible_os_family == "RedHat" - name: install apache2 apt: name=apache2 state=latest when: ansible_os_family == "Debian"
[root@node3 playbooks]# ansible-playbook -C os.yaml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] ok: [192.168.10.13] TASK [install httpd] ************************************************************************************************************************************************************************ ok: [192.168.10.14] ok: [192.168.10.13] TASK [install apache2] ********************************************************************************************************************************************************************** skipping: [192.168.10.13] skipping: [192.168.10.14] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=2 changed=0 unreachable=0 failed=0 192.168.10.14 : ok=2 changed=0 unreachable=0 failed=0
b、循环,迭代
[root@node3 playbooks]# cat iter.yaml - hosts: websrvs remote_user: root tasks: - name: install {{ item }} package yum: name={{ item }} state=latest with_items: - tomcat - tomcat-webapps - tomcat-admin-webapps [root@node3 playbooks]# ansible-playbook iter.yaml
[root@node3 playbooks]# ansible-playbook iter.yaml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.13] ok: [192.168.10.14] TASK [install {{ item }} package] *********************************************************************************************************************************************************** changed: [192.168.10.13] => (item=[u'tomcat', u'tomcat-webapps', u'tomcat-admin-webapps']) changed: [192.168.10.14] => (item=[u'tomcat', u'tomcat-webapps', u'tomcat-admin-webapps']) PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=2 changed=1 unreachable=0 failed=0 192.168.10.14 : ok=2 changed=1 unreachable=0 failed=0
2、roles:角色
a、以nginx为例,我们要尝试去启动nginx,用ansible来实现大体包含如下几个步骤。首先需要安装epel仓库,然后需要装程序包,然后提供nginx配置文件,然后启动服务。提供配置文件也有两种方式,直接复制或用模板生成。因此你需要三四个步骤。更重要的是他还需要一个文件来复制,这个文件应该是你的ansible主机之上,他在ansible主机之上的哪个目录下呢?将来ansible主机坏了我们把对应的playbook挪到另外一个主机上的时候他还是否能正常执行,还要不要把配置文件一起复制过去,如果忘了复制怎么办呢?所以我们为了完成某一特定任务最好把为了创建一个为了完成任务所需要的各种内容都放在一起,比如:tasks任务列表,handler触发器列表,包括模板文件本身等放在一个自包含的目录结构中,这个自包含的目录结构就叫角色。比如我们定义一个角色就叫nginx,里面有tasks专门放任务,vars专门放变量,templates专门放模板文件,files里面各种文件都是我们的纯文本文件专门用于复制的。
b、ansible在配置文件中已经说明他的角色应该放在/etc/ansible/roles目录下或/usr/share/ansible/roles目录下
[root@node3 ~]# cat /etc/ansible/ansible.cfg |grep -Ev "^#|^$" [defaults] roles_path = /etc/ansible/roles:/usr/share/ansible/roles [inventory] [privilege_escalation] [paramiko_connection] [ssh_connection] [persistent_connection] [accelerate] [selinux] [colors] [diff]
c、接下来我们创建一个nginx的role,这里面除了tasks是必须的之外其它都不是必须的
[root@node3 ~]# mkdir -pv /etc/ansible/roles/nginx/{files,templates,tasks,vars,handlers,meta,default} mkdir: created directory ‘/etc/ansible/roles/nginx’ mkdir: created directory ‘/etc/ansible/roles/nginx/files’ mkdir: created directory ‘/etc/ansible/roles/nginx/templates’ mkdir: created directory ‘/etc/ansible/roles/nginx/tasks’ mkdir: created directory ‘/etc/ansible/roles/nginx/vars’ mkdir: created directory ‘/etc/ansible/roles/nginx/handlers’ mkdir: created directory ‘/etc/ansible/roles/nginx/meta’ mkdir: created directory ‘/etc/ansible/roles/nginx/default’
我们先只在nginx角色的tasks中编写任务然后编写安装nginx的playbook文件
[root@node3 ~]# cat /etc/ansible/roles/nginx/tasks/main.yml - name: install nginx yum: name=nginx state=latest when: ansible_os_family == "RedHat" [root@node3 ~]# cat nginx.yml - hosts: websrvs remote_user: root roles: - nginx [root@node3 ~]# ansible-playbook -C nginx.yml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] ok: [192.168.10.13] TASK [nginx : install nginx] **************************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=2 changed=1 unreachable=0 failed=0 192.168.10.14 : ok=2 changed=1 unreachable=0 failed=0
d、其还有其它更为强大的表现,比如nginx起码要有配置文件,假如这个配置文件我们自建一个虚拟主机,因此,在原有配置文件的基础之上我们额外加一个配置文件比如监听在80端口上,而对应的servername是这个主机的自身的主机名此时就需要用ansible的变量来获取主机名并保存在配置文件中,于是我们来开干
[root@node3 ~]# cat /etc/ansible/roles/nginx/templates/vhost1.conf.j2 server { listen 80; server_name {{ ansible_fqdn }}; location / { root "/ngxdata/vhost1"; } } [root@node3 ~]# cat /etc/ansible/roles/nginx/tasks/main.yml - name: install nginx yum: name=nginx state=latest when: ansible_os_family == "RedHat" - name: install conf template: src=vhost1.conf.j2 dest=/etc/nginx/conf.d/vhost1.conf #这儿直接写vhost1.conf.j2他就会自动到templates目录下去找该文件 [root@node3 ~]# cat nginx.yml - hosts: websrvs remote_user: root roles: - nginx [root@node3 ~]# ansible-playbook -C nginx.yml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] ok: [192.168.10.13] TASK [nginx : install nginx] **************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.13] TASK [nginx : install conf] ***************************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=3 changed=2 unreachable=0 failed=0 192.168.10.14 : ok=3 changed=2 unreachable=0 failed=0
e、接下来我们介绍一个包含变量的任务
[root@node3 ~]# cat /etc/ansible/roles/nginx/tasks/main.yml - name: install nginx yum: name=nginx state=latest when: ansible_os_family == "RedHat" - name: install conf template: src=vhost1.conf.j2 dest=/etc/nginx/conf.d/vhost1.conf #这儿直接写vhost1.conf.j2他就会自动到templates目录下去找该文件 tags: conf notify: restart nginx - name: install site home directory file: path={{ ngxroot }} state=directory - name: install index page copy: src=index.html dest={{ ngxroot }}/ - name: start nginx service: name=nginx state=started [root@node3 ~]# cat /etc/ansible/roles/nginx/handlers/main.yml - name: restart nginx service: name=nginx state=restarted [root@node3 ~]# vim /etc/ansible/roles/nginx/vars/main.yml [root@node3 ~]# cat /etc/ansible/roles/nginx/vars/main.yml ngxroot: /ngxdata/vhost1 [root@node3 ~]# cat /etc/ansible/roles/nginx/files/index.html <h1>Vhost1<h1> [root@node3 ~]# cat /etc/ansible/roles/nginx/templates/vhost1.conf.j2 server { listen 80; server_name {{ ansible_fqdn }}; location / { root "/ngxdata/vhost1"; } }
[root@node3 ~]# ansible-playbook -C nginx.yml PLAY [websrvs] ****************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************** ok: [192.168.10.14] ok: [192.168.10.13] TASK [nginx : install nginx] **************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.13] TASK [nginx : install conf] ***************************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] TASK [nginx : install site home directory] ************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] TASK [nginx : install index page] *********************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] TASK [nginx : start nginx] ****************************************************************************************************************************************************************** changed: [192.168.10.14] changed: [192.168.10.13] RUNNING HANDLER [nginx : restart nginx] ***************************************************************************************************************************************************** changed: [192.168.10.13] changed: [192.168.10.14] PLAY RECAP ********************************************************************************************************************************************************************************** 192.168.10.13 : ok=7 changed=6 unreachable=0 failed=0 192.168.10.14 : ok=7 changed=6 unreachable=0 failed=0
将templates目录下文件中监听端口改为8080后再次执行任务后会发现nginx服务重启了并更新了监听端口