コードとしてのインフラストラクチャ: プラットフォームの基盤
L'コードとしてのインフラストラクチャ (IaC) そしてインフラストラクチャーの原理 宣言型または命令型コードを通じてではなく、定義、バージョン管理、および管理を行う 手動構成。プラットフォーム エンジニアリングの文脈では、IaC は単なるベスト プラクティスではありません。 そして、再現可能、拡張可能、監査可能な IDP を構築するための基本的な要件です。
この記事では、2 つの主要なアプローチを比較します。 テラフォーム (宣言的) e プルミ (汎用言語では必須) - そして実装方法を検討します コードとしてのポリシー OPA と Sentinel を使用して、コンプライアンスと自動化されたセキュリティを確保します。
何を学ぶか
- IaC パラダイム: 宣言型 (Terraform/HCL) vs 命令型 (Pulumi/TypeScript)
- 状態管理: リモート状態、ロック、災害復旧
- 再利用可能な Terraform モジュールと構成
- Pulumi: TypeScript、Python、Go を使用した IaC
- コードとしてのポリシー: コンプライアンスのための OPA/Rego と Terraform Cloud のための Sentinel
- 既存のインフラストラクチャの IaC に向けた移行戦略
Terraform: 宣言的アプローチ
テラフォーム HashiCorp による、世界で最も人気のある IaC ツールです。を使用します。 と呼ばれる宣言型言語 HCL (HashiCorp 構成言語) のために インフラストラクチャの望ましい状態を説明します。 Terraform は望ましい状態を比較します 現在の状態を照合し、目標構成を達成するための実行計画を計算します。
Terraform の強みは次のとおりです。
- プロバイダーエコシステム: 数百のクラウドおよび SaaS プロバイダー (AWS、Azure、GCP、Kubernetes、GitHub、Datadog など) をサポート
- 申請前に計画を立てる: 変更を実行する前に表示し、エラーのリスクを軽減します。
- 状態管理: インフラストラクチャの実際の状態を追跡して、増分更新を処理します。
- フォーム: 複雑な構成をカプセル化する再利用可能なコンポーネント
# Terraform: modulo riutilizzabile per microservice infrastructure
# modules/microservice-infra/main.tf
variable "service_name" {
type = string
description = "Nome del microservizio"
}
variable "environment" {
type = string
description = "Environment (dev, staging, production)"
}
variable "cpu_limit" {
type = string
default = "500m"
}
variable "memory_limit" {
type = string
default = "512Mi"
}
# Kubernetes namespace con labels standard
resource "kubernetes_namespace" "service" {
metadata {
name = "${var.service_name}-${var.environment}"
labels = {
"app.kubernetes.io/name" = var.service_name
"app.kubernetes.io/env" = var.environment
"platform.company.io/managed" = "true"
}
}
}
# Database PostgreSQL (RDS)
resource "aws_db_instance" "database" {
identifier = "${var.service_name}-${var.environment}"
engine = "postgres"
engine_version = "15.4"
instance_class = var.environment == "production" ? "db.r6g.large" : "db.t3.micro"
allocated_storage = 20
max_allocated_storage = var.environment == "production" ? 100 : 50
storage_encrypted = true
db_name = replace(var.service_name, "-", "_")
username = "app_user"
password = random_password.db_password.result
backup_retention_period = var.environment == "production" ? 30 : 7
deletion_protection = var.environment == "production"
tags = {
Service = var.service_name
Environment = var.environment
ManagedBy = "terraform"
}
}
# Redis cache (ElastiCache)
resource "aws_elasticache_cluster" "cache" {
cluster_id = "${var.service_name}-${var.environment}"
engine = "redis"
node_type = var.environment == "production" ? "cache.r6g.large" : "cache.t3.micro"
num_cache_nodes = 1
parameter_group_name = "default.redis7"
port = 6379
}
output "namespace" {
value = kubernetes_namespace.service.metadata[0].name
}
output "database_endpoint" {
value = aws_db_instance.database.endpoint
}
output "cache_endpoint" {
value = aws_elasticache_cluster.cache.cache_nodes[0].address
}
Pulumi: 汎用言語を使用した IaC
プルミ は別のアプローチを採用しています。専用言語 (HCL など) の代わりに、 などの標準プログラミング言語を使用してインフラストラクチャを定義できます。 TypeScript、Python、Go、C#、Java。これは、構造体にアクセスできることを意味します ループ、条件文、関数、クラス、選択した言語のライブラリのエコシステム全体など。
プルミの利点は次のとおりです。
- 使い慣れた言語: 新しい言語を学ぶ必要はありません。チームがすでに知っているものを使用する
- ネイティブテスト: 標準テストフレームワークを使用したインフラストラクチャの単体テストおよび統合テスト
- 強力な抽象化: 複雑な IaC コンポーネントを作成するためのクラス、インターフェイス、および構成
- IDEのサポート: オートコンプリート、型チェック、言語ツールによるリファクタリング
// Pulumi: componente riutilizzabile in TypeScript
// microservice-infra.ts
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as k8s from "@pulumi/kubernetes";
interface MicroserviceInfraArgs {
serviceName: string;
environment: string;
cpuLimit?: string;
memoryLimit?: string;
enableDatabase?: boolean;
enableCache?: boolean;
}
export class MicroserviceInfra extends pulumi.ComponentResource {
public readonly namespace: k8s.core.v1.Namespace;
public readonly databaseEndpoint?: pulumi.Output<string>;
public readonly cacheEndpoint?: pulumi.Output<string>;
constructor(
name: string,
args: MicroserviceInfraArgs,
opts?: pulumi.ComponentResourceOptions
) {
super("company:platform:MicroserviceInfra", name, {}, opts);
const isProd = args.environment === "production";
// Kubernetes namespace
this.namespace = new k8s.core.v1.Namespace(
`${args.serviceName}-ns`,
{
metadata: {
name: `${args.serviceName}-${args.environment}`,
labels: {
"app.kubernetes.io/name": args.serviceName,
"app.kubernetes.io/env": args.environment,
"platform.company.io/managed": "true",
},
},
},
{ parent: this }
);
// Database condizionale
if (args.enableDatabase !== false) {
const db = new aws.rds.Instance(
`${args.serviceName}-db`,
{
identifier: `${args.serviceName}-${args.environment}`,
engine: "postgres",
engineVersion: "15.4",
instanceClass: isProd ? "db.r6g.large" : "db.t3.micro",
allocatedStorage: 20,
storageEncrypted: true,
deletionProtection: isProd,
},
{ parent: this }
);
this.databaseEndpoint = db.endpoint;
}
this.registerOutputs({
namespaceName: this.namespace.metadata.name,
});
}
}
状態管理
の管理 滞在する これは IaC の最も重要な側面の 1 つです。状態ファイル コードで定義されたリソースとクラウド内の実際のリソースの間のマッピングが含まれます。経営者 状態のエラッタは、ドリフト、競合、さらにはリソースの損失につながる可能性があります。
- リモート状態: チーム メンバー間で共有するには、状態をリモート バックエンド (S3、GCS、Azure Blob、Terraform Cloud) に保存する必要があります
- ロック中です: 同時変更を防ぐためのロック機構 (AWS の場合は DynamoDB、GCP の場合は GCS)
- 状態の暗号化: 状態には機密情報が含まれているため、保存中および転送中は暗号化する必要があります
- 災害復旧: バケットでバージョニングが有効になっている通常の状態バックアップ
基本ルール
状態ファイルを Git リポジトリにコミットしないでください。 状態には情報が含まれています 機密情報 (パスワード、接続文字列、キー) があり、バックエンド経由で排他的に管理する必要がある 適切な暗号化とアクセス制御を備えたリモート。
OPA と Sentinel を使用したコードとしてのポリシー
コードとしてのポリシー 組織ポリシーをコードとして定義する原則 バージョン管理されており、テスト可能であり、自動的に適用可能です。 IaC コンテキストでは、ポリシーは検証します 定義されたインフラストラクチャがセキュリティ、コンプライアンス、コストの要件を最初に満たしていること 展開の様子。
- OPA (オープン ポリシー エージェント): Rego 言語を使用した汎用ポリシー エンジン。 Terraform プラン、Kubernetes マニフェスト、API リクエストを検証できます
- センチネル: HashiCorp ポリシー フレームワークが Terraform Cloud/Enterprise に統合されました。インフラストラクチャポリシーに最適化された専用言語を使用する
- カイベルノ: YAML を使用してポリシーを定義するネイティブ Kubernetes ポリシー エンジン (K8s 固有のユースケースでは OPA よりもシンプル)
# OPA/Rego: policy per validare Terraform plans
# policy/terraform/mandatory_tags.rego
package terraform.mandatory_tags
import rego.v1
# Tutti i resource devono avere i tag obbligatori
mandatory_tags := ["Environment", "Service", "ManagedBy", "Team"]
# Trova risorse senza tag obbligatori
deny contains msg if {
resource := input.planned_values.root_module.resources[_]
tags := object.get(resource.values, "tags", {})
required_tag := mandatory_tags[_]
not tags[required_tag]
msg := sprintf(
"Resource '%s' manca il tag obbligatorio '%s'",
[resource.address, required_tag]
)
}
# Database in produzione deve avere encryption abilitata
deny contains msg if {
resource := input.planned_values.root_module.resources[_]
resource.type == "aws_db_instance"
resource.values.storage_encrypted != true
msg := sprintf(
"Database '%s' deve avere storage_encrypted = true",
[resource.address]
)
}
# Nessuna risorsa pubblica senza approvazione
deny contains msg if {
resource := input.planned_values.root_module.resources[_]
resource.type == "aws_s3_bucket"
acl := object.get(resource.values, "acl", "private")
acl == "public-read"
msg := sprintf(
"S3 bucket '%s' non può essere pubblico senza approvazione",
[resource.address]
)
}
GitOps と PR ベースのワークフロー
IaC とワークフローの統合 GitOps そして成熟した国内避難民にとって不可欠です。 最も効果的なパターンは、 PRベースのワークフロー: インフラストラクチャへの変更 プル リクエストを介して発生し、マージ前に自動的に検証されます。
- アトランティス: プル リクエストの Terraform ワークフローを自動化するツール (自動計画、承認後に適用)
- スペースリフト: ポリシー、ドリフト検出、モジュール レジストリを備えた IaC 管理のための SaaS プラットフォーム
- 環境0: IaC 環境にガバナンス、コスト、TTL を追加するプラットフォーム
PR ベースのワークフローの利点は次のとおりです。 トレーサビリティ 完了: すべての変更 をインフラストラクチャに追加し、レビュー、コメント、承認とともに PR に文書化します。これは満足です 監査とコンプライアンスの要件を自然な方法で実現します。
移行戦略
既存のインフラストラクチャ (手動またはアドホック スクリプトで作成) を IaC に移行する そして、計画と段階的なプロセスが必要です。
- フェーズ 1 - インポート: 既存のリソースを変更せずに Terraform 状態にインポートします。
- ステップ 2 - コード化する: インポートされたリソースを記述する IaC コードを作成し、計画に変更がないことを確認します。
- フェーズ 3 - 標準化: 共有モジュールと命名規則に向けた進歩的なリファクタリング
- ステップ 4 - 自動化する: 自動適用とポリシー適用のための CI/CD との統合
移住評議会
すべてのインフラストラクチャを一度に移行しようとしないでください。最も単純なコンポーネントから始める 低リスク (S3 バケット、DNS レコード、IAM ポリシー) で経験と自信を獲得し、 次に、最も重要なリソース (データベース、Kubernetes クラスター、ネットワーキング) に進みます。







