helloworlds

not a noun, it's a verb

【AWS】シンプルなリリースプロセス自動化 ( Github + CodePipeline, CodeBuild, Elastic Beanstalk )

今回はAWSを使用したシンプルなリリースプロセスの自動化について考えてみます。

リリースプロセスとは、開発から本番サーバーまであげていく(= リリース)ことをここでは指します。 また、たーっくさんのノウハウがあるので、この記事ではあくまでも一部。 やり方、状況1つでけっこうな構成が考えられるので、そこはググってみて下さい。 また、この記事ではAWSコンソールの画像は載せないので、ご自身のAWSコンソールで確認しながら用語など確認してみて下さい。 今回の記事では、本番というかステージサーバーまでというイメージになりますが、一旦構成できてしまえば、本番も簡単ですので、一読頂けたら幸いです。

f:id:o21o21:20180803144307p:plain

まず、Code3兄弟

AWS界隈では、よくCode三兄弟なんて呼ばれているサービスがあります。

そのサービスとは、

  • CodeCommit
  • CodeDeploy
  • CodePipeline

この3つのことです。

DynamoDBやS3は知ってるけど、この3つは使ったことないという方も多数いるのではないでしょうか。 自分の会社でもし使用しているのであれば、是非構築した人にどうしてこの構成にしたのかなど聞いてみると面白いかもしれません! もしかすると、苦悩など聞けるかもしれません。。。w

また、上記のサービスと合わせて、Jenkinsというツールを使用されている方も多いのでは? けっこう記事も多くありますしね。

ただ、私としてはAWS内のサービスでまかなえたらと思います。 理由は、ただ面倒くさいから....w

この3兄弟についてはざっくりこんなかんじです。

CodeCommitは、AWS版Git。 CodeDeployは、EC2へのファイル配置とスクリプト実行を自動で、プラスで環境毎で管理しやすいよ。 CodePipelineは、アプリのビルドやテストのフローを管理・自動化してくれるよー。

みたいなかんじです。

あれ?タイトルのCodeBuildは?

こちらは2016年のre:Inventにて、発表されたサービスのようです。 もう2年くらい経っているので、今ではCode4兄弟になっているようですww

一旦、Codeなんちゃらと言われるサービスは、リリースまでの手助けをしてくれるものとしてざっくり覚えておけばよさそうですね。

(※ コード書くとかほんとに全てAWSで収めたい場合、CodeStarと呼ばれるサービスもあります。参考 )

CodeBuildもざっくり言うと、フルマネージド型ビルドサービス。(自分でビルドサーバーを管理しなくていい)

うんうん。まあ、一旦公式のドキュメントを以下に。

そして今回は、タイトルにもある通り、

Github + CodePipeline + CodeBuild + Elastic Beanstalk

でかるく流れを追いつつ構成を考えてみます。

前置き

いきなり各サービスを作成していってもいいのですが、面倒なことになりかねないので一旦前知識として!

開発環境について

主にWebアプリだと仮定して、開発だとローカルに仮想環境を構築されている方多いと思います。 CentOSだとかDockerとかですかね? ここではDockerということにします。

ローカルでバグ修正なり、開発を終えると大体先輩やらのコードレビューが入ります。

何でコードを管理しているかによりますが、ここではGithubにします。 大体ブランチを切ってプルリク出してmasterにマージします。

まず、ここで把握しておきたいのは、CodePipelineをキックするのはどのブランチになるかということです。

ここでもう、どんなかんじはフローになるのかを見てみます。

いったん構成図をみてみる

f:id:o21o21:20180803113621p:plain

これさえ見たらもうわかるかと思います。 CodePipelineが管理する管轄は、この3つのサービスです。 (上の構成図では、Githubは点線の外ですが基本的には、CodePipelineを作成する際に、認証接続が必要になります。)

ここでもう一度言います! あくまで、シンプルな構成図です! ビルドしてからのテストや、承認アクション、Slackに通知したりなどなどいくらでもできるのですが、まずは基本ということで、シンプルでいきますw このシンプルな構成ができれば、あとのカスタマイズは楽になるかと思います。

Docker Imageを確認してから....

さて元に戻って...

開発でDockerを使用しているならば、必ずDockerfileなるものを管理していると思います。 そのDockerfileを元にdocker buildなどなどしているはずです。

ローカルでdocker imagesで今どんなイメージ使用しているか確認します。 何故確認するかというと、実はもう1つAWSのサービスを使うためです。

CodeBuildで必要になってきます。 現在のCodeBuildでは、ビルドをする環境イメージがUbuntuしか選択できないのです。 なので、せっかくDockerで開発しているならばそのままDockerイメージを選択してそのままテストできた方がいいですよね。

なので、Dockerfileの内容をきちんと確認しておきます。 そしたら新しく使用するサービスは、ECR (Elastic Container Registry)というサービスです。 簡単に、AWSのDockerレジストリサービスのことです。

Docker Imageを管理しておくことができます。

ということで、まずDocker ImageをECRで管理します。

ECRへプッシュ

特に難しいことはなく、コマンドを打てばECRにイメージが登録できます。

基本的にAWSコンソールの方で先にリポジトリを作成します。 作成が完了すると、コマンドの例が出てくるのでそれを順を追って叩いていけば問題ないです。

1つ、aws cliを使用できるように自分設定しなければなりません!

最終的に以下のようなコマンドを打ち終わると登録完了できたと思います。

$ docker push 506445657567.dkr.ecr.ap-northeast-1.amazonaws.com/docker-image-name:version

ちゃんとヴァージョンを指定してあげましょう! もし間違えても完全新規なら特に影響する範囲がないので、間違えたら削除すればいいや程度で叩いてみても大丈夫でしょう。

ECRを加えることで、以下のような構成図になります。

f:id:o21o21:20180803120908p:plain

ようやく、流れを確認 !w

まず、今回の記事の場合だと以下の手順で構成し始めるといいかもしれません。

  1. 開発環境を確認する (Dockerまわり、Githubブランチまわりなど)
  2. ECRにDocker Imageを管理させる
  3. CodeBuildでプロジェクトを作成する
  4. ElasticBeanstalkでアプリと環境(最低1つ)を作成する
  5. CodePipelineでそれぞれのサービスを紐づけしていく
  6. それぞれ動作するか確認〜

どんな環境でどんなサービスなのかによっても左右されますが、ちょっと詰まりやすいのは、 CodeBuildが正常にいくかなのかな〜と思います。

あと、ElasticBeanstalk(以下EB)で先に現状のプロジェクトをEBの各言語のルールに沿ってそのままzip化して、 そのまま手動で挙げてみて、とりあえず正常に動作するか確認してもいいかもしれません。

そしたら、簡単にはなりますがいくつかサービスの詳細を書いていこーかと思います。

CodeBuildについて

記事の前半にある前知識で、Githubの指定したブランチに対して、CodePipelineがキックされて成功なら、次にCodeBuildに流れていくことが大体わかったかと思います。

CodeBuildのプロジェクトを作成するにあたって重要な項目は以下。

  • ソース:ビルドの対象 > ソースプロバイダ
  • 環境: ビルド方法 > カスタムイメージタイプ(Docker)
  • buildspec 名
  • サービスロール
  • VPC (環境によりけり)
  • 詳細設定全般(特に環境変数かな?)

大体想像できるかと思いますが、buildspecが見慣れないかんじがします。 これは、ビルドを仕様をYAML形式で指定できるものになります。

AWS CodeBuild のビルド仕様に関するリファレンス - AWS CodeBuild

主に以下のようなかんじで記述していきます。 術全ての項目が必須というわけではないので、必要なところだけ記入してプロジェクトのプロジェクト直下に配置します。

version: 0.2

env:
    variables:
        key: "value" #環境変数指定
    parameter-strore:
        key: "value" # Systems Managerから取得し、値は暗号化できる

phases:
    install:  # パッケージインストール
        commands:
             - command
    pre_build: # ビルド前処理
        commands:
             - command
    build:  # ビルドテスト
        commands:
             - command
    post_build:  # アーカイブ化(zipなど), ECRへのプッシュ
        commands:
             - command
artifacts:
    files:  # S3へアップするファイルを指定
        - location

node.jsならnpm installとか、PHPならcomposer.phar installをここに書いておけば大丈夫です。

と、同時に、前にDockerfileを確認と言っていましたが、CodeBuildではECRに登録したDockerイメージを使用します。 ちゃんとbuildspec.ymlと合わせて、CodeBuildでもDockerイメージが使用できるように調整しましょう! テストコードもここでコマンドを叩いてテストできるので、1度はとりあえずビルドかけてみるがいいでしょう。

CodeBuildのログ

ログですが、ビルドするとAWSコンソールでビルド履歴が確認できます。 そこの各項目の詳細を開くと、出力:ログからCloudWatchに飛ぶので確認できます。 どこのコマンドでコケているんだ〜とかチェックできます。

Elastic Beanstalk

EBには、大きくアプリとその環境という枠組みを作成することになります。 例えば、1つアプリ作成して、環境を複数作成し、Blue/Greenデプロイ構成を作成することができます。

環境をステージングと本番に分けてもいいですね。

EBの場合はけっこう設定する項目があります。

  • 環境枠の選択 (Web環境 or Worker環境)
  • 基本設定 > プラットフォーム
  • 基本設定 > アプリケーションコード
  • さらにオプションを設定 > ソフトウェア / インスタンス / 容量 / ロードバランサー / ローリング更新とデプロイ / セキュリティ / モニタリング / 通知 / ネットワーク / データベース / タグ

ほんとは全て気にしないといけないのですが、特に気にしたのが、ネットワークロードバランサー(ALB)ですかね〜。

EBだとデフォルトで、Classic Load Balancer (CLB)になってしまいます。なので、ALBに変更します。 CLBではWAFを使用できませんが、ALBは使用できたりします。 ネットワークは、あれです、会社のルール的なやつです...w

上記を設定し、プラットフォームを使用したい言語に合わせてzip化してとりあえず手動であげれば動きます。 ※ 設定内容は環境作成後、変更は可能ですがインスタンスが新規で作成されたりするので、できれば最初の段階で設定値は運用するにあたっての設定にしといた方が後々楽かと思います。 インスタンスのセキュリティグループの追加でも環境の再構築が始まりました。

とまあ、とりあえずこんなもんかなというEBが作成できてしまえば、設定の保存ができるのでいくらでも環境の作成&削除が可能です。 あんまりこだわっても仕方ないのでね。。w 開発する段階で徐々に調整していくのがいいかもしれません。

.ebextensions

EBには、.ebextensionsというその環境のAWSリソースをカスタマイズできる機能(設定ファイル)を持つことができます。 プロジェクトに.ebextensionsというフォルダを作成し、その中にxxxx.configというファイルをYAMLJSON形式で書いて、置いておけばいいです。 .configという拡張子で認識するので、ファイル名は任意で複数置くこともできます。 また、JSONで記述可能ですが、公式ではYAML形式を推奨しているようです。

CodeBuildでも設定ファイルあるのに、EBでもか.... と思ってしました。

例としてこんなかんじかけます。(パッケージ入れたり環境変数設定したり立ち上げ時のサーバーにファイル生成したり...)

packages:
    yum:
         パッケージ名[]

commands:
    01-xxxxx-command:
        command: なんかコマンド
    02-xxxxx-command:
        command: なんかコマンド
        test: なんかコマンド

files:
    "/path/to/you/want/create/file.sh" :
        mode: ""
        owner: root
        group: root
        content: |
            ファイルの内容

EBのTips

1つ私が詰まって1日費やした箇所があります。 EBの仕組みとして、覚えておかないといけなかったっぽい。。

.ebextensionsをもちろん使用していたのですが、ログを確認するとどうもその記述が悪くあるコマンドでこけていた。。。 エラー内容もよくみるものだし、内容は把握していたのに何故かうまくいかない。。

結論としては、.ebextensionsで記述したコマンドが実行される場所に鍵がありました。

EBがの.ebextensionsが実行される場所は、/var/app/ondeckというディレクトリがワーキングディレクトリになっています。 コマンドが正常に全て完了すると、ondeckディレクトリはなくなって、currentディレクトリにプロジェクトがコピーされ、デプロイの完了になります。

おーーなるほどーーと思い、コマンドを修正したら見事EBのヘルスがOkになりました。。w

ここまで

大体山場を抑えたら、あとはCodePipelineで各サービスを紐づけしていくのみです。 特に難しい操作はありません。ポチポチしていけば、大丈夫です。

Githubの指定したブランチにpushされた時に、CodePipelineが発火します。 AWSのコンソールの進捗状況をみていると、今どこで処理されているのかが確認できます。

まとめ

今回はシンプルな自動化のフローを考えました。 この他、承認フローとして、Lambdaをかませて、Slackのあるチャンネルに通知 > Slack上で任意のユーザーの承認を得る > ステージングに変更を適用などできます。またビルド後のテストのフローもビルド先を増やせば複数できるのかな?

ほんとに色んな方法があるので、いろいろ試してみたいものです! ただ、他サービスを入れてしまうと運用コストが高くなってしまうので、できるだけシンプルに簡単にを意識したいと改めて思いました。

以上