kolla-ansible快速入门

kolla-ansible是一个结构相对简单的项目,它通过一个shell脚本,根据用户的参数,选择不同的playbook和不同的参数调用ansible-playbook执行,没有数据库,没有消息队列,所以本文的重点是ansible本身的语法。

kolla-ansible命令

kolla-ansible命令的主要代码如下:

#!/bin/bash
#
# This script can be used to interact with kolla via ansible.
# 默认变量
INVENTORY="${BASEDIR}/ansible/inventory/all-in-one"
PLAYBOOK="${BASEDIR}/ansible/site.yml"
CONFIG_DIR="/etc/kolla"
PASSWORDS_FILE="${CONFIG_DIR}/passwords.yml" while [ "$#" -gt 0 ]; do
case "$1" in (--inventory|-i)
INVENTORY="$2"
shift 2
;;
kolla-ansible支持的各种参数,略
esac
done case "$1" in
(prechecks)
ACTION="Pre-deployment checking"
EXTRA_OPTS="$EXTRA_OPTS -e action=precheck"
;;
(mariadb_recovery)
略,以下类似皆略
esac CONFIG_OPTS="-e @${CONFIG_DIR}/globals.yml -e @${PASSWORDS_FILE} -e CONFIG_DIR=${CONFIG_DIR}"
CMD="ansible-playbook -i $INVENTORY $CONFIG_OPTS $EXTRA_OPTS $PLAYBOOK $VERBOSITY"
process_cmd

可以看出,当我们执行kolla-ansible deploy时,kolla-ansible命令帮我们调用了对应的ansible-playbook执行,除此之外,没有其他工作。所以对于kolla-ansible项目,主要学习ansible语法即可。

ansible

一个简单的ansible命令示例如下:

ansible -i /root/myhosts ha01 -m setup

这个命令的作用是,对/root/hosts文件中的所有属于ha01分类的主机,执行setup模块收集该主机的信息,它包括两种元素,主机清单和模块,下面分别介绍这两种元素。

Host Inventory(主机清单)

host inventory 是一个文件,存放了所有被ansible管理的主机,可以在调用anabile命令时,通过-i参数指定。

  1. 下面是一个最简单的hosts file的例子,包含1个主机ip和两个主机名:
193.192.168.1.50
ha01
ha02·

可以执行以下命令检查ha01是否能够连通

ansible -i $filename ha01 -m ping

ha01 | SUCCESS => {
"changed": false,
"ping": "pong"
}

2.我们可以把主机分类,示例如下

deploy-node

[ha]
ha01
ha02 [compute]
compute01
compute02
compute03
  1. 如果主机数量比较多,也可以用正则表达,示例如下:
deploy-node

[ha]
ha[01:02] [openstack-compute]
compute[01:50] [openstack-controller]
controller[01:03] [databases]
db-[a:f].example.com
  1. 所有的controller和compute,都是openstack的节点,所以我们可以再定义一个类别openstack-common,把他们里面的主机都包括进去
[openstack-common:children]
openstack-controller
openstack-compute [common:children]
openstack-common
databases
ha
  1. 当我们有了如上的inventory 文件后,可以执行如下命令,检验是不是所有机器都能够被ansible管理
ansible -i $file common -m ping

Module(模块)

ansible封装了很多python脚本作为module提供给使用者,如:yum、copy、template,command,etc. 当我们会特定主机执行某个module时,ansible会把这个module对应的python脚本,拷贝到目标主机上执行。可以使用ansible-doc -l来查看ansible支持的所有module。使用ansible -v 模块名 来查看该模块的详细信息。

1. 一个例子,ping

上文的例子,使用了-m ping参数,意思是对这些主机,执行ping 模块,ping 模块是一个python脚本,作用是用来判断:目标机器是否能够通过ssh连通并且已经安装了python。

# ping module主要源码
description:
- A trivial test module, this module always returns C(pong) on successful
contact. It does not make sense in playbooks, but it is useful from
C(/usr/bin/ansible) to verify the ability to login and that a usable python is configured.
- This is NOT ICMP ping, this is just a trivial test module.
options: {} from ansible.module_utils.basic import AnsibleModule def main():
module = AnsibleModule(
argument_spec=dict(
data=dict(required=False, default=None),
),
supports_check_mode=True
)
#什么都不做,构建一个json直接返回
result = dict(ping='pong')
if module.params['data']:
if module.params['data'] == 'crash':
raise Exception("boom")
result['ping'] = module.params['data']
module.exit_json(**result) if __name__ == '__main__':
main()

2. 自定义模块

example:Ansible模块开发-自定义模块

如果默认模块不能满足需求,可以自定义模块放到ansible指定的目录,默认的ansible配置文件是/etc/ansible/ansible.cfg,library配置项是自定义模块的目录。

openstack的kolla-ansbile项目的ansible/library目录下面存放着kolla自定义的module,这个目录下每一个文件都是一个自定义moudle。可以使用如下的命令来查看自定义module的使用方法:ansible-doc -M /usr/share/kolla-ansible/ansible/library -v merge_configs

3. action moudle

如上文所述,ansible moudle最终执行的位置是目标机器,所以module脚本的执行依赖于目标机器上安装了对应的库,如果目标机器上没有安装对应的库,脚本变不能执行成功。这种情况下,如果我们不打算去改动目标机器,可以使用action moudle,action moudle是一种用来在管理机器上执行,但是可以最终作用到目标机器上的module。

例如,OpenStack/kolla-ansible项目部署容器时,几乎对每一台机器都要生成自己对应的配置文件,如果这个步骤在目标机器上执行,那么需要在每个目标机器上都按照配置文件对应的依赖python库。为了减少依赖,kolla-ansible定义了action module,在部署节点生成配置文件,然后通过cp module将生成的文件拷贝到目标节点,这样就不必在每个被部署节点都安装yml,oslo_config等python库,目标机器只需要支持scp即可。kolla-ansible的action module存放的位置是ansible/action_plugins.

4. 模块学习

不建议深入去学,太多了,用到的时候一个个去查就好了

ansible-playbook

待补充

Playbook(剧本)

前文提到的ansible命令,都是一些类似shell命令的功能,如果要做一些比较复杂的操作,比如说:部署一个java应用到10台服务器上,一个模块显然是无法完成的,需要安装模块,配置模块,文件传输模块,服务状态管理模块等模块联合工作才能完成。把这些模块的组合使用,按特定格式记录到一个文件上,并且使该文件具备可复用性,这就是ansible的playbook。如果说ansible模块类似于shell命令,那playbook类似于shell脚本的功能。

这里举一个使用playbook集群的例子,kolla-ansible deploy 实际上就是调用了:

ansible-playbook -i /usr/share/kolla-ansible/ansible/inventory/all-in-one -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e action=deploy /usr/share/kolla-ansible/ansible/site.yml

1. 一个简单的playbook

---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
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 (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: restart apache
service: name=httpd state=restarted

这个playbook来自ansible官网,包含了一个play,功能是在所有webservers节点上安装配置apache服务,如果配置文件被重写,重启apache服务,在任务的最后,确保服务在启动状态。

playbook中的元素

1. hosts and remote_user

play中的hosts代表这个play要在哪些主机上执行,这里可以使一个或者多个主机,也可以是一个或者多个主机组。remote_user代表要以指定的用户身份来执行此play。remote_user可以细化到task层。

---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname

2. tasks

task是要在目标机器上执行的一个最小任务,一个play可以包含多个task,所有的task顺序执行。

3. vars

在play中可以定义一些参数,如上文webservers中定义的http_port和max_clients,这两个参数会作用到这个play中的task上,最终template模块会使用这两个参数的值来生成目标配置文件。

4. handlers

当某个task对主机造成了改变时,可以触发notify操作,notify会唤起对应的handler处理该变化。比如说上面的例子中,如果template module重写/etc/httpd.conf文件后,该文件内容发生了变化,就会触发task中notify部分定义的handler重启apache服务,如果文件内容未发生变化,则不触发handler。

也可以通过listen来触发想要的handler,示例如下:

handlers:
- name: restart memcached
service: name=memcached state=restarted
listen: "restart web services"
- name: restart apache
service: name=apache state=restarted
listen: "restart web services" tasks:
- name: restart everything
command: echo "this task will restart the web services"
notify: "restart web services"

使用role和include更好的组织playbook

1. role

上文给出的webserver playbook中,task和hanler的部分是最通用的,vars部分其次,hosts参数最次。其他人拿到这个playbook想到使用,一般不需要修改task,但是host和vars部分,就需要修改成自己需要的值。所以ansible这里引入了role的概念,把host从playbook中移出,把剩下的内容按照下面示例的样式,拆成几部分,handler存放到handler中,task存放到task目录中去,默认变量存放到default中,使用到的文件'httpd.j2'存放到templates目录下,按照这样的目录格式组织完成后,我们就得到了一个webserber role。

tasks中可以有很多task,被执行的入口是main.yml

# 官网的一个role目录结构的例子
site.yml
webservers.yml
fooservers.yml
roles/
common/
tasks/
main.yml
handlers/
files/
templates/
defaults/
meta/
webservers/
tasks/
main.yml
defaults/
meta/
templates/

role的使用方法,可以参考下面的例子,下面的playbook作用是:对所有的webservers机器,执行common,weservers,foo_app_instance对应的task,执行最后一个role时,传递了dir和app_port两个参数。

---
- hosts: webservers
roles:
- common
- webservers
- { role: foo_app_instance, dir: '/opt/a', app_port: 5000 }

2. include

可以考虑这样两个问题:

  1. 上文我们定义webserver role作用是在指定服务器上安装并确保apache服务运行,那么如果我们想要升级,关闭或者卸载apache服务呢,该怎么办,再定义新的role,webserver-upgrade看起来似乎太蠢笨了。能不能像面向对象那样,一个对象支持不同的操作?
  2. 上文中的webserver服务安装比较简单,所以我们的playbook也比较简单,但是有时候会遇到比较麻烦的需求,比如说安装openstack的neutron服务,它需要先检车设置,再生存配置文件,同步数据库,等步骤,这项功能如果都写成一个playbook,这个playbook是不是太大了,很难维护。可不可以把检查,配置,同步等功能做成不同的playbook,然后从一个主playbook中看情况调用?

include功能可以解决这样的问题,一个include的例子如下

tasks/
bootstrap.yml
ceph.yml
config.yml
check.yml
deploy.yml
upgrade.yml
precheck.yml
register.yml
main.yml main.yml
---
- include: "{{ action }}.yml" deploy.yml
---
- include: ceph.yml
when:
- enable_ceph | bool and nova_backend == "rbd"
- inventory_hostname in groups['ceph-mon'] or
略 - include: register.yml
when: inventory_hostname in groups['nova-api'] - include: config.yml - include: bootstrap.yml
when: inventory_hostname in groups['nova-api'] or
inventory_hostname in groups['compute'] 略

当nova role被赋给一台服务器后,如果用户指定的action是deploy,ansible会引入deploy.yml,如果是upgrade,则引入upgrade.yml。这样根据用户参数的不同,include不同的playbook,从而实现一个role支持多种功能。

deploy playbook又由多个不同的playbook组成,根据用户的配置的参数,有不同的组合方式,很灵活。

我的理解是,在role的task中,一个play就好像一个内部函数,一个playbook是由一个由多个play组成的公有函数,被其他playbook根据include参数组合调用。

kolla-ansible中常见ansible语法

kolla-ansible中的play都比上面的例子复杂很多,它很多时候都不直接调用module,而是加了很多判断,循环,错误处理之类的逻辑,一个例子:

ansible.roles.prechecks.tasks.package_checks.yml
---
- name: Checking docker SDK version
command: "/usr/bin/python -c \"import docker; print docker.__version__\""
register: result
changed_when: false
when: inventory_hostname in groups['baremetal']
failed_when: result | failed or
result.stdout | version_compare(docker_py_version_min, '<')

这个playbook的功能是:

  1. 开始执行book中的第一个play:Checking docker SDK version
  2. 判断目标主机inventory_hostname是否属于主机清单中的baremetal组
  3. 如果属于,到这台主机上执行command module,参数是"/usr/bin/python -c "import docker; print docker.version""
  4. 将执行的结果赋值给result变量
  5. 因为这个模块不会更改目标主机上的任何设置,所以change_when是false,无论执行结果如何,都不会去改变这个当然任务的changed属性
  6. 将result变量传递给failed函数,判断命令是否执行成功
  7. 如果命令执行成功,将result中的输出结果,传递给version_compare函数,判断版本是否符合要求
  8. 因为这个模块不会更改目标主机上的任何设置,所以change_when永远是false
  9. 如果failed_when判断结果为失败,则设置任务状态为失败,停止执行此playbook

下面分别介绍几种kolla-ansible中常用的ansible语法。

1.条件语句

when,faild_when, change_when 后面可以接入一个条件语句,条件语句的值是true或者false,条件语句示例如下:

ansible_os_family == "Debian"
test == 1 or run == always
hostname in [1,2,3,4]

ansible除了上文的==, or, in来进行判断外,ansible还支持通过管道调用ansible自定义的test plugin进行判断,上文中的 result | failed or result.stdout | version_compare(docker_py_version_min, '<')用到了version_compare和failed两个test plugin,这两个test plugin本质是ansible指定目录下两个python函数,用来解析字符串判断版本版本是否匹配,执行命令是否成功。它们的源码位于ansible.plugins.test.core, ansible。所有test plugin位于ansible.plugins.test,ansible支持自定义test plugin。

2. 迭代

with_itmes 是ansible的迭代语句,作用类似python的 for item in {}, 用法示例:

- name: test list
command: echo {{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 56 - name: Setting sysctl values
sysctl: name={{ item.name }} value={{ item.value }} sysctl_set=yes
with_items:
- { name: "net.bridge.bridge-nf-call-iptables", value: 1}
- { name: "net.bridge.bridge-nf-call-ip6tables", value: 1}
- { name: "net.ipv4.conf.all.rp_filter", value: 0}
- { name: "net.ipv4.conf.default.rp_filter", value: 0}
when:
- set_sysctl | bool
- inventory_hostname in groups['compute']

3. failed_when

一种错误处理机制,一般用来检测执行的结果,如果执行失败,终止任务,和条件语句搭配使用

4. changed_when

当我们控制一些远程主机执行某些任务时,当任务在远程主机上成功执行,状态发生更改时,会返回changed状态响应,状态未发生更改时,会返回OK状态响应,当任务被跳过时,会返回skipped状态响应。我们可以通过changed_when来手动更改changed响应状态。

5. run_once

当对一个主机组赋予进行操作时,有部分操作并不需要在每个主机上都执行,比如说nova服务安装时,需要初始化nova数据库,这个操作只需要在一个节点上执行一次就可以了,这种情况可以使用run_once标记,被标记的任务不会在多个节点上重复执行。

delegate_to可以配合run_once使用,可以在playbook中指定数据库任务要执行的主机,下面的例子中,指定要执行数据库创建的主机是groups['nova-api'][0]

- name: Creating Nova databases
kolla_toolbox:
module_name: mysql_db
module_args:
login_host: "{{ database_address }}"
login_port: "{{ database_port }}"
login_user: "{{ database_user }}"
login_password: "{{ database_password }}"
name: "{{ item }}"
register: database
run_once: True
delegate_to: "{{ groups['nova-api'][0] }}"
with_items:
- "{{ nova_database_name }}"
- "{{ nova_database_name }}_cell0"
- "{{ nova_api_database_name }}"

delegate_to指定的机器可以当前任务的机器没有任何关系,比如,在部署nova服务时,可以delegate_to的目标不限于nova机器,可以到delegate_to ansible控制节点或者存储机器上执行任务。例如:

  • hosts: app_servers

    tasks:

    • name: gather facts from db servers

      setup:

      delegate_to: "{{item}}"

      delegate_facts: True

      with_items: "{{groups[‘dbservers‘}}"

      该例子会收集dbservers的facts并分配给这些机器, 而不会去收集app_servers的facts

6. serial

一般情况下, ansible会同时在所有服务器上执行用户定义的操作, 但是用户可以通过serial参数来定义同时可以在多少太机器上执行操作.

  • name: test play

    hosts: webservers

    serial: 3

    webservers组中的3台机器完全完成play后, 其他3台机器才会开始执行

7. until

这种循环由三个指令完成:

  • until是一个条件表达式,如果满足条件循环结束
  • retry是重试的次数
  • delay是延迟时间

示例如下:

  • action: shell /usr/bin/foo

    register: result

    until: result.stdout.find("all systems go") != -1

    retries: 5

    delay:

8. wait_for

wait_for 可以让ansible等待一段时间,直到条件满足,再继续向下执行,这个模块主要用来等待之前的操作完成,比如服务启动成功,锁释放。

下面是一个kolla-ansible判断murano-api服务是否启动成功的例子:

在murano-api[0]节点上, 尝试和api_interface_address:murano_api_port建立链接,如果成功建立连接,结束等待。如果1秒(connect_timeout)内未建立成功,放弃,休眠1秒(参数sleep,未配置,默认值)后重试,如果60秒(timeout)内没有成功创建链接,任务失败。

- name: Waiting for Murano API service to be ready on first node
wait_for:
host: "{{ api_interface_address }}"
port: "{{ murano_api_port }}"
connect_timeout: 1
timeout: 60
run_once: True
delegate_to: "{{ groups['murano-api'][0] }}"

参考文档

ansible入门书:https://ansible-book.gitbooks.io/ansible-first-book/content/begin/basic_module/module_list_details.html

ansible循环用法:http://www.cnblogs.com/PythonOrg/p/6593910.html

自定义过滤器:http://rfyiamcool.blog.51cto.com/1030776/1440686/

异步和轮询:http://www.mamicode.com/info-detail-1202005.html

ansible 语法:http://blog.csdn.net/ggz631047367/article/details/50359127

ansible官网:http://docs.ansible.com/ansible/latest/

kolla-ansible快速入门的更多相关文章

  1. ansible 快速入门

    安装 $ sudo apt-get install software-properties-common $ sudo apt-add-repository ppa:ansible/ansible $ ...

  2. jumpservice配置:快速入门

    快速入门 说明 到 Jumpserver 会话管理-终端管理 查看 Coco Guacamole 等应用是否在线 一.系统设置 1.1 基本设置 # 修改 url 的"localhost&q ...

  3. Web Api 入门实战 (快速入门+工具使用+不依赖IIS)

    平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html 屁话我也就不多说了,什么简介的也省了,直接简单概括+demo ...

  4. SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

     SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...

  5. 前端开发小白必学技能—非关系数据库又像关系数据库的MongoDB快速入门命令(2)

    今天给大家道个歉,没有及时更新MongoDB快速入门的下篇,最近有点小忙,在此向博友们致歉.下面我将简单地说一下mongdb的一些基本命令以及我们日常开发过程中的一些问题.mongodb可以为我们提供 ...

  6. 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  7. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  8. Mybatis框架 的快速入门

    MyBatis 简介 什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果 ...

  9. grunt快速入门

    快速入门 Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器. Grunt 0.4.x 必须配合Node.js >= 0.8.0版本使用.:奇数版本 ...

随机推荐

  1. [JLOI2011]基因补全

    1973: [JLOI2011]基因补全 Time Limit: 1 Sec  Memory Limit: 256 MB Description 在生物课中我们学过,碱基组成了DNA(脱氧核糖核酸), ...

  2. java面向对象基础(四):抽象类和接口

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  3. left join on/right join on/inner join on/full join on连接

    现在有两张表,第一张表是用户表,第二张表是订单表.情况是这样的,在我这张用户表里用户很多,但是真正下单的人却不多,而且,每一个用户可以有多个订单.然后领导喊话了,小王,你给我查下,现在咱们的订单有多少 ...

  4. SQL Server中计算表达式的和

    项目使用的是SQL Server数据库,需要做一个审核规则,字段A中表达式的值和字段B中的值,做比较: 需求本身很简单,但是表达式中存在很多非法字符(非法全角,运算符,汉字--) eg:1.1.1*2 ...

  5. 从返回的HTTP Header信息中隐藏Apache的版本号及PHP的X-Powered-By信息

    默认情况下,很多apache安装时会显示版本号及操作系统版本,甚至会显示服务器上安装的是什么样的apache模块.这些信息可以为黑客所用,并且黑客还可以从中得知你所配置的服务器上的很多设置都是默认状态 ...

  6. 原生JS实现图片轮播

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. Tomcat时区设置方法[转]

    最近被问到了关于Tomcat时区设置方法,还没碰到类似的问题,网上说是记录日志和定时任务时可能会出现,目前还未发现,先记录下来. 原文地址:http://blog.csdn.net/x_yp/arti ...

  8. uboot之ldr指令

    刚开始接触uboot的时候,就一直对ldr指令很迷惑,因为这个指令有两层用法,一个是加载,一个是伪指令.今天闲着没事就来说一下这两个之间的区别. LDR伪指令的形式是"LDR Rn,=exp ...

  9. nginx上支持.htaccess伪静态的配置实例

    本文介绍下,在nginx上配置.htaccess伪静态的方法,有需要的朋友参考下吧. 在apache上.htaccess转向,只要apache编译的时候指明支持rewrite模块即可. 但是换到ngi ...

  10. nginx/php-fpm 访问php文件直接下载而不运行

    遇到这种问题,首先确认你web服务器配置中的.PHP是不是被指定给FastCGI server处理: location ~ .php$ { fastcgi_pass ; } 如已配置,那么可能是由于f ...