LoginSignup
16
13

More than 5 years have passed since last update.

「Virtual Kubelet」を使って、Azure Kubernetes Service (AKS)とAzure Container Instances (ACI)を連係する

Last updated at Posted at 2018-08-17

はじめに

去年から今年にかけて、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を組み合わせて使ってみた

(スライドの3~6枚目で ざっくりと 説明しています)



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マニフェストファイルを作成します。

rbac-config.yaml
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サービスで振り分けられるようにします。

aci-helloworld.yaml
---
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ブラウザで接続してみます。
helloworld
(以前のキャプチャなのでIPアドレスが違いますが気にしないで下さい)

ACIはどのようになっているか?

az aks install-connector コマンドの --aci-resource-group パラメータの項目で説明した通り、AKSクラスタ作成時に自動的に作成されるリソースグループ「MC_~」内にACIのリソースが作成されます。
aci-resources
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も本番リリースまでにはもっとシンプル・スマートな手順になっていることを期待しています。

16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13