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

 

posted @ 2021-11-11 16:23  天涯160  阅读(184)  评论(0)    收藏  举报