Kubernetes完全ガイド 第6章 Discovery & LB リソース
コンテナに対するエンドポイントの提供や、ラベルに一致するコンテナのディスカバリ
Service
ClusterIP
ExternalIP
NodePort
LoadBalancer
Headless(None)
ExternalName
None-Selector
Ingress
ロードバランシング
Service は複数のPodに対するロードバランシングと、LB の接続口となるエンドポイントを提供
クラスタ内DNSとサービスディスカバリ
Serviceに属するPodを列挙したり、Serviceの名前からエンドポイントの情報を返す
環境変数を利用したサービスディスカバリ
pod内からサービス名(例: sample-_clusterip) -> SAMPLE_CLUSTERIP_PORT とかの環境変数として確認できる
DNS A レコードを利用したサービスディスカバリ
サービス名.namespace名.svc.cluster.local
コンテナ内の/etc/resolv.conf には search default.svc.cluster.local とかが記載されているので、省略できる
DNS SRV レコードを利用したサービスディスカバリ
port番号を含めたエンドポイントをDNSで解決する仕組み
<_ServiceのPort名>.<_protocol>.<service名>.<namespace名>.svc.cluster.local
例: _http-port._tcp.sample_clusterip.default.svc.cluster.local
*.cluster.local はクラスタ内DNSであり、これ以外はクラスタ外のDNSに再帰問い合わせをする
ClusterIP
クラスタ内からのみ疎通性があるinternal networkの仮想IPが割り当てられる
ClusterIP向けの通信は kube-proxy が pod 向けに転送を行う
port: ClusterIPで受け付けるport番号
targetPort: 転送先のコンテナのport番号
ClusterIP を静的に指定することも可能
ClusterIPの指定はImmutable なので、変更したい場合は削除からの再作成
ExternalIP
特定のKubernetes NodeのIPアドレス:Port で受信したトラフィックを、コンテナに転送する形で外部疎通性を確立する
type: ClusterIP を指定して、externalIPs にノードのIPのリストを指定する
kubectl get nodes -o custom-columns="IP: {status.addresses[].address}" とかでノードのIPを確認可能
serviceにはClusterIPが自動的に割り当てられ、ExternalIPも設定される
ノードで ss -napt とか netstat -nap で確認すると、ExternalIPのportをlistenしてるのを確認できる
NodePort
ExternalIPは一部のノードを指定したのに対し、NodePortはすべてのノードのIP:Portで受信したトラフィックをコンテナに転送
0.0.0.0:Port を使用してすべてのIPアドレスでBindするイメージ
全ノードのIPアドレスでspec.ports[].nodePortで指定したポートをlistenするため、バッティングに注意
spec.ports[].nodePort を明示的に指定しないと、空いているPort番号が自動で選択される
多くのk8s環境では 30000~32767 のポート範囲がデフォルトの利用可能範囲。範囲外だとエラー
ノードに到達したリクエストはノードをまたいだpodへもロードバランシングされる
spec.externalTrafficPolicy
Cluster(デフォルト): 他のノードにあるpodを含めてロードバランシングする
Local: ノードをまたがない。そのノードに該当のlabelのpodがない場合はレスポンスを返せない
この設定は LoadBalancer typeでも設定可能
LoadBalancer
クラスタ外のLoadBalancerに外部疎通性のある仮想IPを払い出すことが可能
NortPortではノードが単一障害点。LoadBalancerでは外部のLBを利用するため、ノードが単一障害点にならない
ClusterIPも自動で払い出される
ノードに到達したリクエストはノードをまたいだpodにバランシングされる
loadBalancerIP を指定することで静的なIPを設定
LoadBalancer側のFirewallを設定するためにAWSやGoogle Cloud等の実装あり
Google CloudではloadBalancerSourceRanges とか
Headless
対象の個々のpodのIPが直接返る
DNSラウンドロビンを使ったエンドポイント
クライアント側でのDNSキャッシュ等に注意
StatefulSetがHeadless Serviceを使っている場合に限り、pod名でIPアドレスをディスカバリできる
spec.type: clusterIP spec.clusterIP: None、Serviceのmetadata.nameがStatefulSetのspec.serviceName と同じである必要がある
ExternalName
Service名の名前解決に対して外部のドメイン宛のCNAMEを返す
クラスタ内からのエンドポイントを切り替えやすくする用途など
pod宛の通信にServiceを使うように、SaaS等の外部サービスの利用も疎結合にするのがよい
アプリ側ではServiceのFQDNを持ち、ExternalNameのCNAMEか、ClusterIPのAレコードを返す
None-Selector
ExternalName が外部ドメインへの転送に対し、None-Selectorはクラスタ内の自由な宛先へのロードバランサ
基本的にはClusterIP
externalNameを指定せず、Selectorが存在しないサービスを作成した後、Endpointリソースを作ることで柔軟なServiceを作成
(よくわかってない)
Ingress
L7ロードバランサ
kind: Ingress
リソースとコントローラ
一般にリソースをk8sに登録しただけでは何も処理されない
実際に処理を行うコントローラというシステムコンポーネントが必要
例えばDeploymentには対応したReplicaSetを作成したりレプリカ数を変更したりするDeployment Controller
Deployment Controllerがないと、Deploymentリソースを作成したとしてもReplicaSetは作成されない
Ingress と Ingress Controller
Ingressの実装は複数ある
GKE Ingress Controller
Nginx Ingress Controller
クラスタ外のLBを利用したIngress
Ingressリソースを作成するだけでLBの仮想IPが払い出されて、利用可能になる
例えばGCLBがTLS終端、パスベースルーティングを行い、NortPortに転送する
クラスタ内にIngress用のPodをデプロイするIngress
Ingress用のPod宛にLoadBalancer Serviceを作成するなどが必要
Nginx Ingress
Ingressは、バックエンドとしてServiceが必要