美文网首页
(七)Kubernetes 之 服务 Service

(七)Kubernetes 之 服务 Service

作者: deve_雨轩 | 来源:发表于2021-08-22 16:19 被阅读0次

    kubernetes 服务是一种为一组功能相同的 pod 提供单一不变的接入点的资源。当服务存在时,它的 IP 地址和端口不会改变。客户端通过 IP 地址和端口号建立连接,这些连接会被路由到提供该服务的任意一个 pod 上。通过这种方式,客户端不需要知道每个单独的提供服务的 pod 的地址,这样这些 pod 就可以在集群中随时被创建或移除。

    创建服务

    通过 kubectl expose 快速创建

    kubectl expose rc yx-nginx
    

    执行此命令,就是会根据 rc 控制器 yx-nginx 创建一个同名的 service。

    通过 yaml 配置文件创建

    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: yx-nginx
    spec:
        ports:
        ## 服务访问端口
        - port: 8000
        ## 目标 pod 访问端口
          targetPort: 80
        selector:
            ## 具有 app=nginx 标签的 pod 都属于该服务
            app: nginx
    

    创建了一个名叫 yx-nginx 的服务,它将在端口 8000 接受请求并将连接路由到具有 app=nginx 标签的 pod 的 80 端口上。

    kubectl create -f test-nginx-service.yaml
    

    列出命名空间下所有服务资源

    kubectl get svc
    
    NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    kubernetes              ClusterIP      10.96.0.1       <none>        443/TCP          3d20h
    yx-nginx                ClusterIP      10.109.90.148   <none>        8000/TCP         18h
    

    列表显示分配给服务的 IP 地址是 10.109.90.148。因为只是集群的 iP 地址,只能在集群内部可以被访问。

    配置服务上的会话亲和性

    如果多次请求同一个服务,每次调用执行应该在不同的 pod 上。因为在默认情况下, Kubernetes 采用 RoundRobin 模式对客户端请求进行负载分发。

    如果希望特定客户端产生的所有请求每次都指向同一个 pod,可以设置服务的sessionAffinity 属性为ClientIP,默认值为 None。

    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: yx-nginx
    spec:
        sessionAffinity: ClientIP
        ports:
        ## 服务访问端口
        - port: 8000
        ## 目标 pod 访问端口
          targetPort: 80
        selector:
            ## 具有 app=nginx 标签的 pod 都属于该服务
            app: nginx
    

    同一个服务暴露多个端口

    创建的服务可以暴露一个端口,也可以暴露多个端口。比如,你的 pod 监昕两个端口,比如 HTTP 监听 80 端口、 HTTPS 监听 443 端口,可以使用一个服务从端口 80 和 443 转发至 pod 端口 80 和 443。在这种情况下,无须创建两个不同的服务。通过一个集群 IP,使用一个服务就可以将多个端口全部暴露出来。

    在创建一个有多个端口的服务的时候,必须给每个端口指定名字。

    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: yx-nginx
    spec:
        ports:
        - name: http
          port: 80
          targetPort: 80
        - name: https
          port: 443
          targetPort: 443
        selector:
            ## 具有 app=nginx 标签的 pod 都属于该服务
            app: nginx
    

    标签选择器应用于整个服务,不能对每个端口做单独的配置。如果不同的 pod 有不同的端口映射关系,需要创建两个服务。

    使用命名的端口

    我们可以在定义 pod 端口的时候给端口命名,然后在服务 spec 中按名称引入端口。

    apiVersion: v1
    kind: Pod
    metadata:
        name: test-nginx ##pod名称
    spec:
        containers: ## pod里运行那些容器
        - image: nginx  ## 镜像名称
          name: test    ## 容器名称
          ports:
          - name: http
            containerPort: 80
          - name: https
            containerPort: 443  
    
    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: yx-nginx
    spec:
        ports:
        - name: http
          port: 80
          targetPort: http
        - name: https
          port: 443
          targetPort: https
        selector:
            ## 具有 app=nginx 标签的 pod 都属于该服务
            app: nginx
    

    为什么要采用命名端口的方式?最大的好处就是即使更换端口号也无须更改服务 spec。你的 pod 现在对 http 服务用的是 80,但是假设过段时间你决定将端口更换为 8080 呢?
    如果你采用了命名的端口,仅仅需要做的就是改变 spec pod 中的端口号(当然你的端口号的名称没有改变)。在你的 pod 向新端口更新时,根据 pod 收到的连接 (80 端口在旧的 pod 上、 8080 端口在新的 pod 上 ),用户连接将会转发到对应的端口。

    连接集群外部的服务

    通过 Kubernetes 服务特性暴露外部服务的情况。不要让服务将连接重定向到集群中的 pod,而是让它重定向到外部 IP 和端口。
    这样做可以让你充分利用服务负载平衡和服务发现。在集群中运行的客户端 pod 可以像连接到内部服务一样连接到外部服务 。

    介绍服务 endpoint

    服务并不是和 pod 直接相连的。相反,有一种资源介于两者之间,它就是 Endpoint 资源。

    $ kubectl describe svc yx-nginx
    Name:              yx-nginx
    Namespace:         default
    Labels:            <none>
    Annotations:       <none>
    Selector:          app=nginx
    Type:              ClusterIP
    IP:                10.108.146.21
    Port:              <unset>  80/TCP
    TargetPort:        80/TCP
    Endpoints:         100.108.201.68:80,100.73.43.204:80,100.98.112.72:80
    Session Affinity:  None
    Events:            <none>
    

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

    $ kubectl get endpoints yx-nginx
    NAME       ENDPOINTS                                            AGE
    yx-nginx   100.73.43.204:80,100.73.43.205:80,100.73.43.206:80   23h
    

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

    手动配置服务的 endpoint

    服务的 endpoint 与服务解稍后,可以分别手动配置和更新它们。

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

    创建没有选择器的服务

    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: manual-endponit-service
    spec:
        ports:
        ## 服务访问端口
        - port: 80
    

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

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

    Endpoint 是一个单独的资源并不是服务的一个属性。由于创建的服务中并不包 含选择器,相关的 Endpoints 资源并没有自动创建,所以必须手动创建。

    apiVersion: v1
    kind: Endpoints
    metadata:
        ## endpoint 的名称必须和服务名称一致
        name: manual-endponit-service
    subsets:
      - addresses:
        - ip: 192.168.0.239
        ports:
        - port: 8090
    

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

    将服务暴露给外部访问

    上面只讨论了集群内服务如何被 pod 使用;但是,还需要向外部公开某些服务。例如前端 web 服务器,以便外部客户端可以访问它们。
    有几种方式可以在外部访问服务 :

    • 将服务的类型设置成 NodePort:每个集群节点都会在节点上打开一个端口,对于 NodePort 服务,每个集群节点在节点本身上打开一个端口,并将在该端口上接收到的流量重定向到基础服务。该服务仅在内部集群 IP 和端口上才可访问,但也可通过所有节点上的专用端口访问。
    • 将服务的类型设置成 LoadBalance:NodePort 类型的一种扩展,这使得 服务可以通过一个专用的负载均衡器来访问,这是由 Kubernetes 中正在运行的云基础设施提供的。负载均衡器将流量重定向到跨所有节点的节点端口。 客户端通过负载均衡器的 IP 连接到服务。
    • 创建一个 Ingress 资源,这是一个完全不同的机制,通过一个 IP 地址公开多个服务,它运行在 HTTP 层( 网络协议第 7 层)上,因此可以提供比工作在第 4 层的服务更多的功能。

    创建 NodePort 类型的服务

    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: yx-nginx-nodeport
    spec:
        type: NodePort
        ports:
        ## 服务访问端口
        - port: 8000
        ## 目标 pod 访问端口
          targetPort: 80
          ## 集群节点端口,通过该端口访问服务,如果不设置,kubernetes 会随机一个端口
          nodePort: 30123
        selector:
            ## 具有 app=nginx 标签的 pod 都属于该服务
            app: nginx
    

    将类型设置为 NodePort 并指定该服务应该绑定到的所有集群节点的节点端口。指定端口不是强制性的。如果忽略它,Kubernetes 将选择一个随机端口。

    创建 LoadBalance 负载均衡器服务

    kubernetes 集群通常支持从云基础架构自动提供负载平衡器。所有需要做的就是设置服务的类型为 LoadBadancer 而不是 NodePort。负载均衡器拥有自己独一无二的可公开访问的 IP 地址, 可以通过负载均衡器的 IP 地址访问服务。

    如果 kubernetes 在不支持 LoadBadancer 服务的环境中运行,则不会调 配负载平衡器,但该服务仍将表现得像一个 NodePort 服务。这是因为 LoadBadancer 服务是 Node Port 服务的扩展

    apiVersion: v1
    kind: Service
    metadata:
        ## 服务名称
        name: yx-nginx-loadbalancer
    spec:
        type: LoadBalancer
        ports:
        ## 服务访问端口
        - port: 8000
        ## 目标 pod 访问端口
          targetPort: 80
          nodePort: 30124
        selector:
            ## 具有 app=nginx 标签的 pod 都属于该服务
            app: nginx
    

    了解外部连接的特性

    防止不必要的网络跳数

    当外部客户端通过节点端口连接到服务时,随机选择的 pod 并不一定在接收连接的同一节点上运行。可能需要额外的网络跳转才能到达 pod,但这种行为并不符合期望。

    可以通过将服务配置为仅将外部通信重定向到接收连接的节点上运行的 pod 来阻止此额外跳数。这是通过在服务的 spec 部分中设置 externalTrafficPolicy 字段来完成:

    spec:
        externalTrafficPolicy: Local
    

    如果服务定义包含此设置,并且通过服务的节点端口打开外部连接,则服务代理将选择本地运行的 pod。如果没有本地 pod 存在,则连接将挂起。因此,需要确保负载平衡器将连接转发给至少具有一个 pod 的节点。

    相关文章

      网友评论

          本文标题:(七)Kubernetes 之 服务 Service

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