코드형 인프라: 플랫폼의 기초
L'코드형 인프라(IaC) 인프라가 제공되는 원리 코드가 아닌 선언적 또는 명령형 코드를 통해 정의, 버전화 및 관리됩니다. 수동 구성. 플랫폼 엔지니어링의 맥락에서 IaC는 단순한 모범 사례가 아닙니다. 반복 가능하고 확장 가능하며 감사 가능한 IDP를 구축하기 위한 기본 요구 사항입니다.
이 기사에서는 두 가지 주요 접근 방식을 비교할 것입니다. 테라폼 (선언적) 전자 풀루미 (범용 언어에서는 필수) - 구현 방법을 살펴보겠습니다. 코드로서의 정책 OPA 및 Sentinel을 통해 규정 준수 및 자동화된 보안을 보장합니다.
무엇을 배울 것인가
- IaC 패러다임: 선언적(Terraform/HCL) 대 명령적(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의 가장 중요한 측면 중 하나입니다. 상태 파일 코드에 정의된 리소스와 클라우드의 실제 리소스 간의 매핑을 포함합니다. 관리 상태 정오표는 표류, 충돌, 심지어 자원 손실로 이어질 수 있습니다.
- 원격 상태: 팀 구성원 간에 공유하려면 상태를 원격 백엔드(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 성숙한 IDP에 필수적입니다. 가장 효과적인 패턴은 PR 기반 워크플로우: 인프라 변경 사항 병합 전에 자동으로 검증되는 Pull Request를 통해 발생합니다.
- 아틀란티스: Pull Request 시 Terraform 워크플로를 자동화하는 도구(자동 계획, 승인 후 적용)
- 우주 리프트: 정책, 드리프트 감지, 모듈 레지스트리를 갖춘 IaC 관리용 SaaS 플랫폼
- 환경0: IaC 환경에 거버넌스, 비용, TTL을 추가하는 플랫폼
PR 기반 워크플로우의 장점은 추적성 완료: 모든 변경 사항 인프라에 적용하고 검토, 의견 및 승인을 통해 PR에 문서화합니다. 이는 다음을 만족합니다. 자연스러운 방식으로 감사 및 규정 준수 요구 사항을 충족합니다.
마이그레이션 전략
기존 인프라(수동 또는 임시 스크립트를 사용하여 생성)를 IaC로 마이그레이션 계획과 점진적화가 필요한 프로세스:
- 1단계 - 가져오기: 기존 리소스를 수정하지 않고 Terraform 상태로 가져옵니다.
- 2단계 - 코드화: 가져온 리소스를 설명하는 IaC 코드를 작성하여 계획에 변경 사항이 표시되지 않는지 확인합니다.
- 3단계 - 표준화: 공유 모듈 및 명명 규칙을 향한 점진적인 리팩토링
- 4단계 - 자동화: 자동 적용 및 정책 시행을 위한 CI/CD 통합
이주협의회
모든 인프라를 한꺼번에 마이그레이션하려고 하지 마십시오. 가장 간단한 구성요소부터 시작하세요. 위험도가 낮고(S3 버킷, DNS 레코드, IAM 정책) 경험과 자신감을 얻습니다. 그런 다음 가장 중요한 리소스(데이터베이스, Kubernetes 클러스터, 네트워킹)를 진행합니다.







