设为首页 收藏本站
查看: 2071|回复: 0

[经验分享] kolla-ansible快速入门

[复制链接]

尚未签到

发表于 2018-1-2 14:15:07 | 显示全部楼层 |阅读模式
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参数指定。


  •   下面是一个最简单的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
  


  • 如果主机数量比较多,也可以用正则表达,示例如下:
  

deploy-node  

  
[ha]
  
ha[01:02]
  

  
[openstack-compute]
  
compute[01:50]
  

  
[openstack-controller]
  
controller[01:03]
  

  
[databases]
  
db-[a:f].example.com
  


  • 所有的controller和compute,都是openstack的节点,所以我们可以再定义一个类别openstack-common,把他们里面的主机都包括进去
  

[openstack-common:children]  
openstack-controller
  
openstack-compute
  

  
[common:children]
  
openstack-common
  
databases
  
ha
  


  • 当我们有了如上的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常用模块的用法:http://blog.csdn.net/iloveyin/article/details/46982023
  • ansible官网提供了所有module的用法:http://docs.ansible.com/ansible/latest/modules_by_category.html
  • ansible 所有module源码存放路径:/usr/lib/python2.7/site-packages/ansible/modules/
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
  可以考虑这样两个问题:


  • 上文我们定义webserver role作用是在指定服务器上安装并确保apache服务运行,那么如果我们想要升级,关闭或者卸载apache服务呢,该怎么办,再定义新的role,webserver-upgrade看起来似乎太蠢笨了。能不能像面向对象那样,一个对象支持不同的操作?
  • 上文中的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的功能是:


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

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

ansible_os_family == &quot;Debian&quot;  
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: &quot;net.bridge.bridge-nf-call-iptables&quot;, value: 1}
  - { name: &quot;net.bridge.bridge-nf-call-ip6tables&quot;, value: 1}
  - { name: &quot;net.ipv4.conf.all.rp_filter&quot;, value: 0}
  - { name: &quot;net.ipv4.conf.default.rp_filter&quot;, 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: &quot;{{ database_address }}&quot;
  login_port: &quot;{{ database_port }}&quot;
  login_user: &quot;{{ database_user }}&quot;
  login_password: &quot;{{ database_password }}&quot;
  name: &quot;{{ item }}&quot;
  register: database
  run_once: True
  delegate_to: &quot;{{ groups['nova-api'][0] }}&quot;
  with_items:
  - &quot;{{ nova_database_name }}&quot;
  - &quot;{{ nova_database_name }}_cell0&quot;
  - &quot;{{ nova_api_database_name }}&quot;
  

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


  • hosts: app_servers  
    tasks:


    • name: gather facts from db servers  
      setup:
        
      delegate_to: &quot;{{item}}&quot;
        
      delegate_facts: True
        
      with_items: &quot;{{groups[‘dbservers‘}}&quot;
        
      该例子会收集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(&quot;all systems go&quot;) != -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: &quot;{{ api_interface_address }}&quot;
  port: &quot;{{ murano_api_port }}&quot;
  connect_timeout: 1
  timeout: 60
  run_once: True
  delegate_to: &quot;{{ groups['murano-api'][0] }}&quot;
  

参考文档
  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/

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-430817-1-1.html 上篇帖子: Ansible实战演练 下篇帖子: Ansible自动化运维笔记1(安装配置)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表