はじめに
先進サービス開発事業部の山岡です。
今回はEKSで構築したKubernetes上にCI/CDツールをデプロイしてみた結果について書きたいと思います。「Kubernetesで上手く使えそうか?」という観点の簡易的な動作確認を行う内容なので、このまま商用利用することは止めた方が良いと思います。
前提条件
- EKSの基本操作を理解していること
- Concourseの基本操作を理解していること
- AWSのAPIキーが環境変数にセットされていること 参考資料
検証したプロダクト
- Concourse CI
- Pivotal謹製
- GUIが超格好良いCI/CDツール 参考:Cloud Foundryのパイプライン
EKSの構築
今回紹介する手順では先日の記事と同じくTerraformでEKSを構築しましたので、自分で作ってみたい場合はそちらを参考にして下さい。既に構築済みの環境があるのであればそのまま利用できるはずです。
Concourse CI
概要
このプロダクトがどんなものなのかについては先人の優れた記事をいくつかご紹介しますのでそちらをお読み頂ければと思います。
今回の記事を読むにあたって特にポイントとなるのはConcourseが Web
及び Worker
という2つのコンポーネントで構成されているということです。これらは同じバイナリーのサブコマンドを実行することで起動することができ Web
が全体を統制(リクエストの受け付けやWorkerへのタスク振り等)し Worker
が実際のジョブを処理します。
パイプラインベースのCI/CDツール、Concourseとは?
構築
こちらのリポジトリをcloneし kubectl apply -f concourse-manifest/
して下さい。
利便性のため内部認証に使う秘密鍵やDBのパスワードもベタ書きしてありますが、セキュリティ的にはNGな行為なので真面目な用途に使う場合は自分で再生成したものをしかるべき形で安全に利用して下さい。またLBが無いとアクセスが不便なのでNLBをデプロイするようになっています。他の注意点としては、手順を単純化するためWorker及びPostgre SQLをそのままKubernetes上にデプロイしています。つまりこのままPodが落ちるとビルド成果物やパイプライン状態といったデータが飛びますので、実用する場合はPVやRDS等でデータを永続化する必要があります。
※初回作成時はたまにNamespaceが存在しないエラーが発生しますが、もう一度 kubectl apply -f concourse-manifest/
すれば上手くいくはずです。気になる方は全体をapplyする前に kubectl apply -f concourse-manifest/namespace.yaml
でNamespaceを作成しておくのが良いでしょう。
動作確認
デプロイが完了したら、まずは外部からWebコンソールにアクセスできるよう CONCOURSE_EXTERNAL_URL
を追加で設定します。下記のように concourse-lb
というserviceリソースの EXTERNAL-IP
がロードバランサーのFQDNなのでそれを控えて下さい(もし <pending...>
と表示される場合はNLBが作成中なのでしばらく時間をおいてから再度表示して下さい)。
$ kubectl get services -o wide --namespace concourse NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR concourse-lb LoadBalancer 172.20.214.67 a34229d82086711e9b9d902c7515d989-3b65d45e2c63e12b.elb.us-west-2.amazonaws.com 8080:31232/TCP 55m app=concourse-web concourse-postgresql ClusterIP 172.20.81.96 <none> 5432/TCP 55m app=concourse-postgresql concourse-web ClusterIP 172.20.4.202 <none> 8080/TCP,2222/TCP 5m app=concourse-web concourse-worker ClusterIP None <none> <none> 55m app=concourse-worker
次に concourse-web.yaml
を開くと環境変数 CONCOURSE_EXTERNAL_URL
が空になっていますのでURLスキームとポート番号を付け足し http://a34229d82086711e9b9d902c7515d989-3b65d45e2c63e12b.elb.us-west-2.amazonaws.com:8080
のように設定して下さい。その後 kubectl apply -f concourse-manifest/
をすれば設定が適用されPodが再作成されるはずです。
この状態でブラウザにログインし右上の login
ボタンを押し test:test でログインできることを確認して下さい。また下記のようにConcourseのCLIツールである fly
からもログインしワーカー一覧を取得できることを確認して下さい(インストールしていなければConcourseトップページからバイナリーをダウンロードできます)。
$ fly login -t test -c http:/a34229d82086711e9b9d902c7515d989-3b65d45e2c63e12b.elb.us-west-2.amazonaws.com:8080 -u test -p test logging in to team 'main' target saved $ $ $ fly workers -t test name containers platform tags team state version concourse-worker-56d6674b85-gdkms 0 linux none none running 2.1 concourse-worker-56d6674b85-mzvld 0 linux none none running 2.1 concourse-worker-56d6674b85-scrvz 0 linux none none running 2.1
そしてHello Worldを実行後成功すること、ビルドURLでも成功していることを確認して下さい。
$ curl -sO https://raw.githubusercontent.com/starkandwayne/concourse-tutorial/master/tutorials/basic/task-hello-world/task_hello_world.yml $ fly -t test execute -c task_hello_world.yml executing build 1 at http://a34229d82086711e9b9d902c7515d989-3b65d45e2c63e12b.elb.us-west-2.amazonaws.com:8080/builds/1 initializing waiting for docker to come up... Pulling busybox@sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812... sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812: Pulling from library/busybox 90e01955edcd: Pulling fs layer 90e01955edcd: Verifying Checksum 90e01955edcd: Download complete 90e01955edcd: Pull complete Digest: sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812 Status: Downloaded newer image for busybox@sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812 Successfully pulled busybox@sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812. running echo hello world hello world succeeded
終わりに
今回記事を書いたのはConcourse CIですが、実はJenkins Xも試してみました。取得したログを手違いで削除してしまったためここに書くことは一旦断念したのですが(いつかこのショックから立ち直ったら書きます……)裏側のアーキテクチャーには実は根本的な部分で大きな違いがあります。
先に述べたようにConcourseは Web
(マスター)及び Worker
という2つのコンポーネントによって構成されていますが、これはKubernetesとは全く独立したもので本質的な部分はVMと何ら変わりがありません。ジョブが集中すればWorkerが高負荷に陥り、Horizontal Pod Autoscalerが事前に設定されていなければ特段何の対応も行われません。HPAがあればそれなりに何とかなるとは思いますが、CIはWebのアクセスと違い1つ1つが重く滑らかに負荷を分散することは難しいでしょう。かといって予めWorkerの数を増やしたりPodに割り当てるリソースを増やしたりすることはリソースの効率的利用という観点からなるべく避けたいところです。
対してJenkins Xはジョブ開始時に専用のPodが立ち上がり終了と同時に破棄されるという動作ができます。つまり必要なときに必要な分だけ、且つ都度リソースの空いているノードで起動してくれますのでConcourseと違い余計なことを考える必要がありません。実務上どれほど問題になるかはさておき、この動作は「コンテナネイティブ」さを強く感じ私個人としてはとてもワクワクする仕組みだと感じました。
今回の検証を通してコンテナ環境にネイティブ対応したものとそうでないものの動作の違いを知ることができました。もし今後アプリケーションをKubernetesにデプロイする予定があり、どのCI/CDツールを使用するか未定な場合は「コンテナネイティブなCI/CDツール」を検討してみてはいかがでしょうか。