使用私有镜像创建开发机

除了可以使用英博云的预置镜像创建开发机,您还可以使用私有镜像创建开发机。

私有镜像定义解释

在本文的语境中,私有镜像是与预置镜像相对的概念,具体解释如下:

  • 私有镜像具体包括:自定义镜像外部镜像两类。
  • 自定义镜像是指已经在英博云平台中,租户专属Repository中的镜像,参考这里
  • 外部镜像则泛指不在英博云平台中的,外部container registry中的镜像。

对于私有镜像的要求

为了支持开发机正常启动,私有镜像需要预装如下软件包(或者通过下面介绍的command参数的initialize_install子阶段进行安装):

  • 为了支持SSH远程连接,私有镜像依赖镜像预置安装:openssh-server。这是必须的,否则ContainerServer无法启动。
  • VSCode远程连接需镜像预置安装openssh-sftp-servercurl。若是开发机不需要使用VSCode,可以不安装。
  • JupyterLab服务需镜像预置安装jupyter。若是开发机不需要使用JupyterLab,可以不安装。

基于私有镜像创建开发机

通过英博云控制台创建

你可以通过入口,英博云控制台:资源管理 -> 开发机 -> 创建开发机,然后选择:自定义镜像或者外部镜像创建开发机,示例如下:

私有镜像创建cs

通过kubectl命令创建

您也可以通过kubectl基于私有镜像创建开发机,需要指定镜像地址为您的自定义镜像或者外部镜像,示例如下:

spec:
  image: custom.registry/repository:mytag # 您的自定义镜像
  

创建开发机的完整的yaml示例,可以参考这里

关于command参数

command参数,指定了pod启动的具体命令,分为:initialize阶段launch阶段

其中initialize阶段又进一步分为initialize_install子阶段initialize_config子阶段

为了阐述各阶段的具体功能及逻辑关系,给出一段伪代码参考,示例如下:

## 1. initialize阶段
if not initialized:
    # 若是未初始化,则执行2个子阶段的初始化操作

    ## 1.1 initialize_install子阶段,安装必要的软件包
    install_necessary_pkgs

    ## 1.2 initialize_config子阶段,执行初始化配置
    init_root_passwd
    init_k8s_env
    init_docker_config_json
fi

## 2. launch阶段
start_jupyterlab # 后台启动jupyterlab,注意不可以占据主进程
start_sshd       # 启动sshd服务,这里需要占据pod主进程

以下是一个详细的示例:

## 1. initialize阶段
if [ -z "${EBCS_SYS_INITIALIZED}" ] || [ "$(echo "${EBCS_SYS_INITIALIZED}" | tr '[:upper:]' '[:lower:]')" = "false" ]; then
    ## 1.1 initializate_install子阶段
    # 允许密码登录
    mkdir -p /etc/ssh
    echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
    
    # 允许root用户登录
    echo "PermitRootLogin yes" >> /etc/ssh/sshd_config

    # 允许sftp访问,用于scp文件
    grep -q "^Subsystem sftp" /etc/ssh/sshd_config && sed -i 's|^Subsystem sftp.*|Subsystem sftp /usr/lib/openssh/sftp-server|' /etc/ssh/sshd_config || echo "Subsystem sftp /usr/lib/openssh/sftp-server" >> /etc/ssh/sshd_config 

    # 安装sshd相关pkg,相关pkg已经存在于/public目录
    dpkg -i /public/shared-resources/openssh-server/ubuntu_22.04_amd64/*.deb

    # 安装docker client,相关pkg已经存在于/public目录
    cp /public/shared-resources/docker-build/docker /usr/bin/docker
    
    ## 1.2 initialize_config子阶段
    # 修改root用户密码
    echo "root:$EBCS_SYS_ROOT_PASSWORD" | chpasswd

    # 初始化k8s环境变量
    if [ -f /proc/1/environ ]; then
        echo 'while IFS= read -r line; do export "$line"; done < <(tr "\\0" "\\n" < /proc/1/environ)' | tee -a /etc/profile
        echo "K8s env >> /etc/profile DONE"
    fi

    # 初始化docker config文件
    if [ -n "$DOCKER_CONFJSON" ]; then
        mkdir -p ~/.docker
        echo "$DOCKER_CONFJSON" > ~/.docker/config.json
        chmod 600 ~/.docker/config.json
        echo 'Docker config initialization complete.'
    fi
fi

## 2. launch阶段
# 后台启动jupyter-lab
if command -v jupyter-lab >/dev/null 2>&1 && [ -n "$EBCS_JUPYTER_PORT" ] && [ -n "$EBCS_JUPYTER_TOKEN" ]; then
    cd /root && jupyter-lab --allow-root --ip=0.0.0.0 --port=$EBCS_JUPYTER_PORT  --NotebookApp.token=$EBCS_JUPYTER_TOKEN --no-browser --NotebookApp.allow_origin='*' --NotebookApp.allow_remote_access=True > /tmp/jupyter.log 2>&1 &
fi

# 启动sshd进程
if service ssh start -D; then
    echo "SSHD exited."
else
    /usr/sbin/sshd -D
    echo "SSHD failed to start."
fi
command参数命令可以引用的环境变量
环境变量名称取值示例说明
EBCS_SYS_INITIALIZEDtrue/falseContainServer是否已经初始化
EBCS_SYS_ROOT_PASSWORDQ24dUl$6x0p7W,g1ContainServer的初始密码
DOCKER_CONFJSON{"auths":{"https://registry-cn-huabei1-internal.ebcloud.com":{"username":"myname","password":"SCU5n6j1dfk","auth":"bGlsYmVkd2luOlNxy87uNmoxM2s="}}}租户专属集群的auth信息