[Kubernetes][Network] Kubernetesのクラスタネットワークを外部に展開する

クラスタ外部からKubernetesのサービスリソースへ直アクセスを

前回記事の補足

というわけで、「https://www.bluecore.net/2018/12/30/5863/」の一環でやってみることにしました。

例:MastodonのKubernetes上(我が自宅)の構造

要は、WorkerのNodePortにアクセスを経由させずとも、直接緑色の層「サービスリソース」にアクセスしたいのです。基本的にコンテナは起動停止をする度にIPアドレスが変わります。ルートリフレクタを入れて手に入るアドレス帯は紺色/赤色のPodへ直接つながるためのアドレスだけで、肝心なアドレス不変の緑色領域は手にはいりません。

じゃぁ取り敢えずどうすんのか?

実は探しても見つからなくて掲載できないんですが、外部にパケットをフォワードする手法について書かれた外部ブログがありました。当初は呼んでも全く理解が出来なかったんですが、翌々考えて読んでみると、「kubeproxyをフォワードテーブルとして他のノードと同期・活用する」と言う手法であることがわかりました。
つまりはあれですよ、単純にPodsを管理するネットワークと、クラスタIPを管理するネットワークって別物なんですね・・・そして当然、管理ソフトウェアも違うわけです。

クラスタネットワークとPodネットワーク

クラスタネットワークは、完全にkube-proxyが管理しています。そして、Podネットワークは皆様御存知のCNIプラグインで管理しています。私の環境ではCNIプラグインはProject Calicoを使用していますが、クラスタネットワークに対する理解がいまいち出来てませんでした。

Chain FORWARD (policy DROP 0 packets, 0 bytes)
66814309 15447099738 cali-FORWARD  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* cali:wUHhoiAYhphO9Mso */
54411811 13345770937 KUBE-FORWARD  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes forwarding rules */

Chain KUBE-FORWARD (1 references)
    pkts      bytes target     prot opt in     out     source               destination
       0        0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes forwarding rules */ mark match 0x4000/0x4000
    1154   187786 ACCEPT     all  --  *      *       10.240.0.0/16        0.0.0.0/0            /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
     719   105425 ACCEPT     all  --  *      *       0.0.0.0/0            10.240.0.0/16        /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED

こんな風に大量のFORWARDルールが書かれておりまして、どうやらこのiptables自体がパケットフィルタ兼ルーターの役割を果たしてるようです。

そこで

仕掛けました。ルートリフレクタをやっている仮想ルーターに以下のコンフィグを仕込んでいます。1つ目は10.96.0.0/12の経路を192.168.100.132(Kubernetes Master-node)に振り向けてます。2つ目はstatic経路を再配布するために、OSPF設定でRedistributeしています。

    static {
        route 0.0.0.0/0 {
            next-hop 192.168.100.254 {
            }
        }
        route 10.96.0.0/12 {
            next-hop 192.168.100.132 {
                distance 1
            }
        }
    }
    ospf {
        area 0.0.0.0 {
            network 10.240.0.0/16
            network 192.168.100.0/24
            network 10.96.0.0/12
        }
        parameters {
            abr-type cisco
            router-id 192.168.100.41
        }
        redistribute {
            bgp {
                metric-type 2
            }
            connected {
                metric-type 2
            }
            static {
                metric 3
                metric-type 2
            }
        }
    }

これによって、VPNルーターなんかでも無事経路伝達が行われていることを確認しました。

10.96.0.0/12        192.168.100.132      LAN1/1      OSPF  E2 cost=100 metric=3

これで、10.96.0.0/12上のネットワークにクラスタ外からアクセスすることが可能になります。コレで何が嬉しいかというと、kube-dns(coredns)に直接アクセスすることが出来、<namespace>.svc.cluster.localゾーンへ柔軟にアクセスできるのです。ポート番号縛りとか気にせずに、NodePort以上の扱いやすさを持ってアクセスできるのが何とも嬉しい限りです。

先の記事では、これをうまく活用してAzure Application Gatewayがオンプレミス環境にあるsvcリソースに到達できるよう構成しています。

クラスタネットワークへの経路があるから出来る芸当

svcリソースではセッションアフィニティを行うことも可能なので、それをうまく使えばsvcリソースを簡易ロードバランサーとして動かすことも可能になると思います。

この当たりの応用をうまく効かせると、よりインフラいじりが面白くなる、そんな感じの知見を得ることが出来て、おっちゃんホクホク顔ですw