Dockerで簡単なCICDツールチェーンを構築

[前回の投稿] (http://qiita.com/takahigashi/items/50482d492e9769548caa)で作った環境にDockerコンテナでツールチェーンを作っていく。やってみるとDockerは偉いとつくづく思う。

![image](https://qiita-image-store.s3.amazonaws.com/0/164612/76064c14-9da5-b242-6023-5fa030846913.png)

## GitLab
CentOSでコマンド実行。
` # docker pull gitlab/gitlab-ce:latest`
` #docker run --detach --publish 442:442 --publish 80:80 --name gitlab gitlab/gitlab-ce:latest`
母艦のブラウザでCentOSのポート80にアクセス、rootのパスワードを設定

## Jenkins
kubectlと、(後で使うかどうかも定かではないが)ansibleを仕込んだJenkinsコンテナを立ち上げておくことにした。CentOSで作業。あ、maven… 必要になったら入れよう。
### 作業ディレクトリを作成
`# mkdir <WORK>; cd <WORK>`
~~`# curl https://codeload.github.com/jenkinsci/docker/zip/master > docker-master.zip`
`# unzip docker-master.zip`~~

### Dockerfileを作成
`# vi Dockerfile`
> FROM jenkins
USER root
RUN apt-get update && \
     apt-get install -y ansible && \
     rm -rf /var/lib/apt/lists/*
     curl -Lo /usr/local/bin/kubectl http://storage.googleapis.com/kubernetes-release/release/v1.3.0/bin/linux/amd64/kubectl && \
     chmod +x /usr/local/bin/kubectl
 USER ${user}

### Dockerイメージをビルド
`# docker build -t <JENKINS_IMG> .`

### コンテナ実行
CentOS上のDocker環境をJenkinsからも使用させるために、関連ファイルをマウントしつつコンテナを実行する。
`docker run -d --name Jenkins -p 8080:8080 -p 50000:50000 ¥
	-v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker ¥
	--privileged -u root <JENKINS_IMG>`

### Jenkins有効化
母艦のブラウザでCentOSのポート8080にアクセスすると有効化コードの入力を求められる。
`# docker exec -ti <Container_ID> cat /var/jenkins_home/secrets/initialAdminPassword`
上記コマンドの出力をコピペして有効化。
![image](https://qiita-image-store.s3.amazonaws.com/0/164612/64cab653-237f-2472-33f4-cfb94064d24d.png)

あとはプラグインのインストールとユーザ作成を行う。

### kubectlの設定
CentOSのminikubeをJenkinsのkubectlから操作するために以下の設定ファイルをCentOSから流用する。
> ~/.kube/config
~/.minikube/ca.crt
~/.minikube/apiserver.crt
~/.minikube/apiserver.key

やり方はなんでもよく、configの中身を書き換えてディレクトリ構成も変えてもよい。以下はCentOSからそのままファイルをプッシュする例。
`$ docker exec <ContainerID> mkdir /root/.kube`
`$ docker cp .kube/config <ContainerID>:/root/.kube`
`$ docker exec <ContainerID> mkdir /root/.minikube`
`$ docker cp .minikube/ca.crt <ContainerID>:/root/.minikube`
`$ docker cp .minikube/apiserver.crt <ContainerID>:/root/.minikube`
`$ docker cp .minikube/apiserver.key <ContainerID>:/root/.minikube`

kubectlの動作確認
`$ kubectl version`
`$ kubectl get pod`

## JFrog
CentOSで作業。
`$ docker pull docker.bintray.io/jfrog/artifactory-oss:latest`
JFrogのリポジトリをCentOS上に作っておく。
`$ mkdir <JFrogRepo>`
`$ cd <JFrogRepo>`
`$ mkdir data logs etc`
JFrogコンテナを実行。
`$ docker run -d -p 8081:8081 \
-v <JFrogRepo>/data:/var/opt/jfrog/artifactory/data \
-v <JFrogRepo>/logs:/var/opt/jfrog/artifactory/logs \
-v <JFrogRepo>/etc:/var/opt/jfrog/artifactory/etc \ 
docker.bintray.io/jfrog/artifactory-oss:latest`
母艦のブラウザでCentOSのポート8081にアクセスし、管理者パスワードを設定しておく。

## Docker Registry
DockerRegistryの起動自体は簡単!
### Docker Registry実行
`$ docker run -d -p 5000:5000 --name registry registry:latest`

だが、証明書の設定をまともに対応しようとすると大変なので、Docker Registryに対してinsecure-registryの設定をする。CentOSで作業。
下記のサイトを参考にさせていただいた。
[CentOSリポジトリの docker から Docker社リポジトリの docker-engine に移行する] (http://qiita.com/AirGrowz/items/c7b98450b637176e738c)
https://docs.docker.com/engine/admin/systemd/
### Dockerdが環境設定ファイルを読み込むように指定
`# mkdir /etc/systemd/system/docker.service.d`
`# vi docker.conf`
> [Service]
EnvironmentFile=-/etc/sysconfig/docker
ExecStart=
ExecStart=/usr/bin/dockerd $OPTIONS

### 環境設定ファイル作成
--insecure-registryとしてCentOS_IP:5000を指定する。
`$vi /etc/sysconfig/docker`
> OPTIONS="--insecure-registry CentOS_IP:5000"

### Dockerd再起動
`# systemctl daemon-reload`
`# systemctl restart docker`

minikubeのdockerマシンがRegistryからイメージをプルする時に*minikube:docker pull caused "oversized record received" error*のようなエラーになった。
[「server gave HTTP response to HTTPS client」と言われてDocker Private registoryのpushやpullができなかったときの対処] (http://qiita.com/nkmry/items/e2ce67dd66be1f347b67) を参考にさせていただき対処。

CentOSからminikubeのKVMに入ってinsecure-registryを設定。
`$ minikube ssh`
`$ sudo cat >> /etc/docker/daemon.json`
`{ "insecure-registries":["<CentOS_IP>:5000"] }`
dockerを再起動。
`$ sudo systemctl restart docker`
minikubeのシェルを終了。
`$ exit`

## ルーティングテーブル
これでCIツールの設定は一通り完了。CIツール間の連携のためにはIPアドレスを固定で振っておいた方がよい、が私は~~面倒なので~~コンテナの起動順序をスクリプトで指定して回避することにした。

ただし、このままでは母艦からminikubeのKVMには直接アクセスできない。minikubeで動作するコンテナへのアクセスにはminikubeのKVMへのアクセスが必要なのでこのままでは絵に書いた餅であることに今更気づく。
CentOSにはKVMのためにvirbr0, virbr1の2つのブリッジが設定されている。iptablesを確認すると、virbr0については自己のセグメント内へがフォワードを許可している(ように見える)

> Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
<<中略>>
    8   642 ACCEPT     all  --  *      virbr0  0.0.0.0/0            *virbr0*/24     ctstate RELATED,ESTABLISHED
  740  804K ACCEPT     all  --  virbr0 *       *virbr0*/24     0.0.0.0/0
    0     0 ACCEPT     all  --  virbr0 virbr0  0.0.0.0/0            0.0.0.0/0
37  2916 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
    0     0 REJECT     all  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
<<後略>>

まずは、MacOSでルーティングテーブルを追加
`$ sudo route -n add <virbr0のセグメント>/24 <CentOS_IP>`

これだけでは母艦からbirbr0経由でKVMにアクセスできなかった。
~~CentOSのiptablesになんでもACCEPTルールを追加したら通ったので暫定対処とした。CentOSで作業。~~
~~`$iptables -I FORWARD -o virbr0 -j ACCEPT`~~

>
*2017/03/09 追記:*
`NN ACCEPT all -- * virbr0 0.0.0.0/0 virbr0/24 ctstate RELATED,ESTABLISHED`
上記ルールのctstateにNEWを追加することで対処した。
`$ iptables -R FORWARD NN -o virbr0 -d virbr0/24 -j ACCEPT -m conntrack --ctstate NEW,RELATED,ESTABLISHED`

以上でソースリポ、CIツール、アーティファクトリポ、Dockerプライベートレジストリ、Kubernetes実行環境の構築は完了(のはず)
CentOS VMのスナップショットをとってベースキャンプ確保し、いよいよ次回からDevOps CI/CD連峰の登頂に乗り出すのだ?(および腰)