はじめに
Kubernetes を触り始めて困惑したのは、クラスタの外からどうやってアクセスするのか?ということでした。
GKE なら提供されているロードバランサを使えば良いですが、GKE に頼れない環境でも良い方法が欲しいものです。
ClusterIP
はクラスタ内部からアクセスする際に使用するもので、外部からアクセスすることは意図されていませんが、
これをそのまま利用できればとても楽ができそうです。
ClusterIP
へのアクセスは複数の Pod
に対して振り分けられるので、Ingress や Service Load Balancer が無くてもクラスタの外に対してロードバランサを提供することができます。
調べたところ Project Calico
と kube-proxy
を利用するとクラスタの外から ClusterIP
にアクセスできたので、やり方をまとめておきます。
テスト環境
テスト環境では 5つのホストを構築します。
すべて CentOS 7.2 で作成しています。
- kubemaster ...
kube-apiserver
やetcd
などを動作させる Kubernetes のMaster
です - kubenode01 ...
kubelet
やkube-proxy
を動作させる Kubernetes のNode
1号機です - kubenode02 ...
kubelet
やkube-proxy
を動作させる Kubernetes のNode
2号機です - kubegw ...
kube-proxy
を動作させ、外部との通信を中継するルータ兼ロードバランサ
(L3 ルーティング + NAPT) です
Calico
は上記すべてのホストで動作させます。
Client
はクラスタの外に存在するホストです。ここから ClusterIP
宛てにリクエストを投げます。
Pod
は 172.16.0.0/16
のアドレスレンジから割り当てます。
ClusterIP
は 10.0.100.0/24
のアドレスレンジから割り当てます。
実環境に適用するなら既存のルータから kubegw に向けたスタティックルートを設定するか、kubegw を含める形でダイナミックルーティングを設定することになるでしょう。
ここでは Client
に直接 kubegw に向けたスタティックルートを設定します。
Project Calico について
Kubernetes のドキュメント では僅かに触れられている程度ですが、
kubelet
の Network Plugin として使用すると、クラスタで作成された Pod
(コンテナ) 間で Pod
の IP アドレスをそのまま使って通信できるようになります。
flannel
で overlay network を作る代わりに使います。
各ホストに Docker コンテナとして calico/node
をデプロイし、すべての calico/node
はフルメッシュで BGP ピアリングします。
詳細は Calico のドキュメント を参照してください。
Kubernetes クラスタ構築
まずは Kubernetes のクラスタを構築します。大部分は yum
でさくっといきます。
各ホストは hosts
で名前解決できるようにしています。
192.168.100.10 kubemaster
192.168.100.1 kubenode01
192.168.100.2 kubenode02
Master 構築
バージョンは以下の通りでした
- etcd-2.2.5-1.el7.x86_64
- docker-1.9.1-25.el7.centos.x86_64
- kubernetes-master-1.2.0-0.9.alpha1.gitb57e8bd.el7.x86_64
- calico/node:v0.19.0
# yum install etcd docker kubernetes-master
## 後で使うので EPEL から jq をインストールしておく
# yum install http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-6.noarch.rpm
# yum install jq
まずは etcd
を起動します。この例では etcd
はクラスタを構成せず 1台で起動させています。
この etcd
は Kubernetes
だけでなく Calico
の設定も保存させます。
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.100.10:2379"
# systemctl enable etcd
# systemctl start etcd
続いて Calico
をセットアップします。Docker
を使用するのでこの時点で起動させています。
storage driver は overlayfs にしていますが、何でもよいです。
OPTIONS=
DOCKER_CERT_PATH=/etc/docker
DOCKER_STORAGE_OPTIONS='-s overlay'
# systemctl enable docker
# systemctl start docker
# mkdir -p /opt/calico/bin
# wget https://github.com/projectcalico/calico-containers/releases/download/v0.19.0/calicoctl
# chmod +x calicoctl
# mv calicoctl /opt/calico/bin
## calico のパスを通しておく
# vi ~/.bash_profile
PATH=$PATH:$HOME/bin:/opt/calico/bin
# . ~/.bash_profile
# ETCD_AUTHORITY=127.0.0.1:2379 calicoctl node --ip=192.168.100.10
Pulling Docker image calico/node:v0.19.0
Running Docker container with the following command:
docker run -d --restart=always --net=host --privileged --name=calico-node -e HOSTNAME=kubemaster -e IP=192.168.100.10 -e IP6= -e CALICO_NETWORKING=true -e AS= -e NO_DEFAULT_POOLS= -e ETCD_AUTHORITY=127.0.0.1:2379 -e ETCD_SCHEME=http -v /var/log/calico:/var/log/calico -v /lib/modules:/lib/modules -v /var/run/calico:/var/run/calico calico/node:v0.19.0
Calico node is running with id: f6c2897855834f53d10626051197d22c35f46905c32e542c270ca52dc068b058
Waiting for successful startup
Calico node started successfully
完了すると calico/node
のコンテナが起動します。
起動コマンドを表示してくれているので分かりますが、このコンテナは Restart Policy が always になっています。
起動後は以下のように見えてきます。
# calicoctl node show
+------------+----------------+-----------+-------------------+--------------+--------------+
| Hostname | Bird IPv4 | Bird IPv6 | AS Num | BGP Peers v4 | BGP Peers v6 |
+------------+----------------+-----------+-------------------+--------------+--------------+
| kubemaster | 192.168.100.10 | | 64511 (inherited) | | |
+------------+----------------+-----------+-------------------+--------------+--------------+
デフォルトだと 192.168.0.0/16
をコンテナに割り当てるようですが
クラスC を他で使っていて見づらいので、ここでは 172.16.0.0/16
に変更しておきます。
# calicoctl pool show --ipv4
+----------------+---------+
| IPv4 CIDR | Options |
+----------------+---------+
| 192.168.0.0/16 | |
+----------------+---------+
# calicoctl pool add 172.16.0.0/16
# calicoctl pool remove 192.168.0.0/16
# calicoctl pool show --ipv4
+---------------+---------+
| IPv4 CIDR | Options |
+---------------+---------+
| 172.16.0.0/16 | |
+---------------+---------+
kube-apiserver
は手っ取り早く --insecure-bind-address=0.0.0.0
にして Admission Control も外します。
kube-scheduler
と kube-controller-manager
はデフォルトで http://127.0.0.1:8080
に向いているのでそのままいきます。
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.0.100.0/24"
KUBE_ADMISSION_CONTROL=""
KUBE_API_ARGS=""
# systemctl enable kube-apiserver
# systemctl enable kube-controller-manager
# systemctl enable kube-scheduler
# systemctl start kube-apiserver
# systemctl start kube-controller-manager
# systemctl start kube-scheduler
私の環境では /var/run/kubernetes
が作成されておらず、kube-apiserver
の自己署名証明書も作られませんでした。
一度 OS を再起動してみると、今度は作成され 6443 が Listen されていました。
# systemctl reboot
# ss -nltp | grep 6443
LISTEN 0 128 :::6443 :::* users:(("kube-apiserver",pid=1637,fd=13))
Node 構築
バージョンは以下の通りでした
- docker-1.9.1-25.el7.centos.x86_64
- kubernetes-node-1.2.0-0.9.alpha1.gitb57e8bd.el7.x86_64
- calico/node:v0.19.0
# yum install docker kubernetes-node
Calico
をインストールする部分は Master
とほぼ同じで、IPアドレス指定だけ変更します。
OPTIONS=
DOCKER_CERT_PATH=/etc/docker
DOCKER_STORAGE_OPTIONS='-s overlay'
# systemctl enable docker
# systemctl start docker
# mkdir -p /opt/calico/bin
# wget https://github.com/projectcalico/calico-containers/releases/download/v0.19.0/calicoctl
# chmod +x calicoctl
# mv calicoctl /opt/calico/bin
## calico のパスを通しておく
# vi ~/.bash_profile
PATH=$PATH:$HOME/bin:/opt/calico/bin
# . ~/.bash_profile
## etcd は Master のアドレスを指定する
## Node 2号機 (kubenode02) は --ip=192.168.100.2 にする
# ETCD_AUTHORITY=192.168.100.10:2379 calicoctl node --ip=192.168.100.1
Pulling Docker image calico/node:v0.19.0
Running Docker container with the following command:
docker run -d --restart=always --net=host --privileged --name=calico-node -e HOSTNAME=kubenode01 -e IP=192.168.100.1 -e IP6= -e CALICO_NETWORKING=true -e AS= -e NO_DEFAULT_POOLS= -e ETCD_AUTHORITY=192.168.100.10:2379 -e ETCD_SCHEME=http -v /var/log/calico:/var/log/calico -v /lib/modules:/lib/modules -v /var/run/calico:/var/run/calico calico/node:v0.19.0
Calico node is running with id: bed0fa13d54064786450a90b5a1a8d1d2d98a80434367f756ad35bf245129854
Waiting for successful startup
Calico node started successfully
Node
2台が追加されたことを確認します。
この時点ではまだ Pod
は存在しないので経路情報はアドバタイズされません。
## kubenode01,02 から確認する場合は etcd の場所を指定する
# ETCD_AUTHORITY=192.168.100.10:2379 calicoctl node show
+------------+----------------+-----------+-------------------+--------------+--------------+
| Hostname | Bird IPv4 | Bird IPv6 | AS Num | BGP Peers v4 | BGP Peers v6 |
+------------+----------------+-----------+-------------------+--------------+--------------+
| kubemaster | 192.168.100.10 | | 64511 (inherited) | | |
| kubenode01 | 192.168.100.1 | | 64511 (inherited) | | |
| kubenode02 | 192.168.100.2 | | 64511 (inherited) | | |
+------------+----------------+-----------+-------------------+--------------+--------------+
# ETCD_AUTHORITY=192.168.100.10:2379 calicoctl status
calico-node container is running. Status: Up 5 minutes
Running felix version 1.4.0rc1
IPv4 BGP status
IP: 192.168.100.1 AS Number: 64511 (inherited)
+----------------+-------------------+-------+----------+-------------+
| Peer address | Peer type | State | Since | Info |
+----------------+-------------------+-------+----------+-------------+
| 192.168.100.10 | node-to-node mesh | up | 20:59:02 | Established |
| 192.168.100.2 | node-to-node mesh | up | 20:59:09 | Established |
+----------------+-------------------+-------+----------+-------------+
IPv6 BGP status
No IPv6 address configured.
それでは Calico
を使用するように kubelet
をセットアップします。
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://192.168.100.10:8080"
KUBELET_ADDRESS="--address=0.0.0.0"
KUBELET_HOSTNAME=
KUBELET_API_SERVER="--api-servers=http://192.168.100.10:8080"
KUBELET_ARGS="--network-plugin=cni --network-plugin-dir=/etc/cni/net.d"
kube-proxy
は proxy mode を iptables にします。
KUBE_PROXY_ARGS="--proxy-mode=iptables"
# mkdir -p /etc/cni/net.d
# cat >/etc/cni/net.d/10-calico.conf <<EOF
{
"name": "calico-k8s-network",
"type": "calico",
"etcd_authority": "192.168.100.10:2379",
"log_level": "info",
"ipam": {
"type": "calico-ipam"
}
}
EOF
# wget https://github.com/projectcalico/calico-cni/releases/download/v1.3.0/calico
# chmod +x calico
# mv calico /opt/calico/bin
# systemctl enable kube-proxy
# systemctl enable kubelet
# systemctl start kube-proxy
# systemctl start kubelet
問題なく進んでいれば、Master
で 2台の Node
が登録されている様子が確認できます。
# kubectl get node
NAME LABELS STATUS AGE
kubenode01 kubernetes.io/hostname=kubenode01 Ready 18m
kubenode02 kubernetes.io/hostname=kubenode02 Ready 16m
クラスタ内の通信試験
まずはクラスタ内で Pod
, Service
を作成して ClusterIP
宛てに通信できることを確認してみます。
適当に Nginx の Replication Controller
を作ってみます。
kubectl
の操作は Master
で行います。
apiVersion: v1
kind: ReplicationController
metadata:
name: test01
spec:
replicas: 2
template:
metadata:
labels:
test: test01
spec:
containers:
- name: nginx-test01
image: nginx
ports:
- containerPort: 80
# kubectl create -f nginx-rc.yaml
# kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS AGE
test01 nginx-test01 nginx test=test01 2 5m
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE NODE
test01-chw8x 1/1 Running 0 5m kubenode01
test01-qeftr 1/1 Running 0 5m kubenode02
# kubectl get pod -o json | jq .items[].status.podIP
"172.16.0.64"
"172.16.0.0"
さて、Replication Controller
を通して Pod
がそれぞれの Node
に作成されました。
この時点で各 Pod
には /32 の IPアドレスがアサインされ、そのアドレスが BGP でアドバタイズされています。
Calico
は 1号機・2号機の Pod
にそれぞれ 172.16.0.64/32
172.16.0.0/32
をアサインし、1号機・2号機で使うアドレスレンジとしてそれぞれ 172.16.0.64/26
172.16.0.0/26
のブロックをアサインしたようです。
172.17.0.0/16
は消しておけばよかったですが、Docker がデフォルトで作成したものです。
# ip r
default via 192.168.100.254 dev eno16777984
172.16.0.0/26 via 192.168.100.2 dev eno16777984 proto bird
172.16.0.64/26 via 192.168.100.1 dev eno16777984 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.100.0/24 dev eno16777984 proto kernel scope link src 192.168.100.10
# ip r
default via 192.168.100.254 dev eno16777984
172.16.0.0/26 via 192.168.100.2 dev eno16777984 proto bird
172.16.0.64 dev calieca82516130 scope link
blackhole 172.16.0.64/26 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.100.0/24 dev eno16777984 proto kernel scope link src 192.168.100.1
# ip r
default via 192.168.100.254 dev eno16777984
172.16.0.0 dev caliecb4366c130 scope link
blackhole 172.16.0.0/26 proto bird
172.16.0.64/26 via 192.168.100.1 dev eno16777984 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.100.0/24 dev eno16777984 proto kernel scope link src 192.168.100.2
経路があるので Pod
の IP アドレスに対しては Master
からでも Node
からでも通信可能です。
# curl -s 172.16.0.64 | grep h1
<h1>Welcome to nginx!</h1>
# curl -s 172.16.0.0 | grep h1
<h1>Welcome to nginx!</h1>
Service
も作ってみます。
apiVersion: v1
kind: Service
metadata:
name: test01
spec:
selector:
test: test01
clusterIP: 10.0.100.80
ports:
- name: http
port: 80
protocol: TCP
# kubectl create -f nginx-svc.yaml
# kubectl get svc test01
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE
test01 10.0.100.80 <none> 80/TCP test=test01 31s
# kubectl get ep test01
NAME ENDPOINTS AGE
test01 172.16.0.0:80,172.16.0.64:80 41s
この ClusterIP
10.0.100.80
は、kube-proxy
がいない Master
からはアクセスできませんが、Node
や Pod
からはアクセス可能です。
# uname -n; curl -s 10.0.100.80 | grep h1
kubenode01
<h1>Welcome to nginx!</h1>
## nginx イメージに curl は無いので nsenter を使って Pod 内からアクセスできることを確認
## Pod はまだ Node に 1つずつしかないので単純に pgrep して pause と同じ Namespace に入る
# uname -n
kubenode01
# nsenter -t $(pgrep pause) -u -n
# ip -4 a show dev eth0
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link-netnsid 0
inet 172.16.0.64/32 scope global eth0
valid_lft forever preferred_lft forever
# uname -n; curl -s 10.0.100.80 | grep h1
test01-chw8x
<h1>Welcome to nginx!</h1>
# uname -n
kubenode02
# nsenter -t $(pgrep pause) -u -n
# ip -4 a show dev eth0
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link-netnsid 0
inet 172.16.0.0/32 scope global eth0
valid_lft forever preferred_lft forever
# uname -n; curl -s 10.0.100.80 | grep h1
test01-qeftr
<h1>Welcome to nginx!</h1>
ルータ兼ロードバランサ (kubegw) 構築
いよいよ、外部からアクセスさせるためのポイントになる ルータ兼ロードバランサ
を構築します。
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/routing.conf
# systemctl restart systemd-sysctl
Docker
と kube-proxy
が必要なのでインストールします。バージョンは Node
と同じです。
Docker
は calico/node
を動作させるために使用します。
# yum install docker kubernetes-node
OPTIONS=
DOCKER_CERT_PATH=/etc/docker
DOCKER_STORAGE_OPTIONS='-s overlay'
# systemctl enable docker
# systemctl start docker
# mkdir -p /opt/calico/bin
# wget https://github.com/projectcalico/calico-containers/releases/download/v0.19.0/calicoctl
# chmod +x calicoctl
# mv calicoctl /opt/calico/bin
## calico のパスを通しておく
# vi ~/.bash_profile
PATH=$PATH:$HOME/bin:/opt/calico/bin
# . ~/.bash_profile
# ETCD_AUTHORITY=192.168.100.10:2379 calicoctl node --ip=192.168.100.254
Pulling Docker image calico/node:v0.19.0
Running Docker container with the following command:
docker run -d --restart=always --net=host --privileged --name=calico-node -e HOSTNAME=kubegw -e IP=192.168.100.254 -e IP6= -e CALICO_NETWORKING=true -e AS= -e NO_DEFAULT_POOLS= -e ETCD_AUTHORITY=192.168.100.10:2379 -e ETCD_SCHEME=http -v /var/log/calico:/var/log/calico -v /lib/modules:/lib/modules -v /var/run/calico:/var/run/calico calico/node:v0.19.0
Calico node is running with id: 37955df4f7f99b59f4aec79ae7d8c5564d1ef3ee25af203853ca715c8d2c3212
Waiting for successful startup
Calico node started successfully
## 状態確認
# ETCD_AUTHORITY=192.168.100.10:2379 calicoctl status
calico-node container is running. Status: Up 18 seconds
Running felix version 1.4.0rc1
IPv4 BGP status
IP: 192.168.100.254 AS Number: 64511 (inherited)
+----------------+-------------------+-------+----------+-------------+
| Peer address | Peer type | State | Since | Info |
+----------------+-------------------+-------+----------+-------------+
| 192.168.100.10 | node-to-node mesh | up | 22:44:49 | Established |
| 192.168.100.1 | node-to-node mesh | up | 22:44:48 | Established |
| 192.168.100.2 | node-to-node mesh | up | 22:44:48 | Established |
+----------------+-------------------+-------+----------+-------------+
# ip r
172.16.0.0/26 via 192.168.100.2 dev eno33557248 proto bird
172.16.0.64/26 via 192.168.100.1 dev eno33557248 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.10.0/24 dev eno16777984 proto kernel scope link src 192.168.10.100
192.168.100.0/24 dev eno33557248 proto kernel scope link src 192.168.100.254
Calico
が動作することで Pod
への経路が作られます。
続いて kube-proxy
を設定・起動します。
KUBE_LOGTOSTDERR="--logtostderr=true"
KUBE_LOG_LEVEL="--v=0"
KUBE_ALLOW_PRIV="--allow-privileged=false"
KUBE_MASTER="--master=http://192.168.100.10:8080"
KUBE_PROXY_ARGS="--proxy-mode=iptables"
# systemctl enable kube-proxy
# systemctl start kube-proxy
kube-proxy
が動作することで iptables のエントリが作成され、クラスタの外からも ルータ兼ロードバランサ
を利用すれば ClusterIP
宛てにアクセスできるようになります。
# iptables -t nat -nL PREROUTING
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
felix-PREROUTING all -- 0.0.0.0/0 0.0.0.0/0
KUBE-SERVICES all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
# iptables -t nat -nL POSTROUTING
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
felix-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service traffic requiring SNAT */ mark match 0x4d415351
# iptables -t nat -nL KUBE-SERVICES
Chain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-BP3QRF6W53YFYJDU tcp -- 0.0.0.0/0 10.0.100.80 /* default/test01:http cluster IP */ tcp dpt:80
KUBE-SVC-NPX46M4PTMTKRN6Y tcp -- 0.0.0.0/0 10.0.100.1 /* default/kubernetes:https cluster IP */ tcp dpt:443
KUBE-NODEPORTS all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL
# iptables -t nat -nL KUBE-SVC-BP3QRF6W53YFYJDU
Chain KUBE-SVC-BP3QRF6W53YFYJDU (1 references)
target prot opt source destination
KUBE-SEP-M6FWVBZWU3TAHUXK all -- 0.0.0.0/0 0.0.0.0/0 /* default/test01:http */ statistic mode random probability 0.50000000000
KUBE-SEP-3VEHY3E2FGHEBZJY all -- 0.0.0.0/0 0.0.0.0/0 /* default/test01:http */
# iptables -t nat -nL KUBE-SEP-M6FWVBZWU3TAHUXK
Chain KUBE-SEP-M6FWVBZWU3TAHUXK (1 references)
target prot opt source destination
MARK all -- 172.16.0.0 0.0.0.0/0 /* default/test01:http */ MARK set 0x4d415351
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/test01:http */ tcp to:172.16.0.0:80
# iptables -t nat -nL KUBE-SEP-3VEHY3E2FGHEBZJY
Chain KUBE-SEP-3VEHY3E2FGHEBZJY (1 references)
target prot opt source destination
MARK all -- 172.16.0.64 0.0.0.0/0 /* default/test01:http */ MARK set 0x4d415351
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/test01:http */ tcp to:172.16.0.64:80
クラスタの外にいる Client
から確認してみましょう。
このホストで ClusterIP
である 10.0.100.0/24
は ルータ兼ロードバランサ
に経路を向けておきます。
また、PodIP
として使用される 172.16.0.0/16
の経路も向ければ Pod
とも通信できます。(PodIP
と通信するだけなら kube-proxy
無しでも可能です)
# ip r add 10.0.100.0/24 via 192.168.10.100
# ip r add 172.16.0.0/16 via 192.168.10.100
# curl -s 10.0.100.80 | grep h1
<h1>Welcome to nginx!</h1>
# curl -s 172.16.0.64 | grep h1
<h1>Welcome to nginx!</h1>
# curl -s 172.16.0.0 | grep h1
<h1>Welcome to nginx!</h1>
無事、通信できました。実際の環境で使うなら ルータ兼ロードバランサ
は冗長化する必要があるでしょう。
IPアドレスの変遷
Client
から PublicIP (10.0.100.80)
に通信する際に IP アドレスは以下のように変化します。
タイミング | Src Address | Dest Address |
---|---|---|
Client から出る時点 | 192.168.10.1 | 10.0.100.80 |
ルータ兼ロードバランサ 通過後 (往路) | 192.168.10.1 | 172.16.0.64 または 172.16.0.0 |
Server (Pod) から戻る時点 | 172.16.0.64 または 172.16.0.0 |
192.168.10.1 |
ルータ兼ロードバランサ 通過後 (復路) | 10.0.100.80 | 192.168.10.1 |
ClusterIP
からどちらの Pod
宛てに DNAT されるかは、iptables の statistics
モジュールでランダムに (各 Pod
の確率は等しい) 決定されます。
パケット毎に宛先が選択されるのではなく、connection tracking によって同じ TCP コネクションの通信なら同じ Pod
宛てに転送されます。