Help us understand the problem. What is going on with this article?

github+circleci+codedeployでs3リビジョンとec2デプロイを行う連携のメモ

何をするのか

githubのプッシュを発端にcircleciでテストとデプロイのキックからcodedeployでデプロイを行う連携のメモ
codedeployはec2をターゲットにデプロイを行い、デプロイ成果物はs3のバージョニング機能を使ってリビジョンを維持をします。

IAMの設定

IAMユーザーの作成

IAMはcircleciからs3とcodedeployへの権限が必要。とりあえず最低限の権限ならこののActionをAllowすればよいです。

ここでハマったのはポリシーのアタッチの際の文法ミス。例えばアプリケーション名がAppNameでデベロップメントグループ名がDevelopmentGroupNameのアプリのCreateDeploy権限は下記のような書き方になります。


    {
      "Effect": "Allow",
      "Action": [
        "codedeploy:CreateDeployment"
      ],
      "Resource": [
        "arn:aws:codedeploy:ap-northeast-1:XXXXXXXXXXXX:deploymentgroup:AppName/DevelopmentGroupName"
      ]
    }

Resource属性のarn:aws:codedeploy:ap-northeast-1:XXXXXXXXXXXX:deploymentgroup:AppName/DevelopmentGroupNameの書き順の最後がアプリケーション名/デベロップメントグループ名となることに注意しましょう。

きちんと公式リファレンスを確認しようと思いました。

IAMロールの作成

codedeployとEC2の2ロール作成します。名前は任意のものでポリシーにそれぞれAWSCodeDeployRoleとAmazonS3ReadOnlyAccessをアタッチします。

EC2の設定

注意して設定しなければならない項目はさっき作ったEC2ロールとタグです。ロールはcodedeploy agentの導入に必要です。タグはcodedeployからEC2を認識するために設定します。他は要件にあったものを適当に選択します。

作成したインスタンスが起動したらそれにcodedeploy agentを導入します。
EC2上でcodedeploy agentが動いているか確認するにはsudo service codedeploy-agent statusをcliで打ちましょう。

動作していなかったこれらの手順にしたがってインストールします。今回はAmazon LinuxをEC2のOSに設定したのでこれに従いました。

s3の設定

特に気をつけることはありませんが、リビジョンをs3でもたせたい場合はバケットのバージョニング機能を有効化しましょう。私はs3にこの機能があることを知らず、circleciで時刻.zipというファイル名にするコマンドでセルフリビジョン管理してました。

codedeployの設定

アプリケーションを作成します。アプリケーション名とコンピューティングプラットフォームは任意の物を設定して作成。デプロイのためにはデプロイグループを作成する必要があるので、そのままデプロイグループの作成に移行します。

例えばこんな感じでデプロイグループを作成します。詳細設定はデフォルトのままです。

項目
デプロイグループ名  my-app-deploy-group
サービスロール ※2
デプロイタイプ インプレース
環境設定 Amazon EC2 インスタンス※3
デプロイ設定 CodeDeployDefault.AllAtOnce
ロードバランサー 無効

※2:さっき作ったIAMロールを指定
※2:EC2設定時につけたタグで識別する

この時点でcodedeployは手動で動作させられるので、デプロイの作成を押下後にリビジョンをgithubのコードを指定することでデプロイが動作するはずです。

githubとcircleciの連携

circleciにgithubアカウントでログイン後左メニューのadd projectから任意のレポジトリを選択する。すると、詳細な連携方法が表示されるのでそれに従いましょう。
自分の場合、コミットが300程度積んである既存のレポジトリに.circleci/config.ymlを置いてpushしてもレポジトリが認識されないことがあった。この時はcircleciで読み込むブランチを変えたり読み込む環境変数を変えたりといったconfig.ymlの変更を何度か繰り返すと解決した。

circleciの設定

レポジトリが認識されるとWORKFLOWSにレポジトリが表示されて設定を行えるようになります。circleciにレポジトリで使う環境変数を設定します。環境変数については公式リファレンスがこちら。今回は非公開にしたい情報をブランチ毎に切り替えたかったので全てContextにしました。

左メニュー>SETTINGS>ContextsでCreate Contextを押下して任意の名前をつけます。
Contextには権限を設定できます。デフォルトでは誰でも使用できてしまうので限定しましょう。この権限のないユーザーがcircleci上でcontextを用いようとするとエラーとなります。

今回連携で必要な環境変数はこんな感じでした。

項目 Key Value
アプリケーション名  APPLICATION_NAME my-app
デプロイメントグループ DEPLOYMENT_GROUP my-app-grp
s3バケット名 BUCKET_NAME my-app-bucket
s3バケット名(スキーマ付き) FULL_BUCKET_NAME s3://my-app-bucket
リージョン REGION ap-northeast-1
アクセスキー AWS_ACCESS_KEY_ID ※1
シークレットアクセスキー AWS_SECRET_ACCESS_KEY ※1

※1:AWSで作成したcircleci→codedeployにアクセスするIAMユーザーのもの

config.ymlの設定

circleciでcodedeployをキックしてデプロイを行う記述がこんな感じです。テストコードは省略しています。config.ymlの書き方は公式を見るのが最良と思います。

version: 2.1
jobs:
  deploy_something:
    docker:
      - image: circleci/python
        environment:
          TZ: Asia/Tokyo
    steps:
      - checkout
      - run:
          name: download pip
          command: curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
      - run:
          name: install pip
          command: sudo python get-pip.py
      - run:
          name: install aws-cli
          command: sudo pip install awscli
      - run:
          name: delete get-pip.py
          command: rm -f get-pip.py
      - run:
          name: set AWS region
          command: aws configure set region ${DEFAULT_REGION}
      - run:
          name: zipping
          command: zip -r ${APPLICATION_NAME}.zip .
      - run:
          name: s3 cp
          command: aws s3 cp ${APPLICATION_NAME}.zip ${FULL_BUCKET_NAME}
      - run:
          name: registar app
          #s3のリビジョン登録。バケット側でも有効化しないと意味ないです。
          command: aws deploy register-application-revision --application-name ${APPLICATION_NAME} --s3-location bucket=${BUCKET_NAME},bundleType="zip",key=${APPLICATION_NAME}.zip
      - run:
          name: deploy
          #デプロイ先にすでにファイルがある場合の動作を指定しないとエラー出ます。
          command: aws deploy create-deployment --application-name ${APPLICATION_NAME} --deployment-group-name ${DEPLOYMENT_GROUP} --file-exists-behavior "OVERWRITE" --s3-location bucket=${BUCKET_NAME},bundleType="zip",key=${APPLICATION_NAME}.zip
workflows:
  version: 2.1
  build_deploy:
    jobs:
      - deploy_something:
      # job名。releaseブランチの時のみこれが動作する。
          context: deploy_something_context
          filters:
            branches:
              only: release

aws-cliのコマンドリファレンスはこちらです。

circleciにはorbという機能があってversionを2.1にすることで使用できるのですが、s3以外のorbにメジャーバージョンがないので今回は使用していません。また、dockerイメージにaws-cliが含まれているものを最初から選べばconfig.ymlはもっと短くなるしEC2のロールも不要になるんですが非公式なイメージを使うことに不安を覚えたので今回は使っていません。

ここまでの設定をして、こんな感じでconfig.ymlを書いてpushすれば各ツールがをうまくやってくれるはずです。

参考資料

[公式チュートリアルではじめる]CircleCI+CodeDeployを使ったCD(継続的デプロイ)

CodeDeploy pushコマンドは裏で何をやっている?

EC2デプロイのためにCodeDeployを導入する

CircleCIで特定ブランチで動くワークフローをさらに分岐させたい

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away