IKS K8s/OpenShift マスターの api-server をプライベート専用に変更する方法

IBM Cloud Kubernetes や OpenShift on IBM Cloud のマスターのapi-serverのエンドポイントをプライベートIPアドレスに限定することで、インターネットからのK8sマスターノードへの攻撃を防止できる。そして、利用者はIBM Cloud の仮想サーバーをワークステーションとして、ユーザー専用プライベートVLAN経由で、K8sクラスタをkubectlコマンドなどで操作が可能となる。

図1 IKSクラスタ概要画面
![IKS-Private-Endpoint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/3216385e-44aa-8d5a-7463-5687752f850a.png)


このことで、K8sのapi-serverに対する攻撃の懸念がなくなり、セキュリティ上のリスクを軽減した利用ができる。この実現のためには、IKSクラスタの起動のオプションを設定で、プライベート・サービス・エンドポイントの有効化とパブリック・サービス・エンドポイントの無効化では不十分で、事前に次の２つの作業が必要だ。そこで、この記事では、デフォルト設定で起動したケース、プライベート・サービス・エンドポイントを有効化したケースを比較して、構成のポイントを確認する。

* VRFの有効化
* サービスエンドポイントの有効化

これは、IKSの　Kubernetes と OpenSHift の両者に共通して適用可能な方法である。

# 各接続ケースのネットワーク構成

## IBM Cloud Kubernetes Service(IKS)のマスターノードとkubectlコマンドの接続経路

IKSのKubernetes または OpenShift のクラスタを起動すると、マスターノード上の api-server は、パブリックIPアドレスに、エンドポイントを開設して、kubectlからのコマンドを待ち受ける。 このようなエンドポイントの構造は、主要なクラウドのKuberentesサービスでも同じ構造になっている。 

図2 kubectlとマスターノード、ワーカーノードの概念図
![IKS-Default-Config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/14400f76-b424-f652-52b5-098c79624c7d.png)

もちろん、マスターノードはクラウドのマネージドサービスとして管理され、セキュリティ上の対策もされているが、K8s api-server のサーバーポートが、インターネットに露出していることには違いない。そのため、K8s api-server の脆弱性をついた攻撃を受けるリスクがある。 このようなリスクを軽減するために、K8s api-server のIPアドレスとポート番号について、IBM Cloud のプライベートIPからのアクセスに限定することができる。


## プライベート・サービス・エンドポイント有効化時の接続経路

次の図は、プライベート・サービス・エンドポイントを有効にして、そこからアクセスした時の概念図である。マスターノード上のapi-serverは、パブリック・ネットワークから到達できない場所に、エンドポイントを開くことになる。そして、ユーザーは、一旦、踏み台の仮想サーバー（ワークステーション）にログインして、そこからkubectlコマンドなどを操作する。この構成では、マスターのapi-serverのエンドポイントが、パブリックに露出することがなくなり、リスクを軽減することができる。しかし、踏み台となるサーバーの管理やコストが余分に発生する。

図3 プライベート・サービス・エンドポイント経由でK8sクラスタを操作するケースの概念図
![IKS-Private-Config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/7d72651c-fa80-b868-5746-51fa3e9642d4.png)



## VPNと組み合わせるケース

踏み台サーバー(ワークステーション)に、外部からアクセスさせないために、外部向けNICのセキュリティーグループを「outband」だけに設定する。そして、ユーザーはSSL-VPNを利用して、踏み台サーバーのプライベートIPアドレスからsshでログインする。その後は、前述のケースと同じである。踏み台サーバーのパブリックネットワークへの接続を切ることはできない。何故ならば、ibmcloudコマンドは、パブリックIPアドレスのクラウドAPIのエンドポイントへのアクセスを必要としているためである。しかし、踏み台サーバーの認証、SSL-VPNの認証と二つの関門が作られ、踏み台サーバーがパブリックネットワークから攻撃されることも無くなるため、リスクは前述よりもさらに軽減できる。 このケースでは、ユーザーが利用するパソコンに、VPNクライアントをインストールする必要がある。


図4 SSL-VPN接続と組み合わせるケースの概念図
![IKS-Private-SSLVPN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42829/1c6af018-d90b-a43b-caa3-ffa1f4e89d6f.png)

プロジェクトで、大人数で接続するとなれば、ゲートウェイ・アプライアンスを設置して、定常的なVPN接続を維持することもできる。

今回の目標とするゴールは、図3で表した接続形態を目指すことにする。次にIKSのプライベート・サービス・エンドポイントを開設するための前提条件を整える部分を確認していく。


# 前提条件のセットアップ

ここから、次の2点のセットアップを進めていく。

* VRFの有効化
* サービスエンドポイントの有効化


## VRFの有効化

VRF(Virtual Routing and Forwarding)は、IBM管理のK8sマスターノードに対して、プライベート・ネットワーク経由で接続するためのユーザー個別のルーティングを設定するために利用される。そのため、K8sクラスタの作成時に、プライベート・サービス・エンドポイントを有効化しても、疎通することができない。 VRFの説明は、IBM Cloud のドキュメント [IBM Cloud での Virtual Routing and Forwarding (VRF) の概要](https://cloud.ibm.com/docs/infrastructure/direct-link?topic=direct-link-overview-of-virtual-routing-and-forwarding-vrf-on-ibm-cloud&locale=ja#connectivity-options-for-ibm-cloud) を参照して欲しい。

VRFの有効化は、IBM Cloud の スペシャル・ネットワーク・チーム(SNT)による設定変更が必要なため、ポータルからCaseを起票して、変更を依頼する。起票方法は、[VRFおよびサービス・エンドポイントの有効化](https://cloud.ibm.com/docs/account?topic=account-vrf-service-endpoint&locale=ja) を参照する。

* Case起票 前述のリンク先にある依頼方法にしたがってVRFの有効化をリクエストする。
* 一次受付の応答があり、リクエストはSNTへ転送される。
* SNTから利用目的の確認があるので、IKSのプライベート・サービス・エンドポイントを利用したいことを返す。
* VFRに移行するためにVLAN Spanning が無効になること、切替に必要な作業時間をUS中部時間帯で30分確保して欲しいといった応答がある。
* 作業時間を指定、または、いつでも可能などと英語で返して、作業完了を待つ。
* SNTから作業完了通知を受け、利用開始

SNTは、IBMクラウドの運用チームと異なり、平日のビジネス時間帯のみの対応となるので、時間に十分余裕を持って計画することが必要だ。筆者の実績では、時差もあるため、最初の起票から利用開始できるまで、3日かかった。

次のコマンドでVRFが有効になったことを確認できる。

~~~
$ ibmcloud account show
<中略>                                            
アカウント名:                            XXXX's Account   
アカウント ID:                           **************   
アカウント所有者:                         somebody@sample.com   
アカウント・タイプ:                       PAYG   
アカウント状況:                          ACTIVE   
リンクされている SoftLayer アカウント:     999999   
VRF が有効:                             true   # <--- trueに変わり有効化された
サービス・エンドポイントが有効:             false   
EU サポートあり                          false   
PoC (商用 PoC (概念検証))                false   
HIPAA サポートあり                       false 
~~~

これで一歩進んだ、次のステップは、簡単に終わる。


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

プライベート側のサービスポイントを有効化するコマンドを実行して、結果を確認すれば良い。

~~~
$ ibmcloud account update --service-endpoint-enable true
<中略>
OK
$ ibmcloud account show
<中略>
アカウント名:                            XXXX's Account   
アカウント ID:                           **************   
アカウント所有者:                         somebody@sample.com   
アカウント・タイプ:                       PAYG   
アカウント状況:                          ACTIVE   
リンクされている SoftLayer アカウント:     999999   
VRF が有効:                             true
サービス・エンドポイントが有効:             true   # <---  有効化された
EU サポートあり                          false   
PoC (商用 PoC (概念検証))                false   
HIPAA サポートあり                       false 
~~~



## IKSの起動、踏み台サーバーの起動後の確認

IKSのKubernetesクラスタ、または、OpenShiftクラスタを起動する。 そして、さらに、踏み台サーバーを起動する。踏み台サーバーは、筆者の使い慣れたUbuntu 18.04、vCPU x1、RAM 1GB、Disk 25GB を選択した。

踏み台サーバーログインして、クラスタ管理画面の「アクセス」の案内された方法で、踏み台サーバーにツールをインストールして、IBM Cloud へログインする。

K8sのクラスタ概要画面から、プライベート・サービス・エンドポイントのDNS名を抜き出して、pingで疎通できることを確認する。 このIPアドレスには、パブリックIPアドレスがアサインされているが、インターネットから疎通することはできない。

~~~
root@ubuntu:/# ping -c 3 c1.private.jp-tok.containers.cloud.ibm.com
PING c1.private.jp-tok.containers.cloud.ibm.com (166.*.*.*) 56(84) bytes of data.
<中略>
--- c1.private.jp-tok.containers.cloud.ibm.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 1.373/1.467/1.567/0.079 ms
~~~


## 踏み台サーバーからのK8sクラスタの確認

セットアップ済みの踏み台にログインして、クラスタの状態を確認する。 各URLアドレスには、c1.privateという文字列が含まれており、プライベート側のエンドポイントを指せていることが、読み取れる。

~~~
root@virtualserver01:~# kubectl cluster-info
Kubernetes master is running at https://c1.private.jp-tok.containers.cloud.ibm.com:28679
CoreDNS is running at https://c1.private.jp-tok.containers.cloud.ibm.com:28679/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
kubernetes-dashboard is running at https://c1.private.jp-tok.containers.cloud.ibm.com:28679/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy
Metrics-server is running at https://c1.private.jp-tok.containers.cloud.ibm.com:28679/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
~~~


# まとめ

K8sを運用するにあたり、マスターノードのエンドポイントは、一般のインターネットからのアクセスを禁止してリスクを軽減したい。IBM Cloud では、マネージドのマスターノードのアクセスポイントをプライベートネットワーク側だけにエンドポイントを開くことができる。しかし、K8sクラスタの起動時の選択項目だけでなく、VRFの有効化など、事前の設定が必要である。この一通りの流れを確認した。

パソコンに、SSL-VPNクライアントをインストールして、VPN接続した場合でも、プライベート・サービス・エンドポイントまでルーティングが無いので、踏み台サーバーが必要であった。


# 参考資料

1. IKSでの複数ゾーン・クラスタ、VRF または VLAN Spanning が必要な事が明記、https://cloud.ibm.com/docs/containers?topic=containers-ha_clusters&locale=en#multizone
1. VRF およびサービス・エンドポイントの有効化、https://cloud.ibm.com/docs/account?topic=account-vrf-service-endpoint
1. サービス・エンドポイントの有効化、https://cloud.ibm.com/docs/account?topic=account-vrf-service-endpoint#service-endpoint
1. IBM Cloud での Virtual Routing and Forwarding (VRF) の概要、https://cloud.ibm.com/docs/infrastructure/direct-link?topic=direct-link-overview-of-virtual-routing-and-forwarding-vrf-on-ibm-cloud&locale=ja
1. プライベート・ネットワーク接続のためのサービス・エンドポイント、https://cloud.ibm.com/docs/resources?topic=resources-service-endpoints&locale=ja
1. プライベート・ネットワーク・エンドポイントのセットアップ、https://cloud.ibm.com/docs/resources?topic=resources-private-network-endpoints&locale=ja
1. SSL-VPNのセットアップ方法、https://cloud.ibm.com/docs/infrastructure/iaas-vpn?topic=VPN-setup-ssl-vpn-connections&locale=ja
1. VPNアクセスポイント、https://www.ibm.com/cloud/vpn-access?cm_mc_uid=83233531881915621066569&cm_mc_sid_50200000=70977641565275834053
1. SSL-VPNのパスワード設定、https://cloud.ibm.com/docs/infrastructure/iaas-vpn?topic=VPN-update-users-vpn-password&locale=ja
1. MotionPro VPNクライアントのダウンロードとマニュアル、http://client.arraynetworks.com.cn:8080/en/troubleshooting