AlibabaクラウドにJenkins Slave Poolを実装してCI/CDパイプラインのプロビジョニングを可能にする方法

この記事では、動的で並列なCI/CDパイプラインのプロビジョニングを可能にする**Alibaba Cloud**上に分散型で**Docker**化された**Jenkins** Slave Poolを実装する方法を共有しています。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/hybrid-cicd---hosting-dockerized-jenkins-slaves-on-alibaba-cloud_594978)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#ハイブリッドCI/CDとは
ハイブリッドCI/CDは、オンプレミスとパブリッククラウドを組み合わせた分散型のプラットフォームで、CI/CDを目的としています。ハイブリッドCI/CDは、基本的にプライベートクラウドとパブリッククラウドの間でワークロードを制御し、ニーズとコストのバランスを取ります。

高レベルでは、以下の図のようなアーキテクチャになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/5541c0a7-58d3-bd70-a024-6006deecfaf3.png)


#ハイブリッドCI/CDのメリット
###スケーラビリティと柔軟性
オンプレミスでも一定レベルのスケーラビリティは提供されていますが、これはデータセンターごとのものであり、予算に大きく依存します。また、あるシステムが予想以上にリソースを消費すると、他のすべてのシステムに影響が出ることがよくあります。そのため、予算の境界線をどのように設定するかが厄介な問題となります。パブリッククラウドサービスでは、より大きなクラウドインフラでより大きなスケーラビリティを提供することができます。CI/CDのジョブは通常、分離された短命のものであり、一般的にステートレスであることを考慮すると、パブリッククラウドサービスの方が拡張性が高く、CI/CDジョブをパブリック・クラウドに移行することで、組織はコア・サービスのためにスケーラビリティを確保することができます。

###費用対効果
パブリッククラウドの方が、集中管理のコストをすべてのユーザーが共有するため、経済的な費用対効果が高くなる可能性が高くなります。

###セキュリティ
純粋なパブリッククラウドソリューションと比較して、Hybrid CI/CDは、適用可能なCI/CDジョブにのみアクセスできるようにデータを常に制限することができるため、セキュリティ要求に対する感受性を確保しています。

#Dockerがビルドスレーブとしてホストする理由
###リソースの利用
Dockerがリソースを動的に割り当ててくれるので、複数のJenkins Slavesを並行して走らせることができます。これにより、CI/CDパイプラインのスループットが飛躍的に向上します。

###アイソレーション
Dockerは、アプリケーションとリソースが分離・分離されていることを保証します。Jenkins Slaveが本当に徹底的にクリーンアップするかどうかを気にすることなく、ターゲットコンテナを破棄するだけでよいのです。

###環境の標準化
標準イメージを継承したCI/CD環境を簡単に構築できます。

#Jenkinsスレーブコンテナの実装

Jenkins MasterからJenkins Slavesへの通信プロトコルは2種類あります。Java Web Start(別名JNLP)とSSHです。SSH は Blocking I/O で暗号化されているため、スケーラビリティが制限されますが、ロードバランサへの依存度が低いため、最も一般的な方法です。そこで今回はsshスレーブの種類についてのみ解説します。

Jenkikikns Slave の docker イメージはプロジェクトによって環境が異なる場合があるので、具体的にビルドすることをお勧めします。[https://github.com/jenkinsci/docker-ssh-slave](https://github.com/jenkinsci/docker-ssh-agent?spm=a2c65.11461447.0.0.97435b28FD2F2J) に素晴らしい例が掲載されていますので、参考にしてみてください。

```
Dockerfile
```

```
    FROM openjdk:8-jdk
    LABEL MAINTAINER="Nicolas De Loof <nicolas.deloof@gmail.com>"

    ARG user=jenkins
    ARG group=jenkins
    ARG uid=1000
    ARG gid=1000
    ARG JENKINS_AGENT_HOME=/home/${user}

    ENV JENKINS_AGENT_HOME ${JENKINS_AGENT_HOME}

    RUN groupadd -g ${gid} ${group} \
        && useradd -d "${JENKINS_AGENT_HOME}" -u "${uid}" -g "${gid}" -m -s /bin/bash "${user}"

    # setup SSH server
    RUN apt-get update \
        && apt-get install --no-install-recommends -y openssh-server \
        && rm -rf /var/lib/apt/lists/*
    RUN sed -i /etc/ssh/sshd_config \
            -e 's/#PermitRootLogin.*/PermitRootLogin no/' \
            -e 's/#RSAAuthentication.*/RSAAuthentication yes/'  \
            -e 's/#PasswordAuthentication.*/PasswordAuthentication no/' \
            -e 's/#SyslogFacility.*/SyslogFacility AUTH/' \
            -e 's/#LogLevel.*/LogLevel INFO/' && \
        mkdir /var/run/sshd

    VOLUME "${JENKINS_AGENT_HOME}" "/tmp" "/run" "/var/run"
    WORKDIR "${JENKINS_AGENT_HOME}"

    COPY entrypoint.sh /usr/local/bin/entrypoint.sh

    EXPOSE 22

    ENTRYPOINT ["entrypoint.sh"]
```

Jenkins `Slave entrypoint.sh`

```
    #!/bin/bash -ex

    write_key() {
        mkdir -p "${JENKINS_AGENT_HOME}/.ssh"
        echo "$1" > "${JENKINS_AGENT_HOME}/.ssh/authorized_keys"
        chown -Rf jenkins:jenkins "${JENKINS_AGENT_HOME}/.ssh"
        chmod 0700 -R "${JENKINS_AGENT_HOME}/.ssh"
    }

    if [[ $JENKINS_SLAVE_SSH_PUBKEY == ssh-* ]]; then
    write_key "${JENKINS_SLAVE_SSH_PUBKEY}"
    fi
    if [[ $# -gt 0 ]]; then
    if [[ $1 == ssh-* ]]; then
        write_key "$1"
        shift 1
    else
        exec "$@"
    fi
    fi

    # ensure variables passed to docker container are also exposed to ssh sessions
    env | grep _ >> /etc/environment

    ssh-keygen -A
    exec /usr/sbin/sshd -D -e "${@}"
```

#Jenkinsマスタ設定
すでにJenkins Masterを設定したことがある方を想定しています。Alibaba Cloud上で新規に構築する場合は、以下の三部作の記事も参考にしてください。

- [Jenkinsを使ったCI/CD - Part 1: UbuntuにJenkinsをインストールする](https://www.alibabacloud.com/blog/ci%2Fcd-with-jenkins---part-1%3A-install-jenkins-on-ubuntu_593717?spm=a2c65.11461447.0.0.97435b28FD2F2J)
- [Jenkinsを使ったCI/CD - Part 2：継続的インテグレーションにJenkinsを使う](https://www.alibabacloud.com/blog/ci%2Fcd-with-jenkins---part-2%3A-use-jenkins-for-continuous-integration_593720?spm=a2c65.11461447.0.0.97435b28FD2F2J)
- [Jenkinsを使ったCI/CD - Part 3：継続的なデリバリにJenkinsを使う](https://www.alibabacloud.com/blog/ci%2Fcd-with-jenkins---part-3%3A-use-jenkins-for-continuous-delivery_593724?spm=a2c65.11461447.0.0.97435b28FD2F2J)

その後、Jenkins Dashboard / Manage Jenkins / Manage Pluginsに移動し、"Docker Plugin "を検索してインストールします。

次に、Jenkins Dashboard / Manage Jenkins / Configure systemに移動し、dockerの下のDocker URLにECSのパブリックIPアドレスとdockerリモートAPIのポートを記入します。デフォルトでは`2375`です。test connection "ボタンがあるので、接続が成功するかどうか試してみることができます。

その後、「Add Docker Template」を選択し、「docker template」をクリックします。そして、以下のように詳細を記入します。

- Dockerイメージ: jenkinsci/ssh-slave
- リモートファイリングシステムのルート:/home/jenkins
- ラベル: ssh-slave
- 証明書: the public key you have injected for ssh-slave container


すべての設定が完了したら、「保存」ボタンをクリックします。

#テスト構成
「New item」に移動し、「ssh-slave-test」という名前の`フリースタイル`プロジェクトを作成します。

「Restrict」の下に、スレーブテンプレートで与えたラベル名を入力します。ここでは「ssh-slave」とします。

Build で execute shell オプションを選択し、以下のように echo 文を入力します。

```
    echo "hello {JOB_NAME}"
```

このジョブを保存して「今すぐビルド」をクリックすると、以下のような出力が得られるはずです。

```
    hello ssh-slave-test
```

#次やることは？
上記のすべてが終わったら、コードリポジトリと統合して、実世界のCI/CDジョブを作成します。また、実際の要件に応じてdockerイメージをカスタマイズすることもできます。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*