k8s-service

一、service简介

  1. 个人理解:service类似于一个前端代理,所有的访问通过代理分发,无论后端怎么变化,用户的访问方式始终保持不变
  2. service是一种为一组功能相同的pod提供单一不变的接入点的资源(如何保证service的高可用?service本身是否会成为瓶颈?) 
  3. service也通过标签选择器来选择对应的pod
  4. service可以将特定客户端的请求每次都指向同一个pod(使用次属性需要考虑负载均衡的影响)
  5. service工作在TCP与UDP层,因此无法基于cookie来绑定pod
  6. service的服务发现:
    1)所有的service都以环境变量的形式存放在pod中,pod通过环境变量获取service的IP和端口
    2)DNS发现服务:
       a、k8s自身在kubesystem命名空间有运行dns服务
       b、其他所有在同一集群的pod都配置成使用该dns(k8s通过修改每个容器的/etc/resolv.conf文件实现)
       c、pod是否使用dns由pod中sepcd dnsPolicy属性决定
       d、客户端pod在知道service的名称的情况下可以通过FQDN(全局限定域名)访问
          访问格式:web-test.default.svc.cluster.local   #service名称.命名空间名称.集群本地服务名称中使用的可配置的集群域后缀
                  在同一namespace的pod可以省略集群域后缀及命名空间,即只需要service_name
       e、端口号依旧使用环境变量获取
  7. service的IP是无法ping的,因为service的clusterIP只是一个虚拟的IP,只有与service的port结合使用时才有意义
  8. 通过service访问服务无法记录客户端IP,由于node对数据包执行了SNAT(源网络地址转换),因此数据包的源IP会发生改变

二、endpoint(kubectl get svc svc_name  #可以查看到endpoint)

  1. Endpoint就是暴露一个服务的IP地址和端口的列表
  2. service的标签选择器是用与构建endpoint的IP、端口列表,然后存入endpoint资源中
  3. 手动创建endpoint(用于给没有标签选择器的service创建endpoint)
  4. 手动创建的endpoint需要与对应的service具有相同的名称,并包含该服务的目标IP和端口列表
  5. 创建完整的service后删除seletor选择器,service将不会自动更新endpoint列表,可以人为控制endpoint

三、使用service链接外部服务 

  1. 使用endpoint写入外部服务器的IP和端口链接外部服务(默认服务发现只能链接集群内部的服务)
  2. 创建ExternalName类型的服务,通过externalname属性和ports属性指定外部服务器的IP和端口
  3. 通过service访问外部服务可以直接链接外部服务,隐藏了外部服务的名称、端口等信息

四、将服务暴露给外部客户端 

  1. 创建NodePort类型的service:每个节0点都会打开一个相同的随机端口,用于将流量重定向到节点上的pod,外部通过node_ip:port访问(缺点:pod更换node节点会改变访问方式,或弄得节点故障从而导致服务不可访问)
  2. 创建LoadBalancer类型的service:通过一个专用的负载均衡器访问,客户端通过负载均衡器的IP连接到服务
    (云服务商的k8s集群通常支撑从云基础架构自动提供负载均衡器,用户仅需将类型修改为LoadBalance模式即可,之后根据查看到的负载均衡IP访问服务)
    实现需要负载均衡器+独有的公网IP
  3. 创建一个Ingress资源,通过一个IP地址公布多个service 
    1、Ingress需要一个公网IP
    2、Ingress根据请求的主机名和路劲决定请求转发的服务
    3、Ingress在网络栈(HTTP)的应用层操作,可以实现基于cookie的回话亲和性
    4、只有Ingress控制器在集群中运行,Ingress资源才能正常工作
    5、云供应商的Ingress控制器(例如:GKE)要求Ingress指向一个NodePort服务
    6、ingress工作原理:客户端——》DNS——》返回ingress_IP——》客户端发出HTTP请求,并在Host头中指定域名——》控制器通过域名确定客户端访问的服务——》通过该服务的Endpoint查看pod IP——》并将客户端的请求转发给其中一个pod(通常情况ingress只通过service选择pod,而不是转发给service)
    7、一个Ingress可以暴露多个服务
扫描二维码关注公众号,回复: 5714953 查看本文章

二、service的yaml示例

apiVersion: v1

kind: Service

metadata:

  name: svc-test

spec:

  #type: ExternalName

  #externalname: www.example.com #在externalname模式是的属性,指定外部服务器的FQDN,同时也需要指定ports属性

  sessionAffinity: ClientIp #次属性用于使同一客户端的请求每次都指向同一个pod(有none和client两中选择,默认为none) 

  externalTrafficPolicy: local #负载均衡器——》service——》node——》pod(选择了node的时候可能响应的pod不在该node上(默认随机),此选即开启:接受到请求的node直接使用本地的pod直接响应;缺点,若此node上无pod响应,则该请求将被直接挂起,且node上的pod数量不一致的情况下,可能导致pod的负载不均衡 

  selector:

    app: web 

  ports:

  - name: http  #映射多个端口时需要指定name属性,只需要映射一个端口时可以省略

    port: 8080 #映射的端口

    targetPort: 80 #pod端口

    #nodePort: 30080 #节点端口,使用nodeport模式时可以指定的属性(不指定则自动生成随机端口) 

  - name: http

    port: 8443

    targetPort: 443  #pod端口在pod的yaml文件中也定义有name属性,此处可以直接引用,这样即使pod的端口发生变化,此处也无需修改

Ingress的yaml文件

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: ingress-test

spec:

  rules:

  - host: test.example.com #对外暴露的域名

    http:

    paths:

    - path: /web1 #访问的文件路径

      backend:

        service:Name: test-svc #service的名称

        servicePort: 80  #service的端口

    http:

    paths:

    - path: /web2 #在同一host下的不同路径

      backend:

        service:Name: test-svc2

        servicePort: 80 

  - host: test2.example.com #对外暴露的域名

    http:

    paths:

    - path: /web1 #访问的文件路径

      backend:

        service:Name: test2-svc #service的名称

        servicePort: 80  #service的端口

猜你喜欢

转载自www.cnblogs.com/jayce9102/p/10623023.html