概要
OpenStack Stein以降のOctaviaにてA10と連携させることが出来る。
Octaviaでは、LBがどう作られるか?という実態の処理をプロバイダーという存在に任せてしまうことで、バックエンドの細かい違いをユーザーに意識させない仕組みになっている。
通常のOctaviaではAmphoraプロバイダーが実装されている。ご存知の方も多いと思うが、HAProxyを使ったソフトウェアなLBaaSとなる。
あくまでこれはデフォルトの話。別途、プロバイダーを導入すれば、様々なバックエンドを使用することができる。
ロードバランサーアプライアンスで有名なA10 Networksさんからも、まさにそういったプロバイダーがOSSとして提供されている。
https://github.com/a10networks/a10-octavia
そう、A10と連携させることによりハードウェアを用いた非常にハイパフォーマンスなLBaaSを実現することが可能になる。めちゃめちゃ面白そう。
今回、興味があって上記プロバイダーを使用してA10と連携させてみた。その備忘録的なメモとして本記事を残しておく。
ちなみに、Neutron LBaaSでは以前からこういったことができたが、今回の話はOctavia v2の話。
前提
本記事について
多分、インストール方法やらコンフィグなんて、本記事の内容に興味ある人なら大して必要な情報ではないと思う。
ドキュメントがしっかりしているので、読み込むば環境構築はさほど難しくない。
ただし、このa10-octaviaプロバイダーを使うことで、どういう挙動になるのか?という仕様や挙動の部分は、ドキュメントにはいまいちはっきりと書かれていない。連携させることで、どういう感じに扱えるのか、よくわからない。
まさに自分がこのパターンで、使ってみたい!となったのに"これどう動くんだ?"というのがよくわからなかった。なので、ソースコード読み始めるところから始めた。そのうち、いやーちゃんと動作確認したいな、と思い環境構築した。
私はどうしても確認したかったのでそうしたが、世の中そんなに時間がある人たちばかりでもないだろう。
本記事では、ドキュメントではイマイチ把握し辛いそういった仕様や挙動の部分をまとめようと思う。
同じような思いを抱いているかもしれない誰かに役立つことができれば非常に嬉しい。
連携方法の種類
a10-octaviaプロバイダー(以下、単にa10-octaviaと呼称)を使った連携には大きくわけて2つの方法がある。
- Amphoraの代替としてvThunderを使う方法
- 通常はAmphoraインスタンスが立ち、その中のHAProxyがLBとして動く
- このパターンの場合、vThunderインスタンスが立ちあがり、全て処理してくれる
- インスタンスがAmphoraか?vThunderか?の違いでしかない
- ACOSのAPIを叩いてハードウェアとしてA10と連携させる方法
- Amphoraなどのインスタンスは一切立ち上がらない
- ハードウェアなA10の中にSLB(VS)などが作成され、ハードウェア処理してくれる
今回は後者の方法を試した。正直、前者の方法に魅力を感じない。とはいえ、私は実際のハードウェアとしてのA10を持っていない。(めっちゃ欲しい)
仕方ないので仮想インスタンス版であるvThunder
を使用することにした。あれ?1と同じじゃね?と思うかもしれないが、実は1とは全く異なる。
1は仮想インスタンスとしてvThunderが立ち上がるが、今回は単純にハードウェアなA10の代替としてvThunderを使うだけ。つまりOctaviaから見ると、ハードウェアA10と連携しているように見えている。OctaviaからすればAPIが叩ければ何でも良いのでハードウェアだろうが何だろうが気にしていない。
なので、ハードウェアのA10だろうが、仮想マシンなvThunderだろうがOSバージョン(APIバージョン)とNW足回りが同じなら挙動は変わらないはずなので、この形をとった。
ちなみにvThunderは30日間限定の評価用途として誰でも利用可能。今回の構成においても、こちらを使用させてもらった。A10さんありがとうございます。
vThunder FREE 30-DAY TRIAL
環境
- OpenStack Train
- Octavia 4.1.4
- vThunder ACOS v4.1.4-GR1-P5, build 81
検証構成
下記の環境を構築し、仕様や挙動を動作確認した。
- OpenStackのExternalネットワークとして
192.168.10.0/24
を用意- NW名がpublic
- ここから切り出す形で各インスタンスにFloatingIPを割り当てる
- vThunderには管理系を司るManagementと実際のLB関連リソースを受け持つLB専用NWの2つを用意
- Managementには
192.168.1.210/24
を割り当てる- ここがAPIエンドポイントとなる
- LB専用NWとしてEthernet2に
192.168.20.250/24
を割り当てる- VirtualServerのVIPはこのサブネット内に作成される
- このIPアドレスがヘルスモニターの送信元IPアドレスとなる
- Managementには
$ openstack network show public
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | UP |
| availability_zone_hints | |
| availability_zones | nova |
| created_at | 2020-12-06T02:42:40Z |
| description | |
| dns_domain | None |
| id | efd811b2-ba52-4c10-98cf-a881ac2b9d46 |
| ipv4_address_scope | None |
| ipv6_address_scope | None |
| is_default | True |
| is_vlan_transparent | None |
| location | cloud='', project.domain_id=, project.domain_name=, project.id='94ff72dc09d34915b2e5c3d1b3307ef7', project.name=, region_name='RegionOne', zone= |
| mtu | 1500 |
| name | public |
| port_security_enabled | True |
| project_id | 94ff72dc09d34915b2e5c3d1b3307ef7 |
| provider:network_type | flat |
| provider:physical_network | public |
| provider:segmentation_id | None |
| qos_policy_id | None |
| revision_number | 7 |
| router:external | External |
| segments | None |
| shared | False |
| status | ACTIVE |
| subnets | c8eca79d-b07b-4b71-8e1a-a32dc8db759b, e2c6f1de-dcaf-453d-807f-df11c8d6a51e |
| tags | |
| updated_at | 2020-12-06T12:10:01Z |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
vThunder#sh run
!Current configuration: 453 bytes
!Configuration last updated at 14:10:01 JST Sat Dec 19 2020
!Configuration last saved at 14:10:01 JST Sat Dec 19 2020
!64-bit Advanced Core OS (ACOS) version 4.1.4-GR1-P5, build 81 (Sep-08-2020,09:32)
!
ip dns primary 192.168.0.254
!
timezone Asia/Tokyo
!
glm use-mgmt-port
glm enable-requests
glm token hogehoge
!
interface management
ip address 192.168.1.210 255.255.255.0
ip default-gateway 192.168.1.254
!
interface ethernet 1
enable
!
interface ethernet 2
enable
ip address 192.168.20.250 255.255.255.0
!
参考ドキュメント
下記2つを読めば完璧。
- https://github.com/a10networks/a10-octavia/blob/master/a10_octavia/doc/vthunder_readme.md
- https://github.com/a10networks/a10-octavia/blob/master/a10_octavia/doc/tutorial.md
インストール
本当は細かく書こうかと思ったが・・・
正直、参考ドキュメントに記載のインストール方法などの情報が完璧に近い。わざわざQiitaで別記事としてまとめる必要がないレベル。
なので具体的なインストール方法はドキュメントを読んで欲しい。日本語需要があれば別途書きたいと思う。
コンフィグ
a10-octaviaをインストールすると、/etc/a10
というディレクトリが出来ているはず。その配下のa10-octavia.confに以下のような内容を指定。
[a10_controller_worker]
network_driver = a10_octavia_neutron_driver
workers = 2
loadbalancer_topology = SINGLE
[hardware_thunder]
devices = [
{
"project_id":"79573c69b3de4cf9a976285d09cf22c2",
"ip_address":"192.168.1.210",
"username":"admin",
"password":"a10",
"device_name":"vThunder"
}
]
[listener]
autosnat = True
重要なパラメーターは以下。
-
project_id
: serviceプロジェクトのIDを指定。 -
id_address
: どこに向かってAPIコールするか?の指定。基本的にA10のmanagementのIPアドレスを指定する。 -
unsername/password
: A10に作成済みの管理者アカウントを指定。※評価版vThunderではデフォでadmin/a10で作成される -
autosnat
: 自動的にSNATする設定。有効化しておくべき。- これが有効化されていないとLB配下のメンバーのIPアドレスから直接的にレスポンスすることになる。
- 多くの場合、非対称ルーティングということでパケットがドロップされてしまう。
- VSのVIPではなく、あくまでA10のインターフェースのIPアドレス。HAを組んでいるなら、そこのVIPになる。
他にも実環境なら、HA構成やVCS環境を構築しているはずなので関連設定が必要になるが・・・ひとまず上記のコンフィグで動くはず。
ドキュメントでは、amp_book_networkなどamp_*
というパラメーターがサンプルコンフィグ内にいくつかあるが未設定で良い。
そのあたりは、連携方法の種類で示した1のパターンで使用する。ハードウェアなA10と連携させる場合、使われていないパラメーターになる。
※と思う。動作確認した環境では未設定でも問題なく動作している
注意点
LB専用サブネットをOpenStack側に認識させる
OctaviaのAPIコール時に指定するVIPのサブネットはOpenStackが何らかの形で認識できている必要がある。
※APIコール時の話なので、HorizonやCLI使用時でも同じ
$ openstack loadbalancer create -h | tail -11
VIP Network:
At least one of the following arguments is required.
--vip-port-id <vip_port_id>
Set Port for the load balancer (name or ID).
--vip-subnet-id <vip_subnet_id>
Set subnet for the load balancer (name or ID).
--vip-network-id <vip_network_id>
Set network for the load balancer (name or ID).
This command is provided by the python-octaviaclient plugin.
今回の検証構成の場合、192.168.20.0/24をLB関連の専用サブネットとして用意しているので、このサブネットをExternalネットワークとしてOpenStackに作成しておく必要がある。
192.168.10.0/24
のpublicも使用可能だが、このNWでVIPを作成しても、A10としてそのサブネットを持っておらず事実上使えない。
別の方法として、A10のethernet2をトランクポート化して、複数のVirtualEthernetを持てるようにすればpublicや、あるいはそれ以外のサブネットを使用可能。恐らく実環境では、そうするべきだろう。このときVirtualEthernetなどの設定もa10-octaviaから実行させることができる。ドキュメントにもばっちり書かれているやり方なのでさほど難しくない。
今回でいうと、NetworkとしてLB-Designated
、Subnetとしてlb-designated-subnet
を用意。
単に認識できれば良いだけなので、SubnetにGatewayやDHCPなどの設定は不要。あっても別に構わない。
$ openstack network show LB-Designated
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| admin_state_up | UP |
| availability_zone_hints | nova |
| availability_zones | nova |
| created_at | 2020-12-08T22:50:40Z |
| description | |
| dns_domain | None |
| id | 444d8ba4-eb5f-4471-9778-85e9b6b91fab |
| ipv4_address_scope | None |
| ipv6_address_scope | None |
| is_default | False |
| is_vlan_transparent | None |
| location | cloud='', project.domain_id=, project.domain_name=, project.id='94ff72dc09d34915b2e5c3d1b3307ef7', project.name=, region_name='RegionOne', zone= |
| mtu | 1450 |
| name | LB-Designated |
| port_security_enabled | True |
| project_id | 94ff72dc09d34915b2e5c3d1b3307ef7 |
| provider:network_type | vxlan |
| provider:physical_network | None |
| provider:segmentation_id | 5 |
| qos_policy_id | None |
| revision_number | 4 |
| router:external | External |
| segments | None |
| shared | True |
| status | ACTIVE |
| subnets | 6a0d0b80-6686-48c3-b02a-078dd0f61190 |
| tags | |
| updated_at | 2020-12-08T22:52:56Z |
+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
$ openstack subnet show lb-designated-subnet
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| allocation_pools | 192.168.20.1-192.168.20.249 |
| cidr | 192.168.20.0/24 |
| created_at | 2020-12-08T22:52:56Z |
| description | |
| dns_nameservers | |
| dns_publish_fixed_ip | None |
| enable_dhcp | False |
| gateway_ip | None |
| host_routes | |
| id | 6a0d0b80-6686-48c3-b02a-078dd0f61190 |
| ip_version | 4 |
| ipv6_address_mode | None |
| ipv6_ra_mode | None |
| location | cloud='', project.domain_id=, project.domain_name=, project.id='94ff72dc09d34915b2e5c3d1b3307ef7', project.name=, region_name='RegionOne', zone= |
| name | lb-designated-subnet |
| network_id | 444d8ba4-eb5f-4471-9778-85e9b6b91fab |
| prefix_length | None |
| project_id | 94ff72dc09d34915b2e5c3d1b3307ef7 |
| revision_number | 2 |
| segment_id | None |
| service_types | |
| subnetpool_id | None |
| tags | |
| updated_at | 2021-01-03T18:46:47Z |
+----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
LB配下のバックエンドサーバーはA10から通信可能であること
当たり前だが、LBが成り立つために必要なVirtualServerなど各種リソースがA10内部に作成される。そのため、バックエンドサーバー(Octavia:PoolMember, A10:Server)へのアクセスはA10から行われる。つまり、A10からそれらのサーバーに対してのリーチャビリティを確保しておく必要がある。ルーティングはもちろんことフィルタリングなども予め許可しておく必要がある。
Amphoraを使った標準的なOctaviaの場合、LBのVIPをそのバックエンドサーバーが所属するテナント内部に置くことは珍しくなかったと思う。そしてそのVIPに対してFloatingIPを割り当てることで外部と通信可能にする、といった構成である。
この構成は不可能になる。
理由は、OpenStack内部に存在する各インスタンスが持つテナントIPアドレスに対して、A10から直接的にアクセスすることは出来ないから。
どうにかしてアクセスできるようにしても良いが、メリットがないと思う。
なので、現実的にはそのバックエンドサーバーもとい何らかのインスタンスに対してFloatingIPを割り当て、そのFloatingIPを使う形でバックエンドサーバーを構成することになる。つまり、OctaviaのLB作成APIコール時におけるプールメンバー指定には各インスタンスのFloatingIPを指定することになる。
上図でいえば、
ヘルスモニターなら、Eth2が持つ192.168.20.250が送信元IPアドレスになる。
通常のLB通信であれば、192.168.20.xというVIPが送信元IPアドレスになる。※SNAT有効化時
どちらにせよ、A10が送信元となるため、そこからバックエンドサーバーへのリーチャビリティが必要となる、ということ。
動作確認
正常に動いていれば、通常のOctaviaと全く同じ感覚で利用可能。
LB専用サブネットをOpenStack側に認識させるに記載した通り、予め作成しておいたSubnetを指定する。
↑では、Subnetを指定しただけで具体的なVIPアドレスを指定したわけではなかったので、VIPは自動的に割り当てられる。
A10側を見てみても実際にSLBおよびVirtualServerが作成されている。
長くなるのでここには記載しないが、ヘルスモニターやサービスグループ、必要に応じてL7Policyなども作成される。
vThunder#show running-config slb virtual-server
!Section configuration: 255 bytes
!
slb virtual-server 47af3b29-cea6-4900-91df-701731cfcb63 192.168.20.164
port 80 http
name 9910e987-8808-4c3a-93d4-934b4aad56a0
conn-limit 5000
extended-stats
source-nat auto
service-group bff81e77-05a5-4d62-bed1-b77d594ac354
!
仕様/挙動のまとめ
通常のOctaviaと何か大きく変わる点はある?
ない。HorizonやCLIでのLB作成時、AmphoraだろうとA10だろうと何も変わらない。
むしろ、Amphoraインスタンスの作成待ちがない分、A10連携させたほうがよっぽど早くLBが立ち上がる。数秒でActiveになる。
ただ、ドキュメントにも書かれている通り、a10-octavia用のデーモンが3つ稼働することになる。その点は注意。そいつらが稼働していないと、A10と連携できない。
VIPやヘルスモニターなどの各種リソースはいつ作られる?
OctaviaのAPIコールのタイミング。バックグラウンドでA10のAPIが叩かれている。何らかの理由でA10のAPI叩くの失敗していても何度かリトライはする。
結果、最終的にダメならOctaviaのAPIレスポンスとしてもエラーが返る。
なので、OctaviaのAPIとして200が返っているのに、A10側では実際にはリソース出来上がってません、みたいな状況は基本的に発生しない。
VIPはどこに立ち上がる?
LB作成時に指定したVIPが、A10の中にVirtualServerとして出来上がる。
ただし、LB専用サブネットをOpenStack側に認識させるに記載した通り、VIP指定時のサブネットはOpenStack側が認識している必要がある。
認識できていれば良いだけなので、直接的なリーチャビリティは不要。
ヘルスモニターの送信元IPアドレスはどこになる?
LB作成時に指定したVIP/Subnetを持つA10のインターフェースのIPアドレスになる。
なので、今回の検証構成ならEthernet2のIPアドレスになるし、トランクポート化してVirttualEthernetとして作っているなら、そのVEのIPアドレスになる。
このあたりはOctavia関係なく、A10でSLB作れば皆同じ挙動なはず。
NAT Poolは使える?
標準機能では使えない。NAT Poolを使う構成にはa10-octaviaが非対応。
そもそもNAT Poolを作れないし、作ったところでそのNAT Poolを割り当てることが出来ない。そういった機能が実装されていない。
だが、どうしても使いたい機能があるのにサポートされていない場合はどうしたら?に記載の通り、テンプレート機能によって実現することは可能。
つまり、a10-octaviaとしては非対応だとしても、ACOSとしてのテンプレート機能内ではNAT Poolの割り当てが可能なので、そういったアプローチによって何とかできる。
よって、LB毎にNAT設定を切り替えて・・・みたいなことは柔軟なことは不可能。しかし、広めにIPレンジをとったNAT Poolを用意しておいて、それを汎用的に使い回す・・・ということは、この方法で可能。
一応コンフィグ例を示す。
以下のように予めNAT PoolとPort Templateを作成しておく。
- NAT Pool
ip nat pool default_snat_pool 192.168.20.200 192.168.20.240 netmask /24 gateway 192.168.20.254
- Port Template
slb template port default_port_template
source-nat default_snat_pool
あとは、a10_octavia.confで、そのPort Templateを使用するように設定するだけ。
[service_group]
template_port = "default_port_template"
これで、ServiceGroupが作成されたときに、そのテンプレートがアタッチされている。
設定上は明示されていないが、結局のところテンプレート側でNAT Poolが指定されているので、このServiceGroupはNAT Poolを使うことが出来る。
slb service-group 0a47f2d2-1dec-4461-b2b0-e28fd25d7cb0 tcp
template port default_port_template
method least-connection
health-check 88be3b88-3737-43c9-87fe-b1b4c679863c
member 79573_192_168_10_15 80
!
ちなみに、VSのVIPとNAT Poolを同じサブネットに同居する場合、適切に設定しないとIPアドレスのバッティングがありえる。
固定割り当てをすれば良いが、毎回それをするのも面倒くさい。
そんなときはOpenStack側でサブネットを設定する際に、Allocation Poolを設定しておくと良い。そうすれば、その範囲でしかVIPは自動割り当てされない。
結果的に、例えば/24であれば、.1-200はVSのVIP用途、.200-240はNAT Poolで使用・・というように使い分けることが可能になる。
$ openstack subnet set --no-allocation-pool lb-designated-subnet
$ openstack subnet set --allocation-pool start=192.168.20.1,end=192.168.20.200 lb-designated-subnet
どこまでA10の独自機能を使える?
a10-octaviaでサポートされている機能のみ。下記2つを見ると、何が使えるかわかる。
- https://github.com/a10networks/a10-octavia/blob/master/a10_octavia/doc/tutorial.md#slb-configuration-options
- https://github.com/a10networks/a10-octavia/blob/master/a10_octavia/common/config_options.py
どうしても使いたい機能があるのにサポートされていない場合はどうしたら?
一部のリソースにてテンプレート機能を使えるので、予め自分が使いたい機能を設定したテンプレートを用意しておいて、それを読み込ませる・・・という方法で何とか出来る可能性がある。
あるいは、Octaviaによって作成されたリソースに対して後から手動で任意の設定を入れる、ということも可能。本末転倒だが。
OctaviaからLB削除すると、A10側でも関連リソースは消える?
消える。が、VirtualServer設定のみ消える。まぁそれが消えるだけでVIPは消失するしヘルスモニターなども止まるのでLBとしての能力は失う。
ただし、本来不要なはずのServer/ServiceGroupなど一部の関連するリソースは削除されず残置されてしまう。
このへん、a10-house-keeperが綺麗にしてくれるのかな?と思っていたのだが、どうもしてくれない。
ちょっと気持ち悪い・・・このあたり詳しく調べられていないが、何か設定の問題かもしれない。
時間あるときにもう少し調査してみて可能なら実装してPR出そうかと思っている。
コンフィグは自動保存される?
される。Octaviaから連携されて自動的に各種リソースが作成完了と同時にstartup-config
にも保存される。そのため、障害などで不意な再起動が発生しても、各種パラメーターが消失することはない。
ただしHA構成を組んでいる場合、Standby側への同期は自動的にされない。そこはOpenStackやらOctaviaは関係なく、A10のVRRP-A構成特有のもの。なので別途A10にVCS構成を構築する必要がある。
意図的にA10のコンフィグを消すとどうなる?
コンフィグが消失しているからといって、Octaviaがそれを戻そうとはしない。消えているなら消えているでそのまま。
その状態でOctaviaからLB設定変更系のリクエストを投げてもエラーになるだけ。
手動でコンフィグリストアして戻せば、またOctaviaからは正常に見えるし操作可能。
ログはどこで見る?
a10-octaviaとしてのログなら、journalctl -xu a10-controller-worker
で見るのが手っ取り早い。何かあればここを見れば大体わかる。
トラブル時には、どこのレイヤー別に確認していく必要がある。
つまり、エラーになるといっても、Octaviaが悪いのか、a10-octaviaが悪いのか、A10本体が悪いのかが一見するとわからない。
なので、それぞれのレイヤーでログを追いかけたり切り分けしたりする必要がある。
Amphoraは使えなくなってしまうの? A10専用になってしまう?
プロバイダーを切り替えれば、両方を使い分けることが可能。
そのためには、予めoctavia.confでAmphoraとa10-octaviaの両方を有効化しておく必要がある。
enabled_provider_drivers = amphora: 'The Octavia Amphora driver', a10: 'The A10 Octavia driver.'
default_provider_driver = a10
そうすれば、OctaviaのAPIでプロバイダー一覧を見れば2つが表示されているはず。
$ openstack loadbalancer provider list
+---------+------------------------------+
| name | description |
+---------+------------------------------+
| amphora | 'The Octavia Amphora driver' |
| a10 | 'The A10 Octavia driver.' |
+---------+------------------------------+
あとはLB作成時に、プロバイダーを明示指定すれば良いだけ。
参考: https://docs.openstack.org/api-ref/load-balancer/v2/?expanded=create-a-load-balancer-detail#create-a-load-balancer
ただし、Horizon経由では無理っぽい・・・? Ansibleでも対応していない模様。
https://docs.ansible.com/ansible/2.10/collections/openstack/cloud/loadbalancer_module.html
このあたりは未確認なので検証次第、追記予定。
あとがき
こういうハードウェアとの連携系は結構好き。
ソフトウェアで何でもかんでも、という時代とはいえ、やはりハードウェアパワーは偉大。
自分としても、環境を作ったばかりであまり凝った検証とかはできていないので、随時試していきたい。
新たなことが分かり次第、本記事に追記や変更などをしていきたい。