まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:kubectl

これは自分のスキル不足が原因だと思っているのですが、Kubernetes や OpenShift といったコンテナクラスタ環境を使ったウェブアプリケーションのデプロイではトラブルシューティングに時間を費やすことが珍しくありません。過去に成功したのと同じようなパターンでデプロイすることばかりではなく、ストレージ含めた新しいチャレンジをすることが多く、一発で成功することはあまりありません。

この「トラブルシューティング」は、現象としては「デプロイしたが想定していた URL でウェブアプリが動いていない」ことで分かるのですが、この原因は(期待通りに動いていない箇所が)様々です。k8s の用語でいうと Pod, Deployment, Service, Ingress, ... といった構成要素があり、まずはこの中のどこで問題が発生しているのかを見極め、その上でその箇所で発生している問題の原因を特定して解決していく必要があります。

この「どの部分で問題が発生しているか」を特定する作業において、"port-forward" と呼ばれる機能に助けられています。この port-forward 機能について自分へのメモ目的も含めてまとめておきます。


【コンテナクラスタのトラブルシューティング】
k8s を使ったウェブアプリケーションのデプロイ作業は手動であったり(半)自動化されていたりしますが、リソースと呼ばれる以下のようなパーツの単位で作成され、これらが組み合わされて1つのウェブアプリケーションとなります(ウェブアプリケーションがうまく動かない場合は、このいずれか(または複数)が想定していたように動いていない、ということになります):
・デプロイメント(Deployment)
 - アプリケーションイメージを1つ以上インスタンス化し、クラスタ内で稼働しているもの
・ポッド(Pod)
 - インスタンス化されたアプリケーションイメージ1つ1つを指すもの
 - デプロイメントを作成した場合はデプロイメントに含まれる
・サービス(Service)
 - コンテナ内で稼働しているポッドやデプロイメントを外部公開方法を定義するもの
・イングレス(Ingress)
 - 複数のサービスを管理し、外部からのリクエストに対してロードバランサーとなるもの

2023090706


コンテナクラスタ環境にウェブアプリケーションが正しくデプロイされた場合、ユーザーはアプリケーションの URL にアクセスすると、まずイングレスがそのリクエストを受け取って正しいサービスに転送し、サービスを経由してアプリケーションインスタンスであるポッド(デプロイメント)にアクセスします(イングレス→サービス→ポッド)。そしてそのリクエストに対してポッドが返したレスポンスは逆の順序(ポッド→サービス→イングレス)を通って返される、ということになります。


「デプロイしたアプリケーションが期待していたように動かない」というのは、この中のどこかが期待していたように動いていなくて、全体として「動かない」ように見えていることになります。したがってトラブルシューティングにおいて、まずはどこで問題が発生しているのかを特定する必要があります。
2023090706


【port-forward 機能】
kubectl や oc といった CLI ツールの機能である port-forwarding を使うと、ポート番号を使ったフォワーディング機能によりイングレスを経由せずにコンテナクラスタ内に定義されているサービスやポッドに直接アクセスできるようになります。

例えばイングレスを経由せずにサービスにアクセスすると期待していた挙動になる(期待していた結果が返ってくる)のであればイングレスやその設定に問題がある可能性が高いことが考えられ、サービスにアクセスしても動かないがポッドに直接アクセスすれば期待していた挙動になるのであればサービスやその設定に問題がある可能性が高いことが考えられます(それでも動かない場合はポッドに問題があると考えられます)。 このような障害発生個所の見極めにおいては port-forwarding が便利に使えることになります。


【port-forward 機能を使ってみる】
試しにわざと正しく動かないことがわかっている以下のようなマニフェストファイル(deployment.yaml)を使ってアプリケーションをデプロイし、port-forward で確認する、ということをやってみます:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: guestbook
  labels:
    app: guestbook
spec:
  replicas: 1
  selector:
    matchLabels:
      app: guestbook
  template:
    metadata:
      labels:
        app: guestbook
    spec:
      containers:
      - name: guestbook
        image: ibmcom/guestbook:v1
        imagePullPolicy: Always
        env:
          - name: NODE_ENV
            value: production
---
apiVersion: v1
kind: Service
metadata:
  name: guestbook-svc
  labels:
    app: guestbook
spec:
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 3000
    targetPort: 3000
  selector:
    app: guestbook
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.(アサインされた ingress サブドメイン)
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 4000 # 正しくは3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None

ちなみに上記マニフェストの正しい記述は下から5行目の Route の spec.port.targetPort の値が 3000 になっているものです(今回はわざと 4000 を指定しています)。

なお以下の作業は IBM Cloud の Redhat OpenShift コンテナクラスタ環境を使って確認しました。なので Ingress 部分の定義は apiVersion が "route.openshift.io/v1" の Route というリソースを使って定義しています。またこの Route 内の spec.host の値には "guestbook.(アサインされた ingress サブドメイン)" と記載していますが、実行前にこの()内の部分を OpenShift 画面に表示されているサブドメイン名に置き換えて保存しておいてください:
2023090701


oc コマンドでログインし、このマニフェストファイルをデプロイ(oc apply)して、その結果を確認(oc get all)します:
$ oc apply -f deployment.yml

$ oc get all

NAME                             READY   STATUS    RESTARTS   AGE
pod/guestbook-59b85f9654-22wh5   1/1     Running   0          13m

NAME                                TYPE           CLUSTER-IP       EXTERNAL-IP                            PORT(S)    AGE
service/guestbook-svc               ClusterIP      172.21.150.230                                          3000/TCP   13m
service/kubernetes                  ClusterIP      172.21.0.1                                              443/TCP    6h7m
service/openshift                   ExternalName              kubernetes.default.svc.cluster.local                    5h46m
service/openshift-apiserver         ClusterIP      172.21.46.95                                            443/TCP    6h6m
service/openshift-oauth-apiserver   ClusterIP      172.21.98.204                                           443/TCP    6h6m

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/guestbook   1/1     1            1           13m

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/guestbook-59b85f9654   1         1         1       13m

NAME                                       HOST/PORT                                                                 PATH   SERVICES        PORT   TERMINATION     WILDCARD
route.route.openshift.io/guestbook-route   guestbook.(ingress サブドメイン).jp-tok.containers.appdomain.cloud             guestbook-svc   4000   edge/Redirect   None

"oc get all" の結果は上からポッド、サービス、デプロイメント、レプリカセット、そしてイングレスになっています。ポッドのステータスは Running でちゃんと動いていて、サービスも ClusterIP を使って正しく公開され、イングレスもホスト名が割り当てられています。 この結果だけを見ると正しく動いてそうです。

でも実際にブラウザでイングレスの HOST 名に表示されているサーバーにアクセスするとこのように表示されます(知らない人もいるので補足すると、これは期待していたアプリ画面ではなく、アクセスできなかった場合のエラー画面です):
2023090702


エラー無くデプロイできたけどアプリにアクセスできない、、 こんな時に port-forward の出番です。

まずは(上述の結果で Pod が Running になってるので可能性は低そうですが)ポッドのレベルで正しく動いているかどうかを確認するため、port-forwarding でポッドに直結して動作を確認してみます。

ポッドに対して port-forwarding するには kubectl(または oc )コマンドで以下のように実行します:
$ kubectl port-forward (ポッド名) (ホストのポート番号):(ポッド上で動いているポート番号)

今回の例だと(上述の結果より)ポッド名は "guestbook-svc" だとわかります。また実行したマニフェストファイルより、このサービスは 3000 番ポートで動いているはずです(サービスの spec.ports.targetPort の値)。このポッドにホストの(何番でもいいのですが) 8000 番ポートからフォワーディングして接続させてみます。というわけで、今回のケースであれば以下のコマンドを実行します:
$ kubectl port-forward guestbook-59b85f9654-22wh5 8000:3000

コマンド実行後、ウェブブラウザから http://localhost:8000/ にアクセスしてみます:
2023090703


今回は期待通りの画面が表示されました。ということは「ポッドは正しく動いている」ことが推測できました。Ctrl+C で port-forwarding を解除します。


継はサービスのレベルで正しく動いているかどうかを確認してみます。イングレスを経由せずにサービスにアクセスするため、port-forwarding でサービスに直結して動作を確認してみます。この場合は以下のようなコマンドを実行します:
$ kubectl port-forward service/(サービス名) (ホストのポート番号):(サービスで公開しているポート番号)

今回の例だと(上述の結果より)サービス名は "guestbook-59b85f9654-22wh5" だとわかります。また実行したマニフェストファイルより、このポッド(デプロイメント)は 3000 番ポートで動いているはずです(サービスの spec.ports.port の値)。このポッドにホストの(何番でもいいのですが) 9000 番ポートからフォワーディングして接続させてみます。というわけで、今回のケースであれば以下のコマンドを実行します:
$ kubectl port-forward service/guestbook-svc 9000:3000

コマンド実行後、ウェブブラウザから http://localhost:9000/ にアクセスしてみます:
2023090704


今回は期待通りの画面が表示されました。ということは「サービスも正しく動いている」ことが推測できました。Ctrl+C で port-forwarding を解除します。

これらの結果から、
・ポッド(デプロイメント)は正しく動いていそう
・サービスも正しく動いていそう
・ということはイングレスの設定が間違っていそう?

という切り分けをすることができました。実際、マニフェストの Route 内をわざと間違った内容に弄ったことが分かっているので、正しい切り分けができていることになります。

このケースであればイングレスの設定内容を疑ってみることになります。試しにイングレスの設定名称を指定して describe するとこのようになりました(kubectl の場合は "kubectl describe ingress guestbook-route"):
$ oc describe route guestbook-route 

  :
  :
Path:                   
TLS Termination:        edge
Insecure Policy:        Redirect
Endpoint Port:          4000

Service:        guestbook-svc
Weight:         100 (100%)
Endpoints:      

接続先である Endpoints が空になっていて何も表示されていません。ということは設定内容になんらかの誤りがあってサービスに接続できていないのでは・・・ と考えることができます。実際、今回のマニフェストでは targetPort を 3000 と指定すべきところを 4000 と指定していたため接続できていませんでした。仮に 4000 を 3000 に変更して再度適用した上で接続を試みた所、今度は正しく接続できるようになりました:
2023090705


現実問題として、イングレス部分はポッドやサービスとは異なり Kubernetes からはサードパーティ製品となるので色々な実装があり、トラブルシューティングも実装ごとの方法が考えられるため比較的難しいトラブルシューティングとはなります。それでも「どの部分に設定ミスがあったか」を特定することで解決はしやすくなりますし、その特定において port-forwarding は有効な切り分け方であると思っています。




Windows 10 で kubernates の開発環境を構築する際の方法の1つとして、以下のケースで構築する場合のメモです:
・Kubernetes 本体は minikube を使って Windows 10 に導入
・kubectl は WSL から利用


Kubernetes 本体はローカルで動く minikube を使ってシングルノード環境を構築します。この部分は正しく導入できていさえすれば Windows だろうが、Linux だろうが、Mac だろうが、システム環境の違いを意識することはあまりないと思っています。 ただ実際に利用する段になって kubectl コマンドを実行する環境としては Windows よりもより実践に近い Linux を使いたくなります。というわけで、Windows 10 の WSL (今回は Ubuntu を想定)から利用できるようにしました。

なお、この環境構築をする場合のマシンスペックとして、メモリ 8GB だと構築して minikube start した時点でほぼメモリを使い尽くしてしまいます。動作確認するだけならいいのですが、本格的に開発して動作確認してテストして・・・という段階まで考えるとやはり 16GB くらいはほしいところです。


【前提条件】
- Windows 10
- WSL(Ubuntu 18.0.4) 導入済み


【VirtualBox のインストール】
Windows 10 で minikube を動かす場合、仮想環境のハイパーバイザーが必要です。今回は VirtualBoxを使います。VirtualBox 自体のインストールはごく普通に公式ページから Windows 版をダウンロードし、デフォルト設定のままインストールすればOKです。


【Windows 版 minikube のインストール】
minikube の Github ページから、Windows/amd64 版の minikube 単体をダウンロードします:
2019090801


ダウンロードしたファイルは minikube-windows-amd64.exe というファイル名になっていますが、これを minikube.exe とリネームしてファイルシステムの適当なフォルダに保存します(以下は C:\MyApps\minikube\ というフォルダを作成して、その中に C:\MyApps\minikube\minikube.exe という名前で保存しているものと仮定して以下を続けます)。

このフォルダに PATH を通します。Windows + S キーを押して検索ボックスに「システムの詳細設定」と入力すると「システムの詳細設定の表示」が見つかるので、これを選択します:
2019090802


システムのプロパティウィンドウが表示されたら、「詳細設定」タブを選択し、「環境変数」ボタンをクリック:
2019090803


ユーザー環境変数の Path を選択してから「編集」ボタンをクリック:
2019090804


そして「新規」に minikube.exe が保存されたフォルダ名を追加して、最後に OK ボタンをクリック。これで minikube.exe に PATH が通りました:
2019090805


念の為、動作確認してみます。コマンドプロンプトを起動して、 "minikube version" と入力して実行します。minikube のバージョン番号が表示されれば、ここまでの手順は OK です:
2019090801


【minikube の起動】
コマンドプロンプトから "minikube start" と入力して、minikube を起動します。自動的に必要な VM イメージを見つけて(初回はダウンロードして)自動構築します。通常は minikube が kubectl を見つけてくれるのですが、この方法だと(Windows 版 kubectl を使わない&インストールしていないので)見つからない、という警告が表示されますが、今回は WSL 側に kubectl を用意するので無視します:
2019090802


【WSL に kubectl をインストール】
WSL を起動し、以下のコマンドを入力して kubectl を(/usr/local/bin/ 以下に)導入します:
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl

$ chmod 755 kubectl

$ sudo mv kubectl /usr/local/bin

最後に "kubectl version" を実行して動作確認します(初回は Client Version が表示されれば OK です):
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.3", GitCommit:"2d3c76f9091b6bec110a5e63777c332469e0cba2", GitTreeState:"clean", BuildDate:"2019-08-19T11:13:54Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}

【minikube のエンドポイント情報の取得】
コマンドプロンプトに戻って、"minikube status" を実行し、minikube のエンドポイント情報を確認します。以下の例では 192.168.99.100 というアドレスが表示されていますが、これにポート番号 8443 を加えたもの(192.168.99.100:8443)がエンドポイントとなり、以下で利用することになります:
2019090803


【kubectl の設定】
上記で取得したエンドポイント情報を使って kubectl の設定を行います。WSL から以下のコマンドを順次実行します。なお以下で <コマンドプロンプト実行時のユーザー名> と表示されている部分にはコマンドプロンプト実行時のユーザー名がフォルダ名の一部になっているのでそれをそのまま指定します(上記の画像例の場合であれば、ここには KEIKIMURA が入ります)、また 192.168.99.100:8443 部分は上記で取得したエンドポイント情報です:
$ kubectl config set-credentials minikube --client-certificate=/mnt/c/Users/<コマンドプロンプト実行時のユーザー名>/.minikube/client.crt --client-key=/mnt/c/Users/<コマンドプロンプト実行時のユーザー名>/.minikube/client.key

$ kubectl config set-cluster minikube --server=https://192.168.99.100:8443 --certificate-authority=/mnt/c/Users/<コマンドプロンプト実行時のユーザー名>/.minikube/ca.crt

$ kubectl config set-context minikube --user=minikube --cluster=minikube

$ kubectl config use-context minikube

最後に WSL で "kubectl cluster-info" コマンドを実行して動作を確認し、エンドポイントで正しくクラスタ状態が取得できれば kubectl の設定完了です。シングルノードの kubernetes (kubectl) がローカルの WSL から使えるようになりました:
$ 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'.



(参考)
https://dokupe.hatenablog.com/entry/20180408/1523116886

これらの記事の続きです:
IBM Cloud の無料版 Kubernetes サービスを使ってみた(1)
IBM Cloud の無料版 Kubernetes サービスを使ってみた(2)


IBM Cloud の Kubernetes サービスを使って、無料のワーカーノードにアプリケーションをデプロイして、(いったん)削除する所までを紹介しました。最終回である今回は実際にアプリケーションにアクセスしたり、デプロイしたアプリケーションをスケールさせてみたり、外部(インターネット)に公開してみたりします。

今回の作業も基本的にすべて Web Terminal から行います。というわけで、まず Web Terminal を起動します:
2019041109


改めてアプリケーションをデプロイします。が、今回は後述の RC(ReplicatoinController) としてデプロイするため、デプロイ用のファイル(rc.yaml)を作成します:
apiVersion: v1
kind: ReplicationController
metadata:
  name: kubernetes-bootcamp
spec:
  replicas: 1
  selector:
    app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: myk8x
        image: gcr.io/google-samples/kubernetes-bootcamp:v1
        ports:
        - containerPort: 8080

デプロイ時にはこのファイル(rc.yaml)を指定して、以下のコマンドを実行します:
$ kubectl create -f rc.yaml
replicationcontroller/kubernetes-bootcamp created

このコマンドで前回とほぼ同様に kubernetes-bootcamp アプリケーションを1つのポッドにデプロイします。また app: web というセレクターを指定していますが、この後で使います。

この時点で kubernetes-bootcamp アプリケーションが1つのポッドにデプロイされます。一応ポッドと、そして(詳しくは後述の)サービスの状態を確認しておきます(緑字はコメント):
$ kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-jfswt   1/1     Running   0          41s  1ポッド

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   172.21.0.1   <none>        443/TCP   3d21h  ここはクラスタサービスなので無視、つまり起動したサービスなし

この時点で1つのポッドにアプリケーションがデプロイされたことが確認できました。しかしこのポッドはまだコンテナの外部からアクセスすることができません。コンテナの外部からでもアクセスできるように紐付けるサービスを作成します。

作成するサービスのための設定ファイル(service.json)を以下の内容で用意します:
{
    "kind": "Service",
    "apiVersion": "v1",
    "metadata": {
        "name": "my-service"
    },
    "spec": {
        "selector": {
            "app": "web"
        },
        "ports": [
            {
                "protocol": "TCP",
                "port": 80,
                "targetPort": 8080,
                "nodePort": 30000
            }
        ],
        "type" : "NodePort"
    }
}

"spec" 内で app:web のラベルをセレクターに指定しています。これが先程作成したデプロイメント時の指定内容となっていて、kubernetes-bootcamp に紐づく形になります。また 8080 番ポートをターゲットに接続し、80 番ポートで公開する、という指定も行い、"my-service" という名前でサービスを作るよう指示しています。

ではこのファイル(service.json)を使ってサービスを作成します。同時に再びポッドとサービスの内容を照会してみます:
$ kubectl create -f service.json
service/my-service created

$ kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-jfswt   1/1     Running   0          13m  1ポッド

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   172.21.0.1   <none>        443/TCP   3d21h
my-service   NodePort    172.21.30.70 <none>        80:30000/TCP   94s 追加されたサービス

サービスの追加に成功しました。またその追加されたサービスはクラスター内の内部 IP アドレスである 172.21.30.70:80 上で稼働していることがわかりました。

ではこのサービスを使ってアプリケーションにアクセスしてします:
$ curl http://172.21.30.70/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-jfswt | v=1

アプリケーションにコンテナ外部からアクセスでき、正しく動作していることも確認できました。ただし、この時点ではまだあくまで内部ネットワーク内からのアクセスが確認できただけで、まだインターネットからはアクセスできません(後述します)。


コンテナの外部からアプリケーションにアクセスできることは確認できましたが、せっかくなので Kubernetes っぽい挙動もさせてみます。現在1つのポッドで動作しているこのアプリケーションをスケールアウトして複数の(今回は2つの)ポッドで起動するようにしてみます:
$ kubectl scale -f rc.yaml --replicas=2
replicationcontroller/kubernetes-bootcamp scaled

この状態で再びポッドとサービスの状態を確認します。ポッドが2つになっていることがわかります。(一方、サービスは何も変わっていません):
$ kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-kqkhp   1/1     Running   0          14s スケールアウトして新しく増えたポッド
kubernetes-bootcamp-jfswt   1/1     Running   0          109s

$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   172.21.0.1      <none>        443/TCP        3d23h
my-service   NodePort    172.21.30.70    <none>        80:30000/TCP   5m16s

ではこのアプリケーションをインターネットに公開してみます。以下のコマンドを実行します:
$ kubectl expose rc kubernetes-bootcamp --type=NodePort --name=web
service/web exposed

$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   172.21.0.1       <none>        443/TCP          4d20h
my-service   NodePort    172.21.199.105   <none>        80:30000/TCP     4m30s
web          NodePort    172.21.64.253    <none>        8080:30703/TCP   4m9s

"web" という名称のサービスが追加され、kubernetes-bootcamp の rc が expose(外部公開)されました。公開先のポート番号が 30703 になっていることも確認できます。

また、公開先の IP アドレスはワーカーノードのパブリック IP アドレスになっています。ダッシュボードから確認するか、または以下のコマンドを実行します:
2019041601
$ ibmcloud cs workers mycluster (最後のパラメーターはクラスタ名)

ID                                                 Public IP       Private IP       Machine Type   State    Status   Zone    Version   
kube-mel01-pa351ddd2ea19441a689a49159389f9d45-w1   168.1.149.201   10.118.243.103   free           normal   Ready    mel01   1.12.7_1548*


この例だと、パブリック IP アドレスが 168.1.149.201 となっているので、この 30703 番ポートに対してウェブブラウザでアクセスし、期待通りの結果になることを確認します:
2019041602


最後に、サービスとポッドを削除する場合は以下のコマンドを実行します:
$ kubectl delete svc web
service "web" deleted

$ kubectl delete -f service.json
service "my-service" deleted

$ kubectl delete -f rc.yaml
replicationcontroller "kubernetes-bootcamp" deleted


IBM Cloud の(無料の)Kubernetes サービスを使って、アプリケーションのデプロイ、スケール、動作確認、ウェブ公開、といった一連の作業ができることが確認できました。すでに Kubernetes 環境を手元に持っているような人であればともかく、これから Kubernetes を使ってみようと思う人にとっては面倒な準備作業も不要で気軽に始められて、スケールやウェブ公開といった一通りの作業ができるところまで使える環境としてとても便利だと思いました。





この記事の続きです。

IBM Cloud の無料版 Kubernetes サービスで、Kubernetes クラスタを立ち上げる所までを紹介しました。 今回は(ベータ版の)Web Terminal 機能を使って、この Kubernetes サービスの状態を確認したり、アプリケーションをデプロイしてみます。

IBM Cloud を操作する場合、一般的には ibmcloud コマンドを使います。また Kubernetes クラスタの状態を確認する場合、一般的には kubectl コマンドを使うことが多いと思っています。普段使っているマシンに ibmcloud コマンドや kubectl コマンドがすでにセットアップされているような場合はそれらのコマンドを使えばいいのですが、まだ導入されていないようなケースでは別途セットアップしてから利用する必要があります。 今回紹介する Web Terminal はそういった導入をしなくてもウェブブラウザ内のコンソールから ibmcloud コマンドや kubectl コマンドを使って操作できる方法です。現時点(2019/04/15)でベータ版なので今後どういう形になるかわかりませんが、使ってみて便利だったので紹介させていただくことにしました。

では以下に実際の手順を紹介します。まず前回の記事の内容が正しく実行されて、"mycluster" という名称の Kubernetes クラスタが稼働している状態になっていることを確認します:
2019041107


"Worker Nodes" タブでワーカーノード(今回は1つ)が正しく動いている点も確認します(この画面では IP アドレスをモザイクにしていますが、実際にはモザイクなしに表示されます):
2019041108


ではまずはこのワーカーノードの状態を Web Terminal からも確認してみます。画面内の "Web Terminal" と書かれたボタンをクリックします:
2019041109


最初にクリックした時だけ、「Kubernetes Terminal をインストールする」という確認のダイアログが表示されます。「Install」ボタンをクリックすると Kubernetes Terminal がインストールされます(少し時間がかかります、十数秒くらい?):
2019041110


(Kubernetes Terminal をインストールした場合は十数秒程度待って)改めて "Web Terminal" ボタンをクリックします。するとブラウザ画面下部からターミナルが現れます:
2019041111


このターミナルのプロンプトで、画面内に書かれたセットアップ手順を順に実行していきます。ibmcloud コマンドは特にインストールしていませんが、この Web Terminal 内では導入済みなので普通にそのまま使うことができます(赤字はコメント):
2019041112
$ ibmcloud login -a https://cloud.ibm.com ログイン

$ ibmcloud ks region-set ap-south サービスのリージョンを(作成したリージョンに)指定

$ ibmcloud ks cluster-config mycluster Kubernetes の環境設定用ファイルを生成してダウンロード

最後のコマンドを実行すると KUBECONFIG 環境変数を設定するためのコマンドが表示されます。そこに書かれた内容をそのままコピー&ペーストして、Web Terminal 上で KUBECONFIG 環境変数を設定します:
$ export KUBECONFIG=/home/IBMid-31000086FP/.bluemix/plugins/container-service/clusters/mycluster/kube-config-mel01-mycluster.yml

 

ここまでの作業が完了すると Web Terminal から kubectl コマンドを実行できるようになり、コマンドを通じてワーカーノードの状態を確認することもできるようになります。この kubectl コマンドも特にセットアップすることなく、Web Terminal 上でそのまま実行できます:
$ kubectl get nodes

1つだけ動いているワーカーノードが、名称や状態とあわせて Web Terminal 上に表示されます:

2019041113


先程ウェブ画面で確認したものと同じ内容が表示されました。これでこの Web Terminal 上から Kubernetes クラスタを操作できることが確認できました。


では続けてこのノードにアプリケーションをデプロイしてみます。Kubernetes の公式チュートリアルで紹介されている内容と全く同じ操作を Web Terminal から行ってみます。

デプロイメントの名前(以下の例では kubernetes-bootcamp)とアプリケーションイメージの Docker Hub リポジトリ URL (同 gcr.io/google-samples/kubernetes-bootcamp:v1)、実行ポート番号(同 8080)を指定して kubectl run コマンドを実行し、アプリケーションイメージを Kubernetes クラスタにデプロイします:
$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080

このコマンドが実行されると、アプリケーションが実行可能なノード(今回ははじめから1つしか用意してないので、その1つ)を探し、アプリケーションの実行がスケジュールされてデプロイが実行されます。

実行後に以下のコマンドでデプロイメントの状態を確認してみます。以下のような感じで、1つのアプリケーションが実行されている状態になればデプロイは成功しています:
$ kubectl get deployments
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           16s

また、この時点で Pod の状態も確認しておきます。デプロイ時に特にレプリカ数を指定していなかったので、1つの Pod が起動され、その上でアプリケーションが起動しているはずです:
$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-598f57b95c-w2k4b   1/1     Running   0          2m7s

次の段階に進む前に、いったん作成した Pod を削除しておきます。作成時に指定した名前(kubernetes-bootcamp)を指定してデプロイメントを削除します:
$ kubectl delete deployment kubernetes-bootcamp
deployment.extensions "kubernetes-bootcamp" deleted

$ kubectl get deployments
No resources found.

$ kubectl get pod
No resources found.

↑念の為、デプロイメントと Pod が存在しなくなっていることも確認できました。次回、最終回に改めてアプリケーションをデプロイして、スケールさせたりした上で使ってみることにします。

このページのトップヘ