エントリーのリソースの違いがあやふやになってしまったので、整理した。
Discovery&LBリソース
デプロイされているPod(コンテナ)に外部からアクセスできるようにするリソース。
エンドポイントの提供などをしれくれる。
大きく、SerivceとIngress に分かれる。
両者の違いは、SerivceリソースはL4のロードバランシングを提供するのに対して、 IngressリソースはL7のロードバランシングまで提供してくれる。
つまり、Ingressはパスルーティングを実現できたりする。
Serviceリソース
細かくは7つに分かれる。
- ClusterIP
- ExternalIP
- NodePort
- LoadBalancer
- Headless(None)
- ExternalName
- None-Selector
下から3つについては、今回は省略する。
Cluster IP
クラスタ内部ネットワークのみで疎通できる仮装IPが割り当てられる。 指定した Podに対してロードバランシングを行う。
例えば、クラスタで動くPodAから 3台動いているPodBにアクセスしたいとき、PodAからはCluster IPで割り当てられたIPにアクセスすると、 いい感じにロードバランシングしてくれて、PodBにアクセスすることができる。
構成ファイル例
kind: Service apiVersion: v1 metadata: namespace: wakashiyo-development name: wakashiyo-dev-clusterip spec: selector: app: nginx type: ClusterIP ports: - name: "http-port" port: 8080 targetPort: 80
selectorにはdeployment等でデプロイしているPodのラベルを設定している。
portでCluster IPが受け付けるポート番号を指定し、
targetPort で転送先のコンテナのポート番号を指定する。
External IP
前述のCluster IPは内部疎通だけだったが、これはクラスタ外からも疎通できる。
指定したクラスタのIPアドレスを指定することで、そのNodeへのアクセスを指定したコンテナにロードバランシングする。
ロードバランシングされるのは、指定したIPのNodeにあるコンテナだけでなく、デプロイされているコンテナ全てにロードバランシングされる。
kind: Service apiVersion: v1 metadata: namespace: wakashiyo-development name: wakashiyo-dev-clusterip spec: selector: app: nginx type: ClusterIP # kubectl get nodes -o custom-columns="NAME:{metadata.name},IP:{status.addresses[].address}" externalIPs: - 10.146.0.16 ports: - name: "http-port" port: 8080 targetPort: 80 # It did not work
先ほどのCluster IPと異なるのは、externalIPs という項目が増えている。 これは、GKEであれば、GCEインスタンスの外部IPではなく、OSなどから確認できる内部のIPを使用することができるらしい。
NodePort
こちらは、external IPが外部疎通性のあるノードを指定したのに対して、 こちらは、全てのNodeの外部疎通性を提供する。
(厳密には、0.0.0.0:portnumberでListenし、Node全てのIPにBindする形でロードバランシングされる)
なので、3台のノードが存在した場合、いずれかのIPアドレスにアクセスすると、NodePortからロードバランシングされ、 コンテナにアクセスができる。
構成ファイル例
kind: Service apiVersion: v1 metadata: namespace: wakashiyo-development name: wakashiyo-dev-nodeport spec: selector: app: nginx type: NodePort ports: - name: http-port port: 8080 targetPort: 80 nodePort: 30080 # It did not work when use not ingress
ports.nodePort という項目が増えている。
これは、NodePort -> ClusterIP -> Pod(container)
のようにクラスタ内部ではClustert IP のようにトラフィックが流れる。
port はCluster IPで受け付けるポート番号に対して、nodePortはクラスタのnodeで受け付けるポート番号になる。
LoadBalancer
今までは外部疎通性を提供するのに、node自身のIPを外部疎通できるように設定していたのに対して、
これは完全にクラスタ外に作成されるイメージになる。
その名の通り、クラスタ外のロードバランサが指定したコンテナに対してロードバランシングしてくれる。(L4レベルで)
とあるNodeが障害の場合、そのNodeへのトラフィックは流れないようにしてくれる。
GKEだと内部的にはロードバランサのサービスが使用されているらしい。
構成ファイル例
kind: Service apiVersion: v1 metadata: namespace: wakashiyo-development name: wakashiyo-dev-lb spec: selector: app: nginx type: LoadBalancer ports: - name: "http-port" port: 8080 targetPort: 80 nodePort: 30082 # firewall rule (default: 0.0.0.0/0) loadBalancerSourceRanges: - 10.0.0.0/8
こちらのnodePortはロードバランサで受け付けるポート番号のことを指す。
NodePortと同様にクラスタ内部ではCluster IPが存在して、Cluster IP経由でコンテナまで疎通することができる。
loadBalancerSourceRangesを使用することで、指定したIPレンジからの送信しか受け付けないようにすることができる。
冷やっとしたのは、GKEの場合、Load Balancerを作成した時点で、GCPのロードバランサが作成され、静的IPが払い出される。
これは、クラスタを削除したりしても消えないので注意した方がいい。
Ingress
LoadBalancerと違って、L7のロードバランシングまで提供してくれる。
こちらも内部的には、GCPのロードバランサが使用されている。
構成ファイル例
apiVersion: extensions/v1beta1 kind: Ingress metadata: namespace: wakashiyo-development name: w-d-ig spec: rules: - http: paths: - path: /path1/* backend: serviceName: w-d-np1 servicePort: 8080 - path: /path2/* backend: serviceName: w-d-np2 servicePort: 8080 - path: /path3/* backend: serviceName: w-d-np3 servicePort: 8080
backendには転送したいserviceを指定する。
ここでは、3つのNodePortをあらかじめ用意してからingressをデプロイしている。
というのも、Ingressはserviceをバックエンドとして転送する仕組みになっているため、
Serivceをbackendとして指定している。
ingressを通して公開されるコンテナはロードバランサからのヘルスチェックに応答できるようにしなければならない。
ヘルスチェックで何が行われるかというと、ルートパスへのGETリクエストが来るので、そのリクエストに対して200を返すようにしなければならない。
このことを最初知らずに、いつまで経ってもデプロイが失敗して1時間ほど溶かしてしまった。
Ingress を使用した HTTP(S) 負荷分散 | Kubernetes Engine のドキュメント | Google Cloud