GKEでFastAPIサーバを公開してみた
今回はkubernetesの練習を兼ねて、FastAPIサーバをGKE上にデプロイしてみました。
GKEへのFastAPIサーバのデプロイ
システム構成
今回はレプリカ数を1としてFastAPIサーバをGKE上で構築します。ロードバランサーサービスを利用して外部公開しました。
Google Cloudの設定
ここではプロジェクトは作成済みであるとします。
まず、Dockerイメージを保管するためのArtifact Registryを作成します。
gcloud artifacts repositories create fastapi-repo --repository-format=docker --location=asia-northeast1
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
Pythonコードの実装
まずはプロジェクトをuv
を利用して初期化します。
uv init fastapi_k8s -p 3.12 && cd fastapi_k8s
uv add fastapi uvicorn
touch main.py
次にFastAPIサーバを実装します。今回実装するコードはGETメソッドでhelloと返すだけのAPIを実装します。
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
def hello():
return {"message": "hello"}
Artifact RegistryへのDockerイメージのpush
まず先ほど実装したFastAPIサーバをデプロイするためのDockerfileを用意します。uv
をホストするためのイメージが提供されているので利用します。
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim
WORKDIR /app
COPY . /app
EXPOSE 80
RUN uv sync
CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
次に、イメージをビルドしてpushします。なお、私はmacbookを使っているので--platform linux/amd64
を指定してGKE上で実行できるようにします。
docker build -t fastapi-gke . --platform linux/amd64
docker tag fastapi-gke asia-northeast1-docker.pkg.dev/<PROJECT_ID>/fastapi-repo/fastapi-gke:latest
docker push fastapi-gke asia-northeast1-docker.pkg.dev/<PROJECT_ID>/fastapi-repo/fastapi-gke:latest
Kubernetes設定ファイルの作成
まずはDeploymentの設定を作成します。今回はReplicaSetは1つだけ作成するものとします。また、dockerイメージのタグは毎回latest
を指定したいので、imagePullPolicy: Always
にしています。そして、FastAPIサーバはポート80を使っているのでポートの指定もしています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: fastapi-deployment
spec:
replicas: 1
selector:
matchLabels:
app: fastapi
template:
metadata:
labels:
app: fastapi
spec:
containers:
- name: fastapi
image: asia-northeast1-docker.pkg.dev/<PROJECT-ID>/fastapi-repo/fastapi-gke:latest
imagePullPolicy: Always
ports:
- containerPort: 80
次に外部公開するためにロードバランサーを実装します。fastapi
というラベルをつけたサーバを対象にポート80番でロードバランサーとして利用します。
apiVersion: v1
kind: Service
metadata:
name: fastapi-service
spec:
type: LoadBalancer
selector:
app: fastapi
ports:
- protocol: TCP
port: 80
targetPort: 80
GKEへのデプロイ
まずはクラスタを作成します。今回はArtifact Registryなどはasia-northeast1に作成しましたが、GKEクラスタはうまく作成できずus-central1
にて構成しました。実際の運用では同じリージョンでするのがベストですね。今回はノードは2つとし、マシンタイプはn1-standard-4
を利用しました。
gcloud container clusters create fastapi-cluster --zone us-central1-a --num-nodes 2 --machine-type n1-standard-4
次に、先ほど用意したKubernetes設定を反映します。
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
デプロイできたかを確認するために、まずはPodを確認します。ちゃんとfastapi-deployment-<hash>のようにPodが一つ作成されていることが確認できました。
kubectl get pods --output wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fastapi-deployment-64cb8c5957-jbz2m 1/1 Running 5 (18m ago) 20m 10.80.0.7 gke-fastapi-cluster-default-pool-3e21fba6-rx8c <none> <none>
次にロードバランサーの情報を見てみましょう。以下のように、外部IPアドレスが払い出されました(一応隠しています)。
kubectl get service fastapi-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fastapi-service LoadBalancer <CLUSTER_IP> <EXTERNAL-IP> 80:30727/TCP 40m
アプリケーションへのアクセス
先ほど確認したロードバランサーの外部IPアドレスを利用してアクセスしてみます。ブラウザで<EXTERNAL-IP>/hello
と入力すると、以下のように指定したメッセージが帰ってくることを確認できました。また、<EXTERNAL-IP>/docs
でSwagger UIも表示できることを確認しました。
まとめ
今回は、Kubernetes上でFastAPIサーバをデプロイしてみました。レプリカ数も1にしていますしサーバ構成も最低限のものでありDBなどがないためシンプルでした。今後はもっと複雑なシステムを作ってみたいと思います。
Discussion