本文以nova-api容器为例,说明kolla如何将nova-api配置文件传入容器,容器如何启动nova-api服务并读取配置文件

注:第一部分比较无趣,二三部分 会有意思一些

1. nova-api容器参数

  1. nova-api容器定义

    ansible.roles.nova.defaults.main.yml中定义了nova的所有容器及容器参数,下面的代码nova-api容器的定义, 注意代码中第一条, 对于所有容器kolla都有类似的定义:将/etc/kolla下的配置目录,作为volume挂载到容器内的/var/lib/kolla/config_files目录上,供容器启动时读取
  nova-api:
container_name: "nova_api"
group: "nova-api"
image: "{{ nova_api_image_full }}"
enabled: True
privileged: True
volumes:
# 将用户nova-api服务配置目录/etc/kolla/nova-api传入容器,映射为/var/lib/kolla/config_files/,并设置为只读
- "{{ node_config_directory }}/nova-api/:{{ container_config_directory }}/:ro"
# 容器时钟和虚拟机时钟同步
- "/etc/localtime:/etc/localtime:ro"
# 宿主机内核,mount给容器之后,容器可以启用宿主机未启用的内核模块
- "/lib/modules:/lib/modules:ro"
# openstack日志目录
- "kolla_logs:/var/log/kolla/"
  1. nova-api容器操作定义

    ansible.roles.nova.handlers.main.yml中定义了对nova各个容器的操作及其参数,下面的代码是nova-api服务restart的参数,注意该函数的名称虽然是restart nova-api,但是action是recreate_or_restart_container,如果restart nova-api容器时,该容器不存在,restart函数会创建该容器并启动。

    由于nova的服务都是无状态应用,重启容器和重新创建容器没有区别,所以kolla在handler中仅仅定义了restart or recreate操作,但是对于mariadb容器,handler把创建和重启容器分开来,handler包括中定义了start_container,recreate_or_restart_container两个操作
- name: Restart nova-api container
vars:
service_name: "nova-api"
service: "{{ nova_services[service_name] }}"
config_json: 略
nova_conf: 略
policy_json: 略
nova_api_container: 略
kolla_docker:
action: "recreate_or_restart_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
image: "{{ service.image }}"
privileged: "{{ service.privileged | default(False) }}"
volumes: "{{ service.volumes|reject('equalto', '')|list }}"
when:

  1. nova-api容器创建

    ansible.library.kolla_docker.py中定义了所有容器创建的函数 create_container
    def create_container(self):
self.changed = True
# 获取创建容器的volume配置等容器创建参数
options = self.build_container_options()
# 调用docker driver创建容器
self.dc.create_container(**options) def build_container_options(self):
#生成volume参数
volumes, binds = self.generate_volumes()
return {
'detach': self.params.get('detach'),
'environment': self._format_env_vars(),
'host_config': self.build_host_config(binds),
'labels': self.params.get('labels'),
'image': self.params.get('image'),
'name': self.params.get('name'),
'volumes': volumes,
'tty': True
} def generate_volumes(self):
# self.params在初始化时使用1中的kolla_docker参数定义
volumes = self.params.get('volumes')
# 解析字符串,略
for vol in volumes:
#解析字符串,略
return vol_list, vol_dict

2. 寻找nova-api容器的启动命令

  1. nova-api

    通过上面的步骤,kolla将nova-api容器创建出来并启动,并且将宿主机上的/etc/kolla/nova-api作为volume挂载到容器的/var/lib/kolla/config_files上。容器启动时,会执行容器docker file中的CMD命令。而nova-api的dockerfile位于kolla项目(不是kolla-ansible)的docker.nova.nova-api.Dockerfile.j2,内容如下:
    # 定义父镜像为nova-base镜像
FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
# 作者信息,略 # 安装nova-api服务的步骤,略 COPY extend_start.sh /usr/local/bin/kolla_nova_extend_start
RUN chmod 755 /usr/local/bin/kolla_nova_extend_start
USER nova

这个dockerfile定义了一个基于nova-base的nova-api镜像,在nova-base镜像的基础上,主要做了两件事:安装nova-api服务,复制extend_start.sh文件为kolla_nova_extend_start文件。

"/usr/local/bin/" 是环境变量PATH的默认值之一,将extend_start.sht文件拷贝到这个目录后,kolla_nova_extend_start成为容器里可以直接执行的一个命令。

Dockerfile中,对容器启动时执行的命令是这个定义的CMD ["可执行命令"], 在这个dockerfile中没有定义容器启动命令CMD。

  1. nova-base image

    我们再去看一下父镜像nova-base的Dockerfile:
    FROM {{ namespace }}/{{ image_prefix }}openstack-base:{{ tag }}
LABEL maintainer="{{ maintainer }}" name="{{ image_name }}" build-date="{{ build_date }}" # 安装所有nova服务通用的rpm包,如:python-keystoneclient,nova-common,etc,代码略 # 创建/etc/nova目录并设置权限
COPY nova_sudoers /etc/sudoers.d/kolla_nova_sudoers
RUN chmod 750 /etc/sudoers.d \
&& chmod 440 /etc/sudoers.d/kolla_nova_sudoers COPY extend_start.sh /usr/local/bin/kolla_extend_start RUN touch /usr/local/bin/kolla_nova_extend_start \
&& chmod 755 /usr/local/bin/kolla_extend_start /usr/local/bin/kolla_nova_extend_start

在这个文件里面,kolla复制extend_start.sh生成kolla_extend_start文件。这里依然没有定义CMD。

  1. openstack-base

    我们继续看这个镜像的父镜像openstack-base的Dockerfile:
    FROM {{ namespace }}/{{ image_prefix }}base:{{ tag }}

    # 安装openstack通用rpm包,如git,gcc,eventle,代码略

    ENV PATH /var/lib/kolla/venv/bin:$PATH

    RUN {{ macros.install_pip(openstack_base_pip_packages | customizable("pip_packages")) }}

在这里kolla设置了环境变量PATH=/var/lib/kolla/venv/bin,这个目录下存放了nova-api文件,这样nova-api成为可在容器里直接执行的命令

  1. base image

    继续看父镜像base的Dockerfile:
    FROM {{ base_image }}:{{ base_distro_tag }}

    # 创建用户组

    # 配置yum或者apt的源,pip源

    COPY set_configs.py /usr/local/bin/kolla_set_configs
COPY start.sh /usr/local/bin/kolla_start
COPY sudoers /etc/sudoers
COPY curlrc /root/.curlrc # 安装并设置dumb-init
# 创建 /var/log/kolla 并设置权限
# 创建/usr/local/bin/kolla_extend_start 文件并设置权限 CMD ["kolla_start"]

可以看到这里生成了kolla_start文件,并且将容器启动命令设置为kolla_start,由于base镜像是所有kolla镜像的公共镜像,所以,几乎所有kolla容器启动时,执行的命令,都是kolla_start命令,之所以说几乎,是因为有个别镜像重写了CMD

3. 通过kolla_start启动nova-api

kolla_start是一个shell脚本,内容如下:

#!/bin/bash
set -o errexit # 解析 /var/lib/kolla/config_files/目录下的config.json,将config.json中的command写入/command文件,将config.json中的config_files拷贝到指定目录。 /var/lib/kolla/config_files是由我们在1.1中定义的/etc/kolla/nova-api目录映射而来。
sudo -E kolla_set_configs # 获取config.json中的command内容,对于nova-api,它的值是"nova-api"
CMD=$(cat /run_command)
ARGS="" #执行kolla_extend_start命令,设置nova日志目录的权限,并调用kolla_nova_extend_start命令,进行判断:如果是初始化nova-api服务,执行dbsync,如果不是,什么都不做
. kolla_extend_start #执行nova-api命令,启动该服务
echo "Running command: '${CMD}${ARGS:+ $ARGS}'"
exec ${CMD} ${ARGS}

可以看出,所有的openstack服务都按照上面的流程启动,不同的服务:

  • 所有服务都使用/etc/kolla/服务名/config.json中command,作为服务的启动命令
  • 所有服务都使用/etc/kolla/服务名/config.json中config_files, 作为服务的配置文件
  • 所有服务都有相同的kolla_start脚本。这个脚本在kolla项目中存放的位置是kolla.docker.base.start.sh。这个脚本会先调用kolla_extend_start脚本, 然后执行服务启动命令。
  • 所有同一项目的服务有相同的kolla_extend_start脚本。以nova项目为例,这个脚本在kolla项目中存放的位置是kolla.docker.nova.nova_base.extend_start.sh。所有nova容器都使用这个脚本会创建项目日志目录,设置权限,调用容器内的kolla_nova_extend_start脚本。
  • 所有服务都有不同的kolla_项目名_extend_start脚本,以nova_api项目为例,这个脚本在kolla项目中存放的位置是kolla.docker.nova.nova_api.extend_start.sh。nova-api使用该脚本用来做服务启动前的db_sync, 垃圾清理等操作。

kolla管理openstack容器的更多相关文章

  1. openstack kolla多节点容器化环境安装

    好久没写随笔了,6月份趁着在公司没有太忙的事儿,把公司的服务器进行了虚拟化,采用的openstack当前的容器化方案kolla. 整体安装完的感受时,小白感觉自己是个大牛!哈哈,开玩笑,由于以前是开发 ...

  2. 如何在Ubuntu上创建及管理LXC容器?

    将LXC安装到Ubuntu上 $ sudo apt-get install lxc 安装完毕之后,运行lxc-checkconifg工具,检查当前Linux内核支持LXC的情况.要是一切都已被启用,内 ...

  3. 无需安装 vsftpd , 直接使用 FTP 来管理 docker 容器中的文件

    无图无真相,先放个效果图:     背景 使用 docker 来跑一些服务很方便,但是有的时候想管理容器里面的文件却很麻烦 -- 一般常规做法有3种: 通过数据卷或数据卷容器的方式 启动容器的时候时候 ...

  4. Dcoker镜像管理与容器应用

    Dcoker镜像管理与容器应用 docker基于镜像创建容器 相同版本的镜像只允许存在一个 同一个镜像可以创建多个容器 镜像管理 [root@localhost ~]# docker pull cen ...

  5. Kolla 让 OpenStack 部署更贴心

    目录 目录 Kolla 简介 Kolla & Kolla-ansible 部署 OpenStack 准备操作系统基础环境 准备 Python 基础环境 准备 Docker 基础环境 安装 ko ...

  6. Openstack容器项目之Magnum

    本文以Newton版本为例. 1.Magnum简介 Magnum项目通过Openstack API能够在Openstack中创建基于容器的服务,但它本身并不直接对容器进行操作,而是通过Kubernet ...

  7. 不只是安装,Kolla 让 OpenStack 运维变简单

    使用 kolla 部署的 OpenStack 环境和传统直接安装的环境相比较,因为使用了全容器化部署,基本操作上有很大不同.对于初学者,操作变得更清晰和更简单了,但是如果你已经有了一定的经验,可能反而 ...

  8. OpenStack(四)——使用Kolla部署OpenStack多节点云

    (1).实验环境 主机名 IP地址 角色 内存 网卡 CPU 磁盘 OpenStack-con 192.168.128.110 controller(控制) 8G 桥接网卡ens32和ens33 4核 ...

  9. [docker] 管理docker容器中的数据

    之前我们介绍了Docker的基本概念(前面的没翻译...),了解了如何使用Docker镜像进行工作,并且学习了网 络和容器之间的链接.这一节我们将讨论如何管理容器中及容器之间的数据. 我们将查看下面两 ...

随机推荐

  1. JAVA中JPA的主键自增长注解设置

    JPA的注解来定义实体的时候,使用@Id来注解主键属性即可.如果数据库主键是自增长的,需要在增加一个注解@GeneratedValue,即: @GeneratedValue(strategy=Gene ...

  2. Android开发之蓝牙Socket

    蓝牙Server端就是通过线程来注册一个具有名称和唯一识别的UUID号的BluetoothServerSocket, 然后就一直监听Client端(BluetoothSocket)的请求,并对这些请求 ...

  3. 浅谈TreeMap以及在java中的使用

    treemap结构是红黑树 1.先介绍一下平衡二叉树 其特点是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.也就是说该二叉树的任何一个子节点,其左右子树的高度 ...

  4. Java在已存在的pdf文件中生成文字和图片--基础

    自我总结,有什么不足之处请告知,感激不尽!下一次总结pdf模板映射生成报表(应对多变的pdf报表需求,数据提供和报表生成解耦). 目的:在给定的pdf模板上生成报表,就需要知道最基本的操作:文字添加, ...

  5. 使用locate 的正则查询 查找所有main.c

    locate支持正则查询的功能, 只需输入locate -r 正则表达式     即可. 现在我想查找所有main.c怎么做? 打开终端,输入shell: locate -r main.c$ PS:' ...

  6. JAVA并发编程学习笔记------线程的三种创建方式

    创建线程一般有如下几个方式: 1. 通过继承Thread类来创建一个线程: /** * 步骤1:定义一个继承Thread类的子类 * 步骤2:构造子类的一个对象 * 步骤3:启动线程: * */ pu ...

  7. PowerMockito使用详解

    一.PowerMock概述 现如今比较流行的Mock工具如jMock,EasyMock,Mockito等都有一个共同的缺点:不能mock静态.final.私有方法等.而PowerMock能够完美的弥补 ...

  8. HTTP面试题都在这里

    HTTP常见面试题 Http与Https的区别: Http与Https的区别: HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头 HTTP 是不安全的,而 ...

  9. python基础dict,集合,文件

    字典是一种key:value的数据类型dict1{ 'stud1':'孙礼昭', 'stud2':'slz', 'stud3':'sunlizhao',}dict是无序的,key是唯一的  天生去重增 ...

  10. Xcode iOS布局autolayout和sizeclass的使用

    一.关于自动布局(Autolayout) 在Xcode中,自动布局看似是一个很复杂的系统,在真正使用它之前,我也是这么认为的,不过事实并非如此. 我们知道,一款iOS应用,其主要UI组件是由一个个相对 ...