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, 垃圾清理等操做。
相關文章
相關標籤/搜索