1K Views
January 29, 20
スライド概要
2020/1/28 Ltech#10 不動産・住宅情報サイト「LIFULL HOME'S」の中の人が語るAWS活用前線
LIFULL HOME'S事業本部プロダクトエンジニアリング部プロダクトエンジニアリング3ユニット開発2グループ
衛藤 剛史
LIFULL HOME'Sを運営する株式会社LIFULLのアカウントです。 LIFULLが主催するエンジニア向けイベント「Ltech」等で公開されたスライド等をこちらで共有しております。
LIFULL HOME'S ネイティブアプリ用API のデプロイを自動化する Jan 28, 2020 @ LTech #10 株式会社LIFULL 衛藤 剛史 @doramusukotake
自己紹介 衛藤 剛史(えとう たけし) @doramusukotake ● Android Developer ● Backend Developer ● Machine Learning ● Group Manager 2 執筆活動 Google Cloud AutoML Vision 入門 (2019/9/10 発売) © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Agenda ● ● ● ● ● ● ● 3 現状の構成・仕組み 自動化の方針 SAM (Serverless Application Model) Parameter Store CodeDeploy CodePipeline 自動化後の効果 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Agenda ● ● ● ● ● ● ● 現状の構成・仕組み 自動化の方針 SAM (Serverless Application Model) Parameter Store CodeDeploy CodePipeline 自動化後の効果 の予定でしたが、失敗したので変更します 4 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
なにが起こったか ******************************************* のちほど 5 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
失敗した話 LIFULL HOME'S ネイティブアプリ用APIのデプロイを自動化しようとして Jan 28, 2020 @ LTech #10 株式会社LIFULL 衛藤 剛史 @doramusukotake
Agenda2 ● ● ● ● ● ● ● ● 7 現状の構成・仕組み 解消したい課題 自動化の方針 遭遇した壁1 遭遇した壁2 遭遇した壁3 乗り越えられなかった最後の壁 結局 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
現状の構成・仕組み 8 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
簡易図 AWS Cloud VPC Amazon API Gateway 9 VPC AWS Lambda Amazon EC2 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
1APIG / 複数 Lambda 運用 ● Lambda用ソースコード Lambda 用ソースコード 定義) ● swagger (API path 定義) 1 RestAPI ID → 各 Lambda Function 10 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
APIGとLambdaはstage/alias運用 stage1 lambda-function:alias1 AWS Lambda Amazon API Gateway stage2 ${stageVariables.alias} 11 lambda-function:alias2 stage変数により切り分け © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
抱えている課題 12 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
現在のデプロイフロー git pull deploy command --- profile {dev | prod} Unit Tests Lint Check deploy スクリプトで自動デプロイ ただし実行は個人のPCから 13 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
課題1 .envファイル
{
"production": {
"env1": "hoge-prod",
"env2": "poge-prod"
},
"development": {
"env1": "hoge-dev",
"env2": "poge-dev"
}
env情報を.gitignoreして個人管理
}
14
© LIFULL Co.,Ltd.
本書の無断転載、複製を固く禁じます。
課題2 deploy用スクリプトの複雑化 複雑なスクリプト 高いメンテ難易度 メンテナンスが大変 15 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
課題3 環境依存(今のデプロイ方法) 個人PCから 直接アップロード 個人環境依存が強い 16 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
自動化の方針 17 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
各種AWSサービスを組み合わせて完全自動化 18 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Auto Rollback・Canaryリリースの実現 HelloDeployFunction: Type: AWS::Serverless::Function Properties: FunctionName: HelloDeployFunction AutoPublishAlias: dev1 Runtime: nodejs10.x Handler: index.handler Environment: Variables: NODE_ENV: test CodeUri: ./ DeploymentPreference: Type: Canary10Percent5Minutes Alarms: - !Ref AliasErrorMetricGreaterThanZeroAlarm - !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks: PreTraffic: !Ref PreTrafficLambdaFunction PostTraffic: !Ref PostTrafficLambdaFunction MemorySize: 128 19 Canary10Percent30Minutes Canary10Percent5Minutes Canary10Percent10Minutes Canary10Percent15Minutes Linear10PercentEvery10Minutes Linear10PercentEvery1Minutes Linear10PercentEvery2Minutes Linear10PercentEvery3Minutes AllOtOnce © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Auto Rollback・Canaryリリースの実現 HelloDeployFunction: Type: AWS::Serverless::Function Properties: FunctionName: HelloDeployFunction AutoPublishAlias: dev1 Runtime: nodejs10.x Handler: index.handler Environment: Variables: NODE_ENV: test CodeUri: ./ DeploymentPreference: Type: Canary10Percent5Minutes Alarms: - !Ref AliasErrorMetricGreaterThanZeroAlarm - !Ref LatestVersionErrorMetricGreaterThanZeroAlarm Hooks: PreTraffic: !Ref PreTrafficLambdaFunction この記述のみで Auto PostTraffic: !Ref PostTrafficLambdaFunction MemorySize: 128 20 Canary10Percent30Minutes Canary10Percent5Minutes Canary10Percent10Minutes Canary10Percent15Minutes Linear10PercentEvery10Minutes Linear10PercentEvery1Minutes Linear10PercentEvery2Minutes Linear10PercentEvery3Minutes AllOtOnce Rollback / Canary Release が実現 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Auto Rollback・Canaryリリースの実現 Canary Release の様子 21 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
遭遇した壁1 22 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Parameter Store の制限と速度 Latency .envからの読み出しと比較すると確実に時間がかかる → Lambdaのグローバル変数として保持しておきたい 23 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Parameter Store 取得処理 // load params from parameter store (async function () { await getParameters(); })(); hander() の外で実行により ● Lambda コンテナ立上時のみ実行 async function handler(event, context) { // lambdaエントリーポイント } ただし以下の問題がある ● handler() の処理待ち合わせが必要 ● handler() の処理が終わるとコールバッ クが来ない async function getParameters() { const ssm = new AWS.SSM(credentials); // パラメータストアから取得 const result = await ssm.getParametersByPath(request).promise(); // 後続処理 } 24 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Parameter Store 取得処理 // load params from parameter store (async function () { await getParameters(); })(); Event loop が空になるまで待たせるひつ ようがある (取得処理が間に合わない問題はある) async function handler(event, context) { // lambdaエントリーポイント context.callbackWaitsForEmptyEventLoop = true // 後続処理 } async function getParameters() { const ssm = new AWS.SSM(credentials); // パラメータストアから取得 const result = await ssm.getParametersByPath(request).promise(); // 後続処理 } 25 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Parameter Store 取得処理 // load params from parameter store (async function () { await getParameters(); })(); async function handler(event, context) { // lambdaエントリーポイント const testKey = process.env.TEST_KEY || null; if (testKey === null) { await getParameters(); } else { console.log('env is already set'); } // 後続処理 } async function getParameters() { const ssm = new AWS.SSM(credentials); Lambda のインスタンス立ち上がり後 // パラメータストアから取得 1回のみ取得するように const result = await ssm.getParametersByPath(request).promise(); // 後続処理 } 26 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
遭遇した壁2 27 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
同じAPI Gateway ID がたくさんできる 気づいたら同じ名前の API がたくさんできている → Stack name と openapi.yaml の info を統一して解消 28 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
遭遇した壁3 29 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Lambda alias / API Gateway stage が上書きされてしまう stage1 alias1 stage2 alias2 SAM Template 30 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Lambda alias / API Gateway stage が上書きされてしまう Deleted ! stage1 alias1 stage2 alias2 SAM Template 同じテンプレートで複数 stage / aliasはできない(既存のものが Delete される) → SAM ではなく CloudFormation の記述で回避(次項) 31 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
CloudFormationの記述で回避 - API Gateway HelloDeployApiGateway: Type: AWS::Serverless::Api Properties: StageName: stage1 DefinitionUri: ./openapi.yaml Variables: alias: "stage1" Stage2: Type: AWS::ApiGateway::Stage Properties: RestApiId: !Ref HelloDeployApiGateway DeploymentId: !Ref HelloDeployApiGateway.Deployment StageName: stage2 Variables: alias: :stage2 32 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
CloudFormationの記述で回避 - Lambda HelloDeployFunction: Type: AWS::Serverless::Function Properties: FunctionName: HelloDeployFunction AutoPublishAlias: dev1 // 略 LambdaAlias: Type: AWS::Lambda::Alias Properties: FunctionName: !Ref HelloDeployFunction FunctionVersion: !Select [7, !Split [":", !Ref HelloDeployFunction.Version]] Name: dev2 33 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
乗り越えられなかった最後の壁 34 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
API複数リポジトリ運用の罠 極力APIごとの依存関係を消し去りたいため、 ● Lambda Function ごとに github repository ● 共有なものはライブラリ化として package.json に記述 ● そのため、SAM template をそれぞれ独立させておく必要がある ● Lambda用ソースコード Lambda用ソースコード 定義) ● swagger swagger (API (APIpath path定義) 35 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
API複数リポジトリ運用の罠 既存 Path を一度 remove しないと 違う Template からデプロイできない・・・! 複数リポジトリ運用しているため、Template を分割する必要があ るが、制限があり実現できなかった 36 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
aaaaa 構成の実現が難しい状況であることがわかりました。 構成の実現が難しい状況であることがわかりました。 37 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
結果 38 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
Github Actions 使う 39 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
各種AWSサービスを組み合わせて完全自動化 AWS のサービスだけで自動化できなかった部分 40 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
まとめ 41 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
まとめ ● SAMは便利なので対応可能であればやるべき ○ CodeBuild / CodePipelineと組み合わせてより強力な自動化 ● SAMにも限界があることを知っておく ● 限界あるからといって諦めない ● Github Actionsという他の選択肢もある 42 © LIFULL Co.,Ltd. 本書の無断転載、複製を固く禁じます。
END
We are hiring engineers!! エンジニア積極採用中 LIFULL 採用 検索