コンテナクラスタ管理ツール「kubernetes」でDockerをもっと便利に使う方法

2017/08/21

Jatin Shridhar

72

Articles in this issue reproduced from SitePoint
Copyright © 2017, All rights reserved. SitePoint Pty Ltd. www.sitepoint.com. Translation copyright © 2017, KADOKAWA ASCII Research Laboratories, Inc. Japanese syndication rights arranged with SitePoint Pty Ltd, Collingwood, Victoria,Australia through Tuttle-Mori Agency, Inc., Tokyo

もともと単一サーバーでの利用を前提に開発されたDockerをクラスタ環境でも便利に使いたい。そんなときに便利なツールが「Kubernetes」です。基本的な使い方を紹介します。

コンテナ技術が使われるはじめてから何年かたちました。企業や開発者の多くがアプリを配布するのにコンテナを使っています。使いやすいインターフェイスでコンテナ技術を広めたのがDockerです。

1つのコンテナで済むアプリケーションは稀で、いくつかのコンテナを複数のホストにデプロイします。この記事では、オープンソースシステムで、コンテナ化されたアプリケーションの自動デプロイ、スケーリング、管理ができるKubernetesを紹介します。

前提条件:この記事は、Dockerの知識がある読者を対象とします。Dockerについて復習が必要だと思う人は、Understanding Docker, Containers and Safer Software Deliveryを読んでください。

Kubernetesで解決できる問題

Dockerは、コンテナを起動したり、停止したりするのに、コマンドdocker rundocker stopを使います。単一のコンテナなら十分ですが、複数のホストに新しくイメージを入れ込むdocker deployコマンドはありません。

「コンテナの協調」を解決するツールが多くあります。有名なツールは、Dockerエンジンに含まれているMesosDocker SwarmNomad、そしてKubernetesです。それぞれ長所と短所がありますが、現時点ではKubernetesが一番使われています。

Kubernetes(k8sとも呼ばれます)では、デプロイやスケーリングなどのアプリケーション操作が、基礎となるインフラ操作から完全に独立しています。従って、Kubernetesを使うと、別々のホストや仮想マシンでコードを走らせる必要がなくなります。Kubernetesでは基礎となるインフラを、コンテナを置く計算の海と呼びます。

Kubernetesのコンセプト

Kubernetesはクライアント・サーバー構造を採用しています。Kubernetesサーバーがクラスター(1群のホスト)上で稼働し、アプリをデプロイします。具体的には、kubectl CLIから、クライアントを使ってクラスターとやり取りします。

Pods

PodはKubernetesが扱う基本的な単位であり、複数のコンテナからなるグループです。2つ以上のコンテナが常に協働して、同じマシンになければならない場合はpodとします。Podは便利な抽象化なので、第1級のdockerオブジェクトにすべきだと提案もあったくらいです。

ノード

ノードは、Kubernetesを走らせている物理的、あるいは仮想マシンです。ノード上でpodをスケジューリングできます。

ラベル

ラベルは、リソースを識別するのに用いるkey/valueのペアです。たとえば、productionトラフィックの役目をしているpodに、role=productionのラベルがつきます。

セレクター

セレクターを使うと、ラベルによりリソースの検索・フィルタリングができます。production podをすべて集めるには、セレクターはrole=productionとします。

サービス

podの集合(具体的には、セレクタで選択されたpod)を定義し、アクセスする手段を定義します。たとえば、単一固定のIPアドレスや対応するDNS名で定義します。

KubernetesでGKEにNode.jsアプリをデプロイする

Kubernetesの基本的なコンセプトを理解したところで、Google Container Engine(GKEと呼ばれます)にNode.jsのアプリケーションをデプロイして、Kubernetesの挙動を確認します。Google Cloud Platformアカウントが必要です($300相当のクレジットつきの無料トライアルがあります)。

1.Google Cloud SDKとKubernetesをインストールする

kubectlは、Kubernetesクラスターに対してコマンドを走らせるコマンドラインインターフェイスです。Google Cloud SDKの一部としてインストールできます。Google Cloud SDKがインストールできたら、次のコマンドを走らせてkubectlをインストールします。

$ gcloud components install kubectl

Macは、brew install kubectlとします。インストールがうまくいったか確かめるには、kubectl versionを実行します。

GoogleクラウドアカウントでGoogle cloud SDKを設定します。gcloud initを実行して、指示に従えば大丈夫です。

2.GCPプロジェクトを作成する

Google Cloudプラットホームのリソースはすべて、プロジェクトの下に作るので、web UIからプロジェクトを作ります。

CLIから以下を走らせて、デフォルトのプロジェクトIDを設定します。

gcloud config set project {PROJECT_ID}

3.アプリケーションのDockerイメージを作成する

ここではexpress-hello-worldを例に解説します。Dockerfileを見ると、dockerhubから既存のNode.jsイメージを使っているのが分かります。以下を走らせて、アプリケーションイメージを作ります。

$ docker build -t hello-world-image . 

アプリをローカルで実行します。

docker run --name hello-world -p 3000:3000 hello-world-image

localhost:3000で、実行結果を確認します。

4.クラスターを生成する

3つのインスタンス(仮想マシン)を持つクラスターを作り、アプリケーションをデプロイします。直観的なweb UIのContainer engine pageでデプロイできます。または以下のコマンドで実行します。

$ gcloud container clusters create {NAME} --zone {ZONE} 

以下を走らせて、us-east1-bhello-world-clusterというクラスターを作成します。

$ gcloud container clusters create hello-world-cluster --zone us-east1-b --machine-type f1-micro 

3つのノードからなるクラスターを起動できます。マシンタイプにf1-microを用いていますが、使えるもののうちで最小のものを使って、コストを最小限にするためです。

次を走らせて、kubectlクライアントをクラスターに接続します。

gcloud container clusters get-credentials hello-world-cluster --zone us-east1-b

dockerイメージとクラスターができました。Dockerイメージをクラスターに配置してコンテナを開始すれば目的達成です。

5.DockerイメージをGoogleコンテナイメージレジストリにアップロードする

Googleコンテナイメージレジストリはクラウドレジストリなので、イメージを保存できます。イメージは、コンテナエンジンクラスターで自動的に使えます。イメージを保存するには、適切な名前でビルドする必要があります。

アプリケーションのコンテナイメージを作り、アップロード用のタグをつけます。

$ docker build -t gcr.io/{PROJECT_ID}/hello-world-image:v1 .

v1がイメージのタグです。

いま作成したイメージをアップロードします。

$ gcloud docker -- push gcr.io/{PROJECT_ID}/hello-world-image:v1

6.初回のデプロイ

クラウドにクラスターとイメージができました。Kubernetesを使って、イメージをクラスターにデプロイするために、deploymentスペックファイルを作ります。デプロイメントはkubernetesリソースであり、kubernetesリソースはすべてスペックファイルで宣言的に定義できます。このスペックファイルで求めるリソース状態を規定すると、Kubernetesが現在の状態からその状態までリソースを移行させる方法を考えます。

初回のデプロイのためにスペックファイルを作ります。

deployment.yml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: hello-world-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels: # labels to select/identify the deployment
        app: hello-world  
    spec:     # pod spec                  
      containers: 
      - name: hello-world 
        image: hello-world-image:v1 # image we pushed
        ports:
        - containerPort: 3000

スペックファイルの中身です。与えられたpodスペックで定義された2つのpodをスタートさせます。各podはhello-world-image:v1が入っているコンテナを1つずつ持っています。

実行
$ kubectl create -f deployment.yml --save-config

kubectl get deploymentsを走らせると、デプロイ状態が分かります。デプロイで作られたpodは、kubectl get podsを走らせると、実行中のpodが分かります。

$ kubectl get pods
NAME                                     READY     STATUS    RESTARTS   AGE
hello-world-deployment-629197995-ndmrf   1/1       Running   0          27s
hello-world-deployment-629197995-tlx41   1/1       Running   0          27s

deployment.ymlファイルで、レプリカを2に設定したため、Podの数は2つになります。

サーバーの起動を確認します。以下を走らせてログをチェックします。

$ kubectl logs {pod-name}  # kubectl logs hello-world-deployment-629197995-ndmrf

7.サービスをインターネットに公開する

サービスをインターネットに公開するには、ロードバランサーを作成してVMを登録します。Kubernetes Serviceを作成します。

$ kubectl expose deployment hello-world-deployment --type="LoadBalancer"

裏で、サービスオブジェクト(サービスはデプロイメントと同様、Kubernetesのリソース)が生成され、Google Cloudロードバランサーも作成されます。

kubectl get servicesを走らせて、サービスのパブリックIPを確認します。コンソール出力はこ以下の通りです。

NAME                     CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
hello-world-deployment   10.103.254.137   35.185.127.224   3000:30877/TCP   9m
kubernetes               10.103.240.1     <none>           443/TCP          17d

サービスにアクセスするにはhttp://<EXTERNAL-IP>:<PORT>を確認します。専用のドメインを買って、このIPを指定します。

8.サービスをスケーリングする

サービスのトラフィックが増えて、アプリケーションのインスタンスを増やす必要が出てきたら、deployment.ymlファイルを編集して、replicasの数を変更します(たとえば3に)。それからkubectl apply -f deployment.ymlを実行すると、3つのpodが走ります。自動スケーリングの設定もできますが、チュートリアルの範囲外とします。

9.クリーンアップ

リソースのクリーンアップを忘れてはいけません。Googleクレジットがどんどんなくなります!

$ kubectl delete service/hello-world-deployment
$ kubectl delete deployment/hello-world-deployment
$ gcloud container clusters delete hello-world-cluster --zone us-east1-b 

まとめ

幅広くカバーしましたが、Kubernetesは1つのコマンドでより多くのpodのサービスをスケーリングしたり、AWS認証などのためにpodにsecretをマウントしたりと、いろいろなことができます。しかし、最初はこのチュートリアルの内容で十分だと思います。もっとやってみたい人は、kubernetes.ioに挑戦してください。

本記事はGraham Coxが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。

(原文:Introduction to Kubernetes: How to Deploy a Node.js Docker App

[翻訳:関 宏也/編集:Livit

Copyright © 2017, Jatin Shridhar All Rights Reserved.

Jatin Shridhar

Jatin Shridhar

現役のソフトウェア開発者で、スタンドアップコメディアン志望。Amazonでの勤務経験があり、ずっと「『.js』とは自分のイニシャルなのだ」と考えていました。

Loading...