zoukankan      html  css  js  c++  java
  • Kubernetes对象之Service

    系列目录

    通过ReplicaSet来创建一组Pod来提供具有高可用性的服务。虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题:

    • Pod IP仅仅是集群内可见的虚拟IP,外部无法访问。

    • Pod IP会随着Pod的销毁而消失,当ReplicaSet对Pod进行动态伸缩时,Pod IP可能随时随地都会变化,这样对于我们访问这个服务带来了难度。

    因此,Kubernetes中的Service对象就是解决以上问题的核心关键。

    Service的创建

    Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡

    Service同其他Kubernetes对象一样,也是通过yaml或json文件进行定义。此外,它和其他Controller对象一样,通过Label Selector来确定一个Service将要使用哪些Pod。一个简单的Service定义如下:

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        run: nginx
      name: nginx-service
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 81
      selector:
        app: nginx
      type: ClusterIP
    

    下面简单分析一下上面的Service描述文件:

    • 通过spec.selector字段确定这个Service将要使用哪些Label。在本例中,这个名为nginx的Service,将会管理所有具有app: nginxLabel的Pod。

    • spec.ports.port: 80表明此Service将会监听80端口,并将所有监听到的请求转发给其管理的Pod。spec.ports.targetPort: 81表明此Service监听到的80端口的请求都会被转发给其管理的Pod的81端口,此字段可以省略,省略后其值会被设置为spec.ports.port的值。

    • type: ClusterIP表面此Service的type,会在下文中讲到。

    Service的类型

    在Serive定义时,我们需要指定spec.type字段,这个字段拥有四个选项:

    • ClusterIP。默认值。给这个Service分配一个Cluster IP,它是Kubernetes系统自动分配的虚拟IP,因此只能在集群内部访问。

    • NodePort将Service通过指定的Node上的端口暴露给外部。通过此方法,访问任意一个NodeIP:nodePort都将路由到ClusterIP,从而成功获得该服务。

    • LoadBalancer。在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort。此模式只能在云服务器(AWS等)上使用。

    • ExternalName。将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。需要 kube-dns 版本在 1.7 以上。

    注:kubernetes 1.13以后默认集群coreDns,不再使用默认kube-dns,对ExternalName支持情况需要进一步确认

    NodePort类型

    在定义Service时指定spec.type=NodePort,并指定spec.ports.nodePort的值,Kubernetes就会在集群中的每一个Node上打开你定义的这个端口,这样,就能够从外部通过任意一个NodeIP:nodePort访问到这个Service了。

    下面是一个简单的例子:

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
      labels:
        run: nginx
    spec:
      selector:
        app: nginx
      ports:
      - port: 80
        nodePort: 30001
      type: NodePort
    
    

    假如有3个app: nginx Pod运行在3个不同的Node中,那么此时客户端访问任意一个Node的30001端口都能访问到这个nginx服务。

    LoadBalancer类型

    如果云服务商支持外接负载均衡器,则可以通过spec.type=LoadBalancer来定义Service,一个简单的例子如下:

    kind: Service
    apiVersion: v1
    metadata:
      name: my-service
    spec:
      selector:
        app: MyApp
      ports:
      - protocol: TCP
        port: 80
        targetPort: 9376
      clusterIP: 10.0.171.239
      loadBalancerIP: 78.11.24.19
      type: LoadBalancer
    status:
      loadBalancer:
        ingress:
        - ip: 146.148.47.155
    
    

    Service without selector

    Service可以抽象访问Pod集群,同时 Service也可以抽象其他后端

    • 在生产环境中使用外部数据库,在测试环境中使用自己的数据库

    • 将自己的Service指向其他集群或者其他命名空间的Service

    • 迁移应用到k8s,但是还是有些应用运行在k8s之

    通过定义不包含selector的Service实现

    kind: service
    apiVersion: v1
    metadata:
      name: my-service
    spec:
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376
    

    Service 没有Selector,K8s不会创建Endpoints,你可以通过手动创建Endpoint指向自己的endpoint

    kind: Endpoints
    apiVersion: v1
    metadata:
      name: my-service
      subsets:
       - addresses:
          ip: 1.2.3.4
       - ports:
          port: 9376
    
    

    Endpoint的IP不能是loopback(127.0.0.1/8),link-local(169.254.0.0/16), link-local
    multicast (224.0.0.0/24).

    访问不含有selector的Service和访问含有Selector的Service 方式一样,都会讲流向重定向的endpoint

    其他命名空间的服务是一个特例,他不会定义ports和endpoint,他只是返回一个访问外部服务的别名

    其它名称空间

    其他命名空间的服务是一个特例,他不会定义ports和endpoint,他只是返回一个访问外部服务的别名

    kind: kind
    apiVersion: v1
    metadata:
      name: my-service
      namespace: prod
      spec:
        type: ExternalName
        externalName: my.database.example.com
    

    当你访问服务my-service.prod.svc.CLUSTER时,cluster的dns服务会返回记录my.database.example.com 的CNAME,这个重定向是发生在dns解析阶段。

    虚拟IP 和服务代理

    代理

    K8s集群内每个节点都会运行kube-proxy,负责实现服务的虚拟机IP(不是externalName)。1.0版本的代理模式在是userspace,1.1增加了iptables proxy,从1.2开始 iptables 代理是默认的模式

    K8s 1.0的service是三层(TCP/UDP),从k8s1.1开始,增加了Ingress,实现七层(HTTP)服务

    用户空间的代理模式

    Kube-proxy监控k8s master节点来发现Service、Endpointd的增加和删除,对于Service,在本地打开一个随机端口作为代理端口,任何访问改代理端口的连接都会被指向Service对象的Pod集合,最终指向哪个Pod取决于Service的SessionAffinity,最后,他会配置iptables,捕获流向Service 的Cluster IP 和Port的连接,并重定向到这个代理端口。

    最终结果,任何到Service Cluster Ip 和port的流量都会指向合适的Pod

    默认情况下,都是轮训算法选择后端,也可以通过设置service.spec.sessionAffinity 为ClientIP,将选择算法改为Client-IP based session affinity

    Iptables的代理模式

    该模式与userspace模式类似,只是没有这个代理端口

    比userspace方式更快更可靠,然后与userspace方式不同,当选择的pod异常时,该方式无法自动尝试选择其他Pod。

    • userspace模式只不适合大规模集群使用(数千个服务)

    • userspace模式隐藏了访问服务的源IP,iptables模式虽然没有隐藏源IP,但是也是通过负载均衡或者nodeport 影响了客户端输入

  • 相关阅读:
    大数据架构师技能图谱
    2018年,Java程序员转型大数据开发,是不是一个好选择?
    如何将java web项目上线/部署到公网
    Flume调优
    Spark流处理调优步骤
    zookeeper的WEB客户端zkui使用
    HBase各版本对Hadoop版本的支持情况
    java 代码实现使用Druid 链接池获取数据库链接
    安装postgreSQL出现configure: error: zlib library not found解决方法
    修改postgres密码
  • 原文地址:https://www.cnblogs.com/tylerzhou/p/10989881.html
Copyright © 2011-2022 走看看