話題の記事

[第1回]Kubernetesの公式チュートリアルをやって基本を押さえる -アプリのデプロイ-

2018.05.08

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

コンニチハ、千葉です。

Kubernetesを勉強中です。Kubernetesは簡単に使えて、かつコンテナのデプロイや可用性を向上することができます。高度なことを簡単に使えるようにテクノロジーが注ぎ込まれています。 チュートリアルでは、クラスタの起動からアプリケーションのデプロイ、確認、公開、アップデートまで基本的なライフサイクルを身につけられます。分量が多いので数回に分けて、チュートリアルをやっていきましょう。

範囲

*の箇所が第1回の範囲です。

  • *クラスターの作成
  • *アプリケーションのデプロイ
  • *アプリケーションの状態確認
  • アプリケーションの公開
  • アプリケーションのスケールアウト
  • アプリケーションのアップデート

他の回はこちら

環境の用意

チュートリアルを実施するKubernetesの環境を用意します。 Kubernetesのベーシックチュートリアルでは、Web上でターミナル環境が用意されておりコマンドを打って試すことができます。そのため、特に環境を用意する必要がありませんが、私はガチャガチャ触りたかったのでMinikubeを使ってローカルに環境を用意し試しました。

クラスターの作成

この章では、クラスターの起動と状態の確認を行います。チュートリアルではMinikubeを利用しています。

クラスターの起動と状態確認

Minikubeを利用するのでバージョン確認します。

$ minikube version
minikube version: v0.26.1

Minikubeを利用しKubernetesクラスタを起動します。

$ minikube start
Starting local Kubernetes v1.10.0 cluster...
Starting VM...

Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

クラスターのバージョン確認

Kubernetes APIを実行するコマンドラインツール kubectl のバージョンとマスターノードのKubernetesバージョンの確認します。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.0", GitCommit:"925c127ec6b946659ad0fd596fa959be43f0cc05", GitTreeState:"clean", BuildDate:"2017-12-16T03:16:50Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:44:10Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}

クラスターの詳細確認

クラスターの詳細情報を取得します。

kubectl cluster-info
Kubernetes master is running at https://192.168.99.100:8443
KubeDNS is running at https://192.168.99.100:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

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

マスターノードとダッシュボードが起動しています。ダッシュボードとは実行しているアプリケーションを確認できるUI。このチュートリアルでは、CLIを使います。 ちなみにminikube dashboardでダッシュボードにアクセスできます。

すべてのノード情報を取得。ただしMinikube環境では1つのノードのみ実行されています。ノードとはホスト(物理または仮想ホスト)です。

kubectl get nodes
NAME       STATUS    ROLES     AGE       VERSION
minikube   Ready     master    5d        v1.10.0

Kubernetesはクラスターを管理するマスターとアプリケーション(コンテナ)を実行するノードの2種類があります。Minikubeではマスターのみ起動している状態になります。

アプリケーションのデプロイ

この章では、kubectlを使ってアプリケーション(コンテナ)のデプロイを行います。デプロイされるとアプリケーションは監視され、ホストが停止しても自動復旧するようになります。

アプリのデプロイ

kubectl runを使用してアプリを起動します。runは新しいデプロイを作成します。デプロイの名前とアプリケーションイメージ(Docker Hubやプライベートレポジトリなど)、ポート番号を指定します。

$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080
deployment "kubernetes-bootcamp" created

デプロイを作成すると、いくつかのことが実行されます

  • アプリケーションを実行するノードを探す
  • アプリケーションを探したノードで実行するようにスケジュールする
  • 必要に応じてクラスターを構成し、新しいノードでアプリケーションを実行するうように再スケジュールする。つまり、ノードが停止してもアプリケーションが起動するように維持されます。

デプロイのリストを表示します。インスタンスはDockerコンテナとしてノードで実行されます。

$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           23s

アプリへの通信

デプロイを作成すると、KubernatesはPodを作成しアプリケーションインスタンス(コンテナ)をホストします。Podは、1つまたは複数のアプリケーションコンテナのグループです。今回のチュートリアルでのデプロイは1つのコンテナですが、PodではDocker Compose 的な感じで複数コンテナをグルーピングすることもできます。 デプロイされたPodは、プライベートネットワークで分離されています。デフォルトでは、Kubernetesクラスター内のみ通信ができますが、外との通信はできません。 外部ネットワークとPodを通信させるためには、proxyまたはexposeを利用します。*exposeは第2回でやるのでそちらで説明します。 kubectl proxyを実行すると、KubernetesのAPIエンドポイント経由でアプリケーションにアクセスできます。kubectlがapiエンドポイントへのリバースプロキシとして動作します。 kubectl proxy(ローカル端末) > Kubernetesクラスターで起動しているAPIエンドポイント > Podというイメージです。

プロキシを起動します。プロセスが起動するので停止したい場合はcontrol-Cを入力します。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

別のターミナルを起動し、ローカルで起動しているプロキシ経由でAPIエンドポイントへアクセスし、バージョン情報を取得します。取得した情報を見るとkubectl versionで取得したサーバー情報と同じ内容が取得できてますね!

$ curl http://localhost:8001/version
{
  "major": "1",
  "minor": "10",
  "gitVersion": "v1.10.0",
  "gitCommit": "fc32d2f3698e36b93322a3465f63a14e9f0eaead",
  "gitTreeState": "clean",
  "buildDate": "2018-03-26T16:44:10Z",
  "goVersion": "go1.9.3",
  "compiler": "gc",
  "platform": "linux/amd64"
}

また、APIサーバーはPodへアクセスするためのエンドポイントを自動で作成します。Pod名を取得し、APIサーバー経由でアプリケーションにアクセスしてみます。

$ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-5c69669756-gp797
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-gp797 | v=1

ローカルで起動しているプロキシ経由でデプロイしたアプリケーションにアクセスできてます!

アプリケーションの状態確認

この章では、kubernetesアプリケーションのトラブルシューティングの仕方について学習します。kubectl get, describe, logs and exec commandsを利用します。

アプリケーションの構成情報確認

実行されているPodのを取得します。1つのPodが起動されています。

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-gp797   1/1       Running   1          1d

コンテナの詳細情報(IP、ポート、ライフサイクル)などなど。見説明の情報も出力されてますが、チュートリアル終了時には内容がわかるでしょう。

$ kubectl describe pods
Name:           kubernetes-bootcamp-5c69669756-gp797
Namespace:      default
Node:           minikube/10.0.2.15
Start Time:     Sun, 06 May 2018 10:01:08 +0900
Labels:         pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.17.0.4
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://decd7e0506b562586a7b5bcfd63792d49f2f965b64d5c167636ee002d693d347
    Image:          gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID:       docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af
    Port:           8080/TCP
    State:          Running
      Started:      Mon, 07 May 2018 21:32:01 +0900
    Last State:     Terminated
      Reason:       Error
      Exit Code:    137
      Started:      Sun, 06 May 2018 10:01:08 +0900
      Finished:     Mon, 07 May 2018 16:48:47 +0900
    Ready:          True
    Restart Count:  1
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-bbmpz (ro)
Conditions:
  Type           Status
  Initialized    True
  Ready          True
  PodScheduled   True
Volumes:
  default-token-bbmpz:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-bbmpz
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  SuccessfulMountVolume  45m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-bbmpz"
  Normal  SandboxChanged         45m   kubelet, minikube  Pod sandbox changed, it will be killed and re-created.
  Normal  Pulled                 45m   kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal  Created                45m   kubelet, minikube  Created container
  Normal  Started                45m   kubelet, minikube  Started container

ターミナルからアプリケーションを確認

プロキシを使ったアプリケーションへのアクセスです。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

もうひとつのターミナルで実行します。

$ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
$ echo Name of the Pod: $POD_NAME
Name of the Pod: kubernetes-bootcamp-5c69669756-gp797
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-gp797 | v=1

コンテナログを確認

コンテナのSTDOUTに出力されているログを確認します。STDOUTに出力されている起動ログと、アクセスログが確認できます。

$ kubectl logs $POD_NAME
Kubernetes Bootcamp App Started At: 2018-05-07T12:32:01.991Z | Running On:  kubernetes-bootcamp-5c69669756-gp797

Running On: kubernetes-bootcamp-5c69669756-gp797 | Total Requests: 1 | App Uptime: 1860.883 seconds | Log Time: 2018-05-07T13:03:02.874Z
Running On: kubernetes-bootcamp-5c69669756-gp797 | Total Requests: 2 | App Uptime: 3229.955 seconds | Log Time: 2018-05-07T13:25:51.946Z

コンテナ上でコマンド実行

起動しているコンテナに対して直接コマンドを実行します。execを使います。

$ kubectl exec $POD_NAME env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-5c69669756-gp797
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root

今度はbashセッションを開始します。

$ kubectl exec -ti $POD_NAME bash
root@kubernetes-bootcamp-5c69669756-gp797:/# cat server.js
var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;
var handleRequest = function(request, response) {
  response.setHeader('Content-Type', 'text/plain');
  response.writeHead(200);
  response.write("Hello Kubernetes bootcamp! | Running on: ");
  response.write(host);
  response.end(" | v=1\n");
  console.log("Running On:" ,host, "| Total Requests:", ++requests,"| App Uptime:", (new Date() - startTime)/1000 , "seconds", "| Log Time:",new Date());
}
var www = http.createServer(handleRequest);
www.listen(8080,function () {
    startTime = new Date();;
    host = process.env.HOSTNAME;
    console.log ("Kubernetes Bootcamp App Started At:",startTime, "| Running On: " ,host, "\n" );
});
root@kubernetes-bootcamp-5c69669756-gp797:/# curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-gp797 | v=1
root@kubernetes-bootcamp-5c69669756-gp797:/# exit
exit

sshのようにコンテナに接続してコマンド実行ができました。

さいごに

Minikubeを利用し、クラスターやPodの情報取得、Kubernetes上にコンテナを起動して、接続や直接コマンド実行を行いました。 初めて触りましたが、Kubernetesの雰囲気がつかめました。第2回では、アプリケーションの公開をやります!

他の回はこちら

参考

https://kubernetes.io/docs/tutorials/kubernetes-basics/