たねやつの木

Photographs, Keyboards and Programming

【Kubernetesを学ぶ:6日目】Serviceリソースでアプリケーションを外部に公開する

こんにちは、たねやつです。

前回、FastAPIアプリケーションをDeploymentとしてKubernetesクラスタにデプロイしました。Podが2つ、元気に動いていることも確認できました。 しかし、このままではPodはクラスタ内部のネットワークにしか接続されておらず、私たちのPC(クラスタ外部)からAPIにアクセスすることはできません。 今回は、このPodたちへの安定した入口を提供するService(サービス)リソースについて学びます。

前の記事

www.taneyats.com

この記事でできること

  • 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を探して、転送先にします。これはDeploymenttemplate.metadata.labelsで指定したラベルと一致させる必要があります。
  • spec.ports: ポートのマッピングを定義します。
    • port: 8080: このService自体のポート番号です(ClusterIPのポート)。
    • targetPort: 80: 転送先であるPod(コンテナ)が待ち受けているポート番号です。DockerfileCMDで指定したポートと一致させます。
    • nodePort: ノード上で公開されるポート番号です。省略すると、Kubernetesが利用可能なポートを自動で選択します。

Serviceの適用と動作確認

kubectl applyコマンドでServiceを作成します。

kubectl apply -f service.yml

作成されたServiceを確認してみましょう。

kubectl get service fastapi-service
# または kubectl get svc fastapi-service

TYPENodePortになっており、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におけるデプロイの基本的な要素であるDeploymentServiceが出揃いました。この2つが、アプリケーションを安定して運用するための根幹となります。

次回は本章の締めくくりとして、ここで学んだことを総括し、次のテーマであるMLOpsの世界を少しだけ覗いてみます。

次の記事

www.taneyats.com