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

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

2023/01

GitHub から提供されている静的サイト公開機能である GitHub Pages 。Git 的には「特定ブランチの特定フォルダ以下を静的サイトとして公開する」機能です。GitHub のリポジトリとしてコミットされていれば、GitHub のウェブ UI を使って設定できます。

が、いくつかの制約事項はあるものの git CLI だけでも(GitHub のウェブ UI から操作しなくても) GitHub Pages を公開することもできます。その手順を確認したので以下に記載しておきます。


【前提条件】
GitHub リポジトリに静的サイトのページが公開登録されている前提が必要です。また GitHub ページとして公開したいコンテンツは "/" (つまりリポジトリ直下のフォルダ)にまとまっているものとします。

というわけで以下のようなリポジトリを作りました。リポジトリ直下に README.md, page1.html, page2.html という3つのファイルが存在しているものとします:

(https://github.com/dotnsf/gh-pages-sample)
2023012200


それぞれの中身は以下のようになっています。3つのファイルでそれぞれリンクが設定されている、というだけの単純な内容です:
README.md
# README.md

- [ページ1](./page1.html)

- [ページ2](./page2.html)

page1.html
<html>
<head>
<title>ページ1</title>
</head>
<body>
<h1>ページ1</h1>

<a href="./">README.md</a>
</body>
</html>

page2.html
<html>
<head>
<title>ページ2</title>
</head>
<body>
<h1>ページ2</h1>

<a href="./">README.md</a>
</body>
</html>

このリポジトリをそのまま GitHub Pages で公開することにして、その手順を↓に紹介します(最後に応用の形でサブフォルダを GitHub Pages で公開する方法も紹介します)。


【git CLI での公開手順】
改めて GitHub Pages として公開したいリポジトリを参照し、その URL を確認します。今回の例であれば https://github.com/dotnsf/gh-pages-sample となります:
2023012201


このリポジトリを git clone します:
$ git clone https://github.com/dotnsf/gh-pages-sample

$ cd gh-pages-sample

次に gh-pages という名前のブランチ(←ここが重要!)を作成して checkout します:
$ git checkout -b gh-pages

このブランチをリモートの gh-pages ブランチとして git push します:
$ git push origin gh-pages

ここまでの手順が成功すると、GitHub のリモートリポジトリ側にも gh-pages ブランチが作成されていることが確認できます:
2023012202


(ここまでの手順で GitHub 上で GitHub Pages の設定はしていないのですが)"Settings" - "Pages" を選択して GitHub Pages の設定画面を確認すると、gh-pages ブランチの /(root) フォルダ以下が GitHub Pages として、 https://dotnsf.github.io/gh-pages-sample/ という URL で公開されていることが分かります:
2023012203


この URL にウェブブラウザでアクセスしてみると、README.md の内容が GitHub Pages として確認できます:
2023012204


ページ内のリンク部分をクリックすると想定通りのページに推移できます。GitHub ページとして期待通りに動いていることが確認できました:
2023012205


2023012206


ここで紹介したように gh-pages というブランチを作ってコミット&プッシュすることで、そのコンテンツを GitHub Pages として公開することができるようです。これによってウェブ画面からの操作なしで GitHub Pages 公開が実現できます。


【(応用)特定のサブフォルダ以下を GitHub Pages として公開したい場合】
GitHub で gh-pages という特殊な名前のブランチに登録することで GitHub Pages として公開できることがわかりました。ただ上で説明した方法ではリポジトリのフォルダ全体を公開することになりました。特定のサブフォルダの中だけを GitHub Pages として公開する方法はないのでしょうか?

その方法がこちらです。例えばローカルリポジトリ内の web フォルダ以下を GitHub Pages として公開する場合は以下のように指定します:
$ git subtree push --prefix web origin gh-pages

gh-pages というブランチを指定するのは↑で説明したのと変わりませんが、"git push" ではなく "git subtree push" というコマンドを使います。またこの時に "--prefix フォルダ名" を指定することで指定フォルダの内容だけを gh-pages ブランチとして(=GitHub Pages として)登録する※ことになります。


※少しややこしいのですが、この subtree push を使う方法で GitHub Pages を設定した場合、gh-pages ブランチに全ファイルが登録されて、その中の web フォルダ以下が GitHub Pages になる、というわけではありません。gh-pages ブランチに web フォルダ以下の全ファイルが登録されて、ルートフォルダ以下のファイル(つまりブランチ内の全ファイル)が GitHub Pages になります。つまり main ブランチと gh-pages ブランチではリポジトリのファイル構成が変わってしまう点に注意が必要です。



ウェブアプリケーションの開発ハンズオン(オンライン含めて)を行う場合、その開発環境の準備が面倒です。参加者の 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 でアクセスする場合の方法は別の機会に紹介するつもりです。


(参照)

昨年から自作サービスの多くを dokku 環境で公開しています。このブログでも何件かの dokku 関連ネタを紹介しています。今回のネタはその1つです:
20220609


dokku を使うことで、ウェブアプリケーションだけでなく PostgreSQL のようなデータベースインスタンスを作って利用することもできます。実際に PostgreSQL データベースを作ってウェブアプリケーションと接続(link)して使う方法をブログエントリとして紹介したこともあります:
http://dotnsf.blog.jp/archives/1080505175.html


最終的に dokku で公開するアプリケーションに関しては dokku アプリから dokku の PostgreSQL に接続して使うことになります。この場合はアプリとデータベースとを link することで、アプリケーション側の環境変数 DATABASE_URL に
postgres://postgres:password@dokku-postgres-mydb:5432/mydb

のような接続文字列の値が設定されます(ホスト名 dokku-postgres-mydb、ポート番号 5432、ユーザー名 postgres、パスワード password、DB名 mydb)。この値を使ってデータベースに接続することになります(ホスト名 dokku-postgres-mydb という値は dokku 内部で解決されて、アプリケーションサーバーと同じ dokku 内で動いている PostgreSQL データベースコンテナに接続されます)。この時点では PostgreSQL データベースは dokku 内のアプリケーションだけに公開されていることになります。


ただアプリケーションを一時的に localhost で起動して、localhost から dokku の PostgreSQL に接続して動作確認したくなることもあります(デバッグ時など)。そのようなことをする場合、dokku 内に作った PostgreSQL を dokku 外の(localhost の)アプリケーションから接続することになり、上述の(dokku 内のアプリケーションから接続する前提の)接続文字列を使うことはできません。このような接続設計を実現するための設定を紹介します。

まず PostgreSQL データベースインスタンス(mydb)を作成します:
# dokku postgres:create mydb

この mydb への(link した dokku アプリからの)接続文字列を確認するには以下のようなコマンドを実行します。実行結果の Dsn 値に対象の接続文字列を確認できます:
# dokku postgres:info mydb

=====> mydb postgres service information
       Config dir:          /var/lib/dokku/services/postgres/mydb/data
       Config options:
       Data dir:            /var/lib/dokku/services/postgres/mydb/data
       Dsn:                 postgres://postgres:password@dokku-postgres-mydb:5432/mydb
       Exposed ports:       -
       Id:                  1f5692d21aeb94de6f7bd9f467c41e2a52d6ee9fdff4d628379c883f72d25f9e
       Internal ip:         172.17.0.29
       Links:               -
       Service root:        /var/lib/dokku/services/postgres/mydb
       Status:              running
       Version:             postgres:14.2

この mydb データベースを dokku 外部から利用するには expose コマンドを実行します:
# dokku postgres:expose mydb

-----> Service mydb exposed on port(s) [container->host]: 5432->31157

すると実行結果に(↑の例だと) 5432->31157 という結果が表示されます。この 31157 というのが dokku 外部からこの mydb に接続するための(外向けの)ポート番号となります。仮にこの dokku が動いているホストの名前が dokku.myserver.com であったとすると、外部アプリからの接続文字列は
postgres://postgres:password@dokku.myserver.com:31157/mydb

を指定すればよい、ということになります。


あけましておめでとうございます。これが 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




 

このページのトップヘ