千里之行始于足下

Ceph Container 使用实践

Posted on By Peter Yang

Intro

本文介绍如何使用ceph-ansible部署ceph docker。分三个部分。一是制作ceph docker镜像,二是部署ceph docker镜像,三是ceph-ansible部署docker的主要流程分析。

本文分析的源码版本

  • ceph-container: v3.2.10
  • ceph-ansible: v3.2.29
  • ceph: v12.2.10

制作ceph镜像

如果你没有对ceph进行二次开发,那么可以使用官方编译好的镜像,参考:

如果对ceph有二次开发,并且生成和发布了自己的package,那么就需要编译自己的镜像。

ceph-container

ceph-container 这个项目用于创建ceph docker镜像。

CONTRIBUTING 这篇解释了项目代码的主要结构,如何创建和编译定制的镜像,以及如何debug。

编译命令很简单。

# 命令

make FLAVORS=<CEPH_VERSION>[CEPH_POINT_RELEASE],<DISTRO>,<DISTRO_VERSION> [stage|build] [daemon|daemon-base]

# 含义

FLAVORS - 定义要编译的目标,分为几个部分,用于映射到不同的路径

stage|build: 编译目标
* stage - 只生成待编译文件,放到目录`staging/`下
* build - 先生成待编译文件,再执行`docker build`,产生镜像

daemon|daemon-base: 编译镜像
* daemon-base - 基础镜像,包含指定版本的所有包
* daemon - 可运行的ceph镜像,基于`daemon-base`构建

stage生成的内容遵循一定的规则进行覆盖,利用这个规则来达到定制的目标。以下是覆盖规则。

# Most specific
ceph-releases/<ceph release>/<base os repository>/<base os release>/{daemon-base,daemon}/FILE
ceph-releases/<ceph release>/<base os repository>/<base os release>/FILE
ceph-releases/<ceph release>/<base os repository>/{daemon-base,daemon}/FILE
ceph-releases/<ceph release>/<base os repository>/FILE
ceph-releases/<ceph release>/{daemon-base,daemon}/FILE
ceph-releases/<ceph release>/FILE
ceph-releases/ALL/<base os repository>/<base os release>/{daemon-base,daemon}/FILE
ceph-releases/ALL/<base os repository>/<base os release>/FILE
ceph-releases/ALL/<base os repository>/{daemon-base,daemon}/FILE
ceph-releases/ALL/<base os repository>/FILE
ceph-releases/ALL/{daemon-base,daemon}/FILE
ceph-releases/ALL/FILE
src/{daemon-base,daemon}/FILE
src/FILE
# Least specific

项目使用如上的约定形式来组织override的关系。从上往下看,越向下越通用。<ceph release>等变量的获取是通过FLAVORS得到的。

示例

我的定制镜像的代码路径如下

ceph-releases/luminous/centos/{daemon-base,daemon}

编译命令如下

make FLAVORS=luminous-12.2.10-dev1,centos,7 BASEOS_REGISTRY=docker-registry.peteryj.io/ceph BASEOS_REPO=centos BASEOS_TAG=7.6-dev-1 RELEASE=dev1 build

执行结果如下


  CEPH_VERSION      : luminous
  CEPH_POINT_RELEASE: -12.2.10-dev1
  DISTRO            : centos
  DISTRO_VERSION    : 7
  HOST_ARCH         : x86_64
  BASEOS_REGISTRY   : docker-registry.peteryj.io/ceph
  BASEOS_REPO       : centos
  BASEOS_TAG        : 7.6-dev-1
  IMAGES_TO_BUILD   : daemon-base daemon
  STAGING_DIR       : staging/luminous-12.2.10-dev1-centos-7-x86_64
  RELEASE           : dev1
  DAEMON_BASE_IMAGE : ceph/daemon-base:dev1-luminous-centos-7.6-dev-1-x86_64
  DAEMON_IMAGE      : ceph/daemon:dev1-luminous-centos-7.6-dev-1-x86_64

Computed:
  BASE_IMAGE        : docker-registry.peteryj.io/ceph/centos:7.6-dev-1

从上面可以很清楚看明白,FLAVORS是怎么映射到变量上面,并怎么作用到最终镜像上的。这里不赘述。

编译完成后,执行 docker images,就可以看到daemondaemon-base两个镜像

用 ceph-ansible 部署 ceph docker image

执行命令其实很简单,使用官方自带的site-docker.yml.sample即可,只需要在inventory中指定docker image地址和版本即可。

inventory文件片断示例

[all]
ceph_docker_registry=docker.io
ceph_docker_image=ceph/daemon
ceph_docker_image_tag=latest-luminous

部署命令示例

ansible-playbook -i <inventory> site-docker.yml --extra-vars "ceph_docker_image_tag=12.2.10-dev1.1"

下面分析下ceph-ansible安装 ceph docker 的主要过程

以下假定读者已经熟悉 ceph-ansible 安装 bear-metal 版本。

ceph-ansible 安装 ceph docker 过程分析

我们以项目中 site-docker.yml.sample 为例进行分析。通过对比,发现主要差别在于 ceph-docker-common 这个 role 上。其余的 role 都是采用条件语句控制部分需要 ceph docker 特殊处理的逻辑。

我们主要分析以下几个role:

  • ceph-docker-common
  • ceph-handler
  • ceph-config

对于具体服务类,分析以下几个role:

  • ceph-mon
  • ceph-osd
  • ceph-rgw
  • ceph-mds
  • ceph-nfs

role: ceph-docker-common

基本上分为以下几步

  • 准备 docker 运行环境
  • 获取 ceph docker 镜像
  • 配置文件目录等访问权限

准备 docker 运行环境

主要完成以下工作

  • 检查systemd是否正常工作
  • 检查核心配置是否存在,包括 moniter/rgw 监控地址和端口
  • 预安装
    • 去除不必要的udev文件
    • 安装docker和ntp
    • 启动dockerd
  • 检查配置环境以及是否有ceph集群正在运行,如果发现有残留配置或正在运行,则出错退出,要求手动清理
  • 检查时间同步ntp/chrony是否正确运行

获取 ceph docker 镜像

  • 检查旧docker容器以及对应容器版本,并记录
  • docker pull 指定的docker image, 并记录
  • 比较docker pull 前后的镜像SHA1差异,如不同则触发handler重启
  • 获取并记录ceph_version变量和ceph_release,用于后续任务

配置文件目录等访问权限

设定 /etc/ceph, 以及 /var/lib/ceph/bootstrap-* 的目录权限

role:ceph-handler

handler被放在一个集中的role中,主要用于监听ceph运行版本和状态,在版本变更时触发指定的服务。

注意!对于指定的单个服务而言,如osd,是按并发度一起重启的。因此如果需要分批次,需要在运行时特别指定机器

docker版本和非docker版本差异主要在运行命令上,docker版本通过docker exec <container_name> <ceph command>的方式来执行。

下面主要分析下服务启动脚本的模板,主要分析 monosd 这两个服务

restart_mon_daemon.sh.j2

脚本主要流程如下:

  • 测试*.asok文件是否存在,
  • 尝试运行,并检测到ceph -s中显示加入到monitor集群,即在quorum_names分组中。

restart_osd_daemon.sh.j2

脚本主要流程:

  • 重启每个osd进程
  • 检测*.asok文件是否存在,并运行ceph -s,检测pg是否正常启动。

role: ceph-config

脚本主要流程:

  • 使用ceph_volme脚本创建底层块设备的分区、格式化等工作,传入CEPH_CONTAINER_IMAGE以标识docker版本
  • 生成集群uuid
  • 根据模板 ceph.conf.j2 生成配置文件

ceph_volume通过docker run运行。配置特权权限,并映射进磁盘路径和asok文件。从结果上看,相当于只使用容器的命名空间功能,实际效果和直接运行cpeh_volume没有什么区别。

role: ceph-mon

主要流程

  • 处理配置文件
  • 创建ceph-mon@.service, docker版本会基于docker run 运行,然后启动服务
  • 在docker宿主机上配置命令,便于运维操作。如 ceph, radosgw-admin, rados, rbd。启动方式修改为通过docker exec执行。
  • 检测*.asok文件是否存在,以判断是否正常启动
  • 将monitor组中其它节点加入bootstrap分组中,以在启动时直接互连
  • 从monitor节点宿主机上取回配置和初始生成的keyring文件,存到fetch目录中,以备后续部署使用。
  • 创建restapimgr服务用到的keyring文件并保存到fetch
  • 配置crush rules并更新到 /etc/ceph/ceph.conf

role: ceph-mgr

主要流程

  • copy keyring 和目录到osd机器上,并配置相关权限
  • 生成service文件, 启动mgr
  • 检测ceph mgr dump中的available,判断启动成功
  • 根据配置ceph_mgr_modules,启动相关模块

role: ceph-osd

主要流程

  • ceph系统配置优化
  • copy keyring 和目录到osd机器上
  • 生成ceph-disk相关参数,准备初始化块设备。docker版通过-e传入docker内部执行。
  • 通过docker run运行特权容器,按不同osd场景,non-collocated, lvm等,分别初始化块设备
  • 启动osd
    • 通过模板生成启动脚本ceph-osd-run.sh,以及服务文件ceph-osd.service
    • 如果有对service文件修改,则复制修改进去。这里由于docker版的service均是ceph-ansible生成,因此不需要。
    • 通过ceph-handler重启 ceph-osd@.service 服务。

role: ceph-rgw

主要流程

  • copy keyring 和目录到机器上
  • 启动rgw
    • 通过ceph-radosgw.service.j2生成service文件
    • 启动ceph-radosgw服务
  • 根据参数,配置master|slave集群
  • 根据参数,创建rados pool等

role: ceph-mds

主要流程

  • 创建cephfs_pools指定的2个rados pool, 默认是cephfs_metadatacephfs_data
  • 创建cephfs指定的文件系统,并使用上面创建好的2个pool,启用multimds
  • copy keyring 和目录到机器上
  • 启动mds
    • 生成service文件
    • 启动mds
    • 检测*.asok文件,检测到测启动完成

role: ceph-nfs

主要流程

  • copy keyring 和目录到机器上,并配置权限
  • 关闭正在运行的nfs server
  • 安装包,有nfs-ganesha-cephnfs-ganesha-rgw两个包,对应着底层存储使用文件系统和对象存储两种方案。方案优劣不在本文范围内。
  • 拷贝或生成配置文件,keyring及设置访问权限
  • 根据ganesha.conf.j2生成配置文件,并启动nfs

参考资料