一足遅れて Kubernetes を学び始める - 07. workloads その 3 -でようやく workloads が終了しました。今回は、discovery&LB を進めようと思います。
Kubernetes には、下記のようにリソースの種類が存在します。 今回は、discovery&LB を学習します。
| リソースの分類 | 内容 |
|---|---|
| Workloads リソース | コンテナの実行に関するリソース |
| Discovery&LB リソース | コンテナを外部公開するようなエンドポイントを提供するリソース |
| Config&Storage リソース | 設定・機密情報・永続化ボリュームなどに関するリソース |
| Cluster リソース | セキュリティやクォータなどに関するリソース |
| Metadata リソース | リソースを操作する系統のリソース |
※ Kubernetes の Workloads リソース(その 1)
discovery&LB をには、下記 8 つの種類があります。
Service の概要について学びます。
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.2pi@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# exitcurl がないのでインストールします。
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
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
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
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 は、下記の2つの大きな機能が存在します。
先程の例で、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
## 返答なしサービスディスカバリとは、「問題においての解決策」を指しています。 Kubernetes における問題とは、動的にサービスが生成され続けていることによるサービスを特定することが難しくなる問題です。 そのサービスディスカバリが、Service にあります。 その方法について下記があります。
dnsPolicy による明示的な設定がない限り、Pod 生成時にクラスタ内 DNS へレコード追加されます。 クラスタ内 DNS で名前解決できなかった場合は、クラスタ外 DNS に問い合わせします。
pi@raspi001:~/tmp $ k delete -f sample-deployment.yaml -f sample-clusterip.yaml今回は、Service についての概要を学びました。Kubernetes の世界では、自動的にネットワーク構築されているため、特段意識することはありませんでした。 もう少し理解が進めれば、ネットワークがどのように構築されているのか、クラスタ内 DNS がどのように動いているのか知りたいと思います。 次回は、こちらです。
※ お絵かきしてアウトプットすると、理解が深まるのでおすすめです。
-
タグ「クラウドインフラ」の記事
Dockerイメージ内の構造や設定が期待通りかどうかを検証する `container-structure-test` を知りました。container-structure-test GitHub リポジトリ。せっかくなので、試してみました。
BigQuery、皆さん使っていますか? 私は、業務でBigQueryを使ったデータ構築をしています。品質担保のため、BigQueryのSQLに対してテストをしたいと考えています。本記事では、BigQueryだけで完結し、かつ、Mockデータを差し替え可能なユニットテスト手法について、紹介します。
TikTokへスクレイプするバッチをGCP上で構築しました。GCP構築のシステム設計話と、その構築時に、ハマったことを共有します。