RHCE9学习指南 第27章ansible基本用法
如果管理的服务器很多,如几十几百台,那么就需要一个自动化管理工具了,ansible就是这样的一种自动化管理工具。
ansible是通过ssh连接到被管理主机,然后执行相关操作的,如图27-1所示。
图27-1 ansible通过ssh连接到被管理主机
ansible主机ssh到被管理主机时,需要提前设置密钥登录,这样可以让ansible主机可以无密码ssh到被管理主机。
本实验的拓扑图如图27-2所示。
图27-2 拓扑图
这里server是ansible主机,以lduan用户登录到server上。server2和server3是被管理主机,在这两台主机上创建lduan用户并配置好sudo,使得这两台主机上的lduan用户通过sudo -i可以无密码切换到root,下面开始配置。
27.1 安装ansible
先使用root用户登录server,下载好打包的文件ansible_rhel9.tar.gz,然后解压命令如下。
[root@server ~]# tar zxf ansible_rhel9.tar.gz
[root@server ~]#
在server上安装ansible,命令如下。
[root@server ~]# yum install ansible/* -y
正在更新 Subscription Management 软件仓库。
...输出...
[root@server ~]#
查看ansible的版本,命令如下。
[root@server ~]# ansible --version
ansible [core 2.13.0]
config file = /etc/ansible/ansible.cfg
...输出...
[root@server ~]#
这里安装的ansible的版本是2.13.0,同时也告诉ansible的默认配置文件是/etc/ansible/ansible.cfg。
因为新版的ansible里很多模块都没有集成在ansible-core里,它们是以collection的方式来加载,为了避免后面有的模块找不到,我们这里先安装ansible-collection-community-general(按照章节23.7讲解的内容,提前配置好epel源),命令如下。
[root@server ~]# yum install ansible-collection-community-general.noarch -y
正在更新 Subscription Management 软件仓库。
...输出...
已安装:
ansible-collection-community-general-7.5.0-1.el9.noarch
完毕!
[root@server ~]#
如果以ansible-navigator运行的话,系统会建立一个容器,然后ansible-navigator命令会启动一个容器,把命令放在此容器里运行。所以就需要一个镜像,先使用下面的命令登录镜像仓库。
podman login -u 用户名 -p 密码 registry.redhat.io
这里的用户名需要提前到红帽的网站上自己去注册一个账户,然后用下面的命令先拉取镜像。
podman pull registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest
每次执行ansible-navigator命令的时候,它都会重新拉取镜像,因为镜像的拉取策略默认是always。所以如果想优先使用本地已经拉取的命令,则需要在用户家目录下建立隐藏文件.ansible-navigator.yml或者.ansible-navigator.yaml,或者在当前所在目录下建立非隐藏文件ansible-navigator.yml或者ansible-navigator.yaml。这里在家目录下建立隐藏文文件 .ansible-navigator.yml ,内容如下。
[lduan@server ~]$ cat ~/.ansible-navigator.yml
---
ansible-navigator:
playbook-artifact:
enable: False
execution-environment:
image: registry.redhat.io/ansible-automation-platform-22/ee-supported-rhel8:latest
pull:
policy: never
[lduan@server ~]$
这里policy的值可以是['always', 'missing', 'never', 'tag']中的一个,意思分别如下:
awlays:总是拉取镜像,不管本地有没有镜像
missing:如果本地有镜像,则优先使用本地镜像,如果没有才去拉取
never:如果本地有则使用本地镜像,如果没有也不拉取
tag:如果所用镜像的tag是latest,则每次都会去拉取,以确保镜像是最新的。
这里选择的是never。
当我们后面通过ansible-navigator执行playbook的时候,会在当前目录下生成一个名字类似于"名字--artifact-2024-01-22T14:14:11.291194+00:00.json"这种格式的文件,这个文件是系统自动生成的剧本工具。这个剧本工具里记录了执行playbook的详细过程,如果不想输出此文件,所以我们在~/.ansible-navigator.yml里添加了如下内容:
playbook-artifact:
enable: False
更多参数可以读取到官方文档,地址是:https://ansible.readthedocs.io/projects/navigator/settings/#general-parameters
现在查看有多少collection,通过如下命令查看
ansible-navigator collections
显示结果之后,通过【ctrl+c】组合键终止。
还要确保ansible主机能够解析到所有的被管理机器,这里通过配置/etc/hosts来实现,/etc/hosts的内容如下。
[root@server ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.26.101 server.rhce.cc server
192.168.26.102 server2.rhce.cc server2
192.168.26.103 server3.rhce.cc server3
[root@server ~]#
在server2和server3两台机器上确认已经创建好了lduan用户,如果没有请自行创建,然后配置好sudo,命令如下。
[root@server2 ~]# cat /etc/sudoers.d/lduan
lduan ALL=(root) NOPASSWD: ALL
[root@server2 ~]#
[root@server3 ~]# cat /etc/sudoers.d/lduan
lduan ALL=(root) NOPASSWD: ALL
[root@server3 ~]#
这样在这两台机器上,lduan用户可以通过sudo -i无密码切换到root用户。
使用lduan用户登录server,配置好ssh密钥登录,使得用lduan用户可以无密码登录到server2和server3上,命令如下。
[lduan@server ~]$ ssh server2
Register this system with Red Hat Insights: insights-client --register
...输出...
[lduan@server2 ~]$ exit
注销
Connection to server2 closed.
[lduan@server ~]$ ssh server3
Register this system with Red Hat Insights: insights-client --register
...输出...
[lduan@server3 ~]$ exit
注销
Connection to server3 closed.
[lduan@server ~]$
27.2 编写ansible.cfg和清单文件
执行ansible命令或ansible-playbook命令或者ansible-navigator时,优先使用当前目录中ansible.cfg的配置。如果当前目录中没有,则使用默认的/etc/ansible.cfg中的配置。
下面的操作都是server上的lduan用户操作的,先在家目录下创建ansible.cfg内容如下。
[lduan@server ~]$ cat ansible.cfg
[defaults]
inventory = ./hosts
host_key_checking = False
remote_user = lduan
[privilege_escalation]
become=True
become_method=sudo
become_user=root
[lduan@server ~]$
这里在[defaults]字段下字段的解释:
inventory = ./hosts,表示把当前目录下名称为hosts的文件当做是清单文件(什么是清单文件马上就要讲到)。
host_key_checking :我们知道首次ssh到某台远端机器的时候,需要我们回复yes/no,这里host_key_checking = False的意思是系统自动回复yes
remote_user = lduan:这个指定的是以哪个用户身份ssh到远端服务器,如果后面我们用ansible-navigator,如果在ansible.cfg里没有指定此选项的话,则是使用root用户。
在[privilege_escalation]字段中定义了如何提升权限,因为使用lduan用户登录到被管理主机的,所以需要提权。这个字段中写了3条,分别如下。
(1)become=True:登录到被管理主机时要切换到其他用户。
(2)become_user=root:切换到root用户。
(3)become_method=sudo:以sudo的方式切换。
这三句的意思是,当ssh到被管理主机时,以sudo的方式切换到root,这也是为什么一开始要在被管理主机上配置好sudo的原因。
关于ansible.cfg里完整的选项,可以通过命令ansible-config init --disabled > ansible.cfg来获取。
所有的被管理机器都要写入清单文件中。在实验环境中有两台被管理主机,那么分别写在hosts中内容如下。
[lduan@server ~]$ cat hosts
server2
server3
[lduan@server ~]$
这里一行一台主机,我们在使用ansible或ansible-playbook命令时,指定的主机名必须要是这个名称才行。这里要确保能解析server2和server3,这里写成相应的IP也可以。
如果环境中被管理的主机很多,把主机一台台地写进去太冗繁,所以可以改成如下写法。
[lduan@server ~]$ cat hosts
server2
server3
server[10:15]
[lduan@server ~]$
这里加了一行server[10:15],表示server10到server15。这样在清单文件中就写了8台主机了(需要注意的是,在我们环境中server10到server15不存在)。
如果在执行ansible命令时只是想在部分主机上执行,那么在清单文件中可以对主机进行分组。定义主机组时,组名写在中括号"[]"中,在[]下面写的主机名都属于这个组,直到定义下一个组的位置为止。修改清单文件内容如下。
[lduan@server ~]$ cat hosts
server2
server3
server[10:15]
[db1]
server[2:5]
[db2]
server6
server7
[lduan@server ~]$
这里定义了两个主机组db1和db2,db1组中包括的主机机有server2到server5,db2组中包括的主机有server6和server7。
如果想定义一个主机组,这个组中包括db1和db2两个主机组的主机可以用children关键字,修改hosts内容如下。
[lduan@server ~]$ cat hosts
server2
server3
server[10:15]
[db1]
server[2:5]
[db2]
server6
server7
[db3:children]
db1
db2
[lduan@server ~]$
这里定义了一个主机组db3,但是后面加了":children",则这个主机组下面的db1和db2就不再是表示主机了,而是表示的主机组。所以,db3这个主机组中所包括的主机是server2到server5及server6和server7这台6主机。
下面查看每个主机组中有多少主机,首先查看主机组db1中的主机,命令如下。
[lduan@server ~]$ ansible db1 --list-hosts
hosts (4):
server2
server3
server4
server5
[lduan@server ~]$
共4台主机,查看主机组db2中的主机,命令如下。
[lduan@server ~]$ ansible db2 --list-hosts
hosts (2):
server6
server7
[lduan@server ~]$
共2台主机,查看主机组db3中的主机,命令如下。
[lduan@server ~]$ ansible db3 --list-hosts
hosts (6):
server2
server3
server4
server5
server6
server7
[lduan@server ~]$
这里一共是6台主机,和分析的是一样的。还有一个内置主机组叫作all,表示所有主机。
了解了清单文件的写法之后,最终把清单文件写成如下所示内容。
[lduan@server ~]$ cat hosts
server2
server3
[db]
server2
server3
[lduan@server ~]$
这里就包括了一个主机组db,里面含有server2和server3。
现在查看清单文件里所有主机组和主机之间的关系,可以通过如下命令查看。
[lduan@server ~]$ ansible-inventory --graph
@all:
|--@db3:
| |--@db1:
| | |--server2
| | |--server3
| | |--server4
| | |--server5
| |--@db2:
| | |--server6
| | |--server7
|--@ungrouped:
| |--server10
| |--server11
| |--server12
| |--server13
| |--server14
| |--server15
[lduan@server ~]$
27.3 ansible基本用法
ansible的基本用法如下。
ansible 机器名 -m 模块x -a "模块的参数"
这里的机器名必须要出现在清单文件中,整体的意思是在指定的机器上执行模块x,例如,在server2上执行hostname命令,命令如下。
[lduan@server ~]$ ansible server2 -m shell -a "hostname"
server2 | CHANGED | rc=0 >>
server2.rhce.cc
[lduan@server ~]$
shell模块用于执行操作系统命令,执行的命令就作为shell模块的参数,这里在-a中写要执行的系统命令。所以,上面的命令就是在server2上执行hostname命令,显示的结果是server2.rhce.cc。
要完成不同的任务就需要调用不同的模块来实现,系统中存在的所有ansible模块可以通过ansible-doc -l进行查看。
不同的模块有不同的参数,模块的参数及使用方法可以通过"ansible-doc 模块名"进行查看。
我们将在下一章讲解常见的ansible模块。
ansible-navigator exec -- 'ansible 机器名 -m 模块x -a "模块的参数" '
作业
1.在lduan家目录下编写ansible.cfg,满足如下要求:
(1)使用文件/home/lduan/hosts作为清单文件
(2)当lduan用户登录到被管理主机时,能自动地通过sudo切换到root用户
答案
[lduan@server ~]$ cat ansible.cfg
[defaults]
inventory = ./hosts
host_key_checking = False
remote_user = lduan
[privilege_escalation]
become=True
become_method=sudo
become_user=root
[lduan@server ~]$
2.编写清单文件/home/lduan/hosts,要求:
定义一个名称为db的主机组,里面包含2台主机server2和server3
答案
[lduan@server ~]$ cat hosts
[db]
server2
server3
[lduan@server ~]$
3.在db主机上执行一条系统命令"whoami"
[lduan@server ~]$ ansible db -m shell -a "whoami"
server2 | CHANGED | rc=0 >>
root
server3 | CHANGED | rc=0 >>
root
[lduan@server ~]$
或者
[lduan@server ~]$ ansible db -a "whoami"
server3 | CHANGED | rc=0 >>
root
server2 | CHANGED | rc=0 >>
root
[lduan@server ~]$
这里没有用-m指定模块,则默认为command模块。