Kubernetesのアプリケーション開発で楽をしたい。そうだ、Skaffoldを使ってみよう!

この記事は公開されてから半年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Skaffoldとは?

Skaffold(https://skaffold.dev)は、Kubernetesアプリケーションの継続的開発を促進するコマンドラインツールです。SkaffoldはGoogleによって設計されたオープンソースのツールです。Skaffoldを利用する目的は、ローカル開発のワークフローの高速化するところにあります。Skaffoldがアプリケーションのソースコードの変更を検知して、自動的にコンテナの再作成を行います。コンテナの再作成後、SkaffoldがローカルやリモートのKubernetes環境へプッシュ、デプロイを行ってくれます。Skaffoldを利用することで、ローカル開発環境でのビルドからデプロイまでの手間を省くことができるので、アプリケーション開発者は開発に集中することができます。

本記事では、Skaffoldの概要とローカル環境での基本的な使い方の紹介を行います。

 

Skaffoldの特徴は?

Skaffoldの特徴を紹介します。

ローカルでのKubernetesアプリケーション開発の高速化

アプリケーションのソースコードの変更をSkaffoldが自動で検知し、コンテナのビルド、プッシュ、デプロイを自動で行います。アプリケーションの開発者が docker buildkubectl applyコマンドを実行する手間がなくなります。

どこでも動作できる

作成したSkaffoldプロジェクトは簡単に共有をすることができます。コンテキスト(環境)ごとの設定変更も、プロファイルなどの切り替えで簡単に行うことができます。

軽量である

Skaffoldはクライアント側のコンポーネントだけで、Kubernetesクラスタ側の設定や管理は不要です。またパイプラインも必要最低限の機能に絞り込むことで、簡単で分かりやすいパイプラインを維持できます。

 

Skaffoldは何をしてくれるの?

Skaffoldの動作はとても簡単で分かりやすく、たった一つのコマンド skaffold devを実行するだけです。 skaffold dev コマンドは、以下の操作を順番に実行します。

1. ソースコードの変更を監視する。

Skaffoldはデフォルトで1秒間隔でソースファイルの変更を監視します。監視の間隔は、 --watch-pool-intervalオプションで変更が可能です。

2. 開発者が同期対象(sync)としているものである場合、Podに直接同期する。

Skaffoldは、コンテナの再作成やPodの再起動を避けるために、ファイルのコピーだけでアプリケーションに反映できるものは、Podに直接コピーを行うことができます。skaffold.yamlファイルのsyncセクションで対象のファイルもしくはディレクトリを指定することで、設定を行います。この機能はファイルの更新かつローカルのソースファイルのみを対象とするなどの制限があります。また、2019年5月17日時点ではアルファ版としてのリリースとなっています。

3. ソースコードからビルドを行う。

指定したツールを利用してDockerイメージをビルドします。サポートしているビルドツールは以下の通りです。

  • ローカルのDockerfile
  • Google Cloud BuildのリモートDockerfile
  • Kanikoのクラスタ内Dockerfile
  • ローカルのBazel
  • ローカルのMavenもしくはGradleを用いたJib
  • Google Cloud BuildのリモートJib
  • ローカルのカスタムビルドスクリプト

4. ビルドしたイメージのテストを行う。

container-structure-test(https://github.com/GoogleContainerTools/container-structure-test)を利用して、ビルドしたコンテナのテストを行います。テストを行うには、container-structure-testのバイナリファイルをインストールしておく必要があります。

5. タグ付けを行う。

コンテナのタグ付けを行います。サポートしているタグ付けポリシーは、以下の通りです。

  • gitCommit
    Git Commit IDをタグに利用します。
  • sha256
    コンテンツのsha256ハッシュをタグに利用します。
  • envTemplate
    環境変数の値をタグに利用します。
  • dateTime
    日時をタグに利用します。

6. プッシュを行う。

コンテナイメージをリポジトリにプッシュします。ローカル開発でリポジトリへのプッシュが不要な場合は、プッシュをスキップさせることもできます。コンテキスト名が以下に該当する場合、ローカルクラスタと判定され、プッシュはスキップされます。

  • docker-for-desktop
  • docker-desktop
  • minikube

7. デプロイを行う。

Kubernetesクラスタへのデプロイを行います。サポートしているデプロイ方法は以下の通りです。

  • kubectl
  • helm
  • kustomize

デプロイの完了後、ソースコードの変更がKubernetes上に反映され、修正したアプリケーションの確認ができるようになります。

8. ソースコードの変更監視をつづける。

デプロイの完了後、”1. ソースコードの変更を監視する。“の処理に戻り、ソースコードの変更監視を続けます。

Skaffoldを終了(Ctrl + C)した場合、デプロイの跡片付けを行う。

起動したSkaffoldはターミナル上でCtrl + Cを押すことで終了することができます。Skaffoldが終了するタイミングで、Kubernetes上にデプロイされたアプリケーションも削除されます。

なお、ソースコードの変更監視やSkaffold終了後のデプロイ削除を行いたくない場合は、skaffold runコマンドを実行します。

 

Skaffoldのインストール(Windows WSL編)

WindowsのWSL for Ubuntu18.04にSkaffoldをインストールしてみます。

事前準備

Dockerとkubectlが必要になるので、利用する環境にあわせてインストールを行ってください。

kubectlはSkaffoldのデプロイ対象のKubernetesクラスタに接続できるように設定をしておいてください。ここでは、WSLのUbuntu18.04環境にkubectlのインストールと設定を行う方法を紹介します。

Docker for DesktopのKubernetesの有効化

Docker for Desktopのインストーラーを起動し、Dockerのインストールを完了させておいてください。インストール完了後、Dockerの設定画面を開き、Kubernetesを有効化してください。

※Settings -> Kubernetes -> Enable Kubernetesのチェックボックスをオン

Windowsの再起動後、Dockerの設定画面の左下で”Kubernetes is running”が表示されていれば、Kubernetesが起動しています。

kubectlのインストール

WSLのターミナルから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

kube configのコピー

Docker for Desktopのkube configファイルをWSLのホームディレクトリにコピーします。

$ mkdir ~/.kube
$ cp /mnt/c/Users/<username>/.kube/config ~/.kube

kubectlの実行確認

kubectlの実行確認を行います。Client、Serverのバージョンが取得できれば成功です。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4ca210618a89a555b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:25:46Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}

Skaffoldのインストール

公式ページのインストール手順(https://skaffold.dev/docs/getting-started/)に従って、Skaffoldのインストールを行います。ここではWSLのUbuntu18.04環境にSkaffoldをインストールをしてみます。

WSLのターミナルから以下のコマンドを実行します。

$ curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64
$ chmod +x skaffold
$ sudo mv skaffold /usr/local/bin

skaffoldコマンドでバージョンを表示して、インストールの成功を確認します。

$ skaffold version
v0.29.0

kubectlコマンドで現在のコンテキストも確認しておきましょう。

$ kubectl config get-contexts
CURRENT   NAME                 CLUSTER                      AUTHINFO             NAMESPACE
*         docker-for-desktop   docker-for-desktop-cluster   docker-for-desktop

現在のコンテキストは”docker-for-desktop”になっています。

Dockerクライアントの設定

WSLからDocker for Desktopのデーモンを利用できるようにします。はじめにWSL上のUbuntu18.04にDockerクライアントのインストールを行います。

$ sudo apt-get install \\
    apt-transport-https \\
    ca-certificates \\
    curl \\
    gnupg-agent \\
    software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository \\
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \\
   $(lsb_release -cs) \\
   stable"
$ sudo apt-get update
$ sudo apt-get install docker-ce-cli

dockerコマンドを実行してDockerクライアントの動作確認を行います。

$ docker version
Client:
 Version:           18.09.6
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        481bc77
 Built:             Sat May  4 02:35:57 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

最後のメッセージはWSL上にDockerデーモンが動作していないので出力されるエラーです。現時点ではこのメッセージが表示されていても問題ありません。

Docker for Desktopの設定

Dockerの設定画面からlocalhost:2375を利用できるようにチェックをいれます。

※Settings -> General -> Expose daemon on tcp://localhost:2375 without TLSのチェックボックスをオン

Dockerクライアントを利用するWSLユーザのDOCKER_HOST環境変数を設定します。

$ echo 'export DOCKER_HOST=tcp://localhost:2375' >> ~/.profile
$ source ~/.profile

再度、dockerのバージョンを取得してみます。

$ docker version 
Client:
 Version: 18.09.6
 API version: 1.39
 Go version: go1.10.8
 Git commit: 481bc77
 Built: Sat May 4 02:35:57 2019
 OS/Arch: linux/amd64
 Experimental: false
Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     false

今度は正常にServerのバージョンも取得できました。

 

サンプルアプリケーションの実行

Skaffoldの公式ページで提供されているサンプルのGoアプリケーションでSkaffoldの動作を確認してみます。このサンプルアプリケーションで、Skaffoldの以下の機能を体験してみましょう。

  • Skaffoldでソースコードの変更検知を行う
  • Skaffoldが自動でコンテナイメージのビルドを行う
  • Skaffoldが自動でコンテナイメージをKubernetesにデプロイする

それでは、以下の手順にしたがってSkaffoldの世界を体験してみてください。

サンプルアプリケーションのリポジトリをcloneする

サンプルアプリケーションのGitリポジトリをcloneします。

$ git clone https://github.com/GoogleContainerTools/skaffold

skaffold devの実行

サンプルアプリケーションのディレクトリに移動し、skaffold devコマンドを実行してみます。

$ cd skaffold/examples/getting-started/
$ skaffold dev

<省略>
Build complete in 47.229005s
Starting test...
Test complete in 33μs
Starting deploy...
kubectl client version: 1.14
pod/getting-started created
Deploy complete in 3.087859s
Watching for changes every 1s...
[getting-started] Hello world!

起動に成功するとターミナル上に1秒ごとに[getting-started] Hello world!が表示されます。KubernetesのPodを見てみましょう。

$ kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
getting-started   1/1     Running   0          8s

Kubernetes上で正常にPodが起動しています。続いて、ソースコードの編集をしてみます。編集するファイルはSkaffoldを起動したディレクトリにあるmain.goファイルです。

$ vim main.go

fmt.Println("Hello world!")の部分を適当な文言に修正して、保存をしてください。以下の例では”Hello Hello!”という文言に変更してみました。

package main

import (
        "fmt"
        "time"
)

func main() {
        for {
                fmt.Println("Hello Hello!")

                time.Sleep(time.Second * 1)
        }
}

保存が完了すると、Skaffoldがソースコードの変更を検知し、再度ビルドからデプロイまでのフローが実行されます。ターミナル上には修正した文言が新たに表示されることが確認できます。

 

サンプルアプリケーションの停止

サンプルアプリケーションをCtrl + cで停止します。skaffold devで実行したアプリケーションを停止した場合、skaffoldのクリーニング処理が実行され、対象のリソースが削除されます。

^CPruning images...
Cleaning up...
pod "getting-started" deleted
Cleanup complete in 3.17803s

Kubernetes上のPodが削除されか確認をしてみましょう。

$ kubectl get pods
No resources found.

Podも削除されました。

 

さいごに

Skaffoldを利用することで、ローカルでのKubernetesアプリケーション開発を楽にすることができます。ソースコードの変更をトリガーとしてコンテナのビルドからデプロイが自動化されるので、ビルドやデプロイのミスもなくすことができます。

ローカルでのビルドやデプロイなど、何度も繰り返し行う作業は可能な限り自動化して、手間やミスの削減につなげていきましょう。

スカイアーチ ファンタジー研究室

スカイアーチ ファンタジー研究室

投稿者プロフィール

石川 淳
スカイアーチネットワークスで、新しいサービスの企画を行っています。
元SIer、元スマフォ向けゲームインフラの経験を生かして、新しいサービスをリリースしていきます。現在企画中のサービスはこちら。
https://github.com/easydoggie
コメントを頂けると嬉しいです。

コメントを残す

メールアドレスが公開されることはありません。

Time limit is exhausted. Please reload CAPTCHA.

ABOUTこの記事をかいた人

スカイアーチネットワークスで、新しいサービスの企画を行っています。 元SIer、元スマフォ向けゲームインフラの経験を生かして、新しいサービスをリリースしていきます。現在企画中のサービスはこちら。 https://github.com/easydoggie コメントを頂けると嬉しいです。