惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
云风的 BLOG
云风的 BLOG
IT之家
IT之家
S
Secure Thoughts
U
Unit 42
G
GRAHAM CLULEY
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
The Cloudflare Blog
月光博客
月光博客
V
Visual Studio Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Schneier on Security
Schneier on Security
O
OpenAI News
Hacker News - Newest:
Hacker News - Newest: "LLM"
P
Privacy International News Feed
The Hacker News
The Hacker News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Tailwind CSS Blog
SecWiki News
SecWiki News
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Simon Willison's Weblog
Simon Willison's Weblog
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Docker
Scott Helme
Scott Helme
Engineering at Meta
Engineering at Meta
博客园_首页
W
WeLiveSecurity
MongoDB | Blog
MongoDB | Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Vulnerabilities – Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
J
Java Code Geeks
NISL@THU
NISL@THU
S
Security Affairs
C
Cybersecurity and Infrastructure Security Agency CISA
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

Yee's Blog

腾讯云/轻量云 安装ArchLinux的个人记录 记录我的联想M720Q Arch Sway窗口管理器的安装和配置过程 Jenkins Linux安装 腾讯课堂、钉钉在线网课视频直播回放下载离线播放 Ceph块设备对RBD块设备操作LVM创建PV时报错 Ceph映射RBD块设备 2020年9月26日前端部门Vue考核 2020年9月26日后端部门Python考核 Nginx反向代理下载传输超过1G大文件时断开问题 Windows Server 2019 Datacenter M720q 安装记录 Ceph块设备基础及快照、克隆操作 从Ceph集群中删除OSD节点 Centos8配置 chrony NTP服务端及客户端 搭建Ceph集群 Ceph硬件准备 OSD与Pool池的常见操作及管理 Ceph用户管理 MacOS睡眠管理——让你的Mac睡的更香 初中古诗文必背篇目 Ansible 技巧之场 Ansible 包含和导入文件 Ansible 学习文档 Ansible 主机模式 Ansible 角色 Ansible 调整连接数 Splunk数据搜索和报表 Ansible 变量和事实 Ansible 任务控制 Ansible Playbook Ansible 基础概念 42Team-Flask框架-HTTP协议快速了解 42Team-Flask框架-路由和视图 42Team-Flask框架-请求与响应 42Team-Flask框架 42Team-Flask框架-Flask介绍 42Team-Flask框架-使用Pycharm来构建一个全新的Flask项目 How to install RHEL8(Centos) on Dell R710/R610 server Centos8安装Docker报错解决方案 Centos8安装Docker后容器内无法访问网络 Docker或Podman容器内无法解析DNS问题多种解决方案 使用NetworkManager来管理树莓派Ubuntu系统网络以及个人的体验优化 Linux 存储设备的挂载及识别 Firewalld 防火墙常用指令教程-常用规则(禁止Ping | 放行端口) Linux 查找系统中的文件 Linux 守护进程和控制服务 Linux SSH远程访问 42Team小组_Linux基础培训课件 如何在AmazeUI中当改变select标签后触发Vue方法的问题 使用Docker部署安装WordPress博客平台 在Raspberry树莓派中搭建NFS存储服务器 在 树莓派 Linux 中搭建匿名 danted socks5 代理服务器 HTTP与HTTPS区别随笔 Bash/Shell学习笔记
Ansible 常用模块
本文作者: YeeFire · 2020-06-09 · via Yee's Blog

文件模块

Files文件模块库包含的模块可以对Linux文件进行管理,如创建、删除、编辑和修改文件的权限与属性等。

模块 说明
blockinfile 插入、更新或删除由可定义标记线包围的多行文本块
lineinfile 确保特定行位于某个文件中,或使用反向引用正则表达式来替换现有行。此模块可以在想要更改某一个行的文本时使用
copy 将文件从本地或远程计算机复制到目标主机的某个位置。类似于file模块,copy模块还可以设置文件属性,包括SELinux上下文
fetch 该模块和copy类似,但以相反的方式工作。fetch用来从目标主机获取文件到本机控制节点上
file 设置权限、所有权、SELinux上下文以及常规文件、符号链接、硬连接、目录时间戳等。此模块还可以创建或删除常规文件、符号链接、硬连接和目录。其他过个与文件相关的模块支持与file模块相同的属性设置选项,包括copy模块
stat 检索文件的状态信息,与Linux stat命令相似
synchronize 对rsync命令的打包

文件模块使用示例

确保目标主机上存在文件

- name: Touch a file and set permissions
file:
path: /home/student/touch.me
owner: student
group: root
mode: 0000
state: touch

如果目标主机已存在该文件,则会进行touch操作。上面的task除了确保文件存在以外,还会保证文件的权限为设定值。

  File: touch.me
Size: 14 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 163550 Links: 1
Access: (0000/----------) Uid: ( 1000/ student) Gid: ( 0/ root)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2020-06-02 17:11:40.642364330 -0400
Modify: 2020-06-02 17:11:40.642364330 -0400
Change: 2020-06-02 17:11:40.644530998 -0400
Birth: -
------------------------------
File: touch.me
Size: 14 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 163550 Links: 1
Access: (0000/----------) Uid: ( 1000/ student) Gid: ( 0/ root)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2020-06-02 17:18:59.746867300 -0400
Modify: 2020-06-02 17:18:59.746867300 -0400
Change: 2020-06-02 17:18:59.746867300 -0400
Birth: -

修改文件属性

使用file模块,确保新的或现有文件具有正确的文件属性和SELinux类型。

- name: SELinux type is set to samba_share_t
file:
path: /home/student/touch.me
setype: samba_share_t

修改前touch.me文件的setype属性是user_home_t,使用file模块处理后setype属性已经改变为samba_share_t

$ ls -lZ
----------. 1 student root unconfined_u:object_r:user_home_t:s0 14 Jun 2 17:18 touch.me
$ ls -lZ
----------. 1 student root unconfined_u:object_r:samba_share_t:s0 14 Jun 2 17:18 touch.me

永久更改SELinux文件上下文属性

设置上下文属性时,file模块的行为和chcon类似。通过运行restorecon可能会意外的撤销使用该模块对文件上下文所做的更改。当使用file设置上下文后,可以使用System模块集合中的sefcontext来更新SELinux策略,如semanage fcontext

- name: SELinux type is persistently set to samba_share_t
sefcontext:
target: /home/student/touch.me
setype: samba_share_t
state: present

可以看得到在SELinux上下文策略中目标的默认上下文已经更改为samba_share_t


/home/student/touch.me all files system_u:object_r:samba_share_t:s0

注意:sefcontext模块只更新SELinux策略中目标的默认上下文,并不更改当前现有文件的上下文。

在目标主机上复制和编辑文件

使用copy模块时,模块假定设置了force: yes。这会强制copy模块覆盖远程文件(如果存在并且包含于与当前要发送的文件内容不同)。如果手动设置force: no,则它仅会在目标主机不存在要复制的这个文件时才会进行复制。

- name: Copy a file to managed hosts
copy:
src: file
dest: /home/student/touch.me
force: yes

如果要从目标主机上拉取文件到本机,则使用fetch模块。

- name: Retrieve SSH key from reference host
fetch:
src: "/home/{{ user }}/.ssh/id_rsa.pub"
dest: "files/keys/{{ user }}.pub"

要确保现有文件中存在某行文本,可以使用lineinfile模块。

- name: Add a line of text to file
lineinfile:
path: /home/student/touch.me
line: "Can you touch me?"
state: present

如果要将文本块插入到文档中,应使用blockinfile模块。

- name: Add additional lines to a file
blockinfile:
path: /home/student/touch.me
block: |
This is the block of first line.
And
This is the block of third line.
state: present

使用blockinfile模块时,注释块标记插入到块的开头和结尾,用来让Ansible识别和保持幂等性。


This is the first line.

在目标主机上删除文件

在大多数情况下,如果控制目标主机文件的删除使用file模块的state: absent参数来控制。

- name: Removed file in the server
file:
dest: /home/student/touch.me
state: absent

检索文件的详细信息

使用stat模块可以查看文件的详细信息,并返回文件的事实。你可以利用这些Facts对文件进行检索和校验。stat模块类似于Linux系统中的stat命令。

- name: Check all stat of /etc/passwd
stat:
path: /etc/passwd
register: results

- debug:
vars: results

同步控制节点和受控节点之间的文件

使用synchronize模块来操作同步主机间的文件。synchronize对rsync工具进行打包,它简化了playbook中常见文件管理任务。使用该模块要求双方主机安装rsync工具。

- name: synchronize local file to server file
synchronize:
src: /etc
dest: /home/student/

使用Jinja2模版部署自定义文件

可以利用Jinja2模版语法通过和变量与事实相配合,对固定地方的值进行覆盖和编辑。来实现定制化修改配置文件。

使用`{% EXPR %}`用于表达式或逻辑(循环、判断)
使用`{{ EXPR }}`用于输出最终表达式或变量的结果
使用`{# COMMENT #}`注释,注释的内容不会出现在最终的结果里

构建Jinja2模版

Jinja2模版由多个元素组成:数据、变量和表达式。在呈现Jinja2模版时,这些变量和表达式被替换为对应的值。模版中使用的变量可以在playbook的vars部分中指定。可以将目标主机的事实作为模版中使用的变量。

可以使用ansible all -m setup来查看目标主机中全部的Fact事实。模版文件没有固定的文件拓展名,只要是文本文件即可,但是为了方便记忆理解,通常使用.j2来代表文本文件是Jinja2的模版文件。

部署Jinja2模板

我们刚刚创建好了Jinja2模版,现在要利用这些模版。我们需要使用template模块。src参数指的是模版文件在控制节点中的路径,dest的值是在目标主机的指定目录生成文件。

tasks:
- name: template render
template:
src: motd.j2
dest: /etc/motd
backup: true

template和file模块一样支持对文件权限进行设置。

标示配置文件由Ansible管理

我们使用模版生成文件后,为了避免管理员用户手动的修改这些配置文件,我们最好在模版的开头写上声明。虽然template不会自动地帮我们完成,但是我们可以在模版文件的开头手动引入设定好的提醒文本,使用Jinja2语法将变量的内容填写到配置文件中。

可以使用ansible_managed 指令中默认设置的 Ansible managed字符串来执行此操作。这不是一个正常的变量,但是可以在模版中用作一个变量。ansible_managed指令在ansible.cfg文件中的设置:

ansible_managed = Ansible managed: modified on %Y-%m-%d %H:%M:%S

要将在ansible.cfg文件中配置的ansible_managed字符串包含在Jinja2模版内,使用下面的引用变量语法即可。

{{ ansible_managed }}

通过模版生成的配置文件开头存在了Ansible managed: modified on 2020-06-10 15:55:29。这样就能对修改此文件的人有一个提示的作用。

控制结构

可以在Jinja2模版中使用控制结构,以减少重复的输入。为Play中每个主机能够动态的生成条目,或者有条件的将文本插入到文件中。

循环

Jinja2使用for语句来提供循环功能。

{% for user in users %}
{{ user }}
{% endfor %}

下面的示例模版使用for逐一遍历users变量中的所有值,将myuser替换为各个值,但值为root时除外。

{# for statement #}
{% for myuser in users if not myuser == "root" %}
User number is {{ loop.index }} - {{ myuser }}
{% endfor %}

loop.index变量是循环到当前处的索引号。他在循环第一次执行时的值为1,每一次迭代递增1。

下面的例子是生成hosts文件。

{% for host in groups['all'] %}
{{ hostvars[host]['ansible_facts']['default_ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['fqdn'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}
---
- name: generate hosts
hosts: all
tasks:
- name: generate template
template:
src: hosts.j2
dest: /home/student/hosts
...

条件语句

Jinja2使用if语句来提供条件控制。如果满足某些条件,则会按照语句块内的规则继续生成。

{% if finished %}
{{ result }}
{% endif %}

Jinja2仅能用于模版,不能用于Playbook。条件语句和循环语句可以相互嵌套。

变量过滤器

可以使用Jinja2提供的过滤器改变原有变量输出的格式,例如将字符串转换为JSON或YAML。

如果要转换为json格式时,使用to_json过滤器进行输出。

如果要转换为yaml格式时,使用to_yaml过滤器进行输出。

{{ output | to_json }}
{{ output | to_yaml }}

如果要使结构更适于人类阅读,可以使用下面的过滤器来输出人类可读格式。

{{ output | to_nice_json }}
{{ output | to_nice_yaml }}

变量测试

在Ansible Playbook中与when子句一同使用的表达式是Jinja2表达式。用于测试返回值的内置Ansible测试failed、changed、succeeded、skipped四种。

tasks:
.......
- debug:
msg: "The task was aborted"
when: returnvalue is faild

软件包管理

使用dnf的Ansible模块可以在受控主机上控制dnf软件包管理器。dnf是RHEL8使用的默认包管理器用于替代yum。不过也可以使用yum模块来对RHEL8进行操作。

下面示例中使用task任务来代替原有的dnf包管理器指令:

dnf install httpd -y

- name: Install the httpd packages
dnf:
name: httpd
state: present

state关键字有如下参数:

  • present 如果软件包不存在,则安装软件包
  • absent 如果已安装,则删除软件包
  • latest 如果软件包不是最新版本,则会对软件包进行更新。要是没有安装则会安装最新版本的软件包

name关键字有以下使用方式:

  • 直接填写某一个或以列表的形式填写多个软件包名称
  • 使用'*'配合latest可以进行更新系统全部软件包
  • 若要管理模块或组需要使用@符号

安装Development Tools软件组的示例:

- name: Install the Development Tools group
dnf:
name: ‘@Development Tools’
state: present

安装postgresql数据库模块:

- name: Install the postgresql module
dnf:
name: '@postgresql:9.6/client'
state: present

如果包管理器不是yum或者dnf。可以使用package模块替代yum/dnf模块。package模块可以自动检测并使用受控主机的包管理器去安装配置的软件包。

- name: Install httpd
package:
name: httpd
state: present

收集已安装的软件包信息

使用package_facts模块就能获取到受控主机中已经安装的软件包。它会将获取到的全部软件包信息存入ansible_facts.packages变量中。

使用package_facts模块并进行输出的示例:

---
- name: Output
hosts: prod
tasks:
- name: Check packages
package_facts:
manager: auto
- debug:
var: ansible_facts.packages.httpd

package_facts模块有两个选项:

  • manager 选择软件包管理器。默认auto自动识别
  • strategy 策略

返回prod主机组中已安装的httpd软件包信息。

ok: [serverc] => {
"ansible_facts.packages.httpd": [
{
"arch": "x86_64",
"epoch": null,
"name": "httpd",
"release": "10.module+el8+2764+7127e69e",
"source": "rpm",
"version": "2.4.37"
}
]
}
ok: [serverd] => {
"ansible_facts.packages.httpd": [
{
"arch": "x86_64",
"epoch": null,
"name": "httpd",
"release": "10.module+el8+2764+7127e69e",
"source": "rpm",
"version": "2.4.37"
}
]
}

配置yum仓库

添加yum仓库

使用yum_repository模块来控制第三方yum仓库。在添加仓库时即可配置GPG密钥。

---
- name: Create yum repo
hosts: prod
tasks:
- name: Create yum repo
yum_repository:
name: rpmforge
description: RPMforge YUM repo
file: test
gpgkey: http://materials.example.com/yum/repository/RPM-GPG-KEY-example
baseurl: http://materials.example.com/yum/repository/
enabled: yes
present: yes
gpgcheck: yes

可以直接使用gpgkey选项而不需要使用其他模块进行配置。

用户管理和身份认证

如何管理用户和用户组,以及配置ssh-key。

用户模块

使用user模块可以管理主机上的用户以及它们的许多参数。也可以删除用户、设置主目录、设置UID、关联的用户组等很多参数。

如果需要创建可以登录的计算机用户,需要使用password参数和password_hash('sha512')搭配生成Hash后的密码才可以登陆系统。

---
- name: Add user
hosts: dev
tasks:
- name: User modul
user:
name: natsumi
shell: /bin/bash
groups: wheel
append: yes
state: present
password: "{{ pwd | password_hash('sha512') }}"
vars:
pwd: test123

组模块

group模块可以管理受控主机中的用户组。

---
- name: Add group
hosts: dev
tasks:
- name: change group
group:
name: devuser
state: present

group模块参数: gid,local,name,state,system(如果设置为yes,则表示创建的组是系统组)

系统调度

at一次性任务

使用at模块来创建一个一次性任务。可以安排任务在未来的某一个时间点执行一次。

at模块参数:

参数 选项 说明
command - 计划要运行的命令
count - 单位数字。必须和units一同使用
script_file - 计划要执行的现有脚本文件
state absent/present 添加或删除命令或脚本的状态
unique yes/no 如果任务已在运行,则不会再次执行
units minutes/hours/days/weeks 时间单位

at模块使用示例:

---
- name: Using at make task
hosts: dev
tasks:
- name: create task
at:
command: "echo 'rick' > lala.txt"
count: 1
units: minutes
unique: yes

目前使用at模块总会在文件名末尾拼接上marcinDELIMITERxxxx字符串,经过Google发现这一串文本是用来在at pool中用来标示任务的。可是在这里为什么将他们输出了出来目前还不得而知。

cron计划任务

要完成重复性的任务,也可以使用cron模块来创建计划任务。

- name: Ensure a job that runs at 2 and 5 exists. Creates an entry like "0 5,2 * * ls -alh > /dev/null"
cron:
name: "check dirs"
minute: "0"
hour: "5,2"
job: "ls -alh > /dev/null"

想要在特殊时间点,比如系统重启后运行一个任务,可以使用special_time参数来配置cron计划任务。

- name: Ensure a job that runs at system reboot. Creates an entry like "@reboot ls -alh > /dev/null"
cron:
name: "check dirs"
special_time: reboot
job: "ls -alh > /dev/null"

reboot模块

使用reboot模块重新启动比直接用shell模块发起关机更安全,使用shell模块关闭受控主机后,它会等待再次开机恢复运行,才会继续向下执行其他任务和Play。

对受控主机重启后并持续等待180s。如果受控主机恢复运行则继续执行接下来的任务。

- name: Reboot a slow machine that might have lots of updates to apply
reboot:
reboot_timeout: 180

如果超出运行时间,则执行出错。接下来的task和play都不会继续执行。

fatal: [servera]: FAILED! => {"changed": false, "elapsed": 19, "msg": "Timed out waiting for last boot time check (timeout=18)", "rebooted": true}