3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【本気で学ぶKubernetes】もう迷わない!Service タイプの正しい使い分け

Posted at

はじめに

こんにちは!

本記事は「本気で学ぶKubernetes」シリーズの第5回です。このシリーズでは、Kubernetesの基礎から実践まで、段階的に学んでいきます。

このシリーズは、第1回から順に読むことで体系的に学べる構成にしています。
まだご覧になっていない方は、ぜひ最初からご覧ください!

Kubernetesとは?クラスタ構成の全体像をつかむ

今回はServiceタイプについて深掘りして、それぞれの仕組みと使い分けを整理していければと思います。

この記事は人間がKubernetesの公式ドキュメントを読み漁りながら、人間の手で書いていますのでご安心ください!

前提知識

  • Kubernetes、Pod、Deployment、Serviceの基本概念を理解している方

Serviceとは(おさらい)

KubernetesにおけるServiceとは、 クラスター内で1つ以上のPodとして実行されているアプリケーションを内部や外部に公開する方法です。

以前の記事でServiceはPodへのアクセスを抽象化するための概念と記載しましたが、さらに詳しくいうと公式ドキュメントにも記載のある通り、Podを外部公開するための機能になります。

Podは独自のIPアドレスを保有しており、Podが破棄・削除されてIPアドレスが変更されてしまった場合でも問題なくアクセスできるようにします。

Serviceタイプの全体像

Kubernetesには主に4つのServiceタイプがあります。

タイプ 説明 公開先 主な用途
ClusterIP クラスター内でのみアクセス可能な内部通信の制御 内部向け Pod間の通信、クラスター内のアクセスなど
NodePort 各ノードの特定ポート(30000-32767)を開放して外部アクセス可能にする 外部向け 簡易的な外部公開
LoadBalancer クラウド環境のロードバランサーを作成して外部公開 外部向け 本番環境でのWebアプリケーション公開
ExternalName 外部のDNS名にマッピング(CNAME レコードを返す) - 外部サービスへのエイリアス作成

出典: Kubernetes公式ドキュメント - Service

ClusterIP

ClusterIPは、クラスタ内部でのみアクセス可能なServiceタイプです。
マニフェストでtypeを指定しない場合はデフォルトで利用されます。

外部からは直接アクセスできませんが、クラスタ内の他のPodからはこのServiceを経由してアクセスできます。

出典: Kubernetes公式ドキュメント - Service type: ClusterIP

仕組み

ClusterIPを作成すると、Kubernetesの内部のアドレスプールに仮想IPアドレスが割り当てられます。

Serviceを作成するタイミングで、KubenetesのAPI Serverからkube-proxyを呼び出して、この仮想IPへのアクセスを実際のPodにルーティングするためのiptablesのルールを生成するようになっています。
そのiptablesがNodeに適用されることで、Podへのアクセスが可能になるという仕組みです。

iptables モードを使用したサービス用の仮想 IP メカニズム

出典: Kubernetes公式ドキュメント - Virtual IPs and Service Proxies

マニフェスト

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

上記のマニフェストを適用すると、my-serviceという名前でアクセスできるServiceが作成されます。

ユースケース

ClusterIPは主にクラスタ内部でのサービス間通信に使われます。

具体例として以下のようなユースケースが挙げられます。

  • フロントエンドから外部非公開のバックエンドAPIにアクセスする場合
  • 同じクラスター内に構成したデータベースへアクセスする場合

フロントエンドからバックエンドAPIへのアクセスをする場合は、フロントエンド側のPodがbackend-service(ClusterIP)を経由してバックエンドPodへアクセスします。

また後者のユースケースにおいても、同じクラスター内に構成したデータベースは外部に公開する必要はありませんので、ClusterIPでの内部通信で十分そうですね。

つまり、内部に閉じる通信だけであればClusterIPを使って構成するのが一般的だと思います。

NodePort

NodePortは、各ノードの特定のポートを開放して、クラスタ外部からアクセスできるようにするServiceタイプです。

ClusterIPの機能に加えて、ノード上のポートを使った外部アクセスが可能になります。
指定できるのは30000-32767の範囲です。

出典: Kubernetes公式ドキュメント - Service type: NodePort

仕組み

NodePortを作成すると、ClusterIPも同時に作成されます。その上で、全ノードで同じポート番号が開放されます。
デフォルト設定では30000-32767の範囲から自動的に割り当てられますが、明示的に指定することも可能のようです。

トラフィックの流れは<NodeIP>:<NodePort> → ClusterIP → Podというルーティングになり、適切なPodにトラフィックが届くようになっています。

マニフェスト例

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
      nodePort: 30007

前回の記事ではminikubeコマンドでブラウザを開いてアクセスすることを確認しましたが、その際に使用していた機能です。

ユースケース

NodePort単体だとは主に開発環境やテスト環境で使われます。デフォルトだと30000台のポート番号が使われるということで、標準的なネットワーク設定だと管理が煩雑になりますし、これだけで本番公開することはあまりないと思います。

インターネット公開するような本番環境では後述するLoadBalancerを使う方が適切ですね。(内部的にはNodePortも使用されます)

出典: Kubernetes公式ドキュメント - NodePort

LoadBalancer

LoadBalancerは、クラウドのロードバランサーを自動的に作成して外部公開するServiceタイプです。

主に本番環境でWebアプリケーションやAPIサーバーを公開する際に使用します。

出典: Kubernetes公式ドキュメント - Service type: LoadBalancer

仕組み

LoadBalancerを作成すると、前述したClusterIPとNodePortが自動的に作成されます。その上で、クラウドが提供するロードバランサー(GKEならCloud Load Balancing、EKSならNetwork Load Balancerなど)が作成されて、外部IPアドレスが割り当てられます。

トラフィックの流れは、外部ロードバランサー → NodePort → ClusterIP → Podというルーティングになります。

k8s-ロードバランサー.png

マニフェスト例

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

ユースケース

エンドユーザーがアクセスするためのWebアプリケーションの公開や、外部の開発者やパートナーが利用する公開されたREST API、その他SaaSサービスでの利用が想定されます。

クラウドのロードバランサー自体は従量課金でコストが発生します。Serviceごとにロードバランサーが作成されるということで厳格に管理していくべき箇所になります。

出典: Kubernetes公式ドキュメント - LoadBalancer

ExternalName

最後に、ExternalNameについても簡単に説明します。
ここまでご紹介したようなルーティング制御というよりはDNSのCNAMEレコードを設定する機能になります。
例えば外部のデータベースを使っている場合にKubernetes内からmydb.default.svcといった名前でアクセスしたい場合に使います。

DNSのエイリアスを作るための機能というイメージで十分だと思います。

マニフェスト例

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

上記の場合に、my-service.prod.svc.cluster.localでホスト名検索すると、クラスター内のDNSサービスはCNAMEとして登録されたmy.database.example.comのレコードを返します。

これのメリットとしては、ExternalNameを書き換えることで使用するDBやAPIを開発環境や本番環境で使い分けれる部分にあります。

出典: Kubernetes公式ドキュメント - Service type: ExternalName

Serviceの内部動作について

ここからは少し踏み込んで、Serviceがどのように動作しているのか内部の仕組みを見ていきたいと思います。

kube-proxyの役割

ClusterIPの説明の中でkube-proxyについて触れました。
これはServiceの設定を参照して、仮想IPへのアクセスとPodにルーティングするためiptablesを自動で作成するための機能です。

kube-proxyにはいくつか動作のモードがありますが、ここではiptablesついて触れます。

iptablesモードは、文字通りiptablesルールを使ってトラフィックを転送します。

ServiceのCluster IPへリクエストを送信すると、iptablesのルーティングのルールに従って対象PodのIPにトラフィックが転送されます。

シンプルで使いやすそうですが、Serviceやエンドポイントが大量にある場合はiptablesのルールが大量になるので性能劣化の懸念もあるようです。

sessionAffinity

デフォルトでは、Serviceは毎回異なるPodにリクエストが転送されるようになっています。
しかし同じクライアントからのアクセスは同じPodにアクセスさせたいという要件も多いと思いま。
その際に使えるのがこのsessionAffinityの機能です。

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800  # 3時間
  selector:
    app: web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

上記のようにsessionAffinity: ClientIPを設定すると、同じクライアントのIPアドレスからのリクエストは、常に同じPodに転送されるようになります。

その他にもいろいろなモードや機能設定ができますので公式ドキュメントもご確認ください。

出典: Kubernetes公式ドキュメント - Virtual IPs and service proxies

まとめと次回予告

今回は、Serviceの4つのタイプについて確認しました。
内部通信専用のClusterIP、開発環境向けのNodePort、本番環境向けのLoadBalancer、エイリアス設定のExternalNameという部分だけは最低限理解しておいた方が良いと思います。

次回は「Secret」や「Volume」について確認していきたいと思います。

それでは、また明日!

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?