zoukankan      html  css  js  c++  java
  • service-k8s

    Service

    Kubernetes Pod 是有⽣命周期的,它们可以被创建,也可以被销毁,然⽽⼀旦被销毁⽣命就永远结束。 通过
    ReplicationController 能够动态地创建和销毁 Pod 。 每个 Pod 都会获取它⾃⼰的 IP 地址,即使这些 IP 地址不总是稳定可依赖的。 这会导致⼀个问题:在 Kubernetes 集群中,如果⼀组 Pod (称为 backend)为其它 Pod (称为
    frontend)提供服务,那么那些 frontend 该如何发现,并连接到这组 Pod 中的哪些 backend 呢

    Kubernetes Service 定义了这样⼀种抽象:⼀个 Pod 的逻辑分组,⼀种可以访问它们的策略 —— 通常称为微服务。
    这⼀组 Pod 能够被 Service 访问到,通常是通过 Label Selector (查看下⾯了解,为什么可能需要没有 selector 的
    Service )实现的

    Kubernetes 提供了简单的 Endpoints API,只要 Service 中的⼀组 Pod 发⽣变更,应⽤程序就会被更新。 对⾮ Kubernetes 集群中的应⽤,Kubernetes 提供了基于 VIP 的⽹桥的⽅式访问 Service ,再由Service 重定向到 backend Pod

    三种ip

    • Node IP:Node节点的IP地址
    • Pod IP: Pod的IP地址
    • Cluster IP: ServiceIP地址

    Node IPKubernetes集群中节点的物理网卡IP地址(一般为内网),所有属于这个网络的服务器之间都可以直接通信,所以Kubernetes集群外要想访问Kubernetes集群内部的某个节点或者服务,肯定得通过Node IP进行通信

    Pod IP是每个PodIP地址,它是Docker Engine根据docker0网桥的IP地址段进行分配的

    Cluster IP是一个虚拟的IP,仅仅作用于Kubernetes Service这个对象,由Kubernetes自己来进行管理和分配地址,当然我们也无法ping这个地址,他没有一个真正的实体对象来响应,他只能结合Service Port来组成一个可以通信的服务。

    定义 Service

    ⼀个 Service 在 Kubernetes 中是⼀个 REST 对象,和 Pod 类似。 像所有的 REST 对象⼀样, Service 定义可以基
    于 POST ⽅式,请求 apiserver 创建新的实例。 例如,假定有⼀组 Pod ,它们对外暴露了 9376 端⼝,同时还被打上
    "app=MyApp" 标签

    kind: Service
    apiVersion: v1
    metadata:
      name: my-service
    spec:
      selector:
        app: MyApp
      ports:
        - protocol: TCP
          port: 80
          targetPort: 9376    #pod端口
         
         kubectl create -f myservice.yaml
         
    将创建⼀个名称为 “my-service” 的 Service 对象,它会将请求代理到使⽤ TCP 端⼝ 9376,并且具有标签
    "app=MyApp" 的 Pod 上。 这个 Service 将被指派⼀个 IP 地址(通常称为 “Cluster IP”),它会被服务的代理使⽤(⻅下⾯)。 该 Service 的 selector 将会持续评估,处理结果将被 POST 到⼀个名称为 “my-service” 的 Endpoints 对象上
    Service 能够将⼀个接收端⼝映射到任意的 targetPort 。 默认情况下, targetPort 将被设置为与
    port 字段相同的值。 可能更有趣的是, targetPort 可以是⼀个字符串,引⽤了 backend Pod 的⼀个端⼝的名称。 但
    是,实际指派给该端⼝名称的端⼝号,在每个 backend Pod 中可能并不相同。 对于部署和设计 Service ,这种⽅式会
    提供更⼤的灵活性。 例如,可以在 backend 软件下⼀个版本中,修改 Pod 暴露的端⼝,并不会中断客户端的调⽤。
    Kubernetes Service 能够⽀持 TCP 和 UDP 协议,默认 TCP 协议。
    

    没有 selector 的 Service
    Service 抽象了该如何访问 Kubernetes Pod ,但也能够抽象其它类型的 backend,例如:

    • 希望在⽣产环境中使⽤外部的数据库集群,但测试环境使⽤⾃⼰的数据库。
    • 希望服务指向另⼀个 Namespace 中或其它集群中的服务。
    • 正在将⼯作负载转移到 Kubernetes 集群,和运⾏在 Kubernetes 集群之外的 backend。

    kube-proxy

    Kubernetes集群中,每个Node会运行一个kube-proxy进程, 负责为Service实现一种 VIP(虚拟 IP,就是我们上面说的clusterIP)的代理形式,现在的Kubernetes中默认是使用的iptables这种模式来代理。这种模式,kube-proxy会监视Kubernetes master对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会添加上 iptables 规则,从而捕获到达该 Service 的 clusterIP(虚拟 IP)和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某一个个上面。 对于每个 Endpoints 对象,它也会安装 iptables 规则,这个规则会选择一个 backend Pod。

    默认的策略是,随机选择一个 backend。 我们也可以实现基于客户端 IP 的会话亲和性,可以将 service.spec.sessionAffinity 的值设置为 "ClientIP" (默认值为 "None")

    Service 类型

    定义Service的时候可以指定一个自己需要的类型的Service,如果不指定的话默认是ClusterIP类型

    可以使用的服务类型如下:

    • ClusterIP:通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。
    • NodePort:通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务。
    • LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
    • ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, foo.bar.example.com)。没有任何类型代理被创建,这只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。

    NodePort 类型

    如果设置 type 的值为 "NodePort",Kubernetes master 将从给定的配置范围内(默认:30000-32767)分配端口,每个 Node 将从该端口(每个 Node 上的同一端口)代理到 Service。该端口将通过 Service 的 spec.ports[*].nodePort 字段被指定,如果不指定的话会自动生成一个端口。

    需要注意的是,Service 将能够通过 :spec.ports[].nodePort 和 spec.clusterIp:spec.ports[].port 而对外可见

    apiVersion: v1
    kind: Service
    metadata:
      name: myservice
    spec:
      selector:
        app: myapp
      type: NodePort
      ports:
      - protocol: TCP
        port: 80
        targetPort: 80
        name: myapp-http
        
    创建该服务
    $ kubectl create -f service-demo.yaml
    查看Service对象信息:
    $ kubectl get svc
    

    ExternalName

    ExternalName 是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。 对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务

    kind: Service
    apiVersion: v1
    metadata:
      name: my-service
      namespace: prod
    spec:
      type: ExternalName
      externalName: my.database.example.com
      
    当查询主机 my-service.prod.svc.cluster.local (后面服务发现的时候我们会再深入讲解)时,集群的 DNS 服务将返回一个值为 my.database.example.com 的 CNAME 记录。 访问这个服务的工作方式与其它的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。 如果后续决定要将数据库迁移到 Kubernetes 集群中,可以启动对应的 Pod,增加合适的 Selector 或 Endpoint,修改 Service 的 type,完全不需要修改调用的代码
    
  • 相关阅读:
    [工具分享]JetBrains ReSharper 9.0 正式版和注册码
    JAVA数据库连接池的革命 -- 从BoneCP到HikariCP
    【C#教程10】C# 判断
    【C#教程09】C# 运算符
    【C#教程07】C# 变量
    【C#教程06】C# 类型转换
    【C# 教程05】C# 数据类型
    【C# 教程04】C# 基本语法
    【C# 教程03】C# 程序结构
    【C#教程02】C# 环境
  • 原文地址:https://www.cnblogs.com/g2thend/p/12745129.html
Copyright © 2011-2022 走看看