見出し画像

クラウドネイティブ時代における Infrastructure as Code の必要性

概要

本記事の目的です。

  1. Infrastructure as Code(IaC)の概念を理解する

  2. クラウドネイティブ時代における IaC の必要性を理解する

  3. AWS CDK の有用性を理解する

下記については触れておりませんのでご注意を。

  • IaC ツールの比較

  • AWS CDK の開発環境構築

IaC、AWS CDK に興味のある人はぜひ最後まで読んでいってください。

クラウドネイティブとは

まずはタイトルにもなっている「クラウドネイティブ」の定義について見てみましょう。

クラウドネイティブ技術は、パブリッククラウド、プライベートクラウド、ハイブリッドクラウドなどの近代的でダイナミックな環境において、スケーラブルなアプリケーションを構築および実行するための能力を組織にもたらします。 このアプローチの代表例に、コンテナ、サービスメッシュ、マイクロサービス、イミュータブルインフラストラクチャ、および宣言型APIがあります。
これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実現します。 これらを堅牢な自動化と組み合わせることで、エンジニアはインパクトのある変更を最小限の労力で頻繁かつ予測どおりに行うことができます。
Cloud Native Computing Foundationは、オープンソースでベンダー中立プロジェクトのエコシステムを育成・維持して、このパラダイムの採用を促進したいと考えてます。 私たちは最先端のパターンを民主化し、これらのイノベーションを誰もが利用できるようにします。

CNCF Cloud Native Definition v1.0

難しいこと書いていますが、要は「クラウドネイティブ」=「クラウド前提」とか「クラウド特化」的な捉え方でよいかと思います。

…で、下記のようなクラウドネイティブへのアプローチ方法があり、

  • コンテナ

    • イミュータブルインフラストラクチャ

  • マイクロサービス

    • サービスメッシュ

    • 分散トレーシング

  • 宣言型API

IaC もこれらと関係の深いものとなっています。クラウドネイティブについて詳しく知りたい方は下記の記事がとても参考になります。

Infrastructure as Code とは

では、本題である「Infrastructure as Code」の定義を見てみましょう。

Infrastructure as Codeは自動化、バージョン管理、テスト、継続的インテグレーションといった、ソフトウェア開発のプラクティスをシステム管理に応用するための方法論です。

Infrastructure as Code クラウドにおけるサーバ管理の原則とプラクティス

つまり、ソフトウェア開発の開発者体験をインフラ設計・構築まで拡張しようというお話ですね。IaC とは、そういった方法論や技術そのものを指す言葉ですが、インフラ構築の自動化という狭義の意味で使われることも多いかと思います。

Infrastructure as Code の特徴

IaC をインフラ構築の自動化という点で見た場合、従来のインフラ構築(手作業)と比較した上でどのようなメリットがあるのでしょうか?
分かりやすく、下記の3つの観点から見てみましょう。

  1. 冪等性

  2. 再利用性

  3. 整合性

冪等性

手作業の場合、生産性や品質を向上させるために「手順書」を活用するのが一般的です。しかし、実務経験のある方なら分かると思いますが、手順書というものは非常に厄介なものです。

ヒューマンエラーやミスが発生する(原因:手順書の問題、属人化、etc…)
→ 手順書にエラーを防ぐための確認手順が追加される
→ 手順書の内容が膨大になる
→ 手順書のメンテナンスコストがかかる(最悪、メンテされなくなる)

上記の負のサイクルに加え、根本には、手順書の「正しさ」の担保が難しいという問題もあります。

これに対し、IaC はソースコードで管理されているため、誰が何回実行しても同じ結果になります

冪等性が担保されていることにより、再利用性が確保されます。

再利用性

プロダクトの環境が1つであることはまず無いでしょう。少なくとも、開発、ステージング、本番の3環境はあるのではないでしょうか。

また、昨今のマイクロサービス化を鑑みた場合、API それぞれに対してインフラリソースが必要であるため、なおのこと構築すべきリソース数は多くなるでしょう。

加えて、再利用性は IaC の特徴というよりも、クラウドの特徴そのものでもあります(クラウドリソースは頻繁に作成、破棄されるということ)。

そういった類似した構成且つ頻繁に再作成が起こり得る膨大なインフラリソースを、コンソール画面でポチポチ構築するのは非常に工数がかかり、ナンセンスであることは明白です。
(私の所属しているプロジェクトは 8環境 × 約40API なので、予算が無限でない限り手作業は不可能です笑)

整合性

従来のインフラ構築では、パラメータを別途 Excel 等でパラメータシートとして管理していました。

そういった状況においてインフラ変更が必要な場合、実際のパラメータに加えてパラメータシートの変更も必要です。しかし、手順書同様、ドキュメントというものは意図せず放置されることが多々あります(現場あるある)。

これに対し、IaC はソースコードがドキュメントであり、コードとパラメータが1:1となります。コードで一元管理され、常にコードを正としてみれば、現状のインフラの情報を正しく把握できることになります。

インフラの改訂履歴はどうでしょう。コード化できるということはすなわち Git で管理ができ、CI/CD の仕組みに載せられることを意味します。すなわち Git のコミット履歴ないし、CI/CD パイプラインの実行履歴がそのまま正確な改訂履歴として残ります。

以上、3つの大きな観点から IaC の特徴を見てきました。クラウドネイティブの時代において IaC が必須であることが理解できたと思います。

もちろん、ソースコードの作成や学習コストにより、それなりのオーバーヘッドを要します。しかし、それらはすべて企業、或いは個人の資産となるため、リターンの大きい投資だといえるでしょう。

代表的な IaCツール・サービス

実際にどういったツールやサービスがあるのか代表例を見てみましょう。

  • Chef、Puppet、Ansible(サーバーの構築や管理の自動化)
    あるべき状態を定義したファイルを利用してサーバーを構築する IaCツールです。

  • Docker、Kubernetes(コンテナ型アプリケーション実行環境の構築)
    コンテナ型仮想化基盤の構築ツールおよびオーケストレーションツールです。あるべき状態を定義したファイルを作成し、宣言型API を利用するといった、IaC の考えに沿って設計されています。IaCツールという括りで扱われることは少ないと思いますが、IaC のコンセプトに則っていることは理解しておいたほうがよいでしょう。

  • Terraform、AWS CloudFormation、AWS CDK(クラウドリソースの構築や管理の自動化)
    あるべき状態を定義したファイルを利用してクラウドリソースを構築するIaCツールです。Terraform は HCL という独自の宣言型言語、CloudFormation は YAML/JSON を使用します。Terraform は GCP や Azure にも対応しているのが大きな特徴です。

AWS Cloud Development Kit(CDK)の特徴

AWS CDK はモダンなプログラミング言語で AWSリソースを構築できる IaCサービスです。オープンソースとして公開されているため、サービス自体は無料です。下記の言語が GAとなっています。

  • JavaScript

  • TypeScript

  • Python

  • Java

  • C#

基本的に TypeScript 一択です。静的型付言語で、CDK 自体も TypeScript で書かれている且つリファレンスも多いからです。CDK を利用する上では、そこまで高度な言語理解は要求されないため、他の言語に精通している方でも TypeScript を選択した方がよいと思います。

また、CDK の仕組みとして、内部的に CloudFormation を利用しているため、 CloudFormation の仕様に依存します。プログラミング言語で CloudFormationテンプレートを作成するツールとして捉えてもよいかもしれません。

CDK で出来ることは CloudFormation で出来る、すなわち、CDK を使うメリットは非常にシンプルで、「プログラミング言語を利用できる」これだけです。しかし、それが非常に強力で、下記のようなメリットがあります。

  • L2 construct が便利すぎる(CDK だけ!!)

  • テストができる(Terraform、CloudFormation でも可能)

  • 差分確認ができる(Terraform、CloudFormation でも可能)

  • スキルの幅が広がる(CDK だけ!!)

IaCツール全般のメリットも混在しておりますが、順に見ていきましょう。

L2 construct が便利すぎる

まず、AWS CDK がどういう作りになっているのか、中身を見ていきましょう。

CDK は construct(class)を組み合わせてツリー構造を構成しています。3種類のレイヤ(L1〜L3)に分けられ、Construct Library(各AWSリソースが定義されたモジュール群)として提供されています。

L1 construct
CloudFormation で出来ることをすべて出来るようにしたいなら、CloudFormation のリソースをそのまま愚直に表現した construct が無いと始まりません。それが L1 construct です。抽象化されていないため、「Low Level Construct」とも呼ばれます。特徴として「Cfn~」というプレフィックスが付いています。

例えば、Public サブネットを持つ VPC を作成したい場合、下記の様に愚直にIGW をアタッチしたり、ルートテーブルを定義する必要があります。

const vpc = new ec2.CfnVPC(this, "SampleVpc", {
 cidrBlock: "10.0.0.0/16",
 enableDnsHostnames: true,
 enableDnsSupport: true,
});

const publicSubnet = new ec2.CfnSubnet(this, "SamplePublic", {
 vpcId: vpc.ref,
 cidrBlock: "10.0.0.0/24",
 availabilityZone: this.availabilityZones[0],
});

const igw = new ec2.CfnInternetGateway(this, "lab-igw", {
});

const igwAttach = new ec2.CfnVPCGatewayAttachment(this, "lab-igw-attach", {
 vpcId: vpc.ref,
 internetGatewayId: igw.ref
});

const publicRouteTable = new ec2.CfnRouteTable(this, "lab-public-route", {
 vpcId: vpc.ref
});

const igwRoute = new ec2.CfnRoute(this, "lab-public-route-igw", {
 routeTableId: publicRouteTable.ref,
 destinationCidrBlock: "0.0.0.0/0",
 gatewayId: igw.ref
});

const association = new ec2.CfnSubnetRouteTableAssociation(this, "lab-public-route-association", {
 routeTableId: publicRouteTable.ref,
 subnetId: publicSubnet.ref
});

つまり、「L1 construct を使う」=「CloudFormation テンプレートの YAML を TypeScript で書き直しているだけ」です。確かに YAML地獄を脱却できるだけで嬉しいと感じる人もいるかもしれませんが、旨味としては薄いでしょう。そこで、CDK の真価である L2 construct を紹介します。

L2 construct
construct をラップした construct です。つまり、L1 construct を抽象化したり、まとめたりして、汎用的にしたものが L2 construct(High Level Construct)です。これを利用すれば、より効率的に、短い記述でリソースを構築できるということです。

実際の CDK のソースコードを見てみるとイメージしやすいかもしれません。

確かに、vpc という L2 construct の constructor にて、CfnVPC、CfnInternetGateway、CfnVPCGatewayAttachment などの L1 construct が呼び出されていますね。

先程の L1 construct で紹介した例と同様に Public サブネットを持つ VPC を作成したい場合、L2 construct を使用すれば下記の記述のみで済みます。

const vpc = new ec2.Vpc(this, 'SampleVpc', {
 cidr: '10.0.0.0/16',
 subnetConfiguration: [
   {
     name: 'SamplePublic',
     subnetType: ec2.SubnetType.PUBLIC,
     cidrMask: 24,
   },
 ],
});

Public Subnet を構築したいのであれば、IGW をアタッチするのは当然です。そういった自明の設定をすべてよろしくやってくれるわけですね。

究極、下記でもOKです。この場合、AWS のベストプラクティスとされるマルチAZ構成の Public/Private サブネットが構成されます。

const vpc = new ec2.Vpc(this, 'SampleVpc', {});

マルチAZ構成について知りたい方は下記の記事を読んでみてください。

L3 construct
抽象度が高すぎるため、普通は使わないです。L2 construct を組み合わせて、1つのデザインパターンを構築しているイメージです。例えば、ALB + Fargate の ECSサービスを構成したい場合は下記の様になります。

const loadBalancedFargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(stack, 'Service', {
 cluster,
 memoryLimitMiB: 1024,
 cpu: 512,
 taskImageOptions: {
   image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
 },
});

loadBalancedFargateService.targetGroup.configureHealthCheck({
 path: "/custom-health-path",
});

まとめると、基本的には L2 construct を使用する形になります。ただし、CDK はまだ新しいサービスなので、すべてのサービスで L2 construct が実装されているわけではありません。

例えば、SFTPサーバーを構築する AWS Transfer Family の様なマイナーなサービスでは L2 construct がまだ実装されていません。こういった場合は、渋々 L1 construct を利用するしかありません。

テストができる

コード化できるということは、テストが書けるということです。下記のページが非常によくまとまっているので、ここでの説明は割愛します。私の所属しているプロジェクトではスナップショットテストのみ採用しています。

差分が見れる

cdk diff

ソースコードの変更によるリソースの変更箇所をコマンド一発で確認できます。想定通りの変更なのかを確認するのに非常に便利で、よく使用するコマンドです。差分確認が簡単且つ明確なので、リファクタリングのつもりが予期せぬ変更が発生してしまったみたいなトラブルはまず起こらないです。

スキルの幅が広がる

上記の記事では CDK の学習コストが指摘されています。確かにそれはその通りなのですが、裏を返せば、CDK を学ぶことで、アプリケーションエンジニアはインフラを学べるし、インフラエンジニアはアプリケーション開発について学べるわけです。

巷ではインフラエンジニア不要論的なものが唱えられていますが、正確にはバックエンドエンジニア、インフラエンジニアの担当する範囲が曖昧になってきているのだと思います。

最近では「SREエンジニア」というワードも生まれました。SRE(Site Reliability Engineering)とは、システム運用の自動化・効率化などによって、サービスやプロダクトの信頼性を向上させることを指します。まさしく、SREエンジニアには、IaC や CI/CD のスキルが求められ、その基礎となるアプリケーション開発経験やインフラの知識は必須です。

エンジニアのレベルアップ = 仕事における技術的責任範囲を広げること

だと私は思っています。CDKを学ぶ価値はとても高いのではないでしょうか。

これ余談なんですけど…

先日、既存の Secrets Manager のクロスアカウントアクセス対応をする必要があり、その方法を調べていました。

例えば、ググって真っ先にヒットするのは下記のページでしょう。怪しい日本語で長々と書かれていて読む気も失せると思います。

ただ、私の所属しているプロジェクトは CDK を利用しているので、最終的には CDK での方法を知りたいわけです。下記のページにたどり着きました。

すると、非常に簡潔な 4行のソースコードで、その方法が記載されていました。

const otherAccount = new iam.AccountPrincipal('1234');
const key = new kms.Key(stack, 'KMS');
const secret = new secretsmanager.Secret(stack, 'Secret', { encryptionKey: key });
secret.grantRead(otherAccount);

んー、素晴らしい!!!

以上、IaC のメリットを実感した些細な日常の一コマでした。

まとめ

  1. IaC の目的はソフトウェア開発体験をインフラ構築まで拡張すること

  2. クラウドネイティブ時代に IaC は必須である
    冪等性、整合性、再利用性の観点から IaC の必要性を学びました

  3. AWS を利用する場合は AWS CDK でインフラリソースを構築するべき
    L2 construct の利便性について学びました

補足

AWS Cloud Development Kit (CDK)

とても分かりやすい公式のドキュメントhttps://d1.awsstatic.com/webinars/jp/pdf/services/20200303_BlackBelt_CDK.pdf

CDK テンプレート

CDK 始める際、自由にご活用ください。

なぜ「Infrastructure as Code」が必要なのか

タイトルの通り、IaC の必要性について分かりやすくまとまっています。2021年の資料ですが、CloudFormation がメインで、CDK についてはほとんど触れられていません。

AWS CDKとTerraformをn個の観点で徹底比較

Terraform と CDK を比べたい場合は参考になります。

比べてわかる!IaCの選びかた

購入させていただきましたが、簡潔にまとまった良い本でした。この本で紹介されていた「Pulumi」については今後の発展が気になりますね。

Pulumiを使ってみた


この記事が気に入ったらサポートをしてみませんか?