ansible——template(模板)、角色
1、template(模板)
Ansible 模板是一种强大的工具,可用于在自动化任务中以动态方式生成配置、文件和其他工件。模板使用 Jinja2 模板语言,这是一种功能强大的模板语言,可用于创建复杂的模板。
Jinja2 模板语言:使用字面量,有下面形式。
-
字符串:使用单引号或者双引号
-
数字:整数、浮点数
-
列表:[item1、item2、......]
-
元组:[item1、item2、......]
-
字典:[key1:value1,key2:value2,......]
-
布尔型:true/false
算数运算:+ ,-, *, /,/ /,%,**
比较操作:==, !=, >, >=, <, <=
逻辑运算:and、or、not
流表达式:If For When
1、template使用
template功能:根据模块文件动态生成对应的配置文件
template文件必须存放于templates目录下,且命名为 .j2 结尾 yaml/yml 文件需和templates目录平级,目录结构如下: ./ ├── temnginx.yml └── templates └── nginx.conf.j2
示例1
[root@node2 templates]# vim testtemp.yml
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: nginx
- name: copy template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: service start
service: name=nginx state=started enabled=yes
[root@node2 templates]# ansible-playbook -C testtemp.yml
[root@node2 templates]# ansible 10.0.0.1 -m shell -a 'rpm -q nginx'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'. If you need to use command
because yum, dnf or zypper is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
10.0.0.1 | CHANGED | rc=0 >>
nginx-1.20.1-10.el7.x86_64
示例2:
给nginx的端口修改了一下——引用了/etc/ansible/hosts中的变量
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: copy template
template: src=/root/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart service
service: name=nginx state=restarted enabled=yes
[root@node2 templates]# ansible 10.0.0.1 -m shell -a 'ss -ntl | grep 82'
10.0.0.1 | CHANGED | rc=0 >>
LISTEN 0 128 *:82 *:*
LISTEN 0 128 [::]:82 [::]:*
变量的优先级:命令行》yml文件中定义的变量》/etc/ansible/hosts(主机清单)中定义的变量——单一变量大于公共变量
2、when
-
条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试, 通过when语句实现,在task中使用,jinja2的语法格式
-
when语句:在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
示例:
tasks: name: "shutdown RedHat flavored systems" command: /sbin/shutdown -h now when: ansible_os_family == "RedHat" 当系统属于红帽系列,执行command模块
补充:过滤系统版本号
[root@node2 ~]# ansible all -m setup -a 'filter=ansible_os_family'
10.0.0.7 | SUCCESS => {
"ansible_facts": {
"ansible_os_family": "RedHat",
},
"changed": false
}
10.0.0.8 | SUCCESS => {
"ansible_facts": {
"ansible_os_family": "RedHat",
},
"changed": false
}
10.0.0.1 | SUCCESS => {
"ansible_facts": {
"ansible_os_family": "RedHat",
},
"changed": false
}
示例1:when条件判断
示例:
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name=nginx
- name: copy conf file to centos7
template: src=templates/nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7"
- name: copy conf file to centos6
template: src=templates/nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "6"
- name: start service
service: name=nginx state=started enabled=yes
# 复制相应的CentOS6的nginx配置文件到本主机上,然后进行操作
3、迭代:with_items
在Ansible中,迭代是一种常用的功能,用于在任务或模块中重复执行相同的操作。
迭代:当有需要重复性执行的任务时,可以使用迭代机制 > 对迭代项的引用,固定变量名为"item" > 要在task中使用with_items给定要迭代的元素列表 > 列表格式: 字符串 字典
示例1:
[root@node2 ansible]# vim testitem.yml
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: create some files
file: name=/data/{{ item }} state=touch
with_items:
- file1
- file2
- file3
方法2:
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: create file file1
file: name=file1 state=touch
- name: create file file1
file: name=file2 state=touch
- name: create file file1
file: name=file3 state=touch
[root@node2 ansible]# ansible-playbook -C testitem.yml
迭代套子变量:
- hosts:10.0.0.1
remote_user: root
tasks:
- name: add some groups
group: name={{ item }} state=present
with_items:
- g1
- g2
- g3
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'u1', group: 'g1' }
- { name: 'u2', group: 'g2' }
- { name: 'u3', group: 'g3' }
[root@node2 ansible]# ansible-playbook -C testitem.yml
[root@node2 ansible]# ansible-playbook testitem.yml
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a 'getent group'
g1:x:1002:
g2:x:1003:
g3:x:1004:
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a 'getent passwd'
u1:x:1002:1002::/home/u1:/bin/bash
u2:x:1003:1003::/home/u2:/bin/bash
u3:x:1004:1004::/home/u3:/bin/bash
template中的 for if when循环
template中的 for
[root@node2 ansible]# vim testfor.yml
---
- hosts: 10.0.0.1
remote_user: root
vars:
ports:
- 80
- 81
- 82
tasks:
- name: copy conf
template: src=templates/for.conf.j2 dest=/data/for.conf
方法2:
---
- hosts: 10.0.0.1
remote_user: root
vars:
ports:
- listen_port: 80
- listen_port: 81
- listen_port: 82
tasks:
- name: copy conf
template: src=templates/for.conf.j2 dest=/data/for.conf
[root@node2 templates]# vim for.conf.j2
{% for port in ports %}
server{
listen {{port}}
{% endfor %}
[root@node2 ansible]# ansible-playbook testfor.yml # 此时已经将端口内容复制到目标主机
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a 'rm -f /data/for.conf'
示例2:
[root@node2 templates]# vim for.conf.j2
{% for p in ports %}
server{
listen {{ p.port }}
servername {{ p.name }}
documentroot {{ p.rootdir }}
{% endfor %}
[root@node2 ansible]# vim testfor.yml
---
- hosts: 10.0.0.1
remote_user: root
vars:
ports:
- web1:
port: 80
name: www.haha1.com
rootdir: /data/website1
- web2:
port: 81
name: www.haha2.com
rootdir: /data/website2
- web3:
port: 82
name: www.haha3.com
rootdir: /data/website3
tasks:
- name: copy conf
template: src=templates/for.conf.j2 dest=/data/for.conf
[root@node2 ansible]# ansible-playbook testfor.yml
# 查看另一台主机复制的内容
[root@node1 ~]# cat /data/for.conf
server{
listen 80
servername www.haha1.com
documentroot /data/website1
server{
listen 81
servername www.haha2.com
documentroot /data/website2
server{
listen 82
servername www.haha3.com
documentroot /data/website3
template中的 for if
[root@node2 ansible]# vim testfor.yml
---
- hosts: 10.0.0.1
remote_user: root
vars:
ports:
- web1:
port: 80
#name: www.haha1.com
rootdir: /data/website1
- web2:
port: 81
name: www.haha2.com
rootdir: /data/website2
- web3:
port: 82
#name: www.haha3.com
rootdir: /data/website3
tasks:
- name: copy conf
template: src=templates/for.conf.j2 dest=/data/for.conf
[root@node1 ~]# cat /data/for.conf
server{
listen 80
documentroot /data/website1
server{
listen 81
servername www.haha2.com
documentroot /data/website2
server{
listen 82
documentroot /data/website3
2、roles
roles概念:
ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。 角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
复杂场景:建议使用roles,代码复用度高 变更指定主机或主机组 如命名不规范维护和传承成本大 某些功能需多个Playbook,通过includes即可实现
角色(roles):角色集合 roles/ mysql/ httpd/ nginx/ memcached/ 所有角色都可以互相调用
role目录结构
playbook.yml 调用角色应该与roles角色的目录平级
├── nginx.role.yml ├── roles │ └── nginx │ ├── tasks │ │ ├── group.yml │ │ ├── main.yml │ │ ├── restart.yml │ │ ├── start.yml │ │ ├── template.yml │ │ ├── user.yml │ │ └── yum.yml │ └── templates │ └── nginx.conf.j2
roles各目录作用:
/roles/project/ :项目名称,有以下子目录 files/ :存放由copy或script模块等调用的文件 templates/:template模块查找所需要模板文件的目录 tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件; 其它的文件需要在此文件中通过include进行包含 handlers/:至少应该包含一个名为main.yml的文件; 其它的文件需要在此文件中通过include进行包含 vars/:定义变量,至少应该包含一个名为main.yml的文件; 其它的文件需要在此文件中通过include进行包含 meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件, 其它文件需在此文件中通过include进行包含 default/:设定默认变量时使用此目录中的main.yml文件 roles/appname 目录结构 tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表; 此文件可以使用include包含其它的位于此目录中的task文件 files目录:存放由copy或script等模块调用的文件; templates目录:template模块会自动在此目录中寻找Jinja2模板文件 handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler; 在handler中使用include包含的其它的handler文件也应该位于此目录中; vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量; meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系; ansible1.3及其以后的版本才支持; default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件 roles/example_role/files/ 所有文件,都将可存放在这里 roles/example_role/templates/ 所有模板都存放在这里 roles/example_role/tasks/main.yml: 主函数,包括在其中的所有任务将被执行 roles/example_role/handlers/main.yml:所有包括其中的 handlers 将被执行 roles/example_role/vars/main.yml: 所有包括在其中的变量将在roles中生效 roles/example_role/meta/main.yml: roles所有依赖将被正常登入
示例1:
[root@node2 roles]# tree ├── nginx.role.yml ├── roles │ └── nginx │ ├── tasks │ │ ├── group.yml │ │ ├── main.yml │ │ ├── restart.yml │ │ ├── start.yml │ │ ├── template.yml │ │ ├── user.yml │ │ └── yum.yml │ └── templates │ └── nginx.conf.j2 [root@node2 ansible]# cd roles/ [root@node2 roles]# ll drwxr-xr-x. 4 root root 4096 Jan 9 16:40 nginx -rwxr-xr-x. 1 root root 70 Jan 9 17:04 nginx.role.yml [root@node2 nginx]# ll total 8 drwxr-xr-x. 2 root root 4096 Jan 9 17:02 tasks drwxr-xr-x. 2 root root 4096 Jan 9 16:59 templates [root@node2 tasks]# ll total 28 -rwxr-xr-x. 1 root root 48 Jan 9 16:56 group.yml - name: create group group: name=nginx gid=82 -rwxr-xr-x. 1 root root 105 Jan 9 17:02 main.yml - include: group.yml - include: user.yml - include: yum.yml - include: template.yml - include: start.yml -rwxr-xr-x. 1 root root 74 Jan 9 16:56 restart.yml - name: service restart service: name=nginx state=restarted enabled=yes -rwxr-xr-x. 1 root root 70 Jan 9 16:56 start.yml - name: service start service: name=nginx state=started enabled=yes -rwxr-xr-x. 1 root root 111 Jan 9 16:49 template.yml - name: copy conf template: src=/root/ansible/roles/nginx/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf -rwxr-xr-x. 1 root root 89 Jan 9 16:56 user.yml - name: create user user: name=nginx uid=82 group=nginx system=yes shell=/sbin/nologin -rwxr-xr-x. 1 root root 43 Jan 9 16:46 yum.yml - name: install package yum: name=nginx [root@node2 nginx]# cd templates/ [root@node2 templates]# ll total 4 -rw-r--r--. 1 root root 2364 Jan 9 16:59 nginx.conf.j2
示例2:
# 再创建一个角色 ├── httpd.role.yml ├── nginx.role.yml ├── roles │ ├── httpd │ │ ├── files │ │ │ └── http.conf │ │ └── tasks │ │ ├── copyfile.yml │ │ ├── main.yml │ │ └── user.yml │ └── nginx │ ├── tasks │ │ ├── group.yml │ │ ├── main.yml │ │ ├── restart.yml │ │ ├── start.yml │ │ ├── template.yml │ │ ├── user.yml │ │ └── yum.yml │ └── templates │ └── nginx.conf.j2 [root@node2 ansible]# vim httpd.role.yml --- - hosts: 10.0.0.1 remote_user: root roles: - httpd [root@node2 tasks]# vim copyfile.yml - name: copy files file: src=/root/ansible/roles/httpd/files/http.conf dest=/data/ owner=apache [root@node2 tasks]# vim main.yml - include: user.yml - include: copyfile.yml [root@node2 tasks]# vim user.yml - name: create user user: name=apache system=yes shell=/sbin/nologin [root@node2 ansible]# ansible-playbook httpd.role.yml # 同时在一台主机上调用两个不同角色 [root@node2 ansible]# vim some.role.yml --- - hosts: 10.0.0.1 remote_user: root roles: - nginx - httpd # 在某个角色中想调用另一个角色的yml文件(本例是在nginx角色中调用httpd的copyfile.yml文件) [root@node2 tasks]# vim user.yml - include: group.yml - include: user.yml - include: yum.yml - include: template.yml - include: start.yml - include: roles/httpd/tasks/copyfile.yml [root@node2 ansible]# ansible-playbook nginx.role.yml TASK [nginx : copy files] *************************************************************************************** changed: [10.0.0.1] # 针对不同角色,可以给每个角色添加标签 [root@node2 ansible]# vim some.role.yml --- - hosts: 10.0.0.1 remote_user: root roles: - { role: nginx,tags: ['web','nginx'] } - { role: httpd,tags: ['web','httpd'] ,when ansible_distribution_major_version="7"} 注释:标签内容为单个可以使用"" [root@node2 ansible]# ansible-playbook -C -t 'web','nginx' some.role.yml
示例3:
├── app.role.yml --- - hosts: 10.0.0.1 remote_user: root roles: - app ├── roles │ ├── app │ │ ├── files │ │ │ └── vhosts.conf │ │ ├── handlers │ │ │ └── main.yml - name: service restart service: name=httpd state=restarted enabled=yes │ │ ├── tasks │ │ │ ├── copyfile.yml │ │ │ ├── group.yml │ │ │ ├── main.yml │ │ │ ├── start.yml │ │ │ ├── templ.yml │ │ │ ├── user.yml │ │ │ └── yum.yml │ │ ├── templates │ │ │ └── http.conf.j2 │ │ └── vars │ │ └── main.yml username: app groupname: app [root@node2 ansible]# ansible-playbook -C app.role.yml
补充:
[root@k8s-node2 ansible]# ansible all -m setup -a 'filter="*memtotal*"' # 过滤出内存的大小 10.0.0.1 | SUCCESS => { "ansible_facts": { "ansible_memtotal_mb": 2048, "discovered_interpreter_python": "/usr/bin/python" }, "changed": false }
下载ansible的角色模板的网址:Ansible 星系