Hardware LoadBalancer で
“type LoadBalancer”を
使ってみた
青山 真也 (Masaya Aoyama)
普段の主な仕事↓
← 結果待ち
adtech studio のプライベートクラウド環境
・OpenStack をベースとしたプライベートクラウド環境
・Network のレイテンシが許容されないアドテクシステム
そんな弊社にも
GKE ライクなコンテナ基盤がございます。
AKE (Adtech Container Engine)
This is a slide title
AKE の中でも、
LoadBalancer 周りの話をします。
AKE 1.0 の構成 (NodePort + Metal LB)
eth0: 10.0.0.1:34567
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
type: NodePort
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
52.0.0.1:80
> 10.0.0.1:34567
> 10.0.0.2:34567
(cli で登録が必要)
eth0: 10.0.0.2:34567
AKE 1.0 の構成 (NodePort + Metal LB + (HAProxy))
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
(+ HAProxy)
External
52.0.0.1:80
> 10.0.0.1:34567
> 10.0.0.2:34567
(cli で登録が必要)
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
type: NodePort
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
eth0: 10.0.0.1:34567 eth0: 10.0.0.2:34567
SNAT, NAPT ができない場合
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
仮に Service が増えたことを考えると、
こんな感じになります
52.0.0.1:80
> VM α:80
> VM β:80
52.0.0.2:80
> VM α:80
> VM β:80
lo.0: 52.0.0.1:80
lo.1: 52.0.0.2:80
lo.0: 52.0.0.1:80
lo.1: 52.0.0.2:80
SNAT, NAPT ができない場合
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
52.0.0.1:80
> VM α:80
> VM β:80
52.0.0.2:80
> VM α:80
> VM β:80
NodePort は Interface 全てで
Bind されてしまうため利用出来ない
例: *:80
apiVersion: v1
kind: Service
metadata:
name: svc2
spec:
type: NodePort
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
type: NodePort
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
lo.0: 52.0.0.1:80
lo.1: 52.0.0.2:80
lo.0: 52.0.0.1:80
lo.1: 52.0.0.2:80
SNAT, NAPT ができない場合
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
externalIPs 使えば
いけないことも無いが …
利便性が著しく低い
…
metadata:
name: svc1
spec:
externalIPs:
- 52.0.0.1
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
52.0.0.1:80
> VM α:80
> VM β:80
52.0.0.2:80
> VM α:80
> VM β:80
…
metadata:
name: svc2
spec:
externalIPs:
- 52.0.0.2
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
lo.0: 52.0.0.1:80
lo.1: 52.0.0.2:80
lo.0: 52.0.0.1:80
lo.1: 52.0.0.2:80
おいでおいで〜
…
This is a slide title
① SNAT, NAPT が必須な構成
ボトルネック or リソースが必要
② 外部のコマンドでやってもらうの不便
やっぱりGKE がいいって言われる
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
52.0.0.1:80
> VM α:80
> VM β:80
52.0.0.2:80
> VM α:80
> VM β:80
apiVersion: v1
kind: Service
metadata:
name: svc2
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
AKE 2.0 の構成 (NodePort + Metal LB)
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
52.0.0.1:80
> VM α:80
> VM β:80
52.0.0.2:80
> VM α:80
> VM β:80
apiVersion: v1
kind: Service
metadata:
name: svc2
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
AKE 2.0 の構成 (NodePort + Metal LB)
自前で動的に iptables を書き換えて頑張る
(listen しない、ClusterIP を利用)
52.0.0.1:80 宛にきたパケットを
該当 Service の KUBE-SVC-* に転送
This is a slide title
① SNAT, NAPT が必須な構成
ボトルネック or リソースが必要
② 外部のコマンドでやってもらうの不便
やっぱりGKE がいいって言われる
This is a slide title
① 外部 LoadBalancer の操作
② IP 払い出しの自動化
③ K8s Node の iptables 操作
This is a slide titleやっぱ諦められないよ
type LoadBalancer
type LoadBalancer のつくりかた
CloudProvider を自作しましょう。
● LoadBalancer (今回はここの話)
● Routing
● Host
● Zone
● BlockDevice
(参考)
インターフェースの一覧: pkg/cloudprovider/cloud.go
OpenStack の場合、pkg/cloudprovider/providers/openstack/* 辺り
LoadBalancer 用の Interface
GetLoadBalancer(clusterName string, service *v1.Service)
 ・あまり変える部分はない
EnsureLoadBalancer(clusterName string, service *v1.Service, nodes []*v1.Node)
 ・LoadBalancer を作成する、IP の指定がない場合は自動アサイン
UpdateLoadBalancer(clusterName string, service *v1.Service, nodes []*v1.Node)
 ・LoadBalancer を更新する
EnsureLoadBalancerDeleted(clusterName string, service *v1.Service)
 ・LoadBalancer を削除する
大まかには上記 3 種類の Interface を実装してあげる形
渡ってくる構造体に必要な情報は大体揃っている
service.Name
service.Spec.LoadBalancerIP
service.Spec.Ports[].Port
service.Spec.Ports[].TargetPort
nodes.[].Name
This is a slide title
この 4 つの関数を作ると
VM α
Kubernets node
Internal
VM β
Kubernets node
52.0.0.1:80
LoadBalancer
External
52.0.0.1:80
> VM α:80
> VM β:80
52.0.0.2:80
> VM α:80
> VM β:80
apiVersion: v1
kind: Service
metadata:
name: svc2
spec:
type: LoadBalancer
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
apiVersion: v1
kind: Service
metadata:
name: svc1
spec:
type: LoadBalancer
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
AKE 3.0 の構成 (LoadBalancer + Metal LB)
GKE などと全く同じ type LoadBalancer
今後オンプレにより求められるのは、
パブリッククラウドとのシームレスな統合
コンテナ環境だとなおさら移行し易い
GKE > AKE & AKE > GKE
これでマルチクラウドでの展開も容易に

Kubernetes をいじって Hardware LoadBalancer で "type LoadBalancer" を実現してみた @Kubernetes meetup #7

  • 1.
    Hardware LoadBalancer で “typeLoadBalancer”を 使ってみた
  • 2.
    青山 真也 (MasayaAoyama) 普段の主な仕事↓ ← 結果待ち
  • 3.
    adtech studio のプライベートクラウド環境 ・OpenStackをベースとしたプライベートクラウド環境 ・Network のレイテンシが許容されないアドテクシステム そんな弊社にも GKE ライクなコンテナ基盤がございます。 AKE (Adtech Container Engine)
  • 4.
    This is aslide title AKE の中でも、 LoadBalancer 周りの話をします。
  • 5.
    AKE 1.0 の構成(NodePort + Metal LB) eth0: 10.0.0.1:34567 VM α Kubernets node Internal VM β Kubernets node 52.0.0.1:80 LoadBalancer External apiVersion: v1 kind: Service metadata: name: svc1 spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 52.0.0.1:80 > 10.0.0.1:34567 > 10.0.0.2:34567 (cli で登録が必要) eth0: 10.0.0.2:34567
  • 6.
    AKE 1.0 の構成(NodePort + Metal LB + (HAProxy)) VM α Kubernets node Internal VM β Kubernets node 52.0.0.1:80 LoadBalancer (+ HAProxy) External 52.0.0.1:80 > 10.0.0.1:34567 > 10.0.0.2:34567 (cli で登録が必要) apiVersion: v1 kind: Service metadata: name: svc1 spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 eth0: 10.0.0.1:34567 eth0: 10.0.0.2:34567
  • 7.
    SNAT, NAPT ができない場合 VMα Kubernets node Internal VM β Kubernets node 52.0.0.1:80 LoadBalancer External 仮に Service が増えたことを考えると、 こんな感じになります 52.0.0.1:80 > VM α:80 > VM β:80 52.0.0.2:80 > VM α:80 > VM β:80 lo.0: 52.0.0.1:80 lo.1: 52.0.0.2:80 lo.0: 52.0.0.1:80 lo.1: 52.0.0.2:80
  • 8.
    SNAT, NAPT ができない場合 VMα Kubernets node Internal VM β Kubernets node 52.0.0.1:80 LoadBalancer External 52.0.0.1:80 > VM α:80 > VM β:80 52.0.0.2:80 > VM α:80 > VM β:80 NodePort は Interface 全てで Bind されてしまうため利用出来ない 例: *:80 apiVersion: v1 kind: Service metadata: name: svc2 spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 apiVersion: v1 kind: Service metadata: name: svc1 spec: type: NodePort ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 lo.0: 52.0.0.1:80 lo.1: 52.0.0.2:80 lo.0: 52.0.0.1:80 lo.1: 52.0.0.2:80
  • 9.
    SNAT, NAPT ができない場合 VMα Kubernets node Internal VM β Kubernets node 52.0.0.1:80 LoadBalancer External externalIPs 使えば いけないことも無いが … 利便性が著しく低い … metadata: name: svc1 spec: externalIPs: - 52.0.0.1 ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 52.0.0.1:80 > VM α:80 > VM β:80 52.0.0.2:80 > VM α:80 > VM β:80 … metadata: name: svc2 spec: externalIPs: - 52.0.0.2 ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 lo.0: 52.0.0.1:80 lo.1: 52.0.0.2:80 lo.0: 52.0.0.1:80 lo.1: 52.0.0.2:80
  • 10.
  • 11.
    This is aslide title ① SNAT, NAPT が必須な構成 ボトルネック or リソースが必要 ② 外部のコマンドでやってもらうの不便 やっぱりGKE がいいって言われる
  • 12.
    VM α Kubernets node Internal VMβ Kubernets node 52.0.0.1:80 LoadBalancer External 52.0.0.1:80 > VM α:80 > VM β:80 52.0.0.2:80 > VM α:80 > VM β:80 apiVersion: v1 kind: Service metadata: name: svc2 spec: type: ClusterIP ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 apiVersion: v1 kind: Service metadata: name: svc1 spec: type: ClusterIP ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 AKE 2.0 の構成 (NodePort + Metal LB)
  • 13.
    VM α Kubernets node Internal VMβ Kubernets node 52.0.0.1:80 LoadBalancer External 52.0.0.1:80 > VM α:80 > VM β:80 52.0.0.2:80 > VM α:80 > VM β:80 apiVersion: v1 kind: Service metadata: name: svc2 spec: type: ClusterIP ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 apiVersion: v1 kind: Service metadata: name: svc1 spec: type: ClusterIP ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 AKE 2.0 の構成 (NodePort + Metal LB) 自前で動的に iptables を書き換えて頑張る (listen しない、ClusterIP を利用) 52.0.0.1:80 宛にきたパケットを 該当 Service の KUBE-SVC-* に転送
  • 14.
    This is aslide title ① SNAT, NAPT が必須な構成 ボトルネック or リソースが必要 ② 外部のコマンドでやってもらうの不便 やっぱりGKE がいいって言われる
  • 15.
    This is aslide title ① 外部 LoadBalancer の操作 ② IP 払い出しの自動化 ③ K8s Node の iptables 操作
  • 16.
    This is aslide titleやっぱ諦められないよ type LoadBalancer
  • 17.
    type LoadBalancer のつくりかた CloudProviderを自作しましょう。 ● LoadBalancer (今回はここの話) ● Routing ● Host ● Zone ● BlockDevice (参考) インターフェースの一覧: pkg/cloudprovider/cloud.go OpenStack の場合、pkg/cloudprovider/providers/openstack/* 辺り
  • 18.
    LoadBalancer 用の Interface GetLoadBalancer(clusterNamestring, service *v1.Service)  ・あまり変える部分はない EnsureLoadBalancer(clusterName string, service *v1.Service, nodes []*v1.Node)  ・LoadBalancer を作成する、IP の指定がない場合は自動アサイン UpdateLoadBalancer(clusterName string, service *v1.Service, nodes []*v1.Node)  ・LoadBalancer を更新する EnsureLoadBalancerDeleted(clusterName string, service *v1.Service)  ・LoadBalancer を削除する 大まかには上記 3 種類の Interface を実装してあげる形 渡ってくる構造体に必要な情報は大体揃っている service.Name service.Spec.LoadBalancerIP service.Spec.Ports[].Port service.Spec.Ports[].TargetPort nodes.[].Name
  • 19.
    This is aslide title この 4 つの関数を作ると
  • 20.
    VM α Kubernets node Internal VMβ Kubernets node 52.0.0.1:80 LoadBalancer External 52.0.0.1:80 > VM α:80 > VM β:80 52.0.0.2:80 > VM α:80 > VM β:80 apiVersion: v1 kind: Service metadata: name: svc2 spec: type: LoadBalancer ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 apiVersion: v1 kind: Service metadata: name: svc1 spec: type: LoadBalancer ports: - name: "http-port" protocol: "TCP" port: 80 targetPort: 80 AKE 3.0 の構成 (LoadBalancer + Metal LB) GKE などと全く同じ type LoadBalancer
  • 21.