文章目录
- Palybook
- 概念
- playbook中的yaml要求
- 含核心元素的yaml格式playbook示例
- 模板jinja2的语法
- Playbook实践
- 实验环境
- 实践过程
Palybook
概念
- Palybook:称为剧本,是Ansible的配置,部署和编排语言。 它们可以描述您希望远程系统执行的策略,或一般IT流程中的一组步骤。Playbooks是一个不同于使用Ad-Hoc方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指定的操作步骤有序执行,支持同步和异步方式。值得注意的是playbook是通过YAML格式来进行描述定义的。
- Palybook核心元素:
- yaml:playbook指定编写格式, 与标准yaml有部分区别,存在自定义设置
- hosts:主机(主机组),具体被操作的资源清单
- tasks:任务,剧本中使用模块对资源清单具体操作的部分
- block:块,由于剧本中任务可以是多个,有些任务具有共同条件,方便统一管理,可以划分在一个block中
- rescue:当block中任务处理失败时,处理rescue中的任务
- always :不论block中任务是否处理失败,都处理always中的任务
- vars:变量,变量是一些值,或字典,列表的名称(可以是标量值–整数,布尔型,或字符串,字典,列表),然后变量可以应用在模板和剧本里面,通过设置变量方便后期对剧本的修改管理
- register:注册变量,定义一个变量,储存指定任务处理后的结果,可以通过
ansible-playbook XXXX.yaml -v
参数,查看任务反馈的值进行使用 - vars:自定义变量,剧本中常规定义方式定义变量使用
- facts: 远端节点的信息。当它们被用在模板的时候, facts只能被引用,而不能被设置。Facts是当运行 plays 时候执行内部的
setup
模块自动收集的。你不需要明确的调用 setup 模块,它自己运行,但是当你想节省时间的时候你可以禁止它,添加语句gather_facts:no
- 魔术变量:templates中传递数据的变量
- templates:模板,可以看作一个编译过的模块文件,用来生产目标文本,传递变量数据给模板去替换模板中的标记位置,Jinja2 是 Ansible 模板的首选语言
- handlers:处理器 ,当满足设定的条件后,进行指定操作
- when:可以对处理的任务设置判断条件
- loop:可以对处理的任务进行循环处理
- tags:允许给playbook里面的资源通过自定义的关键字打上标签,然后只运行与关键字一致的部分代码
- 变量优先级问题(不同地方定义的变量会有重复的情况):
- 在命令行中使用 -e指定的变量优先级最高
- 然后是在inventory中定义的连接变量(比如ansible_ssh_user)
- 接着是大多数的其它变量(命令行转换,play中的变量,included的变量,role中的变量等)
- 然后是在inventory定义的其它变量
- 然后是由系统发现的facts
- 然后是 “role默认变量”, 这个是最默认的值,很容易丧失优先权
#细化优先级,由高到低
command line values (eg “-u user”)
role defaults
inventory file or script group vars
inventory group_vars/all
playbook group_vars/all
inventory group_vars/*
playbook group_vars/*
inventory file or script host vars
inventory host_vars/*
playbook host_vars/*
host facts / cached set_facts
play vars
play vars_prompt
play vars_files
role vars (defined in role/vars/main.yml)
block vars (only for tasks in block)
task vars (only for the task)
include_vars
set_facts / registered vars
role (and include_role) params
include params
extra vars (always win precedence)
playbook中的yaml要求
- playbook文件的第一行应该以
---
三个连字符开始,表明YMAL文件的开始 - 在同一行中,
#
之后的内容表示注释 - 支持数据格式:列表、字典、布尔值、复合形式(数据可以复合使用,注意各自标准即可)
- 列表:列表元素以
-
开头,然后紧跟着一个空格,同一个列表中的元素应该保持相同的缩进 - 字典:一个字典是由一个简单的
key: value
的形式组成,这个冒号后面必须是一个空格,字典也可以使用缩进形式来表示 - 布尔值:
yes|no|ture|fals|True|False|TRUE|FALSE
,不区分大小写,均可以表示布尔值 - 复合形式:数据可以复合使用,使用时按照各自标准书写即可
- 可以使用
|
和>
符号来书写文字块,前者其所修饰的所有字符串的换行符均不保留,后者与之相反全部保留(>
符号可以看做折叠换行符),注意主要区别在于保留换行符,但是无论哪种情况,缩进都将被忽略。 - 使用
''
或者""
将含有特殊符号的字符串包裹起来使用,不与格式要求的特殊符号发生语法冲突;单引号和双引号之间的区别在于,在双引号中可以使用转义符\0,\t,\n等
-
"{{ variable }}"
以此格式表示变量,为与字典进行区分所以是双括号+引号
含核心元素的yaml格式playbook示例
仅是一个示例,具体核心元素可以自由组合,并不固定
---
# 一个示例格式
- hosts: 主机或主机组名称
gather_facts: yes|no facts变量获取定义
vars:
vars_key: vars_value 自定义变量
tasks: 任务
- name: "{{vars_key}}" 任务名称,及自定义变量使用
Module: 使用的模块
parameter: 模块使用参数
when: 此任务执行的判断条件
notify: 定义handlers触发
handlers:
- name: 触发器操作
template: 模板
src: name.j2 模板的j2文件
dest:
tags: 定义标签
- name: 块区域命名
block: 块定义
- name: 任务命名
Module: 使用的模块
parameter: 模块使用参数
- name: 多个任务
Module:
parameter:
register: result 注册变量,收集此模块结果
rescue: 与block对齐
- name: 可以是多个
Module:
parameter: result 假设此模块可以使用result注册变量为条件
always:
- name: "{{ item }}" 使用loop循环指定任务A、B
Module:
parameter:
loop:
- A
- B
模板jinja2的语法
- 变量:变量取值格式为
{{ vars }}
,其中vars为引用的变量,jinja2支持python中所有的Python数据类型比如列表、字段、对象等
<p>this is a dicectory:{{ mydict['key'] }} </p>
<p>this is a list:{{ mylist[3] }} </p>
<p>this is a object:{{ myobject.something() }} </p>
- 注释 :用
{# #}
结束表示注释,支持多行注释
{# 单行注释 #}
{#
多行
注释
#}
- 过滤器:变量可以通过过滤器进行修改,过滤器可以理解为是jinja2里面的内置函数和字符串处理函数
safe: 渲染时值不转义
capitialize: 把值的首字母转换成大写,其他子母转换为小写
lower: 把值转换成小写形式
upper: 把值转换成大写形式
title: 把值中每个单词的首字母都转换成大写
trim: 把值的首尾空格去掉
striptags: 渲染之前把值中所有的HTML标签都删掉
join: 拼接多个值为字符串
replace: 替换字符串的值
round: 默认对数字进行四舍五入,也可以用参数进行控制
int: 把值转换成整型
{{ 'abc' | captialize }}
# Abc
{{ 'abc' | upper }}
# ABC
{{ 'hello world' | title }}
# Hello World
{{ "hello world" | replace('world','test') | upper }}
# HELLO TEST
{{ 1.1 | round | int }}
# 1
- 控制:
{% %}
,将控住语句写在其中,支持for循环(迭代),if语句(if..elif..else)
,注意结束都要有end结束提示符
{% for i in [1,2,3,4] if i>2 %}
{{ i }}
{%else%}
{{ i }}
{% endfor %}
#列表迭代
<ul>
{% for user in users %}
<li>{{ user.username|title }}</li>
{% endfor %}
</ul>
#字典迭代
<dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key }}</dt>
<dd>{{ value}}</dd>
{% endfor %}
</dl>
{% if vars > 5 %}
{{ vars }}
{% elif vars < 10 %}
{{ vars }}
{% else %}
{{ vars }}
{% endif %}
Playbook实践
实验环境
主机 | IP | 作用 | 使用用户 |
node1 | 192.168.27.11 | 控制机,安装有ansible 2.9.3 | 设置有ans用户,拥有sudo(all)权限,仅方便实验 |
node2 | 192.168.27.12 | 被控制节点,设置有ans用户 | 拥有sudo(all)权限,仅方便实验 |
node3 | 192.168.27.13 | 被控制节点,设置有ans用户 | 拥有sudo(all)权限,仅方便实验 |
实践过程
- 修改vim编写环境,方便yaml格式调整
####################### 修改vim #######################
[ans@node1 ~]$ vim .vimrc #设置当前用户vim配置
autocmd FileType yaml setlocal ai ts=2 sw=2 et #ts为table的空格数2,sw为换行后智能缩进空格数2,et为用空格代替tab
set cursorcolumn #设置高亮列,方便对齐
set cursorline #高亮行
highlight CursorColumn cterm=NONE ctermbg=black ctermfg=green guibg=NONE guifg=NONE
#设置样式 cterm开启自定义,ctermbg背景色,ctermfg前景色,可以使用颜色用的颜色包括:black, brown, grey, blue, green, cyan, magenta, yellow, white
highlight CursorLine cterm=NONE ctermbg=black ctermfg=none guibg=NONE guifg=NONE
- 1个简单play(安装httpd,运行httpd),测试一些常用命令
####################### playbook,安装httpd,运行服务 #######################
[ans@node1 ansible]$ cat playbook.yml
---
- hosts: web
tasks:
- name: install apache
yum:
name: httpd
state: installed
- name: start apache
service:
name: httpd
state: started
####################### 测试命令 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml --syntax-check
playbook: playbook.yml
#语法检查
[ans@node1 ansible]$ ansible-playbook playbook.yml --list-hosts
playbook: playbook.yml
play #1 (web): web TAGS: []
pattern: [u'web']
hosts (1):
node2
#显示hosts列表
[ans@node1 ansible]$ ansible-playbook playbook.yml --list-tasks
playbook: playbook.yml
play #1 (web): web TAGS: []
tasks:
install apache TAGS: []
start apache TAGS: []
#显示任务列表
**[ans@node1 ansible]$ ansible-playbook playbook.yml
PLAY [web] *************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************
ok: [node2]
TASK [install apache] **************************************************************************************************************
changed: [node2]
TASK [start apache] ****************************************************************************************************************
changed: [node2]
PLAY RECAP *************************************************************************************************************************
node2 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
**
#运行结果
- 添加任务,修改访问页面
####################### 添加任务 #######################
[ans@node1 ansible]$ vim playbook.yml
---
- hosts: web
tasks:
……
- name: create index.html
copy:
content: "node2\n"
dest: /var/www/html/index.html
####################### 运行,测试 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml
……
TASK [create index.html] ***********************************************************************************************************
changed: [node2]
PLAY RECAP *************************************************************************************************************************
node2 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#有一个修改,证明实现了这个任务
[ans@node1 ansible]$ curl node2
node2
- 配置文件拷贝,添加触发器(配置文件的拷贝,仅仅是文件的移动,想要服务读取配置文件,还有添加触发器重新加载文件)
注意:触发器只有在任务执行时,声明生效才能被触发;一旦此任务执行过,处于ok状态,不是change,声明无法生效,触发器不能被执行
####################### 添加拷贝配置文件,触发器任务 #######################
[ans@node1 ansible]$ cat playbook.yml
---
- hosts: web
tasks:
……
- name: config apache
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
notify: restart apache #声明,使用触发任务的名称
handlers:
- name: restart apache #触发器中同名的任务
service:
name: httpd
state: restarted
####################### 配置文件,需提前准备好 #######################
[ans@node1 ansible]$ vim files/httpd.conf
Listen 8080
####################### 运行,测试 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml
……
TASK [config apache] ***************************************************************************************************************
changed: [node2]
RUNNING HANDLER [restart apache] ***************************************************************************************************
changed: [node2]
PLAY RECAP *************************************************************************************************************************
node2 : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#运行了新任务
[ans@node1 ansible]$ curl node2
curl: (7) Failed connect to node2:80; Connection refused
[ans@node1 ansible]$ curl node2:8080
node2
- 设置多个play(将curl测试放入playbook中)
####################### 添加测试play,运行 #######################
[ans@node1 ansible]$ vim playbook.yml
……
- hosts: localhost
become: no
tasks:
- name: curl apache
uri:
url: http://node2:8080
[ans@node1 ansible]$ ansible-playbook playbook.yml
……
PLAY [localhost] ************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [localhost]
TASK [curl apache] **********************************************************************************************************
ok: [localhost]
PLAY RECAP ******************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
#运行成功,但是看不到结果
#想看到结果就要使用注册变量了
- 同时添加使用变量(自定义变量,注册变量,facts变量)
####################### 添加自定义变量,注册变量,facts变量 #######################
[ans@node1 ansible]$ cat playbook.yml
---
- hosts: web
vars: #定义的变量
web_package: httpd
web_service: httpd
tasks:
- name: install apache
yum:
name: "{{ web_package }}" #使用变量package
state: installed
- name: start apache
service:
name: "{{ web_service }}" #使用变量service
state: started
- name: create index.html
copy:
content: "{{ ansible_hostname }}\n" #使用facts变量,ansible_hostname是使用setup模块查询出来的,直接使用
dest: /var/www/html/index.html
- name: config apache
copy:
src: files/httpd.conf
dest: /etc/httpd/conf/httpd.conf
notify: restart apache
handlers:
- name: restart apache
service:
name: "{{ web_service }}"
state: restarted
tags: web #设置标签,方便分步运行play
- hosts: localhost
become: no
tasks:
- name: curl apache
uri:
url: http://node2:8080
register: result #注册变量,可以使用-v查询
- debug:
var: result #使用注册变量
tags: curl
####################### 查看定义变量 和 facts变量 运行 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml -t web
PLAY [web] ******************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [node2]
TASK [install apache] *******************************************************************************************************
ok: [node2]
TASK [start apache] *********************************************************************************************************
ok: [node2]
TASK [create index.html] ****************************************************************************************************
changed: [node2]
TASK [config apache] ********************************************************************************************************
ok: [node2]
PLAY [localhost] ************************************************************************************************************
PLAY RECAP ******************************************************************************************************************
node2 : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[ans@node1 ansible]$ curl node2:8080
node2 #实际已修改为hostname,因为以前也是这个名字。变化不大
####################### 查看注册变量 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml -t curl
PLAY [web] ******************************************************************************************************************
PLAY [localhost] ************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [localhost]
TASK [curl apache] **********************************************************************************************************
ok: [localhost]
TASK [debug] ****************************************************************************************************************
ok: [localhost] => {
"result": {
"accept_ranges": "bytes",
"changed": false,
"connection": "close",
"content_length": "6",
"content_type": "text/html; charset=UTF-8",
"cookies": {},
"cookies_string": "",
"date": "Sun, 08 Mar 2020 03:52:20 GMT",
"elapsed": 0,
"etag": "\"6-5a04fa19cb25a\"",
"failed": false,
"last_modified": "Sun, 08 Mar 2020 03:39:17 GMT",
"msg": "OK (6 bytes)",
"redirected": false,
"server": "Apache/2.4.6 (Red Hat Enterprise Linux)",
"status": 200,
"url": "http://node2:8080"
}
}
PLAY RECAP ******************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 显示结果result 有些多,可以挑选其中想要显示变量使用,挑选一个status,200状态码为成功
# 修改playbook中内容
[ans@node1 ansible]$ vim playbook.yml
……
- debug:
var: result.status #使用注册变量
[ans@node1 ansible]$ ansible-playbook playbook.yml -t curl
PLAY [web] ******************************************************************************************************************
PLAY [localhost] ************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [localhost]
TASK [curl apache] **********************************************************************************************************
ok: [localhost]
TASK [debug] ****************************************************************************************************************
ok: [localhost] => {
"result.status": "200"
}
PLAY RECAP ******************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 使用模板和变量使用,实现httpd配置文件,监听自己的ip地址
####################### 修改web中任务config apache #######################
[ans@node1 ansible]$ vim playbook.yml
……
- name: config apache
template:
src: files/httpd.conf.j2 #调用jinja2模板,设置文件位置
dest: /etc/httpd/conf/httpd.conf
……
[ans@node1 files]$ vim httpd.conf.j2
……
Listen {{ http_host }}:{{ http_port }} #使用自定义变量
……
[ans@node1 ansible]$ cat inventory
[web]
node2 http_host=192.168.27.12 http_port=80 #将变量定义在资源清单中
[ans@node1 ansible]$ ansible-playbook playbook.yml -t web
####################### 查看结果 #######################
[root@node2 ~]# cat /etc/httpd/conf/httpd.conf | grep Listen |grep -v ^#
Listen 192.168.27.12:80
[root@node2 ~]# netstat -antlp |grep httpd
tcp 0 0 192.168.27.12:80 0.0.0.0:* LISTEN 32308/httpd
- 模板和facts变量结合,采集主机信息
####################### 添加play #######################
- hosts: all
tasks:
- name: create hostsinfo
template:
src: files/hosts.j2
dest: /tmp/hosts
tags: hosts
####################### 设置模板文件 #######################
[ans@node1 ansible]$ vim files/hinfo.j2
主机名: {{ ansible_facts['hostname']}}
IP地址: {{ ansible_facts['eth0']['ipv4']['address']}}
接口: {{ ansible_facts['interfaces']}}
DNS: {{ ansible_facts['dns']}}
内核: {{ ansible_facts['kernel']}}
内存空闲: {{ ansible_facts['memfree_mb']}} MB
根分区: {{ ansible_facts['devices']['dm-0']['size']}}
####################### 运行并且查看结果 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml -t hinfo
PLAY [web] ******************************************************************************************************************
PLAY [localhost] ************************************************************************************************************
PLAY [app] ******************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [node2]
ok: [node3]
TASK [create hostinfo] ******************************************************************************************************
changed: [node2]
changed: [node3]
PLAY RECAP ******************************************************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[ans@node2 tmp]$ cat /tmp/hinfo
主机名: node2
IP地址: 192.168.27.12
接口: [u'lo', u'eth0']
DNS: {}
内核: 3.10.0-862.el7.x86_64
内存空闲: 609 MB
根分区: 17.00 GB
#node3与node2相同
- 模板与魔术变量结合,采集信息生成主机hosts文件
####################### 添加play #######################
- hosts: all
tasks:
- name: create hosts
template:
src: files/hosts.j2
dest: /tmp/hosts
tags: hosts
####################### 设置模板文件 #######################
[ans@node1 ansible]$ cat files/hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{%for host in groups['all']%}
{{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{%endfor%}
####################### 运行并且查看结果 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml -t hosts
PLAY [web] ******************************************************************************************************************
PLAY [localhost] ************************************************************************************************************
PLAY [app] ******************************************************************************************************************
PLAY [all] ******************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [node2]
ok: [node3]
ok: [node1]
TASK [create hosts] *********************************************************************************************************
ok: [node2]
ok: [node3]
ok: [node1]
PLAY RECAP ******************************************************************************************************************
node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[ans@node1 ansible]$ cat /tmp/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.27.11 node1
192.168.27.12 node2
192.168.27.13 node3
- 实现haproxy自动化部署,涉及block和when条件
####################### 添加play #######################
- hosts: all
tasks:
- name: only node1 install haproxy
block: #设置block
- name: install haproxy
yum:
name: haproxy
state: installed
- name: start haproxy
service:
name: haproxy
state: started
- name: config haproxy
template:
src: files/haproxy.cfg.j2
dest: /etc/haproxy/haproxy.cfg
notify: reload haproxy
when: ansible_hostname == 'node1' #设置when判断
handlers:
- name: reload haproxy
service:
name: haproxy
state: reloaded
tags: haproxy
####################### 设置模板文件 #######################
……省略部分配置
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main *:80
default_backend app
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
{% for host in groups['app']%}
server {{hostvars[host]['ansible_facts']['hostname']}} {{hostvars[host]['ansible_facts']['eth0']['ipv4']['address']}}:80 check
{% endfor %}
####################### 运行并且查看结果 #######################
[ans@node1 ansible]$ ansible-playbook playbook.yml -t haproxy
PLAY [app] ******************************************************************************************************************
PLAY [localhost] ************************************************************************************************************
PLAY [app] ******************************************************************************************************************
PLAY [all] ******************************************************************************************************************
PLAY [all] ******************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************
ok: [node3]
ok: [node2]
ok: [node1]
TASK [install haproxy] ******************************************************************************************************
skipping: [node3]
skipping: [node2]
ok: [node1]
TASK [start haproxy] ********************************************************************************************************
skipping: [node2]
skipping: [node3]
ok: [node1]
TASK [config haproxy] *******************************************************************************************************
skipping: [node2]
skipping: [node3]
changed: [node1]
RUNNING HANDLER [reload haproxy] ********************************************************************************************
changed: [node1]
PLAY RECAP ******************************************************************************************************************
node1 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=1 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
node3 : ok=1 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
[ans@node1 ansible]$ curl node1
node2
[ans@node1 ansible]$ curl node1
node3
[ans@node1 ansible]$ curl node1
node2
[ans@node1 ansible]$ curl node1
node3
- loop条件与变量文件方式组合使用,进行多用户创建
####################### 添加play #######################
- hosts: node2
vars_files:
- vars/userlist.yml #指定用户文件路径
tasks:
- name: create users
user:
name: "{{item.user}}"
password: "{{item.passwd | password_hash('sha512')}}"
loop: "{{userlist}}"
tags: user
####################### 设置用户文件 #######################
[ans@node1 ansible]$ cat vars/userlist.yml
---
userlist:
- user: user1
passwd: asd
- user: user2
passwd: asd
####################### 运行并且查看结果 #######################
……省略部分
TASK [create users] *********************************************************************************************************
changed: [node2] => (item={u'passwd': u'asd', u'user': u'user1'})
changed: [node2] => (item={u'passwd': u'asd', u'user': u'user2'})
PLAY RECAP ******************************************************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[ans@node2 tmp]$ tail -n 2 /etc/passwd
user1:x:1002:1002::/home/user1:/bin/bash
user2:x:1003:1003::/home/user2:/bin/bash
- ansible自带加密,针对userlist进行加密
####################### 加密|解密 #######################
[ans@node1 ansible]$ ansible-vault encrypt|decrypt vars/userlist.yml
New Vault password:
Confirm New Vault password:
Encryption successful
####################### 查看对比 #######################
[ans@node1 ansible]$ ansible-vault view vars/userlist.yml
Vault password:
---
userlist:
- user: user1
passwd: asd
- user: user2
passwd: asd
[ans@node1 ansible]$ cat vars/userlist.yml
$ANSIBLE_VAULT;1.1;AES256
32663562316438386134396466353166646466666133643231396464333936656265343763346665
3630316665643764306263333564363131333634373330320a376535323465623538633966633338
62376530313461333934396630366166363264316664366466366461373435346531393635306435
3133636135616366350a353162373133373031646564326236613066393337313062663435396135
30363432303762666533383061363636323435303464336562373864323530333165636532646333
33363836653039393066363637343234366435386233663334636266343864323537633635626366
62336336363463646336333164623435636435663731653163353363313637653866623034306236
39313161666339396466
####################### 加密使用 #######################
#必须附带--ask-vault-pass,否则报错
PLAY [all] ******************************************************************************************************************
ERROR! Attempting to decrypt but no vault secrets found
[ans@node1 ansible]$ ansible-playbook playbook.yml -t user --ask-vault-pass
Vault password:
……
PLAY RECAP ******************************************************************************************************************
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0