フラミナル

考え方や調べたことを書き殴ります。IT技術系記事多め

Volterraについて調べてみた(更新中)

f:id:lirlia:20210206023817p:plain

用語

名前 説明
Volterra Node クラウドまたは物理環境に設置されたVolterraManagedなKubernetesが稼働するサーバのこと
Site Volterra Nodeがデプロイされた物理orクラウド環境のこと。AWSでいうVPCやAzureのVNetなどが該当する。Siteは1つ以上のVolterraNodeのClusterで構成される。複数のVolterra NodeによるClusterがある場合には、別々のSiteとして管理される。
vSite Virtual Siteのこと。Siteを束ねる概念で、Siteごとの設定をまとめて管理できる。Siteが渋谷支店なら、vsiteは東京グループや関東グループと言うイメージ。Siteは複数のvSiteに所属することができる。
Physical Kubernetes VoltNode上にインストールされているKubernetesのこと
Virtual Kubernetes 複数のSiteに存在するPhysical Kubernetesを横断して管理する仮想的なKubernetes。Kubernetesの全てのリソースをラップするのではなく、あくまで1Virtual Kubernetesあたり1 Namespace(こっちはPhysicalの方) を管理できる。たとえば複数のPhysical kubernetesに対してdev/stg/prodの3種類のNamespaceを作って管理したい場合には、Virtual Kubernetesを3つ作らないといけない
Namespaces KubernetesのNamespaceとは別の概念(ややこしい) 、わかりやすさのためvNamespaceと記載する(非公式)。Tenantの中のリソースをvNamespaceと言う単位で分割して管理する。複数のvSiteが入っている。すべてのVolterraオブジェクトはユニークなkind,tenant,vnamespace,nameで示されるFQNという識別子で管理される。vNamespaceはTenantのisolationなのでvNamespaceを超えた操作はできない。(金融.マーケティングみたいな組織で分けたり、開発/本番みたいな用途でわける
Tenant 特定のテナントIDを持つユーザが作成した、全ての構成物の所有者。テナントは個人ユーザとエンタープライズがあり、エンタプーライズの場合は複数ユーザが参加することができる。(テナントで権限が分かれているのでテナントを跨いだ操作は無理そう)
Fleet 各Siteに存在する機器のHWの構成や、接続されるデバイス(NIC/ストレージ/FW/NW)などを管理するもの。vSiteはくまで場所の管理であって、同じ設定や機構のSite(Cluster)を管理するものではないのでFleetを使って管理する
Label KubernetesのLabelとは別の概念。(ややこしい)オブジェクトのクラス分類をするためのもの。key&value型。Lebal Selectorをうまく使ってオブジェクトを管理する。

単位としては以下の順序

  • Tenant > vNamespaces > Virtual Kubernetes > vSite > Site(k8s Cluster/Physical Kubernetes) > Volterra Node(物理/仮想マシン)
  • Volterra Site | Volterra Docs

Namespaces

Tenantを作ると以下のNamespaceが作られる。Namespaceを作る時の注意としてはFQDN名として使われることがあるのでRFC1035に準拠して./などの文字を使わないようにすること。

  • system
    • すべてのインフラオブジェクトはここに入る
    • site/network/interface など
    • 削除できない
    • インフラストラクチャ内のsiteオブジェクトは、Tenant内のすべての名前空間に表示されるため、特別です。
  • shared
    • すべてのNamespaceからみることができるオブジェクトがある
    • 削除できない
  • default
    • 最初に作られるやつ
  • ves-io-shared
    • すべてのTenantで共有されるオブジェクトがある。GET操作のみ可能。

Podを外部公開する

Origin Pool

外部公開するには対象のService(kubernetesのリソース)に対してOrigin Poolを設定する。Origin PoolはEndpointへのロードバランスを実現したり、ヘルスチェックやエンドポイントへのTLS機能を実現したりする。

※複数のPhysical kubernetesで稼働するServiceをまとめて抽象化するVolterraリソースという感じだろうか。

そしてここで作成したOrigin Poolに対してVolterraのSaaSで提供されるHTTP Load Balancerをアタッチすると、グローバルから各 Site上のPodへの通信が実現するようになる。このとき各SiteとREはIPsec/SSLトンネルにより接続されているので、Site自体がグローバルIPをもっている必要はない。

Origin Poolの設定

名前 意味
Public IP of Origin Server OriginサーバがグローバルIPを持っている場合。Volterraの外で動くサービスをOriginとして扱うときに使うのだろう。
IP address of Origin Server on given Sites Siteに割り与えられたプライベートIP or グローバルIPを指定する。Volterra Nodeの先にいる別のサーバなどに対して通信をしたいときに使えそう。
Public DNS Name of Origin Server Public IP of Origin ServerのFQDN版
DNS Name of Origin Server on given Sites IP address of Origin Server on given SitesのFQDN版。ただしPrivateでのローカルドメインなどを使っている場合はどのように名前解決がされるか不明なので、使えるかわからない…。Phyisical KubernetesのCoreDNSが判断できればいけるのかな…?
k8s Service Name of Origin Server on given Sites Phyisical kubernetesで稼働するServiceに対する接続
Consul Service Name of Origin Server on given Sites HAshicorp Consul Serviceに接続
Custom Endpoint Object for Origin Server 自分で指定したEndpoint。どこのvsiteのどのプロトコルのどのportまで指定できるので、これを1つ設定しておきOriginで使い回すってのは結構使われるパターンっぽい。

Site内のネットワークトポロジー

singleNICの場合

f:id:lirlia:20210206014239p:plain

1つのNICで全ての通信を賄う。別のSiteへの通信はIPsec/SSLトンネルを利用し通信を行う。(regional edgeというVolterra社のクラウドを経由する or Site-Site間のいずれかの経路)

Multi NIC(以上) の場合

f:id:lirlia:20210206014505p:plain

外向け、内向けの2つのセグメントのパターン。別Site向けの通信はSingleNICと同じくIPsec/SSL越し。これを使うケースとしてはVolterraNode達をWANに面したルーティング・FW装置として活用する場合。(Default Gateway モード)

通常のルータと違い、Kubernetesの機能を生かしつつ統合管理もできるエッジ機器なので利便性が高いかも?(性能は劣るが管理が楽そう)

Clusterに対するVIP

複数のVolterra Nodeが存在するときに代表IPとしてVIPを設定することが可能。

Site間のトポロジー

Regional Edge(RE)の接続

Siteが作成・承認されるとClusterは自動で2つのVolterra Regional Edge(グローバルIP持ち) に接続する。このときGeo-IPアドレスによって近いロケーションが選ばれるが、ユーザが後で変更することも可能。

REへの接続はIPsec/SSLの両方が用いられ、基本的にはIPsecが使われる。REと接続が確立すると、REにある分散コントローラーがSiteを管理し始める。この経路はマネジメント用、データ用とで共有している。

Site-Site間の接続

f:id:lirlia:20210206020524p:plain

VolterraのSite間の通信は基本的にREを通して行われるが、直接Site間をつなぎたい場合は Site Mesh Group を使うことで実現できる。

Site Mesh Group を使う場合はSite間でIPsec or SSL or Clear/Unencrypted Tunnelのいずれかが利用できる。Groupの作り方によって以下のようなHub&Spokeの構成を取ることも可能。

f:id:lirlia:20210206020949p:plain

仮想ネットワーク

VolterraではVolterra Node/Site内のネットワークを抽象的な物として扱うために、Virtual Network/Network Interface/Network Connectorの3種類の概念を用意しています。

f:id:lirlia:20210206035500p:plain

仮想ネットワークはSite内のネットワークのことです。一意のIPアドレスを持ち、相互に通信でき、他のエンドポイントから分離されたエンドポイントのコレクションです。ネットワークの世界では、仮想ネットワークはVRF(仮想ルーティングおよび転送)とも呼ばれます。

仮想ネットワークはユーザが作るものと、ブートストラップ時に勝手に作られるものがあります。

種類 説明
Per-Site Siteごとに存在するNWのこと。別Siteとの疎通性はない。
Global 複数のSiteを跨いで作成される仮想NW。このNWに存在するエンドポイントはSiteに関係なく通信を行うことができる
Site-Local 各サイトに1つしか存在できない。ブートストラップ中にシステムによって自動で作られるもの。NATゲートウェイ/ファーウォールを介してパブリックインターネットに接続できます。
Site-Local-Inside 各サイトに1つしか存在できない。2つのNICを持つサイトでのブートストラップ中にシステムによって自動で作られるもの。inside側のNWのこと。
Public REのNWのこと(ユーザ管理外)
Site-Local-Service physical kubernetesのcluster IPにallocateされたNW
VER-Internal Siteのすべてのコントロールプレーンサービスが存在する場所を表します。これは、コントロールプレーンがテナントサービスにアクセスする必要がある場合にのみ使用されます

ちなみにVoltConsoleだと作れるNWは以下の通り。(ドキュメントとちがくね?)

  • site local inside
  • site local outside
  • global
  • legacy

legacyの中みたら上で解説した Site Local / Site Local Inside / Per Site / Global / Site local inside and outside などがあった。なんやねんlegacyって。

Network Interface

Network InterfaceはFleetで設定される 物理 or 仮想 インターフェース のことを指します。

eth0 や 1といったSite内のNodeが持っているNICのことを 物理インターフェース といい、それにぶら下がるVLANなどのインターフェースを 論理インターフェース と言います。

各インターフェースは以下の2つを満たしている必要があります。

  1. 仮想ネットワークに所属していること
  2. IPアドレスをもっていること(静的またはDHCP)

Siteに仮想ネットワークを設定する

2つの方法があります。

  1. 物理や論理インターフェースを仮想ネットワークに参加させ、それらのインターフェースからアクセスできるエンドポイントを同じ仮想ネットワークのメンバーにします。

例:VolterraNodeのeth0が192.168.0.0/24に所属し、他のサーバからみたらDefaultGatewayだとします。そしてこのeth0を仮想ネットワーク1に参加させるとeth0からアクセスができる192.168.0.0/24上のエンドポイントが全て仮想ネットワーク1のメンバーとなります。(ただしすべてのエンドポイントがユニークなIPを持っている必要があります)

使い方としては、VolterraNodeより先にいるサーバもVolterra経由でアクセスさせるために使えますね。

  1. すでに存在する仮想ネットワークに対して Network Connector を使う方法があります。詳しくはNetwork Connectorのところに書きます。

Network Connector

Network ConnectorはVirtualNetworkをつなげるものです。異なるネットワークを接続するのでイメージはルータですが、機能がいくつかありフォワードプロキシ、リバースプロキシ、SNAT、Directから選べるようです。

  • Two-way connector(Directのこと)
    • 2つの仮想ネットワークを接続する。仮想ネットワーク間のIPかぶりはNG。(Local1-Local2でIP被りなし)
    • 仮想ルータを2つのネットワークの間に設置して経路交換するイメージ
    • site-local-inside ~ global間 / site-local-outside ~ global間 の時に利用可能
  • One-way connector
    • 2つの仮想ネットワークを接続する。仮想ネットワーク間でIPがかぶっている場合に使う。(Local1-Global-Local2みたいなときにLocal1/2でIP被りしてるとき)
    • SNAT/フォワードプロキシ/リバースプロキシを使用してIPを変換して2つのネットワークを接続する。
    • 例:複数のSiteがありそれぞれに同じサブネットのローカル仮想ネットワークがあるとお互いに通信ができない。そこでグローバルの仮想ネットワークを作り、そこに各Siteのローカル仮想ネットワークからコネクタを経由して通信をすることでIPがユニークとなり通信ができるようになる。
  • Reverse Proxy connector
    • 接続する仮想ネットワーク間でIPバッティングする場合に使う(Local1-Local2でIP被り)
    • 設定なさそう

ややこしいのがVoltConsole上だと Direct or SNAT ? が聞かれて、それとは別にフォワードプロキシの有無が聞かれます。あとなぜかリバースプロキシは存在しませんでした。

実際に存在したNetwork Connectorの設定

  • site local inside - site local outside (SNAT) ←One-way connector
  • site local inside - global (Direct) ←Two-way connector
  • site local outside - global (Direct) ←Two-way connector

フォワードプロキシ使うときは下2つのいずれかを選んで、フォワードプロキシを設定するんだろうな〜。また Globalに抜けるときはSNATの選択肢がなかったので、フォワードプロキシ強制なのかな?

ローカル仮想ネットワーク

Siteに存在する仮想的なNWのこと。Fleetを利用してたくさんのしてを管理しているケースにおいて、全てのSiteに対してこれを作ると便利らしい。(別のSiteと接続をしたくない場合はlocal設定にすることで、他のsiteとの接続を実施しない)

グローバル仮想ネットワーク

複数のSite間で共有する仮想ネットワーク。複数のSiteをまたがる。SubmarinerやSkupperを使ったマルチクラスタネットワークと同義っぽい。

ゼロタッチプロビジョニング

ゼロタッチプロビジョニングとは利用者が特に設定することなく、起動するとゼロタッチで設定を自動投入してくれる仕組みのこと。

Volterra Stackはこれを採用しており顧客の環境やエッジ、クラウド基盤にいたるまでゼロあっちが可能。なおKubernetesにおけるMasterは最低1台作成され、VolterraNodeを追加していくと2n+1を維持するように勝手にインストールが走る。

OSについて

VoltStackに最適化された軽量なOSを利用。クラウド、オンプレ気にすることなく動作するLinuxベースが採用されている。

OSは遠隔アップデートやロールバックがサポートされている。アップグレード時は新バージョンを別のファイルシステムにインストール しリブート後に新バージョンに切り替えることで、ダウンタイムを短くしたり、ロールバックを容易にしている。

実際にAWSにAMIで起動してみた

いろいろコマンドを実行してみる

OCI/CRIはdockerを使っているっぽい。CNIもdocker bridgeか。

[root@ip-10-0-0-36 net.d]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 0a:5d:50:a5:d4:38 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.36/24 brd 10.0.0.255 scope global dynamic eth0
       valid_lft 2277sec preferred_lft 2277sec
    inet6 fe80::85d:50ff:fea5:d438/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:bd:4b:16:a8 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:bdff:fe4b:16a8/64 scope link
       valid_lft forever preferred_lft forever

バージョンはこちら。

[root@ip-10-0-0-36 net.d]#
[root@ip-10-0-0-36 net.d]#
[root@ip-10-0-0-36 net.d]# docker version
Client:
 Version:           18.09.9
 API version:       1.39
 Go version:        go1.11.13
 Git commit:        039a7df9ba
 Built:             Wed Sep  4 16:51:21 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.1
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       4c52b90
  Built:            Wed Jan  9 19:06:30 2019
  OS/Arch:          linux/amd64
  Experimental:     false
[root@ip-10-0-0-36 net.d]# uname -a
Linux ip-10-0-0-36.ap-northeast-1.compute.internal 4.18.0-147.5.1.ves4.el7.x86_64 #1 SMP Mon Mar 16 08:47:16 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

特にファイルシステムが分かれている感じもしない。

[root@ip-10-0-0-36 net.d]# df -h
ファイルシス              サイズ  使用  残り 使用% マウント位置
devtmpfs                    383M     0  383M    0% /dev
tmpfs                       410M     0  410M    0% /dev/shm
tmpfs                       410M  1.3M  409M    1% /run
tmpfs                       410M     0  410M    0% /sys/fs/cgroup
/dev/mapper/atomicos-root    20G  5.7G   14G   29% /sysroot
/dev/xvda1                  297M  117M  181M   40% /boot
/dev/dm-2                    10G  331M  9.7G    4% /var/lib/docker/devicemapper/mnt/c21048249300177feb599e6c3e38cecf195c196aab10934b4d113f6606194fab
shm                          64M     0   64M    0% /var/lib/docker/containers/c3347fc99e221a71fbf2c2a47edf99faa5d9c05864b4d7b22b3669836b1b8cce/mounts/shm
/dev/dm-3                    10G  241M  9.8G    3% /var/lib/docker/devicemapper/mnt/1622012e1384118441aab5f777410117cf978cc8ba24c4f35051cad04413946d
shm                          64M     0   64M    0% /var/lib/docker/containers/402ebb32dbe79f7608d2d843b82885f7c8349bba14a2efb7cb1476057038aa3d/mounts/shm
/dev/dm-4                    10G  351M  9.7G    4% /var/lib/docker/devicemapper/mnt/5f74428ab43c0dc07502ea6da272cc96aa481fd9cf56bccc2f4e55e5a328a484
shm                          64M     0   64M    0% /var/lib/docker/containers/acba7b54607e75110cb11500691c117be2a91e15d94075e15dcf8b23ac0ca519/mounts/shm
tmpfs                        82M     0   82M    0% /run/user/1000
tmpfs                        82M     0   82M    0% /run/user/0

起動しているコンテナプロセス

[root@ip-10-0-0-36 net.d]# docker ps
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS               NAMES
acba7b54607e        volterraio/fireball:v1-0       "/bin/fireballd"         21 minutes ago      Up 21 minutes                           fireball
402ebb32dbe7        volterraio/site-console:v1-0   "docker-entrypoint.s…"   22 minutes ago      Up 22 minutes                           site-console
c3347fc99e22        volterraio/vpm:latest          "/bin/vpmd"              22 minutes ago      Up 22 minutes                           vpm

プロセスのオプションなど。ところどころkubeという文言はあるがkubernetes/kubeletが入っているわけではない。

[root@ip-10-0-0-36 net.d]# ps -ef |grep docker
root      4284     1  0 06:45 ?        00:00:06 /usr/bin/dockerd -H fd:// --exec-opt native.cgroupdriver=systemd
root      4764     1  0 06:45 ?        00:00:00 /usr/bin/docker run --rm --name vpm --net=host --privileged -v /dev:/dev -v /etc/:/hostetc/:rw -v /usr/bin/:/hostusr/bin/:ro -v /etc/default/:/etc/default/:rw -v /etc/hosts:/etc/hosts -v /etc/machine-id:/etc/machine-id:ro -v /etc/kubernetes/:/etc/kubernetes/:rw -v /etc/os-release:/etc/os-release:ro -v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro -v /etc/systemd/:/etc/systemd/ -v /etc/vpm/:/etc/vpm/ -v /opt/vpm/certs/:/opt/vpm/certs/ -v /etc/wpa_supplicant/:/etc/wpa_supplicant/ -v /mnt/ves/:/mnt/ves/ -v /opt/bin/:/opt/bin/ -v /root/.docker/:/root/.docker/ -v /root/.kube/:/root/.kube/ -v /run/systemd/:/run/systemd/ -v /sys/:/sys/:ro -v /var/lib/etcd/:/var/lib/etcd/:rw -v /var/lib/kubelet/:/var/lib/kubelet/:rw -v /var/lib/vpm/data/:/data/ -v /var/run/:/var/run/:rw volterraio/vpm:latest
root      4868   867  0 06:45 ?        00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/c3347fc99e221a71fbf2c2a47edf99faa5d9c05864b4d7b22b3669836b1b8cce -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
root      8695     1  0 06:45 ?        00:00:00 /usr/bin/docker run --rm --name site-console --net=host -v /var/lib/vpm/data/certs/used/:/usr/src/apps/volterra/site-console/certs/:ro -v /etc/vpm/basic-auth.json:/usr/src/apps/volterra/site-console/basic-auth.json:ro volterraio/site-console:v1-0
root      8782   867  0 06:45 ?        00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/402ebb32dbe79f7608d2d843b82885f7c8349bba14a2efb7cb1476057038aa3d -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
root      9014     1  0 06:46 ?        00:00:00 /usr/bin/docker run --privileged --net=host -v /var/lib/vpm/:/var/lib/vpm/ -e CERTIFIED_HW=generic-single-nic --name fireball volterraio/fireball:v1-0
root      9062   867  0 06:46 ?        00:00:00 containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/acba7b54607e75110cb11500691c117be2a91e15d94075e15dcf8b23ac0ca519 -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc -systemd-cgroup
root      9308  9149  0 07:09 pts/0    00:00:00 grep --color=auto docker

ここからさらにインストールしていく感じなのだろうか?ドキュメントには続きの手順がなかったので諦め。

Add AWS VPC Siteでインストールしてみた

こちらはSSHするとVolterra専用のconsoleに飛ばされるので叩けるコマンドが制限されていた。しかもconfigureが初めから勝手に終わっていた。楽ちん。

叩けるコマンド

Available Commands:
  collect-debug-info Collect debug info produce /tmp/debuginfo/*.bzip2 file for Volterra support
  configure          Initial configuration of the node
  configure-network  Initial configuration of the network
  exec               Exec Custom command
  exit               Exit shell
  factory-reset      Factory reset
  get-config         Get node's config
  health             Status of the node
  help               Help about any command
  log                Get logs from service
  password-change    Change user password
  ping               ping
  reboot             Reboots the node
  soft-restart       Restart specified service
  status             Status of individual services
  usb                usb interaction
  volterra-status    Status of services

execはlsとpingしか叩けない…(全然中身見れない) なんとかして中に入ってみるとこんな感じのpodが起動していた。

NAMESPACE                     NAME                                                                    READY   STATUS      RESTARTS   AGE
kube-system                   coredns-d5bdd5f97-lmg6w                                                 1/1     Running     0          7h22m
kube-system                   kube-apiserver-ip-10-45-1-52.ap-northeast-1.compute.internal            1/1     Running     0          7h22m
kube-system                   kube-controller-manager-ip-10-45-1-52.ap-northeast-1.compute.internal   1/1     Running     0          7h22m
kube-system                   kube-proxy-wrmkh                                                        1/1     Running     0          7h23m
kube-system                   kube-scheduler-ip-10-45-1-52.ap-northeast-1.compute.internal            1/1     Running     0          7h22m
kube-system                   kube-state-metrics-6bcb7884db-czkrp                                     1/1     Running     0          7h22m
monitoring                    blackbox-exporter-6db8c8858-x2hzq                                       3/3     Running     0          7h22m
monitoring                    event-exporter-594d9d5544-7g2g9                                         1/1     Running     0          7h21m
monitoring                    fluentbit-xd4nm                                                         2/2     Running     0          7h22m
monitoring                    prometheus-7f967d47b7-74m5z                                             6/6     Running     0          7h22m
monitoring                    prometheus-node-exporter-qrnsm                                          1/1     Running     0          7h22m
ves-system                    dnsmasq-79c8bbc76-8lx9n                                                 1/1     Running     0          7h21m
ves-system                    etcd-0                                                                  2/2     Running     0          7h21m
ves-system                    etcd-defrag-1612620000-5r5nb                                            0/2     Completed   0          34m
ves-system                    gubernator-5cd8fdc676-stt95                                             2/2     Running     0          7h21m
ves-system                    obelix-cpvlw                                                            2/2     Running     0          7h22m
ves-system                    opera-8bptl                                                             2/2     Running     0          7h22m
ves-system                    ver-tmmjt                                                               10/10   Running     0          7h21m
webhook                       voucher-6b449685d5-vqjzd                                                1/1     Running     0          7h22m
NAMESPACE                     NAME                 TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)                                                                      AGE
default                       kubernetes           ClusterIP   100.127.192.1     <none>        443/TCP                                                                      7h27m
kube-system                   kube-dns             ClusterIP   100.127.192.10    <none>        53/UDP,53/TCP,9153/TCP                                                       7h26m
kube-system                   kube-state-metrics   ClusterIP   100.127.236.48    <none>        65031/TCP,65032/TCP                                                          7h26m
monitoring                    blackbox-exporter    ClusterIP   100.127.248.100   <none>        9115/TCP                                                                     7h26m
monitoring                    prometheus           NodePort    100.127.216.120   <none>        9090:32222/TCP                                                               7h26m
monitoring                    pushgateway          ClusterIP   100.127.224.160   <none>        65220/TCP                                                                    7h26m
ves-system                    dnsmasq              ClusterIP   100.127.192.15    <none>        1067/UDP                                                                     7h26m
ves-system                    etcd                 ClusterIP   None              <none>        2379/TCP,2380/TCP,23790/TCP,65535/TCP                                        7h26m
ves-system                    gubernator           ClusterIP   100.127.192.26    <none>        65111/TCP,65110/TCP,65112/TCP                                                7h26m
ves-system                    obelix               ClusterIP   100.127.192.16    <none>        18095/TCP,18091/TCP,18092/TCP,18093/TCP,18094/TCP                            7h26m
ves-system                    opera                ClusterIP   100.127.247.47    <none>        8007/TCP,9007/TCP,8507/TCP,9507/TCP                                          7h26m
ves-system                    ver                  NodePort    100.127.192.18    <none>        8005:30805/TCP,9999:31635/TCP,8505:30855/TCP,9005:30905/TCP,9505:30955/TCP   7h26m
webhook                       voucher              ClusterIP   100.127.192.40    <none>        65334/TCP,65333/TCP,443/TCP,8443/TCP,8444/TCP                                7h26m

verというpodの中に10個ものコンテナが入っているようで、中を見ていくとopenvpnとかBFDとかIKEなどのそれっぽいコンテナがいた。openvpnの引数をみてみるとREが宛先にいたのでこれが通信を実現しているのだろう。

それぞれのpodの起動方法はこんな感じ。IPsecVPNはdaemonsetで起動しているので、各VolterraNode→REに対してVPNを貼っている模様。

$ kubectl get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
dnsmasq      1/1     1            1           8h
gubernator   1/1     1            1           8h

$ kubectl get statefulset
NAME   READY   AGE
etcd   1/1     8h

$ kubectl get daemonset
NAMESPACE                     NAME                       DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
ves-system                    obelix                     1         1         1       1            1           <none>          8h
ves-system                    opera                      1         1         1       1            1           <none>          8h
ves-system                    ver                        1         1         1       1            1           <none>          8h

get-config

EmbedEtcdClientPort: 12379
EmbedEtcdDataDir: /data/vpm-embed-etcd
EmbedEtcdPeerPort: 12380
GrpcPort: 65000
GrpcTLSPort: 65002
Kubernetes:
  BootstrapSecretsSubdir: pki
  ClusterCIDR: xx/18
  DNSServiceIP: xx
  EtcdUseTLS: true
  Hostname: ip-10-45-1-52
  Images:
    Apiserver: k8s.gcr.io/kube-apiserver:v1.17.9
    ControllerManager: k8s.gcr.io/kube-controller-manager:v1.17.9
    CoreDNS: k8s.gcr.io/coredns:1.6.5
    Etcd: gcr.io/volterraio/etcd@sha256:9299b4fa5e087e9bbe16b371030360e0745d4f6ebb4116633d76e4ae1d8139f9
    Proxy: k8s.gcr.io/kube-proxy:v1.17.9
    Scheduler: k8s.gcr.io/kube-scheduler:v1.17.9
  Server: vip
  ServiceCIDR: xx/18
  SreDnsServiceIp: xx
  TlsCipherSuites: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
RestPort: 65001
RestTLSPort: 65003
Vpm:
  CertifiedHardware: aws-byol-voltmesh
  CertifiedHardwareEndpoint: https://vesio.blob.core.windows.net/releases/certified-hardware/aws.yml
  ClusterName: test-aws01
  ClusterType: ce
  Config: /etc/vpm/config.yaml
  ContainerRuntime: docker
  Labels:
    ves.io/fleet: ""
  Latitude: 35.689507
  Longitude: 139.6917
  MauriceEndpoint: https://register.ves.volterra.io
  MauricePrivateEndpoint: https://register-tls.ves.volterra.io
  PrivateNIC: eth0
  Token: xxxx
Workload:
  fluentbit:
    params:
      fluentbit_forward_host: fluentd.monitoring.svc.cluster.local
      fluentbit_forward_port: "24224"
      fluentbit_image: gcr.io/volterraio/fluentbit
      fluentbit_namespace: monitoring
  fluentd:
    params:
      fluentd_elasticsearch_host: 192.168.112.4
      fluentd_elasticsearch_port: "30920"
      fluentd_image: gcr.io/volterraio/fluentd
      fluentd_namespace: monitoring
  prometheus:
    params:
      prometheus_app_id: xx
      prometheus_cluster_id: xxx
      prometheus_cluster_name: xx
      prometheus_disable_alerting: "1"
      prometheus_host_network: "1"
      prometheus_image: gcr.io/volterraio/prometheus
      prometheus_namespace: monitoring

health

hostname: xxx
osInfo:
  bios:
    date: xx
    vendor: Amazon EC2
    version: "1.0"
  board:
    assetTag: i-xx
    vendor: Amazon EC2
  chassis:
    assetTag: Amazon EC2
    type: 1
    vendor: Amazon EC2
  cpu:
    cache: 36608
    cores: 4
    cpus: 4
    model: Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
    speed: 2500
    threads: 4
    vendor: GenuineIntel
  kernel:
    architecture: x86_64
    release: 4.18.0-147.5.1.ves4.el7.x86_64
    version: '#1 SMP Mon Mar 16 08:47:16 UTC 2020'
  memory:
    sizeMb: 15690
    type: Other
  os:
    architecture: amd64
    name: CentOS Linux 7.2003.13 (Core)
    release: 7.2003.13
    vendor: centos
    version: 7.2003.13
  product:
    name: t3.xlarge
    serial: xx
    vendor: Amazon EC2
  storage:
  - model: Amazon Elastic Block Store
    name: nvme0n1
    serial: xx
    sizeGb: 85
osVersion: 7.2003.13
publicIp: xx/24
softwareVersion: crt-20210203-845
state: PROVISIONED
version: |
  master 3e58813b2838d631f45c50405e28bf63e0c585e4 2021-01-12T10:45:53+00:00 nil

volterra-status

>>> volterra-status
│────────────│───────────────────────────────────────────────│────────│─────────│
│ NAME (5)   │ NODE                                          │ STATUS │ MESSAGE │
│────────────│───────────────────────────────────────────────│────────│─────────│
│ obelix     │ ip-10-45-1-52.ap-northeast-1.compute.internal │ Ready  │         │
│ opera      │ ip-10-45-1-52.ap-northeast-1.compute.internal │ Ready  │         │
│ ver        │ ip-10-45-1-52.ap-northeast-1.compute.internal │ Ready  │         │
│ dnsmasq    │ ip-10-45-1-52.ap-northeast-1.compute.internal │ Ready  │         │
│ gubernator │ ip-10-45-1-52.ap-northeast-1.compute.internal │ Ready  │         │
│────────────│───────────────────────────────────────────────│────────│─────────│
>>>

VoltConsole

VoltConsole上からはルーティングやtcpdump、USBデバイス、TracerouteなどのNWコマンドやデバイスの状態が確認できるToolsが存在した。

ルーティング

route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.45.1.1       0.0.0.0         UG    0      0        0 vhost0
10.45.1.0       0.0.0.0         255.255.255.0   U     0      0        0 vhost0
169.254.0.0     10.45.1.1       255.255.0.0     UG    0      0        0 vhost0
169.254.10.12   0.0.0.0         255.255.255.252 U     0      0        0 keepalived-tap
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

とくにこれといってVPNを張ってどうこうっていう経路が見当たらない。別Siteへの通信やREへの通信は、keepalived-tapに対して投げてからいい感じに変換して送っている?? (10.45.1.1はAWSのデフォゲ)

26: keepalived-tap: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether 36:6b:b7:45:fd:85 brd ff:ff:ff:ff:ff:ff
    inet 169.254.10.13/30 brd 169.254.10.15 scope global keepalived-tap
       valid_lft forever preferred_lft forever

/var/run/keepalived/keepalived.confの中を見るとVRRPに対するkeepalivedの設定が入っており(BACKUPしかないのはよく分からないけど)、これによってkeepalived-tapという仮想IFが用意されている。またその時のIPはリンクローカルアドレスの169.254.10.13/32をバインドしている。

vrrp_instance vrrp_instance_254 {
        state BACKUP
        interface keepalived-tap
        virtual_router_id 254
        priority 150
        advert_int 1
        authentication {
                auth_type PASS
                auth_pass ves
        }
        virtual_ipaddress {
                169.254.10.13/32
        }
}

中の仕組みの追い方がこれ以上わからないので諦めるが以下のような通信経路だと思われる。

クライアントからVolterraNodeに通信するとき

  • クライアント→RE→〜[IPsec]〜→VolterraNode(ver pod→Cluster IP Service→Nginx Pod)
    • 実際にはIPsecの貼り方はver pod→REとなるはず
    • REはクライアントが指定するHostやPort、IPアドレスなどとVolterraNode内のServiceをMappingしてるんだろう

Site間でPodが通信するとき(REまたぎ)

  • SiteAのVolterraNode(Nginx Pod→Cluster IP Service →ver pod→〜[IPsec]〜→RE→〜[IPsec]〜→SiteBのVolterraNode(ver pod→Cluster IP Service→App Pod)
    • SiteA側ではSiteBのServiceに対するリクエストについてはRE越しに通信しなければならないので、ver podの中のenvoy proxyがetcdに格納したデータを使ってよしなにハンドリングしてるんじゃないかと思う(妄想)

Virtual Kubernetesへの操作

Virtual Kubernetesを作成しkubeconfigをダウンロードしてkubectlを実行。Siteで起動しているPhysical kubernetesをうまくラップしてくれている。NodeのIPは実際のIPではなくキャリアグレードNATのIP(100.64.0.0/10)が用いられており既存のグローバルIPと被らないような形で採番されている。

おそらくVirtual Kubernetes単位でNodeのIPをユニークにする都合で通常のプライベートIPレンジを使用していない物と思われる。

$ kubectl --kubeconfig=kubeconfig get pod -o wide
NAME                              READY   STATUS    RESTARTS   AGE    IP            NODE                                                           NOMINATED NODE   READINESS GATES
nginx-deployment-df5f679c-445vv   2/2     Running   0          7m7s   100.127.0.2   test-aws01-ip-10-45-1-52.ap-northeast-1.compute.internal   <none>           <none>
$ kubectl --kubeconfig=kubeconfig get ns -o wide
NAME              STATUS   AGE
default           Active   9m47s
kube-node-lease   Active   9m52s
kube-public       Active   9m52s
kube-system       Active   9m52s
test              Active   9m52s
$
$ kubectl --kubeconfig=kubeconfig get pod -n kube-system
No resources found.
$ kubectl --kubeconfig=kubeconfig get pod -n kube-public
No resources found.
$ kubectl --kubeconfig=kubeconfig get pod -n kube-node-lease
No resources found.
$
$ kubectl --kubeconfig=kubeconfig get pod -n default
No resources found.

またVirtual Kubernetesにて以下のように明示的にnamespace-aを指定してapplyしたところエラーが発生した。

kind: Deployment
metadata:
  name: nginx-deployment
  namespace: namespace-a
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

先ほどは何も指定せずにApplyしたのでWebで作成したtestというVirtual Kubernetes=Namespaceにデプロイされたのだが、namespace-aというVirtual Kubernetesが存在しないので弾かれた。ということはVirtual Kubernetesは複数のKubernetesを束ねるというよりKubernetesのNamespaceリソースとして扱った方がよさそう。

また使用できるリソースが限定的なのでroleとかcluster roleとかその辺も一切ない。どのnamespaceがみれるとかそう言う類の情報はVolterraのManagedContoroller側で全部管理されている。

疑問

  • origin PoolのDNS Name of Origin Server on given SitesはPrivate FQDNはどう解決される?
    • (Volterraの中の方の回答) CEに設定されたDNSサーバにFQDN引きに行きます。
  • distributed control planeがREにいるらしいが、edgeにはAPIサーバなどはいない?それともいて、遠隔からまとめて指示してるのがdistributed control plane?
    • edgeにAPIサーバいる。遠隔からvirtual kubernetes用のAPIサーバがいる
    • (Volterraの中の方の回答) EdgeのAPIサーバはPhysical K8s (いわゆる普通のK8s)が今後サポートされるので、それを使うとそれぞれのクラスタのAPIをコールできます。GCというVolterraのコンソールでコンフィグを作ると、それが各地のREにコンフィグメッセージを飛ばし、そこに接続しているCEにコンフィグをプッシュするという仕組みです。