OpenShiftのポッド からPrivate Service Endpoint経由のRedisアクセス

OpenShiftのクラスタ上に、Redisクラスタを構築する方法について調べてきた。しかし、IBM Cloud データベースの中の一つに、Redisのサービスがある。ワザワザ、自らK8sクラスタ上にRedisクラストを構築することを疑問視されることもある。そこで、Redisのマネージドサービスについて、従来からの課題に対する解決手段を含めて検証する。

以下は、過去のRedisとK8sに関する記事である。これらは、Redisのコンテナを自身のK8sクラスタで動かしていた。

* [Redisクラスタ を OpenShift on IBM Cloud にデプロイした結果](https://qiita.com/MahoTakara/items/37a9f73509b993034f5d)
* [Redisクラスタをマルチゾーン上のKubernetesで構築する時の考慮点](https://qiita.com/MahoTakara/items/dece9d0d4fd4094a3bc4)
* [Redis+Sentinel を Kubernetes で動かしたメモ](https://qiita.com/MahoTakara/items/2a396958d92cf67f80be)


## Redisのプライベート・サービス・エンドポイント

過去、Bluemix時代では、データベースのサービスは、Bluemix PaaS の Cloud Foundryランタイムから利用するために設計されていた。そのため、PaaSのランタイム以外の仮想サーバー、K8sポッドからアクセスする場合は、必ず、パブリックネットワーク経由でDBaaSのエンドポイントへ接続するために、セキュリティ・リスクに対する懸念、通信量に応じた従量課金が問題となっていた。このような状況に至った背景は、SoftLayerの買収、Bluemix PaaSの構築など、IaaSとPaaSの統合など、主幹事業部の変遷を含めた様々な変遷を辿ってきた名残であり、他社クラウドサービスから遅れを取っていた部分である。

図1 デフォルトのパブリックネットワーク経由のRedisアクセス
![DBaaS_Public.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/9d2c747e-3bc0-7cd4-9f0b-0a932ad449a7.png)


この課題の解決策として、ユーザー個別に提供されるプライベートVLANに、DBaaSのプライベート・エンドポイントを開設するサービスが開始された。 パブリックネットワークから到達不能なプライベートなネットワーク・エリアに、DBaaSのエンドポイントを開いて、バックエンドのPrivate VLANを経由してアクセスするため、第三者からエンドポイントを攻撃されるリスクもなくなり、データのセキュリティが一段と向上する。

図2 プライベートネットワーク経由でのRedisアクセス
![DBaaS_Private.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/3cd84424-962a-08c2-ed0d-5e96129a9821.png)

パブリック・ネットワークに、DBaaSのエンドポイントを開いて、インターネット上から自由にアクセスできることにはメリットがある。例えば、自身の開発環境から自由にアクセスできること、他社クラウドからでも利用できるなどの点でさる。もちろん、SSL/TLSなどを利用して通信を暗号化しておけば、通信傍受により情報漏洩のリスクは無いと考えて良い。そこで、DBaaSのデフォルトは、パブリックネットワークにエンドポイントを開き、利用者が希望すれば、エンドポイントをプライベートエリアだけに限定するといった設定が可能になっている。


## プライベート・サービス・エンドポイントを利用するための準備作業

プライベート・サービス・エンドポイントを有効にするためには、VRF (Virtual Router Forwarding)が有効になっていなければならない。VRFは、アカウントごとに設定されるもので、Caseからリクエストを挙げて、IBM Cloud のネットワークチームに設定変更してもらう必要がある。その上、サービス・エンドポイントを有効にする必要がある。

以前の投稿した記事、[IKS K8s/OpenShift マスターの api-server をプライベート専用に変更する方法](https://qiita.com/MahoTakara/items/97aab7fc88e6f27fba7e)に、VRFとサービス・エンドポイントを有効化する流れについて記録を書いたので参考にして有効にする。

これらの設定はアカウントに適用され、VRFは一度設定すると、元に戻せない。

## 前提設定の確認

前述の2者が有効であることを確認するには、次のコマンドを実行すれば良い。確認するべき項目もターミナル出力中にコメントしておいた。

~~~
root@virtualserver01:~# ibmcloud account show
<中略>
VRF Enabled:                        true   <<--- これと
Service Endpoint Enabled:           true   <<--- これが trueであること
EU Supported                        false   
PoC (Commercial Proof of Concept)   false   
HIPAA Supported                     false   
~~~

## Redis DBaaSのデプロイ

カタログの中から、Database for Redisを選択する。Redisは、次の特徴がある。

* コンプライアンス：SOC 2タイプ1、SOC 1タイプ1、HIPAA対応、GDPR
* IAM、リソースグループ、アクティビティトラッカー、モニタリング、キー保護との統合
* ディスク上のデータ、移動中のデータ、およびバックアップの暗号化
* クロスリージョンIBM Cloud Object Storageで30日間のバックアップ保持
* サーバーレススケーリングのため、ディスクとRAMの独立したスケーリング
* 従量課金、時間単位の請求

図3 カタログの中の Redis
![Catalog_Mini.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/925ed3fd-6643-f8d3-fd2d-549302746f59.png)


## Redisのデプロイ

ほとんどデフォルトを選択するが、「Endopoints」だけ、PublicとPrivateの両方を選択する。

1. サービス名: Redis-0101
1. デプロイする地域/ロケーションの選択: 東京
1. リソース・グループの選択: default
1. タグ: 任意に設定
1. Select an initial memory allocation: 1GB/member (2GB total)
1. Select an initial disk allocation: 1GB/member (2GB total)
1. Select an initial CPU allocation: Shared CPU
1. Select a database version: 4
1. Select a Key Protect instance: Automatic disk encryption key (default)
1. Select a disk encryption key: Automatic disk encryption key (default)
1. Endpoints: Both public & Private network

図4 Redisのインスタンス作成画面
![Redis_Config_Mini.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/c0a8c0b8-b686-d851-ce1f-32aca18b914f.png)

「作成」をクリックして、数分すると、デプロイが完了する。


# Redisへのアクセス

まず、自身のパソコンから、パブリック・ネットワーク経由でRedisへの接続テストを実施する。
パブリック・ネットワーク経由で接続するが、Redisにバンドルされる「redis-cli」には暗号通信機能が無いため、IBM独自のSSL/TLS対応Redisクライアント「redli」を利用する。

参考資料 https://github.com/IBM-Cloud/redli



## クラウドデータベースのプラグインのインストール

初めて、クラウドデータベースを利用する場合、ibmcloudコマンドのクラウドデータベース用のプラグインをインストールする。これにより サブコマンド cdb が利用できるようになる。

~~~
$ ibmcloud plugin install cloud-databases
リポジトリー 'IBM Cloud' から 'cloud-databases' を検索しています...
プラグイン 'cloud-databases 0.6.0' がリポジトリー 'IBM Cloud' 内で見つかりました
バイナリー・ファイルをダウンロードしようとしています...
 9.66 MiB / 9.66 MiB [==================================================================================================================================] 100.00% 14s
10133532 バイトがダウンロードされました
バイナリーをインストールしています...
OK
プラグイン 'cloud-databases 0.6.0' は /Users/maho/.bluemix/plugins/cloud-databases に正常にインストールされました。 'ibmcloud plugin show cloud-databases' を使用して詳細を表示してください。
~~~


## クラウドデータベースのリストを表示

インスタンスとして稼働しているデータベースのサービスをリストする。 2番目に Redis-0101が表示されている。

~~~
$ ibmcloud cdb deployments
<中略>
Name                          Location   State   
Databases for PostgreSQL-hv   us-south   active   
Redis-0101                    jp-tok     active  
~~~


## 管理者パスワードのセット

次のコマンドでデータベース管理者のパスワードをセットする。このパスワードは、後々に利用するので、メモしておく。

~~~
$ ibmcloud cdb user-password Redis-0101 admin newpassword123
<以下省略>
~~~


参考資料 https://cloud.ibm.com/docs/services/databases-for-redis?topic=databases-for-redis-admin-password&locale=ja



## 接続用の文字列の取得

次のコマンドで、Redis-0101のインスタンスに接続するための文字列を表示できる。

~~~
$ ibmcloud cdb deployment-connections Redis-0101
Retrieving public connection strings for Redis-0101...
OK

Type    Connection String   
Redis   rediss://admin:$PASSWORD@3a3e43f3-5801-481a-9092-74dea6e33d69.c437f5ab8b3840e99a1a93dffcce078d.databases.appdomain.cloud:32297/0   
CLI     REDIS_CERTFILE=37388d79-db9d-11e8-907f-e6c932c242f1 redli -u rediss://admin:$PASSWORD@3a3e43f3-5801-481a-9092-74dea6e33d69.c437f5ab8b3840e99a1a93dffcce078d.databases.appdomain.cloud:32297/0   
~~~

参考資料 https://cloud.ibm.com/docs/services/databases-for-redis?topic=databases-for-redis-connection-strings&locale=ja#getting-connection-strings-from-the-cli



## redliのインストール

暗号通信機能を備えたRedisクライアント「redli」をインストールする。go言語環境をインストールしたあと、https://github.com/IBM-Cloud/redli から、redliコマンドをインストールする。 インストールされるディレクトリは、環境によって異なるが、このmacOSの例では、~/go/binになるので、パスを通しておく。

~~~
$ go version
go version go1.12.5 darwin/amd64
$ go get -u github.com/IBM-Cloud/redli
$ go install github.com/IBM-Cloud/redli
$ export PATH=$PATH:~/go/bin
$ redli --help
usage: redli [<flags>] [<commands>...]
<以下省略>
~~~

参考資料 https://github.com/IBM-Cloud/redli



## パブリック側からの redli からのRedisへの接続テスト

パスワードの環境変数は、あらかじめセットしておき、パソコン上のredliから接続テストを実施する。 「--certfile ./redis-cert.pem」は、暗号通信のための証明書である。

これは、https://cloud.ibm.com/resources リソース -> サービス -> Redis-0101 -> 管理 と進み、TLS certificate に表示されたPEMデータをテキストファイルにしたものである。パブリック用とプライベート用の二つがあるので、接続経路に応じて証明書を選択する。

次は、redliコマンドで接続したあと、set/getなどでデータを操作して確認した例である。

~~~
redli -u rediss://admin:$PASSWORD@3a3e43f3-5801-481a-9092-74dea6e33d69.c437f5ab8b3840e99a1a93dffcce078d.databases.appdomain.cloud:32297/0 --certfile ./redis-cert.pem
Connected to 4.0.10
> set key-a 123
OK
> get key-a
"123"
> incr key-a
(integer) 124
~~~



## プライベートのサービス・エンドポイントの有効化

次にプライベート・サービス・エンドポイントを有効化する。


~~~
$ ibmcloud resource service-key-create redis-private-key Administrator --instance-name Redis-0101 --service-endpoint private
~~~

参考資料 https://cloud.ibm.com/docs/services/databases-for-redis?topic=cloud-databases-service-endpoints&locale=ja#credentials-for-private-endpoints


## プライベート・サービス・エンドポイントへの接続テスト


図5 パブリックネットワーク経由でのRedisへのアクセス
![Redis-Workstation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/626fdaf8-7ddf-fc03-483a-43550130dd02.png)

USERNAMEとPASSWORDの環境変数は事前にセットしておく、Redisインスタンスの「管理」画面に表示されるプライベート用の証明書をファイルとして保存する。 そして、接続文字列をコピペして、redliコマンド実行する。


接続文字列、すなわち、RedisインスタンスのURLアドレスに、private.databsesという文字列が含まれており、プライベートのエンドポイントであることが伺われる。 パブリックネットワークからpingを実行して、疎通が無いことを確認するのも良いと思う。

実行結果では、パブリックのエンドポイントに繋いで、キーと値をセットしたものから、キーを指定して値を取得してみる。 以下の実行例のようにデータが取得できた。

~~~
root@virtualserver01:~# redli -u rediss://$USERNAME:$PASSWORD@3a3e43f3-5801-481a-9092-74dea6e33d69.c437f5ab8b3840e99a1a93dffcce078d.private.databases.appdomain.cloud:32297/0 --certfile ./cert.pem 
Connected to 4.0.10
> get key-a
"124"
~~~


## OpenShift の ポッドからの接続テスト

最後に、OpenShift上のポッドから、Redisサーバーへアクセスを試みる。RedisサーバーとOpenShiftのマスターノードは、それぞれ、IBM Cloud の管理下にあり、これらサーバーに直接ログインすることができない。利用者はWorkstationに一旦ログインして、OpenShiftへログイン、そして、Redisサーバーをアクセスするポッドを起動して、アクセステストを実施する。

図6 OpenShiftのポッドからプライベートネットワーク経由のRedisアクセス
![OpenShift_Redis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/bb2a7317-fe01-458b-b235-94a7592ba690.png)


以下は、踏み台となる仮想サーバーにログインしてから、OpenShiftのポッドからRedisをアクセスするまでの操作の記録である。この例は検証のためであり、通常は、コンテナ内のプログラム言語から利用することになる。

~~~
# SSL-VPN経由 踏み台サーバーへログイン
$ ssh -i ~/key/takara3 root@10.212.5.223

# OCコマンドのダウンロード
# curl -L https://github.com/openshift/origin/releases/download/v3.11.0/openshift-origin-server-v3.11.0-0cbc58b-linux-64bit.tar.gz

# OCコマンドのインストール
root@virtualserver01:~# tar xzvf openshift-origin-server-v3.11.0-0cbc58b-linux-64bit.tar.gz 
root@virtualserver01:~# mv openshift-origin-server-v3.11.0-0cbc58b-linux-64bit /usr/local/bin
root@virtualserver01:~# export PATH=$PATH:/usr/local/bin/openshift-origin-server-v3.11.0-0cbc58b-linux-64bit

# OpenShiftへログイン
root@virtualserver01:~# oc login https://c100-e.jp-tok.containers.cloud.ibm.com:31473 --token=*****

# OpenShiftノードをリスト
root@virtualserver01:~# oc get node
NAME           STATUS    ROLES           AGE       VERSION
10.193.10.50   Ready     compute,infra   20m       v1.11.0+d4cacc0

# Ubuntuのポッドを起動して、redliに必要なプライベートのTLS証明書などを準備
root@virtualserver01:~# oc run -it ubuntu --image=maho/my-ubuntu:0.1 --restart=Never --rm -- bash
If you don't see a command prompt, try pressing enter.
root@ubuntu:/# apt-get update
root@ubuntu:/# apt install git golang
root@ubuntu:/# go get -u github.com/IBM-Cloud/redli
root@ubuntu:/# go install github.com/IBM-Cloud/redli
root@ubuntu:/# export PATH=$PATH:~/go/bin
root@ubuntu:/# export USERNAME=admin
root@ubuntu:/# export PASSWORD=newpassword123
root@ubuntu:~# cat - > cert.pem
-----BEGIN CERTIFICATE-----
MIIDHTCCAgWgAwIBAgIUFIO1EGeecAJjDhDdmSdOfCWPboYwDQYJKoZIhvcNAQEL
<中略>

# Redisへ接続して、データを読取りと更新
root@ubuntu:~# redli -u rediss://$USERNAME:$PASSWORD@3a3e43f3-5801-481a-9092-74dea6e33d69.c437f5ab8b3840e991a93dffcce078d.private.databases.appdomain.cloud:32297/0 --certfile ./cert.pem 
Connected to 4.0.10
> get key-a
"124"
> incr key-a
(integer) 125
~~~

## まとめ

仮想サーバー、および、OpenShiftクラスタ上のポッドから、IBM Cloudデータベースのプライベート・サービス・エンドポイントを介したアクセスが可能であることが確認できた。

VRFが有効化や、Redisインスタンスのプライベート・サービス・エンドポイントの有効化など、コマンドラインでしか設定できない項目があるため、ウェブ画面だけでは目的を達成することできないため、ドキュメントを良く読みながら、設定を実施する必要があることが解った。