一足遅れて Kubernetes を学び始める - 08. discovery&LB その1 -
ストーリー
- 一足遅れて Kubernetes を学び始める - 01. 環境選択編 -
- 一足遅れて Kubernetes を学び始める - 02. Docker For Mac -
- 一足遅れて Kubernetes を学び始める - 03. Raspberry Pi -
- 一足遅れて Kubernetes を学び始める - 04. kubectl -
- 一足遅れて Kubernetes を学び始める - 05. workloads その 1 -
- 一足遅れて Kubernetes を学び始める - 06. workloads その 2 -
- 一足遅れて Kubernetes を学び始める - 07. workloads その 3 -
- 一足遅れて Kubernetes を学び始める - 08. discovery&LB その 1 -
- 一足遅れて Kubernetes を学び始める - 09. discovery&LB その 2 -
- 一足遅れて Kubernetes を学び始める - 10. config&storage その 1 -
- 一足遅れて Kubernetes を学び始める - 11. config&storage その 2 -
- 一足遅れて Kubernetes を学び始める - 12. リソース制限 -
- 一足遅れて Kubernetes を学び始める - 13. ヘルスチェックとコンテナライフサイクル -
- 一足遅れて Kubernetes を学び始める - 14. スケジューリング -
- 一足遅れて Kubernetes を学び始める - 15. セキュリティ -
- 一足遅れて Kubernetes を学び始める - 16. コンポーネント -
前回
一足遅れて Kubernetes を学び始める - 07. workloads その 3 -でようやく workloads が終了しました。今回は、discovery&LB を進めようと思います。
discovery&LB
Kubernetes には、下記のようにリソースの種類が存在します。 今回は、discovery&LB を学習します。
リソースの分類 | 内容 |
---|---|
Workloads リソース | コンテナの実行に関するリソース |
Discovery&LB リソース | コンテナを外部公開するようなエンドポイントを提供するリソース |
Config&Storage リソース | 設定・機密情報・永続化ボリュームなどに関するリソース |
Cluster リソース | セキュリティやクォータなどに関するリソース |
Metadata リソース | リソースを操作する系統のリソース |
※ Kubernetes の Workloads リソース(その 1)
discovery&LB をには、下記 8 つの種類があります。
- Service
- ClusterIP
- ExternalIP
- NodePort
- LoadBalancer
- Headless (None)
- ExternalName
- None-Selector
- Ingress
Service の概要について学びます。
Kubernetes とネットワーク
Kubernetes では、Pod 毎に IP アドレスが割り振られています。 そのため、異なる Pod 間で通信する際は、Pod の IP アドレスが必要になります。逆に同一の Pod 内なら localhost で通信できます。
説明するために、準備します。
# sample-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: nginx:1.12
ports:
- containerPort: 80
- name: redis-container
image: redis:3.2
pi@raspi001:~/tmp $ k apply -f sample-deployment.yaml
pi@raspi001:~/tmp $ k get pods -l app=sample-app -o custom-columns="NAME:{metadata.name}, IP:{status.podIP},NODE:{spec.nodeName}"
NAME IP NODE
sample-deployment-9dc487867-h7lww 10.244.1.72 raspi002
sample-deployment-9dc487867-n8x5w 10.244.2.66 raspi003
sample-deployment-9dc487867-nxbxc 10.244.2.67 raspi003
このような状況下で、sample-deployment-9dc487867-n8x5w:redis
を中心に見ていきます。
※ nginx は 80 ポートで開放されています。
前準備
pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# apt-get update && apt-get install curl -y
root@sample-deployment-9dc487867-n8x5w:/data# exit
curl がないのでインストールします。
同一 Node,同一 Pod 内のコンテナへ通信
pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl localhost:80
<!DOCTYPE html>
...
OK
同一 Node,異なる Pod のコンテナへ通信
pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.2.66:80
<!DOCTYPE html>
...
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.2.67:80
<!DOCTYPE html>
...
OK
異なる Node,異なる Pod のコンテナへ通信
pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.1.72:80
<!DOCTYPE html>
...
OK
MasterNode から各 Pod へ通信
pi@raspi001:~/tmp $ curl 10.244.1.72:80
<!DOCTYPE html>
...
pi@raspi001:~/tmp $ curl 10.244.2.66:80
<!DOCTYPE html>
...
pi@raspi001:~/tmp $ curl 10.244.2.67:80
<!DOCTYPE html>
...
OK
ここから分かるように、Pod 内部の通信、Pod 間の通信、さらに Node 間の通信までも、Kubernetes によってネットワークが構築されています。
Service
Service は、下記の2つの大きな機能が存在します。
- pod 宛トラフィックのロードバランシング
- サービスディスカバリとクラスタ内 DNS
pod 宛トラフィックのロードバランシング
先程の例で、Pod 間を通信することは可能です。しかし、pod を作り直すたびに IP アドレスが変わってしまうため、 自作すると、少し大変です。そこで、Service の出番です。 サービスは、複数存在する Pod に対して自動的にロードバランスしてくれるのと、合わせて外向けの IP アドレス(ExternalIP)や、内向けの IP アドレス(ClusterIP)も提供してくれます。
さっそく、試してみます。
# sample-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: sample-clusterip
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 8080
targetPort: 80
selector:
app: sample-app
これは、app=sample-app
にマッチする Pod に対してロードバランスしてくれます。外から 8080 ポートで待ち受けて、80 ポートでコンテナへ通信します。
spec.type が ClusterIP なので、内向けの IP アドレスが提供されています。
pi@raspi001:~/tmp $ k apply -f sample-clusterip.yaml
pi@raspi001:~/tmp $ k get service sample-clusterip
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sample-clusterip ClusterIP 10.111.197.69 <none> 8080/TCP 30s
pi@raspi001:~/tmp $ k describe service sample-clusterip
Name: sample-clusterip
...
Selector: app=sample-app
Type: ClusterIP
IP: 10.111.197.69
Port: http-port 8080/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.72:80,10.244.2.66:80,10.244.2.67:80
...
内向けに 10.111.197.69 の IP アドレスが振られました。また、ロードバランスする対象 Pod は、先にあげた Pod の IP アドレスです。
Endpints に:80
とあるように、port 毎にサービス(clusterIP)を作ることもできます。(service の spec.ports は配列指定)
アクセスできるのか、試します。 せっかくなので、pod 毎に index.html の内容を変化させましょう。
pi@raspi001:~/tmp $ for PODNAME in `k get pods -l app=sample-app -o jsonpath='{.items[*].metadata.name}'`; do
> k exec -it ${PODNAME} -- cp /etc/hostname /usr/share/nginx/html/index.html;
> done
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-nxbxc
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-n8x5w
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-h7lww
確かに、ロードバランシングによって pod に適度なランダム具合でアクセスできています。 もちろん、外からはアクセスできません。
iMac へ移動
~ $ curl 10.111.197.69:8080
# 返答なし
サービスディスカバリとクラスタ内 DNS
サービスディスカバリとは、「問題においての解決策」を指しています。 Kubernetes における問題とは、動的にサービスが生成され続けていることによるサービスを特定することが難しくなる問題です。 そのサービスディスカバリが、Service にあります。 その方法について下記があります。
- 環境変数を利用したサービスディスカバリ
- Pod に IP アドレスや port,protocol が設定されている。
- DNS A レコードを利用したサービスディスカバリ
- Kubernetes 内のクラスタ内 DNS によって、ドメイン名によるアクセスができる。(ドメイン名の命名規則に従う)
- DNS SRV レコードを利用したサービスディスカバリ
- IP アドレスからドメイン名を取得する逆引きもできる。
dnsPolicy による明示的な設定がない限り、Pod 生成時にクラスタ内 DNS へレコード追加されます。 クラスタ内 DNS で名前解決できなかった場合は、クラスタ外 DNS に問い合わせします。
お片付け
pi@raspi001:~/tmp $ k delete -f sample-deployment.yaml -f sample-clusterip.yaml
最後に
今回は、Service についての概要を学びました。Kubernetes の世界では、自動的にネットワーク構築されているため、特段意識することはありませんでした。 もう少し理解が進めれば、ネットワークがどのように構築されているのか、クラスタ内 DNS がどのように動いているのか知りたいと思います。 次回は、こちらです。
※ お絵かきしてアウトプットすると、理解が深まるのでおすすめです。
シェアしよう
関連するタグ
- Cloud Native Days Tokyo 2019 -2019年7月22-23日参加レポート
- 一足遅れて Kubernetes を学び始める - 16. コンポーネント -
- 一足遅れて Kubernetes を学び始める - 15. セキュリティ -
- 一足遅れて Kubernetes を学び始める - 14. スケジューリング -
- 【大阪・梅田】Kubernetes Meetup Tokyo 19 大阪サテライト- 2019年5月31日参加レポート
- 一足遅れて Kubernetes を学び始める - 13. ヘルスチェックとコンテナライフサイクル -
- 一足遅れて Kubernetes を学び始める - 12. リソース制限 -
- 一足遅れて Kubernetes を学び始める - 11. config&storage その2 -
- 一足遅れて Kubernetes を学び始める - 10. config&storage その1 -
- 【大阪】BMXUG勉強会 -Kubernates体験&Watson Discovery入門- 2019年3月27日参加レポート
- 一足遅れて Kubernetes を学び始める - 09. discovery&LB その2 -
- 一足遅れて Kubernetes を学び始める - 07. workloads その3 -
- 一足遅れて Kubernetes を学び始める - 06. workloads その2 -
- 一足遅れて Kubernetes を学び始める - 05. workloads その1 -
- 一足遅れて Kubernetes を学び始める - 04. kubectl -
- 一足遅れて Kubernetes を学び始める - 03. Raspberry Pi -
- 一足遅れて Kubernetes を学び始める - 02. Docker For Mac -
- 一足遅れて Kubernetes を学び始める - 01. 環境選択編 -