クラウドにおけるアプリケーション中心のインフラストラクチャの採用 1
クラウドコンピューティングの世界では、インフラストラクチャとアプリケーションの管理は、しばしば2つの哲学の物語でした。一方では、確実性と一貫性に焦点を当てたエンジニアリングの考え方から生まれたAWS CloudFormationのようなツールがあります。CloudFormationは、コードとしてのインフラストラクチャの定義に優れており、予測可能なデプロイメントと自動ロールバックを保証します。他方では、Kubernetesは運用現場から生まれ、動的なコンテナ化されたアプリケーションのためのアドホックな運用と緩和策を強調しています。Kubernetesはコンテナオーケストレーションにおいて比類のないものですが、伝統的にCloudFormationのような広範なインフラストラクチャ管理能力を欠いていました。
この相違は、ツールチェーンの無秩序な増加、不整合、および運用上の複雑さにつながっています。しかし、「アプリケーション」の定義がより広範囲の密結合リソースを含むように進化するにつれて、新しいパラダイムが出現しています:アプリケーション中心のインフラストラクチャ。AWS Cloud Development Kit (CDK)のようなツールによって可能になるこのアプローチは、インフラストラクチャとランタイム管理を統一し、一貫性、管理性、およびドメイン駆動型の視点をクラウドデプロイメントにもたらすことを目指しています。
CloudFormation vs. Kubernetes:実践における2つの哲学
アプリケーション中心のインフラストラクチャへの移行を理解するためには、CloudFormationとKubernetesの根本的な違いを理解することが不可欠です。
CloudFormation:エンジニアリングの確実性と自動ロールバック
- 焦点: Infrastructure as Code (IaC)、AWSリソースの宣言的プロビジョニング。
- 哲学: エンジニアリングの確実性、一貫性、予測可能性。
- 障害時のロールバック: スタック操作の自動ロールバック。リソースの作成または更新が失敗した場合、CloudFormationはすべての変更を元に戻し、一貫した状態を保証します。これは「オールオアナッシング」のデプロイメントを強調し、安定性と予測可能性を優先します。
- 依存関係管理:
DependsOn
を使用した組み込みの宣言的依存関係サポート。CloudFormationはリソースの作成と削除の順序を理解して強制し、複雑なインフラストラクチャデプロイメントを簡素化します。
Kubernetes:運用上の柔軟性と回復力
- 焦点: コンテナオーケストレーション、コンテナ化されたアプリケーションのライフサイクル管理。
- 哲学: 運用上の柔軟性、回復力、動的環境におけるアドホックな緩和策。
- 障害時のロールバック: 一般的な障害に対するデフォルトでの自動ロールバックなし(Deploymentの更新を除く)。Kubernetesは運用管理を優先し、オペレーターが調査して対象を絞った緩和策を適用できるようにします。ロールバックは通常、明示的なアクションです。
- 依存関係管理: 暗黙的でコントローラー駆動型。Kubernetesはエコシステム内の依存関係(例:PodとService)を管理しますが、CloudFormationのような宣言的なインフラストラクチャレベルの依存関係管理を欠いています。
これらの対照的なアプローチは、それぞれの起源と主要なユースケースを反映しています。CloudFormationは基盤となるインフラストラクチャ用、Kubernetesはアプリケーションランタイム管理用です。
現代の「アプリケーション」:境界付けられたコンテキストとしての垂直スライス
「従来、クラウドにおける『アプリケーション』は、Kubernetesによってオーケストレーションされたコンテナのセットと見なされていたかもしれません。しかし、現代のアプリケーションはビジネス機能の垂直スライスであり、多くの場合、以下のもので構成されています。
- コンテナ:マイクロサービス、コンテナにパッケージ化されたアプリケーションロジック。
- データベース:RDSのようなマネージドデータベース、またはDynamoDBのようなサーバーレスオプション。
- ストレージ:オブジェクトストレージ(S3バケット)、ブロックストレージ(EBS)。
- ネットワーキング:VPC、ロードバランサー、DNS、CDN。
- サーバーレス関数:イベント駆動型ロジックのためのLambda関数。
- APIゲートウェイ:APIの管理と保護のため。
- 決定的に重要なのは、セキュリティと最小権限の原則です。現代のアプリケーションは、最小権限の原則に基づいて構築された堅牢なセキュリティアーキテクチャを必要とします。これは、アプリケーションの各コンポーネントがその機能を実行するために必要な最小限のリソースにのみアクセスできるように、詳細な役割と権限を定義することを意味します。セキュリティは後付けではなく、アプリケーションの設計とデプロイメントの基本的な側面です。」
「アプリケーション」を単なるコンテナとして狭く定義することは、そのドメイン駆動型の範囲を無視することになり、制限的になります。より正確で有用な定義は、物理的な場所や種類に関係なく、ビジネス機能を提供するために必要なすべてのリソースを持つ自己完結型の垂直スライスとして、すべての密結合された論理リソースを境界付けられたコンテキストとして包含します。
アプリケーション中心のインフラストラクチャ:ドメイン駆動型アプローチ
この「アプリケーション」のより広範な定義は、アプリケーション中心のインフラストラクチャ設計につながります。このパラダイムは、個々のリソースを個別に管理することから、論理的なアプリケーション境界の周りにインフラストラクチャを編成することに焦点を移します。主な原則は次のとおりです。
- アプリケーションスタック = 垂直スライス: 各アプリケーションは、インフラストラクチャとランタイムコンポーネントを含む、必要なすべてのリソースを含む自己完結型の「スタック」として定義されます。このスタックは、アプリケーションの環境の単一の信頼できる情報源となり、ドメイン駆動設計(DDD)の「境界付けられたコンテキスト」の概念を反映します。
- 共有モジュラーまたはサービスのためのプラットフォームスタック: 中央EKSクラスターのような共有インフラストラクチャコンポーネントは、別の「プラットフォームスタック」に配置されます。サービスとしてのネットワークを介した共有。アプリケーションスタックは、このプラットフォームスタックに依存し、関心事の明確な分離を作成し、再利用性を促進します。
- 物理性よりも論理的な結束: リソースは、物理的な場所やサービスタイプではなく、アプリケーションとの論理的な関係に基づいてグループ化されます。同じアプリケーションに属するS3バケット、DynamoDBテーブル、およびKubernetesデプロイメントはすべて、アプリケーションスタック内でまとまりのあるユニットとして管理されます。
利点:
- 一貫性の向上:すべてのアプリケーションリソースを単一のスタックで管理することで、構成のずれが減少し、一貫した環境が保証されます。
- 管理性の向上:アプリケーションスタックは、デプロイメント、更新、ロールバックを簡素化し、アプリケーションのライフサイクル管理をより合理化します。
- 明確なアプリケーション所有権:チームはアプリケーションスタック全体を所有および管理でき、自律性と説明責任を促進します。
- 簡素化されたコスト配分:リソースコストは、専用スタックを通じて特定のアプリケーションに簡単に配分されます。
- クラウドネイティブ原則との整合性:疎結合で独立してデプロイ可能なアプリケーションユニットを促進します。
- セキュリティ体制の強化:アプリケーションスタックは、明確なセキュリティ境界を作成し、各アプリケーションの範囲内で詳細な権限管理を可能にすることにより、最小権限アクセス制御の実装を容易にします。
このアプリケーション中心のアプローチは、ドメイン駆動設計(DDD)の哲学と深く共鳴します。DDDが境界付けられたコンテキストとドメインロジックの周りにソフトウェアを編成するのと同様に、アプリケーション中心のインフラストラクチャは、論理的なアプリケーションドメインの周りにクラウドリソースを編成します。この整合性は、明確さ、一貫性、およびインフラストラクチャ管理へのビジネス価値へのより強力な焦点をもたらします。
AWS CDK:インフラストラクチャとランタイム管理の統一
AWS Cloud Development Kit (CDK) は、アプリケーション中心のインフラストラクチャの強力なイネーブラーとして登場します。CDKは、従来のInfrastructure as Codeの複雑さを抽象化し、使い慣れたプログラミング言語を使用して、インフラストラクチャとランタイムオーケストレーションの両方を単一の統一されたコードベースで定義できるようにします。
- 抽象化によるInfrastructure-as-Code: CDKは、ベストプラクティスが組み込まれたAWSリソース(VPC、S3、RDSなど)を定義するための高レベルの構成要素を提供し、インフラストラクチャ定義を簡素化し、定型的な記述を削減します。
- cdk8sによるランタイムオーケストレーション: CDKはcdk8sと統合されており、CDKコード内で直接Kubernetesマニフェストを定義できます。これにより、アプリケーションスタックの一部としてKubernetesリソース(Deployment、Service、Custom Resource)のシームレスな管理が可能になります。
- 統一されたツールとワークフロー: CDKは、インフラストラクチャからランタイムまで、アプリケーションスタック全体を管理するための単一のツールチェーンと一貫した開発者エクスペリエンスを提供します。
- 簡素化された依存関係管理: CDKは依存関係管理を簡素化し、同じスタック内でAWSリソースとKubernetesリソース間の依存関係を定義できるようにします。
- Infrastructure as Secure Code: CDKは、Infrastructure as Codeだけでなく、Infrastructure as Secure Codeでもあります。CDKは、IAMロール、ポリシー、およびセキュリティグループを定義するための構成要素を提供し、セキュリティのベストプラクティスをインフラストラクチャ定義に直接埋め込むことができます。これは、最小権限を実装し、安全なアプリケーションデプロイメントを保証するために不可欠です。
- 詳細な権限管理: CDKにより、アプリケーションスタック内のリソースにきめ細かい権限を付与することが容易になります。各アプリケーションコンポーネントのアクセス要件に正確に一致するIAMロールとポリシーを定義できるため、過剰な権限付与のリスクが最小限に抑えられます。
CDKを使用することで、チームは断片化されたツールやハイブリッドアプローチを超えて、アプリケーションの真に統一されたスタック定義を採用できます。
デプロイメントツールの進化
クラウドインフラストラクチャ管理の状況は、現代のアプリケーションの複雑さの増大と、より効率的で一貫したデプロイメント戦略の必要性によって、大幅な進化を遂げてきました。当初、組織は専門化されたツールの断片化されたエコシステムをナビゲートし、運用上のオーバーヘッドと不整合を引き起こしていました。以下は、クラウドデプロイメントツールの進化を3つの異なるフェーズでたどり、AWS Cloud Development Kit (CDK) に代表される統一スタックアプローチの出現で最高潮に達します。
フェーズ1:断片化されたツール – 専門化とサイロの時代
クラウド導入の初期には、組織はしばしば、それぞれがクラウド環境の特定の側面に対処する、ばらばらで専門化されたツールに依存していました。2つの顕著な例は、AWS CloudFormationとKubernetesであり、それぞれ異なる運用哲学から生まれました。
- AWS CloudFormation:分離されたインフラストラクチャプロビジョニング: CloudFormationは、インフラストラクチャプロビジョニングにおける確実性と一貫性に焦点を当てた、エンジニアリング中心の世界から生まれました。宣言型テンプレートを通じて幅広いAWSリソースを定義およびデプロイすることに優れていました。ただし、Kubernetesリソースへのアプローチはしばしば限定的であり、動的に管理されるエンティティではなく静的なYAML定義として扱っていました。
- Kubernetes:コンテナオーケストレーション、インフラストラクチャに依存しない: Kubernetesは、運用現場から生まれ、動的環境におけるアドホックな運用と緩和策を優先しました。コンテナオーケストレーションに革命をもたらし、基盤となるインフラストラクチャの複雑さを抽象化して、コンテナ化されたアプリケーションを大規模に管理しました。ただし、Kubernetesはネイティブ形式では、ストレージバケットやデータベースなど、クラスター外のクラウドリソースを直接プロビジョニングおよび管理する機能がありませんでした。
結果:ツールチェーンの無秩序な増加と運用上の摩擦
この断片化されたアプローチは、いくつかの課題を引き起こしました。
- ツールチェーンの無秩序な増加: 組織は多様なツールセットを蓄積し、それぞれに専門知識が必要でした。この複雑さにより、トレーニングコストが増加し、全体的な管理が妨げられました。
- 構成のずれ: インフラストラクチャとアプリケーションの構成を別々のシステムで管理すると、必然的に構成のずれが生じました。あるシステムでの変更が他のシステムに自動的に反映されないため、再現やトラブルシューティングが困難な「スノーフレーク」環境が作成されました。
- 運用上のオーバーヘッド: 個別のツールチェーンを運用すると、運用上の複雑さが増しました。異なるシステム間でデプロイメント、更新、監視を調整するには、多大な手作業とカスタムスクリプトが必要であり、エラーや運用上のオーバーヘッドの可能性が高まりました。
- 限定的な全体像: 統合の欠如により、アプリケーションスタック全体の統一された全体像を把握することが困難でした。監視とトラブルシューティングには、多くの場合、さまざまなツールインターフェイス間を移動し、サイロ間でデータを関連付ける必要がありました。
フェーズ2:ハイブリッドアプローチ – 複雑さでギャップを埋める
断片化されたツールの限界を認識し、組織はインフラストラクチャとアプリケーション管理の間のギャップを埋めるためにハイブリッドアプローチを採用し始めました。一般的なパターンは、以下を組み合わせることでした。
- インフラストラクチャ基盤のためのCloudFormation: CloudFormationは、仮想プライベートクラウド(VPC)、コンピューティングリソース、マネージドサービス、さらには基盤となるEKS(Elastic Kubernetes Service)クラスターを含む、基盤となるインフラストラクチャのプロビジョニングに引き続き使用されました。
- アプリケーションデプロイメントのためのKubernetesネイティブツール: CloudFormationによってプロビジョニングされたKubernetesクラスター内で、組織はアプリケーションライフサイクル管理のためにKubernetesネイティブツールを採用しました。
- Helm:Kubernetes内でアプリケーションをチャートとしてパッケージ化、テンプレート化、デプロイするため。
- GitOpsツール(Argo CD、Flux):Gitを信頼できる情報源として使用し、Kubernetes内で継続的デリバリーと宣言的アプリケーション構成管理を実装するため。
ハイブリッドアプローチの限界:
ハイブリッドアプローチは完全に断片化されたツールよりも改善をもたらしましたが、新たな複雑さを導入しました。
- パラダイムの不整合(IaC vs. GitOps): ハイブリッドモデルは、多くの場合、Infrastructure-as-Code(IaC)の原則とGitOpsプラクティスを並置しました。CloudFormationテンプレートは宣言的でインフラストラクチャ中心のアプローチを具現化しましたが、GitOpsはKubernetes内のアプリケーションデプロイメントに焦点を当てた別の宣言的モデルを導入しました。これらの異なる宣言的システムを管理および調整することは、抽象化の層と潜在的な混乱を追加しました。
- 複数システムの専門知識の継続的な必要性: 統合の取り組みにもかかわらず、チームは依然としてCloudFormationとKubernetesエコシステムの両方の専門知識を必要としていました。これにはより広範なスキルセットが必要であり、組織内の知識サイロにつながる可能性がありました。
- 複雑なロールバックと監査: 包括的なロールバックの実行や徹底的な監査の実施は、より複雑になりました。アプリケーションスタック全体をロールバックするには、CloudFormation(インフラストラクチャの変更用)とKubernetesツール(アプリケーションのデプロイメント用)の両方で調整されたロールバックが必要になる場合があり、多くの場合、カスタムスクリプトと手動オーケストレーションが必要でした。これらの異なるシステム間で変更を監査することは依然として課題でした。
フェーズ3:CDKによる統一スタック – インフラストラクチャとランタイムの収束
現在の進化は、インフラストラクチャとランタイム管理が単一のまとまりのあるコードベースに収束する、統一スタックアプローチを示しています。AWS Cloud Development Kit (CDK) はこのフェーズ3を例示しており、基盤となるインフラストラクチャからランタイムオーケストレーションまで、アプリケーションスタック全体を単一の開発者フレンドリーな環境内で定義および管理するための強力なフレームワークを提供します。
AWS CDK:インフラストラクチャとランタイム管理の統一
AWS CDKはAWS CloudFormationの上にある抽象化レイヤーとして機能しますが、開発エクスペリエンスを根本的に変えます。
- プログラミング言語によるInfrastructure-as-Code: CDKにより、開発者はTypeScript、Python、Java、Goなどの使い慣れたプログラミング言語を使用してAWSインフラストラクチャを定義できます。これにより、冗長なJSON/YAMLテンプレートから脱却し、ループ、条件分岐、関数、オブジェクト指向の原則など、インフラストラクチャ定義のためのプログラミング構成要素の力を活用できます。
- 高レベルの抽象化(コンストラクト): CDKは、ベストプラクティスが組み込まれた事前構築済みの再利用可能なコンポーネントであるコンストラクトの豊富なライブラリを提供します。これらのコンストラクトは、VPC、S3バケット、データベース、さらにはEKSクラスターなどの複雑なリソースの定義を簡素化し、定型的な記述を削減し、一貫性を促進します。
- cdk8s統合によるランタイムオーケストレーション: CDKはcdk8s(Cloud Development Kit for Kubernetes)とシームレスに統合されており、開発者は同じプログラミング言語と抽象化を使用して、CDKコード内で直接Kubernetesマニフェストを定義できます。これにより、単一のスタック定義内でAWSクラウドリソースとKubernetesリソースの両方を統一的に管理できます。
- 統一されたツールとワークフロー: CDKは、アプリケーションスタック全体の開発、デプロイ、管理のための統一されたコマンドラインインターフェイス(CDK CLI)とワークフローを提供します。開発者は、単一のツールチェーンとプログラミング言語を使用して、インフラストラクチャプロビジョニングとアプリケーションランタイムオーケストレーションの両方を処理できます。
CDKによる統一スタックの利点:
- 運用の簡素化:単一の統一されたコードベースを管理することで、運用が簡素化されます。インフラストラクチャとアプリケーションの構成が一緒に管理されるため、デプロイメント、更新、ロールバックがより合理化され、アトミックになります。
- 一貫性の向上とドリフトの削減:インフラストラクチャとランタイム構成の両方を同じコードベース内で定義することで、本質的に一貫性が促進され、構成ドリフトが最小限に抑えられます。インフラストラクチャとアプリケーションへの変更はバージョン管理され、一緒にデプロイされるため、よりまとまりのある予測可能な環境が保証されます。
- 開発者エクスペリエンスと生産性の向上:使い慣れたプログラミング言語、高レベルのコンストラクト、および統一されたツールチェーンを使用することで、開発者エクスペリエンスが大幅に向上します。CDKにより、インフラストラクチャ定義がよりアクセスしやすく、楽しく、効率的になり、開発者の生産性が向上し、エラーが削減されます。
- 堅牢な依存関係管理:CloudFormation上に構築されたCDKは、その堅牢な依存関係管理機能を継承します。開発者は、スタック内のすべてのリソース(AWSインフラストラクチャとKubernetesリソースの両方)間の依存関係を定義でき、適切な作成と更新の順序を保証します。
- 合理化された監査とロールバック:統一スタックにより、監査とロールバックが簡素化されます。変更はCDKコードのバージョン管理で追跡され、明確な監査証跡が提供されます。ロールバックはスタックレベルで実行でき、インフラストラクチャとアプリケーション構成の両方を調整された方法で元に戻すことができます。
- アプリケーション中心のインフラストラクチャに向けて:CDKは、アプリケーション中心のインフラストラクチャ設計を容易にします。アプリケーションを、密結合されたすべてのリソース(インフラストラクチャとランタイムコンポーネント)を含む全体的なユニットとして定義することにより、組織はより優れたアプリケーション所有権、分離、および管理性を実現できます。
(注:以下は特定の実装ノートまたはリンクのようです)
https://github.com/ondemandenv/odmd-eks/.../simple-k8s-manifest.ts#L10
この単一のスタックは、EKSクラスター内外のすべてのリソースのライフサイクルと依存関係を管理し、必要なすべてのリソース(インフラストラクチャとランタイムコンポーネント)を含む自己完結型の「スタック」にします。このスタックは、アプリケーションの環境の単一の信頼できる情報源となり、ドメイン駆動設計(DDD)の「境界付けられたコンテキスト」の概念を反映します。
AWS CloudFormationは、スタック内のすべてのリソース間の依存関係を維持し、トランザクション内で順序どおりにデプロイおよびロールバックされるようにします。
これは実際のコードであり、次のようなパラメータ化によるわずかなコーディング抽象化が行われています。
//what branch I am on
const br = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
//configuration based on branch
const imgAndVer = StringParameter.valueForStringParameter(this, '/my-app/' + br );
これにより、異なるブランチ上の同一のコードが、複数の環境(ブランチ指定の構成値を持つ同一のロジック/機能マニフェスト)に対して生成およびデプロイされ、さらなる実験、発見、テスト、または本番環境での高い一貫性、ブランチによるコード比較、および単体テストが可能になり、GitOpsを凌駕します!
上記はhttps://ondemandenv.devの根本的な哲学であり、もう1つの抽象化レイヤーをサポートしています。つまり、複数のアカウント間でVPCを接続し、各アカウントが動的な値/トークン解決を使用してプライベートサブネット経由でk8sマニフェストをデプロイできるようにします。