前書き
Kubernetesは、サーバーノードのクラスター全体でコンテナー化されたアプリケーションを管理できるコンテナーオーケストレーションシステムです。 クラスタ内のすべてのコンテナ間のネットワーク接続を維持するには、高度なネットワーク技術が必要です。 この記事では、このネットワーク設定を検査するためのいくつかのツールとテクニックについて簡単に説明します。
これらのツールは、接続の問題をデバッグしている場合、ネットワークスループットの問題を調査している場合、またはKubernetesを探索してその動作を学習する場合に役立ちます。
Kubernetes全般について詳しく知りたい場合は、ガイドAn Introduction to Kubernetesで基本を説明しています。 Kubernetesのネットワーク固有の概要については、Kubernetes Networking Under the Hoodをお読みください。
入門
このチュートリアルでは、kubectl
がローカルにインストールされ、クラスターに接続するように構成されたKubernetesクラスターがあることを前提としています。
次のセクションには、Kubernetesノードで実行することを目的とした多くのコマンドが含まれています。 次のようになります。
echo 'this is a node command'
ローカルマシンで実行するコマンドは、次のように表示されます。
echo 'this is a local command'
[.note]#Note:このチュートリアルのほとんどのコマンドは、rootユーザーとして実行する必要があります。 代わりに、Kubernetesノードでsudo対応ユーザーを使用する場合は、sudo
を追加して、必要に応じてコマンドを実行してください。
#
ポッドのクラスターIPを見つける
KubernetesポッドのクラスターIPアドレスを見つけるには、ローカルマシンでオプション-o wide
を指定してkubectl get pod
コマンドを使用します。 このオプションには、ポッドが存在するノードやポッドのクラスターIPなどの詳細情報が一覧表示されます。
kubectl get pod -o wide
OutputNAME READY STATUS RESTARTS AGE IP NODE
hello-world-5b446dd74b-7c7pk 1/1 Running 0 22m 10.244.18.4 node-one
hello-world-5b446dd74b-pxtzt 1/1 Running 0 22m 10.244.3.4 node-two
IP列には、各ポッドの内部クラスターIPアドレスが含まれます。
探しているポッドが表示されない場合は、適切なネームスペースにいることを確認してください。 フラグ--all-namespaces
を追加することにより、すべての名前空間のすべてのポッドを一覧表示できます。
サービスのIPを見つける
kubectl
を使用してサービスIPを見つけることもできます。 この場合、すべてのネームスペースのすべてのサービスをリストします。
kubectl get service --all-namespaces
OutputNAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.32.0.1 443/TCP 6d
kube-system csi-attacher-doplugin ClusterIP 10.32.159.128 12345/TCP 6d
kube-system csi-provisioner-doplugin ClusterIP 10.32.61.61 12345/TCP 6d
kube-system kube-dns ClusterIP 10.32.0.10 53/UDP,53/TCP 6d
kube-system kubernetes-dashboard ClusterIP 10.32.226.209 443/TCP 6d
サービスIPは、CLUSTER-IP列にあります。
ポッドネットワーク名前空間の検索と入力
各Kubernetesポッドには、独自のネットワーク名前空間が割り当てられます。 ネットワーク名前空間(またはネット)は、ネットワークデバイス間の分離を提供するLinuxネットワークプリミティブです。
ポッドのネット内からコマンドを実行して、DNS解決または一般的なネットワーク接続を確認すると便利です。 そのためには、まずポッド内のコンテナの1つのプロセスIDを検索する必要があります。 Dockerの場合、一連の2つのコマンドを使用してこれを実行できます。 最初に、ノードで実行されているコンテナをリストします。
docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
173ee46a3926 gcr.io/google-samples/node-hello "/bin/sh -c 'node se…" 9 days ago Up 9 days k8s_hello-world_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
11ad51cb72df k8s.gcr.io/pause-amd64:3.1 "/pause" 9 days ago Up 9 days k8s_POD_hello-world-5b446dd74b-pxtzt_default_386a9073-7e35-11e8-8a3d-bae97d2c1afd_0
. . .
関心のあるポッド内の任意のコンテナのcontainer IDまたはnameを見つけます。 上記の出力では、2つのコンテナーを示しています。
-
最初のコンテナーは、
hello-world
ポッドで実行されているhello-world
アプリです。 -
2つ目は、
hello-world
ポッドで実行されているpauseコンテナです。 このコンテナは、ポッドのネットワーク名前空間を保持するためだけに存在します
いずれかのコンテナのプロセスIDを取得するには、コンテナIDまたは名前をメモし、次のdocker
コマンドで使用します。
docker inspect --format '{{ .State.Pid }}' container-id-or-name
Output14552
プロセスID(またはPID)が出力されます。 これで、nsenter
プログラムを使用して、そのプロセスのネットワーク名前空間でコマンドを実行できます。
nsenter -t your-container-pid -n ip addr
必ず独自のPIDを使用し、ip addr
をポッドのネットワーク名前空間内で実行するコマンドに置き換えてください。
[.note]#Note:docker exec
のようなものを使用するのと比較して、nsenter
を使用してポッドの名前空間でコマンドを実行する利点の1つは、で使用可能なすべてのコマンドにアクセスできることです。コンテナにインストールされる通常限定されたコマンドセットの代わりにノード。
#
ポッドの仮想イーサネットインターフェイスを見つける
各ポッドのネットワーク名前空間は、仮想イーサネットパイプを介してノードのルートネットと通信します。 ノード側では、このパイプは通常veth
で始まり、veth77f2275
やveth01
などの一意の識別子で終わるデバイスとして表示されます。 ポッド内では、このパイプはeth0
として表示されます。
どのveth
デバイスが特定のポッドとペアになっているのかを関連付けると便利です。 そのためには、ノード上のすべてのネットワークデバイスをリストし、次にポッドのネットワーク名前空間にあるデバイスをリストします。 その後、2つのリスト間でデバイス番号を関連付けて接続を確立できます。
まず、nsenter
を使用して、ポッドのネットワーク名前空間でip addr
を実行します。 これを行う方法の詳細については、前のセクションFinding and Entering Pod Network Namespaces
を参照してください。
nsenter -t your-container-pid -n ip addr
Output1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
10: eth0@if11: mtu 1450 qdisc noqueue state UP group default
link/ether 02:42:0a:f4:03:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.3.4/24 brd 10.244.3.255 scope global eth0
valid_lft forever preferred_lft forever
このコマンドは、ポッドのインターフェースのリストを出力します。 出力例のeth0@
の後のif11
番号に注意してください。 これは、このポッドのeth0
がノードの11番目のインターフェースにリンクされていることを意味します。 次に、ノードのデフォルトの名前空間でip addr
を実行して、そのインターフェースを一覧表示します。
ip addr
Output1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
. . .
7: veth77f2275@if6: mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether 26:05:99:58:0d:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::2405:99ff:fe58:db9/64 scope link
valid_lft forever preferred_lft forever
9: vethd36cef3@if8: mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether ae:05:21:a2:9a:2b brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::ac05:21ff:fea2:9a2b/64 scope link
valid_lft forever preferred_lft forever
11: veth4f7342d@if10: mtu 1450 qdisc noqueue master docker0 state UP group default
link/ether e6:4d:7b:6f:56:4c brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::e44d:7bff:fe6f:564c/64 scope link
valid_lft forever preferred_lft forever
この出力例では、11番目のインターフェイスはveth4f7342d
です。 これは、調査中のポッドへの仮想イーサネットパイプです。
Conntrack接続追跡の検査
バージョン1.11より前では、Kubernetesはiptables NATとconntrackカーネルモジュールを使用して接続を追跡していました。 現在追跡されているすべての接続を一覧表示するには、conntrack
コマンドを使用します。
conntrack -L
新しい接続を継続的に監視するには、-E
フラグを使用します。
conntrack -E
特定の宛先アドレスへのconntrack-tracked接続を一覧表示するには、-d
フラグを使用します。
conntrack -L -d 10.32.0.1
ノードにサービスへの信頼できる接続を確立するのに問題がある場合、接続追跡テーブルがいっぱいで、新しい接続がドロップされている可能性があります。 その場合、システムログに次のようなメッセージが表示される場合があります。
/var/log/syslog
Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet.
追跡する接続の最大数のsysctl設定があります。 次のコマンドを使用して、現在の値をリストできます。
sysctl net.netfilter.nf_conntrack_max
Outputnet.netfilter.nf_conntrack_max = 131072
新しい値を設定するには、-w
フラグを使用します。
sysctl -w net.netfilter.nf_conntrack_max=198000
この設定を永続的にするには、sysctl.conf
ファイルに追加します。
/etc/sysctl.conf
. . .
net.ipv4.netfilter.ip_conntrack_max = 198000
Iptablesルールの検査
バージョン1.11より前では、Kubernetesはiptables NATを使用して、仮想IP変換とサービスIPの負荷分散を実装していました。
ノード上のすべてのiptablesルールをダンプするには、iptables-save
コマンドを使用します。
iptables-save
出力が長くなる可能性があるため、ルールをより簡単に確認するために、ファイル(iptables-save > output.txt
)またはページャー(iptables-save | less
)にパイプすることをお勧めします。
KubernetesサービスのNATルールのみを一覧表示するには、iptables
コマンドと-L
フラグを使用して、正しいチェーンを指定します。
iptables -t nat -L KUBE-SERVICES
OutputChain KUBE-SERVICES (2 references)
target prot opt source destination
KUBE-SVC-TCOU7JCQXEZGVUNU udp -- anywhere 10.32.0.10 /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain
KUBE-SVC-ERIFXISQEP7F7OF4 tcp -- anywhere 10.32.0.10 /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:domain
KUBE-SVC-XGLOHA7QRQ3V22RZ tcp -- anywhere 10.32.226.209 /* kube-system/kubernetes-dashboard: cluster IP */ tcp dpt:https
. . .
クラスターDNSのクエリ
クラスターのDNS解決をデバッグする1つの方法は、必要なすべてのツールを含むデバッグコンテナーをデプロイし、kubectl
を使用してnslookup
を実行することです。 これはthe official Kubernetes documentationで記述されます。
クラスタDNSをクエリする別の方法は、ノードからdig
とnsenter
を使用することです。 dig
がインストールされていない場合は、DebianベースのLinuxディストリビューションにapt
とともにインストールできます。
apt install dnsutils
まず、kube-dnsサービスのクラスターIPを見つけます。
kubectl get service -n kube-system kube-dns
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.32.0.10 53/UDP,53/TCP 15d
クラスターIPは上記で強調表示されています。 次に、nsenter
を使用して、コンテナの名前空間でdig
を実行します。 詳細については、セクションFinding and Entering Pod Network Namespacesを参照してください。
nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10
このdig
コマンドは、サービスの完全ドメイン名service-name.namespace.svc.cluster.localを検索し、クラスターDNSサービスIP(@10.32.0.10
)のIPを指定します。
IPVSの詳細を見る
Kubernetes 1.11以降、kube-proxy
は仮想サービスIPからポッドIPへの変換を処理するようにIPVSを設定できます。 ipvsadm
を使用してIPの変換テーブルを一覧表示できます。
ipvsadm -Ln
OutputIP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 100.64.0.1:443 rr
-> 178.128.226.86:443 Masq 1 0 0
TCP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
UDP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
単一のサービスIPを表示するには、-t
オプションを使用して、目的のIPを指定します。
ipvsadm -Ln -t 100.64.0.10:53
OutputProt LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 100.64.0.10:53 rr
-> 100.96.1.3:53 Masq 1 0 0
-> 100.96.1.4:53 Masq 1 0 0
結論
この記事では、Kubernetesクラスターのネットワークの詳細を調査および検査するためのいくつかのコマンドとテクニックを確認しました。 Kubernetesの詳細については、our Kubernetes tutorials tagとthe official Kubernetes documentationをご覧ください。