1. 序章

このチュートリアルでは、Kanikoを使用してコンテナイメージを構築する方法を見ていきます。

2. カニコ

Kanikoは、Dockerfileからコンテナイメージを構築するためのツールです。 Dockerとは異なり、KanikoはDockerデーモンを必要としません。

デーモンプロセスへの依存関係がないため、これは、Kubernetesクラスターのようにユーザーがrootアクセス権を持たない任意の環境で実行できます。

Kanikoは、 executor image を使用して、ユーザースペースでDockerfile内の各コマンドを完全に実行します。 たとえば、Kubernetesポッド。 Dockerfile 内の各コマンドを順番に実行し、各コマンドの後にファイルシステムのスナップショットを取得します。

ファイルシステムに変更があった場合、エグゼキュータはファイルシステムの変更のスナップショットを「差分」レイヤーとして取得し、イメージメタデータを更新します。

Kanikoをデプロイして実行するには、さまざまな方法があります。

  • Kubernetesクラスター
  • gVisor
  • Google Cloud Build

このチュートリアルでは、Kubernetesクラスターを使用してKanikoをデプロイします。

3. Minikubeのインストール

Minikubeを使用してKubernetesをローカルにデプロイします。 スタンドアロンのバイナリとしてダウンロードできます。

$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 &&
  chmod +x minikube

次に、Minikube実行可能ファイルをパスに追加できます。

$ sudo mkdir -p /usr/local/bin/
$ sudo install minikube /usr/local/bin/

次に、Dockerデーモンが実行されていることを確認しましょう。

$ docker version

また、このコマンドは、インストールされているクライアントとサーバーのバージョンを示します。

これで、Kubernetesクラスターを作成できます。

$ minikube start --driver=docker

startコマンドが正常に実行されると、次のメッセージが表示されます。

Done! kubectl is now configured to use "minikube"
For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/

minikube status コマンドを実行すると、kubeletステータスが「Running」と表示されます。

m01
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

次に、Kubernetesコマンドを実行できるように、kubectlバイナリを設定する必要があります。 バイナリをダウンロードして実行可能にしましょう。

$ curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s \ 
  https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl &&
  chmod +x ./kubectl

これをパスに移動しましょう:

$ sudo mv ./kubectl /usr/local/bin/kubectl

次を使用してバージョンを確認できます。

$ kubectl version

4. カニコを使用して画像を作成する

Kubernetesクラスターの準備ができたので、Kanikoを使用してイメージの作成を開始しましょう。

まず、ビルドコンテキストとしてKanikoコンテナにマウントされるローカルディレクトリを作成する必要があります。

このためには、KubernetesクラスターにSSHで接続し、ディレクトリを作成する必要があります。

$ minikube ssh
$ mkdir kaniko && cd kaniko

次に、Ubuntuイメージをプルして文字列「hello」をエコーするDockerfileを作成しましょう。

$ echo 'FROM ubuntu' >> dockerfile
$ echo 'ENTRYPOINT ["/bin/bash", "-c", "echo hello"]' >> dockerfile

cat dockerfile を実行すると、次のように表示されます。

FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]

最後に、 pwd コマンドを実行して、後で永続ボリュームで指定する必要があるローカルディレクトリへのパスを取得します。

このための出力は次のようになります。

/home/docker/kaniko

そして最後に、SSHセッションを中止できます。

$ exit

4.1. カニコエグゼキュータイメージ引数

Kubernetes構成ファイルの作成に進む前に、Kanikoエグゼキューターイメージに必要な引数のいくつかを見てみましょう。

  • Dockerfile( –dockerfile )–イメージのビルドに必要なすべてのコマンドを含むファイル
  • ビルドコンテキスト( –context )–これはDockerのビルドコンテキストに似ており、Kanikoがイメージのビルドに使用するディレクトリを参照します。 ここのところ、 Kanikoは、Google Cloud Storage(GCS)、Amazon S3、Azure BLOBストレージ、Gitリポジトリ、およびローカルディレクトリをサポートしています。 このチュートリアルでは、前に構成したローカルディレクトリを使用します。
  • 宛先( –destination )–これは、イメージをプッシュするDockerレジストリまたは同様のリポジトリを指します。 この引数は必須です。 画像をプッシュしたくない場合は、代わりに –no-pushフラグを使用して動作をオーバーライドできます。

渡すことができる追加のフラグも表示されます。

4.2. 構成ファイルの設定

それでは、KubernetesクラスターでKanikoを実行するために必要な構成ファイルの作成を開始しましょう。

まず、クラスター内で以前に作成されたボリュームマウントパスを提供する永続ボリュームを作成しましょう。 ファイルをvolume.yamlと呼びましょう。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: dockerfile
  labels:
    type: local
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: local-storage
  hostPath:
    path: /home/docker/kaniko # replace this with the output of pwd command from before, if it is different

次に、この永続ボリュームの永続ボリュームクレームを作成しましょう。 次のファイルvolume-claim.yamlを作成します。

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: dockerfile-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
  storageClassName: local-storage

最後に、エグゼキュータイメージを構成するポッド記述子を作成しましょう。 この記述子には、上記で指定されたボリュームマウントへの参照があり、これは、前に作成したDockerfileを指します。

ファイルをpom.yamlと呼びます。

apiVersion: v1
kind: Pod
metadata:
  name: kaniko
spec:
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:latest
    args: ["--dockerfile=/workspace/dockerfile",
            "--context=dir://workspace",
            "--no-push"] 
    volumeMounts:
      - name: dockerfile-storage
        mountPath: /workspace
  restartPolicy: Never
  volumes:
    - name: dockerfile-storage
      persistentVolumeClaim:
        claimName: dockerfile-claim

前述のように、このチュートリアルでは、Kanikoを使用したイメージの作成のみに焦点を当てており、公開はしていません。 したがって、エグゼキュータへの引数にno-pushフラグを指定します。

必要な構成ファイルがすべて揃ったら、それぞれを適用してみましょう。

$ kubectl create -f volume.yaml
$ kubectl create -f volume-claim.yaml
$ kubectl create -f pod.yaml

記述子を適用した後、Kanikoポッドが完了ステータスになったことを確認できます。 これは、 kubectl getpoを使用して確認できます。

NAME     READY   STATUS      RESTARTS   AGE
kaniko    0/1   Completed       0        3m

これで、 kubectl logs kaniko、を使用してこのポッドのログを確認し、イメージ作成のステータスを確認できます。次の出力が表示されます。

INFO[0000] Resolved base name ubuntu to ubuntu          
INFO[0000] Resolved base name ubuntu to ubuntu          
INFO[0000] Retrieving image manifest ubuntu             
INFO[0003] Retrieving image manifest ubuntu             
INFO[0006] Built cross stage deps: map[]                
INFO[0006] Retrieving image manifest ubuntu             
INFO[0008] Retrieving image manifest ubuntu             
INFO[0010] Skipping unpacking as no commands require it. 
INFO[0010] Taking snapshot of full filesystem...        
INFO[0013] Resolving paths                              
INFO[0013] ENTRYPOINT ["/bin/bash", "-c", "echo hello"] 
INFO[0013] Skipping push to container registry due to --no-push flag

コンテナがDockerfileに入れたステップを実行したことが出力でわかります。

最初はベースのUbuntuイメージをプルすることから始まり、echoコマンドをエントリポイントに追加することで終わりました。 no-push フラグが指定されたため、イメージをどのリポジトリにもプッシュしませんでした。

前述のように、エントリポイントを追加する前にファイルシステムのスナップショットが作成されていることもわかります。

5. 結論

このチュートリアルでは、カニコの基本的な紹介を見てきました。 これを使用してイメージを構築し、Kanikoを実行するために必要な構成でMinikubeを使用してKubernetesクラスターをセットアップする方法を確認しました。

いつものように、この記事で使用されているコードスニペットは、GitHubから入手できます。