Kubernetesでサービスを提供するときは、テスト用イメージを作っておくと便利です

# はじめに

この記事は [さくらインターネット Advent Calendar 2024](https://qiita.com/advent-calendar/2024/sakura) 13日目の記事です。

さくらインターネットのkawaiです。

社内ではKubernetes（以下K8s）、コンテナを用いたサービス開発を行っています。
最近リリースした[AppRun](https://manual.sakura.ad.jp/cloud/manual-sakura-apprun.html)にも関わっており、AppRunはk8sおよび[Knative serving](https://knative.dev/docs/serving/)という技術を用いています。
※ AppRun APIの詳細は[AppRun β APIドキュメント](https://manual.sakura.ad.jp/sakura-apprun-api/spec.html)をご参照ください。

---

Knative servingは、service, route, configuration, revison といったリソースから構成されるカスタムリソースで、

- サーバレスなサービス、コンテナベースのサービスの迅速なデプロイ
- Podをゼロまでスケールダウンさせる自動スケーリング
- Contour、Kourier、Istio などの複数のネットワークレイヤーのサポート

といった特徴があります。

さて、このように便利なKnative servingですが、いくつかのリソースから構成されるがゆえに単純なイメージではデバッグが少し面倒です。

そこで、想定されるユースケースに応じて確認が可能なコンテナイメージを作っておくと便利なので紹介します。

# 成果物と使い方

https://github.com/Asya-kawai/ocaml-http-server-for-test

コンテナイメージとしてビルドする場合は下記コマンドを実行してください。

```bash
docker build . --no-cache --pull
```

プログラムは8080ポートで起動するようになっているので、起動するには下記のようなコマンドを実施します。

```bash:10080ポートで実行する例
docker run --rm -p 10080:8080 <IMAGE ID>
```

## ケース１： リクエストヘッダとボディーを表示する

最もシンプルな使い方は、`GET /`することです。
`curl localhost:10080/`のようなリクエストを送信すると、下記のような出力を得ます。

出力されているのは、リクエストヘッダおよびリクエストボディーです。

```
URI: http://localhost/
Method: GET
Version: HTTP/1.1
Headers: ---
Host: localhost:8080
User-Agent: curl/7.68.0
Accept: */*
Body: ---
<-- Bodyがあればここに表示される --!>
```

### どのように役立つか

K8sは基本的にクラスタで構成され、前段にはロードバランサもあります。
また、クラスタ内にはistio, nginx ingressなどの複数のネットワークレイヤーが存在する場合もあるため、意図せずリクエストヘッダやボディーが欠落していないかを確認した時があります。

このように、Podにどのような情報が渡っているかを確認したい時に便利です。

## ケース２： ファイルの内容を表示する

`curl localhost:10080/whoami`のように`GET /whoami`をリクエストすると`whoami.txt`ファイルの内容を表示します。


```bash
(* ここに whoami.txt の内容が表示される *)
```

### どのように役立つか

K8sのファイルマウントや設定書き込みといった、サーバサイドの設定が正しいことを確認するのに便利です。

## ケース３： 特定のHTTPステータスコードを得る

`curl localhost:10080/statuses/404`のように`GET /statuses/:code`をリクエストすると、`:code`に与えたHTTPステータスコードを返してくれます。

```
Code: 404
Reason: Not Found
```

### どのように役立つか

フロントエンドまたはクライアント側でのエラー処理をデバッグする際に便利です。

## ケース４： ディレイをかける

`curl localhost:10080/delay/3`のように`/delay/:second`をリクエストすると、`:second`秒だけwaitした後でレスポンスを返します。

```bash:timeコマンドによる応答時間の確認
time curl localhost:8080/delay/3
Waited for 3 seconds.
curl localhost:8080/delay/3  0.00s user 0.01s system 0% cpu 3.014 total
```

### どのように役立つか

フロントエンドまたはクライアント側でのタイムアウト処理のデバッグや、クライアントとPod間にあるネットワーク機器および設定に関するデバッグができます。

## ケース５： Basic認証を体験する

`curl localhost:10080/basic-auth/hoge/fuga`のように`/basic-auth/:user/:password`をリクエストすると、`:user`名および`:password`（パスワード）によるBasic認証を設定できます。

```bash:正しいユーザ名およびパスワードを入力した場合
curl --user "hoge:fuga" localhost:8080/basic-auth/hoge/fuga
Accepted user: hoge
```

```bash:間違ったパスワードを入力した場合
curl -v --user "hoge:BaaaaaaaaaaaaadPassword" localhost:8080/basic-auth/hoge/fuga
*   Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Server auth using Basic with user 'hoge'
> GET /basic-auth/hoge/fuga HTTP/1.1
> Host: localhost:8080
> Authorization: Basic aG9nZTpwaXlv
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Content-Length: 0
< 
* Connection #0 to host localhost left intact
```

### どのように役立つか

Authorizationヘッダーが欠落していないかといったネットワーク設定の確認や、クライアント側の処理の確認に役立ちます。

# 終わりに

このように提供するサービス機能や制限に応じて、デバッグに役立つAPIを備えたイメージを用意しておくと便利です！

なお、わたしが作成したOCamlのコンテナイメージは、無事にチームメンバが**Goで書き換え**てくれました :tada: :joy: :tada: