知識ゼロでknative使ってみた

# はじめに
kubernetes関連の業務を担当していると時折聞いていたknativeについて今回調べて検証してみました。
knativeの検証はサーバレスの部分のみとし、最近はやっているChatGPT (GPT 4o)を利用してできるだけ楽をします。

# Knativeとは
Kubernetes上でのサーバーレス環境を実現するためのソフトウェアです。
主なコンポーネントは以下2つ。 (場合によってはFunctionsが含まれて3つとしていることもあるが、ここでは2つとしている)
* Serving
    * サーバレスアプリケーションのデプロイを可能にする
    * Servingには主に4つのリソースがある
        * Services
        * Routes
        * Configurations
        * Revisions
* Eventing
    * イベント駆動型のアーキテクチャを構築する際に利用
        * 今回は検証の対象外
    * Servingの機能を補強するイメージ
        * （イベント駆動型のアーキテクチャとサーバレスの相性がいいためKnativeの主なコンポーネントになっている認識です）

### Serving 4つのリソース
* Services
    * アプリケーションのデプロイと管理のためのリソース
    * Routes, Configurationsを管理する
* Routes
    * アプリの異なるバージョン（リビジョン）へのトラフィックを制御
* Configurations
    * アプリのデプロイ設定を保持し、更新時に新しいリビジョンを作成
    * Revisionsを管理する
* Revisions
    * デプロイされた設定を保持
    * このリソースは不変

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606568/eb952598-80e9-6c96-965e-0e6265069b2e.png)
図. Knative Servingコンポーネント
出典：https://knative.dev/docs/concepts/#what-is-knative

上記リソースの関係を文字だけでまとめると以下になります。
Services (管理)-> Routes
Services (管理)-> Configurations
Configurations (管理)-> Revisions

# 検証準備
ということでKnativeのServingを検証するための環境を構築していきます。
Kubernetes環境を構築するところから始めますが、インストール自体は省略します。具体的なインストール方法については適宜記載するURLを参照ください。

### 実行環境とソフトウェア
検証に利用したソフトウェアとバージョンを以下に列挙します。また、Container RegistoryにはDocker Hubを使用しました。

実行環境
* Windows 11
* wsl ubuntu

利用ソフトウェア
* knative 1.14.0
* kubernetes v1.30.0
* kubectl v1.29.2
* Docker Desktop 4.30.0
* docker 26.1.1
* kind v0.17.0
* Python 3.11.9
* Flask 2.2.5 (Pythonのweb framework)

### GitHub
今回使う資材は以下に置いてあります。
* https://github.com/hsmto25519/Flask_webapp

### kindを利用してkubernetesクラスタを構築
kindを使ってkubernetesクラスタを構築します。configファイルを準備すればすぐに作成できます。
kindインストールはこちら：https://kind.sigs.k8s.io/docs/user/quick-start/

``` yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: my-cluster
nodes:
- role: control-plane
  image: kindest/node:v1.30.0
- role: worker
  image: kindest/node:v1.30.0
```
実行します。
```
kind create cluster --config .\config.yaml
```

### アプリの作成
ChatGPTに「postメソッドで加算する」、「Flaskを使ったPython」を指定してプログラムを出力し、細かいところを修正しただけです。
最終的に以下のようになりました。(ブラウザからの確認用にhello関数を追加してます)
``` python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/add', methods=['POST'])
def add():
    data = request.get_json()
    num1 = data.get('num1')
    num2 = data.get('num2')
    if num1 is None or num2 is None:
        return jsonify({"error": "Please provide num1 and num2"}), 400
    try:
        sum = float(num1) + float(num2)
    except ValueError:
        return jsonify({"error": "Invalid numbers"}), 400
    return jsonify({"sum": sum})

@app.route('/hello', methods=['GET'])
def hello():
    return "hello!"

if __name__ == '__main__':
    app.run(host='::', port=8080)
```

動作確認です。想定通り動いていることを確認できました。
```
python add.py
 * Serving Flask app 'add'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (::)
 * Running on http://[::1]:8080
Press CTRL+C to quit
```

``` bash
curl localhost:8080/hello
hello!

curl -H "Content-Type: application/json" -d '{"num1":"4","num2":"5"}' localhost:8080/add
{"sum":9.0}
```


# Knative検証

### Knative インストール
まずはKnativeをインストールするところからやります。
今回はKnative-Operatorを使います。
https://knative.dev/docs/install/operator/knative-with-operators/#install-the-knative-operator

```
kubectl apply -f https://github.com/knative/operator/releases/download/knative-v1.14.2/operator.yaml

# "knative-operator" があるかを確認
kubectl get deployment -A
```
Serving リソースを使えるように以下のファイルを適用します。
``` yaml
# knativeserving.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: knative-serving
---
apiVersion: operator.knative.dev/v1beta1
kind: KnativeServing
metadata:
  name: knative-serving
  namespace: knative-serving
```

```
kubectl apply -f knativeserving.yaml
```
コンポーネントがデプロイされるまでに少し時間がかかるので待機。各コンポーネントは以下で確認可能
```
kubectl get deployment -n knative-serving
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
activator                1/1     1            1           7d
autoscaler               1/1     1            1           7d
autoscaler-hpa           1/1     1            1           7d
controller               1/1     1            1           7d
net-contour-controller   1/1     1            1           7d
webhook                  1/1     1            1           7d
```

### アプリのデプロイ
Knativeのインストールができたらアプリをデプロイして疎通確認します。
アプリをKubernetes上にデプロイするためにはDocker Image化とそのImageをContainer Registryに格納必要があります。

まずはDockerfileを作成します。
ChatGPTにDockerfileを出力してもらいました。
``` requirements.txt(Dockerfileのビルドに必要)
Flask==2.2.5
```

``` Dockerfile
FROM python:3.11-slim

# Set the working directory
WORKDIR /app

# Copy the requirements file to the working directory
COPY requirements.txt .

# Install the dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code
COPY ./src .

# Expose the port the app runs on
EXPOSE 8080

# Define the command to run the app
CMD ["python", "add.py"]
```
Imageのビルドをします。今回はDocker Hubを利用するので以下のような形式になります。
```
docker build -t <username>/web-app:v1
docker push <username>/web-app:v1 
```
※DockerHubの補足。docker imageをアップロードする際にログインが必要な場合は以下の手順でアクセストークンを取得してからdocker imageをアップロードする。
「My Account」 -> 「Security」 -> 「Access Tokens」
```
# 以下は
docker login -u <username>
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
```

Knativeのマニフェストファイルを作成してアプリをデプロイします。
``` add.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: test-web-app-serverless
  namespace: webapp
spec:
  template:
    spec:
      containers:
        - image: <username>/web-app:v1.0.1
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /hello
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 30
```

```
kubectl apply -f add.yaml
```

これでKnative上にデプロイされたアプリにアクセスできるようになりました。
kubernetes上に疎通確認用のPodを作成します。
```
kubectl --rm -it run conn-test --image=nginx -- bash

# 疎通確認
curl http://test-web-app-serverless.webapp.svc.cluster.local/hello
hello!
root@nginx:/# curl -H "Content-Type: application/json" -d '{"num1":"4","num2":"5"}' test-web-app-serverless.webapp.svc.cluster.local/add
{"sum":9.0}
```

検証は以上になります。
今回はネットワークの設定をしていないので、外部からのアクセスができませんが、Ingressを設定することで外からの疎通も可能です。

# まとめと余談
knativeの概要を説明し、実際にkubernetes環境の構築からアプリケーションの作成を含め準備しました。
その後、knativeを使って実際にアプリケーションをデプロイし、疎通確認まで行いました。

余談ですが、当初は一言で言えば「knative with wasmをChatGPTに質問するだけで作ってみた」のような記事を書きたかったです。
しかし、Axumを使ってRustのwebappを作成するところは簡単にできたのですが、それをwasmにコンパイルするのがChatGPTに質問するだけでは難しく、またトラブルシュートもRustの知識がかなりないと厳しかったです。Rust on Wasmはあきらめ、Python on Wasmをpy2wasmを使って実装を試みました。
https://wasmer.io/posts/py2wasm-a-python-to-wasm-compiler
余談の余談になってしまうのですが、pythonの場合はwasmを使うよりもpythonを実行した方がはやいんですかね。上記ページではCpython (Native)がwasmを使った実装よりもパフォーマンスがよい。wasm周りに詳しい方いらっしゃいましたら教えてください。。。

py2wasmでのwasm実装は実行時にエラーが出てしまい、デバッグ方法が全く分からなかったのであきらめました。ChatGPTに聞いてもよい返事を得られませんでした。
```
$ pip install py2wasm
$ py2wasm <myflaskapp>.py -o <myflaskapp>.wasm  # <-ここまではうまくいく
$ wasmer run <myflaskapp>.wasm  # <- ここで失敗する
```

という感じでwasmをあきらめて結局knativeの検証となりました。

検証後、knativeについて体系的に理解したいと思い以下の書籍を読みましたが、非常に良かったです。執筆時一部参考にさせていただいてます。
* Knative実践ガイド (impress top gear)
https://www.amazon.co.jp/Knative%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-impress-top-gear-%E5%B0%8F%E9%87%8E/dp/4295016357

以上です。最後までお読みいただきありがとうございました。

# 参考
* 書籍
    * Knative実践ガイド (impress top gear)
https://www.amazon.co.jp/Knative%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-impress-top-gear-%E5%B0%8F%E9%87%8E/dp/4295016357

* リンク
    * Knative Concepts
        https://knative.dev/docs/concepts/
    * Knative Operator install
        https://knative.dev/docs/install/operator/knative-with-operators/#install-the-networking-layer