service は pod の抽象化で、いわゆる仮想 IP (VIP) アドレスを安定して提供します。pod に変更があるとそれに付随する IP アドレスも変更される可能性がありますが、service は VIP を使うため pod 内で実行するコンテナにクライアントから確実に接続できます。VIP の virtual とはどういうことかというと、ネットワークインターフェイスに結びついた実際の IP アドレスではないということです。その目的は単純で、一つ以上の pod にトラフィックを転送することです。VIP と pod のマッピングを最新状態で維持するのは、kube-proxy の役目です。kube-proxy とは各 node 上で実行されるプロセスで、クラスタ内の新しい service について知るために API サーバーに問い合わせます。

RCservice によって管理された pod を作成してみましょう。

$ kubectl apply -f https://raw.githubusercontent.com/openshift-evangelists/kbe/master/specs/services/rc.yaml

$ kubectl apply -f https://raw.githubusercontent.com/openshift-evangelists/kbe/master/specs/services/svc.yaml

管理対象の pod が実行されているのを確認できます。

$ kubectl get pods -l app=sise
NAME           READY     STATUS    RESTARTS   AGE
rcsise-6nq3k   1/1       Running   0          57s

$ kubectl describe pod rcsise-6nq3k
Name:                   rcsise-6nq3k
Namespace:              default
Security Policy:        restricted
Node:                   localhost/192.168.99.100
Start Time:             Tue, 25 Apr 2017 14:47:45 +0100
Labels:                 app=sise
Status:                 Running
IP:                     172.17.0.3
Controllers:            ReplicationController/rcsise
Containers:
...

pod に割り当てられた IP 172.17.0.3 を通じて、クラスタ内部から pod に直接アクセスできます。

[cluster] $ curl 172.17.0.3:9876/info
{"host": "172.17.0.3:9876", "version": "0.5.0", "from": "172.17.0.1"}

ただし、これは前述のように pod に割り当てられた IP アドレスが変更される可能性があるためお勧めできません。そこで、作成した simpleservice に入ります。

$ kubectl get svc
NAME              CLUSTER-IP       EXTERNAL-IP   PORT(S)                   AGE
simpleservice     172.30.228.255   <none>        80/TCP                    5m

$ kubectl describe svc simpleservice
Name:                   simpleservice
Namespace:              default
Labels:                 <none>
Selector:               app=sise
Type:                   ClusterIP
IP:                     172.30.228.255
Port:                   <unset> 80/TCP
Endpoints:              172.17.0.3:9876
Session Affinity:       None
No events.

service は label を通じてトラフィックの転送先となる pod を追跡します。私たちの例で、label は app=sise です。

クラスタ内部から simpleservice にアクセスできます。

[cluster] $ curl 172.30.228.255:80/info
{"host": "172.30.228.255", "version": "0.5.0", "from": "10.0.2.15"}

どうやって VIP 172.30.228.255 のトラフィックを pod に転送させているのでしょうか。答えは IPtables です。IPtables は簡単にいうと Linux カーネルに特定の IP パッケージをどう処理するかを教える長大なリストです。

私たちの service に関するルールを見ます。(クラスタノード上で実行します)

[cluster] $ sudo iptables-save | grep simpleservice
-A KUBE-SEP-4SQFZS32ZVMTQEZV -s 172.17.0.3/32 -m comment --comment "default/simpleservice:" -j KUBE-MARK-MASQ
-A KUBE-SEP-4SQFZS32ZVMTQEZV -p tcp -m comment --comment "default/simpleservice:" -m tcp -j DNAT --to-destination 172.17.0.3:9876
-A KUBE-SERVICES -d 172.30.228.255/32 -p tcp -m comment --comment "default/simpleservice: cluster IP" -m tcp --dport 80 -j KUBE-SVC-EZC6WLOVQADP4IAW
-A KUBE-SVC-EZC6WLOVQADP4IAW -m comment --comment "default/simpleservice:" -j KUBE-SEP-4SQFZS32ZVMTQEZV

上を見ると、ありがたいことに kube-proxy がルーティングテーブルに 4 つのルールを追加したことがわかります。そのルールが述べていることをかいつまむと、172.30.228.255:80 に来る TCP トラフィックを 172.17.0.3:9876 に、つまり私たちの pod に転送しなさいということです。

次に、pod を管理している RC をスケールアップして、二番目の pod を追加しましょう。

$ kubectl scale --replicas=2 rc/rcsise
replicationcontroller "rcsise" scaled

$ kubectl get pods -l app=sise
NAME           READY     STATUS    RESTARTS   AGE
rcsise-6nq3k   1/1       Running   0          15m
rcsise-nv8zm   1/1       Running   0          5s

ルーティングテーブルの関連する部分をもう一度確認すると、IPtables のルールが追加されているのがわかります。

[cluster] $ sudo iptables-save | grep simpleservice
-A KUBE-SEP-4SQFZS32ZVMTQEZV -s 172.17.0.3/32 -m comment --comment "default/simpleservice:" -j KUBE-MARK-MASQ
-A KUBE-SEP-4SQFZS32ZVMTQEZV -p tcp -m comment --comment "default/simpleservice:" -m tcp -j DNAT --to-destination 172.17.0.3:9876
-A KUBE-SEP-PXYYII6AHMUWKLYX -s 172.17.0.4/32 -m comment --comment "default/simpleservice:" -j KUBE-MARK-MASQ
-A KUBE-SEP-PXYYII6AHMUWKLYX -p tcp -m comment --comment "default/simpleservice:" -m tcp -j DNAT --to-destination 172.17.0.4:9876
-A KUBE-SERVICES -d 172.30.228.255/32 -p tcp -m comment --comment "default/simpleservice: cluster IP" -m tcp --dport 80 -j KUBE-SVC-EZC6WLOVQADP4IAW
-A KUBE-SVC-EZC6WLOVQADP4IAW -m comment --comment "default/simpleservice:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-4SQFZS32ZVMTQEZV
-A KUBE-SVC-EZC6WLOVQADP4IAW -m comment --comment "default/simpleservice:" -j KUBE-SEP-PXYYII6AHMUWKLYX

上のルーティングテーブルのリストをみると、新しく作られた pod は 172.17.0.4:9876 でサービス提供していて、その pod 用のルールが追加されたのがわかりますが、他にもう一つルールが追加されています。

-A KUBE-SVC-EZC6WLOVQADP4IAW -m comment --comment "default/simpleservice:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-4SQFZS32ZVMTQEZV

このルールによって、IPtables の statistics モジュールが呼び出され、service に来るトラフィックが 2 つの pod に平等に分配されます。

すべてのリソースを削除するには以下を実行します。

$ kubectl delete svc simpleservice

$ kubectl delete rc rcsise

前へ | 次へ