今まではなんとなくの知識だけで、自分で触ってみたことはなかったので、今更ですが公式チュートリアルで Kubernetes に入門してみました。
チュートリアルの中にも色々あるのですが、今回は一番基本的な Kubernetes Basics をやってみます。
チュートリアルはブラウザ上で仮想ターミナルからコマンドを実行できる Katacoda の環境の上で提供されています。
また、 Katacoda の上で Minikube という簡単にローカルに Kubernetes 環境を構築するツールが使われています。
Kubernetes Basics は6つの Modules に分かれているので、一つずつ進めてみます。分量が多くなってしまったので、今回は Module 1 から 3 までを進めます。
Kubernetes Clusters(Module 1)
まずは Kubernetes Clusters についてです。 Kubernetes は可用性の高いクラスタ環境を管理し、アプリケーションコンテナの管理を自動化します。
クラスタの中には Master と Node が存在し、 Master がクラスタを管理します。 Node は実際にサービスを提供するVMもしくは物理コンピュータになります。
また、 Node が Master と連携するために Kubelet というエージェントが存在します。
さらに Node はコンテナのオペレーションをハンドリングするために、 Docker または rkt を使用します。
Kubenetes Cluster ではトラフィックを処理するためには最低3つの Node を保持する必要があります。
では実際にチュートリアルを進めてみます。チュートリアルは Katacoda 環境でコマンドを実行しながら進めることができます。
まずは Minikube のバージョンを確認します。
$ minikube version minikube version: v0.28.2
そして Minikube を実行します。
$ 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.
Minikube によって Kubernetes 環境が構築されました。
Kubernetes の操作には CLI の kubectl を使用します。まずはバージョンを確認してみます。
$ kubectl version Client Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.0", GitCommit:"91e7b4fd31fcd3d5f436da26c980becec37ceefe", GitTreeState:"clean", BuildDate:"2018-06-27T20:17:28Z", GoVersion:"go1.10.2", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-04-10T12:46:31Z", GoVersion:"go1.9.4", Compiler:"gc", Platform:"linux/amd64"}
Client Version は kubectl のバージョンで、 ServerVersion は Master にインストールされている Kubernetes のバージョンになります。
次にクラスタの情報を確認してみます。
$ kubectl cluster-info Kubernetes master is running at https://172.17.0.48:8443 To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
チュートリアル中は CLI のみで進めますが、表示された URL にアクセスすると、クラスタの情報が確認できるダッシュボードを表示することができます。
続いて Node を確認してみます。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION minikube Ready <none> 7m v1.10.0
現在は Node は一つだけで、 STATUS が Ready になっていて、アプリケーションのデプロイが可能な状態になっています。
Kubernetes Deployments(Module 2)
Kubernetes Cluster を稼働させていれば、その上にコンテナ化されたアプリケーションをデプロイすることができます。そのためには Kubernetes Deployment の設定を作成します。
もし Node がダウンしたり削除されたりすると、 Deployment コントローラはそれをリプレイスします。これによってメンテナンス時や障害時の自律回復機構を提供します。
Deployment の管理は kubectl で行うことができます。 Deployment を作成するときは、アプリケーションのコンテナイメージと、稼働させるレプリカの数を指定します。このチュートリアルでは Docker コンテナにパッケージされた Node.js アプリケーションが使われます。
チュートリアルを開始すると下記のように自動的にシェルが実行され、クラスタが起動します。
$ sleep 1; launch.sh Starting Kubernetes... Kubernetes Started
Node を確認すると下記のように一つだけ稼働していることがわかります。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION minikube Ready <none> 2m v1.10.0
新しい Deployment を作成するには、 kubectl run コマンドを使用します。実行時には Deployment名とコンテナイメージのロケーションを指定する必要があります。また、特定のポートでアプリを実行するためには --port オプションを使用します。
$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080 deployment.apps/kubernetes-bootcamp created
Deployment を確認してみます。
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 1 1 1 30m
Deployment が一つあり、一つのインスタンスで稼働していることがわかります。このインスタンスは Node の Docker コンテナ上で稼働しています。
Kubernetes 内で稼働している Pod はプライベートで独立したネットワーク内で稼働しています。デフォルトでは同じクラスタ内からのみアクセス可能です。 kubectl 使用時には API エンドポイントを通して連携が行われています。また、 kubectl コマンドでクラスタ内のプライベートネットワーク内でのアクセスを転送するプロキシを作成することができます。作業用のターミナルとは別ターミナルで下記のコマンドを実行します。
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
これでオンラインターミナルが稼働しているホストと Kubernetes Cluster 間でのコネクションが作成されました。プロキシによって API にターミナルからダイレクトにアクセスできるようになっています。
$ curl http://localhost:8001/version { "major": "1", "minor": "10", "gitVersion": "v1.10.0", "gitCommit": "fc32d2f3698e36b93322a3465f63a14e9f0eaead", "gitTreeState": "clean", "buildDate": "2018-04-10T12:46:31Z", "goVersion": "go1.9.4", "compiler": "gc", "platform": "linux/amd64" }
API サーバは自動的に Pod名をベースにしたエンドポイントを作成します。プロキシを通してそのエンドポイントにもアクセスすることができます。そのためには Pod名が必要なので、 Pod名を取得して環境変数に保持します。
$ 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-288s7
この Pod名を使ってエンドポイントにアクセスしてみます。 Pod の API の URL は下記のようになります。
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/ Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-288s7 | v=1
Kubernetes Pods And Nodes(Module 3)
Pod は一つまたはそれ以上のアプリケーションコンテナ(Docker または rkt)を表していて、いくつかのリソースをコンテナ間で共有します。リソースには下記のようなものが含まれます。
共有ストレージ
ネットワーク(ユニークなクラスタIP)
コンテナイメージのバージョンや使用するポートなどの情報
Pod 内のコンテナは IP アドレスとポートの空間を共有します。
Pod は Kubernetes プラットフォームでの最小ユニットになります。
また、 Pod は常に Node 上で稼働します。
全ての Node では少なくとも Kubelet(Pod とコンテナを管理し、Master と Node の連携を行う)と、コンテナのランタイム(Docker や rkt など)が稼働します。
現在の Pod を確認するには kubectl の get コマンドを使用します。
$ kubectl get pods NAME READY STATUS RESTARTS AGE kubernetes-bootcamp-5c69669756-sv4wc 1/1 Running 0 1m
Pod 内のコンテナや、そのコンテナで使われているイメージを確認するには、 kubectl describe pods
コマンドを使用します。このコマンドによって Pod の IP アドレスやポート、ライフサイクルイベントなども確認することができます。
$ kubectl describe pods Name: kubernetes-bootcamp-5c69669756-sv4wc Namespace: default Node: minikube/172.17.0.4 Start Time: Sat, 29 Dec 2018 10:40:18 +0000 Labels: pod-template-hash=1725225312 run=kubernetes-bootcamp Annotations: <none> Status: Running IP: 172.18.0.2 Controlled By: ReplicaSet/kubernetes-bootcamp-5c69669756 Containers: kubernetes-bootcamp: Container ID: docker://051074e6dc2c7b6fb75c92ace46fad77838d4392b7270a7b2fa9dad372a9086d Image: gcr.io/google-samples/kubernetes-bootcamp:v1 Image ID: docker-pullable://gcr.io/google-samples/kubernetes-bootcamp@sha256:0d6b8ee63bb57c5f5b6156f446b3bc3b3c143d233037f3a2f00e279c8fcc64af Port: 8080/TCP Host Port: 0/TCP State: Running Started: Sat, 29 Dec 2018 10:40:18 +0000 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-l6t4t (ro) Conditions: Type Status Initialized True Ready True PodScheduled True Volumes: default-token-l6t4t: Type: Secret (a volume populated by a Secret) SecretName: default-token-l6t4t 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 ---- ------ ---- ---- ------- Warning FailedScheduling 4m (x4 over 4m) default-scheduler 0/1 nodes are available: 1 node(s) were not ready. Normal Scheduled 4m default-scheduler Successfully assigned kubernetes-bootcamp-5c69669756-sv4wc to minikube Normal SuccessfulMountVolume 4m kubelet, minikube MountVolume.SetUpsucceeded for volume "default-token-l6t4t" Normal Pulled 4m kubelet, minikube Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine Normal Created 4m kubelet, minikube Created container Normal Started 4m kubelet, minikube Started container
プロキシ経由で Pod 関連の操作を行うために再度別ターミナルでプロキシを実行します。
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
Pod 名を環境変数に格納します。
$ 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-sv4wc
curl コマンドでアプリケーションのアウトプットを確認します。
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/ Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-sv4wc | v=1
アプリケーションが標準出力に送ったものは Pod 内のコンテナのログになります。そのログは kubectl logs
コマンドで確認することができます。 Pod 内にコンテナが一つの場合はコンテナ名を指定する必要はありません。
$ kubectl logs $POD_NAME Kubernetes Bootcamp App Started At: 2018-12-29T10:40:18.825Z | Running On: kubernetes-bootcamp-5c69669756-sv4wc Running On: kubernetes-bootcamp-5c69669756-sv4wc | Total Requests: 1 | App Uptime: 725.334 seconds | Log Time: 2018-12-29T10:52:24.159Z
Pod が稼働していれば、コンテナ上で直接コマンドを実行することができます。そのためには exec コマンドと Pod 名を使用します。環境変数のリストを表示する例は下記の通りです。
$ kubectl exec $POD_NAME env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=kubernetes-bootcamp-5c69669756-sv4wc KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 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 NPM_CONFIG_LOGLEVEL=info NODE_VERSION=6.3.1 HOME=/root
bash のセッションを開始することもできます。
$ kubectl exec -ti $POD_NAME bash root@kubernetes-bootcamp-5c69669756-sv4wc:/#
セッション開始後はそのままコマンドが実行できます。
root@kubernetes-bootcamp-5c69669756-sv4wc:/# ls
bin core etc lib media opt root sbin srv tmp var
boot dev home lib64 mnt proc run server.js sys usr
NodeJS コンテナ内からの実行になるので、 curl も localhost 指定で実行可能です。
root@kubernetes-bootcamp-5c69669756-sv4wc:/# curl localhost:8080 Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-sv4wc | v=1
まとめ
仮想環境が提供されているので、すぐにチュートリアルが始められるのはハードルが低くて良いですね。今回は前半まででしたが、クラスタ環境の構成まではイメージすることができました。後編ではスケーリングやローリングアップデートも扱われているので、サクッとやってみたいと思います。