kolla管理openstack容器

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

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

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文件。git

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

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

  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。json

  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成为可在容器里直接执行的命令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命令,之因此说几乎,是由于有个别镜像重写了CMDbash

3. 经过kolla_start启动nova-api

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服务都按照上面的流程启动,不一样的服务:函数

  • 全部服务都使用/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, 垃圾清理等操做。
相关文章
相关标签/搜索