ansible-playbook

发布时间 2023-08-02 00:03:59作者: 我的城市没有海

为什么引入playbook?
一般运维人员完成一个任务, 比如安装部署一个httpd服务会需要多个模块(一个模块也可以称之为task)提供功能来完成。而playbook就是组织多个task的容器,它的实质就是一个文件,有着特定的组织格式,它采用的语法格式是YAML(Yet Another Markup Language)。YAML语法能够简单的表示散列表,字典等数据结构。简单来说, playbook是由一个或多个模块组成的,使用多个不同的模块,完成一件事情。 

Ansible核心功能
-  pyYAML用于ansible编写剧本所使用的语言格式(saltstack---python);
-  rsync-ini语法, sersync-xml语法, nsible-pyYAML语法;
-  paramiko远程连接与数据传输;
-  Jinja2用于编写ansible的模板信息;

YAML三板斧
缩进: YAML使用一个固定的缩进风格表示层级结构,每个缩进由两个空格组成, 不能使用tabs;
冒号: 以冒号结尾的除外,其他所有冒号后面所有必须有空格;
短横线: 表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表;

YAML基本语法
Ansible-playbook采用YAML语法编写。连续的项目(即列表)用 -减号来表示,key/value(字典)用冒号:分隔。

列表:每一个列表成员前面都要有一个短横线和一个空格

fruits:
    - Apple
    - Orange
    - Strawberry
    - Mango
 
或者:
fruits: ['Apple', 'Orange', 'Strawberry', 'Mango']

 字典:每一个成员由键值对组成,注意冒号后面要有空格

martin:
    name: Martin D'vloper
    job: Developer
    skill: Elite
或者
martin: {name: Martin D'vloper, job: Developer, skill: Elite}

 列表和字典可以混合使用

-  martin:
    name: Martin D'vloper
    job: Developer
    skills:
      - python
      - perl
      - pascal
-  tabitha:
    name: Tabitha Bitumen
    job: Developer
    skills:
      - lisp
      - fortran
      - erlang

 示例如下:
[root@localhost ~]# cat httpd.yaml

---
- hosts: control-node    #将要执行任务的主机,已经在hosts文件中定义好了,可是单个主机或主机组
  remote_user: root      #在目标主机上执行任务时的用户身份
  vars:
    - pkg: httpd
  tasks:
    - name: "install httpd package."
      yum: name={{ pkg }}  state=installed
    - name: "copy httpd configure file to remote host."
      copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: restart httpd     #当这个任务执行状态发生改变时,触发handlers执行.
    - name: "boot httpd service."
      service: name=httpd state=started
  handlers:                     #handlers与tasks是同一级别
    - name: restart httpd
      service: name=httpd state=restarted enabled=yes

 playbook语法特性
1.  以 --- (三个减号)开始,必须顶行写;
2. 次行开始写Playbook的内容,但是一般要求写明该playbook的功能;
3. 严格缩进,并且不能用Tab键缩进;
4. 缩进级别必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的;
5. K/V的值可同行写,也可换行写。同行使用 :分隔,换行写需要以 - 分隔;

playbook基础组件
Hosts:运行执行任务(task)的目标主机

playbook中的每个play的目的都是为了让特定主机以某个指定用户身份执行任务,hosts主要用于指定要执行的任务主机,须事先定义在主机清单中

- hosts: websrvs
- hosts: 192.168.0.21
- hosts: websrvs:appsrvs # 两个组的并集
- hosts: websrvs:&appsrvs # 两个组的交集
- hosts: websrvs:!appsrvs # 在websrvs组中,但不在appsrvs中

remote_user:在远程主机上执行任务的用户

可用于HostTask中,也可以通过指定其通过sudo方式在远程主机上执行任务,其可用于play全局或某个任务中;可以在sudo时使用become_user指定sudo时切换的用户,默认为root

- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: admin
sudo: yes
sudo_user: yuan
# become: yes
# become_user: yuan

 

 注意:2.9版本 sudo已经替换为become

tasks任务列表和action组件

play主体部分是task listtask list有一个或多个task,每个task按次序逐个在hosts中指定的所有主机上执行,即在所有主机上执行完一个task后,再执行下一个task;task的目的是使用指定的参数执行模块,再模块参数中可以使用变量。模块执行为幂等的,意味着多次执行是安全的,其结果一致 ;每个task都应该有其name,用于playbook执行结果输出,建议其内容能够清晰描述任务执行步骤,如果没有提供name,则action的结果将用于输出

#task的两种格式
action: module arguments #示例: action: shell wall hello
module: arguments # 推荐使用此格式 # 示例:shell: wall hello

#示例1
ͬͬ˱
- hosts: websrvs
remote_user: root
gather_facts: no # 不收集系统信息,提高执行效率
tasks:
- name: test network connection
ping:
- name: excute command
command: wall "hello world!"

#示例2
ͬͬ˱
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes

 

 handlers:任务,与tasks不同的是只有在接受到通知时才会被触发

templates:使用模板语言的文本文件,使用jinja2语法。
variables:变量,变量替换{{ variable_name }}

整个playbook是以task为中心,表明要执行的任务。hosts和remote_user表明在远程主机以何种身份执行,其他组件让其能够更加灵活。下面介绍插件:

1.  variable
变量定义在资产 (inventory) 中, 默认就是/etc/ansible/hosts文件中

主机变量:
192.168.200.22 http_port=808 maxRequestsPerChild=808
192.168.200.23 http_port=8080 maxRequestsPerChild=909
 
主机组变量:
[websers]
192.168.200.22
192.168.200.23
 
[websers:vars] 
ntp_server=ntp.exampl.com
proxy=proxy.exampl.com

 变量定义在playbook中

- hosts: webservers
  vars:
    http_port: 80

 使用facts变量

facts变量是由setup模块获取远程主机的信息。
 
用法:
# ansible 192.168.200.23 -m setup

 在roles中定义变量, 这个后面会介绍到.

ansible-playbook 命令中传入参数

使用 -e选项传入参数
# ansible-playbook 192.168.200.23 -e "httpd_port=808" httpd04.yml

 变量的引用

{{ var_name }}

 2.  templates
它是一个模块功能,与copy不同的是他的文本文件采用了jinga2语法,jinga2基本语法如下:

字面量:
  字符串:使用单引号或双引号
  数字:整型,浮点数
  列表:{item1,item2,...}
  字典:{key1:value1,key2:value2,...}
  布尔型:true/false
算术运算:
  +,-,*,/,//,%,**
比较运算:
  ==,!=,>,>=,<,<=
逻辑运算:
  and,or,not

 注意:template只能在palybook中使用。

3.  tasks

执行的模块命令

格式:
  action:模块参数(此种方式只在较新的版本中出现)
  module:参数(已键值对的形式出现)
 
每一个task都有一个名称,用于标记此任务。任务示例:
  name: install httpd
  yum: name=httpd state=present
 
注意:shell和command没有参数,可在后面直接跟命令
  shell: ss -tnl | grep :80
 
1)某任务的运行状态为changed后,可通过相应的notify通知相应的handlers
2)任务可以通过tags打标签,然后通过palybook命令-t选项调用.

 playbook命令及调用方式

用法:
ansible-playbook  <filename.yml> ... [options]

<filename.yml>: yaml格式的playbook文件路径,必须指明
[options]: 选项

Options:
--ask-vault-pass    
             #ask for vault password
             #加密playbook文件时提示输入密码
  -C, --check         
             #don't make any changes; instead, try to predict some of the changes that may occur
             #模拟执行,不会真正在机器上执行(查看执行会产生什么变化)。即并不在远程主机上执行,只是测试。
  -D, --diff          
             #when changing (small) files and templates, show the differences in those files; works great with --check
             #当更新的文件数及内容较少时,该选项可显示这些文件不同的地方,该选项结合-C用会有较好的效果
  -e EXTRA_VARS, --extra-vars=EXTRA_VARS
             #set additional variables as key=value or YAML/JSON
             #在Playbook中引入外部参数变量
  --flush-cache       
             #clear the fact cache
             #清理fact缓存,将fact清除到的远程主机缓存
  --force-handlers    
             #run handlers even if a task fails
             #强制运行handlers的任务,即使在任务失败的情况下
  -f FORKS, --forks=FORKS
             #specify number of parallel processes to use(default=5)
             #并行任务数。FORKS被指定为一个整数,默认是5
  -h, --help          
             #show this help message and exit
             #打开帮助文档API
  -i INVENTORY, --inventory-file=INVENTORY
             #specify inventory host path (default=/etc/ansible/hosts) or comma separated host list.
             #指定要读取的Inventory清单文件
  -l SUBSET, --limit=SUBSET
             #further limit selected hosts to an additional pattern
             #限定执行的主机范围
  --list-hosts        
             #outputs a list of matching hosts; does not execute anything else
             #列出执行匹配到的主机,但并不会执行任何动作。
  --list-tags         
             #list all available tags
             #列出所有可用的tags
  --list-tasks        
             #list all tasks that would be executed
             #列出所有即将被执行的任务
  -M MODULE_PATH, --module-path=MODULE_PATH
             #specify path(s) to module library (default=None)
             #要执行的模块的路径
  --new-vault-password-file=NEW_VAULT_PASSWORD_FILE
             #new vault password file for rekey
             #
  --output=OUTPUT_FILE
             #output file name for encrypt or decrypt; use - for stdout
             #
  --skip-tags=SKIP_TAGS
             #only run plays and tasks whose tags do not match these values
             #跳过指定的tags任务
  --start-at-task=START_AT_TASK
             #start the playbook at the task matching this name
             #从第几条任务(START_AT_TASK)开始执行
  --step              
             #one-step-at-a-time: confirm each task before running
             #逐步执行Playbook定义的任务,并经人工确认后继续执行下一步任务
  --syntax-check      
             #perform a syntax check on the playbook, but do not execute it
             #检查Playbook中的语法书写,并不实际执行
  -t TAGS, --tags=TAGS
             #only run plays and tasks tagged with these values
             #指定执行该tags的任务
  --vault-password-file=VAULT_PASSWORD_FILE
             #vault password file
             #
  -v, --verbose       
             #verbose mode (-vvv for more, -vvvv to enable connection debugging)
             #执行详细输出
  --version           
             #show program's version number and exit
             #显示版本
  
  ############Connection Options,即下面时连接权限############
    control as whom and how to connect to hosts
  
    -k, --ask-pass    
             #ask for connection password
             #
    --private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
             #use this file to authenticate the connection
             #
    -u REMOTE_USER, --user=REMOTE_USER
             #connect as this user (default=None)
             #指定远程主机以USERNAME运行命令
    -c CONNECTION, --connection=CONNECTION
             #connection type to use (default=smart)
             #指定连接方式,可用选项paramiko (SSH)、ssh、local,local方式常用于crontab和kickstarts
    -T TIMEOUT, --timeout=TIMEOUT
             #override the connection timeout in seconds(default=10)
             #SSH连接超时时间设定,默认10s
    --ssh-common-args=SSH_COMMON_ARGS
             #specify common arguments to pass to sftp/scp/ssh (e.g.ProxyCommand)
             #
    --sftp-extra-args=SFTP_EXTRA_ARGS
             #specify extra arguments to pass to sftp only (e.g. -f, -l)
             #
    --scp-extra-args=SCP_EXTRA_ARGS
             #specify extra arguments to pass to scp only (e.g. -l)
             #
    --ssh-extra-args=SSH_EXTRA_ARGS
             #specify extra arguments to pass to ssh only (e.g. -R)
             #
  
  ############Privilege Escalation Options, 即下面时权限提升权限############
    control how and which user you become as on target hosts
  
    -s, --sudo        
             #run operations with sudo (nopasswd) (deprecated, use become)
             #相当于Linux系统下的sudo命令
    -U SUDO_USER, --sudo-user=SUDO_USER
             #desired sudo user (default=root) (deprecated, use become)
             #使用sudo,相当于Linux下的sudo命令
    -S, --su          
             #run operations with su (deprecated, use become)
             #
    -R SU_USER, --su-user=SU_USER
             #run operations with su as this user (default=root)(deprecated, use become)
    -b, --become      
             #run operations with become (does not imply password prompting)
             #
    --become-method=BECOME_METHOD
             #privilege escalation method to use (default=sudo),valid choices: [ sudo | su | pbrun | pfexec | doas |dzdo | ksu | runas ]
             #
    --become-user=BECOME_USER
             #run operations as this user (default=root)
             #
    --ask-sudo-pass   
             #ask for sudo password (deprecated, use become)
             #传递sudo密码到远程主机,来保证sudo命令的正常运行
    --ask-su-pass     
             #ask for su password (deprecated, use become)
             #
    -K, --ask-become-pass
             #ask for privilege escalation password
             #

 ansible-playbook需要注意的两个命令

1)检查语法,只检查是否是yaml语法格式。并不做逻辑校验。(记住这个要经常使用, 它是判断语法是否正确!!!)
# ansible-playbook --syntax-check kevin.yml
2)模拟执行(不是真的执行)
# ansible-playbook -C kevin.yml

关闭Facts
如果不需要使用主机的任何fact数据,可以选择关闭fact数据的获取,这样有利于增强Ansible面对大量系统的push模块。
在playbook中关闭Facts方法(gather_facts: no):

---
- hosts: webserver
  gather_facts: no

 palybook书写格式

---                                   # 也可以不使用这一行。可以省略。
- hosts: 192.168.200.22                #处理指定服务器.   - (空格)hosts:(空格)192.168.200.22
  task:                               #剧本所要干的事情; (空格)(空格)task:
  - name:                             #(两个空格)-(空格)name。
    command: echo hello clsn linux    #(四个空格)command:(空格)
 
需要注意:
Task任务里的name可以省略不写,将-(空格)放到下一行模块墙面。例如:
---                                  
- hosts: 192.168.200.22              
  task:                            
  - command: echo hello clsn linux
 
小示例:
[root@localhost ansible]# cat haha.yaml
---
- hosts: test
  remote_user: root
  gather_facts: no
  tasks:
     - file: path=/opt/task1.txt state=touch

 palybook格式示例

 

[root@server01 ~]# cat test.yaml 
- hosts: test
  tasks:
    - name: Install httpd
      yum: name=httpd state=installed

#playbook检查方法
[root@server01 ~]# ansible-playbook --syntax-check test.yaml 

playbook: test.yaml

[root@server01 ~]# ansible-playbook -C test.yaml 

PLAY [test] *************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************************************************
ok: [192.168.200.22]
ok: [192.168.200.23]

TASK [Install httpd] ****************************************************************************************************************************************************************************************************************
changed: [192.168.200.22]
changed: [192.168.200.23]

PLAY RECAP **************************************************************************************************************************************************************************************************************************
192.168.200.22             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.200.23             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

上面两个检查命令, 第一个是进行playbook剧本配置信息语法检查; 第二个是模拟playbook剧本执行(彩排)