Help us understand the problem. What is going on with this article?

Virtual Kubelet CRI Provider

はじめに

最近Edge Computingに漠然とした興味があります。
Edgeっていう響きが、なんかカッコいい。
k3skubeedgeの登場により、KubernetesのEdge Computingでの利用・応用というアプローチが登場してきています。
KubeCon + CloudNativeCon North America 2019ではコネクテッドカーへの応用という新しいアプローチも発表されていました。
世間的にはローカル5Gなどの動きが出てきている中、クラウドとの連携、Edge Computingに対するアプリケーションのデプロイ、ワークロードの管理といった領域は様々な技術が複合する必要があり、これから色々な業界で盛り上がることは間違いないでしょう。
そんな状況の中、本記事ではVirtual KubeletのCRI Providerに触れてみました。

Virtual Kubeletとは

Virtual Kubeletをご存知でしょうか?
これは、Kubernetesの各Nodeで稼働するコンポーネントであるkubelet1を装う、仮のkubeletです。
Virtual Kubeletで検索すると、すでに運用しているKubernetesクラスタに対し、Serverlessプラットフォームで提供されるNodeをKubernetesクラスタに追加する事例がよくヒットします。
Kubernetesクラスタをインターネットサービスで使っている時、トラフィックがバーストするタイミングが事前にわかる場合、事前にKubernetesクラスタのWorkerをスケールアウトし、Podを増やすことをよくします。
Virtual KubeletはServerlessプラットフォームと連携し、プラットフォームが払い出した一時的なVM/コンテナで、KubernetesのNodeとして振る舞うことができます。また、KubernetesのNodeとして機能するため、APIやCLIによる操作を受付け、Podのデプロイができます。
バーストへの対策や、WorkerのVM自体を運用したくないケースでの利用が考えられます。
またバッチ処理だけ実行したい場合、かつVMは運用したくない場合などの利用も考えられます。

さて、Virtual KubeletのレポジトリのREADMEには冒頭に以下が記載されています。

Virtual Kubelet is an open source Kubernetes kubelet implementation that masquerades as a kubelet for the purposes of connecting Kubernetes to other APIs. This allows the nodes to be backed by other services like ACI, AWS Fargate, IoT Edge etc. The primary scenario for VK is enabling the extension of the Kubernetes API into serverless container platforms like ACI and Fargate, though we are open to others. However, it should be noted that VK is explicitly not intended to be an alternative to Kubernetes federation.

IoT Edgeとあります。が、Azure IoT Edgeを意味しているようです。
Kubernetesクラスタを他のServerlessプラットフォームに拡張するのが主なシナリオであり、複数のKubernetesクラスタを一元管理するFederationの代替ではないとあります。
ServerlessなContainerプラットフォームでの利用が主な用途なのでしょう。

Virtual Kubelet Provider

Virtual Kubeletを実行するには提供されているProviderを使うもしくは自作する必要があります。

  • 公式Provider 2
    • Alibaba Cloud Elastic Container Instance (ECI)
    • AWS Fargate
    • Azure Batch
    • Azure Container Instances (ACI)
    • Kubernetes Container Runtime Interface (CRI)
    • Huawei Cloud Container Instance (CCI)
    • HashiCorp Nomad
    • OpenStack Zun
  • 自作例

さて、私が興味を持ったのは、Virtual Kubeletではありません。興味の矛先はEdge Computingです。またAzure IoT Edge Connectorなど特定のサービスに依存したくはありませんでした。
そこで、Kubernetes Container Runtime Interface (CRI) Providerが提供されていることに着目しました。
これがあれば、Raspberry PIのようなシングルボードコンピュータとの連携もでき、IoTやEdge Computingでの活用もあり得るのではないか、そういう淡い期待を抱きました。

CRI Providerを試す

さっそく触ってみましょう。
今回はお試しということで、すべてローカル環境で完結させました。

  • 環境(Mac)
    • K8s
      • minikube v1.5.2
        • K8s 1.16.2 on VirtualBox 6.0
    • Virtual Kubelet
      • ubuntu-16.04 on VirtualBox 6.0
    • その他
      • Vagrant 2.2.6

Kubernetesクラスタのセットアップ

Mac
# VirtualBox間で相互接続できるよう、HyperKitではなく、VirtualBoxを使います
$ minikube start --vm-driver=virtualbox
$ kubectl get no
NAME       STATUS   ROLES    AGE    VERSION
minikube   Ready    master   9m9s   v1.16.2

Virtual Kubeletのセットアップ

Mac
# Vagrant BoxでサクッとVM作ります
$ vagrant init ubuntu/xenial64
$ vim Vagrantfile
# 以下を変更。minikubeとVirtual Boxで作るVMが相互アクセスできるNWになるよう、ホストオンリーアダプターを設定
35c35
<   # config.vm.network "private_network", ip: "192.168.33.10"
---
>   config.vm.network "private_network", ip: "192.168.33.10"

$ vagrant up

Virtual Kubelet用証明書、設定ファイルのコピー。
今回はお試しなのでminikubeのクライアント証明書をそのままVirtual Kubeletにコピーして利用します。

Mac
$ minikube ssh sudo cat /etc/kubernetes/admin.conf > admin.conf
$ vagrant upload admin.conf
$ vagrant upload `kubectl config view -o jsonpath='{.users[?(@.name=="minikube")].user.client-key}'` client.key
$ vagrant upload `kubectl config view -o jsonpath='{.users[?(@.name=="minikube")].user.client-certificate}'` client.crt

Virtual Kubelet CRI Providerを実行するには、CRI, CNIのセットアップおよびgoでのビルドが必要です。

ubuntu
### CRIのセットアップ
$ VERSION=1.3.0
$ wget https://storage.googleapis.com/cri-containerd-release/cri-containerd-${VERSION}.linux-amd64.tar.gz
#### checksum確認
$ sha256sum cri-containerd-${VERSION}.linux-amd64.tar.gz
$ curl https://storage.googleapis.com/cri-containerd-release/cri-containerd-${VERSION}.linux-amd64.tar.gz.sha256
$ sudo tar --no-overwrite-dir -C / -xzf cri-containerd-${VERSION}.linux-amd64.tar.gz

### CNIのセットアップ
$ wget https://github.com/containernetworking/plugins/releases/download/v0.8.2/cni-plugins-linux-amd64-v0.8.2.tgz

$ sudo mkdir -p \
  /etc/cni/net.d \
  /opt/cni/bin
$ sudo tar -xvf cni-plugins-linux-amd64-v0.8.2.tgz -C /opt/cni/bin/

#### bridge
$ POD_CIDR=10.128.0.0/16
$ cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf
{
    "cniVersion": "0.3.1",
    "name": "bridge",
    "type": "bridge",
    "bridge": "cnio0",
    "isGateway": true,
    "ipMasq": true,
    "ipam": {
        "type": "host-local",
        "ranges": [
          [{"subnet": "${POD_CIDR}"}]
        ],
        "routes": [{"dst": "0.0.0.0/0"}]
    }
}
EOF

#### loopback
$ cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf
{
    "cniVersion": "0.3.1",
    "name": "lo",
    "type": "loopback"
}
EOF

### Containerd起動
$ sudo systemctl start containerd

### Golangセットアップ
$ sudo add-apt-repository ppa:longsleep/golang-backports
$ sudo apt-get update
$ sudo apt-get install -y golang-go

### Virtual Kubelet CRI Providerのビルド
$ git clone https://github.com/virtual-kubelet/cri.git
$ cd cri
$ make build && mv bin ../ && cd ..

### kube-apiserverアクセス用client証明書のコピー
$ sudo mkdir /etc/virtual-kubelet
$ sudo mv client.key /etc/virtual-kubelet/client.key
$ sudo mv client.crt /etc/virtual-kubelet/client.crt

### 起動スクリプトの作成
# admin.confのIPをminikubeのホストIPに置換
$ sed -i -e 's/localhost/192.168.99.105/g' ./admin.conf

# 以下、起動スクリプトの準備。VirtualBoxのIPアドレスに合わせて変更
cat << EOF | tee startup.sh
#!/bin/bash
# VM Host IP
export VKUBELET_POD_IP=192.168.33.10
export APISERVER_CERT_LOCATION="/etc/virtual-kubelet/client.crt"
export APISERVER_KEY_LOCATION="/etc/virtual-kubelet/client.key"
export KUBELET_PORT="10250"
export KUBERNETES_SERVICE_PORT="8443"

# minikube Host IP
export KUBERNETES_SERVICE_HOST=192.168.99.105
cd bin
./virtual-kubelet --provider cri --kubeconfig ../admin.conf
EOF

$ chmod +x startup.sh
$ sudo ./startup.sh

動作確認

Mac
# Virtual Kubeletの追加を確認
$ kubectl get no
NAME              STATUS   ROLES    AGE   VERSION
minikube          Ready    master   17h   v1.16.2
virtual-kubelet   Ready    agent    19s   v1.15.2-vk-cri-5dec3cb

Podをデプロイ

Virtual Kubeletで起動したNodeはデフォルトで以下のtaintsが設定されています。
そのため、デプロイするときは、.spec.tolerationsをセット、もしくはNodeのtaintsを削除する必要があります。

spec:
  taints:
  - effect: NoSchedule
    key: virtual-kubelet.io/provider
    value: cri

今回は.spec.tolerationsをセットし、nginx Podをデプロイします。

Mac
$ cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: edge-nginx
  labels:
    app: edge-nginx
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
  tolerations:
  - effect: NoSchedule
    key: virtual-kubelet.io/provider
    value: cri
    operator: Equal
EOF

$ kubectl get po
NAME         READY   STATUS    RESTARTS   AGE
edge-nginx   1/1     Running   0          8s

$ kubectl exec -it edge-nginx sh
# レスポンスは空

$ kubectl logs edge-nginx
# レスポンスは空

CRI Providerには現在execやlogsは実装されていません。必要なら自分で実装する3ことが可能です。
今回のセットアップだけではminikubeのPodからのアクセスや、Service Type Loadbalancerなどが実現できないので、Podが稼働しているか確認するために、直接VM上でport forwardをして確認します。

ubuntu
# port-forwardにはsocatが必要
$ sudo apt-get install -y socat
$ sudo crictl pods 
POD ID              CREATED             STATE               NAME                NAMESPACE           ATTEMPT
f9ba814efc837       4 minutes ago       Ready               edge-nginx          default             0
676b7b074c729       15 minutes ago      Ready               kube-proxy-qcqf8    kube-system         0

$ POD_ID=`sudo crictl pods --name='^edge-nginx$' | grep edge-nginx | awk '{print $1}'`

$ sudo crictl port-forward $POD_ID 80

$ curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Podがデプロイされ、nginxが稼働していることが確認できました。

ちなみに、複数のVirtual Kubelet CRI Providerも稼働できますが、デフォルトだとNodeの名前が衝突してしまい、おかしな挙動になります。
スクリプトでvirtual kubeletを起動する際に、—node-name=virtual-kubelet-foo などセットしましょう。

感想

今回、Edge Computingに興味を持った私は、Virtual Kubelet CRI Providerが活用できないかと思い触ってみましたが、CRI Provider自体がほとんどメンテされていないこともあり、セットアップに手間がかかるものになっていました。
ここまで手間がかかるのであれば、Edge側でk3sを構築した上でクラウドからアクセスもしくはEdge側にsshし、K3sを操作する。
Edge側でセンサーなどのIoT機器との通信が必要であれば、Kubernetesだけで完結することはできないため、Azure IoT Hubなど特定サービスの利用がよいかもしれません。このあたりはKubeEdgeが強く意識しているようなので、いつか触れてみたいと思います。

Edge Computingに必要な要件は様々でしょう。
たとえば、NW帯域制限、通信できるタイミング・時間の制限、Edge内で閉じた閉域NW、省電力、クラウドからの操作、アプリケーションの更新方法など考えられます。
Virtual KubeletをEdge Computingの一部として利用する、ことはありえるかもしれませんが、それだけで何か完結することはなく、周辺コンポーネントの作り込みも重要になりそうです。

個人的には、Virtual KubeletはやはりServerlessなコンテナプラットフォームなどで稼働させるのがベストなのではないか、と考えます。
とはいえ、Amazon EKS on Fargateなど、Virtual Kubeletを使っていないプロダクトもでており、今後どういうプロダクトがMajorityになっていくのか、まだわかりません。

参考

後記

実際にEdge Computingという側面でどういったプロダクト・サービスが登場していくのでしょうか?
今後も興味の赴くままに追ってみたいと思います。
また、公式で紹介しているCRI Providerのセットアップ手順は、ほぼ無いも同然なので、本記事が誰かの助けになれば幸いです。

本記事は、あくまでも個人的な興味であり、現在Z LabにはEdge Computingの業務はありませんので、誤解なさらず。


  1. kubeletについては公式ドキュメントをご覧ください。https://kubernetes.io/ja/docs/concepts/overview/components/ 

  2. GitHub上には、Azure IoT Edge Connector for Kubernetesもありますが、2019/12現在サイトのDocsには含まれていないようです。 

  3. https://godoc.org/github.com/virtual-kubelet/virtual-kubelet/node/api 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした