linux一切皆文件,通过文件模块可以高效部署linux配置,服务等
1、 文件模块
ansible可以通过文件模块管理主机,通过command命令只能一次性改一台主机,但是使用文件模块可以批量修改大量主机
1.1 常用文件模块
模块名称 | 模块介绍 |
---|---|
blockinfile | 在文件上下添加注释 |
copy | 将本地文件复制到远程主机 |
fetch | 将受管节点数据拉取到本地 |
file | 创建、删除文件,设置文件权限、SELinux等信息 |
lineinfile | 编辑已存在的文件,可以通过正则匹配 |
stat | 查看文件信息 |
synchronize | 做文件同步相关操作 |
1.2 使用file模块
state | 说明 |
---|---|
state: touch | 指定类型为普通文件 |
state: directory | 指定类型为目录文件 |
state: link | 指定类型为连接文件 |
state:absent | 删除文件 |
1.2.1 创建一个文件
- name: 创建一个文件
file:
path: /etc/foo.conf
state: touch
1.2.2 创建一个目录文件
- name: 创建一个目录文件
file:
path: /etc/foo
state: directory
1.2.3 创建一个软链接
- name: 创建一个软链接
file:
src: /file/to/link/to
dest: /path/to/symlink
owner: foo
group: foo
state: link
1.2.4 创建一个硬链接
- name: 创建一个硬链接
file:
src: '/tmp/{{ item.src }}'
dest: '{{ item.dest }}'
state: link
with_items:
- { src: x, dest: y }
- { src: z, dest: k }
1.2.5 指定文件权限
- name: 指定文件权限
file:
path: /etc/some_directory
state: directory
mode: '0755'
1.2.6 设置文件SELinux
- name: 创建一个文件
file:
path: /etc/foo.conf
state: touch
setype: samba_share_t
1.2.7 删除一个文件
- name: 删除一个文件
file:
path: /etc/foo.conf
state: absent
1.2.7 file模块小练习
- 创建一个文件,权限0644
- 使用stat模块查看
[student@workstation control-review]$ cat mmx.yml
---
- name: 文件模块
hosts: all
tasks:
- name: 创建一个文件
file:
path: /root/mmx
state: touch
mode: 0644
[student@workstation control-review]$ ansible all -a 'ls -al /root/mmx'
serverb.lab.example.com | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 0 Aug 14 11:20 /root/mmx
1.3 修改文件属性
给文件增加安全上下文
- name: Allow apache to modify files in /srv/git_repos
sefcontext:
target: '/srv/git_repos(/.*)?'
setype: httpd_git_rw_content_t
state: present
可以使用force:yes,开启SELinux
1.4 从远端拉取文件
[student@workstation control-review]$ cat mmx01.yml
---
- name: 文件模块
hosts: all
tasks:
- name: 拉取文件
fetch:
src: /etc/fstab
dest: /home/student/control-review/
[student@workstation control-review]$ tree serverb.lab.example.com/
serverb.lab.example.com/
└── etc
└── fstab
1.5 修改文件内容
lineinfile是一个功能很强大的模块
1.5.1 linefile常用参数
参数 | 说明 |
---|---|
path | 文件路径 |
regexp | 通过正则匹配 |
line | 修改的行 |
owner | 所有者 |
group | 所属组 |
mode | 权限 |
create | 是否创建 |
state | 新增或删除 |
1.5.2 lineinfile添加一行内容
# 加入一行
[student@workstation control-review]$ cat mmx02.yml
---
- name: 文件模块
hosts: all
become: no
tasks:
- name: 修改文件内容
lineinfile:
path: ~/xiaoming.txt
line: 'hello mmx!'
state: present
[student@workstation control-review]$ ansible all -a 'cat xiaoming.txt'
serverb.lab.example.com | CHANGED | rc=0 >>
hello xiaoming
hello mmx!
1.6 添加注释
利用blockinfile加入注释,可以通过marker在文字上下加入必要说明
[student@workstation control-review]$ cat mmx03.yml
---
- name: 文件模块
hosts: all
become: no
tasks:
- name: 创建一个文件
file:
path: xiaobai.txt
state: touch
- name: 加入注释
blockinfile:
path: xiaobai.txt
block: |
Match User ansible-agent
PasswordAuthentication no
marker: "### hello world ###"
[student@workstation control-review]$ ansible all -a 'cat /home/devops/xiaobai.txt'
serverb.lab.example.com | CHANGED | rc=0 >>
### hello world ###
Match User ansible-agent
PasswordAuthentication no
### hello world ###
1.7 检查文件状态
[student@workstation control-review]$ cat mmx04.yml
---
- name: 检查文件状态
hosts: all
vars_files:
- vars/mmx.yml
tasks:
- name: use stat module
stat:
path: /etc/fstab
checksum_algorithm: "{{ stat }}"
register: result
- debug: msg='The checksum of the file is "{{ result.stat.checksum }}"'
[student@workstation control-review]$ ansible-playbook mmx04.yml
TASK [debug] ***********************************************************************************************************************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com] => {
"msg": "The checksum of the file is \"3b1d0d2a7e340e67cf2fe0fed228b5a0\""
}
1.8 同步文件
synchronize模块可以很好的同步文件,如果不满足需求的时候,可以使用命令rsync
- name: 同步文件
synchronize:
src: some/relative/path
dest: /some/absolute/path
1.9 文件模块练习
1.9.1 第一题
- 开启实验环境,进入目录,创建一个名为secure_log_backups.yml的play
- secure_log_backups.yml作用于所有主机组,提权到用户root
- 使用fetch模块拉取/var/log/secure目录文件到本地目录secure-backups
[student@workstation file-manage]$ cat secure_log_backups.yml
---
- name: 使用fetch模块
hosts: all
remote_user: root
tasks:
- name: 拉取/var/log/secure信息
fetch:
src: /var/log/secure
dest: secure-backups
falt: no
# 检查语法
[student@workstation file-manage]$ ansible-playbook --syntax-check secure_log_backups.yml
playbook: secure_log_backups.yml
# 执行playbook
[student@workstation file-manage]$ ansible-playbook secure_log_backups.yml
PLAY [使用fetch模块] ****************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]
TASK [拉取/var/log/secure信息] ******************************************************************************************************************************************************************************************************************************
changed: [serverb.lab.example.com]
changed: [servera.lab.example.com]
PLAY RECAP **********************************************************************************************************************************************************************************************************************************************
servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
serverb.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 查看拉取结果
[student@workstation file-manage]$ ls
ansible.cfg files inventory secure-backups secure_log_backups.yml
[student@workstation file-manage]$ tree secure-backups/
secure-backups/
├── servera.lab.example.com
│ └── var
│ └── log
│ └── secure
└── serverb.lab.example.com
└── var
└── log
└── secure
6 directories, 2 files
1.9.2 第二题
-
创建copy_file.yml的playbook文件,将本地文件复制到目标主机
-
copy模块参数如下
参数 值 src files/users.txt dest /home/devops/users.txt owner devops group devops mode u+rw,g-wx,o-rwx setype samba_share_t
[student@workstation file-manage]$ cat copy_file.yml
---
- name: use copy module
hosts: all
remote_user: root
tasks:
- name: copy filea and set attributes
copy:
src: files/users.txt
dest: /home/devops/users.txt
owner: devops
group: devops
mode: u+rw,g-wx,o-rwx
setype: samba_share_t
# 使用-Z参数可以查看安全上下文
[student@workstation file-manage]$ ansible all -a 'ls -Z users.txt' -u devops
serverb.lab.example.com | CHANGED | rc=0 >>
unconfined_u:object_r:samba_share_t:s0 users.txt
servera.lab.example.com | CHANGED | rc=0 >>
unconfined_u:object_r:samba_share_t:s0 users.txt
1.9.3 第三题
- 创建selinux_defaults.yml的playbook
- 创建文件users.txt,设置user、role、tpye、level均为_default
[student@workstation file-manage]$ cat selinux_defaults.yml
---
- name: set file selinux
hosts: all
remote_user: root
tasks:
- name: set selinux
file:
path: /home/devops/users.txt
seuser: _default
serole: _default
setype: _default
selevel: _default
# 使用ad hoc查看selinux
[student@workstation file-manage]$ ansible all -a 'ls -ldZ users.txt' -u devops
servera.lab.example.com | CHANGED | rc=0 >>
-rw-r-----. 1 devops devops unconfined_u:object_r:user_home_t:s0 0 Aug 14 16:23 users.txt
serverb.lab.example.com | CHANGED | rc=0 >>
-rw-r-----. 1 devops devops unconfined_u:object_r:user_home_t:s0 0 Aug 14 16:23 users.txt
1.9.4 第四题
- 创建add_line.yml的playbook
- 将"This line was added by the lineinfile module."添加到/home/devops/users.txt中
[student@workstation file-manage]$ cat add_line.yml
---
- name: 添加一段话
hosts: all
remote_user: root
tasks:
- name: 使用lineinfile添加一行
lineinfile:
path: /home/devops/users.txt
line: "This line was added by the lineinfile module."
[student@workstation file-manage]$ ansible all -a 'cat ~/users.txt' -u devops
servera.lab.example.com | CHANGED | rc=0 >>
This line was added by the lineinfile module.
serverb.lab.example.com | CHANGED | rc=0 >>
This line was added by the lineinfile module.
1.9.5 第五题
-
创建add_block.yml添加一个说明
-
在users.txt下添加:
- This block of the consists of two lines.
- They have been added by the blockinfile module
[student@workstation file-manage]$ cat add_block.yml
---
- name: 添加一个说明
hosts: all
remote_user: root
tasks:
- name: 使用blockinfile模块
blockinfile:
path: /home/devops/users.txt
block: |
This block of the consists of two lines
They have been added by the blockinfile module
[student@workstation file-manage]$ ansible all -a 'cat users.txt' -u devops
serverb.lab.example.com | CHANGED | rc=0 >>
This line was added by the lineinfile module.
# BEGIN ANSIBLE MANAGED BLOCK
This block of the consists of two lines
They have been added by the blockinfile module
# END ANSIBLE MANAGED BLOCK
servera.lab.example.com | CHANGED | rc=0 >>
This line was added by the lineinfile module.
# BEGIN ANSIBLE MANAGED BLOCK
This block of the consists of two lines
They have been added by the blockinfile module
# END ANSIBLE MANAGED BLOCK
1.9.6 第六题
- 创建一个remove_file.yml的文件
- 删除文件users.txt
[student@workstation file-manage]$ cat remove_file.yml
---
- name: 删除文件
hosts: all
remote_user: root
tasks:
- name: 删除users.txt的文件
file:
path: /home/devops/users.txt
state: absent
[student@workstation file-manage]$ ansible all -a 'ls -l' -u devops
serverb.lab.example.com | CHANGED | rc=0 >>
total 0
servera.lab.example.com | CHANGED | rc=0 >>
total 0
2、 JINJA2 模板
通过jinja2模板可以编写一个模板,当通过template模块调用此模板,可以灵活针对不同被管理主机,一起的配置文件都可以写成j2模板形式
2.1 使用模板文件
# 如果是循环or条件判断,开头{% EXPR %},结尾{{ EXPR }}
# 包裹变量{{ 变量 }}
# 注释{# XXX #}
{# /etc/hosts line #}
{{ ansible_facts['defaults_ipv4']['address'] }}
{{ ansible_facts['hostname'] }}
2.2 创建JINJA2模板
JINJA2模板文件的后缀.j2
- 可以使用ansible hostname -m setup查看fact变量,magic变量
- 可以使用自定义变量group_vars(存放主机组)和host_vars(存放主机)
[student@workstation file-manage]$ cat test.j2
hello , {{ inventory_hostname }} !
my ip : {{ ansible_default_ipv4['address'] }}
2.3 使用template模块调用JINJA2模板
[student@workstation file-manage]$ cat mmx.yml
---
- name: 使用jinja2模板文件
hosts: all
remote_user: root
tasks:
- name: 创建/root/mmx.txt文件
template:
src: test.j2
dest: /root/mmx.txt
[student@workstation file-manage]$ ansible all -a 'cat /root/mmx.txt' -u root
serverb.lab.example.com | CHANGED | rc=0 >>
hello , serverb.lab.example.com !
my ip : 172.25.250.11
servera.lab.example.com | CHANGED | rc=0 >>
hello , servera.lab.example.com !
my ip : 172.25.250.10
2.4 使用JINJA2循环
2.4.1 循环格式
# 格式:{% for 变量 in 变量组%}
# {{ 变量 }}
# {% endfor %}
[student@workstation file-manage]$ cat test.j2
hello , {{ inventory_hostname }} !
my ip : {{ ansible_default_ipv4['address'] }}
{% for name in home %}
家庭成员: {{ name }}
{% endfor %}
2.4.2 循环示例
[student@workstation file-manage]$ cat mmx.yml
---
- name: 使用jinja2模板文件
hosts: all
vars:
- home:
- xiaoming
- xiaohong
- xiaobai
- xiaoli
remote_user: root
tasks:
- name: 创建/root/mmx.txt文件
template:
src: test.j2
dest: /root/mmx.txt
[student@workstation file-manage]$ ansible all -a 'cat /root/mmx.txt' -u root
serverb.lab.example.com | CHANGED | rc=0 >>
hello , serverb.lab.example.com !
my ip : 172.25.250.11
家庭成员: xiaoming
家庭成员: xiaohong
家庭成员: xiaobai
家庭成员: xiaoli
servera.lab.example.com | CHANGED | rc=0 >>
hello , servera.lab.example.com !
my ip : 172.25.250.10
家庭成员: xiaoming
家庭成员: xiaohong
家庭成员: xiaobai
家庭成员: xiaoli
2.5 使用JINJA2用于判断
2.5.1 判断格式
# 使用if+endif开头结尾,中间是条件成立执行
# {% if 条件 %}
# {{ result}}
# {% endif %}
或
# {% if 条件 %}
# {{ result1 }}
# {% else %}
# {{ result2 }}
# {% endif %}
2.5.2 判断示例
# 4>3,所以一定执行第一个if判断,第二个不会执行
[student@workstation file-manage]$ cat test.j2
{% if 4>3 %}
4大于3
{% else %}
4小于3
{% endif %}
[student@workstation file-manage]$ ansible all -a 'cat /root/mmx.txt' -u root
serverb.lab.example.com | CHANGED | rc=0 >>
4大于3
2.6 变量过滤器
可以通过参数:filter过滤出json格式的变量
[student@workstation file-manage]$ ansible all -m setup -a 'filter="*fqdn*"'
serverb.lab.example.com | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "serverb.lab.example.com",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
servera.lab.example.com | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "servera.lab.example.com",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
2.7 JINJA2模板练习
2.7.1 题目说明
- 开启实验环境
- 创建一个inventory文件,文件包括
[webservers]
servera.lab.example.com
[workstations]
workstation.lab.example.com
- 创建一个motd.j2的文件
- 使用变量ansible_facts['fqdn'],描述主机完全限定域名
- 使用变量ansible_facts['distribution'],描述主机系统
- 使用变量ansible_facts['distribution_version'],描述系统版本
- 使用变量system_owner,描述系统所有者邮箱
- 创建一个motd.yml的文件,使用motd.j2模板,在所有节点设置/etc/motdd文件信息,所有者所属组均为root,权限0644
2.7.2 实验
1、 编辑模板文件
[student@workstation file-template]$ cat motd.j2
主机的FQDN: {{ ansible_facts['fqdn'] }}
主机系统: {{ ansible_facts['distribution'] }}
系统版本: {{ ansible_facts['distribution_version'] }}
系统所有者邮箱: {{ system_owner }}
2、 编辑playbook文件
[student@workstation file-template]$ cat motd.yml
---
- name: 配置SOE
hosts: all
remote_user: root
become: true
vars:
- system_owner: mmx@qq.com
tasks:
- name: 配置/etc/motd
template:
src: motd.j2
dest: /etc/motd
owner: root
group: root
mode: 0644
3、 执行
[student@workstation file-template]$ ansible-playbook motd.yml
PLAY [配置SOE] ********************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [workstation.lab.example.com]
TASK [配置/etc/motd] **************************************************************************************************************************************************************************************************************************************
changed: [servera.lab.example.com]
changed: [workstation.lab.example.com]
PLAY RECAP **********************************************************************************************************************************************************************************************************************************************
servera.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
workstation.lab.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4、 测试查看结果
登录显示系统信息,题目还是蛮有意思的哈!!!
[student@workstation file-template]$ ssh workstation
主机的FQDN: workstation.lab.example.com
主机系统: RedHat
系统版本: 8.0
系统所有者邮箱: mmx@qq.com
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Sun Aug 14 22:33:28 2022 from 172.25.250.9
[student@workstation ~]$ ssh servera
主机的FQDN: servera.lab.example.com
主机系统: RedHat
系统版本: 8.0
系统所有者邮箱: mmx@qq.com
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Sun Aug 14 22:33:28 2022 from 172.25.250.9
3、 综合实验
3.1 题目要求
- 开启实验
- 创建inventory文件,主机组:servers包括主机severb.lab.example.com
- 创建motd.j2文件,输出系统总内存和核心数
- 使用变量ansible_facts['memtotal_mb']统计系统总内存
- 使用变量ansible_processor_count统计系统处理器个数
- 创建motd.yml文件
- 使用motd.j2模板
- 所有者和所有组为root
- 权限为0644,输出到/etc/motd
- 使用stat和debug模块,检查 /etc/motd的状态并打印出相关信息
- 使用copy模块将files/issue放到受管节点/etc目录下,所有者和所有组均为root,权限为0644
- 使用file模块确定将/etc/issue.net链接到/etc/issue
- 远程连接用户为devops,需要提升权限
- 运行playbook,检查语法
- 判断成绩,结束实验
3.2 实验
3.2.1 开启实验
[student@workstation ~]$ lab file-review start
Setting up workstation for lab exercise work:
· The ansible package is installed on workstation............. SUCCESS
· Creating the working directory.............................. SUCCESS
· Downloading ansible.cfg..................................... SUCCESS
· Downloading inventory....................................... SUCCESS
· Downloading motd.j2......................................... SUCCESS
· Downloading issue........................................... SUCCESS
· Downloading motd.yml........................................ SUCCESS
· Changing permissions to the working directory............... SUCCESS
· Configuring sshd on serverb.lab.example.com................. SUCCESS
· Restarting sshd on serverb.lab.example.com.................. SUCCESS
· Backing up files on serverb.lab.example.com................. SUCCESS
[student@workstation ~]$ cd file-review/
[student@workstation file-review]$ cat ansible.cfg
[defaults]
inventory = inventory
ansible_managed = Ansible managed: modified on %Y-%m-%d %H:%M:%S
3.2.2 编辑inventory文件和motd.j2文件
[student@workstation file-review]$ cat inventory
[servers]
serverb.lab.example.com
[student@workstation file-review]$ cat motd.j2
总内存: {{ ansible_facts['memtotal_mb'] }}
核心数: {{ ansible_facts['pocessor_count'] }}
3.2.3 编辑playbook文件
[student@workstation file-review]$ cat motd.yml
---
- name: 综合实验
hosts: all
remote_user: devops
become: yes
tasks:
- name: 配置/etc/motd
template:
src: motd.j2
dest: /etc/motd
owner: root
group: root
mode: 0644
- name: 使用copy模块将files/issue放到/etc/issue
copy:
src: files/issue
dest: /etc/issue
owner: root
group: root
mode: '0644'
- name: 使用stat模块+debug检查文件
stat:
path: /etc/issue
register: issue_msg
- debug:
var: issue_msg
- name: 删除一个文件
file:
path: /etc/issue.net
state: absent
ignore_errors: yes
- name: 使用file模块做链接
file:
src: /etc/issue
dest: /etc/issue.net
state: link
3.2.4 运行playbook
[student@workstation file-review]$ ansible-playbook motd.yml
PLAY [综合实验] ********************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
TASK [配置/etc/motd] *************************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
TASK [使用copy模块将files/issue放到/etc/issue] ****************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
TASK [使用stat模块+debug检查文件] ******************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
TASK [debug] *******************************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com] => {
"issue_msg": {
"changed": false,
"failed": false,
"stat": {
"atime": 1660493389.059687,
"attr_flags": "",
"attributes": [],
"block_size": 4096,
"blocks": 8,
"charset": "us-ascii",
"checksum": "daa29e8adf76b04b6c747a9d5b87afaa88bcb3be",
"ctime": 1660493346.003687,
"dev": 64513,
"device_type": 0,
"executable": false,
"exists": true,
"gid": 0,
"gr_name": "root",
"inode": 4320643,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mimetype": "text/plain",
"mode": "0644",
"mtime": 1660493345.818687,
"nlink": 1,
"path": "/etc/issue",
"pw_name": "root",
"readable": true,
"rgrp": true,
"roth": true,
"rusr": true,
"size": 395,
"uid": 0,
"version": "1968508434",
"wgrp": false,
"woth": false,
"writeable": true,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
}
}
TASK [删除一个文件] ******************************************************************************************************************************************************************************************************************
changed: [serverb.lab.example.com]
TASK [使用file模块做链接] *************************************************************************************************************************************************************************************************************
changed: [serverb.lab.example.com]
PLAY RECAP *********************************************************************************************************************************************************************************************************************
serverb.lab.example.com : ok=7 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 测试实验结果
[student@workstation file-review]$ ssh serverb
*------------------------------- PRIVATE SYSTEM -----------------------------*
* Access to this computer system is restricted to authorised users only. *
* *
* Customer information is confidential and must not be disclosed. *
*----------------------------------------------------------------------------*
总内存: 821
核心数: 1
3.2.5 判断成绩
[student@workstation file-review]$ lab file-review grade
Grading the student's work on workstation:
· Ensuring Ansible inventory file is present.................. PASS
· Ensuring motd.j2 file is present............................ PASS
· Ensuring Ansible playbook is present........................ PASS
Grading the student's work on serverb.lab.example.com:
· Checking motd............................................... PASS
· Checking /etc/issue......................................... PASS
· Checking /etc/issue.net..................................... PASS
Overall lab grade.............................................. PASS
# 结束实验
[student@workstation file-review]$ lab file-review grade
Grading the student's work on workstation:
· Ensuring Ansible inventory file is present.................. PASS
· Ensuring motd.j2 file is present............................ PASS
· Ensuring Ansible playbook is present........................ PASS
Grading the student's work on serverb.lab.example.com:
· Checking motd............................................... PASS
· Checking /etc/issue......................................... PASS
· Checking /etc/issue.net..................................... PASS
Overall lab grade.............................................. PASS