Inside Kolla - 05 從 tools 目錄開始

從 tools 目錄開始

在上一篇中已介紹了 Kolla 的源代碼目錄結構和各個目錄中源代碼的基本做用,如今開始深刻到各個目錄,介紹目錄中的具體內容。每一個人分析代碼的思路和方法不一樣,會選擇從不一樣的目錄開始。在這裏,我選擇從 tools 目錄開始,從高層瞭解 Kolla 組件間的關係、編譯依賴,命令行工具等,而後再次按照依賴來逐個組件分析。linux

tools 目錄的文件樹以下:git

.
├── build-all-docker-images
├── build-docker-image
├── cleanup-containers
├── cleanup-images
├── genenv
├── init-runonce
├── kolla
├── pre-commit-hook
├── update-build-links
├── validate-all-json.sh
├── validate-all-maintainer.sh
├── validate-all-yaml.sh
├── validate-json.py
├── validate-maintainer.sh
└── validate-yaml.py

這些文件都是腳本文件,核心的文件爲:build-* genenv kolla 。(這裏使用了 vi 來查看,並使用了 set nu,所以會帶上行號,使用一些支持列模式的編輯器可很簡單地去掉行號;由於文件版本不一樣的話,內容和行號不相同,僅供參考)docker

build-* 腳本

build-* 負責處理 Dockerfile ,編譯 doker 鏡像。有兩個 Shell 腳本文件:json

  1. build-docker-imagecentos

    編譯一個組件的 docker 鏡像。這個腳本的用法可以使用 build-docker-image -h 查看。數組

    這裏涉及了一點隱含的 Shell 技巧。 Kolla 中各個 docker 鏡像定義的目錄中,都有一個 build 文件用來編譯當前的 docker 鏡像。這些 build 文件其實都是一個連接,指向 build-docker-image 腳本。當調用 build 文件,會把 build 文件路徑做爲 $0 參數,因此 build-docker-image 腳本的 IMGDIR 變量爲指向 build 文件所在的鏡像目錄(即 docker 鏡像定義目錄,經過 dirname $0 得到),所以 build-docker-image 腳本能夠編譯當前 docker 鏡像。安全

    腳本中首先定義了一系列編譯使用到的變量,並設置了默認值,改變這些值時應參考默認值:bash

    3 TOPDIR=$(git rev-parse --show-toplevel)
       4 IMGDIR="$(cd "$(dirname "$0")" && pwd)"
       5 
       6 RELEASE_NAMESPACE=kollaglue
       7 NAMESPACE=kollaglue
       8 PREFIX=centos-rdo-
       9 TAG=$(git rev-parse --short HEAD)
      10 RELEASE_TAG=kilo

    而後,定義了一個 usage 函數,用來打印幫助內容(略)。網絡

    而後,在正式執行前,先檢查是否有編譯配置文件,若是有,執行這些文件:編輯器

    29 [ -f $TOPDIR/.buildconf ] && . $TOPDIR/.buildconf
      30 [ -f $IMGDIR/.buildconf ] && . $IMGDIR/.buildconf

    而後,會有一段常規的命令後參數處理腳本,讀取參數並轉換(略)。而後,根據參數,對鏡像命名

    97 IMAGE="${PREFIX}${IMGDIR##*/}"
      98 FULLIMAGE="${NAMESPACE}/${IMAGE}${TAG:+:${TAG}}"

    IMAGE是鏡像的名字,用編譯時前綴PREFIX和鏡像在的目錄IMGDIR(只保留路徑中最後一個'/'後的部分)來命名,如 centos-rdo-keystoneFULLIMAGE是鏡像的全名,是在 docker-registry 中的名字,並當 TAG 變量不爲空時,在IMAGE後面加上一個版本標籤,如 kollaglue/centos-rdo-keystone:kilo

    而後,建立編譯時的臨時目錄,把鏡像目錄內容拷貝到臨時目錄,使用 sed 修改掉 Dockerfile 中定義的 %%KOLLA_NAMESPACE%% %%KOLLA_PREFIX%% %%KOLLA_TAG%% 等值,而後使用 docker build 編譯。因爲全部的編譯使用同一個 TEMPDIR,所以不能同時編譯多個 docker 鏡像!

    112 TMPDIR=$(mktemp -d /tmp/kolla-build.XXXXXXXXXX)
     113 cp -aL $IMGDIR/* $TMPDIR
     114 # Use an extension for in-place editing for portability, as GNU and BSD
     115 # versions of sed behave differently otherwise
     116 sed -i.bak "s/%%KOLLA_NAMESPACE%%/${NAMESPACE}/g" $TMPDIR/Dockerfile
     117 sed -i.bak "s/%%KOLLA_PREFIX%%/${PREFIX}/g" $TMPDIR/Dockerfile
     118 sed -i.bak "s/%%KOLLA_TAG%%/${PARENT_TAG}/g" $TMPDIR/Dockerfile
     119 
     120 if ! docker build ${BUILDFLAGS} -t "$FULLIMAGE" $TMPDIR; then
     121     echo "ERROR: failed to build $FULLIMAGE"
     122     exit 1
     123 fi
     124 rm -rf $TMPDIR

    最後,若是使用了push選項,會把鏡像push到docker倉庫,此時使用到 FULLIMAGE 變量。

    128 if [ "$PUSH" = 1 ]; then
     129     if ! docker push "$FULLIMAGE"; then
     130         echo "ERROR: failed to push $FULLIMAGE"
     131         exit 1
     132     fi
     133 
     134     echo "Pushed: $FULLIMAGE"
     135 fi
  2. build-all-docker-images

    編譯全部組件的 docker 鏡像。這個腳本的用法經過 build-all-docker-image -h 得到。

    這個腳本是對 build-docker-image 的進一步封裝,從而能支持一次性編譯全部的 docker 鏡像。須要注意的是,這個腳本註明了要使用 bash 4 和 gawk。因爲部分的 Linux distribution 裏面沒有包含這些軟件,須要本身安裝(裏面只用了一句 gawk 啊!!!不明白爲何不直接用awk,或者用which檢查哪一個awk兼容軟件可用)。

    1 #!/usr/bin/env bash
       2 # Depends on bash 4 and gawk

    在 Ubuntu 14.04 Desktop裏面,就缺乏了 gawk,經過apt安裝:

    sudo apt-get install -y --force-yes gawk

    首先,定義了3個用於變量的目錄變量。 TOPDIR 是 Kolla 根目錄,這裏用了 git 來進行判斷,也可經過 dirname 來獲取; WORKDIR 是編譯時的臨時目錄; DOCKERDIR 是編譯全部 docker 鏡像的臨時目錄。Kolla 根目錄的全部內容 copy 到 WORKDIR中。

    4 TOPDIR=$(git rev-parse --show-toplevel)
       5 # Work in a temp dir so that developers can continue working while a build is
       6 # in progress
       7 WORKDIR=$(mktemp -d /tmp/kolla-workdir.XXXXXXXXXX)
       8 # Remove $WORKDIR otherwise $TOPDIR is copied *inside* of it
       9 rm -rf $WORKDIR
      10 cp -aL "$TOPDIR" $WORKDIR
      11 DOCKERDIR="$WORKDIR/docker"

    而後,定義了3個數組變量。 dependency 保存了各個 docker 鏡像依賴關係; img_dirs 保存 docker 鏡像的目錄; status 保存 docker 鏡像的編譯狀態。

    13 declare -A dependency
      14 declare -A img_dirs
      15 declare -A status
    而後,是一系列函數的定義:
    1. info
      打印普通訊息

    2. success
      打印成功信息

    3. warn
      打印警告

    4. set_defaults
      設置 PREFIXNAMESPACE 等參數默認值

    5. has_changed
      經過 git 檢查是否有文件的改變。參數爲 image,所在的目錄爲 ${img_dirs[$image]#$WORKDIR/} 經過 git diff 檢查是否有改變。

    6. requires_build
      檢查鏡像是否須要進行編譯

    7. build_image
      編譯鏡像。調用鏡像目錄中的 build 腳本(即 build-docker-image 腳本),進行編譯。

    8. init_image
      初始化鏡像編譯配置。調用 set_defaults,運行鏡像目錄的buildconf文件,經過 gawk 檢查鏡像所依賴的鏡像(就是這個地方使用了 gawk ),並處理鏡像的名字

      69 function init_image {
        70     local img_dir=$1
        71 
        72     set_defaults
        73     [ -f $WORKDIR/.buildconf ] && . $WORKDIR/.buildconf
        74     [ -f $img_dir/.buildconf ] && . $img_dir/.buildconf
        75     [ -n "$FORCE_NAMESPACE" ]  && NAMESPACE=$FORCE_NAMESPACE
        76 
        77     local image="${NAMESPACE:+${NAMESPACE}/}${PREFIX}${img_dir##*/}"
        78     local base_image=$(cat $img_dir/Dockerfile | gawk 'match($0, /^\s*FROM\s+(\S+)/, matches) {print matches[1]}' )
        79     base_image=${base_image//%%KOLLA_NAMESPACE%%/$NAMESPACE}
        80     base_image=${base_image//%%KOLLA_PREFIX%%/$PREFIX}
        81     base_image=${base_image//:%%KOLLA_TAG%%/}
        82 
        83     img_dirs[$image]=$img_dir
        84     dependency[$image]=$base_image
        85 
        86     # Restore defaults to minimize risk of side effects
        87     set_defaults
        88 }

      79-81行替換掉 %%KOLLA_NAMESPACE%% %%KOLLA_PREFIX%% :%%KOLLA_TAG%% 等標記,而後記錄到數組 img_dirsdependency 裏面。

    9. process_image
      處理鏡像。函數先根據 ${dependency[$image]} 遞歸地調用process-image處理其基礎鏡像,而後調用 requires_build 檢查 $image 是否須要從新編譯,須要編譯時用 build-image 進行編譯,最後更新 status中的狀態爲 up-to-date

    10. print_summary
      打印編譯總結。把 status 中的狀態信息打印出來。

    11. interrupted
      中斷處理函數。在中斷編譯時,會刪除 $WORKDIR

    12. usage 和參數處理
      顯示幫助信息,處理腳本運行參數。

    13. 其它
      處理邏輯。找到 $DOCKERDIR 裏面的全部 Dockerfile,而後執行 init_image 初始化編譯配置,而後使用 process_image 處理鏡像編譯。

      175 # Do a first pass to find images to build and their dependencies
      176 for dockerfile in $(find $DOCKERDIR -name Dockerfile); do
      177     init_image $(dirname $dockerfile)
      178 done
      179 
      180 # Process all images
      181 for image in "${!img_dirs[@]}"; do
      182     process_image $image
      183 done
      184 
      185 print_summary
      186 rm -rf $WORKDIR

genenv

生成 Kolla 所須要的環境變量。

genenv 最終生成 2 個環境變量文件 ./openrc./compose/openstack.env

  1. openrc

    OpenStack的訪問文件,用於各類 client 訪問 OpenStack API。

    128 export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
     129 export OS_USERNAME=$ADMIN_TENANT_NAME
     130 export OS_PASSWORD=$ADMIN_USER_PASSWORD
     131 export OS_TENANT_NAME=$ADMIN_TENANT_NAME
  2. openstack.env

    Kolla 全部 docker 鏡像在啓動時須要的配置文件。從鏡像啓動一個容器時,須要讀取這個文件的內容,並初始化各個服務(在編譯鏡像時,各類 OpenStack 服務尚未配置,只是安裝在鏡像中而已)。

kolla

Kolla 輔助工具腳本。這個腳本可經過 kolla -h 查詢用法。

腳本里面定義了一系列的函數:

  1. process

    經過 docker-compose 啓動 docker 容器。

  2. process_all

    啓動一整個OpenStack所須要的容器,單個容器經過 process 啓動

  3. check_selinux

    檢查 selinux 狀態

  4. pre_start

    調用 check_selinux,並 source openrc,若是 openrc 文件不存在,那麼須要經過 genenv 生成

  5. post_start

    等待 OpenStack 服務啓動完畢

  6. usage

    幫助函數

使用這個腳本可啓動一個測試環境。

其它腳本

cleanup-* 清理環境

init-runonce 初始化 OpenStack 配置,下載鏡像、增長安全組、創建初始網絡、更新配額設置等

pre-commit-hook Git 提交前的鉤子腳本,會調用 validate* 腳本進行處理

update-build-links 更新 docker 鏡像定義目錄的 build 文件連接

validate* 檢查各個文件是否有效

相關文章
相關標籤/搜索