-
ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(1/3)
概要編 -
ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(2/3)
クラウド側環境構築編 <-- 今回 -
ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(3/3)
ロボット側環境構築編
はじめに
前回は、VPNやWebRTCを使ったインターネット越しにカメラ映像を視聴するシステムの概要とネットワーク構成について書きました。今回は、Azure上にクラウド側環境を構築していきます。
なおLet's EncryptでTLS証明書を取得しますので、お名前.com等のドメインレジストラからドメインを一つ調達しておいてください。
各種バージョン
- クライアント側
バージョン | |
---|---|
OS | macOS Sierra 10.12.6 |
azure-cli | 2.0.61 |
kubectl | 1.14.0 |
docker | 18.09.2 |
git | 2.4.13 |
envsubst | 0.19.8.1 |
- クラウド側
バージョン | |
---|---|
AKS | 1.12.6 |
環境変数の設定
クラウド側環境を構築する際に必要になる設定値を、環境変数として定義しておきます。 DOMAIN
や EMAIL
は、自分が所有するものに適切に変更してください。それ以外の環境変数は、特に理由がなければ変更しなくても大丈夫です(既存のAzure上で同じ名前のリソースがある場合など)。
個別に変更する必要がある環境変数
kurento-robot-camera-k8s$ export DOMAIN="example.com"
kurento-robot-camera-k8s$ export EMAIL="nobody@example.com"
利用するAzureリージョン
kurento-robot-camera-k8s$ export REGION="japaneast"
Azureのリソース名
kurento-robot-camera-k8s$ export DNS_ZONE_RG="dns-zone"
kurento-robot-camera-k8s$ export SYSTEM_RG="kurento"
kurento-robot-camera-k8s$ export VNET_NAME="kurentovnet"
kurento-robot-camera-k8s$ export PODSUBNET_NAME="kurentosubnet"
kurento-robot-camera-k8s$ export GW_PUBLICIP="gwpublicip"
kurento-robot-camera-k8s$ export GW_NAME="kurentogw"
kurento-robot-camera-k8s$ export AKS_NAME="kurentoaks"
AKSノードのスペック(ノード数は3以上)
kurento-robot-camera-k8s$ export NODE_COUNT=3
kurento-robot-camera-k8s$ export NODE_VM_SIZE="Standard_D2s_v3"
kurento-robot-camera-k8s$ export NODE_OSDISK_SIZE_GB=64
kurento-robot-camera-k8s$ export K8S_VERSION="1.12.6"
2019/04/04時点で、東日本リージョンのAKSは
1.12.6
が最新版でした。
自動生成するユーザー名やパスワード
kurento-robot-camera-k8s$ export COTURN_CREDENTIAL="$(cat /dev/urandom | \
LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 8):$(cat /dev/urandom | \
LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 16)"; echo ${COTURN_CREDENTIAL}
kurento-robot-camera-k8s$ export BASIC_USERNAME="$(cat /dev/urandom | \
LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 8)"; echo ${BASIC_USERNAME}
kurento-robot-camera-k8s$ export BASIC_PASSWORD="$(cat /dev/urandom | \
LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 16)"; echo ${BASIC_PASSWORD}
上記のコマンドはBSD系のMacOS用です。Linuxの場合、
$(cat /dev/urandom 2>/dev/null | head -n 40 | tr -cd 'a-zA-Z0-9' | head -c 8)
のようなコマンドで代替できると思います。
Azureにログイン
az
コマンドを用いてAzureにログインします。会社でAzureを利用している場合など、 "規定のディレクトリ" 以外にテナントが存在する場合は、適切なテナントを指定してください。
kurento-robot-camera-k8s$ az login
kurento-robot-camera-k8s$ export TENANT="example.onmicrosoft.com"
kurento-robot-camera-k8s$ az login --tenant ${TENANT}
ソースコードの取得
Githubより、今回構築するシステムのソースコードを取得します。
$ git clone https://github.com/nmatsui/kurento-robot-camera-k8s.git
$ cd kurento-robot-camera-k8s/
Azure Virtual NetworkとAzure VPN Gatewayの構築
Azure Virtual Networkを用いて、今回のシステムに必要な仮想ネットワークを構築します。またその仮想ネットワーク上にAzure VPN Gatewayを構成し、IKEv2でPoint-to-siteのVPNトンネルを敷設できるようにします。
今回のシステム用のリソースグループ作成
kurento-robot-camera-k8s$ az group create --name ${SYSTEM_RG} --location ${REGION}
Azure Virtual Networkを作成
kurento-robot-camera-k8s$ az network vnet create \
--name ${VNET_NAME} \
--resource-group ${SYSTEM_RG} \
--location ${REGION} \
--address-prefix 10.168.0.0/16 \
--subnet-name ${PODSUBNET_NAME} \
--subnet-prefix 10.168.0.0/24
VPN Gateway用subnetを追加
kurento-robot-camera-k8s$ az network vnet subnet create \
--vnet-name ${VNET_NAME} \
--name GatewaySubnet \
--resource-group ${SYSTEM_RG} \
--address-prefix 10.168.255.0/27
Azureの場合、VPN Gateway用subnetの名前は GatewaySubnet
に固定されています。
VPN Gateway用Public IPの取得
kurento-robot-camera-k8s$ az network public-ip create \
--name ${GW_PUBLICIP} \
--resource-group ${SYSTEM_RG} \
--allocation-method Dynamic
VPN Gatewayを作成
kurento-robot-camera-k8s$ az network vnet-gateway create \
--name ${GW_NAME} \
--resource-group ${SYSTEM_RG} \
--location ${REGION} \
--public-ip-address ${GW_PUBLICIP} \
--vnet ${VNET_NAME} \
--gateway-type Vpn \
--sku VpnGw1 \
--vpn-type RouteBased \
--address-prefixes 10.255.0.0/24 \
--client-protocol IkeV2 \
--no-wait
VPN Gatewayの作成にはある程度時間がかかるようです。この記事を書いた際は、20分ぐらいかかりました。(公式マニュアルによれば、45分以上かかる場合もあるそうな)。
VPN Gatewayの確認
kurento-robot-camera-k8s$ az network vnet-gateway show \
--name ${GW_NAME} \
--resource-group ${SYSTEM_RG} \
--query provisioningState \
--output tsv
構築に成功すれば、 Succeeded
と表示されます。
AKS起動
先程作成したAzure Virtual Network上に、Azure AKSを起動します。
実はAzure AKSは、何も指定しなければAKS専用のAzure Virtual Networkを自動的に構成し、その上にKubernetesのデフォルトのネットワークドライバを用いてK8S用の仮想ネットワークを重畳します。K8S単体で動作させるだけならば、これで問題ありません。
しかし今回は、POD間通信で用いられるK8S内部のネットワークをAzure VPN Gateway経由でロボットのLANにまで延伸したいので、K8SのネットワークドライバとしてAzure Virtual Networkを明示的に指定してAKSを起動します。
pod用subnetのIDを取得
kurento-robot-camera-k8s$ export PODSUBNET_ID=$(az network vnet subnet list \
--resource-group ${SYSTEM_RG} \
--vnet-name ${VNET_NAME} \
--query "[?name=='${PODSUBNET_NAME}'].id" \
--output tsv)
network pluginとsubnetを指定してAKSを起動
kurento-robot-camera-k8s$ az aks create \
--name ${AKS_NAME} \
--resource-group ${SYSTEM_RG} \
--location ${REGION} \
--node-count ${NODE_COUNT} \
--node-vm-size ${NODE_VM_SIZE} \
--node-osdisk-size ${NODE_OSDISK_SIZE_GB} \
--network-plugin azure \
--vnet-subnet-id ${PODSUBNET_ID} \
--docker-bridge-address 172.17.0.1/16 \
--dns-service-ip 10.2.0.10 \
--service-cidr 10.2.0.0/24 \
--no-ssh-key \
--kubernetes-version ${K8S_VERSION} \
--no-wait
VPN Gatewayと同様に、AKSの起動にも時間がかかります。この記事を書いた際は、やはり20分ぐらいかかりました。
AKSの確認
kurento-robot-camera-k8s$ az aks show \
--name ${AKS_NAME} \
--resource-group ${SYSTEM_RG} \
--query provisioningState \
--output tsv
構築に成功すれば、 Succeeded
と表示されます。
Credentialの取得
kurento-robot-camera-k8s$ az aks get-credentials \
--name ${AKS_NAME} \
--resource-group ${SYSTEM_RG} \
--overwrite-existing
AKSのnode確認
kurento-robot-camera-k8s$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
aks-nodepool1-78167327-0 Ready agent 8m40s v1.12.6
aks-nodepool1-78167327-1 Ready agent 10m v1.12.6
aks-nodepool1-78167327-2 Ready agent 10m v1.12.6
AKS上にSTUN & TURN Server起動
WebRTCでNAT越えをする際には、ブラウザやKurentoのコンテナが "インターネット側から見て" どのようなPublic IPとPortで到達できるのかを知る必要があります。その際に用いられるのが、STUN Serverです。ブラウザやKurentoが用いるLAN内のPrivate IPとPortが、最終的にどのようにNATされインターネット側から見えるのかをSTUN Serverが観測できれば、その観測されたPublic IPとPortを用いてブラウザとKurentoがP2Pで接続できます。
一方、NATやFirewallの構成次第ですが、WebRTCで必要となるPublic IPやPortの情報をSTUN Serverが観測できないことがあります。このような場合でも、ブラウザやKurentoがPulbic IPを持つTURN Serverに接続できるなら、TURN ServerにWebRTCのパケットを中継してもらうことで、映像を流すことは可能になります。
今回はこのSTUN & TURN Serverとして、coturnというOSSを利用します。
K8Sの制限により、今回構築するTURN ServerはUDPのみListenします。そのため、80/tcpや443/tcpしか通さないような制約が厳しいネットワークでは、TURN Serverにさえ接続できません。仕様上、TURN ServerはTCPでもTLSでも動作しますので、TCPとTLSをListenするTURN Serverを別途起動すれば、この問題を解決できます。
coturnのLoadBalancer Serviceを起動
coturnはその仕様上、coturn自身がNATされた状況で動作する場合、どのPublic IPからNATされてくるのかを知っておく必要があります。そこで、coturnのPodへルーティングするLoadBalancer Serviceを最初に起動します。
kurento-robot-camera-k8s$ kubectl apply -f coturn/coturn-service.yaml
kurento-robot-camera-k8s$ kubectl get services -l app=coturn
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
coturn LoadBalancer 10.2.0.139 xx.xx.xx.xx 80:32704/UDP,49150:30983/UDP,49151:32439/UDP,49152:32325/UDP,49153:32277/UDP,49154:32220/UDP,49155:31336/UDP,49156:31185/UDP,49157:30756/UDP,49158:31146/UDP,49159:31975/UDP 1m
coturnのPublic IPを確認
kurento-robot-camera-k8s$ COTURN_PUBLIC_IP=$(kubectl get services \
-l app=coturn \
-o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}'); \
echo ${COTURN_PUBLIC_IP}
coturnの設定ファイルを生成
テンプレートをもとに、NAT元のPublic IPやTURN Serverのcredentialを変更してcoturnの設定ファイル turnserver.conf
を生成します。
kurento-robot-camera-k8s$ cp coturn/turnserver.conf.template coturn/turnserver.conf
kurento-robot-camera-k8s$ sed -i '' -e "s/^external-ip=.*$/external-ip=${COTURN_PUBLIC_IP}/" \
coturn/turnserver.conf
kurento-robot-camera-k8s$ sed -i '' -e "s/^user=.*$/user=${COTURN_CREDENTIAL}/" \
coturn/turnserver.conf
kurento-robot-camera-k8s$ sed -i '' -e "s/^realm=.*$/realm=coturn.${DOMAIN}/" \
coturn/turnserver.conf
coturnの設定ファイルをsecretに登録
coturnのPodから参照できるように、生成した設定ファイルを turnserver-conf
という名前のSecretとしてAKSに登録します。
kurento-robot-camera-k8s$ kubectl create secret generic turnserver-conf \
--from-file=coturn/turnserver.conf
coturnのPodを起動
最後に、coturnのPodを起動します。
kurento-robot-camera-k8s$ kubectl apply -f coturn/coturn-deployment.yaml
kurento-robot-camera-k8s$ kubectl get pods -l app=coturn
NAME READY STATUS RESTARTS AGE
coturn-7ff4c894cb-dr5bh 1/1 Running 0 108s
AKS上にKurento起動
Kurentoの公式Docker imageを用いて、AKS上にKurentoを起動します。Serviceを経由してNATを増やす意味は無いので、WebRTCのシグナリング時にはPODの生Private IPをそのまま使うべきです。そのため、Headless ServiceとStatefulSetを用いて、Signaling&APPコンテナからPodに直接到達できるようにします。
KurentoのHeadless Serviceを起動
kurento-robot-camera-k8s$ kubectl apply -f kurento/kurento-service.yaml
kurento-robot-camera-k8s$ kubectl get services -l app=kurento
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kurento ClusterIP None <none> 8888/TCP 27s
KurentoのWebRTC用設定ファイルを生成
テンプレートをもとに、STUN ServerとTURN Serverの設定を変更してKurentoのWebRTC用設定ファイル WebRtcEndpoint.conf.ini
を生成します。
kurento-robot-camera-k8s$ cp kurento/WebRtcEndpoint.conf.ini.template kurento/WebRtcEndpoint.conf.ini
kurento-robot-camera-k8s$ sed -i '' -e "s/^stunServerAddress=.*$/stunServerAddress=${COTURN_PUBLIC_IP}/" \
kurento/WebRtcEndpoint.conf.ini
kurento-robot-camera-k8s$ sed -i '' -e "s/^turnURL=.*$/turnURL=${COTURN_CREDENTIAL}@${COTURN_PUBLIC_IP}:80/" \
kurento/WebRtcEndpoint.conf.ini
KurentoのWebRTC用設定ファイルをsecretに登録
KurentoのPodから参照できるように、生成した設定ファイルを kurento-webrtcendpoint-conf
という名前のSecretとしてAKSに登録します。
kurento-robot-camera-k8s$ kubectl create secret generic kurento-webrtcendpoint-conf \
--from-file=kurento/WebRtcEndpoint.conf.ini
KurentoのPodを起動
最後に、KurentoのPodを起動します。
kurento-robot-camera-k8s$ kubectl apply -f kurento/kurento-statefulset.yaml
kurento-robot-camera-k8s$ kubectl get pods -l app=kurento -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
kurento-0 1/1 Running 0 110s 10.168.0.132 aks-nodepool1-78167327-1 <none>
Kurento PodのPrivate IPが、生成したAzure Virtual NetworkのSubnet内で割り振られていることが確認できます。
AKS上にAPI Gatewayと認証認可サービス構築
ブラウザがロボットのカメラ映像を視聴する際、最初にKurentoとWebRTCで接続するためのJavascriptを持ったWebページを表示します。このHTTP GET Requestの処理はSignaling&APPコンテナが担当しますが、インターネットからアクセスされる以上、TLSによる経路の暗号化とユーザー認証は必須となります。
このような横断的な機能を各Signaling&APPコンテナに作り込むのは無駄ですので、TLSの終端と認証認可を行うAPI Gatewayをフロントに立て、各Signaling&APPコンテナから責務を切り離すことにします。
DNSの設定
まずはSignaling&APPコンテナをFQDNで名前解決できるように、自分のドメインのname serverをAzure DNSに構築します。
DNS用リソースグループ作成
kurento-robot-camera-k8s$ az group create --name ${DNS_ZONE_RG} --location ${REGION}
DNS Zone作成
kurento-robot-camera-k8s$ az network dns zone create \
--resource-group ${DNS_ZONE_RG} \
--name "${DOMAIN}"
name server確認
kurento-robot-camera-k8s$ az network dns zone show \
--resource-group ${DNS_ZONE_RG} \
--name "${DOMAIN}" \
--query nameServers
このコマンドを実行すると、次のようなname serverのリストが帰ってきます。これらをドメインレジストラに登録してください。
[
"ns1-XX.azure-dns.com.",
"ns2-XX.azure-dns.net.",
"ns3-XX.azure-dns.org.",
"ns4-XX.azure-dns.info."
]
TLS証明書の取得
自分のドメインで名前解決ができるようになれば、Let's EncryptからTLS証明書を取得できます。後々複数のサブドメインで異なるアプリを立ち上げますので、DNSチャレンジを用いてワイルドカード証明書を取得します。
certbotコンテナを用いてDNSチャレンジを生成
最初に設定したDOMAINやEMAIL等を変数展開しつつ、DNSチャレンジを行うdockerコマンドを生成します。
kurento-robot-camera-k8s$ echo "docker run -it \
-v $(pwd)/secrets:/etc/letsencrypt certbot/certbot certonly \
--manual \
--domain *.${DOMAIN} \
--email ${EMAIL} \
--no-eff-email \
--agree-tos \
--manual-public-ip-logging-ok \
--preferred-challenges dns-01 \
--server https://acme-v02.api.letsencrypt.org/directory"
別のターミナルを開き、生成したdockerコマンドを実行すると、自分のドメインのTXTレコードに設定すべき値を表示して入力待ちになります。例えば次のような感じです。
$ docker run -it -v /tmp/kurento-robot-camera-k8s/secrets:/etc/letsencrypt certbot/certbot certonly --manual --domain ........
....
-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.cloudconductor.jp with the following value:
ABCDEFGHIJKLMNO-PQRST-UVWXYZabcdefghijklmno
Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue
TXTレコード登録
TERMINAL1で、表示された名前と値を持つTXTレコードをDNS Zoneに作成します。 DNS_TXT
の値は、実際に表示された値に書き換えてください。
kurento-robot-camera-k8s$ export DNS_TXT="ABCDEFGHIJKLMNO-PQRST-UVWXYZabcdefghijklmno"
kurento-robot-camera-k8s$ az network dns record-set txt add-record \
--resource-group ${DNS_ZONE_RG} \
--zone-name "${DOMAIN}" \
--record-set-name "_acme-challenge" \
--value "${DNS_TXT}"
次のコマンドを実行し、TXTレコードが生成されていることを確認しましょう。
kurento-robot-camera-k8s$ az network dns record-set txt list \
--resource-group ${DNS_ZONE_RG} \
--zone-name "${DOMAIN}"
TLS証明書の取得
TXTレコードが登録されていれば、TERMINAL2でエンターキーを押してTLS証明書を取得します。TERMINAL2で次のように表示されれば成功です。
.....
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
.....
実際のTLS証明書は、 secrets
ディレクトリの下に格納されています。 privkey.pem
と fullchain.pem
が生成されていることを確認してください。
kurento-robot-camera-k8s$ ls -al secrets/live/${DOMAIN}
不要なTXTレコードの削除
TLS証明書が取得できれば、先程登録したTXTレコードは削除してしまいましょう。
kurento-robot-camera-k8s$ az network dns record-set txt remove-record \
--resource-group ${DNS_ZONE_RG} \
--zone-name "${DOMAIN}" \
--record-set-name "_acme-challenge" \
--value "${DNS_TXT}"
API Gateway ServiceとPodを起動
今回は、OSSのK8S API Gatewayであるambassadorを用いて、TLS終端とsubdomainによるサービスルーティングを行います。
ambassadorのLoadBalancer Serviceを起動
kurento-robot-camera-k8s$ kubectl apply -f ambassador/ambassador-service.yaml
kurento-robot-camera-k8s$ kubectl get services -l app=ambassador
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ambassador LoadBalancer 10.2.0.19 xx.xx.xx.xx 443:30517/TCP,80:31893/TCP 2m50s
TLS証明書をsecretに登録
kurento-robot-camera-k8s$ kubectl create secret tls ambassador-certs \
--cert=$(pwd)/secrets/live/${DOMAIN}/fullchain.pem \
--key=$(pwd)/secrets/live/${DOMAIN}/privkey.pem
ambassadorのPodを起動
kurento-robot-camera-k8s$ kubectl apply -f ambassador/ambassador-deployment.yaml
kurento-robot-camera-k8s$ kubectl get pods -l app=ambassador
NAME READY STATUS RESTARTS AGE
ambassador-5c79db557-289pd 1/1 Running 0 2m29s
認証認可サービスの起動
ambassadorは、別のサービスと連携することでHTTPリクエストの認証を行うことができます。今回は、シンプルなBasic認証を行う自作のサービスと連携させます。
認証認可サービスのCluster IP Serviceを起動
kurento-robot-camera-k8s$ kubectl apply -f auth/auth-service.yaml
kurento-robot-camera-k8s$ kubectl get services -l app=auth
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
auth ClusterIP 10.2.0.237 <none> 3000/TCP 33s
認証認可サービスの設定ファイルを生成
環境変数として定義したBasic認証のCredentialを元に、設定ファイルを生成します。
kurento-robot-camera-k8s$ cat secrets/auth-tokens.json.template | \
envsubst > secrets/auth-tokens.json
認証認可設定ファイルをsecretに登録
認証認可サービスのPodから参照できるように、生成した設定ファイルを auth-tokens
という名前のSecretとしてAKSに登録します。
kurento-robot-camera-k8s$ kubectl create secret generic auth-tokens \
--from-file=secrets/auth-tokens.json
認証認可サービスのPodを起動
kurento-robot-camera-k8s$ kubectl apply -f auth/auth-deployment.yaml
kurento-robot-camera-k8s$ kubectl get pods -l app=auth
NAME READY STATUS RESTARTS AGE
auth-67ff6bd94b-xt5hf 1/1 Running 0 44s
WebRTC検証用のSignaling&APPコンテナ(loopback)を起動
実際にロボットに接続する前に、WebRTCが正しく動作するかを確認します。Azure AKS上のcoturnやKurentoを利用して、PCのカメラ映像を自分自身へループバックするアプリを作りましたので、それを動作させてみましょう。
loopbackコンテナのCluster IP Serviceを起動
looopbackコンテナのServiceには、次のようなambassadorのMapping定義が記述されています。
kind: Service
metadata:
name: loopback
labels:
app: loopback
annotations:
getambassador.io/config: |
---
apiVersion: ambassador/v0
kind: Mapping
name: loopback-mapping
prefix: /
host: "^loopback\\..+$"
host_regex: true
service: http://loopback:3000
use_websocket: true
spec:
type: ClusterIP
selector:
app: loopback
ports:
- port: 3000
targetPort: loopback
name: loopback
ambassadorはこのannotationを検知して、 loopback.${DOMAIN}
というsubdomainの場合はこのloopback ServiceにHTTP Requestを転送してくれます。
kurento-robot-camera-k8s$ kubectl apply -f loopback/loopback-service.yaml
kurento-robot-camera-k8s$ kubectl get services -l app=loopback
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loopback ClusterIP 10.2.0.125 <none> 3000/TCP 20s
loopbackコンテナの設定情報をSecretに登録
このloopbackコンテナは、起動前に接続するSTUN ServerやTURN Serverの情報を loopback-secrets
という名前のSecretに設定しておく必要があります。詳細はソースコードを確認してください。
kurento-robot-camera-k8s$ kubectl create secret generic loopback-secrets \
--from-literal=STUN_LIST=${COTURN_PUBLIC_IP}:80 \
--from-literal=TURN_LIST=${COTURN_CREDENTIAL}@${COTURN_PUBLIC_IP}:80
loopbackコンテナのPodを起動する
kurento-robot-camera-k8s$ kubectl apply -f loopback/loopback-deployment.yaml
kurento-robot-camera-k8s$ kubectl get pods -l app=loopback
NAME READY STATUS RESTARTS AGE
loopback-5f5798bbfd-xv2b9 1/1 Running 0 2m8s
DNSにloopbackアプリ用のAレコードを登録する
kurento-robot-camera-k8s$ AMBASSADOR_PUBLIC_IP=$(kubectl get services \
-l app=ambassador \
-o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}'); \
echo ${AMBASSADOR_PUBLIC_IP}
kurento-robot-camera-k8s$ az network dns record-set a add-record \
--resource-group ${DNS_ZONE_RG} \
--zone-name "${DOMAIN}" \
--record-set-name "loopback" \
--ipv4-address "${AMBASSADOR_PUBLIC_IP}"
kurento-robot-camera-k8s$ nslookup loopback.${DOMAIN}
WebRTCの動作確認
では最後に、このloopbackコンテナを使ってWebRTCの動作確認を行います。
loopback Web画面を表示
ChromeやFirefox等のモダンブラウザを立ち上げ、 https://loopback.${DOMAIN}
にアクセスしてください。API Gatewayと認証認可サービス、及びloopbackコンテナが正しく起動していれば、Basic認証の画面が表示されます。
secrets/auth-tokens.json
に定義されている username
と password
を使ってログインしてください。loopbackコンテナのWeb画面が表示されます。
シグナリング
Start
ボタンをクリックすると、loopbackコンテナを中心に、WebSocketを用いてブラウザとKurentoがSDPを交換します(この際に、coturnを使ってNAT越えのための情報を収集します)。
WebSocketで交換しているSDPの内容等は
Console
に出力されますので、興味があれば確認してください。
WebRTCによるブラウザ - Kurento間の経路確立
STUN & TURN Serverの情報をもとに最適な経路が確定すると、自動的にWebRTCによってSRTPによるMedia Streamが開設されます。
この図は、TURNサーバを経由せずにブラウザとKurentoが直結した場合です。
Web画面の左側の Local Stream
はカメラ映像そのもので、右側に表示される Remote Stream
はAzure AKS上のKurentoを経由して表示されています。
接続経路の確認
ブラウザの機能を用いて、ブラウザとKurentoが最終的にどのように接続されたのかを確認することができます。TURNサーバ経由で接続されてしまった場合は、TURNサーバのCPUを消費しますので、注意が必要です。
値 | 意味 |
---|---|
host | ローカルネットワークのIPとPortで接続 |
prflx | UDPホールパンチング中に発見された接続候補のIPとPortを元に接続 |
srlfx | STUN Serverを利用して入手したIPとPortを元に接続 |
relay | TURN Serverを中継して接続 |
Chromeの場合
chrome://webrtc-internals/
を開くと、結局どのような経路で接続されているのかがわかります。様々な経路候補の中から、最終的に選択された経路が 太字 の Conn-xxxx-x-x という項目でまとめられています。
そのうち、googLocalCandidateType
がブラウザ側から見た接続経路、 googRemoteCandidateType
がKurento側から見た接続経路になります。
Firefoxの場合
about:webrtc
を開くと、経路候補が表になって表示されます。最終的に選択された経路は、テーブル右端の選択がtrueとなっている経路です。 ローカル通信情報
がブラウザ側から見た接続経路、 リモート通信情報
がKurento側から見た接続経路になります。
この記事を書いたネットワーク環境では、UDPホールパンチングで発見した経路を使い、ブラウザとKurentoが直結したようです。
次回は
ここまででクラウド側は構築できました。次回はロボット側を構築し、Raspberry PiやROSロボットのカメラ映像をインターネット越しに視聴したいと思います。