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

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

コンニチハ、千葉です。

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

範囲

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

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

他の回はこちら

アプリケーションの公開

この章では、以下がわかります。

  • Kubernetesのserviceについて
  • labelsとLabelSelectorがどのようなものか、またサービスとの関係について
  • サービスを使ったアプリケーションの外部公開

チュートリアルではkubectl exposeコマンドを使って、Kubernetesクラスターの外にどうやってアプリケーションを公開するかを学びます。また、kubectl labelコマンドを使ってラベルを確認したり反映します。

新しいServiceの作成

前回起動したpodとminikubeがデフォルトで起動しているserviceを確認します。

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-gp797   1/1       Running   2          2d
$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d

新しいserviceを作成します。exposeコマンドで、ポート番号を指定することで外側と通信ができるようになります。以下のコマンドでは第1回で作成したkubernetes-bootcampというdeploymentsに対してserviceを作成しています。(minikubeはLoadBalancerオプションをまだサポートしていません)

$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080
deployment "kubernetes-bootcamp" created
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service "kubernetes-bootcamp" exposed
$ kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP          8d
kubernetes-bootcamp   NodePort    10.100.255.141   <none>        8080:31674/TCP   11s

serviceが作られたので、インターナルからのアクセスのみだったpodへ、クラスターIP経由でアクセスできるようになりました。イメージ的には、EC2にEIPを付与した感じでしょうか。 どのようなポートがオープンされているか確認します。

$ kubectl describe services/kubernetes-bootcamp
Name:                     kubernetes-bootcamp
Namespace:                default
Labels:                   run=kubernetes-bootcamp
Annotations:              <none>
Selector:                 run=kubernetes-bootcamp
Type:                     NodePort
IP:                       10.100.255.141
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  31674/TCP
Endpoints:                172.17.0.3:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

ノードポートを取得して、起動されたコンテナにアクセスしてみます。

$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=31674
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-64czk | v=1

アクセスできました。

labelを使う

deploymentを作成すると、podに自動的にlabelが作成されます。labelはkey/valueのペア文字列で、AWSでいうタグのようなものになります。 podeに付与されたlabelを確認します。

$ kubectl describe deployment
Name:                   kubernetes-bootcamp
Namespace:              default
CreationTimestamp:      Wed, 09 May 2018 08:11:28 +0900
Labels:                 run=kubernetes-bootcamp
Annotations:            deployment.kubernetes.io/revision=1
Selector:               run=kubernetes-bootcamp
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:        gcr.io/google-samples/kubernetes-bootcamp:v1
    Port:         8080/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   kubernetes-bootcamp-5c69669756 (1/1 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  21m   deployment-controller  Scaled up replica set kubernetes-bootcamp-5c69669756 to 1

labelを指定することで、pod一覧やservice一覧を取得するときにフィルタリングできます。

$ kubectl get pods -l run=kubernetes-bootcamp
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-64czk   1/1       Running   0          23m
$ kubectl get services -l run=kubernetes-bootcamp
NAME                  TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes-bootcamp   NodePort   10.100.255.141   <none>        8080:31674/TCP   22m

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-64czk

labelコマンドを使って、新しいlabel名を設定します。

$ kubectl label pod $POD_NAME app=v1
pod "kubernetes-bootcamp-5c69669756-64czk" labeled
$ kubectl describe pods $POD_NAME
Name:           kubernetes-bootcamp-5c69669756-64czk
Namespace:      default
Node:           minikube/10.0.2.15
Start Time:     Wed, 09 May 2018 08:11:28 +0900
Labels:         app=v1
                pod-template-hash=1725225312
                run=kubernetes-bootcamp
Annotations:    <none>
Status:         Running
IP:             172.17.0.3
Controlled By:  ReplicaSet/kubernetes-bootcamp-5c69669756
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://9cc7ac40161cd91b3682ea418b423777c9cdc3941035570fc48d59f97c1bdad6
    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:      Wed, 09 May 2018 08:11:29 +0900
    Ready:          True
    Restart Count:  0
    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  Scheduled              29m   default-scheduler  Successfully assigned kubernetes-bootcamp-5c69669756-64czk to minikube
  Normal  SuccessfulMountVolume  29m   kubelet, minikube  MountVolume.SetUp succeeded for volume "default-token-bbmpz"
  Normal  Pulled                 29m   kubelet, minikube  Container image "gcr.io/google-samples/kubernetes-bootcamp:v1" already present on machine
  Normal  Created                29m   kubelet, minikube  Created container
  Normal  Started                29m   kubelet, minikube  Started container

app=v1というlabelが設定できました。新しいlabelを指定してpodをフィルタしてみます。

$ kubectl get pods -l app=v1
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-5c69669756-64czk   1/1       Running   0          29m

serviceの削除

delete serviceコマンドでserviceを削除します。

$ kubectl delete service -l run=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   8d

serviceが削除されたので、外部からアクセスができなくなりました。

curl $(minikube ip):$NODE_PORT

serviceを削除しても、インターナルからのアクセスは可能です。

$ kubectl exec -ti $POD_NAME curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-5c69669756-64czk | v=1

最後に

Serviceを使ったアプリケーションを外部から接続から、labelの設定を行いました。次回はアプリケーションのスケールアウトを行っていきたいと思います。

他の回はこちら

参考

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