kubernetes連携時の動作1

contrail と kubernetes を組み合わせた場合の動作について、ざっくりとまとめておく。
詳細はこちらを参照。
https://github.com/Juniper/contrail-controller/wiki/Kubernetes

使用したyamlについては、こちらにまとめておく。
https://github.com/tnaganawa/contrail-k8s-tutorial/tree/master/yml/3_contrail-cni-features

pod, deployment

podは、kubernetes 内で実際にアプリの処理を行う部分で、複数のコンテナで構成される。
deploymentは、同じpodを複数まとめて立ち上げる仕組みで、スケールアウト等に用いられる。
※ 特に通常のkubernetes の動作と変わりがないので、詳しくはこちら等を参照。

https://kubernetes.io/docs/concepts/workloads/pods/pod/
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

service

service はpod にアクセスを行うための、ロードバランサーのようなものになる。
contrail では、type: ClusterIP (pod間の通信向け) と type: LoadBalancer (外部からの通信向け) が使用できる。

contrailを使用した場合、複数のpodを持つdeployment に対してserviceを定義すると、各vrouter (外部ルーターがある場合、そちらにも) にnext-hopが2つ設定され、ECMPでの負荷分散が行われる動作になる。

実際 clusterip で定義を行ってみて、内部のpodから確認してみたときの出力は以下となる。
2台のノード上にあるdeploymentに対して、ssh 用のsvc (ip: 10.96.205.1) を定義しているのだが、この場合、contrail内のルーティングテーブルには、svc用に、2つのnext-hop(172.31.6.143, 24と172.31.15.186, 60)が定義されている。
f:id:aaabbb_200904:20171104020938p:plain


kubernetes 側から確認した場合、以下のように、deploymentに対応したpod2つと、svc 1つが定義されている状況となる。

root@ip-172-31-3-97:~# kubectl get pod -o wide
NAME                                READY     STATUS    RESTARTS   AGE       IP              NODE
cirros-deployment-899733556-cj3jp   1/1       Running   0          1h        10.47.255.246   ip-172-31-15-186
cirros-deployment-899733556-tlr0m   1/1       Running   0          1h        10.47.255.247   ip-172-31-6-143
cirros-pod                          1/1       Running   0          18s       10.47.255.252   ip-172-31-6-143
root@ip-172-31-3-97:~# 

root@ip-172-31-3-97:~# kubectl get deployment -o wide
NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINER(S)   IMAGE(S)   SELECTOR
cirros-deployment   2         2         2            2           1h        cirros         cirros     app=cirros-deployment
root@ip-172-31-3-97:~# 

root@ip-172-31-3-97:~# kubectl get svc -o wide
NAME               CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE       SELECTOR
cirros-clusterip   10.96.205.1           22/TCP    6s        app=cirros-deployment
kubernetes         10.96.0.1             443/TCP   19d       
root@ip-172-31-3-97:~# 

podにログインした後、何度かsshを発行すると、以下のように別の鍵が返ってきて、負荷分散が行われていることが分かる。

root@ip-172-31-3-97:~# kubectl exec -it cirros-pod sh
/ # ssh 10.96.205.1

Host '10.96.205.1' is not in the trusted hosts file.
(fingerprint md5 8b:31:ad:50:47:de:8d:b3:9a:3a:e6:da:b9:e5:f8:7a)
Do you want to continue connecting? (y/n) 
ssh: Connection to root@10.96.205.1:22 exited: Didn't validate host key
/ # ssh 10.96.205.1

Host '10.96.205.1' is not in the trusted hosts file.
(fingerprint md5 bb:ac:0e:ea:1e:a9:41:57:dc:e0:04:59:f7:49:b5:23)
Do you want to continue connecting? (y/n) 
ssh: Connection to root@10.96.205.1:22 exited: Didn't validate host key


ノード上でvrouterのflow をダンプしてみた結果は以下となり、 vrouter上で 10.96.205.1 向けの通信について、DNAT が発行されていることが分かる。

root@ip-172-31-15-186(agent):/# flow -l
Flow table(size 80609280, entries 629760)

Entries: Created 639 Added 639 Deleted 1020 Changed 1020 Processed 639 Used Overflow entries 0
(Created Flows/CPU: 639)(oflows 0)

Action:F=Forward, D=Drop N=NAT(S=SNAT, D=DNAT, Ps=SPAT, Pd=DPAT, L=Link Local Port)
 Other:K(nh)=Key_Nexthop, S(nh)=RPF_Nexthop
 Flags:E=Evicted, Ec=Evict Candidate, N=New Flow, M=Modified Dm=Delete Marked
TCP(r=reverse):S=SYN, F=FIN, R=RST, C=HalfClose, E=Established, D=Dead

    Index                Source:Port/Destination:Port                      Proto(V)
 -----------------------------------------------------------------------------------
   138600<=>147932       10.47.255.246:22                                    6 (2->2)
                         10.47.255.252:57490
(Gen: 1, K(nh):60, Action:N(S), Flags:, TCP:SSrEEr, QOS:-1, S(nh):60, 
 Stats:8/1458,  SPort 55502, TTL 0, Sinfo 11.0.0.0)

   147932<=>138600       10.47.255.252:57490                                 6 (2->2)
                         10.96.205.1:22   
(Gen: 1, K(nh):60, Action:N(D), Flags:, TCP:SSrEEr, QOS:-1, S(nh):65, 
 Stats:8/1022,  SPort 60991, TTL 0, Sinfo 172.31.6.143)

(snip)

※ flow -l の詳しい読み方は以下を参照。
https://www.juniper.net/documentation/en_US/contrail3.2/topics/task/configuration/vrouter-cli-utilities-vnc.html#jd0e369



type: LoadBalancer では、上記の動作に加えて、外部から疎通するためのIPが払い出される動作になるが、こちらを定義する場合、事前にexternalのネットワークから、floating-ipを取得できるようにしておく必要がある。
作業としては以下の順番で実施する。
1. configure>networking>networks から適当な仮想ネットワークを作成 (public-network1, 10.0.101.0/24 で作成) し、advanced options の external にチェックをつける。
2. configure>networking>floating ips でfloating-ipの作成を行い、取得元のvnとして、1で作成したネットワークを指定する。
3. 2で取得したfloating-ip を、contrail-kube-manager に設定する

※ 3 の設定方法は以下となる。

(マスター上で実施)
# kubectl exec -it -n kube-system contrail-kube-manager-xxxxx bash
# vi /etc/contrail/kube-manager.conf
(以下を追記)
 -public_fip_pool = {}
 +public_fip_pool = {'domain': 'default-domain', 'project': 'default', 'network': 'public-network1', 'name': 'default' }

# systemctl restart contrail-kube-manager.service

上記実施後、deployment に対して、service を定義すると、external ip としてipが払い出され、該当ipがvMXに配布されることが確認出来る。
※ 今回は 10.0.101.5 として払い出されている

root@ip-172-31-3-97:~# kubectl get svc -o wide
NAME                  CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE       SELECTOR
cirros-clusterip      10.96.205.1             22/TCP         14m       app=cirros-deployment
cirros-loadbalancer   10.101.93.103   ,10.0.101.5   22:30344/TCP   21s       app=cirros-deployment
kubernetes            10.96.0.1               443/TCP        19d       
root@ip-172-31-3-97:~#

実際にvMXに連携用の設定を入れた際の、show route は以下となった。

_contrail_public-network1-l3-1.inet.0: 5 destinations, 7 routes (5 active, 0 holddown, 0 hidden)
@ = Routing Use Only, # = Forwarding Use Only
  1. = Active Route, - = Last Active, * = Both
0.0.0.0/0 *[Static/5] 02:20:39 to table inet.0 10.0.101.0/24 *[Static/5] 02:20:39 Discard 10.0.101.3/32 *[BGP/170] 00:00:06, MED 100, localpref 200, from 172.31.3.97 AS path: ? validation-state: unverified, > via gr-0/0/0.32772, Push 23 10.0.101.5/32 @[BGP/170] 00:00:14, MED 100, localpref 200, from 172.31.3.97 AS path: ? validation-state: unverified, > via gr-0/0/0.32769, Push 24 [BGP/170] 00:00:39, MED 100, localpref 200, from 172.31.3.97 AS path: ? validation-state: unverified, > via gr-0/0/0.32772, Push 60 #[Multipath/255] 00:00:14, metric 100, metric2 0 via gr-0/0/0.32769, Push 24 > via gr-0/0/0.32772, Push 60

配布された経路のnext-hop は、2つのmplsラベル となっており、それぞれdeployment で作成されたpodのラベルに対応している。
このため、external-router を通過した通信が、直接別のスレーブノードに分散されて、負荷分散が行われることになる。

使用したvMXコンフィグは以下を参照(一部、multipathの設定を追加する必要があった)。
https://github.com/tnaganawa/contrail-k8s-tutorial/blob/master/vmx-config/vmx-config-k8s-ecmp-loadbalance

稼働確認用のインスタンスから確認してみたところ、こちらも、以下のように異なった鍵が返っており、外部からアクセスする場合も、負荷分散が行われていることが確認出来た。

[root@ip-172-31-9-34 ~]# ssh 10.0.101.5
The authenticity of host '10.0.101.5 (10.0.101.5)' can't be established.
RSA key fingerprint is SHA256:rbD/ry5jzyMDiqR/EYljBE0PZCG/jmBrhtSTEUvkqUs.
RSA key fingerprint is MD5:bb:ac:0e:ea:1e:a9:41:57:dc:e0:04:59:f7:49:b5:23.
Are you sure you want to continue connecting (yes/no)? 
Host key verification failed.
[root@ip-172-31-9-34 ~]# ssh 10.0.101.5
The authenticity of host '10.0.101.5 (10.0.101.5)' can't be established.
RSA key fingerprint is SHA256:pVn6/oc05FNLEpZ5djBX4+gqh2D/fiBClMQ1DbXUsK0.
RSA key fingerprint is MD5:8b:31:ad:50:47:de:8d:b3:9a:3a:e6:da:b9:e5:f8:7a.
Are you sure you want to continue connecting (yes/no)? 
Host key verification failed.
[root@ip-172-31-9-34 ~]# 

通常、service を提供する場合、haproxy等が使われる場合が多いかとは思うが、contrail を使う場合、上記のようにルーターから直接割り振りが行われるため、状況によっては、構成が簡単になるのではなかろうか。