一、上集回顾

  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 # (all): all    TAGS: [] #第一出戏适用于all主机,标签没有定义,也就意味着all
pattern: [u'all']
hosts ():
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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=
192.168.10.15 : ok= changed= unreachable= failed=

    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= >>
tcp 127.0.0.1: 0.0.0.0:* LISTEN /redis-server 192.168.10.13 | SUCCESS | rc= >>
tcp 127.0.0.1: 0.0.0.0:* LISTEN /redis-server 192.168.10.14 | SUCCESS | rc= >>
tcp 127.0.0.1: 0.0.0.0:* LISTEN /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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=
192.168.10.15 : ok= changed= unreachable= failed=

    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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=
192.168.10.15 : ok= changed= unreachable= failed=

      如果两个任务标签都一样那么这两个任务都会执行

  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= changed= unreachable= failed= [root@node3 playbooks]# ansible 192.168.10.14 -m shell -a "cat /tmp/ansible.env"
192.168.10.14 | SUCCESS | rc= >>
{"LANG": "en_US.utf8", "TERM": "xterm", "SHELL": "/bin/bash", "XDG_RUNTIME_DIR": "/run/user/0", "MAIL": "/var/mail/root", "SHLVL": "", "SSH_TTY": "/dev/pts/0", "SSH_CLIENT": "192.168.10.15
", "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=:di=;:ln=;:mh=:pi=;:so=;:do=;:bd=;;:cd=;;:or=;;:mi=;;;:su=;:sg=;:ca=;:tw=;:ow=;:st=;:ex=;:*.tar=;:*.tgz=;:*.arc=;:*.arj=;:*.taz=;:*.lha=;:*.lz4=;:*.lzh=;:*.lzma=;:*.tlz=;:*.txz=;:*.tzo=;:*.t7z=;:*.zip=;:*.z=;:*.Z=;:*.dz=;:*.gz=;:*.lrz=;:*.lz=;:*.lzo=;:*.xz=;:*.bz2=;:*.bz=;:*.tbz=;:*.tbz2=;:*.tz=;:*.deb=;:*.rpm=;:*.jar=;:*.war=;:*.ear=;:*.sar=;:*.rar=;:*.alz=;:*.ace=;:*.zoo=;:*.cpio=;:*.7z=;:*.rz=;:*.cab=;:*.jpg=;:*.jpeg=;:*.gif=;:*.bmp=;:*.pbm=;:*.pgm=;:*.ppm=;:*.tga=;:*.xbm=;:*.xpm=;:*.tif=;:*.tiff=;:*.png=;:*.svg=;:*.svgz=;:*.mng=;:*.pcx=;:*.mov=;:*.mpg=;:*.mpeg=;:*.m2v=;:*.mkv=;:*.webm=;:*.ogm=;:*.mp4=;:*.m4v=;:*.mp4v=;:*.vob=;:*.qt=;:*.nuv=;:*.wmv=;:*.asf=;:*.rm=;:*.rmvb=;:*.flc=;:*.avi=;:*.fli=;:*.flv=;:*.gl=;:*.dl=;:*.xcf=;:*.xwd=;:*.yuv=;:*.cgm=;:*.emf=;:*.axv=;:*.anx=;:*.ogv=;:*.ogx=;:*.aac=;:*.au=;:*.flac=;:*.mid=;:*.midi=;:*.mka=;:*.mp3=;:*.mpc=;:*.ogg=;:*.ra=;:*.wav=;:*.axa=;:*.oga=;:*.spx=;:*.xspf=;:", "XDG_SESSION_ID": "", "_": "/usr/bin/python", "SSH_CONNECTION": "192.168.10.15 192.168.10.14 "}

    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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=
192.168.10.15 : ok= changed= unreachable= failed=

      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 ():
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[:].wohaoshuai.com
[dbsrvs]
192.168.10.15
192.168.10.14 #IP可以复用
[root@node3 ansible]# ansible websrvs --list-hosts
hosts ():
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= 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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=
192.168.10.15 : ok= changed= unreachable= failed=

        接下来我们通过在主机清单中设置连接用户来连接管控的机器

[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= >>
wohaoshuai 192.168.10.14 | SUCCESS | rc= >>
wohaoshuai

      6)、我们在向主机传递参数时是可以直接传递变量的,接下来我们给组定义变量

[root@node3 playbooks]# cat /etc/ansible/hosts |grep -Ev "^$|^#"
[websrvs]
192.168.10.13
192.168.10.14
[websrvs:vars]
http_port= #表示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=
192.168.10.14 http_port=
[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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=
[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= >>
commandlinevariabletestingplaybook variable testing10080 192.168.10.13 | SUCCESS | rc= >>
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= changed= unreachable= failed= [root@node3 playbooks]# ansible 192.168.10.13 -m shell -a "cat /tmp/redis.conf|grep -E ^bind"
192.168.10.13 | SUCCESS | rc= >>
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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed= [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= >>
Listen
tcp6 ::: :::* LISTEN /httpd
tcp6 ::: :::* LISTEN /httpd 192.168.10.14 | SUCCESS | rc= >>
Listen
tcp 192.168.10.14: 192.168.10.15: ESTABLISHED /sshd: root@pt
tcp6 ::: :::* LISTEN /httpd
tcp6 ::: :::* LISTEN /httpd
tcp6 ::: :::* LISTEN /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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=

    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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=

  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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=

    d、其还有其它更为强大的表现,比如nginx起码要有配置文件,假如这个配置文件我们自建一个虚拟主机,因此,在原有配置文件的基础之上我们额外加一个配置文件比如监听在80端口上,而对应的servername是这个主机的自身的主机名此时就需要用ansible的变量来获取主机名并保存在配置文件中,于是我们来开干

[root@node3 ~]# cat /etc/ansible/roles/nginx/templates/vhost1.conf.j2
server {
listen ;
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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=

    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 ;
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= changed= unreachable= failed=
192.168.10.14 : ok= changed= unreachable= failed=

      将templates目录下文件中监听端口改为8080后再次执行任务后会发现nginx服务重启了并更新了监听端口

mage Ansible学习2 Playbook的更多相关文章

  1. mage Ansible学习3 ansible role实例

    一.ansible配置文件解析 1./etc/ansible/ansible.cfg配置文件详解 [root@node3 ~]# cat /etc/ansible/ansible.cfg |grep ...

  2. mage Ansible学习1 常用模块

    一.Ansible特点 二.Ansible架构 1.core modules实现常用模块 2.Custom modules实现自定义模块 3.Connection Plugins 连接插件,可通过SS ...

  3. ansible 学习与实践

    title: ansible 学习与实践 date: 2016-05-06 16:17:28 tags: --- ansible 学习与实践 一 介绍 ansible是新出现的运维工具是基于Pytho ...

  4. Ansible学习实战手记-你想要知道的可能都在这里了

    最近接触了ansible工具,查找了一些资料,也做了一些总结.希望能给刚接触的新手带来一些帮助. 此总结有实际例子,大部分也是从实践中用到才逐一总结的. 当然可能肯定一定会存在一些错误和纰漏,还望大家 ...

  5. ansible核心模块playbook介绍

    ansible的playbook采用yaml语法,它简单地实现了json格式的事件描述.yaml之于json就像markdown之于html一样,极度简化了json的书写.在学习ansible pla ...

  6. ansible编译httpd playbook示例

    以下是playbook的内容.它的处理流程是: 1.先在本地下载apr,apr-util,httpd共3个.tar.gz文件. 2.解压这3个文件. 3.安装pcre和pcre-devel依赖包. 4 ...

  7. ansible学习笔记一

    ansible学习笔记一 参考博客: ansible学习 - 51CTO博客 一.安装 1 .下载epel源 wget -O /etc/yum.repos.d/epel.repo http://mir ...

  8. Ansible学习记录一:Linux下部署

    0.Ansible介绍 Ansible 是一个简单的自动化运维管理工具,可以用来自动化部署应用.配置.编排 task(持续交付.无宕机更新等),采用 paramiko 协议库(fabric 也使用这个 ...

  9. ansible学习笔记三:playbook和roles

    参考博客: Ansible 系列之 Playbooks 剧本 -飞走不可(博客园) linux运维学习之ansible的playbook及roles的使用 - 51CTO博客 nginx 基于uwsg ...

随机推荐

  1. Python基础 — eval 函数的作用

    eval函数就是实现list.dict.tuple与str之间的相互转化str函数把list,dict,tuple转为为字符串 # 字符串转换成列表a = "[[1,2], [3,4], [ ...

  2. c#自制抽奖小程序

    #region 第一部分界面设计 ; Button button = new Button(); Image[] images = new Image[N]; PictureBox[] picture ...

  3. 混编用到 C++中数组和vector 复习下大学课本

    本文基于邓俊辉编著<数据结构(C++语言版)(第3版)>.<C++ Primer(第5版)>以及网上的相关博文而写,博主水平有限,若有不妥处,欢迎指出. 一.数组 C++中数组 ...

  4. 常用的HTTP响应头

    响应头 说明 示例 状态 Access-Control-Allow-Origin 指定哪些网站可以跨域源资源共享 Access-Control-Allow-Origin: * 临时 Accept-Pa ...

  5. 4.linux下配置Golang的环境变量

    装好linux后优先在linux上配置Golang开发环境. 1.到Go语言中文网下载Linux安装包 https://studygolang.com/dl 2.到下载的目录下解压,下载的文件一般在“ ...

  6. CSS知识整理

    1. 权重问题(CSS优先级): 继承或 * :0,0,0,0 标签:0,0,0,1 每个类,伪类:0,0,1,0 每个ID:0,1,0,0 每个行内式:1,0,0,0 !important:无穷大 ...

  7. HTML—链接

    怎么看都觉得链接太神奇了,尤其是创建电子邮件的链接,于是决定单独写一篇关于HTML链接的内容,同时加深记忆 一.首先,超链接可以是一个字,一个词,或者一组词,也可以是一幅图像,通过点击这些内容来跳转到 ...

  8. 如何方便引用自己的python包

    有时候想要把一些功能封装成函数然后包装到模块里面最后形成一个包,然后在notebook里面去引用它去处理自己的数据和分析一些有用的部分,比如自己在 之前用到的一个datascience模板就是这样组织 ...

  9. buffer和cache区别?

    写入数据到内存里,这个数据的内存空间称为缓冲区(buffer) 从内存读取数据,这个存储数据的内存空间称为缓存区(cache) 由于大部分网站以读取为主,写入为辅,所以并发写入一般不是问题.

  10. grpc的简单用例 (C++实现)

    这个用例的逻辑很简单, 服务器运行一个管理个人信息的服务, 提供如下的四个服务: (1) 添加一个个人信息 注: 对应于Unary RPCs, 客户端发送单一消息给服务器, 服务器返回单一消息 (2) ...