Ansible
- [一、 Ansible](#一、 Ansible)
- [二、Ansible 安装](#二、Ansible 安装)
- 三、快速使用
- 四、模块
- 五、剧本(Playbook)
-
- [5.1 概述](#5.1 概述)
- [5.2 结构](#5.2 结构)
一、 Ansible

二、Ansible 安装
2.1 准备工作
已配置主机名、IP地址
主机名 | IP地址 | 软件 |
---|---|---|
ansible-controller | 192.168.98.10 | |
ansible-node1 | 192.168.98.20 | |
ansible-node2 | 192.168.98.30 |
配置主机映射
- 配置主机映射
bash
[root@ansible-controller ~]# cat >> /etc/hosts <<EOF
> 192.168.98.10 ansible-controller
> 192.168.98.20 ansible-node1
> 192.168.98.30 ansible-node2
> EOF
- scp到另外两台主机
bash
[root@ansible-controller ~]#scp /etc/hosts [email protected]:/etc
The authenticity of host '192.168.98.20 (192.168.98.20)' can't be established.
ED25519 key fingerprint is SHA256:I3/lsrnTEnXOE3LFvTLRUXAJ+AhSVrIEWtqTnleRz9w.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.98.20' (ED25519) to the list of known hosts.
[email protected]'s password:
hosts 100% 247 338.2KB/s 00:00
[root@ansible-controller ~]# scp /etc/hosts [email protected]:/etc
The authenticity of host '192.168.98.30 (192.168.98.30)' can't be established.
ED25519 key fingerprint is SHA256:I3/lsrnTEnXOE3LFvTLRUXAJ+AhSVrIEWtqTnleRz9w.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:1: 192.168.98.20
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.98.30' (ED25519) to the list of known hosts.
[email protected]'s password:
hosts
配置免密登录
只需要在主控节点上创建密钥对
bash
ssh-keygen [-t ras](默认就是使用的rsa加密)
执行此命令,四次回车成功创建密钥对。创建成功后,执行命令将公钥拷贝到两台被控节点:
bash
ssh-copy-id ansible-node1
ssh-copy-id ansible-node2
bash
[root@ansible-controller ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:qoSVNc7fSMs0RH6lJFCXBUT8Ma7FQXq4TiOHn+STljQ root@ansible-controller
The key's randomart image is:
+---[RSA 3072]----+
| .o++*=+ |
| o +o=+ |
| o o =+.+ |
| = o o o= |
| o o S Eo |
| o * #.* |
| . . . = @ |
| . . . . |
| . |
+----[SHA256]-----+
shell
[root@ansible-controller ~]# ssh-copy-id ansible-node1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host 'ansible-node1 (192.168.98.20)' can't be established.
ED25519 key fingerprint is SHA256:I3/lsrnTEnXOE3LFvTLRUXAJ+AhSVrIEWtqTnleRz9w.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:1: 192.168.98.20
~/.ssh/known_hosts:4: 192.168.98.30
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@ansible-node1's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'ansible-node1'"
and check to make sure that only the key(s) you wanted were added.
[root@ansible-controller ~]# ssh-copy-id ansible-node2
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host 'ansible-node2 (192.168.98.30)' can't be established.
ED25519 key fingerprint is SHA256:I3/lsrnTEnXOE3LFvTLRUXAJ+AhSVrIEWtqTnleRz9w.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:1: 192.168.98.20
~/.ssh/known_hosts:4: 192.168.98.30
~/.ssh/known_hosts:5: ansible-node1
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@ansible-node2's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'ansible-node2'"
and check to make sure that only the key(s) you wanted were added.
关闭防火墙
bash
systemctl disable --now firewalld
关闭SELinux
shell
setenforece 0
sed -i "s/SELINUX=enforcing/SELINUX=permissive/" /etc/selinux/config
挂载仓库
三台主机:
shell
mount /dev/sr0 /mnt
[root@ansible-controller ~]# mount /dev/sr0 /mnt
mount: /mnt: WARNING: source write-protected, mounted read-only.
vim /etc/fstab
...
/dev/sr0 /mnt iso9660 defaults 0 0
mount -a
2.2 安装Ansible
dnf 安装
- 安装epel源
dnf install https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm
- 安装anible
dnf install ansible -y
- 验证安装是否成功
ansible --version
bash
[root@ansible-controller ~]# dnf install https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm -y
[root@ansible-controller ~]# ls /etc/yum.repos.d/
dnf.repo docker-ce.repo epel-cisco-openh264.repo epel.repo epel-testing.repo redhat.repo
bash
[root@ansible-controller ~]# dnf install ansible -y
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.
[root@ansible-controller ~]# ansible --version
ansible [core 2.14.17]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.9/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.9.19 (main, Aug 23 2024, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-2)] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True
python安装(pip安装)
- 安装 python pip sshpass 工具包
dnf install python3.9 python3.9-pip sshpass -y
- 安装 ansible
python3.9 -m pip install ansible
- 验证ansible
ansible --version
bash
[root@ansible-node1 ~]# dnf install python3.9 python3.9-pip sshpass -y
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered with an entitlement server. You can use "rhc" or "subscription-manager" to register.
三、快速使用
- 创建项目目录
bash
[root@ansible-controller ~]# mkdir ansible_ping
[root@ansible-controller ~]# cd ansible_ping/
[root@ansible-controller ansible_ping]#
- 创建清单文件
bash
[root@ansible-controller ansible_ping]# vim inventory.ini
[root@ansible-controller ansible_ping]# cat inventory.ini
[server]
ansible-node1
ansible-node2
- 执行 ansible
bash
[root@ansible-controller ansible_ping]# ansible server -i inventory.ini -m ping
ansible-node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
ansible-node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
绿色状态:仅仅执行了,并没有对其做出改变
黄色状态:执行并做出改变
红色状态:有错误
紫色状态:执行无误,但有可能有更好的方案
四、模块
官方文档: ansible模块

查看所有模块
1. 官网
2. 执行命令 (按q退出)
ansible-doc -l
查看某个模块:ansible-doc 模块名称
使用模块
使用 file 模块
- 创建项目目录
bash
[root@ansible-controller ~]# mkdir ansible_file
[root@ansible-controller ~]# cd ansible_file/
- 创建清单文件和目录
bash
[root@ansible-controller ansible_file]# mkdir inventory
[root@ansible-controller ansible_file]# cd inventory/
[root@ansible-controller inventory]# vim hosts
[root@ansible-controller inventory]# cat hosts
[server]
ansible-node[1:2]
- 执行 ansible
bash
[root@ansible-controller ansible_file]# ansible server -i inventory/hosts -m file -a "path=/root/a.txt state=touch owner=redhat group=root"
# 以下命令为黄色状态
ansible-node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/root/a.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "redhat",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 0,
"state": "file",
"uid": 1000
}
ansible-node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"dest": "/root/a.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "redhat",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 0,
"state": "file",
"uid": 1000
}
bash
[root@ansible-controller ansible_file]# ansible server -i inventory/hosts -m file -a "path=/root/d1 state=directory"
ansible-node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/root/d1",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
ansible-node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/root/d1",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
get_url模块
- 创建项目目录
bash
[root@ansible-controller ansible_file]# cd ..
[root@ansible-controller ~]# ls
ansible_file ansible_ping deploy-redis-cluster.sh redis-8.0.2.tar.gz
[root@ansible-controller ~]# mkdir ansible_get_url
[root@ansible-controller ~]# cd ansible_get_url/
- 创建清单目录及文件
bash
[root@ansible-controller ansible_get_url]# mkdir inventory
[root@ansible-controller ansible_get_url]# cd inventory/
[root@ansible-controller inventory]# vim hosts
[root@ansible-controller inventory]# cat hosts
[server]
ansible-node[1:2]
- 执行模块
bash
[root@ansible-controller inventory]# cd ..
[root@ansible-controller ansible_get_url]# ansible server -i inventory/hosts -m get_url -a "url=https://nginx.org/download/nginx-1.28.0.tar.gz dest=/root/"
ansible-node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"checksum_dest": null,
"checksum_src": "430fbd93dc0457e5dc901fd6a20a368c0d355791",
"dest": "/root/nginx-1.28.0.tar.gz",
"elapsed": 25,
"gid": 0,
"group": "root",
"md5sum": "1ad2b6606c3709ed1268ca32ae447c21",
"mode": "0644",
"msg": "OK (1280111 bytes)",
"owner": "root",
"secontext": "system_u:object_r:admin_home_t:s0",
"size": 1280111,
"src": "/root/.ansible/tmp/ansible-tmp-1749370583.1186264-2407-8833024505451/tmp_wfw0ssd",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "https://nginx.org/download/nginx-1.28.0.tar.gz"
}
ansible-node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"checksum_dest": null,
"checksum_src": "430fbd93dc0457e5dc901fd6a20a368c0d355791",
"dest": "/root/nginx-1.28.0.tar.gz",
"elapsed": 34,
"gid": 0,
"group": "root",
"md5sum": "1ad2b6606c3709ed1268ca32ae447c21",
"mode": "0644",
"msg": "OK (1280111 bytes)",
"owner": "root",
"secontext": "system_u:object_r:admin_home_t:s0",
"size": 1280111,
"src": "/root/.ansible/tmp/ansible-tmp-1749370583.118948-2408-236501869821397/tmp4iey3km8",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "https://nginx.org/download/nginx-1.28.0.tar.gz"
}
另外两台主机已经成功下载 nignx
bash
[root@ansible-node1 ~]# ls
a.txt d1 nginx-1.28.0.tar.gz redis-8.0.2.tar.gz
[root@ansible-node2 ~]# ls
a.txt d1 nginx-1.28.0.tar.gz redis-8.0.2.tar.gz
五、剧本(Playbook)
剧本: Playbook文档说明
5.1 概述
Playbook 是 Ansible 自动化中的核心组件,以 YAML格式 编写,用于定义一组或多组任务的执行步骤
。
-
作用
- 自动化执行复杂任务
- 提供可重用的任务定义文件
- 支持人物的条件判断和动态配置
-
特点
- 结构化,且可读性强:
- 模块化支持:
- 幂等性:确保任务多次运行后,目标主机状态保持一致
5.2 结构
示例:使用Playbook来实现nginx安装
- 创建项目目录
- 创建清单目录及文件
- 创建 ansible.cfg 配置文件
- 创建 playbook.yaml 文件
- 创建 index.html
- 执行 playbook
- 测试安装结果
完整流程:
- 创建项目目录
shell
[root@ansible-controller ~]# mkdir ansible_nginx
[root@ansible-controller ~]# ls
ansible_file ansible_get_url ansible_nginx ansible_ping deploy-redis-cluster.sh redis-8.0.2.tar.gz
[root@ansible-controller ~]# cd ansible_nginx/
- 创建清单目录及文件
shell
[root@ansible-controller ansible_nginx]# mkdir inventory
[root@ansible-controller ansible_nginx]# cd inventory/
[root@ansible-controller inventory]# vim hosts
[root@ansible-controller inventory]# cat hosts
[server]
ansible-node[1:2]
- 创建 ansible.cfg 配置文件
shell
[root@ansible-controller inventory]# cd ..
[root@ansible-controller ansible_nginx]# vim ansible.cfg
[root@ansible-controller ansible_nginx]# cat ansible.cfg
[defaults]
inventory=inventory/hosts
- 创建 playbook.yaml 文件
shell
[root@ansible-controller ansible_nginx]# ls
ansible.cfg inventory
[root@ansible-controller ansible_nginx]# vim playbook.yaml
[root@ansible-controller ansible_nginx]# cat playbook.yaml
---
- name: Install nginx web servers
hosts: server
tasks:
- name: Install nginx
ansible.builtin.dnf:
name: nginx
state: installed
- name: create nginx index
ansible.builtin.template:
src: files/index.html
dest: /usr/share/nginx/html/index.html
- name: start nginx service
ansible.builtin.service:
name: nginx
state: started
#enable: yes
- 创建 index.html
shell
[root@ansible-controller ansible_nginx]# ls
ansible.cfg inventory playbook.yaml
[root@ansible-controller ansible_nginx]# mkdir files
[root@ansible-controller ansible_nginx]# cd files/
[root@ansible-controller files]# vim index.html
[root@ansible-controller files]# cat index.html
<html>
<head>
<meta charset="utf-8">
<title>index.html</title>
<head>
<body>
index.html
</body>
</html>
- 执行 playbook
shell
[root@ansible-controller files]# cd ..
[root@ansible-controller ansible_nginx]# tree
.
├── ansible.cfg
├── files
│ └── index.html
├── inventory
│ └── hosts
└── playbook.yaml
2 directories, 4 files
[root@ansible-controller ansible_nginx]# ansible-playbook playbook.yaml
PLAY [Install nginx web servers] ********************************************************************************
TASK [Gathering Facts] ******************************************************************************************
ok: [ansible-node1]
ok: [ansible-node2]
TASK [Install nginx] ********************************************************************************************
changed: [ansible-node1]
changed: [ansible-node2]
TASK [create nginx index] ***************************************************************************************
changed: [ansible-node1]
changed: [ansible-node2]
TASK [start nginx service] **************************************************************************************
changed: [ansible-node1]
changed: [ansible-node2]
PLAY RECAP ******************************************************************************************************
ansible-node1 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible-node2 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 测试
node主机执行curl命令
shell
[root@ansible-node1 ~]# curl localhost
<html>
<head>
<meta charset="utf-8">
<title>index.html</title>
<head>
<body>
index.html
[root@ansible-node2 ~]# curl localhost
<html>
<head>
<meta charset="utf-8">
<title>index.html</title>
<head>
<body>
index.html
</body>
</html>
示例:使用Playbook来实现nginx源码安装
先卸载node两台的nginx
bash
[root@ansible-node1 ~]# dnf remove nginx -y
- 创建项目目录
- 创建清单目录及文件
- 创建 ansible.cfg 配置文件
- 创建 playbook.yaml 文件
- 创建 index.html
- 执行 playbook
- 测试安装结果
完整流程:
- 创建项目目录
shell
- 创建清单目录及文件
shell
- 创建 ansible.cfg 配置文件
shell
- 创建 playbook.yaml 文件
shell
- 创建 index.html
shell
- 执行 playbook
shell
- 测试
node主机执行curl命令
shell
[root@ansible-node1 ~]# ls
a.txt d1 nginx-1.27.4.tar.gz nginx-1.28.0.tar.gz redis-8.0.2.tar.gz
[root@ansible-node1 ~]# curl localhost
welcome to index.html
[root@ansible-node2 ~]# ls
a.txt d1 nginx-1.27.4.tar.gz nginx-1.28.0.tar.gz redis-8.0.2.tar.gz
[root@ansible-node2 ~]# curl localhost
welcome to index.html
shell
[root@ansible-controller ansible_nginx]# cd
[root@ansible-controller ~]# ls
ansible_file ansible_nginx deploy-redis-cluster.sh
ansible_get_url ansible_ping redis-8.0.2.tar.gz
[root@ansible-controller ~]# mkdir playbook_nginx
[root@ansible-controller ~]# cd playbook_nginx/
[root@ansible-controller playbook_nginx]# mkdir inventory
[root@ansible-controller playbook_nginx]# cd inventory/
[root@ansible-controller inventory]# vim hosts
[root@ansible-controller inventory]# cat hosts
[web]
ansible-node[1:2]
[root@ansible-controller inventory]# cd ..
[root@ansible-controller playbook_nginx]# vim ansible.cfg
[root@ansible-controller playbook_nginx]# cat ansible.cfg
[defaults]
inventory=inventory/hosts
[root@ansible-controller playbook_nginx]# ls
ansible.cfg inventory
[root@ansible-controller playbook_nginx]# vim playbook.yaml
[root@ansible-controller playbook_nginx]# cat playbook.yaml
---
- name: Install Source Code nginx Servers
hosts: web
vars:
- src_nginx: /root/nginx-1.27.4.tar.gz
- nginx_unzip_dir: /opt
- nginx_install_dir: /usr/local/nginx
- nginx_unzip_name: nginx-1.27.4
tasks:
- name: Install Compile dependencies
ansible.builtin.dnf:
name:
- gcc
- openssl-devel
- openssl
- zlib
- zlib-devel
- pcre
- pcre-devel
- gcc-c++
state: installed
- name: Download nginx source package
ansible.builtin.get_url:
url: https://nginx.org/download/nginx-1.27.4.tar.gz
dest: "{{ src_nginx }}"
- name: Uzip nginx and config nginx and install nginx
ansible.builtin.shell: |
tar -zxf /root/nginx-1.27.4.tar.gz -C /opt
cd /opt/nginx-1.27.4
./configure --prefix=/usr/local/nginx
make
make install
- name: create nginx of index.html
ansible.builtin.template:
src: files/index.html
dest: "{{ nginx_install_dir}}/html/index.html"
- name: start nginx service
ansible.builtin.shell: |
/usr/local/nginx/sbin/nginx
[root@ansible-controller playbook_nginx]# ls
ansible.cfg inventory playbook.yaml
[root@ansible-controller playbook_nginx]# mkdir files
[root@ansible-controller playbook_nginx]# cd files/
[root@ansible-controller files]# vim index.html
[root@ansible-controller files]# cat index.html
welcome to index.html
[root@ansible-controller files]# cd ..
[root@ansible-controller playbook_nginx]# ansible-playbook playbook.yaml
PLAY [Install Source Code nginx Servers] **********************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [ansible-node1]
ok: [ansible-node2]
TASK [Install Compile dependencies] ***************************************************************
changed: [ansible-node1]
changed: [ansible-node2]
TASK [Download nginx source package] **************************************************************
changed: [ansible-node2]
changed: [ansible-node1]
TASK [Uzip nginx and config nginx and install nginx] **********************************************
changed: [ansible-node2]
changed: [ansible-node1]
TASK [create nginx of index.html] *****************************************************************
changed: [ansible-node1]
changed: [ansible-node2]
TASK [start nginx service] ************************************************************************
changed: [ansible-node1]
changed: [ansible-node2]
PLAY RECAP ****************************************************************************************
ansible-node1 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible-node2 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
shell
shell
shell