はじめに
chillSAP 夏の自由研究2022、8/30の記事として執筆しています。
この記事はCAPで作ったサービスをKyma runtimeにデプロイシリーズの2回目です。以下のチュートリアルを参考にしつつ、
- CAPで作ったアプリをKymaにデプロイするにはどのような仕組みが使われているか
- 一からアプリを作成してKymaにデプロイするには何が必要か
について確認することを目的としています。
今回は、基本的なCAPサービス(認証なし)を作成してKyma runtimeにデプロイします。
基本的なCAPアプリを作成してKyma runtimeにデプロイ
ステップ
- CAPプロジェクトを生成
- Dockerイメージを作成
- Helmの設定
- Kyma runtimeにデプロイ
- デプロイ結果の確認
1. CAPプロジェクトを生成
1.1. プロジェクトの生成
以下のコマンドでCAPプロジェクトを生成します。
cds init <プロジェクト名>
例
cds init capkyma
1.2. サンプルスキーマとサービスの生成
時間短縮のため、以下のコマンドでサンプルのスキーマとサービスを生成します。
cds add samples
1.3. HANAにデプロイ用の設定を追加
以下のコマンドで、HANAにデプロイするための設定を追加します。
cds add hana --for production
2. Dockerイメージを作成
2.1 Buildpackを使用したイメージの作成
Dockerイメージの作成方法については、自分でDockerfileを作成する方法もありますが、チュートリアルではCloud Native Buildpacksというものを使ってイメージを作成しています。
Buildpacksを使うと、Dockerfileを使わずにソースコードをコンテナイメージに変換することができます。Buildpackはアプリケーションを実行するのに必要なdependency(モジュール)を自動的に検知してインストールし、クラウド環境で実行できる状態にしてくれます。
参考
- https://blogs.sap.com/2022/07/12/cap-on-kyma-now-officially-supported/
- https://buildpacks.io/docs/concepts/
2.2 イメージの作成対象
Kyma runtimeにデプロイするために、2つのDockerイメージを作成する必要があります。一つはCAPで作成したサービスのため、もう一つはHANA Cloudにテーブルやビューをデプロイするためのものです。
MTAを使ってCloud Foundryにデプロイするときも、mta.yamlに以下のように2つのモジュールが設定されます(今回mta.yamlは使いません)。以下のcapkyma-srv
とcapkyma-db-deployer
に対応するDockerイメージを作成するということになります。
modules:
- name: capkyma-srv
type: nodejs
path: gen/srv
parameters:
buildpack: nodejs_buildpack
build-parameters:
builder: npm-ci
provides:
- name: srv-api # required by consumers of CAP services (e.g. approuter)
properties:
srv-url: ${default-url}
requires:
- name: capkyma-db
- name: capkyma-db-deployer
type: hdb
path: gen/db
parameters:
buildpack: nodejs_buildpack
requires:
- name: capkyma-db
以下ではプロジェクトをビルドし、各モジュールのためのDockerイメージを作成していきます。
2.3. ビルド
以下のコマンドでビルドします。
cds build --production
オプションとして、以下のコマンドでサンプルデータがデプロイされないように消すこともできます。今回はサンプルデータで動作確認したいので、そのまま残しておきます。
rm -rf gen/db/data
/genフォルダにdbモジュールとsrvモジュールのデプロイ用のソースが格納されました。
2.4. CAPサービスのDockerイメージを作成
Buildpackを使ってイメージを作成します。以下のコマンドを実行します。pack
というコマンドは、事前準備編でインストールしたものです。
pack build <コンテナレジストリ※>/<CAPのサービス名> --path gen/srv \
--buildpack gcr.io/paketo-buildpacks/nodejs \
--builder paketobuildpacks/builder:base
# 例
pack build miyasuta/capkyma-srv --path gen/srv \
--buildpack gcr.io/paketo-buildpacks/nodejs \
--builder paketobuildpacks/builder:base
# Powershellの場合、改行はバックスクオート
pack build miyasuta/capkyma-srv --path gen/srv `
--buildpack gcr.io/paketo-buildpacks/nodejs `
--builder paketobuildpacks/builder:base
※コンテナレジストリ:Dokcer Hubを使用する場合、Docker HubのユーザIDを指定する
イメージの作成が終わると、docker image ls
コマンドでイメージができていることを確認できます。(作成がなぜか42年前になっていますが…)
REPOSITORY TAG IMAGE ID CREATED SIZE
miyasuta/capkyma-srv latest 589516e87e29 42 years ago 261MB
2.5. DBデプロイヤーのDockerイメージを作成
以下のコマンドを実行します。
pack build <コンテナレジストリ>/<deployer名> --path gen/db \
--buildpack gcr.io/paketo-buildpacks/nodejs \
--builder paketobuildpacks/builder:base
# 例
pack build miyasuta/capkyma-db-deployer --path gen/db \
--buildpack gcr.io/paketo-buildpacks/nodejs \
--builder paketobuildpacks/builder:base
2.6. Dockerイメージをプッシュ
コンテナレジストリにログインします。
docker login
以下のコマンドでDockerイメージをコンテナレジストリにプッシュします。
docker push <コンテナレジストリ>/<CAPのサービス名>
docker push <コンテナレジストリ>/<deployer名>
例
docker push miyasuta/capkyma-srv
docker push miyasuta/capkyma-db-deployer
Docker Hubでみると、以下のように登録されています。
3. Helmの設定
前回の記事で書いたように、CAPのデプロイにはHelmというツールを使います。前提としてhelmのインストールが必要です。
まずは以下のコマンドを実行してみましょう。
cds add helm
すると、chartフォルダが追加されました。この中にデプロイ用のyamlファイルを作成するためのテンプレートと、テンプレートに値を設定するvalue.yamlファイルが入っています。手を入れるのはvalues.yamlファイルだけです。
values.yamlの初期状態は以下のようになっています。
global:
domain: null
imagePullSecret:
name: null
srv:
bindings:
db:
fromSecret: null
image:
repository: <your-container-registry>/capkyma-srv
tag: latest
resources:
limits:
cpu: 100m
ephemeral-storage: 1G
memory: 500M
requests:
cpu: 100m
ephemeral-storage: 1G
memory: 500M
health_check:
liveness:
path: /
readiness:
path: /
hana_deployer:
image:
repository: <your-container-registry>/capkyma-hana-deployer
tag: latest
bindings:
hana:
fromSecret: null
更新箇所は4つあります。
①globalセクション
globalセクションではdomain
とimagePullSecret.name
を指定します。
global:
domain: <Kyma runtimeのドメイン>
imagePullSecret:
name: <Dockerレジストリ用のシークレット>
domain
にはデプロイ先のKyma runtimeのドメインを指定します。以下のコマンドで確認できます。
kubectl get gateway -n kyma-system kyma-gateway -o jsonpath='{.spec.servers[0].hosts[0]}'
以下のような結果が返ってくるので、先頭の*.
を除いた部分を設定します。
# 結果(例)
*.a2985eb.kyma.shoot.live.k8s-hana.ondemand.com
# 設定値(例)
a2985eb.kyma.shoot.live.k8s-hana.ondemand.com
imagePullSecret.name
には事前準備で作成したDockerレジストリアクセス用のシークレットを指定します。
②srvセクション
srvセクションではbindings.db.fromSecret
とimage.repository
を指定します。
srv:
bindings:
db:
fromSecret: capkyma-db
image:
repository: docker.io/miyasuta/capkyma-srv # Docker Hubの場合、docker.io/をつける
tag: latest
bindings.db.fromSecret
に事前準備で作成したHDIコンテナにアクセスするためのシークレットを指定します。
image.repository
に2.6.でプッシュしたCAPサービスのイメージを指定します。
③hana_deployerセクション
hana_deployerセクションではimage.repository
とbindings.hana.fromSecret
を指定します。
hana_deployer:
image:
repository: docker.io/miyasuta/capkyma-hana-deployer
tag: latest
bindings:
hana:
fromSecret: capkyma-db
image.repository
に2.6.でプッシュしたDBデプロイヤーのイメージを指定します。
bindings.hana.fromSecret
にHDIコンテナにアクセスするためのシークレットを指定します。
どんなyamlファイルが生成されるか
実際に生成されるデプロイ用のyamlファイルは内部的なもので、ローカル環境には作成されません。ですが、Helmのtemplateコマンドで生成されるyamlをターミナル上で見ることができます。
以下のコマンドを実行します。
helm template <name> <chartフォルダのパス>
# 例
helm template capkyma ./chart
すると、以下のように長い結果が返ってきます。
---
# Source: capkyma/charts/srv/templates/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: capkyma-srv
labels:
helm.sh/revision: "1"
helm.sh/chart: srv-0.1.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: srv
app.kubernetes.io/instance: capkyma
spec:
ingress:
- from:
- podSelector:
matchLabels:
app: istio-ingressgateway
namespaceSelector: {}
podSelector:
matchLabels:
app.kubernetes.io/name: srv
app.kubernetes.io/instance: capkyma
policyTypes:
- Ingress
---
...省略
kindを見るとどのような種類のリソースが作られるかわかるので、それをまとめたものが以下です。6種類のリソースができることがわかります。
リソース | 何をするものか |
---|---|
NetworkPolicy | CAPのサービスのPodへの通信を許可するPodを指定(istio-ingressgatewayにマッチするものを許可している) |
PodDisruptionBudget | Podを停止する際に停止できる数を制限する |
Service | CAPのサービスを公開する |
Deployment | CAPのサービスをデプロイし、Podを作成する |
APIRule | CAPのサービスへのアクセスポリシーなどを設定 |
Job (hana-deployer) | CAPのdbモジュールをHANA Cloudにデプロイ |
JobはHANA Cloudにデプロイするために一時的に作成されるリソースで、デプロイが完了すると消えます。
4. Kyma runtimeにデプロイ
以下のコマンドを実行します。Helmはchartとvalueの組み合わせをリリースとして管理するので、任意のリリース名を指定します。
helm upgrade <リリース名> <chartフォルダのパス> --install
# 例
helm upgrade capkyma ./chart --install
正常に終了した場合は、ターミナルに以下のメッセージが出力されます。
The release "capkyma" is installed in namespace "capkyma".
Your services are available at:
- https://capkyma-srv-capkyma.a2985eb.kyma.shoot.live.k8s-hana.ondemand.com
Booksをクリックするとデータが表示されます。HANA Cloudへの接続もOKです。
5. デプロイ結果の確認
Podの状態
以下のコマンドでPodの状態を確認できます。
kubectl get pods
デプロイ中は以下の状態ですが、完了するとデプロイヤーのPodは消えます。
NAME READY STATUS RESTARTS AGE
capkyma-hana-deployer-6qf2w 0/1 Completed 0 13s
capkyma-srv-588798958f-gzppj 2/2 Running 0 24m
Helmのリリース
以下のコマンドでhelmのリリース一覧を照会できます。RIVISIONが2となっているのは、初回のデプロイに失敗して2度デプロイしたためです。
helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
capkyma capkyma 2 2022-08-26 06:28:33.6311764 +0900 JST deployed capkyma-1.0.0 1.0.0
リリースはKubernatesのシークレットとして保存されています。以下のコマンドで確認することができます。
kubectl get secrets
NAME TYPE DATA AGE
...
sh.helm.release.v1.capkyma.v1 helm.sh/release.v1 1 24h
sh.helm.release.v1.capkyma.v2 helm.sh/release.v1 1 23h
トラブルシューティング
最初にデプロイしたときに、以下のエラーになりました。トラブルシューティングの手順を載せておきます。
Error: failed post-install: timed out waiting for the condition
ジョブの状況確認
以下のコマンドでDBにデプロイするためのジョブの状況を確認できます。
kubectl get jobs
ジョブが正常に終了すると、結果に出てこなくなります。ジョブがずっと残っている場合は何らかの問題が発生したと考えられるので、DBデプロイヤーのログを確認します。
DBデプロイヤーのログ確認
以下のコマンドでエラーになっているPodを確認します。
kubectl get pods
NAME READY STATUS RESTARTS AGE
capkyma-hana-deployer-6s7fl 0/1 Error 0 6m16s
capkyma-hana-deployer-n5fnq 0/1 Error 0 7m46s
capkyma-hana-deployer-plfmh 0/1 Error 0 7m16s
capkyma-hana-deployer-z2nxh 0/1 Error 0 8m8s
capkyma-hana-deployer-zc9c2 0/1 Error 0 6m56s
エラーになっているPodの名前を取得して、以下のコマンドを実行します。複数ある場合は一番上のものでよいと思います。
kubectl logs <Pod名>
# 例
kubectl logs capkyma-hana-deployer-6s7fl
私の場合、以下のログが表示されました。ログの内容からHANA Cloudに接続する際に認証エラーが起きていることがわかりました。HDIコンテナのシークレットを作成したときに、値の一部が間違っていたことが原因でした。
シークレットを修正して再度デプロイした結果、正常にデプロイできました。
@sap/hdi-deploy, version 4.4.1 (mode default), server version unknown (0.0.0.0), node version 16.16.0, HDI version -1, container API version -1
Using hana-client for connection
Detection of server version failed; root cause: authentication failed
Detection of container API version failed; root cause: authentication failed
Detection of HDI version failed; root cause: authentication failed
The server does not support live updating of make messages. The messages will be displayed, when the make is done. No ignore file at /workspace/.hdiignore.
Collecting files...
Collecting files... ok (0s 2ms)
3 directories collected
7 files collected
0 reusable modules collected
Target service: hana
Could not check if session variable APPLICATION is set correctly: authentication failed
Could not determine status of last build: authentication failed
Processing revoke files...
Processing revoke files... ok (0s 0ms)
Processing grants files...
Processing grants files... ok (0s 0ms)
Preprocessing files...
Preprocessing files... ok (0s 0ms)
Connecting to the container "CAC6988D1FD049B6A3A2AE628CD6EB1C"...
Deployment to container CAC6988D1FD049B6A3A2AE628CD6EB1C failed - error: authentication failed [Deployment ID: none]. Deployment ended at 2022-08-25 21:04:50
Error: authentication failed
(2s 117ms)
kubectl logs <Pod名>
はDBデプロイヤーに限らず、例えばサービスがエラーになったときにログを確認することもできます。Cloud Foundryでいうところのcf logs <サービス名>
と同じです。