Azure Kubernetes Serviceデプロイしたらvirtual-nodeが機能しなかったので対応メモ

virtual-nodeアドオンは、Azure Container InstancesをAKS(Azure Kubernetes Service)の仮想ノードとして利用できる便利な機能です。

azure.microsoft.com

Azureのウィザードで作成している分には問題無く動いていたのですが、環境構築をTerraform化した際に理解不足から動かない部分が出てきたので、その対応のメモです。(Terraformに問題があったわけではありません)

virtual-node-aci-linuxが機能していない

Terraformの定義を作ってデプロイ。デプロイが通ったので内容を確認していたら、nodeとしてアサインされているはずの virtual-node-aci-linux が無いことに気付きました。

$ kubectl get nodes
NAME                              STATUS   ROLES   AGE   VERSION
aks-default-12077424-vmss000000   Ready    agent   78m   v1.16.7

サブネット設定を確認

ググって見ると同じような事象が発生している人もいて、その対応メモから、最初はSubnetNameのところにサブネット名でなくリソースのID(例: /subscriptions/.../aci-virtualnode-subnet )を入れてしまうミスを見つけたので、そこを直しました。

$ az aks show -g ${rg} -n ${akscluster}
#--- 省略
    "aciConnectorLinux": {
      "config": {
        "SubnetName": "my-vnode-snet"
      },
      "enabled": true,
      "identity": null
    },
#--- 省略

Service Principalの権限の確認

それでも起動しない。virtual-nodeの機能のログを確認してみることにしました。

aci-connector-linux-xxx という名前のpodでkube-systemにデプロイされています。

見てみるとステータスが CrashLoopBackOff となっていました。

$ kubectl get po -n kube-system
NAMESPACE     NAME                                                              READY   STATUS             RESTARTS   AGE
kube-system   aci-connector-linux-6d84cd8f4d-cb8nr                              0/1     CrashLoopBackOff   5          5m40s
kube-system   addon-http-application-routing-default-http-backend-7fc6fcfbjcz   1/1     Running            0          79m
#--- 省略

ログを確認してみるとネットワーク読み込み権限が足りないようです。

$ kubectl logs -n kube-system aci-connector-linux-6d84cd8f4d-cb8nr
Error: error initializing provider azure: error setting up network profile: error while looking up subnet: api call to https://management.azure.com/subscriptions/xxxx-xxxx-xxx/resourcegroups/rg/providers/Microsoft.Network/virtualNetworks/network/subnets/virtual-node-subnet?api-version=2018-08-01: got HTTP response status code 403 error code "AuthorizationFailed": The client 'xxxx-xxxx-xxx' with object id 'xxxx-xxxx-xxx' does not have authorization to perform action 'Microsoft.Network/virtualNetworks/subnets/read' over scope '/subscriptions/xxxx-xxxx-xxx/resourcegroups/rg/providers/Microsoft.Network/virtualNetworks/network/subnets/virtual-node-subnet' or the scope is invalid. If access was recently granted, please refresh your credentials.
#--- 省略

AKSにアサインしているService Principalに仮想ネットワークの読み込み権限を付与します。

後は以下のようにAddonを無効化⇒有効化するか、クラスタを再構築します。

az aks disable-addons  -g ${rg} -n ${akscluster} --addons virtual-node
az aks enable-addons  -g ${rg} -n ${akscluster} --addons virtual-node --subnet virtual-node-subnet

これでvirtual-nodeが使えるようになりました。

$ kubectl get nodes
NAME                              STATUS   ROLES   AGE    VERSION
aks-default-12077424-vmss000000   Ready    agent   93m    v1.16.7
virtual-node-aci-linux            Ready    agent   108s   v1.14.3-vk-azure-aci-v1.2.1

TerraformでService Principalに権限設定する

TerraformでのService Principalへの権限設定例も書いておきます。

まず、Service PrincipalのオブジェクトIDを取得します。(Application IDではないので注意)

Azure ADのエンタープライズアプリケーションの部分でオブジェクトIDとして確認することが可能です。 f:id:yomon8:20200331133008p:plain

または、azure cliでも以下のように取得できます。

az ad sp show --id http://${YOUR_SP_NAME} --query 'objectId'
"d3edxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"

後はtfファイルに以下のように設定入れます。

resource "azurerm_role_assignment" "sp_network_role_assignment" {
  scope                = azurerm_virtual_network.your_cluster_network.id
  role_definition_name = "Reader"
  principal_id         = "d3edxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
}

AzureマネージドID(MSI)の場合

MSIが有効化されているクラスタでvirtual-nodeを有効化すると、 MC_ 始まりのリソースグループ内にある aciconnectorlinux-<clustername> が対象のIDになりますので、こちらに権限を付与します。

ただ、 az aks enable-addons --addons virtual-node で有効化した直後はMSIに権限が無いのでエラーになってしまいます。

$ kubectl get po -n kube-system
NAME                                   READY   STATUS             RESTARTS   AGE
aci-connector-linux-659864bcc7-6nb69   0/1     CrashLoopBackOff   1          12s

その場合は以下のコマンドで aci-connector-linux を再起動してあげます。

$ kubectl rollout restart deployment -n kube-system aci-connector-linux

後はこちらを参考にPodをデプロイすれば、以下のように確認できます。

$ kubectl get po -o wide
NAME                              READY   STATUS       RESTARTS   AGE     IP           NODE                     NOMINATED NODE   READINESS GATES
aci-helloworld-5c6bf56994-dl69z   1/1     Running      0          14m     10.240.2.4   virtual-node-aci-linux   <none>           <none>