kolla-ansible快速入門

kolla-ansible快速入門

kolla-ansible是一個結構相對簡單的項目,它經過一個shell腳本,根據用戶的參數,選擇不一樣的playbook和不一樣的參數調用ansible-playbook執行,沒有數據庫,沒有消息隊列,因此本文的重點是ansible自己的語法。html

kolla-ansible命令

kolla-ansible命令的主要代碼以下:java

#!/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語法便可。node

ansible

一個簡單的ansible命令示例以下:
ansible -i /root/myhosts ha01 -m setup
這個命令的做用是,對/root/hosts文件中的全部屬於ha01分類的主機,執行setup模塊收集該主機的信息,它包括兩種元素,主機清單和模塊,下面分別介紹這兩種元素。python

Host Inventory(主機清單)

host inventory 是一個文件,存放了全部被ansible管理的主機,能夠在調用anabile命令時,經過-i參數指定。mysql

  1. 下面是一個最簡單的hosts file的例子,包含1個主機ip和兩個主機名:
193.192.168.1.50
ha01
ha02·

能夠執行如下命令檢查ha01是否可以連通git

ansible -i $filename ha01 -m ping

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

2.咱們能夠把主機分類,示例以下web

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 模塊名 來查看該模塊的詳細信息。sql

1. 一個例子,ping

上文的例子,使用了-m ping參數,意思是對這些主機,執行ping 模塊,ping 模塊是一個python腳本,做用是用來判斷:目標機器是否可以經過ssh連通而且已經安裝了python。docker

# 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_configsshell

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

能夠考慮這樣兩個問題:

  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/

相關文章
相關標籤/搜索