GKE(Google Kubernetes Engine)のServiceについて

2023年1月11日

Serviceとは

  • 固定のIPアドレスをもつRESTのオブジェクト
  • Cluster内外からのPod群(や、その他のバックエンド)へのアクセスを抽象化し、L4負荷分散の役割も担う
    • PodもIPアドレスを持つが、同じPodが複数ある場合や、頻繁に破棄・再生成される場合があり、サービスに対するIPアドレスが定まらない
    • 負荷分散アルゴリズムの設定については別途調査予定

Serviceのtype

ClusterIP

  • デフォルトのモード
  • Cluster内部からのみアクセス可能なService
  • Pod間通信をさせたいがCluster外部からPodへアクセスさせたくない場合はこれを使う
apiVersion: v1
kind: Service
metadata:
  name: my-cip-service
spec:
  selector:
    app: metrics
    department: sales
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

NodePort

  • ノードのある特定のポートへのアクセスを受け付けるService
    • ノード:マシンのこと
    • ポート番号は、Kuberentesが自動で指定する(非推奨だが、マニフェスト内のnodePortというキーに割り当てる値(30000~32767)で指定することもできる)
  • ノードのある特定のポートにアクセスすればよいので、Cluster外からもアクセスできる
  • Cluster外部からPodへのアクセスを受け付けたい場合はこれを使うが、基本的に直接アクセスできてしまいセキュリティ的によろしくないので、デバッグかdemoアプリのみで使う
  • ClusterIPの拡張版
apiVersion: v1
kind: Service
metadata:
  name: my-np-service
spec:
  selector:
    app: products
    department: sales
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

LoadBalancer

  • Cloud Load Balancingのロードバランサ―が作成されるService
  • Cluster内外から、作成されたロードバランサ―のIPアドレスにアクセスすることでServiceにアクセスできる
  • NodePortの拡張版
  • 作成できるロードバランサ―の種類は下記の種類
    • 内部ロードバランサ―
      • Clusterが所属するVPC(Virtual Private Cloud)ネットワークに接続されたネットワークにあるクライアントのみがServiceにアクセスすることができる
      • metadata.annotations[]に、下記のアノテーションを設定する必要がある
        • networking.gke.io/load-balancer-type: "Internal" (GKE 1.17 以降)
        • cloud.google.com/load-balancer-type: "Internal" (1.17 より前のバージョン)
    • 外部ロードバランサ―
      • 外部からServiceにアクセスすることができる
      • 負荷分散の方法が異なる下記の種類のロードバランサ―を設定可能
        (違いの詳細については要追加調査)
        • バックエンドサービスベースのロードバランサー
          • metadata.annotations[] cloud.google.com/l4-rbs: "enabled" を設定する
        • ターゲットプールベースのロードバランサ―

ExternalName

  • Cluster外のサービスへのアクセスを、Cluster内にあるかのように抽象化できるService
  • metadata下のnameキーに設定した値がmy-xn-serviceで、spec下のexternalNameというキーに設定した値がexample.comだった場合(節末の例を参照)、Cluster内のPodからmy-xn-service.default.svc.cluster.localへアクセスすると、example.comへリダイレクトされる
    • defaultの部分はServiceのnamespace名
  • Cluster内からCluster外のサービスを、IPアドレスを抽象化して使いたいときにこれを使う
apiVersion: v1
kind: Service
metadata:
  name: my-xn-service
spec:
  type: ExternalName
  externalName: example.com

Headless

  • 負荷分散の機能とIPアドレスを持たないService
  • spec下のclusterIPというキーにNoneを設定することでHeadless Serviceを構成できる
  • ServiceとしてのIPアドレスは持たない(Cluster IPは持たない)が、selectorに設定したPod群のIPアドレスすべてをDNAが返す
    • 下の例であれば、hl-service.default.svc.cluster.localのIPアドレスをCluster内のDNSに問い合わせると、app: mongodbのPod群のIPアドレスがすべて返ってくる(hl-serviceのnamespaceがdefaultと想定)
  • (Serviceにより抽象化されない)ある特定のPodと直接通信したい場合にこれを使う
    • 状態を持つアプリケーション(例えばDBなど)のデバッグ用途が主
    • NodePort Serviceを使うとどのPodにアクセスできるかわからない
apiVersion: v1
kind: Service
metadata:
  name: hl-service
spec:
  clusterIP: None
  selector:
    app: mongodb
  ports:
  - protocol: TCP
    port: 27107
    targetPort: 27107

参考