[ 言語選択: English ]

1. 作業の流れ

kubernetes.ioで公開されている公式サンプルを、このk8sクラスターで実行する方法を説明します。

ここでの作業はゼミ室内のThinkPadで実行することを前提に作成しています。

演習室や自分のPCで実施する場合には、次の点に留意してください。

  1. "$(id -un)" の部分を 自分のID (s13xxxxx) に変更すること

  2. "browse"コマンドを"echo"コマンドに置き換えるなどし、URLを自分のWebブラウザーを利用して表示すること

2. 手順の実施について

参考情報にある公式サイトの手順に従って、ゼミ室のk8sで実行するためのコマンドに置き換えて説明します。

3. Creating a service for an application running in five pods

3.1. / 1. Run a Hello World application in your cluster:

ここでは次のように -n $(id -un) を追加してコマンドを実行します。

$ kubectl -n $(id -un) apply -f https://kubernetes.io/examples/service/load-balancer-example.yaml

成功すると次のようなメッセージが表示されます。

deployment.apps/hello-world created

3.2. / 2. Display information about the Deployment:

ここからは、作成されたhello-worldについて調査していきます。

状態を確認するためには、getを利用します。(5つのWebサーバーのプロセスが起動していることが分かります)

$ kubectl -n $(id -un) get deployments hello-world

次のようにDeploymentオブジェクトの情報が表示されます。

NAME          READY   UP-TO-DATE   AVAILABLE   AGE
hello-world   5/5     5            5           98s

もう一つの確認方法は、describeを利用するもので、表示内容が異なります。

$ kubectl -n $(id -un) describe deployments hello-world

getの他にdescribe命令を指定すると、詳細な情報が表示されます。

Name:                   hello-world
Namespace:              yasu-abe
CreationTimestamp:      Wed, 09 Oct 2019 05:57:52 +0000
Labels:                 app.kubernetes.io/name=load-balancer-example
Annotations:            deployment.kubernetes.io/revision: 1
                        kubectl.kubernetes.io/last-applied-configuration:
                          {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app.kubernetes.io/name":"load-balancer-example"},"name...
Selector:               app.kubernetes.io/name=load-balancer-example
Replicas:               5 desired | 5 updated | 5 total | 5 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app.kubernetes.io/name=load-balancer-example
  Containers:
   hello-world:
    Image:        gcr.io/google-samples/node-hello:1.0
...
## 以下省略

getを利用した際に、引数で-o yamlを指定すると詳細な定義情報を確認できます。

$ kubectl -n $(id -un) get deployments hello-world -o yaml
## 出力結果は各自で確認してください。

3.3. / 3. Display information about your ReplicaSet objects:

Deploymentはkubectl createで登録されたトップレベルの定義ですが、Deploymentを元に自動的にReplicaSetが作成されています。 公式サンプルでは、この内容を確認するようコマンドが掲示されています。

$ kubectl -n $(id -un) get replicasets -l app.kubernetes.io/name=load-balancer-example
$ kubectl -n $(id -un) describe replicasets -l app.kubernetes.io/name=load-balancer-example

出力内容は各自で確認してください。

3.4. / 4. Create a Service object that exposes the deployment:

ここでは外部にサービスを公開するために、LoadBalancerを利用しています。 この場合、ゼミ室外のネットワークから、アクセスすることはできません。

ここで作成したhello-worldアプリにアクセスするためには、外部から接続できるようにIPアドレスとポート番号を準備します。 kubectl exposeコマンドを実行することで自動的にtype: LoadBalancerが設定されます。

$ kubectl -n $(id -un) expose deployment hello-world --type=LoadBalancer --name=my-service
service/my-service exposed

3.5. / 5. Display information about the Service:

作成されたservice/my-serviceの内容を確認するために、公式サンプルではgetserviceに適用しています。

$ kubectl -n $(id -un) get services my-service
NAME         TYPE           CLUSTER-IP    EXTERNAL-IP       PORT(S)          AGE
my-service   LoadBalancer   10.233.2.82   192.168.100.160   8080:32415/TCP   95s

ここで表示されたEXTERNAL-IPの192.168.100.160とポート番号8080にWebブラウザなどでアクセスすると、hello-worldアプリの内容が確認できます。

3.6. / 6. Display detailed information about the Service:

先ほどと同様に、getだけでなく、describeでも内容を確認します。

$ kubectl -n $(id -un) describe services my-service
## 出力結果が公式サンプルとほぼ変わらない事を確認してください

3.7. / 7. In the preceding output, …​

次に公式サンプルでは、kubectl getの出力を変化させています。 --output=wide が利用されていますが、通常は省略した、-o wide の形式がよく使われているので、そちらでコマンドラインを紹介します。

$ kubectl -n $(id -un) get pods -o wide -l app.kubernetes.io/name=load-balancer-example
OR
$ kubectl -n $(id -un) get pods --output=wide -l app.kubernetes.io/name=load-balancer-example
NAME                          READY   STATUS    RESTARTS   AGE   IP              NODE       NOMINATED NODE   READINESS GATES
hello-world-bbbb4c85d-4csvp   1/1     Running   0          44m   10.233.105.24   u109ls04   <none>           <none>
hello-world-bbbb4c85d-lwqxv   1/1     Running   0          44m   10.233.112.15   u109ls03   <none>           <none>
hello-world-bbbb4c85d-nntdf   1/1     Running   0          44m   10.233.105.23   u109ls04   <none>           <none>
hello-world-bbbb4c85d-r8h46   1/1     Running   0          44m   10.233.113.11   u109ls01   <none>           <none>
hello-world-bbbb4c85d-xkszr   1/1     Running   0          44m   10.233.115.12   u109ls02   <none>           <none>

この他に-oオプションに指定できる形式は、k8s.io公式ガイドのkubectl::Syntaxで確認してください。

ここでNODE欄をみると4台全てのサーバーに分散して、hello-worldアプリが動いていることが分かります。 公式サイトの説明では、GCPを利用している(GKE, Google Kubernetes Engine)様子がNODE名から分かります。

3.8. / 8. Use the external IP address (LoadBalancer Ingress) to access …​

最後にcurlコマンドを利用して、Webブラウザではなくコマンドラインからhello-worldアプリに接続して終っています。

## IPアドレス(192.168.100.160)は自分の環境に合わせて適宜変更してください。
$ curl http://192.168.100.160:8080/

IPアドレス(192.168.100.160)の部分は、先ほどget servicesで確認したEXTERNAL-IPの値を指定します。

Webブラウザ(Firefox)からWebページを表示する場合には、URL( http://192.168.100.160:8080/ )を直接入力するか、browseコマンドが利用できます。

## IPアドレス(192.168.100.160)は自分の環境に合わせて適宜変更してください。
$ browse http://192.168.100.160:8080/

ゼミ室の環境で自分のIPアドレスにアクセスする場合には、次のようなコマンドを実行してください。

$ curl http://$(kubectl -n $(id -un) get svc my-service -o=jsonpath='{.status.loadBalancer.ingress[0].ip}'):8080

4. my-proxyを利用したゼミ室外ネットワークからの接続について

まだ リバースプロキシー のチュートリアルを実施していなければ、リバースプロキシーのチュートリアルの後で戻ってきてください。

ここまでの操作では、ゼミ室の内部でなければ curl http://192.168.100.160:8080/ にアクセスできませんでした。

リバースプロキシーで作成したmy-proxyから、このアプリケーションにアクセスするために次の操作が必要です。

  1. type: CluserIP を指定したServiceオブジェクトを追加する (e.g. svc/hello-world-svc)

  2. cm/nginx-confオブジェクトのproxy.confの設定を変更し、追加したサービス名をホスト名としてアクセスするように変更する。

  3. pod/my-proxy-xxxx-xxxxxxx を再起動する

まず新しいServiceオブジェクトを追加します。 以前にServiceオブジェクトを作成する時に使用したファイルの一部を変更します。

$ curl "https://web-int.u-aizu.ac.jp/~yasu-abe/ja/sccp/manual/ingress-proxy.svc-proxy.yaml" | sed -e "s/s12xxxxx/hello-world/" -e "s/app: my-proxy/app.kubernetes.io\/name: load-balancer-example/" -e "s/80/8080/" | kubectl -n $(id -un) apply -f -

ここでは3項目(5行)の内容を変更しています。

  1. "s12xxxxx""hello-world" に置換

  2. "app: my-proxy""app.kubernetes.io/name: load-balancer-example" に置換

  3. "80""8080" に置換

結果として次のようなServiceオブジェクトを追加しました。

$ kubectl -n $(id -un) get svc hello-world-svc -o yaml
---
apiVersion: v1
kind: Service
metadata:
  name: hello-world-svc
  labels:
    app.kubernetes.io/name: load-balancer-example
spec:
  type: ClusterIP
  ports:
     -  port: 8080
        protocol: TCP
        targetPort: 8080
  selector:
    app.kubernetes.io/name: load-balancer-example

次に cm/nginx-conf オブジェクトを変更します。 ここでは、ポート番号がデフォルトの80番ではないので、明示的に8080番を指定しています。

      ## proxy.confへの変更内容
      location /s12xxxxx/hello-world/ {
        proxy_pass    http://hello-world-svc:8080/;
      }

cm/nginx-confの設定を修正するには次のようなコマンドラインで可能です。 必要に応じて、EDITOR環境変数を使用してください。

$ env EDITOR=emacs kubectl -n $(id -un) edit cm/nginx-conf

最後に以前と同様の方法で、pod/my-proxy を再起動します。

$ kubectl -n $(id -un) delete pod -l app=my-proxy

ここまできたら、下記のリストから自分のURLを指定して、/s12xxxxx/hello-world/ にアクセスし、アプリに接続できるか確認します。

5. Cleaning up

ここから先のCleaning upの内容を実行すると、構成を削除し、元の状態に戻します。 Podを作ったり、消したりが簡単にできることを確認してください。

$ kubectl -n $(id -un) delete services my-service
service "my-service" deleted

メッセージから削除されたであろうことは分かりますが、本当に削除されたのか確認するためには次のようにします。

$ kubectl -n $(id -un) get services my-service
## 同じ命令は短縮して記述することも可能です
$ kubectl -n $(id -un) get svc/my-service
## いずれの命令でも下記のようにErrorメッセージが表示されます
Error from server (NotFound): services "my-service" not found

deploymentを削除する時には、一つの定義を削除することで、ReplicaSetやPodの定義も自動的に消える事を確認してください。

$ kubectl -n $(id -un) delete deployment hello-world

最初にkubectl -n $(id -un) get allを実行すると、まだPod等が残っている場合があります。 しばらく時間をおいてから再度kubectl -n $(id -un) get allを実行すると、ReplicaSetやPodの定義も自動的に削除している事が分かります。

6. ここまでのまとめ

ひととおり実行して、よく分からなかった場合は、再度先頭から実行してみてください。

再度実行する場合には、いくつかスキップできる不要な作業が含まれているため、最初と違うエラーが出力されたりするかもしれません。

重複して実行して問題になる事はないので、安心して納得するまで繰り返してください。