IK.AM

@making's tech note


Tanzu Application PlatformでCronJobのWorkloadを作成する

🗃 {Dev/CaaS/Kubernetes/TAP}
🏷 Kubernetes 🏷 Cartographer 🏷 kind 🏷 Tanzu 🏷 TAP 
🗓 Updated at 2023-04-11T01:16:49Z  🗓 Created at 2023-04-10T20:01:15Z   🌎 English Page

⚠️ 本記事の内容はVMwareによってサポートされていません。 記事の内容で生じた問題については自己責任で対応し、 VMwareサポート窓口には問い合わせないでください

Tanzu Application Platform (1.4時点)では、こちらのドキュメントに記載されているように、Out of the Box (OOTB) Supply Chainsにて以下のWorkload Typeがサポートサポートされています。

  • type=web ... スケーラブルなWebアプリケーションを想定したもの。KnativeのServiceリソースをが作成される。Scale to Zero、Zero to Nがサポートされる。
  • type=server ... トラディショナルなWebアプリケーションを想定したもの。K8s標準のDeployment、Serviceリソースが作成される。
  • type=worker ... キューを処理するバックグラウンドアプリケーションを想定したもの。K8s標準のDeploymentが作成される。

今回はここにtype=cronjobを追加して、K8s標準のCronJobリソースを作成できるようにします。

TAPのWorkloadはCartographerによって管理されています。 Workloadによって作成されるリソースをカスタマイズは、通常はClusterSupplyChainリソースを追加することで行えます。 ただし、1からSupply Chainを作る場合は、

  • ソースコードの取得
  • ソースコードの脆弱性スキャン
  • ソースコードのテスト
  • コンテナイメージの取得
  • コンテナイメージの脆弱性スキャン
  • マニフェストの作成
  • マニフェストのパッケージング

などなど、Supply Chainを構成するコンポーネントを定義していく必要があります。(チュートリアルはこちら) TAPのOOTB Supply Chainで定義されているものを再度定義するのは面倒くさいですね。

TAPではOOTB Supply Chainのうち、"マニフェストの作成"の部分だけをカスタマイズできるようになっています。 ドキュメントはこちらです。 ドキュメントではtype=serverのリソースに加えてIngressリソースを作る例を説明しています。 Supply Chainによって生成させたいマニフェストのテンプレートをCartographerのClusterConfigTemplateで定義すれば良いです。

こちらの記事で作成した環境で試します。

目次

ClusterConfigTemplateの定義

CronJobのテンプレートを次のようにClusterConfigTemplateに定義します。

cat <<EOF > cronjob-template.yaml
apiVersion: carto.run/v1alpha1
kind: ClusterConfigTemplate
metadata:
  name: cronjob-template
spec:
  configPath: .data
  lifecycle: mutable
  ytt: |
    #@ load("@ytt:data", "data")
    #@ load("@ytt:yaml", "yaml")
    
    #@ def merge_labels(fixed_values):
    #@   labels = {}
    #@   if hasattr(data.values.workload.metadata, "labels"):
    #@     labels.update(data.values.workload.metadata.labels)
    #@   end
    #@   labels.update(fixed_values)
    #@   return labels
    #@ end

    #@ def update_config(config):
    #@   values = {}
    #@   values.update(config)
    #@   spec = dict(values["spec"])
    #@   spec.update({"restartPolicy": data.values.params.restartPolicy if hasattr(data.values.params, "restartPolicy") else "Never"})
    #@   workload = dict(spec["containers"][0])
    #@   if hasattr(data.values.params, "command"):
    #@     workload.update({"command": data.values.params.command})
    #@   end
    #@   if hasattr(data.values.params, "args"):
    #@     workload.update({"args": data.values.params.args})
    #@   end
    #@   spec["containers"][0] = workload
    #@   values["spec"] = spec
    #@   return values
    #@ end
    
    #@ def delivery():
    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: #@ data.values.workload.metadata.name
      annotations:
        kapp.k14s.io/update-strategy: "fallback-on-replace"
        ootb.apps.tanzu.vmware.com/servicebinding-workload: "true"
        kapp.k14s.io/change-rule: "upsert after upserting servicebinding.io/ServiceBindings"
      labels: #@ merge_labels({ "app.kubernetes.io/component": "run", "carto.run/workload-name": data.values.workload.metadata.name })
    spec:
      schedule: #@ data.values.params.schedule if hasattr(data.values.params, "schedule") else "0 15 * * *"
      successfulJobsHistoryLimit: 1
      failedJobsHistoryLimit: 3
      concurrencyPolicy: Forbid
      jobTemplate:
        metadata:
          labels: #@ data.values.config.metadata.labels
        spec:
          backoffLimit: 0
          template: #@ update_config(data.values.config)
    #@ end
    
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: #@ data.values.workload.metadata.name + "-cronjob"
      labels: #@ merge_labels({ "app.kubernetes.io/component": "config" })
    data:
      delivery.yml: #@ yaml.encode(delivery())
EOF

K8s標準のCronJobではなく、Argo WorkflowsFurikoのような拡張スケジューラを使いたい場合もこのClusterConfigTemplateを変更すれば良いです。

このCronJobのmanifestは最終的にDeliverableによってデプロイされるので、Deliverableを管理するService AccountがCronJobを作成する権限を持つ必要があります。 apps.tanzu.vmware.com/aggregate-to-deliverable: "true"というラベルをClusterRoleにつければ、Deliverableを管理するService Accountにバインドされます。

cat <<EOF > deliverable-with-cronjob.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: deliverable-with-cronjob
  labels:
    apps.tanzu.vmware.com/aggregate-to-deliverable: "true"
rules:
- apiGroups:
  - batch
  resources:
  - cronjobs
  verbs:
  - get
  - list
  - watch
  - create
  - patch
  - update
  - delete
  - deletecollection
EOF

これらをapplyします。

# Muti Cluster構成の場合はBuild Clusterにて
kubectl apply -f cronjob-template.yaml
# Muti Cluster構成の場合はRun Clusterにて
kubectl apply -f deliverable-with-cronjob.yml

最後にWorkload Typeを追加するための設定をtap-values.yamlに追加します。

ootb_supply_chain_basic: # supply_chainの値がbasicの場合
# or ootb_supply_chain_testing: supply_chainの値がtestingの場合
# or ootb_supply_chain_testing_scanning: supply_chainの値がtesting_scanningの場合
  supported_workloads:
  - type: web
    cluster_config_template_name: config-template
  - type: server
    cluster_config_template_name: server-template
  - type: worker
    cluster_config_template_name: worker-template
  - type: cronjob
    cluster_config_template_name: cronjob-template # <---

tap-values.yamlの変更を反映させます。

tanzu package installed update -n tap-install tap --values-file tap-values.yaml

更新が完了すると、source-to-url Supply Chainにtype=cronjobが追加されていることがわかります。

$ tanzu apps cluster-supply-chain get source-to-url 
---
# source-to-url: Ready
---
Supply Chain Selectors
   TYPE          KEY                                   OPERATOR   VALUE
   expressions   apps.tanzu.vmware.com/workload-type   In         web
   expressions   apps.tanzu.vmware.com/workload-type   In         server
   expressions   apps.tanzu.vmware.com/workload-type   In         worker
   expressions   apps.tanzu.vmware.com/workload-type   In         cronjob

現状はService Bindingの機能が使えません。CronJobへのBindに対応していません。

(Optional) Overlaysによる設定変更

TAPをインストールした後に

kubectl apply -f cronjob-template.yaml
kubectl apply -f deliverable-with-cronjob.yml

を実行してTAPをアップデートするという手順が、宣言的でなくて好みでない場合は、overlay fileとしてClusterConfigTemplateとClusterRoleを追加すれば、 tanzu package installあるいはtanzu package installed updateでTAPをインストール/更新する際に同時にClusterConfigTemplateとClusterRoleも作成されます。

この場合は、次のようにoverlayとしてClusterConfigTemplateとClusterRoleを作成します。

# Muti Cluster構成の場合はBuild Clusterにて
kubectl -n tap-install create secret generic ootb-templates-cronjob-template \
  -o yaml \
  --dry-run=client \
  --from-file=cronjob-template.yaml \
  | kubectl apply -f-
# Muti Cluster構成の場合はRun Clusterにて
kubectl -n tap-install create secret generic tap-auth-deliverable-with-cronjob \
  -o yaml \
  --dry-run=client \
  --from-file=deliverable-with-cronjob.yml \
  | kubectl apply -f-

tap-values.yamlに以下の設定を追加。

package_overlays:
- name: ootb-templates
  secrets:
  - name: ootb-templates-cronjob-template # Muti Cluster構成の場合はBuild Clusterにて
- name: tap-auth
  secrets:
  - name: tap-auth-deliverable-with-cronjob # Muti Cluster構成の場合はRun Clusterにて

初回インストールの場合、

tanzu package install tap -p tap.tanzu.vmware.com -v 1.4.2 --values-file tap-values.yaml -n tap-install

更新の場合

tanzu package installed update -n tap-install tap --values-file tap-values.yaml

type=cronjobが使えるようになります。

CronJob Workloadの作成

いろいろなCronJobを作成してみます。

シンプルなCronJob

Kubernetesの公式ドキュメントに載っているサンプルを作成しいてみます。

次のコマンドでCronJobを作るためのWorkloadを作成します。今回は --image でCronJobで実行するコンテナイメージを指定します。

tanzu apps workload apply \
  -n demo \
  --type cronjob \
  --image ghcr.io/making/busybox \
  --param-yaml 'command=["/bin/sh", "-c", "date; echo Hello from TAP"]' \
  --param schedule="* * * * *" \
  --app cronjob-demo \
  cronjob-demo

公式ドキュメントと同じように--image busybox:1.28で実行するとImageRepositoryリソースで次のようなエラーが発生しました。 unable to pull image "busybox:1.28": Expected an Image but got: application/vnd.docker.distribution.manifest.list.v2+json 次のようなRelocationが必要でした。

docker pull busybox 
docker tag busybox ghcr.io/making/busybox
docker push busybox

しばらくするとCronJobが作成され、さらにJobが実行されます。

$ tanzu apps workload get cronjob-demo --namespace demo
📡 Overview
   name:        cronjob-demo
   type:        cronjob
   namespace:   demo

💾 Source
   type:    image
   image:   ghcr.io/making/busybox

📦 Supply Chain
   name:   basic-image-to-url

   NAME               READY   HEALTHY   UPDATED   RESOURCE
   image-provider     True    True      10m       imagerepositories.source.apps.tanzu.vmware.com/cronjob-demo
   config-provider    True    True      10m       podintents.conventions.carto.run/cronjob-demo
   app-config         True    True      10m       configmaps/cronjob-demo-cronjob
   service-bindings   True    True      10m       configmaps/cronjob-demo-with-claims
   api-descriptors    True    True      10m       configmaps/cronjob-demo-with-api-descriptors
   config-writer      True    True      10m       runnables.carto.run/cronjob-demo-config-writer

🚚 Delivery
   name:   delivery-basic

   NAME              READY   HEALTHY   UPDATED   RESOURCE
   source-provider   True    True      9m34s     imagerepositories.source.apps.tanzu.vmware.com/cronjob-demo-delivery
   deployer          True    True      60s       apps.kappctrl.k14s.io/cronjob-demo

💬 Messages
   No messages found.

🛶 Pods
   NAME                                   READY   STATUS      RESTARTS   AGE
   cronjob-demo-28018560-zdp85            0/1     Completed   0          4s
   cronjob-demo-config-writer-l68rw-pod   0/1     Completed   0          10m

To see logs: "tanzu apps workload tail cronjob-demo --namespace demo --timestamp --since 1h"

作成されたCronJobとJobを確認します。

$ kubectl get cronjob,job -n demo 
NAME                         SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/cronjob-demo   * * * * *   False     0        23s             81s

NAME                              COMPLETIONS   DURATION   AGE
job.batch/cronjob-demo-28018560   1/1           7s         23s

ログを確認します。時刻が表示されています。

$ kubectl logs -n demo cronjob-demo-28018560-zdp85 
Mon Apr 10 08:00:04 UTC 2023
Hello from TAP

schedule* * * * *なので、このJobは毎分実行されます。

確認できたらworkloadを削除します。

tanzu apps workload delete -n demo cronjob-demo

curlを実行するだけのCronJob

次のコマンドでCronJobを作るためのWorkloadを作成します。

tanzu apps workload apply \
  -n demo \
  --type cronjob \
  --image ghcr.io/making/curl \
  --param-yaml 'command=["curl"]' \
  --param-yaml 'args=["-s", "https://httpbin.org/get"]' \
  --param schedule="* * * * *" \
  --app hello-curl \
  hello-curl

しばらくするとCronJobが作成され、さらにJobが実行されます。

$ tanzu apps workload get hello-curl --namespace demo
📡 Overview
   name:        hello-curl
   type:        cronjob
   namespace:   demo

💾 Source
   type:    image
   image:   ghcr.io/making/curl

📦 Supply Chain
   name:   basic-image-to-url

   NAME               READY   HEALTHY   UPDATED   RESOURCE
   image-provider     True    True      106s      imagerepositories.source.apps.tanzu.vmware.com/hello-curl
   config-provider    True    True      102s      podintents.conventions.carto.run/hello-curl
   app-config         True    True      102s      configmaps/hello-curl-cronjob
   service-bindings   True    True      102s      configmaps/hello-curl-with-claims
   api-descriptors    True    True      102s      configmaps/hello-curl-with-api-descriptors
   config-writer      True    True      91s       runnables.carto.run/hello-curl-config-writer

🚚 Delivery
   name:   delivery-basic

   NAME              READY   HEALTHY   UPDATED   RESOURCE
   source-provider   True    True      44s       imagerepositories.source.apps.tanzu.vmware.com/hello-curl-delivery
   deployer          True    True      42s       apps.kappctrl.k14s.io/hello-curl

💬 Messages
   No messages found.

🛶 Pods
   NAME                                 READY   STATUS      RESTARTS   AGE
   hello-curl-28018564-2rlgc            0/1     Completed   0          11s
   hello-curl-config-writer-k76bd-pod   0/1     Completed   0          101s

To see logs: "tanzu apps workload tail hello-curl --namespace demo --timestamp --since 1h"

作成されたCronJobとJobを確認します。

$ kubectl get cronjob,job -n demo 
NAME                       SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/hello-curl   * * * * *   False     0        42s             76s

NAME                            COMPLETIONS   DURATION   AGE
job.batch/hello-curl-28018564   1/1           8s         42s

ログを確認します。curlの実行結果が出力されています。

$ kubectl logs -n demo hello-curl-28018564-2rlgc 
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/8.0.1-DEV", 
    "X-Amzn-Trace-Id": "Root=1-6433c2f5-5f649b191de9f1ea4e83fb8f"
  }, 
  "origin": "220.242.176.124", 
  "url": "https://httpbin.org/get"
}

確認できたらworkloadを削除します。

tanzu apps workload delete -n demo hello-curl

PythonのScriptを実行するCronJob

次はCronJobで実行するコンテナイメージをソースコードから作成します。 https://github.com/making/hello-python のPythonコードをCloud Native Buildpacksでコンテナイメージ化してCronJob実行します。

次のコマンドでCronJobを作るためのWorkloadを作成します。今回は--git-repoでソースコードのURLを指定します。

tanzu apps workload apply \
  -n demo \
  --type cronjob \
  --git-repo https://github.com/making/hello-python \
  --git-branch main \
  --param schedule="* * * * *" \
  --app hello-python \
  --label apps.tanzu.vmware.com/has-tests=true \
  hello-python

しばらくするとCronJobが作成され、さらにJobが実行されます。

$ tanzu apps workload get hello-python --namespace demo 
📡 Overview
   name:        hello-python
   type:        cronjob
   namespace:   demo

💾 Source
   type:     git
   url:      https://github.com/making/hello-python
   branch:   main

📦 Supply Chain
   name:   source-to-url

   NAME               READY   HEALTHY   UPDATED   RESOURCE
   source-provider    True    True      4m58s     gitrepositories.source.toolkit.fluxcd.io/hello-python
   image-provider     True    True      3m58s     images.kpack.io/hello-python
   config-provider    True    True      3m52s     podintents.conventions.carto.run/hello-python
   app-config         True    True      3m52s     configmaps/hello-python-cronjob
   service-bindings   True    True      3m52s     configmaps/hello-python-with-claims
   api-descriptors    True    True      3m52s     configmaps/hello-python-with-api-descriptors
   config-writer      True    True      3m38s     runnables.carto.run/hello-python-config-writer

🚚 Delivery
   name:   delivery-basic

   NAME              READY   HEALTHY   UPDATED   RESOURCE
   source-provider   True    True      2m54s     imagerepositories.source.apps.tanzu.vmware.com/hello-python-delivery
   deployer          True    True      2m52s     apps.kappctrl.k14s.io/hello-python

💬 Messages
   No messages found.

🛶 Pods
   NAME                                   READY   STATUS      RESTARTS   AGE
   hello-python-28018837-25db8            0/1     Completed   0          32s
   hello-python-build-1-build-pod         0/1     Completed   0          4m57s
   hello-python-config-writer-ch8z4-pod   0/1     Completed   0          3m50s

作成されたCronJobとJobを確認します。

$ kubectl get cronjob,job -n demo 
NAME                         SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/hello-python   * * * * *   False     0        45s             3m6s

NAME                              COMPLETIONS   DURATION   AGE
job.batch/hello-python-28018837   1/1           5s         45s

ログを確認します。

$ kubectl logs -n demo hello-python-28018837-25db8 
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.28.2", 
    "X-Amzn-Trace-Id": "Root=1-643402ed-0e6ea59220b36d3636bd2a41"
  }, 
  "origin": "220.242.176.124", 
  "url": "https://httpbin.org/get"
}

確認できたらworkloadを削除します。

tanzu apps workload delete -n demo hello-python

Spring BatchのJobを実行するCronJob

今後はSpring Batchで実装されたバッチ処理のソースコード https://github.com/making/billing-job をCloud Native Buildpacksでコンテナイメージ化してCronJob実行します。

次のコマンドでCronJobを作るためのWorkloadを作成します。

tanzu apps workload apply \
  -n demo \
  --type cronjob \
  --git-repo https://github.com/making/billing-job \
  --git-branch master \
  --param schedule="0 15 * * *" \
  --app billing-job \
  --label apps.tanzu.vmware.com/has-tests=true \
  --build-env BP_JVM_VERSION=17 \
  --env BPL_JVM_THREAD_COUNT=8 \
  --env JAVA_TOOL_OPTIONS=-Dmanagement.health.probes.enabled=false \
  billing-job

--env JAVA_TOOL_OPTIONS=-Dmanagement.health.probes.enabled=false はSpring Boot Actuatorを使った場合に自動で追加されるProbeの設定を向こうにするために追加しています。
ドキュメントはこちら

しばらくするとCronJobが作成されます。00:00 JSTに実行されるようにScheduleしたのでまだJobは作成されません。

 $ tanzu apps workload get billing-job --namespace demo
📡 Overview
   name:        billing-job
   type:        cronjob
   namespace:   demo

💾 Source
   type:     git
   url:      https://github.com/making/billing-job
   branch:   master

📦 Supply Chain
   name:   source-to-url

   NAME               READY   HEALTHY   UPDATED   RESOURCE
   source-provider    True    True      4m51s     gitrepositories.source.toolkit.fluxcd.io/billing-job
   image-provider     True    True      3m39s     images.kpack.io/billing-job
   config-provider    True    True      3m34s     podintents.conventions.carto.run/billing-job
   app-config         True    True      3m34s     configmaps/billing-job-cronjob
   service-bindings   True    True      3m33s     configmaps/billing-job-with-claims
   api-descriptors    True    True      3m33s     configmaps/billing-job-with-api-descriptors
   config-writer      True    True      3m17s     runnables.carto.run/billing-job-config-writer

🚚 Delivery
   name:   delivery-basic

   NAME              READY   HEALTHY   UPDATED   RESOURCE
   source-provider   True    True      2m48s     imagerepositories.source.apps.tanzu.vmware.com/billing-job-delivery
   deployer          True    True      2m46s     apps.kappctrl.k14s.io/billing-job

💬 Messages
   No messages found.

🛶 Pods
   NAME                                  READY   STATUS      RESTARTS   AGE
   billing-job-build-1-build-pod         0/1     Completed   0          4m52s
   billing-job-config-writer-mlhff-pod   0/1     Completed   0          3m33s

To see logs: "tanzu apps workload tail billing-job --namespace demo --timestamp --since 1h"

作成されたCronJobを確認します。

$ kubectl get cronjob,job -n demo 
NAME                        SCHEDULE     SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/billing-job   0 15 * * *   False     0        <none>          3m48s

手動でJobを作成します。

kubectl create job -n demo --from cronjob/billing-job test-run

作成されたCronJobとJobを確認します。

$ kubectl get cronjob,job -n demo 
NAME                        SCHEDULE     SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/billing-job   0 15 * * *   False     0        <none>          5m12s

NAME                 COMPLETIONS   DURATION   AGE
job.batch/test-run   1/1           13s        26s

ログを確認します。

$ kubectl logs -n demo test-run-c9r5d 
Setting Active Processor Count to 8
Calculating JVM memory based on 4528180K available memory
For more information on this calculation, see https://paketo.io/docs/reference/java-reference/#memory-calculator
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx4191438K -XX:MaxMetaspaceSize=72549K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 4528180K, Thread Count: 8, Loaded Class Count: 10395, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 124 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Dmanagement.health.probes.enabled="false" -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError -XX:ActiveProcessorCount=8 -XX:MaxDirectMemorySize=10M -Xmx4191438K -XX:MaxMetaspaceSize=72549K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enable=true

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.5)

2023-04-10T16:38:45.371Z  INFO 1 --- [           main] lol.maki.billing.BillingJobApplication   : Starting BillingJobApplication v0.0.1-SNAPSHOT using Java 17.0.6 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2023-04-10T16:38:45.376Z  INFO 1 --- [           main] lol.maki.billing.BillingJobApplication   : No active profile set, falling back to 1 default profile: "default"
2023-04-10T16:38:46.207Z  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2023-04-10T16:38:46.436Z  INFO 1 --- [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:b918459b-19ff-41d4-8f50-d482bba0dee8 user=SA
2023-04-10T16:38:46.440Z  INFO 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2023-04-10T16:38:46.829Z  INFO 1 --- [           main] lol.maki.billing.BillingJobApplication   : Started BillingJobApplication in 1.968 seconds (process running for 2.419)
2023-04-10T16:38:46.832Z  INFO 1 --- [           main] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2023-04-10T16:38:46.844Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.845Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.860Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.860Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE I1 where I1.JOB_NAME = ? and I1.JOB_INSTANCE_ID in (SELECT max(I2.JOB_INSTANCE_ID) from BATCH_JOB_INSTANCE I2 where I2.JOB_NAME = ?)]
2023-04-10T16:38:46.868Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.869Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.871Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.871Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.872Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.872Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]
2023-04-10T16:38:46.878Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.879Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]
2023-04-10T16:38:46.889Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.889Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT into BATCH_JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATED) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:46.892Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL batch update [INSERT into BATCH_JOB_EXECUTION_PARAMS(JOB_EXECUTION_ID, PARAMETER_NAME, PARAMETER_TYPE, PARAMETER_VALUE, IDENTIFYING) values (?, ?, ?, ?, ?)] with a batch size of 100
2023-04-10T16:38:46.893Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT into BATCH_JOB_EXECUTION_PARAMS(JOB_EXECUTION_ID, PARAMETER_NAME, PARAMETER_TYPE, PARAMETER_VALUE, IDENTIFYING) values (?, ?, ?, ?, ?)]
2023-04-10T16:38:46.901Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.902Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT INTO BATCH_JOB_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, JOB_EXECUTION_ID) VALUES(?, ?, ?)]
2023-04-10T16:38:46.904Z  INFO 1 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=BillingJob]] launched with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}]
2023-04-10T16:38:46.922Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.923Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:46.928Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.928Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT COUNT(*) FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?]
2023-04-10T16:38:46.932Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.932Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_JOB_EXECUTION set START_TIME = ?, END_TIME = ?,  STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:46.936Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.936Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT  SE.STEP_EXECUTION_ID, SE.STEP_NAME, SE.START_TIME, SE.END_TIME, SE.STATUS, SE.COMMIT_COUNT, SE.READ_COUNT, SE.FILTER_COUNT, SE.WRITE_COUNT, SE.EXIT_CODE, SE.EXIT_MESSAGE, SE.READ_SKIP_COUNT, SE.WRITE_SKIP_COUNT, SE.PROCESS_SKIP_COUNT, SE.ROLLBACK_COUNT, SE.LAST_UPDATED, SE.VERSION, SE.CREATE_TIME, JE.JOB_EXECUTION_ID, JE.START_TIME, JE.END_TIME, JE.STATUS, JE.EXIT_CODE, JE.EXIT_MESSAGE, JE.CREATE_TIME, JE.LAST_UPDATED, JE.VERSION from BATCH_JOB_EXECUTION JE join BATCH_STEP_EXECUTION SE      on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID where JE.JOB_INSTANCE_ID = ?      and SE.STEP_NAME = ? order by SE.CREATE_TIME desc, SE.STEP_EXECUTION_ID desc]
2023-04-10T16:38:46.940Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.940Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT COUNT(*)  from BATCH_JOB_EXECUTION JE JOIN BATCH_STEP_EXECUTION SE       on SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID where JE.JOB_INSTANCE_ID = ?      and SE.STEP_NAME = ?]
2023-04-10T16:38:46.942Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.942Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT into BATCH_STEP_EXECUTION(STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED, CREATE_TIME) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:46.943Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.943Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT INTO BATCH_STEP_EXECUTION_CONTEXT (SHORT_CONTEXT, SERIALIZED_CONTEXT, STEP_EXECUTION_ID) VALUES(?, ?, ?)]
2023-04-10T16:38:46.945Z  INFO 1 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [BilliProcessing]
2023-04-10T16:38:46.946Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.947Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:46.948Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:46.948Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:46.955Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:46.955Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.023Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL batch update [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.023Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.027Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.028Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.029Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.029Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.030Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:47.030Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.034Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing SQL batch update [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.035Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT INTO BILL_STATEMENTS (id, first_name, last_name, minutes, data_usage,bill_amount) VALUES (?, ?, ?, ?, ?, ?)]
2023-04-10T16:38:47.037Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.038Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.039Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.039Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.040Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:47.040Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.042Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.042Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE STEP_EXECUTION_ID = ?]
2023-04-10T16:38:47.045Z  INFO 1 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [BilliProcessing] executed in 99ms
2023-04-10T16:38:47.045Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.045Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_STEP_EXECUTION set START_TIME = ?, END_TIME = ?, STATUS = ?, COMMIT_COUNT = ?, READ_COUNT = ?, FILTER_COUNT = ?, WRITE_COUNT = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, READ_SKIP_COUNT = ?, PROCESS_SKIP_COUNT = ?, WRITE_SKIP_COUNT = ?, ROLLBACK_COUNT = ?, LAST_UPDATED = ? where STEP_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.046Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:47.046Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.048Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.048Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_JOB_EXECUTION_CONTEXT SET SHORT_CONTEXT = ?, SERIALIZED_CONTEXT = ? WHERE JOB_EXECUTION_ID = ?]
2023-04-10T16:38:47.051Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:47.052Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT VERSION FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID=?]
2023-04-10T16:38:47.055Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2023-04-10T16:38:47.056Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT COUNT(*) FROM BATCH_JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?]
2023-04-10T16:38:47.057Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2023-04-10T16:38:47.057Z DEBUG 1 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE BATCH_JOB_EXECUTION set START_TIME = ?, END_TIME = ?,  STATUS = ?, EXIT_CODE = ?, EXIT_MESSAGE = ?, VERSION = ?, CREATE_TIME = ?, LAST_UPDATED = ? where JOB_EXECUTION_ID = ? and VERSION = ?]
2023-04-10T16:38:47.069Z  INFO 1 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=BillingJob]] completed with the following parameters: [{'run.id':'{value=1, type=class java.lang.Long, identifying=true}'}] and the following status: [COMPLETED] in 129ms
2023-04-10T16:38:47.082Z  INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2023-04-10T16:38:47.088Z  INFO 1 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Native Memory Tracking:
...

確認できたらworkloadを削除します。

tanzu apps workload delete -n demo billing-job

TAPからCronJobを作成されるようになりました。TAPをカスタマイズすることで可能性が広がりますね。

ちなみに、このブログをbackupしてS3に保存するためのWorkloadはこちらです。


✒️️ Edit  ⏰ History  🗑 Delete