Skip to content

필사 모드: DevOps/SRE 完全攻略:CI/CDからKubernetes、MLOpsまで

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

はじめに

現代のソフトウェア開発において、**DevOps**と**SRE(Site Reliability Engineering)**はもはや選択肢ではなく、必須事項です。Netflixは1日に数千回デプロイし、Googleは数十億ユーザーに99.99%の可用性を保証しています。その背後には、徹底的に自動化されたパイプラインとデータ駆動の運用哲学があります。

このガイドでは、DevOps/SREの核心概念からKubernetesの実践運用、AI/MLワークフロー自動化まで、**実際のコードとともに**完全解説します。

1. DevOps基礎:CI/CDパイプライン

CI/CDとは何か

**CI(Continuous Integration)**は、開発者が頻繁にコードを統合し、自動的にビルド・テストする実践です。**CD(Continuous Delivery/Deployment)**は、検証済みコードを自動的にプロダクションにデプロイします。

| 区分 | 目的 | 自動化範囲 |

| --------------- | ---------------- | ---------------------- |

| CI | コード統合の検証 | ビルド、テスト、Lint |

| CD (Delivery) | リリース準備 | ステージングまで自動 |

| CD (Deployment) | 自動デプロイ | プロダクションまで自動 |

GitHub ActionsでCI/CDを構築

.github/workflows/ci-cd.yml

name: CI/CD Pipeline

on:

push:

branches: [main, develop]

pull_request:

branches: [main]

env:

REGISTRY: ghcr.io

IMAGE_NAME: ${{ github.repository }}

jobs:

test:

name: Test & Lint

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- name: Set up Python

uses: actions/setup-python@v5

with:

python-version: '3.11'

cache: 'pip'

- name: Install dependencies

run: |

pip install -r requirements.txt

pip install pytest pytest-cov flake8

- name: Lint with flake8

run: flake8 src/ --max-line-length=88

- name: Run tests

run: pytest tests/ --cov=src --cov-report=xml

- name: Upload coverage

uses: codecov/codecov-action@v4

with:

file: coverage.xml

build:

name: Build & Push Docker Image

runs-on: ubuntu-latest

needs: test

if: github.ref == 'refs/heads/main'

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: Extract metadata

id: meta

uses: docker/metadata-action@v5

with:

images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

tags: |

type=sha,prefix=sha-

type=ref,event=branch

type=semver,pattern={{version}}

- name: Build and push

uses: docker/build-push-action@v5

with:

context: .

push: true

tags: ${{ steps.meta.outputs.tags }}

cache-from: type=gha

cache-to: type=gha,mode=max

deploy:

name: Deploy to Kubernetes

runs-on: ubuntu-latest

needs: build

environment: production

steps:

- uses: actions/checkout@v4

- name: Configure kubectl

uses: azure/k8s-set-context@v3

with:

kubeconfig: ${{ secrets.KUBECONFIG }}

- name: Deploy with Helm

run: |

helm upgrade --install my-app ./helm/my-app \

--namespace production \

--set image.tag=${{ github.sha }} \

--wait --timeout=5m

デプロイ戦略の比較

**Blue-Greenデプロイ**:同一のプロダクション環境を2つ(Blue/Green)維持します。新バージョンをGreenにデプロイ後、トラフィックを一度に切り替えます。ロールバックは即座ですが、リソースが2倍必要です。

**Canaryデプロイ**:トラフィックの一部(例:5%)のみを新バージョンへルーティングし、段階的に拡大します。実際のユーザーで検証しながらリスクを最小化します。

Argo Rollouts Canaryデプロイ設定

apiVersion: argoproj.io/v1alpha1

kind: Rollout

metadata:

name: my-app

spec:

replicas: 10

strategy:

canary:

steps:

- setWeight: 10

- pause: { duration: 5m }

- setWeight: 30

- pause: { duration: 10m }

- setWeight: 60

- pause: { duration: 10m }

- setWeight: 100

canaryService: my-app-canary

stableService: my-app-stable

2. GitOpsとInfrastructure as Code

GitOpsの原則

GitOpsはGitを**唯一の信頼できる情報源(Single Source of Truth)**として使用する運用モデルです。

- **宣言的(Declarative)**:システム状態をコードで宣言

- **バージョン管理**:すべての変更がGit履歴で追跡

- **自動化**:Git変更 → 自動同期

- **監査可能**:PR ベースの変更で誰が何をなぜ変更したかを記録

主要ツールとして**ArgoCD**と**Flux**があります。

TerraformでIaCを実装

main.tf - AWS EKSクラスターのプロビジョニング

terraform {

required_providers {

aws = {

source = "hashicorp/aws"

version = "~> 5.0"

}

}

backend "s3" {

bucket = "my-terraform-state"

key = "prod/eks/terraform.tfstate"

region = "ap-northeast-1"

}

}

module "eks" {

source = "terraform-aws-modules/eks/aws"

version = "~> 20.0"

cluster_name = "prod-cluster"

cluster_version = "1.29"

vpc_id = module.vpc.vpc_id

subnet_ids = module.vpc.private_subnets

eks_managed_node_groups = {

general = {

instance_types = ["m5.xlarge"]

min_size = 2

max_size = 10

desired_size = 3

}

gpu = {

instance_types = ["g4dn.xlarge"]

min_size = 0

max_size = 5

desired_size = 1

taints = [{

key = "nvidia.com/gpu"

value = "true"

effect = "NO_SCHEDULE"

}]

}

}

}

3. Kubernetes完全攻略

コアリソースの理解

| リソース | 役割 |

| ---------- | ----------------------------------------- |

| Pod | 実行単位、1つ以上のコンテナの集合 |

| Deployment | Podレプリカ管理、ローリングアップデート |

| Service | Podグループへのネットワークエンドポイント |

| HPA | CPU/メモリ基準の水平自動スケーリング |

| ConfigMap | 環境変数/設定ファイルの分離 |

| Secret | 機密情報(パスワード、トークン)の管理 |

| Ingress | 外部HTTPトラフィックのルーティング |

実践的なDeployment + HPAマニフェスト

deployment.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: ml-inference-api

namespace: production

labels:

app: ml-inference-api

version: v1

spec:

replicas: 3

selector:

matchLabels:

app: ml-inference-api

strategy:

type: RollingUpdate

rollingUpdate:

maxSurge: 1

maxUnavailable: 0

template:

metadata:

labels:

app: ml-inference-api

version: v1

annotations:

prometheus.io/scrape: 'true'

prometheus.io/port: '8080'

prometheus.io/path: '/metrics'

spec:

containers:

- name: api

image: ghcr.io/myorg/ml-inference-api:sha-abc123

ports:

- containerPort: 8080

env:

- name: MODEL_NAME

valueFrom:

configMapKeyRef:

name: ml-config

key: model_name

- name: DB_PASSWORD

valueFrom:

secretKeyRef:

name: db-secret

key: password

resources:

requests:

cpu: '500m'

memory: '512Mi'

limits:

cpu: '2000m'

memory: '2Gi'

readinessProbe:

httpGet:

path: /health

port: 8080

initialDelaySeconds: 10

periodSeconds: 5

livenessProbe:

httpGet:

path: /health

port: 8080

initialDelaySeconds: 30

periodSeconds: 10

hpa.yaml

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: ml-inference-api-hpa

namespace: production

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: ml-inference-api

minReplicas: 3

maxReplicas: 20

metrics:

- type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 70

- type: Resource

resource:

name: memory

target:

type: Utilization

averageUtilization: 80

- type: Pods

pods:

metric:

name: http_requests_per_second

target:

type: AverageValue

averageValue: '100'

behavior:

scaleUp:

stabilizationWindowSeconds: 60

policies:

- type: Pods

value: 4

periodSeconds: 60

scaleDown:

stabilizationWindowSeconds: 300

HelmチャートによるPackage管理

HelmはKubernetesのパッケージマネージャです。複雑なアプリケーションのデプロイをテンプレートで管理します。

helm/my-app/values.yaml

replicaCount: 3

image:

repository: ghcr.io/myorg/my-app

pullPolicy: IfNotPresent

tag: 'latest'

service:

type: ClusterIP

port: 80

targetPort: 8080

ingress:

enabled: true

className: nginx

annotations:

cert-manager.io/cluster-issuer: letsencrypt-prod

hosts:

- host: api.example.com

paths:

- path: /

pathType: Prefix

tls:

- secretName: api-tls

hosts:

- api.example.com

resources:

requests:

cpu: 500m

memory: 512Mi

limits:

cpu: 2000m

memory: 2Gi

autoscaling:

enabled: true

minReplicas: 3

maxReplicas: 20

targetCPUUtilizationPercentage: 70

postgresql:

enabled: true

auth:

database: myapp

existingSecret: db-credentials

redis:

enabled: true

architecture: replication

4. モニタリングと可観測性

可観測性の3つの柱

| 柱 | ツール | 用途 |

| --------------------- | ------------------- | -------------------------- |

| メトリクス(Metrics) | Prometheus, Grafana | 数値データ、ダッシュボード |

| ログ(Logs) | Loki, Elasticsearch | イベント記録、デバッグ |

| トレース(Traces) | Jaeger, Tempo | 分散リクエスト追跡 |

Prometheusアラートルール

prometheus-rules.yaml

apiVersion: monitoring.coreos.com/v1

kind: PrometheusRule

metadata:

name: ml-service-alerts

namespace: monitoring

spec:

groups:

- name: ml-service.rules

interval: 30s

rules:

- alert: HighErrorRate

expr: |

sum(rate(http_requests_total{status=~"5.."}[5m]))

/

sum(rate(http_requests_total[5m])) > 0.05

for: 2m

labels:

severity: critical

annotations:

summary: '高いエラーレートを検出'

description: '過去5分間のエラーレートは{{ $value | humanizePercentage }}です'

- alert: SlowResponseTime

expr: |

histogram_quantile(0.99,

sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service)

) > 1.0

for: 5m

labels:

severity: warning

annotations:

summary: 'p99レイテンシが遅い'

description: '{{ $labels.service }}のp99レイテンシは{{ $value }}秒です'

- alert: PodCrashLooping

expr: |

increase(kube_pod_container_status_restarts_total[15m]) > 3

for: 0m

labels:

severity: critical

annotations:

summary: 'Podがクラッシュループ中'

description: 'Pod {{ $labels.namespace }}/{{ $labels.pod }}がクラッシュループしています'

- alert: HighMemoryUsage

expr: |

container_memory_usage_bytes

/

container_spec_memory_limit_bytes > 0.85

for: 5m

labels:

severity: warning

annotations:

summary: 'メモリ使用率が高い'

OpenTelemetryによる計装

instrumentation.py

from opentelemetry import trace, metrics

from opentelemetry.sdk.trace import TracerProvider

from opentelemetry.sdk.trace.export import BatchSpanProcessor

from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

from opentelemetry.sdk.metrics import MeterProvider

from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor

from opentelemetry.instrumentation.requests import RequestsInstrumentor

def setup_telemetry(service_name: str, otlp_endpoint: str):

"""OpenTelemetryの設定"""

トレーサーの設定

tracer_provider = TracerProvider()

otlp_exporter = OTLPSpanExporter(endpoint=otlp_endpoint)

tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))

trace.set_tracer_provider(tracer_provider)

メトリクスの設定

meter_provider = MeterProvider()

metrics.set_meter_provider(meter_provider)

return trace.get_tracer(service_name)

FastAPIアプリへの適用

from fastapi import FastAPI

app = FastAPI()

tracer = setup_telemetry("ml-inference-api", "http://otel-collector:4317")

自動計装

FastAPIInstrumentor.instrument_app(app)

RequestsInstrumentor().instrument()

@app.post("/predict")

async def predict(payload: dict):

with tracer.start_as_current_span("model-inference") as span:

span.set_attribute("model.name", "bert-base")

span.set_attribute("input.length", len(str(payload)))

result = run_inference(payload)

span.set_attribute("prediction.confidence", result["confidence"])

return result

5. SREの原則

SLI / SLO / SLAの階層構造

- **SLI(Service Level Indicator)**:実際に測定されるサービスパフォーマンス指標(例:リクエスト成功率、レイテンシ)

- **SLO(Service Level Objective)**:SLIに対する目標値(例:99.9%の可用性)

- **SLA(Service Level Agreement)**:顧客と合意した契約レベル(SLOより緩く設定)

Error Budgetの計算

SLOが99.9%の場合、1か月(30日)で許容されるダウンタイムは以下の通りです。

エラーバジェット = 100% - SLO = 0.1%

月次許容ダウンタイム = 30日 x 24時間 x 60分 x 0.1% ≈ 43.2分

エラーバジェットが消費されると、新機能のデプロイを停止し、安定性作業に集中します。

| SLOレベル | 月次許容ダウンタイム |

| --------- | -------------------- |

| 99% | 7時間18分 |

| 99.9% | 43分48秒 |

| 99.99% | 4分22秒 |

| 99.999% | 26秒 |

Toil削減戦略

**Toil**は手動的・反復的・自動化可能な運用作業です。Google SREは、Toilを全業務時間の50%未満に抑えることを推奨しています。

Toil削減の方法:

1. 繰り返し作業のスクリプト化・自動化

2. ランブック(Runbook)を自動化コードへ変換

3. アラート品質の改善によるノイズ削減

4. セルフヒーリング(Self-Healing)システムの構築

6. AI/MLワークフローの自動化

MLflowによる実験管理

train.py

from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import accuracy_score, f1_score

mlflow.set_tracking_uri("http://mlflow-server:5000")

mlflow.set_experiment("fraud-detection-v2")

with mlflow.start_run(run_name="rf-baseline"):

ハイパーパラメータの記録

params = {"n_estimators": 100, "max_depth": 10, "random_state": 42}

mlflow.log_params(params)

モデルの学習

model = RandomForestClassifier(**params)

model.fit(X_train, y_train)

メトリクスの記録

y_pred = model.predict(X_test)

mlflow.log_metric("accuracy", accuracy_score(y_test, y_pred))

mlflow.log_metric("f1_score", f1_score(y_test, y_pred))

モデルの保存

mlflow.sklearn.log_model(model, "model",

registered_model_name="fraud-detector")

Argo WorkflowsによるMLパイプライン

ml-pipeline.yaml

apiVersion: argoproj.io/v1alpha1

kind: Workflow

metadata:

name: ml-training-pipeline

spec:

entrypoint: ml-pipeline

templates:

- name: ml-pipeline

dag:

tasks:

- name: data-prep

template: prepare-data

- name: train

template: train-model

dependencies: [data-prep]

- name: evaluate

template: evaluate-model

dependencies: [train]

- name: deploy

template: deploy-model

dependencies: [evaluate]

- name: prepare-data

container:

image: ghcr.io/myorg/data-prep:latest

command: [python, prepare_data.py]

resources:

requests:

memory: 4Gi

cpu: '2'

- name: train-model

container:

image: ghcr.io/myorg/ml-trainer:latest

command: [python, train.py]

resources:

requests:

memory: 16Gi

cpu: '8'

nvidia.com/gpu: '1'

- name: evaluate-model

container:

image: ghcr.io/myorg/ml-evaluator:latest

command: [python, evaluate.py]

- name: deploy-model

container:

image: ghcr.io/myorg/model-deployer:latest

command: [python, deploy.py]

Python MLサービスのDockerfile

Dockerfile

FROM python:3.11-slim AS builder

WORKDIR /app

依存関係レイヤーの分離(キャッシュ活用)

COPY requirements.txt .

RUN pip install --no-cache-dir --user -r requirements.txt

FROM python:3.11-slim AS runtime

セキュリティ:root権限なしで実行

RUN groupadd -r appuser && useradd -r -g appuser appuser

WORKDIR /app

ビルダーからパッケージをコピー

COPY --from=builder /root/.local /home/appuser/.local

COPY --chown=appuser:appuser src/ ./src/

COPY --chown=appuser:appuser models/ ./models/

USER appuser

ENV PATH=/home/appuser/.local/bin:$PATH

ENV PYTHONUNBUFFERED=1

ENV PYTHONDONTWRITEBYTECODE=1

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \

CMD python -c "import requests; requests.get('http://localhost:8080/health').raise_for_status()"

CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8080", "--workers", "4"]

7. セキュリティ:RBACとSecretsの管理

Kubernetes RBAC

rbac.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

name: ml-service-account

namespace: production

最小権限のRole

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

name: ml-service-role

namespace: production

rules:

- apiGroups: ['']

resources: ['pods', 'services']

verbs: ['get', 'list', 'watch']

- apiGroups: ['']

resources: ['secrets']

resourceNames: ['ml-model-secrets']

verbs: ['get']

apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

name: ml-service-rolebinding

namespace: production

subjects:

- kind: ServiceAccount

name: ml-service-account

namespace: production

roleRef:

kind: Role

apiGroup: rbac.authorization.k8s.io

name: ml-service-role

HashiCorp VaultによるSecret管理

vault_client.py

def get_secret(secret_path: str) -> dict:

"""Vaultからシークレットを安全に取得します。"""

client = hvac.Client(

url=os.environ["VAULT_ADDR"],

token=os.environ["VAULT_TOKEN"]

)

if not client.is_authenticated():

raise RuntimeError("Vault認証失敗")

secret = client.secrets.kv.v2.read_secret_version(

path=secret_path,

mount_point="secret"

)

return secret["data"]["data"]

KubernetesではVault Agent Injectorを使用して

Podアノテーションによる自動シークレット注入が可能

NetworkPolicyによるトラフィック制御

network-policy.yaml

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: ml-service-netpol

namespace: production

spec:

podSelector:

matchLabels:

app: ml-inference-api

policyTypes:

- Ingress

- Egress

ingress:

- from:

- namespaceSelector:

matchLabels:

name: ingress-nginx

ports:

- protocol: TCP

port: 8080

egress:

- to:

- namespaceSelector:

matchLabels:

name: database

ports:

- protocol: TCP

port: 5432

- to:

- namespaceSelector:

matchLabels:

name: monitoring

ports:

- protocol: TCP

port: 4317 # OTLP gRPC

8. インシデント管理

インシデント対応プロセス

1. **検出(Detection)**:Prometheusアラートまたはユーザー報告

2. **トリアージ(Triage)**:深刻度の判断(P1/P2/P3)

3. **コミュニケーション(Communication)**:ステータスページ更新、ステークホルダーへの通知

4. **緩和(Mitigation)**:トラフィック切り替え、ロールバック、スケールアウト

5. **解決(Resolution)**:根本原因の修正

6. **事後レビュー(Post-Mortem)**:ブレームレスPost-Mortemの作成

効果的なPost-Mortemの書き方

良いPost-Mortemは個人の責任ではなく、**システムの改善**に集中します。

- 詳細なタイムラインの記録

- 根本原因(Root Cause)と誘発要因(Trigger)の区別

- 5 Whys分析の実施

- 具体的なアクションアイテム(担当者と期限付き)

まとめ

DevOps/SREは単なるツールセットではなく、**文化と哲学**です。自動化で人為的ミスを減らし、データで意思決定を行い、継続的な改善でシステムの信頼性を高めます。

核心原則をまとめると:

- **自動化優先**:すべての繰り返し作業はコードで

- **測定可能性**:SLI/SLOで目標を明確に

- **高速な失敗**:Canaryデプロイでリスクを最小化

- **ブレームレス文化**:システムを改善し、人を非難しない

クイズ

**答え**: Blue-Greenは2つの同一プロダクション環境を維持し、トラフィックを一度に切り替える方式で、Canaryはトラフィックの一部のみを新バージョンに段階的に切り替える方式です。

**解説**: Blue-Greenデプロイはロールバックが即座(トラフィック切り替えのみ)でダウンタイムがありませんが、リソースが2倍必要です。Canaryデプロイは実際のユーザートラフィックで新バージョンを検証しながらリスクを最小化できますが、監視が複雑になります。Argo Rolloutsのようなツールが両方式をサポートします。

**答え**: デフォルトではCPU使用率とメモリ使用率です。Custom Metrics APIを通じて、RPS(秒あたりリクエスト数)やキュー深度などのカスタムメトリクスも使用できます。

**解説**: HPA(HorizontalPodAutoscaler)のv2 APIでは、`resource`、`pods`、`object`、`external`の4種類のメトリクスタイプをサポートします。CPU 70%の目標を設定すると、既存Podの平均CPUがそれを超えたときにPod数を増やします。Prometheus Adapterをインストールすると、PrometheusメトリクスをHPAに連携できます。

**答え**: Error Budgetは、SLOで定義された許容失敗量であり、安定性と機能開発速度のバランスを取るメカニズムです。

**解説**: SLOが99.9%の場合、Error Budgetは0.1%です。このバジェットが十分であれば、新機能のデプロイや実験的な変更が可能です。バジェットが枯渇すると、新しいデプロイを凍結し、安定性の改善に集中します。これにより、開発チームと運営チームがデータに基づいてデプロイ速度を協議できます。

**答え**: pull方式はPrometheusがスクレイピング対象を中央で管理するため設定がシンプルで、対象サービスがダウンした際に即座に検出でき、セキュリティ面でファイアウォールのインバウンドルールが不要です。

**解説**: push方式(StatsD、InfluxDBなど)では、各サービスがメトリクスサーバーのアドレスを知る必要があり、ネットワーク問題時にデータが失われる可能性があります。pull方式はPrometheusが設定ファイルやサービスディスカバリで対象を管理するため、サービスの追加・削除が柔軟です。非常に短命なバッチジョブにはPushgatewayを活用します。

**答え**: GitOpsはGitを唯一の信頼できる情報源として使用し、宣言的な状態を継続的に同期させるのに対し、従来のCI/CDはパイプラインが直接命令的にデプロイを実行します。

**解説**: 従来のCI/CD(Jenkins、GitHub Actions)はパイプラインから直接`kubectl apply`や`helm upgrade`を実行します。GitOps(ArgoCD、Flux)はGitの宣言的な状態とクラスターの実際の状態を継続的に比較し、自動同期します。GitOpsはドリフト検出、自動ロールバック、完全な監査証跡が可能で、CI/CDシステムにクラスターアクセス権限を付与する必要がなくセキュリティが強化されます。

현재 단락 (1/601)

現代のソフトウェア開発において、**DevOps**と**SRE(Site Reliability Engineering)**はもはや選択肢ではなく、必須事項です。Netflixは1日に数千回デプロ...

작성 글자: 0원문 글자: 15,406작성 단락: 0/601