开始学习 Kubernetes 时有点晚了——08. 发现与负载均衡 第一部分
故事
-
- 一步步迟到地学习Kubernetes – 01. 环境选择编辑 –
-
- 一步步迟到地学习Kubernetes – 02. Docker For Mac编辑 –
-
- 一步步迟到地学习Kubernetes – 03. Raspberry Pi编辑 –
-
- 一步步迟到地学习Kubernetes – 04. kubectl编辑 –
-
- 一步步迟到地学习Kubernetes – 05. workloads第一部分编辑 –
-
- 一步步迟到地学习Kubernetes – 06. workloads第二部分编辑 –
-
- 一步步迟到地学习Kubernetes – 07. workloads第三部分编辑 –
-
- 一步步迟到地学习Kubernetes – 08. 发现和负载均衡第一部分编辑 –
-
- 一步步迟到地学习Kubernetes – 09. 发现和负载均衡第二部分编辑 –
-
- 一步步迟到地学习Kubernetes – 10. 配置和存储第一部分编辑 –
-
- 一步步迟到地学习Kubernetes – 11. 配置和存储第二部分编辑 –
-
- 一步步迟到地学习Kubernetes – 12. 资源限制编辑 –
-
- 一步步迟到地学习Kubernetes – 13. 健康检查和容器生命周期编辑 –
-
- 一步步迟到地学习Kubernetes – 14. 调度编辑 –
-
- 一步步迟到地学习Kubernetes – 15. 安全编辑 –
- 一步步迟到地学习Kubernetes – 16. 组件编辑 –
上次
错过了 Kubernetes 学习的最佳时机 – 在第07部分工作负载的第3节,workloads 终于结束了。本次,我们打算继续探讨发现和负载均衡。
探索与LB
在Kubernetes中,有以下的资源类型存在。
这次我们将学习discovery&LB。
※ Kubernetes的工作负载资源(第1部分)
在发现和LB方面,有以下8种类型。
-
- Service
ClusterIP
ExternalIP
NodePort
LoadBalancer
Headless (None)
ExternalName
None-Selector
Ingress
我会学习有关该服务的概述。
Kubernetes和网络
在Kubernetes中,每个Pod都被分配了一个IP地址。
因此,在不同的Pod之间进行通信时,需要知道Pod的IP地址。反之,在同一个Pod内可以使用localhost进行通信。
为了解释,我会做准备。
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,所以需要安装。
与同一节点上的同一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>
...
好
与同一节点通信到不同的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>
...
好的
与不同的节点、不同的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>
...
好的
从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>
...
好的
正如这里所示,Kubernetes通过构建网络来实现Pod内部通信、Pod间通信和节点间通信。
服务
Service有以下两个主要功能。
-
- pod宛トラフィックのロードバランシング
- サービスディスカバリとクラスタ内DNS
pod的网络负载均衡
在之前的示例中,可以通过Pod之间进行通信。但是,每次重新创建Pod时,IP地址会发生变化,这就使得自己创建变得有点麻烦。因此,轮到Service登场了。
Service可以自动为多个存在的Pod进行负载均衡,并提供对外的IP地址(ExternalIP)和内部的IP地址(ClusterIP)。
我立即尝试一下。
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
...
给内向服务分配了IP地址10.111.197.69。另外,要进行负载均衡的Pod是之前提到的那个Pod的IP地址。
正如在Endpoints中指定了:80那样,你也可以为每个端口创建一个服务(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
最後
本次,我们学习了有关服务的概述。在Kubernetes的世界里,网络会自动构建,所以我们不需要特别关注。当我们进一步理解时,我想了解网络是如何构建的以及集群内DNS的工作原理。下次我们会讲到这个话题。
当你进行绘画并输出作品时,它可以帮助加深理解,所以我推荐这样做。