こんにちは、たねやつです。
前回、FastAPIアプリケーションをDeploymentとしてKubernetesクラスタにデプロイしました。Podが2つ、元気に動いていることも確認できました。
しかし、このままではPodはクラスタ内部のネットワークにしか接続されておらず、私たちのPC(クラスタ外部)からAPIにアクセスすることはできません。
今回は、このPodたちへの安定した入口を提供するService(サービス)リソースについて学びます。
前の記事
この記事でできること
- Kubernetesの
Serviceリソースの役割を理解できる。 Serviceの主な種類(ClusterIP,NodePort,LoadBalancer)の違いを説明できる。NodePortタイプのServiceを作成し、クラスタ外部からアプリケーションにアクセスできるようになる。
Serviceとは? なぜ必要か?
Deploymentによって管理されているPodは、再起動したり、別のノードに移動したりすると、その都度新しいIPアドレスが割り振られます。これでは、他のPodや外部のクライアントが安定して通信することができません。
この問題を解決するのがServiceリソースです。 Serviceは、複数のPodに対する単一の安定した窓口(IPアドレスとDNS名)を提供します。クライアントはServiceにアクセスしさえすれば、Serviceがその後ろにいる正常なPodのいずれかに、自動的にリクエストを振り分けて(ロードバランスして)くれます。
Serviceの主な種類
Serviceには、どのようにPodを公開するかに応じて、いくつかのタイプがあります。
| タイプ | 公開範囲 | 説明 |
|---|---|---|
ClusterIP |
クラスタ内部のみ | デフォルトのタイプ。クラスタ内部でのみ有効なIPアドレスをServiceに割り当てます。マイクロサービスのバックエンド間通信などで使われます。 |
NodePort |
クラスタ外部(ノード経由) | 各ワーカーノードに特定の静的ポートを公開します。ノードのIP:NodePortで、そのServiceにアクセスできるようになります。ローカルでのテストや学習で便利です。 |
LoadBalancer |
クラスタ外部(クラウド経由) | クラウドプロバイダー(AWS, GCPなど)が提供するロードバランサーを自動的にプロビジョニングし、Serviceに紐付けます。本番環境で外部にサービスを公開する際の標準的な方法です。 |
今回は、ローカルのMinikube環境でも簡単に試せるNodePortタイプを使ってみましょう。
Serviceマニフェストの作成
それでは、前回のDeploymentで作成した2つのFastAPI Podへのアクセスを提供するServiceを作成します。
service.ymlという名前で、以下のマニフェストファイルを作成してください。
apiVersion: v1
kind: Service
metadata:
name: fastapi-service
spec:
type: NodePort
selector:
app: fastapi
ports:
- protocol: TCP
port: 8080
targetPort: 80
# nodePort: 30007 # 省略すると30000-32767の範囲で自動的に割り当てられる
ポイント解説'
kind: Service: 作成するリソースがServiceであることを示します。spec.type: NodePort: ServiceのタイプをNodePortに指定しています。spec.selector: このServiceがどのPodにリクエストを転送するかを定義します。app: fastapiというラベルを持つPodを探して、転送先にします。これはDeploymentのtemplate.metadata.labelsで指定したラベルと一致させる必要があります。spec.ports: ポートのマッピングを定義します。port: 8080: このService自体のポート番号です(ClusterIPのポート)。targetPort: 80: 転送先であるPod(コンテナ)が待ち受けているポート番号です。DockerfileのCMDで指定したポートと一致させます。nodePort: ノード上で公開されるポート番号です。省略すると、Kubernetesが利用可能なポートを自動で選択します。
Serviceの適用と動作確認
kubectl applyコマンドでServiceを作成します。
kubectl apply -f service.yml
作成されたServiceを確認してみましょう。
kubectl get service fastapi-service # または kubectl get svc fastapi-service
TYPEがNodePortになっており、PORT(S)の項目に8080:3xxxx/TCPのようにポートマッピングが表示されているはずです。3xxxxの部分が、今回外部に公開されたNodePortの番号です。
Minikube環境では、以下のコマンドでこのServiceにアクセスするためのURLを簡単に取得できます。
minikube service fastapi-service --url
このコマンドが返したURL(例: http://127.0.0.1:31234)にブラウザでアクセスしてみてください。
{"message":"Hello World"}が表示されれば成功です!
表示されたURL/dbにアクセスすれば、DBのバージョン情報も取得できるはずです。
最後に
お疲れ様でした!今回は、Serviceリソースを使って、クラスタ内部で動いているアプリケーションを外部に公開する方法を学びました。
これで、DeploymentでPodを増やしたり、Podが再起動してIPアドレスが変わったりしても、クライアントは常に同じServiceの窓口にアクセスすればよくなりました。
Kubernetesにおけるデプロイの基本的な要素であるDeploymentとServiceが出揃いました。この2つが、アプリケーションを安定して運用するための根幹となります。
次回は本章の締めくくりとして、ここで学んだことを総括し、次のテーマであるMLOpsの世界を少しだけ覗いてみます。