Tanzu Application Service(beta)にPacketo Python Buildpackを追加する

訂正

より正しい手順は、この回で紹介しました。この回で紹介した手順はビルドパックを永続化に失敗しているので不完全な手順です。ですが、参考になるポイントはあるので、保管しておきます。

はじめに

Cloud Foudry for Kubernetesを商用化したものがTanzu Application Service for Kubernetes (AKA TAS4K8S)です。執筆時点でこの製品はBeta扱いです。 その中のソースコードからイメージのビルドには、kpackとよばれる、Cloud Native BuildpackをKubernetes上で利用できる仕組みを提供しています。

さて、この記事執筆時点では、以下の言語のビルドパックがサポートされています。

  • java
  • nodejs
  • go
  • .Net core
  • php
  • nginx
  • httpd
  • procfile

そして、以下のビルドパックはまだコミュニティ向けで、意図的にインストールから除外されているようになっています。

  • Ruby
  • python

今後GAもしくはその後に順次サポートされていく予定ですが、なんとか現段階でも試せないか。。。ということでこの記事で実際にPythonのビルドバックをTAS4K8Sで有効化してみました。

注意点

以下の記事の方法はVMwareからサポートされない手段です。 また、使用するのはPacketoがメンテをしている以下を利用します。

https://github.com/paketo-community/python

なお、PacketoのSlackチャネルでも記載されていますが、このPythonビルドパックはAlpha扱いであり、今後リリースで大幅変更が加えられると予告されています。 以下Slackコメントから抜粋。

https://paketobuildpacks.slack.com/archives/CULAS8ACD/p1600791481010300?thread_ts=1600789945.010200&cid=CULAS8ACD

The Python buildpack is not anywhere near the same level of support as Ruby. Ruby is getting promoted into the official buildpacks org while Python is slated to be rewritten from scratch in the next few months. It is essentially alpha quality software at this point.

環境

TAS4K8S Beta 0.4.0

なお、パブリックに公開されているBetaの最新バージョンは0.3.0ですが、ほぼ同じ手順で動くと思われます

準備

まず、kpackを操作するためのkp cliをダウンロードします。 これはTanzu Networkから開発端末のOSにあわせてkp-*のファイルをダウンロードしてください。

https://network.pivotal.io/products/build-service/#/releases/667179

なお、注意点として、すくなくとも執筆時点では、kpのバージョン0.2.0を使いください。これは1.0.0に伴い大幅変更をされており、TAS4K8Sがまだ追いついていないためです。 cliをインストール後以下のようにkubeconfigファイルを読み込み、出力が問題ないか確認してください。

1% export KUBECONFIG=~/.tas
2% kp store list
3NAME                  READY
4cf-buildpack-store    True

手順

手順の大まかな流れを説明します。kpackには以下の二つの要素があります。

  • Store(最新バージョンでは、ClusterStoreに名称変更されています。): ビルドパックについての情報を登録
  • CustomBuilder: ソースコードからどのビルドパックを利用してイメージを生成するかを定義

TAS4K8Sでは、Storeはcf-buildpack-store、CustomBuilderはcf-default-builderがハードコードされており、使われています。

今回は大きくは二つの手順で実施ます。

  1. cf-buildpack-storeにPythonビルドバックを登録する
  2. cf-default-builderにPythonビルドバックを利用するよう再定義

以下それぞれ説明します。

1. Pythonビルドバックを登録する

まず、以下のとおり、cf-buildpack-storeをパッチする必要があります。これがないと後続の手順が失敗することが確認されています。なおREPO/PROJECT/IMAGEにはHarborなどのプライベートレポジトリーに対応する値をしていします。

1kubectl patch stores cf-buildpack-store --patch '{"metadata": { "annotations" : { "buildservice.pivotal.io/defaultRepository" : "REPO/PROJECT/IMAGE" }}}' --type=merge

うまく行けば以下のように表示されます。

1store.experimental.kpack.pivotal.io/cf-buildpack-store patched

つぎに、pythonのビルドバックをStoreに追加します。

1kp store add cf-buildpack-store gcr.io/paketo-community/python

以下のコマンドでpaketo-community/pythonが見えてくれば成功です。

1% kp store status cf-buildpack-store
2BUILDPACKAGE ID                  VERSION
3paketo-buildpacks/php            0.0.8
4paketo-buildpacks/procfile       1.4.0
5paketo-community/python          0.0.3
6tanzu-buildpacks/go              1.0.3
7tanzu-buildpacks/nodejs          1.0.4
8tanzu-buildpacks/java            2.5.0
9paketo-buildpacks/dotnet-core    0.0.8

2. Pythonビルドバックを利用するよう再定義

以下のようなファイルを利用します。なお、コメント行のFrom below here...にも書いていますが、ビルドパック名がバージョンによって違うかもしれないので、kp store status cf-buildpack-storeの出力結果と照らし合わせて、変更してください。

 1cat ~/packeto-python-order.yaml
 2---
 3- group:
 4  - id: paketo-community/python
 5## From below here should match the output of `kp store status cf-buildpack-store`
 6- group:
 7  - id: tanzu-buildpacks/java
 8- group:
 9  - id: tanzu-buildpacks/nodejs
10- group:
11  - id: tanzu-buildpacks/go
12- group:
13  - id: paketo-buildpacks/dotnet-core
14- group:
15  - id: paketo-buildpacks/php
16- group:
17  - id: paketo-buildpacks/httpd
18- group:
19  - id: paketo-buildpacks/nginx
20- group:
21  - id: paketo-buildpacks/procfile

ファイルを生成したら、以下のコマンドを実行します。

1kp cb patch -n cf-workloads-staging cf-default-builder -o ~/packeto-python-order.yaml

以下の確認コマンドで以下のようにPythonがリストに追加されていれば成功です。

 1% kp cb status -n cf-workloads-staging cf-default-builder
 2...
 3DETECTION ORDER
 4Group #1
 5  paketo-community/python
 6Group #2
 7  tanzu-buildpacks/java
 8Group #3
 9  tanzu-buildpacks/nodejs
10Group #4
11  tanzu-buildpacks/go
12Group #5
13  paketo-buildpacks/dotnet-core
14Group #6
15  paketo-buildpacks/php
16Group #7
17  paketo-buildpacks/httpd
18Group #8
19  paketo-buildpacks/nginx
20Group #9
21  paketo-buildpacks/procfile

試してみる

PacketoビルドパックのHelloWorldのテストアプリは以下に公開されています。

https://github.com/paketo-community/python/tree/v0.0.3/integration/testdata

これを開発端末側にダウンロードして、cf pushをします。

1% cf push pypy
2Pushing app pypy to org demo / space demo as admin...
3Getting app info...
4Creating app with these attributes...
5+ name:       pypy
6  path:       /Users/mhoshino/python/integration/testdata/pip
7  routes:
8...

うまくいけば、ビルドとアプリの稼働が実行されます。

 1Waiting for app to start...
 2
 3name:                pypy
 4requested state:     started
 5isolation segment:   placeholder
 6routes:              pypy.apps.SYSTEMDOMAIN
 7last uploaded:       Thu 15 Oct 10:55:58 JST 2020
 8stack:
 9buildpacks:
10
11type:            web
12instances:       1/1
13memory usage:    1024M
14start command:   gunicorn server:app
15
16     state     since                  cpu    memory    disk      details
17#0   running   2020-10-15T01:57:01Z   0.0%   0 of 1G   0 of 1G

curlコマンドでアクセスもできるか確認します。

1% curl  -k https://pypy.apps.SYSTEMDOMAIN/
2Hello, World with pip!

いい感じですね成功です。

おまけ、依存関係の事前用用意

cf pushをする際には、TAS4K8Sが自動でアプリケーションの依存関係を解消してくれます。Pythonの場合はrequirements.txtに記載されている内容です。 ところがインターネットにアクセスがない環境やより高速のビルドを求める場合、事前に依存関係をダウンロードする必要性がでるかもしれません。

この点は従来のPythonのビルドパックがサポートされる手法で回避することができます。

https://docs.cloudfoundry.org/buildpacks/python/index.html#vendoring

以下のようにソースコードのディレクトリーに/vendorとよばれるディレクトリーを作り、その中に依存関係をいれます。

 1% mkdir -p vendor
 2% pip download -r requirements.txt --no-binary=:none: -d vendor
 3Collecting Flask==0.12.3
 4  Downloading Flask-0.12.3-py2.py3-none-any.whl (88 kB)
 5     |████████████████████████████████| 88 kB 299 kB/s
 6  Saved ./vendor/Flask-0.12.3-py2.py3-none-any.whl
 7Collecting Jinja2==2.7.2
 8  Downloading Jinja2-2.7.2.tar.gz (378 kB)
 9     |████████████████████████████████| 378 kB 854 kB/s
10  Saved ./vendor/Jinja2-2.7.2.tar.gz
11Collecting MarkupSafe==0.21
12  Downloading MarkupSafe-0.21.tar.gz (13 kB)
13  Saved ./vendor/MarkupSafe-0.21.tar.gz
14Collecting Werkzeug==0.10.4
15  Downloading Werkzeug-0.10.4-py2.py3-none-any.whl (293 kB)
16     |████████████████████████████████| 293 kB 5.8 MB/s
17  Saved ./vendor/Werkzeug-0.10.4-py2.py3-none-any.whl
18Collecting gunicorn==19.5.0
19  Downloading gunicorn-19.5.0-py2.py3-none-any.whl (113 kB)
20     |████████████████████████████████| 113 kB 7.4 MB/s
21  Saved ./vendor/gunicorn-19.5.0-py2.py3-none-any.whl
22Collecting click>=2.0
23  Using cached click-7.1.2-py2.py3-none-any.whl (82 kB)
24  Saved ./vendor/click-7.1.2-py2.py3-none-any.whl
25Collecting itsdangerous>=0.21
26  Using cached itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
27  Saved ./vendor/itsdangerous-1.1.0-py2.py3-none-any.whl
28Successfully downloaded Flask Jinja2 MarkupSafe Werkzeug gunicorn click itsdangerous

すると、cf pushの際は、/vendorの中身が優先され、ビルド中に依存関係のダウンロードが発生しません。

 1% cf push pypy2
 2...
 3
 4Staging app and tracing logs...
 5...
 6   pip installing from vendor directory
 7   Looking in links: file:///workspace/vendor
 8   Processing ./vendor/Flask-0.12.3-py2.py3-none-any.whl
 9   Processing ./vendor/Jinja2-2.7.2.tar.gz
10   Processing ./vendor/MarkupSafe-0.21.tar.gz
11   Processing ./vendor/Werkzeug-0.10.4-py2.py3-none-any.whl
12   Processing ./vendor/gunicorn-19.5.0-py2.py3-none-any.whl
13   Processing ./vendor/click-7.1.2-py2.py3-none-any.whl
14   Processing ./vendor/itsdangerous-1.1.0-py2.py3-none-any.whl

まとめ

今回は、BetaのTAS4K8sにPythonのビルドパックを追加する方法ですが、非常にシンプルにできました。 また、kpackの柔軟性を改めて認識することができました。