yinxin
作者yinxin5天前
项目经理, 某集团公司

非常好的Ansible入门教程

字数 18925阅读 54评论 2赞 6

Ansible是一个配置管理和配置工具,类似于Chef,Puppet或Salt。这是一款很简单也很容易入门的部署工具,它使用SSH连接到服务器并运行配置好的任务,服务器上不用安装任何多余的软件,只需要开启ssh,所有工作都交给client端的ansible负责。

关于Ansible的一个好处是,将bash脚本转换为可执行任务是非常容易的。我们可以编写自己的配置程序,但是Ansible更加干净,因为它可以自动在执行任务之前获取上下文。ansible任务是幂等的,没有大量额外的编码,ansible可以一次又一次地安全运,而bash命令这种幂等性。

ansible使用“facts”来确保任务的幂等安全运行, 它是在运行任务之前收集的系统和环境信息。ansible使用这些facts来检查状态,看看是否需要改变某些东西以获得所需的结果。这使得ansible可以让服务器一次又一次地运行可复制的任务。

1 安装

当然我们需要先安装Ansible。任务可以从任何可安装的机器上运行。

1.1 Ubuntu

在Ubuntu 16.04上安装Ansible的方法。

sudo apt-get install -y ansible

apt-get安装的ansible版本很低,建议使用pip方式安装

sudo pip install ansible

2 配置

ansible的默认配置文件路径为 /etc/ansible,然而,一个常见的用途是将其安装在一个virtualenv中,在这种情况下,我们一般不会使用这些默认文件。我们可以根据需要在本地目录中创建配置文件。

2.1 管理服务器:Inventory文件

您可以创建一个inventory文件,用于定义将要管理的服务器。这个文件可以命名为任何名字,但我们通常会命名为hosts或者项目的名称。

在hosts文件中,我们可以定义一些要管理的服务器。这里我们将定义我们可能要在“web”标签下管理的两个服务器。标签是任意的。

[web]
192.168.22.10
192.168.22.11

现在已经够好了,如果需要,我们可以定义主机范围,多个组,可重用变量,并使用其他花哨的设置,包括创建动态的inventory。

当我们在本地机器运行ansible时,我们不需要关心inventory文件中的内容,我将告诉您在本地和远程服务器上运行ansible。现在,让我们将hosts文件设置为指向本地主机local和remote虚拟远程主机。
hosts文件:

[local]
127.0.0.1

[remote]
192.168.1.2

与本地主机和远程服务器连接的命令。

2.2 基础:运行命令

我们开始对服务器运行任务。ansible会假定你的服务器具有SSH访问权限,通常基于SSH-Key。因为Ansible使用SSH,所以它需要能够SSH连接到服务器。但是,ansible将尝试以正在运行的当前用户身份进行连接。如果我正在运行ansible的用户是ubuntu,它将尝试以ubuntu连接其他服务器。

Run against localhost

$ ansible -i ./hosts --connection=local local -m ping

Run against remote server

$ ansible -i ./hosts remote -m ping
127.0.0.1 | success >> {
"changed": false,
"ping": "pong"
}

如果你是在cygwin下运行,遇到了“Failed to connect to the host via ssh: mux_client_request_session: read from master failed”的错误,可以执行:

ansible -i ./hosts remote -v -m ping -u root --private-key=~/.ssh/id_rsa

使用–connection=local告诉ansible不尝试通过SSH运行命令,因为我们只是影响本地主机。但是,我们仍然需要一个hosts文件,告诉我们连接到哪里。
在任何情况下,我们可以看到从ansible得到的输出是一些JSON,它告诉我们Task(我们对ping模块的调用)是否进行了任何更改和结果。

命令说明:

-i ./hosts - 设置库存文件,命名为 hosts
remote,local,all-使用这个标签的下定义的服务器hosts清单文件。“all”是针对文件中定义的每个服务器运行的特殊关键字
-m ping- 使用“ping”模块,它只是运行ping命令并返回结果
-c local| --connection=local - 在本地服务器上运行命令,而不是SSH

一些常用命令:
-i PATH --inventory=PATH 指定host文件的路径,默认是在/etc/ansible/hosts
--private-key=PRIVATE_KEY_FILE_PATH 使用指定路径的秘钥建立认证连接
-m DIRECTORY --module-path=DIRECTORY 指定module的目录来加载module,默认是/usr/share/ansible
-c CONNECTION --connection=CONNECTION 指定建立连接的类型,一般有ssh ,local

2.2.1 模块(Modules)

ansible使用“模块”来完成大部分的任务。模块可以做安装软件,复制文件,使用模板等等。
模块是使用Ansible 的方法

因为它们可以使用可用的上下文(“Facts”),以便确定要完成任务需要做什么操作。
如果我们没有模块,我们将运行任意的shell命令,我们也可以使用bash脚本。这是一个任意shell命令看起来像在Ansible(它使用的shell模块!):

Run against a local server

ansible -i ./hosts local --connection=local -b --become-user=root \
-m shell -a 'apt-get install nginx'

Run against a remote server

ansible -i ./hosts remote -b --become-user=root all \
-m shell -a 'apt-get install nginx'

这里,sudo apt-get install nginx命令将使用“shell”模块运行。
命令说明:

-b - “成为”,在运行命令时告诉可以成为另一个用户。
--become-user=root - 以用户“root”运行以下命令(例如,使用命令使用“sudo”)。我们可以在此定义任何现有的用户。
-a 用于将任何参数传递给定义的模块 -m

但是这并不是特别强大。尽管能够一次在所有服务器上运行这些命令,但是我们仍然只能完成任何bash脚本可能执行的操作。如果我们使用了更合适的模块,我们可以运行命令来保证结果。可靠的模块确保我们可以一次又一次地运行相同的任务,而不会影响最终结果。
要在Debian / Ubuntu服务器上安装软件,“apt”模块将运行相同的命令,但确保幂等。

Run against a local server

ansible -i ./hosts local --connection=local -b --become-user=root \
-m apt -a 'name=nginx state=installed update_cache=true'

127.0.0.1 | success >> {
"changed": false
}

Run against a remote server

ansible -i ./hosts remote -b --become-user=root \
-m apt -a 'name=nginx state=installed update_cache=true'

127.0.0.1 | success >> {
"changed": false
}

or:
ansible -i ./hosts remote -v -m apt -a 'name=nginx state=installed update_cache=true' -u test -s -K --private-key=~/.ssh/id_rsa

这将使用apt模块来更新存储库缓存并安装Nginx(如果没有安装)。
运行任务的结果是”changed”: false。这表明没有变化; 我已经使用该shell模块安装了Nginx 。好的是,我可以一遍又一遍地运行这个命令,而不用担心它会改变预期的结果 - Nginx已经安装,Ansible知道,并且不尝试重新安装它。
命令说明:

-i ./hosts - 设置inventory文件,命名为 hosts
-b - “成”,告诉可以成为另一个用户来运行命令
--become-user=root - 以用户“root”运行以下命令(例如,使用“sudo”命令)
local| remote - 从库存文件中的本地或远程定义的主机上运行
-m apt- 使用apt模块
-a 'name=nginx state=installed update_cache=true' - 提供apt模块的参数,包括软件包名称,所需的结束状态以及是否更新软件包存储库缓存

常用命令:
-u USERNAME --user=USERNAME 指定移动端的执行用户
-U SUDO_USERNAME --sudo-user=USERNAME
-s --sudo -u指定用户的时候,使用sudo获得root权限
-k --ask-pass 提示输入ssh的密码,而不是使用基于ssh的密钥认证
-K --ask-sudo-pass 提示输入sudo密码,与--sudo一起使用

我们可以通过这种特殊方式运行我们所需要的所有任务(通过模块),但是让我们来做这个更具管理性。我们将把这个任务移动到一个Playbook中,它可以运行和协调多个Tasks。
2.3 剧本(Playbooks)

Playbook可以运行多个任务,并提供一些更高级的功能。让我们将上述任务移到一本剧本中。在ansible中剧本(playbooks)和角色(roles)都使用Yaml文件定义。
创建文件nginx.yml:


hosts could have been "remote" or "all" as well

  • hosts: local connection: local become: yes become_user: root tasks:
    • name: Install Nginx apt: name: nginx state: installed update_cache: true

此任务与我们的ad-hoc命令完全相同,包括设置本地连接的使用。
这将使用inventory文件中[local]标签下的服务器hosts。
如果我们没有使用本地连接,我们会这样做:


  • hosts: remote become: yes become_user: root tasks:
    • name: Install Nginx apt: name: nginx state: installed update_cache: true

这将使用inventory文件中[remote]标签下的服务器hosts。

在我们的Tasks文件中使用become并become_user再次使用Ansible来sudo以root用户身份运行命令,然后传递Playbook文件。

使用一个yaml playbook文件,我们需要使用这个ansible-playbook命令,现在就更容易运行:

$ ansible-playbook -i ./hosts nginx.yml

PLAY [local] ******************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [Install Nginx] *********************************************************
ok: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0

我们在运行过程中获得了一些有用的反馈,包括“可执行任务”运行及其结果。在这里我们看到所有运行都OK,但没有改变。我已经安装了Nginx
2.3.1 处理程序(Handlers)

处理程序与任务完全相同(它可以做task可以做的任何事),但只有当另一个任务调用它时才会运行。您可以将其视为事件系统的一部分; 处理程序将通过其侦听的事件调用进行操作。
这对于运行任务后可能需要的“辅助”操作非常有用,例如在配置更改后安装或重新加载服务后启动新服务。


Example shows using the local machine still

Remove 'connection' and set hosts to 'remote' for a remote connection

  • hosts: local
    connection: local
    become: yes
    become_user: root
    tasks:

    • name: Install Nginx apt: name: nginx state: installed update_cache: true notify:
      • Start Nginx

    handlers:

    • name: Start Nginx service: name: nginx state: started

这里我们添加一个notify指令到安装任务。这将在任务运行后通知名为“Start Nginx”的处理程序。

然后我们可以创建名为“Start Nginx”的处理程序。此处理程序是通知“Start Nginx”时调用的任务。
这个特定的处理程序使用服务模块,它可以启动,停止,重启,重新加载(等等)系统服务。在这种情况下,我们告诉Ansible,我们要启动Nginx。
让我们再次运行这本Playbook:

$ ansible-playbook -i ./hosts nginx.yml

PLAY [local] ******************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [Install Nginx] *********************************************************
ok: [127.0.0.1]

NOTIFIED: [nginx | Start Nginx] ***********************************************
ok: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0

我们得到类似的输出,但是这次Handler是运行的。
通知程序只在运行任务时运行。
Note:如果我已经安装了Nginx,则安装Nginx任务将不会运行,通知程序也将不会被调用。

我们可以使用Playbook来运行多个任务,添加变量,定义其他设置,甚至包括其他的剧本。
2.3.2 更多的任务(More Tasks)

接下来,我们可以为此Playbook添加更多的任务,并探索其他一些功能。


Example shows using the local machine still

Remove 'connection' and set hosts to 'remote' for a remote connection

  • hosts: local
    connection: local
    become: yes
    become_user: root
    vars:

    • docroot: /var/www/serversforhackers.com/public tasks:
    • name: Add Nginx Repository
      apt_repository:
      repo: ppa:nginx/stable
      state: present
      register: ppastable

    • name: Install Nginx
      apt:
      pkg: nginx
      state: installed
      update_cache: true
      when: ppastable|success
      notify:

      • Start Nginx
    • name: Create Web Root
      file:
      path: '{{ docroot }}'
      mode: 775
      state: directory
      owner: www-data
      group: www-data
      notify:

      • Reload Nginx

    handlers:

    • name: Start Nginx
      service:
      name: nginx
      state: started

    • name: Reload Nginx
      service:
      name: nginx
      state: reloaded

现在有三个任务:

Add Nginx Repository- 使用apt_repository模块添加Nginx稳定PPA以获取最新的稳定版本的Nginx 。
Install Nginx - 使用Apt模块安装Nginx。
Create Web Root - 最后创建一个Web根目录。

新的register和when指令,可以实现在某些事情发生后让ansible执行任务的功能。
Note: 您还可以注册模块操作的结果,并使用定义的变量根据注册(register)的变量值有条件(when)地执行操作。例如,注册通过shell模块运行命令的结果可以让您访问该命令的stdout。

同时还使用了一个变量。docroot变量在定义vars部分。然后将其用作创建定义目录的文件模块的目标参数。

需要注意的是,path配置使用括号{{ var-name }},这是Jinja2的模板。为了使Ansible能够在括号内解析Jinja2模板变量,该行必须是单引号或双引号 - 例如,path: ‘{{ docroot }}’而不是path: {{ docroot }}。不使用引号将导致错误。
这个playbook可以用通常的命令运行:

ansible-playbook -i ./hosts nginx.yml

所以,我们已经运行了一些ad-hoc命令,使用了可复制的模块,并将一些相关任务组织到一个手册中。

接下来,我们将通过将Playbook组织成一个角色进一步获得可靠性,这有助于我们组织相关项目,如文件和模板,同时还帮助我们组织更复杂的相关任务和操作。
2.4 角色(roles)

角色很适合组织多个相关任务并封装完成这些任务所需的数据。例如,安装Nginx可能涉及添加软件包存储库,安装软件包和设置配置。
此外,真实的配置通常需要额外的数据,如变量,文件,动态模板等等。这些工具可以与Playbook一起使用,但是我们可以通过将相关任务和数据组织成一个角色(role, 相关的结构)很快就能做得更好。
角色有一个这样的目录结构:

roles
rolename
- files
- handlers
- meta
- templates
- tasks
- vars

在每个子目录中(eg: files,handlers等等),Ansible将自动搜索并读取叫做main.yml的yaml文件。
接下来我们将分解nginx.yml文件内容为不同的组件,并将每个组件放在相应的目录中,以创建一个更干净,更完整的配置工具集。
2.4.1 创建角色(Creating a Role)

我们可以使用ansible-galaxy命令来创建一个新角色。此工具可用于将角色保存到Ansible的公共注册表,但是我通常只是使用它来在本地创建role的基础目录结构。

我们来看看如何设置:

Head to our previously created directory

cd ~/ansible-example

In case we left our virtualenv at some point

source .venv/bin/activate

Create a roles directory

mkdir roles
cd roles

Bootstrap a new role named "nginx"

ansible-galaxy init nginx

目录名称roles是一种惯例,在运行一个playbook时可以用来查找角色。该目录应该始终被命名roles,但并不强制。在roles目录中运行 ansible-galaxy init nginx 命令将创建新角色所需的目录和文件。

我们来看看我们新建的nginx角色的每个部分~/ansible-example/roles/nginx。
2.4.2 文件(files)

首先,在files目录中,我们可以添加我们要复制到我们的服务器中的文件。对于nginx,我经常复制H5BP的Nginx组件配置。我只需从Github下载最新的信息,进行一些调整,并将它们放入files目录中。

~/ansible-example
- roles
- - nginx
- - - files
- - - - h5bp

我们稍后会看到,H5BP配置文件将通过复制模块添加到服务器。
2.4.3 处理程序(handlers)

我们可以把曾经在nginx.yml 剧本中的定义的所有处理程序放入到handlers目录中。约定必须包含main.yml文件。

handlers/main.yml 内容:


  • name: Start Nginx
    service:
    name: nginx
    state: started

  • name: Reload Nginx
    service:
    name: nginx
    state: reloaded

一旦handlers/main.yml中的处理程序定义好了,我们可以自由地从其他的yaml配置中引用它们。
2.4.4 元(meta)

meta目录中的main.yml文件包含Role元数据,包含的依赖关系。如果这个角色依赖于另一个角色,我们可以在这里定义。例如,nginx角色取决于安装SSL证书的ssl角色。约定必须包含main.yml文件。
meta/main.yml 内容:


dependencies:
- { role: ssl }

如果我调用了“nginx”角色,它将尝试首先运行“ssl”角色。
否则我们可以省略此文件,或将角色定义为没有依赖关系:


dependencies: []

2.4.5 模板(templates)

基于Python的Jinja2模板引擎(和django的模板引擎很类似),模板文件可以包含模板变量。这里的文件应该以.j2为类型后缀(eg.uwsgi.j2),提倡但是不强制,也可以取其他的名字。类似于files,在templates目录中没有main.yml文件,只包含.j2后缀的模板文件。
这是一个Nginx服务器(“虚拟主机”)配置的例子。请注意,它使用了稍后在vars/main.yml文件中定义的一些变量。
我们的示例中的Nginx配置文件位于templates/serversforhackers.com.conf.j2:

server {
# Enforce the use of HTTPS
listen 80 default_server;
server_name {{ domain }};
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl default_server;

root /var/www/{{ domain }}/public;
index index.html index.htm index.php;

access_log /var/log/nginx/{{ domain }}.log;
error_log  /var/log/nginx/{{ domain }}-error.log error;

server_name {{ domain }};

charset utf-8;

include h5bp/basic.conf;

ssl_certificate           {{ ssl_crt }};
ssl_certificate_key       {{ ssl_key }};
include h5bp/directive-only/ssl.conf;

location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt  { log_not_found off; access_log off; }

location ~ \.php$ {
    include snippets/fastcgi.conf;
    fastcgi_pass unix:/var/run/php7.1-fpm.sock;
}

}

这是一个相当标准的用于PHP应用程序的Nginx配置。这里有三个变量:


ssl_crt
ssl_key
这三个变量将在变量部分(vars)中定义。
2.4.6 变量(vars)

在使用任务集成所有事情之前,让我们来看看变量。该vars目录包含一个main.yml文件(如handlers和meta目录一样),在main.yml中我们可以列出将要使用的所有变量。
以下是该vars/main.yml文件的内容:


domain: serversforhackers.com
ssl_key: /etc/ssl/sfh/sfh.key
ssl_crt: /etc/ssl/sfh/sfh.crt

我们可以在这个角色的其他地方使用这三个变量。我们在上面的模板中看到它们的使用,但是我们也可以在我们定义的任务中看到它们。
Note:如果您有敏感信息添加到变量文件中,则可以使用ansible-vault加密文件,下面将对此进行说明。
2.4.7 任务(tasks)

终于到了将一切都是放在一系列的任务中的时候了。
使用角色时运行的主文件是tasks/main.yml文件。看看我们的用例将会是什么样的:


  • name: Add Nginx Repository
    apt_repository:
    repo: ppa:nginx/stable
    state: present

  • name: Install Nginx
    apt:
    pkg: nginx
    state: installed
    update_cache: true
    notify:

    • Start Nginx
  • name: Add H5BP Config
    copy:
    src: h5bp
    dest: /etc/nginx
    owner: root
    group: root

  • name: Disable Default Site Configuration
    file:
    dest: /etc/nginx/sites-enabled/default
    state: absent

dest in quotes as a variable is used!

  • name: Add SFH Site Config register: sfhconfig template: src: serversforhackers.com.j2 dest: '/etc/nginx/sites-available/{{ domain }}.conf' owner: root group: root

src/dest in quotes as a variable is used!

  • name: Enable SFH Site Config file: src: '/etc/nginx/sites-available/{{ domain }}.conf' dest: '/etc/nginx/sites-enabled/{{ domain }}.conf' state: link

dest in quotes as a variable is used!

  • name: Create Web root file: dest: '/var/www/{{ domain }}/public' mode: 775 state: directory owner: www-data group: www-data notify:
    • Reload Nginx

dest in quotes as a variable is used!

  • name: Web Root Permissions file: dest: '/var/www/{{ domain }}' mode: 775 state: directory owner: www-data group: www-data recurse: yes notify:
    • Reload Nginx

这一系列任务使得Nginx能被完整的安装。任务按照出现的顺序完成以下工作:

1 添加nginx / stable库
2 安装并启动Nginx
3 添加H5BP配置文件
4 从sites-enabled目录中删除文件的符号链接来禁用默认的Nginx配置
5 将serversforhackers.com.conf.j2虚拟主机模板复制到Nginx配置中,渲染模板
6 通过将其符号链接到sites-enabled目录来启用Nginx服务器配置
7 创建Web根目录
8 更改项目根目录的权限(递归),该目录位于之前创建的Web根目录之上

有一些新的模块(和一些我们已经涵盖的新用途),包括复制,模板和文件模块。通过设置每个模块的参数,我们可以做一些有趣的事情,例如确保文件“不存在”(如果存在则删除它们)的state: absent,或者通过创建一个文件作为符号链接的state: link。您应该检查每个模块的文档,以查看可以用它们完成哪些有趣和有用的事情。
2.4.8 运行角色(Running the Role)

要对服务器运行一个或多个角色,我们将重新使用另一个playbook。该playbook与roles目录位于同一个目录中,同一层级。当我们用ansible-playbook命令运行的时候需要先cd进入到该目录中。
让我们创建一个“主”的yaml文件(被ansible-playbook命令执行的文件),该文件定义要使用的角色以及运行它们的主机:
文件~/ansible-example/server.yml位于与roles目录相同的目录中:


run locally here, yadda yadda yadda

  • hosts: local connection: local roles:
    • nginx

所以,我们只是定义角色,而不是在本Playbook文件中定义所有的变量和任务。角色负责具体细节。

然后我们可以运行角色:

ansible-playbook -i ./hosts server.yml

以下是运行Nginx角色的Playbook文件的输出:

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [nginx | Add Nginx Repository] ******************************************
changed: [127.0.0.1]

TASK: [nginx | Install Nginx] *************************************************
changed: [127.0.0.1]

TASK: [nginx | Add H5BP Config] ***********************************************
changed: [127.0.0.1]

TASK: [nginx | Disable Default Site] ******************************************
changed: [127.0.0.1]

TASK: [nginx | Add SFH Site Config] *******************************************
changed: [127.0.0.1]

TASK: [nginx | Enable SFH Site Config] ****************************************
changed: [127.0.0.1]

TASK: [nginx | Create Web root] ***********************************************
changed: [127.0.0.1]

TASK: [nginx | Web Root Permissions] ******************************************
ok: [127.0.0.1]

NOTIFIED: [nginx | Start Nginx] ***********************************************
ok: [127.0.0.1]

NOTIFIED: [nginx | Reload Nginx] **********************************************
changed: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1 : ok=8 changed=7 unreachable=0 failed=0

我们将所有各种组件放在一起,形成一致的角色,现在已经安装并配置了Nginx!
2.5 事实(Facts)

请注意,运行剧本时的第一行总是“收集事实”。
在运行任何任务之前,Ansible将收集有关其配置的系统的信息。这些被称为事实,并且包括广泛的系统信息,如CPU核心数量,可用的ipv4和ipv6网络,挂载的磁盘,Linux发行版等等。

事实在“任务”或“模板”配置中通常很有用。例如,Nginx通常设置为使用与CPU内核一样多的工作处理器。知道这一点,您可以选择如下设置nginx.conf.j2文件的模板:

user www-data;
worker_processes {{ ansible_processor_cores }};
pid /var/run/nginx.pid;

And other configurations...

或者如果你具有多个CPU的服务器,则可以使用:

user www-data;
worker_processes {{ ansible_processor_cores * ansible_processor_count }};
pid /var/run/nginx.pid;

And other configurations...

所有的ansible facts全局变量都是以“anisble_”为前缀,并且可以在其他任何地方使用。
尝试对你的本地机器运行以下内容以查看可用的事实:

Run against a local server

Note that we say to use "localhost" instead of defining a hosts file here!

ansible -m setup --connection=local localhost

Run against a remote server

ansible -i ./hosts remote -m setup

2.6 加密(Vault)

我们经常需要将敏感数据存储在我们的模板,文件或变量文件中; 这样安全性有一定要求的情况是不可避免的(当我们将这些敏感数据文件推送到远程Git仓库时,这是一个痛苦的事情)。Ansible有一个叫做Ansible Vault的解决方案。
Vault允许您加密任何Yaml文件,通常将其作用与变量文件,Vault不会加密文件和模板,只能使用Yaml文件。
在创建加密文件时,系统会询问您必须使用的密码,以便稍后在调用角色或Playbook时进行编辑。
将密码保存在安全的地方。

例如我们可以创建一个新的变量文件:

ansible-vault create vars/main.yml
Vault Password:

输入加密密码后,该文件将在您的默认编辑器(通常是Vim或Nano)中打开。
默认使用的编辑器由EDITOR环境变量定义。默认值通常是Vim。如果您不是Vim用户,可以通过设置环境变量来快速更改:

EDITOR=nano ansible-vault edit vars/main.yml

在大多数情况下,我们将使用ansible-vault create|edit /path/to/file.yml。更多可用的命令如下:

create - 创建一个新文件并进行加密
decrypt - 从加密文件创建明文文件
edit - 编辑已经存在的加密文件
encrypt - 加密现有的纯文本文件
rekey - 在加密文件中设置新密码

如果你有一个现有的配置文件要加密,请使用 ansible-vault encrypt /path/to/file.yml。
示例: users角色

我们创建一个名为“users”的角色:

cd ~/ansible-example/roles
ansible-galaxy init users

创建新用户并设置密码时,我使用Vault 。在用户角色中,您可以设置带有用户密码和公钥的变量文件,以添加到用户的authorized_keys文件(从而提供SSH访问权限)。公共SSH密钥在技术上是安全的,一般公众可以看到 - 所有人都可以使用它来允许你访问自己的服务器。在没有配对私钥的情况下,公钥是不能获得系统访问权限的,我们没有将密钥加入此角色。
以下是可以使用Vault创建和加密的示例变量文件。在编辑它时,它是纯文本。

~/ansible-example/roles/users/vars/main.yml:

admin_password: $6$lpQ1DqjZQ25gq9YW$mHZAmGhFpPVVv0JCYUFaDovu8u5EqvQi.Ih
deploy_password: $6$edOqVumZrYW9$d5zj1Ok/G80DrnckixhkQDpXl0fACDfNx2EHnC
common_public_key: ssh-rsa ALongSSHPublicKeyHere

请注意,用户的密码也是散列的。您可以阅读Ansible有关生成加密密码的文档,用户模块需要设置用户密码。作为一个快速入门,它在Ubuntu上看起来像这样:

The whois package makes the mkpasswd

command available on Ubuntu

$ sudo apt-get install -y whois

Create a password hash

$ mkpasswd --method=SHA-512
Password:

这将生成一个散列密码供你与user模块一起使用。
Note:变量文件中的密码是散列的,但我仍然喜欢加密包含散列密码的yaml文件。这些文件通常包含未标记的数据,如API令牌或SSH私钥,使加密非常重要。

一旦你设置了用户密码并将公钥添加到变量文件中,我们就可以加密此文件,然后在任务中使用这些加密变量。

ansible-vault encrypt roles/users/vars/main.yml

然后我们可以编辑我们的任务文件,使用(加密)变量添加新用户:

这是文件~/ansible-example/roles/users/tasks/main.yml:


  • name: Create Admin User
    user:
    name: admin
    password: '{{ admin_password }}'
    groups: sudo
    append: yes
    shell: /bin/bash

  • name: Add Admin Authorized Key
    authorized_key:
    user: admin
    key: '{{ common_public_key }}'
    state: present

  • name: Create Deploy User
    user:
    name: deploy
    password: '{{ deploy_password }}'
    groups: www-data
    append: yes
    shell: /bin/bash

  • name: Add Deployer Authorized Key
    authorized_key:
    user: deploy
    key: '{{ common_public_key }}'
    state: present

这些任务使用该user模块来创建新用户,传递变量文件中设置的密码。
它还使用该authorized_key模块将SSH公钥作为SSH授权密钥添加到每个用户的服务器中。
加密变量的使用像在常规任务文件中使用一样。但是,为了运行此角色,我们需要告诉Ansible请求输入vault密码,以便它可以解密变量。
编辑我们的server.ymlPlaybook文件,调用user角色:


Local connection here, yadda yadda yadda

  • hosts: local connection: local sudo: yes roles:
    • nginx
    • user

要运行此Playbook,我们需要告知Ansible请求vault的密码,因为我们正在运行包含加密文件的角色:

ansible-playbook --ask-vault-pass -i ./hosts server.yml

3 总结

本篇文章带着做了如下工作:

安装了ansible
配置了ansible inventory文件(仅在不使用connection: local 时才需要)
同时在多个服务器上执行幂等的 ad-hoc命令
创建一个基本的Playbook来运行多个任务(tasks),并使用了处理程序(handlers)
将多个任务抽象为一个角色,以保持所有Nginx相关的操作在一个角色内
    展示了如何设置依赖关系
    展示了如何注册任务的“依赖”执行关系,当一个任务执行成功后再执行另一个任务
    展示了如何在我们的任务中使用更多的模板,文件和变量
展示了如何整合使用ansible事实(facts)
展示了如何使用ansible的vault来增加我们的变量的安全性

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

6
{}

添加新评论2 条评论

#leoadmin存储工程师, Xstor
1天前
收藏了,谢谢分享。
#wuwenpin软件开发工程师, 南京
2天前
非常不错,值得收藏!
Ctrl+Enter 发表

作者其他文章

相关文章

关于TWT  使用指南  社区专家合作  厂商入驻社区  企业招聘  投诉建议  版权与免责声明  联系我们
© 2018  talkwithtrend — talk with trend,talk with technologist 京ICP备09031017号-30