安装 Ansible
配阿里yum源。
[root@localhost ~]# dnf list all|grep ansible
[root@localhost ~]# dnf -y install centos-release-ansible-29
[root@localhost ~]# ls /etc/yum.repos.d/
CentOS-Base.repo CentOS-SIG-ansible-29.repo redhat.repo
[root@localhost ~]# dnf list all|grep ansible
[root@localhost ~]# dnf -y install ansible
[root@localhost ~]# ansible --version
ansible 2.9.27
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.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Sep 9 2021, 07:49:02) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]
# 通过使用setup模块验证localhost上的ansible_python_version
[root@localhost ~]# ansible -m setup localhost|grep ansible_python_version
"ansible_python_version": "3.6.8",
清单文件
[root@localhost ~]# cd /etc/ansible/
[root@localhost ansible]# ls
ansible.cfg hosts roles
[root@localhost ansible]# vim hosts
node1
[root@localhost ansible]# ansible node1 --list-hosts
hosts (1):
node1
[root@localhost ansible]# ansible node2 --list-hosts
[WARNING]: Could not match supplied host pattern, ignoring: node2
[WARNING]: No hosts matched, nothing to do
hosts (0):
[root@localhost ansible]# vim hosts
[webs]
node1
node2
[root@localhost ansible]# ansible webs --list-hosts
hosts (2):
node1
node2
[root@localhost ansible]# vim hosts
11.1.1.1
[webs]
node1
node2
node3
[dbs]
node3
node4
[root@localhost ansible]# ansible webs --list-hosts
hosts (3):
node1
node2
node3
[root@localhost ansible]# ansible dbs --list-hosts
hosts (2):
node3
node4
使用以下命令列出默认清单文件中的所有受管主机:
[root@localhost ansible]# ansible all --list-hosts
hosts (5):
11.1.1.1
node1
node2
node3
node4
使用以下命令列出不属于任何组的受管主机:
[root@localhost ansible]# ansible ungrouped --list-hosts
hosts (1):
11.1.1.1
自定义清单文件
在/etc/ansible/目录中,创建一个名为inventory的自定义静态清单文件。
[root@localhost ansible]# vim inventory
[webs]
web01.example.com
[root@localhost ansible]# hostnamectl set-hostname control
[root@localhost ansible]# bash
[root@control ansible]#
[root@localhost ~]# hostnamectl set-hostname web01.example.com
[root@localhost ~]# bash
[root@web01 ~]#
[root@control ansible]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.163.132 web01.example.com
[root@control ansible]# ping web01.example.com
PING web01.example.com (192.168.163.132) 56(84) bytes of data.
64 bytes from web01.example.com (192.168.163.132): icmp_seq=1 ttl=64 time=0.414 ms
[root@control ansible]# ansible web01.example.com -i /etc/ansible/inventory --list-hosts
hosts (1):
web01.example.com
[root@control ansible]# ansible webs -i /etc/ansible/inventory --list-hosts
hosts (1):
web01.example.com
管理Ansible配置文件
配置Ansible
[root@control ~]# ls
anaconda-ks.cfg
[root@control ~]# mkdir httpd
[root@control ~]# ls
anaconda-ks.cfg httpd
[root@control ~]# cd httpd/
[root@control httpd]# cp /etc/ansible/ansible.cfg .
[root@control httpd]# ls
ansible.cfg
[root@control httpd]# vim inventory
[webservers]
web01.example.com
~
[root@control httpd]# ls
ansible.cfg inventory
[root@control httpd]# ansible all --list-hosts
hosts (5):
11.1.1.1
node1
node2
node3
node4
[root@control httpd]# vim ansible.cfg
inventory = inventory
[root@control httpd]# ansible all --list-hosts
hosts (1):
web01.example.com
[root@control httpd]# echo $ANSIBLE_COONFIG
[root@control httpd]# ASIBLE_CONFIG=/etc/ansible/inventory
[root@control httpd]# echo $ANSIBLE_CONFIG
[root@control httpd]# cd
[root@control ~]# mv httpd /opt/
[root@control ~]# ls
anaconda-ks.cfg
[root@control ~]# cd /opt/
[root@control opt]# ls
httpd
[root@control opt]# cd httpd/
[root@control httpd]# ls
ansible.cfg inventory
[root@control httpd]# vim inventory
[root@control httpd]# ansible all --list-hosts
hosts (1):
web01.example.com
[root@control httpd]# echo $ANSIBLE_CONFIG
[root@control httpd]# ANSIBLE_CONFIG=/etc/ansible/inventory
[root@control httpd]# echo $ANSIBLE_CONFIG
/etc/ansible/inventory
[root@control ~]# export ANSIBLE_CONFIG=/opt/httpd/ansible.cfg
[root@control ~]# ansible --version
ansible 2.9.27
config file = /opt/httpd/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Sep 9 2021, 07:49:02) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]
[root@control ~]# ansible webservers --list-hosts
hosts (1):
web01.example.com
[root@control ~]# vim /opt/httpd/inventory
[webservers]
web01.example.com ansible_user=root ansible_password=12345
~
[root@control ~]# ansible all -m user -a "name=tom uid=4000 state=present"
web01.example.com | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 4000,
"home": "/home/tom",
"name": "tom",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 4000
}
[root@web01 ~]# id tom
uid=4000(tom) gid=4000(tom) groups=4000(tom)
[root@control ~]# ansible all -m command -a 'hostname'
web01.example.com | CHANGED | rc=0 >>
web01.example.com
[root@control ~]# ansible all -m command -a 'uptime'
web01.example.com | CHANGED | rc=0 >>
22:43:09 up 17:14, 2 users, load average: 0.00, 0.00, 0.00
//rc=return code=0,就是命令执行成功了
[root@control ~]# ansible all -m command -a 'hostname' -o
web01.example.com | CHANGED | rc=0 | (stdout) web01.example.com
//加上-o,可以在一行显示
[root@control ~]# ansible all -m ping
web01.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
ansible常用模块之ping
ping模块用于检查指定节点机器是否连通,用法很简单,不涉及参数,主机如果在线,则回复pong
[root@control ~]# cd /opt/httpd
[root@control httpd]# ls
ansible.cfg inventory
[root@control httpd]# ansible all -m ping
web01.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
ansible常用模块之command
command模块用于在远程主机上执行命令,ansible默认就是使用command模块。
command模块有一个缺陷就是不能使用管道符和重定向功能。
[root@control httpd]# ansible all -m command -a 'date'
web01.example.com | CHANGED | rc=0 >>
Mon May 30 15:05:27 CST 2022
[root@control httpd]# ansible all -a 'date'
web01.example.com | CHANGED | rc=0 >>
Mon May 30 15:03:39 CST 2022
//不用-m指定模块,是因为它默认使用的就是command模块
ansible常用模块之raw
raw模块用于在远程主机上执行命令,其支持管道符与重定向
//支持重定向
[root@control httpd]# ansible all -m raw -a 'echo "hello world"> /tmp/hehe'
web01.example.com | CHANGED | rc=0 >>
Shared connection to web01.example.com closed.
[root@control httpd]# ansible all -m raw -a 'cat /tmp/hehe'
web01.example.com | CHANGED | rc=0 >>
hello world
Shared connection to web01.example.com closed.
//支持管道符
[root@web01 ~]# sleep 60000
[root@control httpd]# ansible all -m raw -a 'ps -ef|grep sleep'
web01.example.com | CHANGED | rc=0 >>
root 6086 4242 0 15:18 pts/0 00:00:00 sleep 60000
root 6094 6093 0 15:19 pts/1 00:00:00 bash -c ps -ef|grep sleep
root 6112 6094 0 15:19 pts/1 00:00:00 grep sleep
Shared connection to web01.example.com closed.
ansible常用模块之shell
shell模块用于在受控机上执行受控机上的脚本,亦可直接在受控机上执行命令。
shell模块亦支持管道与重定向。
[root@control httpd]# ansible all -m shell -a 'ps -ef|grep sleep'
web01.example.com | CHANGED | rc=0 >>
root 6086 4242 0 15:18 pts/0 00:00:00 sleep 60000
root 6200 6123 0 15:23 pts/1 00:00:00 /bin/sh -c /usr/libexec/platform-python /root/.ansible/tmp/ansible-tmp-1653895395.026254-14605-179176237230367/AnsiballZ_command.py && sleep 0
root 6218 6217 0 15:23 pts/1 00:00:00 /bin/sh -c ps -ef|grep sleep
root 6220 6218 0 15:23 pts/1 00:00:00 grep sleep
[root@control httpd]# ansible all -m shell -a 'echo "hehe">>/tmp/hehe'
web01.example.com | CHANGED | rc=0 >>
[root@control httpd]# ansible all -m shell -a 'cat /tmp/hehe'
web01.example.com | CHANGED | rc=0 >>
hello world
hehe
[root@web01 ~]# mkdir /scripts
[root@web01 ~]# vi /scripts/test.sh
#!/bin/bash
nohup sleep 7000 &
~
[root@control httpd]# ansible all -m shell -a '/bin/bash /scripts/test.sh'
web01.example.com | CHANGED | rc=0 >>
[root@control httpd]# ansible all -m shell -a 'ps -ef|grep sleep'
web01.example.com | CHANGED | rc=0 >>
root 6890 1 0 15:43 ? 00:00:00 sleep 7000
root 6979 6794 0 15:44 pts/1 00:00:00 /bin/sh -c /usr/libexec/platform-python /root/.ansible/tmp/ansible-tmp-1653896640.9660017-14818-272955809851124/AnsiballZ_command.py && sleep 0
root 6997 6996 0 15:44 pts/1 00:00:00 /bin/sh -c ps -ef|grep sleep
root 6999 6997 0 15:44 pts/1 00:00:00 grep sleep
[root@control httpd]# ansible all -m shell -a 'kill -9 6890'
web01.example.com | CHANGED | rc=0 >>
[root@control httpd]# ansible all -m shell -a 'ps -ef|grep sleep'
web01.example.com | CHANGED | rc=0 >>
root 7324 7026 0 15:50 pts/1 00:00:00 /bin/sh -c /usr/libexec/platform-python /root/.ansible/tmp/ansible-tmp-1653897010.8285494-14909-220752588463343/AnsiballZ_command.py && sleep 0
root 7342 7341 0 15:50 pts/1 00:00:00 /bin/sh -c ps -ef|grep sleep
root 7344 7342 0 15:50 pts/1 00:00:00 grep sleep
ansible常用模块之template
template模块用于生成一个模板,并可将其传输至远程主机上。
[root@control httpd]# vim ansible.cfg
......
command_warnings = False
//取消注释。取消了注释不能留空格不然会出问题
[root@control httpd]# mkdir files
[root@control httpd]# ls
ansible.cfg files inventory
[root@control httpd]# cd files/
[root@control files]# cp /etc/yum.repos.d/CentOS-Base.repo .
[root@control files]# ls
CentOS-Base.repo
[root@control files]# cd ..
[root@control httpd]# ansible all -m template -a 'src=files/CentOS-Base.repo dest=/etc/yum.repos.d/CentOS-Base.repo owner=root group=root mode=0644'
[root@web01 ~]# ls /etc/yum.repos.d/
CentOS-Base.repo redhat.repo
ansible常用模块之yum
dnf模块用于管理受控机上的软件,其支持的参数主要有两个
name和state
state常用的值:
- present:安装软件
- absent:卸载软件
[root@control httpd]# ansible all -m dnf -a 'name=vsftpd state=present'
[root@web01 ~]# rpm -qa|grep vsftpd
[root@web01 ~]# rpm -qa|grep vsftpd
vsftpd-3.0.3-34.el8.x86_64
[root@control httpd]# ansible all -m dnf -a 'name=vsftpd state=absent'
[root@web01 ~]# rpm -qa|grep vsftpd
[root@web01 ~]#
ansible常用模块之copy
copy模块用于复制文件至远程受控机。
涉及到的参数主要有src和dest:
src后面接当前主机要传的文件路径 dest后面接对面受控机放文件的目录,可以设置该文件的属主owner,属组group,权限mode,备份backup
src=source 来源
dest=destination 目的地
[root@control httpd]# ansible all -m copy -a 'content="xixi\nhello world\nhello tom\n123\n" dest=/tmp/hehe'
[root@web01 ~]# cat /tmp/hehe
xixi
hello world
hello tom
123
[root@control httpd]# ansible all -m copy -a 'src=inventory dest=/tmp/inventory owner=root group=root mode=0644'
[root@web01 ~]# ll /tmp/inventory
-rw-r--r--. 1 root root 72 May 31 11:35 /tmp/inventory
ansible常用模块之group
group模块用于在受控机上添加或删除组。
[root@control httpd]# ansible all -m group -a 'name=tom state=present gid=2000'
web01.example.com | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"gid": 2000,
"name": "tom",
"state": "present",
"system": false
}
[root@web01 ~]# grep tom /etc/group
tom:x:2000:
[root@control httpd]# ansible all -m group -a 'name=tom state=absent'
web01.example.com | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"name": "tom",
"state": "absent"
}
[root@web01 ~]# grep tom /etc/group
[root@web01 ~]#
ansible常用模块之user
user模块用于管理受控机的用户帐号。
涉及到的参数有:
name
uid
state状态,比如present创建用户,absent删除用户
[root@control httpd]# ansible all -m user -a 'name=apache state=present system=yes create_home=no shell=/sbin/nologin'
//system是否是系统账户,create_home是否创建家目录,shell是否有可登录的交互shell
[root@web01 ~]# id apache
uid=995(apache) gid=992(apache) groups=992(apache)
[root@web01 ~]# grep apache /etc/passwd
apache:x:995:992::/home/apache:/sbin/nologin
[root@web01 ~]# ll /home/
total 0
drwx------. 2 4000 4000 62 May 29 22:35 tom
[root@control httpd]# ansible all -m user -a 'name=tom password="12345" state=present'
[root@control httpd]# ansible all -m user -a 'name=jerry state=present'
[root@web01 ~]# id tom
uid=1000(tom) gid=1000(tom) groups=1000(tom)
[root@web01 ~]# id jerry
uid=1001(jerry) gid=1001(jerry) groups=1001(jerry)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FReDQML6-1654444699591)(C:\Users\abc\AppData\Roaming\Typora\typora-user-images\image-20220605163149221.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJ3UVnKO-1654444699593)(C:\Users\abc\AppData\Roaming\Typora\typora-user-images\image-20220605163224149.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCw5pi2X-1654444699594)(C:\Users\abc\AppData\Roaming\Typora\typora-user-images\image-20220605163308608.png)]
[root@control ~]# ansible all -i localhost, -m debug -a "msg={{ '12345' | password_hash('sha512', 'mysecretsalt') }}"
[root@control httpd]# ansible all -m user -a 'name=tom password="$6$mysecretsalt$kVH/eMVeKqLKiGqUuqG.CKAUIUQivoutArAtEfm9nJAIHTDAZPvlO9/3drY.ZE2D7kDqHMz5z1MZiUlFjKqHa0" state=present'
[root@web01 ~]# su - jerry
Last login: Wed Jun 1 09:56:48 CST 2022 on pts/0
[jerry@web01 ~]$ su - tom
Password:
Last failed login: Wed Jun 1 09:57:08 CST 2022 on pts/0
There was 1 failed login attempt since the last successful login.
su: warning: cannot change directory to /home/tom: Permission denied
-bash: /home/tom/.bash_profile: Permission denied
[tom@web01 jerry]$
ansible常用模块之service
service模块用于管理受控机上的服务。
涉及到的参数有:
name
enabled开机自启
state状态:started启动,stopped关闭
[root@control httpd]# ansible all -m dnf -a 'name=vsftpd state=present'
[root@control httpd]# ansible all -m service -a 'name=vsftpd enabled=yes state=started'
playbook
YAML语言
YAML
是一种直观的能够被电脑识别的数据序列化格式,是一个可读性高并且容易被人类阅读,容易和脚本语言交互,用来表达资料序列的编程语言。
它类似于标准通用标记语言的子集XML的数据描述语言,语法比XML简单很多。
YAML
语言的格式如下:
house:
family:
name: Doe
parents:
- John
- Jane
children:
- Paul
- Mark
- Simone
address:
number: 34
street: Main Street
city: Nowheretown
zipcode: 12345
YAML的基本规则:
- 使用缩进来表示层级关系,每层2个空格,禁止使用TAB键
- 当冒号不是处于最后时,冒号后面必须有一个空格
- 用 - 表示列表,- 的后面必须有一个空格
- 用 # 表示注释
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rT0xUF5x-1654614876789)(C:\Users\abc\AppData\Roaming\Typora\typora-user-images\image-20220606184159022.png)]
[root@control httpd]# vim test.yml
---
- name: create user
hosts: all
tasks:
- name: create user for zhangsan
user:
name: zhangsan
state: present
~
[root@control httpd]# ansible-playbook test.yml //执行playbook
PLAY [create user] *************************************************************
TASK [Gathering Facts] *********************************************************
ok: [web01.example.com]
TASK [create user for zhangsan] ************************************************
changed: [web01.example.com]
PLAY RECAP *********************************************************************
web01.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@control httpd]# ansible-playbook --syntax-check test.yml
playbook: test.yml
//检查是否有飘红报错
执行空运行
可以使用-C选项对playbook执行空运行。这会使Ansible报告在执行该playbook时将会发生什么更改,但不会对受管主机进行任何实际的更改。
下例演示了一个playbook的空运行,它包含单项任务,可确保在受管主机上安装了最新版本的httpd软件包。注意该空运行报告此任务会对受管主机产生的更改。
ansible-playbook -C webserver.yml
[root@control httpd]# vim test.yml
---
- name: create user
hosts: all
tasks:
- name: create user for zhangsan
user:
name: zhangsan
state: absent
[root@control httpd]# ansible-playbook -C test.yml
PLAY [create user] *************************************************************
TASK [Gathering Facts] *********************************************************
ok: [web01.example.com]
TASK [create user for zhangsan] ************************************************
changed: [web01.example.com]
PLAY RECAP *********************************************************************
web01.example.com : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@web01 ~]# id zhangsan
uid=1002(zhangsan) gid=1002(zhangsan) groups=1002(zhangsan)
[root@control httpd]# vim test.yml
---
- name: create user
hosts: all
tasks:
- name: create user for zhangsan
user:
name1: zhangsan
state: absent
//语法没错,参数错误(name1)
[root@control httpd]# ansible-playbook --syntax-check test.yml
playbook: test.yml
[root@control httpd]# ansible-playbook -C test.yml
PLAY [create user] *************************************************************
TASK [Gathering Facts] *********************************************************
ok: [web01.example.com]
TASK [create user for zhangsan] ************************************************
fatal: [web01.example.com]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (user) module: name1 Supported parameters include: append, authorization, comment, create_home, expires, force, generate_ssh_key, group, groups, hidden, home, local, login_class, move_home, name, non_unique, password, password_lock, profile, remove, role, seuser, shell, skeleton, ssh_key_bits, ssh_key_comment, ssh_key_file, ssh_key_passphrase, ssh_key_type, state, system, uid, update_password"}
PLAY RECAP *********************************************************************
web01.example.com : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
[root@control httpd]# vim test.yml
---
- name: create user
hosts: all
tasks:
- name: modify /etc/hosts
lineinfile:
path: /etc/hosts
line: "10.10.10.132 web01.example.com"
state: present