美文网首页k8s in action实践笔记
5.2 连接集群外部的服务

5.2 连接集群外部的服务

作者: 众神开挂 | 来源:发表于2021-07-20 08:26 被阅读0次

    5.2 连接集群外部的服务

    到现在为止,我们已经讨论了后端是集群中运行的一个或多个pod的服务。但也存在希望通过Kubernetes服务特性暴露外部服务的情况。不要让服务将连接重定向到集群中的pod,而是让它重定向到外部IP和端口。

    这样做可以让你充分利用服务负载平衡和服务发现。在集群中运行的客户端pod可以像连接到内部服务一样连接到外部服务。

    5.2.1 介绍服务endpoint

    在进入如何做到这一点之前,先阐述一下服务。服务并不是和pod直接相连的。相反,有一种资源介于两者之间——它就是Endpoint资源。如果之前在服务上运行过kubectl describe,可能已经注意到了endpoint,如下面的代码清单所示。

    代码清单5.7 用kubectl describe展示服务的全部细节

    # kubectl describe svc kubia
    Name:              kubia
    Namespace:         custom
    Labels:            <none>
    Annotations:       <none>
    Selector:          app=kubia  #用于创建endpoint列表的服务pod选择器
    Type:              ClusterIP
    IP Family Policy:  SingleStack
    IP Families:       IPv4
    IP:                10.111.56.158
    IPs:               10.111.56.158
    Port:              <unset>  80/TCP
    TargetPort:        8080/TCP
    Endpoints:         172.18.0.2:8080,172.18.0.3:8080,172.18.0.4:8080 # 代表服务endpoint的pod的IP和端口列表
    Session Affinity:  None
    Events:            <none>
    

    Endpoint资源就是暴露一个服务的IP地址和端口的列表,Endpoint资源和其他Kubernetes资源一样,所以可以使用 kubectl info 来获取它的基本信息。

    $ kubectl get endpoint kubia
    

    尽管在 spec服务中定义了pod选择器,但在重定向传入连接时不会直接使用它。相反,选择器用于构建IP和端口列表,然后存储在Endpoint资源中。当客户端连接到服务时,服务代理选择这些IP和端口对中的一个,并将传入连接重定向到在该位置监听的服务器。

    5.2.2 手动配置服务的endpoint

    或许已经意识到这一点,服务的 endpoint与服务解耦后,可以分别手动配置和更新它们。

    如果创建了不包含pod选择器的服务,Kubernetes将不会创建Endpoint资源(毕竟,缺少选择器,将不会知道服务中包含哪些pod)。这样就需要创建Endpoint资源来指定该服务的endpoint列表。

    要使用手动配置endpoint的方式创建服务,需要创建服务和Endpoint资源。

    创建没有选择器的服务

    首先为服务创建一个YAML文件,如下面的代码清单所示。

    代码清单5.8 不含pod选择器的服务:external-service.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: external-service # 服务的名字必须和endpoint对象的名字相匹配
    spec:
      ports:
      - port: 80
    
    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      selector:
        app: MyApp
      ports:
        - name: http
          protocol: TCP
          port: 80
          targetPort: 9376
      externalIPs:
        - 80.11.12.10
    

    定义一个名为external-service的服务,它将接收端口80上的传入连接。并没有为服务定义一个pod选择器。

    为没有选择器的服务创建Endpoint资源

    Endpoint是一个单独的资源并不是服务的一个属性。由于创建的资源中并不包含选择器,相关的Endpoints资源并没有自动创建,所以必须手动创建。如下所示的代码清单中列出了YAML manifest。

    k get pod -o wide
    NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
    kubia-7d5b548867-4qn2x   1/1     Running   1          23h   172.18.0.2   minikube   <none>           <none>
    kubia-7d5b548867-8wnls   1/1     Running   1          23h   172.18.0.3   minikube   <none>           <none>
    kubia-7d5b548867-m4bfz   1/1     Running   1          23h   172.18.0.4   minikube   <none>           <none>
    

    代码清单5.9 手动创建Endpoint资源:external-service-endpoints.yaml

    apiVersion: v1
    kind: Endpoints
    metadata:
      name: external-service # endpoint的名称必须和服务相匹配
    subsets:
      - addresses:
        - ip: 172.18.0.2 #服务将连接重定向到endpoint的ip地址
        - ip: 192.168.0.105 
        - ip: 119.147.33.43
        ports:
        - port: 8080  #endpoint的目标端口
    

    验证一下

    $ k exec -it kubia-7d5b548867-4qn2x -- bash
    $ curl http://external-service
    

    Endpoint对象需要与服务具有相同的名称,并包含该服务的目标IP地址和端口列表。服务和Endpoint资源都发布到服务器后,这样服务就可以像具有pod选择器那样的服务正常使用。在服务创建后创建的容器将包含服务的环境变量,并且与其IP:port对的所有连接都将在服务端点之间进行负载均衡。

    图5.4显示了三个pod连接到具有外部endpoint的服务。

    如果稍后决定将外部服务迁移到Kubernetes中运行的pod,可以为服务添加选择器,从而对Endpoint进行自动管理。反过来也是一样的——将选择器从服务中移除,Kubernetes将停止更新Endpoints。这意味着服务的IP地址可以保持不变,同时服务的实际实现却发生了改变。

    5.2.3 为外部服务创建别名

    除了手动配置服务的Endpoint来代替公开外部服务方法,有一种更简单的方法,就是通过其完全限定域名(FQDN)访问外部服务

    创建ExternalName类型的服务

    要创建一个具有别名的外部服务的服务时,要将创建服务资源的一个type字段设置为ExternalName。例如,设想一下在http://api.somecompany.com上有公共可用的API,可以定义一个指向它的服务,如下面的代码清单所示。

    代码清单5.10 ExternalName类型的服务:external-service-externalname.yaml\

    apiVersion: v1
    kind: Service
    metadata:
      name: external-service
    spec:
      type: ExternalName
      externalName: www.baidu.com  #实际服务的域名
      ports:
      - port: 80
    

    服务创建完成后,pod可以通过 external-service.default.svc.cluster.local 域名(甚至是 external-service )连接到外部服务,而不是使用服务的实际FQDN。这隐藏了实际的服务名称及其使用该服务的pod的位置,允许修改服务定义,并且在以后如果将其指向不同的服务,只需简单地修改externalName属性,或者将类型重新变回ClusterIP并为服务创建Endpoint——无论是手动创建,还是对服务上指定标签选择器使其自动创建。

    ExternalName 服务仅在DNS级别实施——为服务创建了简单的CNAME DNS记录。因此,连接到服务的客户端将直接连接到外部服务,完全绕过服务代理。

    出于这个原因,这些类型的服务甚至不会获得集群IP。

    注意 CNAME记录指向完全限定的域名而不是数字IP地址。

    相关文章

      网友评论

        本文标题:5.2 连接集群外部的服务

        本文链接:https://www.haomeiwen.com/subject/gyykmltx.html