你应该知道的关于Ansible的15件事

最近一直在用 Ansible 做一些东西,决定分享我在学习过程中学到的一些东西,我认为你应该知道的关于 Ansible 的 15 件事的清单。 如果你觉得有什么遗漏的,欢迎留言分享!

1 - 您可以将参数传递给角色

创建角色来组织您的剧本是一个很好的做法。 假设我们想要创建一个安装Jenkins的角色。 此角色的文件夹结构可能如下所示:

1
2
3
4
5
6
jenkins/
files/
templates/
tasks/
handlers/
defaults/

文件夹 defaults 用于存储角色的默认变量值。在其中我们可以有这个 main.yml 文件:

1
2
3
jenkins_port: 8080
jenkins_context_path: /jenkins
jenkins_home: /jenkins

您可以通过将不同的参数传递给角色来覆盖默认变量,如下所示:

1
2
3
roles:
- { role: jenkins, jenkins_port: 8181, jenkins_home: '/jenkins1' }
- { role: jenkins, jenkins_port: 8080, jenkins_home: '/jenkins2' }

2 - 如何使命令模块具有幂等性

幂等性是某些操作的属性,可以多次执行而不改变初始应用程序的结果。 这个概念出现在大多数Ansible模块中:您指定了所需的最终状态,Ansible决定是否应该运行任务。 默认情况下,此原则不适用于command模块。 默认情况下,如果您在playbook中有以下任务,它将始终运行:

1
- command: /usr/bin/create-database.sh

为了实现幂等性,您可以使用属性creates 。 如果存在,Ansible将仅在模式指定的文件不存在时运行命令任务。 或者,您可以使用removes ,它仅在指定的文件存在时才执行任务。

1
- command : /usr/bin/create-database.sh creates = /path/to/database

始终要记住,Ansible有很多模块,大多数常见操作都不需要使用命令模块。 例如,有一些模块用于创建文件系统 , 修改iptables和管理cron条目 。 默认情况下,所有这些模块都是幂等的,因此您始终应该更喜欢它们。

3 - 使用Ansible安装程序模块收集有关主机的信息

你可能已经看到Ansible在运行一个剧本时所做的第一件事是这样的:

1
TASK [ setup] ******************* ok: [ servername]

发生这种情况是因为Ansible在执行第一个任务之前调用特殊模块setup 。 设置模块连接到主机并收集各种详细信息:IP地址,磁盘空间,CPU架构,可用内存等。 手动调用此模块可能很有用,可以快速收集有关主机的信息。 为此,只需运行以下命令:

1
2
3
4
5
6
7
8
9
$ ansible localhost -m setup
localhost | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.27.12.77",
"192.168.33.1"
],
(MANY more facts)
}

4 - 您可以列出剧本的所有任务

想要记住剧本的作用吗? 使用–list-tasks标志运行ansible-playbook ,Ansible将列出其所有任务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ ansible-playbook install-jenkins.yml --list-tasks
PLAY: #1
tasks:
TASK: meta
TASK: open-jdk : Install open jdk 1.8
TASK: mount-partition : Creating the filesystem for the device {{ device }} (if needed)
TASK: mount-partition : Mounting the device {{ device }} on path {{ path }}
TASK: jenkins : Ensure Jenkins repo is installed.
TASK: jenkins : Add Jenkins repo GPG key.
TASK: jenkins : Ensure Jenkins is present.
TASK: jenkins : Ensures that the home directory exists
TASK: jenkins : include
TASK: jenkins : Ensure Jenkins is started and runs on startup.
TASK: jenkins : Wait for Jenkins to start up before proceeding.
TASK: jenkins : Get the jenkins-cli jarfile from the Jenkins server.

5 - 如果要存储敏感信息,请使用ansible-vault

如果您的某个任务需要敏感信息(比如数据库用户和密码),最好将这些信息加密,而不是以纯文本形式存储。

Ansible附带一个名为ansible-vault的命令行工具,允许您创建和管理加密文件。 这样,您可以将加密文件提交到源代码控制,只有拥有解密密码的用户才能读取它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Encrypt an existing file. You'll need to create an encryption password.
ansible-vault encrypt secrets.yml

# Creates a new, encrypted file. You'll need to create an encryption password.
ansible-vault create secrets.yml

# Decrypt a file. You'll have to enter password used for encryption.
# Use it with caution! Don't leave your files unecrypted.
ansible-vault decrypt secrets.yml

# Edit an encrypted file (uses vim by default, can be overriden by the environment variable $EDITOR)
ansible-vault edit secrets.yml

# Print the contents of the encrypted file
ansible-vault edit secrets.yml

如果您在Playbook中导入vars_file secrets.yml,Ansible将失败,因为它不知道如何读取加密文件。 您必须指定命令行参数–ask-vault-pass ,这将使Ansible提示您加密文件的密码。

1
ansible-playbook playbook.yml -i hosts --ask-vault-password

另一种方法是将密码存储在一个文件中(不应该提交),并使用–vault-password-file参数指定文件的路径。 如果此文件标记为可执行文件,Ansible将运行它并使用输出作为密码。

6 - 使用with_items可能是个好主意

当您使用with_items子句时,Ansible将创建一个名为{ {item } }的变量,其中包含当前迭代的值。 有些模块可以很好地处理项目集合,实际上比使用不同参数多次运行相同任务更快。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Installing all packages with one task (faster)
- name: install required packages using the apt module
apt: package={{ item }} update_cache=yes
sudo: True
with_items:
- git
- memcached
- nginx

# Installing packages individually (slower)
- name: install git
apt: package=git update_cache=yes
sudo: True

- name: install memcached
apt: package=memcached update_cache=yes
sudo: True

- name: install nginx
apt: package=nginx update_cache=yes
sudo: True

7 - 本地行动的运作方式

有时您可能希望在本地计算机上运行任务,而不是在远程计算机上运行它。 当我们想要等待服务器启动(如果它刚刚启动)或者我们想要在负载均衡器池中添加一些节点(或删除它们)时,这可能很有用:

1
2
3
4
5
6
7
8
9
10
11
tasks:
- name: take out of load balancer pool
local_action: >
command /usr/bin/take_out_of_pool {{ inventory_hostname }}

- name: update application
yum: name=acme-web-stack state=latest

- name: add back to load balancer pool
local_action: >
command /usr/bin/take_out_of_pool {{ inventory_hostname }}

下面是如何启动EC2实例并等待其可用的示例:

1
2
3
4
5
6
7
8
9
10
11
- name: Launching EC2 Instance
# instance options here
register: ec2


- name: Waiting for ec2 instances to listen on port 22
wait_for:
state=started
host={{ item.public_dns_name }}
port=22
with_items: ec2.instances

8 - 您可以告诉Ansible仅运行一次任务

有时您可能只想运行一次任务,即使有多个主机也是如此。 例如,假设您有多个连接到同一数据库的应用程序服务器,并且您有一个执行数据库迁移的任务。 在这种情况下,您只需运行此任务一次。

要实现这一点,您可以使用run_once参数告诉Ansible只运行一次命令:

1
2
3
- name: run the database migrations
command: bundle exec rake db:migrate
run_once: true

9 - 处理程序是特殊类型的任务

处理程序是具有唯一名称的任务,只有在被另一个任务通知时才会执行。 它们对于重新启动服务或重新引导系统非常有用。

被通知的处理程序将在剧本结束时执行一次 ,无论他们被通知多少次。 您可以使用handler子句声明它们并使用notify触发它们。

下面是一个示例,说明当文件内容发生更改时如何重新启动两个服务,但仅当文件更改时(从Ansible 文档中提取):

1
2
3
4
5
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache

应该在你的剧本中的其他地方声明处理程序:

1
2
3
4
5
6
handlers:
- name: restart memcached
# The service module was used, but you could use whatever module you wanted
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted

10 - 用流水线加速
您可以采取一些措施使Ansible运行得更快:

  • 启用流水线操作

启用流水线操作可以减少在远程服务器上执行模块所需的SSH操作数,方法是将脚本传送到SSH会话而不是复制它。 启用后,这可以显着提高性能。

不过你应该小心。 只有在sudoers文件(/ etc / sudoers)中的所有远程计算机上禁用选项requiretty管道requiretty才有效。

1
2
[ssh_connection]
pipelining = True
  • 关闭事实收集或启用事实缓存

如果您未在任务中使用任何Ansible事实,则可以禁用“事实收集”步骤以提高速度。 为此,只需在playbook中添加属性gather_facts: False :

1
2
3
4
5
- hosts: servername
gather_facts: False
tasks:
- name: ...
# ...

或者,如果您确实需要使用Ansible事实(由安装任务自动收集),您可以缓存它们,以便后续执行更快。 Ansible文档在此详细介绍了这一点 ,如果您想了解更多信息。

11 - Ansible有几个通知模块

使用Ansible自动进行蓝绿部署? 运行Playbooks以在AWS上配置新实例? 让您的团队使用其中一个通知模块。 例如,下面的任务将发送带有自定义消息的松弛通知:

1
2
3
4
5
6
7
8
9
10
11
- hosts: servername
tasks:
- name: Send notification message via Slack
local_action:
module: slack
# To retrieve your slack token, open your team settings and look for the
# Incoming Webhooks plugin
token: <your>/<token>/<goes here>
msg: "Hello team! I just finished updating our production environment."
channel: "#general"
username: "ansible-bot"

还有一些模块可用于通知irc,twillio,hipchat,jabber 等等 。

12 - EC2实例按其标签自动分组

使用Amazon Web Services和Ansible的EC2动态库存脚本时,所有实例都将根据其特征(例如类型,密钥对和标记)进行分组。 EC2标签只是key =与您的实例关联的名称值,您可以随意使用它们。 有些人使用标签对其生产/登台服务器进行分组,在蓝绿部署期间标记Web服务器甚至“活动”服务器。

当按标记对主机进行分组时,EC2动态库存脚本使用以下模式(不带括号):

1
tag_[TAG_NAME]_[TAG_VALUE]

因此,如果要在标签为env=staging所有主机上运行任务,只需将其添加到您的playbook:

1
2
3
4
hosts: tag_env_staging
tasks:
- name: This task will be run on all servers with env == staging
# ...

为了使它更有趣,您可以使用Ansible模式( docs )更具体地说明哪些主机应该受任务影响。 例如,如果要在生产数据库服务器上执行特定任务(假设它们已正确标记),则可以使用交叉模式( :& ),如下所示:

1
2
3
4
hosts: tag_env_production&:tag_type_db
tasks:
- name: This task will be run on all servers with tags 'env=production' and 'type=db'
# ...

13 - 您可以在“Dry Run”模式下运行

Ansible支持在干运行模式下运行一个剧本(也称为检查模式),在这种模式下,Ansible 不会对你的主机进行任何更改,而只是报告如果没有这个标志运行剧本就会发生什么变化。

1
$ ansible-playbook --check playbook.yml

虽然这在某些情况下很有用,但如果您的任务使用条件步骤,它可能无法正常工作。

14 - 任务可以一步一步地进行

有时您不想在游戏手册中运行所有任务。 当你编写一个新的剧本并想要测试它时,这有点常见。 Ansible提供了一种方法,通过使用–step标志,让您决定要运行哪些任务。 它会让你选择是否要运行任务(y),跳过它(n)或(c)ontinue而不要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
# playbook.yml
- hosts: servername
tasks:
- name: First task
# ...
- name: Second task
# ...

$ ansible-playbook provision.yml -i hosts --step

> Perform task: TASK: setup (y/n/c): n #
> Perform task: TASK: First task (y/n/c): n
> Perform task: TASK: Second task (y/n/c): y

15 - 可以根据标签运行任务

您可以将一个或多个标签添加到任务或游戏中。 为此,只需使用tags属性标记要标记的内容:

1
2
3
4
5
6
7
8
9
10
11
12
# playbook.yml
- hosts: servername
tags:
- server
tasks:
- name: Download optional files
tags:
- download
- optional
- name: Install dependencies
tags:
- dependencies

稍后您可以使用标志–tags (或简称-t )和–skip-tags –tags 来决定运行或跳过哪些标签:

1
2
3
4
5
# will run only tasks with the tag 'dependencies'
$ ansible-playbook --tags=dependencies playbook.yml

# will run all tasks except the ones that contain the tag 'optional'
$ ansible-playbook --skip-tags=optional playbook.yml

您可以通过用逗号分隔来指定多个标记。

参考:

http://codeheaven.io/15-things-you-should-know-about-ansible/

hoxis wechat
一个脱离了高级趣味的程序员,关注回复1024有惊喜~
赞赏一杯咖啡
0%