はじめに
去年から今年にかけて、Azureの「Azure Container Instances (ACI)」、AWSの「Fargate」、GCPの「Serverless containers」などのサーバーレスコンテナプラットフォームが次々に発表/リリースされました。
かつ、各社のマネージドKubernetesサービス(AKS、EKS、GKE)とこれらのサーバーレスコンテナプラットフォームを連係するソリューションも提供が予定されています。
- AKS: マイクロソフトがOSSとして「Virtual Kubelet」を公開
- EKS: EKSにおけるFargateのサポートを2018年に開始する予定であると公表
- GKE: Serverless containersの発表と同時に「GKE serverless add-on」を発表
これらのうち、現時点で実際に触ってみることができるのは「Virtual Kubelet」です。
6月に一度試してみて、Azureのユーザーコミュニティ「JAZUG熊本 (くまあず)」で紹介させて頂いたのですが、その後、いくつか変更点があったようなので、その点を含めて再度試してみました。
Virtual Kubeletとは
もともと、ACIをAKSの仮想ノードとして利用できるようにするOSSとして、マイクロソフトが「ACI Connector for Kubernetes (aci-connector-k8s)」を公開していました。
これを、AKSのみでなく他のマネージドKubernetesサービスにも対応できるPluggableなOSSとして発展させたものが「Virtual Kubelet」です。
https://github.com/virtual-kubelet/virtual-kubelet
Virtual Kubeletを用いてAKSとACIがどのように連係して動作するのか、イメージを掴みたい方は、よろしければ「JAZUG熊本 (くまあず)」での私の発表スライドをご覧になって下さい。(手抜き)
SlideShare: AKSとACIを組み合わせて使ってみた
Virtual Kubelet導入手順
「Virtual Kubelet ACI provider」のドキュメント
https://github.com/virtual-kubelet/virtual-kubelet/tree/master/providers/azure
に記載されている手順に従って導入します。
ただし、内容が一部古い部分があるようですので、その点を解説しながら進めて行きます。
前提
- Microsoft Azureのアカウントを持っていること
は当然として、手元のPCに下記のツールがインストールされている必要があります。
- Azure CLI
- Kubernetes CLI (kubectl)
- Helm CLI
Helmは、Virtual Kubeletの設定コマンド( az aks install-connector
)の内部で使われます。
なお、Azure Cloud Shellであれば上記のツールは全てインストール済みですので楽チン(死語)です。
参考:私が試した時のバージョン
- Azure CLI : 2.0.44
- Kubernetes CLI: 1.11.0
- Helm CLI: 2.9.1
1. AKSクラスタの作成
AKSクラスタはGUI(Azure Portal)でも作成できますが、ここではAzure CLIでの作成手順を示します。
(1) リソースグループを作成する
AKS自体は既に日本(東日本リージョン)で利用可能ですが、ACIがまだ日本に来ていないため、今回は「米国西部(westus)」リージョンを使用することにします。
$ az group create -n myResourceGroup -l westus
(2) AKSクラスタを作成する
最低限、指定が必須なパラメータは「リソースグループ」「クラスタ名」です。
$ az aks create -g myResourceGroup -n myAksCluster
ワーカーノードのスペックについて、パラメータ省略時のデフォルトは以下のようになります。
- VMサイズ(
--node-vm-size
/-s
): Standard_DS1_v2 - ノード数(
--node-count
/-c
): 3
費用を節約したい場合はVMサイズをより小さいものにしたりノード数を「1」とかにしても問題ありませんが、余りにも低スペックのVMを指定すると(Standard_A0など)コマンドがエラーを返します。
【ワンポイント】 AKSクラスタ作成時の「RBAC有効/無効」の指定について
Azure CLIの バージョン2.0.40 (2018/7/3リリース) 以降、az aks create
コマンドでAKSクラスタを作成する際にデフォルトで「RBAC (ロールベースのアクセス制御)」が有効化されるようになりました。
(RBACを無効にしたい場合は明示的に --disable-rbac
を指定する必要あり)
RBACが有効/無効のどちらであるのかは、後の手順に影響してきます。
どちらでAKSクラスタが作成されるのかを意識しておきましょう。
(3) kubectlの設定を行い、AKSクラスタへ接続する
AKSクラスタが作成されたら、kubectlからAKSクラスタへ接続するために ~/.kube/config
ファイルを記述します。
手で書いてもよいですが、AKSの場合はコマンド一発で必要な情報をconfigに取り込んでくれるので楽チ・・・便利です。
$ az aks get-credentials -g myResourceGroup -n myAksCluster
Merged "myAksCluster" as current context in /home/user/.kube/config
設定が終わったら、ASKクラスタへ接続できることを確認しましょう。
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* myAksCluster myAksCluster clusterUser_myResourceGroup_myAksCluster
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
aks-nodepool1-38988403-0 Ready agent 6m v1.9.9 10.240.0.4 <none> Ubuntu 16.04.5 LTS 4.15.0-1018-azure docker://1.13.1
aks-nodepool1-38988403-1 Ready agent 6m v1.9.9 10.240.0.6 <none> Ubuntu 16.04.5 LTS 4.15.0-1018-azure docker://1.13.1
aks-nodepool1-38988403-2 Ready agent 6m v1.9.9 10.240.0.5 <none> Ubuntu 16.04.5 LTS 4.15.0-1018-azure docker://1.13.1
2. Helmの設定
(1) AKSクラスタを「RBAC無効」で作成した場合
この場合は、単純に helm init
コマンドを実行するだけです。
$ helm init
Creating /home/user/.helm
Creating /home/user/.helm/repository
Creating /home/user/.helm/repository/cache
Creating /home/user/.helm/repository/local
Creating /home/user/.helm/plugins
Creating /home/user/.helm/starters
Creating /home/user/.helm/cache/archive
Creating /home/user/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /home/user/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!
(2) AKSクラスタを「RBAC有効」で作成した場合
この場合は、Helmのドキュメントにある通り、追加の手順が必要です。
https://github.com/helm/helm/blob/master/docs/rbac.md
まず、以下のKubernetesマニフェストファイルを作成します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
マニフェストからServiceAccount(およびClusterRoleBinding)リソースを作成します。
$ kubectl apply -f rbac-config.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created
作成したServiceAccountを指定してHelmの初期化を行います。
$ helm init --service-account tiller
Creating /home/user/.helm
Creating /home/user/.helm/repository
Creating /home/user/.helm/repository/cache
Creating /home/user/.helm/repository/local
Creating /home/user/.helm/plugins
Creating /home/user/.helm/starters
Creating /home/user/.helm/cache/archive
Creating /home/user/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /home/user/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!
3. Virtual Kubeletのインストール
Virtual Kubeletのインストールは az aks install-connector
コマンドで行います。
ここでも最低限指定が必須なパラメータは「リソースグループ」「クラスタ名」のみです。
$ az aks install-connector -g myResourceGroup -n myAksCluster
その他の主なパラメータは、以下の通りです。
-
--connector-name
- ACI Connectorの名前を指定します。
以前は省略不可でしたが、現在では省略可能となっており、省略時にはデフォルトで「aci-connector」という名前が付けられます。
-
--os-type
- 使用するACIのOSタイプを「Linux」「Windows」「Both」から選択して指定します。(Bothの場合は両方が選択される)
省略時のデフォルトは「Linux」です。
-
--aci-resource-group
- ACIのデプロイ先リソースグループを指定します。
デフォルトでは、AKSクラスタ作成時に自動的に作成される「MC_~」で始まるリソースグループが指定されます。
ドキュメントには「Azure CLIのバグのため、このパラメータは明示的に指定する必要がある(省略できない)」とありますが、現在ではこのバグは解消されているようです。
az aks install-connector
コマンドの実行結果は以下のようになります。
$ az aks install-connector -g myResourceGroup -n myAksCluster
Merged "myAksCluster" as current context in /tmp/tmp4yibmvpa
Deploying the ACI connector for 'Linux' using Helm
NAME: aci-connector-linux-westus
LAST DEPLOYED: Thu Aug 16 12:44:12 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Secret
NAME TYPE DATA AGE
aci-connector-linux-westus-virtual-kubelet-for-aks Opaque 3 1s
==> v1/ServiceAccount
NAME SECRETS AGE
aci-connector-linux-westus-virtual-kubelet-for-aks 1 1s
==> v1beta1/ClusterRoleBinding
NAME AGE
aci-connector-linux-westus-virtual-kubelet-for-aks 1s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
aci-connector-linux-westus-virtual-kubelet-for-aks 1 1 1 0 1s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
aci-connector-linux-westus-virtual-kubelet-for-aks-7f6589dhzmht 0/1 ContainerCreating 0 1s
NOTES:
The virtual kubelet is getting deployed on your cluster.
To verify that virtual kubelet has started, run:
kubectl --namespace=default get pods -l "app=aci-connector-linux-westus-virtual-kubelet-for-aks"
Note:
TLS key pair not provided for VK HTTP listener. A key pair was generated for you. This generated key pair is not suitable for production use.
user@Azure:~/aks-virtualkubelet$
【ワンポイント】 az aks install-connectorコマンドでエラーとなってしまった場合
「2. Helmの設定」において、AKSクラスタでRBACが有効であるのにもかかわらず helm init
(オプション無し)で初期化してしまった場合、az aks install-connector
コマンドの実行時に以下のようなエラーとなってしまいます。
Error: release myconnector-linux-westus failed: namespaces "default" is forbidden: User "system:serviceaccount:kube-system:default" cannot get namespaces in the namespace "default"
こうなってしまった場合は、一度 helm reset --force
コマンドでHelm環境をリセットした後、「(2) AKSクラスタを「RBAC有効」で作成した場合」からやり直しましょう。
4. インストール後の確認
さて、ここまででVirtual Kubeletの導入は終わりです。
ノードの一覧を確認してみましょう。
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
aks-nodepool1-38988403-0 Ready agent 13m v1.9.9 10.240.0.4 <none> Ubuntu 16.04.5 LTS 4.15.0-1018-azure docker://1.13.1
aks-nodepool1-38988403-1 Ready agent 13m v1.9.9 10.240.0.6 <none> Ubuntu 16.04.5 LTS 4.15.0-1018-azure docker://1.13.1
aks-nodepool1-38988403-2 Ready agent 13m v1.9.9 10.240.0.5 <none> Ubuntu 16.04.5 LTS 4.15.0-1018-azure docker://1.13.1
virtual-kubelet-aci-connector-linux-westus Ready agent 45s v1.8.3 10.244.2.3 <none> <unknown> <unknown> <unknown>
既にある3つの物理ノード(aks-nodepool1-~)に加えて、4番目のノード(仮想ノード)として「virtual-kubelet-aci-connector-linux-westus」が作成されたことが分かります。
ついでに、デプロイされたACI Connector/Virtual Kubeletの実体を確認してみましょう。
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE
pod/aci-connector-linux-westus-virtual-kubelet-for-aks-7f6589dhzmht 1/1 Running 0 1m 10.244.2.3 aks-nodepool1-38988403-2
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 14m <none>
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.extensions/aci-connector-linux-westus-virtual-kubelet-for-aks 1 1 1 1 1m aci-connector-linux-westus-virtual-kubelet-for-aks microsoft/virtual-kubelet:latest app=aci-connector-linux-westus-virtual-kubelet-for-aks
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.extensions/aci-connector-linux-westus-virtual-kubelet-for-aks-7f6589df64 1 1 1 1m aci-connector-linux-westus-virtual-kubelet-for-aks microsoft/virtual-kubelet:latest app=aci-connector-linux-westus-virtual-kubelet-for-aks,pod-template-hash=3921458920
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/aci-connector-linux-westus-virtual-kubelet-for-aks 1 1 1 1 1m aci-connector-linux-westus-virtual-kubelet-for-aks microsoft/virtual-kubelet:latest app=aci-connector-linux-westus-virtual-kubelet-for-aks
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/aci-connector-linux-westus-virtual-kubelet-for-aks-7f6589df64 1 1 1 1m aci-connector-linux-westus-virtual-kubelet-for-aks microsoft/virtual-kubelet:latest app=aci-connector-linux-westus-virtual-kubelet-for-aks,pod-template-hash=3921458920
「default」ネームスペースにデプロイされていますし(kube-systemとかの方がいいと思うのですが・・・)、レプリカ数は「1」となっています。
このあたりはHelmのチャートを書き換えれば変更できそうではありますが、Virtual Kubelet自体が「プレビュー中 (本番環境には推奨しない)」となっているため、正式リリースまでには見直されるのかもしれません。
動作確認
作成したVirtual Kubelet環境にポッドをデプロイして、動作を確認してみます。
ドキュメントにある「virtual-kubelet-test.yaml」をそのまま実行してもよいのですが、どうせなら複数個のポッドをデプロイした時にACIがどのように展開されるのかを見てみましょう。
マニフェストの記述方法
レプリカ数「3」のポッドをデプロイするDeploymentを記述し、LoadBalancerサービスで振り分けられるようにします。
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: aci-helloworld
spec:
replicas: 3
selector:
matchLabels:
app: aci-helloworld
template:
metadata:
labels:
app: aci-helloworld
spec:
containers:
- name: aci-helloworld
image: microsoft/aci-helloworld
ports:
- containerPort: 80
nodeSelector:
kubernetes.io/hostname: virtual-kubelet-aci-connector-linux-westus
tolerations:
- key: azure.com/aci
effect: NoSchedule
---
apiVersion: v1
kind: Service
metadata:
name: aci-helloworld-lb
spec:
type: LoadBalancer
selector:
app: aci-helloworld
ports:
- protocol: TCP
port: 80
targetPort: 80
Virtual Kubeletを使って仮想ノード(ACI)上にポッドをデプロイする際のポイントは、以下の記述です。
nodeSelector:
kubernetes.io/hostname: virtual-kubelet-aci-connector-linux-westus
tolerations:
- key: azure.com/aci
effect: NoSchedule
Virtual Kubeletでは、「kube-proxy」等のシステム上重要なポッドあるいはVirtual Kubelet自身のポッドが意図せず仮想ノードで実行されることを避けるため、「Taints」が設定されています。
(Taintsについての詳細はKubernetes公式ドキュメントを参照して下さい)
意図して仮想ノード上へポッドを配置したい場合は、「nodeSelector:」および「tolerations:」を上記のように記述する必要があります。
それぞれの記述の意味は以下の通りです。
- 「nodeSelector:」
- ポッドの配置先を特定のホスト名を持つノードに限定します。
物理ノードへ配置させないための指定とも言えます。
仮想ノードのホスト名はkubectl get nodes
で確認できますが、デフォルトに従って手順を進めた場合は「virtual-kubelet-aci-connector-linux-westus」となっているはずです。
- 「tolerations:」
- 前述の通り、仮想ノードには「Taints」が指定されているため、「Taints」の指定を無視して強制的にポッドを配置させるための設定です。
【ワンポイント】 「tolerations:」の記述方法について
ドキュメントでは「tolerations:」を次のように記述するよう書かれています。
tolerations:
- key: virtual-kubelet.io/provider
value: azure
effect: NoSchedule
より汎用的な記述方法にした、ということのようですが、現時点で「virtual-kubelet-for-aks」にはまだ反映されていないようです。
実際、仮想ノードのTaintsを確認してみると以下のようになっています。
$ kubectl describe node/virtual-kubelet-aci-connector-linux-westus
Name: virtual-kubelet-aci-connector-linux-westus
(中略)
Taints: azure.com/aci:NoSchedule
(後略)
現時点では古い記述方法「key: azure.com/aci」にしておきましょう。(近々変更されるものと思われます)
ポッドのデプロイ
それでは、ポッド(およびサービス)をデプロイします。
$ kubectl apply -f aci-helloworld.yaml
deployment.apps/aci-helloworld created
service/aci-helloworld-lb created
ポッドが以下のように配置・実行されていれば成功です。
NODE欄が「virtual-kubelet-aci-connector-linux-westus」となっているのが確認できます。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
aci-connector-linux-westus-virtual-kubelet-for-aks-7f6589dhzmht 1/1 Running 0 7m 10.244.2.3 aks-nodepool1-38988403-2
aci-helloworld-674f5554bd-57z7g 1/1 Running 0 2m 40.78.0.207 virtual-kubelet-aci-connector-linux-westus
aci-helloworld-674f5554bd-jkw2z 1/1 Running 0 2m 104.42.184.78 virtual-kubelet-aci-connector-linux-westus
aci-helloworld-674f5554bd-nbn2r 1/1 Running 0 2m 40.78.61.148 virtual-kubelet-aci-connector-linux-westus
もし、ポッドのSTATUSがいつまで経っても「Pending」となっている場合は、「nodeSelector:」および「tolerations:」の設定が間違っている可能性が大です。(行き場の無いポッドが「待ち」状態に陥っている)
マニフェストの記述内容を見直してみて下さい。
Virtual Kubeletと直接関係しませんが、LoadBalancerサービスの方は以下のようになっていればOKです。
EXTERNAL-IPが取得されるまで結構時間がかかる場合があるので、気長に待ちましょう。
$ kubectl get services -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
aci-helloworld-lb LoadBalancer 10.0.33.249 104.210.56.69 80:32172/TCP 3m app=aci-helloworld
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 20m <none>
ここまで出来たら、LoadBalancerサービスの「EXTERNAL-IP」欄に表示されているIPアドレスに対して、Webブラウザで接続してみます。
(以前のキャプチャなのでIPアドレスが違いますが気にしないで下さい)
ACIはどのようになっているか?
az aks install-connector
コマンドの --aci-resource-group
パラメータの項目で説明した通り、AKSクラスタ作成時に自動的に作成されるリソースグループ「MC_~」内にACIのリソースが作成されます。
1つのポッドにつき1つのACIリソースが作成されていることが確認できます。
リソース名は、Kubernetesの「ネームスペース名」+「ポッド名」が付与されていることが分かります。
CLIでも確認してみましょう。
$ az container list -g MC_myResourceGroup_myAksCluster_westus -o table
Name ResourceGroup ProvisioningState Image IP:ports CPU/Memory OsType Location
--------------------------------------- -------------------------------------- ------------------- ------------------------ ---------------- --------------- -------- ----------
default-aci-helloworld-674f5554bd-57z7g MC_myResourceGroup_myAksCluster_westus Succeeded microsoft/aci-helloworld 40.78.0.207:80 1.0 core/1.5 gb Linux westus
default-aci-helloworld-674f5554bd-jkw2z MC_myResourceGroup_myAksCluster_westus Succeeded microsoft/aci-helloworld 104.42.184.78:80 1.0 core/1.5 gb Linux westus
default-aci-helloworld-674f5554bd-nbn2r MC_myResourceGroup_myAksCluster_westus Succeeded microsoft/aci-helloworld 40.78.61.148:80 1.0 core/1.5 gb Linux westus
IPアドレスがグローバル(パブリック)であることが確認できます。
そうです、パブリックIPアドレス なのです。ですので、ACIのIPアドレスを直接指定してもアクセスできてしまいます。
これをプライベートIPアドレスにすることができるのかどうか・・・については、すみません、調べきれていません。
(まあ、ACIはもともと単体で外部から利用できるコンテナサービスであるため、仕方ないのかもしれません)
また、CPU/メモリのスペックも確認できます。
このあたりを指定したい場合は、マニフェストに明示的に記述しましょう。
おわりに
Kubernetesとサーバーレスコンテナプラットフォームの連係(融合?)として期待できるVirtual Kubeletですが、現在はプレビュー段階ということもあり「Azure CLI一発では導入できない(Helmの初期化等が必要)」「仕様がちょくちょく変わっていく」といった点が見受けられます。
ただ、AKSリリース時のUI(Azure Portal/Azure CLI)の完成度などを考えると、Virtual Kubeletも本番リリースまでにはもっとシンプル・スマートな手順になっていることを期待しています。