您是那种典型的系统管理员吗?总是工作太多而时间不够?在整个服务器场中进行简单的 DNS 服务器更改或调整内核参数,这种可能性是否会让您感到紧张?甚至更糟糕的是,要根据可变系统特征(如已安装的内存或发布版本)进行更改?您企业中的开发人员是否在整个 DevOps 过程中使用另一种语言与您沟通?  

红帽 Ansible 自动化是一款无代理的人类可读自动化工具,这款工具使用 SSH 在平面或多层环境中编排配置管理、应用部署和置备。红帽 Ansible 自动化基于开源 Ansible 技术,且该技术已成为世界上最受欢迎的开源 IT 自动化技术之一。

这篇博客文章将帮助您了解 Ansible 的基础知识,以及系统管理员如何使用该技术更高效地管理系统。

在开始之前,我们需要定义一些术语:

控制节点:您使用 Ansible 在受管节点上执行任务的主机

受管节点:由控制节点配置的主机

主机清单:受管节点的列表

临时命令:简单的一次性任务

Playbook:一组可重复的任务,用于更复杂的配置

模块:执行特定常见任务(如添加用户、安装软件包等)的代码

幂等性:如果执行一次运算的结果与重复执行的结果完全相同,且没有进行任何干预操作,则该运算是幂等的。

环境

本文中的环境包括一个控制节点(vm1)和四个受管节点(vm2、vm3、vm4、vm5),所有这些节点都在虚拟环境中运行,仅需安装最小的红帽企业 Linux 7.4 即可。为了简单起见,控制节点在 /etc/hosts 文件中具有以下条目:

192.168.102.211 vm1 vm1.redhat.lab 
192.168.102.212 vm2 vm2.redhat.lab 
192.168.102.213 vm3 vm3.redhat.lab 
192.168.102.214 vm4 vm4.redhat.lab 
192.168.102.215 vm5 vm5.redhat.lab

为了方便使用,我将在此次演示中为我的系统用户提供无密码 sudo,因为您的安全策略可能不同,Ansible 可以处理各种权限升级的用例。该用户帐户已通过 /etc/sudoers 文件中的以下条目配置为权限升级:

%wheel ALL=(ALL) NOPASSWD: ALL

这仅仅是一个示例,您可能希望使用自己的 sudo 配置变体。  

最终,为该用户帐户配置并测试了从控制节点到每个受管节点的 SSH 公钥身份验证。

安装

用于红帽企业 Linux 7 的 Ansible 位于 Extras 频道。如果您使用的是红帽企业 Linux 6,请启用 EPEL 存储库。对于适用于企业 Linux 的额外软件包(EPEL),客户门户中的该解决方案也可能有所帮助。在 Fedora 系统上,您可以在基本存储库中找到 Ansible。

配置合适的存储库后,即可快速简单地进行安装:

[curtis@vm1 ~]$ sudo yum install -y ansible 

检查一下版本:

[curtis@vm1 ~]$ ansible --version
ansible 2.4.1.0
 config file = /etc/ansible/ansible.cfg
 configured module search path = [u'/home/curtis/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
 ansible python module location = /usr/lib/python2.7/site-packages/ansible
 executable location = /bin/ansible
 python version = 2.7.5 (default, May 3 2017, 07:55:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-14)]

请注意,默认配置文件和 python 是必需的,并且存在于最小的红帽企业 Linux 7.4 安装中。

配置

由于我们已经通过用户帐户、权限升级和 SSH 公钥身份验证对受管节点进行配置,因此我们将继续配置控制节点。

控制节点的配置包括 Ansible 配置文件和主机清单文件。

配置文件

正如我们刚才发现的,默认配置文件是 /etc/ansible/ansible.cfg

您可以修改该全局配置文件,或创建特定于特定目录的副本。配置文件所在的顺序如下:

  • ANSIBLE_CONFIG(环境变量)
  • ansible.cfg(每个目录)
  • ansible.cfg(主目录)
  • /etc/ansible/ansible.cfg(全局)

在这篇文章中,我将使用之前添加的用户帐户的主目录中最小的配置文件:

[curtis@vm1 ~]$ cat ansible.cfg 
[defaults] 
inventory = $HOME/hosts 

主机清单

默认主机清单文件为 /etc/ansible/hosts, 但可以通过配置文件(如上所示)或使用 ansible 命令上的 -i 选项进行更改。我们将使用一个简单的静态清单文件。动态清单也是可以的,但不在本篇文章的讨论范围内。

我们的主机清单文件如下:

[webservers] 
vm2 
vm3 

[dbservers] 
vm4 

[logservers] 
vm5 

[lamp:children] 
webservers 
dbservers 

我们已经定义了四组:vm2 和 vm3 上的 Web 服务器、vm4 上的数据库服务器、vm5 上的日志服务器以及由 Web 服务器和数据库服务器组所组成的 lamp。

确认一下可以使用该配置文件定位所有主机:

[curtis@vm1 ~]$ ansible all --list-hosts
 hosts (4):
   vm5
   vm2
   vm3
   vm4

对于单个组(如 Web 服务器组)也是如此:

[curtis@vm1 ~]$ ansible webservers --list-hosts
 hosts (2):
   vm2
   vm3

现在我们已经验证了主机清单,接下来快速检查以确保所有主机都已启动并运行。我们将通过使用 ping 模块的临时命令来执行此操作:

[curtis@vm1 ~]$ ansible all -m ping
vm4 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}
vm5 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}
vm3 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}
vm2 | SUCCESS => {
   "changed": false, 
   "failed": false, 
   "ping": "pong"
}

从上面的输出中我们可以看出,所有系统都返回了一个成功的结果,没有任何变化,并且每个“ping”的结果是“pong”。

您可以使用以下命令获取可用模块的列表:

[curtis@vm1 ~]$ ansible-doc -l 

内置模块的数量随着每个 Ansible 版本而持续增加:

[curtis@vm1 ~]$ ansible-doc -l | wc -l 
1378 

每个模块的文档都可以在 http://docs.ansible.com/ansible/latest/modules_by_category.html 找到

环境中的最后一个设置任务是使用 Apache 和红帽企业 Linux 7 yum 存储库配置 vm1,以便受管节点安装其他软件包:

[root@vm1 ~]# yum install -y httpd
[root@vm1 ~]# systemctl enable httpd
[root@vm1 ~]# systemctl start httpd
[root@vm1 ~]# mkdir /media/iso
[root@vm1 ~]# mount -o loop /root/rhel-server-7.4-x86_64-dvd.iso /media/iso
[root@vm1 ~]# ln -s /media/iso /var/www/html/rhel7

准备就绪,开始使用 Ansible!

现在我们已经配置环境并准备就绪,可以使用 Ansible 执行一些切实工作了。

由于受管节点需要安装一些额外的软件包,那么我们的第一个任务就是使用该配置文件在每个主机上配置一个 yum 存储库:

[curtis@vm1 ~]$ cat dvd.repo
[RHEL7]
name = RHEL 7
baseurl = http://vm1/rhel7/
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
enabled = 1
gpgcheck = 1

我们可以使用临时命令,将该文件复制到每个受管节点,复制模块使用 -m 选项,同时使用 -a 选项指定所需参数,如下所示:

[curtis@vm1 ~]$ ansible all -m copy -a 'src=dvd.repo dest=/etc/yum.repos.d owner=root group=root mode=0644' -b
vm5 | SUCCESS => {
   "changed": true, 
   "checksum": "c15fdb5c1183f360ce29a1274c5f69e4e43060f5", 
   "dest": "/etc/yum.repos.d/dvd.repo", 
   "failed": false, 
   "gid": 0, 
   "group": "root", 
   "md5sum": "db5a5da08d1c4be953cd0ae6625d8358", 
   "mode": "0644", 
   "owner": "root", 
   "secontext": "system_u:object_r:system_conf_t:s0", 
   "size": 135, 
   "src": "/home/curtis/.ansible/tmp/ansible-tmp-1516898124.58-210025572567032/source", 
   "state": "file", 
   "uid": 0
}

[...]

为了简洁起见,已删除其余主机的额外输出。

此时,有一些项目值得注意:

  1. 每个节点报告“成功”和“已更改”:true 表示模块执行成功,并且文件已创建/已更改。如果我们再次运行该命令,输出将包括“已更改”:false 则表示该文件已存在并根据需要进行配置。换句话说,Ansible 只会在所需更改尚不存在的情况下进行更改。这就是所谓的“幂等性”。

  2. -b 选项(参见 http://docs.ansible.com/ansible/latest/become.html)使远程任务使用权限升级(即 sudo),这是将文件复制到 /etc/yum.repos.d 目录的必要条件

  3. 您可以了解复制模块需要使用哪些参数:

[curtis@vm1 ~]$ ansible-doc copy 

 

Ansible Playbook

尽管临时命令对于测试和简单的一次性任务是有用的,但 playbook 可用来捕获一组可重复的任务,方便其在将来运行。Playbook 包含一个或多个 play,这些 play 定义了一组要配置的主机和要执行的任务列表。

在我们的情景中,我们需要配置 Web 服务器、数据库服务器和集中式日志服务器。具体要求为:

  1. httpd 软件包安装在 Web 服务器上,启用并启动

  2. 每个 Web 服务器都有一个默认页面,其中包含“欢迎使用位于 <ip address> 的 <hostname>”文本

  3. 每个 Web 服务器都有一个用户帐户,该帐户有适用于内容管理的访问权限

  4. MariaDB 软件包安装在数据库服务器上,启用并启动

  5. 日志服务器主机配置为可接受远程日志记录消息

  6. Web 服务器和数据库服务器组中的主机将日志消息的副本发送至日志服务器主机

 

以下 playbook(myplaybook.yml)将配置我们需要的一切内容。

在查看 playbook 时,请注意下列事项:

  1. 用户模块需要明文密码的哈希值(详细信息请参阅“ansible-doc 用户”)。这可以实现如下

    • [curtis@vm1 ~]$ python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())" Password: $6$rounds=656000$bp7zTIl.nar2WQPS$U5CBB15GHnzBqnhY0r7UX65FrBI6w/w9YcAL2kN9PpDaYQIDY6Bi.CAEL6PRRKUqe2bJYgsayyh9NOP1kUy4w.
  2. 默认网页内容是使用从主机收集的“事实”创建的。您可以使用设置模块,发现并使用主机事实:

[curtis@vm1 ~]$ ansible vm2 -m setup

---
- hosts: webservers
 become: yes
 tasks:
   - name: install Apache server
     yum:
       name: httpd
       state: latest

   - name: enable and start Apache server
     service:
       name: httpd
       enabled: yes
       state: started

   - name: open firewall port
     firewalld:
       service: http
       immediate: true
       permanent: true
       state: enabled

   - name: create web admin group
     group:
       name: web
       state: present

   - name: create web admin user
     user:
       name: webadm
       comment: "Web Admin"
       password: $6$rounds=656000$bp7zTIl.nar2WQPS$U5CBB15GHnzBqnhY0r7UX65FrBI6w/w9YcAL2kN9PpDaYQIDY6Bi.CAEL6PRRKUqe2bJYgsayyh9NOP1kUy4w.
       groups: web
       append: yes

   - name: set content directory group/permissions 
     file:
       path: /var/www/html
       owner: root
       group: web
       state: directory
       mode: u=rwx,g=rwx,o=rx,g+s

   - name: create default page content
     copy:
       content: "Welcome to {{ ansible_fqdn}} on {{ ansible_default_ipv4.address }}"
       dest: /var/www/html/index.html
       owner: webadm
       group: web
       mode: u=rw,g=rw,o=r

- hosts: dbservers
 become: yes
 tasks:
   - name: install MariaDB server
     yum:
       name: mariadb-server
       state: latest

   - name: enable and start MariaDB server
     service:
       name: mariadb
       enabled: yes
       state: started

- hosts: logservers
 become: yes
 tasks:
   - name: configure rsyslog remote log reception over udp
     lineinfile:
       path: /etc/rsyslog.conf
       line: "{{ item }}"
       state: present
     with_items:
       - '$ModLoad imudp'
       - '$UDPServerRun 514'
     notify:
       - restart rsyslogd

   - name: open firewall port
     firewalld:
       port: 514/udp
       immediate: true
       permanent: true
       state: enabled

 handlers:
   - name: restart rsyslogd
     service:
       name: rsyslog
       state: restarted

- hosts: lamp
 become: yes
 tasks:
   - name: configure rsyslog
     lineinfile:
       path: /etc/rsyslog.conf
       line: '*.* @192.168.102.215:514'
       state: present
     notify:
       - restart rsyslogd

 handlers:
   - name: restart rsyslogd
     service:
       name: rsyslog
       state: restarted

如何运行 Ansible playbook?

我们的 playbook 可以通过以下方式运行:

[curtis@vm1 ~]$ ansible-playbook myplaybook.yml 

从下面的输出中,我们可以看到 Web 服务器配置仅发生在 vm2 和 vm3(play 1)上,而数据库安装在 vm4 上(play 2),日志服务器(vm5)使用 play 3 配置。最后,play 4 通过“lamp”组配置 Web 服务器和数据库服务器主机,从而实现远程日志记录。

PLAY [webservers] *********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm2]
ok: [vm3]

TASK [install Apache server] **********************************************************
changed: [vm3]
changed: [vm2]

TASK [enable and start Apache server] *************************************************
changed: [vm2]
changed: [vm3]

TASK [open firewall port] *************************************************************
changed: [vm2]
changed: [vm3]

TASK [create web admin group] *********************************************************
changed: [vm3]
changed: [vm2]

TASK [create web admin user] **********************************************************
changed: [vm3]
changed: [vm2]

TASK [set content directory group/permissions] ****************************************
changed: [vm3]
changed: [vm2]

TASK [create default page content] ****************************************************
changed: [vm3]
changed: [vm2]

PLAY [dbservers] **********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm4]

TASK [install MariaDB server] *********************************************************
changed: [vm4]

TASK [enable and start MariaDB server] ************************************************
changed: [vm4]

PLAY [logservers] *********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm5]

TASK [configure rsyslog remote log reception over udp] ********************************
changed: [vm5] => (item=$ModLoad imudp)
changed: [vm5] => (item=$UDPServerRun 514)

TASK [open firewall port] *************************************************************
changed: [vm5]

RUNNING HANDLER [restart rsyslogd] ****************************************************
changed: [vm5]

PLAY [lamp] ***************************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [vm3]
ok: [vm2]
ok: [vm4]

TASK [configure rsyslog] **************************************************************
changed: [vm2]
changed: [vm3]
changed: [vm4]

RUNNING HANDLER [restart rsyslogd] ****************************************************
changed: [vm3]
changed: [vm2]
changed: [vm4]

PLAY RECAP ****************************************************************************
vm2                        : ok=11 changed=9 unreachable=0    failed=0 
vm3                        : ok=11 changed=9 unreachable=0    failed=0 
vm4                        : ok=6 changed=4 unreachable=0    failed=0 
vm5                        : ok=4 changed=3 unreachable=0    failed=0 

大功告成!

您可以使用以下命令验证 Web 服务器主机:

[curtis@vm1 ~]$ curl http://vm2
Welcome to vm2 on 192.168.102.212
[curtis@vm1 ~]$ curl http://vm3
Welcome to vm3 on 192.168.102.213 

以及使用 Web 服务器和数据库主机上的 logger 命令进行远程日志记录:

[curtis@vm1 ~]$ ansible lamp -m command -a 'logger hurray it works'
vm3 | SUCCESS | rc=0 >>

vm4 | SUCCESS | rc=0 >>

vm2 | SUCCESS | rc=0 >>

在中央日志服务器上进行确认:

[curtis@vm1 ~]$ ansible logservers -m command -a "grep 'hurray it works$' /var/log/messages" -b
vm5 | SUCCESS | rc=0 >>
Jan 30 13:28:29 vm3 curtis: hurray it works
Jan 30 13:28:29 vm2 curtis: hurray it works
Jan 30 13:28:29 vm4 curtis: hurray it works

技巧和提示

如果您是 YAML 新手,起初语法可能会相当棘手,尤其是在空格(无制表符)方面。

在运行 playbook 之前,您可以使用以下命令检查语法:

$ ansible-playbook --syntax-check myplaybook.yml 

使用带有语法高亮显示功能的 vim 不仅有助于学习 yaml,还有助于查找语法问题。针对 yaml 语法启用 vim 的快速方法为将以下行添加到 ~/.vimrc 文件中:

 

autocmd Filetype yaml setlocal tabstop=2 ai colorcolumn=1,3,5,7,9,80

如果您想要使用具有更多功能的工具,包括颜色,可以在此处找到一个这样的插件。
如果您更喜欢使用 emacs 而非 vim,请启用 EPEL 存储库,并安装 emacs-yaml-mode 软件包。

无需对目标主机进行任何实际更改,您便可以测试 playbook:

$ ansible-playbook --check myplaybook.yml 

逐步完成 playbook 也可能有帮助:

$ ansible-playbook --step myplaybook.yml 

与 shell 脚本相似,您可以将 Ansible playbook 设为可执行文件,并将以下内容添加到文件顶部:

#!/bin/ansible-playbook 

要执行任意临时 shell 命令,请使用命令模块(如果未指定 -m,则为默认模块)。 如果您需要使用重定向、管道等,那么请使用 shell 模块。

查看特定模块文档中的“示例:”部分,加快剧本 playbook。

在 playbook 中使用字符串引号,以避免字符串出现特殊字符的问题。

默认情况下日志记录禁用。要启用日志记录,请使用 Ansible 配置文件中的 log_path 参数。

我希望这篇文章能帮助您更好地了解 Ansible 的工作原理,以及它如何使用 playbook 轻松且准确地记录并重复单调乏味的任务,以此来节省时间和精力。务必要继续在 http://docs.ansible.comhttps://www.redhat.com/en/technologies/management/ansible 学习。

开心自动化!

 

图像 Curtis Rempel,RHCA,加拿大高级平台 TAM 和团队负责人,曾是红帽认证讲师和考官(RHCI/RHCX)。他的 Linux 之旅始于 1994 年 Jon “maddog” Hall 的红帽 Linux 2.1 CD。作为 TAM,他利用自己在自动化、内核和存储方面的专业知识为金融、电信行业和航空行业的企业客户提供支持。了解有关 Curtis 的更多信息。

帽大客户技术经理(TAM)是专业的产品专家,其与 IT 企业协作,通过战略规划实现成功部署,并帮助企业获得最佳性能和增长。TAM 是红帽的世界级 客户体验与互动服务企业的一部分,可提供前瞻性的建议和指导,帮助您在潜在问题发生之前识别和解决它们。如果出现问题,TAM 会利用我们最好的资源尽快帮助解决问题,同时将对您业务的干扰降至最低。

在您附近的红帽 Convergence 活动与 TAM 联系!红帽 Convergence 是一项仅限邀请的免费活动,可为技术用户提供机会来加深其对红帽产品知识的理解,并发现应用开源技术实现其业务目标的新方法。这些活动将在世界各地的城市举办,为您提供方便的、本地一日游体验,帮助您与红帽专家和行业同仁相互学习并建立联系。

开源将好奇心协同合作。参加 5 月 8 日至 10 日在旧金山举行的红帽全球峰会,与 TAM 和其他红帽专家面对面交流!现在注册,使用代码 CEE18,仅需 1,100 美元。

红帽云成功案例通过丰富的产品专业知识、指导和支持,旨在帮助您简化 IT 转型,同时加速采用云技术。从概念验证阶段到生产阶段,技术精湛的云技术专家将与您合作,为您提供可持续性,并帮助您确保云解决方案的成功实施。通过这种限时互动,红帽云成功案例可以帮助您有效地规划和部署云解决方案,并为未来制定战略性规划。