ansible 进阶使用
- template模板:实现配置文件的模板生成
- with_items:playbook循环执行
- When:playbook条件判断
- for or if:template模板文件的循环操作和 if 操作
template模板
可以理解为是copy的升级版,常规copy文件到远程主机后如果需要修改文件内容可以使用replace,但是这样操作就会有一个问题,文件发生了改变,下次再执行playbook文件,又会copy一次文件,然后执行replace,失去了幂等性也不方便,template模板就是可以利用jinja2语言编写好后复制到远程服务器
对比如下
#不用template模板
- hosts: os
tasks:
- name: copy nova
copy: src=./nova.conf dest=/etc/nova/
- name: replace
replace:
regexp: '^my_ip.*'
replace: 'my_ip = {{ansible_default_ipv4["address"]}}'
path: /etc/nova/nova.conf
#使用template模板
- name: copy nova
template: src=./nova.conf dest=/etc/nova/
#配置文件,可以基于变量或者运算符
my_ip = {{ ansible_default_ipv4["address"] }}
with_items
playbook编写对于添加多个值的时候很不方便,比如添加hosts,需要多写很多个lineinfile模块,with_items可以基于定义的列表进行循环
对比如下
#常规添加
- name: sysctl
lineinfile:
dest: /etc/sysctl.conf
line: fs.file-max = 655350
- name: sysctl
lineinfile:
dest: /etc/sysctl.conf
line: net.bridge.bridge-nf-call-iptables = 1
#with_items
- name: sysctl
lineinfile: dest=/etc/sysctl.conf line={{ item }}
with_items:
- fs.file-max = 655350
- net.bridge.bridge-nf-call-iptables = 1
#支持嵌套
- name: create_user #任务2,新建用户且指定组
user: name={{ item.user }} group={{ item.group1 }}
with_items:
- {user: user1,group: group1}
- {user: user2,group: group2}
- {user: user3,group: group3}
When
符合When条件的才会执行单个模块的功能
- name: sysctl
lineinfile:
dest: /etc/sysctl.conf
line: fs.file-max = 655350
when: {{ansible_default_ipv4["address"]}} == "172.17.0.70"
# 只有符合ip地址是172.17.0.70远程主机才会执行lineinfile模块
for or if
template模板文件可以支持for 循环和 if
- 控制结构:用法跟其他语言类似,写法有点区别
必须写在"{% %}" 两个百分号之间
{% endfor $}结尾
{% endif %}结尾
{% for vhost in xxxx %}
server {
listen {{ xxxx }}
}
{% endfor %}
#xxxx是定义的一个变量,变量值是一个列表,循环从变量里拿数据
vars:
xxxx:
- x1
- x2
- x3
{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
{% endif %}
#如果vhost.server_name被定义了,就执行下面的内容
#if多分支
{% if vhost.port is undefined %}
http_port=80
{% elif vhost.port == 81 %}
http_port=81
{% else %}
http_port = 83
{% endif %}
线上写了一个openstack的节点批量加入
---
#openstack_evn
- hosts: os
tasks:
- name: hostname
hostname: name={{host_name}}
- name: disable firewall
service: name=firewalld state=stopped enabled=no
- name: disable selinux
replace:
path: /etc/selinux/config
regexp: '^SELINUX=.*'
replace: 'SELINUX=disabled'
- name: setenforce 0
command: setenforce 0
ignore_errors: yes
- name: yum aliyun
uri:
url: https://mirrors.aliyun.com/repo/Centos-7.repo
dest: /etc/yum.repos.d/CentOS-Base.repo
- name: yum opentack
yum: name=centos-release-openstack-train.noarch update_cache=yes
- name: yum package
yum: name=bash-completion,epel-release,net-tools,chrony,openstack-selinux,lrzsz
- name: hosts
lineinfile:
dest: /etc/hosts
line: 172.17.0.254 controller
- name: chrony_conf
replace:
path: /etc/chrony.conf
regexp: '^server.*'
replace: 'server controller iburst'
- name: start chroyd
service: name=chronyd state=restarted enabled=yes
- name: sysctl
lineinfile: dest=/etc/sysctl.conf line={{ item }}
with_items:
- fs.file-max = 655350
- net.bridge.bridge-nf-call-iptables = 1
- name: sysctl -p
shell: modprobe br_netfilter && sysctl -p
# node
- name: yum nova && neutron
yum: name=openstack-nova-compute,openstack-neutron-linuxbridge,ebtables,ipset
- name: copy nova
template: src=./nova.conf dest=/etc/nova/
- name: copy neutron
copy: src=./neutron.conf dest=/etc/neutron/
- name: copy linuxbridge
copy: src=./linuxbridge_agent.ini dest=/etc/neutron/plugins/ml2/
- name: mkdir instances
file: path=/instances state=directory mode=777
- name: start libvirtd
service: name=libvirtd.service state=started enabled=yes
- name: start nova
service: name=openstack-nova-compute.service state=started enabled=yes
- name: start neutron
service: name=neutron-linuxbridge-agent.service state=started enabled=yes
- name: log nova
shell: tail -n 100 /var/log/nova/nova-compute.log
register: log
- debug: var=log.stdout_lines
- name: log neutron
shell: tail -n 100 /var/log/neutron/linuxbridge-agent.log
register: log
- debug: var=log.stdout_lines