Azure Kubernetes Service(AKS)を構成するAzureリソース

#目次
1. 目的
2. 前提
3. AKSを操作する際のリソースの動き
4. AKSを構成するAzureリソース
5. まとめ

#1. 目的
この記事は [Microsoft Azure Tech Advent Calendar 2018](https://qiita.com/advent-calendar/2018/microsoft-azure-tech) の22日目の記事です。

2018年はAzure Kubernetes Service(AKS)[^1],Amazon Elastic Container Service for Kubernetes (Amazon EKS)[^2]などが一般提供となったりIBMのRedHat買収にKubernetesが鍵となっているように見られた[^3]り、様々な企業がKubernetesへの取り組みを強めた年だったと思います。この記事を読んでくださっている皆様の中にも、一度はkubectlコマンドを打ってみた方が多いのではないでしょうか。

この記事では、そんなKubernetesのプラットフォームの一つであるAzure Kubernetes Service(AKS)が、どのようなAzureリソースで構成されているのか、Azure視点で考えてみる記事です。
Azureインフラを現在運用されていて、「AKSを使ってみたいけど、Virtual NetworkとかVirtual Machineとかとどう絡んでいるんだろう」と考えている方や、
Kubernetesは利用されていて、「AKSを使う場合にどこに気を付けなくてはならないのだろう」と考えている方に、
特に役立てばいいなと思い書いています。

ゴールは、以下の図にある構成要素がどのようにAKSを構成しているか理解を深めてもらうことです。![1_component.png](https://qiita-image-store.s3.amazonaws.com/0/125247/2ca13f7b-bf84-7c35-6838-33dbe5ae008e.png)

#2. 前提
- Kubernetesの基礎知識(Podとは？Nodeとは？)にはこの記事では触れません。ただし、できる限り参考URLを載せるようにしているので、そこから基礎知識は参照できるようにしたいと思います。
- AKSのネットワークはkubenetを用いた"基本"ネットワークとAzure CNIを用いた"高度"ネットワークがある[^4]のですが、ここでは"高度"ネットワークを前提に紹介します。

#3. AKSを操作する際のリソースの動き
以下の6つを紹介します。リソースごとの深掘りは次の章で書きます。

- AKSクラスタを作成する
- PodがStorage Firewallを有効にしたAzure Fileをマウントする
- PodがAzure Container Registry(ACR)からimageをpullする
- クライアント(PCなど)がPodにアクセスする
- クライアント(PCなど)がKubernetesのAPIを呼ぶ
- 永続化ボリュームを作成する

##AKSクラスタを作成する
![2_FlowA1_CallARM.png](https://qiita-image-store.s3.amazonaws.com/0/125247/8246b8d6-6c39-bf36-5cac-b42910d3f5fc.png)
まずはお使いのPCなどのクライアントから[Azureポータル](https://portal.azure.com) からGUIで作ったり、Azure CLIコマンドで`az aks create` を実行したりして、Azure Resource Manager(ARM)のAPIが呼ばれます。これはAKSに限らず、Virutual MachineやVirtual NetworkなどAzureのリソースに対する操作では共通です。ここではARMはAzureリソースを操作するためにAzureが用意したAPIサーバだと思ってください。

![3_FlowA2_CreateSP.png](https://qiita-image-store.s3.amazonaws.com/0/125247/723527aa-f771-baf6-d39e-05315ce9aed3.png)
サービスプリンシパルはこの後もたびたび出てきますが**とても重要な構成要素**です。次の章で深掘りしますが、ここではAzureのリソースを操作するための認証情報と思ってください。

![4_FlowA3_CreateMaster.png](https://qiita-image-store.s3.amazonaws.com/0/125247/d6ac198f-751f-f387-2bfc-2374887dbf60.png)
'Master'というのはKubernetesの用語です。Kubernetesリソースを操作するためのAPIサーバ(kube-apiserver)など様々な役割があります。AzureではMasterはAzure側で管理されており、利用は無料です。そして、**このMasterはサービスプリンシパルのID/Passwordを持ちます。**

![5_FlowA4_CreateOthers.png](https://qiita-image-store.s3.amazonaws.com/0/125247/86b12e15-612c-6579-c75b-cbd83ef4a8a3.png)
それぞれの構成要素の働きは後述しますが、これらのリソースが作成されることでKubernetesを利用できる準備が整いました。ここでも大事なのが、**Agent NodeがサービスプリンシパルのID/Passwordを持つ**ことです。

##PodがStorage Firewallを有効にしたAzure Fileをマウントする
![6_FlowB_mountAzureFile.png](https://qiita-image-store.s3.amazonaws.com/0/125247/3a071f30-001b-f285-a4d1-bfa967d7d673.png)
AzureにはAzure FilesというサービスがありSMB, CIFSでの接続が可能です。Storage Firewallは指定したVirtual Networkのサブネットからのみアクセスを受け付けるなど、接続元の制限が可能です。AKSの[高度]ネットワーク[^4]においてPodはVirtual NetworkのIPアドレス帯に所属しています。
Virtual Machineも同じ方法で接続元を制限したAzure Filesへ接続できるように、上記方法でPodからの接続が可能になります。ここで伝えたかったのは、**Virtual Machineと近い感覚でできることは多い**、ということです。ただし**そうでないこともある**ので、Azure IaaS運用経験者がAKSを運用する場合は注意が必要です。
サービスエンドポイントについては特に解説しなかったのですが、詳細を学びたい方は[こちら](https://docs.microsoft.com/ja-jp/azure/virtual-network/virtual-network-service-endpoints-overview#securing-azure-services-to-virtual-networks)をご参照ください。

##PodがAzure Container Registry(ACR)からimageをpullする
![7_FlowC1_ACRlogin.png](https://qiita-image-store.s3.amazonaws.com/0/125247/7f7927f9-9edb-079b-74a3-8f519573159d.png)
Kubernetesを利用するうえで、Podが用いるDocker Containerのイメージ管理は重要です。AzureではプライベートレジストリとしてAzure Container Registry(ACR)が用意されています。プライベートレジストリですので、アクセス認証は重要となります。ここで、サービスプリンシパルを用いてログインを行うことが可能です。imagePullSecretを使用する[^5]ことも可能ですが、サービスプリンシパルにACRへのアクセス権限を与えておけば特に意識することなく認証が可能です。
![8_FlowC2_ACRpull.png](https://qiita-image-store.s3.amazonaws.com/0/125247/5de78297-a854-f158-6007-b23108f7889f.png)

##クライアント(PCなど)がPodにアクセスする
![9_FlowD_AccessFromClient.png](https://qiita-image-store.s3.amazonaws.com/0/125247/5a276ec6-c508-0ffc-8572-8a351f31064d.png)
PodはVirtual NetworkにプライベートIPアドレスを持っているので直接プライベートIPアドレスにsshなどもできますが、たとえばWebサーバなどを作ったらインターネットからアクセスすることが一般です。厳密にはPodにアクセスという表現は正しくなくKubernetesのネットワークは複雑なのですが、Azureから見た観点としては上記の画像のように、**Virtual Machineとあまり変わらず**、ロード バランサーやアプリケーション ゲートウェイ経由でアクセスを受けていると考えて問題ないと考えています。

## クライアント(PCなど)がKubernetesのAPIを呼ぶ
![10_FlowE_AccessToMaster.png](https://qiita-image-store.s3.amazonaws.com/0/125247/8e52b2d3-414e-a08a-cc3d-fae43b9744e2.png)
AKSごとにkube-apiserver用のエンドポイントが用意されており、そこへクライアントはアクセスが可能です。エンドポイントがどのように見えるかは後述します。

## 永続化ボリュームを作成する
![11_FlowF_CreatePV.png](https://qiita-image-store.s3.amazonaws.com/0/125247/ae0d0ef8-3bc6-5b96-d86a-ed7aba3cc87d.png)
永続化ボリューム(Persistent Volume)はKubernetesの用語です。ここではストレージのリソースと思ってください。Kubernetesで使用したいリソースはKubernetesのAPIで作成要求ができます。その裏側では、上記のように**サービスプリンシパルで認証してAzureのリソースが作成されています。**このように、サービスプリンシパルはKubernetesをAzure上で動かすAKSとして非常に重要な構成要素であることがわかるかと思います。

##ここまでのまとめ
KubernetesをAzure上で動かすAKSではサービスプリンシパルを使用してAzureのリソースを操作しています。これはKubernetesから見ると[Cloud Controller Manager](https://kubernetes.io/docs/concepts/architecture/cloud-controller/)というコンセプトにのっとっています。サービスプリンシパルはAKSを理解するうえで重要な要素です。
また、Azure FilesのマウントやクライアントからPodへのトラフィック経路などVirtual Machineと変わらない動きもあります。Azure IaaSエンジニアがAKSを利用する場合は何が同じで何が違うのか見極めていくと理解が容易になるかと思います。

#AKSを構成するAzureリソース
![12_ComponentNum.png](https://qiita-image-store.s3.amazonaws.com/0/125247/8cbc6951-9e80-731d-f601-852aca393403.png)
改めて、上記の7カテゴリに分けて紹介していきます。
なお、実際にAKSを作成された際は以下のように2つのリソースグループに分かれて配置されます。'MC_'とついているリソースグループに、追加のAgent NodeであるVirtual MachineやパブリックIPアドレスが配置されます。
<img width="796" alt="13_AKSRG.png" src="https://qiita-image-store.s3.amazonaws.com/0/125247/7cbad846-4848-c0fd-fbf5-d2cbc1153afb.png">
<img width="796" alt="14_MCRG.png" src="https://qiita-image-store.s3.amazonaws.com/0/125247/76b87edd-da87-29e0-ffa1-51b6b5f663d1.png">

##構成リソース1 サービスプリンシパル
サービスプリンシパルはAzureを操作するための認証情報です。Agent Nodeに格納されているサービスプリンシパルの情報は/etc/kubernetes/azure.jsonファイルに格納されています。下記のように、「実行コマンド」機能をAgent NodeのVirtual Machineに用いることで確認できます。
<img width="983" alt="15_showSP.png" src="https://qiita-image-store.s3.amazonaws.com/0/125247/dfe17940-6843-9011-c8d9-80aaba373718.png">

サービスプリンシパルを理解するには、上記で確認したサービスプリンシパルを用いてログインしてみるのが良いかもしれません。以下のコマンドでログインできます。

```shell-session
# az login --service-principal --username "サービスプリンシパルID" --password "サービスプリンシパルPassword" --tenant "テナント名"
```
<img width="931" alt="16_loginWithSP.png" src="https://qiita-image-store.s3.amazonaws.com/0/125247/6260f2e2-ef02-6154-6581-efc8b3a217cd.png">
これにより、サービスプリンシパルとして実際にAzureのリソースを操作することも可能です。「サービスプリンシパルはAzureを操作するための認証情報」をより理解できるのではないでしょうか。

サービスプリンシパルにどのような権限が割り当てられているか確認するには以下のコマンドで可能です。

```shell-session
# az role assignment list --assignee "サービスプリンシパルID" --all
```
##構成リソース2 Master
AKSではMasterはAzureにて管理されており、かつ無料です。ユーザはkube-apiserverのエンドポイントや認証情報を取得しすぐにKubernetesの操作に着手できます。エンドポイントは以下のように"API server address"で確認できます。
<img width="944" alt="17_AKSendpoint.png" src="https://qiita-image-store.s3.amazonaws.com/0/125247/c80c959e-4889-8c38-f25e-c74d538477c2.png">

認証情報の取得は以下のコマンドで可能です。
 
```shell-session
# az aks get-credentials -g "リソースグループ名" -n "AKS名"
```

##構成リソース3 Network
- Virtual Network: アドレス空間内にPodがプライベートIPアドレスを持ちます。他のVirtual Networkと接続したりVPN Gatewayを配置してオンプレミスなどとVPN接続することも可能です[^6]。
- NSG(Network Security Group): Virtual Network外との通信においてアクセス制御を行います。なお、KubernetesのNetwork Policy(Podのマイクロセグメンテーション)はNSGでの制御でなくKubernetesでの設定として行います[^7]。
- Load Balancer: Kubernetesのリソースである'Service'が追加された際はAzureではLoad Balancerのルールが更新されます。Public IPアドレスが追加となった際もLoad BalancerのIP構成として追加されます。
- Application Gateway: WAFなどをKubernetesが用いたい際に利用が可能です。また、Kubernetesのリソースである'Ingress Controller'としても利用できます[^8]。
- Azure DNS: AKSのアドオンである'HTTP アプリケーション ルーティング'を利用することで活用できます。このアドオンを用いると、Kubernetesで作成したIngressに対し外部から解決できる名前をAzure DNSに登録できます[^9]。

Load Balancerのルール更新などは、サービスプリンシパルを用いて行われます。

##構成リソース4 Virtual Machine
KubernetesのAgent NodeはVirtual Machineそのものであり、Podは狭義ではVirtual Machine上のDockerコンテナといえます。たとえばAgent NodeであるVirtual Machineにssh接続することで実際にDockerコンテナが動いていることなどもみられるかと思います[^10]。
AKSは管理されたKubernetesプラットフォームを目指しているため、Agent Nodeへの自動パッチあてなども行います。ただし、再起動はユーザにて必要となりますのでご注意ください[^11]。

##構成リソース5 Container Registry
フローでも紹介しましたが、Container Registryを利用するにはサービスプリンシパルを用いての認証が必要です。しかしながら、AKSを作成する際にAzure Container Registry(ACR)が一緒に作成されるわけではないので、**ユーザは自身でサービスプリンシパルへACRへの操作権限を与える必要があります。**ここがAKSを使い始めた方がよく躓くポイントです。[公式ドキュメント](https://docs.microsoft.com/ja-jp/azure/container-registry/container-registry-auth-aks)にも記載がありますので、ぜひ注意してみてください。
また、ACRはKubernetesの管理を行う上で重要なコンポーネントですので、多くの機能が日々開発され[^12]、またフィードバックも多く受けてます[^13]。

##構成リソース6 Storage
AKSのStorageとして用いられるのはManaged DiskとAzure Filesが多いです。Managed Diskは単一のVirtual Machineとしか接続ができないため単一のAgent Nodeからの接続に用いられ、Azure Filesは複数の接続が必要な際に用いられます[^14]。
バックアップが必要な際、現時点ではArkの利用が紹介されているようです[^15]。

##構成リソース7 その他
基本的な構成要素ではないと思うためこの記事では重点を置きませんが、その他のリソースがAKSの差別化要素だと考えています。是非注目してもらえればと思います。簡単に紹介します。

- Azure Container Instance(ACI): 単体ではdockerコンテナを稼働するAzureリソースに過ぎないのですが、Virtual Kubeletと組み合わせることでAKSのVirtual Nodeとして利用できます[^16]。構想としては、Agent Nodeをユーザが意識せず、欲しい時に必要なリソースのPodを秒課金で利用できる世界を目指しているようです[^17]。
- Azure DevOps: Visual Studio Team Service(VSTS)からリブランディングされました。これを用いることでAKSをCI/CDパイプラインへ容易に組み込めます[^18]。
- Azure Monitor for Container: Kubernetesを運用することを考えるとリソースや状態、ログの監視は不可欠です。AKSではAzureの監視サービスであるAzure Monitorとシームレスに統合しました[^19]。2018年のアドベントカレンダーでも一般提供開始についての記事が投稿されています[^20]。

個人の意見ですが、Kubernetesはオープンソースプラットフォームであるため、基本的にはどのクラウドプラットフォームで使用してもKubernetesであることに変わりはないと考えています。極論ですが、Linux仮想マシンをどのクラウドプラットフォームで使用してもLinuxであることに変わりはないことに似ています。しかし、上記のような機能があることでクラウドプラットフォームごとの違いが出てきて面白いのではないかと思います。なお、ACIとAKSを連携するためのVirtual Kubeletはオープンソースとして開発されており、CNCFのSandBox Projectにもなっていることも面白いかと思います[^21]。

#まとめ
AKSが関連するAzureリソースたちが、どのようにAKSに関わっているのかを紹介してみました。クラウドプラットフォームでKubernetesを利用する際はKubernetesのことだけでなく、各クラウドプラットフォームの特性なども知る必要が出てくると思います。この記事で少しでもAKSに親しみを持っていただけたら幸いです。
気になることなどありましたら是非コメント欄に記載ください。

# 脚注
[^1]: https://blogs.technet.microsoft.com/jpitpro/2018/06/15/azure-kubernetes-service-aks-ga-new-regions-new-features-new-productivity/
[^2]: https://aws.amazon.com/jp/blogs/news/amazon-eks-now-generally-available/
[^3]: http://ascii.jp/elem/000/001/770/1770551/
[^4]: https://docs.microsoft.com/ja-jp/azure/aks/concepts-network#azure-virtual-networks
[^5]: https://docs.microsoft.com/ja-jp/azure/container-registry/container-registry-auth-aks#access-with-kubernetes-secret
[^6]: https://docs.microsoft.com/ja-jp/azure/aks/configure-advanced-networking
[^7]: https://docs.microsoft.com/ja-jp/azure/virtual-network/kubernetes-network-policies
[^8]: https://docs.microsoft.com/ja-jp/azure/application-gateway/overview#azure-kubernetes-service-aks-ingress-controller-preview
[^9]: https://docs.microsoft.com/ja-jp/azure/aks/http-application-routing
[^10]: https://docs.microsoft.com/ja-jp/azure/aks/ssh
[^11]: https://docs.microsoft.com/ja-jp/azure/aks/faq#are-security-updates-applied-to-aks-agent-nodes
[^12]: https://azure.microsoft.com/ja-jp/updates/?product=container-registry
[^13]: https://feedback.azure.com/forums/903958-azure-container-registry
[^14]: https://docs.microsoft.com/ja-jp/azure/aks/operator-best-practices-storage
[^15]: https://docs.microsoft.com/ja-jp/azure/aks/operator-best-practices-storage#secure-and-back-up-your-data
[^16]: https://docs.microsoft.com/ja-jp/azure/aks/virtual-nodes-portal
[^17]: https://azure.microsoft.com/ja-jp/blog/bringing-serverless-to-azure-kubernetes-service/
[^18]: https://docs.microsoft.com/ja-jp/azure/devops-project/azure-devops-project-aks
[^19]: https://docs.microsoft.com/ja-jp/azure/azure-monitor/insights/container-insights-overview
[^20]: https://qiita.com/keikhara/items/8699d8e1fa45f2e61185
[^21]: https://www.cncf.io/sandbox-projects/