一、loop字典循环
1、启动多个服务
在 Ansible 中,可以使用 loop
循环来启动多个服务。这里会用到 item
变量,它是在循环过程中依次代表列表中的每个元素。一次循环赋值一次变量
示例代码如下:
- name: 启动多个服务
hosts: web
tasks:
- name: 启动服务
systemd:
name: "{{ item }}"
state: started
loop:
- service1
- service2
- service3
在上述代码中,loop
列出了需要启动的服务名称列表,item
变量在每次循环中依次取值为 service1
、service2
、service3
,从而实现启动多个服务的目的。
2、创建多个文件
通过字典循环来创建多个文件,并且可以根据不同的子集属性设置不同的权限。一次循环赋值一次变量
示例代码如下:
[root@Ansible ~/ansible]# cat var.yml
- hosts: backup
tasks:
- name: create file
file:
path: /root/{{ item.filename }}
owner: "{{ item.owner }}"
group: "{{ item.group }}"
mode: "{{ item.mode }}"
state: touch
loop:
- { filename: "123", owner: "www", group: "www", mode: "0600"}
- { filename: "abd", owner: "root", group: "root", mode: "0644" }
在这个例子中,loop
循环遍历一个包含文件名和权限的字典列表。item.filename
用于指定文件的名称,item.mode
用于设置文件的权限。
3、拷贝多个文件
可以使用 loop
循环来实现拷贝多个文件的操作。一次循环赋值一次变量
示例代码如下:
- name: 拷贝多个文件
hosts: your_hosts
tasks:
- name: 拷贝文件
copy:
src: "{{ item.src }}"
dst: "{{ item.dst }}"
loop:
- { src: "/source/path/file1.txt", dst: "/root/path/file1.txt" }
- { src: "/source/path/file2.txt", dst: "/opt/path/file2.txt" }
在这个任务中,loop
循环遍历一个包含源文件路径和目标文件路径的字典列表。item.src
代表源文件路径,item.dst
代表目标文件路径,从而实现多个文件的拷贝。
二、标签(Tags)的使用
标签(Tags)可以用来对任务进行分类和筛选,方便在执行 Playbook 时只运行特定标签的任务。
列出标签
可以使用以下命令列出 Playbook 中的所有标签:
[root@Ansible ~/ansible]# ansible-playbook var.yml --list-tags
playbook: var.yml
play #1 (backup): backup TAGS: []
TASK TAGS: [abd]
运行指定标签的任务
使用 -t
选项来指定运行带有特定标签的任务:
- 给某个任务打tag,单独让它执行
- 可以给多个任务打相同的tag
ansible-playbook nfs.yml -t hehe
在 Playbook 中,给任务添加标签的方式如下:
- 测试带标签运行,和不带标签运行的结果
- hosts: backup
tasks:
- name: copy file
copy:
src: "{{ item.src }}"
dest: "{{ item.dst }}"
loop:
- { src: 12 , dst: /root/ }
- { src: 34 , dst: /opt/ }
tags: abd
- name: l
command: ls -l /root/
register: ll
- name: ls
debug:
msg: "{{ ll.stdout_lines }}"
三、使用 include
组合多个任务
include
可以将多个任务组合在一起,方便管理和复用。同时,changed_when: false
可以用来控制任务是否被标记为已改变。
示例代码如下:
- name: 主Playbook
hosts: your_hosts
tasks:
- name: 包含其他任务
include: tasks.yml
changed_when: false
在 tasks.yml
文件中,可以定义多个任务:
- name: 任务1
debug:
msg: "这是任务1"
- name: 任务2
debug:
msg: "这是任务2"
在上述示例中,主 Playbook 通过 include
引入了 tasks.yml
文件中的所有任务,并且通过 changed_when: false
确保这些任务不会被标记为已改变(即使它们实际上执行了操作)。这在某些情况下很有用,例如当任务只是查询信息而不改变系统状态,但 Ansible 可能会误判为改变时。
四、include将多个tasks组合
一、操作目的
通过 Ansible 的 include
功能,将多个任务文件组合在一起,根据主机名条件执行不同的任务。
通过 include_tasks
指令,我们可以方便地将多个任务文件进行组合,并根据不同的条件在不同的主机上执行相应的任务,这提高了 Ansible 任务编排的灵活性和可维护性。在实际应用中,可以根据项目的具体需求,进一步扩展和优化这种任务组合方式。
二、具体操作步骤
(一)准备两个任务文件
- 创建
vars.yml
文件
[root@ansible haoshuaicong]# cat vars.yml
- hosts: all
tasks:
- include_tasks: web01.yml
when: ansible_hostname == "web01"
- include_tasks: backup.yml
when: ansible_hostname == "backup01"
这个文件定义了任务的基本框架,其中包含了根据主机名条件来包含其他任务文件的逻辑。
- 编辑
web01.yml
具体任务内容
[root@ansible haoshuaicong]# cat web01.yml
- name: create nginx.txt
file:
path: /root/nginx.txt
state: touch
该任务的作用是在 /root
目录下创建一个名为 nginx.txt
的空文件。
- 编辑
backup.yml
具体任务内容
[root@ansible haoshuaicong]# cat backup.yml
- name: create file
file:
path: /root/rsync.txt
state: touch
此任务是在 /root
目录下创建一个名为 rsync.txt
的空文件。
(二)整合任务文件
创建 all.yml
文件,将前面两个文件整合起来:
- 使用all全部主机,when判断那个文件需要对应的主机
- 总的来说,就是all.yml调用其他文件,然后when判断对应主机执行对应任务
[root@ansible haoshuaicong]# vim all.yml
- hosts: all
- include_tasks: web.yml
when: ansible_hostname == "web02"
- include_tasks: mysql.yml
when: ansible_hostname == "backup"
五、Jinja2 模版
一、Jinja2 模版基础
在 Ansible 中,Jinja2 模版用于动态生成配置文件或其他文本内容。使用 {{ EXPR }}
来输出变量值,这些变量可以是自定义变量,也可以是 Ansible facts(系统事实信息)。Jinja2 模版通常在文件中使用。
二、准备变量文件示例
(一)创建 motd.j2
文件
[root@ansible haoshuaicong]# cat motd.j2
Welcome to {{ ansible_hostname }}
This system total mem is : {{ ansible_memtotal_mb }} MB
This system ip address: {{ ansible_default_ipv4.address }}
此文件通过 Jinja2 模版语法,使用 Ansible facts 变量 ansible_hostname
(主机名)、ansible_memtotal_mb
(系统总内存,单位为 MB)和 ansible_default_ipv4.address
(系统默认的 IPv4 地址)来生成欢迎信息。
(二)将 motd.j2
拷贝到目标主机
- 必须使用 template模块才能识别变量
[root@ansible haoshuaicong]# cat cp.yml
- hosts: web01
tasks:
- name: copy motd
template:
src: motd.j2
dest: /root/motd.txt
- 查看web01的/root/motd.txt文件是否识别变量
[root@Ansible ~/ansible]# cat vars.yml
- hosts: backup
tasks:
- name: cat
command: cat /root/motd.txt
register: cat
- name: cat2
debug:
msg: "{{ cat.stdout_lines }}"
[root@Ansible ~/ansible]# ansible-playbook vars.yml
TASK [cat2] ***************************************************************************************************************************
ok: [backup] => {
"msg": [
"Welcome to backup01",
"This system total mem is : 948 MB",
"This system ip address: 10.0.0.41"
]
}
PLAY RECAP ****************************************************************************************************************************
backup : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@Ansible ~/ansible]#
在 cp.yml
任务文件中,使用 template
模块将 motd.j2
模版文件拷贝到目标主机的 /root/motd.txt
路径下。在拷贝过程中,Ansible 会根据目标主机的实际情况替换模版中的变量。
三、使用 for 循环生成配置文件案例
(一)创建 nginx.conf
配置文件模版
[root@ansible haoshuaicong]# cat nginx.conf
upstream {{ server_name }} {
{% for n in range(7,9) %}
server 172.16.1.{{ n }}:{{ up_port }};
{% endfor %}
}
server {
listen 80;
server_name {{ server_name }};
location / {
root /code;
index index.html;
proxy_pass http://{{ server_name }};
proxy_set_header Host $http_host;
}
}
这个 nginx.conf
模版文件中,使用 Jinja2 的 for
循环语法动态生成 upstream 部分的服务器列表。range(7, 9)
表示生成从 7 到 8 的数字序列,每个数字将被用于构建服务器地址。同时,还使用了自定义变量 server_name
和 up_port
。
(二)调用 nginx.conf
配置文件
- 必须使用template模块,使用copy模块不识别
[root@ansible haoshuaicong]# cat cp.yml
- hosts: lnmp
vars:
- server_name: www.wp.com
- up_port: 80
tasks:
- name: copy motd
template:
src: nginx.conf
dest: /root/
在 cp.yml
文件中,通过 vars
部分定义了 server_name
和 up_port
变量的值。然后使用 template
模块将 nginx.conf
模版文件拷贝到目标主机的 /root
目录下。生成后的 nginx.conf
文件内容如下:
[root@web01 ~]# cat nginx.conf
upstream www.wp.com {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name www.wp.com;
location / {
root /code;
index index.html;
proxy_pass http://www.wp.com;
proxy_set_header Host $http_host;
}
}
可以看到,模版中的变量和循环部分都被正确替换和展开。
四、使用 Jinja2 生成 keepalived 配置文件
(一)创建 keep.j2
配置文件模版
[root@ansible haoshuaicong]# cat keep.j2
global_defs {
router_id {{ ansible_fqdn }}
}
vrrp_instance VI_1 {
{% if ansible_fqdn == "web01" %}
state MASTER
priority 150
{% else %}
state BACKUP
priority 100
{% endif %}
interface eth0
virtual_router_id 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.0.0.3
}
}
在 keep.j2
模版文件中,使用 Jinja2 的 if - else
条件语句根据 ansible_fqdn
(主机的完全限定域名)来动态生成 vrrp_instance
的状态和优先级。如果主机的 ansible_fqdn
是 web01
,则状态为 MASTER
,优先级为 150;否则为 BACKUP
,优先级为 100。
(二)将 keep.j2
配置文件拷贝到目标主机
[root@ansible haoshuaicong]# cat cp.yml
- hosts: lnmp
vars:
- server_name: www.wp.com
- up_port: 80
tasks:
- name: copy motd
template:
src: keep.j2
dest: /root/
同样在 cp.yml
文件中,使用 template
模块将 keep.j2
模版文件拷贝到目标主机的 /root
目录下,以生成符合不同主机条件的 keepalived 配置文件。
五、总结
通过以上示例,可以看到 Jinja2 模版在 Ansible 中强大的动态配置生成能力。通过结合变量、循环和条件语句,可以根据不同的主机环境和需求,灵活地生成各种配置文件,提高了自动化配置管理的效率和灵活性。
六、Jinja2 模版重构rsync
(一)创建 rsyncd.conf.j2
配置文件模版
[root@ansible ansible]# cat rsyncd.conf.j2
uid = {{ user }}
gid = {{ user }}
port = {{ rsync_port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[backup]
path = {{ rs_dir }}
(二)使用playbook的jinja2重构rsync
[root@ansible ansible]# cat rs.yml
- hosts: backup
vars:
- user: www
- rsync_port: 873
- rs_dir: /backup
tasks:
- name: Install Rsync Server
yum:
name: rsync
state: present
- name: Configure Rsync Server
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
loop:
- { src: rsyncd.conf.j2, dest: /etc/rsyncd.conf,mode: '0644' }
- { src: rsync.passwd, dest: /etc/,mode: '0600' }
notify: Restart Rsync Server
- name: Create "{{ user }}" group
group:
name: "{{ user }}"
gid: 666
- name: Create "{{ user }}" user
user:
name: "{{ user }}"
uid: 666
group: "{{ user }}"
shell: /sbin/nologin
create_home: false
- name: Create "{{ rs_dir }}"
file:
path: "{{ rs_dir }}"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
- name: Start Rsync Server
systemd:
name: rsyncd
state: started
enabled: yes
handlers:
- name: Restart Rsync Server
systemd:
name: rsyncd
state: restarted
七、roles角色
一、roles 角色优点
- 复用性强:多个项目能共用同一角色配置相同服务,团队成员也可共享,减少重复工作。
- 结构清晰:按特定目录存放任务、变量等文件,逻辑分明,查找和修改文件轻松。
- 管理方便:可将复杂任务拆分成小任务块,不同角色按序执行,还能在不同场景复用、组合。
- 变量灵活:角色有独立变量,避免冲突,还能在调用时覆盖默认值,支持变量继承。
- 维护简单:需求变化时只改对应角色,不影响其他部分,且利于版本控制,方便回滚 。
总结:就是各个功能模块放到各个目录下。编辑自带的main.yml即可
二、Rsync 服务使用 roles 编排
1.1 创建 rsync 角色
使用 ansible-galaxy init rsync
命令初始化 rsync 角色。
[root@ansible roles]# ansible-galaxy init rsync
1.2 rsync 角色目录结构
- jinja2带变量的放到templates里面
[root@ansible rsync]# ll
total 0
drwxr-xr-x 2 root root 6 Jan 2 16:38 files
drwxr-xr-x 2 root root 22 Jan 2 16:38 handlers
drwxr-xr-x 2 root root 22 Jan 2 16:38 tasks
drwxr-xr-x 2 root root 6 Jan 2 16:38 templates
drwxr-xr-x 2 root root 22 Jan 2 16:38 vars
1.3 各文件内容
- tasks/main.yml:包含安装、配置、启动 Rsync 服务以及创建用户和目录等任务。
- name: Install Rsync Server
yum:
name: rsync
state: present
- name: Configure Rsync
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
loop:
- { src: rsyncd.conf.j2,dest: /etc/rsyncd.conf,mode: '0644' }
- { src: rsync.passwd,dest: /etc/,mode: '0600' }
notify: Restart Rsync Server
- name: Create "{{ user }}" group
group:
name: "{{ user }}"
gid: 666
- name: Create "{{ user }}" user
user:
name: "{{ user }}"
uid: 666
group: "{{ user }}"
shell: /sbin/nologin
create_home: false
- name: Create "{{ rs_dir }}"
file:
path: "{{ rs_dir }}"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
- name: Start Rsync Server
systemd:
name: rsyncd
state: started
enabled: yes
- vars/main.yml:定义了变量
user
、rsync_port
和rs_dir
。
user: www
rsync_port: 873
rs_dir: /backup
- handlers/main.yml:定义了重启 Rsync 服务的任务。
- name: Restart Rsync Server
systemd:
name: rsyncd
state: restarted
- templates/rsyncd.conf.j2:Rsync 服务的配置文件模板。
uid = {{ user }}
gid = {{ user }}
port = {{ rsync_port }}
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[backup]
path = {{ rs_dir }}
- templates/rsync.passwd:Rsync 认证密码文件。
rsync_backup:123456
三、NFS 服务使用 roles 重构
2.1 创建 nfs 角色目录
[root@ansible roles]# mkdir nfs
[root@ansible roles]# cd nfs/
[root@ansible nfs]# ls../rsync/
files handlers tasks templates vars
[root@ansible nfs]# ls../rsync/|xargs mkdir
2.2 nfs 角色目录结构
- 运行的.yml集合文件要和nfs目录在同一级
[root@ansible nfs]# tree nfs/
nfs/
├── files
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
│ └── exports.j2
└── vars
└── main.yml
2.3 各文件内容
- tasks/main.yml:包含安装、配置、启动 NFS 服务以及创建用户和目录等任务。
- name: Install nfs Server
yum:
name: nfs-utils
state: present
- name: Configure nfs Server
template:
src: exports.j2
dest: /etc/exports
notify: Restart nfs Server
- name: Create "{{ user }}" group
group:
name: "{{ user }}"
gid: 666
- name: Create "{{ user }}" user
user:
name: "{{ user }}"
uid: 666
group: "{{ user }}"
shell: /sbin/nologin
create_home: false
- name: Create "{{ nfs_dir }}"
file:
path: "{{ nfs_dir }}"
state: directory
owner: "{{ user }}"
group: "{{ user }}"
- name: Start nfs Server
systemd:
name: nfs
state: started
enabled: yes
- vars/main.yml:定义了变量
nfs_dir
、nfs_ip
和user
。
nfs_dir: /data/wp
nfs_ip: 172.16.1.0/24
user: www
- templates/exports.j2:NFS 服务的配置文件模板。
{{ nfs_dir }} {{ nfs_ip }}(rw,sync,all_squash,anonuid=666,anongid=666)
- handlers/main.yml:定义了重启 NFS 服务的任务。
- name: Restart nfs Server
systemd:
name: nfs
state: restarted
2.4 调用 roles
在 site.yml
文件中调用 rsync 和 nfs 角色。
- hosts: all
roles:
- role: rsync
when: ansible_hostname == "backup"
- role: nfs
when: ansible_hostname == "nfs"