1. はじめに
Red Hat OpenShift on IBM Cloud(ROKS)はVPC上でPrivate Only環境を構築することができる。もっと言えば、このROKS上のWorker nodeが配置されるSubnetは、Public Gatewayと紐づける必要もない。これにより、VPC内部からインターネットにさえアクセスできない閉域なOpenShift環境を構築することが可能である。
しかし、、、
実際は、インターネットアクセスできないとDocker Imageが取得できない、Githubにアクセスできないといった制約も生じる。もちろん、**「いやいや、せっかく閉域環境で構築しているんだから、そりゃあ仕方がないでしょ。そもそもそういうレポジトリとかは全部プライベート環境に作るものだよ」**というのはごもっともであり、私もそのように構成するべきだと思う。でも、たとえばちゃんとオンプレミスにあるProxy経由でアクセス制御を行いつつ、「統制の取れた」インターネットアクセスをしたいという要望もあるだろう(Public GatewayではIPアドレス指定はできるがドメイン指定はできない)。
そこで、今回は、Proxyサーバーをsquidで構築し、ROKSインターネットアクセスをする際には必ずProxy経由になるように構成できないかを試してみた。以下の手順は、公式ドキュメントに載っている訳ではないが、とりあえず色々Proxyでログを取りつつ試行錯誤して確認したところうまく動いているように見えるので、あくまで参考情報としてもらいたい(ホストの設定を直接編集している時点で、サポートされる構成と言えるのかはちょっと微妙)。
検証は、ROKS 4.7.29_1531で行った。
また、この手順例ではProxyとして10.0.0.4:3128
のサーバーを利用している。
2. cluster-wide proxyの構成。
はじめ、このcluster-wideのproxy構成をすれば、全ての通信がproxy経由になると思っていたのだが、そうではなかった。
- ICOSへのアクセス
- (Build中に)ソースファイルをGitHubから取得
- (Build中に)DockerFileに指定されているベースイメージを取得
- Operator Hubへの通信
などのようなOCPプロセス内からの呼び出しに利用されているように見える。一方で、Builder Imageの取得や外部のDocker Imageそのものを取得する際には、後述のCRI-Oの構成が必要のように見える。
2-1. 設定と確認
私の環境に設定したアドレスは以下になるが、VPC内部からROKSにアクセスするのであれば、VPC内部のIPアドレスもProxyを経由しないようにNoProxy
に入れておくと良いかもしれない。
$ oc edit proxy/cluster
(省略)
spec:
httpProxy: http://10.0.0.4:3128
httpsProxy: http://10.0.0.4:3128
noProxy: localhost,.svc,.cluster.local,.cloud-object-storage.appdomain.cloud,.containers.appdomain.cloud,icr.io,.icr.io,registry.au-syd.bluemix.net,registry.eu-de.bluemix.net,registry.eu-gb.bluemix.net,registry.ng.bluemix.net
trustedCA:
name: ""
(省略)
noProxy
には、自動的にc100-e.private.jp-tok.containers.cloud.ibm.com
などが追加されていた。
$ oc get proxy/cluster -o json | jq -r '.spec,.status'
{
"httpProxy": "http://10.0.0.4:3128",
"httpsProxy": "http://10.0.0.4:3128",
"noProxy": "localhost,.svc,.cluster.local,.cloud-object-storage.appdomain.cloud,.containers.appdomain.cloud,icr.io,.icr.io,registry.au-syd.bluemix.net,registry.eu-de.bluemix.net,registry.eu-gb.bluemix.net,registry.ng.bluemix.net",
"trustedCA": {
"name": ""
}
}
{
"httpProxy": "http://10.0.0.4:3128",
"httpsProxy": "http://10.0.0.4:3128",
"noProxy": ".cloud-object-storage.appdomain.cloud,.cluster.local,.containers.appdomain.cloud,.icr.io,.svc,10.0.0.0/16,127.0.0.1,172.17.0.0/18,172.21.0.0/16,c100-e.private.jp-tok.containers.cloud.ibm.com,icr.io,localhost,registry.au-syd.bluemix.net,registry.eu-de.bluemix.net,registry.eu-gb.bluemix.net,registry.ng.bluemix.net"
}
2-2. NoProxyで上記を指定した理由
NoProxyに何も設定しない場合は、Proxyサーバー上では以下のようなログが確認できた。
1631605621.901 90054 10.0.0.24 TCP_TUNNEL/200 4926 CONNECT s3.direct.ap.cloud-object-storage.appdomain.cloud:443 - HIER_DIRECT/161.26.85.12 -
ICOSのendpoint一覧はこちら。https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-endpoints
1631606804.225 17 10.0.0.24 TCP_TUNNEL/200 6129 CONNECT console-openshift-console.privonly-syasuda-roksvpc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-i000.jp-tok.containers.appdomain.cloud:443 - HIER_DIRECT/10.1.0.5 -
1631605630.946 30323 10.0.0.24 TCP_TUNNEL/200 6018 CONNECT canary-openshift-ingress-canary.privonly-syasuda-roksvpc-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-i000.jp-tok.containers.appdomain.cloud:443 - HIER_DIRECT/10.1.0.5 -
1631605620.556 636 10.0.0.24 TCP_TUNNEL/200 4402 CONNECT infogw.api.openshift.com:443 - HIER_DIRECT/34.225.158.211 -
1つ目のものはICOSへのアクセスでありVPC内部からのアクセスである必要があるため、必ずnoProxy
で除外設定をするべきである。2つ目と3つ目も、VPC Load BalancerへのアクセスなのでProxyを経由させる必要はないので、こちらもnoProxy
で除外されるように構成した。
また、IBM Cloud: Red Hat OpenShift on IBM Cloud(ROKS)でicr.ioにpublic gatewayなしでアクセスできる理由でも記載したとおり、icr.io
やregistry.au-syd.bluemix.net
は、一見インターネットへのアクセスのように見えるが実際は内部NWにアクセス
するように構成されているので、その恩恵を受けるために除外した。。image-registry.openshift-image-registry.svc
やimage-registry.openshift-image-registry.svc.cluster.local
なども明示的に内部NWにアクセス
するように構成されているので、こちらもnoProxy
で除外した(一応、.svc
や.cluster.local
は自動的に挿入されるようだが、明示的に入れた。)
なお、infogw.api.openshift.com
はTelemetryのための情報収集用のインターネットアクセスのようだ。
https://docs.openshift.com/container-platform/4.7/installing/install_config/configuring-firewall.html
2-3. テスト(/host/etc/sysconfig/crio-network設定前)
$ oc new-app --as-deployment-config --name test1 https://github.com/nin2yasu/DO288-apps#container-build --context-dir container-build
1631610425.550 518 10.1.0.16 TCP_TUNNEL/200 5128 CONNECT github.com:443 - HIER_DIRECT/13.250.177.223 -
1631610426.902 1329 10.1.0.16 TCP_TUNNEL/200 1088883 CONNECT github.com:443 - HIER_DIRECT/13.250.177.223 -
1631610430.285 637 10.1.0.16 TCP_TUNNEL/200 3854 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610430.962 673 10.1.0.16 TCP_TUNNEL/200 5086 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610431.654 690 10.1.0.16 TCP_TUNNEL/200 14511 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.298 637 10.1.0.16 TCP_TUNNEL/200 5695 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.307 647 10.1.0.16 TCP_TUNNEL/200 5667 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.309 649 10.1.0.16 TCP_TUNNEL/200 5638 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.314 654 10.1.0.16 TCP_TUNNEL/200 5695 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.318 657 10.1.0.16 TCP_TUNNEL/200 5667 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.322 662 10.1.0.16 TCP_TUNNEL/200 5695 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610432.324 12 10.1.0.16 TCP_TUNNEL/200 6547 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
1631610432.325 15 10.1.0.16 TCP_TUNNEL/200 6547 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
1631610432.335 12 10.1.0.16 TCP_TUNNEL/200 6547 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
1631610432.343 17 10.1.0.16 TCP_TUNNEL/200 8043 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
1631610432.794 476 10.1.0.16 TCP_TUNNEL/200 6054459 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
1631610433.011 615 10.1.0.16 TCP_TUNNEL/200 5695 CONNECT quay.io:443 - HIER_DIRECT/50.16.140.223 -
1631610433.029 14 10.1.0.16 TCP_TUNNEL/200 6664 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
1631610436.397 4096 10.1.0.16 TCP_TUNNEL/200 71058269 CONNECT cdn02.quay.io:443 - HIER_DIRECT/13.249.162.2 -
3. Worker Nodeにおける/host/etc/sysconfig/crio-network
の構成
OpenShiftにおいてDockerImageを外界から取得しているのは、コンテナエンジンであるCRI-Oであるため、CRI-OがProxyを利用するように構成する必要"も"ある。
ちなみに、Worker NodeのUpdateやReplaceを行うとこの設定は消えてしまうので、再度設定が必要になることにも注意(逆に言ったら設定を間違えたらUpdateやReplaceをすれば良い)。理想的にはスクリプトを作り上げるとか、DaemonSetを作るとかをした方が良いかもしれない。もっと良い設定方法などがあったら教えてください。
3-1. 設定と確認
# oc get nodes
NAME STATUS ROLES AGE VERSION
10.0.0.25 Ready master,worker 4h41m v1.20.0+9689d22
10.1.0.17 Ready master,worker 4h40m v1.20.0+9689d22
$ oc debug node/10.0.0.25
Creating debug namespace/openshift-debug-node-z6mx2 ...
Starting pod/100025-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.0.0.25
If you don't see a command prompt, try pressing enter
sh-4.4# echo HTTP_PROXY="http://10.0.0.4:3128/" >> /host/etc/sysconfig/crio-network;
sh-4.4# echo HTTPS_PROXY="http://10.0.0.4:3128/" >> /host/etc/sysconfig/crio-network;
sh-4.4# echo NO_PROXY="localhost,.svc,.cluster.local,127.0.0.1,172.16.0.0/16,172.17.0.0/18,172.18.0.0/16,172.19.0.0/16,172.20.0.0/16,172.21.0.0/16,172.30.0.0/16,161.26.0.0/16,166.8.0.0/14,icr.io,.icr.io,registry.au-syd.bluemix.net,registry.eu-de.bluemix.net,registry.eu-gb.bluemix.net,registry.ng.bluemix.net" >> /host/etc/sysconfig/crio-network;
sh-4.4# cat /host/etc/sysconfig/crio-network
# /etc/sysconfig/crio-network
CRIO_NETWORK_OPTIONS=
HTTP_PROXY=http://10.0.0.4:3128/
HTTPS_PROXY=http://10.0.0.4:3128/
NO_PROXY=localhost,.svc,.cluster.local,127.0.0.1,172.16.0.0/16,172.17.0.0/18,172.18.0.0/16,172.19.0.0/16,172.20.0.0/16,172.21.0.0/16,172.30.0.0/16,161.26.0.0/16,166.8.0.0/14,icr.io,.icr.io,registry.au-syd.bluemix.net,registry.eu-de.bluemix.net,registry.eu-gb.bluemix.net,registry.ng.bluemix.net
問題なければ、この構成を反映させるためにWorker nodeを再起動する。
3-2. NoProxyで上記を指定した理由
CRI-OはどうやらKubernetes Networkである172.x.x.xなどと通信しており、NO_Proxyに何も入れないで全部Proxy経由にすると、(当然ProxyサーバーがKubernetes Networkを認識しているわけはないので)403エラーが多発してたちまち挙動がおかしくなった。
Proxyを通すべきではない、ROKSとして予約しているアドレスは例えば、https://cloud.ibm.com/docs/openshift?topic=openshift-plan_clusters&interface=ui などが参考になる。
1631611678.135 0 10.0.0.24 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.140 0 10.0.0.24 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.144 0 10.0.0.24 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.147 0 10.0.0.24 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.148 0 10.0.0.24 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.254 0 10.1.0.16 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.258 0 10.1.0.16 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
1631611678.260 0 10.1.0.16 TCP_DENIED/403 3894 CONNECT 172.20.0.1:2040 - HIER_NONE/- text/html
また、NoProxyをあまり構成していなかった時は以下のようなアクセスログをProxyサーバーで確認できたが、この中には*.svcのような内部レジストリへのアクセスまで含まれており、当然Proxy経由では通信できないものなので、最終的にはNoProxyにて除外構成をした。
先述の通り、icr.io
やregistry.au-syd.bluemix.net
は一見インターネットへのアクセスのように見えるが実際には内部NWにアクセスするように構成されていることに注意。
1631622802.457 0 10.0.0.25 TCP_DENIED/403 3993 CONNECT image-registry.openshift-image-registry.svc:5000 - HIER_NONE/- text/html
1631622650.584 609 10.0.0.25 TCP_TUNNEL/200 4565 CONNECT registry.au-syd.bluemix.net:443 - HIER_DIRECT/135.90.66.54 -
1631622803.430 574 10.0.0.25 TCP_TUNNEL/200 4629 CONNECT icr.io:443 - HIER_DIRECT/169.62.37.246 -
1631622699.386 659 10.0.0.25 TCP_TUNNEL/200 3854 CONNECT quay.io:443 - HIER_DIRECT/3.213.173.170 -
1631622804.322 144 10.1.0.17 TCP_TUNNEL/200 5391 CONNECT registry.redhat.io:443 - HIER_DIRECT/23.2.36.201 -
4. 問題判別
- 必ずProxyサーバーのログとセットで構成を確認しましょう。
- Proxyサーバーのログに表示される宛先ドメインに対して、
ホスト内部から
名前解決をしてみましょう。ここでも紹介した通り、Global IPアドレスだと思っていたものが、思わぬところでVPC内部からのアクセスが必須になることもあるかもしれません。その場合は、NoProxyに入れて構成する必要があります。