Zenn
🪞

mirrordを使いローカルプロセスをOrbStack k8s環境で実行

に公開

今回はmirrordというツールが興味深かったので個人のPCでサクッと試せる環境を作ります。具体的にはローカルでOrbStack k8s環境を作りmirrordを適用します。

mirrordとは?


mirrordはクラウド環境でローカルのプロセスを実行できるようにするツールです。
https://mirrord.dev/

mirrordのユースケースは?


ローカル環境にあるプログラムの変更を即座にクラウド環境へ適用できます。例えばローカルの変更をmirrodを使ってステージング環境に適用することでCI/CDの待ち時間なしに動作確認をすることができます。

似たようなツールとの違いは?

クラウド環境でコードを実行できるツールは他にもあります。他のツールはVPNやシステムファイルを編集することでクラウド環境での実行を行いますがmirrordはプロセスレベルでローカル/リモートの切り替えができます。なので細かい設定が可能になります。

mirrordの仕組み

mirrordの公式情報

ローカルにk8s環境を用意する

minikubeを使おうとしましたがorbstackでk8s環境を作成できるみたいなのでorbstackを使います。

https://docs.orbstack.dev/kubernetes/

OrbStackとは?

コンテナ、Linux環境管理ツールです。Docker Desktopより高速です。

kubectlのインストール

brew install kubectl

clusterを有効化

  • GUIメニューから「Turn On」

  • settingからチェックボックスにチェックを入れてもよいです

cluster起動の確認

╰─$  kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:26443
CoreDNS is running at https://127.0.0.1:26443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Node.jsアプリケーションを作る

基本ファイルの作成

package.json

{
  "name": "nodejs-k8s-demo",
  "version": "1.0.0",
  "description": "Simple NodeJS app for Kubernetes demo",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {}
}

service.js

const http = require('http');

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello from OrbStack Kubernetes!\n');
});

const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

dockerfile

FROM node:22-alpine

WORKDIR /app

COPY package.json .
RUN npm install

COPY server.js .

EXPOSE 8080

CMD ["node", "server.js"]
  • nodejs versionは22にした。他のバージョンにしても動くはずです。

docker imageのビルド

docker build -t nodejs-k8s-demo:v1 .

k8sファイルの設定

development.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nodejs-app
  template:
    metadata:
      labels:
        app: nodejs-app
    spec:
      containers:
      - name: nodejs-app
        image: nodejs-k8s-demo:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
  • 一旦replicaを2に設定

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nodejs-app-service
spec:
  selector:
    app: nodejs-app
  ports:
  - port: 80
    targetPort: 8080
  type: NodePort

Kubernetesリソースのデプロイ

OrbStackのKubernetesクラスタにリソースをデプロイします。

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Podが正常に起動しているか確認。

╰─$ kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
nodejs-app-5dd85958c6-dkhcd   1/1     Running   0          44s
nodejs-app-5dd85958c6-kxqr9   1/1     Running   0          44s

Serviceが作成されたか確認。

╰─$ kubectl get services
NAME                 TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)        AGE
kubernetes           ClusterIP   192.168.194.129   <none>        443/TCP        78m
nodejs-app-service   NodePort    192.168.194.247   <none>        80:32597/TCP   42s

アプリケーションへのアクセス

NodePortのポート番号を確認してアクセス:

╰─$ kubectl get service nodejs-app-service 
NAME                 TYPE       CLUSTER-IP        EXTERNAL-IP   PORT(S)        AGE
nodejs-app-service   NodePort   192.168.194.247   <none>        80:32597/TCP   88s

http://localhost:32597/

にアクセスすると下記が表示

Hello from OrbStack Kubernetes!

service.jsを更新する手順(mirrordなし)

service.jsを更新

レスポンスの文字列の末尾に「changed」を追加。

const http = require('http');

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello from OrbStack Kubernetes! changed\n');
});

const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Dockerイメージの再ビルド

docker build -t nodejs-k8s-demo:v1 .

Deploymentの更新

╰─$ kubectl rollout restart deployment nodejs-app
deployment.apps/nodejs-app restarted

変更の確認

╰─$ kubectl get pods
NAME                          READY   STATUS        RESTARTS   AGE
nodejs-app-5dd85958c6-dkhcd   1/1     Terminating   0          18m
nodejs-app-5dd85958c6-kxqr9   1/1     Terminating   0          18m
nodejs-app-7ff5cc5f8-gkxg4    1/1     Running       0          26s
nodejs-app-7ff5cc5f8-j27k5    1/1     Running       0          24s

http://localhost:32597/

にアクセスすると下記が表示

Hello from OrbStack Kubernetes! changed

mirrordの環境構築

https://mirrord.dev/

mirrordのinstall

https://github.com/metalbear-co/mirrord?tab=readme-ov-file#installation-2

brew install metalbear-co/mirrord/mirrord

xcodeのエラーが出た

brew install中に下記のエラーが出た。

Error: Xcode alone is not sufficient on Sonoma.
Install the Command Line Tools:
  xcode-select --install

↓下記のコマンドを実行して解決。

xcode-select --install

deployment更新

わかりやすくするためにレプリカを1つにする

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodejs-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nodejs-app
  template:
    metadata:
      labels:
        app: nodejs-app
    spec:
      containers:
      - name: nodejs-app
        image: nodejs-k8s-demo:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

変更したファイルを適用

kubectl apply -f deployment.yaml

service.jsを更新する手順(mirrordを使用)

レスポンスの文字列の末尾に「from local」を追加。

const http = require('http');

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello from OrbStack Kubernetes! from local\n');
});

const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

npm packageが存在する場合はnpm installしておきましょう。

npm install

mirrordのconfiguration

https://mirrord.dev/docs/using-mirrord/steal/

mirrord.jsonに設定を記述。一旦remoteに到達する全てのtrafficをローカルプロセスにリダイレクトさせるためにstealに設定。

{
  "feature": {
    "network": {
      "incoming": "steal"
    }
  }
}

mirrord実行

mirrordを使ってローカルコードを実行。

mirrord exec --target pod/nodejs-app-7ff5cc5f8-j27k5 -f mirrord.json node server.js

反映を確認

╰─$ curl http://localhost:32597/
Hello from OrbStack Kubernetes! from local

k8s serviceのurlであるが、ローカルのservice.jsの変更が反映されました。

dockerのイメージ再ビルドをすることなくローカルの変更が反映されました。

おわりに

今回はtrafficのstealしか設定しませんでしたがドキュメントには様々な設定方法が書かれています。細かい設定を試してみたい方はドキュメントもぜひ参考にしてみてください。

Discussion

ログインするとコメントできます