一、安装ansible
环境:centos8
//配置阿里源
[root@localhost ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
[root@localhost ~]# sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
[root@localhost ~]# yum clean all
[root@localhost ~]# yum makecache
//安装ansible
[root@localhost ~]# yum install -y ansible
二、部署ansible
2.1 定义清单
清单定义Ansible将要管理的一批主机。这些主机也可以分配到组中,以进行集中管理。组可以包含子组,主机也可以是多个组的成员。清单还可以设置应用到它所定义的主机和组的变量。
可以通过两种方式定义主机清单。静态主机清单可以通过文本文件定义。动态主机清单可以根据需要使用外部信息提供程序通过脚本或其他程序来生成。
2.2 使用静态清单指定受管主机
静态清单文件是指定Ansible目标受管主机的文本文件。可以使用多种不同的格式编写此文件,包括INI样式或YAML。
在最简单的形式中。INI样式的静态清单文件是受管主机的主机名或IP地址的列表,每行一个:
alpha.example.org
beta.example.org
192.168.1.100
但通常而言,可以将受管主机组织为主机组。通过主机组,可以更加有效的对一系列系统运行Ansible。这时,每一部分的开头为以中括号括起来的主机组名称。其后为该组中每一受管主机的主机名或IP地址,每行一个。
[webservers]
alpha.example.org
beta.example.org
192.168.1.100
www[001:006].example.com //代表001到006
[dbservers]
db01.intranet.mydomain.net
db02.intranet.mydomain.net
10.25.1.56
db-[99:101]-node.example.com
2.3检验清单
[root@localhost ~]# vim /etc/ansible/hosts //添加下列
1.1.1.1 //无组的主机需添加到最前面
[webs] //组名
node1 //组内包含的主机
node2
[dbs]
node3
node4
//查看指定主机
[root@localhost ~]# ansible node1 --list-hosts
hosts (1):
node1
//查看指定组中的所有主机
[root@localhost ~]# ansible webs --list-hosts
hosts (2):
node1
node2
[root@localhost ~]# ansible dbs --list-hosts
hosts (2):
node3
node4
//查看所有主机
[root@localhost ~]# ansible all --list-hosts
hosts (4):
node1
node2
node3
node4
//查看无组的主机
[root@localhost ~]# ansible ungrouped --list-hosts
hosts (1):
1.1.1.1
2.4覆盖清单位置
/etc/ansible/hosts文件被视为系统的默认静态清单文件。不过,通常的做法是不使用该文件,而是在Ansible配置文件中为清单文件定义一个不同的位置。
2.5 构建Ansible清单
修改默认清单文件/etc/ansible/hosts添加以下内容:
172.16.103.129
[webservers]
172.16.103.130
172.16.103.131
使用以下命令列出默认清单文件中的所有受管主机:
ansible all --list-hosts
使用以下命令列出不属于任何组的受管主机:
ansible ungrouped --list-hosts
使用以下命令列出属于某组的受管主机:
ansible webservers --list-hosts
2.6自定义清单文件
[root@localhost ~]# cd /etc/ansible/
[root@localhost ansible]# cat inventory
[webservers]
web01.example.com
//设置主机192.168.132.128的主机名为control
[root@localhost ansible]# hostnamectl set-hostname control
[root@localhost ansible]# bash
[root@control ansible]#
//设置主机192.168.132.10的主机名为web01
[root@localhost ~]# hostnamectl set-hostname web01.example.com
[root@localhost ~]# bash
[root@web01 ~]#
//切换到控制段192.168.132.128
[root@control ~]# cat /etc/hosts //此文件添加服务器的ip和域名
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.132.10 web01.example.com
[root@control ~]# ping web01.example.com //测试通信
PING web01.example.com (192.168.220.10) 56(84) bytes of data.
64 bytes from web01.example.com (192.168.132.10): icmp_seq=1 ttl=64 time=0.718 ms
64 bytes from web01.example.com (192.168.132.10): icmp_seq=2 ttl=64 time=0.700 ms
^C
--- web01.example.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1057ms
rtt min/avg/max/mdev = 0.700/0.709/0.718/0.009 ms
查看所有主机
[root@control ~]# ansible all -i /etc/ansible/inventory --list-hosts
hosts (1):
web01.example.com
查看受webservers管理的主机
[root@control ~]# ansible webservers -i /etc/ansible/inventory --list-hosts
hosts (1):
web01.example.com
三.管理Ansible配置文件
3.1 配置Ansible
可以通过修改 Ansible 配置文件中的设置来自定义 Ansible安装的行为。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命令的目录中创建ansible.cfg文件。此目录中也将包含任何供Ansible项目使用的文件,如清单和playbook。这是用于Ansible配置文件的最常用位置。实践中不常使用~/.ansible.cfg或/etc/ansible/ansible.cfg文件
使用ANSIBLE_CONFIG环境变量
我们可以通过将不同的配置文件放在不同的目录中,然后从适当的目录执行Ansible命令,以此利用配置文件。但是,随着配置文件数量的增加,这种方法存在局限性并且难以管理。有一个更加灵活的选项,即通过ANSIBLE_CONFIG环境变量定义配置文件的位置。定义了此变量时,Ansible将使用变量所指定的配置文件,而不用上面提到的任何配置文件。
3.2 配置文件优先级
ansible.cfg文件内修改权限是最低的
[root@control ~]# cd /opt/
[root@control opt]# mkdir httpd/
[root@control opt]# cd httpd/
[root@control httpd]# vim inventory //创建清单
[root@control httpd]# cat inventory
[webservers]
web02.example.com
[root@control httpd]# cp /etc/ansible/ansible.cfg /opt/httpd/ //复制ansible的配置文件到httpd目录内
[root@control httpd]# ls
ansible.cfg inventory
[root@control httpd]# vim ansible.cfg
inventory = inventory //取消注释修改期清单位置 因为是配置文件和清单都放在httpd目录内 所以可以使用相对路径
[root@control httpd]# ansible all --list-hosts //查看所有主机
hosts (1):
web02.example.com
[root@control httpd]# ansible --version //安装的Ansible版本以及正在使用的配置文件
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, Mar 25 2022, 11:18:52) [GCC 8.5.0 20210514 (Red Hat 8.5.0-10)]
ANSIBLE_CONFIG环境变量指定的任何文件将覆盖所有其他配置文件。如果没有设置该变量,则接下来检查运行ansible命令的目录中是否有ansible.cfg文件。如果不存在该文件,则检查用户的家目录是否有.ansible.cfg文件。只有在找不到其他配置文件时,才使用全局/etc/ansible/ansible.cfg文件。如果/etc/ansible/ansible.cfg配置文件不存在,Ansible包含它使用的默认值。
修改环境变量
[root@control ~]# export ANSIBLE_CONFIG=/etc/ansible/ansible.cfg
[root@control ~]# 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, Mar 25 2022, 11:18:52) [GCC 8.5.0 20210514 (Red Hat 8.5.0-10)]
[root@control ~]# ansible all --list-hosts //查看清单所有主机
hosts (5):
1.1.1.1
node1
node2
node3
node4
3.3 管理配置文件中的设置
Ansible配置文件由几个部分组成,每一部分含有以键值对形式定义的设置。部分的标题以中括号括起来。对于基本操作,请使用以下两部分:
[defaults]部分设置Ansible操作的默认值
[privilege_escalation]配置Ansible如何在受管主机上执行特权升级
例如,下面是典型的ansible.cfg文件:
[defaults]
inventory = ./inventory
remote_user = user
ask_pass = false
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
部署ansible(控制主机与被控主机)全过程
//被控主机
[root@web01 ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: e>
Active: inactive (dead)
Docs: man:firewalld(1)
[root@localhost ~]# hostnamectl set-hostname web01.example.com
[root@localhost ~]# bash
[root@web01 ~]#
[root@web01 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:14:8b:cf brd ff:ff:ff:ff:ff:ff
inet 192.168.31.130/24 brd 192.168.31.255 scope global dynamic noprefixroute ens160
valid_lft 1175sec preferred_lft 1175sec
inet6 fe80::20c:29ff:fe14:8bcf/64 scope link noprefixroute
valid_lft forever preferred_lft forever
//控制主机
[root@localhost ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor pres>
Active: inactive (dead)
Docs: man:firewalld(1)
[root@localhost ~]# cd /etc/ansible/
[root@localhost ansible]# pwd
/etc/ansible
[root@localhost ansible]# vim inventory
[root@localhost ansible]# cat inventory
[webservers]
web01.example.com
[root@localhost ansible]# hostnamectl set-hostname control
[root@localhost ansible]# bash
[root@control ansible]# vim /etc/hosts
[root@control ansible]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.31.130 web01.example.com
[root@control ansible]# ping web01.example.com
PING web01.example.com (192.168.31.130) 56(84) bytes of data.
64 bytes from web01.example.com (192.168.31.130): icmp_seq=1 ttl=64 time=0.259 ms
64 bytes from web01.example.com (192.168.31.130): icmp_seq=2 ttl=64 time=0.239 ms
64 bytes from web01.example.com (192.168.31.130): icmp_seq=3 ttl=64 time=0.330 ms
^C
--- web01.example.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2082ms
rtt min/avg/max/mdev = 0.239/0.276/0.330/0.039 ms
[root@control ansible]# ansible web01.example.com -i /etc/ansible/inventory --list-hosts
hosts (1):
web01.example.com
[root@control ansible]# cd
[root@control ~]# ls
anaconda-ks.cfg Documents initial-setup-ks.cfg Pictures Templates
Desktop Downloads Music Public Videos
[root@control ~]# mkdir httpd
[root@control ~]# ls
anaconda-ks.cfg Documents httpd Music Public Videos
Desktop Downloads initial-setup-ks.cfg Pictures Templates
[root@control ~]# cd httpd
[root@control httpd]# pwd
/root/httpd
[root@control httpd]# ls
[root@control httpd]# cp /etc/ansible/ansible.cfg .
[root@control httpd]# ls
ansible.cfg
[root@control httpd]# vim inventory
[root@control httpd]# cat inventory
[webservers]
web01.example.com
[root@control httpd]# vim ansible.cfg
[root@control httpd]# cd
[root@control ~]# mv httpd /opt/
[root@control ~]# ls
anaconda-ks.cfg Documents initial-setup-ks.cfg Pictures Templates
Desktop Downloads Music Public Videos
[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 ansible.cfg
[defaults]
# some basic default values...
inventory = inventory //这一行改成这样
#library = /usr/share/my_modules/
#module_utils = /usr/share/my_module_utils/
[root@control httpd]# export ANSIBLE_CONFIG=/opt/httpd/ansible.cfg
[root@control httpd]# 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 httpd]# ansible webservers --list-hosts
hosts (1):
web01.example.com
[root@control httpd]# ansible webservers -m ping
The authenticity of host 'web01.example.com (192.168.31.130)' can't be established.
ECDSA key fingerprint is SHA256:BxGnpHODRFdM0jcbOgO5SKFma+geH9tsJts7L9uhtHE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
web01.example.com | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Warning: Permanently added 'web01.example.com,192.168.31.130' (ECDSA) to the list of known hosts.\r\nroot@web01.example.com: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"unreachable": true
}
[root@control httpd]# cd
[root@control ~]# vim /opt/httpd/inventory
[root@control ~]# cat /opt/httpd/inventory
[webservers]
web01.example.com ansible_user=root ansible_password=runtime
[root@control ~]# ansible webservers -m ping
web01.example.com | UNREACHABLE! => {
"changed": false,
"msg": "Invalid/incorrect password: Permission denied, please try again.",
"unreachable": true
}
[root@control ~]# ssh-keygen -t rsa
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:W16vSA92V7YddUh2MmmSt4cvFXpI0gl+kc7R2VhobG4 root@control
The key's randomart image is:
+---[RSA 3072]----+
| .o+O==|
| ..oO@O.|
| .=O=o+|
| .=E.=|
| S . ...=o|
| + . ..o=|
| . = . oo.|
| o = o |
| . o |
+----[SHA256]-----+
[root@control ~]# ls .ssh/
id_rsa id_rsa.pub known_hosts
[root@control ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.31.130
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/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@192.168.31.130's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@192.168.31.130'"
and check to make sure that only the key(s) you wanted were added.
[root@control ~]# ssh root@192.168.31.130
Activate the web console with: systemctl enable --now cockpit.socket
This system is not registered to Red Hat Insights. See https://cloud.redhat.com/
To register this system, run: insights-client --register
Last failed login: Mon Jun 13 18:48:14 CST 2022 from 192.168.31.128 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Mon Jun 13 16:55:31 2022
[root@web01 ~]# exit
logout
Connection to 192.168.31.130 closed.
[root@control ~]# ansible webservers -m ping
web01.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@control ~]#