🎉

K8sを意識せずにアプリをデプロイできるKubeVelaにシュっと入門

2020/11/23に公開

GitHubのトレンドを眺めていたところ、KubeVelaというOSSが目に止まりました。

KubeVelaとは

一言で言えば、開発者が楽にK8sにアプリをデプロイするためのツールセットです。

https://kubevela.io/#/

通常、開発者がK8sにアプリをデプロイする際はPod、Service、Ingress、Resource Request、CRD etc...の概念を理解する必要があり、これらを全て理解することは決して楽ではありません。
KubeVelaはこの労力を最小限にするアプローチの1つとして提供されており、開発者はAppfileという設定ファイルのみを管理するだけで良くなるため、複雑なK8sの設定をあまり意識せずにデプロイすることが可能になります。

今回は、このKubeVelaをローカルのK8sクラスター上に展開しながら、動作を確認していきます。

検証環境

  • Mac OS Catalina
  • Docker: 19.03.13
  • kubectl: v1.19.4
  • Kind: 0.9.0
  • Vela: v0.1.2

説明しないこと

  • 以下のインストール手順
    • Docker
    • kind
    • kubectl

もし新規でkind、kubectlのインストールを行う場合は、公式の手順通り入れても全く問題ありませんが、以下のasdf-vmというCLI用のバージョン管理マネージャーを利用するのも個人的にオススメです[1]

https://github.com/asdf-vm/asdf

KubeVelaのインストール

  • kindでクラスター構築
$ cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
EOF

# 起動確認
$ kubectl get no
NAME                 STATUS   ROLES    AGE     VERSION
kind-control-plane   Ready    master   2m49s   v1.19.1
  • Nginx Ingressのインストール

ルーティングの設定を行うために必要です。

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml 
  • Vela CLIのインストール

公式のReleaseページからバイナリをダウンロードし、PATHが通っているところに配置します。

https://github.com/oam-dev/kubevela/releases

$ tar zxvf ~/Downloads/vela-v0.1.2-darwin-amd64.tar.gz
$ sudo mv darwin-amd64/vela /usr/local/bin/vela
$ sudo chmod +x /usr/local/bin/vela
  • Velaの動作確認

Macの新しいバージョンだと、Apple Developer Keyで署名されていないバイナリの実行がブロックされるため、システム環境設定 -> セキュリティとプライバシー -> 一般 -> ダウンロードしたアプリケーションの実行許可から許可をします。

$ vela version
Version: refs/tags/v0.1.2
GitRevision: git-816b7d2
GolangVersion: go1.14.12
  • Velaの初期化

このタイミングでVela用のNamespaceが作成され、専用のHelm Chartがインストールされます。

$ vela install
...
- Finished successfully.
  • Velaコンポーネントの諸々の確認

Velaは内部的に複数のOSS・Operatorを利用しており、vela installのタイミングでDeployツールのFlagger、イベント駆動でPodのオートスケールを実現するKEDA、Prometheusがインストールされていることが分かります。

# Chart
$ helm list -n vela-system
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS     CHART            APP VERSION
flagger         vela-system     1               2020-11-23 07:03:14.4367091 +0000 UTC   deployed   flagger-1.1.0    1.1.0      
kubevela        vela-system     1               2020-11-23 16:02:25.955088 +0900 JST    deployed   vela-core-0.1.0  0.1.0    
$ helm list --all-namespaces
NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS      CHART                           APP VERSION
flagger                 vela-system     1               2020-11-23 07:03:14.4367091 +0000 UTC   deployed    flagger-1.1.0                   1.1.0      
keda                    keda            1               2020-11-23 07:03:20.8723254 +0000 UTC   deployed    keda-2.0.0-rc3                  2.0.0-rc2  
kube-prometheus-stack   monitoring      1               2020-11-23 07:03:35.7623397 +0000 UTC   deployed    kube-prometheus-stack-9.4.4     0.38.1     
kubevela                vela-system     1               2020-11-23 16:02:25.955088 +0900 JST    deployed    vela-core-0.1.0                 0.1.0      

KubeVelaでサンプルアプリを動かす

  • 公式のサンプルアプリをクローン
$ git clone https://github.com/oam-dev/kubevela.git
$ cd kubevela/docs/examples/testapp
  • vela.yamlを確認する

見ての通り、docker-compose.yamlライクな設定ファイルとなっています。
こちらは偶然ではなく、公式にもdocker-composeを意識したつくりとしていることが示唆されています。

vela.yaml
name: testapp

services:
  express-server:
    # this image will be used in both build and deploy steps
    image: oamdev/testapp:v1

    build:
      # Here more runtime specific build templates will be supported, like NodeJS, Go, Python, Ruby.
      docker:
        file: Dockerfile
        context: .

      # Uncomment the following to push to local kind cluster
      # push:
      #   local: kind

    # type: webservice (default) | worker | task

    cmd: ["node", "server.js"]
    port: 8080

    # scaler:
    #   replicas: 1

    # route:
    #   domain: example.com
    #   rules:
    #     - path: /testapp
    #       rewriteTarget: /

    # metrics:
    #   format: "prometheus"
    #   port: 8080
    #   path: "/metrics"
    #   scheme:  "http"
    #   enabled: true

    # autoscale:
    #   min: 1
    #   max: 4
    #   cron:
    #     startAt:  "14:00"
    #     duration: "2h"
    #     days:     "Monday, Thursday"
    #     replicas: 2
    #     timezone: "America/Los_Angeles"

  # pi:
  #   image: perl 
  #   cmd: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
  • vela.yamlの編集

公式ページでは、image: oamdev/testapp:v1の部分を自分のレジストリアカウントに変更した後、そのままvela upというdocker-compose upライクなコマンドを用いてデプロイする手順が記載されています。
ただその場合はリモートレジストリの用意が必須となってしまうため、ローカルの閉じた環境で検証できるように
ローカルプッシュオプションを有効化します。

具体的には、vela.yamlの以下の部分をコメントインします。

vela.yaml
    build:
       # Uncomment the following to push to local kind cluster
-      # push:
-      #   local: kind
+      push:
+        local: kind
  • サンプルアプリのデプロイ
$ vela up
Parsing vela.yaml ...
Loading templates ...
~~~
Applying deploy configs ...
Checking if app has been deployed...
App has not been deployed, creating a new deployment...
✅ App has been deployed 🚀🚀🚀
    Port forward: vela port-forward testapp
             SSH: vela exec testapp
         Logging: vela logs testapp
      App status: vela status testapp
  Service status: vela status testapp --svc express-server
  • サンプルアプリの動作確認

アプリへのポートフォワード、コマンド実行、ログ確認など
必要なものは一通り揃っています。

# ポートフォワード
# kubectl port-forwardと違い、そのままブラウザでページが開かれる点が異なる
$ vela port-forward testapp
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

Forward successfully! Opening browser ...
Handling connection for 8080
Handling connection for 8080
# コンテナ内でのコマンド実行
$ vela exec testapp -it -- sh 
/app # ls
Dockerfile         node_modules       package-lock.json  package.json       server.js          vela.yaml
# ログ確認。表示のされ方はsternと似ている
$ vela logs testapp
+ express-server-666bd6b4dc-wzsnl › express-server
express-server-666bd6b4dc-wzsnl express-server 2020-11-23T07:37:10.689096100Z Running on http://0.0.0.0:8080
# ステータス確認
$ vela status testapp express-server 
About:

  Name:         testapp                             
  Namespace:    default                             
  Created at:   2020-11-23 16:37:09.443828 +0900 JST
  Updated at:   2020-11-23 16:37:09.44383 +0900 JST 

Services:

  - Name: express-server
    Type: webservice
    HEALTHY Ready: 1/1 
    Traits:

    Last Deployment:
      Created at: 2020-11-23 16:37:09 +0900 JST
      Updated at: 2020-11-23T16:37:09+09:00

vela port-forwardするとブラウザが開くので、
そこでHello Worldが表示されれば正常に動作しています。

KubeVelaでルーティングの設定

ここまででサンプルアプリの動作確認はできたので、ルーティングの設定を試していきます。

  • vela.yamlの編集
vela.yaml
-    # route:
-    #   domain: example.com
-    #   rules:
-    #     - path: /testapp
-    #       rewriteTarget: /
+    route:
+      domain: example.com
+      rules:
+        - path: /testapp
+          rewriteTarget: /
  • vela up
$ vela up
  • ステータス確認

再度vela statusを叩くと、通常のコンテナの起動状態の他に、追加したルーティングの状態も確認可能です。

$ vela status testapp                                
About:

  Name:         testapp                             
  Namespace:    default                             
  Created at:   2020-11-23 18:20:39.551359 +0900 JST
  Updated at:   2020-11-23 18:20:39.551359 +0900 JST

Services:

  - Name: express-server
    Type: webservice
    HEALTHY Ready: 1/1 
    Traits:
      - ✅ route:       Visiting URL: http://example.com        IP: localhost

    Last Deployment:
      Created at: 2020-11-23 16:37:09 +0900 JST
      Updated at: 2020-11-23T18:20:39+09:00
  • 設定確認

Hostヘッダーを付与しつつ確認を行うと、次のように正常に振り分けられていることが確認できます。

$ curl -H "Host:example.com" http://localhost/testapp
Hello World

# 対応するIngress、Serviceも作成されている
$ kubectl get ing,svc -l app.oam.dev/component=express-server 
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
NAME                                                   CLASS    HOSTS         ADDRESS     PORTS   AGE
ingress.extensions/express-server-trait-64845c5b65-0   <none>   example.com   localhost   80      5m44s

NAME                                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/express-server-trait-64845c5b65   ClusterIP   10.96.149.63   <none>        8080/TCP   5m44s

KubeVelaでオートスケールの設定

先述の通り、KEDAが入っている環境のため、Podのオートスケールを行うこともできます。

条件としては、タイミング(e.g. 火曜日の22時から1時間)か、
負荷(e.g. コンテナのCPU使用率が10%増える)のいずれかに対応してスケールさせることが可能です。

今回は、決まったタイミングでオートスケールさせるCronタイプのスケーリングを試していきます。

  • vela.yamlの編集

例によってvela.yamlを編集します。
見ての通りですが、Podのレプリカ数の最小値と最大値に加えて
オートスケールする条件(月曜21:12から1分間だけレプリカを2個にスケール)を加えています。

vela.yaml
-    # autoscale:
-    #   min: 1
-    #   max: 4
-    #   cron:
-    #     startAt:  "14:00"
-    #     duration: "2h"
-    #     days:     "Monday, Thursday"
-    #     replicas: 2
-    #     timezone: "America/Los_Angeles"
+    autoscale:
+      min: 1
+      max: 5
+      cron:
+        startAt:  "21:12"
+        duration: "1m"
+        days:     "Monday"
+        replicas: 2
+        timezone: "Asia/Tokyo"
  • vela up
$ vela up
  • 動作確認
# 元々のPod数
$ vela status testapp
~~~
  - Name: express-server
    Type: webservice
    HEALTHY Ready: 1/1 
    Traits:
      - ✅ autoscale: type: cron    replicas(min/max/current): 1/5/1
# 時間になるとオートスケール
$ vela status testapp
~~~
  - Name: express-server
    Type: webservice
    HEALTHY Ready: 2/2 
    Traits:
      - ✅ autoscale: type: cron    replicas(min/max/current): 1/5/2
# durationを過ぎると元のPod数に戻る
$ vela status testapp
~~~
  - Name: express-server
    Type: webservice
    HEALTHY Ready: 1/1 
    Traits:
      - ✅ autoscale: type: cron    replicas(min/max/current): 1/5/1

待っていると、無事オートスケールされました。
少し気になった点として、スケールアウトは時間通りに実行されたものの
スケールインされるまでは5分弱ラグがありました(理由はKEDAの仕様と絡んでいるかもしれないので、調査中です)。

所感

とにかくdocker-composeの使用感を維持したままK8sにアプリをデプロイしたい人にとっては、ちょうどいいツールという肌感でした。

アプリのビルドからリリースまで一貫して面倒を見るという意味では、先日Hashicorpから発表されたWaypointに少し似ていますが、次のような点に違いがあります。

項目 KubeVela Waypoint
ビルドランタイム Docker Buildpacks
対応プラットフォーム K8sのみ K8s以外も対応
対応言語 制限なし Buildpacksの対応に依存
設定フォーマット Yaml HCL

Waypointは幅広いプラットフォームに対応していますが、KubeVelaはK8s上の利用に特化している分、K8sの関連OSSと連携して痒い所に手が届くような印象でした。

また一方で、動かす上で躓く点は少なかったですが、複数のOperatorが自動セットアップされる関係でリソースをそこそこ食うので、個人開発用のような小さめのクラスターだと少し重く感じるかもしれません。

現在KubeVelaはアルファリリースですが、使用感や設定自体は非常にシンプルで良かったので、今後の動向をチェックしていきたいと思います。

脚注
  1. 対応しているCLIツールのバージョン切り替えが簡単に行えます。 ↩︎

Discussion