TR;DR

  • KubernetesのServiceで、Internal LoadBalancerってのがあるので、それを使うと良い

Internal LoadBalancer

皆さんはEKS、もう使ってますか?私は使っています。業務システムをリプレースで新規開発する的な案件で、新システムの基盤がEKSという感じです。EKSはネットワークが素敵に気持ち悪い感じになっており、普通はKubernetesのクラスタ内部っていうのは、外側と別のサブネットを作る訳なんですが、なんとEKSが所属するVPCと同じサブネットで接続できるようになっています。

そんなわけで、同一VPCに存在したり、VPC PeeringしたりなんかしちゃってるEC2インスタンスとEKS上のPodはIPアドレスベースでは普通に接続がとれちゃったりするんです。 EKS上のアプリケーションから、EC2インスタンスへアクセスしたいときは、普通にEC2インスタンスのIPアドレスやら内部エンドポイントへアクセスすれば良いですね。EC2インスタンスが動きっぱなしならまぁさほどIPも変わらんでしょう(雑)。

しかし逆は問題です。PodのIPは勿論割り振られてはいますけれど、これはPodが再生成されると勿論変わってしまいます。アプリケーションは動きっぱなしだから変わらない、なんて言うこともできないです。EC2インスタンスはインスタンス上でアプリケーションの更新なんかもしちゃうかもしれないですけど、EKS上のPodに乗ったアプリケーションの更新は普通、Podの再作成が伴います。Podの再作成が起きると、勿論IPが変わります。

そうすると、やはり考えるのはServiceをつくることですね。外部からアクセスするためにはそうしますから、同じように考えるのが普通です。 しかし、ここで問題が発生します。普通に外部向けに公開するのと同じようにServiceを作成すると、グローバルIPが当たってしまい、プライベートIPベースで接続できる状況では接続ができないのです。困った。

まぁドキュメントちゃんと読めよって話なんですが、Kubernetesのドキュメント を読むと、Internal LoadBalancerってのがちゃんと書いてあります。AWSの方のドキュメントには無かったのでちょっと盲点でした。annotationで次の様に指定します。

1
2
3
4
5
6
# ...
metadata:
    name: my-service
    annotations:
        service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
# ...

これだけで、type: LoadBalancerで作成されるELBが内部向けのものになります。internal-なんちゃらみたいなエンドポイントです。IPアドレスもしっかりプライベートIPです。最高。後ろの0.0.0.0/0のところで、アクセスできるIPレンジ制限できるのかなーなんて希望的観測を持ちましたが、全然関係ありませんでした。 ちょっと気持ち悪いのは、普通にパブリックDNSで名前引きができてしまうことですかね。全然関係ない外部のネットワークとかでも(パブリックDNSに名前があるので)名前解決ができてしまって、かつプライベートのアドレスが帰って来るという不思議な体験をすることができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ nslookup internal-xxxxx.us-west-2.elb.amazonaws.com 1.1.1.1
Server:		1.1.1.1
Address:	1.1.1.1#53

Non-authoritative answer:
Name:	internal-xxxxx.us-west-2.elb.amazonaws.com
Address: 192.168.187.214
Name:	internal-xxxxx.us-west-2.elb.amazonaws.com
Address: 192.168.222.128
Name:	internal-xxxxx.us-west-2.elb.amazonaws.com
Address: 192.168.109.84

うーん、まぁ実害は無いんでしょうけど。