ai

Pulumi IaC Best Practices ที่ต้องรู้ —

Pulumi IaC Best Practices ที่ต้องรู้ —

Pulumi Best Practices

Pulumi IaC Best Practices ที่ต้องรู้ —

Pulumi IaC Best Practices Project Structure State Management Testing Secrets Policy as Code CrossGuard CI/CD Production Deployment

PracticeLevelImpactEffortPriority
Project StructureFoundationสูง — Maintainabilityต่ำP0 ทำทันที
State ManagementFoundationสูง — Reliabilityต่ำP0 ทำทันที
Secret ManagementSecurityสูง — SecurityกลางP0 ทำทันที
Policy as CodeGovernanceสูง — ComplianceกลางP1 สัปดาห์แรก
TestingQualityสูง — ConfidenceสูงP1 สัปดาห์แรก
CI/CD IntegrationAutomationสูง — VelocityกลางP1 สัปดาห์แรก

Project Structure

=== Pulumi Project Structure ===

infrastructure/

├── Pulumi.yaml # Project definition

├── Pulumi.dev.yaml # Dev stack config

├── Pulumi.staging.yaml # Staging stack config

├── Pulumi.prod.yaml # Production stack config

├── __main__.py # Entry point

├── config.py # Config loader

├── components/

│ ├── network.py # VPC, Subnets, SG

│ ├── compute.py # EC2, ECS, Lambda

│ ├── database.py # RDS, DynamoDB

│ ├── monitoring.py # CloudWatch, Alerts

│ └── cdn.py # CloudFront, S3

└── tests/

├── test_network.py

├── test_compute.py

└── test_policy.py

__main__.py

import pulumi

from config import get_config

from components.network import NetworkStack

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน brad garlinghouse — ข้อมูลครบถ้วน 2026

from components.compute import ComputeStack

from components.database import DatabaseStack

config = get_config()

network = NetworkStack("network", config)

database = DatabaseStack("database", config, network)

compute = ComputeStack("compute", config, network, database)

pulumi.export("vpc_id", network.vpc.id)

แนะนำเพิ่มเติม — ติดตาม XM Signal

pulumi.export("api_url", compute.api_url)

ComponentResource Example

class NetworkStack(pulumi.ComponentResource):

def __init__(self, name, config, opts=None):

super().__init__("custom:infra:Network", name, None, opts)

self.vpc = aws.ec2.Vpc(f"{name}-vpc",

cidr_block=config["vpc_cidr"],

enable_dns_hostnames=True,

tags={"Name": f"{name}-vpc", "Environment": config["env"]},

opts=pulumi.ResourceOptions(parent=self))

self.register_outputs({"vpc_id": self.vpc.id})

from dataclasses import dataclass

@dataclass

class StackConfig:

stack: str

env: str

instance_type: str

min_size: int

เนื้อหาเกี่ยวข้อง — ทำความเข้าใจ Elasticsearch OpenSearch CQRS Event Sourcing

max_size: int

db_instance: str

multi_az: bool

configs = [

StackConfig("dev", "development", "t3.small", 1, 2, "db.t3.micro", False),

StackConfig("staging", "staging", "t3.medium", 2, 4, "db.t3.small", False),

StackConfig("prod", "production", "t3.large", 3, 10, "db.r6g.large", True),

]

print("=== Stack Configurations ===")

for c in configs:

print(f" [{c.stack}] Env: {c.env}")

print(f" Instance: {c.instance_type} | Scale: {c.min_size}-{c.max_size}")

print(f" DB: {c.db_instance} | Multi-AZ: {c.multi_az}")

Testing Infrastructure

=== Pulumi Testing ===

แนะนำเพิ่มเติม — หนังสือเทรดที่ SiamCafeBook

Unit Test with Mocks (pytest)

import pulumi

import pytest

class MyMocks(pulumi.runtime.Mocks):

def new_resource(self, args):

return [args.name + "_id", args.inputs]

def call(self, args):

return {}

pulumi.runtime.set_mocks(MyMocks())

from components.network import NetworkStack

@pulumi.runtime.test

def test_vpc_has_tags():

def check_tags(args):

tags = args[0]

assert "Environment" in tags

เนื้อหาเกี่ยวข้อง — Web Components Agile Scrum Kanban

assert "Name" in tags

config = {"vpc_cidr": "10.0.0.0/16", "env": "test"}

network = NetworkStack("test", config)

pulumi.Output.all(network.vpc.tags).apply(check_tags)

@pulumi.runtime.test

def test_vpc_cidr():

Pulumi IaC Best Practices ที่ต้องรู้ —

def check_cidr(cidr):

assert cidr == "10.0.0.0/16"

config = {"vpc_cidr": "10.0.0.0/16", "env": "test"}

network = NetworkStack("test", config)

network.vpc.cidr_block.apply(check_cidr)

Policy as Code (CrossGuard)

from pulumi_policy import PolicyPack, ResourceValidationPolicy

def no_public_s3(args, report_violation):

if args.resource_type == "aws:s3/bucket:Bucket":

acl = args.props.get("acl")

if acl == "public-read" or acl == "public-read-write":

report_violation("S3 buckets must not be public")

def require_encryption(args, report_violation):

if args.resource_type == "aws:s3/bucket:Bucket":

encryption = args.props.get("serverSideEncryptionConfiguration")

if not encryption:

report_violation("S3 buckets must have encryption enabled")

PolicyPack("security-policies", policies=[

ResourceValidationPolicy(name="no-public-s3", validate=no_public_s3),

ResourceValidationPolicy(name="require-encryption", validate=require_encryption),

])

@dataclass

class TestType:

test: str

tool: str

เนื้อหาเกี่ยวข้อง — แนะนำให้อ่าน แทง คืออะไร — คำศัพท์และความหมายในบริบทต่างๆ 2026

what: str

when: str

example: str

tests = [

TestType("Unit Test", "pytest + Mocks", "Resource properties, tags, config",

"Every PR", "VPC has correct CIDR, tags present"),

TestType("Property Test", "CrossGuard", "Security policies, compliance",

"Every preview/up", "No public S3, encryption required"),

TestType("Integration Test", "pytest + real provider", "Full stack deployment",

"Nightly", "Deploy to test account, verify connectivity"),

TestType("Preview Test", "pulumi preview", "Change detection, drift",

"Every PR", "No unexpected destroys, correct changes"),

TestType("Cost Test", "Infracost + Pulumi", "Cost estimation before deploy",

"Every PR", "Monthly cost < $5000 for staging"),

]

print("\n=== Testing Strategy ===")

for t in tests:

print(f" [{t.test}] Tool: {t.tool}")

print(f" What: {t.what}")

print(f" When: {t.when}")

print(f" Example: {t.example}")

CI/CD and Operations

# === GitHub Actions CI/CD ===

# .github/workflows/pulumi.yml
# name: Pulumi IaC
# on:
#   pull_request:
#     paths: ['infrastructure/**']
#   push:
#     branches: [main]
#     paths: ['infrastructure/**']
#
# jobs:
#   preview:
#     if: github.event_name == 'pull_request'
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - uses: actions/setup-python@v5
#         with: { python-version: '3.11' }
#       - run: pip install -r infrastructure/requirements.txt
#       - uses: pulumi/actions@v5
#         with:
#           command: preview
#           stack-name: dev
#           work-dir: infrastructure
#           comment-on-pr: true
#         env:
#           PULUMI_ACCESS_TOKEN: }
#
#   deploy:
#     if: github.ref == 'refs/heads/main'
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v4
#       - uses: pulumi/actions@v5
#         with:
#           command: up
#           stack-name: prod
#           work-dir: infrastructure
#         env:
#           PULUMI_ACCESS_TOKEN: }

@dataclass
class BestPractice:
    category: str
    practice: str
    why: str
    how: str

practices = [
    BestPractice("Structure", "Use ComponentResource for modules",
        "Reusable, testable, organized",
        "class MyComponent(pulumi.ComponentResource)"),
    BestPractice("State", "Use remote backend (Pulumi Cloud/S3)",
        "Team collaboration, backup, locking",
        "pulumi login s3://my-state-bucket"),
    BestPractice("Secrets", "Never hardcode secrets",
        "Security compliance",
        "pulumi config set --secret dbPassword"),
    BestPractice("Tags", "Tag all resources consistently",
        "Cost tracking, ownership, compliance",
        "Default tags via transformations"),
    BestPractice("Naming", "Use consistent naming convention",
        "Readability, searchability",
        "{project}-{env}-{component}-{resource}"),
    BestPractice("Review", "Preview before every deploy",
        "Prevent accidents, catch drift",
        "pulumi preview in CI, comment on PR"),
    BestPractice("Policy", "Enforce policies with CrossGuard",
        "Compliance, security guardrails",
        "PolicyPack with required rules"),
    BestPractice("Import", "Import existing resources",
        "Migrate to IaC without recreating",
        "pulumi import aws:ec2/instance:Instance myvm i-xxx"),
]

print("Best Practices:")
for p in practices:
    print(f"  [{p.category}] {p.practice}")
    print(f"    Why: {p.why}")
    print(f"    How: {p.how}")

เคล็ดลับ

  • Component: สร้าง ComponentResource สำหรับทุก Module ที่ใช้ซ้ำ
  • Preview: รัน pulumi preview ทุกครั้งก่อน up ตรวจ Changes
  • Stack: แยก Stack ตาม Environment ใช้ Config แยกกัน
  • Import: ใช้ pulumi import นำ Resource เดิมเข้า IaC ไม่ต้องสร้างใหม่
  • Automation: ใช้ Automation API สำหรับ CI/CD ที่ซับซ้อน

Pulumi คืออะไร

IaC Platform Python TypeScript Go C# Java AWS Azure GCP Kubernetes State Management Policy CrossGuard Automation API Open Source Free Tier

XM Legend · เทรดเดอร์ & ผู้สอน Forex 13 ปี

ผู้ก่อตั้ง SiamCafe ตั้งแต่ปี 1997 · เทรดเดอร์สาย Forex มากกว่า 13 ปี ได้รับการยกย่องเป็น XM Legend · แบ่งปันความรู้ Forex, ไอที, AI และการเทรด จากประสบการณ์จริงในตลาดจริง