【Kubernetes in Action读书笔记】5.1 Service
知识点
- Service的主要目标就是使集群内部的一组组Pod可以相互访问。
- 客户端无法提前知道Pod的IP地址,因为Kubernetes是在Pod调度到节点之后才为其分配IP地址的。
- Kubernetes分配给Service的IP地址只是集群的IP地址(私有/内网IP地址),所以只能在集群内部访问。
- 在Service的整个生命周期内,这个IP地址保持不变。服务后面的Pod的IP地址可能会变化,但始终可以通过Service的单一不变的IP地址访问这些Pod
- 客户端通过Service的IP地址和端口号与其建立连接,这些连接会被路由到提供该Service的任意一个Pod上。
- a service can be backed by more than one pod. Connections to the service are load-balanced across all the backing pods. (Service的连接对所有的后端Pod是负载均衡的)
- Service仅支持两种形式的会话亲和性
sessionAffinity:None和ClientIP,因为Service工作在传输层上。
命名端口
命名端口的好处:即使Pod更换了端口号,也无须更改Service的spec.ports.targetPort(当然,前提是端口号名称没有改变)
实验1
实验针对书中这段描述
英文P128
But why should you even bother with naming ports? The biggest benefit of doing so is that it enables you to change port numbers later without having to change the service spec. Your pod currently uses port 8080 for http, but what if you later decide you’d like to move that to port 80?
If you’re using named ports, all you need to do is change the port number in the pod spec (while keeping the port’s name unchanged). As you spin up pods with the new ports, client connections will be forwarded to the appropriate port numbers, depending on the pod receiving the connection (port 8080 on old pods and port 80 on the new ones).
中文P129
为什么要采用命名端口的方式?最大的好处就是即使更换端口号也无须更改服务spec 。 你的pod现在对http 服务用的是8080,但是假设过段时间你决定将端口更换为80呢 ?
如果你采用了命名的端口,仅仅需要做的就是改变spec pod中的端口号(当然你的端口号的名称没有改变)。在你的pod向新端口更新时,根据pod收到的连接(8080端口在旧的pod上、80端口在新的pod上),用户连接将会转发到对应的端口号上。
Service使用命名端口时,Pod开始更新端口名称对应的端口。更新过程中存在名称相同的新旧两个端口,Service此时会如何处理(转发请求)?
实验环境
Pod和Service的yaml见文末。
- 此时两个Pod监听的都是8080端口。名为
kubia-service的Service将从80端口接收到的请求路由到带有app=kubia标签的Pod的8080端口上。
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 36d
kubia-service ClusterIP 10.108.27.114 <none> 80/TCP 36m
2. 进入一个Pod,执行curl 10.108.27.114。可以看到请求被均匀地转发到这两个Pod上。
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-1
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-2
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-1
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-2
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-2
3. 修改Pod1监听的端口号
$ k get pods --template '{{range .items}}{{.metadata.name}}{{range .spec.containers}} {{range .ports}}{{.containerPort}}{{"\n"}}{{end}}{{end}}{{end}}'
kubia-manual-1 80
kubia-manual-2 8080
4. 进入Pod1,再次执行curl,会看到失败的请求
这应该是因为Pod1和Pod2此时不再是**同构(Homogeneous ホモジーニアス)**的了
root@kubia-manual-1:/# curl 10.108.27.114
curl: (7) Failed to connect to 10.108.27.114 port 80: Connection refused
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-2
root@kubia-manual-1:/# curl 10.108.27.114
curl: (7) Failed to connect to 10.108.27.114 port 80: Connection refused
root@kubia-manual-1:/# curl 10.108.27.114
curl: (7) Failed to connect to 10.108.27.114 port 80: Connection refused
root@kubia-manual-1:/# curl 10.108.27.114
You've hit kubia-manual-2
附:创建Pod和Service的yaml
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-1
labels:
app: kubia
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- name: http
containerPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
name: kubia-manual-2
labels:
app: kubia
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- name: http
containerPort: 8080
protocol: TCP
apiVersion: v1
kind: Service
metadata:
name: kubia-service
spec:
selector:
app: kubia
ports:
- name: http
port: 80
targetPort: http
参考
stackoverflow.com/questions/6…
uml图
@startuml
cloud Service
note right of Service
kubia-service
port: 80
targetPort: `http`
end note
node Pod1
note bottom of Pod1
kubia-manual-1
port: http=8080
labels: app=kubia
end note
node Pod2
note bottom of Pod2
kubia-manual-2
port: http=8080
labels: app=kubia
end note
Service -- Pod1
Service -- Pod2
@enduml