Azure Kubernetes Service (AKS) でエグレス トラフィックを制限する - Azure Kubernetes Service | Microsoft Docs をベースに Eclipse Che をデプロイしたが、 Pod が Public IP へアクセスしたときのルーティングがうまくいかずに動作させることができなかった。
Eclipse Che のことは置いておくとして、 AKS と Firewall の組み合わせ手順の備忘。
前提条件
- OS: Windows 10 Pro
- Docker Desktop インストール済み
- DNS に
nip.io
を利用 - Docker: Docker version 20.10.5, build 55c4c88
- 使用イメージ: mikoto2000/aks-tools
作業用 Docker コンテナを起動
必要なツール類をインストール
bind-tools
dig を使うため。
chectl
デプロイに使用。
設定ファイル編集に使用
必要な azure-cli 拡張機能をインストール
作業手順
必要な情報の整理
# ログイン
az login
## 基本?情報
# サブスクリプション ID
SUBID=$(az account show --query id -o tsv)
PREFIX="eclipse-che1"
LOC="japaneast"
PLUGIN="azure"
# リソースグループ名
RG="${PREFIX}-rg"
# AKS 名
AKSNAME="${PREFIX}"
## 仮想ネットワーク
# AKS と Firewall を配置するサブネット
VNET_NAME="${PREFIX}-vnet"
# AKS 用サブネット名
AKSSUBNET_NAME="aks-subnet"
# Firewall 用サブネット名。 Azure Firewall の要件なので、名前の変更不可。
FWSUBNET_NAME="AzureFirewallSubnet"
## Firewall
# Firewall 名
FWNAME="${PREFIX}-fw"
# Firewall の外部 IP 名
FWPUBLICIP_NAME="${PREFIX}-fwpublicip"
# Firewall の設定情報名
FWIPCONFIG_NAME="${PREFIX}-fwconfig"
## ルーティングテーブル
# ルーティングテーブル名
FWROUTE_TABLE_NAME="${PREFIX}-fwrt"
# ルート名。 AKS から Firewall 内部 IP へのルーティング
FWROUTE_NAME="${PREFIX}-fwrn"
# ルート名。 Firewall インターネットへのルーティング
FWROUTE_NAME_INTERNET="${PREFIX}-fwinternet"
## プライベート DNS ゾーン
#PDZ_DOMAIN="nip.io"
#PDZ_LINK_NAME="${PREFIX}-pdz-link"
リソースグループの作成
仮想ネットワーク作成
仮想ネットワークと、 AKS 用サブネットの作成
az network vnet create \
--resource-group $RG \
--name $VNET_NAME \
--location $LOC \
--address-prefixes 10.42.0.0/16 \
--subnet-name $AKSSUBNET_NAME \
--subnet-prefix 10.42.1.0/24
仮想ネットワークに、 Firewall 用のサブネットを追加
az network vnet subnet create \
--resource-group $RG \
--vnet-name $VNET_NAME \
--name $FWSUBNET_NAME \
--address-prefix 10.42.2.0/24
Firewall を配置
Eclipse Che の出入り口となるパブリック IP アドレスを作成
Firewall を作成
以下コマンドで、 Firewall リソースを作成。
Firewall をサブネットへ配置してパブリック IP を割り当てる
以下コマンドで、サブネットへの配置と、パブリック IP の割り当てを実行。 この時点で Firewall のプライベート IP も自動生成される。
az network firewall ip-config create -g $RG -f $FWNAME -n $FWIPCONFIG_NAME --public-ip-address $FWPUBLICIP_NAME --vnet-name $VNET_NAME
生成された IP を記録
以下コマンドで、パブリック IP とプライベート IP を記録。
FWPUBLIC_IP=$(az network public-ip show -g $RG -n $FWPUBLICIP_NAME --query "ipAddress" -o tsv)
FWPRIVATE_IP=$(az network firewall show -g $RG -n $FWNAME --query "ipConfigurations[0].privateIpAddress" -o tsv)
ルーティングテーブル(UDR: User Defined Routing)の作成・設定
ルートテーブル作成
以下コマンドで、ルートテーブルを作成。
ルーティングルールを追加
ルートテーブルに、ルールを追加する。
ここの FW → インターネットのルーティングの意味が良くわかっていないが、こすると外向きの通信がインターネットへ届くようになるようだ。
# AKS 用サブネット → FW プライベート IP
az network route-table route create -g $RG --name $FWROUTE_NAME --route-table-name $FWROUTE_TABLE_NAME --address-prefix 0.0.0.0/0 --next-hop-type VirtualAppliance --next-hop-ip-address $FWPRIVATE_IP --subscription $SUBID
# FW → インターネット
az network route-table route create -g $RG --name $FWROUTE_NAME_INTERNET --route-table-name $FWROUTE_TABLE_NAME --address-prefix $FWPUBLIC_IP/32 --next-hop-type Internet
ルートテーブルを適用
仮想ネットワークにルートテーブルを適用する。
az network vnet subnet update -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --route-table $FWROUTE_TABLE_NAME
アクセス権設定
AKS が各種リソースを生成・配置できるように、権限を付与したサービスプリンシパルを作成しておく。
サービスプリンシパル作成
表示された appId
と password
を記録。
サービスプリンシパルにロールを設定
仮想ネットワークを操作できる権限を、サービスプリンシパルへ割り当てる。
VNETID=$(az network vnet show -g $RG --name $VNET_NAME --query id -o tsv)
az role assignment create --assignee $APPID --scope $VNETID --role "Network Contributor"
Firewall の規則を追加
先ほど生成された IP アドレスを使って、規則を作成する。
Azure Global に必要なネットワーク規則 を追加
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apiudp' --protocols 'UDP' --source-addresses '*' --destination-addresses "AzureCloud.$LOC" --destination-ports 1194 --action allow --priority 100
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apitcp' --protocols 'TCP' --source-addresses '*' --destination-addresses "AzureCloud.$LOC" --destination-ports 9000
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'time' --protocols 'UDP' --source-addresses '*' --destination-fqdns 'ntp.ubuntu.com' --destination-ports 123
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'aksfwar' -n 'fqdn' --source-addresses '*' --protocols 'http=80' 'https=443' --fqdn-tags "AzureKubernetesService" --action allow --priority 100
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'aksfwar' -n 'japaneast' --source-addresses '*' --protocols 'https=443' --target-fqdns 'japaneast.monitoring.azure.com'
Azure Monitor に必要な規則。
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'monitor' --protocols 'TCP' --source-addresses '*' --destination-addresses "AzureMonitor.$LOC" --destination-ports 443
コンテナイメージ Pull のために必要な規則。
# docker
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'docker-io' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns '*.docker.io' 'production.cloudflare.docker.com' --action allow --priority 200
# k8s.gcr.io
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'k8s-gcr-io' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'k8s.gcr.io' 'storage.googleapis.com'
# quay.io
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'quay-io' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'quay.io' '*.quay.io'
# registry.access.redhat.com
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'container-registry' -n 'registry-access-redhat-com' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'registry.access.redhat.com'
helm チャート取得のために必要な規則。
# grafan
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'che' -n 'grafan' --source-addresses '*' --protocols 'https=443' --target-fqdns 'grafana.github.io' --action allow --priority 300
# prometheus
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'che' -n 'prometheus' --source-addresses '*' --protocols 'http=80' 'https=443' --target-fqdns 'prometheus-community.github.io'
Theia プラグインダウンロードに必要な規則。
# github
az network firewall application-rule create -g $RG -f $FWNAME --collection-name 'theia-plugin' -n 'github-io' --source-addresses '*' --protocols 'https=443' --target-fqdns 'github.com' 'github-releases.githubusercontent.com' --action allow --priority 400
Kubernetes クラスターをデプロイする
AKS 用サブネットへ、 Kubernetes クラスターをデプロイする。
SUBNETID=$(az network vnet subnet show -g $RG --vnet-name $VNET_NAME --name $AKSSUBNET_NAME --query id -o tsv)
az aks create -g $RG -n $AKSNAME -l $LOC \
--node-vm-size Standard_DS2_v2 \
--node-count 1 \
--generate-ssh-keys \
--enable-addons monitoring \
--enable-managed-identity \
--network-plugin $PLUGIN \
--outbound-type userDefinedRouting \
--service-cidr 10.41.0.0/16 \
--dns-service-ip 10.41.0.10 \
--docker-bridge-address 172.17.0.1/16 \
--vnet-subnet-id $SUBNETID \
--service-principal $APPID \
--client-secret $PASSWORD
az aks get-credentials --name ${AKSNAME} --resource-group ${RG}
kubectl get pods -n kube-system
Ingress をデプロイ
helm が Kubernetes クラスタの API へアクセスできるように Firewall ルールを追加する
AKSFQDN=$(az aks show -g $RG -n $AKSNAME --query fqdn -o tsv)
AKSIP=$(dig $AKSFQDN +short)
az network firewall network-rule create -g $RG -f $FWNAME --collection-name 'aksfwnr' -n 'apiserver' --protocols 'TCP' --source-addresses '*' --destination-addresses "$AKSIP" --destination-ports 443
Ingress 用 Public IP の作成
INGRESS_IP_ADDRESS_NAME="${PREFIX}-ingresspublicip"
az network public-ip create -g $RG --name $INGRESS_IP_ADDRESS_NAME --sku Standard --allocation-method static
INGRESS_IP_ADDRESS=$(az network public-ip show -g $RG --name $INGRESS_IP_ADDRESS_NAME --query ipAddress -o tsv)
サービスプリンシパル作成
AKS_CLIENT_ID=$(az aks show -g $RG -n $AKSNAME --query "servicePrincipalProfile.clientId" -o tsv)
az role assignment create \
--assignee $AKS_CLIENT_ID \
--role "Network Contributor" \
--scope /subscriptions/$SUBID/resourceGroups/$RG
helm による Ingress デプロイ
DNS_LABEL="ingress"
kubectl create namespace ingress-nginx
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm upgrade --install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx \
--set controller.replicaCount=1 \
--set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
--set controller.admissionWebhooks.patch.nodeSelector."beta\.kubernetes\.io/os"=linux \
--set controller.service.loadBalancerIP="$INGRESS_IP_ADDRESS" \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="$DNS_LABEL" \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="$RG"
Ingress の EXTERNAL-IP
を記録。
INGRESS_IP=$(kubectl get services --namespace ingress-nginx -o jsonpath='{.items[].status.loadBalancer.ingress[0].ip}')
Firewall から Ingress へつなげる DNAT 設定を行う
az network firewall nat-rule create --collection-name ingress --destination-addresses $FWPUBLIC_IP --destination-ports 80 --firewall-name $FWNAME --name http --protocols Any --resource-group $RG --source-addresses '*' --translated-port 80 --action Dnat --priority 200 --translated-address $INGRESS_IP
az network firewall nat-rule create --collection-name ingress --destination-addresses $FWPUBLIC_IP --destination-ports 443 --firewall-name $FWNAME --name https --protocols Any --resource-group $RG --source-addresses '*' --translated-port 443 --translated-address $INGRESS_IP
この時点で $FWPUBLIC_IP
に接続すると、 NGINX の 404 Not Found
画面が表示される。
Eclipse Che のデプロイ
以降、 AKS 操作用 VM 上での作業。
Eclipse Che リポジトリのクローン
クローンして helm デプロイ用のディレクトリへ移動。
chectl による Eclipse Che のデプロイ
INGRESS_DOMAIN="$(echo $FWPUBLIC_IP | sed -e "s/\./-/g").nip.io"
chectl server:deploy -n che --installer=helm --platform=k8s --helm-patch-yaml=values.yaml --domain=webide.$INGRESS_DOMAIN --multiuser
以下のようなメッセージが表示される。
✔ Show important messages
✔ Eclipse Che 7.30.0-SNAPSHOT has been successfully deployed.
✔ Documentation : https://www.eclipse.org/che/docs/
✔ -------------------------------------------------------------------------------
✔ Users Dashboard : http://webide.20-48-87-43.nip.io
✔ Admin user login : "admin:admin". NOTE: must change after first login.
✔ -------------------------------------------------------------------------------
✔ Plug-in Registry : http://webide.20-48-87-43.nip.io/plugin-registry/v3
✔ Devfile Registry : http://webide.20-48-87-43.nip.io/devfile-registry
✔ -------------------------------------------------------------------------------
✔ Identity Provider URL : http://webide.20-48-87-43.nip.io/auth
✔ Identity Provider login : "admin:gOlU40cdAiKe".
✔ -------------------------------------------------------------------------------
✔ [ACTION REQUIRED] Please add Che self-signed CA certificate into your browser: /tmp/cheCA.crt.
Documentation how to add a CA certificate into a browser: https://www.eclipse.org/che/docs/che-7/end-user-guide/impor
ting-certificates-to-browsers/
Command server:deploy has completed successfully in 08:52.
http://webide.20-48-87-43.nip.io/dashboard
へログインして適当なワークスペースを起動してみる。
エラー。
デバッグ情報を表示して再挑戦。
values.yaml
の以下項目で変更できると思っていたのだけど、なぜか反映されなかった…。
logLevel: "INFO"
->logLevel: "DEBUG"
loggerConfig: ""
->loggerConfig: "org.eclipse.che.api.workspace.server.WorkspaceManager=DEBUG,che.infra.request-logging=DEBUG,org.eclipse.che.api.workspace.server.hc.HttpConnectionServerChecker=DEBUG"
なので、 ConfigMap を手動で修正する。
ConfigMap を以下のように修正。
CHE_LOG_LEVELL: INFO
->CHE_LOG_LEVELL: DEBUG
CHE_LOGGER_CONFIG: ""
->CHE_LOGGER_CONFIG: "org.eclipse.che.api.workspace.server.WorkspaceManager=TRACE,che.infra.request-logging=TRACE,org.eclipse.che.api.workspace.server.hc.HttpConnectionServerChecker=TRACE"
リスタート。
kubectl rollout restart -n che deployments/che
kubectl rollout restart -n che deployments/che-dashboard
kubectl rollout restart -n che deployments/devfile-registry
kubectl rollout restart -n che deployments/keycloak
kubectl rollout restart -n che deployments/plugin-registry
kubectl rollout restart -n che deployments/postgres
kubectl rollout restart -n ingress-nginx deployments/nginx-ingress-ingress-nginx-controller
今度は verbose mode でワークスペースを起動。
websocket 通信に、Firewall Public IP のアドレスが使われている。
Azure Firewall はプライベート IP からプライベート IP への DNAT に対応していないようだ…?
https://docs.microsoft.com/ja-jp/azure/firewall/overview#known-issues より
CHE_WEBSOCKET_ENDPOINT
, CHE_WEBSOCKET_ENDPOINT__MINOR
の変更でインターナル通信できるようだ…?
https://github.com/eclipse-che/che-operator/pull/685/files#diff-83745225d10c6e28020233af5d16a2fa740200d2e15f56a70f054c167a579812R182-R184
もういちど ConfigMap を修正してリスタート。
ConfigMap を以下のように修正。
CHE_WEBSOCKET_ENDPOINT: ws://webide.20-48-87-43/api/websocket
->CHE_WEBSOCKET_ENDPOINT: ws://che-host.che.svc:8080/api/websocket
CHE_WEBSOCKET_ENDPOINT__MINOR: ws://webide.20-48-87-43/api/websocket-minor
->CHE_WEBSOCKET_ENDPOINT__MINOR: ws://che-host.che.svc:8080/api/websocket-minor
websocket は通ったが、コンテナ起動ができていない。
ログを見てもよくわからないので、勘で single-host
から default-host
に変更してやってみた。
ConfigMap を以下のように修正。
CHE_INFRA_KUBERNETES_SERVER__STRATEGY: single-host
->CHE_INFRA_KUBERNETES_SERVER__STRATEGY: default-host
再実行。
うーん、ワークスペースは起動するが、そこへ接続するための URL が INGRESS の IP アドレスになっていて、ブラウザから届かない感じか。
これは分からん…。
参考資料
- Azure Kubernetes Service (AKS) でエグレス トラフィックを制限する - Azure Kubernetes Service | Microsoft Docs
- Azure Firewall を使用して Azure Kubernetes Service (AKS) のデプロイを保護する | Microsoft Docs
- プライベート Azure Kubernetes Service クラスターを作成する - Azure Kubernetes Service | Microsoft Docs
- docker - How to retry image pull in a kubernetes Pods? - Stack Overflow
- 静的 IP でイングレス コントローラーを使用する - Azure Kubernetes Service | Microsoft Docs
- Azure Kubernetes Service でマネージド ID を使用する - Azure Kubernetes Service | Microsoft Docs
0 件のコメント:
コメントを投稿