Teche Note
734 文字
4 分
Istioで複数FQDNのホスティング

Istioで複数アプリケーションのホスティングするのに詰まったので、記事にしておきます。 Istio自体の導入については前回の記事などをご参考ください。

問題#

前回の記事で導入したのと同じように

  • 別のNamespaceを新たに作成し、Istio injectionを有効化
  • そこに新しいFQDN用のGatewayとVirtualServiceを作成

して、新しいFQDN用のリソースをIstioで受けられるようにしたかったのですが、どうしてもできないのです。

いろいろ試して実験してみたところ、

  • VirtualServiceは、自分が所属するNamespace内に存在するGatewayにしか紐づけできない
  • 複数のGatewayを複数のNamespaceにデプロイすると、最初にデプロイしたGatewayに記載のあるFQDNしか名前解決ができない

ということがわかりました。

異なるアプリケーションは別のNamespaceで管理したかったため、全部を一つのNamespaceで管理することは避けたく、原因を調査しました。 (全て同じNamespace内にデプロイする方法は公式のドキュメントに記載があります)

原因: GatewayリソースはNamespace間で共通#

今回の問題の調査として大いに参考になったのがこちらのGoogle groupのディスカッション

gateways are not namespaced -they are common across all namespaces.

これが全てでした。Gatewayは複数デプロイすると互いに干渉するようです。 (Issueも立っていますが、仕様かバグかよくわからない)

じゃあNamespace分割するにはどうしたらいいんだ…?と思ったのですが、kube-dnsを使えば解決できます。 k8s内のリソースの名前解決は

<service-name>.<cluster-namespace>.svc.cluster.local

が使えるので、これをVirtualService > destination > host に記載すれば、Namespaceをまたいでサービスディスカバリが可能になります。

コードでは下記の感じです。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: common-istio-gateway
spec:
 selector:
   istio: ingressgateway # use istio default controller
 servers:
 - port: #マルチドメインの場合は、certificateなどを別名で(another-tls.crtなど)Secretとしてデプロイし、この項目を増やしていく
     number: 443
     name: https
     protocol: HTTPS
   tls:
     mode: SIMPLE
     serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
     privateKey: /etc/istio/ingressgateway-certs/tls.key
   hosts:
   - my-app1.example.com
   - my-app2.example.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: my-app1
spec:
 hosts:
 - my-app1.example.com
 gateways:
 - common-istio-gateway
 http:
 - route:
   - destination:
       host:
         my-service1.my-app1.svc.cluster.local
       port:
         number: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: my-app2
spec:
 hosts:
 - my-app2.example.com
 gateways:
 - common-istio-gateway
 http:
 - route:
   - destination:
       host:
         my-service2.my-app2.svc.cluster.local
       port:
         number: 80

Namespaceをまたいで共通のリソースなので、全てdefault namespaceにデプロイすることにします。 これで無事マルチホスティングができました。

補足#

さきほどのディスカッションにて

Also, I would suggest launching different gateway controllers for each gateway spec, instead of adding multiple gateways to the same controller (istio: ingressgateway).

ということが述べられており、Controllerを複数作成することで複数Gatewayも可能のようですが、まだ試していません。