IK.AM

@making's tech note


kpack on kind (K8s in Docker)でBuild Serviceによるコンテナイメージ管理をスモールスタート

🗃 {Dev/Infrastructure/CloudNativeBuildpacks/kpack}
🏷 Cloud Native Buildpacks 🏷 Tanzu Build Service 🏷 kpack 🏷 Kubernetes 
🗓 Updated at 2021-12-21T02:20:41+09:00  🗓 Created at 2021-12-20T23:56:53+09:00 {✒️️ Edit  ⏰ History  🗑 Delete}

TUNA-JP Advent Calendar 2021 その2の20日目のエントリです。

Spring Fest 2021 で"Cloud Native Buildpacksで作る至高のコンテナイメージ for Spring Boot~ おそらくあなたの知らないBuildpack活用法 ~"という話をしました(スライド動画)。

このセッション中でCloud Native Buildpacksによるコンテナイメージのビルド・アップデートをk8s上で一括で行う kpack を紹介しました。 またコンテナイメージをビルドしたいだけなのに、k8sを運用するのは億劫だという方のために使った次のスライドでkindを使ってスモールスタートする方法を紹介しました。

image

この方法であれば余ったLinuxサーバー上にDockerをインストールするだけで、k8sを本格的に運用することなくkpackにコンテナイメージのビルドを任せることができます。

本記事ではこのkpack on kindの環境を構築する方法をメモします。

目次

Dockerのインストール

Ubuntuの例を示します。

の通りです。rootユーザーで以下を実行します。

apt-get install ca-certificates curl gnupg lsb-release -y
rm -f /usr/share/keyrings/docker-archive-keyring.gpg
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io -y

groupadd docker
usermod -aG docker jumpbox

この設定の後、sshで再ログインが必要です。

kindクラスタの作成

まずは kind クラスタを作成します。

kindコマンドを次のようにインストールします。

curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.1/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

今回はkpackでコンテナイメージをビルドしたい開発者がkindのk8sクラスタにアクセスできる必要があります。 kindはデフォルトではインストールした端末内からのみアクセスできますが、 開発者がLinuxにsshでログインしてkpackにアクセスするのは不便なので、kindのクラスタを他の端末からもアクセスできるようにします。

今回kindをインストールするサーバーのIPアドレスは次の通り、192.168.11.239です。

$ ifconfig eth0 | grep inet | awk '{print $2}'
192.168.11.239

次の設定ファイルを作成します。apiServerAddressを他の端末からアクセス可能なIPアドレスに設定するのがポイントです。

cat <<EOF > kind.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  apiServerAddress: "192.168.11.239"
  apiServerPort: 6443
EOF

次のコマンドでkindクラスタを作成します。

kind create cluster --config kind.yaml

今回は簡易的に全開発者を信用してadminのkubeconfigを配る運用とします。次のコマンドでkubeconfigを取得します。

kind get kubeconfig

次のようなYAMLが得られます。

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUd....
    server: https://192.168.11.239:6443
  name: kind-kind
contexts:
- context:
    cluster: kind-kind
    user: kind-kind
  name: kind-kind
current-context: kind-kind
kind: Config
preferences: {}
users:
- name: kind-kind
  user:
    client-certificate-data: LS0tLS1CRUd...
    client-key-data: LS0tLS1CRUdJTiBSU0E...

このYAMLを開発者の端末に保存します。ここでは$HOME/kind.yamlに保存します。

次のように、環境変数KUBECONFIGにこのパスを設定します。

export KUBECONFIG=$HOME/kind.yaml

次のように kubectl がkindのクラスタにアクセスできます。

$ kubectl cluster-info
Kubernetes control plane is running at https://192.168.11.239:6443
CoreDNS is running at https://192.168.11.239:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl get node -owide
NAME                 STATUS   ROLES                  AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION     CONTAINER-RUNTIME
kind-control-plane   Ready    control-plane,master   78m   v1.21.1   172.19.0.2    <none>        Ubuntu 21.04   5.4.0-91-generic   containerd://1.5.2

$ kubectl get pod -A -owide
NAMESPACE            NAME                                         READY   STATUS    RESTARTS   AGE     IP           NODE                 NOMINATED NODE   READINESS GATES
kube-system          coredns-558bd4d5db-4vjlx                     1/1     Running   0          9m49s   10.244.0.3   kind-control-plane   <none>           <none>
kube-system          coredns-558bd4d5db-m4qtm                     1/1     Running   0          9m50s   10.244.0.4   kind-control-plane   <none>           <none>
kube-system          etcd-kind-control-plane                      1/1     Running   0          9m54s   172.19.0.2   kind-control-plane   <none>           <none>
kube-system          kindnet-4d644                                1/1     Running   0          9m50s   172.19.0.2   kind-control-plane   <none>           <none>
kube-system          kube-apiserver-kind-control-plane            1/1     Running   0          9m54s   172.19.0.2   kind-control-plane   <none>           <none>
kube-system          kube-controller-manager-kind-control-plane   1/1     Running   0          9m54s   172.19.0.2   kind-control-plane   <none>           <none>
kube-system          kube-proxy-kk489                             1/1     Running   0          9m50s   172.19.0.2   kind-control-plane   <none>           <none>
kube-system          kube-scheduler-kind-control-plane            1/1     Running   0          9m54s   172.19.0.2   kind-control-plane   <none>           <none>
local-path-storage   local-path-provisioner-547f784dff-fcxzf      1/1     Running   0          9m50s   10.244.0.2   kind-control-plane   <none>           <none>

kpackのインストール

kubectlがkindクラスタを指している状態で、次のコマンドによりkpackをインストールします。ここではkpack 0.5.0を使用します。

kubectl apply -f https://github.com/pivotal/kpack/releases/download/v0.5.0/release-0.5.0.yaml

しばらくすると、次のように kpack namespaceに2つPodが立ち上がります。

$ kubectl get pod -A
NAMESPACE            NAME                                         READY   STATUS    RESTARTS   AGE
kpack                kpack-controller-5865df8c5f-sx4dl            1/1     Running   0          22s
kpack                kpack-webhook-65995b9f8f-wjsh7               1/1     Running   0          21s
kube-system          coredns-558bd4d5db-4vjlx                     1/1     Running   0          11m
kube-system          coredns-558bd4d5db-m4qtm                     1/1     Running   0          11m
kube-system          etcd-kind-control-plane                      1/1     Running   0          11m
kube-system          kindnet-4d644                                1/1     Running   0          11m
kube-system          kube-apiserver-kind-control-plane            1/1     Running   0          11m
kube-system          kube-controller-manager-kind-control-plane   1/1     Running   0          11m
kube-system          kube-proxy-kk489                             1/1     Running   0          11m
kube-system          kube-scheduler-kind-control-plane            1/1     Running   0          11m
local-path-storage   local-path-provisioner-547f784dff-fcxzf      1/1     Running   0          11m

kpackの設定

今回のビルドシステムで使用するClusterStore (サポートするBuildpackのコレクション)、ClusterStack (OSのベースイメージ)、ClusterBuilder (ClusterStoreとClusterStackの組み合わせ)を定義します。

ClusterBuilderリソースによってCloud Native Buildpacksのbuilderが作成されます。このbuilderはコンテナレジストリにpushされます。 push先のコンテナレジストリとして今回はghcr.ioを使用します。次のアカウントを使用します。

export GITHUB_USERNAME=making
export GITHUB_API_TOKEN=*************

docker login ghcr.io -u ${GITHUB_USERNAME} -p ${GITHUB_API_TOKEN}

次のコマンドで、このレジストリのcredentialsをSecretに登録し、Service Accountのsecrets及びimagePullSecretsに設定します。

cat <<EOF > dockerconfig.yaml
apiVersion: v1
kind: Secret
metadata:
  name: regsecret
  namespace: default
type: kubernetes.io/dockerconfigjson
stringData:
  .dockerconfigjson: |
    {
      "auths": {
        "https://ghcr.io": {
          "username": "${GITHUB_USERNAME}",
          "password": "${GITHUB_API_TOKEN}"
        }
      }
    }
EOF
kubectl apply -f dockerconfig.yaml
kubectl patch -n default serviceaccount default -p "{\"secrets\":[{\"name\":\"regsecret\"}],\"imagePullSecrets\":[{\"name\":\"regsecret\"}]}"

ghcr.io以外のコンテナレジストリを使用する場合は適宜変更してください。

AWS Elastic Container Registry (ECR)を使用する場合は、パスワードが定期的に切れるので、以下のような仕組みを使用して定期的にパスワード更新が必要です。

次のようにClusterStore、ClusterStack、ClusterBuilderを定義します。 今回はJava Buildpackのみインストールします。

cat <<EOF > clusterbuilder.yaml
apiVersion: kpack.io/v1alpha2
kind: ClusterStore
metadata:
  name: default
spec:
  sources:
  - image: gcr.io/paketo-buildpacks/java:6.2.1
---
apiVersion: kpack.io/v1alpha2
kind: ClusterStack
metadata:
  name: base
spec:
  id: io.buildpacks.stacks.bionic
  buildImage:
    image: paketobuildpacks/build:1.1.38-base-cnb
  runImage:
    image: paketobuildpacks/run:1.1.38-base-cnb
---
apiVersion: kpack.io/v1alpha2
kind: ClusterBuilder
metadata:
  name: base
spec:
  tag: ghcr.io/${GITHUB_USERNAME}/kpack/clusterbuilder:base
  stack:
    name: base
    kind: ClusterStack
  store:
    name: default
    kind: ClusterStore
  serviceAccountRef:
    name: default
    namespace: default    
  order:
  - group:
    - id: paketo-buildpacks/java
EOF
kubectl apply -f clusterbuilder.yaml 

ここではbuildpackもstackも特定のバージョンをタグで固定しています。定義時はバージョンを固定した方が管理しやすいです。

しばらくすると、builderが作成され、次のコマンドのようにclusterbuilderの結果でイメージ名を確認できます。

$ kubectl get clusterbuilder
NAME   LATESTIMAGE                                                                                                        READY
base   ghcr.io/making/kpack/clusterbuilder:base@sha256:294048d99b113c675f8417a406e5a34593034be0ec0f18ca2aa4d9a84c9aa3f7   True

ClusterBuilderの詳細を見ると、builderに含まれるBuildpackやStackの情報を見ることができます。

$ kubectl get clusterbuilder base -oyaml
apiVersion: kpack.io/v1alpha2
kind: ClusterBuilder
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"kpack.io/v1alpha2","kind":"ClusterBuilder","metadata":{"annotations":{},"name":"base"},"spec":{"order":[{"group":[{"id":"paketo-buildpacks/java","version":"6.2.1"}]}],"serviceAccountRef":{"name":"default","namespace":"default"},"stack":{"kind":"ClusterStack","name":"base"},"store":{"kind":"ClusterStore","name":"default"},"tag":"ghcr.io/making/kpack/clusterbuilder:base"}}
  creationTimestamp: "2021-12-20T14:26:30Z"
  generation: 4
  name: base
  resourceVersion: "4732"
  uid: ecc4eed8-9e25-446c-88e9-9c48c392fe86
spec:
  order:
  - group:
    - id: paketo-buildpacks/java
      version: 6.2.1
  serviceAccountRef:
    name: default
    namespace: default
  stack:
    kind: ClusterStack
    name: base
  store:
    kind: ClusterStore
    name: default
  tag: ghcr.io/making/kpack/clusterbuilder:base
status:
  builderMetadata:
  - homepage: https://github.com/paketo-buildpacks/bellsoft-liberica
    id: paketo-buildpacks/bellsoft-liberica
    version: 9.0.1
  - homepage: https://github.com/paketo-buildpacks/spring-boot
    id: paketo-buildpacks/spring-boot
    version: 5.2.0
  - homepage: https://github.com/paketo-buildpacks/apache-tomcat
    id: paketo-buildpacks/apache-tomcat
    version: 7.0.2
  - homepage: https://github.com/paketo-buildpacks/google-stackdriver
    id: paketo-buildpacks/google-stackdriver
    version: 5.1.0
  - homepage: https://github.com/paketo-buildpacks/ca-certificates
    id: paketo-buildpacks/ca-certificates
    version: 3.0.1
  - homepage: https://github.com/paketo-buildpacks/azure-application-insights
    id: paketo-buildpacks/azure-application-insights
    version: 5.1.1
  - homepage: https://github.com/paketo-buildpacks/procfile
    id: paketo-buildpacks/procfile
    version: 5.0.1
  - homepage: https://github.com/paketo-buildpacks/encrypt-at-rest
    id: paketo-buildpacks/encrypt-at-rest
    version: 4.0.1
  - homepage: https://github.com/paketo-buildpacks/maven
    id: paketo-buildpacks/maven
    version: 6.0.1
  - homepage: https://github.com/paketo-buildpacks/sbt
    id: paketo-buildpacks/sbt
    version: 6.0.2
  - homepage: https://github.com/paketo-buildpacks/gradle
    id: paketo-buildpacks/gradle
    version: 6.0.1
  - homepage: https://github.com/paketo-buildpacks/clojure-tools
    id: paketo-buildpacks/clojure-tools
    version: 2.0.1
  - homepage: https://github.com/paketo-buildpacks/leiningen
    id: paketo-buildpacks/leiningen
    version: 4.0.1
  - homepage: https://github.com/paketo-buildpacks/watchexec
    id: paketo-buildpacks/watchexec
    version: 2.0.1
  - homepage: https://github.com/paketo-buildpacks/syft
    id: paketo-buildpacks/syft
    version: 1.2.0
  - homepage: https://github.com/paketo-buildpacks/executable-jar
    id: paketo-buildpacks/executable-jar
    version: 6.0.1
  - homepage: https://github.com/paketo-buildpacks/dist-zip
    id: paketo-buildpacks/dist-zip
    version: 5.0.1
  - homepage: https://github.com/paketo-buildpacks/environment-variables
    id: paketo-buildpacks/environment-variables
    version: 4.0.1
  - homepage: https://github.com/paketo-buildpacks/image-labels
    id: paketo-buildpacks/image-labels
    version: 4.0.1
  - homepage: https://github.com/paketo-buildpacks/java
    id: paketo-buildpacks/java
    version: 6.2.1
  conditions:
  - lastTransitionTime: "2021-12-20T14:31:10Z"
    status: "True"
    type: Ready
  latestImage: ghcr.io/making/kpack/clusterbuilder:base@sha256:294048d99b113c675f8417a406e5a34593034be0ec0f18ca2aa4d9a84c9aa3f7
  observedGeneration: 4
  observedStackGeneration: 1
  observedStoreGeneration: 2
  order:
  - group:
    - id: paketo-buildpacks/java
      version: 6.2.1
  os: linux
  stack:
    id: io.buildpacks.stacks.bionic
    runImage: index.docker.io/paketobuildpacks/run@sha256:f9e78e309fe5af1d376d3ce4593e3d25260604e4a62430dad7ec65b11289cf89

ghcr.io上でもbuilderがpushされていることを確認できます。

image

Imageの作成

早速kpackでイメージを作成します。ここでは次のサンプルアプリをビルドします。必要に応じてforkしてください。

https://github.com/making/reward-dining

kp CLIを使うことkpackにImageリソース作成が簡単に行えます。 こちら からバイナリをダウンロードしてPATHの通ったディレクトリに配置してください。

次のコマンドでkpackにImageリソースを作成ます。

kp image save reward-dining --tag ghcr.io/${GITHUB_USERNAME}/reward-dining --git https://github.com/making/reward-dining.git --git-revision main --watch

次のようなログが出力され、コンテナイメージのビルドが始まります。初回はダウンロード待ちなどで完了までに時間がかかります。二回目以降はキャッシュが働くので速くなります。

Creating Image Resource...
Image Resource "reward-dining" created
===> PREPARE
Build reason(s): CONFIG
CONFIG:
    resources: {}
    - source: {}
    + source:
    +   git:
    +     revision: 4518c9348168be38c8b91da4380d82e1a9b5e58e
    +     url: https://github.com/making/reward-dining.git
Loading secret for "https://ghcr.io" from secret "regsecret" at location "/var/build-secrets/regsecret"
Cloning "https://github.com/making/reward-dining.git" @ "4518c9348168be38c8b91da4380d82e1a9b5e58e"...
Successfully cloned "https://github.com/making/reward-dining.git" @ "4518c9348168be38c8b91da4380d82e1a9b5e58e" in path "/workspace"
===> ANALYZE
Previous image with name "ghcr.io/making/reward-dining" not found
===> DETECT
8 of 19 buildpacks participating
paketo-buildpacks/ca-certificates   3.0.1
paketo-buildpacks/bellsoft-liberica 9.0.1
paketo-buildpacks/syft              1.2.0
paketo-buildpacks/maven             6.0.1
paketo-buildpacks/executable-jar    6.0.1
paketo-buildpacks/apache-tomcat     7.0.2
paketo-buildpacks/dist-zip          5.0.1
paketo-buildpacks/spring-boot       5.2.0
===> RESTORE
===> BUILD

Paketo CA Certificates Buildpack 3.0.1
  https://github.com/paketo-buildpacks/ca-certificates
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_ca-certificates/helper/exec.d/ca-certificates-helper

Paketo BellSoft Liberica Buildpack 9.0.1
  https://github.com/paketo-buildpacks/bellsoft-liberica
  Build Configuration:
    $BP_JVM_TYPE                 JRE             the JVM type - JDK or JRE
    $BP_JVM_VERSION              11              the Java version
  Launch Configuration:
    $BPL_DEBUG_ENABLED           false           enables Java remote debugging support
    $BPL_DEBUG_PORT              8000            configure the remote debugging port
    $BPL_DEBUG_SUSPEND           false           configure whether to suspend execution until a debugger has attached
    $BPL_HEAP_DUMP_PATH                          write heap dumps on error to this path
    $BPL_JAVA_NMT_ENABLED        true            enables Java Native Memory Tracking (NMT)
    $BPL_JAVA_NMT_LEVEL          summary         configure level of NMT, summary or detail
    $BPL_JFR_ARGS                                configure custom Java Flight Recording (JFR) arguments
    $BPL_JFR_ENABLED             false           enables Java Flight Recording (JFR)
    $BPL_JMX_ENABLED             false           enables Java Management Extensions (JMX)
    $BPL_JMX_PORT                5000            configure the JMX port
    $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    $JAVA_TOOL_OPTIONS                           the JVM launch flags
  BellSoft Liberica JDK 11.0.13: Contributing to layer
    Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.13+8/bellsoft-jdk11.0.13+8-linux-amd64.tar.gz
    Verifying checksum
    Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jdk
    Adding 128 container CA certificates to JVM truststore
    Writing env.build/JAVA_HOME.override
    Writing env.build/JDK_HOME.override
  BellSoft Liberica JRE 11.0.13: Contributing to layer
    Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.13+8/bellsoft-jre11.0.13+8-linux-amd64.tar.gz
    Verifying checksum
    Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jre
    Adding 128 container CA certificates to JVM truststore
    Writing env.launch/BPI_APPLICATION_PATH.default
    Writing env.launch/BPI_JVM_CACERTS.default
    Writing env.launch/BPI_JVM_CLASS_COUNT.default
    Writing env.launch/BPI_JVM_SECURITY_PROVIDERS.default
    Writing env.launch/JAVA_HOME.default
    Writing env.launch/JAVA_TOOL_OPTIONS.append
    Writing env.launch/JAVA_TOOL_OPTIONS.delim
    Writing env.launch/MALLOC_ARENA_MAX.default
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/active-processor-count
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/java-opts
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/jvm-heap
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/link-local-dns
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/openssl-certificate-loader
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/security-providers-configurer
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/jmx
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/jfr
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/nmt
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/security-providers-classpath-9
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/debug-9
  Java Security Properties: Contributing to layer
    Writing env.launch/JAVA_SECURITY_PROPERTIES.default
    Writing env.launch/JAVA_TOOL_OPTIONS.append
    Writing env.launch/JAVA_TOOL_OPTIONS.delim

Paketo Syft Buildpack 1.2.0
  https://github.com/paketo-buildpacks/syft
    Downloading from https://github.com/anchore/syft/releases/download/v0.32.0/syft_0.32.0_linux_amd64.tar.gz
    Verifying checksum

Paketo Maven Buildpack 6.0.1
  https://github.com/paketo-buildpacks/maven
  Build Configuration:
    $BP_MAVEN_BUILD_ARGUMENTS  -Dmaven.test.skip=true package  the arguments to pass to Maven
    $BP_MAVEN_BUILT_ARTIFACT   target/*.[ejw]ar                the built application artifact explicitly.  Supersedes $BP_MAVEN_BUILT_MODULE
    $BP_MAVEN_BUILT_MODULE                                     the module to find application artifact in
    $BP_MAVEN_POM_FILE         pom.xml                         the location of the main pom.xml file, relative to the application root
    Creating cache directory /home/cnb/.m2
  Compiled Application: Contributing to layer
    Executing mvnw --batch-mode -Dmaven.test.skip=true package
      [INFO] Scanning for projects...
      [INFO] Downloading from spring-releases: https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.5.6/spring-boot-starter-parent-2.5.6.pom
      [INFO] Downloaded from spring-releases: https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.5.6/spring-boot-starter-parent-2.5.6.pom (8.6 kB at 2.4 kB/s)
      ....
      [INFO] Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar (500 kB at 229 kB/s)
      [INFO] Replacing main artifact with repackaged archive
      [INFO] ------------------------------------------------------------------------
      [INFO] BUILD SUCCESS
      [INFO] ------------------------------------------------------------------------
      [INFO] Total time:  04:48 min
      [INFO] Finished at: 2021-12-20T14:46:43Z
      [INFO] ------------------------------------------------------------------------
  Removing source code

Paketo Executable JAR Buildpack 6.0.1
  https://github.com/paketo-buildpacks/executable-jar
  Class Path: Contributing to layer
    Writing env/CLASSPATH.delim
    Writing env/CLASSPATH.prepend
  Process types:
    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
    task:           java org.springframework.boot.loader.JarLauncher (direct)
    web:            java org.springframework.boot.loader.JarLauncher (direct)

Paketo Spring Boot Buildpack 5.2.0
  https://github.com/paketo-buildpacks/spring-boot
  Creating slices from layers index
    dependencies
    spring-boot-loader
    snapshot-dependencies
    application
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings
  Spring Cloud Bindings 1.8.0: Contributing to layer
    Downloading from https://repo.spring.io/release/org/springframework/cloud/spring-cloud-bindings/1.8.0/spring-cloud-bindings-1.8.0.jar
    Verifying checksum
    Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings
  Web Application Type: Contributing to layer
    Servlet web application detected
    Writing env.launch/BPL_JVM_THREAD_COUNT.default
  4 application slices
  Image labels:
    org.opencontainers.image.title
    org.opencontainers.image.version
    org.springframework.boot.version
===> EXPORT
Adding layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/bellsoft-liberica:helper'
Adding layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'
Adding layer 'paketo-buildpacks/bellsoft-liberica:jre'
Adding layer 'paketo-buildpacks/executable-jar:classpath'
Adding layer 'paketo-buildpacks/spring-boot:helper'
Adding layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'
Adding layer 'paketo-buildpacks/spring-boot:web-application-type'
Adding layer 'launch.sbom'
Adding 5/5 app layer(s)
Adding layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Adding label 'org.opencontainers.image.title'
Adding label 'org.opencontainers.image.version'
Adding label 'org.springframework.boot.version'
Setting default process type 'web'
Saving ghcr.io/making/reward-dining...
*** Images (sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6):
      ghcr.io/making/reward-dining
      ghcr.io/making/reward-dining:b1.20211220.144029
Adding cache layer 'paketo-buildpacks/bellsoft-liberica:jdk'
Adding cache layer 'paketo-buildpacks/syft:syft'
Adding cache layer 'paketo-buildpacks/maven:application'
Adding cache layer 'paketo-buildpacks/maven:cache'
Adding cache layer 'cache.sbom'
===> COMPLETION
Build successful

ログからghcr.io/making/reward-dining:b1.20211220.144029というコンテナイメージが作成されたことがわかります。

image

dockerでこのイメージを起動しましょう。

docker run --rm -p 8080:8080 ghcr.io/${GITHUB_USERNAME}/reward-dining

次のログが出力され、アプリが起動します。

Setting Active Processor Count to 8
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx429124K -XX:MaxMetaspaceSize=107451K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 1G, Thread Count: 250, Loaded Class Count: 16557, Headroom: 0%)
Enabling Java Native Memory Tracking
Adding 128 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -XX:+ExitOnOutOfMemoryError -XX:ActiveProcessorCount=8 -XX:MaxDirectMemorySize=10M -Xmx429124K -XX:MaxMetaspaceSize=107451K -XX:ReservedCodeCacheSize=240M -Xss1M -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+PrintNMTStatistics -Dorg.springframework.cloud.bindings.boot.enable=true

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

2021-12-20 14:54:00.536  INFO [reward-dining,,] 1 --- [           main] l.m.r.RewardDiningApplication            : Starting RewardDiningApplication v0.0.1-SNAPSHOT using Java 11.0.13 on 929fefdf40e3 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-12-20 14:54:00.540  INFO [reward-dining,,] 1 --- [           main] l.m.r.RewardDiningApplication            : No active profile set, falling back to default profiles: default
2021-12-20 14:54:01.544  INFO [reward-dining,,] 1 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=183768df-74c8-321a-88bd-1a0c94396110
2021-12-20 14:54:02.089  INFO [reward-dining,,] 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-12-20 14:54:02.098  INFO [reward-dining,,] 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-12-20 14:54:02.098  INFO [reward-dining,,] 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.54]
2021-12-20 14:54:02.153  INFO [reward-dining,,] 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-12-20 14:54:02.153  INFO [reward-dining,,] 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1572 ms
2021-12-20 14:54:02.727  INFO [reward-dining,,] 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-12-20 14:54:02.892  INFO [reward-dining,,] 1 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-12-20 14:54:03.483  INFO [reward-dining,,] 1 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2021-12-20 14:54:03.786  INFO [reward-dining,,] 1 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint(s) beneath base path '/actuator'
2021-12-20 14:54:03.814  INFO [reward-dining,,] 1 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Will secure Mvc [pattern='/resources/**'] with []
2021-12-20 14:54:03.861  INFO [reward-dining,,] 1 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@718ad3a6, org.springframework.security.web.context.SecurityContextPersistenceFilter@575d48db, org.springframework.security.web.header.HeaderWriterFilter@3c9ef37b, org.springframework.web.filter.CommonsRequestLoggingFilter@603c2dee, org.springframework.security.web.csrf.CsrfFilter@54737322, org.springframework.security.web.authentication.logout.LogoutFilter@4efed0e0, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@73aae7a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@495e8a3, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3a3bc0da, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@50d666a2, org.springframework.security.web.session.SessionManagementFilter@51f4439e, org.springframework.security.web.access.ExceptionTranslationFilter@5b895e76, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@6fc28e5b]
2021-12-20 14:54:04.042  INFO [reward-dining,,] 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-12-20 14:54:04.060  INFO [reward-dining,,] 1 --- [           main] l.m.r.RewardDiningApplication            : Started RewardDiningApplication in 3.939 seconds (JVM running for 4.287)

ブラウザで http://localhost:8080 にアクセスすると次のような画面が表示されます。 image

kpackによって管理されているImageやBuild結果はkp CLIで次のように確認できます。

$ kp image list
NAME             READY    LATEST REASON    LATEST IMAGE                                                                                            NAMESPACE
reward-dining    True     CONFIG           ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    default

$ kp build list
BUILD    STATUS     BUILT IMAGE                                                                                             REASON    IMAGE RESOURCE
1        SUCCESS    ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG    reward-dining

kubectlでも次のように確認できます。

$ kubectl get image,build
NAME                           LATESTIMAGE                                                                                            READY
image.kpack.io/reward-dining   ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6   True

NAME                                   IMAGE                                                                                                  SUCCEEDED
build.kpack.io/reward-dining-build-1   ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6   True

ソースコードのアップデート

https://github.com/making/reward-dining/commit/60ae941452421948a4d4432ab025ea56a09ce843 のコミットでSpring Bootのバージョンを2.5.6から2.5.7にアップデートしました。

Image作成の際に--git-branch mainを指定しており、このブランチにコミットが追加されると、そのソースコードに対して自動でビルドが行われます。

コミットの後、しばらくすると、次のようにSTATUSBUILDINGがbuildリソースが作成されます。

$ kp build list
BUILD    STATUS      BUILT IMAGE                                                                                             REASON    IMAGE RESOURCE
1        SUCCESS     ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG    reward-dining
2        BUILDING

次のコマンドでbuildのログを確認できます。

$ kp build logs reward-dining -b 2
===> PREPARE
Build reason(s): COMMIT
COMMIT:
    - 4518c9348168be38c8b91da4380d82e1a9b5e58e
    + 60ae941452421948a4d4432ab025ea56a09ce843
Loading secret for "https://ghcr.io" from secret "regsecret" at location "/var/build-secrets/regsecret"
Cloning "https://github.com/making/reward-dining.git" @ "60ae941452421948a4d4432ab025ea56a09ce843"...
Successfully cloned "https://github.com/making/reward-dining.git" @ "60ae941452421948a4d4432ab025ea56a09ce843" in path "/workspace"
===> ANALYZE
===> DETECT
8 of 19 buildpacks participating
paketo-buildpacks/ca-certificates   3.0.1
paketo-buildpacks/bellsoft-liberica 9.0.1
paketo-buildpacks/syft              1.2.0
paketo-buildpacks/maven             6.0.1
paketo-buildpacks/executable-jar    6.0.1
paketo-buildpacks/apache-tomcat     7.0.2
paketo-buildpacks/dist-zip          5.0.1
paketo-buildpacks/spring-boot       5.2.0
===> RESTORE
Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:helper" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:java-security-properties" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jre" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jdk" from cache
Restoring metadata for "paketo-buildpacks/syft:syft" from cache
Restoring metadata for "paketo-buildpacks/maven:cache" from cache
Restoring metadata for "paketo-buildpacks/maven:application" from cache
Restoring metadata for "paketo-buildpacks/spring-boot:helper" from app image
Restoring metadata for "paketo-buildpacks/spring-boot:spring-cloud-bindings" from app image
Restoring metadata for "paketo-buildpacks/spring-boot:web-application-type" from app image
Restoring data for "paketo-buildpacks/bellsoft-liberica:jdk" from cache
Restoring data for "paketo-buildpacks/syft:syft" from cache
Restoring data for "paketo-buildpacks/maven:application" from cache
Restoring data for "paketo-buildpacks/maven:cache" from cache
===> BUILD

Paketo CA Certificates Buildpack 3.0.1
  https://github.com/paketo-buildpacks/ca-certificates
  Launch Helper: Reusing cached layer

Paketo BellSoft Liberica Buildpack 9.0.1
  https://github.com/paketo-buildpacks/bellsoft-liberica
  Build Configuration:
    $BP_JVM_TYPE                 JRE             the JVM type - JDK or JRE
    $BP_JVM_VERSION              11              the Java version
  Launch Configuration:
    $BPL_DEBUG_ENABLED           false           enables Java remote debugging support
    $BPL_DEBUG_PORT              8000            configure the remote debugging port
    $BPL_DEBUG_SUSPEND           false           configure whether to suspend execution until a debugger has attached
    $BPL_HEAP_DUMP_PATH                          write heap dumps on error to this path
    $BPL_JAVA_NMT_ENABLED        true            enables Java Native Memory Tracking (NMT)
    $BPL_JAVA_NMT_LEVEL          summary         configure level of NMT, summary or detail
    $BPL_JFR_ARGS                                configure custom Java Flight Recording (JFR) arguments
    $BPL_JFR_ENABLED             false           enables Java Flight Recording (JFR)
    $BPL_JMX_ENABLED             false           enables Java Management Extensions (JMX)
    $BPL_JMX_PORT                5000            configure the JMX port
    $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    $JAVA_TOOL_OPTIONS                           the JVM launch flags
  BellSoft Liberica JDK 11.0.13: Reusing cached layer
  BellSoft Liberica JRE 11.0.13: Reusing cached layer
  Launch Helper: Reusing cached layer
  Java Security Properties: Reusing cached layer

Paketo Syft Buildpack 1.2.0
  https://github.com/paketo-buildpacks/syft

Paketo Maven Buildpack 6.0.1
  https://github.com/paketo-buildpacks/maven
  Build Configuration:
    $BP_MAVEN_BUILD_ARGUMENTS  -Dmaven.test.skip=true package  the arguments to pass to Maven
    $BP_MAVEN_BUILT_ARTIFACT   target/*.[ejw]ar                the built application artifact explicitly.  Supersedes $BP_MAVEN_BUILT_MODULE
    $BP_MAVEN_BUILT_MODULE                                     the module to find application artifact in
    $BP_MAVEN_POM_FILE         pom.xml                         the location of the main pom.xml file, relative to the application root
    Creating cache directory /home/cnb/.m2
  Compiled Application: Contributing to layer
    Executing mvnw --batch-mode -Dmaven.test.skip=true package
      [INFO] Scanning for projects...
      [INFO] Downloading from spring-releases: https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.5.7/spring-boot-starter-parent-2.5.7.pom
      ...
      [INFO] Replacing main artifact with repackaged archive
      [INFO] ------------------------------------------------------------------------
      [INFO] BUILD SUCCESS
      [INFO] ------------------------------------------------------------------------
      [INFO] Total time:  28.577 s
      [INFO] Finished at: 2021-12-20T16:13:56Z
      [INFO] ------------------------------------------------------------------------
  Removing source code

Paketo Executable JAR Buildpack 6.0.1
  https://github.com/paketo-buildpacks/executable-jar
  Class Path: Contributing to layer
    Writing env/CLASSPATH.delim
    Writing env/CLASSPATH.prepend
  Process types:
    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
    task:           java org.springframework.boot.loader.JarLauncher (direct)
    web:            java org.springframework.boot.loader.JarLauncher (direct)

Paketo Spring Boot Buildpack 5.2.0
  https://github.com/paketo-buildpacks/spring-boot
  Creating slices from layers index
    dependencies
    spring-boot-loader
    snapshot-dependencies
    application
  Launch Helper: Reusing cached layer
  Spring Cloud Bindings 1.8.0: Reusing cached layer
  Web Application Type: Contributing to layer
    Servlet web application detected
    Writing env.launch/BPL_JVM_THREAD_COUNT.default
  4 application slices
  Image labels:
    org.opencontainers.image.title
    org.opencontainers.image.version
    org.springframework.boot.version
===> EXPORT
Reusing layers from image 'ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6'
Reusing layer 'paketo-buildpacks/ca-certificates:helper'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:helper'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:jre'
Reusing layer 'paketo-buildpacks/executable-jar:classpath'
Reusing layer 'paketo-buildpacks/spring-boot:helper'
Reusing layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'
Reusing layer 'paketo-buildpacks/spring-boot:web-application-type'
Adding layer 'launch.sbom'
Reusing 3/5 app layer(s)
Adding 2/5 app layer(s)
Reusing layer 'launcher'
Adding layer 'config'
Reusing layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Adding label 'org.opencontainers.image.title'
Adding label 'org.opencontainers.image.version'
Adding label 'org.springframework.boot.version'
Setting default process type 'web'
Saving ghcr.io/making/reward-dining...
*** Images (sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f):
      ghcr.io/making/reward-dining
      ghcr.io/making/reward-dining:b2.20211220.161253
Reusing cache layer 'paketo-buildpacks/bellsoft-liberica:jdk'
Reusing cache layer 'paketo-buildpacks/syft:syft'
Adding cache layer 'paketo-buildpacks/maven:application'
Adding cache layer 'paketo-buildpacks/maven:cache'
Reusing cache layer 'cache.sbom'
===> COMPLETION
Build successful

ghcr.io/making/reward-dining:b2.20211220.161253というイメージが作成されました。 キャッシュが効いているので一回目よりもビルドが早く終わりました。

imageまたはbuildリソースを確認すると、次のようにLATEST REASON/REASONCOMMITになっていることが分かります。これはwatchしているbranchに新規のコミットが追加されたことをトリガーにビルドが始まったことを意味します。

$ kp image list                    
NAME             READY    LATEST REASON    LATEST IMAGE                                                                                            NAMESPACE
reward-dining    True     COMMIT           ghcr.io/making/reward-dining@sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f    default

$ kp build list                                                                                                                        
BUILD    STATUS     BUILT IMAGE                                                                                             REASON    IMAGE RESOURCE
1        SUCCESS    ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG    reward-dining
2        SUCCESS    ghcr.io/making/reward-dining@sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f    COMMIT    reward-dining

kpackでソースコードの変更に追従してイメージの自動ビルドができることを確認できました。

この機能は便利ですが、CIと連携したい場合は、例えばユニットテストが完了した後にコンテナイメージをビルドしたいと思うので、その場合はbranchのwatchはやめて、 次のようにgitのcommitを指定して毎コミットCIジョブとしてkpコマンドを実行するのが良いです。

# Jenkinsの例
kp image save reward-dining --tag ghcr.io/${GITHUB_USERNAME}/reward-dining --git https://github.com/making/reward-dining.git --git-revision ${GIT_COMMIT} --watch

# GitLab CIの例
kp image save reward-dining --tag ghcr.io/${GITHUB_USERNAME}/reward-dining --git https://github.com/making/reward-dining.git --git-revision ${CI_COMMIT_SHA} --watch

# GitHub Actionsの例
kp image save reward-dining --tag ghcr.io/${GITHUB_USERNAME}/reward-dining --git https://github.com/making/reward-dining.git --git-revision ${GITHUB_SHA} --watch

詳細は次のドキュメントを確認してください。
https://docs.vmware.com/en/Tanzu-Build-Service/1.3/vmware-tanzu-build-service-v13/GUID-tbs-in-ci.html

ClusterStackのアップデート

ClusterStackをアップデートします。OSのベースイメージの脆弱性Fixなどを想定します。 初回は1.1.38-base-cnbというタグのイメージを使用したので、今回は次のバージョンの1.1.39-base-cnbを使用します。

次のコマンドでClusterStackをアップデートします。

cat <<EOF > clusterstack.yaml
apiVersion: kpack.io/v1alpha2
kind: ClusterStack
metadata:
  name: base
spec:
  id: io.buildpacks.stacks.bionic
  buildImage:
    image: paketobuildpacks/build:1.1.39-base-cnb
  runImage:
    image: paketobuildpacks/run:1.1.39-base-cnb
EOF
kubectl apply -f clusterstack.yaml 

しばらくすると次のように新たにbuildリソースが作成されます。

$ kp build list                       
BUILD    STATUS      BUILT IMAGE                                                                                             REASON    IMAGE RESOURCE
1        SUCCESS     ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG    reward-dining
2        SUCCESS     ghcr.io/making/reward-dining@sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f    COMMIT    reward-dining
3        BUILDING                                                                                                            STACK     reward-dining

次のコマンドでログを確認すると、ベースイメージのrebaseが行われていることがわかります。

$ kp build logs reward-dining -b 3
===> REBASE
Build reason(s): STACK
STACK:
    - sha256:f9e78e309fe5af1d376d3ce4593e3d25260604e4a62430dad7ec65b11289cf89
    + sha256:50c74ebc95c169ea54ee4650d39d3c71d0fc738a3f0ad89b23d646cfd9ea36f2
Loading secret for "https://ghcr.io" from secret "regsecret" at location "/var/build-secrets/regsecret"
*** Images (sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95):
      ghcr.io/making/reward-dining
      ghcr.io/making/reward-dining:b3.20211220.165203

*** Digest: sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95
===> COMPLETION
Build successful

ghcr.io/making/reward-dining:b3.20211220.165203というイメージが、ベースイメージが自動でアップデートされた新しいイメージです。

imageまたはbuildリソースを確認すると、次のようにLATEST REASON/REASONSTACKになっていることが分かります。ベースイメージの変更に伴ったリソースの更新であることを意味します。

$ kp build list
BUILD    STATUS     BUILT IMAGE                                                                                             REASON    IMAGE RESOURCE
1        SUCCESS    ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG    reward-dining
2        SUCCESS    ghcr.io/making/reward-dining@sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f    COMMIT    reward-dining
3        SUCCESS    ghcr.io/making/reward-dining@sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95    STACK     reward-dining

$ kp image list
NAME             READY    LATEST REASON    LATEST IMAGE                                                                                            NAMESPACE
reward-dining    True     STACK            ghcr.io/making/reward-dining@sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95    default

ClusterBuilderも更新されます。

$ kubectl get clusterbuilder
NAME   LATESTIMAGE                                                                                                        READY
base   ghcr.io/making/kpack/clusterbuilder:base@sha256:accced241e26b3ce3dd3eaf2305812e4d5e9479a3b6e80ad4acb27b90f4e4265   True

このようにClusterStackを更新するだけで新しいOSイメージを使用したコンテナイメージを自動で作成することができます。 これはkpackで管理しているimageのうち同じClusterStackを使用しているもの全てが対象になるので、一括でイメージをよりセキュアにすることができ、管理が楽になります。

ClusterStackのアップデート

ClusterStackの更新と同じようにClusterStoreをアップデートします。Buildpackにアップデートがあった場合にこの作業を行います。 初回はJava Buildpackのイメージにgcr.io/paketo-buildpacks/java:6.2.1を使用したので、今回は次のバージョンのgcr.io/paketo-buildpacks/java:6.3.0を使用します。

cat <<EOF > clusterstore.yaml
apiVersion: kpack.io/v1alpha2
kind: ClusterStore
metadata:
  name: default
spec:
  sources:
  - image: gcr.io/paketo-buildpacks/java:6.3.0
EOF
kubectl apply -f clusterstore.yaml 

しばらくすると次のように新たにbuildリソースが作成されます。

$ kp build list
BUILD    STATUS      BUILT IMAGE                                                                                             REASON       IMAGE RESOURCE
1        SUCCESS     ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG       reward-dining
2        SUCCESS     ghcr.io/making/reward-dining@sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f    COMMIT       reward-dining
3        SUCCESS     ghcr.io/making/reward-dining@sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95    STACK        reward-dining
4        BUILDING                                                                                                            BUILDPACK    reward-dining

次のコマンドでログを確認すると、Buildpackの更新(この例ではpaketo-buildpacks/syft 1.2.0 -> 1.3.0)によって再ビルドが行われていることがわかります。 ソースコードに変更はないので、Maven Buildは実行されていません。

$ kp build logs reward-dining -b 4
===> PREPARE
Build reason(s): BUILDPACK
BUILDPACK:
    - - id: paketo-buildpacks/syft
    -   version: 1.2.0
Loading secret for "https://ghcr.io" from secret "regsecret" at location "/var/build-secrets/regsecret"
Cloning "https://github.com/making/reward-dining.git" @ "60ae941452421948a4d4432ab025ea56a09ce843"...
Successfully cloned "https://github.com/making/reward-dining.git" @ "60ae941452421948a4d4432ab025ea56a09ce843" in path "/workspace"
===> ANALYZE
===> DETECT
8 of 19 buildpacks participating
paketo-buildpacks/ca-certificates   3.0.1
paketo-buildpacks/bellsoft-liberica 9.0.1
paketo-buildpacks/syft              1.3.0
paketo-buildpacks/maven             6.0.1
paketo-buildpacks/executable-jar    6.0.1
paketo-buildpacks/apache-tomcat     7.0.2
paketo-buildpacks/dist-zip          5.0.1
paketo-buildpacks/spring-boot       5.2.0
===> RESTORE
Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:helper" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:java-security-properties" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jre" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jdk" from cache
Restoring metadata for "paketo-buildpacks/syft:syft" from cache
Restoring metadata for "paketo-buildpacks/maven:application" from cache
Restoring metadata for "paketo-buildpacks/maven:cache" from cache
Restoring metadata for "paketo-buildpacks/spring-boot:web-application-type" from app image
Restoring metadata for "paketo-buildpacks/spring-boot:helper" from app image
Restoring metadata for "paketo-buildpacks/spring-boot:spring-cloud-bindings" from app image
Restoring data for "paketo-buildpacks/bellsoft-liberica:jdk" from cache
Restoring data for "paketo-buildpacks/syft:syft" from cache
Restoring data for "paketo-buildpacks/maven:application" from cache
Restoring data for "paketo-buildpacks/maven:cache" from cache
===> BUILD

Paketo CA Certificates Buildpack 3.0.1
  https://github.com/paketo-buildpacks/ca-certificates
  Launch Helper: Reusing cached layer

Paketo BellSoft Liberica Buildpack 9.0.1
  https://github.com/paketo-buildpacks/bellsoft-liberica
  Build Configuration:
    $BP_JVM_TYPE                 JRE             the JVM type - JDK or JRE
    $BP_JVM_VERSION              11              the Java version
  Launch Configuration:
    $BPL_DEBUG_ENABLED           false           enables Java remote debugging support
    $BPL_DEBUG_PORT              8000            configure the remote debugging port
    $BPL_DEBUG_SUSPEND           false           configure whether to suspend execution until a debugger has attached
    $BPL_HEAP_DUMP_PATH                          write heap dumps on error to this path
    $BPL_JAVA_NMT_ENABLED        true            enables Java Native Memory Tracking (NMT)
    $BPL_JAVA_NMT_LEVEL          summary         configure level of NMT, summary or detail
    $BPL_JFR_ARGS                                configure custom Java Flight Recording (JFR) arguments
    $BPL_JFR_ENABLED             false           enables Java Flight Recording (JFR)
    $BPL_JMX_ENABLED             false           enables Java Management Extensions (JMX)
    $BPL_JMX_PORT                5000            configure the JMX port
    $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    $JAVA_TOOL_OPTIONS                           the JVM launch flags
  BellSoft Liberica JDK 11.0.13: Reusing cached layer
  BellSoft Liberica JRE 11.0.13: Reusing cached layer
  Launch Helper: Reusing cached layer
  Java Security Properties: Reusing cached layer

Paketo Syft Buildpack 1.3.0
  https://github.com/paketo-buildpacks/syft
    Downloading from https://github.com/anchore/syft/releases/download/v0.33.0/syft_0.33.0_linux_amd64.tar.gz
    Verifying checksum
    Writing env.build/SYFT_CHECK_FOR_APP_UPDATE.default

Paketo Maven Buildpack 6.0.1
  https://github.com/paketo-buildpacks/maven
  Build Configuration:
    $BP_MAVEN_BUILD_ARGUMENTS  -Dmaven.test.skip=true package  the arguments to pass to Maven
    $BP_MAVEN_BUILT_ARTIFACT   target/*.[ejw]ar                the built application artifact explicitly.  Supersedes $BP_MAVEN_BUILT_MODULE
    $BP_MAVEN_BUILT_MODULE                                     the module to find application artifact in
    $BP_MAVEN_POM_FILE         pom.xml                         the location of the main pom.xml file, relative to the application root
    Creating cache directory /home/cnb/.m2
  Compiled Application: Reusing cached layer
  Removing source code

Paketo Executable JAR Buildpack 6.0.1
  https://github.com/paketo-buildpacks/executable-jar
  Class Path: Contributing to layer
    Writing env/CLASSPATH.delim
    Writing env/CLASSPATH.prepend
  Process types:
    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
    task:           java org.springframework.boot.loader.JarLauncher (direct)
    web:            java org.springframework.boot.loader.JarLauncher (direct)

Paketo Spring Boot Buildpack 5.2.0
  https://github.com/paketo-buildpacks/spring-boot
  Creating slices from layers index
    dependencies
    spring-boot-loader
    snapshot-dependencies
    application
  Launch Helper: Reusing cached layer
  Spring Cloud Bindings 1.8.0: Reusing cached layer
  Web Application Type: Reusing cached layer
  4 application slices
  Image labels:
    org.opencontainers.image.title
    org.opencontainers.image.version
    org.springframework.boot.version
===> EXPORT
Reusing layers from image 'ghcr.io/making/reward-dining@sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95'
Reusing layer 'paketo-buildpacks/ca-certificates:helper'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:helper'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:jre'
Reusing layer 'paketo-buildpacks/executable-jar:classpath'
Reusing layer 'paketo-buildpacks/spring-boot:helper'
Reusing layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'
Reusing layer 'paketo-buildpacks/spring-boot:web-application-type'
Adding layer 'launch.sbom'
Reusing 5/5 app layer(s)
Reusing layer 'launcher'
Adding layer 'config'
Reusing layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Adding label 'org.opencontainers.image.title'
Adding label 'org.opencontainers.image.version'
Adding label 'org.springframework.boot.version'
Setting default process type 'web'
Saving ghcr.io/making/reward-dining...
*** Images (sha256:2ac64a823ea6d527a8943e067a6201c3bd0507689c789e58e4fa73dd0140a600):
      ghcr.io/making/reward-dining
      ghcr.io/making/reward-dining:b4.20211220.170207
Reusing cache layer 'paketo-buildpacks/bellsoft-liberica:jdk'
Adding cache layer 'paketo-buildpacks/syft:syft'
Reusing cache layer 'paketo-buildpacks/maven:application'
Reusing cache layer 'paketo-buildpacks/maven:cache'
Adding cache layer 'cache.sbom'
===> COMPLETION
Build successful

ghcr.io/making/reward-dining:b4.20211220.170207というイメージが、Buildpackがアップデートされた新しいイメージです。

imageまたはbuildリソースを確認すると、次のようにLATEST REASON/REASONBUILDPACKになっていることが分かります。Buildpackの変更に伴ったリソースの更新であることを意味します。

$ kp build list
BUILD    STATUS     BUILT IMAGE                                                                                             REASON       IMAGE RESOURCE
1        SUCCESS    ghcr.io/making/reward-dining@sha256:33e56e7c8970793aeb38e3d53781028ca08a86a3caf9fd9a51c80f76062da3d6    CONFIG       reward-dining
2        SUCCESS    ghcr.io/making/reward-dining@sha256:2e2bcde16dafc093fc732abf8a880ffa710912cc48c37dccabd59ddf6005928f    COMMIT       reward-dining
3        SUCCESS    ghcr.io/making/reward-dining@sha256:4d21a374a74c6411040c140da0e052b79b402d1288c2d888e78bf2a6c1ddaa95    STACK        reward-dining
4        SUCCESS    ghcr.io/making/reward-dining@sha256:2ac64a823ea6d527a8943e067a6201c3bd0507689c789e58e4fa73dd0140a600    BUILDPACK    reward-dining

$ kp image list
NAME             READY    LATEST REASON    LATEST IMAGE                                                                                            NAMESPACE
reward-dining    True     BUILDPACK        ghcr.io/making/reward-dining@sha256:2ac64a823ea6d527a8943e067a6201c3bd0507689c789e58e4fa73dd0140a600    default

Buildpackが更新されたことでイメージの再ビルドが行われることがわかりました。 例えばJavaのバージョンが11.0.12 -> 11.0.13に上がった場合にコンテナイメージを自動で作成することができます。(メジャーバージョンは固定です)


kpackをkind上で簡単に構築することができました。またkpackを使ってイメージの自動更新ができることを確認できました。

kpackにイメージを管理してもらうことでセキュアなイメージを作り続けることができるので、kind上でまずはスモールスタートしてはいかがでしょうか。

エンタープライズ版が必要になれば Tanzu Build Service をお求めください。