Linux-Ansible学习手杂
Ansible 介绍
Ansible是一个配置管理和配置工具,使用SSH连接到服务器并运行配置好的任务,服务器上不需要安装任何其他软件,只需要开启SSH,客户端的ansible会完成所有其他的工作。
上图为ansible的基本架构,从上图可以了解到其由以下部分组成:
- 核心:ansible
- 核心模块(Core Modules):这些都是ansible自带的模块
- 扩展模块(Custom Modules):如果核心模块不足以完成某种功能,可以添加扩展模块
- 插件(Plugins):完成模块功能的补充
- 剧本(Playbooks):ansible的任务配置文件,将多个任务定义在剧本中,由ansible自动执行
- 连接插件(Connectior Plugins):ansible基于连接插件连接到各个主机上,虽然ansible是使用ssh连接到各个主机的,但是它还支持其他的连接方法,所以需要有连接插件
- 主机群(Host Inventory):定义ansible管理的主机
Ansible 部署
YUM方式安装
# debian & Ubuntu
sudo apt-get install ansible
# mac os
brew install ansible
# Centos
yum install ansible
# pip
sudo pip install ansible
Centos-安装信息:
# 添加Ansible源
cat <<EOF> /etc/yum.repos.d/tsinghua.repo
[ansible]
name=ansible
baseurl=https://mirror.tuna.tsinghua.edu.cn/epel/7/x86_64/
gpgcheck=0
EOF
# 安装Ansible
yum -y install ansible
正在安装:
ansible noarch 2.9.25-1.el7
为依赖而安装:
python-babel noarch 0.9.6-8.el7
python-jinja2 noarc2.7.2-4.el7
python-markupsafe x86_64 0.11-10.el7
python-paramiko noarch2.1.1-9.el7
python2-httplib2 noarch 0.18.1-3.el7
python2-jmespath noarch 0.9.4-2.el7
sshpass x86_64 1.06-2.el7
# 验证Ansible
ansible --version
源码方式安装
# 安装git客户端/gcc编译包
yum install git gcc-c++
# 拉取源码
git clone https://github.com/ansible/ansible.git /usr/local/ansible
# 执行安装文件
source /usr/local/ansible/hacking/env-setup
# 验证Ansible
ansible --version
安装好 Ansible 后,我们可以在 /etc/ansible/
的目录底下找到 Ansible 的一些配置文件.
公司通常把 ansible.cfg
和 hosts
这两个配置文件与其它的 Playbooks
放在同个目录下,然后通过git
把它们一起管理起来防止出现不必要的问题.
Ansible 配置文件介绍
目录结构介绍
通过如下命令我们可以获取Ansible所有文件存放目录:
# 查看ansible 安装目录结构
rpm -ql ansible
该命令输出内容较多, 大致分为如下几类:
描述 | 路径 |
---|---|
配置文件目录 | /etc/ansible/ |
执行文件目录 | /usr/bin/ |
Lib库依赖目录 | /usr/lib/pythonX.X/site-packages/ansible/ |
Help 文档目录 | /usr/share/doc/ansible-X.X.X/ |
Man文档目录 | /usr/share/man/manl/ |
Ansible配置文件解析(ansible.cfg)
Inventory
用于定义 Ansible 的主机列表配置, Ansible 的自身配置文件只有一个, 即ansible.cfg
, Ansible 安装好后它默认存放于/etc/ansible/ 目录下。
ansible.cfg
配置文件可以存在于多个地方, Ansible 读取配置文件的顺序依次是当前命令执行目录→用户家目录下的。ansible.cfg→ /etc/ansible.cfg, 先找到哪个就使用哪个的配置。其 ansible.cfg 配置的所有内容均可在命令行通过参数的形式传递或定义在 Playbooks 中。目前ansible 配置文件有四种,如下显示:
- 使用/etc/ansible/ansible.cfg
ansible 软件包提供一个基本的配置文件,它位于/etc/ansible/ansible.cfg
如果找不到其他配置文件,则使用此文件。
- 使用~/ansible.cfg
Ansible 在用户的主目录中查找 .ansible.cfg
文件。如果存在此配萱并且当前工作目录中也没有ansible.cfg
文件,则使用此配置取代/etc/ansible/ansible.cfg
。
- 使用./ansible.cfg
如果执行ansible 命令的目录中存在ansible.cfg 文件,则使用它,而不使用全局文件或用户的个入文件。这样,管理员可以创建一种目录结构,将不同的环境或项目存储在单独的目录中,并且每一目录包含为独特的一组设置而定制的配置文件。
- 使用ANSIBLE_CONFIG 环境变量
通过ANSIBLE_CONFIG 环境变量定义配萱文件的位置。定义了此变量时,Ansible 将使用变 量所指定的配置文件,而不用上文中提及的任何配置文件。
- 这四种文件的优先级为
ANSIBLE_CONFIG环境变量 > ./ansible.cfg > ~/ansible.cfg > /etc/ansible/ansible.cfg
配置文件 ansible.cfg 约有 500 行语句, 大多数为注释行默认配置项。 该文件遵循 INI 格 式, 主要常修改配置如下:
inventory = /etc/ansible/hosts # 定义的inventory文件
library = /usr/share/my_modules/ # 自定义lib库存放目录
forks = 5 # 默认并发数
poll_interval = 15 # 默认轮询时间间隔
sudo_user = root # 默认sudo用户
remote_port = 22 # 默认远程ssh 端口
host_key_checking = False #第一次交互目标主机,需要输入yes/no,改成False不用输入
timeout = 10 # 设置SSH连接的超时时间,单位为秒
log_path = /var/log/ansible.log #设置日志路径
Ansible 管理主机配置文件解析(Inventory)
Inventory 是 Ansible 管理主机信息的配置文件,相当于系统 HOSTS 文件的功能,默认存放在/etc/ansible/hosts。为方便批量管理主机,便捷使用其中的主机分组.
内置变量清单
主机连接配置
ansible_connection
:与主机的连接类型。可以是ansible的连接插件的名称。SSH协议类型为smart、ssh或paramiko。默认值是smart。
所有连接配置
ansible_host
:要连接到远程主机的名称。
ansible_port
:要连接到远程主机的端口,默认为22。
ansible_user
:连接到远程主机的用户名。
ansible_password
:连接到远程主机的用户名密码。
SSH连接配置
ansible_ssh_private_key_file
:ssh使用的私有文件,适用于有多个秘钥,但不想使用ssh agent情况。
ansible_ssh_common_args
:该设置附加到默认的sftp、scp和ssh命令行上。
ansible_sftp_extra_args
:该设置总是附加到默认的sftp命令行上。
ansible_scp_extra_args
:该设置总是附加到默认的scp命令行上。
ansible_ssh_extra_args
:该设置总是附加到默认的ssh命令行上。
ansible_ssh_pipelining
:确定是否使用SSH pipelining,该参数会覆盖ansible.cfg中的pipelining设置。
ansible_ssh_executable
:此设置会覆盖使用系统ssh的默认行为,会覆盖ansible.cfg中的ssh_executable参数。
如果只有一个 Inventory 时可不用指定路径,默认读取/etc/ansible/hosts
,Inventory 可以同时存在多个.
参考示例:
## 直接指明主机地址或主机名:
192.168.1.88
192.168.1.34
192.168.1.33
## 定义一个主机组[组名]把地址或主机名加进去
[docker]
192.168.1.88
## 192.168.1.33,192.168.1.34
192.168.1.3[3:4]
[docker:vars]
## 加上这个就不用输入密码,也不用密钥,但是真心不建议密码明文写在这里
ansible_password='密码'
## 端口
ansible_port=22
## 可设置登录用户
ansible_user='test'
[ansible:children]
docker
Ansible 通过Inventory 来定义其主机和组,在使用时通过-i 或 --inventory-file 指定读取,与 Ansible 命令结合使用时组合如下:
ansible -i /etc/ansible/hosts docker -m ping
Ansible 常用命令
Ansible 命令集
/usr/bin/ansible # Ansibe AD-Hoc 临时命令执行工具,常用于临时命令的执行
/usr/bin/ansible-doc # Ansible 模块功能查看工具
/usr/bin/ansible-galaxy # 下载/上传优秀代码或Roles模块 的官网平台,基于网络的
/usr/bin/ansible-playbook # Ansible 定制自动化的任务集编排工具
/usr/bin/ansible-pull # Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)
/usr/bin/ansible-vault # Ansible 文件加密工具
/usr/bin/ansible-console # Ansible基于Linux Consoble界面可与用户交互的命令执行工具
其中,我们比较常用的是/usr/bin/ansible
和/usr/bin/ansible-playbook
Ansible 命令详解
命令的具体格式如下:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
也可以通过ansible -h
来查看帮助,下面我们列出一些比较常用的选项,并解释其含义:
-a MODULE_ARGS
#模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等
-k
,--ask-pass
#ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证
--ask-su-pass
#ask for su password。su切换密码
-K
,--ask-sudo-pass
#ask for sudo password。提示密码使用sudo,sudo表示提权操作
--ask-vault-pass
#ask for vault password。假设我们设定了加密的密码,则用该选项进行访问
-B SECONDS
#后台运行超时时间
-C
#模拟运行环境并进行预运行,可以进行查错测试
-c CONNECTION
#连接类型使用
-f FORKS
#并行任务数,默认为5
-i INVENTORY
#指定主机清单的路径,默认为/etc/ansible/hosts
--list-hosts
#查看有哪些主机组
-m MODULE_NAME
#执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
-o
#压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用
-S
#用 su 命令
-R SU_USER
#指定 su 的用户,默认为 root 用户
-s
#用 sudo 命令
-U SUDO_USER
#指定 sudo 到哪个用户,默认为 root 用户
-T TIMEOUT
#指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改
-u REMOTE_USER
#远程用户,默认为 root 用户
-v
#查看详细信息,同时支持-vvv
,-vvvv
可查看更详细信息
Ansible 配置公私钥
上面我们已经提到过 ansible 是基于 ssh 协议实现的,所以其配置公私钥的方式与 ssh 协议的方式相同,具体操作步骤如下:
ssh-keygen -t rsa
ssh-copy-id root@192.168.1.88
ssh-copy-id root@192.168.1.33
ssh-copy-id root@192.168.1.34
Ansible 常用模块
1. 主机连通性测试(ping模块)
我们使用ansible docker -m ping
命令来进行主机连通性测试,效果如下:
[root@app31 .ssh]# ansible docker -m ping
192.168.1.34 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.33 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.88 | SUCCESS => {
"changed": false,
"ping": "pong"
}
这样就说明我们的主机是连通状态的
2. command 模块
这个模块可以直接在远程主机上执行命令,并将结果返回本主机。如:ansible docker -m command -a 'df -h'
# 查询磁盘
[root@app31 .ssh]# ansible docker -m command -a 'df -h'
192.168.1.34 | SUCCESS | rc=0 >>
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 50G 6.0G 45G 12% /
devtmpfs 16G 0 16G 0% /dev
192.168.1.33 | SUCCESS | rc=0 >>
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 50G 13G 38G 25% /
devtmpfs 16G 0 16G 0% /dev
192.168.1.88 | SUCCESS | rc=0 >>
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 48G 0 48G 0% /dev
tmpfs 48G 0 48G 0% /dev/shm
# #先切换到/data/ 目录在ls查看信息
[root@app31 .ssh]# ansible docker -m command -a 'chdir=/data ls'
192.168.1.34 | SUCCESS | rc=0 >>
es
mysql
192.168.1.88 | SUCCESS | rc=0 >>
20210415
yarn
192.168.1.33 | SUCCESS | rc=0 >>
命令模块接受命令名称,后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理,比如$HOME和操作如"<",">","|",";","&" 工作(需要使用(shell)模块实现这些功能)。
注意,该命令不支持
| 管道命令
。
3. shell 模块
shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等。如:ansible docker -m shell -a 'cat /etc/passwd | grep root'
[root@app31 home]# ansible docker -m shell -a 'cat /etc/passwd | grep root'
192.168.1.34 | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.1.88 | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.1.33 | SUCCESS | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@app31 home]# ansible docker -m shell -a 'echo $USER'
192.168.1.34 | SUCCESS | rc=0 >>
root
192.168.1.88 | SUCCESS | rc=0 >>
root
192.168.1.33 | SUCCESS | rc=0 >>
root
只要是我们的shell命令,都可以通过这个模块在远程主机上运行.
4. copy 模块
这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。其相关选项如下:
src # 被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于"rsync"
content # 当不使用src指定拷贝的文件时,可以使用content直接指定文件内容,src与content两个参数必有其一,否则会报错
dest # 必选项,将源文件复制到的远程主机的绝对路径
backup=yes # 表示将受控主机存在文件时,将源文件备份
mode # 递归设定目录的权限,默认为系统默认权限,如果你想将权限设置为”rw-r--r--“,则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示
owner # 指定目的地文件所有人
group # 指定目的地文件所有组
force # 当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;设为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"
4.1 复制文件:
[root@app31 home]# ansible docker -m copy -a 'src=/home/test2.sh dest=/data/'
192.168.1.34 | SUCCESS => {
"changed": true,
"checksum": "b4f51832b152e08b304b1c682ba05adece71c045",
"dest": "/data/test2.sh",
"gid": 0,
"group": "root",
"md5sum": "ffc3725f409617864c817447685a4eda",
"mode": "0644",
"owner": "root",
"size": 15,
"src": "/root/.ansible/tmp/ansible-tmp-1638782767.44-93562767670664/source",
"state": "file",
"uid": 0
}
192.168.1.88 | SUCCESS => {
"changed": true,
"checksum": "b4f51832b152e08b304b1c682ba05adece71c045",
"dest": "/data/test2.sh",
"gid": 0,
"group": "root",
"md5sum": "ffc3725f409617864c817447685a4eda",
"mode": "0644",
"owner": "root",
"size": 15,
"src": "/root/.ansible/tmp/ansible-tmp-1638782767.43-213537548213422/source",
"state": "file",
"uid": 0
}
192.168.1.33 | SUCCESS => {
"changed": true,
"checksum": "b4f51832b152e08b304b1c682ba05adece71c045",
"dest": "/data/test2.sh",
"gid": 0,
"group": "root",
"md5sum": "ffc3725f409617864c817447685a4eda",
"mode": "0644",
"owner": "root",
"size": 15,
"src": "/root/.ansible/tmp/ansible-tmp-1638782767.44-117162678116772/source",
"state": "file",
"uid": 0
}
4.2.给定内容生成文件,并赋予权限:
[root@app31 home]# ansible docker -m copy -a 'content="this is test" dest=/data/test.txt mode=755'
192.168.1.34 | SUCCESS => {
"changed": true,
"checksum": "b6794b2000d94d348203d0279c2e7322b922cb16",
"dest": "/data/test.txt",
"gid": 0,
"group": "root",
"md5sum": "8c6d115258631625b625486f81b09532",
"mode": "0755",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1638783198.51-187666865731240/source",
"state": "file",
"uid": 0
}
192.168.1.88 | SUCCESS => {
"changed": true,
"checksum": "b6794b2000d94d348203d0279c2e7322b922cb16",
"dest": "/data/test.txt",
"gid": 0,
"group": "root",
"md5sum": "8c6d115258631625b625486f81b09532",
"mode": "0755",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1638783198.5-100956289999740/source",
"state": "file",
"uid": 0
}
192.168.1.33 | SUCCESS => {
"changed": true,
"checksum": "b6794b2000d94d348203d0279c2e7322b922cb16",
"dest": "/data/test.txt",
"gid": 0,
"group": "root",
"md5sum": "8c6d115258631625b625486f81b09532",
"mode": "0755",
"owner": "root",
"size": 12,
"src": "/root/.ansible/tmp/ansible-tmp-1638783198.5-15493567640531/source",
"state": "file",
"uid": 0
}
4.3. 文件存在,覆盖备份
[root@app31 home]# ansible docker -m copy -a 'content="this is test2" dest=/data/test.txt mode=755 backup=yes'
192.168.1.34 | SUCCESS => {
"backup_file": "/data/test.txt.32304.2021-12-06@17:35:41~",
"changed": true,
"checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"dest": "/data/test.txt",
"gid": 0,
"group": "root",
"md5sum": "fc30b9256da0d4d40c2e6ad176dd835a",
"mode": "0755",
"owner": "root",
"size": 13,
"src": "/root/.ansible/tmp/ansible-tmp-1638783339.75-149812909314543/source",
"state": "file",
"uid": 0
}
192.168.1.33 | SUCCESS => {
"backup_file": "/data/test.txt.31756.2021-12-06@17:35:42~",
"changed": true,
"checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"dest": "/data/test.txt",
"gid": 0,
"group": "root",
"md5sum": "fc30b9256da0d4d40c2e6ad176dd835a",
"mode": "0755",
"owner": "root",
"size": 13,
"src": "/root/.ansible/tmp/ansible-tmp-1638783339.75-5933564884918/source",
"state": "file",
"uid": 0
}
192.168.1.88 | SUCCESS => {
"backup_file": "/data/test.txt.20905.2021-12-06@17:35:42~",
"changed": true,
"checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"dest": "/data/test.txt",
"gid": 0,
"group": "root",
"md5sum": "fc30b9256da0d4d40c2e6ad176dd835a",
"mode": "0755",
"owner": "root",
"size": 13,
"src": "/root/.ansible/tmp/ansible-tmp-1638783339.74-85375342208580/source",
"state": "file",
"uid": 0
}
5. file 模块
该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。下面是一些常见的命令:
force # 需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
dest # 被链接到的路径,只应用于state=link的情况
group # 定义文件/目录的属组。后面可以加上mode:定义文件/目录的权限 默认为root
owner # 定义文件/目录的属主。后面必须跟上path:定义文件/目录的路径 默认为root
recurse# 递归设置文件的属性,只对目录有效,后面跟上src:被链接的源文件路径,只应用于state=link的情况
mode # 文件复制到远程并设定权限,默认file=644,directory=755
path # 指定远程服务器的路径,也可以写成‘dest’,‘name’
state # 状态,有以下选项:
directory # 如果目录不存在,就创建目录
file # 即使文件不存在,也不会被创建
link # 创建软链接
hard # 创建硬链接
touch# 如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent#删除目录、文件或者取消链接文件
5.1. 创建一个文件并且赋值
[root@app31 data]# ansible docker -m file -a 'path=/data/test_file.txt owner=root group=root mode=755 state=touch'
192.168.1.34 | SUCCESS => {
"changed": true,
"dest": "/data/test_file.txt",
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"size": 0,
"state": "file",
"uid": 0
}
192.168.1.33 | SUCCESS => {
"changed": true,
"dest": "/data/test_file.txt",
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"size": 0,
"state": "file",
"uid": 0
}
192.168.1.88 | SUCCESS => {
"changed": true,
"dest": "/data/test_file.txt",
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"size": 0,
"state": "file",
"uid": 0
}
5.2. 创建目录
[root@app31 data]# ansible docker -m file -a 'path=/data/test_file_dir state=directory'
192.168.1.34 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/test_file_dir",
"size": 6,
"state": "directory",
"uid": 0
}
192.168.1.88 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/test_file_dir",
"size": 6,
"state": "directory",
"uid": 0
}
192.168.1.33 | SUCCESS => {
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/test_file_dir",
"size": 6,
"state": "directory",
"uid": 0
}
5.3. 创建软链
[root@app31 data]# ansible docker -m file -a 'src=/data/test2.sh dest=/data/test2.sh.link state=link'
192.168.1.34 | SUCCESS => {
"changed": true,
"dest": "/data/test2.sh.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 14,
"src": "/data/test2.sh",
"state": "link",
"uid": 0
}
192.168.1.88 | SUCCESS => {
"changed": true,
"dest": "/data/test2.sh.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 14,
"src": "/data/test2.sh",
"state": "link",
"uid": 0
}
192.168.1.33 | SUCCESS => {
"changed": true,
"dest": "/data/test2.sh.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 14,
"src": "/data/test2.sh",
"state": "link",
"uid": 0
}
5.4.删除目录和文件:
[root@app31 data]# ansible docker -m file -a 'path=/data/test2.sh.link state=absent'
192.168.1.34 | SUCCESS => {
"changed": true,
"path": "/data/test2.sh.link",
"state": "absent"
}
192.168.1.33 | SUCCESS => {
"changed": true,
"path": "/data/test2.sh.link",
"state": "absent"
}
192.168.1.88 | SUCCESS => {
"changed": true,
"path": "/data/test2.sh.link",
"state": "absent"
}
[root@app31 data]# ansible docker -m file -a 'path=/data/test2.sh state=absent'
[root@app31 data]# ansible docker -m file -a 'path=/data/test_file_dir state=absent'
6. fetch 模块
该模块用于从远程某主机获取(复制)文件到本地。
src # 复制的源文件路径,源文件只能是文件
dest#目标绝对路径
6.1. 远程复制文件
把被控主机/data/test.txt
复制到ansible主机/tmp
目录下
[root@app31 tmp]# ansible docker -m fetch -a 'src=/data/test.txt dest=/tmp'
192.168.1.34 | SUCCESS => {
"changed": true,
"checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"dest": "/tmp/192.168.1.34/data/test.txt",
"md5sum": "fc30b9256da0d4d40c2e6ad176dd835a",
"remote_checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"remote_md5sum": null
}
192.168.1.33 | SUCCESS => {
"changed": true,
"checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"dest": "/tmp/192.168.1.33/data/test.txt",
"md5sum": "fc30b9256da0d4d40c2e6ad176dd835a",
"remote_checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"remote_md5sum": null
}
192.168.1.88 | SUCCESS => {
"changed": true,
"checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"dest": "/tmp/192.168.1.88/data/test.txt",
"md5sum": "fc30b9256da0d4d40c2e6ad176dd835a",
"remote_checksum": "ef6ea4aa3e5d645f0138cbce096dd551a26dad5d",
"remote_md5sum": null
}
[root@app31 tmp]# tree
.
├── 192.168.1.33
│ └── data
│ └── test.txt
├── 192.168.1.34
│ └── data
│ └── test.txt
├── 192.168.1.88
│ └── data
│ └── test.txt
6.2. 拷贝远程主机的目录到本机
#1.首先需要把远程主机的目录打包,默认打包到远程主机的家目录下(/root)
[root@tmp ~]# ansible docker -m shell -a 'tar -czvf log.tar /var/log/nginx/access*'
#2.把打包文件取回本机:
[root@tmp ~]# ansible docker -m fetch -a 'src=/root/log.tar dest=/root/nginx'
7. cron 模块
功能:管理被控端计划任务;
主要参数如下:
name #定时任务基本描述
job #定时任务要执行的命令
minute #分
hour #小时
day #日
month #月
weekday #周,0-6
disabled #yes:禁用计划任务,no:启用计划任务,
state #absent: 删除计划任务
7.1 创建时间同步定时任务
[root@app31 home]# ansible docker -m cron -a 'name="synctime" job="ntpq -p> /dev/null" minute=*/10'
192.168.1.34 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"synctime"
]
}
192.168.1.33 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"synctime"
]
}
192.168.1.88 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"synctime"
]
}
7.2 取消时间同步定时任务
[root@app31 home]# ansible docker -m cron -a 'name="synctime" job="ntpq -p> /dev/null" minute=*/10 disabled=yes'
192.168.1.34 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"synctime"
]
}
192.168.1.33 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"synctime"
]
}
192.168.1.88 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": [
"synctime"
]
}
7.3 删除时间同步定时任务
[root@app31 home]# ansible docker -m cron -a 'name="synctime" job="ntpq -p> /dev/null" minute=*/10 state=absent'
192.168.1.34 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": []
}
192.168.1.33 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": []
}
192.168.1.88 | SUCCESS => {
"changed": true,
"envs": [],
"jobs": []
}
8.yum 模块
管理软件包,需要确认被管理端为红帽系列的,并且需要被管理端配置好yum源。主要的参数如下:
name # 指定安装软件包名或软件包URL
state # 指定yum对应的方法,present(Defaults)表示安装;absent表示卸载;latest表示安装最新版本软件包,支持多程序一起安装,用逗号隔开
enablerepo # 允许从哪些仓库获取软件
disablerepo # 禁止从哪些仓库获取软件
exclude # 排除某些软件包,例如kernel
download_only # 仅下载软件包,不安装
disable_gpg_check # 不进行gpg检测
update_cache # 可以在安装包的同时更新yum缓存
安装一个httpd
包
[root@app31 ansible]# ansible 192.168.1.88 -m yum -a 'name=httpd state=present'
192.168.1.88 | SUCCESS => {
"changed": true,
"msg": "http://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\nhttp://mirror.centos.org/centos/7/dotnet/x86_64/repodata/repomd.xml: [Errno 14] curl#7 - \"Failed to connect to 2604:1380:3000:2800::1: Network is unreachable\"\nTrying other mirror.\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror, langpacks\nLoading mirror speeds from cached hostfile\n * base: mirrors.tuna.tsinghua.edu.cn\n * centos-sclo-rh: mirrors.tuna.tsinghua.edu.cn\n * centos-sclo-sclo: mirrors.tuna.tsinghua.edu.cn\n * epel: mirrors.tuna.tsinghua.edu.cn\n * extras: mirrors.tuna.tsinghua.edu.cn\n * updates: mirrors.tuna.tsinghua.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-97.el7.centos.2 will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-97.el7.centos.2 for package: httpd-2.4.6-97.el7.centos.2.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-97.el7.centos.2.x86_64\n--> Running transaction check\n---> Package httpd-tools.x86_64 0:2.4.6-97.el7.centos.2 will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n httpd x86_64 2.4.6-97.el7.centos.2 updates 2.7 M\nInstalling for dependencies:\n httpd-tools x86_64 2.4.6-97.el7.centos.2 updates 94 k\n mailcap noarch 2.1.41-2.el7 base 31 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package (+2 Dependent packages)\n\nTotal download size: 2.8 M\nInstalled size: 9.6 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal 6.5 MB/s | 2.8 MB 00:00 \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : httpd-tools-2.4.6-97.el7.centos.2.x86_64 1/3 \n Installing : mailcap-2.1.41-2.el7.noarch 2/3 \n Installing : httpd-2.4.6-97.el7.centos.2.x86_64 3/3 \n Verifying : httpd-2.4.6-97.el7.centos.2.x86_64 1/3 \n Verifying : mailcap-2.1.41-2.el7.noarch 2/3 \n Verifying : httpd-tools-2.4.6-97.el7.centos.2.x86_64 3/3 \n\nInstalled:\n httpd.x86_64 0:2.4.6-97.el7.centos.2 \n\nDependency Installed:\n httpd-tools.x86_64 0:2.4.6-97.el7.centos.2 mailcap.noarch 0:2.1.41-2.el7 \n\nComplete!\n"
]
}
卸载apache
软件包
[root@app31 ansible]# ansible 192.168.1.88 -m yum -a 'name=httpd state=absent'
192.168.1.88 | SUCCESS => {
"changed": true,
"msg": "",
"rc": 0,
"results": [
"已加载插件:fastestmirror, langpacks\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-97.el7.centos.2 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package 架构 版本 源 大小\n================================================================================\n正在删除:\n httpd x86_64 2.4.6-97.el7.centos.2 @updates 9.4 M\n\n事务概要\n================================================================================\n移除 1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n 正在删除 : httpd-2.4.6-97.el7.centos.2.x86_64 1/1 \n 验证中 : httpd-2.4.6-97.el7.centos.2.x86_64 1/1 \n\n删除:\n httpd.x86_64 0:2.4.6-97.el7.centos.2 \n\n完毕!\n"
]
}
9. systemd 模块 or systemd模块
该模块用于服务程序的管理。
name # 指定需要控制的服务名称
state # 指定服务状态,其值可以为stopped、started、reloaded、restarted、running
enabled # 指定服务是否为开机启动,yes为启动,no为不启动
daemon_reload # yes:重启systemd服务,让unit文件生效 systemd才有
启动nginx
服务,并设置为开机自启:
ansible 192.168.1.88 -m service -a 'name=nginx state=started enabled=yes'
ansible 192.168.1.88 -m systemd -a 'name=nginx state=started enabled=yes'
10. ansible user 模块 和 group 模块
group模块
管理被控端用户组
name # 指定创建的组名
gid # 为组设置gid
state # 是否将组创建在远程主机上,创建:present(Default)、删除:absent
system # 是否创建系统组,创建系统组:yes、不创建系统组:no(Default)
创建组tester
,gid
为8888
:
[root@app31 ~]# ansible 192.168.1.88 -m group -a 'name=tester state=present gid=8888'
192.168.1.88 | SUCCESS => {
"changed": true,
"gid": 8888,
"name": "tester",
"state": "present",
"system": false
}
[root@sdw88 ~]# getent group tester
tester:x:8888:
删除组tester
:
[root@app31 ~]# ansible 192.168.1.88 -m group -a 'name=tester state=absent'
192.168.1.88 | SUCCESS => {
"changed": true,
"name": "tester",
"state": "absent"
}
user模块
管理被控端用户
name # 创建或删除的用户名
uid # 为用户设置uid
group # 设置用户的主组
groups # 设置用户的附加组
shell # 为用户设置登陆时的Shell
create_home # 是否为用户创建主目录,yes(Default)、no
state # 创建或删除用户,创建:present(Default)、删除:absent
remove # 是否删除与用户关联的目录,例如家目录和邮箱目录,只有当state=absent 时生效,删除:yes、不删除:no(Default)
system #是否添加为系统用户,yes:为系统用户,no:不是系统用户
generate_ssh_key # 为相关用户生成ssh密钥。不会覆盖现有的ssh密钥
ssh_key_bits # 创建用户ssh密钥中位数
ssh_key_file # 可以实现ssh密钥改名,或变更存放ssh密钥位置,默认为.ssh/id_rsa
append # yes:表示追加附加组
添加一个系统用户,用户名为test1
,uid=2222
,创建家目录,主组为root
,附加组为bin
,默认shell
为nologin
[root@app31 ~]# ansible 192.168.1.88 -m user -a 'name=test1 uid=2222 group=root groups=bin shell=/sbin/nologin system=yes home=/home/test1'
192.168.1.88 | SUCCESS => {
"changed": true,
"comment": "",
"createhome": true,
"group": 0,
"groups": "bin",
"home": "/home/test1",
"name": "test1",
"shell": "/sbin/nologin",
"state": "present",
"system": true,
"uid": 2222
}
删除test1
用户:
[root@app31 ~]# ansible 192.168.1.88 -m user -a 'name=test1 state=absent'
192.168.1.88 | SUCCESS => {
"changed": true,
"force": false,
"name": "test1",
"remove": false,
"state": "absent"
}
11.script 模块
在远程主机运行本地的脚本,实例:
[root@app31 ~]# vi /tmp/df.sh
#!/bin/bash
df -lh >> /tmp/disk_total.log
# 我们直接运行命令来实现在被管理端执行该脚本:
[root@app31 ~]# ansible 192.168.1.88 -m script -a '/tmp/df.sh'
192.168.1.88 | SUCCESS => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.1.88 closed.\r\n",
"stdout": "",
"stdout_lines": []
}
12.get_url 模块
通过互联网下载软件至被控端本地
url # 资源文件在互联网上的具体url地址
dest #文件下载位置的绝对路径
mode #文件下载位置的绝对路径
checksum #对下载的资源进行校验
timeout #URL请求超时时间,默认10s
下载互联网的软件至本地
[root@app31 ~]# ansible 192.168.1.88 -m get_url -a "url=https://199604.com/wp-content/uploads/2021/03/20190921090433354.gif dest=/tmp"
192.168.1.88 | SUCCESS => {
"changed": true,
"checksum_dest": null,
"checksum_src": "2f6ba1d4fd455893895d5b1daec75cfe06f4d4b0",
"dest": "/tmp/20190921090433354.gif",
"gid": 0,
"group": "root",
"md5sum": "8af3c72918267a47eaf8e7ec817473eb",
"mode": "0644",
"msg": "OK (1118661 bytes)",
"owner": "root",
"size": 1118661,
"src": "/tmp/tmpqgBY0k",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "https://199604.com/wp-content/uploads/2021/03/20190921090433354.gif"
}
13.hostname 模块
管理远程主机的主机名
更改192.168.1.88
的主机名为test88
[root@app31 ~]# ansible 192.168.1.88 -m hostname -a 'name=test88'
192.168.1.88 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "",
"ansible_fqdn": "test88",
"ansible_hostname": "test88",
"ansible_nodename": "test88"
},
"changed": true,
"name": "test88"
}
[root@sdw88 tmp]# hostname
test88
14.archive 模块 和 unarchive 模块
archive模块
在远端主机打包与压缩
path # 要压缩的文件或目录
dest # 压缩后的文件
format # 指定打包压缩的类型:bz2、gz、tar、xz、zip
将 /var/log/nbdc
目录压缩为 tar.gz
格式,并存储至 /tmp
目录下
[root@app31 ~]# ansible 192.168.1.88 -m archive -a 'path=/var/log/nbdc dest=/tmp/nbdc.tar.gz format=gz'
192.168.1.88 | SUCCESS => {
"archived": [
"/var/log/nbdc/download/Main.log"
],
"arcroot": "/var/log/",
"changed": true,
"dest": "/tmp/nbdc.tar.gz",
"expanded_exclude_paths": [],
"expanded_paths": [
"/var/log/nbdc"
],
"gid": 0,
"group": "root",
"missing": [],
"mode": "0644",
"owner": "root",
"size": 60423,
"state": "file",
"uid": 0
}
unarchive模块
在远端主机解包与解压缩
src # 要解压的软件包路径
dest # 解压到目标位置,需要是一个目录
remote_src # yes:要解压的包在被控端、no:要解压的包在控制端 默认no
owner #文件复制到远程并设定属主,默认为root
group #文件复制到远程并设定属组,默认为root
mode #文件复制到远程并设定权限,默认file=644,directory=755
远程解压192.168.1.88下的/tmp/nbdc.tar.gz
文件
[root@app31 ~]# ansible 192.168.1.88 -m unarchive -a 'src=/tmp/nbdc.tar.gz dest=/tmp/ remote_src=yes'
192.168.1.88 | SUCCESS => {
"changed": true,
"dest": "/tmp/",
"extract_results": {
"cmd": [
"/usr/bin/gtar",
"--extract",
"-C",
"/tmp/",
"-z",
"-f",
"/tmp/nbdc.tar.gz"
],
"err": "",
"out": "",
"rc": 0
},
"gid": 0,
"group": "root",
"handler": "TgzArchive",
"mode": "01777",
"owner": "root",
"size": 4096,
"src": "/tmp/nbdc.tar.gz",
"state": "directory",
"uid": 0
}
15.selinux 模块
管理远端主机的 SELINUX
防火墙
state #Selinux模式:enforcing、permissive、disabled
polocy #targeted
设置 selinux 为 enforcing
[root@app31 selinux]# ansible 192.168.1.88 -m selinux -a 'state=enforcing policy=targeted'
[WARNING]: Reboot is required to set SELinux state to enforcing
192.168.1.88 | SUCCESS => {
"changed": true,
"configfile": "/etc/selinux/config",
"msg": "Config SELinux state changed from 'disabled' to 'enforcing'",
"policy": "targeted",
"reboot_required": true,
"state": "enforcing"
}
设置 selinux 为 disabled
[root@app31 selinux]# ansible 192.168.1.88 -m selinux -a 'state=disabled'
192.168.1.88 | SUCCESS => {
"changed": true,
"configfile": "/etc/selinux/config",
"msg": "Config SELinux state changed from 'enforcing' to 'disabled'",
"policy": "targeted",
"reboot_required": false,
"state": "disabled"
}
playbook--有空再深入学习....
Playbook语法简介
Ansible使用YAML语法描述配置文件,YAML语法以简洁明了、结构清晰著称。Ansible的任务配置文件被称为Playbook,我们可以称之为"剧本”。
每一个剧本(Playbook)中都包含一系列的任务,这每个任务在Ansible中又被称为"戏剧”(play)。一个剧本(Playbook)中包含多出戏剧(play),这很容易理解。
具体可到:https://www.junmajinlong.com/ansible/4_ansible_soul_playbook/ 学习,文章系列也非常不错
以下是一个例子:
---
- name: this is demo
hosts: yn
tasks:
- name: df shell
shell: df -h
register: df_data
- name: debug
debug:
msg: "{{df_data}}"
命令行执行:ansible-playbook demo.yml
下面收Ansible-Linux巡检的一个例子:
1.编写自己的主机清单:/etc/ansible/hosts
2.编写check_server.yml
的playbook的文件
---
- name: check_server_yn
hosts: yn
tasks:
# 执行巡检脚本
- name: run sh
script: check_resources.sh
register: run_data
- name: debug
debug:
msg: "{{run_data.stdout_lines}}"
3.编写巡检脚本check_resources.sh
linux巡检:CPU、内存、磁盘。
#!/bin/bash
free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }';
df -h | grep -vE '^Filesystem|tmpfs|cdrom|文件系统' | awk '{ print "Disk Usage:"" " $1 " " $3"/"$2" ""("$5")"}';
# 只看使用率>60%的磁盘
# df -hP | grep -vE '^Filesystem|tmpfs|cdrom|文件系统' |awk 'NR>1 && int($5) > 60'
top -bn1 | grep load | awk '{printf "CPU Load: %.2f\n", $(NF-2)}';
4.运行ansible-playbook check_server.yml
结果:
[root@mdw193 shell]# ansible-playbook check_server.yml
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
PLAY [check_server_yn] ********************************************************************************************
ok: [10.174.237.195] => {
"msg": [
"Memory Usage: 75052/257387MB (29.16%)",
"Disk Usage: /dev/mapper/centos-root 17G/50G (34%)",
"Disk Usage: /dev/sdb 4.5T/11T (42%)",
"Disk Usage: /dev/sda1 179M/1014M (18%)",
"Disk Usage: /dev/mapper/centos-home 636M/782G (1%)",
"Disk Usage: cm_processes 1.5G/126G (2%)",
"CPU Load: 0.53"
]
}
PLAY RECAP ********************************************************************************************
10.173.108.100 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0