LESSON 30分

ストーリー

佐藤CTO
50%ルールを達成するための最大の敵がある。それがトイル(Toil)だ
あなた
うちのSREチームの日報を分析した。手動デプロイ、証明書の更新、ログの手動確認、アカウント作成…全体の業務時間の70%が手作業で占められていた
あなた
70%は多すぎますね。自動化すべき作業が山積みということですか
佐藤CTO
まさにそうだ。ただし、すべての手作業がトイルというわけではない。トイルの定義を正確に理解し、優先順位をつけて効率的に削減していこう

トイルの定義

トイルとは

トイルとは、以下の特徴を全て持つ作業のことです。

特徴説明
手動的(Manual)人間が手作業で実施するサーバーへの手動SSH、手動デプロイ
繰り返し(Repetitive)同じ作業を何度も繰り返す毎週のログローテーション
自動化可能(Automatable)原理的に自動化できる定期的なDB容量チェック
戦術的(Tactical)長期的な価値を生まない一時的なフラグの切り替え
サービス成長に比例(O(n))サービスの拡大に伴い線形に増加新規テナント追加時の手動設定
永続的な価値がない実施後に残る成果物がない手動での健全性チェック

トイルではないもの

作業トイルか?理由
オンコール対応部分的にトイル調査はエンジニアリング、手動復旧はトイル
ドキュメント作成トイルではない永続的な価値がある
アーキテクチャ設計トイルではない創造的・戦略的
自動化ツールの開発トイルではないトイルを削減するエンジニアリング
1回限りの手動作業トイルではない繰り返しではない
ポストモーテムの実施トイルではない学びと改善という永続的な価値がある

トイルの分類(タクソノミー)

カテゴリ別分類

graph TD
    Title["トイルのカテゴリ"]

    Title --- Deploy["デプロイ関連<br/>・手動デプロイ<br/>・手動ロールバック<br/>・設定変更"]
    Title --- Infra["インフラ関連<br/>・サーバー設定<br/>・証明書更新<br/>・ディスク容量管理"]
    Title --- Data["データ関連<br/>・手動DB移行<br/>・バックアップ確認<br/>・データ修正<br/>・レポート生成"]
    Title --- Access["アクセス管理<br/>・アカウント作成/削除<br/>・権限変更<br/>・APIキー発行"]
    Title --- Monitor["モニタリング<br/>・手動ログ確認<br/>・手動アラート対応<br/>・手動ヘルスチェック"]
    Title --- Comm["コミュニケーション<br/>・ステータス報告<br/>・手動チケット更新<br/>・定例会議での手動<br/>ステータス収集"]

    classDef title fill:#1a1a2e,stroke:#e94560,color:#fff
    classDef category fill:#e94560,stroke:#c23050,color:#fff

    class Title title
    class Deploy,Infra,Data,Access,Monitor,Comm category

トイルの測定

測定方法

interface ToilEntry {
  id: string;
  description: string;
  category: 'deploy' | 'infra' | 'data' | 'access' | 'monitoring' | 'communication';
  timeSpentMinutes: number;
  frequency: 'daily' | 'weekly' | 'monthly' | 'per_event';
  occurrencesPerMonth: number;
  automatable: boolean;
  automationEffort: 'low' | 'medium' | 'high';  // 自動化の難易度
}

interface ToilReport {
  totalToilHoursPerMonth: number;
  totalWorkHoursPerMonth: number;
  toilPercentage: number;
  topToilItems: ToilEntry[];
  automationCandidates: ToilEntry[];
}

function analyzeToil(entries: ToilEntry[], teamSize: number): ToilReport {
  const totalWorkHoursPerMonth = teamSize * 160; // 月160時間/人

  const entriesWithMonthlyHours = entries.map(entry => ({
    ...entry,
    monthlyHours: (entry.timeSpentMinutes * entry.occurrencesPerMonth) / 60,
  }));

  const totalToilHours = entriesWithMonthlyHours.reduce(
    (sum, e) => sum + e.monthlyHours,
    0
  );

  const sorted = entriesWithMonthlyHours.sort(
    (a, b) => b.monthlyHours - a.monthlyHours
  );

  const automationCandidates = sorted.filter(
    e => e.automatable && e.monthlyHours > 2
  );

  return {
    totalToilHoursPerMonth: totalToilHours,
    totalWorkHoursPerMonth: totalWorkHoursPerMonth,
    toilPercentage: (totalToilHours / totalWorkHoursPerMonth) * 100,
    topToilItems: sorted.slice(0, 5),
    automationCandidates,
  };
}

トイル計測テンプレート

# トイル計測シート
team: "SRE Team"
period: "2026-01"
members: 4

toil_entries:
  - description: "手動デプロイ作業"
    category: deploy
    time_per_occurrence: 30min
    frequency: "1日3回"
    monthly_occurrences: 66
    monthly_hours: 33
    automatable: true
    automation_effort: medium

  - description: "SSL証明書の更新"
    category: infra
    time_per_occurrence: 45min
    frequency: "月4回"
    monthly_occurrences: 4
    monthly_hours: 3
    automatable: true
    automation_effort: low

  - description: "新規ユーザーアカウント作成"
    category: access
    time_per_occurrence: 15min
    frequency: "週5回"
    monthly_occurrences: 20
    monthly_hours: 5
    automatable: true
    automation_effort: low

  - description: "手動ログ調査(インシデント以外)"
    category: monitoring
    time_per_occurrence: 20min
    frequency: "1日2回"
    monthly_occurrences: 44
    monthly_hours: 14.7
    automatable: true
    automation_effort: high

# サマリー
summary:
  total_toil_hours: 55.7
  total_work_hours: 640  # 4人 × 160時間
  toil_percentage: 8.7%
  target_percentage: 5%

自動化戦略

自動化の優先順位付け

評価軸重み説明
月間時間消費最も時間を消費しているトイルを優先
自動化の容易さQuick Winを先に達成
エラーリスク手動ミスが障害につながるものを優先
スケーラビリティサービス成長で増加するものを優先

ROI計算

interface AutomationROI {
  toilItem: string;
  currentMonthlyHours: number;
  automationDevelopmentHours: number;
  maintenanceHoursPerMonth: number;
  paybackMonths: number;
  yearlyTimeSaved: number;
}

function calculateAutomationROI(
  toilItem: string,
  monthlyToilHours: number,
  developmentHours: number,
  monthlyMaintenanceHours: number = 1
): AutomationROI {
  const monthlySaving = monthlyToilHours - monthlyMaintenanceHours;
  const paybackMonths = developmentHours / monthlySaving;
  const yearlyTimeSaved = monthlySaving * 12 - developmentHours;

  return {
    toilItem,
    currentMonthlyHours: monthlyToilHours,
    automationDevelopmentHours: developmentHours,
    maintenanceHoursPerMonth: monthlyMaintenanceHours,
    paybackMonths: Math.ceil(paybackMonths),
    yearlyTimeSaved: Math.round(yearlyTimeSaved),
  };
}

// 例: 手動デプロイの自動化
const deployAutomation = calculateAutomationROI(
  '手動デプロイ作業',
  33,    // 月33時間のトイル
  40,    // CI/CDパイプライン構築に40時間
  2      // 月2時間のメンテナンス
);
// paybackMonths: 2ヶ月で元が取れる
// yearlyTimeSaved: 332時間/年の節約

自動化のレベル

レベル0: 完全手動
  └─ 手順書に従い人間が全ステップを実行

レベル1: 支援ツール
  └─ スクリプトやツールが一部のステップを自動化
     人間がトリガーし、結果を確認

レベル2: 半自動
  └─ 人間が承認するだけで、残りは自動実行
     ロールバックも自動

レベル3: 完全自動
  └─ トリガーから完了まで全自動
     人間は結果の通知を受けるだけ

レベル4: 自律的
  └─ システムが自ら異常を検知し、自動で修復
     人間の介入は不要
自動化の落とし穴と対策
落とし穴説明対策
自動化の過信自動化したから安全と思い込む自動化自体の監視・テストを実施
複雑性の増大自動化ツール自体が複雑になるシンプルに保ち、段階的に改善
属人化の移動トイルの属人化が自動化ツールの属人化にドキュメントとコードレビュー
ROIの無視自動化に時間をかけすぎるROI計算で投資対効果を確認
メンテナンス負債自動化ツールのメンテナンスが放置される定期的なレビューと更新

トイル削減の実践例

例1: SSL証明書の自動更新

# cert-manager による自動証明書管理
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: sre@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: nginx

---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: api-tls
  namespace: production
spec:
  secretName: api-tls-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - api.example.com
    - "*.api.example.com"
  renewBefore: 720h  # 30日前に自動更新

例2: ユーザーアカウント管理の自動化

// セルフサービスAPI: ユーザーがSlackコマンドでアカウントを管理
import { SlackApp } from '@slack/bolt';

const app = new SlackApp({ token: process.env.SLACK_BOT_TOKEN });

app.command('/create-account', async ({ command, ack, respond }) => {
  await ack();

  const { text: targetService } = command;
  const requestor = command.user_id;

  // 承認フロー
  const approval = await requestApproval({
    requestor,
    service: targetService,
    approvers: await getServiceOwners(targetService),
  });

  if (approval.approved) {
    // 自動アカウント作成
    const account = await createServiceAccount({
      service: targetService,
      user: requestor,
      role: 'developer',
      expiresIn: '90d', // 90日で自動失効
    });

    await respond({
      text: `アカウントを作成しました: ${account.username}\n有効期限: ${account.expiresAt}`,
    });

    // 監査ログ
    await auditLog.record({
      action: 'ACCOUNT_CREATED',
      requestor,
      target: targetService,
      approvedBy: approval.approver,
    });
  }
});

まとめ

ポイント内容
トイルの定義手動的・繰り返し・自動化可能・戦術的・O(n)・永続的価値なし
トイルの測定カテゴリ分類し、月間時間と比率を可視化する
自動化の優先順位ROI計算で投資対効果が高いものから着手
自動化のレベル完全手動→支援ツール→半自動→完全自動→自律的
目標チーム全体のトイル比率を50%以下に維持する

チェックリスト

  • トイルの6つの特徴を列挙できる
  • トイルとトイルでない作業を区別できる
  • トイルの計測方法とテンプレートを理解した
  • 自動化のROI計算ができる
  • トイル削減の具体的な実装例を把握した

次のステップへ

次は「演習:SRE原則を適用しよう」です。ここまで学んだSREの基本原則、信頼性メトリクス、エラーバジェット、トイル削減を実際のシナリオに適用してみましょう。


推定読了時間: 30分