Lima で k3s を使った Kubernetes 環境を構築し、サンプルアプリケーションをビルドして実行します。
1. k3s の環境構築
まずは、https://github.com/lima-vm/lima/blob/master/examples/k3s.yaml を参考に、k3s を実行するための Lima の構成ファイルを次のようにしてみました。
コンテナは k3s が管理するので containerd
の設定を false
にして、あとは k3s をインストールするだけで良さそうです。
なお、~/temp/lima_k3s
で作業を行うように書き込み可でマウントしています。
images:
...省略
mounts:
- location: "~/temp/lima_k3s"
writable: true
containerd:
system: false
user: false
provision:
- mode: system
script: |
#!/bin/sh
curl -sfL https://get.k3s.io | sh -
probes:
- script: |
#!/bin/bash
set -eux -o pipefail
if ! timeout 30s bash -c "until test -f /etc/rancher/k3s/k3s.yaml; do sleep 3; done"; then
echo >&2 "k3s is not running yet"
exit 1
fi
このファイルで Lima を実行し、シェルへ入っておきます。
実行例
% cd ~/temp/lima_k3s
% limactl start --tty=false lima_k3s.yaml
・・・
% limactl shell lima_k3s
$
以降の作業は基本的に lima_k3s シェルで実施します。
2. コンテナイメージのビルド
上記で構築した環境では nerdctl
がインストールされないので、コンテナイメージをビルドする手段が無さそうです。
そこで、ここでは BuildKit でコンテナイメージをビルドします。
2-1. BuildKit インストール
今回は BuildKit をダウンロードして手動でインストールしました。
解凍すると ./bin が作られるので、その中のコマンド群を /usr/local/bin へ配置しています。
BuildKit インストール例
$ wget https://github.com/moby/buildkit/releases/download/v0.11.6/buildkit-v0.11.6.linux-arm64.tar.gz
$ tar zxf buildkit-v0.11.6.linux-arm64.tar.gz
$ sudo cp ./bin/* /usr/local/bin/
$ rm -fr ./bin
2-2. サンプルアプリケーション
次のような Rust アプリケーションをビルドする事にします。
ファイル一式は ~/temp/lima_k3s/sampleapp
へ配置しているものとします。
[package]
name = "sampleapp"
version = "0.1.0"
edition = "2021"
[dependencies]
gotham = "0.7"
[profile.release]
lto = true
use gotham::state::State;
use gotham::prelude::FromState;
use gotham::hyper::Uri;
use std::env;
fn sample(state: State) -> (State, String) {
let uri = Uri::borrow_from(&state);
println!("path={}", uri);
let res = format!("ok:{}", uri);
(state, res)
}
fn main() {
let port = env::var("APP_PORT").unwrap_or("3000".to_owned());
let addr = format!("0.0.0.0:{}", port);
println!("listening: {}", addr);
gotham::start(addr, || Ok(sample)).unwrap();
}
FROM rust:1.69 as builder
WORKDIR /app
COPY . .
RUN cargo install --path .
FROM debian:bullseye-slim
WORKDIR /app
RUN apt-get update && rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local/cargo/bin/sampleapp .
CMD ["./sampleapp"]
Dockerfile は https://hub.docker.com/_/rust の内容を参考にしましたが、これだと cargo install
実行時に依存パッケージの処理が毎回行われるので、あまり効率的では無さそうでした。
2-3. ビルド
buildkitd
を実行しておき、buildctl
を使ってコンテナイメージをビルドします。
今回は k3s へコンテナイメージを直接インポートする事にしたので、コンテナイメージを tar ファイル(sampleapp.tar
)へ出力しています。
buildkitd 実行例
$ sudo buildkitd &
ビルド例
$ sudo buildctl build --frontend dockerfile.v0 \
--local context=./sampleapp --local dockerfile=./sampleapp \
--output type=oci,name=sampleapp > sampleapp.tar
buildkitd 終了例
$ sudo killall buildkitd
3. 実行
まずは、sampleapp.tar を k3s ctr
でインポートしておきます。
コンテナイメージのインポート
$ sudo k3s ctr images import sampleapp.tar
実行用の Deployment + Service の構成ファイルを用意します。
インポートしたコンテナイメージを使うので imagePullPolicy: Never
としています。
kind: Service
apiVersion: v1
metadata:
name: sampleapp
labels:
app: sampleapp
spec:
selector:
app: sampleapp
ports:
- protocol: TCP
port: 8080
targetPort: 3000
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sampleapp
labels:
app: sampleapp
spec:
replicas: 1
selector:
matchLabels:
app: sampleapp
template:
metadata:
labels:
app: sampleapp
spec:
containers:
- name: sampleapp
image: sampleapp
ports:
- containerPort: 3000
imagePullPolicy: Never
kubectl apply
を実行してリソースを作成します。
リソース作成
$ sudo kubectl apply -f sampleapp.yaml
service/sampleapp created
deployment.apps/sampleapp created
次のようになりました。
Pod 確認
$ sudo kubectl get pods
NAME READY STATUS RESTARTS AGE
sampleapp-6786f87bd7-gs6sq 1/1 Running 0 6s
Service 確認
$ sudo kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 122m
sampleapp LoadBalancer 10.43.198.42 192.168.5.15 8080:30201/TCP 10s
最後にホスト OS(macOS)からアクセスしてみます。
動作確認1
% curl http://localhost:8080/
ok:/
動作確認2
% curl http://localhost:8080/ab
ok:/ab