Edited at

Cloud Native Application Bundles(CNAB)をporterで動かしてみた

株式会社日立製作所 研究開発グループ サービスコンピューティング研究部の長沼です。

今回はCloud Native Application Bundles(CNAB)を、開発ツールの1つであるporterを使って開発・利用してみましたので、その内容について紹介します。


CNABとは

CNABとは、分散型アプリケーションのインストールや管理のためのパッケージ仕様を定めたものです。KubeCon NA 2018で紹介され、以降、仕様のアップデートや関連ツールの開発が行われています。


CNABの基本的な構成要素は

- インストール処理を行うコンテナイメージであるinvocation image

- パッケージの説明やバージョン、対となるinvocation image名や処理実行時に入力するパラメータの定義などを記述したbundle.json、

となります。


要は、最近のCloud Nativeなアプリケーションを立ち上げようとすると、構築のために色々なクライアントツール入れ、構成定義を取得し、、、準備だけでも大変です。これを1コマンド(例えばdocker run)で、クライアントツール準備からアプリケーションのインストールまでやってくれる、そんなパッケージを作りましょう、という仕様です。


CNABを実現する開発ツール

CNABはパッケージの仕様であって、bundle.jsonやInvocation Imageの具体的な開発や利用方法までは定めていません。

全部手書き開発して、Invocation Imageをdocker runすれば利用することもできますが大変です。

そこでCNABの実装として、いくつかのツール(以下)も開発が進められています。



  • duffle:

    bundle.json(とinvocation image)を用いてアプリケーションのインストール、アンインストールなどCNABの利用が可能。


  • porter:

    porter.yamlというYAMLで記述された独自の書式をもとに、bundle.jsonとinvocation imageを生成。
    helmterraformのラインタイム(Mixinと呼ばれる)が用意されており、様々なプラットフォーム(Kubernetes, パブリッククラウドサービス etc.)に対してアプリケーションのインストールが可能。


  • docker-app:

    docker-composeで用いるdocker-compose.yamlやそのメタ情報からbundle.jsonとinvocation imageを生成。
    生成したinvocation imageを用いて、kubernetesまたはswarmへアプリケーションのインストールが可能。

今回は数あるツールの中からporterを用いて、CNABの開発・利用を行ってみることとしました。


porterによるCNABの開発・利用

https://github.com/deislabs/porter/blob/master/docs/content/quickstart.md

を参考に、

- porterをセットアップ

- helmによりkubernetesにアプリケーションをインストールするためのbundle.json、invocation imageを作成

- 作成したbundle.jsonとinvocation imageを用いて、事前に構築済みのkubernetesクラスタ(helm tillerも立ち上げ済)に実際にインストール(デプロイ)

を動かしてみた流れを紹介します。

なお今回使っているporterのバージョンはv0.10.0-beta.2であり、執筆時点で頻繁にアップデートされています。

このためバージョンによっては一部動作が異なる場合があります。


porterの準備

https://github.com/deislabs/porter/blob/master/docs/content/install.md

の記述を参考に、利用するクライアントのOSに対応したスクリプトを実行します。例えば、MacOSの場合は、以下となります。

curl https://cdn.deislabs.io/porter/canary/install-mac.sh | bash

なおプロキシ環境下で動作させる場合、mixinのインストール失敗する場合がありました。注意ください。


porterによる開発

まず今回開発するパッケージ用のディレクトリを作成・移動し、porter createにより雛型を生成します。

mkdir -p my-bundle/ && cd my-bundle

porter create

すると作成したディレクトリ(上記my-bundle)下に以下のような雛型が生成されます。

my-bundle

├── Dockerfile.tmpl
├── README.md
└── porter.yaml

次に、インストールに使うhelm chart(下記my-bundle/chart/my-noderedの部分)の追加と、生成されたporter.yamlの編集を行います。

今回の例は、サンプルとしてNode-REDのhelm chartを用い、

フローベースプログラミングツールNode REDをインストールする例を試しました。


  • helm chartを追加したディレクトリ構成:

my-bundle

├── Dockerfile.tmpl
├── README.md
├── chart
│   └── my-nodered
│   ├── Chart.yaml
│   ├── templates
│   │   └── ...
│   └── values.yaml
└── porter.yaml


  • 編集後のporter.yamlの内容:


porter.yaml

name: my-bundle

version: 0.1.0
description: "An example Porter configuration"
invocationImage: path-to-registry/my-bundle:0.1.0

# インストールほか処理で利用するmixins(ランタイム)を定義すると、invocation imageビルド時に読み込まれる
mixins:
- helm

# デフォルトで読み込まれるkubeconfigの場所
credentials:
- name: kubeconfig
path: /root/.kube/config

# 変数の定義
parameters:
- name: release-name
type: string
default: default-name

install:
- helm:
description: "Install my-bundle"
name: "{{ bundle.parameters.release-name}}" #{{ bundle.parameters.xxx}}でparametersで指定の変数を読み込む
chart: chart/my-nodered #相対パスでchartの格納場所を指定
version: 0.1.0
replace: true
...


このように準備したディレクトリ下で

porter build

を実行すると、bundle.json(bundle.jsonはmy-bundle/.cnab/配下に格納)とinvocation imageが作成されます。

invocation imageの作成では、porter.yamlのmixins部分に指定のmixinを含むコンテナイメージが自動的に作成されるため、必要なツールを都度準備して格納するといった作業は不要となります。


porterによるインストール

同じく上記で準備したディレクトリ(my-bundle)下で

porter install

を実行します。

すると、対応するinvocation image(今回の場合は上記porter buildで作成したもの)内で定義されたinstall処理が実行されます。

具体的には、porter.yamlのinstall部分に記述された処理(今回の場合はhelm install chart/my-nodered)が実行されることになります。

結果、対象としたkubernetesクラスタ上でNode REDがインストールされる(動作している)ことが確認できました。

なお作成済みのbundle.json、invocation imageを利用してインストールする場合は、オプションで次のように--cnab-file=を指定することができます(bundle.jsonのkeyの一つとしてinvocation imageが含まれています)。

porter install --cnab-file=path_to/bundle.json

同様に、認証情報(今回の場合はkubeconfig)やporter.yamlに指定したパラメータ(今回の場合はrelease-name)をデフォルトから変更することもできます。

例えば、kubeconfigとしてクライアントのpath_to_kubeconfigディレクトリにあるmy-kubeconfigを用い、パラメータrelease-nameをchanged-nameに変更する場合、


- $HOME/credset.yaml:


$HOME/credeset.yaml

name: my-credentials

credentials:
- name: kubeconfig
source:
path: /path_to_kubeconfig/my-kubeconfig

というファイルを用意しておき、オプションとして認証情報の変更:-c $HOME/cred.yaml、変数の変更:-param release-name=changed-nameを付加した

poter install -c $HOME/credset.yaml -param release-name=changed-name

を実行することになります。

なおporterで認証情報を扱う仕組みとして、porter credentialsコマンドが用意されているように見えますが、今回はうまく動かすことができず利用を断念しました。こちらは引き続き調査したいと思います。


porterによるインストール内容の確認

porterでインストールしたbundleの内容は、

# 一覧の出力

porter bundles list

# 個々のインストールbundle(名称$NAME)の出力
porter bundles show $NAME

のコマンドにより確認することができます。

なお現仕様では、porterが動作するクライアントの$HOME/.porter下に状態を管理するファイルが置かれており、その内容を整形・出力しているようです。


まとめ

porterを使ってCNABのinvocation image, bundle.jsonを作成し、サンプルのアプリケーションをkubernetesにインストール(デプロイ)することができました。

作成済みのCNABを利用しアプリケーション環境を構築する立場から見ると、環境構築のために色々なツールを準備せずコンテナが実行可能な環境(要はdocker runが可能)のみ用意すればよいため、便利そうな印象を受けました。

一方で、porterを使ったとしても、CNABのコンテンツ(bundle.jsonやinvocation image)を準備するのはまだまだ大変そうな印象です。また利用の立場でもinvocation imageの中の処理次第では、インストール先環境との不整合で結局うまく動かない場合も考えられます。

このあたりはCNABの周辺ツール含めて、動向を引き続きウォッチしていきたいと思います。


参考