הגדרת Pulumi לתשתית כקוד
מצב טיפוסי: יש לך פרויקט TypeScript, DevOps מבקש ממך ללמוד HCL עבור Terraform, ואתה כותב legacy כבר שישה חודשים. עברנו את זה: בסטארטאפ, במהלך מיגרציה רב-אזורית, קוד ה-Terraform גדל ל-500+ שורות, בעוד Pulumi הרכיב את אותה תשתית ב-150 שורות של TypeScript — פי שלושה פחות קוד עם פונקציונליות מלאה. המקרה הזה הוא אחד מ-10+ פרויקטים שבהם יישמנו Pulumi. בממוצע, צוותים מבלים שבועיים בכתיבת מודולי Terraform עבור אפליקציית web טיפוסית; עם Pulumi, זה לוקח 5 ימים. Pulumi אינו דורש למידת HCL, מוריד את החסם למפתחים וחוסך בתקציב.
אילו בעיות Pulumi פותר?
- לוגיקה מורכבת וקונפיגורציות דינמיות. Terraform עם HCL מתקשה ביצירת משאבים על סמך נתונים חיצוניים. לדוגמה, יצירת 20 דליים של S3 עם מדיניות שונה מקובץ CSV. ב-HCL — לולאה מייגעת עם count; ב-Pulumi ב-TypeScript — map יחיד עם forEach, שמקטין את הקוד פי 5.
- שימוש חוזר בקוד. ב-HCL — מודולים; ב-Pulumi — חבילות npm. אתה מחלץ תבניות נפוצות (VPC, cluster, service) לספרייה ומייבא אותה כתלות רגילה. זה מפחית כפילויות ומאיץ פיתוח ב-30%.
- ניפוי באגים ובדיקות. Pulumi משתמש באותם כלים כמו הפיתוח: מהדר TypeScript, linter, בדיקות יחידה. שגיאות טיפוס נתפסות בזמן קומפילציה, לא בייצור. זה מפחית את זמן ניפוי הבאגים ב-30% ומוריד עלויות תחזוקה.
למה Pulumi עדיף על Terraform?
Pulumi מהיר פי 3 בפיתוח בזכות שפות מוכרות. אתה משתמש במהדר TypeScript וב-Jest לבדיקות, לא רק ב-terraform plan. שגיאות טיפוס נתפסות בזמן קומפילציה, לא בייצור. Pulumi גם זול יותר לתפעול: אין צורך בכלים נוספים לניהול state. כפי שנכתב בתיעוד של Pulumi: "Pulumi משתמש בשפות תכנות מוכרות כדי להגדיר ולנהל משאבי ענן."
איך אנחנו עושים את זה: מקרה אמיתי
פרויקט: אפליקציית web על AWS עם RDS PostgreSQL 16, ECS Fargate, ו-CI/CD דרך GitHub Actions. בעבר, 4 מפתחים תחזקו קוד Terraform; כל שינוי לקח יומיים. עברנו ל-Pulumi תוך שבוע, והפחתנו את עלויות ניהול התשתית ב-$15,000 בשנה. ה-stack כלל 3 שירותי ECS, 2 מאזני עומס ליישומים, 4 קבוצות אבטחה, ו-2 סודות ב-parameter store.
Stack: TypeScript, Pulumi v3, ספק AWS v6, PostgreSQL 16, ECS עם Fargate. השתמשנו ב-2 Availability Zones, 100 GB SSD gp3, 256 יחידות CPU, 512 MB זיכרון, 3 משימות לכל שירות.
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const dbPassword = config.requireSecret("dbPassword");
const vpc = new awsx.ec2.Vpc("myapp-vpc", {
numberOfAvailabilityZones: 2,
enableDnsHostnames: true,
});
const cluster = new aws.ecs.Cluster("myapp-cluster", {
settings: [
{
name: "containerInsights",
value: "enabled",
},
],
});
const db = new aws.rds.Instance("myapp-db", {
engine: "postgres",
engineVersion: "16.1",
instanceClass: aws.rds.InstanceType.T3_Medium,
allocatedStorage: 100,
dbName: "myapp",
username: "myapp",
password: dbPassword,
skipFinalSnapshot: !pulumi.getStack().startsWith("prod"),
vpcSecurityGroupIds: [dbSg.id],
dbSubnetGroupName: dbSubnetGroup.name,
storageEncrypted: true,
});
const service = new awsx.ecs.FargateService("myapp-web", {
cluster: cluster.arn,
taskDefinitionArgs: {
container: {
name: "web",
image: "registry.example.com/myapp:latest",
cpu: 256,
memory: 512,
essential: true,
portMappings: [
{
containerPort: 8080,
},
],
environment: [
{
name: "APP_ENV",
value: "production",
},
{
name: "DB_HOST",
value: db.endpoint,
},
],
secrets: [
{
name: "DB_PASSWORD",
valueFrom: dbPasswordSecret.arn,
},
],
},
},
desiredCount: 3,
loadBalancers: [
{
targetGroupArn: targetGroup.arn,
containerName: "web",
containerPort: 8080,
},
],
});
export const dbEndpoint = db.endpoint;
export const serviceUrl = pulumi.interpolate`https://${loadBalancer.dnsName}`;
לאחר המיגרציה, מהירות הפריסה עלתה ב-40%, השגיאות צומצמו בחצי, ומפתח חדש נקלט תוך יום.
תהליך העבודה
- ניתוח — ביקורת על התשתית הקיימת, בחירת ספק (AWS, GCP, Azure).
- עיצוב — ארכיטקטורת stack (dev/staging/prod), אינטגרציית CI/CD.
- יישום — כתיבת קוד ב-TypeScript/Python, הגדרת stack.
- בדיקות —
import * as aws from "@pulumi/aws"; import * as awsx from "@pulumi/awsx"; import * as pulumi from "@pulumi/pulumi"; const config = new pulumi.Config(); const dbPassword = config.requireSecret("dbPassword"); const vpc = new awsx.ec2.Vpc("myapp-vpc", { numberOfAvailabilityZones: 2, enableDnsHostnames: true, }); const cluster = new aws.ecs.Cluster("myapp-cluster", { settings: [{ name: "containerInsights", value: "enabled" }], }); const db = new aws.rds.Instance("myapp-db", { engine: "postgres", engineVersion: "16.1", instanceClass: aws.rds.InstanceType.T3_Medium, allocatedStorage: 100, dbName: "myapp", username: "myapp", password: dbPassword, skipFinalSnapshot: !pulumi.getStack().startsWith("prod"), vpcSecurityGroupIds: [dbSg.id], dbSubnetGroupName: dbSubnetGroup.name, storageEncrypted: true, }); const service = new awsx.ecs.FargateService("myapp-web", { cluster: cluster.arn, taskDefinitionArgs: { container: { name: "web", image: "registry.example.com/myapp:latest", cpu: 256, memory: 512, essential: true, portMappings: [{ containerPort: 8080 }], environment: [ { name: "APP_ENV", value: "production" }, { name: "DB_HOST", value: db.endpoint }, ], secrets: [ { name: "DB_PASSWORD", valueFrom: dbPasswordSecret.arn }, ], }, }, desiredCount: 3, loadBalancers: [{ targetGroupArn: targetGroup.arn, containerName: "web", containerPort: 8080, }], }); export const dbEndpoint = db.endpoint; export const serviceUrl = pulumi.interpolate`https://${loadBalancer.dnsName}`;+ בדיקות יחידה ב-TypeScript. - פריסה — חיבור ל-CI/CD (GitHub Actions, GitLab CI) ושחרור canary.
טיפ: השתמש ב-Pulumi Cloud עבור state—הוא מספק locking והיסטוריית שינויים. זה מונע קונפליקטים במהלך פריסות מקבילות.
מה כלול
| רכיב | תיאור |
|---|---|
| מאגר קוד | פרויקט Pulumi עם קוד וקונפיגורציה |
| Stacks | dev/staging/prod עם state נפרד |
| CI/CD | צינור GitHub Actions / GitLab CI |
| תיעוד | הוראות פריסה |
| הדרכה | סדנת יום אחד לצוות (הדרכת Pulumi) |
| תמיכה | 30 יום לאחר השחרור |
הערכות זמנים
- Stack טיפוסי (AWS + PostgreSQL + ECS) — 5-7 ימים.
- ארכיטקטורה רב-אזורית מורכבת — עד 14 ימים.
- המחיר מחושב באופן אישי לאחר ביקורת. חיסכון טיפוסי: $10,000–$20,000 בשנה בזמן מפתחים. השירות שלנו עולה $3,500 עבור הגדרה בסיסית של שלושה stacks.
איך לאוטומט פריסה עם Pulumi?
אנחנו מחברים את Pulumi ל-CI/CD שלך תוך יום אחד. דוגמה עבור GitHub Actions:
---
- name: Pulumi Deploy
uses: pulumi/actions@v4
with:
command: up
stack-name: production
cloud-url: https://api.pulumi.com
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
---במקביל, אנו מגדירים את Pulumi Cloud לאחסון state וסיבוב סודות.
השוואה: Pulumi מול Terraform
| קריטריון | Pulumi | Terraform |
|---|---|---|
| שפה | TypeScript, Python, Go, C# | HCL |
| שימוש חוזר | חבילות npm/pip | מודולים |
| בדיקות | Jest, מהדר TypeScript | רק pulumi preview |
| טיפול בשגיאות | קומפילציית TypeScript | שגיאות ריצה |
| עלות | קהילה חינם, בתשלום עבור Team ו-Enterprise | קהילה חינם, בתשלום עבור Cloud |
| קהילה | גדלה באופן פעיל | ענקית, בוגרת |
| תדירות פריסה | עד פי 10 ביום | פעם אחת ביום טיפוסית |
טעויות נפוצות בעבודה עם Pulumi
- חוסר locking ל-state — אם שני מפתחים מריצים
- name: Pulumi Deploy uses: pulumi/actions@v4 with: command: up stack-name: production cloud-url: https://api.pulumi.com env: PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}במקביל, ייתכן קורruption של state. פתרון: השתמש ב-backend עם locking (S3 + DynamoDB). - תלות קשיחה ב-stack — אל תשתמש בשמות משאבים מוחלטים. תמיד החל
terraform planו-pulumi up. - התעלמות מ-preview —
pulumi.getStack()חוסך שעות של ניפוי באגים. תמיד בדוק את ה-diff לפני פריסה.
למהנדסים שלנו יש מעל 5 שנות ניסיון ב-IaC; יישמנו Pulumi עבור 10+ פרויקטים. אנו מבטיחים סובלנות לתקלות ועמידה בשיטות עבודה מומלצות. לפרטים נוספים, ראה את התיעוד הרשמי של Pulumi.
קבל הגדרת Pulumi: נעריך את הפרויקט שלך תוך יום אחד, פשוט כתוב לנו. קבל ייעוץ על יישום Pulumi. צור קשר לביקורת.







