Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what? がよくまとまった記事だったので社内で共有するために適当に訳してみた
Kubernetes NodePort と LoadBalancer と Ingress のどれを使うべきか
最近、NodePorts、LoadBalancers、Ingress の違いを尋ねられます。
それらは外部のトラフィックをクラスタ内に取り込む方法で、全て異なる方法で実現しています。
それぞれがどのように動作するか、それとどのように使うべきか見てみましょう。
注意 : すべてがGKEで適用したものであり、もしあなたがその他のクラウド、オンプレ、minikube、その他で稼働している場合には少々異なる場合があります。深い技術的な説明はしません。もっと学ぶことに興味があれば、オフィシャルドキュメントはとてもいい資料です。
ClusterIP
ClusterIPは標準のk8sサービスです。
ClusterIPはクラスタ内のアプリケーションがアクセスできるクラスタ内のサービスを提供し、外部からのアクセスはできません。
ClusterIPサービスのYAMLは以下のようになります :
apiVersion: v1
kind: Service
metadata:
name: my-internal-service
spec:
selector:
app: my-app
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
ClusterIPに外部からアクセスできない場合、なぜでしょう。
あなたはKubernetes Proxyを利用してアクセスできることがわかります。
Kubernetes Proxyを起動します :
$ kubectl proxy --port=8080
今度はこちらのスキームを利用して、Kubernetes APIにたどり着くことができます
http://localhost:8080/api/v1/proxy/namespaces//services/<SERVICE-NAME>:<PORT-NAME>/
よって、上で定義したサービスにアクセスするには、以下のアドレスを利用することができます
http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/
どんな時に使いますか?
Kubernetes Proxyを利用してあなたのサービスにアクセスするいくつかのシナリオがあります
サービスをデバッグする、もしくは、直接何らかの理由でラップトップから直接接続を行う。
内部トラフィックを許可する、ダッシュボードを閲覧するなど。
しかしこの方法を用いて、kubectlを認証されたユーザで実行する必要があり、サービスをインターネットに公開したり、プロダクションサービスとして利用すべきではありません。
NodePort
NodePortサービスは外部トラフィックをあなたのサービスに届ける最も基本的な方法です。
NodePortの名前が示すように、すべてのノードの特定のポートを開き、このポートに送られたすべてのトラフィックはサービスにフォワードされます。
NodePortサービスのYAMLは以下のようになります :
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
spec:
selector:
app: my-app
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
基本的に、NodePortサービスには通常の "ClusterIP" サービスとの2点違いがあります。
まず、Typeが "NodePort" であり、ノード上で開くポートを指定する nodePort
という追加のポートもあります。
もしポートを指定しない場合にはランダムなポートが選択されます。
殆どの場合、Kubernetesにポートを選択させる必要があります。thockinによれば、利用できるポートについては多くの注意点があります。
どんな時に使いますか?
これらの方法には多くの弱点があります :
1サービスあたり1つのポートしか利用できない
30000–32767の間のポートだけが利用できます
ノード/VMのIPを変更した場合、対処する必要がある
それらの理由から、その方法を利用してプロダクションのアプリケーションを公開することを私はおすすめしません。
いつも利用可能である必要がないサービスを実行している場合や、コストを気にする場合、この方法は役にたちます。
そのようなアプリケーションの良い例はデモアプリケーションや一時的なものの場合です。
LoadBalancer
LoadBalancerサービスは、サービスをインターネットに公開する一番標準な方法です。
GKEでは、Network Load Balancerが立ち上がり、すべてのトラフィックがサービスにフォワードされる1つのIPアドレスを取得できます。
どんな時に使いますか?
あなたが直接サービスを公開しようとしたばあい、これが標準の方法です。
指定したすべてのポートに対するトラフィックがサービスにフォワードされます。
フィルタリングされず、ルーティングなどもされません。
HTTP、TCP、UDP、Websocket,gRPCなど様々なあらゆる種類のトラフィックを送ることができます。
大きな欠点として、LoadBalancerを利用して公開するそれぞれのサービスがIPアドレスを取得し、LoadBalancerを公開するサービスごとに支払いが発生するため、とても高価になります!
上記の例と違い、Ingressは実際にはサービスの一種ではありません。
代わりに、複数のサービスの前に配置され、"smart router" または、クラスタのエントリポイントとして振る舞います。
あなたはIngressを利用することで様々な事ができる、異なる機能を持った様々なタイプのIngressコントローラーがあります。
標準のGKEのIngressコントローラーはHTTP(S) LoadBalancerを起動します。
そのため、バックエンドサービスへのパスベースルーティングとサブドメインベースルーティングの両方ができます。
たとえば、foo.youdomain.com宛はfooサービスへ、youdomain.com/bar/以下の全てはbarサービスへ送ることができます。
L7 HTTP Load Balancerを使用するGKEのIngressオブジェクトのYAMLは次のような感じです :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
backend:
serviceName: other
servicePort: 8080
rules:
- host: foo.mydomain.com
http:
paths:
- backend:
serviceName: foo
servicePort: 8080
- host: mydomain.com
http:
paths:
- path: /bar/*
backend:
serviceName: bar
servicePort: 8080
どんな時に使いますか?
Ingressはあなたのサービスを外部に公開する場合に最もパワフルな方法ですが、最も難解な方法にすることもできます。
Ingressコントローラーの種類は、GCLB、Nginx、Contour、istioなどあがります。
また、cert-managerのようなIngressコントローラー用のプラグインもあり、サービスのSSL証明書を自動的にプロビジョニングできます。
Ingressは同じIPアドレスで複数のサービスを公開吸う場合に非常に便利であり、これらのサービスはすべて同じL7プロトコルを利用します。(通常はHTTP)
ネイティブGCP統合を利用している場合にはLoadBalancer一台分を払うだけ、Ingressは "smart" なので、多くの機能をそのまま利用できます。(SSLやAuth,Routingなど)