中文社区:国内最专业的Ansible中文官方学习手册

ansible安装

在线安装

1
2
yum -y install epel-release
yum install ansible -y

离线安装

现在有网的centos服务器下载,然后打包,A是有网的,B的无网络的。

以下操作是A服务器

1
2
yum -y install epel-release  # 下载epel仓库
yum install -y ansible --downloadonly --downloaddir=~/ansible # 仅下载,并下载到~/ansible

打包

1
tar zcvf ansible.tar.gz ~/ansible

image-20240612161049955

上传到服务器B,以下是B的操作

1
2
3
tar zxvf ansible.tar.gz && cd ansible
yum localinstall *.rpm -y --nogpgcheck

验证安装

1
ansible --version

image-20240612161059776

image-20240606224709751

image-20240606225133739

主机清单配置

查看已配置的分组

1
grep -vE '^#|^$' /etc/ansible/hosts 

主机分组

在/etc/ansible/hosts 文件中配置文件

1
2
3
4
5
6
7
8
9
[web]
192.168.0.100
192.168.0.101

[mysql]
192.168.0.102

[backup]
192.168.0.103

更多请查看官网:How to build your inventory — Ansible Community Documentation

连接参数配置

这部分内容很重要,详细可以查看Connecting to hosts: behavioral inventory parameters,使用密码登录,当然可以使用免密登录,详细可以查看之前的博客配置ssh免密Linux安全:SSH原理 | 道坤 (daokun.eu.org)

参数 参数类型 参数说明
ansible_host 主机地址 远程主机ip
ansible_port 主机端口 设置SSH连接端口,默认22
ansible_user 主机用户 默认SSH远程连接的用户身份
ansible_password 用户密码 指定SSH远程主机密码
1
2
3
4
5
6
7
8
9
[web]
192.168.0.100 ansible_port=22 ansible_user=root ansible_password='daokun'
192.168.0.101 ansible_port=4422 ansible_user=root ansible_password='daokun'

[mysql]
192.168.0.102 ansible_port=22 ansible_user=root ansible_password='daokun'

[backup]
192.168.0.103 ansible_port=22 ansible_user=root ansible_password='daokun'

image-20240625100010043

故障解决

连接故障

image-20240625100238063

如果你是第一次连接远程主机,会出现如上报错,这是新机器的指纹确认问题。具体原因在我之前的博客SSH原理。解决办法有两个:

  1. 手动ssh连接远程主机,进行指纹确认即可

  2. ansible配置文件中忽略指纹确认

    1
    2
    grep 'host_key_checking' /etc/ansible/ansible.cfg 
    host_key_checking = False

当我手动添加之后,可以看到kown_hosts文件含有192.168.0.101信息,这时候,使用ansible就正常了。
image-20240625110213547

ansible缓存问题

ansible在对远程主机操作之前,默认会先通过setup模块获取机器的facts(静态属性),并且会生成缓存,便于加速远程主机的操作;但缓存也会导致一些奇怪的现象,比如客户端的机器信息更新了,服务端依旧使用的是旧数据,那就不准确了,因此可以删除缓存。详细可见缓存问题

1
2
#清理ansible的缓存目录即可
rm -rf ~/.ansible/cp/*

连续的主机名

1
2
[web]
192.168.0.[100:110]

公共变量

局部变量

1
2
3
4
5
6
[web:vars]
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_pass='daokun'
[web]
192.168.0.[100:110]

全局变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[all:vars]
ansible_port=7722
ansible_user=root
ansible_password='123123'

[web]
192.168.0.100 ansible_port=22 ansible_user=root ansible_password='daokun'
192.168.0.101 ansible_port=4422 ansible_user=root ansible_password='daokun'

[mysql]
192.168.0.102 ansible_port=22 ansible_user=root ansible_password='daokun'

[backup]
192.168.0.103 ansible_port=22 ansible_user=root ansible_password='daokun'

局部变量的优先大于全局

ansible的执行模式

Ansible实现批量管理主机的模式主要有俩:

  • 利用ansible命令实现批量管理(ad-hoc)模式
  • 利用ansible剧本实现批量管理(playbook)模式

Ad-hoc和playbook的关系就好比shell命令与shell scripts的关系

Ansible的ad-hoc模式也就是ansible的命令行模式,该模式通常用来临时处理一些任务。例如

  • 临时批量查看所有被管控机器的内存、负载、磁盘
  • 临时批量分发某个特定文件

Ansible的playbook模式就是针对特定的具体较大的任务,事先写好执行剧本,然后在其他机器上批量执行相同的任务,属于定制化的批量执行任务,例如

  • 一键安装Rsync
  • 一键搭建LNMP集群等

ad-hoc模式

ansible ad-hoc命令用法

1
2
3
ansible 主机(主机组) -m module(模块名)  -a "action(执行的动作)"
# 如下
ansible 192.168.0.100 -m command -a "hostname" # 在192.168.0.100主机上使用command模块执行hostname命令

ad-hoc帮助用法

1
2
3
4
5
6
7
8
9
10
ansible-doc -l |grep ^ping  # 列出ping开头的模块
ansible-doc -l |grep ^shell # 列出shell开头的模块
ansible-doc -l |wc -l # 列出ansible所支持的模块
ansible-doc -s shell # 查看shell的参数
ansible-doc -l #列出所有的模块列表
ansible-doc -s 模块名 #查看指定模块的参数
ansible-doc 模块名 #查看指定模块的详细参数
ansible-doc copy #查看copy模块的帮助
ansible-doc yum #查看yum模块的帮助

image-20240625112113145

image-20240625112138568

ansible核心内容(模块)

ansible正确玩法:ansible社区

各个颜色意义

绿色 黄色 紫色 红色 蓝色
命令以用户期望的执行了,但是状态没有发生改变。 命令以用户期望的执行了,并且状态发生了改变。 警告信息,说明ansible提示你有更合适的用法。 命令错误,执行失败。 详细的执行过程。

以下模块默认使主机组web

ping测试连通性

1
2
ansible web -m ping
ansible-doc -s ping # 查看模块用法
image-20240625113225432

command 简单命令

command模块是ansible命令基本模块

  • 使用command模块执行远程命令,命令不得用变量($HOME)

  • 不得出现特殊符号

    1
    < 、>、|、;、& ,

    否则无法识别,需要则使用shell模块实现。也就是无法使用复杂的linux命令

    选项参数 选项说明
    chdir 在执行命令前进入到指定目录
    creates 定义一个文件是否存在,如果不存在则运行相应命令,存在则跳过执行
    removes 定义一个文件是否存在,如果存在则运行相应命令,如果不存在则跳过执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ansible web -m command -a "free -m"   # 远程查看主机内存
ansible web -m command -a "uptime" # 远程查看负载
ansible all -m command -a "df -h" # 查看磁盘使用情况
ansible all -m command -a "service httpd restart" # http重启
ansible all -m command -a "mkdir /path/to/new/directory" # 创建目录
ansible all -m command -a "rm /path/to/file" # 删除文件
ansible all -m command -a "rm /path/to/file" # 执行脚本文件

ansible web -m command -a 'mkdir /opt creates=/opt' # 目标目录已经存在了,就别创建该目录了

ansible web -m command -a 'tar -zcf /backup_config/etc.tgz removes=/backup_config' # 判断如果该文件夹不存在,则不执行备份


ansible web -m command -a 'touch /home/daokun ansible.log warn=False' # 创建文件且忽略警告

image-20240625113527078

image-20240625113613185

image-20240625144605767

这个command模块不支持复杂的命令

shell模块(万能模块)

shell模块功能:在远程节点上执行命令(复杂的命令)

1
2
3
4
5
6
7
8

ansible web -m shell -a 'ps -ef|grep ssh'

ansible web -m shell -a "mkdir -p /server/scripts/;echo 'hostname' > /server/scripts/hostname.sh;chmod +x /server/scripts/hostname.sh;/usr/bin/bash /server/scripts/hostname.sh"
#创建文件夹
#生成sh脚本文件
#赋予脚本可执行权限
#执行脚本
image-20240625150032402

image-20240625153809170

copy拷贝文件

copy模块是远程推送数据模块,只能把数据推送给远程主机节点,无法拉取数据到本地。

image-20200317155559101
简单发送文件
1
ansible web -m copy -a 'src=~/fast_github.sh dest=/opt/'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@master ~]# ls
anaconda-ks.cfg a.sh cali.tar.gz cri-dockerd-0.3.8-3.el7.x86_64.rpm fast_github.sh k8s-1-29-5.tar.gz log.tar Python-3.7.5.tar
ana.py cali clean_pos.py fast_github2.sh ins_k8s.sh logs Python-3.7.5 test
[root@master ~]# ansible web -m copy -a 'src=~/fast_github.sh dest=/opt/'
192.168.0.102 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "98db8b930a8e627297adebfd5360e14da21c4765",
"dest": "/opt/fast_github.sh",
"gid": 0,
"group": "root",
"md5sum": "4217dd1158b3ba69a57183c2e216f515",
"mode": "0644",
"owner": "root",
"size": 1704,
"src": "/root/.ansible/tmp/ansible-tmp-1719302376.08-106171-121380087039244/source",
"state": "file",
"uid": 0
}
192.168.0.101 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "98db8b930a8e627297adebfd5360e14da21c4765",
"dest": "/opt/fast_github.sh",
"gid": 0,
"group": "root",
"md5sum": "4217dd1158b3ba69a57183c2e216f515",
"mode": "0644",
"owner": "root",
"size": 1704,
"src": "/root/.ansible/tmp/ansible-tmp-1719302376.06-106169-80912088180686/source",
"state": "file",
"uid": 0
}

发送文件且指定文件属性

权限改为600、修改为www用户(要求目标机器存在该用户)

1
2
3
4
5
6
# 创建www用户
[root@master ~]#ansible web -m shell -a "useradd www"
# 远程拷贝文件,修改权限
[root@master ~]#ansible web -m copy -a "src=~/fast_github.sh dest=/tmp/ owner=www group=www mode=600"
# 远程检查文件信息
[root@master ~]#ansible web -m shell -a "ls -l /tmp/fast_github.sh"

image-20240625160833843

发送文件且先做好备份

使用backup参数,防止覆盖远程文件,丢失备份,提前备份该目标机器的数据

1
2
ansible web -m copy -a "src=/opt/fast_github.sh  dest=/tmp/ owner=www group=www mode=600  backup=yes"
ansible web -m shell -a "ls /tmp -l" # 查看
指定数据写入到远程文件中
1
ansible web -m copy -a "content='hello world' dest=/tmp/test.txt mode=600" 

像这样的覆盖操作,还是添加备份参数更合适

1
ansible web -m copy -a "content='hello world' dest=/tmp/test.txt mode=600 backup=yes" 
复制文件夹,注意结尾斜杠

远程拷贝~/Python-3.7.5/下的所有内容

1
2
3
4
5
#远程拷贝~/Python-3.7.5/下的所有内容
ansible backup -m copy -a "src=~/Python-3.7.5/ dest=/opt/"

# 远程拷贝/opt/yuchao整个目录到目标机器
ansible backup -m copy -a "src=~/Python-3.7.5 dest=/opt/"

file文件操作模块

参数 描述
path 必须指定操作的文件或目录。在之前版本中使用dest或name也可。
state 根据操作需求设置,例如directory、touch、link、hard、absent。
假设,我想要在远程主机上创建/testdir/a/b目录,那么我则需要设置path=/testdir/a/b,但是,我们和ansible无法从一个字符串就知道你要创建文件还是目录,所以,我们需要通过state参数进行说明,当我们想要创建的/testdir/a/b是一个目录时,需要将state的值设置为directory
当我们想要删除一个文件时(删除时不用区分目标是文件、目录、还是链接),则需要将state的值设置为absent
src 当state为link或hard时指定软硬链接的源文件。
force 当state为link时,可以强制创建链接,即使源文件不存在或同名文件已存在。
owner 设置被操作文件的属主用户。属主用户必须在远程主机中存在。
group 设置被操作文件的属组。属组必须在远程主机中存在。
mode 设置被操作文件的权限,如rw-r-x–,使用mode=650进行设置或特殊权限如suid(4700)。
recurse 当操作目标为目录时设置为yes,递归修改目录中文件属性。

使用

复制文件

将家目录下的1.txt和2.txt复制到远程主机的家目录下

playbook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
---
- name: Copy files to remote hosts
hosts: all
tasks:
- name: Copy 1.txt to remote hosts
copy:
src: ~/1.txt
dest: ~/1.txt
owner: "{{ ansible_user_id }}"
group: "{{ ansible_user_id }}"
mode: '0644'

- name: Copy 2.txt to remote hosts
copy:
src: ~/2.txt
dest: ~/2.txt
owner: "{{ ansible_user_id }}"
group: "{{ ansible_user_id }}"
mode: '0644'

运行

1
ansible-playbook copy_files.yml

参考资料:

  1. 傻瓜式Ansible离线安装,适合任何系统_一键离线安装ansible的shell脚本-CSDN博客
  2. Linux云计算自学-猿来教育官方网站 (apecome.com)
  3. Ansible 学习 (curder.github.io)