Skip to content
Published on

Platform Engineering 完全ガイド 2025: Internal Developer Platform, Backstage, Golden Path

Authors

目次(もくじ)

1. Platform Engineeringとは?

1.1 DevOpsの進化(しんか)とPlatform Engineering

DevOpsは開発(かいはつ)と運用(うんよう)の壁(かべ)を取(と)り払(はら)いましたが、新(あたら)しい問題(もんだい)を生(う)みました。「You build it, you run it」の原則(げんそく)が広(ひろ)まるにつれ、開発者の**認知負荷(にんちふか)(Cognitive Load)**が急激(きゅうげき)に増加(ぞうか)しました。

開発者の認知負荷の変化:

2010年代前半:               現在:
┌───────────────┐            ┌───────────────┐
│ ビジネスロジック │           │ ビジネスロジック │
│               │            ├───────────────┤
│               │            │ CI/CDパイプライン│
│               │            ├───────────────┤
│               │            │ インフラ管理    │
│               │            ├───────────────┤
│               │            │ 可観測性        │
│               │            ├───────────────┤
│               │            │ セキュリティ    │
│               │            ├───────────────┤
│               │            │ Kubernetes└───────────────┘            └───────────────┘

Gartnerは2026年までに大規模(だいきぼ)ソフトウェアエンジニアリング組織(そしき)の**80%**がPlatform Engineeringチームを設立(せつりつ)すると予測(よそく)しました。

1.2 Platform Engineeringの定義(ていぎ)

Platform Engineeringは、セルフサービス機能(きのう)を備(そな)えた**Internal Developer Platform(IDP)**を設計(せっけい)し構築(こうちく)する分野(ぶんや)です。開発者がインフラの複雑性(ふくざつせい)に直接(ちょくせつ)向(む)き合(あ)わずに、必要なリソースをプロビジョニングし、アプリケーションをデプロイできるようにします。

核心的目標(もくひょう):

  • 開発者の認知負荷の軽減(けいげん): インフラの複雑性を抽象化(ちゅうしょうか)
  • セルフサービス: チケットなしで開発者が直接リソースプロビジョニング
  • 標準化(ひょうじゅんか): Golden Pathによるベストプラクティスの提供(ていきょう)
  • ガードレール: セキュリティとコンプライアンスを自動的(じどうてき)に保証(ほしょう)
  • Developer Experience(DX)の向上(こうじょう): 開発者の生産性(せいさんせい)と満足度(まんぞくど)の向上

1.3 Platform Team vs DevOps Team

# Team Topologiesベースの比較
devops_team:
  役割: "開発と運用の橋渡し"
  アプローチ: "各チームにDevOpsエンジニアを派遣"
  問題点:
    - "DevOpsエンジニアがボトルネックに"
    - "チームごとに異なるツールとプロセス"
    - "知識が個人に偏る"
    - "反復的なインフラ作業"

platform_team:
  役割: "内部プラットフォームプロダクトの開発と運用"
  アプローチ: "セルフサービスプラットフォームの提供"
  利点:
    - "開発者の自律性向上"
    - "標準化されたツールとプロセス"
    - "知識がプラットフォームに内在化"
    - "自動化されたガードレール"

team_topologies:
  stream_aligned: "ビジネス機能開発チーム(開発者)"
  platform: "IDPを構築・運用するチーム"
  enabling: "新技術導入を支援するチーム"
  complicated_subsystem: "複雑なサブシステムの専門家チーム"

2. IDP(Internal Developer Platform)アーキテクチャ

2.1 IDPの5層(そう)構造(こうぞう)

┌─────────────────────────────────────────────────────┐
Developer Portal Layer     (Backstage, Port, Humanitec Score UI)├─────────────────────────────────────────────────────┤
Integration & Delivery Layer     (CI/CD: GitHub Actions, ArgoCD, Tekton)├─────────────────────────────────────────────────────┤
Security & Compliance Layer     (OPA, Kyverno, Vault, Policy-as-Code)├─────────────────────────────────────────────────────┤
Resource Management Layer     (Terraform, Crossplane, Pulumi, Helm)├─────────────────────────────────────────────────────┤
Infrastructure Layer     (AWS, GCP, Azure, Kubernetes)└─────────────────────────────────────────────────────┘

2.2 IDP核心(かくしん)コンポーネント

# IDP核心コンポーネント
service_catalog:
  説明: "すべてのサービス、API、インフラの中央カタログ"
  機能:
    - "サービスオーナーと依存関係の追跡"
    - "APIドキュメントの自動生成"
    - "サービス成熟度スコアカード"
  ツール: "Backstage Software Catalog, Port"

software_templates:
  説明: "新プロジェクトを標準化された方法で作成"
  機能:
    - "マイクロサービスのスキャフォールディング"
    - "CI/CDパイプラインの自動設定"
    - "モニタリング/ロギングをデフォルト包含"
  ツール: "Backstage Software Templates, Cookiecutter"

self_service_infrastructure:
  説明: "開発者が直接インフラをプロビジョニング"
  機能:
    - "データベース作成"
    - "キャッシュクラスタのプロビジョニング"
    - "メッセージキューの設定"
  ツール: "Crossplane, Terraform modules, Pulumi"

documentation:
  説明: "コードリポジトリと連携した技術ドキュメント"
  機能:
    - "Markdownベースのドキュメント"
    - "APIドキュメント自動化"
    - "アーキテクチャダイアグラム"
  ツール: "Backstage TechDocs, ReadTheDocs"

3. Backstage深層(しんそう)分析

3.1 Backstageとは?

BackstageはSpotifyが作成(さくせい)しCNCFに寄贈(きぞう)したオープンソースの開発者ポータルフレームワークです。2020年にオープンソース化され、現在(げんざい)CNCF Incubatingプロジェクトです。

3.2 Software Catalog

Software CatalogはBackstageの核心で、組織のすべてのソフトウェア資産(しさん)を追跡(ついせき)します。

# catalog-info.yaml - サービス登録ファイル
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: user-service
  description: "ユーザー管理マイクロサービス"
  annotations:
    github.com/project-slug: "myorg/user-service"
    backstage.io/techdocs-ref: "dir:."
    pagerduty.com/service-id: "PXXXXXX"
    grafana/dashboard-selector: "user-service"
    sonarqube.org/project-key: "myorg_user-service"
  tags:
    - java
    - spring-boot
    - user-management
  links:
    - url: "https://grafana.internal/d/user-service"
      title: "Grafana Dashboard"
      icon: dashboard
    - url: "https://user-service.internal/swagger-ui"
      title: "API Docs"
      icon: docs
spec:
  type: service
  lifecycle: production
  owner: team-backend
  system: user-platform
  providesApis:
    - user-api
  consumesApis:
    - auth-api
    - notification-api
  dependsOn:
    - resource:default/user-database
    - resource:default/redis-cache
---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: user-api
  description: "ユーザー管理REST API"
spec:
  type: openapi
  lifecycle: production
  owner: team-backend
  system: user-platform
  definition:
    $text: ./api/openapi.yaml
---
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
  name: user-database
  description: "ユーザーサービスPostgreSQLデータベース"
spec:
  type: database
  owner: team-backend
  system: user-platform

3.3 Software Templates

# template.yaml - マイクロサービス作成テンプレート
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: spring-boot-microservice
  title: "Spring Boot Microservice"
  description: "標準Spring Bootマイクロサービスプロジェクトの作成"
  tags:
    - java
    - spring-boot
    - recommended
spec:
  owner: team-platform
  type: service

  parameters:
    - title: "サービス基本情報"
      required:
        - serviceName
        - owner
        - description
      properties:
        serviceName:
          title: "サービス名"
          type: string
          description: "kebab-case形式(例: user-service)"
          pattern: "^[a-z][a-z0-9-]*$"
        owner:
          title: "所有チーム"
          type: string
          ui:field: OwnerPicker
          ui:options:
            allowedKinds:
              - Group
        description:
          title: "サービス説明"
          type: string
        javaVersion:
          title: "Javaバージョン"
          type: string
          enum: ["17", "21"]
          default: "21"

    - title: "インフラ設定"
      properties:
        database:
          title: "データベース"
          type: string
          enum: ["postgresql", "mysql", "none"]
          default: "postgresql"
        cache:
          title: "キャッシュ"
          type: string
          enum: ["redis", "none"]
          default: "redis"

  steps:
    - id: fetch-template
      name: "テンプレートコードの取得"
      action: fetch:template
      input:
        url: "./skeleton"
        values:
          serviceName: "${{ parameters.serviceName }}"
          owner: "${{ parameters.owner }}"
          description: "${{ parameters.description }}"
          javaVersion: "${{ parameters.javaVersion }}"
          database: "${{ parameters.database }}"
          cache: "${{ parameters.cache }}"

    - id: publish
      name: "GitHubリポジトリの作成"
      action: publish:github
      input:
        allowedHosts: ["github.com"]
        repoUrl: "github.com?owner=myorg&repo=${{ parameters.serviceName }}"
        description: "${{ parameters.description }}"
        defaultBranch: main
        protectDefaultBranch: true
        repoVisibility: internal

    - id: register
      name: "Backstageカタログに登録"
      action: catalog:register
      input:
        repoContentsUrl: "${{ steps.publish.output.repoContentsUrl }}"
        catalogInfoPath: "/catalog-info.yaml"

    - id: create-argocd-app
      name: "ArgoCDアプリケーションの作成"
      action: argocd:create-resources
      input:
        appName: "${{ parameters.serviceName }}"
        argoInstance: "main"
        namespace: "${{ parameters.serviceName }}"
        repoUrl: "${{ steps.publish.output.remoteUrl }}"
        path: "k8s/overlays/development"

  output:
    links:
      - title: "GitHubリポジトリ"
        url: "${{ steps.publish.output.remoteUrl }}"
      - title: "Backstageカタログ"
        icon: catalog
        entityRef: "${{ steps.register.output.entityRef }}"

3.4 TechDocs

# mkdocs.yml - TechDocs設定
site_name: "User Service"
site_description: "ユーザー管理マイクロサービス技術ドキュメント"

nav:
  - Home: index.md
  - Architecture:
    - Overview: architecture/overview.md
    - Data Model: architecture/data-model.md
    - API Design: architecture/api-design.md
  - Development:
    - Getting Started: development/getting-started.md
    - Local Setup: development/local-setup.md
    - Testing Guide: development/testing.md
  - Operations:
    - Deployment: operations/deployment.md
    - Monitoring: operations/monitoring.md
    - Runbook: operations/runbook.md

plugins:
  - techdocs-core

3.5 Backstageプラグインエコシステム

# 人気Backstageプラグイン
kubernetes_plugin:
  機能: "K8sクラスタのサービス状態確認"
  活用: "Pod状態、ログ、イベントをBackstageで直接確認"

github_actions_plugin:
  機能: "CI/CDパイプライン状態の表示"
  活用: "ビルド/デプロイ状況をサービスページで確認"

pagerduty_plugin:
  機能: "オンコールスケジュールとインシデント連携"
  活用: "サービスオーナーのオンコール状態を表示"

cost_insights_plugin:
  機能: "クラウドコスト分析"
  活用: "サービス別コスト追跡とトレンド分析"

tech_radar_plugin:
  機能: "テクノロジーレーダーの可視化"
  活用: "組織の技術採用状況の管理"

sonarqube_plugin:
  機能: "コード品質メトリクスの表示"
  活用: "サービス別コード品質スコアの確認"

4. Golden Path設計(せっけい)

4.1 Golden Pathとは?

Golden Path(ゴールデンロードまたはPaved Roadとも呼(よ)ばれる)は、組織が推奨(すいしょう)する標準化された開発パスです。開発者が新(あたら)しいサービスを作る際(さい)に「どの言語(げんご)を使(つか)うか、CI/CDはどう設定するか、モニタリングは何を使うか」と悩(なや)まずに済(す)むよう、整備(せいび)された道(みち)を提供します。

Golden Pathの核心原則:

1. 提案であって強制ではない (Suggestion, not Mandate)
   ├── 強制しないが従えば最も楽な道
   ├── 外れることもできるが、外れるとサポートは自己責任
   └── 「未舗装道路も行けるが、舗装道路の方が速い」

2. Day 1からプロダクションレディ
   ├── CI/CDパイプラインがデフォルト含有
   ├── モニタリング/ロギング/アラートの基本設定
   ├── セキュリティスキャンの自動化
   └── ヘルスチェックエンドポイント

3. 継続的な進化
   ├── 開発者フィードバックの反映
   ├── 新技術/ツールの統合
   └── 定期的なアップデート

4.2 Golden Path例(れい): 新マイクロサービス

# Golden Path: スキャフォールディングからプロダクションデプロイまで
golden_path_microservice:
  step_1_scaffolding:
    ツール: "Backstage Software Template"
    結果:
      - "GitHubリポジトリ作成"
      - "プロジェクト構造(src, tests, k8s, docs)"
      - "Dockerfile, docker-compose.yml"
      - "CI/CDパイプライン(.github/workflows)"
      - "catalog-info.yaml(Backstage登録)"
      - "mkdocs.yml(TechDocs)"

  step_2_development:
    ツール: "標準開発環境"
    結果:
      - "devcontainer設定"
      - "pre-commit hooks(lint, format, security)"
      - "統合テストフレームワーク"
      - "ローカル開発環境(docker-compose)"

  step_3_ci_cd:
    ツール: "GitHub Actions + ArgoCD"
    結果:
      - "PR時: ビルド、テスト、セキュリティスキャン、コードレビュー"
      - "マージ時: Dockerイメージビルド、レジストリプッシュ"
      - "ArgoCD自動同期(dev -> staging -> prod)"

  step_4_observability:
    ツール: "OpenTelemetry + Grafana Stack"
    結果:
      - "メトリクス: Prometheus + Grafana"
      - "ログ: Loki + Grafana"
      - "トレーシング: Tempo + Grafana"
      - "アラート: Grafana Alerting -> Slack/PagerDuty"

  step_5_security:
    ツール: "自動化されたセキュリティガードレール"
    結果:
      - "SAST: SonarQube"
      - "SCA: Dependabot, Snyk"
      - "イメージスキャン: Trivy"
      - "Policy-as-Code: OPA/Kyverno"

4.3 標準CI/CDパイプライン

# .github/workflows/golden-path-ci.yml
name: Golden Path CI

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: "${{ github.repository }}"

jobs:
  lint-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '21'
          cache: 'gradle'
      
      - name: Lint
        run: ./gradlew spotlessCheck
      
      - name: Unit Tests
        run: ./gradlew test
      
      - name: Integration Tests
        run: ./gradlew integrationTest

  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: SonarQube Scan
        uses: SonarSource/sonarqube-scan-action@v2
        env:
          SONAR_TOKEN: "${{ secrets.SONAR_TOKEN }}"

  build-and-push:
    needs: [lint-and-test, security-scan]
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      
      - name: Log in to Container Registry
        uses: docker/login-action@v3
        with:
          registry: "${{ env.REGISTRY }}"
          username: "${{ github.actor }}"
          password: "${{ secrets.GITHUB_TOKEN }}"
      
      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: |
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
      
      - name: Scan Image
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}"
          format: 'table'
          exit-code: '1'
          severity: 'CRITICAL,HIGH'

5. セルフサービスインフラ

5.1 Crossplaneによるインフラプロビジョニング

CrossplaneはKubernetes APIを拡張(かくちょう)して、クラウドリソースをK8sマニフェストで管理(かんり)できるようにします。

# Crossplane Composition: RDS PostgreSQL
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: postgresql-aws
  labels:
    provider: aws
    database: postgresql
spec:
  compositeTypeRef:
    apiVersion: database.platform.io/v1alpha1
    kind: PostgreSQLInstance
  resources:
    - name: rds-instance
      base:
        apiVersion: rds.aws.crossplane.io/v1alpha1
        kind: DBInstance
        spec:
          forProvider:
            engine: postgres
            engineVersion: "15"
            dbInstanceClass: db.t3.medium
            allocatedStorage: 20
            masterUsername: admin
            skipFinalSnapshot: true
            publiclyAccessible: false
          providerConfigRef:
            name: aws-provider
      patches:
        - fromFieldPath: "spec.parameters.storageGB"
          toFieldPath: "spec.forProvider.allocatedStorage"
        - fromFieldPath: "spec.parameters.instanceClass"
          toFieldPath: "spec.forProvider.dbInstanceClass"
---
# 開発者が要求するリソース(Claim)
apiVersion: database.platform.io/v1alpha1
kind: PostgreSQLInstance
metadata:
  name: user-db
  namespace: backend
spec:
  parameters:
    storageGB: 50
    instanceClass: db.t3.medium
  compositionSelector:
    matchLabels:
      provider: aws
      database: postgresql

5.2 Terraformモジュールベースのセルフサービス

# modules/microservice-infra/main.tf
# マイクロサービスインフラ標準モジュール

variable "service_name" {
  type        = string
  description = "マイクロサービス名"
}

variable "team" {
  type        = string
  description = "所有チーム"
}

variable "environment" {
  type        = string
  description = "環境(dev, staging, prod)"
}

variable "enable_database" {
  type    = bool
  default = false
}

variable "enable_cache" {
  type    = bool
  default = false
}

# EKS Namespace
resource "kubernetes_namespace" "service" {
  metadata {
    name = var.service_name
    labels = {
      team        = var.team
      environment = var.environment
      managed-by  = "terraform"
    }
  }
}

# PostgreSQL(オプション)
module "database" {
  count  = var.enable_database ? 1 : 0
  source = "../rds-postgresql"

  name        = "${var.service_name}-db"
  environment = var.environment
  
  instance_class    = var.environment == "prod" ? "db.r6g.large" : "db.t3.medium"
  allocated_storage = var.environment == "prod" ? 100 : 20
  multi_az          = var.environment == "prod" ? true : false
}

# Redis Cache(オプション)
module "cache" {
  count  = var.enable_cache ? 1 : 0
  source = "../elasticache-redis"

  name        = "${var.service_name}-cache"
  environment = var.environment
  
  node_type       = var.environment == "prod" ? "cache.r6g.large" : "cache.t3.medium"
  num_cache_nodes = var.environment == "prod" ? 3 : 1
}

# モニタリングダッシュボード自動生成
module "monitoring" {
  source = "../grafana-dashboard"

  service_name = var.service_name
  namespace    = kubernetes_namespace.service.metadata[0].name
  
  enable_database_metrics = var.enable_database
  enable_cache_metrics    = var.enable_cache
}

output "namespace" {
  value = kubernetes_namespace.service.metadata[0].name
}

output "database_endpoint" {
  value     = var.enable_database ? module.database[0].endpoint : null
  sensitive = true
}

6. Developer Experience測定(そくてい)

6.1 DORAメトリクス

# DORAメトリクス(DevOps Research and Assessment)
dora_metrics:
  deployment_frequency:
    説明: "デプロイ頻度 - プロダクションにどれだけ頻繁にデプロイするか"
    elite: "1日に複数回"
    high: "週1回〜日1回"
    medium: "月1回〜週1回"
    low: "月1回未満"

  lead_time_for_changes:
    説明: "変更リードタイム - コミットからプロダクションデプロイまでの時間"
    elite: "1時間未満"
    high: "1日〜1週間"
    medium: "1週間〜1ヶ月"
    low: "1ヶ月以上"

  change_failure_rate:
    説明: "変更失敗率 - デプロイ後の障害/ロールバック率"
    elite: "0-15%"
    high: "16-30%"
    medium: "16-30%"
    low: "31%以上"

  time_to_restore:
    説明: "復旧時間 - 障害発生からサービス復旧までの時間"
    elite: "1時間未満"
    high: "1日未満"
    medium: "1日〜1週間"
    low: "1週間以上"

6.2 SPACEフレームワーク

# SPACEフレームワーク
space_framework:
  S_satisfaction:
    説明: "開発者の満足度とウェルビーイング"
    測定:
      - "四半期ごとの開発者満足度アンケート(NPS)"
      - "バーンアウトリスク評価"
      - "ツール/プラットフォーム満足度スコア"

  P_performance:
    説明: "コードとシステムのパフォーマンス"
    測定:
      - "コードレビュー品質スコア"
      - "サービス信頼性(SLO達成率)"
      - "顧客影響インシデント数"

  A_activity:
    説明: "開発活動の定量的測定"
    測定:
      - "PR数とサイズ"
      - "デプロイ頻度"
      - "コードレビュー参加度"
    注意: "活動量だけで生産性を判断しないこと"

  C_communication:
    説明: "チーム間コラボレーションの効果性"
    測定:
      - "PRレビュー応答時間"
      - "ドキュメント最新化率"
      - "クロスチームコラボレーション頻度"

  E_efficiency:
    説明: "開発プロセスの効率性"
    測定:
      - "ビルド時間"
      - "テスト実行時間"
      - "環境プロビジョニング時間"
      - "オンボーディング時間(最初のPRまで)"

6.3 Platform効果(こうか)測定ダッシュボード

# Platform効果測定スクリプト
# platform_metrics.py

import statistics


def calculate_platform_metrics(data):
    """プラットフォーム効果の核心指標を計算"""
    
    metrics = {}
    
    # 1. サービス作成時間
    creation_times = data.get('service_creation_times', [])
    if creation_times:
        metrics['avg_service_creation_minutes'] = round(
            statistics.mean(creation_times), 1
        )
        metrics['target_service_creation'] = 15  # 目標: 15分
    
    # 2. オンボーディング時間(最初のコミットまで)
    onboarding_hours = data.get('onboarding_hours', [])
    if onboarding_hours:
        metrics['avg_onboarding_hours'] = round(
            statistics.mean(onboarding_hours), 1
        )
        metrics['target_onboarding_hours'] = 4  # 目標: 4時間
    
    # 3. セルフサービス率
    total_requests = data.get('total_infra_requests', 0)
    self_service = data.get('self_service_requests', 0)
    if total_requests > 0:
        metrics['self_service_rate'] = round(
            (self_service / total_requests) * 100, 1
        )
        metrics['target_self_service_rate'] = 80  # 目標: 80%
    
    # 4. Golden Path採用率
    total_svc = data.get('total_services', 0)
    gp_svc = data.get('golden_path_services', 0)
    if total_svc > 0:
        metrics['golden_path_adoption_rate'] = round(
            (gp_svc / total_svc) * 100, 1
        )
    
    # 5. プラットフォームNPS
    nps_scores = data.get('nps_scores', [])
    if nps_scores:
        promoters = len([s for s in nps_scores if s >= 9])
        detractors = len([s for s in nps_scores if s <= 6])
        total = len(nps_scores)
        metrics['platform_nps'] = round(
            ((promoters - detractors) / total) * 100
        )
    
    return metrics

7. Platform as a Product

7.1 プロダクト管理原則の適用(てきよう)

# Platform as a Productの原則
principles:
  developer_is_customer:
    説明: "開発者がプラットフォームの顧客"
    実践:
      - "定期的なユーザーインタビュー"
      - "NPS測定"
      - "ユーザビリティテスト"
      - "フィードバックループ"

  product_roadmap:
    説明: "プラットフォームにもプロダクトロードマップが必要"
    実践:
      - "四半期ごとのロードマップ共有"
      - "優先度ベースの機能開発"
      - "リリースノートの公開"
      - "変更事項の通知"

  sla_and_support:
    説明: "内部SLAとサポート体制"
    実践:
      - "プラットフォーム可用性SLA(例: 99.9%)"
      - "応答時間SLA(例: 30分)"
      - "専用サポートチャンネル(Slack)"
      - "定期的なオフィスアワー"

  marketing:
    説明: "内部マーケティングで採用を促進"
    実践:
      - "ショーケースセッション"
      - "ユースケースの共有"
      - "チャンピオンプログラム"
      - "内部ブログ/ニュースレター"

8. IDPツール比較

┌──────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│              │ BackstagePortHumanitecKratix├──────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
│ 種類          │ オープンソース│ SaaS/セルフ  │ SaaS         │ オープンソース│
│ 開発元        │ Spotify/CNCFPortHumanitecSyntasso│ 核心強み      │ 拡張性       │ 高速セット   │ スコアエンジン│ K8sネイティブ│
│ プラグイン    │ 100+         │ 内蔵         │ 内蔵         │ K8s CRD│ セルフサービス│ テンプレート  │ アクション   │ スコアベース │ Promiseベース│
│ 学習曲線      │ 高い         │ 中程度       │ 低い         │ 高い         │
│ カスタマイズ  │ 非常に高い   │ 高い         │ 中程度       │ 高い         │
│ コミュニティ  │ 非常に活発   │ 成長中       │ 小規模       │ 成長中       │
│ 適正規模      │ 50+エンジニア│ 20+エンジニア│ 20+エンジニア│ K8s専門チーム│
└──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘

9. GitOpsとPlatform Engineering

9.1 ArgoCD + Backstage統合

# ArgoCDアプリケーション定義
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: user-service
  namespace: argocd
  labels:
    team: backend
    managed-by: backstage
spec:
  project: default
  source:
    repoURL: "https://github.com/myorg/user-service"
    targetRevision: HEAD
    path: k8s/overlays/production
  destination:
    server: "https://kubernetes.default.svc"
    namespace: user-service
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

9.2 ApplicationSetでマルチ環境(かんきょう)管理

# ArgoCD ApplicationSet - 環境別自動デプロイ
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: user-service-environments
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - environment: development
            cluster: dev-cluster
            namespace: user-service-dev
          - environment: staging
            cluster: staging-cluster
            namespace: user-service-staging
          - environment: production
            cluster: prod-cluster
            namespace: user-service-prod
  template:
    metadata:
      name: "user-service-{{ environment }}"
    spec:
      project: default
      source:
        repoURL: "https://github.com/myorg/user-service"
        targetRevision: HEAD
        path: "k8s/overlays/{{ environment }}"
      destination:
        server: "https://{{ cluster }}.internal:6443"
        namespace: "{{ namespace }}"
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

10. セキュリティガードレール

10.1 Policy-as-Code: OPA/Gatekeeper

# Gatekeeper ConstraintTemplate: 必須ラベル検証
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: requiredlabels
spec:
  crd:
    spec:
      names:
        kind: RequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package requiredlabels

        violation[{"msg": msg}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("Missing required labels: %v", [missing])
        }
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
  parameters:
    labels:
      - "team"
      - "environment"
      - "service"

10.2 Kyvernoポリシー

# Kyvernoポリシー: イメージレジストリ制限
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-image-registries
spec:
  validationFailureAction: Enforce
  rules:
    - name: validate-image-registry
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "承認されたレジストリのイメージのみ使用できます。"
        pattern:
          spec:
            containers:
              - image: "ghcr.io/myorg/* | 123456789.dkr.ecr.*.amazonaws.com/*"
---
# Kyvernoポリシー: リソースリミット必須
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce
  rules:
    - name: validate-resources
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "すべてのコンテナにCPU/メモリのrequestsとlimitsを設定する必要があります。"
        pattern:
          spec:
            containers:
              - resources:
                  requests:
                    memory: "?*"
                    cpu: "?*"
                  limits:
                    memory: "?*"
                    cpu: "?*"

11. 組織(そしき)規模別(きぼべつ)IDP導入(どうにゅう)戦略

# 組織規模別IDP導入戦略
small_org:  # 20-50エンジニア
  phase_1:
    - "標準CI/CDパイプラインの構築"
    - "サービスカタログ(シンプルなWikiまたはスプレッドシート)"
    - "Terraformモジュールの標準化"
  phase_2:
    - "Backstage導入(Software Catalog)"
    - "1-2個のGolden Pathテンプレート"
    - "基本セルフサービス(DB、キャッシュ)"
  導入期間: "3〜6ヶ月"

medium_org:  # 50-200エンジニア
  phase_1:
    - "Backstageフルスタック導入"
    - "3-5個のGolden Pathテンプレート"
    - "CrossplaneまたはTerraformベースのセルフサービス"
    - "DORAメトリクス測定"
  phase_2:
    - "セキュリティガードレール(OPA/Kyverno)"
    - "コスト可視性統合"
    - "開発者満足度アンケート"
  導入期間: "6〜12ヶ月"

large_org:  # 200+エンジニア
  phase_1:
    - "専任プラットフォームチーム編成(8-15名)"
    - "Platform as a Product運用モデル"
    - "包括的IDPアーキテクチャ設計"
  phase_2:
    - "マルチクラスタ/マルチクラウドサポート"
    - "高度なセキュリティ・コンプライアンス自動化"
    - "FinOps統合"
  導入期間: "12〜18ヶ月"

12. クイズ

Q1. Platform EngineeringがDevOpsと異なる点を3つ説明してください。

回答(かいとう):

  1. アプローチ: DevOpsは各チームにDevOpsエンジニアを派遣(はけん)してサポートしますが、Platform Engineeringはセルフサービスプラットフォームを構築して開発者が直接インフラを管理できるようにします。

  2. スケーラビリティ: DevOpsエンジニアは個人の能力に依存するため、組織が大きくなるとボトルネックになりますが、Platform Engineeringはプラットフォーム自体がスケール可能で、開発者数の増加に比例して拡張されます。

  3. 標準化: DevOpsではチームごとに異なるツールとプロセスを使用できますが、Platform EngineeringはGolden Pathを通じて組織全体の標準化された開発パスを提供します。知識が個人ではなくプラットフォームに内在化されます。

Q2. Backstageの核心コンポーネント3つとそれぞれの役割を説明してください。

回答:

  1. Software Catalog: 組織のすべてのソフトウェア資産(サービス、API、ライブラリ、インフラ)を追跡する中央カタログ。サービスオーナー、依存関係、ステータスを一目で把握できます。

  2. Software Templates: 新プロジェクトを標準化された方法で作成するテンプレートシステム。GitHubリポジトリ作成、CI/CD設定、Backstage登録まで自動化します。

  3. TechDocs: docs-as-code方式の技術ドキュメントシステム。コードリポジトリ内のMarkdownファイルをBackstageでレンダリングし、サービス別技術ドキュメントを中央で閲覧(えつらん)できます。

Q3. Golden Pathの核心原則3つを説明し、「強制標準」との違いを説明してください。

回答:

核心原則:

  1. 提案であって強制ではない: Golden Pathに従(したが)えば最も楽な道ですが、外(はず)れる自由があります。ただし、外れるとプラットフォームチームのサポートは受(う)けられません。

  2. Day 1からプロダクションレディ: Golden Pathで作成されたサービスはCI/CD、モニタリング、セキュリティスキャンがデフォルトで含まれ、Day 1からプロダクションデプロイが可能です。

  3. 継続的進化: 固定(こてい)された標準ではなく、開発者フィードバックと技術の発展に応(おう)じて継続的にアップデートされます。

強制標準との違い: 強制標準は違反時にブロックまたは罰則(ばっそく)がありますが、Golden Pathは従えばリワード(簡単なインフラ、自動モニタリング、迅速なサポート)があるインセンティブベースのアプローチです。

Q4. DORAメトリクスの4つの指標とそれぞれの「Elite」レベルを説明してください。

回答:

  1. デプロイ頻度(Deployment Frequency): プロダクションにどれだけ頻繁にデプロイするか。Elite: 1日に複数回(オンデマンドデプロイ)。

  2. 変更リードタイム(Lead Time for Changes): コードコミットからプロダクションデプロイまでの時間。Elite: 1時間未満。

  3. 変更失敗率(Change Failure Rate): デプロイ後のロールバック、ホットフィックス、障害の割合。Elite: 0-15%。

  4. サービス復旧時間(Time to Restore Service): 障害発生からサービス復旧までの時間。Elite: 1時間未満。

Q5. Platform as a Productの原則で「開発者が顧客」という概念を実践するための方法4つを説明してください。

回答:

  1. 定期的なユーザーインタビュー: 開発者と1対1またはグループインタビューを実施し、ペインポイントと要件を把握します。実際の使用パターンを観察するユーザビリティテストも含みます。

  2. NPS(Net Promoter Score)測定: 四半期ごとにプラットフォーム満足度アンケートを実施し、定量的に開発者体験を追跡します。トレンドの変化をモニタリングし改善領域を特定します。

  3. プロダクトロードマップとリリースノート: プラットフォームの今後の計画を透明に共有し、変更事項をリリースノートとして整理して開発者が新機能を活用できるようにします。

  4. 専用サポートチャンネルとSLA: Slackチャンネル、オフィスアワーなど専用サポートチャンネルを運営し、応答時間SLAを設定して開発者が安定的にプラットフォームを利用できるようにします。


13. 参考資料(さんこうしりょう)

  1. Backstage.io - https://backstage.io/
  2. CNCF Platforms White Paper - CNCF TAG App Delivery
  3. Team Topologies - Matthew Skelton & Manuel Pais
  4. Platform Engineering on Kubernetes - Manning Publications
  5. DORAメトリクス - https://dora.dev/
  6. SPACEフレームワーク - Microsoft Research
  7. Crossplane Documentation - https://crossplane.io/
  8. ArgoCD Documentation - https://argo-cd.readthedocs.io/
  9. Port - https://www.getport.io/
  10. Humanitec - https://humanitec.com/
  11. Kratix - https://kratix.io/
  12. OPA Gatekeeper - https://open-policy-agent.github.io/gatekeeper/
  13. Kyverno - https://kyverno.io/
  14. Spotify Engineering Blog - Platform Engineering記事

まとめ

Platform EngineeringはDevOpsの自然(しぜん)な進化(しんか)です。開発者の認知負荷を軽減(けいげん)し、セルフサービスを通(つう)じて生産性(せいさんせい)を高(たか)め、Golden Pathで組織全体の品質(ひんしつ)と一貫性(いっかんせい)を向上させます。

成功(せいこう)するPlatform Engineeringの核心は**「プロダクトのようにプラットフォームを運営すること」**です。開発者を顧客(こきゃく)として扱(あつか)い、フィードバックを収集(しゅうしゅう)し、継続的(けいぞくてき)に改善(かいぜん)しましょう。最高のプラットフォームは、開発者が自然(しぜん)に使(つか)いたくなるプラットフォームです。