用 Ansible 执行日常工作
这篇文章是Wano集团 2016年Advent Calendar中第22天的文章。
Ansible 是一种用作为配置管理工具,但是它也可以在日常的小任务中使用。安装特定的软件包,查看日志等操作,如果只需执行一次,似乎并不困难,但是当涉及到大量目标服务器时,逐个登录并执行这些操作会变得非常繁琐。为了处理这种情况,我们可以事先建立一个环境来执行这些操作,并且在实际操作时,只需编写一个 Ansible Playbook,并将其应用于所有服务器,从而减轻工作负担。
用于样本的配置。
服务器管理对象
操作系统
Ubuntu 14.04 is 尤布图 14.04.
生产 × 2 × 2)
-
- sample_prod_01
-
- sample_prod_02
- パスワード: prodpasswd
舞台设计 x 2
-
- sample_stage_01
-
- sample_stage_02
- パスワード: stagepasswd
发展 x 2
-
- sample_dev_01
-
- sample_dev_02
- パスワード: devpasswd
请用中文重述以下内容,只需要一种选项:
用户
管理员
-
- sudo 権限あり
-
- パスワードは上記の通り
- 管理マシン側から公開鍵認証にてSSHログイン可能
建造程序
这次将工作目录命名为ansible-work。(可以使用任何名称)
$ mkdir ansible-work
$ cd ansible-work
添加默认设置。
[defaults]
hostfile=hosts
管理目标服务器的设置
将要管理的服务器配置到 hosts 文件中。(与 /etc/hosts 不同。请在当前的 ansible-work 目录下创建此文件。)
[production]
sample_prod_01
sample_prod_02
[stage]
sample_stage_01
sample_stage_02
[development]
sample_dev_01
sample_dev_02
[生产][阶段][开发]是组名,我们在这里将每个服务器进行分组。
取消sudo命令时的密码输入
在这个例子中,每个环境的密码都是不同的。
使用带有-K选项的ansible-playbook来输入sudo密码的方法只能一次指定一个密码,对于每个环境都需要执行ansible-playbook非常麻烦。
如果事先为每个环境指定密码,那么就不需要输入密码了。
$ mkdir group_vars
---
ansible_ssh_user: admin
ansible_sudo_pass: prodpasswd
---
ansible_ssh_user: admin
ansible_sudo_pass: stagepasswd
---
ansible_ssh_user: admin
ansible_sudo_pass: devpasswd
---
remote_user: admin
请根据组名设置文件名。在 all.yml 中写入所有服务器共有的配置(稍后将在Playbook中使用)。
密码文件的加密
所以,对于个人使用来说这样已经可以了,但是如果在多个成员之间共享执行环境,最好不要把密码明文写在文件中。(即使只是个人使用,拥有密码明文文件也有点不安全感)
因此,我们将使用ansible-vault命令,对包含密码的文件进行共享钥匙方式的加密处理。
首先,将共享密钥保存在版本管理范围之外的位置。
$ echo samplepasswd > ~/.ansible_vault_pass
可以将“samplepasswd”作为密码使用。请根据需要进行更改。文件名也可以不按照上述方式命名,没有问题。
进行加密处理。
$ ansible-vault encrypt group_vars/production.yml --vault-password-file ~/.ansible_vault_pass
$ ansible-vault encrypt group_vars/stage.yml --vault-password-file ~/.ansible_vault_pass
$ ansible-vault encrypt group_vars/development.yml --vault-password-file ~/.ansible_vault_pass
实例
执行示例1:安装软件包。
请安装libxml2-dev软件包作为示例。创建如下文件。
$ mkdir tasks
---
- name: Install libxml2-dev
hosts: all
remote_user: "{{ remote_user }}"
become: yes
tasks:
- apt:
name: libxml2-dev
state: present
update_cache: yes
我会执行。
$ ansible-playbook tasks/install_libxml2-dev.yml --vault-password-file ~/.ansible_vault_pass
PLAY [Install libxml2-dev] *****************************************************
TASK [setup] *******************************************************************
ok: [sample_dev_02]
ok: [sample_prod_01]
ok: [sample_prod_02]
ok: [sample_dev_01]
ok: [sample_stage_01]
ok: [sample_stage_02]
TASK [apt] *********************************************************************
changed: [sample_dev_01]
changed: [sample_dev_02]
changed: [sample_prod_02]
changed: [sample_stage_01]
changed: [sample_prod_01]
changed: [sample_stage_02]
PLAY RECAP *********************************************************************
sample_dev_01 : ok=2 changed=1 unreachable=0 failed=0
sample_dev_02 : ok=2 changed=1 unreachable=0 failed=0
sample_prod_01 : ok=2 changed=1 unreachable=0 failed=0
sample_prod_02 : ok=2 changed=1 unreachable=0 failed=0
sample_stage_01 : ok=2 changed=1 unreachable=0 failed=0
sample_stage_02 : ok=2 changed=1 unreachable=0 failed=0
通过添加 –limit 选项,您可以将 libxml2-dev 包仅安装在开发环境中,而不是所有服务器上。
$ ansible-playbook --limit development tasks/libxml2-dev.yml --vault-password-file ~/.ansible_vault_pass
您也可以使用下述命令轻松执行。个人而言,我认为上述方法更可取,因为它可以保存操作记录并且结果易于查看。
ansible all -s -m apt -a 'name=libxml2-dev state=present update_cache=yes' --vault-password-file ~/.ansible_vault_pass
例2:检查包的版本
openssl等安全补丁经常发布的软件包,经常需要确认当前安装的版本是否为最新版本。因此,我们将创建一个Playbook,将版本写入文件并将其传输到本地。
- name: Check version of openssl
hosts: all
remote_user: "{{ remote_user }}"
become: no
vars:
outfile: /tmp/{{ inventory_hostname }}.txt
tasks:
- shell: echo {{ inventory_hostname }}
&& sh -c 'dpkg -l | grep openssl | grep -v gnutls'
&& echo >> {{ outfile }}
- fetch:
src: "{{ outfile }}"
dest: /tmp/openssl_version
flat: yes
fail_on_missing: yes
事先在管理机器上创建/tmp/openssl_version目录,然后进行执行。
$ mkdir /tmp/openssl_version
$ ansible-playbook tasks/openssl_version.yml --vault-password-file ~/.ansible_vault_pass
PLAY [Check version of openssl] ************************************************
TASK [setup] *******************************************************************
(...略...)
TASK [command] *****************************************************************
(...略...)
TASK [fetch] *******************************************************************
(...略...)
PLAY RECAP *********************************************************************
sample_dev_01 : ok=3 changed=2 unreachable=0 failed=0
sample_dev_02 : ok=3 changed=2 unreachable=0 failed=0
sample_prod_01 : ok=3 changed=2 unreachable=0 failed=0
sample_prod_02 : ok=3 changed=2 unreachable=0 failed=0
sample_stage_01 : ok=3 changed=2 unreachable=0 failed=0
sample_stage_02 : ok=3 changed=2 unreachable=0 failed=0
之后,
cat /tmp/openssl_version/*
如果执行该命令,可以列出每个服务器的 OpenSSL 版本。
sample_dev_01
ii openssl 1.0.1f-1ubuntu2.21 amd64 Secure Sockets Layer toolkit - cryptographic utility
sample_dev_02
ii openssl 1.0.1f-1ubuntu2.21 amd64 Secure Sockets Layer toolkit - cryptographic utility
(...略...)
sample_stage_02
ii openssl 1.0.1f-1ubuntu2.21 amd64 Secure Sockets Layer toolkit - cryptographic utility
只需要一个选项。+ 追加记录
在 Ansible 文档的 Vault 页面中
Ansible 1.5 新增了一个“Vault”功能,它允许将敏感数据(如密码或密钥)保存在加密文件中,而不是以明文形式存在于playbooks或roles中。这些密保文件可以进行分发或放置在源代码控制中。
「文件经过加密后可以发布」。虽然被加密了,但还是能够解密,所以最好从版本控制中排除以确保安全。