Pod-to-Pod Communication / Kubernetes

クラウドサービスがあたりまえになる今日このごろ。Kubernetesを知らないではすまされない? という空気を感じましたので、Pod間通信を試してみました。

/usr/local/bin/kubectl -> /mnt/wsl/docker-desktop/cli-tools/usr/local/bin/kubectl

AzureはBizSparkのライセンスがあるときしかできず、AWSは大抵仕事としてやっているため(あそびでは使えず)、クラウドはブログの記事にしにくいという先入観からKubernetesとは縁がありませんでしたが、Dockerがあれば簡単にできることを知りました。
しかもWindowsではDockerのKubernetesを有効にすると、WSLにマウントして/usr/local/binにシンボリックリンクをはってくれるためとても便利です。

今回の目的は、httpdとnginxのpodを作り、相互の通信の確認と、Windowsのブラウザからも接続を確認しました。(どういったホスト名、ポート番号が使われているのか)

httpd.yml

コンテナの中にcurlがなかったため、busyboxのイメージを記述しました。このためPodが二つできてしまいましたので、記述の仕方がおかしいかもしれません。

nginx.yml

nodePortは30000以上でないとだめのようです。

$ kubectl apply -f httpd.yml
service/httpd-serv created
deployment.apps/httpd-deploy created
pod/httpd-pod created
$ kubectl apply -f nginx.yml
service/nginx-serv created
deployment.apps/nginx-deploy created
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
httpd-deploy-8575cc69c7-b82t5 1/1 Running 0 27s 10.1.0.54 docker-desktop
httpd-pod 1/1 Running 0 27s 10.1.0.53 docker-desktop
nginx-deploy-7fd96bc599-sv5rk 1/1 Running 0 17s 10.1.0.55 docker-desktop
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
httpd-serv NodePort 10.105.215.199 none 8090:30090/TCP 41s
kubernetes ClusterIP 10.96.0.1 none 443/TCP 155m
nginx-serv NodePort 10.101.189.145 none 8080:30080/TCP 31s
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
httpd-deploy 1/1 1 1 48s
nginx-deploy 1/1 1 1 38s

コンテナの定義の仕方とか扱い方は、Dockerとかわらないですね。
podの中に入ってみます。

$ kubectl exec -it httpd-pod — sh
/home # curl http://nginx-serv:8080

/home # ping nginx-serv
PING nginx-serv (10.101.189.145): 56 data bytes
^C(レスポンスなし)

$ kubectl exec -it nginx-deploy-7fd96bc599-sv5rk — sh
/ # curl http://httpd-serv:8090

/ # ping httpd-serv
PING httpd-serv (10.105.215.199): 56 data bytes
^C(レスポンスなし)
/ # curl http://localhost
(上記nginx welcome画面と同じ)

おまけで、proxyを経由して、curlで操作するテストをしてみました。

$ kubectl proxy
Starting to serve on 127.0.0.1:8001

他のコンソールから

$ curl -X GET http://localhost:8001/api/v1/namespaces/default/pods
{
“kind”: “PodList”,
“apiVersion”: “v1”,
“metadata”: {
“resourceVersion”: “14048”
},
“items”: [
{
“metadata”: {
“name”: “httpd-deploy-8575cc69c7-b82t5”,
“generateName”: “httpd-deploy-8575cc69c7-“,
“namespace”: “default”,
“uid”: “aa13884d-0462-4479-908e-0b5d2768f7b8”,
“resourceVersion”: “12511”,
……

次に、WindowsからブラウザでWSLにアクセスしてみます。(WSLのlocahostと同じになるようにする設定が必要です)

Pod間通信では、http-servやnginx-servのように、IPアドレスを知らなくてもアクセスできるのがポイントなのでしよう。(pingはできませんてした)

参考)
「【Kubernetes】Podのコンテナでコマンド実行とシェル取得」
https://amateur-engineer-blog.com/kubernetes-container-exec/
「【入門】Kubernetes で nginx をたててデフォルトページを表示させる」
https://beyondjapan.com/blog/2022/09/start-kubernetes/
「【k8s】pod間通信をやってみた!」
https://qiita.com/higakin/items/494883ee563dd71c9989

また下記興味深い記述がありました。
「CNIのCiliumについて調べてみた」
https://blog.framinal.life/entry/2021/02/20/222728

ServiceMeshやマイクロサービスの登場によってPod間の通信(East-West通信)が増えた。通常アプリケーションの内部処理よりもNWのレイテンシの方が大きい。しかも1つのリクエストを捌くために複数のNodeの複数のPodに跨って通信をするようになれば、そのレイテンシは累積することになる。
k8sのおける通信はkube-proxyにて管理されるが、その裏はデフォルトでiptablesが用いられる。iptablesはPodの数が増えるとルールが比例して増えるため、計算量がどんどん多くなる。(計算量としてO(n)として表現される)

他でもクラウドサービスでのマイクロサービス間の通信のコストは高いものになっているという記事を見たことがあります。
カーネルモードで動かすというのを見て、以前組み込みLinux(VoIPルータ)でパケットの輻輳制御をカーネルでやったことを思い出しました。AWSのような設定でインフラを動かせる時代に、まだまだローレベルの開発は必要のようですね。

関連項目としてカーネルコードをPythonで送り込むBCCを下記で試しました。
「BPF Compiler Collection」
https://decode.red/blog/202302031560/
(CiliumでもeBPFが使われている)