# 在 K8S 集群中分布构建 Docker 镜像

## 镜像更新

最近给我的 [Jenkins 镜像](https://github.com/fleeto/docker-jenkins) 做了一些更新：

- 加入了基于 RunC 的镜像操作工具：[IMG](https://github.com/genuinetools/img)。在特权模式下，可以方便的使用命令行创建和操作 Docker 镜像。
- 更新 Jenkins 以及 Remoting 版本。
- 修复一些初始化问题。

下面根据这一版本的镜像简单说说分布式构建过程中的一些要点。

## Jenkins 镜像的一些值得注意的东西

- Jenkins 在启动 Slave 节点时，会设置下面三个环境变量，所以在 `run.sh` 就可以引用这几个环境变量启动 Worker 节点：
  - JENKINS_URL：MASTER 服务的地址。
  - JENKINS_NAME：为 Worker 节点分配的名称
  - JENKINS_SECRET：Worker 节点和 Master 节点通信时所使用的认证密钥。

  ~~~sh
    java \
    -cp /usr/share/jenkins/slave.jar hudson.remoting.jnlp.Main \
    -headless -url $JENKINS_URL $JENKINS_SECRET $JENKINS_NAME
  ~~~

- `img` 工具依赖于 [runc](https://github.com/opencontainers/runc/)，因此也需要把 runc 加入到镜像之中。
- `config.xml` 中：
  - 直接设置了 8081 作为 jnlp 端口，因此在 Dockerfile 中也进行了 EXPOSE 声明。
  - 开启 CSRF 选项，并设置代理服务器兼容，防止在 Kube-Proxy 的情况下无法提供服务。

## Jenkins 在 Kubernetes 中的启动：

- RBAC：因为要启动 Worker 节点，因此在开启了 RBAC 的集群上，要给 Jenkins 的 Service Account 进行授权，允许进行 Pod 的操作。
- Service：需要暴露 jnlp 端口到集群内部，无需为其提供 loadbalancer 以及 nodePort 等形式的外网接入能力。
- 可以根据需要提供加载卷，用于保存配置等。

## 分布式构建的配置

- 首先需要安装 Kubernetes 插件。
- 插件安装后，就可以在 Jenkins 的 credentials 中加入 `Kubernetes ServiceAccount` 类型的凭据，用于连接和操作 Kubernetes 集群。
- 容器模板设置中，系统缺省会提供一个名为 jnlp 的容器模板，要想使用自己的镜像，需要进行同名覆盖。
  - 容器模板中可以按需设置加载卷等，例如要进行镜像的 PUSH 操作，就需要将 CA 证书通过一定方法加入到容器的信任列表之中。
  - 如果要进行 IMG 的操作，需要选中容器的 `Run in privileged mode` 选项，开启特权模式。

## 任务的设置

- 要进行镜像的构建，就非常的容易，加入几行简单的 Shell 命令，例如：

  ~~~bash
    mkdir tmp
    # 生成一个 Dokerfile
    echo "FROM registry.docker-cn.com/library/alpine" > tmp/Dockerfile
    # 构建镜像
    img build -t 10.211.55.19:5000/alpine:163 tmp
    # 更新证书信任列表
    update-ca-certificates
    # 把镜像推送到私库
    img push 10.211.55.19:5000/alpine:163
  ~~~
