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と繋ぐという手段も考えられるので、そちらも検証したいところである。

Leave a Reply

Your email address will not be published. Required fields are marked *