Kubernetes on OpenStack with Octaviaでスケーラブルなロードバランサーを実現する
KubernetesのCloud-ProviderはOpenStackのLoadBalancerをサポートしている。v1.9からOctaviaがサポートされたので、kubesprayで構築して試した。OctaviaについてはOpenStack Octaviaの概要を参照していただきたい。
構築自体はkubesprayのmasterなどv1.9以降が使えるもので設定して、かつcloud-configファイルのLoadBalancerセクションでuse-octavia=trueとなるようにテンプレートを修正する。その後ansibleを適用したらよいのだけど、kubernetes v1.9.1だと動かない。というのも、バグでLoadBalancer作成中に叩くAPIエンドポイントが間違っていた。
すでに修正済みかつv1.9.3に修正が含まれると思われるが、今すぐためしたかったのでv1.9.1のタグからブランチを切り、修正PRをcherry-pickし、イメージをビルドして検証を継続した。gophercloudを使ってOpenStackのAPIを叩いていれば読みやすいので助かる。hyperkubeをビルドする時、デフォルトだと全OSかつ全アーキテクチャ向けにビルドするようで滅茶苦茶時間がかかるので、Kubernetes: Build Your Custom Kubelet Imageのように環境変数で指定してあげるのがよいです。それでもイメージを作るのに15分くらいはかかる(体感)ので、なんかいい方法ないものか。
検証用には microservices-demoを使っていて、front-end ServiceのtypeをLoadBalancerに変更すればよい(portsからnodePortを消すのを忘れずに)。これで、LoadBalancerが作られる。
無事LoadBalancerが作られると、以下のようにfront-end ServiceのTYPEがLoadBlancerとなり、EXTERNAL-IPにLoadBalancerが使うFloatingIPのIPアドレスが割り振られる。このアドレスにブラウザでアクセスすると、microservices-demoのショップ画面を見ることができる。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
carts ClusterIP 10.233.45.134 <none> 80/TCP 20m
carts-db ClusterIP 10.233.1.15 <none> 27017/TCP 20m
catalogue ClusterIP 10.233.18.173 <none> 80/TCP 20m
catalogue-db ClusterIP 10.233.54.204 <none> 3306/TCP 20m
front-end LoadBalancer 10.233.5.150 XXX.XXX.XXX.XXX 80:31133/TCP 19m
orders ClusterIP 10.233.13.160 <none> 80/TCP 19m
orders-db ClusterIP 10.233.46.106 <none> 27017/TCP 19m
payment ClusterIP 10.233.1.219 <none> 80/TCP 19m
queue-master ClusterIP 10.233.3.45 <none> 80/TCP 19m
rabbitmq ClusterIP 10.233.9.44 <none> 5672/TCP 19m
shipping ClusterIP 10.233.43.87 <none> 80/TCP 19m
user ClusterIP 10.233.44.200 <none> 80/TCP 19m
user-db ClusterIP 10.233.3.11 <none> 27017/TCP 19m
このとき、インターネットからコンテナへの経路は以下のようになるはず。
front-end Serviceの詳細も見ておこう。とはいっても特別見る点はないが。
Name: front-end
Namespace: sock-shop
Labels: name=front-end
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"name":"front-end"},"name":"front-end","namespace":"sock-shop"},"spec":{"por...
Selector: name=front-end
Type: LoadBalancer
IP: 10.233.5.150
LoadBalancer Ingress: XXX.XXX.XXX.XXX
Port: <unset> 80/TCP
TargetPort: 8079/TCP
NodePort: <unset> 31133/TCP
Endpoints: 10.233.101.142:8079
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 20m service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 18m service-controller Ensured load balancer
Octaviaによって作られたLoadBalancer自体を確認しておく。名前が分かりにくい…(当然だが、各idはダミー)
+---------------------+--------------------------------------------------------------+
| Field | Value |
+---------------------+--------------------------------------------------------------+
| admin_state_up | True |
| created_at | 2018-02-06T08:52:21 |
| description | Kubernetes external service a0a62264f0b1b11e8b5a7fa163ec99b5 |
| flavor | |
| id | b231e712-59b2-4d11-8243-a801c4d532b2 |
| listeners | 9bb69e7e-7901-4137-93db-8fca651fe13b |
| name | a0a62264f0b1b11e8b5a7fa163ec99b5 |
| operating_status | OFFLINE |
| pools | 1e1be81f-8cf6-4043-8c47-59020d9fba1b |
| project_id | 4b7dea695f3f4b7abcd4175dd6464783 |
| provider | octavia |
| provisioning_status | ACTIVE |
| updated_at | 2018-02-06T08:53:33 |
| vip_Address | YYY.YYY.YYY.YYY |
| vip_network_id | 1574d358-0f43-4c27-9004-f6be31be92eb |
| vip_port_id | 4f2d5855-3630-4139-bf33-1a2d520f256e |
| vip_subnet_id | 1351ff61-368e-48a9-9e90-dd39840a583f |
+---------------------+--------------------------------------------------------------+
このLoadBalancerや関連リソース(listener、pool、member)はKubernetes側でリソースを消すと自動的に削除されるので便利である。
なお、デフォルトではマニフェストで許可したポートについて、0.0.0.0/0からのアクセスを許可した状態となっている。要件によってはここを制限したくなることがあると思うが、これをマニフェストから設定できるのかは今後調査したい。さらには、Kubernetes on AWS: LoadBalancer型 Service との決別のように、LoadBalancerをTerraformで作成してKubernetesと繋ぐという手段も考えられるので、そちらも検証したいところである。