APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

EKS上にConcourse CIをデプロイする

はじめに

先進サービス開発事業部の山岡です。

今回はEKSで構築したKubernetes上にCI/CDツールをデプロイしてみた結果について書きたいと思います。「Kubernetesで上手く使えそうか?」という観点の簡易的な動作確認を行う内容なので、このまま商用利用することは止めた方が良いと思います。

前提条件

  • EKSの基本操作を理解していること
  • Concourseの基本操作を理解していること
  • AWSのAPIキーが環境変数にセットされていること 参考資料

検証したプロダクト

EKSの構築

今回紹介する手順では先日の記事と同じくTerraformでEKSを構築しましたので、自分で作ってみたい場合はそちらを参考にして下さい。既に構築済みの環境があるのであればそのまま利用できるはずです。

Concourse CI

概要

このプロダクトがどんなものなのかについては先人の優れた記事をいくつかご紹介しますのでそちらをお読み頂ければと思います。

今回の記事を読むにあたって特にポイントとなるのはConcourseが Web 及び Worker という2つのコンポーネントで構成されているということです。これらは同じバイナリーのサブコマンドを実行することで起動することができ Web が全体を統制(リクエストの受け付けやWorkerへのタスク振り等)し Worker が実際のジョブを処理します。

パイプラインベースのCI/CDツール、Concourseとは?

Concourse CI入門 ライブ環境構築&ビルド

構築

こちらのリポジトリを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トップページからバイナリーをダウンロードできます)。

f:id:ryo-yamaoka:20181226053102p:plain

$ 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

f:id:ryo-yamaoka:20181226053106p:plain

終わりに

今回記事を書いたのは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ツール」を検討してみてはいかがでしょうか。