ハンズラボ Advent Calendar 2018 16日目の記事です。
ECサイト担当になって早3年を過ぎ、その間にCI/CD環境を継続して改善し続けてきました。
この度ようやくParavirtualなインスタンスで動作していたJenkinsサーバを停止し、一段落したこともあり、来し方を振り返ってみます。
APIサーバのCI/CD環境今昔
チーム参加時点(2015/09)
Gitリポジトリ: Atlassian Stash
- 今はBitbucketに吸収されてしまいました
CI: Jenkins
- Antから以下を実行
- PHP Lint(php -l)
- PHP Mess Detector
- PHP Code Sniffer
- PHPUnit
CD: Jenkins
- eb deployコマンドをbashスクリプトで実行
当時を振り返って
- Atlassian Stashにログインできるメンバーが社内に数名しかいなかった・・・
- AntジョブがXMLで書いてありメンテナンスできない
Gitリポジトリ移行(2015/12)
+ Gitリポジトリ: Backlog
当時を振り返って
- BacklogのGitリポジトリでプルリクエスト機能が追加されたこともありBacklogへ移行
- Githubも社内で利用開始していたが、Backlogは当時からエンタープライズプランで追加費用がなかった
決済APIサーバ分離(2016/02)
+ CI: Jenkins
+ - Antをやめて、composerスクリプトでの実行に修正
+ CD: Jenkins
+ - bashスクリプトで待機系を判定し、待機系へ`eb deploy`
当時を振り返って
- ステージング環境と本番環境のAWSアカウントの分離にチャレンジした
- ステージング環境にdeployしたCommitと本番環境に差異を発生させたくなかったため、ステージング環境deploy時に本番環境の待機系へもdeploy
- 本番環境のCNAMEから待機系を判断
- Jenkinsユーザが実行するジョブをvisudoで追加するのを忘れていて動かない
決済APIサーバのCI/CD環境移行(2018/06)
+ Gitリポジトリ: CodeCommit
+ CI: CodePipeline + CodeBuild
+ - PHP Parallel Lint に変更
+ - CodeBuildのDockerイメージでhttpdを起動してAPIのテストを実行
+ CD: CodeBuild
+ - CodeBuildからeb deployコマンドをbashスクリプトで実行
当時を振り返って
- Meltdown/Spectre以降、Paravirtualインスタンスへのメンテナンス頻度が上がり、Jenkins廃止の機運が高まった
- CodePipelineはBacklogのGitリポジトリからhookできない・・・
- CodeCommitの使い心地を試してみる
- CodeBuildでのCIでハマる
- 今はローカル実行できていいですよね・・・
- CodePipelineからElastic BeanstalkへdeployしたいがAWSアカウントをまたいでのdeployは素直には無理
- 仕方なくCodeBuildから
eb deploy
する
- 仕方なくCodeBuildから
APIサーバのCI/CD環境移行(2018/11)
+ Gitリポジトリ: Github
+ CD: CodePipeline + Lambda
+ - CodePipelineからElastic Beanstalkの待機系へdeploy
+ - 手動承認したらLambdaでswap
+ - swap完了後に未deploy側へdeploy
+ - deploy完了したら再swap
当時を振り返って
- CodeCommit辛い
- プルリクエストしたらAWSのマネジメントコンソール開くの???
- httpsにしてもsshにしても辛い
- 諦めてGithubに移行
- CodeBuildでのPHPMD/PHPCSで落ちる
- Jenkinsサーバでは通るが、新環境では落ちる・・・
- 仕方なく、通るまでチェックルールからルールを一つずつ削除する。辛い。
- ステージング環境と本番環境のAWSアカウントを分離
- featureブランチからdevelopブランチにマージ→ステージング環境にdeploy
- developブランチからmasterブランチにマージ→本番環境にdeploy
- CodePipelineからのLambda呼び出しでハマる
- LambdaからCodePipelineへ「ジョブが完了した」と通知する必要がありました
import boto3
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
SOURCE_EB = os.environ['source_eb']
DEST_EB = os.environ['dist_eb']
def lambda_handler(event, context):
logger.info(event)
try:
beanstalk = boto3.client('elasticbeanstalk')
response = beanstalk.swap_environment_cnames(
SourceEnvironmentName = SOURCE_EB,
DestinationEnvironmentName = DEST_EB,
)
logger.info(response)
except Exception as e:
logger.error(e)
raise e
try:
codepipeline = boto3.client('codepipeline')
jobid = event['CodePipeline.job']['id']
response = codepipeline.put_job_success_result(
jobId=jobid,
)
logger.info(response)
except Exception as e:
logger.error(e)
raise e
今後
Elastic BeanstalkへのAmazon Linux2の公式対応待ちです。
その際には決済APIサーバのCI/CD方式をAPIサーバに合わせる予定です。
ECS + Fargate環境にも挑戦したいです。
今後も改善は続きます。
参考資料
ハンズラボ Advent Calendar 2018 明日17日目は@sr-mtmtです!