SkaffoldのPipeline Stagesについてまとめる

はじめに

自分が所属する組織ではSkaffoldを開発ワークフローのツールとして導入しているのですが、しっかり使っていく上で動作の基本をきちんと抑えておこうかと。
今まででは、JavaのアプリをデプロイしてデバッグしてみたりHelmを使って環境変数の切り替えをやってみたりやりたいことベースで学んでいたんですが、ツールの動作に関する全体感を抑えておこうかと思いました。 基本はSkaffold Pipeline Stagesに書かれる内容を自分が気になったところに関してまとめたり、動かしたりして深堀する感じで行なう感じでやろうかと思います。
より正確な情報は本家の方を参照するようにお願いします。
特定の文字列を返すだけのサンプルアプリを1つ作って、このアプリにSkaffoldを適用してそれぞれのStageで提供される機能を使ってみます。
動かすサンプルアプリはGoでEchoを使って作ろうかと思います。

Skaffold Pipeline Stagesについて

Skaffoldには以下のようなパイプラインのステージがあります。

Stage名 説明
Init Skaffoldプロジェクトの作成
Build イメージのビルド。様々なビルダーを利用することが可能
Tag ビルドしたイメージのタグ付け。様々なポリシーでタグ付けを行なうことが可能
Test テスターを用いたテストの実行する
Deploy アプリをk8sクラスターにデプロイする。kubectl、Helm、kustomize等を用いることが可能
File Sync ローカルのファイルを直接コンテナにシンクする
Log Tailing デプロイしたアプリやワークフローのログをテールする
Port Forwarding Serviceや任意のリソースをlocalhostへポートフォワードする
Lifecycle Hooks Skaffoldの実行ライフサイクルの中のざまざまなイベントでコードをHookする
Clean Up リソースやイメージのクリーンアップ

Skaffoldのコマンドによって実行するステージが違っており、スキップ可能なものもあります。

各ステージの機能を少しほってみる(ものによっては動かしてみる)

動作環境

今回クラスターはminikube(docker driver)を用いて作成します。

作ったクラスターやその他のバージョンは以下の通り

$ uname -srvmpio
Linux 5.4.0-88-generic #99-Ubuntu SMP Thu Sep 23 17:29:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
LSB Version:    core-11.1.0ubuntu2-noarch:security-11.1.0ubuntu2-noarch
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:    20.04
Codename:   focal


$ minikube version
minikube version: v1.23.2
commit: 0a0ad764652082477c00d51d2475284b5d39ceed

$ kubectl version -o yaml
clientVersion:
  buildDate: "2021-09-15T21:38:50Z"
  compiler: gc
  gitCommit: 8b5a19147530eaac9476b0ab82980b4088bbc1b2
  gitTreeState: clean
  gitVersion: v1.22.2
  goVersion: go1.16.8
  major: "1"
  minor: "22"
  platform: linux/amd64
serverVersion:
  buildDate: "2021-09-15T21:32:41Z"
  compiler: gc
  gitCommit: 8b5a19147530eaac9476b0ab82980b4088bbc1b2
  gitTreeState: clean
  gitVersion: v1.22.2
  goVersion: go1.16.8
  major: "1"
  minor: "22"
  platform: linux/amd64

$ docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:27 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:52:33 2021
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          1.4.10
  GitCommit:        8848fdb7c4ae3815afcc990a8a99d663dda1b590
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0


$ go version
go version go1.17.1 linux/amd64

また、Skaffoldのバージョンは以下のものを用います。

$ skaffold version
v1.33.0

Skaffoldのインストールに関してはこちらをご確認ください。

サンプルアプリとDockerfileを用意する

以下のコマンドを実行してサンプルアプリを作成します。

$ mkdir skaffold-demo && cd skaffold-demo

$ go mod init skaffold-demo

$ go get github.com/labstack/echo/v4
go: downloading github.com/labstack/echo/v4 v4.6.1
go get: added github.com/labstack/echo/v4 v4.6.1
go get: added github.com/labstack/gommon v0.3.0
go get: added github.com/mattn/go-colorable v0.1.8
go get: added github.com/mattn/go-isatty v0.0.14
go get: added github.com/valyala/bytebufferpool v1.0.0
go get: added github.com/valyala/fasttemplate v1.2.1
go get: added golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
go get: added golang.org/x/net v0.0.0-20210913180222-943fd674d43e
go get: added golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0
go get: added golang.org/x/text v0.3.7

以下のように文字列を返すだけのサーバを記述します。

server.go

package main

import (
    "net/http"
 
    "github.com/labstack/echo/v4"
)

func main() {
    e := echo.New()
    e.GET("/hello", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    e.Logger.Fatal(e.Start(":1323"))
}

アプリを起動します。

$ go run server.go 

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.6.1
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:1323


$ curl localhost:1323/hello
Hello, World!

次にアプリのイメージをビルドするDockerfileを作成します。

FROM golang:1.17 as buildImage

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64

WORKDIR /usr/src
COPY . .
RUN go build -o skaffold-demo-app server.go

FROM alpine:3.14.2

COPY --from=buildImage /usr/src/skaffold-demo-app /

ENTRYPOINT ["/skaffold-demo-app"]

イメージをビルドして起動してみます。
(docker buildx installコマンドでBuildxを有効化してます)

$ docker build -t skaffold-demo-app .
[+] Building 18.9s (14/14) FINISHED                                                                                                                                                                        
 => [internal] load build definition from Dockerfile                                                                                                                                                  0.0s
 => => transferring dockerfile: 300B                                                                                                                                                                  0.0s
 => [internal] load .dockerignore                                                                                                                                                                     0.0s
 => => transferring context: 2B                                                                                                                                                                       0.0s
 => [internal] load metadata for docker.io/library/alpine:3.14.2                                                                                                                                      2.2s
 => [internal] load metadata for docker.io/library/golang:1.17                                                                                                                                        2.2s
 => [auth] library/golang:pull token for registry-1.docker.io                                                                                                                                         0.0s
 => [auth] library/alpine:pull token for registry-1.docker.io                                                                                                                                         0.0s
 => [buildimage 1/4] FROM docker.io/library/golang:1.17@sha256:45d45a39258425b0386643efc863b3b3c1481173d64ec6151b18d48b565df9a0                                                                       0.0s
 => CACHED [stage-1 1/2] FROM docker.io/library/alpine:3.14.2@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a                                                                 0.0s
 => [internal] load build context                                                                                                                                                                     0.1s
 => => transferring context: 6.86MB                                                                                                                                                                   0.1s
 => CACHED [buildimage 2/4] WORKDIR /usr/src                                                                                                                                                          0.0s
 => [buildimage 3/4] COPY . .                                                                                                                                                                         0.0s
 => [buildimage 4/4] RUN go build -o skaffold-demo-app server.go                                                                                                                                     16.4s
 => [stage-1 2/2] COPY --from=buildImage /usr/src/skaffold-demo-app /                                                                                                                                 0.0s
 => exporting to image                                                                                                                                                                                0.0s
 => => exporting layers                                                                                                                                                                               0.0s
 => => writing image sha256:ecb267c14c4664a488afe8586e64c5bf6b80b1715b6a86e4e9efb626b6d3a279                                                                                                          0.0s 
 => => naming to docker.io/library/skaffold-demo-app   

$ docker run -d -p 1323:1323 skaffold-demo-app  
1fd8dc30d0e0e19ec439ebacc5a411427ab42d06dab5aa4efd93fd86a969fbc0

$ curl localhost:1323/hello
Hello, World!

下準備はこれで完了です。

各ステージをみていく

Init

先ずはInit ステージからみていきます。
前述の通りこのステージではSkaffoldプロジェクトの作成を行います。
Initステージはskaffold initコマンドで実行します。
skaffold initコマンドで初期設定可能なものとしては、以下のようなビルダーをサポートします。

また、skaffold initではプロジェクトのディレクトリ内を走査して、以下のようなファイルからビルドの設定を読み込みます。

  • Dockerfile
  • build.gradle/pom.xml
  • package.json
  • requirements.txt
  • go.mod
  • init

この際、500MB以上のファイルは無視されるようです。
例えば今回作成下アプリの場合Dockerfilego.modがあるので以下のように2つの選択肢を提示してくれるようになります。

$ skaffold init
? Which builders would you like to create kubernetes resources for?  [Use arrows to move, space to select, <right> to all, <left> to none, type to filter]
> [ ]  Buildpacks (go.mod)
  [ ]  Docker (Dockerfile)

ここではDockerを選びます方向キーで上下の移動をし、スペースキーで選択します。
プロジェクト作成の際プロジェクト内にk8sのリソースファイルがない場合は以下のようなエラーが出力されます。

$ skaffold init
? Which builders would you like to create kubernetes resources for? Docker (Dockerfile)
one or more valid Kubernetes manifests are required to run skaffold

skaffold initを行なう場合先にマニフェストを容易しておくか、--generate-manifestsフラグを指定してマニフェストの自動生成を行なう必要があります。
今回は自動生成をしてもらうので以下のようにコマンドを実行します。

$ skaffold init --generate-manifests 
? Which builders would you like to create kubernetes resources for? Docker (Dockerfile)
? Select port to forward for dockerfile-image (leave blank for none): 1323
apiVersion: skaffold/v2beta22
kind: Config
metadata:
  name: skaffold-demo
build:
  artifacts:
  - image: dockerfile-image
    docker:
      dockerfile: Dockerfile
deploy:
  kubectl:
    manifests:
    - deployment.yaml
portForward:
- resourceType: service
  resourceName: dockerfile-image
  port: 1323

deployment.yaml - apiVersion: v1
kind: Service
metadata:
  name: dockerfile-image
  labels:
    app: dockerfile-image
spec:
  ports:
  - port: 1323
    protocol: TCP
  clusterIP: None
  selector:
    app: dockerfile-image
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dockerfile-image
  labels:
    app: dockerfile-image
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dockerfile-image
  template:
    metadata:
      labels:
        app: dockerfile-image
    spec:
      containers:
      - name: dockerfile-image
        image: dockerfile-image

? Do you want to write this configuration, along with the generated k8s manifests, to skaffold.yaml? Yes
Generated manifest deployment.yaml was written
Configuration skaffold.yaml was written
You can now run [skaffold build] to build the artifacts
or [skaffold run] to build and deploy
or [skaffold dev] to enter development mode, with auto-redeploy

実行が成功すると以下のようにSkaffoldの設定ファイルのskaffold.yamlk8sのリソース定義ファイルであるdeployment.yamlが生成されているのが確認できます。

$ ls
Dockerfile  deployment.yaml  go.mod  go.sum  server.go  skaffold-demo-app  skaffold.yaml

前のログでも出力されていますが、できたskaffold.yamlは以下のようになっています。

apiVersion: skaffold/v2beta22
kind: Config
metadata:
  name: skaffold-demo
build:
  artifacts:
  - image: dockerfile-image
    docker:
      dockerfile: Dockerfile
deploy:
  kubectl:
    manifests:
    - deployment.yaml
portForward:
- resourceType: service
  resourceName: dockerfile-image
  port: 1323

今回はStageをざっくり把握することが目的なので詳しくはみませんが skaffold.yamlに関してはこちらを参照ください。
これでプロジェクトのinitは完了です。

Build

Buildステージではイメージのビルドを行います。
このステージはskaffold buildskaffold runskaffold devなどで実行されるようです。
Buildステージでは以下のようなビルドの方法があるみたいです。

各ビルド手法でのビルダーサポートはここをご確認ください。
ローカルでは基本的にどのようなビルダーもサポートしているようです。

Buildに関する設定はskaffold.yamlbuildセクションで行います。

skaffold buildでコマンドでビルドしてみます。
設定的にはローカルのDockerが利用されビルドされるようです。
ちなみにBuild時のBuildKitの有効無効は設定で明示的にOnにしない限りはローカルのDockerの設定に依存するようです。

$ skaffold build

$ docker images | grep dockerfile-image
dockerfile-image              83b1cdbd0c82d697b527964e54a126ebb6b65bf690d1a40fe8b00f313ba380f8   83b1cdbd0c82   55 seconds ago   12.4MB
dockerfile-image              latest                                                             83b1cdbd0c82   55 seconds ago   12.4MB

Tag

ビルドしたイメージのタグ付けを行います。
この際以下のようなポリシーでタグ付けを行えるようです。

  • gitCommit : Gitのcommit referencesを用いたタグ付け
  • inputDigest : ソースファイルのダイジェスト情報を用いたタグ付け
  • envTemplate : 環境変数を用いたタグ付け
  • datetime : ビルド時の日付を用いたタグ付け。設定変更可能
  • customTemplate : 複数のタガーとテンプレートを用いたタグ付け

skaffold.yamlに特に指定がない場合はgitCommitが用いられるようです。
また、コマンド実行時に--tagを指定するとタグの上書きが可能になるようです。

今回はcustomTemplateiinputDigestdatetimeを用いてタグ付けをしてみます。 skaffold.yamlファイルを以下のように書き換えます。

apiVersion: skaffold/v2beta22
kind: Config
metadata:
  name: skaffold-demo
build:
  tagPolicy:
    customTemplate:
      template: "{{.FOO}}_{{.BAR}}"
      components:
      - name: FOO
        dateTime:
          format: "2006-01-02"
          timezone: "UTC"
      - name: BAR
        inputDigest: {}
  artifacts:
  - image: dockerfile-image
    docker:
      dockerfile: Dockerfile
deploy:
  kubectl:
    manifests:
    - deployment.yaml
portForward:
- resourceType: service
  resourceName: dockerfile-image
  port: 1323

customTemplateを用いる場合templateセクションでテンプレートを定義しcomponentsセクションでそれぞれのタガーのコンポーネントを定義するようです。
この設定でBuildを実行するとタグが先程と違い日付とダイジェストを指定したテンプレートに当てはめて作られていることが確認できます。

$ skaffold build
(省略)

$ docker images | grep dockerfile-image
dockerfile-image              2021-10-09_a0660834a25ae146d26458a6b6247f101a093ec6fde33e3955fe488031ee13ac   83b1cdbd0c82   28 minutes ago   12.4MB
dockerfile-image              83b1cdbd0c82d697b527964e54a126ebb6b65bf690d1a40fe8b00f313ba380f8              83b1cdbd0c82   28 minutes ago   12.4MB
dockerfile-image              latest                                                                        83b1cdbd0c82   28 minutes ago   12.4MB           

Test

Skaffoldはパイプラインの中でテストを実行することも可能です。
skaffold testskaffold runskaffold devなどのコマンドでテストが実行されます。

現状では以下の2つのタイプのテストをサポートしています。

  • Custom Test : Skaffoldのパイプラインの中でテストフェーズとしてカスタムコマンドの実行をおこなう。ユニットテストやセキュリティスキャンの実行が可能
  • Container Structure Test : ビルドされたコンテナをデプロイ前にバリデーションする。

ここではCustom Testの方を使ってGoのユニットテストの実行を試してみたいと思います。
まずは以下のようなテストを実行するスクリプトを用意します。

#!/bin/bash

set -e

echo "go custom test $@"

go test .

次に適当に失敗するテストを用意しておきます。

server_test.go

package main

import "testing"

func TestServer(t *testing.T) {
    t.FailNow()
}

このテストをSkaffoldのTestステージで実行するようにします。
skaffold.yamlを以下のように書き換えます。

apiVersion: skaffold/v2beta22
kind: Config
metadata:
  name: skaffold-demo
build:
  tagPolicy:
    customTemplate:
      template: "{{.FOO}}_{{.BAR}}"
      components:
      - name: FOO
        dateTime:
          format: "2006-01-02"
          timezone: "UTC"
      - name: BAR
        inputDigest: {}
  artifacts:
  - image: dockerfile-image
    docker:
      dockerfile: Dockerfile
test:
  - image: dockerfile-image
    custom:
      - command: ./test.sh
        timeoutSeconds: 60
        dependencies:
          paths:
          -  "*_test.go"
          -  "test.sh"
deploy:
  kubectl:
    manifests:
    - deployment.yaml
portForward:
- resourceType: service
  resourceName: dockerfile-image
  port: 1323

testセクションを追加しています。
customセクションに諸々の設定を書いてます。
大体はセクション名の通りですが、dependenciesセクションにはファイル変更を検知してテストを再実行するための設定を記述しています。

skaffold devコマンドでテストを実行してみます。
(skaffold testコマンドを用いる場合はビルド時にskaffold build --file-output tags.jsonのようにしてアーティファクト情報を出力しテスト時にskaffold test --build-artifacts tags.jsonの用に指定してやる必要があります)

$ skaffold dev

(省略)

Successfully built a68e7ef37e4e
Successfully tagged dockerfile-image:2021-10-09_a22222e721470777f9403c07cef58d363eeb53a438486c9f999cd5499ca5eb44
Starting test...
Testing images...
Running custom test command: "./test.sh" with timeout 60 s
go custom test 
--- FAIL: TestServer (0.00s)
FAIL
FAIL    skaffold-demo   0.002s
FAIL
Command finished with non-0 exit code.
running tests: command ./test.sh finished with non-0 exit code: exit status 1. Check the custom command contents: "./test.sh".

ビルド後にテストが実行されているのが確認できます。
テストを修正してもう一度skaffold devを実行してみます。

package main

import "testing"

func TestServer(t *testing.T) {
}

なにもテストしてないですが、成功のステータスになればよいので一旦これで勧めます。

$ skaffold dev

(省略)

Successfully tagged dockerfile-image:2021-10-09_829325c7d6931da186db8c88d95d30cdbcc7de9fd7782f7c86db821e5834899a
Starting test...
Testing images...
Running custom test command: "./test.sh" with timeout 60 s
go custom test 
ok      skaffold-demo   0.002s
Command finished successfully.
Tags used in deployment:
 - dockerfile-image -> dockerfile-image:a68e7ef37e4ecb1a02a8787b476221750e931017692745e632d7b2f8e83a5eee
Starting deploy...
 - service/dockerfile-image created
 - deployment.apps/dockerfile-image created
Waiting for deployments to stabilize...

(省略)

今度はテストの実行も成功しているみたいですね。

Deploy

デプロイのステージではその名の通りアプリをk8sにデプロイします。
skaffold devskaffold runskaffold deployなどのコマンドで実行されます。

デプロイ時には以下のステップが実行されます。

Skaffoldはデプロイ時に以下のようなツールをサポートします。

  • kubectl
  • helm
  • kustomize

今回は生成されたskaffold.yamlに記述されているようにkubectlを用いたデプロイを行います。
skaffold devコマンドを実行します。

$ skaffold dev --kube-context=minikube

(省略)

Tags used in deployment:
 - dockerfile-image -> dockerfile-image:22f84ce796f1c77f1bc5fceb6b494b9a5f67b86f8eeeb345fee0328047b3c115
Starting deploy...
 - service/dockerfile-image created
 - deployment.apps/dockerfile-image created
Waiting for deployments to stabilize...
 - deployment/dockerfile-image is ready.
Deployments stabilized in 2.228 seconds
Port forwarding service/dockerfile-image in namespace default, remote port 1323 -> http://127.0.0.1:1323
Press Ctrl+C to exit
Watching for changes...
[dockerfile-image] 
[dockerfile-image]    ____    __
[dockerfile-image]   / __/___/ /  ___
[dockerfile-image]  / _// __/ _ \/ _ \
[dockerfile-image] /___/\__/_//_/\___/ v4.6.1
[dockerfile-image] High performance, minimalist Go web framework
[dockerfile-image] https://echo.labstack.com
[dockerfile-image] ____________________________________O/_______
[dockerfile-image]                                     O\
[dockerfile-image] ⇨ http server started on [::]:1323

(省略)

kubecltコマンドでリソースを確認してみます。

$ kubectl --context=minikube -n default get all 
NAME                                    READY   STATUS    RESTARTS   AGE
pod/dockerfile-image-6bc7589896-vth7m   1/1     Running   0          6m16s

NAME                       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/dockerfile-image   ClusterIP   None         <none>        1323/TCP   6m16s
service/kubernetes         ClusterIP   10.96.0.1    <none>        443/TCP    99m

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/dockerfile-image   1/1     1            1           6m16s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/dockerfile-image-6bc7589896   1         1         1       6m16s

DeploymentやServiceなどがクラスターにデプロイされました。
--kube-context=minikubeでコンテキストを明示的に指定していますが、指定しない場合kubectlのカレントコンテキストを用いるようです。
[skaffold config](https://skaffold.dev/docs/references/cli/#skaffold-config)コマンドでカレントコンテキストを変えることも可能なようです。

File Sync

Skaffoldは不要なリビルドを避けるためにファイルをコンテナに直接コピーする方法も提供しています。
リビルドの必要のない設定ファイルやHTMLファイルをシンクしたい場合この方法が使えます。
今回は深く機能は試しませんが、以下のようなパターンでのシンクを実行できます。

  • manual : ローカルのディレクトリと実行されているコンテナのファイルパスをマニュアルで指定してシンクする。すべてのアーティファクトに対応している
  • infer : ビルダーから推測可能なファイルディレクトリの中をチェックしシンクする。dockerやkanikoの場合はDokcerfileから推測される。
  • auto : Skaffoldがシンクの設定を自動的に設定する。JibやBuildpacksのアーティファクトに対して有効。Buildpacksを用いている場合はデフォルトで有効になる。

Port Forwarding

Skaffoldはビルドインでクラスターからローカルマシンへのポートフォワードのサポートを行ってくれています。
この機能はskaffold devskaffold debugskaffold deployskaffold runなどのコマンドで有効にできます。
(コマンドによって、有効になるポートフォワードの種類が違います。詳細はこちらをご確認ください)

ポートフォワードはskaffold.yaml内で以下のような種類で定義することが可能です。

  • user : ユーザが明示的に有効にできるポートフォワード。k8sのリソースタイプを指定してぽーどフォワードを行なう(設定方法はこちら
  • services : Skaffoldでデプロイされた、Serviceリソースに対して設定できるポートフォワード
  • debug : デバック用のポートを公開するためのポートフォワード(skaffold debugコマンドで有効にできる)
  • pods : SkaffoldがビルドしたイメージのすべてのPodのcontainerPortsに対するポートフォワード

また、ポートフォワードを明示的にoffにしたい場合はコマンドのフラグとして--port-forward=offを指定します。

今回はデフォルトで生成されたuserのタイプのServiceリソースに対するポートフォワードを行ってみます。
以下のコマンドを実行します。

$ skaffold dev --kube-context=minikube

(省略)

Port forwarding service/dockerfile-image in namespace default, remote port 1323 -> http://127.0.0.1:1323

(省略)

ログからポートフォワードが動作しているのがわかります。
cURLlocalhost:1323にアクセスしてみます。

$ curl localhost:1323/hello
Hello, World!

Lifecycle Hooks

Lifecycle Hooksでは、Skaffoldのライフサイクルイベントによってコードを実行したりすることができます。
buildsyncdeployのフェーズでそれぞれbeforeafterのホックを設定できます。
以下の2つのタイプのホックが存在します。

  • Host hooks : ランナー(例えばホストマシン)内で実行されるホック
  • Container hooks : 実行されるコンテナ内で実行されるホック

また、Host hooksでは、フェーズによって利用できるいくつかの環境変数が存在しており、例えばbuildsyncのフェーズではSKAFFOLD_IMAGEというイメージ名が設定された環境変数が利用可能です。
環境変数の一覧とその環境変数が利用できるフェーズの詳細はこちらをご確認ください。

今回は、Host hooksを利用して、ビルドの前と後にechoコマンドを実行してイメージ名を出力してみます。
具体的にはskaffold.yamlbuildセクションを以下のように書き換えます。

build:
  tagPolicy:
    customTemplate:
      template: "{{.FOO}}_{{.BAR}}"
      components:
      - name: FOO
        dateTime:
          format: "2006-01-02"
          timezone: "UTC"
      - name: BAR
        inputDigest: {}
  artifacts:
  - image: dockerfile-image
    docker:
      dockerfile: Dockerfile
    hooks:
      before:
        - command: ["sh", "-c", "echo Start Building: $SKAFFOLD_IMAGE"]
          os: [linux]
      after:
        - command: ["sh", "-c", "echo Finish Building: $SKAFFOLD_IMAGE"]
          os: [linux]

そして、skaffold buildコマンドを実行します。

$ skaffold build

(省略)

Starting pre-build hooks...
Start Building: dockerfile-image:2021-10-09_7db982f9391c94bd44049fdefeb1e2e15d4a9f876009f322744cca7ca74c3667
Completed pre-build hooks

(省略)


Starting post-build hooks...
Finish Building: dockerfile-image:2021-10-09_7db982f9391c94bd44049fdefeb1e2e15d4a9f876009f322744cca7ca74c3667
Completed post-build hooks

Clean Up

最後に、クリーンアップステージです。
Skaffoldはローカルマシンやクラスターに以下のような副作用を起こします。

Skaffoldは自動でこれらの副作用をクリーンアップしてくれる機能を有しています。
skaffold deleteを使えばそれらのリソースのクリーンアップが行えます。
また、skaffold devskaffold debugコマンドを用いていてクラスターへのデプロイを行っている場合はCtrl + cを実行すれば自動的に作成されたリソースやイメージがクリーンアップされます。

$ skaffold dev --kube-context=minikube

(省略)

Watching for changes...
^CCleaning up...
 - service "dockerfile-image" deleted
 - deployment.apps "dockerfile-image" deleted

ログから不要なリソースがクリーンアップされていることがわかります。
実際にkubectlコマンドで確認してみてもクリーンアップされています。

$ kubectl --context=minikube -n default get all 
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   103m