本文以nova-api容器为例,说明kolla如何将nova-api配置文件传入容器,容器如何启动nova-api服务并读取配置文件node
注:第一部分比较无趣,二三部分 会有意思一些python
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/"
- 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: 略
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
# 定义父镜像为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文件。git
"/usr/local/bin/" 是环境变量PATH的默认值之一,将extend_start.sht文件拷贝到这个目录后,kolla_nova_extend_start成为容器里能够直接执行的一个命令。docker
Dockerfile中,对容器启动时执行的命令是这个定义的CMD ["可执行命令"], 在这个dockerfile中没有定义容器启动命令CMD。shell
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。json
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成为可在容器里直接执行的命令api
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命令,之因此说几乎,是由于有个别镜像重写了CMDbash
kolla_start是一个shell脚本,内容以下:curl
#!/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服务都按照上面的流程启动,不一样的服务:函数