
Ansible Playbook的用法(变量与template)
使用变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头。
我们可以通过setup模块查看远程系统中的变量,都可以直接调用。
setup模块示例
# 获取远程主机的所有环境变量
ansible all -m setup
# 如果只需要看部分的,如只查看有address的我们可以用filter参数进行模糊匹配查询
ansible all -m setup -a 'filter=*address*'
# 关于该模块更多参数请参考
ansible-doc -s setup
通过过滤查看ipaddress4
在playbook中定义变量(外部赋值)
这里我们创建file3.yaml
文件并以安装httpd
与vsftpd
两个包举例
---
- hosts: webserver
remote_user: root
tasks:
- name: install {{ pkname1 }} package
yum: name={{ pkname1 }}
- name: install {{ pkname2 }} package
yum: name={{ pkname2 }}
注意在定义变量名时,要以两个大括号包着,并且变量前后要有一个空格。
然后我们通过-e
参数进行赋值,执行测试一下
# 这里传入变量参数级别最高
ansible-playbook -e pkname1=httpd -e pkname2=vsftpd file3.yaml
# 也可以这样
ansible-playbook -e 'pkname1=httpd pkname2=vsftpd' file3.yaml
在playbook中定义变量(内部赋值)
根据上面的示例,我们可以直接在内部进行赋值。(这里我就不尝试了)
---
- hosts: webserver
remote_user: root
vars:
- pkname1: httpd
- pkname2: vsftpd
tasks:
- name: install {{ pkname1 }} package
yum: name={{ pkname1 }}
- name: install {{ pkname2 }} package
yum: name={{ pkname2 }}
配置文件中定义变量与运用
我们知道配置文件的位置在/etc/ansible/hosts
,我们可以针对不同的ip地址定义不同的值比如,我这里定义一个my_host_last_number
变量,修改/etc/ansible/hosts
:
[webserver]
10.211.55.5 my_host_last_number=5
10.211.55.6 my_host_last_number=6
[dbserver]
10.211.55.5
然后我们创建一个file4.yaml
文件的一个脚本,里面将变量值复制到my_number
文件里面
---
- hosts: webserver
remote_user: root
tasks:
- name: Create Number File
shell: echo '{{ my_host_last_number }}' > my_number
然后我们执行file4.yaml
脚本,先测试在执行。
# 测试
ansible-playbook -C file4.yaml
# 执行
ansible-playbook file4.yaml
# 获取执行结果
ansible all -a 'cat my_number'
我们也可以通过指定组进行设置变量,格式为[组名:vars]
,然后在下面定义变量。然后我们修改一下file4.yaml
进行执行
[webserver]
10.211.55.5 my_host_last_number=5
10.211.55.6 my_host_last_number=6
[webserver:vars]
mygroup=webserver
[dbserver]
10.211.55.5
---
- hosts: webserver
remote_user: root
tasks:
- name: Create Number File
shell: echo '{{ my_host_last_number }}' > my_number
- name: Create Group name
shell: echo '{{ mygroup }}' > my_number
ansible-playbook file4.yaml
ansible all -a 'cat my_number'
普通变量:主机组中主机单独定义,优先级高于公共变量
公共(组)变量:针对主机组中所有主机定义统一变量
命令优先级最高
添加自定义变量文件
创建自定义vars.yml
环境变量的文件。
# cat vars.yml
xx: hello
hi: io
创建var.yml
文件,并通过vars_files
属性指定环境变量配置文件的路径
---
- hosts: webserver
remote_user: root
vars_files:
- vars.yml
tasks:
- name: XX Write
shell: echo '{{ xx }}' > my_number
然后我们执行一下,查看是否将xx
配置变量的hello
值覆盖到my_number
文件中
ansible-playbook -C var.yml
ansible-playbook var.yml
# 检查一下
ansible all -m shell -a 'cat my_number'
注意:这里的vars_files
属性最好还是指定为绝对路径。
jinja2语法
jinja2介绍
jinja2模板中使用 {{ }}
语法表示一个变量,它是一种特殊的占位符。当利用jinja2进行渲染的时候,它会把这些特殊的占位符进行填充/替换,jinja2支持python中所有的Python数据类型比如列表、字段、对象等。
Jinja2算术运算
Jinja 允许你用计算值。这在模板中很少用到,但为了完整性允许其存在
支持下面的运算符
+
:把两个对象加到一起。
通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。
无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2
-
:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1
/
:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }}
//
:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%
:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
*
:用右边的数乘左边的操作数。 {{ 2 2 }} 会返回 4 。
也可以用于重 复一个字符串多次。{{ ‘=’ 80 }} 会打印 80 个等号的横条
**
:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8
比较操作符
==
比较两个对象是否相等!=
比较两个对象是否不等>
如果左边大于右边,返回 true>=
如果左边大于等于右边,返回 true<
如果左边小于右边,返回 true<=
如果左边小于等于右边,返回 true
逻辑运算符
对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式and
如果左操作数和右操作数同为真,返回 trueor
如果左操作数和右操作数有一个为真,返回 truenot
对一个表达式取反(见下)(expr)
表达式组 ['list', 'of', 'objects']
:
Template 模块
Template模块的介绍
当对不同的机器有不同的配置设置时我们可以通过Template的方式设置配置模块。
也可以理解为根据模块文件动态生成对应的配置文件。
Template的注意事项
template文件必须存放于templates目录下,且命名为 .j2 结尾。
# yaml/yml 文件需和templates目录平级,目录结构如下:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
示例同步nginx配置
我们首先在本地安装nginx,并复制相应的配置文件到templates
目录下。
(一般都是需要先添加nginx源,如果未添加请参考:https://www.tnblog.net/hb/article/details/5843)
yum install nginx
# 查看配置
cat /etc/nginx/nginx.conf
然后我们想通过不同的主机上cpu的个数去创建nginx的进程数乘2进行创建,将配置文件复制到templates目录下
ansible all -m setup -a 'filter=*cpu*'
ansible all -m setup -a 'filter=ansible_processor_vcpus'
# 创建templates
mkdir templates
# 将配置文件复制到templates目录下
cp /etc/nginx/nginx.conf templates/nginx.conf.j2
# 修改nginx.conf.j2文件
vim templates/nginx.conf.j2
user nginx;
worker_processes {{ ansible_processor_vcpus*2 }};
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
先结束Apache服务器防止端口冲突,接下来我们来编辑nginx.yaml
文件,接着检查并执行。最后访问一下nginx的页面。
ansible all -m shell -a 'systemctl stop httpd'
---
- hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx
- name: nginx conf template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx service
service: name=nginx state=restarted
ansible all -m shell -a 'curl 127.0.0.1'
如果我们想不受Apache默认启动的80端口影响的话,我们可以通过8拼接my_host_last_number
属性形成新的端口,这里就是:85与86端口。然后我们通过cp /etc/nginx/conf.d/default.conf templates/default.conf.j2
命令将默认配置移动至templates
目录下。
# cat /etc/ansible/hosts
[webserver]
10.211.55.5 my_host_last_number=5
10.211.55.6 my_host_last_number=6
[webserver:vars]
mygroup=webserver
[dbserver]
10.211.55.5
# 编辑模版
# cat templates/default.conf.j2
server {
listen 8{{ my_host_last_number }};
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.lo
接着我们修改nginx.yaml
Play文件,最后执行一下。
---
- hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx
- name: stop service
service: name=nginx state=stopped
ignore_errors: True
- name: nginx default conf template
template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
notify: restart nginx service
- name: nginx conf template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx service
service: name=nginx state=restarted
ansible-playbook nginx.yaml
# 检查一下
ansible all -m shell -a 'curl 127.0.0.1:8{{ my_host_last_number }}'
When的运用
当我们对不同操作系统的时候或对相同操作系统不同版本的时候,会做出不同的修改。所以when
正是因为此操作而诞生的。
when的介绍
条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时要用到条件测试,通过when的语句实现,在task中使用,jinja2的语法格式。
when语句
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
示例
获取不同主机的系统环境版本变量,可以通过如下命令进行查询。
ansible all -m setup -a 'filter=*distribution*'
# 最后查看不同的系统版本时我们发现它是ansible_distribution_major_version
ansible all -m setup -a 'filter=*distribution*'
接着我们可以只判断系统环境为Centos7的才执行。
---
- hosts: all
remote_user: root
tasks:
- name: install nginx package
yum: name=nginx
- name: stop service
service: name=nginx state=stopped
ignore_errors: True
- name: nginx default conf template
template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
when: ansible_distribution_major_version == "7"
notify: restart nginx service
- name: nginx conf template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
notify: restart nginx service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx service
service: name=nginx state=restarted
Jinja2配合Template的语法的运用
with_items介绍
迭代:当有需要重复性执行的任务时,可以使用迭代机制。
- 对迭代项的引用,固体变量名为 “item”
- 要在task中使用with_items给定要迭代的元素列表
- 列表格式:
字符串
字典
示例
先创建3个group组,再创建3个group组的用户。
---
- hosts: all
remote_user: root
tasks:
- name: add some groups
group: name={{item}}
when: ansible_distribution_major_version == "7"
with_items:
- g1
- g2
- g3
- name: add some users
user: name={{item.name}} group={{item.group}}
with_items:
- { name: 'user1', group: 'g1' }
- { name: 'user2', group: 'g1' }
- { name: 'user3', group: 'g3' }
循环语句
在j2
文件中使用for
循环遍历Ansible的变量。首先我们定义testfor.yaml
文件。再在for3.conf.j2
文件中定义循环。
---
- hosts: all
remote_user: root
vars:
ports:
- web1:
port: 81
name: web1
rootdir: /data/web1
- web2:
port: 82
name: web2
rootdir: /data/web2
- web3:
port: 83
name: web3
rootdir: /data/web3
tasks:
- name: copy conf
template: src=for3.conf.j2 dest=/data/for3.conf
然后在相对路径中,创建for3.conf.j2
文件,并添加相关内容。最后执行命令。
{% for p in ports %}
server{
listen {{ p.port }}
servername {{ p.name }}
documentroot {{ p.rootdir }}
}
{% endfor %}
ansible-playbook -C testfor.yaml
ansible-playbook testfor.yaml
验证一下
ansible all -m shell -a 'cat /data/for3.conf'
判断语句
通过if
条件语句判断值有没有被定义。
---
- hosts: all
remote_user: root
vars:
ports:
- web1:
port: 81
#name: web1
rootdir: /data/web1
- web2:
port: 82
name: web2
rootdir: /data/web2
- web3:
port: 83
#name: web3
rootdir: /data/web3
tasks:
- name: copy conf
template: src=for3.conf.j2 dest=/data/for3.conf
{% for p in ports %}
server{
listen {{ p.port }}
{% if p.name is defined %}
servername {{ p.name }}
{% endif %}
documentroot {{ p.rootdir }}
}
{% endfor %}
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739


荔枝大娘
第三百篇了 牛啊