【云原生】Kubernetes之ClusterIP Service、NodePort Service

Kubernetes与容器一起工作,以pod的形式管理。我们可以使用pod对象创建单个pod,也可以使用replicaset或deployment对象创建多个pod。无论哪种方式,最终我们都会得到一组pod,并且在某个时刻我们需要访问这些pod。

  • 在集群网络中,容器可以通过使用本地主机通信来与同一个pod中的其他容器进行通信。容器的行为就好像它们在同一个主机上一样,这没有任何问题!

  • 当涉及到pod之间的通信时,IP地址似乎是解决方案。因为每个pod都有一个唯一的集群范围的IP地址。然而,这种通信方式存在一个问题。当pod失败或我们缩减副本时,pod会被终止。当然,被终止的pod会被新的pod取代,但新的pod会有一个新的IP地址。那么我们如何跟踪所有这些新的IP地址呢?

  • Kubernetes的Service对象提供了解决这个问题的方法。当我们创建一个Service对象时,它会有一个虚拟的IP地址,只要Service还存在,该IP地址就保持不变。

  • 通过使用选择器,我们可以将pod与Service关联起来,所有的pod可以通过该Service相互通信,无需处理pod的IP地址变更。因此,终止一个pod并用新的IP地址重新创建一个pod都不会影响通信。简而言之,Service为在集群中统一工作的Pod提供网络连接性。

Kubernetes的Service对象还提供了一种负载均衡机制,kube-proxy将连接负载均衡到支持该Service的一组pod上。

ClusterIP

  • ClusterIP是Kubernetes中的默认服务类型。当创建一个服务时,如果省略了服务类型,它将默认为ClusterIP。

  • 官方文档将ClusterIP定义为"在集群内部IP上公开服务。选择此值使服务仅能从集群内部访问。"

  • 如果您不需要从集群外部访问您的pod,您可以使用这种类型的服务。ClusterIP将为每个Service分配一个唯一的虚拟IP地址,只能从集群内部访问。这意味着Service只能通过集群内部的其他pod来访问,无法从集群外部进行访问。这种类型的服务通常用于内部服务或其他Service的后端。

  • 要创建一个ClusterIP服务,您可以创建一个YAML文件,指定Service的名称、选择器和端口映射。然后使用kubectl命令将该YAML文件应用到Kubernetes集群中。这样就会创建一个ClusterIP服务,并分配一个唯一的虚拟IP地址。

xml 复制代码
➜  day1 kubectl create -f demo_cluster_ip.yaml 
replicaset.apps/my-kubia-rs-1 created
service/kubia-service created
➜  day1 kubectl get svc,rs,pod -o wide -L app
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE    SELECTOR    APP
service/bar-service     ClusterIP   10.96.10.193    <none>        8080/TCP   9d     app=bar     
service/foo-service     ClusterIP   10.96.113.198   <none>        8080/TCP   9d     app=foo     
service/kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP    9d     <none>      
service/kubia-service   ClusterIP   10.96.251.111   <none>        9696/TCP   111s   app=kubia   

NAME                                         DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES         SELECTOR                                APP
replicaset.apps/my-kubia-rs-1                3         3         3       111s    my-kubia-1   luksa/kubia    app=kubia                               
replicaset.apps/nginx-deployment-74b6b979f   3         3         3       5d22h   nginx        nginx:1.16.1   app=nginx,pod-template-hash=74b6b979f   nginx
replicaset.apps/nginx-deployment-cbdccf466   0         0         0       5d23h   nginx        nginx:1.14.2   app=nginx,pod-template-hash=cbdccf466   nginx

NAME                                   READY   STATUS    RESTARTS   AGE     IP            NODE                       NOMINATED NODE   READINESS GATES   APP
pod/bar-app                            1/1     Running   0          9d      10.244.3.14   my-k8s-cluster-3-worker    <none>           <none>            bar
pod/foo-app                            1/1     Running   0          9d      10.244.2.13   my-k8s-cluster-3-worker2   <none>           <none>            foo
pod/my-bootcamp-pod-2-annotation       1/1     Running   0          8d      10.244.1.14   my-k8s-cluster-3-worker3   <none>           <none>            
pod/my-bootcamp-pod-2-label            1/1     Running   0          8d      10.244.3.26   my-k8s-cluster-3-worker    <none>           <none>            
pod/my-kubia-rs-1-glvqr                1/1     Running   0          111s    10.244.3.29   my-k8s-cluster-3-worker    <none>           <none>            kubia
pod/my-kubia-rs-1-k5cws                1/1     Running   0          111s    10.244.1.17   my-k8s-cluster-3-worker3   <none>           <none>            kubia
pod/my-kubia-rs-1-rhk76                1/1     Running   0          111s    10.244.2.17   my-k8s-cluster-3-worker2   <none>           <none>            kubia
pod/nginx-deployment-74b6b979f-dcq8f   1/1     Running   0          5d22h   10.244.1.16   my-k8s-cluster-3-worker3   <none>           <none>            nginx
pod/nginx-deployment-74b6b979f-lb2tl   1/1     Running   0          5d22h   10.244.3.28   my-k8s-cluster-3-worker    <none>           <none>            nginx
pod/nginx-deployment-74b6b979f-vm9ww   1/1     Running   0          5d22h   10.244.2.16   my-k8s-cluster-3-worker2   <none>           <none>            nginx

现在我们尝试通过服务的IP、Port进行访问,效果如下所示。不难看出服务同时具有负载均衡的功能了

python 复制代码
  day1 kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
bar-service     ClusterIP   10.96.10.193    <none>        8080/TCP   9d
foo-service     ClusterIP   10.96.113.198   <none>        8080/TCP   9d
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP    9d
kubia-service   ClusterIP   10.96.251.111   <none>        9696/TCP   4m39s
➜  day1 kubectl get svc -o wide
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE     SELECTOR
bar-service     ClusterIP   10.96.10.193    <none>        8080/TCP   9d      app=bar
foo-service     ClusterIP   10.96.113.198   <none>        8080/TCP   9d      app=foo
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP    9d      <none>
kubia-service   ClusterIP   10.96.251.111   <none>        9696/TCP   4m46s   app=kubia
➜  day1 kubectl get pod        
NAME                               READY   STATUS    RESTARTS   AGE
bar-app                            1/1     Running   0          9d
foo-app                            1/1     Running   0          9d
my-bootcamp-pod-2-annotation       1/1     Running   0          8d
my-bootcamp-pod-2-label            1/1     Running   0          8d
my-kubia-rs-1-glvqr                1/1     Running   0          5m16s
my-kubia-rs-1-k5cws                1/1     Running   0          5m16s
my-kubia-rs-1-rhk76                1/1     Running   0          5m16s
nginx-deployment-74b6b979f-dcq8f   1/1     Running   0          5d23h
nginx-deployment-74b6b979f-lb2tl   1/1     Running   0          5d23h
nginx-deployment-74b6b979f-vm9ww   1/1     Running   0          5d23h
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.251.111:9696
You've hit my-kubia-rs-1-glvqr
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.251.111:9696
You've hit my-kubia-rs-1-rhk76
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.251.111:9696
You've hit my-kubia-rs-1-k5cws
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.251.111:9696
You've hit my-kubia-rs-1-k5cws
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.251.111:9696
You've hit my-kubia-rs-1-rhk76
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.251.111:9696
You've hit my-kubia-rs-1-rhk76
➜  day1 

此外,还可以通过sessionAffinity配置服务的会话亲和性。当配置为ClientIP时,其可以保证将来自相同客户端IP的请求总是转发至同一个Pod中

yaml 复制代码
apiVersion: v1
kind: Service
spec:
  # 基于客户端IP的会话亲和性
  sessionAffinity: ClientIP

需要注意的是,当Service暴露多个端口时,需要给每个端口指定名字。如下所示

yaml 复制代码
apiVersion: v1
kind: Service
spec:
  ports:
    - name: http-port #名为http-port的端口转发
      port: 80  # 服务监听端口
      targetPort: 3080  # 服务将请求转发到的目标端口
    - name: https-port #名为https-port的端口转发
      port: 443  # 服务监听端口
      targetPort: 3443  # 服务将请求转发到的目标端口
    - name: test-port #名为test-port的端口转发
      port: 69  # 服务监听端口
      targetPort: 3069  # 服务将请求转发到的目标端口

NodePort

NodePort是一种服务类型,解决了ClusterIP无法从集群外部访问Pod的问题。

  • 使用NodePort,您可以定义要公开的特定端口号,用户可以通过该端口号访问连接到NodePort类型服务的Pod中的应用程序。默认情况下,NodePort使用30000到32767之间的端口范围。您可以指定特定的端口号,也可以让服务从该范围内分配一个随机的端口号。这样,用户就可以通过集群节点上的该端口号与应用程序进行通信。

  • 它允许外部流量通过节点的IP地址和指定的端口访问服务。与ClusterIP不同,NodePort类型的服务可以从集群外部访问。

  • 要创建一个NodePort服务,您需要创建一个YAML文件,指定Service的名称、选择器、端口映射和NodePort。然后使用kubectl命令将该YAML文件应用到Kubernetes集群中。这样就会创建一个NodePort服务,并将指定的端口映射到每个节点的IP地址上。

  • NodePort类型的服务通常用于暴露集群内的服务到集群外部,但请注意,NodePort不提供负载均衡功能。如果您需要负载均衡,可以考虑使用LoadBalancer类型的服务或结合使用NodePort和外部负载均衡器来实现。

yaml 复制代码
# API组、版本
apiVersion: apps/v1
# 资源类型
kind: ReplicaSet
metadata:
  # RS名称
  name: my-kubia-rs-1
spec:
  # 副本数量
  replicas: 3
  # 标签选择器
  selector:
    matchLabels:
      app: kubia
  # Pod 模板
  template:
    metadata:
      # 标签信息
      labels:
        app: kubia
    spec:
      # 容器信息
      containers:
        - name: my-kubia-1
          image: luksa/kubia
          # 仅用于展示容器所使用的端口
          ports:
            - containerPort: 8080
              protocol: TCP

---
# API组、版本
apiVersion: v1
# 资源类型
kind: Service
metadata:
  # 资源名称
  name: my-nodeport-service-1
spec:
  # Service类型
  type: NodePort
  selector:
    app: kubia
  ports:
    - port: 80 # 服务监听端口
      targetPort: 8080 # 服务将请求转发到Pod的目标端口
      # 在集群各节点所打开的端口, 使得可以通过集群中任一节点IP、nodePort端口号访问该服务
      nodePort: 30123

创建成功后如图所示

scss 复制代码
➜  day1 kubectl get pod -o wide     
NAME                               READY   STATUS    RESTARTS   AGE     IP            NODE                       NOMINATED NODE   READINESS GATES
bar-app                            1/1     Running   0          9d      10.244.3.14   my-k8s-cluster-3-worker    <none>           <none>
foo-app                            1/1     Running   0          9d      10.244.2.13   my-k8s-cluster-3-worker2   <none>           <none>
my-bootcamp-pod-2-annotation       1/1     Running   0          8d      10.244.1.14   my-k8s-cluster-3-worker3   <none>           <none>
my-bootcamp-pod-2-label            1/1     Running   0          8d      10.244.3.26   my-k8s-cluster-3-worker    <none>           <none>
my-kubia-rs-1-glvqr                1/1     Running   0          16m     10.244.3.29   my-k8s-cluster-3-worker    <none>           <none>
my-kubia-rs-1-k5cws                1/1     Running   0          16m     10.244.1.17   my-k8s-cluster-3-worker3   <none>           <none>
my-kubia-rs-1-rhk76                1/1     Running   0          16m     10.244.2.17   my-k8s-cluster-3-worker2   <none>           <none>
nginx-deployment-74b6b979f-dcq8f   1/1     Running   0          5d23h   10.244.1.16   my-k8s-cluster-3-worker3   <none>           <none>
nginx-deployment-74b6b979f-lb2tl   1/1     Running   0          5d23h   10.244.3.28   my-k8s-cluster-3-worker    <none>           <none>
nginx-deployment-74b6b979f-vm9ww   1/1     Running   0          5d23h   10.244.2.16   my-k8s-cluster-3-worker2   <none>           <none>
➜  day1 kubectl get svc -o wide
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE    SELECTOR
bar-service             ClusterIP   10.96.10.193    <none>        8080/TCP       9d     app=bar
foo-service             ClusterIP   10.96.113.198   <none>        8080/TCP       9d     app=foo
kubernetes              ClusterIP   10.96.0.1       <none>        443/TCP        9d     <none>
kubia-service           ClusterIP   10.96.251.111   <none>        9696/TCP       16m    app=kubia
my-nodeport-service-1   NodePort    10.96.59.99     <none>        80:30123/TCP   2m9s   app=kubia
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.59.99:80    
You've hit my-kubia-rs-1-rhk76
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.59.99:80
You've hit my-kubia-rs-1-glvqr
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.59.99:80
You've hit my-kubia-rs-1-glvqr
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.59.99:80
You've hit my-kubia-rs-1-rhk76
➜  day1 kubectl exec my-bootcamp-pod-2-label  -- curl -s 10.96.59.99:80
You've hit my-kubia-rs-1-rhk76

现在我们尝试通过集群节点IP、NodePort Service在节点上打开的端口来访问服务。

结论

总之,ClusterIP和NodePort是Kubernetes中常用的两种服务类型。ClusterIP仅在集群内部可访问,并为每个Service分配唯一的虚拟IP地址。NodePort允许从集群外部访问服务,通过节点的IP地址和指定的端口。

相关推荐
gb421528726 分钟前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶27 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
颜淡慕潇1 小时前
【K8S问题系列 |19 】如何解决 Pod 无法挂载 PVC问题
后端·云原生·容器·kubernetes
向前看-8 小时前
验证码机制
前端·后端
超爱吃士力架10 小时前
邀请逻辑
java·linux·后端
AskHarries12 小时前
Spring Cloud OpenFeign快速入门demo
spring boot·后端
isolusion13 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp13 小时前
Spring-AOP
java·后端·spring·spring-aop
TodoCoder14 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试