コンテナ標準化時代における次世代Buildpack『Cloud Native Buildpack』について


# はじめに

この記事は『NTTテクノクロス Advent Calendar 2018』の7日目の記事です。

執筆はNTTテクノクロスの森川です。

現在、OpenStackやCloud Foundry等のIaaSやPaaSをメインとしたチームに所属しており
普段はCloud Foundryやコンテナ関連の業務が主な業務です。

NTTテクノクロスではOpenStack、Cloud Foundry共に2012年頃から受託による検証作業等の活動を開始しており、
獲得したノウハウやスキルを生かし[『OSSクラウド基盤トータルサービス 』](https://www.ntt-tx.co.jp/products/osscloud/?utm_source=qiita&utm_medium=ac2018&utm_campaign=07)として、
お客様環境でのトラブルに対応する、案件対応として設計をお客様と一緒に検討する等のサービスを提供しています。

今回は、2018年10月にCNCF Sandboxに追加された『Cloud Native Buildpack』と、そのベースとなるBuildpackについて記事になります。
初めにBuildpackの説明と課題について説明し、その後で『Cloud Native Buildpack』について説明して行きたいと思います。


# Buildpackとは

Buildpackとは元々はPaaS基盤のHerokuが2011年に考案し、『Cloud Foundry』、『Gitlab』、『Knative』、『Deis』、 『Dokku』、『 Drie』等で採用されている仕組みです。

Buildpackは各プログラミング言語やフレームワークごとに定義されたスクリプトのまとまりで、基盤側で様々な言語のBuildpackを使ってユーザのアプリケーションコードに対して、「判定」、「ビルド」、「イメージ化」といった一連の流れを実施する事によって、基盤上で動作可能な形にアプリケーションコードを組み立てます。

アプリケーションコードを元にBuildpackの仕組みを使って組み立てたイメージは『Golden Package』と呼ばれ(Herokuの場合はSlug, Cloud Foundryの場合はDroplet)、Stacksと呼ばれるrootfs(root file system) イメージと組み合わせて基盤の実行環境上でコンテナ化して起動します。

イメージ化したGolden Packageは、起動時に環境変数でリッスンポートの指定可能になり、基盤の実行環境上であればどのサーバでも動作するように組み立てられるのが特徴です。

（参考）現在提供されているStacksのdistribution nameとCloud FoundryとHeroku上での呼び名

| distribution name | Cloud Foundry | Heroku |
|:-------------------|:-------------:|:------------:|
| Ubuntu 14.04| cflinuxfs2| Cedar-14 <br>※deprecated |
| Ubuntu 16.04 | - | Heroku-16 |
| Ubuntu 18.04 | cflinuxfs3 | Heroku-18 <br> ※default|

## Cloud Foundryの場合

ユーザはAPI経由で基盤側にアプリケーションのコードをpush（CLI経由でソースコードを転送）することで、基盤側でBuildpackの仕組みによって自動的にフレームワークを判別し、フレームワークに応じた形でイメージ化を行います。

## Herokuの場合

Cloud Foundryと同様にCLI経由でソースコードを転送することで、内部で管理するGitリポジトリでコードを管理した上でBuildpackを使ってイメージ化を行います。

## Buildpackを利用したアプリ向けのノウハウ

アプリケーションの動作環境がPaaS基盤の場合、通常のアプリの作法とは少し異なり、その作法にあわせた形でアプリケーションを作成する必要があります。その為、既存のアプリをそのまま載せ替えようとした際に、うまく動作しない事があります。

Buildpackの仕組みを使ったHerokuやCloud Foundry上でのでアプリを乗せるノウハウは
[『The Twelve-Factor App』](https://12factor.net/ja/)という形でまとめられており、DockerやK8S等の上でアプリを動作させる際にも参考になる情報となっています。
また、それらのノウハウを更に発展させた[『Beyond the Twelve-Factor App』](https://content.pivotal.io/blog/beyond-the-twelve-factor-app)もありますので、初めて利用する前等で、参考にして頂けばと思います。

## Buildpackのメリットと課題

### Buildpackのメリット

Buildpackのメリットとしては、以下があげられます。

* アプリケーションのデプロイがシンプルな手順で行える
    * 開発者はアプリケーションコードをpushするだけでよく、面倒なビルド作業を基盤側に任せることができます
* 開発者はアプリの開発に専念できる
    * 脆弱性が発生した際など新しい言語やフレームワークのバージョンを基盤側が提供する事でユーザ（アプリケーション開発者）は簡単な手順でそのバージョンを利用する事が可能になる


![image.png](https://qiita-image-store.s3.amazonaws.com/0/317746/60ab7a71-39b1-c64f-29f5-9ed69c1457d1.png)


### Buildpackの課題

Buildpackの課題としては、以下があげられます。

* Buildpackの互換性がないものがある
    * Github上に公開されているBuildpackを試してみるとHeroku向けに作られており、Cloud Foundryでは動作しないといった事がある

* アプリケーションの不具合解析が難しい
    * 基盤上にデプロイしたアプリがエラーが発生してプロセスが落ちると、基本的にはAPI経由でのログ確認等で解析を実施することになり、通常のアプリケーション開発時のローカルでのデバッグと比較して状況の把握が難しい[^1]
    * Cloud Foundryの場合、Vagrantを使ってローカル環境に構築する方法等もありましたが、Cloud Foundryに詳しくないと解析が困難という課題があった

[^1]: よくあるエラー箇所例として、『Buildpackを使ってGolden Packageが組み立てられる部分』や、『出来上がったイメージを実行環境上で起動する際にプロセスがエラーで落ちる』等がある

![image.png](https://qiita-image-store.s3.amazonaws.com/0/317746/d1d384ad-e049-ffff-f833-7fe07ea2e823.png)

## Buildpackの課題に対するこれまでの試み

Buildpackの抱える課題については、私がCloud Foundryに関わり始めた当初（2012年頃）から課題に感じていましたが、
同じくPaaSサービスを提供していたDocker社(旧：DotCloud)によるDockerの登場によって
コンテナ技術を手軽に使えるようになり、世の中に普及した事で課題解決に向けた試みが。

その前提の流れとして、現在のCloud Foundry上ではDockerImageの利用も可能になった事や、Stacks用のrootfsを作成する際の手順がDockerfileを使って作成されるようになった事で、Buildpackのノウハウがコンテナイメージと組み合わせやすい状態になりました。

その後、Cloud Foundryの基盤に関わる開発者がBuildpackの課題解決を目指し、Cloud FoundryのCLIのPlugin機能としてローカル環境上のDockerを使ってStacksのイメージとBuildpackの動きをローカル環境で組み合わせる方式の
[『local push』](https://github.com/rakutentech/cf-plugin-local-push)や[『cflocal』](https://github.com/cloudfoundry-incubator/cflocal)が生み出された事で、手軽にローカル環境で動作の確認が行えるようになり、解析が行いやすくなりました。

そうした試みの後に登場したものが、今回の内容である『Cloud Native Buildpack』プロジェクトです。

# Cloud Native Buildpack

> ![.png](https://qiita-image-store.s3.amazonaws.com/0/317746/396d37ed-3cc8-55c8-5e08-ceab2e559ab2.png)
buildpack.ioのトップページより引用(https://buildpacks.io/)

[『Cloud Native Buildpack』](https://buildpacks.io/)とは2018年1月にHerokuが開始し、2018年10月にCloud Native Computing Foundation (CNCF)が[『CNCF SandboxとしてCloud Native Buildpack【略称：CNB】の受け入れを発表』](https://www.cncf.io/blog/2018/10/03/cncf-to-host-cloud-native-buildpacks-in-the-sandbox/)した、比較的最近のプロジェクトです。

Dockerfileと比較して、より高度な抽象化の提供を目的とし、Buildpackのノウハウを生かしてソースコードをOpen Container Initiative（OCI）が定めたコンテナイメージの標準仕様であるOCI Imageに変換します。
仕様は[『Buildpack API v3 - Specification』](https://github.com/buildpack/spec)にまとめられており、Buildpackの仕様の統一化という、まさにBuildpackとDockerfileのメリットを組み合わせたものになっています。

## 既存のBuildpackとの違い

既存のBuildpackとの違いの一例をあげると、アプリケーションのコードを元にパッケージ化（イメージ化）するフェーズの名前や役割に違いがあります。

### 既存のBuildpackの場合

|順序| フェーズ | 役割 |
|:------|:-------------|:------------|
|1.|detect|どのアプリケーションフレームワークかの判定を行う
|2.|compile|判定に従った形でコンパイルを実施|
|3.|release|起動時に必要な情報を設定|

### Cloud Native Buildpackの場合

|順序| フェーズ | 役割 |
|:------|:-------------|:------------|
|1.|Detection|従来のdetectに相当|
|2.|Analys|イメージ差分をチェックし効率的なbuildの準備を行う|
|3.|Build|従来のcompileに相当|
|4.|Export|OCIイメージを作成|


## Cloud Native Buildpackの試し方

Cloud Native Buildpackをまずは試してみたい場合は、『[pack](https://github.com/buildpack/pack/releases)』コマンドいうGo言語で実装されたCLIとDockerを使うことで、ローカル環境でCloud Native Buildpackを使ったコンテナイメージの作成が行えます。
※現在デフォルトで組み込まれている[サンプル](https://github.com/buildpack/samples)にはNode.jsとJavaが組み込まれています。

* pack cliのUsage

```shell
Usage:
  pack [command]

Available Commands:
  add-stack           Create a new stack with the provided build and run image(s)
  build               Create runnable app image from source code using buildpacks
  create-builder      Compose several buildpacks into a builder image
  delete-stack        Delete a named stack
  help                Help about any command
  rebase              Update an app image to an new underlying stack
  run                 Create and immediately run an app image from source code using buildpacks
  set-default-builder Set the default builder used by `pack build`
  set-default-stack   Set the default stack used by `pack create-builder`
  update-stack        Update a stack with the provided versions of build and run image(s)
  version             Display the version of the `pack` tool

Flags:
  -h, --help   help for pack

Use "pack [command] --help" for more information about a command.
```

* buildの仕方

```shell

$ pack build --path <path to source code> <repository name>:<image tag (optional)>
```

* イメージの起動方法

```shell
$ docker run -p 8080:8080 <image name>
```

# おわりに

簡単にですが、ここまででPaaSで使われているBuildpackを発展させたCloud Native Buildpackの紹介をさせて頂きました。
今回、Cloud Native Buildpackについて興味を持って頂き、より詳しい内容を参考にしたい方は
[『第39回 PaaS勉強会』](https://paas.connpass.com/event/100821/)で @jacopenさんが発表された
[『Cloud Native Buildpacksで、めんどうなコンテナイメージ作成を自動化しよう』](https://speakerdeck.com/jacopen/cloud-native-buildpackde-mendounakontenaimezizuo-cheng-wo-zi-dong-hua-siyou)や
[『Buildpack API v3 - Specification』](https://github.com/buildpack/spec)等を参考に、ぜひ自分の得意なプログラミング言語やフレームワーク向けCloud Native Buildpackの自作などにもチャレンジしていただければと思います。