Kubernetes的Service类型详解

1. Service详解

1.1 Service介绍

在Kubernetes中,Service资源解决了Pod IP地址不固定的问题,提供了一种更稳定和可靠的服务访问方式。以下是Service的一些关键特性和工作原理:

  • Service的稳定性:由于Pod可能会因为故障、重启或扩容而获得新的IP地址,直接使用Pod的IP来访问服务是不可靠的。Service通过提供一个固定的虚拟IP(ClusterIP)作为访问入口,使得服务访问变得更加稳定。

  • Service的类型:Kubernetes支持不同类型的Service,包括ClusterIP、NodePort、LoadBalancer和ExternalName,每种类型适用于不同的访问场景:

    • ClusterIP:为Service在集群内部提供一个固定的虚拟IP,只有集群内部的客户端可以访问此服务。

    • NodePort:在所有节点的特定端口上公开Service,使得外部可以通过<NodeIP>:<NodePort>访问服务。

    • LoadBalancer:在NodePort的基础上,通过云服务商的负载均衡器对外提供服务,适用于公有云环境。

    • ExternalName:将服务映射到外部服务的DNS名称,不通过kube-proxy进行代理。

  • Service的负载均衡:Service可以对关联的Pod进行轮询或随机的负载均衡,使得请求可以均匀地分发到各个Pod上。

  • Service的发现机制:Kubernetes中的Pod可以通过DNS或环境变量来发现Service。通过DNS,Pod可以通过Service的名称和命名空间来解析Service的ClusterIP。

  • Service和Pod的关系:Service通过标签选择器(label selector)与一组Pod关联。当Service创建后,kube-proxy或相关的网络插件会监控Pod的变化,并更新Service的后端列表(Endpoints。

  • Headless Service:一种特殊的Service,不分配ClusterIP,而是通过DNS返回Pod的IP列表,适用于需要直接访问每个Pod的场景,如StatefulSets。

  • Service的端口:Service可以定义一个或多个端口,将外部请求映射到Pod的特定端口上。端口分为Service端口(port)、Pod端口(targetPort)和NodePort(仅NodePort类型Service)

image-20240514095437913

  • Service在很多情况下只是一个概念,真正起作用的其实是kube-proxy服务进程,每个Node节点上都运行着一个kube-proxy服务进程。当创建Service的时候会通过api-server向etcd写入创建的service的信息,而kube-proxy会基于监听的机制发现这种Service的变动,然后它会将最新的Service信息转换成对应的访问规则。

image-20240514095556728

1.2 kube-proxy三种工作模式

8.2.1 userspace模式

  • userspace模式下,kube-proxy会为每一个Service创建一个监听端口,发向Cluster IP的请求被iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法选择一个提供服务的Pod并和其建立链接,以将请求转发到Pod上。

  • 该模式下,kube-proxy充当了一个四层负责均衡器的角色。由于kube-proxy运行在userspace中,在进行转发处理时会增加内核和用户空间之间的数据拷贝,虽然比较稳定,但是效率比较低。

  • kube-proxyuserspace模式下的工作原理如下:

    • Service的监听kube-proxy为每个Service创建一个监听端口,这个端口对应Service的ClusterIP和端口号。当客户端向Service的ClusterIP:Port发送请求时,请求会被iptables规则捕获并重定向到kube-proxy的监听端口上。

    • 负载均衡kube-proxy根据定义的负载均衡算法(如轮询、随机等)从提供该服务的所有Pod中选择一个Pod,然后与该Pod建立连接,并将请求转发到选定的Pod上。kube-proxy在此过程中充当了四层(TCP/UDP)负载均衡器的角色。

    • 用户空间的开销:由于kube-proxyuserspace模式下运行,数据包需要在内核空间和用户空间之间来回拷贝,这会导致额外的性能开销。虽然这种方法比较稳定,但是在高负载情况下,由于数据拷贝的开销,效率相对较低。

    • 其他模式:除了userspace模式,kube-proxy还支持iptables模式和ipvs模式,这两种模式效率更高,因为它们直接在内核空间工作,减少了数据拷贝的开销。iptables模式通过修改网络规则来实现负载均衡,而ipvs模式则是内核级别的负载均衡,通常提供更好的性能和更复杂的负载均衡特性。

image-20240514100818525

8.2.2 iptables模式

  • iptables模式下,kube-proxy为service后端的每个Pod创建对应的iptables规则,直接将发向ClusterIP的请求重定向到一个Pod IP。

  • 该模式下kube-proxy不承担四层负责均衡器的角色,只负责创建iptables规则。该模式的优点是较userspace模式效率更高,但不能提供灵活的LB策略,当后端Pod不可用时也无法进行重试。

  • iptables模式下的kube-proxy工作原理如下:

    • 创建规则:在iptables模式下,kube-proxy为每个Service后端的Pod创建相应的iptables规则。当请求到达Service的ClusterIP时,这些规则将请求直接重定向到后端Pod的IP地址上。

    • 直接重定向:与userspace模式不同,在iptables模式下,kube-proxy不进行实际的流量转发,而是通过修改网络规则来实现负载均衡。这意味着流量直接从客户端通过网络路由到目的Pod,而不需要经过kube-proxy进程。

    • 效率提升:由于避免了用户空间和内核空间之间的上下文切换以及数据拷贝,iptables模式通常比userspace模式有更高的网络性能。

    • 简化的LB策略:在iptables模式下,kube-proxy不实现复杂的负载均衡策略,如会话保持或智能负载均衡。它仅根据轮询策略简单地分发请求到各个Pod。

    • 重试限制:由于iptables规则直接将流量路由到Pod,如果选定的Pod不可用,请求将失败,而kube-proxy不会进行重试。这与userspace模式不同,在userspace模式下,kube-proxy可以检测到连接失败并重新选择另一个Pod进行重试。

    • 安全性iptables模式下,流量直接从客户端路由到Pod,这意味着Pod的网络安全策略需要正确配置,以确保不会直接暴露给不受信任的网络。

  • iptables模式提供了一种高效的方式来实现Service的负载均衡,但牺牲了一定程度的灵活性和容错能力。选择合适的模式需要根据具体的应用需求和性能要求来决定。对于需要高性能和简单负载均衡策略的场景,iptables模式是一个不错的选择。而对于需要复杂负载均衡策略和容错能力的场景,userspace模式或ipvs模式可能更合适。

image-20240514101428737

8.2.3 ipvs模式

  • ipvs模式和iptables类似,kube-proxy监控Pod的变化并创建相应的ipvs规则。ipvs相对iptables转发效率更高。除此以外,ipvs支持更多的LB算法。

  • ipvs(IP Virtual Server)模式是kube-proxy的另一种工作模式,它在很多方面都优于iptables模式:

    • 内核级负载均衡:与iptables不同,ipvs是在内核空间实现的,这意味着它可以直接进行网络包的转发,而不需要在用户空间和内核空间之间来回拷贝数据。因此,ipvs可以提供更低的延迟和更高的数据包转发速率。

    • 高效的性能:由于ipvs在内核中实现,它通常能够提供比iptables更高的性能,尤其是在高负载和大规模集群中。

    • 丰富的负载均衡算法ipvs支持多种负载均衡算法,包括轮询(round-robin)、最小连接(least-connection)、源IP哈希(source IP hashing)等,这为实现复杂的负载均衡策略提供了可能。

    • Session persistenceipvs支持会话保持(Session persistence),这意味着来自同一客户端的请求可以始终被路由到同一个后端Pod,这对于需要维持会话状态的应用非常重要。

    • 健康检查ipvs可以根据Pod的健康状态来路由流量,只将请求转发到健康的Pod上,从而提高服务的可用性。

    • SNAT优化ipvs可以更有效地处理源地址转换(SNAT),这对于使用NodePortLoadBalancer服务类型时,从外部网络访问集群内部服务非常重要。

    • 直接路由ipvs使用直接路由(Direct Routing)模式,这意味着流量不需要经过额外的网络地址转换,从而减少了资源消耗。

    • 状态同步kube-proxyipvs模式下,会监控Pod和Service的变化,并将这些变化实时同步到ipvs规则中。

image-20240514101729240

  • 此模式必须安装ipvs内核模块,否则会降级为iptables

[root@K8s-master ~]# kubectl edit configmap kube-proxy -n kube-system    
    mode: "ipvs"  #修改此处,默认为空
    
[root@K8s-master ~]# kubectl get pod -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-74586cf9b6-96v5x             1/1     Running   0          3d2h
coredns-74586cf9b6-f5q7h             1/1     Running   0          3d2h
etcd-k8s-master                      1/1     Running   0          3d2h
kube-apiserver-k8s-master            1/1     Running   0          3d2h
kube-controller-manager-k8s-master   1/1     Running   0          3d2h
kube-flannel-ds-6gqmv                1/1     Running   0          3d
kube-flannel-ds-g7zcj                1/1     Running   0          3d
kube-flannel-ds-hh52b                1/1     Running   0          3d
kube-proxy-glhml                     1/1     Running   0          3d1h
kube-proxy-klcs2                     1/1     Running   0          3d1h
kube-proxy-x9v8k                     1/1     Running   0          3d2h
kube-scheduler-k8s-master            1/1     Running   0          3d2h
[root@K8s-master ~]# kubectl delete pod kube-proxy-glhml kube-proxy-klcs2 kube-proxy-x9v8k -n kube-system
pod "kube-proxy-glhml" deleted
pod "kube-proxy-klcs2" deleted
pod "kube-proxy-x9v8k" deleted

1.3 Service类型

  • Service的资源清单文件:

---
kind: Service # 资源类型
apiVersion: v1 # 资源版本
metadata: # 元数据
  name: service # 资源名称
  namespace: dev # 命名空间
spec: # 描述
  selector: # 标签选择器,用于确定当前service代理哪些pod
    app: nginx
  type: ClusterIP # Service类型,指定service的访问方式
  clusterIP: None # 虚拟服务的ip地址,设置为None表示创建Headless Service
  sessionAffinity: ClientIP # session亲和性,支持ClientIP、None两个选项
  ports: # 端口信息
    - protocol: TCP
      port: 3017 # service端口
      targetPort: 5003 # pod端口
  • ClusterIP

    • 默认类型。Kubernetes 为 Service 分配一个虚拟的 IP 地址(ClusterIP),这个 IP 只能在集群内部访问。

    • 适用于在集群内部提供服务发现和负载均衡,而不对外公开服务。

  • NodePort

    • 在集群的所有节点上打开一个静态端口(NodePort),外部可以通过任何节点的 IP 地址加这个端口来访问 Service。

    • 适用于需要从集群外部访问服务的场景,但不像 LoadBalancer 那样需要云服务提供商的支持。

  • LoadBalancer

    • 与 NodePort 类似,但会利用云服务提供商的负载均衡器来分发流量。

    • 适用于需要高可用性和可扩展性的场景,并且外部访问流量较大时推荐使用。

    • 注意:需要云服务商支持,并且可能涉及额外的费用。

  • ExternalName

    • 不分配 ClusterIP,而是将服务映射到一个外部的 DNS 名称。

    • 适用于将集群外部的服务(如数据库服务)映射到 Kubernetes 集群内部,使得集群内的服务可以像调用集群内的服务一样调用这些外部服务。

1.4 Service使用

1.4.1 环境准备

  • 创建三个Pod

[root@K8s-master ~]# vim deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80
​
[root@K8s-master ~]# kubectl apply -f deployment.yaml 
deployment.apps/pc-deployment created
​
[root@K8s-master ~]# kubectl get pod -n test -o wide
NAME                             READY   STATUS    RESTARTS   AGE    IP           NODE          NOMINATED NODE   READINESS GATES
pc-deployment-6769786c4c-62d94   1/1     Running   0          3m1s   10.244.2.2   k8s-node-02   <none>           <none>
pc-deployment-6769786c4c-fv6jj   1/1     Running   0          3m1s   10.244.2.3   k8s-node-02   <none>           <none>
pc-deployment-6769786c4c-qn9ls   1/1     Running   0          3m1s   10.244.1.4   k8s-node-01   <none>           <none>
​
[root@K8s-master ~]# kubectl get pod -n test --show-labels
NAME                             READY   STATUS    RESTARTS   AGE     LABELS
pc-deployment-6769786c4c-62d94   1/1     Running   0          3m20s   app=nginx-pod,pod-template-hash=6769786c4c
pc-deployment-6769786c4c-fv6jj   1/1     Running   0          3m20s   app=nginx-pod,pod-template-hash=6769786c4c
pc-deployment-6769786c4c-qn9ls   1/1     Running   0          3m20s   app=nginx-pod,pod-template-hash=6769786c4c
​
​
# 为了方便后面的测试,修改下三台nginx的index.html页面(三台修改的IP地址不一致)
[root@K8s-master ~]# kubectl exec -it pc-deployment-6769786c4c-62d94 -n test /bin/sh
# echo "`hostname -I` web-01" > /usr/share/nginx/html/index.html
# exit
​
[root@K8s-master ~]# kubectl exec -it pc-deployment-6769786c4c-fv6jj -n test /bin/sh
# echo "`hostname -I` web-02" > /usr/share/nginx/html/index.html           
# exit
​
[root@K8s-master ~]# kubectl exec -it pc-deployment-6769786c4c-qn9ls -n test /bin/sh
# echo "`hostname -I` web-03" > /usr/share/nginx/html/index.html
# exit
​
[root@K8s-master ~]# curl 10.244.2.2
10.244.2.2  web-01
[root@K8s-master ~]# curl 10.244.2.3
10.244.2.3  web-02
[root@K8s-master ~]# curl 10.244.1.4
10.244.1.4  web-03

1.4.2 ClusterIP类型的Service

  • ClusterIP 类型的 Service 是 Kubernetes 中最基本的服务之一,它提供了一种稳定的、只限于集群内部访问的方式。以下是 ClusterIP 类型 Service 的一些关键特点:

    • 虚拟 IP 地址:ClusterIP 类型的 Service 会被分配一个虚拟的 IP 地址(Cluster IP),这个 IP 地址在 Service 的整个生命周期中保持不变。

    • 集群内部通信:Pods 可以通过这个固定的 Cluster IP 来访问 Service,从而实现集群内部的服务发现和负载均衡,而无需关心后端 Pods 的具体 IP 地址。

    • 不对外公开:ClusterIP 类型的 Service 不会被分配外部可访问的 IP 地址,因此它只能从集群内部访问,不能从集群外部直接访问。

    • 负载均衡:Kubernetes 会自动为 ClusterIP 类型的 Service 提供简单的负载均衡,将请求分发到后端的多个 Pods 上。

    • 会话亲和性:可以通过设置 sessionAffinity 属性来控制会话亲和性,确保来自同一客户端的请求始终被路由到同一个后端 Pod。

    • DNS 解析:在集群内部,可以通过 Service 名称进行 DNS 解析,解析结果为分配给该 Service 的 Cluster IP。

    • 适用于内部服务:ClusterIP 类型的 Service 非常适合用于需要在集群内部通信的内部服务,如数据库、缓存服务等。

[root@K8s-master ~]# vim service-clusterip.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
  namespace: test
spec:
  selector:
    app: nginx-pod
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80
​
[root@K8s-master ~]# kubectl apply -f service-clusterip.yaml 
service/svc-clusterip created
​
[root@K8s-master ~]# kubectl get svc,pod -n test
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/svc-clusterip   ClusterIP   10.110.170.62   <none>        80/TCP    78s
​
NAME                                 READY   STATUS    RESTARTS   AGE
pod/pc-deployment-6769786c4c-62d94   1/1     Running   0          5m48s
pod/pc-deployment-6769786c4c-fv6jj   1/1     Running   0          5m48s
pod/pc-deployment-6769786c4c-qn9ls   1/1     Running   0          5m48s
​
[root@K8s-master ~]# kubectl describe svc svc-clusterip -n test
Name:              svc-clusterip
Namespace:         test
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.110.170.62
IPs:               10.110.170.62
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.4:80,10.244.2.2:80,10.244.2.3:80
Session Affinity:  None
Events:            <none>
​
#访问ClusterIP
[root@K8s-master ~]# for ((i=1;i<=6;i++)) do  curl 10.110.170.62; done  #集群内部访问(只能再集群内部fan
10.244.2.3  web-02
10.244.2.2  web-01
10.244.1.4  web-03
10.244.2.3  web-02
10.244.2.2  web-01
10.244.1.4  web-03
​
[root@K8s-master ~]# ipvsadm -Ln | grep -A3  10.110.170.99:80  #默认负载均衡算法为轮询
TCP  10.110.170.62:80 rr
  -> 10.244.2.3:80                Masq    1      0          0         
  -> 10.244.2.2:80                Masq    1      0          0         
  -> 10.244.1.4:80                Masq    1      0          0   

1.4.3 Endpoint类型的Service

  • Endpoint是kubernetes中的一个资源对象,存储在etcd中,用来记录一个service对应的所有pod的访问地址,它是根据service配置文件中selector描述产生的。

  • 一个Service由一组Pod组成,这些Pod通过Endpoints暴露出来,Endpoints是实现实际服务的端点集合。换句话说,service和pod之间的联系是通过endpoints实现的。

  • Endpoint 类型 Service 的一些特点:

    • 直接使用 Endpoints:Endpoint 类型的服务不提供标准的负载均衡器或代理,它允许客户端直接与 Endpoints 对象中的 Pod 进行通信。

    • 无需代理:与标准的 Service 类型不同,Endpoint 类型的服务不会创建 kube-proxy 监听的端点。这意味着,使用这种服务类型的客户端需要能够直接解析和连接到 Endpoints 对象中定义的 Pod IP 地址。

    • 适用于特定场景:这种服务类型适用于那些需要绕过 Kubernetes 服务发现机制的特定场景,例如,当您需要直接与 Pod 通信以进行调试或使用自定义的负载均衡器时。

    • 手动管理:使用 Endpoint 类型的服务时,您需要手动管理 Endpoints 对象,包括添加和删除端点。

    • 不提供服务发现:由于它不通过标准的 Kubernetes 服务发现机制,所以它不提供自动的服务发现功能。

    • 安全性:直接与 Pod 通信可能会带来安全风险,因为 Pod 的 IP 地址可能会变化,而且没有内置的负载均衡或健康检查机制。

    • 使用场景限制:Endpoint 类型的服务通常只在特定的用例中使用,比如当您需要直接控制网络流量或使用自定义的网络策略时。

image-20240514213245379

[root@K8s-master ~]# kubectl get endpoints -n test -o wide
NAME            ENDPOINTS                                   AGE
svc-clusterip   10.244.1.4:80,10.244.2.2:80,10.244.2.3:80   93s

在 Kubernetes 中,负载分发策略用于确定如何将传入的网络请求分配到后端的 Pod 上。以下是您提到的两种策略的详细说明:

  • 默认的 kube-proxy 策略

    • 随机(Random):kube-proxy 随机选择一个后端 Pod 来处理传入的请求。这种策略适用于大多数情况,因为它可以提供良好的负载均衡,并且实现起来相对简单。

    • 轮询(Round Robin):kube-proxy 按顺序将请求分发给后端的每个 Pod。当所有 Pod 都具有相同的处理能力时,这种策略可以确保每个 Pod 接收到相同数量的请求。

    除了随机和轮询,Kubernetes 还提供了其他几种负载分发策略,包括:

    • 最小连接数(Least Connections):选择当前活跃连接数最少的 Pod。

    • 源 IP(Source IP):确保来自同一个客户端 IP 的所有请求都发送到同一个 Pod,以保持会话的一致性。

  • 会话保持

    • Kubernetes 的服务可以配置会话保持,也称为会话亲和性或粘性会话。当启用会话保持时,来自同一个客户端的所有请求都将被路由到同一个后端 Pod,直到该会话结束。

    • 这种策略对于需要保持用户会话状态的应用非常有用,例如购物车应用或需要用户登录信息的应用。

    • 会话保持可以通过两种方式实现:

      • 客户端 IP:基于客户端的 IP 地址进行会话保持,确保来自同一 IP 的请求总是路由到同一个 Pod。

      • Cookie 基于会话:kube-proxy 可以生成一个特殊的哈希值,存储在客户端的 Cookie 中,以确保来自同一个 Cookie 的请求被路由到同一个 Pod。

      • 此模式可以使在spec中添加 sessionAffinity: ClientIP选项,表示Service将使用客户端IP地址来进行会话亲和性(session affinity)。当一个客户端请求连接到Service时,Service将根据客户端的IP地址将请求转发到一个稳定的Pod上。这意味着来自同一个客户端的所有请求在默认情况下都会被转发到同一个Pod上,直到该Pod不再可用。

[root@K8s-master ~]# kubectl delete -f service-clusterip.yaml 
service "svc-clusterip" deleted
[root@K8s-master ~]# vim service-clusterip.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
  namespace: test
spec:
  selector:
    app: nginx-pod
  clusterIP: 10.110.170.99    #可以指定IP
  type: ClusterIP
  sessionAffinity: ClientIP   #表示Service将使用客户端IP地址来进行会话亲和性
  ports:
    - port: 80
      targetPort: 80
​
[root@K8s-master ~]# kubectl apply -f service-clusterip.yaml 
service/svc-clusterip created
​
[root@K8s-master ~]# kubectl describe service/svc-clusterip -n test
Name:              svc-clusterip
Namespace:         test
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.110.170.99
IPs:               10.110.170.99
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.4:80,10.244.2.2:80,10.244.2.3:80
Session Affinity:  ClientIP
Events:            <none>
​
[root@K8s-master ~]# ipvsadm -Ln | grep -A3  10.110.170.99:80
TCP  10.110.170.99:80 rr persistent 10800   #会话保持,在10800秒内始终由最稳定的一台提供访问
  -> 10.244.1.4:80                Masq    1      0          0         
  -> 10.244.2.2:80                Masq    1      0          0         
  -> 10.244.2.3:80                Masq    1      0          0     
  
[root@K8s-master ~]# for ((i=1;i<=6;i++)) do  curl 10.110.170.99; done
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.3  web-02

1.4.4 HeadLiness类型的Service

  • 在某些场景中,开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。

  • 在 Kubernetes 中,存在一种不分配 Cluster IP 的 Service 类型,称为 "Headless Service"。

  • Headless Service 的特点如下:

    • 不分配 Cluster IP:与标准的 ClusterIP 类型 Service 不同,Headless Service 不会为服务分配一个虚拟 IP 地址。

    • 通过域名访问:Pods 可以通过 Service 的 DNS 名称直接访问到后端的 Pods。由于没有 Cluster IP,客户端不能直接通过一个固定的 IP 地址来访问服务,而是通过 DNS 解析来获取后端 Pods 的实际 IP 地址。

    • 自定义负载均衡:开发者可以自由地实现自己的负载均衡策略,而不是依赖 Kubernetes 提供的内置负载均衡。

    • DNS 解析:Kubernetes 会为每个后端 Pod 创建一个 DNS 记录。这意味着通过 DNS 查询,客户端可以获取到后端所有 Pod 的 IP 地址。

    • 适用于无头服务:Headless Service 特别适合于那些需要直接与 Pod 通信的场景,例如,当使用 StatefulSets 部署具有唯一身份的 Pods 时。

[root@K8s-master ~]# vim service-headliness.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: svc-clusterip
  namespace: test
spec:
  selector:
    app: nginx-pod
  clusterIP: None   #这里IP设为None
  type: ClusterIP
  sessionAffinity: ClientIP
  ports:
    - port: 80
      targetPort: 80
​
[root@K8s-master ~]# kubectl apply -f service-headliness.yaml 
service/svc-clusterip created
[root@K8s-master ~]# kubectl describe service/svc-clusterip -n test  #这里集群IP为None
Name:              svc-clusterip
Namespace:         test
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                None
IPs:               None
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.4:80,10.244.2.2:80,10.244.2.3:80
Session Affinity:  ClientIP
Events:            <none>
​
# 查看域名解析
[root@K8s-master ~]# kubectl exec -it pc-deployment-6769786c4c-62d94 -n test /bin/bash
root@pc-deployment-6769786c4c-62d94:/# cat /etc/resolv.conf 
search test.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
​
[root@K8s-master ~]# nslookup svc-clusterip.test.svc.cluster.local 10.96.0.10
Server:         10.96.0.10
Address:        10.96.0.10#53
​
Name:   svc-clusterip.test.svc.cluster.local
Address: 10.244.2.2
Name:   svc-clusterip.test.svc.cluster.local
Address: 10.244.2.3
Name:   svc-clusterip.test.svc.cluster.local
Address: 10.244.1.4
​
[root@K8s-master ~]# sed -i 's/^nameserver/#nameserver/' /etc/resolv.conf
[root@K8s-master ~]# echo 'nameserver 10.96.0.10' >> /etc/resolv.conf   #指定DNS
​
[root@K8s-master ~]# for ((i=1;i<=6;i++)) do  curl svc-clusterip.test.svc.cluster.local; done
10.244.1.4  web-03
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.3  web-02
10.244.2.2  web-01

1.4.5 NodePort类型的Service

  • 之前的样例中,创建的Service的ip地址只有集群内部才可以访问,如果希望将Service暴露给集群外部使用,那么就要使用到另外一种类型的Service,称为NodePort类型。NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过 NodeIp: NodePort 来访问Service了。

  • NodePort 类型的 Service 是 Kubernetes 中用于将服务暴露给集群外部的一种方式。下面是 NodePort 类型 Service 的一些关键点:

    • 端口映射:NodePort 类型的 Service 会在集群的所有节点上打开一个静态端口(NodePort),这个端口范围通常是 30000-32767。这个端口将被映射到 Service 所代理的后端 Pods 的端口上。

    • 通过节点 IP 访问:外部用户可以通过 <NodeIP>:<NodePort> 的形式访问到这个 Service。这里的 NodeIP 是集群中任何节点的 IP 地址,而 NodePort 是 Service 映射的端口号。

    • 无需额外配置:与 LoadBalancer 类型相比,NodePort 不需要云服务商提供的额外配置或支持,因此它在不支持 LoadBalancer 的环境中非常有用。

    • 安全性考虑:由于 NodePort 会在所有节点上开放端口,因此需要考虑到安全性问题。通常建议使用防火墙规则来限制访问,只允许特定的 IP 地址访问这些端口。

    • 适用于简单的外部访问:NodePort 适合于简单的外部访问需求,但对于生产环境,通常推荐使用 LoadBalancer 或 Ingress,因为它们提供了更好的性能、安全性和高级路由功能。

image-20240516112136442

[root@K8s-master ~]# vim service-nodeport.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: svc-nodeport
  namespace: test
spec:
  selector:
    app: nginx-pod
  type: NodePort
  ports:
    - port: 80     # Service 在所有节点上监听的端口号
      nodePort: 32522  # 默认的取值范围是:30000-32767, 如果不指定,会默认分配
      targetPort: 80  # 后端 Pod 监听的端口号
​
[root@K8s-master ~]# kubectl apply -f service-nodeport.yaml 
service/svc-nodeport created
​
[root@K8s-master ~]# kubectl get svc,pod -n test -o wide
NAME                   TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service/svc-nodeport   NodePort   10.102.4.48   <none>        80:32522/TCP   5s    app=nginx-pod
​
NAME                                 READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
pod/pc-deployment-6769786c4c-62d94   1/1     Running   0          74m   10.244.2.2   k8s-node-02   <none>           <none>
pod/pc-deployment-6769786c4c-fv6jj   1/1     Running   0          74m   10.244.2.3   k8s-node-02   <none>           <none>
pod/pc-deployment-6769786c4c-qn9ls   1/1     Running   0          74m   10.244.1.4   k8s-node-01   <none>           <none>
  • 外部访问测试

image-20240516113258620

[root@K8s-master ~]# ipvsadm -Ln | grep -A3 32522
TCP  192.168.110.21:32522 rr
  -> 10.244.1.4:80                Masq    1      0          0         
  -> 10.244.2.2:80                Masq    1      0          1         
  -> 10.244.2.3:80                Masq    1      0          1         
--
TCP  10.244.0.0:32522 rr
  -> 10.244.1.4:80                Masq    1      0          0         
  -> 10.244.2.2:80                Masq    1      0          0         
  -> 10.244.2.3:80                Masq    1      0          0       

1.4.6 LoadBalancer类型的Service

  • LoadBalancer和NodePort很相似,目的都是向外部暴露一个端口,区别在于LoadBalancer会在集群的外部再来做一个负载均衡设备,而这个设备需要外部环境支持的,外部服务发送到这个设备上的请求,会被设备负载之后转发到集群中。

  • LoadBalancer 类型的 Service 是 Kubernetes 中用于将服务暴露给外部世界的一种方式,它通常需要云服务商的支持。以下是 LoadBalancer 类型 Service 的一些关键特点:

    • 外部负载均衡器:LoadBalancer 类型的 Service 会利用云服务商提供的外部负载均衡器(如 AWS ELB、Azure Load Balancer 或 GCP Load Balancer)来暴露服务。

    • 自动配置:Kubernetes 会自动配置负载均衡器,将外部请求路由到后端的 Pods。

    • 外部 IP 地址:LoadBalancer 会提供一个或多个外部可访问的 IP 地址,这些 IP 地址可以是公网 IP 或云服务商的内部 IP。

    • 自动扩展:许多云服务商的负载均衡器支持自动扩展,这意味着它们可以根据流量自动调整后端 Pods 的数量。

    • 安全性和性能:LoadBalancer 提供了额外的安全和性能优势,因为它们通常包括内置的防火墙规则、SSL 终止和 DDoS 防护。

    • 适用于生产环境:由于其高级特性和性能,LoadBalancer 类型的 Service 非常适合生产环境。

    • 可能涉及费用:使用云服务商的负载均衡器可能会产生额外的费用。

image-20240516114217789

1.4.6.1 开源 Kubernetes 负载均衡器
1. MetalLB
  • 介绍:MetalLB 是一个为 Kubernetes 集群设计的负载均衡器,特别适用于裸金属环境。它通过在集群中运行的组件来监控服务对象的变化,为 LoadBalancer 类型的服务提供实现。10^

  • 工作原理:MetalLB 通过标准的路由协议(如 ARP、NDP 或 BGP)来实现负载均衡。它有两种工作模式:Layer2 模式和 BGP 模式。在 Layer2 模式下,MetalLB 会在集群中的一个节点上处理所有服务 IP 的流量,而在 BGP 模式下,它通过与网络路由器建立 BGP 会话来实现真正的负载均衡。2^11^

  • 特点:MetalLB 易于部署,支持自动和静态 IP 地址分配,并且可以与 kube-proxy 紧密集成。

2. PureLB
  • 介绍:PureLB 是另一种负载均衡器,它使用自定义资源(CRD)进行配置,由两部分组成:分配器负责分配 IP 地址,而 lbnodeagent 负责在所有节点上配置节点网络。

  • 工作原理:PureLB 的 Layer2 工作模式特点在于它会在 Kubernetes 集群的受管节点上创建一个虚拟网卡(如 kube-lb0),并通过任意路由协议实现 ECMP(等价多路径),以进行负载均衡和流量分发。

  • 特点:PureLB 可以根据单个 VIP 选择节点,并将多个 VIP 分散到不同节点,以此来避免节点负载失衡。

3. OpenELB
  • 介绍:OpenELB 是由 KubeSphere 社区发起的云原生负载均衡器,现已成为 CNCF 沙箱项目。它适用于物理机和虚拟化环境,利用 BGP 和 ECMP 实现高性能和高可用性。

  • 工作原理:OpenELB 支持两种工作模式:Layer2 模式和 BGP 模式。在 BGP 模式下,它通过与集群的边界路由器建立 BGP 连接来实现高效的流量调度和管理。OpenELB 还支持 ECMP,允许在多条路径之间进行负载均衡和流量分发。6^

  • 特点:OpenELB 易于与 Kubernetes 集成,提供了丰富的监控和日志功能,支持动态服务发现、流量调度和安全防护等高级特性。

特性/项目MetalLBPureLBOpenELB
介绍适用于裸金属环境的负载均衡器使用 CRD 配置的负载均衡器云原生负载均衡器,CNCF 沙箱项目
支持环境裸金属、云环境裸金属、云环境物理机、虚拟化环境
工作原理ARP/NDP/BGP任意路由协议BGP/ECMP
Layer2 模式支持支持支持
BGP 模式支持不适用支持
IP 地址分配自动和静态不明确动态服务发现
节点负载均衡不适用支持支持
与 kube-proxy 集成紧密集成不明确支持
监控和日志基本不明确丰富
安全性基本不明确支持
高级特性基本不明确高级特性支持
社区活跃度
1.4.6.2 LoadBalancer 类型的 Service 的定义示例可能如下:
apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  type: LoadBalancer
  ports:
    - port: 80  # Service 的端口
      targetPort: 8080  # 后端 Pod 的端口
  selector:
    app: my-app  # 选择具有该标签的 Pods

1.4.7 ExternalName类型的Service

  • ExternalName类型的Service用于引入集群外部的服务,它通过 externalName 属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。

  • ExternalName 类型的 Service 在 Kubernetes 中用于将一个 DNS 名称映射到一个外部的服务,而不需要在集群内创建任何代理或负载均衡器。这种方式非常适合于将集群内部的应用程序指向外部的数据库、API 服务或其他不在 Kubernetes 管理下的资源。

  • ExternalName 类型 Service 的一些关键特点:

    • 无 Cluster IP:ExternalName 类型的 Service 不分配 Cluster IP。

    • DNS 解析:在 Kubernetes 集群内部,当对这种类型的 Service 进行 DNS 解析时,将直接返回 externalName 字段指定的值。

    • 简单配置:只需要指定一个 externalName 和一个可选的 port

    • 直接访问:Pods 可以直接通过 Service 名称访问外部服务,就像访问集群内的其他服务一样。

    • 适用于外部资源:适合于引用那些不在 Kubernetes 控制范围内的外部服务。

    • 无需特殊网络配置:不需要任何特殊的网络配置或云服务提供商支持。

image-20240516114724022

  • 配置实例

apiVersion: v1
kind: Service
metadata:
  name: my-external-service
spec:
  type: ExternalName
  externalName: api.example.com  # 外部服务的地址
  ports:
    - port: 443  # 外部服务监听的端口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/632253.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文件批量改名神器:轻松实现导入文件筛选与批量重命名,提升文件管理效率新体验!

电脑中的文件堆积如山&#xff0c;你是否曾为寻找某个特定文件而头疼不已&#xff1f;是否曾因为文件命名不规范而错失重要信息&#xff1f;别担心&#xff0c;现在有了这款文件批量改名神器&#xff0c;一切问题都将迎刃而解&#xff01; 第一步&#xff0c;我们打开需要改名文…

【ONE·基础算法 || 队列(宽搜运用) 优先级队列(堆运用) 】

总言 主要内容&#xff1a;编程题举例&#xff0c;熟悉理解宽搜类题型&#xff0c;队列、堆此类STL容器使用。       文章目录 总言1、 宽搜2、N 叉树的层序遍历&#xff08;medium&#xff09;2.1、题解 3、二叉树的锯齿形层序遍历&#xff08;medium&#xff09;3.1、题解…

【永洪BI】精确不同值计数

一、功能演示 二、使用说明 1、 功能简介 精确不同值计数&#xff0c;即统计所有数据行中不同数据值的总数量&#xff0c;数据值相同时只计算一次&#xff0c;如果存在维度字段&#xff0c;会按照不同类别分别计数。 2、 应用场景 想要统计数据中不同值出现的次数时可以使用…

Metasploit基本命令

1. 开启控制台 命令&#xff1a; msfconsole2. 搜索模块 命令&#xff1a; search ms17-010 # 模块名这里以搜索 ms17-010 为例&#xff0c; auxiliary 开头的为测试模块&#xff0c;也就是 POC&#xff0c;看看存不存在漏洞&#xff0c; exploit 开头的为攻击模块 3. 调…

DCMM(数据管理能力成熟度模型)对企业的价值

随着大数据时代的来临&#xff0c;数据已成为企业发展的重要驱动力。为了有效地管理和利用数据&#xff0c;企业需要建立一套完善的数据管理体系&#xff0c;而DCMM&#xff08;数据管理能力成熟度模型&#xff09;正是这样一个帮助企业构建和优化数据管理能力的框架。 DCMM结构…

芯片固定环氧胶有什么优点?

芯片固定环氧胶有什么优点&#xff1f; 芯片固定环氧胶在电子封装和芯片固定应用中具有多种显著优点&#xff0c;以下是其中的一些关键优势&#xff1a; 高粘接强度&#xff1a;环氧胶能够牢固地粘合芯片和基板&#xff0c;提供出色的粘接强度&#xff0c;确保芯片在各种环境条…

webpack优化构建速度示例-IgnorePlugin:

IgnorePlugin是webpack的一个内置插件&#xff0c;允许你忽略某些特定的模块或文件 webpack.config.jsconst config {entry: ./src/index.js,output: {filename: main.js},mode: development, }module.exports config;src/index.js import moment from moment console.log(mo…

剑指Offer打卡day34——AcWing 66. 两个链表的第一个公共结点

AcWing 66. 两个链表的第一个公共结点 暴力做法&#xff0c;两层for循环 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ class Solutio…

LeetCode109:组合总和Ⅳ

题目描述 给你一个由 不同 整数组成的数组 nums &#xff0c;和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 解题思想 使用完全背包 代码 /*dp[i]&#xff1a;表示装满容量为i的背包有dp[i]种方…

OpenHarmony上移植memtester

1. 下载源码&#xff1a; wget https://pyropus.ca./software/memtester/old-versions/memtester-4.6.0.tar.gz 2. 解压并指定交叉编译方式 解压 tar -xvf memtester-4.6.0.tar.gz 修改conf-cc和conf-ld&#xff0c;指定交叉编译方式 conf-cc conf-ld 3. 编译 直接运行m…

【问题实操】银河高级服务器操作系统实例分享,三台服务器宕机解决方式

1.服务器环境以及配置 物理机/虚拟机/云/容器 物理机 外网/私有网络/无网络 私有网络 处理器&#xff1a; Hygon C86 7265 24-core Processor 2 of 2 CPU sockets populated, 24 cores/48 threads per CPU 48 total cores, 96 total threads 内存&#xff1a; 768 GiB …

1W、2W 3KVAC隔离 宽电压输入 交直两用AC/DC 电源模块 ——TP01(02)AZ 系列

TP01(02)AZ为客户提供一款超小体积模块式开关电源&#xff0c;该系列模块电源输出功率为1W、2W&#xff0c;具有极低的空载损耗&#xff0c;低漏电流仅0.1mA&#xff0c;小体积&#xff0c;隔离耐压高达3KV等特点。产品安全可靠&#xff0c;EMC 性能好&#xff0c;EMC 及安全规…

哪个品牌的开放式耳机性价比高?五大高口碑优质爆款直入

最近几年来耳机音频市场上的质量问题层出不穷&#xff0c;就连最近火爆的开放式耳机也未能幸免。这是由于很多企业过分强调智能化、注重外形设计等&#xff0c;而忽视了作为一款开放式耳机最基本的音质和舒适性。很多品牌使用劣质材料制作开放式耳机产品&#xff0c;从而存在着…

英睿达硬盘数据恢复方法:从丢失到找回的详细指南

在数字化时代&#xff0c;硬盘作为我们存储重要数据的关键设备&#xff0c;承载着大量的个人、工作甚至商业信息。然而&#xff0c;无论是由于意外删除、格式化、病毒感染还是硬件故障&#xff0c;硬盘数据丢失的情况时有发生。英睿达硬盘作为市场上的知名品牌&#xff0c;其数…

基于yolov8+flask搭建一个web版本的网页模型预测系统

测试环境&#xff1a; anaconda3python3.8 torch1.9.0cu111 ultralytics8.2.2 首先我们将训练好的权重放在weights目录下面 并将名字改成yolov8n.pt&#xff0c;如果不想改可以在代码app.py都把路径改过来即可。然后我们打开 python app.py之后看到 我们点击选择文件支持图…

在PDF中使用Paragraph进行文本段落的处理

上一篇文章中我们使用itxtpdf库中的方法&#xff0c;绘制了一个固定表格与一个动态表格。如果你想在PDF中加入文字该怎么办呢。可以使用本文推荐的Paragraph这个类去实现&#xff0c;效果如下&#xff1a; 我在PDF中插入了一个工作流的审批流程。具体实现呢还是使用itextpdf库中…

0.98T优于10米高程DEM数据

我们在《全球30米100%水陆覆盖高程》一文中&#xff0c;为大家分享了全球100%覆盖&#xff0c;且包括海底高程的30米DEM数据。 该数据虽然全球无死角覆盖&#xff0c;但分辨率只有30米。 这里&#xff0c;再为大家分享一个优于10米的高程数据&#xff0c;但目前仅覆盖全国范围…

CSS学习笔记之中级教程(二)

CSS学习笔记之中级教程&#xff08;一&#xff09; 6、CSS 布局 - display: inline-block 与 display: inline 相比&#xff0c;主要区别在于 display: inline-block 允许在元素上设置宽度和高度。 同样&#xff0c;如果设置了 display: inline-block&#xff0c;将保留上下外…

Node.js基础:从入门到实战

初识 Node.js 与内置模块 &#xff08;初识&#xff09; 1、知道什么是node.js 2、知道node.js可以做什么 3、node.js 中js的组成部分 &#xff08;内置模块&#xff09; 4、用 fs 模块读写操作文件 5、使用 path 模块处理路径 6、使用http 模块写一个基本的web服务器 初识 N…

二.PVE创建 Ubuntu CT

二&#xff0e;PVE创建 Ubuntu CT 浏览器地址栏输入访问pve系统的网址&#xff0c;利用web端进行管理。注意进入pve系统时默认显示的有访问地址。本步骤的web访问地址为&#xff1a;https://192.168.1.102:8006。 出现该页面&#xff0c;选择继续前往。 进入管理页面后&…