☁️

MicroshiftでRouteを使う

2021/10/18に公開

Microshiftは、OpenShiftを極限までダウンサイズしてIoTやリソースの限られたPC上で実行できるようにしようというプロジェクト。現在、自分はMicroshiftをGitHub Actions上で使えるようにしようとしている。
https://github.com/redhat-et/microshift

始まったばかりのプロジェクトでユーザはまだほとんどいないと思うが、自分用の備忘録としてまとめておく。

Routeを通すにはDNSの設定が必要

Microshiftはまだ出来たてのプロジェクトなので、まだMinikubeやCRCのように色々な機能がすぐ使えるようにはなっていない。

OpenshiftのRouteを作成しても、そのままではすぐに割り当てられたホスト名にアクセスできない。

(この記事ではMicroshiftをVagrantにインストールする方法を前提にする。)

試しにアプリをMicroshiftにデプロイして、ルートを公開してみる。

oc create deploy hello --image=quay.io/tasato/hello-js
oc expose deploy hello --port 8080
oc expose svc hello

サービスとルートが出来上がる。

$ oc get svc,route
NAME                          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/hello                 ClusterIP   10.43.122.106   <none>        8080/TCP   6s
...

NAME                             HOST/PORT                     PATH   SERVICES   PORT   TERMINATION   WILDCARD
route.route.openshift.io/hello   hello-default.cluster.local          hello      8080                 None

しかし、このままだと hello-default.cluster.local にはアクセスできない。

$ curl hello-default.cluster.local
curl: (6) Could not resolve host: hello-default.cluster.local

Routerを公開する

最初にやるのは、OpenShiftのRouterをNodePortサービスとして公開すること。Routerはopenshift-ingressネームスペースに元々走っている。

$ oc get pods -n openshift-ingress 
NAME                              READY   STATUS    RESTARTS   AGE
router-default-6d8c9d8f57-wjfk7   1/1     Running   1          4d21h

これを30080->80(HTTP)、30443->443(HTTPS)でNodePortサービスとして公開する。これでクラスタ外から3008030443ポートでRouterにアクセスできるようにする。

$ cat <<EOF | oc apply -f -
apiVersion: v1
kind: Service
metadata:
  name: router
  namespace: openshift-ingress
spec:
  type: NodePort
  selector:
    ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
  ports:
    - name: http
      port: 80
      targetPort: 80
      nodePort: 30080
    - name: https
      port: 443
      targetPort: 443
      nodePort: 30443
EOF

なお、今作ったrouterサービスの他に元々router-internal-defaultというClusterIPサービスが用意されている。

$ oc get svc -n openshift-ingress 
NAME                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
router                    NodePort    10.43.205.107   <none>        80:30080/TCP,443:30443/TCP   4d2h
router-internal-default   ClusterIP   10.43.95.166    <none>        80/TCP,443/TCP,1936/TCP      36d

Microshiftクラスタのノード内からRouteにアクセスしたいだけ(GitHub Actionsで使う場合など)なら、わざわざrouterサービスを作らずこちらのrouter-internal-defaultがそのまま使える。

クライアント側のDNSを設定する

この時点でVagrant VMの30080ポートからhello-default.cluster.localにアクセスできるようになっている。VMのIPアドレスを192.168.99.11として、HTTPのHostヘッダにディスパッチ先のルート名を指定する。

$ curl -H 'Host: hello-default.cluster.local' 192.168.99.11:30080
Hello ::ffff:10.42.0.51 from hello-64c47c44c8-5bbjg

あとは、クライアント側でhello-default.cluster.localにアクセスしたらVagrant VMのIPアドレス192.168.99.11に名前解決されるようにすればいい。

dnsmasq

動的に作成されるURL *.cluster.localに特定IPアドレスを割り当てるにはdnsmasqを使うのが簡単。dnsmasqが入っていなければインストールする。

Fedora/RHEL/CentOS
$ sudo dnf install dnsmasq
Ubuntu
$ sudo apt install dnsmasq

/etc/dnsmasq.confを編集する。Vagrant VMのIPアドレス192.168.99.11cluster.localドメインに割り振る。address=/cluster.local/192.168.99.11を追加する。またコメントアウトされている#bind-interfacesのコメントを外して有効にする。

/etc/dnsmasq.conf
address=/cluster.local/192.168.99.11
...
bind-interfaces

bind-interfacesを有効にするのは、そうしないとsystemd-resolvedが見ている127.0.0.53:53と競合してdnsmasqが起動しないため。

dnsmasqを再起動する。

$ sudo systemctl restart dnsmasq

systemd-resolved

最近のLinuxではsystemd-resolvedがデフォルトのDNSサービスになっている。
/etc/systemd/resolved.confを修正して、dnsmasq(127.0.0.1)を見にいくようにする。

/etc/systemd/resolved.conf
DNS=127.0.0.1 8.8.8.8

8.8.8.8はもしかしたら要らないかもしれない。)

/etc/resolv.conf/run/systemd/resolve/stub-resolv.confへのリンクになっているのを/run/systemd/resolve/resolv.confに切り替える。

$ sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

/etc/nsswitch.conf

Fedoraを使っている場合には、/etc/nsswitch.confの設定に要注意。
*.localはmDNSに優先的に解決されるため、nsswitch.confでmDNSの解決後すぐにリターンするような設定になっている場合は、それを変える必要がある。

以下のようにhosts:[...=return]の設定がある場合は、それを全部外して必ずdnsまで到達するように変更する。

/etc/nsswitch.conf(変更前)
hosts:      files myhostname mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns
/etc/nsswitch.conf(変更後)
hosts:      files myhostname mdns4_minimal resolve dns

systemd-resolvedを再起動する。

$ sudo systemctl restart systemd-resolved

VM側のポートフォーワードを設定する

ここまででhello-default.cluster.local:30080でアプリにアクセスできるようになっている。

$ curl hello-default.cluster.local:30080
Hello ::ffff:10.42.0.51 from hello-64c47c44c8-5bbjg

curl hello-default.cluster.localでアクセスできるようにするには、VM側で3008080にポートフォーワードを設定する。

redir

一番簡単だったのはredirを使う方法。

redirをインストールする。

Fedora/RHEL/CentOS
$ sudo dnf install redir
Ubuntu
$ sudo apt install redir

VM内でredirをバックグラウンド起動する。

sudo redir -l debug :80 localhost:30080

redirのログはVM内のsyslogで確認できる。

$ sudo tail -f /var/log/syslog | grep redir
Oct 18 06:29:31 ubuntu-focal redir[142824]: peer IP is 192.168.99.1
Oct 18 06:29:31 ubuntu-focal redir[142824]: peer socket is 33402
Oct 18 06:29:31 ubuntu-focal redir[142824]: target IP address is 127.0.0.1
Oct 18 06:29:31 ubuntu-focal redir[142824]: target port is 30080
Oct 18 06:29:31 ubuntu-focal redir[50856]: target is localhost:30080
Oct 18 06:29:31 ubuntu-focal redir[50856]: Waiting for client to connect on server socket ...
Oct 18 06:29:31 ubuntu-focal redir[142824]: Connecting 192.168.99.1:33402 to 192.168.99.1:30080
Oct 18 06:29:31 ubuntu-focal redir[142824]: Entering copyloop() - timeout is 0
Oct 18 06:29:31 ubuntu-focal redir[142824]: Disconnect after 0 sec, 332 bytes in, 91 bytes out

確認

hello-default.cluster.localでアクセスできるようになる。

$ curl hello-default.cluster.local
Hello ::ffff:10.42.0.51 from hello-64c47c44c8-5bbjg

以上。

Discussion