网聊大管家,3u8543,裴新华老公
本文收录在
kubernetes pod 是有生命周期的,它们可以被创建,也可以被销毁,然而一旦被销毁生命就永远结束。 通过 replicationcontroller 能够动态地创建和销毁 pod(例如,需要进行扩缩容,或者执行 滚动升级)。 每个 pod 都会获取它自己的 ip 地址,即使这些 ip 地址不总是稳定可依赖的。 这会导致一个问题:在 kubernetes 集群中,如果一组 pod(称为 backend)为其它 pod (称为 frontend)提供服务,那么那些 frontend 该如何发现,并连接到这组 pod 中的哪些 backend 呢?答案是:service。
kubernetes service 定义了这样一种抽象:一个 pod 的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。 这一组 pod 能够被 service 访问到,通常是通过 label selector(下面我们会讲到我们为什么需要一个没有label selector的服务)实现的。
举个例子,考虑一个图片处理 backend,它运行了3个副本。这些副本是可互换的 —— frontend 不需要关心它们调用了哪个 backend 副本。 然而组成这一组 backend 程序的 pod 实际上可能会发生变化,frontend 客户端不应该也没必要知道,而且也不需要跟踪这一组 backend 的状态。 service 定义的抽象能够解耦这种关联。
对 kubernetes 集群中的应用,kubernetes 提供了简单的 endpoints api,只要 service 中的一组 pod 发生变更,应用程序就会被更新。 对非 kubernetes 集群中的应用,kubernetes 提供了基于 vip 的网桥的方式访问 service,再由 service 重定向到 backend pod。
这种模式,kube-proxy 会监视 kubernetes master 对 service 对象和 endpoints 对象的添加和移除。 对每个 service,它会在本地 node 上打开一个端口(随机选择)。 任何连接到“代理端口”的请求,都会被代理到 service 的backend pods 中的某个上面(如 endpoints 所报告的一样)。 使用哪个 backend pod,是基于 service 的 sessionaffinity 来确定的。 最后,它安装 iptables 规则,捕获到达该 service 的 clusterip(是虚拟 ip)和 port 的请求,并重定向到代理端口,代理端口再代理请求到 backend pod。
网络返回的结果是,任何到达 service 的 ip:port 的请求,都会被代理到一个合适的 backend,不需要客户端知道关于 kubernetes、service、或 pod 的任何信息。
默认的策略是,通过 round-robin 算法来选择 backend pod。 实现基于客户端 ip 的会话亲和性,可以通过设置 service.spec.sessionaffinity 的值为 "clientip" (默认值为 "none")。
这种模式,kube-proxy 会监视 kubernetes master 对 service 对象和 endpoints 对象的添加和移除。 对每个 service,它会安装 iptables 规则,从而捕获到达该 service 的 clusterip(虚拟 ip)和端口的请求,进而将请求重定向到 service 的一组 backend 中的某个上面。 对于每个 endpoints 对象,它也会安装 iptables 规则,这个规则会选择一个 backend pod。
默认的策略是,随机选择一个 backend。 实现基于客户端 ip 的会话亲和性,可以将 service.spec.sessionaffinity 的值设置为 "clientip" (默认值为 "none")。
和 userspace 代理类似,网络返回的结果是,任何到达 service 的 ip:port 的请求,都会被代理到一个合适的 backend,不需要客户端知道关于 kubernetes、service、或 pod 的任何信息。 这应该比 userspace 代理更快、更可靠。然而,不像 userspace 代理,如果初始选择的 pod 没有响应,iptables 代理能够自动地重试另一个 pod,所以它需要依赖 readiness probes。
ipvs (ip virtual server) 实现了传输层负载均衡,也就是我们常说的4层lan交换,作为 linux 内核的一部分。ipvs运行在主机上,在真实服务器集群前充当负载均衡器。ipvs可以将基于tcp和udp的服务请求转发到真实服务器上,并使真实服务器的服务在单个 ip 地址上显示为虚拟服务。
在kubernetes v1.8 中引入了 ipvs 模式,在 v1.9 中处于 beta 阶段,在 v1.11 中已经正式可用了。 iptables 模式在 v1.1 中就添加支持了,从 v1.2 版本开始 iptables 就是 kube-proxy 默认的操作模式,ipvs 和 iptables 都是基于netfilter的, ipvs 模式和 iptables 模式之间的差异:
同时ipvs 也依赖 iptables,ipvs 会使用 iptables 进行包过滤、snat、masquared(伪装)。具体来说,ipvs 将使用ipset来存储需要drop或masquared的流量的源或目标地址,以确保 iptables 规则的数量是恒定的,这样我们就不需要关心我们有多少服务了
ipvs虽然在v1.1版本中已经支持,但是想要使用,还需激活ipvs:
① 修改配置文件
[root@master ~]# vim /etc/sysconfig/kubelet
kube_proxy=mode=ipvs
② 编写脚本,让kubelet所在的主机,启动时装入以下几个模块:
ip_vs,ip_vs_rr,ip_vs_wrr,ip_vs_sh,nf_conntrack_ipv4
(1)编写yaml文件并创建名为redis的service
先创建一个deployment,启动一个redis pod;在使用service绑定这个pod
[root@master manifests]# vim redis-svc.yaml
apiversion: apps/v1
kind: deployment
metadata:
name: redis
namespace: default
spec:
replicas: 1
selector:
matchlabels:
app: redis
role: logstor
template:
metadata:
labels:
app: redis
role: logstor
spec:
containers:
- name: redis
image: redis:4.0-alpine
ports:
- name: redis
containerport: 6379
---
apiversion: v1
kind: service
metadata:
name: redis
namespace: default
spec:
selector:
app: redis
role: logstor
clusterip: 10.99.99.99
type: clusterip
ports:
- port: 6380
targetport: 6379
[root@master manifests]# kubectl apply -f redis-svc.yaml
deployment.apps/redis created
service/redis created
(2)查询验证
[root@master ~]# kubectl get svc
name type cluster-ip external-ip port(s) age
kubernetes clusterip 10.96.0.1 <none> 443/tcp 142d
redis clusterip 10.99.99.99 <none> 6380/tcp 12s
---查询service详细信息,pod绑定成功
[root@master ~]# kubectl describe svc redis
name: redis
namespace: default
labels: <none>
annotations: kubectl.kubernetes.io/last-applied-configuration={"apiversion":"v1","kind":"service","metadata":{"annotations":{},"name":"redis","namespace":"default"},"spec":{"clusterip":"10.99.99.99","ports":[{"por...
selector: app=redis,role=logstor
type: clusterip
ip: 10.99.99.99
port: <unset> 6380/tcp
targetport: 6379/tcp
endpoints: 10.244.2.94:6379
session affinity: none
events: <none>
(1)编写yaml文件并创建名为myapp的service
先创建一个deployment,启动3个myapp pod;在使用service绑定这3个pod
[root@master manifests]# vim myapp-svc.yaml
apiversion: apps/v1
kind: deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchlabels:
app: myapp
release: canary
template:
metadata:
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerport: 80
---
apiversion: v1
kind: service
metadata:
name: myapp
namespace: default
spec:
selector:
app: myapp
release: canary
clusterip: 10.97.97.97
type: nodeport
ports:
- port: 80
targetport: 80
nodeport: 31180
[root@master manifests]# kubectl apply -f myapp-svc.yaml
deployment.apps/myapp-deploy unchanged
service/myapp created
(2)查询验证
[root@master ~]# kubectl get svc
name type cluster-ip external-ip port(s) age
kubernetes clusterip 10.96.0.1 <none> 443/tcp 145d
myapp nodeport 10.97.97.97 <none> 80:31180/tcp 39s
redis clusterip 10.99.99.99 <none> 6380/tcp 2d
[root@master ~]# kubectl describe svc myapp
name: myapp
namespace: default
labels: <none>
annotations: kubectl.kubernetes.io/last-applied-configuration={"apiversion":"v1","kind":"service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterip":"10.97.97.97","ports":[{"nod...
selector: app=myapp,release=canary
type: nodeport
ip: 10.97.97.97
port: <unset> 80/tcp
targetport: 80/tcp
nodeport: <unset> 31180/tcp
endpoints: 10.244.1.96:80,10.244.2.101:80,10.244.2.102:80
session affinity: none
external traffic policy: cluster
events: <none>
(3)在集群外访问服务
(1)sessionaffinity默认是none,没有修改前,访问业务是随机调度
[root@master ~]# while true; do curl 192.168.10.103:31180/hostname.html; sleep 1; done
myapp-deploy-69b47bc96d-mmb5v
myapp-deploy-69b47bc96d-wtbx7
myapp-deploy-69b47bc96d-wtbx7
myapp-deploy-69b47bc96d-cj48v
... ...
(2)打补丁修改sessionaffinity为clientip;实现会话连接
也可以使用exec修改;或者直接修改yaml文件也可以;
[root@master ~]# kubectl patch svc myapp -p '{"spec":{"sessionaffinity":"clientip"}}'
service/myapp patched
(3)查询验证
[root@master ~]# kubectl describe svc myapp
name: myapp
namespace: default
labels: <none>
annotations: kubectl.kubernetes.io/last-applied-configuration={"apiversion":"v1","kind":"service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"clusterip":"10.97.97.97","ports":[{"nod...
selector: app=myapp,release=canary
type: nodeport
ip: 10.97.97.97
port: <unset> 80/tcp
targetport: 80/tcp
nodeport: <unset> 31180/tcp
endpoints: 10.244.1.96:80,10.244.2.101:80,10.244.2.102:80
session affinity: clientip
external traffic policy: cluster
events: <none>
(4)访问业务查询验证;发现同一客户端的请求始终发往同一pod
[root@master ~]# while true; do curl 192.168.10.103:31180/hostname.html; sleep 1; done
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-cj48v
... ...
(5)重新打补丁修改为none,立即恢复为随机调度
[root@master ~]# kubectl patch svc myapp -p '{"spec":{"sessionaffinity":"none"}}'
service/myapp patched
[root@master ~]# while true; do curl 192.168.10.103:31180/hostname.html; sleep 1; done
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-mmb5v
myapp-deploy-69b47bc96d-cj48v
myapp-deploy-69b47bc96d-mmb5v
(1)编写yaml文件并创建名为myapp-svc的service
绑定上面创建myapp的3个pod
[root@master manifests]# vim myapp-svc-headless.yaml
apiversion: v1
kind: service
metadata:
name: myapp-svc
namespace: default
spec:
selector:
app: myapp
release: canary
clusterip: none
ports:
- port: 80
targetport: 80
[root@master manifests]# kubectl apply -f myapp-svc-headless.yaml
service/myapp-svc created
(2)查询验证
[root@master ~]# kubectl get svc
name type cluster-ip external-ip port(s) age
kubernetes clusterip 10.96.0.1 <none> 443/tcp 145d
myapp nodeport 10.97.97.97 <none> 80:31180/tcp 2h
myapp-svc clusterip none <none> 80/tcp 6s
redis clusterip 10.99.99.99 <none> 6380/tcp 2d
(3)和有头正常myapp的service对比
无头service的解析:
[root@master manifests]# dig -t a myapp-svc.default.svc.cluster.local. @10.96.0.10
... ...
;; answer section:
myapp-svc.default.svc.cluster.local. 5 in a 10.244.1.96
myapp-svc.default.svc.cluster.local. 5 in a 10.244.2.101
myapp-svc.default.svc.cluster.local. 5 in a 10.244.2.102
... ...
有头正常myapp的service的解析:
[root@master manifests]# dig -t a myapp.default.svc.cluster.local. @10.96.0.10
... ...
;; answer section:
myapp.default.svc.cluster.local. 5 in a 10.97.97.97
... ...
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
网友评论