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

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

タグ:openshift

これは自分のスキル不足が原因だと思っているのですが、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 は有効な切り分け方であると思っています。




ちょっとした UI 系トラブルに巻き込まれた結果とある機会に CLI 操作だけで IBM Cloud 上に Openshift クラスタ(いわゆる "ROKS")を作る必要が生じて、実際に試してみました。以下、その時に実行したコマンド群を順に紹介します。


【前提条件】
やりたかったことは単純に「VPC(Virtual Private Cloud)環境内に OpenShift クラスタを1つ作る」ことでした。既に VPC 自体はサブネット含めて作成済みで、バックアップストレージの Cloud Object Storage インスタンスも作成済みです。 後はこの VPC 内に OpenShift クラスタをスペックやワーカーノード数を指定して作るだけ、という状況です。


【CLI コマンド】
以下 CLI コマンドを記載します。ここまでに "ibmcloud login" は実行済みであるとします。

詳しくは下記参考ページを参照いただきたいのですが、VPC 内に OpenShift クラスタを作るための CLI コマンドは以下のようになります:
$ ibmcloud oc cluster create vpc-gen2 --name (クラスタ名) --zone (作成先ゾーン名) --vpc-id (作成先 VPC ID) --subnet-id (作成先サブネット ID)  --flavor (ワーカーノードのフレーバー) --version (OpenShift バージョン) --cos-instance (Cloud Object Storage の CRN) --workers (1ゾーンあたりのワーカーノード数)

で、このコマンドを実行するためには(上記コマンド内にも括弧がたくさんあるように)指定する必要がある多くのパラメータ情報を事前に集めておく必要があります。というわけでまずはパラメータ情報を収集するための CLI コマンドから説明します。

まず "--name" パラメータで指定する「クラスタ名」は自分で自由に指定することができるので説明は不要だと思います。次に "--zone" パラメータで指定する「作成先ゾーン名」ですが、これは目的のゾーンが例えば「大阪3」であったとして、この「大阪3」を指定するための文字列です。これを調べるには次のコマンドでゾーン一覧を取得して、そこから目的のゾーンの ID を取り出します(青字が入力コマンドです):
$ ibmcloud oc zone ls --provider vpc-gen2
OK
ID           Name         Metro             Flavors
au-syd-1     au-syd-1     Sydney            -
au-syd-2     au-syd-2     Sydney            -
au-syd-3     au-syd-3     Sydney            -
br-sao-1     br-sao-1     Sao Paulo         -
  :
eu-gb-3      eu-gb-3      London            -
jp-osa-1     jp-osa-1     Osaka             -
jp-osa-2     jp-osa-2     Osaka             -
jp-osa-3     jp-osa-3     Osaka             -
jp-tok-1     jp-tok-1     Tokyo             -
jp-tok-2     jp-tok-2     Tokyo             -
jp-tok-3     jp-tok-3     Tokyo             -
us-east-1    us-east-1    Washington D.C.   -
  :

この結果から「大阪3」を使う場合に指定するゾーン名が "jp-osa-3" であることが分かります。

次に作成先の「VPC ID」です。VPC が決まっていても、その ID を取り出して指定する必要があります。これは以下のコマンドを実行することで取り出せます:
$ ibmcloud oc vpcs --provider vpc-gen2
OK
Name              ID                                          Provider
xxxxxxx-vpc-osa   ****-********-****-****-****-************   vpc-gen2
  :

目的の VPC 名と照らし合わせることで ID を確認することができます("****-********-****-****-****-************" という値であったと仮定します)。

作成先の「サブネットID」も調べる必要があります。普段は名称で扱っていて、ID を意識することがあまりないのですが CLI 操作時には必要な情報です。これは以下のコマンドで "xxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" であることが確認できます:

$ ibmcloud oc subnets --provider vpc-gen2 --vpc-id (VPC ID) --zone (ゾーン名)
OK
Name                ID                                          Public Gateway Name                        Public Gateway ID                           IPv4 CIDR Block   Available IPv4 Addresses
sn-xxxxxxxxxxx-03   xxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   pgw-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx   10.xxx.xxx.0/24   244

ワーカーノードのフレーバー(スペック)も実行時に指定する必要のある情報です。これは以下のコマンドでフレーバーの一覧を取得し、目的のフレーバーの ID を取り出します。今回は "bx2.16x64" というスペックのフレーバーを使うことにします:
$ ibmcloud oc flavors --zone (ゾーン名) --provider vpc-gen2
OK
For more information about these flavors, see 'https://ibm.biz/flavors'
Name           Cores   Memory   Network Speed   OS             Server Type   Storage
  Secondary Storage   Flavor Class   Provider
bx2.16x64      16      64GB     24Gbps          UBUNTU_20_64   virtual       100GB     0B, *               bx2            vpc-gen2
bx2.2x8†       2       8GB      4Gbps           UBUNTU_20_64   virtual       100GB     0B                  bx2            vpc-gen2
bx2.32x128     32      128GB    25Gbps          UBUNTU_20_64   virtual       100GB     0B, *               bx2            vpc-gen2
b
  :
  :

OpenShift のバージョンも指定する必要がある項目ですが、これは普通に "4.11_openshift" などと指定できます。またゾーンあたりのワーカーノード数も普通に "2" などと数字で指定可能です。

最後に Cloud Object Storage の CRN を取得します。これは取得が面倒なのですが、作成済みリソースの一覧を取得し、そこから目的の Cloud Object Storage サービスを探して、その ID を見つける、という方法で取得します:
$ ibmcloud resource service-instances --long
OK
   :
   :
ID:                 crn:v1:bluemix:public:cloud-object-storage:global:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::

GUID:               xxxxxxxxxxxxxx


Name                Cloud Object Storage for me


Location            global
   :
   :

これで OpenShift クラスタを作成するために必要な最低限の情報が揃いました:
情報
ゾーン名jp-osa-3
VPC ID****-********-****-****-****-************
サブネット IDxxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ワーカーノードのフレーバーbx2.16x64
OpenShift バージョン4.11_openshift
1ゾーンあたりのワーカーノード数2
Cloud Object Storage の CRNcrn:v1:bluemix:public:cloud-object-storage:global:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::



これらの情報を使って以下のコマンドを実行します:
$ ibmcloud oc cluster create vpc-gen2 --name (クラスタ名) --zone jp-osa-3 --vpc-id ****-********-****-****-****-************ --subnet-id xxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  --flavor bx2.16x64 --version 4.11_openshift --cos-instance crn:v1:bluemix:public:cloud-object-storage:global:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:: --workers 2
Creating cluster...
OK
Cluster created with ID ***************************

成功すると上述のようにクラスタ ID("***************************")が表示され、「デプロイ中」のステータスとなります。


なお、マルチゾーンで作成する場合は上記の作業を行ってシングルゾーンでクラスタを作成した上で、追加するゾーンのゾーン名とサブネット ID を取得してから以下のコマンドを実行してワーカープールにワーカーノードを追加します:
$ ibmcloud oc zone add vpc-gen2 --zone (追加するゾーン名) -c (クラスタ名) --worker-pool (追加先のワーカープール名) --subnet-id (サブネットID)
OK

これで IBM Cloud のダッシュボード画面にアクセスできなくてもしなくても、CLI だけで Openshift クラスタを作ることができそうです。


【参考】
https://cloud.ibm.com/docs/openshift?topic=openshift-cluster-create-vpc-gen2&interface=cli


 

以前のブログエントリで OpenShift 関連の以下2つの紹介をしていました:
IBM Cloud の VPC(Virtual Private Cloud) でプライベート OpenShift クラスタ環境を構築する
IBM Cloud の仮想プライベートクラウド OpenShift 上にデプロイしたコンテナアプリに HTTP パブリックアクセスを許可する


前者は IBM Cloud の VPC(Virtual Private Cloud) 環境を使って、プライベートな OpenShift クラスタ環境を作る手順(と VPN を使ったプライベート OpenShift へのアクセス手順)を紹介しました。 また後者ではこのプライベート環境を使ってデプロイしたプライベートなアプリケーションに対して、VPN なしでパブリックインターネットアクセスを(HTTPS ではなく、HTTP で)行うための設定手順を紹介しました。

今回のブログエントリではこの最終形ともいえる「デプロイしたアプリケーションに対する HTTPS によるアクセス」を実現するための手順を紹介します。上で紹介した2つのエントリの、後者に近い内容ではありますが、純粋な続きというわけではありません。前者の環境が構築済みであるという前提のもとで、oc CLI を使ったアプリケーションのデプロイと、プライベートアクセスを可能にするための手順を紹介していきます。


【3通りの方法】
今回のブログエントリの結論めいたことを最初に紹介します。この「プライベートクラウドにデプロイしたアプリケーションにパブリックにアクセスする」には目的や制約に応じた3通りの方法があります(うち(1)は前回説明済み):
(1)HTTP でパブリックアクセスする(前回説明
(2)HTTPS でパブリックアクセスする(自己証明書を使う場合)
(3)HTTPS でパブリックアクセスする(有効な証明書を使う場合)

要は「HTTP でいいのか? HTTPS が必要か?」「HTTPS の場合、自己証明書でいいか?NGか?」という2つの考慮点があり、その要件によって選択肢を選ぶ必要がある、ということです。「この中でどれか?と言われたら(3)でしょ?」と思うかもしれませんが、それぞれに制約事項があったりして(例えば(1)、(2)は IBM Cloud 内の設定のみで実現できますが、(3)の場合はカスタムドメインが別途必要になります)、検証目的なのか本運用なのか、といった背景によっても選択肢は変える必要が生じるものだと思います。

以下では、最終的には(3)を実現する前提として、(1)から順に実現手順を紹介します。なお(1)と同じことを前回紹介しているのですが、(3)まで行うことを考えると(1)も少し手順を変える必要があるので、改めて(1)から実現手順を、以下で順に紹介します。


【0. 事前準備】
まず事前準備としてプライベートクラウドでの OpenShift クラスタ環境と、同環境にアクセスするための VPN が必要です。これらの構築手順はシリーズ初回で紹介しているので、こちらの手順を参照してプライベートクラウドの OpenShift クラスタと、同クラスタにアクセスするための VPN 環境を作っておいてください。

ここまでが完了している前提で以下の説明を続けます。


【1. プライベート OpenShift クラスタにアプリケーションをデプロイし、パブリックアクセスのパスを定義する】

2023020205


以前にも紹介した内容ですが、今回は HTTPS でのアクセスまでを考慮した手順を紹介します。そのため、HTTP でアクセスするこの部分から以前とは異なる、oc CLI コマンドと yaml ファイルを使ってアプリケーションをデプロイする手順を紹介します。

まず前提として、以下のようなプライベート OpenShift クラスタ環境が IBM Cloud 内に作られているものと仮定します:

OpenShift クラスタ名: kkimura-mycluster-jp-osa-2-priv
2023020101


Ingress が定義したサブドメイン名: kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-osa.containers.appdomain.cloud
2023020102


アプリケーションをデプロイする OpenShift プロジェクト(ネームスペース): default

OpenShift にデプロイするアプリ:DockerHub 上の ibmcom/guestbook:v1
2023020103


※ちなみにこの ibmcom/guestbook をデプロイしてウェブブラウザでアクセスするとこのような↓画面が表示されます。この画面が表示されればデプロイとアクセスが成功している、と判断してください:
2023020101



以下では上述の名称や設定を前提として説明します。適宜自分の環境での名称や設定に読み替えてください。

では実際に oc CLI を使って、アプリケーションをプライベート OpenShift クラスタにデプロイします。まずはプライベート環境へアクセスする VPN を有効にした上で「OpenShift Web コンソール」を開きます(VPN が有効でないと開けません):
2023020104


OpenShift Web コンソールが開きます。今回は oc CLI と呼ばれるコマンドラインツールを使ってアプリケーションのデプロイや設定変更を行うので、まだこのツールをインストールしていない場合は導入が必要です。OpenShift Web コンソール画面上部のクエスチョンマークをクリックし、コンテキストメニューから「コマンドラインツール」を選択して、自分の PC 環境にあった oc CLI ツールをダウンロード&インストールしておいてください:
2023020108


同様にして ibmcloud CLI コマンドも(未導入の場合は)インストールしておきます:
https://cloud.ibm.com/docs/cli?topic=cli-install-ibmcloud-cli&locale=ja


oc CLI ツールと ibmcloud CLI ツールがインストールできている状態で、改めて OpenShift Web コンソール画面右上の名前部分をクリックしてコンテキストメニューを開き、「ログインコマンドのコピー」を選択します:
2023020105


新しいウィンドウが開くと、"Display Token" とだけ表示されているので、この部分をクリックしてトークン情報を参照します:
2023020106


するとトークン情報が書かれたページが表示されます。この中の "Log in with this token" で書かれた部分を(この後ペーストするので)コピーします:
2023020107


ターミナルを開き、さきほどコピーした内容をペーストして Enter キーを押すと、ターミナル画面で IBM Cloud の OpenShift 環境にログインできます:
2023020109


同様にして ibmcloud CLI ツールからも IBM Cloud へのログインを行っておきます:
$ ibmcloud login


ではここからプライベート OpenShift クラスタ内にアプリケーションをインストールします。改めて以下のような内容の yaml ファイル(guestbook_deployment.yaml)を用意します:
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:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    app: guestbook
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-osa.containers.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None


この yaml ファイルは Deployment, Service, Route を1つずつ含んでいて、これ一つでアプリケーションをデプロイして、クラスタ外に公開して、ホスト名でアクセスできるようなルーティングを設定しています。数か所ある太字部分を補足します。

まず Deployment 内の image 名で ibmcom/guestbook:v1 と記載している部分、これがデプロイするアプリケーションのイメージです。別のイメージを使う場合はここを変えてください。

また数か所ある 3000 という数字、これは ibmcom/guestbook アプリが内部的に待ち受けるポート番号です。使うアプリイメージによって変わるので、ここもそのアプリ向けの正しい値を指定してください。

最後に Route 内の host 名、ここは (アプリ固有の名).(Ingress サブドメイン) を指定します。今回の例ではアプリ固有の名として guestbook とし、Ingress サブドメインは上記で調べた値(kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-osa.containers.appdomain.cloud)を使っています。

では用意した yaml ファイルを使って実際にプライベート OpenShift にデプロイします:
$ oc apply -f guestbook_deployment.yaml

成功したら上述の host 名に HTTPS でアクセスし、期待通りに動作することを確認します(この時点でプライベートクラウドへはデプロイできました):
2023020101


次にこのアプリケーションをパブリッククラウドから(最初は HTTP で)アクセスできるように設定します。大まかな手順としては以下のことを行います:
・OpenShift 内にパブリック・ルーター(の Pod)とパブリック・ロードバランサーを作成し、
・パブリック・ロードバランサー → パブリック・ルーター を経由して、アプリケーションだけにアクセスできるようなパスを通し、
・パブリック・ロードバランサーの外部ホスト名でアプリケーションを公開できるよう DNS を変更する


では順に実行していきます。ロードバランサーを OpenShift のパブリックネットワーク側に作りたいのですが、その際の(パブリックネットワーク用の)サブドメインを決める必要があります。まずは以下の ibmcloud コマンドを実行します:
$ ibmcloud oc nlb-dns ls --cluster kkimura-mycluster-jp-osa-2-priv
(最後のパラメータは OpenShift クラスタ名)

(以下、実行結果例)
OK
Subdomain                                                                                          Target(s)                            SSL Cert Status   SSL Cert Secret Name                                             Secret Namespace    Status
kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-osa.containers.appdomain.cloud   59aa36c3-jp-osa.lb.appdomain.cloud   created           kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000   openshift-ingress   OK

この実行結果例では1行しか表示されていませんが、複数行表示されることもあります。で、この結果の Subdomain を見ると "i000" と表示されている部分があります。この "i" で始まって数字が3桁続くサブドメインはプライベートネットワークであることを示しています。

新たにパブリックなサブドメインを追加したいのですが、その名称は、
・↑の方法でプライベートネットワークのサブドメインのうち、"i" 以降の数字が最も大きいもの(今回であれば "000")を探して、
・その数字に1を追加し、"i" をゼロ(0)にしたもの(今回であれば "0001")
にします。つまり今回の例であれば、
kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud

をパブリック用のサブドメインとします。

パブリック用のサブドメインが決まったら、以下のような yaml ファイル(ingresscontroller.yaml)を作って実行し、パブリックネットワークにパブリックルーターとパブリックロードバランサーを作ります(太字部分はパブリック用サブドメイン):
apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  name: public
  namespace: openshift-ingress-operator
spec:
  replicas: 2
  domain: kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud
  endpointPublishingStrategy:
    loadBalancer:
      scope: External
    type: LoadBalancerService
$ oc apply -f ingresscontroller.yaml

そして以下を実行し、結果の "EXTERNAL-IP" を参照します:
$ oc get svc router-public -n openshift-ingress

NAME            TYPE           CLUSTER-IP       EXTERNAL-IP                          PORT(S)                      AGE
router-public   LoadBalancer   172.21.191.252   5ca5ada9-jp-osa.lb.appdomain.cloud   80:31127/TCP,443:30992/TCP   32h

この例では EXTERNAL-IP は "5ca5ada9-jp-osa.lb.appdomain.cloud" となっています。これがパブリックロードバランサーのホスト名となります。

このサービスのパブリック VPC ホスト名を DNS に登録します。以下のコマンドを実行します:
$ ibmcloud oc nlb-dns create vpc-gen2 --cluster (OpenShiftクラスタ名) --lb-host (ロードバランサーホスト名) --type public

※今回の例だと、
 OpenShift クラスタ名: kkimura-mycluster-jp-osa-2-priv
 ロードバランサーホスト名: 5ca5ada9-jp-osa.lb.appdomain.cloud

最後にアプリのサービスをパブリックルーターで expose します:
$ oc expose svc/guestbook-svc --name guestbook-public --hostname guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud

これでサービス(guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud)がパブリックネットワーク上で HTTP で公開されました。いったん VPN を切ってから、パブリックホスト名(http://guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud)に HTTP でアクセスできることを確認してみましょう:
2023020201


【2. プライベート OpenShift クラスタにアプリケーションをデプロイし、自己証明書の HTTPS アクセスができるよう定義する】

2023020206


1. で説明した作業の続きとして、パブリックロードバランサー名(今回であれば "5ca5ada9-jp-osa.lb.appdomain.cloud")で自己証明書を使った HTTPS アクセスを可能にします。

そのためにはアプリケーションのデプロイ時に使った yaml ファイル(guestbook_deployment.yaml)を少し改良します。具体的には以下の青字部分を(自分の環境のホスト名やパブリックロードバランサー名を使って)追加します:
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:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    app: guestbook
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-osa.containers.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: 5ca5ada9-jp-osa.lb.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None

これによりパブリックロードバランサー(5ca5ada9-jp-osa.lb.appdomain.cloud)への HTTPS アクセスが可能になります。ただ証明書が自己証明書のため、アクセス制約がかかります。この yaml ファイルでデプロイしなおします(VPN を切ったままの場合は再接続してから):
$ oc apply -f guestbook_deployment.yaml


そしてブラウザでアクセスしてみます。具体的には以下のようになります。VPN を切断後にブラウザで https://5ca5ada9-jp-osa.lb.appdomain.cloud にアクセスすると、以下のような画面になります。「詳細設定」をクリックします:
2023020202


証明書が自己証明書なので安全ではない、というメッセージが表示されます。安全ではないことを理解した上でアクセスしてみます:
2023020203


すると、(保護はされていないけれど)一応 HTTPS でアクセスできることが確認できます:
2023020204


このパブリックロードバランサーのドメインは OpenShift 環境から自動発行されたもので、内部的に使うぶんにはこれで問題ないのですが、ユーザーが直接使う場合はちょっと気になる部分ではあります:
2023020205


後述の手順で正しい証明書を使った HTTPS アクセス方法を紹介しますが、こちらにも別の制約事項があるので、両方理解した上でどちらを使うべきか検討してください。


【3. プライベート OpenShift クラスタにアプリケーションをデプロイし、カスタムドメインの証明書を使って HTTPS アクセスができるよう定義する】

2023020207


最後のケースは HTTPS としては完成形のような位置づけですが、これまでのケースにはない制約事項が1つあります。それは「カスタムドメインを使う」必要がある点です。2. では IBM Cloud 発行のドメインを使って HTTPS ができなかったのを、自前のドメインを使うことで回避する方法になります。

例えば "pi314.jp" というカスタムドメインを使うことにして、2. までに説明してきたアプリケーションを "guestbook.pi314.jp" というホスト名で HTTPS アクセス可能にする、という想定で以下の説明を行います。

まずカスタムドメインの DNS を設定します。契約したドメイン会社や DNS 移管先によって具体的な設定手順は異なりますが、guestbook という CNAME に対して、パブリックロードバランサー名を設定します(下図は CloudFlare.com を使った場合のスクリーンショット):
2023020206


更にデプロイ用の guestbook_deployment.yaml をもう一度改良して、赤字部分を更に追加します:
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:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    app: guestbook
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-osa.containers.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.kkimura-mycluster-jp-osa-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-osa.containers.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: 5ca5ada9-jp-osa.lb.appdomain.cloud
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: guestbook-route
  labels:
    app: guestbook
spec:
  host: guestbook.pi314.jp
  to:
    kind: Service
    name: guestbook-svc
    weight: 100
  port:
    targetPort: 3000
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect
  wildcardPolicy: None

この yaml ファイルを(VPN が切れている場合は再接続してから)再度適用します:
$ oc apply -f guestbook_deployment.yaml

そして VPN を切断し、ブラウザでカスタムドメイン側に登録した名前(guestbook.pi314.jp)に HTTPS アクセスしてみましょう:
2023020207


警告などが表示されることなく、ちゃんと HTTPS でパブリックアクセスできることが確認できるはずです。


以上、コンテナ環境を運用する上で
・コンテナ管理はプライベートネットワークで運用し、
・デプロイしたアプリはパブリックネットワークから利用する

という要件はあってもおかしくなさそうですが、今回紹介したような方法で実現できそうです。自己証明書を使うページはスマホから利用するのが難しいのですが、カスタムドメインという高めのハードルを越えることができればその問題もなくなります。利用環境や目的に応じて検討してください。


ウェブアプリケーションの開発ハンズオン(オンライン含めて)を行う場合、その開発環境の準備が面倒です。参加者の PC を使おうとすると言語ランタイムやエディタのインストールやバージョン管理を含めて事前に準備してもらう項目が多く、また特にオンライン環境だとネットワークの設定が問題になったりするので、色んな環境のケースを想定した準備が必要になります。

そんな「開発環境構築」を比較的容易にする RedHat CodeReady Workspaces を使う機会があったので、使い方やこれを使って構築する開発環境がどんなものかまとめてみました:
2023011700


【事前準備】
今回は RedHat OpenShift クラスタ環境を使って CodeReady Workspaces を準備します。というわけで OpenShift クラスタ環境が必要です。以下では IBM Cloud 上に作った OpenShift クラスタ環境を使って紹介しますが、他のクラウドやオンプレミス版などを使っていても構いません。


【OpenShift に RedHat CodeReady Workspaces を導入】
まずは OpenShift クラスタに RedHat CodeReady Workspaces を導入します。RedHat CodeReady Workspaces は OpenShift 上のオペレータとして提供されているのでこれを使って環境を作ります。最初に OpenShift のウェブコンソールを開いて、Administrator パースペクティブで左メニューから Operator - OperatorHub を選択します。そこでプロジェクト(例えば "default")を1つ選び、検索フィールドに "codeready" などと入力して "Red Hat CodeReady Workspaces" を見つけてクリックします:
2023011701


Red Hat CodeReady Workspaces の説明画面が表示されたら「インストール」ボタンをクリックします:
2023011702


次の画面を下までスクロールしてもう一度「インストール」ボタンをクリックします:
2023011703


ここでしばらく待つと RedHat CodeReady Workspaces オペレータがインストールされます:
2023011704


インストールが完了すると以下のような画面になるので、「Operator の表示」ボタンをクリックします:
2023011705


インストールされた RedHat CodeReady Workspaces オペレータが表示されます。実際に CodeReady Workspaces インスタンスを動かすために「提供される API」欄の "CodeReady Workspaces Instance Specification" の下の「インスタンスの作成」をクリックします:
2023011706


もう一度下までスクロールして「作成」ボタンをクリックするとインスタンスの作成が始まります:
2023011707


インスタンスが作成されると以下のような画面になるので、"codeready-workspaces" と書かれた箇所をクリックします:
2023011708


下のような画面になります。この画面ではまだインスタンスは準備中ですが、用意ができると "CodeReady Workspaces URL" の下にリンク URL 文字列が表示されます:
2023011709


このような表示になるとインスタンスの作成も完了しています。早速 CodeReady Workspaces URL 下のリンクをクリックします:
2023011710


最初の1回だけアクセス権の設定を行う必要があります。"user-full" にチェックが入っていることを確認して "Allow selected permissions" ボタンをクリックします:
2023011711


するとアカウント情報の画面が表示されます:
2023011712


この画面内でユーザー名、メールアドレス、ファースト/ラストネームを入力して、最後に Submit ボタンをクリックします。これでアカウント情報の登録も行われます:
2023011713


CodeReady Workspaces の起動が開始します。ここまで行うことができれば RedHat CodeReady Workspaces の環境構築手順は無事に成功しました:
2023011714



【RedHat CodeReady Workspaces を使ってアプリケーション開発を行う】

RedHat CodeReady Workspaces の起動が完了すると最初のワークスペースを作るようナビゲートされます:
2023011715


Git リポジトリを指定してソースコード一式をインポートすることもできますが、今回はテンプレートからワークスペースを作ってみます。(なんでもいいのですが)画面下の "NodeJS Express" と書かれた Node.js のシンプルなソースコードをベースに選択して、ここからワークスペースを作ることにしてみましょう:
2023011716


すると指定されたテンプレートを元にしたソースコード一式が作成されるので、完了するまで少し待ちます:
2023011717


ワークスペースの生成が完了するとこのような画面が表示されます。ウェブ版の VSCode が起動し、(今回の例であれば)シンプルな Node.js + Express のウェブアプリケーションの雛形となるソースコードが読み込まれています。指定したファイルを開いたり、その内容を変更することもできます(最初は README.md がプレビューモードで開かれています):
2023011718


依存関係や起動コマンドを確認するため、package.json を開いてみました。ここから最初に起動するべきファイルは app/app.js であることがわかります:
2023011719


実際に app/app.js も開いて内容を確認してみました。いわゆる「ハローワールド」のウェブ版のアプリケーションのようです:
2023011720


このアプリを起動するには VSCode 内でターミナルを起動します。メニューの Terminal - Open Terminal in specific container を選択し、"vscode-nodeajs" を選択します:
2023011721


すると画面右下にターミナルが現れ、CLI コマンドを実行できるようになります:
2023011722


実際にアプリケーションを起動してみましょう。まずはターミナルで "npm install" と入力してライブラリをインストールします:
2023011723


そして "node app/app.js" と入力してウェブアプリケーションを起動します。すると画面右下に「起動したウェブアプリケーションをブラウザで表示するか?」と聞かれるので、「新しいタブで起動(Open In New Tab)」を選択します:
2023011724


新しいブラウザタブが開いて、そこで起動したアプリケーションが実行されます。期待通り、"Hello World!" が表示できました。CodeReady Workspaces で作ったオンライン開発環境を使ってアプリケーションを開発/実行/動作確認までできることが確認できました:
2023011725


CodeReady Workspaces のエディタ画面で編集したアプリケーションをウェブブラウザで実行(表示)することができました:
2023011700


【まとめ】
OpenShift コンテナクラスタ環境を使うことで、開発環境も実行環境もコンテナ上で簡単に構築・実現することができました。個人の PC にはランタイムや CLI などを導入する必要がなく、ネットワークも(HTTP/HTTPS さえインターネットに通っていればいいので)環境による試行錯誤はほぼ不要だと思います。簡易的なアプリケーション開発環境の構築程度であれば非常に用意に作れると感じました。


先日のブログで IBM Cloud の VPC(Virtual Private Cloud : 仮想プライベートクラウド)上に OpenShift クラスタ環境を構築する手順を紹介しました:
IBM Cloud の VPC(Virtual Private Cloud) でプライベート OpenShift クラスタ環境を構築する


↑で紹介した内容は完全にインターネットと断絶したプライベートクラウドではなく、「プライベートクラウド側からインターネット側へのアクセスは許す」というものでした。デプロイ時に GitHub や DockerHub などを参照する場合はこのような設定になるので(それも許さない場合はこれらに相当する機能も VPC 内に用意する必要があるため)そこまで珍しい構成ではないと思っています。

今回紹介するのはもう1段階緩めのプライベートクラウドと言えるもので、「デプロイしたアプリはパブリックインターネットから利用できるようにする」というものです。OpenShift クラスタのウェブコンソールや oc CLI コマンドの利用は VPC 必須としたたま、コンテナとしてデプロイしたアプリはインターネットからでも利用可能にする、という設計です。OpenShift の管理者機能のみを VPC 内に入れ(VPN 必須として)、クラスタにデプロイしたアプリケーションについては利用制約を設けないというもので、これも現実的には珍しくないプライベートクラウド環境であると思っています。


【構築手順】
この環境を作る上で、まずは前回紹介した VPC での OpenShift 環境が必要です。こちらの内容を参照して仮想プライベートクラウド内に OpenShift クラスタを構築しておいてください:
IBM Cloud の VPC(Virtual Private Cloud) でプライベート OpenShift クラスタ環境を構築する


ここまでの環境準備ができ、かつ構築した VPN 接続ができている前提で以下を説明します。改めて IBM Cloud ダッシュボードにログインし、作成した OpenShift クラスタを表示します:
2023011501


この画面の "OpenShift Web コンソール" ボタンをクリックしてコンソール画面を表示します(VPN 接続していないとエラーになります):
2023011502


OpenShift ウェブコンソール画面が表示されたら右上の ID 部分をクリックし「ログインコマンドのコピー」を選択します:
2023011503


"Display Token" をクリックすると oc CLI でのログインコマンドが表示されます。"oc login" で始まるコマンドを確認します:
2023011504


ここまでできたら CLI で IBM Cloud (ibmcloud)および OpenShift (oc)環境にログインします:
$ ibmcloud login

$ oc login --token=sha256xxxxx(↑で確認したコマンド)

ログイン後、まずはドメイン名を調べます。以下のコマンドを入力します:
$ ibmcloud oc nlb-dns ls -c (OpenShift クラスタ名)

2023011501


実行結果の "Subdomain" 欄(上図では "kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-tok.containers.appdomain.cloud)を確認します。これが IBM Cloud から割り振られたドメイン名です。途中 i000 となっている部分がプライベートドメインであることを意味しています(i00x がプライベート、000x がパブリック)。パブリック用にこの x を1つカウントアップして(i000 -> 0001 として)以下のような IngressController 作成用 yaml ファイル(ingresscontroller-0001.yaml)を作成します:
(ingresscontroller-i001.yaml)

apiVersion: operator.openshift.io/v1
kind: IngressController
metadata:
  name: public
  namespace: openshift-ingress-operator
spec:
  replicas: 2
  domain: kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-tok.containers.appdomain.cloud
  endpointPublishingStrategy:
    loadBalancer:
      scope: External
    type: LoadBalancerService

そしてこれを実行します:
$ oc create -f ingresscontroller-0001.yaml

成功すると router-public という Pod が作成されているはずです:
$ oc get pods -n openshift-ingress
NAME READY STATUS RESTARTS AGE router-default-58cb7bcc6-6nmtv 1/1 Running 0 6h28m router-default-58cb7bcc6-mxlkd 1/1 Running 0 6h28m router-public-55cf9586d-5qwkv 1/1 Running 0 77s router-public-55cf9586d-bqnv6 1/1 Running 0 77s

この時、裏側でパブリックロードバランサーが作成されています。ロードバランサーのホスト名を確認します。結果の EXTERNAL-IP(下の場合であれば "b881dcc5-jp-tok-lb.appdomain.cloud)が確認できます:
$ oc get svc/router-public -n openshift-ingress

NAME            TYPE           CLUSTER-IP      EXTERNAL-IP                          PORT(S)                      AGE
router-public   LoadBalancer   172.21.233.58   b881dcc5-jp-tok.lb.appdomain.cloud   80:31920/TCP,443:32264/TCP   3m17s

パブリック用ドメイン名とロードバランサーのホスト名を紐づけて DNS 登録します:
$ ibmcloud oc nlb-dns create vpc-gen2 -c kkimura-mycluster-jp-tok2 --lb-host b881dcc5-jp-tok.lb.appdomain.cloud --type public --secret-namespace openshift-ingress

$ ibmcloud oc nlb-dns ls -c kkimura-mycluster-jp-tok2
OK
Subdomain
               Target(s)                            SSL Cert Status   SSL Cert Secret Name                                              Secret Namespace    Status
kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-tok.containers.appdomain.cloud   b881dcc5-jp-tok.lb.appdomain.cloud   creating          kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-0001   openshift-ingress   OK
kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-i000.jp-tok.containers.appdomain.cloud   57a0f594-jp-tok.lb.appdomain.cloud   created           kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-i000   openshift-ingress   OK

サービスをパブリックルーターで公開します。--hostname には 0001 のドメイン名に任意のサブドメインを指定します:
$ oc expose svc/hostname --name hostname-public --hostname hostname.kkimura-mycluster-jp-tok2-6fe57c7eaf38abe6232341d97eae54c0-0001.jp-tok.containers.appdomain.cloud

これでパブリッククラウドへの公開ができたはずです。VPN 接続を切ってから curl やウェブブラウザ等で --hostname に指定したホストに HTTP アクセスし、正しくアクセスできることを確認します:

(VPN 接続してプライベートアクセスした場合)
2023011501

(VPN 接続を切ってからパブリックアクセスした場合)
2023011502


プライベートネットワークにデプロイしてアプリケーションがパブリックインターネット経由でもアクセスできるようになりました。今回紹介した内容はパブリックインターネットから HTTP でアクセスする例でしたが、HTTPS でアクセスする場合の方法は別の機会に紹介するつもりです。


(参照)

このページのトップヘ