LinuCエヴァンジェリストの鯨井貴博@opensourcetechです。
はじめに
今回は、kubernetesでPod(コンテナ)へのアクセスってどのような分散がされるのか確認してみます。
具体的には、こんな環境で実施します。

環境構築
まず、以下の記事を参考に"Deployment1"と"Deployment2"を作成します。
nginxコンテナ(Pod)のコンテンツ(index.html)をConfigMapで提供・更新する(kubernetes)
https://www.opensourcetech.tokyo/?page=1679832639
kubeuser@master01:~/variable_deploy$ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE nginx 2/2 2 2 3d nginx2 1/1 1 1 3d kubeuser@master01:~/variable_deploy$ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-6cbc9bb4f5-jm8mr 1/1 Running 0 2d8h nginx-6cbc9bb4f5-pfhfz 1/1 Running 0 3d nginx2-f96cfc57b-vnsfm 1/1 Running 0 3d
以下に使ったyamlファイルやindex.htmlを格納しています。
https://github.com/kujiraitakahiro/kubernetes/tree/master/kanarya_release
そして、Serviceを使ってクライアントがアクセスするIPアドレス&ポート番号を作成します。
kubeuser@master01:~/variable_deploy$ kubectl expose deployment nginx --port=80 --type=LoadBalancer kubeuser@master01:~/variable_deploy$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 11d nginx LoadBalancer 10.1.55.116 192.168.1.51 80:30267/TCP 3d
負荷分散状況の測定
まず、クライアント(Webブラウザ)からアクセスできるかの確認。
大丈夫ですね!
※F5(再読み込み)を実施すると、Version1/Version2いずれかのコンテンツが表示されます。


では、分散状況のチェック。
Apache Benchを使って1,000アクセスしてみます。
※今回は、windowsでXAMPPを使っています。
c:\xampp\apache\bin>ab.exe -n 1000 -c 1000 http://192.168.1.51/
This is ApacheBench, Version 2.3 <$Revision: 1901567 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.1.51 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.23.0
Server Hostname: 192.168.1.51
Server Port: 80
Document Path: /
Document Length: 256 bytes
Concurrency Level: 1000
Time taken for tests: 3.817 seconds
Complete requests: 1000
Failed requests: 325
(Connect: 0, Receive: 0, Length: 325, Exceptions: 0)
Total transferred: 489325 bytes
HTML transferred: 256325 bytes
Requests per second: 261.97 [#/sec] (mean)
Time per request: 3817.165 [ms] (mean)
Time per request: 3.817 [ms] (mean, across all concurrent requests)
Transfer rate: 125.19 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 3 2.5 3 44
Processing: 217 1931 968.8 1935 3618
Waiting: 5 1831 1015.0 1841 3588
Total: 222 1934 968.7 1938 3620
Percentage of the requests served within a certain time (ms)
50% 1938
66% 2456
75% 2723
80% 2927
90% 3290
95% 3452
98% 3553
99% 3582
100% 3620 (longest request)
アクセス状況はwiresharkを使います。
1,000アクセスに対して、200OKが返されています。

では、そのうちVersion2のコンテンツはどれくらい表示されるのか確認します。
すると、325回であることが分かります。

「均等にならないものなの?」という疑問が沸いたので、何度か試してみました。
結果は、339回・306回・353回・ 342回。
きっちりではないですが、だいたい均等に分散していま
https://kubernetes.io/ja/docs/concepts/services-networking/service/#proxy-mode-iptablesすね。
おわりに
実施する前はきれいに分散するのかなと思っていたのですが、
実際にはだいたい均等でした。
なんとなくリソースの負荷見ながら(least-connection) 均等分散(round-robin)しているのかなというように見えるのですが、合ってるんだろうか。。。
もうちょっと調べてみよう。
追記
Serviceのトラフィック分散について、追記。
kube-proxyが関連しており、ipvsモード・iptablesモードがあるが、
デフォルトは後者(iptablesモード)。
https://kubernetes.io/ja/docs/concepts/services-networking/service/#proxy-mode-iptables
kube-proxyの設定(configmap)のmode ""のデフォルトがiptablesモード、
ipvsとすればipvsモードとなる。
また、ipvsモードだと、scheduler:でrr(ラウンドロビン)など選択可能。

kubeuser@master01:~$ kubectl get cm -n kube-system
NAME DATA AGE
calico-config 4 12d
coredns 1 12d
extension-apiserver-authentication 6 12d
kube-proxy 2 12d
kube-root-ca.crt 1 12d
kubeadm-config 1 12d
kubelet-config 1 12d
kubeuser@master01:~$ kubectl get cm -n kube-system kube-proxy -o yaml
apiVersion: v1
data:
config.conf: |-
apiVersion: kubeproxy.config.k8s.io/v1alpha1
bindAddress: 0.0.0.0
bindAddressHardFail: false
clientConnection:
acceptContentTypes: ""
burst: 0
contentType: ""
kubeconfig: /var/lib/kube-proxy/kubeconfig.conf
qps: 0
clusterCIDR: 10.0.0.0/16,fd12:b5e0:383e::/64
configSyncPeriod: 0s
conntrack:
maxPerCore: null
min: null
tcpCloseWaitTimeout: null
tcpEstablishedTimeout: null
detectLocal:
bridgeInterface: ""
interfaceNamePrefix: ""
detectLocalMode: ""
enableProfiling: false
healthzBindAddress: ""
hostnameOverride: ""
iptables:
localhostNodePorts: null
masqueradeAll: false
masqueradeBit: null
minSyncPeriod: 0s
syncPeriod: 0s
ipvs:
excludeCIDRs: null
minSyncPeriod: 0s
scheduler: ""
strictARP: false
syncPeriod: 0s
tcpFinTimeout: 0s
tcpTimeout: 0s
udpTimeout: 0s
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: ""
nodePortAddresses: null
oomScoreAdj: null
portRange: ""
showHiddenMetricsForVersion: ""
winkernel:
enableDSR: false
forwardHealthCheckVip: false
networkName: ""
rootHnsEndpointName: ""
sourceVip: ""
kubeconfig.conf: |-
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
server: https://master01:6443
name: default
contexts:
- context:
cluster: default
namespace: default
user: default
name: default
current-context: default
users:
- name: default
user:
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
kind: ConfigMap
metadata:
annotations:
kubeadm.kubernetes.io/component-config.hash: sha256:e1193cefc1046d8fe6dbffed62d04e546bd4142781cc28f632adfe72f499e4be
creationTimestamp: "2023-03-14T13:45:56Z"
labels:
app: kube-proxy
name: kube-proxy
namespace: kube-system
resourceVersion: "271"
uid: 687e9c38-9699-46dc-9fbb-5de6bf270781
kube-proxyの設定について
https://kubernetes.io/docs/reference/config-api/kube-proxy-config.v1alpha1/#kubeproxy-config-k8s-io-v1alpha1-ProxyMode
ipvsモードのDeep Dive
https://kubernetes.io/docs/reference/config-api/kube-proxy-config.v1alpha1/#kubeproxy-config-k8s-io-v1alpha1-ProxyMode