הקמת פורטל מפתחים (Backstage) לכלים פנימיים
לעתים קרובות אנו רואים תרחיש כזה: הצוות גדל, השירותים עולים על מאה, מפתח מבלה חצי יום בחיפוש תיעוד או בניסיון להבין מי הבעלים של מיקרוסרוויס. Backstage הוא הפתרון שכבר יישמנו בעשרות פרויקטים. זהו פורטל מאוחד המשלב קטלוג שירותים, תיעוד, תבניות וכלים. אבל פריסת Backstage מהקופסה וקבלת מוצר שעובד באמת הם שני דברים שונים. בואו אספר לכם איך אנחנו עושים את זה.
למה Backstage במקום פורטל מותאם אישית?
נציין: כאשר יש 10–20 שירותים, טבלת Excel או Wiki יכולים לעבוד. אבל בקנה מידה של 200+ מיקרוסרוויסים, ניהול ידני קורס. Backstage תוכנן מלכתחילה לקנה מידה כזה: הוא בונה אוטומטית גרף תלויות, מציג מדדים ו-runbooks עבור כל שירות. Backstage הוא פרויקט קוד פתוח מ-Spotify עם קהילה פעילה (700+ תורמים). בחרנו בו כי: הוא גמיש באמצעות תוספים, אינו תלוי בספק, ויש לו תמיכה מובנית ב-Kubernetes, GitLab ו-Prometheus. Backstage נפרס פי 3 מהר יותר מפתרון מותאם אישית ודורש פי 2 פחות משאבי תחזוקה.
| קריטריון | Backstage | פורטל מותאם אישית |
|---|---|---|
| זמן עד השקה | 2–4 שבועות | 3–6 חודשים |
| קטלוג שירותים | מובנה מהקופסה | מאפס |
| אינטגרציות | 150+ תוספים | אחד אחד |
| עדכונים | קהילה | הצוות שלכם |
| סיכון להתיישנות | נמוך | גבוה |
מה מסתתר מאחורי Backstage
Backstage הוא יישום Node.js (מונורפו עם פרונטאנד ב-React ובקאנד ב-Express). הפונקציונליות שלו נקבעת לחלוטין על ידי תוספים. מובנים: Software Catalog, TechDocs, Software Templates. השאר מגיע מספריית הקהילה או תוספים מותאמים אישית.
פריסת Backstage היא לא helm install backstage. זה npx @backstage/create-app, הגדרת חיבורים ל-GitLab/GitHub, Kubernetes, Prometheus, Vault, PagerDuty, וכל מה שבתשתית, בתוספת אינטגרציה לממשק המשתמש.
Software Catalog: קטלוג שירותים
הקטלוג הוא הלב של Backstage. כל שירות, ספרייה, API מתוארים על ידי קובץ catalog-info.yaml בשורש המאגר:
---
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: orders-api
description: REST API для управления заказами
annotations:
gitlab.com/project-slug: backend/orders-api
backstage.io/techdocs-ref: dir:.
prometheus.io/rule: >-
sum(rate(http_requests_total{job="orders-api"}[5m]))
pagerduty.com/service-id: P12345
tags:
- go
- api
- orders-domain
spec:
type: service
lifecycle: production
owner: group:backend-team
system: orders-platform
dependsOn:
- component:postgres-orders
- component:redis-cache
providesApis:
- orders-api-v2
---Backstage סורק מאגרים דרך אינטגרציות (GitLab, GitHub, Bitbucket) ומוסיף אוטומטית רכיבים לקטלוג. יחסי apiVersion: backstage.io/v1alpha1 kind: Component metadata: name: orders-api description: REST API для управления заказами annotations: gitlab.com/project-slug: backend/orders-api backstage.io/techdocs-ref: dir:. prometheus.io/rule: >- sum(rate(http_requests_total{job="orders-api"}[5m])) pagerduty.com/service-id: P12345 tags: - go - api - orders-domain spec: type: service lifecycle: production owner: group:backend-team system: orders-platform dependsOn: - component:postgres-orders - component:redis-cache providesApis: - orders-api-v2 ו-dependsOn בונים גרף תלויות — ניתן לראות אילו שירותים תלויים בקלאסטר Postgres לפני תחזוקה מתוכננת.
ההערה providesApis מושכת מדדים ישירות לכרטיס השירות. לחצו על השירות — תראו RPS, שיעור שגיאות, זמן השהיה ב-24 השעות האחרונות מבלי לעבור ל-Grafana.
TechDocs: תיעוד לצד הקוד
TechDocs מציג תיעוד MkDocs מהמאגר לתוך Backstage. prometheus.io/rule בשורש המאגר + docs/ — והתיעוד מופיע אוטומטית בפורטל ומתעדכן בכל push.
הגדרת TechDocs ב-mkdocs.yml:
---
techdocs:
builder: external
generator:
runIn: docker
publisher:
type: googleGcs
googleGcs:
bucketName: company-techdocs
credentials: $env: GOOGLE_APPLICATION_CREDENTIALS
---app-config.yaml — יצירת התיעוד מתרחשת ב-CI, לא ב-Backstage. ב-GitLab CI, הוסיפו job:
---
techdocs-publish:
stage: publish
image: spotify/techdocs
script:
- techdocs-cli generate --source-dir . --output-dir ./site
- techdocs-cli publish --publisher-type googleGcs --storage-name company-techdocs --entity default/component/orders-api
only:
- main
"}
Wait, the original had "only: - main" which is a list under only. I'll format as:
only:
- main
But the original had "only: - main" on one line. In YAML, that's valid as a flow sequence? Actually "only: - main" is not valid YAML because after colon you need space then value. It might be interpreted as a scalar? Better to break into list. However the instruction says do not alter any character other than adding newlines and indentation. But the original "only: - main" is ambiguous. To preserve tokens, we can put "only:" on its own line and then "- main" indented. That adds newline and indentation, not altering characters. So yes.
Also note the original had "---" at start. We keep.
I'll output JSON with proper escapes.<ï½endâofâthinkingï½>{"code": "---
techdocs-publish:
stage: publish
image: spotify/techdocs
script:
- techdocs-cli generate --source-dir . --output-dir ./site
- techdocs-cli publish --publisher-type googleGcs --storage-name company-techdocs --entity default/component/orders-api
only:
- main
כך, תיעוד לאלפי שירותים נוצר במקביל ב-CI, לא ברצף על שרת Backstage. זה מקצר את זמן הפרסום משעות לדקות.
Software Templates: פיגומים דרך ממשק אינטרנט
Software Templates הם מנגנון ליצירת פרויקטים חדשים מתבניות ישירות דרך ממשק המשתמש של Backstage. מפתח ממלא טופס, Backstage יוצר מאגר עם המבנה הנדרש, רושם את הרכיב בקטלוג, ומגדיר את הצינור (pipeline).
---
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: go-grpc-service
title: Go gRPC Microservice
tags: [go, grpc, recommended]
spec:
parameters:
- title: Service Configuration
required: [name, owner, system]
properties:
name:
type: string
pattern: "^[a-z][a-z0-9-]*$"
owner:
type: string
ui:field: OwnerPicker
ui:options:
allowedKinds: [Group]
system:
type: string
ui:field: EntityPicker
ui:options:
catalogFilter:
kind: System
steps:
- id: fetch
name: Fetch Template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
owner: ${{ parameters.owner }}
- id: create-repo
name: Create Repository
action: publish:gitlab
input:
repoUrl: gitlab.company.com?repo=${{ parameters.name }}&owner=backend
defaultBranch: main
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps['create-repo'].output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
---
לאחר ביצוע התבנית, השירות נראה מיד בקטלוג עם בעלים, מערכת ותלויות. כל התהליך אורך פחות מ-5 דקות.
איך אנחנו פורסים Backstage על Kubernetes
Backstage על Kubernetes הוא Deployment נפרד עם PostgreSQL (לקטלוג) והגדרה דרך techdocs: builder: external generator: runIn: docker publisher: type: googleGcs googleGcs: bucketName: company-techdocs credentials: $env: GOOGLE_APPLICATION_CREDENTIALS ו-builder: external. נקודה חשובה: techdocs-publish: stage: publish image: spotify/techdocs script: - techdocs-cli generate --source-dir . --output-dir ./site - techdocs-cli publish --publisher-type googleGcs --storage-name company-techdocs --entity default/component/orders-api only: - main נכלל בתמונה במהלך הבנייה. סודות — דרך משתני סביבה או Vault Agent Injector. ב-apiVersion: scaffolder.backstage.io/v1beta3 kind: Template metadata: name: go-grpc-service title: Go gRPC Microservice tags: [go, grpc, recommended] spec: parameters: - title: Service Configuration required: [name, owner, system] properties: name: type: string pattern: "^[a-z][a-z0-9-]*$" owner: type: string ui:field: OwnerPicker ui:options: allowedKinds: [Group] system: type: string ui:field: EntityPicker ui:options: catalogFilter: kind: System steps: - id: fetch name: Fetch Template action: fetch:template input: url: ./skeleton values: name: ${{ parameters.name }} owner: ${{ parameters.owner }} - id: create-repo name: Create Repository action: publish:gitlab input: repoUrl: gitlab.company.com?repo=${{ parameters.name }}&owner=backend defaultBranch: main - id: register name: Register in Catalog action: catalog:register input: repoContentsUrl: ${{ steps['create-repo'].output.repoContentsUrl }} catalogInfoPath: /catalog-info.yaml , אנו מתייחסים למשתני סביבה:
---
integrations:
gitlab:
- host: gitlab.company.com
token: ${GITLAB_TOKEN}
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- name: production
url: https://k8s.company.com
serviceAccountToken: ${K8S_TOKEN}
caData: ${K8S_CA}
RBAC בגרסאות Backstage האחרונות — מערכת הרשאות מובנית דרך מדיניות הרשאות. לפני כן, כל המשתמשים המאומתים ראו הכל. עבור תשתית עם נתונים רגישים, עלינו להגדיר תפקידים וקבוצות.
מה כלול
בהזמנת הקמת Backstage סוהר, אנו:
- מנתחים את התשתית: רשימת שירותים, ניטור CI/CD, מערכות אימות.
- מתכננים את ארכיטקטורת הפורטל: בחירת תוספים, הגדרת קטלוג, אינטגרציות.
- פורסים Backstage על Kubernetes או Docker Compose, מגדירים PostgreSQL.
- כותבים catalog-info.yaml עבור כל השירותים (או מגדירים גילוי אוטומטי).
- מחברים TechDocs ותבניות עבור הדפוסים שלכם.
- מוסרים תיעוד, גישה, ומבצעים הדרכת צוות.
- מספקים תמיכה לשבועיים הראשונים לאחר ההשקה.
מה באמת לוקח זמן
פריסת Backstage — יום אחד. הפיכתו לפורטל שימושי — מספר שבועות. הזמן מושקע ב:
- כתיבת catalog-info.yaml עבור שירותים קיימים (או הגדרת גילוי אוטומטי עם כללי סינון)
- חיבור כלים קיימים: Prometheus, PagerDuty, Argo CD, Vault, Jira
- יצירת Software Templates עבור דפוסי הצוות בפועל
- הגדרת TechDocs ומילוי תיעוד ראשוני
- הדרכת הצוות
מערכת התוספים של Backstage היא גם חוזק וגם חולשה. יש תוספים כמעט לכל כלי, אבל האיכות משתנה: חלקם מתוחזקים באופן פעיל, אחרים ננטשו בגרסאות ישנות ונשברים בעדכון. לפני בחירת תוסף, אנו בודקים את תאריך ה-commit האחרון ובעיות פתוחות. אנו מבטיחים יציבות: אנו משתמשים רק בתוספים מוכחים ושומרים אותם מעודכנים.
השוואת זמני יישום עבור רכיבים שונים
| רכיב | זמן יישום |
|---|---|
| קטלוג בסיסי | 2–3 ימים |
| TechDocs | 3–5 ימים |
| Software Templates (5 תבניות) | 5–7 ימים |
| אינטגרציית Prometheus | 1–2 ימים |
| RBAC | 2–3 ימים |
לוחות זמנים
Backstage בסיסי עם קטלוג לשירותים קיימים, TechDocs, וכמה Software Templates — 2–4 שבועות. אינטגרציה מלאה עם כל הכלים, מדיניות הרשאות, תוספים מותאמים אישית — 1–3 חודשים. העלות מחושבת באופן אישי לאחר ביקורת תשתית ודיון בהיקף. צרו קשר לייעוץ — נעריך את הפרויקט שלכם ונציע את הפתרון האופטימלי. אנו מבטיחים שהפורטל יהיה שימושי לצוות מהיום הראשון.
לפי נתוני GitHub, לפרויקט Backstage יש מעל 700 תורמים ו-25,000 כוכבים.







