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

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

タグ:private

以前のブログエントリで 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 でパブリックアクセスできることが確認できるはずです。


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

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


先日のブログで 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 でアクセスする場合の方法は別の機会に紹介するつもりです。


(参照)

あけましておめでとうございます。これが 2023 年最初のブログエントリとなります。本年もよろしくお願いいたします。



これまで IBM Cloud で OpenShift クラスタ環境を何度も作って(&そして削除して)来ました。が、それらは全てパブリッククラウド環境としての OpenShift クラスタでした。 このたびプライベートクラウド環境としての OpenShift クラスタを作る機会がありました。その考慮点や手順がパブリッククラウドの時と比べてかなり複雑だったので、備忘録の意味も含めて最初から最後まで手順をまとめてみました。


【プライベートクラウドの設計】
一言で「プライベートクラウド」といっても、その制約というか仕様には色々なパターンが考えられます。例えば「プライベートクラウド」なので、ウェブの管理コンソールや管理 CLI の操作、クラスタにデプロイしたアプリケーションにインターネットからアクセスできない(インターネット側からプライベートクラウドへのアクセスは不可とする)、というのは共通仕様だと思っています。一方で、デプロイするアプリケーションのイメージは Docker ハブから使いたい(つまりプライベートクラウド側からインターネットへのアクセスは許可したい)というケースはあるかもしれませんし、そこも制約として許可したくないケースもあると思います(後者の場合でイメージからデプロイするにはイメージリポジトリもプライベートクラウド内に構築する必要も出てきます)。

以下で手順を紹介するのは「前者」のパターンとします。つまり、
・CLI やウェブコンソールを含めて、インターネットからの直接アクセスは許可しない
・専用の VPN 環境を構築し、この VPN 接続が有効な場合のみアクセスを許可する
・プライベートクラウド側からインターネットへのアクセスは許可する(Docker ハブなどからのアプリケーションデプロイを可能とする)


という条件でプライベートクラウド環境を構築します。なお以下の作業を行う上で必要なユーザー権限は全て取得済みであるものとします。


【VPC とサブネットの作成】
まず、今回のようなパブリックインターフェースを持たないプライベートインターフェースのみの OpenShift クラスタを IBM Cloud に作る場合、クラシックインフラではなく VPC(Virtual Private Cloud)インフラに作る必要があります。そのためまずは OpenShift クラスタを作成するための VPC(Virtual Private Cloud:仮想プライベートクラウド)環境を作成します。IBM Cloud のダッシュボードから「リソースの作成」をクリックします:
2023010401


カタログ画面の検索バーに "Virtual Private" と入力すると選択候補の中に "Virtual Private Cloud" というのが出てくると思うので、これを選択します:
2023010402


VPC 環境を作成するロケーションを選択します。以下の例では「アジア太平洋地域」の「東京」を選択しています。ここは自分の環境にあったもの(なるべく利用者に近い場所)を選択してください。そして VPC の名称(下の例では "kkimura-vpc")を入力します:
2023010403


下にスクロールするとデフォルト接頭部とサブネットに関する情報が表示されます。デフォルトでは選択したロケーション(この場合は東京)の3つのゾーンに1つずつサブネットが用意されます。このままでもよければこのまま進めることもできますが、今回は規模の小さいプライベートクラウド環境を作る想定なので、デフォルト設定を無効にした上でサブネットを1つだけ用意することにします:
2023010404


というわけで、「各ゾーンのデフォルト接頭部の作成」のチェックを外してください。最後に「仮想プライベート・クラウドの作成」ボタンをクリックします:
2023010405


仮想プライベート・クラウドの一覧画面に遷移し、先ほど指定した名前の VPC が追加されたことを確認し、これを選択します:
2023010406


VPC の中身を確認するとアドレス接頭部が空になっています。ここに1つだけ追加することにします:
2023010407


同じ画面の「アドレス接頭部」タブを選択して「作成」ボタンをクリックします:
2023010408


画面右から「アドレス接頭部の作成」というウィンドウが表示されます。ここに作成するアドレス空間の範囲(下の例では 10.10.0.0/18)と、そのアドレス空間を作るロケーション(下の例では東京2)を指定して「作成」ボタンをクリックします:
2023010409


指定した値(10.10.0.0/18)のアドレス空間が定義できました:
2023010410


アドレス空間が定義できたので、次にサブネットを作成します。画面左ペインから「サブネット」を選択し、「作成」ボタンをクリックします:
2023010411


ロケーション(下の例ではアジア太平洋の東京2)とサブネットの名称(下の例では "sn-tok2")を指定します。まだ入力項目があるので、そのまま下にスクロールします:
2023010412


このサブネットを使う VPC を指定し、最後にアドレス接頭部(10.10.0.0/18)内のどの部分をサブネットとして利用するかを指定します(下の例では "10.10.0.0/24" を指定しています)。ここまで指定できたら最後に「サブネットの作成」ボタンをクリックします:
2023010413


VPC 用のサブネットを新しく1つ定義できました。この後 OpenShift 環境を構築する場合に、このサブネット上に構築することになります:
2023010414


【パブリックゲートウェイの作成】
今回のプライベートクラウドでは「プライベート環境側からインターネット側へのアクセスは許可する」前提で環境を構築します。これを実現するには「パブリックゲートウェイ」と呼ばれるゲートウェイをサブネットに紐づけることで実現します。 以下ではその手順を紹介します。なお「プライベート環境側からインターネット側へのアクセスも禁止する」というポリシーで構築する場合は、このパブリックゲートウェイ作成手順は読み飛ばしてください。

VPC インフラストラクチャー画面の左ペインで「パブリック・ゲートウェイ」を選択し、「作成」ボタンをクリックします:
2023010415


画面右からパブリック・ゲートウェイの設定画面が現れます。まずはパブリック・ゲートウェイを作成するロケーション(下の例ではアジア太平洋の東京2)を指定します:
2023010416


画面を下にスクロールして設定の続きを行います。作成するパブリック・ゲートウェイの名前("kkimura-pgw")、対象となる VPC("kkimura-vpc")を指定し、最後に「作成」ボタンをクリックします:
2023010417


しばらく待つとパブリック・ゲートウェイが作成されます。ただこの時点では作成されただけで、まだ対象となるプライベート・サブネットとの接続ができていない状態です:
2023010418


というわけで、プライベート・サブネットとの接続を行います。対象パブリック・ゲートウェイの右(必要に応じてスクロールしてください)のメニューをクリックして「接続」を選択します:
2023010419


接続するサブネットを選択します。ここでは先ほど作成した "sn-tok2" サブネットを指定しています。最後に「作成」ボタンをクリックします:
2023010420


パブリック・ゲートウェイとサブネットとの接続ができました。これで対象サブネット内に作られるサーバーリソースからインターネット側へアクセスすることができるようになりました:
2023010421


【Secrets Manager で証明書を管理】
この後 OpenShift クラスタをプライベート環境内に作るのですが、プライベート環境なのでそのままでは(ウェブコンソールにも oc CLI からも)アクセスできません。というわけで、プライベート環境にアクセスするための VPN をあらかじめ用意しておくことにします。

この VPN 接続をセキュアにするためには証明書が必要で、その証明書を Secrets Manager を使って管理します。したがってまず最初に Secrets Manager を(まだ使ったことがなければ)作成します。

IBM Cloud のダッシュボードから「リソースの作成」をクリックし、カタログ内の検索画面で "Secrets" と入力すると "Secrets Manager" が見つかるはずです。これを選択します:
2023010401


Secrets Manager の構成画面ではまずロケーション(下の例では「東京」)を選択します。また Secrets Manager の料金プランを選択します。Secrets Manager を初めて使う場合は無料の「トライアル」プランを 30 日間だけ使うこともできます:
2023010402


最後に、作成する Secrets Manager の名称(下の例では "kkimura-secrets-manager-tok2")を指定し、「以下のご使用条件を読み、同意します」にチェックを入れて「作成」します:
2023010403


Secrets Manager が作成できたら VPN サービスから Secrets Manager を使うことができるよう権限を設定する必要があります。IBM Cloud の画面右上のメニューから 管理→アクセス(IAM) を選択します:
2023010401


左ペインで「許可」を選択して許可の管理画面を表示してから「作成」をクリックします:
2023010402


サービス許可の設定をします。ここでは以下のように指定します:
 ソースアカウント:当該アカウント
 ソースサービス:VPC Infrastructure Services
 アクセス権限の範囲の指定:選択された属性に基づくリソース
 リソースタイプにチェックして "Client VPN for VPC" を選択
 (下に続く)

2023010403


 (上から続く)
 ターゲット・サービス: Secrets Manager
 アクセス権限の範囲の指定:全てのリソース
 サービス・アクセス:シークレット・リーダーにチェック

最後に「作成」ボタンをクリックします:
2023010404



指定した内容の許可レコードが作成されたことを確認します:
2023010405


ここまで準備できたら実際に証明書を作成します。ターミナル等で以下を実行します:
Easy-RSA 3 リポジトリをローカルフォルダに複製
$ git clone https://github.com/OpenVPN/easy-rsa.git

$ cd easy-rsa/easyrsa3
新しい PKI と CA を作成
$ ./easyrsa init-pki

$ ./easyrsa build-ca nopass
VPN サーバー証明書(vpn-server.vpn.ibm.com)を生成
$ ./easyrsa build-server-full vpn-server.vpn.ibm.com nopass

(プロンプトが止まったら "yes" と入力)
VPN クライアント証明書(client1.vpn.ibm.com)を生成
$ ./easyrsa build-client-full client1.vpn.ibm.com nopass

(プロンプトが止まったら "yes" と入力)
証明書ファイルの取り出し
./pki/ 以下をまとめて取り出しておく

作成した Secrets Manager に、作成した証明書を登録します。IBM Cloud で作成した Secrets Manager インスタンスを選択し、画面左の「シークレット」を選択し、画面右の「作成」をクリックします:
2023010401


次の画面では「TLS 証明書」を選択します:
2023010402


次の画面では「証明書のインポート」を選択します。また、この時点でシークレットの名称(下の例では "kkimura-vpn-certs" )を指定します:
2023010403


画面を下方向に、ファイルを3つアップロードするところまでスクロールします:
2023010404


3か所に、先ほど作成した証明書からそれぞれ以下のファイルを選択して指定します:
 証明書: "./pki/issued/vpn-server.vpn.ibm.com.crt"
 秘密鍵:"./pki/private/vpn-server.vpn.ibm.com.key"
 中間証明書:"./pki/ca.crt"
最後に「作成」ボタンをクリックします:
2023010405


正しく処理が行われて、新しいシークレットが作成されたことを確認します:
2023010406


これで VPN 接続をセキュアに行うための証明書を作成して Secrets Manager で管理するところまでの作業が完了しました。この後はこれらの情報を使って実際に VPN 環境を構築します。


【VPN 環境の作成】
改めて IBM Cloud の VPC のプライベート環境にアクセスするための VPN 環境を作ります。IBM Cloud のカタログから "client vpn for vpc" を検索して選択します:
2023010401


VPN の設定項目を指定しながら作成していきます。まず VPN タイプには「クライアントとサイト間のサーバー」を選択し、ロケーションは VPN サーバーをどのロケーションに設置するかを指定(下の例では「東京」)します:
2023010402


設定を続けます。次に VPN サーバー名を適当に(下の例では "kkimura-client-vpn")入力し、接続対象となる VPC(下の例では上で作成した "kkimura-vpc")を入力します。その下のクライアント IPv4 アドレスプールには VPN 接続したマシンに割り振られる IP アドレスの範囲(下の例では 10.244.0.0/16)を指定します。ここは上で作成したサブネットと被らないアドレス帯を指定してください:
2023010403


設定を続けます。VPN サーバーモードは「スタンドアロン・モード」を選択し、そのサブネットは上で作成したサブネット(下の例では "sn-tok2")を指定します:
2023010404


設定を続けます。次は認証に関わる設定を行います。サーバー認証の証明書ソースは "Secrets Manager" を選択し、「インスタンスで検索」をクリックしてからサーバー・シークレット・マネージャーとサーバー SSL 証明書として先ほど作成したもの(下の例では "kkimura-secrets-manager-tok2" と "kkimura-vpn-certs")を指定します:
2023010405


設定を続けます。次はクライアント認証の設定を行います。「クライアント証明書」にチェックを入れ、証明書ソースは "Secrets Manager"、「インスタンスで検索」を選んでから、上同様にクライアント・シークレット・マネージャーとクライアント SSL 証明書をそれぞれ先ほど作成したもの(下の例では "kkimura-secrets-manager-tok2" と "kkimura-vpn-certs")を指定します:
2023010406


設定を続けます。次は一番下までスクロールして追加の構成部分を設定します。トランスポートプロトコルは "UDP" 、VPN ポートは 443 を指定します。またトンネルモードは「フル・トンネル」か「分割トンネル」かを選びます。クライアントがこのプライベートネットワークに VPN 接続中もインターネットの利用をさせる場合は「分割トンネル」を、VPN 接続中はインターネットアクセスを無効にさせる場合は「フルトンネル」を、それぞれ目的に応じて選択します(下の例では「分割トンネル」)。最後に「VPN サーバーの作成」ボタンをクリックして作成します:
2023010407


作成して状況が「安定」になるまで少し時間がかかりますが、VPN の「クライアントとサイト間のサーバー」タブに VPN が1つ追加されたことが確認できます:
2023010401


直前の設定で UDP/443 ポートを使う旨を指定しましたが、この設定内容がセキュリティグループでも許可されている必要があります。そのための設定を追加します。

VPC インフラストラクチャー画面の左ペインで「セキュリティ・グループ」を選択します。そこから今設定している VPC(下の例であれば "kkimura-vpc")のセキュリティグループになっているものを探してクリックします:
2023010401


セキュリティグループの「ルール」タブを選択して、「作成」ボタンをクリックします:
2023010402


新しいインバウンドルールを追加します。今回の例であればプロトコルは "UDP"、ポートは「ポート範囲」を選択した上で、最小値と最大値の両方に "443" を入力します。またソースタイプは「すべて」を選択して、最後に「作成」ボタンをクリックします:
2023010403


これで新しいインバウンドルールが追加され、セキュリティグループでも UDP/443 を許可することができました:
2023010404


VPN の設定項目はまだ必要なのですが、ここまでの作業ができたら一旦終わりとして、次はプライベートな OpenShift クラスタを作ります。



【プライベート OpenShift クラスタ環境の作成】
パブリックな OpenShift 環境の場合はいきなり OpenShift クラスタを作ってそのまま使い始めることができますが、プライベート環境の場合は(そのセキュリティポリシーにもよりますが)かなり準備が必要でした。が、ここまでできていればあと少しで、OpenShift クラスタを作ることもできます。

IBM Cloud のダッシュボードから「リソースの作成」を選び、カタログの検索バーに "OpenShift" と入力すると "Red Hat OpenShift on IBM Cloud" が見つかるのでこれを選択します:
2023010401


作成する OpenShift クラスタの設定項目を指定していきます。まずセットアップの種類は「手動セットアップ」で、インフラストラクチャーは "VPC" を選びます。なお、この後マスターサービス・エンドポイントを指定する項目があるのですが、そこで「プライベートのみ」を選択できるのはここで "VPC" を選んだ場合のみです。つまりプライベートクラウドとしての OpenShift 環境を構築するにはここで VPC を選択する必要があり、そのためこの上で準備したような設定を行う必要があったのでした:
2023010402


続けて利用する VPC("kkimura-vpc")とクラウド・オブジェクト・ストレージを指定します。クラウド・オブジェクト・ストレージを使っていない場合は新規に1つ作ってからここで指定します。また OpenShift のバージョンは特にこだわりがなければ最新版を、OCP ライセンスは「このワーカー・プールの追加ライセンスを購入する」を選択します:
2023010403


ワーカー・ゾーンはワーカーノードをどのゾーンのどのサブネットに配置するかを指定します。サブネットを作成したゾーンと、そのサブネットを指定します。それ以外のゾーンのチェックを外します。またワーカープールのノード数は「2」を指定します(ここで1以下を指定すると作成前のチェックでエラーになりますが、この後の作業でワーカー・ノードは1つに変更できます)。ワーカープールのフレーバー(1台あたりのスペックは必要に応じて適宜変更してください):
2023010404


マスター・サービス・エンドポイントを指定します。ここで「プライベート・エンドポイントのみ」を指定します(OpenShift を VPC で作成する場合はプライベートのみが選択できます。Classic 環境だとプライベートのみという選択肢はありません)。また適当な名称でクラスター名を指定します:
2023010405


最後の統合項目ではアクティビティトラッキングやロギング、モニタリングを有効にすることも可能ですが、不要の場合はチェックを外しても問題ありません。最後に「作成」ボタンをクリックします:
2023010406


これでプライベート版 OpenShift クラスタ環境のセットアップが開始されます。セットアップが完了するまでしばらく(30分ほど?)待ちます:
2023010407


ステータスが「正常」になり、Ingress まで含めた全ての機能が正常に稼働している状態になることを確認します:
2023010401


この状態で「OpenShift Web コンソール」ボタンをクリックしても「OpenShift Web コンソール URL に到達できませんでした」というエラーになることを確認します。この環境はプライベートネットワーク上に構築されているので、これまでのようにインターネット経由でのアクセスができないからです(つまり現時点ではアクセスできないことが正しい状態で、クラスタがプライベートネットワーク上に構築されていることを意味します):
2023010402


では次にこのプライベート OpenShift クラスタにアクセスすることができるようになる VPN 環境を構築します:


【VPN サーバー環境の作成】
最後にもう一度 VPN の設定を行います。VPN の経路情報を登録します。VPC インフラストラクチャー画面の左ペインで "VPN" を選択し、「クライアントとサイト間のサーバー」タブに表示される VPN を選択します:
2023010401


この VPN の「VPN サーバー経路」タブを選択して「作成」ボタンをクリックします:
2023010402


まずサブネット 10.10.0.0/24 へのアクセスはそのまま通す必要があるので、CIDR に "10.10.0.0/24"、アクションは「配信」を選択して「作成」します(名前は適当に):
2023010403


同様に、他のクラウドサービスへもアクセスできる必要があるため、同じ作業を繰り返して、CIDR に "166.8.0.0/14" 、アクションは「変換」でルールを1つ追加します:
2023010404


下図のように VPN サーバー経路が2つ登録できていれば VPN の経路に関する設定は終わりです:
2023010401



【VPN クライアント環境の作成】
VPN サーバーの準備ができたので、次に VPN クライアントを用意します。まずは VPN クライアント用のプロファイルをダウンロードします。VPN インフラストラクチャー画面の左ペインで VPN を選び、「クライアントとサイト間のサーバー」タブから先ほど作成した VPN 接続を選択します:
2023010401



そして「クライアント」タブ内の「クライアント・プロファイルのダウンロード」を選択します。すると .ovpn という拡張子がついた Open VPN 向けプロファイルがダウンロードできます:
2023010402


自分が付けた VPN 名(この例では "kkimura-client-vpn")に ".ovpn" という拡張子が付いたファイル名のプロファイルがダウンロードされているはずです。このファイルをテキストエディタで開きます:
2023010403


ファイルの最後に近いあたりにある "#cert " で始まる行と、"#key " で始まる行両方の "#" を削除します。加えて "cert", "key" に続く文字列を以下のように変更して保存します:
 cert client1.vpn.ibm.com.crt
 key client1.vpn.ibm.com.key
2023010404


そして証明書ファイルを作った際の ./pki/issued/client1.vpn.ibm.com.crt および ./pki/private/client1.vpn.ibm.com.key の2つのファイルを OVPN ファイルを同じフォルダにコピーします:
2023010405


これで VPN 接続用プロファイルが準備できました。後は VPN クライアントを用意して、このプロファイルを適用するだけです。

VPN クライアントは(2023/01/04 時点では)OpenVPN クライアントの V2 および V3 が推奨されています。今回はこちらから OpenVPN V3 をダウンロード&インストールしました。自分のシステム環境プラットフォームにあったものを選んでダウンロードしてください:
https://openvpn.net/vpn-client/#tab-windows


OpenVPN クライアントのインストールが環境したら起動します。初回起動時にプロファイルのインポート画面になるので、FILE タブを選んで"BROWSE" ボタンをクリックし、上で用意した OVPN ファイル(kkimura-client-vpn.ovpn)を指定します:
2023010401


OVPN ファイルが正しく作成され、また正しく編集できていれば鍵ファイルごと読み込まれてプロファイルのインポートが完了します。ここで "CONNECT" ボタンを押すと VPN 接続が開始します:
2023010402


設定にミスがなければ VPN 接続は一瞬で完了するはずです。"CONNECTED" と表示されていれば接続できていることになります:
2023010403


試しにこの VPN 接続ができている間を使ってプライベート OpenShift クラスタが正しく作られていることを確認してみます。IBM Cloud のダッシュボード画面に戻り、作成した OpenShift クラスタを選択して「OpenShift Web コンソール」ボタンをクリックしてみます(先ほどはエラーになったオペレーションです):
2023010401


今回は OpenShift のウェブコンソール画面が表示されるはずです。VPN 接続が有効になっているので、この URL にアクセスすることができました。なお IBM Cloud の OpenShift では URL のリージョン部分(例えば "jp-tok")の直前が "0000" であればパブリック、"i000" であればプライベートな URL になっているとのことで、今回は "****-i000-jp-tok.***" というパターンになっているので、ここでもプライベートな URL にアクセスできていることが確認できます:
2023010404


ついでに今回は「プライベートクラウド側からインターネット側へのアクセスは許可」するポリシーで環境を構築しました。上述のパブリックゲートウェイが有効になっているので、プライベートクラウド側から Docker ハブ等にもアクセスできるはずなので、それを確認してみます。まずはパースペクティブを切り替えるため、画面左の "Administrator" と書かれた部分をクリックして "Developer" に変更します:
2023010406


Developer パースペクティブの状態で「+追加」をクリックし、プロジェクト(例えば "default")を選択してから「コンテナイメージ」を選択します(新しいアプリケーションをコンテナイメージから作る、という指示を意味しています):
2023010407


今回動作検証用に使うアプリケーションのイメージはこれを使うことにします。私が作って Docker ハブで公開しているもので、HTTP でアクセスすると /etc/hostname の内容を読み取って text/plain で返す、というシンプルなアプリケーションです。イメージ名は dotnsf/hostname です:
2023010401


このイメージを指定します。OpenShift の画面には docker.io/dotnsf/hostname と入力します(Docker ハブ上の dotnsf/hostname という指定です)。入力後に「検証済み」と表示されるまで少し待ちます:
2023010402


これ以外のオプションは特に変更の必要はありませんが、名称などはお好きなように指定してください。ただ「生成するリソースタイプの選択」は「デプロイメント」を指定するようにしてください。最後に「作成」ボタンをクリックします:
2023010403


少し時間がかかりますが、以下のような画面が表示されればデプロイ完了です。アイコン右上のリンクボタンをクリックして動作確認してます:
2023010404


別のウィンドウタブが開いて、プライベート OpenShift 上にデプロイされた dotnsf/hostname アプリにアクセスできることを確認します。またこの URL パターンが "***.i000-jp-tok***" となっていて、プライベート OpenShift のパターンになっていることも合わせて確認します:
2023010405


無事にプライベート OpenShift 環境を構築することができました。VPN 接続を切る場合、Windows であればタスクバーなどから OpenVPN クライアントを選択して disconnect することもできます:
2023010405




 

(このブログエントリは自作DBMS Advent Calendar 2020 の 12/3 にエントリーしています)


偉そうなブログタイトルになってしまいました、申し訳ない。


業務でも個人サービスでもブロックチェーンを使う機会があります。業務で携わることで世の中のお客様がどういった用途でどのようにブロックチェーンを使おうとしているのか、という貴重な情報を得ることができると同時に、企業内利用ゆえの様々な制約に直面することもあります。また個人サービスでもブロックチェーンを使うことで業務での必要十分な範囲にとらわれない(自分が挑戦してみたい)実装にチャレンジすることもできています。いろいろ恵まれた立場であることを実感しています。

一方で、この2つの立場でブロックチェーンを活用していると、「自分が理解してるブロックチェーン」と「実際のブロックチェーンプラットフォーム」との間に存在しているギャップが気になることもあります。このギャップは自分のブロックチェーンに対する理解がまだまだ足りないことに起因している可能性が大きいこともわかっていますが、それはつまり「ブロックチェーンは難しいもの」という先入観にも原因があるのかもしれません。

何を言いたいのかと言うと、自分のようなアプリケーション開発者の視点から考えるブロックチェーンはこういうものであってほしい(こういうものであってくれると使いやすいし、管理しやすい)んだけど、現実はそうではない、ということに何度か直面するのでした。具体的にいくつか挙げるとこのようなことです:


0 「ブロックチェーン」としての定義を満たしている

これは要件というよりも、後述する「ブロックチェーン」という用語への共通理解のための項目です。例えば日本では一般社団法人日本ブロックチェーン協会このような定義をしています。この中の「広義のブロックチェーン」で考えられるものが(広い意味での)ブロックチェーンであり、ここに定義された条件を満たしていれば、仮にサーバーノードを管理する権限を持っているような立場の人であっても、その中身を改ざんすることは困難になる、というものです。この「改ざんが困難」な特徴によって(法律などでルールを作らなくても、技術的に)記録内容の正当性を保証できるようになるもの、それがブロックチェーンだと理解しています。

で、特に開発者の視点ではブロックチェーンがここから下の要件を満たすものであってもらえるといろいろ嬉しいなあ、、と思っていまして、それを3つほど列挙させていただきます。


1 可能な限りブロックチェーンを意識せずにアプリケーション開発ができる

上述したようにブロックチェーンに関する最小限の知識はアプリケーション開発者が理解しているべきであると思いますが、一方でアプリケーション開発者がブロックチェーンを意識して開発すべきであるとは思いません。極端な言い方ですが、ブロックチェーンの存在すら知ることなく「開発者がデータベースを使ってアプリケーションを開発したら、データベースへのトランザクションは全て自動的にブロックチェーンに記録されて、改ざんが困難になったり、改ざんされてもすぐバレる」ようにできると理想的だと考えています。 要はブロックチェーンというインフラ部分をアプリケーション開発者の責任範囲から可能な限り分離したい、という意見です。


2 プライベートネットワークからもブロックチェーンに参加できる

ブロックチェーンネットワーク内に存在するノード間では台帳情報を分散管理します。したがって全てのノードがパブリックなネットワークに存在していて自由に同期をとることができることが理想ではあります。

一方、実際に企業のサービスがブロックチェーンネットワークに参加する場合、パブリックネットワークでの運用を前提とする時点で懸念が生じることがあります。比較対象として相応しいかどうかわかりませんが、例えば企業内で使っているデータベースをパブリッククラウド上に移行することですら問題になるのが現実で、そんな中で台帳情報を共有するブロックチェーンはパブリックでもオッケー、となるわけがありません。わがままにも聞こえますが「ネットワークはパブリックで構築してもいいが、うちが用意するノードはプライベートな状態で運用したい」のが本音となっているケースも散見します。

このわがままにも聞こえる懸念に対して「ブロックチェーンだからパブリックネットワークでないといけないのか?」という観点で考えるとどうでしょう? ある程度中身まで理解しているブロックチェーン技術者にとっては当然のようにパブリックネットワーク運用前提で考えてしまうかもしれませんが、ブロックチェーンを活用したいと考えている経営者からは厄介な制約に感じられてしまうものかもしれませんし、上述の「1 可能な限りブロックチェーンを意識せずにアプリケーション開発ができる」ようになると、アプリケーション開発者としてもネットワーク・トポロジーの制約を意識せずに開発できるようになるのが理想と考えています。 開発者と経営者、どちらもブロックチェーンを活用したいという想いは同じなのに、協力しあえないのはあまりに不幸な話と思えるため、それならなんらかの制約(※)が加わるにせよ、開発者側から歩み寄る形でプライベートネットワーク内からもブロックチェーンネットワークに参加して同期を取る方法を(技術的に不可能でないのだとしたら)検討する価値はあるのではないか、と考えています。そしてブロックチェーンそのものにそういった機能がはじめから付与されていれば歩み寄りも最小限で済むため理想的ではないかと思っています。

※具体的にはブロックチェーンをプライベート型やコンソーシアム型にせざるを得なくなる、といった制約です。


3 ブロックチェーンに全てのトランザクションが記録されるのであれば、例えばノードの引っ越し時やデータ破損時などにブロックチェーンからリストアできるはず

実は僕がブロックチェーンの存在や概要を知って、真っ先に思いついたブロックチェーンのメリットがこれでした。そもそも開発するサービス全体のうち、ブロックチェーンには何を(どの部分の情報を)記録するのかという問題があることは理解しています。例えばユーザー情報はブロックチェーンには記録せずに運用するけど、お金の動きに関わる部分だけはブロックチェーンに記録する、という考え方です。その意味ではサービス全体の情報がブロックチェーンに格納されるわけではないことは理解しておく必要があります。

でもブロックチェーンに記録されている情報に関してはそこに全トランザクションが記録されているわけだから、仮にデータ部分が破損したケースであっても、ブロックチェーンを最初からたどることで理論上は元通りに戻せるはず(つまりブロックチェーンからリストアできるはず)、だと思ったのでした。これができると運用者は楽だし、運用者が困っている面倒な部分の開発も楽になります。

ところが実際にそのようなリストア機能をもったブロックチェーンは自分の知る限りでは存在していません。もちろん実際のデータベースとの紐付け情報が必要だったり、どのサービスで使うデータに関するトランザクションなのか、といった情報も含めてブロックチェーンに記録されていないと実現できないことは理解できます。ブロックチェーン側のデータフォーマット仕様にも関わる話になってしまうと後からの変更や対応は難しいかもしれないなあ、といった事情もあるのでしょう。

この「ブロックチェーンからリストア」の実現について、色々面倒な制約があってできないのか、それともあまり重要視されていないのかわかりません。ただ自分のような開発者・運用者の視点からはこれがブロックチェーン側の機能の一部として実現できたらバックアップへの不安という心理的な負担を軽くことのできる開発プラットフォームが実現できて、それは開発にブロックチェーンを採用するメリットにもなり得るのではないか、、、と感じていたのでした。



そして、実はいま上述した3点を含む「開発者視点で考えた、使いやすいブロックチェーン」を実装中です。「開発者視点」と言いつつ、あくまで「自分の視点」ではありますけど(笑)。簡単に特徴を列挙するとこのような感じ:
  • 名前は HATOYA 、デフォルトの実行ポート番号は 4126
  • 表向きは REST API でデータベースやデータベース内のドキュメントを CRUD(Create/Read/Update/Delete 加えて Search も) 可能な JSON データベースシステム
  • データベースやドキュメントへの変更トランザクションは全て内蔵ブロックチェーンに自動記録
  • 複数ノードでブロックチェーンネットワークを作ると、参加するノードのブロックチェーン情報は1つにマージされる。つまりブロックチェーンネットワークで1つのブロックチェーンを共有管理する(データベース情報は共有しない)
  • ブロックチェーンネットワークにはプライベートネットワークからも参加可能(ただしその場合は push 型の同期処理となる)
  • サーバー引っ越し時や、データ破損時などにブロックチェーンからデータベースをリストアすることができる

なおスケーラビリティやアベイラビリティ、セキュリティといった非機能要件はまだ不十分な上、機能実装も現時点ではあくまで予定としているものではあるのですが、上述3点については実現にも目処が立っています:
20200724



現在は複数ノード環境での動作テストやデバッグ、このブロックチェーンを使ったツールやサンプルアプリなどを開発するのが中心の段階に至っています(つまり上述の3点の特徴含めてある程度は動く状態になっています):
2020072400


近い将来になんらかの形で公開予定です。本来アプリケーション開発とは利用者の観点を重要視するべきで、そこを開発者観点で作ることに異論を唱える人が存在するであろうことも理解しています。ただブロックチェーンってそもそもエンドユーザーが意識するべきものではないし、「ブロックチェーンの利用者」が誰なのかを考えると、それは「開発者」であるという視点があってもいいのかな、と。そう考えた時の答の1つになれればいいと思っています。あと深く勉強しなくてもすぐに実装が開始できるので、PoC 的な用途には向いているんじゃないかなあ、とも。

まだ動くものを公開していないので感想を持ちにくいということも理解していますが、こういった考え方で作られるブロックチェーンへの賛同や反論などありましたら、傷が浅いうちに(笑)ぜひ聞いておきたいです。コメント等でご意見いただければと。


(追記 公開しました)
HATOYA の Docker イメージを公開
HATOYA をマルチノード運用して、ブロックチェーン情報を分散管理する

誤解のないよう最初に書いておきますが、マンホールマップを始めとする僕個人が開発・運用するサービスを終了する予定がある、という意味・意図のコンテンツではありません。 ただ、もし自分に万が一・・・なことがあったら現実問題としてユーザーに迷惑をかける形で終える形になってしまいそうだし、そろそろこういうのを気にする年齢になってきた(苦笑)ようで、同じような立場の人がいたら意見を聞きたいなあ、、とか、今はこう考えているんだけど間違ってたりしないかな、、という思いからこのブログエントリを書くことにしました。 


改めまして、約10年前から「知る人ぞ知る」という感じでマンホールマップという「自称世界最大の位置情報付きマンホール情報共有サービス」を運営しています。もともとマニア向けに作ったものですが、マンホール蓋(特にデザイン性)に興味を持つ人がそこそこ増えつつあるようで、利用者からの情報を共有いただき続けています。マンホールマップ自体に利益を生む仕組みは(現在は)存在していないので、利益面に関してはプラスというよりはマイナスのサービスです。これまで色々運用形態を変えつつも、開発および運用はすべて自分一人で行っています。なおマンホールマップに投稿いただいた画像やテキストの著作権は投稿者にあるものと規定しています:
2020012801


「すべて自分一人で」の部分をより正確に表現すると「自分一人で開発・運用できる範囲でサービスを提供している」という言い方が正しいかもしれません。正直な所、あまりに急激に人気が出すぎてアクセス数が増えすぎるのも(特に運用コスト面で)困ってしまいますw 今後も安いネットサービスを探しつつ(笑)、細々と続けていく予定です。


で、こういう個人開発・運用サービスの場合、サービス提供開始後しばらくして「全く使われなくなる」ケースも少なからずあると思っています。アクセスログや Google Analytics を使えばコストをかけずに利用状況の確認はできる時代になりました。その結果、自分以外ほぼ誰も使っていないことがわかれば、ある程度周知した上でサービスを止めてしまうことにそこまでの心理的な抵抗もないと思っています(自分の場合はこのケースが多くて、人気のないサービスを終了することへの抵抗はほぼありませんw)。そのようなサービスは本ブログエントリの対象外と考えています。 その上で「個人開発・運用サービスをどうやって終わらせるべきか?」を考えました。


例えばの話ですが、もし万が一、この後自分に何かがあってしまった場合、もうマンホールマップをメンテナンスできる人はいません。マンホールマップは現在はマルチクラウド上で機能ごとに稼働していますが、その(銀行口座が解約されたりして)契約が終了した時点でサーバーインスタンスも止まってしまいます。ユーザーデータを救うこともできないし、「こういう状況なので止まる前にバックアップを取ってください」と予め伝えることもできない可能性もあります。 いわば「保険がかかっていない状態」にあって、「自分が救いの手を差し伸べたい」という奇特な人がどこかに存在していたとしてもどうにもならなくなってしまう可能性すらあります。そうなることを避けて方法はないだろうか?と考え、3つ程案を出してみました。


方法の1つは「家族や友人に託す」という方法です。が、これは(ケース・バイ・ケースですが、ある程度のコスト負担があることを理解した上で)そういうことを頼める家族や友人がいれば自分がやっていたように運用してもらえるのではないか、と期待しての方法です。ただ厳密には開発ライセンスなどの権利問題を解決する必要もあり、よほど信頼できる相手と事前にそのような話し合いができていれば、という条件が付く方法です。

#そういえばソースコードって相続の対象になるのかな??


別の方法として「オープンソース化」も考えました。現在マンホールマップのソースコードは公開していません。が、Github 上には存在しているので「多少の準備期間があれば公開」できないことはないです。ソースコードを公開することで、誰かが運用を引き継げる形だけはとっておく、というものです。 ただこの方法にも「既存データをどう扱うか」という問題点があります。ソースコードがあれば新たにマンホールマップサービスを立ち上げることはできるようになりますが、それまでに利用者から投稿いただいたデータが溜まっているデータベースにアクセスできるかどうかは別問題です。特に現行のマンホールマップのように僕の自宅内にデータベース・サーバーやバックアップ・サーバーがあるケースは厄介ですよね。。

手続き的に一番ハードルが低いと想像しているのが「法人化」です(実は大変なのかも・・)。要は個人のサービスではなく、法人のサービスという形にして、法人として(担当者が変わる形で)サービスの開発や運用を引き継ぐというものです。「法人化」が簡単だと思っているわけではありませんが、法人化されていれば別の人が引き継いでサービスを継続する上での権利的な問題は解決できると考えています。本格的に事業者する場合ははじめからこの形態なんでしょうけど、個人開発サービスでも法人化する意味はなくはないのでは、、と思うようになりました。

そして最後が「自分がなんとかできるうちにサービスを終了する」方法です。別にお金に困っているわけでもなく、ユーザーの過疎化に悩まされているわけでもなく、でもどこかで見切りをつけてサービス終了を宣言して、各ユーザーに自分のデータだけでもバックアップしてもらう、という方法です。ただ現実問題として、この場合の判断のタイミングは本当に難しく、いつどこで判断するかというのは正解のない決断に迫られることになると思っています。


まだ切羽詰まってサービス終了を考えているわけではないので急を要する事態ではないのですが、ただ最後のサービス終了決断以外はいずれの場合でも「ある程度のスキルを持った誰かに作業を引き継いでもらう(予めある程度の作業を教えて引き継げるようにしておく)必要がある」ことには変わりはありません。個人で興味本位から作り始めたサービスって、どういう形で終了を迎えるのが理想なんでしょうね。。

同じように個人開発サービスを運用されている方のご意見など、伺って参考にさせていただきたいです。なんかうまい方法ないんですかね。。

このページのトップヘ