Kubernetes 服务类型概述

一、什么是 Kubernetes 中的服务?

在 Kubernetes 环境中,你可以有数百个(如果不是数千个)短暂的 pod。无论是因为节点被缩减、Pod 副本被缩减,还是 Pod 被重新调度到新节点,Pod 的 IP 地址都无法保证。Pod IP 地址是在调度到特定节点之后和引导之前分配的。

鉴于我们处于云原生环境中,我们希望能够水平扩展 Pod。因此,跟踪我们所有应用程序的所有IP地址将非常困难。Kubernetes 有一种资源类型,可以解决不断变化的 pod IP 问题,称为服务。Kubernetes 服务允许您创建单个常量 IP 地址,其中包含一组包含相同服务的 Pod 的 IP 地址。这非常有用,因为服务 IP 保持静态,而 Pod IP 可以不断更改。您永远不必担心没有正确的IP地址。

二、服务如何运作?

服务如何工作?如何配置?

让我们首先创建一个包含三个 Nginx pod 实例的部署。

apiVersion: apps/v1

  kind: Deployment

metadata:

  labels:

    app: nginx

  name: nginx

spec:

  replicas: 3

  selector:

    matchLabels:

      app: nginx

    spec:

      containers:

      - image: nginx

        name: nginx

应用部署清单后,我们可以看到有三个 nginx 实例与 IP 一起运行。另外,请注意我们为这些 Pod 分配的标签。这对于服务如何监视这些 Pod 至关重要。10.244.242.66, 10.244.242.67, 10.244.230,199app=nginx

$ kubectl get pods -owide --show-labels

NAME                    READY   STATUS    RESTARTS   AGE     IP               NODE                      LABELS

nginx-8f458dc5b-6vcxt   1/1     Running   0          2m27s   10.244.242.66    nodepool-a-95e9c8e86208   app=nginx,pod-template-hash=8f458dc5b

nginx-8f458dc5b-ktvtf   1/1     Running   0          2m27s   10.244.242.67    nodepool-a-95e9c8e86208   app=nginx,pod-template-hash=8f458dc5b

nginx-8f458dc5b-mlkwd   1/1     Running   0          2m27s   10.244.230.199   nodepool-a-11aa1dc199fa   app=nginx,pod-template-hash=8f458dc5b

现在,让我们定义我们的服务清单,下面定义服务清单,其中包含所定义内容的细分。

apiVersion: v1

kind: Service

metadata:

  name: nginx

  labels:

    app: nginx

spec:

  selector:

    app: nginx

  type: ClusterIP

  ports:

  - name: 80-80

    port: 80

    protocol: TCP

    targetPort: 80

当我们开始分解这个清单时,我们注意到这种清单是。接下来,元数据部分应该很熟悉,因为它与其他 Kubernetes 资源上的元数据字段相同。规范部分定义了我们的服务将如何以及与什么交互。Service

菲尔德。在此字段中,您可以定义希望此服务监视的容器。这是通过标签匹配完成的。您会注意到这有一个定义。如果您还记得,这些是我们在部署清单中为 Pod 定义的标签。通过此选择器定义,我们声明任何带有标签的 Pod 都将成为此服务的一部分。selectorselectorapp: nginxapp=nginx

接下来,我们有字段。这定义了我们希望这是什么样的服务。稍后我们将更深入地介绍服务类型,但我们现在刚刚将其定义为 a。typeClusterIP

最后,我们有领域。在这里,我们定义流量流经服务的方式和位置。请注意,此字段包含一个数组,以便您可以定义多个条目。ports

让我们分解端口中的每个字段:

  • 名称:可以为给定端口条目分配特定名称。
  • 端口:这是服务将侦听的端口。
  • 目标端口:这是服务将请求转发到的端口。这应该与 Pod 正在侦听的端口匹配。
  • 协议:您希望服务侦听并与之交互的特定协议。

现在,我们已经基本了解了服务清单的功能以及它如何与 Pod 交互,接下来我们将部署清单并检查服务。

$ k get svc

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE

kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   90m

nginx        ClusterIP   10.108.176.62   <none>        80/TCP    18m



$ kubectl describe svc nginx

Name:              nginx

Namespace:         default

Labels:            app=nginx

Annotations:       <none>

Selector:          app=nginx

Type:              ClusterIP

IP Family Policy:  SingleStack

IP Families:       IPv4

IP:                10.108.176.62

IPs:               10.108.176.62

Port:              80-80  80/TCP

TargetPort:        80/TCP

Endpoints:         10.244.230.199:80,10.244.242.66:80,10.244.242.67:80

Session Affinity:  None

Events:            <none>

描述命令中的所有内容都应与清单定义保持一致,但两个字段和除外。IPEndpoints

该字段定义服务的 IP 地址。这是可用于访问服务后面的 Pod 的静态 IP。IP

该字段定义当前分配给此服务的容器 IP。您注意到这些 IP 来自我们的 Nginx 部署。Endpoints

在我们继续讨论其他服务类型之前,让我们展示如何缩减 Nginx 部署,并查看服务将如何处理此更改。

$ kubectl scale deployment/nginx --replicas 1

deployment.apps/nginx scaled



$ kubectl get pods -owide

NAME                    READY   STATUS    RESTARTS   AGE   IP               NODE                      NOMINATED NODE   READINESS GATES

nginx-8f458dc5b-mlkwd   1/1     Running   0          43m   10.244.230.199   nodepool-a-11aa1dc199fa   <none>           <none>



$ kubectl describe service nginx | grep Endpoints  

Endpoints:         10.244.230.199:80



$ kubectl scale deployment/nginx --replicas 5

deployment.apps/nginx scaled



$ kubectl get pods -owide

NAME                    READY   STATUS    RESTARTS   AGE    IP               NODE                      NOMINATED NODE   READINESS GATES

nginx-8f458dc5b-9pmhb   1/1     Running   0          108s   10.244.242.69    nodepool-a-95e9c8e86208   <none>           <none>

nginx-8f458dc5b-mlkwd   1/1     Running   0          47m    10.244.230.199   nodepool-a-11aa1dc199fa   <none>           <none>

nginx-8f458dc5b-r2pcp   1/1     Running   0          108s   10.244.242.70    nodepool-a-95e9c8e86208   <none>           <none>

nginx-8f458dc5b-vgwv6   1/1     Running   0          108s   10.244.242.68    nodepool-a-95e9c8e86208   <none>           <none>

nginx-8f458dc5b-x6thl   1/1     Running   0          108s   10.244.230.200   nodepool-a-11aa1dc199fa   <none>           <none>



$ kubectl describe service nginx | grep Endpoints

Endpoints:         10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...

您可以看到,向上和向下扩展 Pod 会立即反映在服务中,允许单个静态 IP 访问 Pod。

三、服务类型

在服务资源中,有三种不同的类型。它们如下:

  1. 集群IP
  2. 节点端口
  3. 负载均衡器

    这些都有自己的行为和特定的用例,因此知道何时使用每个非常重要。在以下部分中,我们将对其中的每一个进行更深入的探讨。

3.1、集群 IP

集群 IP 是最基本的“服务类型。它将创建一个静态 IP 地址,该地址位于与 Pod IP 范围不同的子网上,并通过标签选择器监控一组 Pod。

集群-IP

ClusterIP 允许 Pod 之间轻松通信,因为 Pod 可以向静态 IP 发送请求,也可以使用 Kubernetes DNS 发送请求。在我们部署的前面的示例中,DNS 应该是。使用 ClusterIP 存在一些限制。最大的问题是没有办法向外界公开这项服务。这是服务类型应该使用的地方。{service-name}.{namespace}nginx.defaultnodePortloadBalancer

3.2、节点端口

该服务建立在类型之上。它通过在工作节点上打开端口来转发流量,从而向外界公开。这意味着,如果您有 50 个工作器节点,则每个工作器节点都将侦听分配的端口,即使 Pod 不存在于该工作节点上也是如此。NodePortClusterIPClusterIP

节点端口

要创建服务,唯一的区别是定义NodePortTypeNodePort

kind: Service

metadata:

  labels:

    app: nginx

  name: nginx

spec:

  ports:

  - name: 80-80

    port: 80

    protocol: TCP

    targetPort: 80

    # nodePort: 30001

  selector:

    app: nginx

  type: NodePort

您可能会注意到它被注释掉了。这是因为如果您不定义该部分,Kubernetes 将自动从该范围内分配一个随机端口。如果要定义特定端口,则必须从此范围完成。nodePortnodePortports30000-32767

部署 NodePort 服务清单并让我们对其进行审核。

$ kubectl get svc

NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        135m

nginx        NodePort    10.98.246.253   <none>        80:30828/TCP   5s



$ kubectl describe svc nginx

Name:                     nginx

Namespace:                default

Labels:                   app=nginx

Annotations:              <none>

Selector:                 app=nginx

Type:                     NodePort

IP Family Policy:         SingleStack

IP Families:              IPv4

IP:                       10.98.246.253

IPs:                      10.98.246.253

Port:                     80-80  80/TCP

TargetPort:               80/TCP

NodePort:                 80-80  30828/TCP

Endpoints:                10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...

Session Affinity:         None

External Traffic Policy:  Cluster

Events:                   <none>

在这里,我们看到一个名为值的新字段。这是分配给此服务的端口和协议。现在,如果我们要使用该端口向任何工作节点 IP 地址发送请求,则请求将发送到服务,然后服务将发送到我们的 Pod。NodePort30828/TCP

$ kubectl get nodes -owide

NAME                      STATUS   ROLES    AGE    VERSION   INTERNAL-IP   EXTERNAL-IP     OS-IMAGE                       KERNEL-VERSION    CONTAINER-RUNTIME

nodepool-a-11aa1dc199fa   Ready    <none>   140m   v1.24.4   10.1.96.5     45.77.152.173   Debian GNU/Linux 10 (buster)   4.19.0-22-amd64   containerd://1.6.8

nodepool-a-95e9c8e86208   Ready    <none>   140m   v1.24.4   10.1.96.4     140.82.44.105   Debian GNU/Linux 10 (buster)   4.19.0-22-amd64   containerd://1.6.8

$ curl 140.82.44.105:30828

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>



$ curl 45.77.152.173:30828

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

虽然这是向外界公开我们的服务的有用方法,但它不能很好地扩展。在高度自动扩展的 Kubernetes 集群中,工作节点可能是短暂的,因为它们可能不断上下旋转。这使我们陷入了与pod类似的问题,我们可以在其中找出IP是什么,但这并不意味着它们将永远存在。如果您的服务需要静态外部 IP 地址,则服务类型将满足该需求。LoadBalancer

3.3、负载均衡器

与 how’s 构建在 ‘, the’s 服务构建在 –使用服务时,每个工作节点继续具有分配给特定服务的唯一端口。但是,现在部署并配置了 L4 以路由到特定的工作器节点和端口。高级请求流如下所示:将请求发送到负载均衡器,负载均衡器转发到特定节点端口上的工作节点,然后传递到特定服务,最后发送到 Pod。NodePortClusterIPLoadBalancerNodePortLoadBalancer

负载均衡器

如果需要,配置服务会更加复杂。一个非常简单的配置可以如下所示,只是将字段更改为。LoadBalancertypeLoadBalancer

apiVersion: v1

kind: Service

metadata:

  labels:

    app: nginx

  name: nginx

spec:

  ports:

  - name: 80-80

    port: 80

    protocol: TCP

    targetPort: 80

  selector:

    app: nginx

  type: LoadBalancer

例如,如果您希望更改负载均衡器以强制 SSL 重定向、配置防火墙规则、使用 HTTPS 而不是 HTTP 或使用不同的平衡算法,则需要在您的服务上定义。Annotations

下面是一个这样的例子。LoadBalancer

apiVersion: v1

kind: Service

metadata:

  annotations:

    service.beta.kubernetes.io/vultr-loadbalancer-protocol: "http"

    service.beta.kubernetes.io/vultr-loadbalancer-https-ports: "443"

    # You will need to have created a TLS Secret and pass in the name as the value

    service.beta.kubernetes.io/vultr-loadbalancer-ssl: "ssl-secret"

    service.beta.kubernetes.io/vultr-loadbalancer-algorithm: "least_connections"

    service.beta.kubernetes.io/vultr-loadbalancer-ssl-redirect: "true"

    service.beta.kubernetes.io/vultr-loadbalancer-firewall-rules: "0.0.0.0/80;0.0.0.0/443"

  labels:

    app: nginx

  name: nginx

spec:

  ports:

    - port: 80

      name: "http"

    - port: 443

      name: "https"

  selector:

    app: nginx

  type: LoadBalancer

有关更多详细信息,请参阅可与 Vultr 负载均衡器一起使用的所有可用注释列表。

当您第一次部署您的服务时,您将看到该部分是LoadBalancerEXTERNAL-IPpending

$ portfolio [talk-postman] âš¡  k get svc

NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE

kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP        150m

nginx        LoadBalancer   10.103.252.120   <pending>     80:30092/TCP   4s



$ portfolio [talk-postman] âš¡  kubectl describe service nginx

Name:                     nginx

Namespace:                default

Labels:                   app=nginx

Annotations:              <none>

Selector:                 app=nginx

Type:                     LoadBalancer

IP Family Policy:         SingleStack

IP Families:              IPv4

IP:                       10.103.252.120

IPs:                      10.103.252.120

Port:                     80-80  80/TCP

TargetPort:               80/TCP

NodePort:                 80-80  30092/TCP

Endpoints:                10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...

Session Affinity:         None

External Traffic Policy:  Cluster

Events:

  Type     Reason                  Age               From                Message

  ----     ------                  ----              ----                -------

  Normal   EnsuringLoadBalancer    8s (x4 over 44s)  service-controller  Ensuring load balancer

  Warning  SyncLoadBalancerFailed  8s (x4 over 44s)  service-controller  Error syncing load balancer: failed to ensure load balancer: load-balancer is not yet active - current status: pending

您注意到,这里 Kubernetes 已经部署了一个 Vultr 负载均衡器,并且正在进行持续通信,以检查负载均衡器是否已被配置并分配了 IP。

一旦 Vultr 负载均衡器已配置并准备好用于流量,您将在字段中看到分配的 IP 地址,并且 LB 已得到保证”。这意味着 Kubernetes 现在可以控制相应地监控和更新负载均衡器。另外,请注意,分配了一个唯一的节点端口。EXTERNAL-IP

$ portfolio [talk-postman] âš¡  k get svc

NAME         TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)        AGE

kubernetes   ClusterIP      10.96.0.1        <none>         443/TCP        154m

nginx        LoadBalancer   10.103.252.120   45.63.15.140   80:30092/TCP   4m9s



$ kubectl describe service nginx

Name:                     nginx

Namespace:                default

Labels:                   app=nginx

Annotations:              <none>

Selector:                 app=nginx

Type:                     LoadBalancer

IP Family Policy:         SingleStack

IP Families:              IPv4

IP:                       10.103.252.120

IPs:                      10.103.252.120

LoadBalancer Ingress:     45.63.15.140

Port:                     80-80  80/TCP

TargetPort:               80/TCP

NodePort:                 80-80  30092/TCP

Endpoints:                10.244.230.199:80,10.244.230.200:80,10.244.242.68:80 + 2 more...

Session Affinity:         None

External Traffic Policy:  Cluster

Events:

  Type     Reason                  Age                    From                Message

  ----     ------                  ----                   ----                -------

  Warning  SyncLoadBalancerFailed  2m21s (x5 over 3m37s)  service-controller  Error syncing load balancer: failed to ensure load balancer: load-balancer is not yet active - current status: pending

  Normal   EnsuringLoadBalancer    61s (x6 over 3m37s)    service-controller  Ensuring load balancer

  Normal   EnsuredLoadBalancer     60s                    service-controller  Ensured load balancer

要验证我们的 Vultr 负载均衡器是否正常工作,我们可以向负载均衡器公共 IP 地址发送请求。EXTERNAL-IP

$ curl 45.63.15.140

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

您可以将服务类型视为一个绝佳的解决方案。但是,它们有一个缺点;不能定义任何类型的 URL 路径,这不允许灵活性或将其路由到多个服务。该服务绑定到单个服务,因此如果要从群集中公开另一个应用程序,则需要部署另一个 Vultr 负载均衡器,如果您有多个应用程序,这可能会迅速增加成本。LoadBalancerLoadBalancer

这个问题的解决方案不是另一种服务类型,而是调用不同的 Kubernetes 资源。ingress

3.4、入口

Anresource是一种更灵活的方法来定义外部世界要访问的服务。这里最大的卖点之一是您可以定义单个入口资源,并将此路由路由到您定义的子域、端口或 URL 路径下的所有服务。它们还提供了大量其他功能,例如速率限制、身份验证、自动 TLS、加权路由等等。所有这些都可以使用单个负载均衡器完成,因为 theresource 与服务类型一起工作,唯一的区别是部署负载均衡器充当代理将所有流量发送到 theresource,它充当集群中的 L7 负载均衡器。ingressIngressLoadBalancerIngress

美人鱼图

这里唯一需要注意的是,Kubernetes没有内部入口控制器。那里有各种入口控制器,都具有不同类型的功能。最终,这取决于您的需求和愿望,然后再决定安装哪个入口控制器。有关配置指南,请参阅入口控制器的文档。

一些更流行的入口控制器是:

  • 使者入口
  • 大使边缘堆栈
  • 入口 nginx

四、总结

虽然这篇文章可能会让你很好地理解不同类型的 Kubernetes 服务和入口控制器,但这只是划伤了服务。这些服务还有更多配置选项和一些免费功能,例如网络策略。请查看下面列出的一些链接以获取更多信息。

赞(0)
未经允许不得转载:主机百科 » Kubernetes 服务类型概述