今回は、Discovery&LBリソースタイプを説明します。WorkloadsリソースにおけるPodやReplicaSetなどの基本的なリソースに対して、外部から参照する口を提供するものです。

まず、ServiceはL4のロードバランシングを実現します。Podの数は変動するため、個別のIPアドレスへアクセスするというよりは、代表IPアドレスにアクセスするなどにより、個別のPodとの疎結合を実現します。

次に、IngressはL7ロードバランシングを実現します。IPアドレスは同じだが、別のPodにアクセスさせたい場合などに利用します。URL1へのアクセスはPodAへ、URL2へのアクセスはPodBへといった制御が可能です。

次節より、ServiceとIngressについて、それぞれ説明します。

リソースタイプ(再掲)

4つのServiceの特徴

Serviceの種別は以下の4つです。それぞれについて説明を交えていきます。

  • 1. ClusterIP
    • クラスタ内仮想IP指定
    • 外部公開IP指定(externalIPs)
    • Headless(DNSラウンドロビン)
    • Endpoint(selector 指定無し)
  • 2. NodePort
  • 3. Loadbalancer
  • 4. ExternalName

以下、設定例を先に示しておきます。ClusterIPをベースとした設定例としていますが、NodePortなど他の種別に変更する方法を、コメントアウト(#)で記載しています。設定箇所の違いを併せて理解していくと良いでしょう。

apiVersion: v1
kind: Service
metadata:
  name: sample-clusterip
spec:
  type: ClusterIP # 他にもNodePort、LoadBalancer、ExternalNameがある
  clusterIP: xxx.xxx.xxx.xxx # Headlessの場合はNoneを指定
  # externalIPs:
  #   - xxx.xxx.xxx.xxx
  #   - xxx.xxx.xxx.xxx
  # externalName: ext.sample.com (typeがExternalNameの際に指定)

  ports:
    - name: "http-port"
      protocol: "TCP"
      port: 8080
      targetPort: 80
      # nodePort: 38080 (NodePort、LoadBalancerの時に指定)
  selector:
    app: sample-app

#apiVersion: v1
#kind: StatefulSet (Headlessの場合で、かつPod名でのサービスディスカバリをする場合
#kind: Endpoint (個別の転送先を指定する場合)

順に説明していきましょう。

ClusterIP

1つ目に、ClusterIPサービスはクラスタ内でアクセス可能な代表IPアドレスを提供します。デフォルトで、このService種別になります。以下の例では、ClusterIPサービスを[spec.type]にて指定し、[clusterIP]にてクラスタ内からアクセス可能な仮想IPを指定しています。[externalIPs]を設定するとクラスタ外部からのアクセスのための代表IPアドレス提供します。

サービスディスカバリを行うためのServiceを定義したい場合には、clusterIPにNoneを設定することで、Headlessサービスを作成できます。代表IPアドレスは提供されず、個々のPodへのIPアドレスへアクセスするためのDNSラウンドロビン機能が提供されます。

個別の転送先を定義したい場合には、Endpointリソースと組み合わせて定義します。[spec.selector]を指定せず、同名のEndpoint(sample-app)を設定します。

NodePort

2つ目に、NodePortサービスは各Podへの直接アクセスを可能とし、指定した<NodeIP>:<NodePort>にアクセスできます。お試し環境などで、外部からPodへ簡易にアクセスしたい場合は、NodePortサービスを利用すると良いでしょう。

LoadBalancer

3つ目に、LoadBalancerサービスはクラスタ外に代表IPアドレスを提供します。外部に公開するという意味では、externalIPsとNodePortもありますが、いずれかのNodeが単一障害点となってしまいます。LoadBalancerでは外部の仕組みで信頼性を担保するため、本番運用を見据える上では最も実用的と言えるでしょう。

ExternalName

4つ目にExternalNameサービスは外部のドメイン宛のCNAMEを返す機能を提供します。一方でNon-SelectorはClusterIPなどの自ら定義したサービスのCNAMEを返します。

YAMLとの関連

設定箇所の差分をより明確にするため、前述の内容を表形式にし、各Serviceの種類/特徴と設定項目(YAML)の対応づけを示します。

表:Serviceの種類/特徴と設定項目(YAML)の対応づけ

各Serviceの特徴/用途 YAML内の設定箇所
spec kind
type clusterIP externalIPs externalName ports[].nodePort selector StatefulSet Endpoint
クラスタ内仮想IP指定 ClusterIP - - - - -
外部公開IP指定(externslIPs) - - - - -
Headless(DNSラウンドロビン) ◯(None) - - - ※2 -
Endpoint - - - - - -
外部公開Port指定 NodePort - - - - -
クラスタ外ロードバランサの配置 LoadBalancer - - - ※1 - -
名前解決(CNAME) ExternalName - - - - - -
※1 指定しない場合は自動でポートが付与される
※2 Pod名でのサービスディスカバリをする場合指定する

Ingress

Minikubeのアドオンを使ってIngressを使ってみましょう。enableオプションを使って起動するのみでインストール完了です。

$minikube addons list
- ingress: disabled
$minikube addons enable ingress
  ingress was successfully enabled
$kubectl get pod -n kube-system
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-586cdc477c-lllkc   1/1     Running   0          15s

※ 無関係な行は記載を省略

DeploymentとServiceを作った上で、Ingressリソースを作ってみましょう。

$kubectl create deployment sample-nginx --image=nginx
deployment.apps/sample-nginx created
$kubectl expose deployment sample-nginx --target-port=80 --port=80
service/sample-nginx exposed
$cat sample.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx
spec:
  rules:
  - host: sample.nginx
    http:
      paths:
      - backend:
          serviceName: sample-nginx
          servicePort: 80
$kubectl apply -f sample.yaml
ingress.extensions/nginx created
$kubectl get ing
NAME    HOSTS          ADDRESS     PORTS   AGE
nginx   sample.nginx   10.0.2.15   80      4m53s

作成したIngressにアクセスしてみましょう。ホスト名[sample.nginx]にてアクセスできていることがわかります。

$curl -I http://`minikube ip` -H 'Host: sample.nginx'
HTTP/1.1 200 OK
Server: nginx/1.15.9
Date: Sat, 20 Apr 2019 18:44:19 GMT
Content-Type: text/html
Content-Length: 612
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Tue, 16 Apr 2019 13:08:19 GMT
ETag: "5cb5d3c3-264"
Accept-Ranges: bytes

*  *  *

今回は5つのリソースタイプの2つ目であるDiscovery&LBを紹介しました。コンテナの外部からL4でアクセスするServiceやL7でアクセスするIngressなどがあります。

簡易に試したい場合や、本番環境で運用したい場合など利用シーンに応じて使い分けると良いでしょう。連載第3回で紹介しましたが、マネージドサービスや構築ツールによってさまざまな特徴があります。例えば、マネージドサービス以外の場合、LoadBalancerなど利用環境が限定されるケースもあります。使い始めてから制約を知るということがないよう、利用条件を確認しておくと良いでしょう。

著者紹介


正野 勇嗣 (SHONO Yuji ) - NTTデータ 課長

2011年まで開発自動化技術のR&Dに従事。その後、開発プロジェクト支援やトラブルシューティング等に主戦場を移す。「ソースコード自動生成」に加えて、JenkinsやMaven等の「ビルド自動化」、JsTestDriverやSelenium等の「テスト自動化」を扱うようになり、多様化する開発自動化技術動向に興味。

最近は第四の自動化であるInfrastructure as Code等の「基盤自動化」の魅力に惹かれている。開発自動化技術に関する雑誌・記事執筆も行う。2児のパパ。