在上一篇中已介绍了 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-* 负责处理 Dockerfile ,编译 doker 镜像。有两个 Shell 脚本文件:json
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-keystone
。 FULLIMAGE
是镜像的全名,是在 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
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而后,是一系列函数的定义:
info
打印普通讯息
success
打印成功信息
warn
打印警告
set_defaults
设置 PREFIX
和 NAMESPACE
等参数默认值
has_changed
经过 git 检查是否有文件的改变。参数为 image
,所在的目录为 ${img_dirs[$image]#$WORKDIR/}
经过 git diff 检查是否有改变。
requires_build
检查镜像是否须要进行编译
build_image
编译镜像。调用镜像目录中的 build 脚本(即 build-docker-image
脚本),进行编译。
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_dirs
和 dependency
里面。
process_image
处理镜像。函数先根据 ${dependency[$image]}
递归地调用process-image
处理其基础镜像,而后调用 requires_build
检查 $image
是否须要从新编译,须要编译时用 build-image
进行编译,最后更新 status
中的状态为 up-to-date
print_summary
打印编译总结。把 status
中的状态信息打印出来。
interrupted
中断处理函数。在中断编译时,会删除 $WORKDIR
。
usage
和参数处理
显示帮助信息,处理脚本运行参数。
其它
处理逻辑。找到 $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
生成 Kolla 所须要的环境变量。
genenv 最终生成 2 个环境变量文件 ./openrc
和 ./compose/openstack.env
。
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
openstack.env
Kolla 全部 docker 镜像在启动时须要的配置文件。从镜像启动一个容器时,须要读取这个文件的内容,并初始化各个服务(在编译镜像时,各类 OpenStack 服务尚未配置,只是安装在镜像中而已)。
Kolla 辅助工具脚本。这个脚本可经过 kolla -h
查询用法。
脚本里面定义了一系列的函数:
process
经过 docker-compose
启动 docker 容器。
process_all
启动一整个OpenStack所须要的容器,单个容器经过 process
启动
check_selinux
检查 selinux 状态
pre_start
调用 check_selinux,并 source openrc,若是 openrc 文件不存在,那么须要经过 genenv 生成
post_start
等待 OpenStack 服务启动完毕
usage
帮助函数
使用这个脚本可启动一个测试环境。
cleanup-*
清理环境
init-runonce
初始化 OpenStack 配置,下载镜像、增长安全组、创建初始网络、更新配额设置等
pre-commit-hook
Git 提交前的钩子脚本,会调用 validate*
脚本进行处理
update-build-links
更新 docker 镜像定义目录的 build 文件连接
validate*
检查各个文件是否有效