纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

管理2000+Docker镜像Kolla是如何做到的

DavyCloud   2020-01-30 我要评论

根据 DockerHub 上的数据整个 Kolla 项目管理的 镜像有 2000 多个这么多的镜像是怎么定义又是如何构建的呢?

简介

我们一直在说的 Kolla通常情况下泛指包括了 KollaKolla-Ansible 两个项目

实际上根据 OpenStack Wiki还有个 Kayobe 项目也是相关的但是这个用的比较少而且我试用后觉得不是特别符合我的需求就不过多介绍了

此外还有一个项目 Kolla-kubernetes 致力于和 Kubernetes 结合但是和另一个项目 openstack-helm 重合较多提前退休了

Kolla 项目开始之初只有一个项目从构建 docker 容器到使用 ansible 部署全流程搞定后来把 ansible 这块分离了出来独立为 kolla-ansible 项目原来的 kolla 专门负责 docker 镜像的构建

镜像划分的维度

虽然最终的镜像个数超过 2000 个实际并不是完全独立的 2000 多个服务而是针对不同的场景分别构建多维度全面覆盖的结果

镜像分层

熟悉 Docker 的小伙伴都知道Dockerfile 是可以指定“继承”关系的也就是利用镜像分层的特性逐层构建

OpenStack 中有很多子服务隶属于同一个项目例如nova-api nova-compute 等都属于 nova所以很自然地可以先构建一个通用的 nova-base 镜像然后在此基础上分别构建不同的服务

这是一个纵向的划分维度

功能划分

因为 Kolla 项目不仅是把 OpenStack 的服务集成了周边用到的组件和辅助服务也都囊括在内包括 RabbitMQMariaDB 等

这是一个横向的划分维度

以上两个是最基础的划分维度也是我们能够很容易想到的

操作系统

每个 Docker 镜像最底层只能是操作系统的基础镜像现在主流的 Linux 发行版有好几家OpenStack 作为一个世界级的开源项目要是只绑定一家其他人可不答应

所以必须要同时支持多个操作系统这个靠 Dockerfile 显然解决不了

如果为每个操作系统单独的定义一份 Dockerfile 显然不够聪明 Kolla 使用了 Jinja 模板文件多做了一层抽象根据指定的参数先由 Dockerfile.j2 生成 Dockerfile

这个维度在 kolla 中对应的参数是 base目前支持的操作系统有:

['centos', 'rhel', 'ubuntu', 'debian']

Jinja 是 Python 中使用比较广泛的模板引擎(template engine)之所以叫 Jinja是因为日本的神社(Jinja)英文单词是 temple而模板的英文是 template两者发音很相似(什么脑回路)Jinja 项目的 Logo 也是一个神社的图标可能是因为这层关系这个在国内似乎讨论的并不多

安装方式

Kolla 不仅是要作单纯的部署工具还希望能够替代 devstack 为开发助力所以除了从软件源(如 yumapt 等)直接安装打包好的程序还要能够直接从源码安装

从软件包称为 binary从源码安装称为 source

这个维度也是在处理 Jinja 模板的阶段完成

实际上还有 2 个安装方式rdorhos都是针对 RedHat 系统的一般不怎么会用到

操作系统和安装方式这两个维度决定了镜像名称的前缀:

文件的组织结构

了解了划分维度我们来看一下具体的文件组织结构是怎样的

所有的构建 Docker 镜像相关的文件都存放在 kollahttps://cdn9.52xs.com.cn/docker 目录下这下面的文件夹众多下面把有代表性的列了出来:

docker/
├── base
│   └── Dockerfile.j2
├── horizon
│   └── Dockerfile.j2
├── mariadb
│   └── Dockerfile.j2
├── nova
│   ├── nova-api
│   │   └── Dockerfile.j2
│   ├── nova-base
│   │   └── Dockerfile.j2
│   └── nova-compute
│       └── Dockerfile.j2
└── openstack-base
    └── Dockerfile.j2

每个文件夹代表了一个服务除了名字带 base 的其中顶层的有 2 个:

  • base 这是所有镜像的初始层
  • openstack-base 这是所有 OpenStack 相关服务的初始层

如果一个组件包含多个服务比如 nova它内部就会又多出一层基础层: nova-base所有其它的 nova-<xxx> 都是从这层开始如果一个组件只有一个服务则不需要再有子文件夹直接是 Dockerfile.j2 文件

镜像层之间的关系是在 Dockerfile 文件中的 FROM 语句定义的它们在 jinja 模板中是固定的

例如 horizon/Dockerfile.j2 中:

FROM {{ namespace }}/{{ image_prefix }}openstack-base:{{ tag }}

openstack-base/Dockerfile.j2 中:

FROM {{ namespace }}/{{ image_prefix }}base:{{ tag }}

它们之间的依赖关系是这样的:

base
├── openstack-base
│   ├── nova-base
│   │   └── nova-api
│   │   └── nova-compute
│   └── horizon
└── mariadb

可以看到最多就 4 层

包含 .j2 文件的文件夹名字最终会成为镜像名的一部分如 <os>-<type>-nova-api

这里的 <os>-<type>- 也就是对应上面的 {{ image_prefix }} 字符串分别对应:

所以最终上面的文件对应的镜像是:

centos-binary-base
centos-binary-openstack-base
centos-binary-nova-base
centos-binary-nova-api
centos-binary-nova-compute
centos-binary-horizon

注意并不是每个镜像都支持任意的类型组合具体需要查看 kolla 源码

base 镜像的作用

所有镜像的源头都是 base所以它肯定是很重要的其中内容主要有两个地方比较关键:

设置软件仓库源

所有软件包的安装源配置都在 base 中完成不管是 OpenStack 安装源还是其它依赖的公共组件安装源统统在基础镜像里固定下来了

所以在国内网络不好的情况下就必须要替换其中的仓库源

设置容器启动命令

定义了默认的 ENTRYPOINTCMD也就是把容器的启动方式固定了下来

相信这里大家会有疑惑那么多不同的服务怎么可能在这里把启动命令固定下来呢?其实这里有一点技巧

这里 kolla 固定了一个启动脚本 start.sh在这个脚本里从固定位置 /run_command 读到真正的执行命令/run_command 则是由 kolla-ansible 在启动容器的时候注入的

还记得在 介绍 Kolla 的配置文件 时看到的 config.json 么其中有一个 command 字段例如 Horizon 服务的配置:

{
    "command": "/usr/sbin/httpd -DFOREGROUND",
    "config_files": [
        {
            "source": "/var/lib/kolla/config_files/horizon.conf",
            "dest": "/etc/httpd/conf.d/horizon.conf",
            "owner": "horizon",
            "perm": "0600"
        },
    ]
}

这样做既保证了构建镜像时候的一致性又保证了容器启动的灵活性

处理流程

kolla 构建镜像的流程非常简单大体就是 5 个步骤:

1. 生成 Dockerfile

docker 整个目录复制到一个临时的工作目录然后在其中扫描包含有 Dockerfile.j2 文件的文件夹正如在上面分析的那样这样的一个文件夹就对应一个镜像

使用从配置文件中获取的操作系统基础镜像和安装方式等参数渲染生成 Dockerfile 文件

参考源码:create_dockerfiles

2. 构建镜像列表

将上一步生成的 Dockerfile 都读取到内存处理里面的 FROM 语句可以获得每个镜像的 parent 名字还有其它一些关于安装方式的细节也要处理不用过多关心

这一步完成我们就得到了一个镜像列表这里的镜像指的是 kolla 定义的 Image 类的实例

3. 查找镜像关系

遍历整个镜像列表把它们的依赖关系整理清楚

4. 过滤镜像列表

因为总共镜像数量比较多所以需要根据用户提供的参数做一下过滤

过滤参数有两种方式:

  • 预先定义了几组常用的镜像分组称为 profile指定分组名就可以构建对应的镜像
  • 通过正则表达式匹配镜像的名字来选择

5. 执行构建

使用多线程任务队列批量执行构建

构建完镜像后还有一个可选操作将镜像 push 到指定的 registry 中

以上过程有兴趣的可以自行去看 kolla 源码主要内容就集中在 1 个 build.py 文件还是很简单的

使用方法

为避免本文内容失效请关注 Kolla 项目官方文档 获取更新

安装 Python 3

CentOS 7 自带的 Python 版本还是 2.7在 2020 年后不再维护Kolla 项目有的依赖包不再支持

yum install python3

CentOS 7 的安装源提供的 Python 3 版本是 3.6.8

创建虚拟环境(可选)

推荐在 Python 虚拟环境中安装 Kolla:

python3 -m venv .virtualenvs/kolla-build
source .virtualenvs/kolla-build/bin/activate
(kolla-build) [root@davycloud ~]#

以下操作默认都在虚拟环境下执行

安装 Kolla

有两种方式

  • 使用 pip 安装
  • 从源码安装

推荐采用后者有助于学习也方便改代码

使用 git 下载源码:

# OpenStack 官方 git 源
git clone https://opendev.org/openstack/kolla

# 上面网速慢的可以使用下面的镜像站地址
git clone http://git.trystack.cn/openstack/kolla

然后使用 pip 安装即可:

(kolla-build) $ pip install kolla/

注意最后的斜杠表示我们安装的是本地目录安装完毕后可以执行:

(kolla-build) [root@davycloud ~]# kolla-build --version
9.1.0

生成配置文件

Kolla 构建镜像有不少配置项但是基本保持默认即可并且缺少配置文件 kolla-build 命令也能执行所以这一步这里就 略过 了

如果你想生成 kolla-build.conf 配置文件可以参考 官方文档 

构建 base 镜像

构建最最基础的 base 镜像:

(kolla-build) [root@davycloud ~]# kolla-build ^base
INFO:kolla.common.utils:Found the docker image folder at /root/.virtualenvs/kolla-build/share/kollahttps://cdn9.52xs.com.cn/docker
INFO:kolla.common.utils:Added image base to queue
INFO:kolla.common.utils:Attempt number: 1 to run task: BuildTask(base)
INFO:kolla.common.utils.base:Building started at 2020-01-28 19:54:50.158139
INFO:kolla.common.utils.base:Step 1/37 : FROM centos:7
INFO:kolla.common.utils.base: ---> 5e35e350aded
INFO:kolla.common.utils.base:Step 2/37 : LABEL maintainer="Kolla Project
...
INFO:kolla.common.utils.base:Successfully tagged kolla/centos-binary-base:9.1.0

注意^base 前面的 ^ 符号不可省略这是正则表达式中表示句首的符号如果缺少该符号kolla-build 会把 openstack-basenova-base 等一众名字包含 base 的镜像都匹配上了

构建的镜像标签默认是 kolla 的版本号9.1.0我们后面会指定自己的版本号

修改 base 镜像

我们在前面分析过了所有的安装源都在 base 镜像中指定了

如果我们直接使用这个 base 镜像后面的镜像构建过程中软件的安装速度没法保证

当然我们可以在下载完 kolla 源码之后就直接修改 base 对应的 Dockerfile.j2 和相关的构建文件但是这样修改是比较麻烦的因为其中夹杂着其它情况的处理代码例如:

{% if base_package_type == 'rpm' %}
# For RPM Variants, enable the correct repositories - this should all be done
# in the base image so repos are consistent throughout the system.  This also
# enables to provide repo overrides at a later date in a simple fashion if we
# desire such functionality.  I think we will :)

RUN CURRENT_DISTRO_RELEASE=$(awk '{match($0, /[0-9]+/,version)}END{print version[0]}' /etc/system-release); \
    if [  $CURRENT_DISTRO_RELEASE != "{{ supported_distro_release }}" ]; then \
        echo "Only release '{{ supported_distro_release }}' is supported on {{ base_distro }}"; false; \
    fi \
    && cat /tmp/kolla_bashrc >> /etc/bashrc \
    && sed -i 's|^\(override_install_langs=.*\)|# \1|' {% if distro_package_manager == 'dnf' %}/etchttps://cdn9.52xs.com.cn/dnfhttps://cdn9.52xs.com.cn/dnf.conf{% else %}/etc/yum.conf{% endif %}

{% block base_yum_conf %}

{% if distro_package_manager == 'dnf' %}
COPY dnf.conf /etchttps://cdn9.52xs.com.cn/dnfhttps://cdn9.52xs.com.cn/dnf.conf
{% else %}
COPY yum.conf /etc/yum.conf
{% endif %}

修改难度是比较大的要把其中的逻辑捋清楚才能下手而且以后每次这个文件的版本有变化更新都要对照着修改

这里我采取了比较投机取巧的办法等这个 base 镜像构建完成后直接在它之上修改这个时候我们已经确定了操作系统(CentOS)和安装方式(Binary)这样只需要替换 /etc/yum.repos.d/ 下面的 .repo 文件即可

先把 kolla/centos-binary-base:9.1.0 镜像内的 /etc/yum.repos.d/ 整个文件夹都拷贝出来逐个 .repo 修改把其中的 URL 替换成阿里云镜像站的 URL

然后写了一个超级简单粗暴的 Dockerfile:

FROM kolla/centos-binary-base:9.1.0

RUN mkdir -p /etc/yum.repos.d/bak && mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak

COPY CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo
COPY CentOS-Ceph-Nautilus.repo /etc/yum.repos.d/CentOS-Ceph-Nautilus.repo
COPY CentOS-CR.repo /etc/yum.repos.d/CentOS-CR.repo
COPY CentOS-Debuginfo.repo /etc/yum.repos.d/CentOS-Debuginfo.repo
COPY CentOS-fasttrack.repo /etc/yum.repos.d/CentOS-fasttrack.repo
COPY CentOS-Media.repo /etc/yum.repos.d/CentOS-Media.repo
COPY CentOS-NFS-Ganesha-28.repo /etc/yum.repos.d/CentOS-NFS-Ganesha-28.repo
COPY CentOS-OpenStack.repo /etc/yum.repos.d/CentOS-OpenStack.repo
COPY CentOS-OpsTools.repo /etc/yum.repos.d/CentOS-OpsTools.repo
COPY CentOS-QEMU-EV.repo /etc/yum.repos.d/CentOS-QEMU-EV.repo
COPY CentOS-Sources.repo /etc/yum.repos.d/CentOS-Sources.repo
COPY CentOS-Storage-common.repo /etc/yum.repos.d/CentOS-Storage-common.repo
COPY CentOS-Vault.repo /etc/yum.repos.d/CentOS-Vault.repo
COPY crmsh.repo /etc/yum.repos.d/crmsh.repo
COPY elasticsearch.repo /etc/yum.repos.d/elasticsearch.repo
COPY epel.repo /etc/yum.repos.d/epel.repo
COPY epel-testing.repo /etc/yum.repos.d/epel-testing.repo
COPY grafana.repo /etc/yum.repos.d/grafana.repo
COPY influxdb.repo /etc/yum.repos.d/influxdb.repo
COPY opendaylight.repo /etc/yum.repos.d/opendaylight.repo
COPY rabbitmq_rabbitmq-server.repo /etc/yum.repos.d/rabbitmq_rabbitmq-server.repo
COPY td.repo /etc/yum.repos.d/td.repo

然后用它来构建一个新的镜像:

(kolla-build) [root@davycloud ~]# docker build . -t kolla/centos-binary-base:davycloud

注意其中的镜像 tag 可以自己随便定义

构建 openstack-base 镜像

有了基础镜像就可以开始构建其它的镜像了可以先挑一个试一试比如 openstack-base

注意上面已经把 tag 修改了所以接下来的命令必须要带两个选项:

  • --tag davycloud用来指定自定义的 tag
  • --skip-existing略过已经创建好的镜像
(kolla-build) [root@davycloud aliyun]# kolla-build --tag davycloud --skip-existing  openstack-base

INFO:kolla.common.utils:Found the docker image folder at /root/.virtualenvs/kolla-build/share/kollahttps://cdn9.52xs.com.cn/docker
INFO:kolla.common.utils:===========================
INFO:kolla.common.utils:Images that failed to build
INFO:kolla.common.utils:===========================
ERROR:kolla.common.utils:openstack-base Failed with status: matched

会出现这么一个莫名其妙的错误这其实是 kolla 这里处理的逻辑有点问题找到下面所示代码在 image.status = STATUS_UNMATCHED 上面加一个判断:

@@ -1117,9 +1117,9 @@ class KollaWorker(object):
                                 ancestor_image.status = STATUS_MATCHED
                         LOG.debug('Image %s matched regex', image.name)
                 else:
+                    # See: https://bugs.launchpad.net/kolla/+bug/1810979
+                    if image.status != STATUS_SKIPPED:
+                        image.status = STATUS_UNMATCHED
-                    # we do not care if it is skipped or not as we did not
-                    # request it
-                    image.status = STATUS_UNMATCHED
         else:
             for image in self.images:
                 if image.status != STATUS_UNBUILDABLE:

我已经给社区提了修改补丁但是没有下文

修改完毕之后就可以重试上面的命令来构建镜像了

构建其它镜像

Kolla 总共支持的镜像比较多不太可能全部需要所以最好事先挑选一番

最简单的是通过 profile 来批量指定然后通过 --list-images 选项在构建之前查看镜像列表做到心中有数:

(kolla-build) [root@davycloud aliyun]# kolla-build -p default --list-images

1 : openstack-base
2 : chrony
3 : barbican-keystone-listener
4 : barbican-base
5 : nova-spicehtml5proxy
6 : nova-conductor
7 : nova-ssh
8 : nova-libvirt
9 : nova-scheduler
10 : nova-compute-ironic
11 : nova-novncproxy
12 : nova-serialproxy
13 : nova-api
14 : nova-compute
15 : nova-base
16 : glance-api
17 : glance-registry
18 : glance-base
19 : kolla-toolbox
20 : neutron-server-opendaylight
21 : neutron-l3-agent
22 : neutron-mlnx-agent
23 : neutron-server
24 : neutron-server-ovn
25 : neutron-metadata-agent
26 : neutron-dhcp-agent
27 : neutron-openvswitch-agent
28 : neutron-bgp-dragent
29 : neutron-linuxbridge-agent
30 : neutron-infoblox-ipam-agent
31 : neutron-base
32 : neutron-metering-agent
33 : neutron-sriov-agent
34 : neutron-metadata-agent-ovn
35 : fluentd
36 : heat-api-cfn
37 : heat-engine
38 : heat-base
39 : heat-api
40 : heat-all
41 : ironic-neutron-agent
42 : mariadb
43 : keystone-ssh
44 : keystone
45 : keystone-fernet
46 : keystone-base
47 : openvswitch-db-server
48 : openvswitch-base
49 : openvswitch-vswitchd
50 : prometheus-haproxy-exporter
51 : prometheus-base
52 : prometheus-memcached-exporter
53 : base
54 : rabbitmq
55 : cron
56 : haproxy
57 : keepalived
58 : memcached
59 : horizon
60 : placement-base
61 : placement-api

也可以查看源码文件:kolla/common/config.py 中的 _PROFILE_OPTS 查看支持哪些 profile 以及包含的镜像列表

(kolla-build) [root@davycloud ~]# kolla-build --tag davycloud --skip-existing -p default

把镜像推送到 registry

可以是本地自建的服务也可以是其它平台提供的比如 阿里云的容器镜像服务

具体的过程就不赘述了

一切完工之后就可以参考我之前的文章在使用 Kolla-Ansible 部署环境的时候在 globals.yml 中修改 registry 相关配置使用自己的镜像源了


如果本文对你有帮助请 点赞、 关注、分享谢谢!


相关文章

猜您喜欢

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式