8.service---服务发现与负载均衡
一、访问pod场景
1.集群内部访问
2.集群内部访问外部
3.集群外部访问内部
1.集群内部访问
1.pod之间直接ip通讯(利用calico通过路由表经过三层将ip流量转发)由于容器之间ip并不固定不推荐使用ip直连
2.pod通过service-ip访问后端pod(service为虚拟ip,kube-proxy将请求分发给ipvs,负载到某个后端pod,calico通过路由转发将请求转发过去)
3.(dns+ClusterIp)pod通过service-name访问后端pod(pod通过dns解析service名字的ip到kube-proxy,kube-proxy将请求分发给ipvs,负载到某个后端pod,calico通过路由转发将请求转发过去)
4.(headlessService)service创建时将 Service 的 spec.ClusterIP 设为 None,得到的就是一个 Headless Service,该service对应的不是一个虚拟ip,service name 只提供 SRV 记录的 DNS 解析,返回一个 Pods 的 ip/dns 列表。
2.集群内部访问外部
1.(IP或域名)写死ip直接访问,ip通过eth网卡直连,域名的话通过宿主机resolve直接访问,(coredns查询本地缓存,查询corednspod当前namespace下域名,查询全部namespace下域名无的话直接访问宿主机dns,外部链接的话最后以.结尾绝对域名去访问提高解析记录)
2. (outservice)service绑定Endpoint endpoint绑定的外部具体地址,pod通过dns访问到service,kube-proxy将service绑定的endpoint地址返回给pod。(有点当外部地址变化只需要修改endpoint即可)通过watch/list监测kube-proxy更新iptables。
3.集群外部访问内部
1.(NodePort)service-nodeport类型除生成clusterip外会在每个节点都开放一个相同的端口,访问集群内任何一个节点的对应端口都会重新转发到service上,kube-proxy通过ipvs将请求转发到一个具体pod上。(缺点:端口混乱,转发次数增多。)
2.(HostPort)service生成cluster-ip后,在指定相对应的pod所在节点开启对应端口。
3.(域名访问通过ingress-nginx/ingress-controller)将指定域名绑定到后端service上。ingress-controller负责解析与转发通过watch监听service-api,同步修改后端ingress-nginx。
service
- 将多个相同的 Pod 包装成一个完整的 service 对外提供服务。
- 获取到这些相同的 Pod方法,每个 Pod 启动时都会设置 labels 属性,在 service 中我们通过选择器 selector,选择具有相同 name 标签属性的 Pod。
- 将服务信息通过 apiserver 存入 etcd 中,该工作由 Service Controller 来完成。
- 每个节点上会启动一个 kube-proxy 进程,由它来负责服务地址到 Pod 地址的代理以及负载均衡等工作。
K8S中的三种IP
- Node IP: Node节点的IP地址
- Cluster IP: Service的IP地址
仅仅作用于service这个对象,只能结合service port来组成一个可以通信的服务。相当于VIP,代理后端服务。
- Pod IP: Pod的IP地址
由Docker Engine根据docker0网桥的IP地址段进行分配。
Service的定义
kubectl explain svc ##查看svc的定义帮助文件
其中重要的4个字段:
apiVersion:
kind:
metadata:
spec:
clusterIP: 可以自定义,也可以动态分配
ports:(与后端容器端口关联)
selector:(关联到哪些pod资源上)
type:服务类型
Service的类型
Type 的取值以及行为如下:
ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort服务会路由到ClusterIP服务,这个ClusterIP服务会自动创建。通过请求<NodeIP>:<NodePort>,可以从集群的外部访问一个NodePort服务。LoadBalancer:使用云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到NodePort服务和ClusterIP服务。ExternalName:通过返回CNAME和它的值,可以将服务映射到externalName字段的内容(例如,foo.bar.example.com)。 没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的kube-dns才支持。
示例:apiVersion: apps/v1kind: Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd labels: app: httpd-demo spec: replicas: 3
selector:
matchLabels:
app: httpd-demo
template: metadata: labels: app: httpd spec: containers: - name: httpd image: httpd ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: httpd-svc spec: selector: app: httpd-demo ports: - protocol: TCP port: 8082 targetPort: 80 ##pod端口
kubectl create -f svc.yml
kubectl get svc
用命令实现service kubectl expose deploy/httpd --port=8082 --target-port=80 --type=ClusteIP
service kubectl expose deploy httpd --port=8082 --target-port=80 --type=NodePort

此时service IP为cluster-IP 仅在集群内有效;在容器内部可以有用 svc名.namespace名.svc访问
把上面默认的service type改为NodePort
apiVersion: v1 kind: Service metadata: name: httpd-svc spec: selector: app: httpd-demo type: NodePort ports: - protocol: TCP port: 8082 ##容器间服务调用端口 targetPort: 80 ##容器暴露端口 nodePort: 30088 ##外部访问端口


随意使用哪一个node或master的IP:30088都可以访问到它


Pod的会话保持
Service资源还支持Session affinity(粘性会话)机制,可以将来自同一个客户端的请求始终转发至同一个后端的Pod对象,这意味着它会影响调度算法的流量分发功用,进而降低其负载均衡的效果。因此,当客户端访问Pod中的应用程序时,如果有基于客户端身份保存某些私有信息,并基于这些私有信息追踪用户的活动等一类的需求时,那么应该启用session affinity机制。
Service affinity的效果仅仅在一段时间内生效,默认值为10800秒,超出时长,客户端再次访问会重新调度。该机制仅能基于客户端IP地址识别客户端身份,它会将经由同一个NAT服务器进行原地址转换的所有客户端识别为同一个客户端,由此可知,其调度的效果并不理想。Service 资源 通过. spec. sessionAffinity 和. spec. sessionAffinityConfig 两个字段配置粘性会话。 spec. sessionAffinity 字段用于定义要使用的粘性会话的类型,它仅支持使用“ None” 和“ ClientIP” 两种属性值。
默认是None(随机调度) ClientIP是来自于同一个客户端的请求调度到同一个pod中
kubectl explain svc.spec.sessionAffinity

浙公网安备 33010602011771号