Ussuri版Kolla-ansbile源碼分析

基於OpenStack Ussuri版,源碼下載地址:
# git clone https://github.com/openstack/kolla-ansible -b stable/ussuri
相關命令:
# kolla-ansible -i ./multinode bootstrap-servers
# kolla-ansible -i ./multinode prechecks
# kolla-ansible -i ./multinode deploy
 
簡介:
kolla-ansible是自動化部署OpenStack的項目,經過一個shell腳本,根據用戶的傳參,選擇不一樣的playbook和參數調用ansible-playbook執行,沒有數據庫和消息隊列,主要是ansible語法的處理。
 

1、kolla-ansible腳本入口

 

一、kolla-ansible命令入口文件

[root@ksfusion1 wuyongpeng]# whereis kolla-ansible
kolla-ansible: /usr/local/bin/kolla-ansible
查看文件格式爲Bourne-Again shell,即bash腳本
[root@ksfusion1 wuyongpeng]# file /usr/local/bin/kolla-ansible
/usr/local/bin/kolla-ansible: Bourne-Again shell script, ASCII text executable
[root@ksfusion1 wuyongpeng]# vim /usr/local/bin/kolla-ansible
 

二、kolla-ansible腳本結構

腳本處理流程是,先定義幾個函數,再用case ... esac處理不一樣參數狀況的處理。最後一行的process_cmd是腳本入口。

1)腳本總體結構

###******************** kolla-ansible start *****************************###
function check_environment_coherence {
執行which ansible獲取ansible路徑;
獲取並校驗ansible shebang line,從shebang line中截取python cmdline;
根據ansible_python_cmdline獲取python版本;
檢查python環境檢查是否存在kolla_ansible模塊;
獲取ansible具體版本,定義最小版本2.8,最大版本2.9;檢查若不在規定版本範圍內,則報錯退出。
}
function find_base_dir {
根據dirname "$0",獲取dir_name,用於找到kolla-ansible腳本所在的路徑。
根據返回不一樣的dir_name,拼接不一樣的BASEDIR,做爲全局變量
【此處dirname執行時,不是以root用戶,而是以kolla用戶的身份執行,返回的不是"/bin",而是"/usr/local/bin"】
}
function process_cmd {
    直接執行拼接的CMD命令(CMD命令即:ansible-playbook -i 加指定參數)。
}
function usage {
    使用手冊打印值(即在xshell中直接執行kolla-ansible後返回值,用於命令行添加參數--help返回的幫助文檔)
}
function bash_completion {
    用於配合bash-completion工具,實現命令行自動補全加強功能(詳見bash-completion工具用法)
}
 
INVENTORY="${BASEDIR}/ansible/inventory/all-in-one"  # INVENTORY默認值
PLAYBOOK="${BASEDIR}/ansible/site.yml"  # 若不指定PLAYBOOK變量,則默認值/usr/local/share/kolla-ansible/ansible/site.yml
EXTRA_OPTS=${EXTRA_OPTS}
CONFIG_DIR="/etc/kolla"
....
#While判斷,當參數個數不爲0,開始匹配參數,以」kolla-ansible -i ./multinode deploy」爲例分析
while [ "$#" -gt 0 ]; do
    case "$1" in
    (--inventory|-i)
            INVENTORY="$2"  # 獲取第二個參數,如上例,即把’/multinode’賦值給INVENTORY
            shift 2           # shift命令用於位置參數左移,如上例,shift 2執行前,$1是’-i’,執行後$1是’deploy’,(多個條件處理時,用shift可適配不一樣個數的參數)
            ;;               # case固定用法,匹配發現取值符合某一模式後,其間全部命令開始執行直至 ;;
    (......)
# 其它參數相似處理
esac
done
 
case "$1" in
(prechecks)
        ACTION="Pre-deployment checking"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=precheck"
;;
(mariadb_recovery)
        ACTION="Attempting to restart mariadb cluster"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
        PLAYBOOK="${BASEDIR}/ansible/mariadb_recovery.yml"
        ;;
(bootstrap-servers)
        ACTION="Bootstrapping servers"
        PLAYBOOK="${BASEDIR}/ansible/kolla-host.yml"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=bootstrap-servers"
        ;;
(deploy)
        ACTION="Deploying Playbooks"
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=deploy"
(......)
esac    # esac是case的結束標記。case ... esac,與switch ... case 語句相似,是一種多分枝選擇結構。case匹配一個值或一個模式成功,執行匹配的命令。
 
#  CONFIG_DIR變量默認值爲:"/etc/kolla";
#  EXTRA_OPTS的值根據shift以後的$1來肯定,例如deploy對應值爲"$EXTRA_OPTS -e kolla_action=deploy"(EXTRA_OPTS初始值爲空)
PASSWORDS_FILE="${PASSWORDS_FILE:-${CONFIG_DIR}/passwords.yml}"
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"  # ansible-playbook指定參數變量的調用,參數都是以上shell腳本內容處理以後的值
process_cmd         # 整個腳本的調用入口,其實只是調用了CMD命令
###*********************** kolla-ansible end **************************###
 
 

2)CMD命令具體解析

CMD結構:
CMD="ansible-playbook -i $INVENTORY $CONFIG_OPTS $EXTRA_OPTS $PLAYBOOK $VERBOSITY"
 
參數解釋:
INVENTORY參數,即INVENTORY文件,用於ansible配置主機組信息;(Ansible可同時操做屬於一個組的多臺主機,組和主機之間的關係經過 inventory 文件配置. 默認的文件路徑爲/etc/ansible/hosts)
CONFIG_OPTS,用於指定globals.yml,passwords.yml,配置文件目錄,主要是指定一些配置相關;
EXTRA_OPTS主要是指定執行的動做,例如」-e kolla_action=deploy」;
PLAYBOOK爲roles的入口文件site.yml.(Playbooks是Ansible的配置、部署、編排語言.能夠被描述爲一個須要遠程主機執行命令的方案,或者一組IT程序運行的命令集合。)
 
Deploy動做的調用過程爲:kolla-ansible -i multinode deploy ---->調用/usr/local/share/kolla-ansible/ansible/site.yml ---->根據site.yml文件的task調用執行各role
 
例如,執行如下三個命令,實際調用的ansible-playbook及參數以下:
[root@ksfusion1 ]# kolla-ansible -i ./multinode bootstrap-servers
Bootstrapping servers : ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=bootstrap-servers /usr/local/share/kolla-ansible/ansible/kolla-host.yml
[root@ksfusion1 ]# kolla-ansible -i ./multinode prechecks
Pre-deployment checking : ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=precheck /usr/local/share/kolla-ansible/ansible/site.yml
[root@ksfusion1 ]# kolla-ansible -i ./multinode deploy
Deploying Playbooks : ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=deploy /usr/local/share/kolla-ansible/ansible/site.yml
 
執行的ansible-playbook命令,是一個軟連接,本質上仍是調用ansible命令,區別是ansible通常執行pattern參數,ansible-playbook指定playbook參數,多用於分佈式系統的批量配置、部署、運維。
[root@ksfusion1 ]# whereis ansible-playbook
ansible-playbook: /usr/local/bin/ansible-playbook
[root@ksfusion1 ]# file /usr/local/bin/ansible-playbook
/usr/local/bin/ansible-playbook: symbolic link to ansible
[root@ksfusion1 ]# ll /usr/local/bin/ansible-playbook
lrwxrwxrwx. 1 root root 7 Aug 20 15:53 /usr/local/bin/ansible-playbook -> ansible
[root@ksfusion1 wuyongpeng]# ansible --help
usage: ansible [-h] [--version] [-v] [-b][-i INVENTORY] [-e EXTRA_VARS] [......] pattern
[root@ksfusion1 ~]# ansible-playbook -h
usage: ansible-playbook [-h] [--version] [-v] [-k] [-i INVENTORY] [-e EXTRA_VARS] playbook [playbook ...]
 
說明:
-e: playbook經過參數-e傳入變量,做爲全局變量在整個playbook中被調用。【-e @指定文件,用於批量導入全局變量】
-i: 用於指定INVENTORY文件
patterm: 用於指定yaml文件
playbook: 直譯「劇本」,可理解爲yaml格式的任務列表文件。playbook是ansible用於配置,部署和管理被控節點的劇本。經過playbook的詳細描述,執行其中的一系列tasks,可讓遠端主機達到預期的狀態。
 

3)擴展: 什麼是shebang

Shebang,也念作 hashbang,Linux中國翻譯組的GOLinux將其翻譯爲「釋伴」,即「解釋伴隨行」的簡稱。Unix 術語中,井號一般稱爲 sharp,hash 或 mesh;而歎號則經常稱爲 bang。
Shebang一般出如今類Unix系統的腳本中第一行,做爲前兩個字符。在Shebang以後,能夠有一個或數個空白字符,後接解釋器的絕對路徑,用於指明執行這個腳本文件的解釋器。在直接調用腳本時,系統的程序載入器會分析 Shebang 後的內容,將這些內容做爲解釋器指令,並調用該指令,將載有 Shebang 的文件路徑做爲該解釋器的參數,執行腳本,從而使得腳本文件的調用方式與普通的可執行文件相似。
例如,以指令#!/bin/sh開頭的文件,在執行時會實際調用 /bin/sh 程序(一般是 Bourne shell 或兼容的 shell,例如 bash、dash 等)來執行。 
 
Shebang的用法:
若是#!以後的解釋程序是一個可執行文件,那麼執行這個腳本時,它就會把文件名及其參數一塊兒做爲參數傳給那個解釋程序去執行。
 
Shebang注意事項:
#! 必須鏈接在一塊兒
#! 一句必須在文件的最開始的第一行
# 開頭的語句通常狀況下會被當成註釋而忽略,因此Shebang 對文件的內容是沒有影響的
#! 開頭的一行會設置解釋器運行環境
 
 

三、kolla-ansible項目文件目錄分析

a、一級目錄

1)ansible[d]: ansible的整個playbook代碼,包括部署docker容器和openstack組件。源碼主要集中在這個目錄下。
2)Doc[d]:文檔
3)Etc[d]: 配置文件,當前只有globals.yml和passwords.yml兩個文件,安裝完了引用到了/etc目錄下。
4)Tools[d]: 一些和kolla交換的腳本工具,大部分是可手動調用,主要完成一些安裝先後的一些操做。有些會被ansible目錄下的task調用到。
包括kolla-ansible指定命令腳本、init-runonce初始化配置腳本、openrc-example生成openrc模板等文件
5)文件及說明
setup.cfg[-]:安裝配置入口文件 
setup.py[-]:安裝執行腳本,經過pbr打包,執行過程會讀取setup.cfg配置,還會安裝同父目錄下requirements.txt中的依賴。setup.py所需的實際元數據存儲在setup.cfg中
python pbr打包說明 : [OpenStack項目都使用了setuptools和pbr來執行打包工做,項目的元數據都放在 setup.cfg 文件中]
 

b、二級目錄(只分析ansible目錄的二級目錄)

1)ansible/action_plugins[d]: 自定義ansible插件,兩個腳本,用於合併yml和conifg的配置文件。
merge_configs.py文件,在playbook內經過使用merge_config來合併配置文件模板,生成openstack各服務的配置文件
2)ansible/group_vars[d]: 目錄下只有一個all.yml文件,用於ansible腳本的全局變量定義。
all.yml文件做爲ansible的變量文件,定義了各種配置信息。好比:配置文件路徑,網卡,IP,端口號,各服務的開啓等。與global.yml文件的差異就是,部分的配置已經在global.yml文件內作了定義,global.yml具備更高優先級。
3)ansible/inventory[d]: 包括all-in-one和mulitnode兩個inventory清單模板文件。
4)ansible/library[d]: 包括一些自定義的ansible模塊,bslurp.py和kolla_docker.py用到比較多。
5)ansible/role[d]: 全部的openstack的組件,幾乎包含了說有開源項目,當前Ussuri版本有81個組件。
6)ansible/site.yml[-] : roles引用的入口文件,kolla-ansible部署的入口,kolla調用ansible執行playbook的入口文件
 

c、三級目錄library

1)ansible/library/ bslurp.py : 從遠程節點獲取文件,並分發到更多節點
2)ansible/library/kolla_docker.py : 用於控制Docker容器的啓動、刪除等相關操做。openstack的組件都經過容器部署,每一個組件role的部署都會用到。
3)ansible/library/kolla_container_facts.py : 用於檢查是否有容器正在運行

d、三級目錄role

在kolla-ansible內,爲了便於維護不一樣組件業務的多個playbook文件,對各個openstack服務進行部署,ansible採用role的方式對playbook進行目錄結構規範。
在roles目錄內,有部署openstack各服務所需的各類playbook、定義的變量以及模板文件等。
 
以roles目錄下的nova目錄爲例說明,
(/usr/local/src/kolla-ansible/ansible/roles/nova)
nova/  //nova角色的目錄
├── defaults  //爲當前角色設定默認變量時使用此目錄,應當包含一個main.yml文件
│   └── main.yml //做爲當前role的變量文件,定義了關於nova服務的相關參數
├── handlers  //此目錄總應當包含一個main.yml文件,用於定義各角色用到的各handler
│   └── main.yml //建立,啓動nova各服務容器的playbook,但handlers只能在被觸發的狀況下才會去執行相關被觸發的task
├── tasks
│   ├── bootstrap_service.yml //將會啓動bootstrap引導容器,用於解決nova服務所需的依賴配置,在完成後,這些引導容器將被自動刪除
│   ├── bootstrap.yml //爲nova建立數據庫及數據庫用戶等
│   ├── config.yml //經過模板爲nova的各服務生成配置文件
│   ├── deploy.yml
│   ├── main.yml //入口執行文件
│   ├── precheck.yml
│   ├── pull.yml
│   ├── reconfigure.yml
│   ├── register.yml
│   └── upgrade.yml
└── templates //templates目錄下存放着不少j2格式的文件,他們都是nova各服務的配置文件模板,這些模板將被config.yml根據須要生成爲各服務的配置文件. template模塊會自動在此目錄中尋找Jinja2模板文件
    ├── nova-api-bootstrap.json.j2
    ├── nova-api.json.j2
    ├── nova.conf.j2
    ├── nova-scheduler.json.j2
    └── nova-super-conductor.json.j2
 

2、bootstrap-servers動做

一、命令描述

shell調用命令:
# kolla-ansible -i ./multinode bootstrap-servers
在kolla-ansible腳本中的相關處理:
(bootstrap-servers)
        ACTION="Bootstrapping servers"
        PLAYBOOK="${BASEDIR}/ansible/kolla-host.yml"  # 此處即/usr/local/share/kolla-ansible/ansible/kolla-host.yml
        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=bootstrap-servers"
        ;;
具體調用:
# ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=bootstrap-servers /usr/local/share/kolla-ansible/ansible/kolla-host.yml
 

二、yaml文件分析

源碼以下:
[root@ksfusion1 ]# cat /usr/local/share/kolla-ansible/ansible/kolla-host.yml
---
- import_playbook: gather-facts.yml
- name: Apply role baremetal
  hosts: baremetal
  serial: '{{ kolla_serial|default("0") }}'
  gather_facts: false
  roles:
    - { role: baremetal,
        tags: baremetal }
說明:
1)import_playbook:主playbook能夠導入子playbook,./kolla-ansible/ansible/gather-facts.yml用於獲取遠程主機信息。
2)hosts值爲baremetal,在all-in-one節點,baremetal指向control組;在multinode節點,baremetal指向control、network、compute等全部物理節點的組;
all-in-one node:
[baremetal:children]
control
multinode node:
[baremetal:children]
control
network
compute
storage
monitoring
3)role和tags都爲baremetal,接下來進入roles的baremetal目錄中執行
4)roles/baremetal/defaults/main.yml文件中,定義了default變量。
5)roles/baremetal/tasks/main.yml文件,爲入口文件
內容以下,使用include_tasks分散調用tasks:
---
- include_tasks: "{{ kolla_action }}.yml"
 
即調用執行bootstrap-servers.yml
---
- include_tasks: pre-install.yml
- include_tasks: install.yml
- include_tasks: post-install.yml
- include_tasks: configure-containerd-for-zun.yml
  when: containerd_configure_for_zun|bool and
        inventory_hostname in groups['zun-cni-daemon']
pre-install.yml、install.yml、post-install.yml等文件中,直接展現的是task的內容。
 
所以,執行 kolla-ansible -i ./multinode bootstrap-servers,實際執行的是pre-install.yml、install.yml、post-install.yml等文件的tasks任務清單。
6)pre-install.yml文件task內容分析
共有6個task和一個block
task1:Ensure localhost in /etc/hosts
task2:Ensure hostname does not point to 127.0.1.1 in /etc/hosts
task3:把全部節點信息寫入/etc/hosts
task4:檢查cloud-init是否已安裝,確保manage_etc_hosts配置disabled。
task5:確保sudo組狀態爲present
task6:確保kolla組狀態爲present
block(當前只分析RedHat,包含四個task):
(1)確保/etc/yum.repos.d/目錄存在
(2)啓動docker的yum倉庫yum_repository
(3)確保/etc/yum.repos.d/docker.repo中module_hotfixes = True
(4)安裝docker rpm gpg key
7)install.yml文件task內容分析
共有12個task和一個bolck,主要功能以下:
更新Debian apt緩存;關閉Debian防火牆;檢查RedHat下firewalld是否安裝;關閉RedHat下firewalld;檢查是否有docker運行;
安裝apt/RPM包(從roles/baremetal/defaults/main.yml的對應變量中讀取安裝包列表,例如redhat_pkg_install);
啓動docker,並等待Docker啓動成功;
當環境是virtualenv,在對應virtualenv中安裝最新的pip;
爲python安裝docker SDK;
刪除配置文件列表中指定的待刪除包(roles/baremetal/defaults/main.yml中的ubuntu_pkg_removals和redhat_pkg_removals);
 
8)post-install.yml文件task內容分析
共有35個task,主要功能以下:
建立kolla用戶、添加kolla用戶的公鑰、受權kolla用戶無密碼sudo權限;
確保virtualenv權限正確;確保node_config_directory對應目錄存在,且給kolla用戶使用【node_config_directory參數再main.yml沒有,global.yml也沒有??】;
【如下操做,因爲當前defaults/main.yml配置中docker_custom_option相關值爲空,所以不執行。】
Merge Zun docker config;
警告docker_custom_option是不同意的使用方法;設置docker不安全的註冊表;設置docker存儲驅動;設置docker運行目錄;
docker默認iptables的警告;禁用docker默認ipbtales規則;merge自動以的docker配置;把自定義docker配置寫入/etc/docker/daemon.json;移除舊的docker配置文件;
確保docker服務目錄/etc/systemd/system/docker.service.d存在;使用此目錄下的kolla.conf,配置docker服務;
 
Reload docker service文件;
建立docker group;添加kolla用戶到docker組;啓動docker;當docker有變化,重啓docker;
按OS類型,中止時間服務器;若enable_host_ntp爲True(當前爲False),則同步時間;啓動ntpd服務;
更改selinux狀態;
 
補充:
(1)node_config_directory默認爲/etc/kolla/,以下:
# ll /etc/| grep kolla
drwxr-xr-x. 42 kolla kolla   4096 Nov 11 17:54 kolla
在何處配置讀取node_config_directory變量的默認值,待分析。
 
 

3、prechecks動做 和 deploy動做

一、prechecks命令描述

# kolla-ansible -i ./multinode prechecks
具體調用:
ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=precheck /usr/local/share/kolla-ansible/ansible/site.yml
 

二、deploy命令描述

# kolla-ansible -i ./multinode deploy
具體調用:
ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=deploy /usr/local/share/kolla-ansible/ansible/site.yml
 
 

三、site.yml文件結構task內容分析

共有69個task和2個import_playbook。
import_playbook包括最開始的gather-facts.yml和nova.yml。
其中nova.yml中又包含10個task子任務,分別完成nova API和cell的數據庫初始化、調用nova role的main.yml、調用nova-cell role的main.yml、重載scheduler|conductor|api|cell服務等操做。
 
site.yml文件中,除了第一個task,其它task都是基於roles的應用,會執行kolla-ansible/ansible/roles/目錄下對應roles目錄中的內容。
第一個task,用於根據kolla的配置對主機進行分組,共有兩個group_by進行分組:
1)第一個分組,是根據傳入的kolla_action變量進行hosts分組,以後的tasks列表中,只有kolla_action_precheck使用此分組,此處指定kolla_action=precheck,即執行此role內容;
2)第二個分組,會遍歷with_items中全部roles列表。
 

四、prechecks調用

對應site.yml中的task以下:
- name: Apply role prechecks
  gather_facts: false
  # Apply only when kolla action is 'precheck'.
  hosts: kolla_action_precheck
  roles:
    - role: prechecks
 
即調用roles下prechecks目錄對應的main.yml文件,依次執行如下導入yml對應的task。
---
- include_tasks: host_os_checks.yml
  when: prechecks_enable_host_os_checks | bool
- include_tasks: timesync_checks.yml
  when:
    - not enable_chrony | bool
- include_tasks: datetime_checks.yml
- include_tasks: port_checks.yml
  when:
    - inventory_hostname not in groups['deployment']|default([])
- include_tasks: service_checks.yml
- include_tasks: package_checks.yml
- include_tasks: user_checks.yml
- include_tasks: database_checks.yml
 
疑問:kolla_action_precheck變量從哪裏定義的?? 若沒有定義,是否默認值是localhost??
 

五、deploy 調用

1)deploy操做總體分析

具體調用:# ansible-playbook -i ./multinode -e @/etc/kolla/globals.yml -e @/etc/kolla/passwords.yml -e CONFIG_DIR=/etc/kolla  -e kolla_action=deploy /usr/local/share/kolla-ansible/ansible/site.yml
deploy操做對應的kolla_action參數deploy,可是調用site.yml會遍歷執行yml中的全部符合條件的任務,而不只僅是kolla_action=deploy的task。
 

2)site.yml文件中kolla_action=deploy時執行的操做

kolla_action=deploy時,執行是name爲’Apply role haproxy’的task,使用include_role動態導入tasks列表中全部組件的role。
- name: Apply role haproxy
  gather_facts: false
  hosts:
    - haproxy
    - '&enable_haproxy_True'
  serial: '{{ kolla_serial|default("0") }}'
  tags:
    - haproxy
  roles:
    - { role: haproxy,
        when: enable_haproxy | bool }
  tasks:
    - block:
        - include_role:
            name: aodh
            tasks_from: loadbalancer
          tags: aodh
          when: enable_aodh | bool
        - include_role:
            name: barbican
         ...... #此處省略openstack其它組件的role導入,共47個組件
when:
  - enable_haproxy | bool
  - kolla_action in ['deploy', 'reconfigure', 'upgrade', 'config']
 
 
 

3)haproxy role task中,包含47個task子任務,此處以nova爲例分析

(1)在tasks中使用include_role動態導入nova的入口

在name爲’Apply role haproxy’的tasks清單中,nova使用include_role動態導入流程以下(nova和nova-cell分開):
- include_role:
    name: nova
    tasks_from: loadbalancer
  tags:
    - nova
    - nova-api
  when: enable_nova | bool
此處的tasks_from,和include_role配合使用,用於指定要從tasks目錄中加載的文件,即roles/nova/tasks/loadbalancer.yml(若tasks_from不指定,默認爲main.yml),加載的文件以下:
 
[root@ksfusion1 nova]# cat roles/nova/tasks/loadbalancer.yml
---
- name: "Configure haproxy for {{ project_name }}"
  import_role:
    name: haproxy-config
  vars:
    project_services: "{{ nova_services }}"
  tags: always
[root@ksfusion1 nova]#
 

(2)使用import_role靜態導入haproxy-config

 
首先,讀取nova_services變量值,即project_services變量值的獲取
變量會從roles/nova/defaults/main.yml中讀取,nova_services爲嵌套的字典結構,包括三個鍵值對,nova-api、nova-scheduler、nova-super-conductor,具體以下:
[root@ksfusion1 ansible]# more roles/nova/defaults/main.yml
---
project_name: "nova"
 
nova_services:
  nova-api:
    container_name: "nova_api"
    group: "nova-api"
    image: "{{ nova_api_image_full }}"
    enabled: True
    privileged: True
    volumes: "{{ nova_api_default_volumes + nova_api_extra_volumes }}"
    dimensions: "{{ nova_api_dimensions }}"
    haproxy:
      nova_api:
        enabled: "{{ enable_nova }}"
        mode: "http"
        external: false
        port: "{{ nova_api_port }}"
        listen_port: "{{ nova_api_listen_port }}"
        tls_backend: "{{ nova_enable_tls_backend }}"
      nova_api_external:
        enabled: "{{ enable_nova }}"
        mode: "http"
        external: true
        port: "{{ nova_api_port }}"
        listen_port: "{{ nova_api_listen_port }}"
        tls_backend: "{{ nova_enable_tls_backend }}"
      nova_metadata:
        enabled: "{{ enable_nova }}"
        mode: "http"
        external: false
        port: "{{ nova_metadata_port }}"
        listen_port: "{{ nova_metadata_listen_port }}"
        tls_backend: "{{ nova_enable_tls_backend }}"
      nova_metadata_external:
        enabled: "{{ enable_nova }}"
        mode: "http"
        external: true
        port: "{{ nova_metadata_port }}"
        listen_port: "{{ nova_metadata_listen_port }}"
        tls_backend: "{{ nova_enable_tls_backend }}"
  nova-scheduler:
    container_name: "nova_scheduler"
    group: "nova-scheduler"
    image: "{{ nova_scheduler_image_full }}"
    enabled: True
    volumes: "{{ nova_scheduler_default_volumes + nova_scheduler_extra_volumes }}"
    dimensions: "{{ nova_scheduler_dimensions }}"
  nova-super-conductor:
    container_name: "nova_super_conductor"
    group: "nova-super-conductor"
    enabled: "{{ enable_cells }}"
    image: "{{ nova_super_conductor_image_full }}"
    volumes: "{{ nova_super_conductor_default_volumes + nova_super_conductor_extra_volumes }}"
    dimensions: "{{ nova_super_conductor_dimensions }}"
......
 
 
對於always的tag,在執行playbook時,只要沒有明確指定不執行always tag,那麼它就會被執行。
所以,此處爲導入nova組件的role真正執行的動做,即import_role靜態導入haproxy-config的role,加載執行roles/haproxy-config/tasks/main.yml文件,以下:
 
[root@ksfusion1 ansible]# cat roles/haproxy-config/tasks/main.yml
---
- name: "Copying over {{ project_name }} haproxy config"
  vars:
    service: "{{ item.value }}"
    haproxy_templates:
      - "{{ node_custom_config }}/haproxy-config/{{ inventory_hostname }}/{{ haproxy_service_template }}"
      - "{{ node_custom_config }}/haproxy-config/{{ haproxy_service_template }}"
      - "templates/{{ haproxy_service_template }}"
    template_file: "{{ query('first_found', haproxy_templates) | first }}"
  template:
    src: "{{ template_file }}"
    dest: "{{ node_config_directory }}/haproxy/services.d/{{ item.key }}.cfg"
    mode: "0660"
  become: true
  when:
    - service.enabled | bool  # 從roles/nova/defaults/main.yml可知此變量爲True
    - service.haproxy is defined # 從roles/nova/defaults/main.yml可知此變量已定義
    - enable_haproxy | bool # 從/etc/kolla/globals.yml可知此變量默認值爲yes,所以,nova組件的三個條件都知足
  with_dict: "{{ project_services }}"
  notify:
    - Restart haproxy container
[root@ksfusion1 ansible]#
 
其中,ansible/group_vars/all.yml文件中有如下變量:node_config_directory: "/etc/kolla" ;node_custom_config: "/etc/kolla/config"
roles/haproxy-config/defaults/main.yml中有如下變量定義:haproxy_service_template: "haproxy_single_service_listen.cfg.j2"
 
當前環境中,因爲沒法讀取到node_custom_config變量對應的路徑(node_custom_config默認值爲/etc/kolla/globals.yml中的#node_custom_config: "/etc/kolla/config"),所以
{{ query('first_found', haproxy_templates) | first }}會遍歷讀取到第三個路徑的文件,即roles/haproxy-config/templates/haproxy_single_service_listen.cfg.j2
 
template模塊用於從本地拷貝文件到遠程節點,並進行變量的替換。通常用於遠程複製配置文件,用jinja2格式的{{}}注入變量。
此處,item.key爲nova-api,template模塊操做,把本地的haproxy_single_service_listen.cfg.j2模板,注入變量後,複製到遠程的文件路徑爲/etc/kolla/haproxy/services.d/nova-api.cfg。
 
所以,47個task子任務中,nova子任務完成的實際操做是,把本地的haproxy_single_service_listen.cfg.j2模板注入變量後,複製到遠程節點目錄/etc/kolla/haproxy/services.d/nova-api.cfg。其它的nova相關操做,在nova.yml中執行。
 

4)haproxy role task中,包含47個task子任務,此處再以cinder爲例分析

(1)在tasks中使用include_role動態導入cinder的入口

首先,根據全局配置文件,組成enable_cinder_True變量,使用group_by模塊按此變量分組。
- enable_cinder_{{ enable_cinder | bool }}
在/etc/kolla/globals.yml配置文件中:enable_cinder: "yes",所以,site.yml的第一個task中,組合的enable_cinder_True變量,
此變量用於group_by模塊動態添加分組主機,使用流程爲:先按模塊分組;而後再分別對指定組進行playbook的設置。
 

(2)在name爲’Apply role haproxy’的tasks清單中,cinder使用include_role動態導入流程

- include_role:
    name: cinder
    tasks_from: loadbalancer
  tags: cinder
  when: enable_cinder | bool
此處的tasks_from,和include_role配合使用,用於指定要從tasks目錄中加載的文件,即roles/cinder/tasks/loadbalancer.yml,加載的文件以下:
[root@ksfusion1 ansible]# cat roles/cinder/tasks/loadbalancer.yml
---
- name: "Configure haproxy for {{ project_name }}"
  import_role:
    name: haproxy-config
  vars:
    project_services: "{{ cinder_services }}"
  tags: always
 

(3)使用import_role靜態導入haproxy-config

 
首先,讀取cinder_services變量值,即project_services變量值的獲取。
變量會從roles/cinder/defaults/main.yml中讀取,cinder_services爲嵌套的字典結構,包括四個鍵值對,cinder-api、cinder-scheduler、cinder-volume、cinder-backup,具體以下:
[root@ksfusion1 ansible]# more roles/cinder/defaults/main.yml
---
project_name: "cinder"
 
cinder_services:
  cinder-api:
    container_name: cinder_api
    group: cinder-api
    enabled: true
    image: "{{ cinder_api_image_full }}"
    volumes: "{{ cinder_api_default_volumes + cinder_api_extra_volumes }}"
    dimensions: "{{ cinder_api_dimensions }}"
    haproxy:
      cinder_api:
        enabled: "{{ enable_cinder }}"
        mode: "http"
        external: false
        port: "{{ cinder_api_port }}"
        listen_port: "{{ cinder_api_listen_port }}"
        tls_backend: "{{ cinder_enable_tls_backend }}"
      cinder_api_external:
        enabled: "{{ enable_cinder }}"
        mode: "http"
        external: true
        port: "{{ cinder_api_port }}"
        listen_port: "{{ cinder_api_listen_port }}"
        tls_backend: "{{ cinder_enable_tls_backend }}"
  cinder-scheduler:
    container_name: cinder_scheduler
    group: cinder-scheduler
    enabled: true
    image: "{{ cinder_scheduler_image_full }}"
    volumes: "{{ cinder_scheduler_default_volumes + cinder_scheduler_extra_volumes }}"
    dimensions: "{{ cinder_scheduler_dimensions }}"
  cinder-volume:
    container_name: cinder_volume
    group: cinder-volume
    enabled: true
    image: "{{ cinder_volume_image_full }}"
    privileged: True
    ipc_mode: "host"
    volumes: "{{ cinder_volume_default_volumes + cinder_volume_extra_volumes }}"
    dimensions: "{{ cinder_volume_dimensions }}"
  cinder-backup:
    container_name: cinder_backup
    group: cinder-backup
    enabled: "{{ enable_cinder_backup | bool }}"
    image: "{{ cinder_backup_image_full }}"
    privileged: True
    volumes: "{{ cinder_backup_default_volumes + cinder_backup_extra_volumes }}"
dimensions: "{{ cinder_backup_dimensions }}"
......
 
對於always的tag,在執行playbook時,只要沒有明確指定不執行always tag,那麼它就會被執行。
所以,此處爲導入cinder組件的role真正執行的動做,即import_role靜態導入haproxy-config的role,加載執行roles/haproxy-config/tasks/main.yml文件,以下:
 
[root@ksfusion1 ansible]# cat roles/haproxy-config/tasks/main.yml
---
- name: "Copying over {{ project_name }} haproxy config"
  vars:
    service: "{{ item.value }}"
    haproxy_templates:
      - "{{ node_custom_config }}/haproxy-config/{{ inventory_hostname }}/{{ haproxy_service_template }}"
      - "{{ node_custom_config }}/haproxy-config/{{ haproxy_service_template }}"
      - "templates/{{ haproxy_service_template }}"
    template_file: "{{ query('first_found', haproxy_templates) | first }}"
  template:
    src: "{{ template_file }}"
    dest: "{{ node_config_directory }}/haproxy/services.d/{{ item.key }}.cfg"
    mode: "0660"
  become: true
  when:
    - service.enabled | bool  # 從roles/nova/defaults/main.yml可知此變量爲True
    - service.haproxy is defined # 從roles/nova/defaults/main.yml可知此變量已定義
    - enable_haproxy | bool # 從/etc/kolla/globals.yml可知此變量默認值爲yes,所以,nova組件的三個條件都知足
  with_dict: "{{ project_services }}"
  notify:
    - Restart haproxy container
[root@ksfusion1 ansible]#
 
其中,ansible/group_vars/all.yml文件中有如下變量:node_config_directory: "/etc/kolla" ;node_custom_config: "/etc/kolla/config"
roles/haproxy-config/defaults/main.yml中有如下變量定義:haproxy_service_template: "haproxy_single_service_listen.cfg.j2"
 
當前環境中,因爲沒法讀取到node_custom_config變量對應的路徑(node_custom_config默認值爲/etc/kolla/globals.yml中的#node_custom_config: "/etc/kolla/config"),所以
{{ query('first_found', haproxy_templates) | first }}會遍歷讀取到第三個路徑的文件,即roles/haproxy-config/templates/haproxy_single_service_listen.cfg.j2
 
template模塊用於從本地拷貝文件到遠程節點,並進行變量的替換。通常用於遠程複製配置文件,用jinja2格式的{{}}注入變量。
此處,with_dict遍歷讀取project_services中的四組鍵值對,當item.key爲cinder-api時,haproxy-config中template模塊會把本地的haproxy_single_service_listen.cfg.j2模板,注入變量後,複製到遠程節點路徑爲/etc/kolla/haproxy/services.d/cinder-api.cfg。
 

5)執行cinder服務相關操做

上一步,在haproxy中配置好cinder以後,往下會執行到名爲Apply role cinder的task,以下:
 
- name: Apply role cinder
  gather_facts: false
  hosts:
    - cinder-api
    - cinder-backup
    - cinder-scheduler
    - cinder-volume
    - '&enable_cinder_True'
  serial: '{{ kolla_serial|default("0") }}'
  roles:
    - { role: cinder,
        tags: cinder,
        when: enable_cinder | bool }
 
此處,主要執行roles目錄下cinder子目錄中task中的main.yml,順序調用deploy.yml中的任務便可。
主要實現:
register.yml調用roles/service-ks-register/tasks/main.yml,對cinder組件在keystone服務中建立相關的'endpoints'、'project'、'user'、'role'等。
config.yml調用roles/cinder/tasks/config.yml,實現cinder相關的檢查配置policy文件、cinder-api服務配置、cinder.conf配置、cinder_volume使用的nfs配置、檢查cinder container等。
clone.yml,下載cinder源碼;
bootstrap.yml,建立cinder數據庫、數據庫用戶及權限配置;
check.yml,建立volume,清除volume操做。
 
[root@ksfusion1 ansible]# cat roles/cinder/tasks/main.yml
---
- include_tasks: "{{ kolla_action }}.yml"
 
[root@ksfusion1 ansible]# cat roles/cinder/tasks/deploy.yml
---
- include_tasks: register.yml
  when: inventory_hostname in groups['cinder-api']
- include_tasks: config.yml
- include_tasks: clone.yml
  when: cinder_dev_mode | bool
- include_tasks: bootstrap.yml
  when: inventory_hostname in groups['cinder-api']
- name: Flush handlers
  meta: flush_handlers
- include_tasks: check.yml
 
此處的meta任務是一種特殊任務,meta任務可影響ansible的內部運行方式。meta:flush_handlers表示當即執行以前的task所對應handler.
相關文章
相關標籤/搜索