入門 Kubernetes の読書メモ、第3弾。
- Kubernetesクラスタを構成するコンポーネントについて(入門k8s 読書メモ) - えいのうにっき
- Kubernetes における Label と Annotation(入門k8s 読書メモ) - えいのうにっき
- 作者:Kelsey Hightower,Brendan Burns,Joe Beda
- 発売日: 2018/03/22
- メディア: 単行本(ソフトカバー)
Kubernetes でのサービスディスカバリ
Kubernetes は、ノードへの Pod の配置を制御し、Pod が間違いなく起動して動き続けているようにし、必要に応じて別のノードに割り当て直す・負荷に応じて Pod の数を自動的に変更する、など、ダイナミックなシステムである。
このダイナミックな性質により、Kubernetes 上でたくさんのサービスを同時に実行することができるが、同時に、動いているサービスを見つけることが難しくなる。「稼働しているサービスを見つけることが難しくなること」「その解決策」を、サービスディスカバリと呼ぶ。(DNSも伝統的なサービスディスカバリの一種。)
Service オブジェクト
- Kubernetes オブジェクトのうちのひとつ。名前の付いた Label セレクタを作る仕組み。
- クラスタ内外に対してサービスを公開するための、柔軟で強力な方法。
- Label については Kubernetes における Label と Annotation(入門k8s 読書メモ) - えいのうにっき
kubectl expose
で Service を作成することが可能。kubectl expose
することにより、対象(ここでは Deployment)の定義から、「Label セレクタ」と「関連するポート情報」を引用してくる。
$ kubectl expose deployment hoge-prod $ kubectl get services -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.43.xxx.x <none> 443/TCP 32d <none> hoge-prod LoadBalancer 10.43.xxx.xx 35.230.xx.xxx 80:31000/TCP 32d app=hoge,env=prod,ver=2
- さらに Service は、クラスタIPと呼ばれる新しいタイプの仮想IPアドレスを割り当てる。
- 同じ Label セレクタがつけられたすべてのPodにロードバランスするために使用する、特別なIPアドレス。
クラスタIPと Service DNS
- クラスタIPは仮想IPのため、Service オブジェクトを再作成しない限りは変更されない
- そのため、DNSアドレスとして使用するのにも適している
- 同一 Namespace 内において、Service によって識別される Pod に接続する際、Service 名を使ってしまうことができる
$ dig hoge-prod A ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45113 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 4 ;; QUESTION SECTION: ;hoge-prod.default.svc.cluster.local. IN A ;; ANSWER SECTION: hoge-prod.default.svc.cluster.local. 30 IN A 10.43.xxx.xx
- Kubernetes DNS Service は、クラスタIPのDNS名を返す。
- 完全な DNS 名は
hoge-prod.default.svc.cluster.local.
。10.43.xxx.xx
は Service のクラスタIPと一致している。
- 完全な DNS 名は
外部からのアクセスを受け入れる
- 外部からのアクセスを受け入れる際、Service を拡張する NodePort を使う。
- クラスタIPに加え、システムがポートを選択する/ユーザーがポートを指定することもできるようになる
- クラスタ内の各ノードは、そのポートにトラフィックをフォワードできるようになり、それにより、クラスタ内のノードにアクセスさえできれば、Serviceと通信できるようになる
- NodePort をハードウェア、もしくはソフトウェアのロードバランサと連携させて Service を公開することも可能。
$ kubectl describe service hoge-prod Name: hoge-prod Namespace: default Labels: app=hoge-prod env=prod ver=2 Annotations: <none> Selector: app=hoge-prod,env=prod,ver=2 Type: LoadBalancer IP: 10.43.xxx.xx LoadBalancer Ingress: 35.230.xx.xxx Port: <unset> 80/TCP TargetPort: 8080/TCP NodePort: <unset> 31000/TCP Endpoints: 10.40.xx.x:8080,10.40.xx.x:8080,10.40.xx.x:8080 + 1 more... Session Affinity: None External Traffic Policy: Cluster Events: <none>
システムが、ポート31000をこの service に割り当てたことがわかる・クラスタ内のどのノードからも、Service へのアクセスにこのポートを使えるようになった。Service に対して送信されたリクエストは、Service で定義されている Pod のどれかにランダムで送られる。
クラウドとの統合
- クラスタを動かしているクラウドでサポートされており、なおかつクラスタが使用できるよう設定されていれば、LoadBalancer タイプを使用できる(ここまでのコマンド実行結果はすべて LoadBalancer タイプの Service への実行結果)。
- この機能により、クラウド上に新しいロードバランサが自動的に作成され、そのロードバランサ配下にクラスタ内のノードが入れられる
- Service を拡張する NodePort の、さらなる拡張と考えてもよいかもしれない?LoadBalancer タイプを使用した場合でも、NodePort を使って通信することにはなる。
その他応用機能など
Endpoints
- クラスタIPを使わずに Service を使用したい場合に用いる。
- Kubernetes は、各 Service オブジェクトに対応する Endpoints オブジェクトを作成する
- Endpoints オブジェクトには、対応する Service オブジェクトの Label セレクタに合致する Pod の IP アドレスが入れられている。
$ kubectl describe endpoints hoge-prod Name: hoge-prod Namespace: default Labels: app=hoge-prod env=prod ver=2 Annotations: <none> Subsets: Addresses: 10.40.xx.x,10.40.xx.x,10.40.xx.x,10.40.xx.x NotReadyAddresses: <none> Ports: Name Port Protocol ---- ---- -------- <unset> 8080 TCP Events: <none>
- Pod が再作成されるなどして IP アドレスが変わった場合、Endpoints も合わせて変更する必要があるが、Kubernetes API には、オブジェクトを監視し変更があると通知する機能が備わっているため、すぐに反応できる
kube-proxy とクラスタIP
- クラスタIPは、上述の通り、同じ Label セレクタがつけられたすべてのPodにロードバランスするために使用する、特別なIPアドレス。
- 言い換えると、Service内の各Endpointsにトラフィックをロードバランスするための仮想IP。
- この仕組みは、クラスタ内の各ノードで動いている kube-proxy コンポーネントが実現している。
- 新しい Service が作られると、kube-proxy は iptables のルールをホストのカーネルに設定する。これにより、パケットの宛先が Service の Endpoints に書き換えられる。
クラスタIP関連の環境変数
- 通常、クラスタIPの特定にはDNSサービスを使用すればよいが、起動時に Pod に設定されている環境変数を用いる方法もある。
HOGE_PROD_SERVICE_HOST
HOGE_PROD_SERVICE_PORT
などがある。
- 問題点としては、リソース(オブジェクト)を作る順番。
- Service が Pod よりも先に作られる必要がある
- 大きなアプリケーションを構成する Service をデプロイするときには複雑さが増してしまう