Slide 1

Slide 1 text

CFnからCDKへ the future of developer tools on AWS 2020/02/27 ⼩⽥勝也

Slide 2

Slide 2 text

今⽇の⽬的は、CDKを使う⼈を増やすこと CDKは本当に便利。便利さをシェアしたい ⾃分が楽するために、ユーザを増やしたい Page 2 / 32

Slide 3

Slide 3 text

今⽇話すこと CDKとは CloudFormation(CFn)のつらみ CDKの強み HiCustomerの宣伝 Page 3 / 32

Slide 4

Slide 4 text

今⽇話さないこと CFnとは 他の⽅が話していなければ話す マルチクラウドの話 弊社はマルチクラウドを考えていない。BigQueryだけ使うかも HerokuもCircleCIもチャーンして、AWSのアップセル・クロスセルに貢献中 Terraformとの違い TerraformはRubyのDSLで定義して、aws-sdk-goを使ってAPIでデプロイ CDKはTypeScriptで定義して、CFnでデプロイ Page 4 / 32

Slide 5

Slide 5 text

⾃⼰紹介 アプリケーションプログラマ 前職はネットワーク応⽤通信研究所。新卒からずっと 2018年の12⽉に、HiCustomerに⼊社 CloudfrontによるフロントエンドのSPA化 Cognitoを使ったIDaaS環境の構築 Event sourcingとCQRSを使ったデータモデルの設計と実装 Blue/Greenデプロイによるリリース全般の改善 今は、AWS KinesisとElasticsearchをかまっています Page 5 / 32

Slide 6

Slide 6 text

CDKとは The AWS Cloud Development Kit (AWS CDK) is an open-source software development framework to define cloud infrastructure in code and provision it through AWS Cloudformation. https://github.com/aws/aws-cdk Page 6 / 32

Slide 7

Slide 7 text

CDKとは The AWS Construct Library includes a very large amount of "undifferentiated heavy lifting" that you can only enjoy if you use the high level resources which encapsulate all this goodness for you behind a nice clean object-oriented API. https://github.com/aws/aws-cdk/tree/master/packages/cdk-dasm Page 7 / 32

Slide 8

Slide 8 text

CDKとは CDKは「undifferentiated heavy lifting」を積極的にやってくれる スタートアップはいかに「undifferentiated heavy lifting」をやらないかが鍵 Page 8 / 32

Slide 9

Slide 9 text

CDKとは 慣れ親しんだ⾔語で宣⾔的にAWSのインフラを定義 vim lib/hello-stack.(ts|py|java|cs) 宣⾔的な定義から、最終的にCFnのテンプレートを出⼒する npm run build && cdk synth hello-stack > template.yml 出⼒したテンプレートを簡単にAWSのインフラにデプロイできる cdk deploy hello-stack Page 9 / 32

Slide 10

Slide 10 text

CDKとは 慣れ親しんだ⾔語で宣⾔的にAWSのインフラを定義できる CDK⾃体はTypeScriptで書かれている DSLやテンプレートではなく、汎⽤的なプログラミング⾔語を使える 再利⽤可能な定義が豊富に⽤意されている Node.jsのRuntimeで動作しない⾔語は、まずNode.jsが別プロセスであがる。次 に、⾔語ごとのライブラリがIPCでそのプロセスと通信する。 https://github.com/aws/jsii/blob/master/docs/runtime-architecture.md Page 10 / 32

Slide 11

Slide 11 text

CDKとは 宣⾔的な定義から、最終的にCFnのテンプレートを出⼒する CFnのテンプレートに落ちる安⼼感 今までの知⾒が使える StackSetsを使って複数のアカウントにデプロイできる 定義したスタックのリソースはツリー構造(construct tree)で表現される 既に定義されたツリーを操作して、出⼒するテンプレートを調整できる Page 11 / 32

Slide 12

Slide 12 text

CDKとは 出⼒したテンプレートを簡単にAWSのインフラにデプロイできる マルチスタックに対応。スタックが増えてもデプロイの難度があがらない cdk ls && cdk deploy stack01 && cdk deploy stack02 S3へのアップロードとかMakefileとか、⼀切必要ない Page 12 / 32

Slide 13

Slide 13 text

CDKとは CloudFormationを強⼒に補完するもの Page 13 / 32

Slide 14

Slide 14 text

CFnのつらみ デプロイがつらい 開発がつらい コードの共有がつらい Page 14 / 32

Slide 15

Slide 15 text

CFnのつらみ デプロイがつらい スタックテンプレートのサイズによって、デプロイ⽅法が変わる 51200 characters limit Parametersをローカルで展開できない Runtimeでエラーになって初めてわかる Macrosをローカルで展開できない Runtimeでエラーになって初めてわかる SAMのMacrosがどう展開されるかはテストコードを⾒ないとわからない Page 15 / 32

Slide 16

Slide 16 text

CFnのつらみ 開発がつらい ⼤量にあるプリミティブなリソース ユースケースにそって⾃分で組み⽴てなければならない もう誰か作っているだろってのを⾃分で組み⽴てる不⽑さと悲しさ テスタブルでない構造 ローカルでテストできない テストするためには、Change Setsをつくらないといけない 独⾃のテンプレート⾔語 オンボーディングコストが⾼い Page 16 / 32

Slide 17

Slide 17 text

CFnのつらみ コードの共有がつらい Nested Stackを気軽に使うとにすぐにlimitに達する 200 stacks limit Nested Stackは⼦のスタックのエラーが親から⾒えない つらい AWS::Includeはネストすることができない つらい Page 17 / 32

Slide 18

Slide 18 text

CDKの強み デプロイが楽 開発が楽 コード共有も楽 CFnにできてCDKにできないことはない CFnのテンプレートからの移⾏も楽 Page 18 / 32

Slide 19

Slide 19 text

CDKの強み デプロイが楽 TypeScriptのオプショナルな型ヒントによる⼤幅な時間節約 buildが通ればだいたい動く、試⾏錯誤の回数が減る インフラはアプリに⽐べて、Tryのコストが極端に⾼い ParametersもMacrosもいらない ContextがParametersの代わり。build時に決まる Runtimeでのエラーが減る Page 19 / 32

Slide 20

Slide 20 text

CDKの強み 開発が楽 ユースケースごとに⽤意されたConstruct テスタブルな構造 遅延評価。デプロイ時にresolveされる値 Tokens synth時にintrinsic関数の Ref に置き換えてくれる deploy時に値が決定する Lazy Values synth時に評価され、値が決定する Page 20 / 32

Slide 21

Slide 21 text

CDKの強み コード共有も楽 コードを共有し放題 DSLやテンプレートにはない、汎⽤的なプログラミング⾔語を使える強み 横軸でコードに機能を追加できる Aspectsの利⽤ 既存のコードを修正せずに、リソースを変更できる 再利⽤性が⾼まる Page 21 / 32

Slide 22

Slide 22 text

CDKの強み Aspectsの利⽤例 const gitRepoUrl = capture('git config --get remote.origin.url') const gitCommitId = capture('git rev-parse HEAD') const gitBranchName = capture('git rev-parse --abbrev-ref HEAD') for (const c of [cloudfront, s3]) { cdk.Tag.add(c, "hc:env", hcEnv); cdk.Tag.add(c, "hc:git-repo-url", gitRepoUrl); cdk.Tag.add(c, "hc:git-commit-id", gitCommitId); cdk.Tag.add(c, "hc:git-branch-name", gitBranchName); } Page 22 / 32

Slide 23

Slide 23 text

CDKの強み CFnにできてCDKにできないことはない Escape Hatchesが⽤意されている CFnの全リソースに1対1に対応するクラスが存在 https://github.com/aws/aws-cdk/tree/master/tools/cfn2ts addPropertyOverride を使⽤してリソースのPropertyを上書きできる Page 23 / 32

Slide 24

Slide 24 text

CDKの強み CFnXzy と addPropertyOverride の利⽤例 const cluster = new rds.CfnDBCluster( this, "DBCluster", dbClusterProps ); cluster.addPropertyOverride("EnableHttpEndpoint", true); cluster.cfnOptions.updateReplacePolicy = cdk.CfnDeletionPolicy.RETAIN; Page 24 / 32

Slide 25

Slide 25 text

CDKの強み CFnからの移⾏も楽 テンプレートからTypeScriptのコードを出⼒するディスアセンブラがある cdk-dasm < hello-stack.yml > lib/hello-stack.ts 強⼒だが、たった157⾏のシンプルな実装 https://github.com/aws/aws-cdk/blob/master/packages/cdk-dasm/lib/dasm.ts これで変換して、少しいじるだけで移⾏は終わり。ロジカルIDが変わる可能性も あるので⾃⼰責任で 制限もいくつかある。 Fn::Join などのIntrinsic Functionは対象外。Parameters などは扱えない。⼀部のリソースのキーがパスカルケースになるなど Page 25 / 32

Slide 26

Slide 26 text

CDKを使った安全なBastionの構築例 Session ManagerがPort Forwardingに対応 https://aws.amazon.com/blogs/aws/new-port-forwarding-using-aws- system-manager-sessions-manager/ Bastionをprivateなsubnetにおけるようになった CloudflareみたいにSSH Certificatesも対応してほしい Security UpdateもSystem Managerで⾃動化 Page 26 / 32

Slide 27

Slide 27 text

CDKを使った安全なBastionの構築例 export class BastionStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props: cdk.StackProps = {}) { super(scope, id, props); const hcEnv = this.node.tryGetContext("HC_ENV"); const vpcId = this.node.tryGetContext("VPC_ID"); const vpc = ec2.Vpc.fromLookup(this, "Vpc", { vpcId }); const bastion = new ec2.BastionHostLinux(this, "Bastion", { vpc, instanceName: `${hcEnv}-hc-vpc-bastion`, subnetSelection: { subnetType: ec2.SubnetType.PRIVATE }, }); bastion.instance.role.addManagedPolicy({ managedPolicyArn: "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM" }) cdk.Tag.add(bastion.instance, 'Patch Group', `${hcEnv}-hc-vpc-bastion`, { includeResourceTypes: [ 'AWS::EC2::Instance' ], }); Page 27 / 32

Slide 28

Slide 28 text

CDKを使った安全なBastionの構築例 new cdk.CfnOutput(this, "BastionAzOutput", { value: bastion.instanceAvailabilityZone, exportName: `${hcEnv}-hc-vpc-bastion-az` }); new cdk.CfnOutput(this, "BastionIdOutput", { value: bastion.instanceId, exportName: `${hcEnv}-hc-vpc-bastion-id` }); new ssm.CfnPatchBaseline(this, "BastionPatchBaseline", { name: `${hcEnv}-hc-vpc-bastion-patch-baseline`, operatingSystem: 'AMAZON_LINUX_2', patchGroups: [ `${hcEnv}-hc-vpc-bastion` ], approvalRules: { patchRules: [ { approveAfterDays: 0, enableNonSecurity: true, patchFilterGroup: { patchFilters: [ { key: "PRODUCT", values: [ "*" ] }, { key: "CLASSIFICATION", values: [ "*" ] }, { key: "SEVERITY", values: [ "*" ] } ] } } ] } }); Page 28 / 32

Slide 29

Slide 29 text

CDKを使った安全なBastionの構築例 const maintenanceWindow = new ssm.CfnMaintenanceWindow(this, "BastionMaintenanceWindow", { name: `${hcEnv}-hc-vpc-bastion-maintenance-window`, allowUnassociatedTargets: true, cutoff: 1, duration: 2, schedule: "cron(0 3 ? * * *)", scheduleTimezone: "Asia/Tokyo", }); const maintenanceWindowTarget = new ssm.CfnMaintenanceWindowTarget(this, "BastionMaintenanceWindowTarget", { windowId: maintenanceWindow.ref, resourceType: "INSTANCE", targets: [ { key: "InstanceIds", values: [ bastion.instanceId ] } ] }); Page 29 / 32

Slide 30

Slide 30 text

CDKを使った安全なBastionの構築例 new ssm.CfnMaintenanceWindowTask(this, "BastionMaintenanceWindowTask", { windowId: maintenanceWindow.ref, maxConcurrency: "50", maxErrors: "0", priority: 1, targets: [ { key: "WindowTargetIds", values: [ maintenanceWindowTarget.ref ] } ], taskInvocationParameters: { maintenanceWindowRunCommandParameters: { parameters: { "Operation": [ "Install" ], "SnapshotId": [ "{{WINDOW_EXECUTION_ID}}" ] }, timeoutSeconds: 600 } }, taskArn: "AWS-RunPatchBaseline", taskType: "RUN_COMMAND" }); } } Page 30 / 32

Slide 31

Slide 31 text

HiCustomerの宣伝 会社のフェーズ 3ヶ⽉前にプレシリーズAの資⾦調達が完了 優秀なエンジニアを探しています https://speakerdeck.com/hizeny/engineers- at-hicustomer お⾦も優秀だったらそこそこもらえます もっと⾯⽩い仕事いっぱいあります GoyaccでDSLつくったり、KinesisでStreaming データと戯れたり Page 31 / 32

Slide 32

Slide 32 text

HiCustomerの宣伝 これを⾒ている⽅で、「お前だめだ!もっと俺のほうが できる!」と⾃⾝がある⽅、ぜひ⼀度ご連絡いただける と助かります @dkzks: CEO @hizeny: VPoE @poppopoyoyo: 今話している⼈ Page 32 / 32