さくらのクラウドでつくるワークフロー: Workflowsをやってみよう(1)

クラウド時代の「ワークフロー自動化」がもたらす価値

クラウドコンピューティングの発展により、現在では多くの企業がクラウドを活用するようになりました。クラウドは、必要なときに必要なだけリソースを確保できる「弾力性」や、主要な機能をAPI経由で操作できる「操作性」といった特長を備えており、これらがもたらすインフラやアプリケーション運用の自動化は、企業のIT戦略において極めて重要なテーマとなっています。

不要なインフラやリソースを必要のないタイミングで解放することで、クラウド利用コストの最適化が図れるだけでなく、運用工数の削減や、さらには環境負荷を低減したIT運用にもつながります。

こうした文脈の中で、特に注目されているのが「ワークフローの自動化」です。これは、一連の操作や判断プロセスをYAMLなどで記述し、機械的に実行できるようにする仕組みであり、条件分岐・並列処理・スケジューリングなどを駆使して反復的な業務を効率化できます。

たとえば、以下のようなシーンで活用されています:

  • サーバーやストレージの定期バックアップ
  • システム障害時の自動通知・リカバリ処理
  • データパイプライン(ETL)や機械学習ジョブの実行管理
  • API連携を用いたSaaS間の処理連動 など

このようにワークフローは、「人の手で操作していた手順」を「再現可能で透明性のある処理」として記録・再利用・拡張できる点が大きな利点です。

さくらのクラウドにおける「Workflows」サービス

このような背景のもと、さくらインターネットでは、クラウド利用者が柔軟に自動化を実現できる新サービス「Workflows」を提供開始しました。

Workflowsは、さくらのクラウド上で自動化処理をYAML形式で定義し、繰り返し実行できるプラットフォームです。管理画面やAPIからワークフロー(処理手順)を登録・実行でき、例えば定期的なバックアップ、データ処理、外部APIとの連携などの自動化に活用できます 。

リリース当初はAPIから操作するサービスでしたが、2025年7月17日にGUIベースのコントロールパネル機能もリリースされより使いやすくなっています。

https://cloud.sakura.ad.jp/news/2025/07/17/workflows-controlpanel/

主な特徴と機能

  • 豊富な式・関数assign による変数操作、組み込み関数(配列操作、数学関数、文字列操作など)を使ってステップ内で動的に処理できます
  • シリアル/並列処理 — 処理手順の依存関係に応じて順番に実行したり、依存のない処理を同時に実行したりすることで効率化が可能
  • 条件分岐 — 条件によって処理を分岐させたりスキップするなど、柔軟な制御が可能です

さっそくやってみる

ではさっそく、ワークフローを作ってみましょう。

さくらのクラウドコンソールのトップ画面に ワークフロー アイコンがありますのでそちらをクリックします。

ワークフローのトップ画面が表示されます。

ワークフローを作ってみます。公式のクイックスタートドキュメントは下記のURLにあります。

https://manual.sakura.ad.jp/cloud/appliance/workflows/reference-getting_started.html

  • ワークフロー名:任意の名前を付けて下さい。
  • ワークフローの公開状態:公開 を設定します。非公開 というステータスは過去使っていたワークフローを削除したくはないがもう利用しない、という管理用に用意されています。
  • モニタリングスイート連携:今回は ログを収集しない で進めます。
  • Runbook:こちらがワークフロー本体になります。さくらのクラウドのWorkflowsはYAML形式で設定を行います。

今企業にとってクラウドは、使うかどうかというフェーズからどのように使うかというフェーズになっています。ここで生まれる新しい課題がマルチクラウド戦略です。それぞれが独自のインターフェースをサポートしているとその差分が大きな障害となります。さくらのクラウドではお客様のマルチクラウド戦略を支えるため、ワークフローのインターフェースには独自言語の実装を避けて一番多く導入されていると思われるYAMLを採用しました。これにより既存のドキュメント管理システムをお持ちのユーザーであれば統合したバージョン管理が実現できます。

meta:
  description: サンプルワークフロー
args:
  sample:
    type: number
    description: サンプル引数
steps:
  result:
    return: ${args.sample * 2}

上記はRunbookのサンプルです。非常にシンプルなコードで、 sample という数字を外部パラメータとして取得し、2倍の数字 (return: ${args.sample * 2}) を出力します。

画面右下の作成ボタンを押し、無事に作成されたら 最新のリビジョンで実行 をクリックします。

実行開始画面が出てきたら、以下の内容で引数の入力を指定します。

{
  "sample": 5
}

実行開始ボタンを押すと、詳細画面で実行ステータスや時間などが表示されます。

入力と出力 タブをクリックすると実行結果が確認できます。

実行結果は90日間保存されます。

Runbookで利用可能なコマンドのリファレンスなどはこちらにまとまっています。

https://manual.sakura.ad.jp/cloud/appliance/workflows/index.html#id36

シリアル処理、並列処理、条件分岐

続いて、少しシナリオベースのRunbookを見ていきます。まずは シリアル 処理からです。Step1の実行結果を引数としてStep2につなげる、といった使い方ができます。

meta:
  description: シリアル処理:2倍→さらに2倍

args:
  sample:
    type: number
    description: サンプル引数

steps:
  step1:
    assign:
      result1: ${args.sample * 2}

  step2:
    assign:
      result2: ${result1 * 2}  # ← グローバル変数として直接参照

  step3:
    return: ${result2}

上記のRunbookに対して前回と同じ引数を入力した場合、出力は20となります。result1: にstep1の結果である10が格納され、Step2でさらに2倍されています。

次に 並列処理 です。

meta:
  description: parallel branchのデモ(掛け算・引き算・足し算)
steps:
  set:
    assign:
      result: []
      a: 2
      b: 3

  parallelBranch:
    parallel:
      shared: [result]
      branches:
        - multiply:
            assign:
              mulResult: ${a * b}
          pushMultiply:
            assign:
              _: ${array.push(result, "multiply() = " + mulResult)}

        - subtract:
            assign:
              subResult: ${a - b}
          pushSubtract:
            assign:
              _: ${array.push(result, "subtract() = " + subResult)}

        - add:
            assign:
              addResult: ${a + b}
          pushAdd:
            assign:
              _: ${array.push(result, "add() = " + addResult)}

  done:
    return: ${result}

定義された2つの変数 a = 2, b = 3 を並列で加算、減算、乗算を行い result に格納しています。resultはArrayとなっており、3つの並列処理が終わった順に結果が追記されていきますので、順番は不同となります。

最後は 条件分岐 です。

meta:
  description: エラトステネスの篩
args:
  maxNumber:
    type: number
    description: 素数を求める最大の数
steps:
  setup:
    assign:
      sieve: ${array.fill(array.range(args.maxNumber), true)}
      primes: []
  initial:
    assign:
      _a: ${array.set(sieve, 0, false)}
      _b: ${array.set(sieve, 1, false)}
  loop:
    for:
      in: ${array.range(2, math.ceil(math.sqrt(args.maxNumber)))}
      as: index
      steps:
        if:
          switch:
            # falseだったら飛ばす
            - condition: ${sieve[index] == false}
              next: continue
            # trueだったら素数
            - condition: ${sieve[index] != false}
              steps:
                # 素数の倍数を篩にかける
                updateSieve:
                  for:
                    in: ${array.range(index * 2, args.maxNumber, index)}
                    as: n
                    steps:
                      set:
                        assign:
                          _a: ${array.set(sieve, n, false)}
        continue:
  printPrimes:
    for:
      in: ${array.range(2, args.maxNumber)}
      as: index
      steps:
        if:
          switch:
            - condition: ${sieve[index] == true}
              steps:
                push:
                  assign:
                    _a: ${array.push(primes, index)}
                log:
                  assign:
                    log: '${"素数: " + index}'
  done:
    return: ${primes}

以下で与えられた引数よりも小さい素数をすべて出力しています。

{
    "maxNumber": 50
}
[
  2,
  3,
  5,
  7,
  11,
  13,
  17,
  19,
  23,
  29,
  31,
  37,
  41,
  43,
  47
]

if: switch: で処理を分岐させて、素数の場合のみprimesに値を格納しています。

次回予告

この記事ではWorkflowsの使い方と簡単なRunbookをご紹介しました。様々なものを自動化させるためには、このワークフローをAPI呼び出しで自動実行させる必要があり、またワークフロー自体も外部API呼び出しを行う必要があります。次回はこのあたりの機能をご紹介させていただく予定です。