自动化神器 Ansible

2017-09-16 Ansible Tower终于开源了- AWX,Ansible 作为 deploy 的 engine,而 AWX 或者 Tower 则在此基础上满足企业级软件的需求:

  • A GUI dashboard
  • Role-based access control
  • Job scheduling
  • Graphical inventory management
  • Multi-playbook workflow
  • REST API
  • External logging integrations
  • Real-time job status updates
  • ……

Why Ansible

做 IT 的的都知道,除了设计,写代码,离不开装机器,装软件,装系统,原始的办法是手动安装和配置,但如果一个大型项目或产品:

  • 需要做很多次(100+)
  • 需要在很多机器上做(100+)
  • 项目中,有安装文档,但是都是手工行为,步骤超多,如何防止人为疏忽
  • 不同的项目,不同的环境怎么办,特别是大型项目和产品类软件,支持的 OS 不同,版本不同,配置不同,需求不同:N 个客户 _ N 个环境 _ N 个发布 * N 台机器

种一颗树和种 1000 颗树的方法是不同的

原始的解决办法就是写脚本,尽量自动化,让机器来替我们干活 - 机器不累,不出错。这也就是为什么需要 Ansible,它完成两个最基本的事情:

  • 配置管理(configuration or change management):Ansible 不是专门的配置管理系统 CMDB(configuration management database),但没有这些配置信息无法干活啦,一般软件项目需要的配置也就是 ip, hostname, configuration files, 这些东东足已。Ansbile 可以和 CMDB 结合工作,达成动态配置,这个“高级”用法就不在本文讨论范围。

  • 自动化框架(automation framework):注意不只是 automation,Ansible 把自动化的动作按它的方式编写和组织,这样才能完成其它的事情如编排(orchestration:把几个事情串在一起执行),包括重用,和共享,这就比脚本和脚本库高一个档次。使用者也不必纠缠于命令行的参数,选项等等各种细节(当然 Ansbile 允许你直接调用命令行),Ansbile 采用类似 SQL“声明式”的理念,而不是一大段具体的实现细节,关注点在“What”上而不是“How”,例如:

- name: set up & configure web servers
hosts: webservers
vars:
http_port: 80
max_clients: 200
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted

该例子完成三件事:

  1. 通过 yum 安装 httpd;
  2. 通过 template 修改 httpd.conf(httpd 的配置文件),如有任何修改重启 apache;
  3. 通过 service 确定 httpd 服务已启动

Ansible 是自动化配置管理的顶级三大利器之一,另两个是 Puppet 和 Chef,Puppet 老字号,应该是最成熟的,Chef 也很普遍,但我选择 Ansible 的原因是:

  • 简单:no databases,no daemons,no agents,Puppet 和 Chef 需要在每台机器上安装 agent 并持续 monitor 而 Ansible 无 agent 设计,通过发 SSH 命令到各台机器上执行,而非监管机器,其依赖于 Python 2.4+(Python 3 目前还木有支持)(Ansible 是 Python 编写的)和 SSH,这在 Linux 机器上基本上就是默认的,所以安装使用 Ansible 及其简单,对目标机器无任何影响和副作用;

  • 易用,易扩展:Ansible 的开发就是写 YAML 文件,无编程要求,无脚本,非常易读和理解,Ansbile 没有花里花俏的概念,提供抽象的同时,没有强行你穿两条内裤,你照样能做任何原来想做的事情,这是好工具的哲学。

Ansible 的工作原理

Ansible 由一台机器(control server)来配置其它机器,基本原理可以用下面这张图概述:

Ansible原理

图中包含了 Ansible 的几个基本概念/术语:

inventory

『inventory』以 YAML 文本文件形式存在,定义了机器的基本信息,包含 ip 等。上面 hosts 中指定的 webservers 就定义在 inventory 文件里。通常都要给 Ansible 指定一个 inventory。

task or task module(任务模块)

这个就是具体干活的家伙,Ansible 把各种最基本的自动化动作『task』以 Python module 的形式实现,拿来就可以用了,是 Ansible 的最基本动作单元,例如上面 webservers 例子中的 yum,template, service 就是 Ansible 提供的任务模块。Ansible 提供的任务模块超过 400 个,运维最基本的东西都包括了,具体见Ansbile Module 文档。自己也可以通过 Python 扩充任务模块(编写自己的模块),这个不在本文讨论范畴(我感觉用不到的)。

称之为 module/模块的原因是因为 Ansible 是用 Python 开发的吧,不叫 component,lib,package,等等。

role(任务角色)

由 Ansible 和 community 分享提供,或自己编写。一个『role』就是一组 task,相当于一个迷你 playbook,这样相同的 role,在不同的地方就不需要重复写 task,例如,上面的例子中可以把 yum,template,service 合为一个 apache 的 role:

- name: set up & configure web servers
hosts: webservers
tasks:
- { role: apache, http_port: 80, max_clients: 200 }

role 把任务的执行,重用,扩展的提高了一个层次。

playbook

『playbook』也是 yaml 文本文件,相当于演戏的脚本,把角色(role),任务(task),inventory 串起来,例如:

- name: set up & configure web servers
hosts: myapp-webs
become: true
tasks:
- {role: apache, http_port: 80, max_clients: 200}
- name: set up & configure app servers
hosts: myapp-apps
become: true
- {role: tomcat, http_port: 8080}
- name: set up & configure db servers
hosts: myapp-dbs
become: true
tasks:
- {role: mysql, max_connection: 200}

playbook 把任务的执行,重用,扩展的又提高了一个层次,达到系统级别,例如上面的例子就完成了整个系统包括 web server, app server, db server 的配置。

在运行时,Ansbile 把 playbook 结合 inventory 和 module/roles 编译成 Python 程序,control server 通过 SSH 将其发送至目标机器,然后在目标机器上执行。 Ansible 把系统/目标机器看成是一个状态机,每做一个 task,状态会发生改变,通过若干 task 后,目标机器就从原始状态达到你想要的状态,实现“变化管理”。如果目标机器已经处于目标状态中,该 task 就不会被执行。每一步变化是“等幂”的 - 可重复,可验证。例如上面的这个 yum 任务:

- name: set up & configure web servers
hosts: myapp-webs
vars:
http_port: 80
max_clients: 200
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest

如果 httpd 最新版本已经安装,上面这段 yum 任务将不会执行。Ansiblez 在执行任务时具有一定的状态控制和逻辑。

Ansible 的基本操作

安装

Ansible 只安装在 control server 上,安装 Ansible 通过 Linux 上各种包安装工具如 RedHat 的 yum,Suse 的 zypper,Mac 的 brew 等,很容易搞定),如果 offline 安装,手动安装所需要的 rpm。由于 Ansible 是 Python 编写的,所以也可以用 pip 来安装。具体参见(官方安装文档)。

Ansible 的目标机器可以是 Linux 或 Windows,但目前 control server 必须是 Linux,虽然有各种 hack,但强烈不建议 Windows 作为 control server。

设置

Ansible 的设置文件可以按顺序下面找到:

  • $ANSIBLE_CONFIG
  • ./ansible.cfg
  • ~/.ansible.cfg
  • /etc/ansible/ansible.cfg

他们不会相互覆盖,遇到第一个设置文件就停止。下面是 ansible.cfg 例子:

[defaults]
forks = 5
host_key_checking = False
gathering = smart
roles_path = /usr/local/repository/ansible/roles
[priviledge_escalation]
become_method = sudo
[ssh_connection]
ssh_args = -o ForwardAgent=yes
scp_if_ssh = True
pipelining = True

编写

如何编写和组织 inventory,role,playbook 是 Ansible 的主要工作内容。Ansible 采用 YAML 文档格式,其语法简单,编写前先了解一下,参考『阮一峰的 YAML 语言教程』。注意 Ansible 很多动作是自动进行的,类似编程,默认以 main.yml 为入口(convention over configuration)。

Ansible Best Practices

必读,必读,必读Ansible Best Practices,官方网页非常清楚了。 我改动的地方是 group_vars 和 host_vars,接下来会解释。

Ansible

inventory

下面 inventory 的例子定义了 dev 环境中的机器:

localhost ansible_connection=local
myapp-db1 ansible_ssh_host=172.16.0.62
myapp-db2 ansible_ssh_host=172.16.0.63
myapp-app1 ansible_ssh_host=172.16.0.60
myapp-app2 ansible_ssh_host=172.16.0.61
myapp-web1 ansible_ssh_host=172.16.0.64
myapp-web2 ansible_ssh_host=172.16.0.66
[dev:children]
myapp-dbs
myapp-apps
myapp-webs
[myapp-dbs]
myapp-db1
myapp-db2
[myapp-apps]
myapp-app1
myapp-app2
[myapp-webs]
myapp-web1
myapp-web2
[dev:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file="/home/ansible/.ssh/id_rsa"

myapp-db1 ansible_ssh_host=172.16.0.62

定义了 myapp-db1 这台机器 host,ansible_ssh_host 是系统变量名,用来定义此台机器的 IP 地址(其实是隶属于 myapp-db1 的一个 key),自己可以加入自定义的变量。

[dev:children]

children这个关键字说明 dev 的成员 myapp-dbs 和 myapp-apps 不是单个 host,而是一个组,[myapp-dbs]和[myapp-apps]则分别定义了他们的组成员

[dev:vars]

vars这个关键字说明里面的变量将作用在所有的 dev 成员上(dev 的通用变量),ansible_ssh_user 和 ansible_ssh_private_key_file 也都是系统变量名。

role

role 由几部分组成:

  • defaults: 定义该 role 用到默认变量,该 role 运行时自动加入这里定义的变量,但其定义的变量优先级别最低,若已在其他地方定义,可被覆盖。
  • vars: 该 role 运行时自动加入这里定义的变量,通常可把需要传入的变量定义在这里,vars 和 defaults 很类似,通常把必须用到变量的放在 defaults 里,可变的放在 vars 里,例如 tasks 里针对不同的 OS,版本用到的变量,需要到的时候可以引入,include_vars 可自动在此目录中寻找变量文件(相对路径):
  • files:存放各种文件,该 role 需要执行相关 file tasks 时,file module 可自动在此目录中寻找文件(相对路径)
  • templates:该 role 需要执行 template task 时,可自动在此目录中寻找 template 文件(相对路径),template 这个 task 专门用来修改配置文件。
  • tasks:该 role 需要执行的 tasks,类似 playbook,include 可在此目录中寻找 tasks 文件(相对路径)
  • handlers:定义该 role 需要的回调 task,在 tasks 里可以调用

可以参考一下别人是如何编写 role 的,这是一个安装和配置 mysql 的 role

playbook

playbook 定义了一系列的 tasks,每一段包含下面的字段:

  • name: 任务组名称或描述
  • hosts: 目标机器
  • become & become_user: 指定登录执行任务的用户,目标机器和执行任务的用户可能不同,例如需要 root 权限
  • tags: 任务标签
  • tasks: 一组具体任务,可以调用某个或多个任务模块(task module)、某个或多个角色(task role)

tags 和 vars 对使用好 Ansible 非常重要,下面会介绍。

这是 provision-dbs.yml 的内容:

#!/usr/bin/env ansible-playbook
- name: set fact-related variables (always run)
hosts:
- myapp-dbs
gather_facts: true
tags: always
tasks:
- include: vars.yml
- name: db server common
hosts:
- myapp-dbs
become: true
roles:
- { role: server-common, tags: ["common"] }
- name: install & config mongodb
hosts:
- myapp-db1
become: true
roles:
- { role: mongodb, tags: ["mongodb"] }
- name: install & config mysql
hosts:
- myapp-db2
become: true
roles:
- { role: mysql, tags: ["mysql"] }

执行

Ansible 的运行有两种主要模式,一种是 playbook 模式,另一种是随机模式。

playbook 例子,一个命令把整个系统搞起:

> ansible-play site.yml

随机例子 1,执行某个命令行”service status-all”:

> ansible db1 -a 'service --status-all' -u ansible -b

随机例子 2,执行某个 task module(shell),通过-a 输入该 task module 附加参数,效果和上面一样:

> ansible db1 -m shell -a 'service --status-all' -u ansible

当然 playbook 是主要模式。

项目实践

Ansible 比较新,版本间的差别比较大,有些问题具体运行才知道。下面是运用 Ansible 的几个重点和技巧:

重点:部署四部曲 lifecycle

部署基本上遵循下面四步:

部署四步

3,4 由 Ansible 完成,所以通常我会有两个 playbook - sys.yml 和 site.yml:

#!/usr/bin/env ansible-playbook
# sys.yml
- name: display environment name
hosts: localhost
tags: always
tasks:
- debug:
msg: "MyApp environment :::> {{ app_env }}"
- name: display environment name
hosts: localhost
tags: always
tasks:
- debug:
msg: "MyApp OS :::> {{ ansible_os_family }}"
- include: sys-dbs.yml
- include: sys-apps.yml
- include: sys-webs.yml
#!/usr/bin/env ansible-playbook
# site.yml
- name: display environment name
hosts: localhost
tags: always
tasks:
- debug:
msg: "MyApp environment :::> {{ app_env }}"
- name: display environment name
hosts: localhost
tags: always
tasks:
- debug:
msg: "MyApp OS :::> {{ ansible_os_family }}"
- include: site-cots.yml
- include: site-apps.yml
- include: site-misc.yml

重点:变量 vars

运维的复杂性和灵活性由变量 vars 来体现的,Ansible 的 variable 可在多处定义,并有优先顺序。不过不用那么复杂,关键是搞清楚变量应用的范围:

  • 全局变量 vars/main:不受部署环境影响,到处都要用到,全局变量的例子比如 project_name, app_user,db_port, 等等。

  • 环境变量 env_xxx/group_vars/all/xxx:项目开发中通常有多个环境 xxx:local, dev, staging, uat, production,有些变量随环境改变而改变,但相当于该环境下的全局变量,除了 inventory/机器变量外,其它的变量例子如 host file, resource_dir,repo_url,等等。

Ansible 没有提出全局变量和环境变量的使用和区别,只有机器变量(group_vars & host_vars),Ansible Best Practices 里把它们当做了全局变量,但结构上是支持的,也就是每个环境下都可以分别有 inventory 和 group_vars & host_vars,而 all 就是默认的机器组,所以 env_xxx/group_vars/all/下所有的变量文件都会被识别为机器全局变量,而且 all 的机器变量引用时不需要前缀指定,特定的 group_vars & host_vars 变量 xxx 必须指明是哪个 group()或 host(),“groups”和“hostvars”是 Ansible 内置变量。为了支持全局变量(各个环境都使用),可以通过 file link 的方法让每个 env_xxx/group_vars/all/main 指向同一个文件,上图中的 env_dev/group_vars/all/main 指向 vars/main。

  • 支持多 OS,多基础设施的变量:这种变量主要是支撑产品级的软件项目,通常是动态的,通过任务执行来设定,例如上面的 dbservers.yml 里引用的 vars.yml:
- name: define os family (suse)
set_fact:
os_family: "suse"
when: ansible_os_family == "SuSe"
- name: define os family (redhat)
set_fact:
os_family: "redhat"
when: ansible_os_family == "RedHat"
- name: define os family (debian)
set_fact:
os_family: "debian"
when: ansible_os_family == "Debian"
- name: check os_family
fail:
msg: "ERROR - can not detect supported os_family"
when: os_family is not defined

变量 os_family 在以后的 tasks 和 roles 中都可能用到。

  • role 变量:这些变量应用范畴只是该 role,是传统意义上各软件 component 的参数变量,在 role 里定义和使用,但 playbook 调用时可以进行指定或覆盖默认值,例如一个 Tomcat 的 war 部署时传人 war_name:
- name: deploy my app1
hosts:
- myapp-apps
become: true
become_user: "{{ app_user }}"
roles:
- { role: tomcat-deploy, war_name: "app1", tags: ["app1"] }
  • Ansible 流程和控制变量:上面的变量主要用来支持配置的,还有一些属于控制或者辅助控制 Ansible 流程的,这些通过 Ansible 提供的功能来指定,例如从命令行输入:
- name: create app user name & password
hosts: all
become: true
become_user: root
vars_prompt:
- name: app_user prompt: "app user name -> "
- name: app_password prompt: "app password -> "
- name: app_group prompt: "app group -> "
user:
name: "{{ app_user }}"
password: "{{ app_password }}"
group: "{{ app_group }}"
append: yes
generate_ssh_key: yes
shell: /bin/bash
home: "/home/{{ app_user }}"
createhome: yes
state: present

流程控制的例子见下面“技巧:有条件执行 conditional execution”。

  • Ansible 默认/内置变量:例如获得当前运行的 playbook 路径, 则是当前 role 的路径,这里有个『非常好的参考

重点:标签 tags

在调试和部署的时候,有些任务需要重复多次的,而 playbook 包含从头到尾,所以需要指定特定的任务(过滤掉其它的),这时候标签 tags 发挥作用。Ansible 命令行支持两种标签指定方式:

  • -t or –tags
  • –skip-tags

怎么打标签关键是看需要做什么样的动作,例如 provision-dbs.yml 里:

- name: db server common
hosts:
- myapp-dbs
become: true
roles:
- { role: server-common, tags: ["common"] }

如果指定标签 common,就可以执行所有 common 的任务。而在 common 这个 role 的 tasks 里:

- include: repo.yml
tags: repo
- include: hostfile.yml
tags: hostfile
- include: misc.yml

如果我在命令行里指定标签 hostfile,这样就能执行部分特定的 common 任务。通过不同标签的组合也可以完成一定的任务,例如用于升级系统的 tomcat:

>
play appservers.yml -t tomcat,app1

标签 tag 最终是落在每一个 task 上的(透过 playbook,role),但直接给每个 task 打标签就很麻烦,为保持 role 的可移植,我基本不在 role 里打标签。我遇到了 playbook 的 include 打上标签,但不起作用(Ansible bug or defeit?)。

有的时候 tags 还是不好用,例如 mysql 里要不要做 clustering,这时可以通过变量来控制,参考下面的例子“技巧:有条件执行 conditional execution”。

技巧:gathering facts

在 ansible.cfg 中加入:

gathering = smart
fact_caching = jsonfile
fact_caching_connection = /app/intellisurf/deployment
fact_caching_timeout = 86400

技巧:host

除了 tags,可以通过-l 来限定目标机器,Ansible 支持比较复杂的机器组合方式:

  • OR 关系: h1:h2
  • NOT 关系: !h1
  • Wildcard: web*.app.com
  • Regx: (~web[0-9]+)

通过-t 和-l 就能指定在某个目标机器某个动作,例如:

> play dbservers.yml -t mysql -l db1

技巧:SSH Keys

通过 key 免去登录密码输入,有几种选项:

  • 一个 key 登录所有机器,通过默认的 key 实现,在 ansible.cfg 文件里的[defaults]定义:
private_key_file=/etc/ansible/keys/access.pem
  • 一个 key 登录一组机器,例如在上面的 inventory 文件里:
[dev:vars]
ansible_ssh_user=ansible
ansible_ssh_private_key_file="/home/ansible/.ssh/id_rsa"

一个 key 登录一台机器, 也是在在上面的 inventory 文件里定义:

myapp-db1 ansible_ssh_host=172.16.0.62 ansible_ssh_private_key_file=/etc/ansible/keys/db1.pem
myapp-db2 ansible_ssh_host=172.16.0.63 ansible_ssh_private_key_file=/etc/ansible/keys/db2.pem
myapp-app1 ansible_ssh_host=172.16.0.60 ansible_ssh_private_key_file=/etc/ansible/keys/app1.pem
myapp-app2 ansible_ssh_host=172.16.0.61 ansible_ssh_private_key_file=/etc/ansible/keys/app2.pem
  • 让 SSH/SSH-Agent 自己去解决, 有空我会具体介绍一下 SSH。

技巧:有条件执行 conditional execution

register, when, _changed_when_, _failed_when_ 例子:

- name: install jdk rpm (suse)
shell: zypper -n in {{ java_rpm }}
when: os_family == "suse"
register: install_java
changed_when: install_java.rc == 0 and "already installed" not in install_java.stdout
- name: validate java home
shell: . /etc/profile && echo $JAVA_HOME
register: java_home_result
failed_when: java_home_result.stdout is not defined or java_home_result.stdout

有些配置只需要做一次,例如数据库初始化,虽然 Ansible 提供了『run_once』,但感觉不好用,还是直接用变量做开关来控制。

技巧:循环执行

下面的例子循环构建所有的 docker image:

- name: build all service docker images
host: app-build
become: true
tasks:
- name: build a docker image
include_role:
name: docker-build
vars:
- image_name: "{{ item.name }}"
- image_tags: "{{ item.tags }}"
with_items: "{{ service_images }}"
when: (incldes is not defined) or (item.name in includes)

Ansible 通过『with_items』『with_dict』等达到循环的目的,上面的例子还加入命令行动态变量 includes 来控制指定的 image:

# play docker-build.yml -e "includes=[service1, service2]"

Ansible 支持多重循环,

- name: build all service docker images
host: app-build
become: true
tasks:
- name: build a docker image
include_role:
name: docker-build
vars:
- module_name: "{{ item.0.name }}"
- image_name: "{{ item.1.name }}"
- image_tags: "{{ item.1.tags }}"
with_subelements::
- “{{ modules }}”
- service_images
when: (incldes is not defined) or (item.0.name in includes)

item.0 和 item.1 对应循环体的循环变量。

技巧:ansible-vault 存储敏感信息

密码等属于敏感信息,可以把包含敏感信息的文件通过『ansible-vault』加密,加密后的文件看起来就像乱码而非明文,例如:

> cat password.txt
$ANSIBLE_VAULT;1.1;AES256
66633936653834616130346436353865303665396430383430353366616263323161393639393136
3737316539353434666438373035653132383434303338640a396635313062386464306132313834
34313336313338623537333332356231386438666565616537616538653465333431306638643961
3636663633363562320a613661313966376361396336383864656632376134353039663662666437
39393639343966363565636161316339643033393132626639303332373339376664

创建 create,加密 encrypt,解密 decript,编辑加密文件 edit,都可以通过 ansible-vault 进行:

[email protected]:~> ansible-vault
Usage: ansible-vault [create|decrypt|edit|encrypt|encrypt_string|rekey|view] [--help] [options] vaultfile.yml

当直接运行包含这些加密 vars 文件的 playbook 时,会出错(加密后的 vars 已经乱码了),要操作加密文件必须有密码保护,ansible 或 ansible-playbook 要加上 ask-vault-pass:

$ ansible-playbook site.yml --ask-vault-pass

或者创建一个.vault_pass 的文件,把密码放进去,让 ansible 自动去读取:

$ echo "my_vault_password" > .vault_pass
$ ansible-playbook site.yml --vault-password-file=.vault_pass

记住在生存环境上创建这个文件.vault_pass,不要把它 commit 进 git 或 svn,否则人人都知道解密密码啦:

$ echo '.vault_pass' >> .gitignore

由于 ansible 只能支持整个文件加密,所以如果把变量分成要加密的,不要加密的,就会破坏变量本事的结构,导致可读性变差,例如:

$ cat group_vars/database/vars
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred
# sensitive data
mysql_password: this_is_my_password

想要对 mysql_password 加密的话,要吗对整个文件加密,要吗把 mysql_password 移出到另一加密文件,但这都不是我们想要的,技巧是创建另一变量,通过引入来解决:

$ cat group_vars/database/vars
# nonsensitive data
mysql_port: 3306
mysql_host: 10.0.0.3
mysql_user: fred
# sensitive data
mysql_password: “{{ vault_mysql_password }}”
$ ansible-vault view group_vars/database/vault
vault_mysql_password: this_is_my_password

技巧:debug

通过环境变量:

$ export ANSIBLE_STRATEGY=debug

或者直接在 playbook:

- hosts: localhost
strategy: debug
tasks:
-

当该任务出错时,Ansible 暂停执行,调用 debugger,这时可以任意调整变量:

(debug) task.args

详细文档:https://docs.ansible.com/ansible/playbooks_debugger.html

另一个常用的方法时debug module,拿来输出信息:

- name: display environment name
hosts: localhost
tasks:
- debug:
msg: "environment :::> {{ app_env }}"
verbosity:3
- name: display OS name
hosts: localhost
tasks:
- debug:
msg: "OS :::> {{ ansible_os_family }}"
verbosity:3

注意 verbosity,Ansible 命令行用 -v,-vv, -vvv, -vvvv 等来控制 debug 输出的 verbosity 程度,当 verbosity: 3 时,-v,-vv 时将看不到 debug 的输出。

几个运行技巧

把 ansible-playbook 匿名成 play,下面是几个有用的选项:

  • play site.yml –list-tasks:列出所有的 tasks
  • play site.yml –list-tags:列出所有的 tags
  • play site.yml –syntax-check:做语法检查
  • play site.yml –check:“虚假”运行,可告知那些 tasks 会产生改变,如果带上 -D or –diff,如果相关 module 支持,如 template,会显示前后改变的具体内容
  • play site.yml –step:“单步”执行

容器架构对 Devops 的影响

Docker/Container 带来了颠覆性革命,大大简化了 DevOps,提倡 :

Build Once, Run Anywhere

注意,这里木有 install(安装),木有 config(配置)。复杂软件的安装和配置是个麻烦的事情,自动化完成提高了很大一步,但能不能完全省去呢?我们开发的服务器软件能不能像绿色软件那样,双击即可运行?能不能像绿色软件那样,双击即可运行?能不能像绿色软件那样,双击即可运行?接下来我会介绍近年来很火的 Docker/Container。

福利

0%