キーポイント
-
DevOpsが業界の中心にある今、チームは従来のインフラストラクチャやコンフィギュレーションにとどまらず、"as Code"アプローチを拡大できる。
-
Pipelines as Codeは、開発者がワークフローの中で自動化されたタスクを実行する方法を変え、ツールのロックインから完全に独立した方法へと移行し、そのすべてがコードリポジトリに含まれる。
-
開発者は、テンプレートやループなどの高度な機能だけでなく、以前はコードファイルに予約されていたすべての機能を利用できるようになり、パイプラインを使用して従来のビルドとリリース以外のタスクを実行する方法が改善された。
-
このアプローチへの移行は、ソフトウェアエンジニアリングの新たな標準となり、生産性を向上させ、開発者に新たなレベルのコントロールをもたらすだろう。
-
レガシーな定義を新しいモデルに移行するには多少の労力がかかるかもしれないが、開発者はすでに知っているツールやアプローチから恩恵を受けられるだけでなく、より強力な自動化オーケストレーターを活用できるようになる。
ソフトウェアエンジニアリングの現状を見ると、この業界がカメレオンのようなレベルの変容を遂げたことは明らかだ。かつて主流だったものは、今ではほとんど絶滅し、まったく異なるツールやテクノロジーに取って代わられている。
私が10年前にやっていたことを振り返ってみると、集中型バージョン管理システムを多用していたこと、ワークロードが動作するオペレーティングシステムの選択に縛られていたこと、そして一般的に「開発者」であることと「インフラ」で働くことの間に強い境界意識があったことを覚えている。
状況は明らかに変わったが、この分野で唯一最大の破壊者はGitだ。Gitはすべてを変えた。ソース管理のような優れたエンジニアリングの実践を民主化し、その基盤の上に豊富なツールを構築することを可能にした。DevOpsは明らかにこの中で大きな役割を果たし、多くの新しいツール、アプローチ、テクノロジーを結びつける接着剤となった。要するに、このボトムアップの普及とDevOpsプラクティスの広範な採用により、業界は有機的に"as Code"アプローチへと移行したのである。
こうしてツール群の連携がサポートされ、ほとんどの企業でDevOpsが主流になったことに後押しされて、Terraform(や類似の)ツールが登場してきたのである。Infrastructure as Codeは今やユビキタスであり、どのクラウドプロバイダーもコードファイルやAPI経由でインフラをデプロイする機能を提供している。これは、Hello Worldサンプル以外のアプリケーションではデフォルトの選択であるはずだ。
Infrastructure as Codeはその始まりに過ぎない。Configuration as Codeはその直後に登場し、これまた極めて一般的なものとなって、組織のエンジニアリング能力を何倍にも拡張することを可能にした。そして、開発チームが生み出す価値を継続的に高めるために、Pipelines as Codeは当然の帰結となった。
なぜビルドとリリースの定義をコードに取り込む必要があるのか?
Pipelines as Codeは、エンジニアリング・チームが毎日使っている重要な成果物を自然に進化させたものだ。考えてみてほしい。Infrastructure as CodeやConfiguration as Codeがあるのに、なぜPipelines as Codeではないのか?
コンセプトは簡単だ。パイプラインをCI/CDエンジンの観点だけで考えるのではなく、開発プラットフォームのオーケストレーターとして拡張ができ、その成果物はすべてコードファイルに保存される。
そうすることで、バージョン管理、チーム作業機能などを提供すると同時に、すべてのプロセスを自動化する力を得る。自動化が進めば進むほど、品質が向上し、スピードが向上し、回復力が飛躍的に高まる。あらゆる開発チームにとって、ゲームチェンジャーなのだ。
私のブログの公開システムを見てほしい。すべてGitHubでホストされていて、私が何かを投稿するといつもこうなる。
2つのパイプライン(GitHubの専門用語ではワークフロー)がある条件の下で毎回実行され、1つは公開用、もう1つはその他のアクティビティ用だ。なぜ二つなのか、なぜ CI ワークフローが pages-build-deployment ワークフローの近くにあるのか不思議に思うかもしれない。1つ目はカスタムで、2つ目は公開用だ。カスタムの方を見てみよう。
name: CI
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
push:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
if: "!contains(github.event.head_commit.message, 'NO CI')"
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Send Tweet Action
uses: ethomson/send-tweet-action@v1.0.0
with:
# The status ("tweet") to post to twitter.
status: "Blogged! ${{ github.event.head_commit.message }} - https://mattvsts.github.io #mvpbuzz #AzureDevOps @AzureDevOps @GitHub"
# Consumer API key, available in the "Keys and tokens" section of your application in the Twitter Developer site.
consumer-key: ${{ secrets.TWITTER_CONSUMER_API_KEY }}
consumer-secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }}
access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }}
access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
このワークフローは、私の代わりに自動的にツイートする。コミットのメッセージにCIが含まれていない限り、毎回実行される。これはコードファイルで、私のリポジトリに保存されている。私のアカウントから他のリポジトリに移動しても、問題なく動作し続ける。
すべてのCI/CDオーケストレーターは、この方向に向かっている。Azure Pipelines、GitHub Actions、Jenkinsなどだ。UIはもはや重視されず、Pipelines as Codeは開発者にとって非常に特別な利点をもたらす。
Pipelines as Codeの利点
パイプラインが単なるコードであるということは、エンジニアリング組織ですでに使われているすべてのツールの恩恵を受けられることを意味する。これには、バージョン管理、ブランチ、プルリクエストなどが含まれる。開発者はコードの扱い方を知っているので、パイプラインはGitに保存された単なる成果物になる。
これはまた、トレーサビリティや監査可能性などを維持しながら、アクセスのしやすさや親しみやすさを維持しなければならない多くの状況を容易にする。繰り返しになるが、コードとしてのパイプラインは、使いやすさと再現性を維持しながら、すべてが完全な履歴とアクセス制御とともに保存されることを意味する。
最終的にはポータビリティだ。ターゲットとするプラットフォームによってPipelines as Codeの方言は異なるだろうが、コンセプトはどのプラットフォームでも変わらない。例えば、GitHub ActionsとAzure Pipelinesについて考えてみよう。どちらもYAMLをベースにしているが、構文が異なり、いくつかの特殊性もある。開発者がスピードに乗るにはせいぜい1日、違いに慣れるには長くて1週間かかる。ビルドパイプラインとリリースパイプラインの区別がなくなったことを考えると、生産性の向上は信じられないほどだ。すべてが、同じエンジンによって実行される一連のオーケストレーションされたタスクにすぎない。
最新のオーケストレーターには、それぞれ高度な機能がある。テンプレートは今や本当に一般的で、まさに救世主だ。一度パイプラインを定義すれば、最小限の変更で複数のオートメーションやプロジェクトで再利用できる。テンプレートには、すべてのロジックと、メインパイプラインから呼び出される可能性のあるコンフィギュレーションが含まれる。見てみよう。
これは、リポジトリにあるtemplate.ymlという名前のテンプレートになる。
parameters:
input : []
steps:
- ${{ each p in parameters.input }}:
- script: 'echo ${{ p }}'
このテンプレートは入力配列を受け取り、コマンドライン・タスクを使って配列を構成する個々のアイテムをひとつずつリレーしていく。非常にシンプルなロジックだが、パイプラインの中では(eachキーワードを使って)forループのような複雑なコンストラクトを使うことができ、入力配列のアイテムの数だけ動的にタスクを構成できる。
別のパイプラインから呼び出す場合は、次のようにすればいい。
steps:
- template: template.yml
parameters:
input: ["Pipelines", "Azure DevOps", "Demo", "Pipelines as Code"]
このメインパイプラインの出力は、次のようになる。
4つのコマンドラインタスクがオンデマンドで生成され、値を出力する。すべてがすぐさまオーケストレーションされる。
私がとても気に入っているもう一つの機能は、Azure PipelinesのMatrixだ。
strategy:
matrix:
'Ubuntu 18.04':
image: 'ubuntu-18.04'
'Ubuntu latest version':
image: 'ubuntu-latest'
'MacOS X 10.15':
image: 'macos-10.15'
'MacOS X latest version':
image: 'macos-latest'
'Windows Server 2016':
image: 'vs2017-win2016'
'Windows Server 2019':
image: 'windows-2019'
pool:
vmImage: $(imageName)
steps:
…
このスニペットは、ステップセクションで指定されたタスクを3つの異なるパイプラインで実行する。これだけである。
言うまでもなく、順風満帆で簡単なことばかりではない。学習コストはかかる。当然のことながら、最大のハードルはUIがないことだ。少なくとも10年間は、我々のビルド・オーケストレーターは、開発者がプロセスを完全にコントロールできないため、プロセスをよりシンプルで消化しやすくするためにUIに頼っていた。業界として、我々はUIは物事を消化しやすくするために存在しなければならないという期待に落ち着いた。
その後、as codeの動きが現れ、それを突破し始めた。Infrastructure as Codeが最初の進出であり、その後、他のすべてがそれに続いた。それから10年が経ち、UIはもはやほとんどの機能やオプションを持たず、as Codeの実装に移る前に主要な機能を学ぶためのビルド・オーケストレーターへの単なる入り口になっている。
もう1つの重要な変更点は、すべてがパイプラインで実行されるようになり、ビルドとリリースの区別がなくなったことだ。これらの境界を定義するのは開発者次第であり、すべてのものに対して1対1のマッピングが存在しないため、移行には多少の作業が必要になる。しかし、かなり軽い作業なので、それほど大きな障害ではない。
何を学んだか?
多くのプラットフォームで作業しているうちに、パターンや再利用可能なアプローチがあることに気づくだろう。しかし、それでも学んだ主な教訓は、できるだけ早い段階でパイプラインをコードとして実装する習慣を身につけることだ。ビルド定義の作成は、エンジニアが最初に行うべきことである。なぜなら、ビルド定義はアプリケーションコードとともに進化し、DevOpsプラットフォームで使用されればシームレスなエクスペリエンスを提供するからだ。
典型的な例は次のようなものだ。パイプライン定義をコードリポジトリに埋め込むということは、リポジトリは即座に完全に粒度の揃った独立したものになる。なぜなら、アプリケーションのソースコードだけでなく、そのようなアプリケーションをコンパイルしてデプロイするために必要なビルド定義も含まれることになり、DevOpsプラットフォーム全体で移動可能なアーティファクトになるからだ。マイクロサービス開発は非常に簡単になる。テストはよりシンプルになる。平凡な作業を自動化することで、チームに多くの付加価値をもたらすことができ、どのエンジニアも同じ手順をずっと繰り返すのではなく、実際の問題を解決することに集中できる。Pipelines as Codeは素晴らしい。
まとめ
Pipelines as Codeへの移行は一朝一夕にはいかないが、開発チームに多くのドアと道を開ける。これから始めるのであれば、1つだけ実行してほしいことがある。ビルドとリリースのプロセスをピックアップし、コードファイルに再現し始めることだ。それだけだ。これらのプロセスを自動化すればするほど、デフォルトのオプションとして実装するようになり、反復的なタスクに費やされる膨大な時間を節約できる。
そうすることで、エンジニアが慣れ親しんだ開発経験の恩恵を受けながら、現在足かせになっているステップを自動化する方向に自然と導かれる。変更の追跡が容易になり、マージが簡単になり、ピアレビュープロセスと相まって、すべての開発者がアクセスできるようになるだろう。