K8s新手系列之Service资源

打印 上一主题 下一主题

主题 1969|帖子 1969|积分 5907

概述

官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/
在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务举行访问。
为相识决这个问题,kubernetes提供了Service资源,Service会对提供同一个服务的多个pod举行聚合,并且提供一个统一的入口地址。通过访问Service的入口地址就能访问到后面的pod服务。

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

简单点说就是:Service可以实现pod的负载平衡和服务发现功能,为访问Pod提供了统一的访问入口。
Service的类型

Service的类型有四类:分别是以下四类
ClusterIP

这是svc默认的类型,是k8s集群内部分配的虚拟IP,实用于集群内部举行访问,外部访问不到,但是可以利用 Ingress 大概 Gateway API 来公开服务。创建svc时会自动关联endpoints资源。

NodePort

在ClusterIP基础之上,多添加了对所有Worker节点实现端口映射的功能。NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。

LoadBalancer

实现负载平衡的服务,主要应用场景是云厂商环境,它能够为服务提供外部可访问的 IP 地址。这种类型的服务通过云服务提供商的负载平衡器实现,允许外部流量进入集群中的 Pod。

ExternalName

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

Service的作用

服务发现与负载平衡


  • 服务发现:Kubernetes 中的 Pod 是动态创建和销毁的,它们的 IP 地址也是动态分配的。Service 为一组具有雷同功能的 Pod 提供了一个固定的虚拟 IP 地址和 DNS 名称。其他组件可以通过这个固定的地址来访问这些 Pod,而无需关心详细 Pod 的 IP 地址变化。
  • 负载平衡:Service 可以将流量均匀地分发到后端的多个 Pod 上,实现负载平衡的功能。这样可以确保应用能够处置惩罚大量的并发哀求,提高系统的性能和可靠性。例如,一个 Web 应用可能由多个 Pod 组成,通过 Service 可以将用户的哀求平衡地分配到这些 Pod 上,克制单个 Pod 因负载过高而出现性能问题。
应用解耦


  • 解耦客户端与服务端:Service 使得客户端与后端服务的 Pod 之间实现相识耦。客户端只需要知道 Service 的地址,而不需要相识后端详细有哪些 Pod 以及它们的状态。当后端 Pod 发生变化(如扩容、缩容或升级)时,客户端无需举行任何修改,仍然可以通过 Service 正常访问服务。
  • 支持微服务架构:在微服务架构中,不同的微服务之间通常需要相互调用。Service 为每个微服务提供了独立的访问入口,使得各个微服务可以独立地举行部署、扩展和升级,而不会影响到其他微服务。这种解耦方式提高了整个系统的可维护性和可扩展性。
提供稳定的网络端点


  • 外部访问入口:对于需要对外提供服务的应用,Service 可以作为外部访问的入口点。通过将 Service 设置为 NodePort 类型或 LoadBalancer 类型,可以将服务暴露到集群外部,让外部用户能够访问到 Kubernetes 集群中的应用。
  • 内部网络隔离:在 Kubernetes 集群内部,Service 还可以用于实现网络隔离。通过定义不同的 Service 和相应的访问规则,可以限制哪些 Pod 能够访问特定的服务,从而提高集群的安全性和稳定性。
方便应用管理与维护


  • 统一管理:通过 Service,可以对一组相关的 Pod 举行统一的管理和配置。例如,可以通过 Service 来设置访问策略、监控指标收集等,而无需对每个 Pod 单独举行配置。
  • 简化运维操纵:当需要对应用举行升级、回滚或其他运维操纵时,只需要对 Service 举行相应的配置修改,Kubernetes 会自动根据 Service 的定义来调整后端 Pod 的状态,从而简化了运维操纵的复杂度。
Service的工作原理

Service 通过 Label Selector 来选择对应的 Pods,当 Service 吸收到哀求时,它会根据负载平衡算法将哀求转发到后端的某个 Pod 上。K8s 中的 kube - proxy 组件负责在节点上维护网络规则,确保 Service 能够精确地将流量路由到后端 Pods。
Service的资源配置文件
  1. apiVersion: v1          # API版本,Service属于核心API组,固定使用v1
  2. kind: Service           # 资源类型为Service
  3. metadata:               # 元数据,定义Service的标识信息
  4.   name: my-service      # Service名称,必须符合DNS标签规范
  5.   namespace: default    # 命名空间,默认为default
  6.   labels:               # 标签,用于组织和选择资源
  7.     app: my-app
  8.     tier: backend
  9.   annotations:          # 注解,用于存储非标识性元数据(如配置信息)
  10.     service.beta.kubernetes.io/aws-load-balancer-type: nlb
  11. spec:                   # 服务规范,定义Service的行为和关联的Pod
  12.   type: ClusterIP       # Service类型(ClusterIP/NodePort/LoadBalancer/ExternalName)
  13.   
  14.   selector:             # 标签选择器,用于确定哪些Pod属于此服务
  15.     app: my-app
  16.     tier: backend
  17.   
  18.   ports:                # 端口配置,定义服务如何接收流量
  19.   - name: http          # 端口名称,必须符合DNS标签规范
  20.     protocol: TCP       # 协议类型,支持TCP/UDP/SCTP,默认为TCP
  21.     port: 80            # 服务暴露的端口(集群内部访问使用)
  22.     targetPort: 8080    # 后端Pod接收流量的端口
  23.     nodePort: 30080     # NodePort类型时,节点上暴露的端口(30000-32767)
  24.   
  25.   externalIPs:          # 外部IP列表,允许通过这些IP访问服务
  26.   - 80.11.12.10
  27.   
  28.   sessionAffinity: None # 会话亲和性(None/ClientIP),默认为None
  29.   sessionAffinityConfig:  # 会话亲和性配置(仅当sessionAffinity为ClientIP时有效)
  30.     clientIP:
  31.       timeoutSeconds: 10800  # 客户端IP会话保持时间(秒)
  32.   
  33.   loadBalancerIP: 70.42.103.12  # LoadBalancer类型时,指定负载均衡器的IP
  34.   loadBalancerSourceRanges:    # 限制访问LoadBalancer的客户端IP范围
  35.   - 10.0.0.0/8
  36.   
  37.   externalName: my.database.example.com  # ExternalName类型时,指定外部域名
  38.   
  39.   publishNotReadyAddresses: false  # 是否发布未就绪的端点,默认为false
复制代码
Service之ClusterIP实战

这是svc默认的类型,是k8s集群内部分配的虚拟IP,实用于集群内部举行访问,外部访问不到,但是可以利用 Ingress 大概 Gateway API 来公开服务。创建svc时会自动关联endpoints资源。
创建一个Deployment
  1. [root@master01 ~/deploy]# cat deploy-nginx.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5.   name: deployment-nginx
  6.   namespace: default
  7. spec:
  8.   # 设置Pod的副本数量
  9.   replicas: 3
  10.   selector:
  11.     # 标签匹配规则
  12.     matchLabels:
  13.       app: nginx
  14.   template:
  15.     metadata:
  16.       name: pod-nginx
  17.       labels:
  18.         app: nginx
  19.     spec:
  20.       containers:
  21.       - name: container-nginx
  22.         image: nginx:1.14.1
  23.       restartPolicy: Always
  24. # 创建deploy
  25. [root@master01 ~/deploy]# kubectl apply -f deploy-nginx.yaml
  26. deployment.apps/deployment-nginx created
复制代码
创建Service
  1. # 定义service
  2. [root@master01 ~/service]# cat service-clusterip.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6.   # 需要和pod在一个命名空间内
  7.   namespace: default
  8.   name: nginx-svc-clusterip
  9. spec:
  10.   # 定义service的类型
  11.   type: ClusterIP
  12.   # 标签选择器,选择pod的标签,而不是deploy的标签
  13.   selector:
  14.     app: nginx
  15.   # 定义端口映射
  16.   ports:
  17.   - name: clusterip-nginx
  18.     # 访问service的端口
  19.     port: 6789
  20.     # 容器的端口
  21.     targetPort: 80
  22.     protocol: TCP
  23. # 创建service
  24. [root@master01 ~/service]# kubectl apply -f service-clusterip.yaml
  25. service/nginx-svc-clusterip created
复制代码
查看service的详情
  1. # 查看service
  2. [root@master01 ~/service]# kubectl get svc -o wide
  3. NAME                  TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE   SELECTOR
  4. nginx-svc-clusterip   ClusterIP   10.96.3.77   <none>        6789/TCP   91s   app=nginx
  5. # 查看详情
  6. [root@master01 ~/service]# kubectl describe svc nginx-svc-clusterip
  7. Name:              nginx-svc-clusterip
  8. Namespace:         default
  9. Labels:            <none>
  10. Annotations:       <none>
  11. Selector:          app=nginx
  12. Type:              ClusterIP
  13. IP Family Policy:  SingleStack
  14. IP Families:       IPv4
  15. IP:                10.96.3.77
  16. IPs:               10.96.3.77
  17. Port:              clusterip-nginx  6789/TCP
  18. TargetPort:        80/TCP
  19. Endpoints:         100.117.144.188:80,100.117.144.189:80,100.95.185.217:80
  20. Session Affinity:  None
  21. Events:            <none>
复制代码
注意看Endpoints字段,该字段对应的是关联的所有的pod的IPORT地址,service和pod之间的接洽是通过endpoints实现的。
访问service

访问clusterip的service需要通太过配给service的IP和PORT举行访问
  1. # 可以看到CLUSTER-IP字段分配的值是10.96.3.77,PORT(S)字段的值是6789(我们在资源配置文件中定义的)
  2. [root@master01 ~/service]# kubectl get svc -o wide
  3. NAME                  TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE   SELECTOR
  4. nginx-svc-clusterip   ClusterIP   10.96.3.77   <none>        6789/TCP   91s   app=nginx
  5. # 访问service
  6. [root@master01 ~/service]# curl 10.96.3.77:6789
  7. <!DOCTYPE html>
  8. <html>
  9. <body>
  10. <h1>Welcome to nginx!</h1>
  11. # 省略部分内容
  12. <p><em>Thank you for using nginx.</em></p>
  13. </body>
  14. </html>
复制代码
Service之NodePort实战

ClusterIP只能在K8s集群内部访问,外部无法访问,而NodePort在ClusterIP基础之上,多添加了对所有Worker节点实现端口映射的功能。实现了外部访问Pod。
NodePort的工作原理其实就是将service的端口映射到Node的一个端口上,然后就可以通过NodeIp:NodePort来访问service了。
创建deployment
  1. # 定义资源文件
  2. [root@master01 ~/deploy]# cat deploy-tomcat.yaml
  3. apiVersion: apps/v1
  4. kind: Deployment
  5. metadata:
  6.   name: deployment-tomcat
  7.   namespace: default
  8. spec:
  9.   # 定义更新策略
  10.   strategy:
  11.     type: RollingUpdate
  12.     rollingUpdate:
  13.       maxSurge: 1
  14.       maxUnavailable: 1
  15.   replicas: 3
  16.   selector:
  17.     matchLabels:
  18.       app: tomcat
  19.   template:
  20.     metadata:
  21.       name: pod-tomcat
  22.       labels:
  23.         app: tomcat
  24.     spec:
  25.       containers:
  26.       - name: container-tomcat
  27.         image: tomcat:9.0
  28.       restartPolicy: Always
  29. # 创建deployment
  30. [root@master01 ~/deploy]# kubectl apply -f deploy-tomcat.yaml
  31. deployment.apps/deployment-tomcat created
复制代码
创建service
  1. # 定义资源文件
  2. [root@master01 ~/service]# cat service-nodeport.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6.   # 需要和pod在一个命名空间内
  7.   namespace: default
  8.   name: tomcat-svc-nodeport
  9. spec:
  10.   # 定义service的类型
  11.   type: NodePort
  12.   # 标签选择器,选择pod的标签,而不是deploy的标签
  13.   selector:
  14.     app: tomcat
  15.   # 定义端口映射
  16.   ports:
  17.   - name: nodeport-tomcat
  18.     # 访问service的端口
  19.     port: 16789
  20.     # 容器的端口
  21.     targetPort: 8080
  22.     # nodePort的取值是30000-32767,会随机生成,但建议配置
  23.     nodePort: 31180
  24.     protocol: TCP
  25. # 创建service
  26. [root@master01 ~/service]# kubectl apply -f service-nodeport.yaml
  27. service/tomcat-svc-nodeport created
复制代码
查看service
  1. ## 查看service
  2. [root@master01 ~/service]# kubectl get svc -o wide
  3. NAME                  TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)           AGE     SELECTOR
  4. tomcat-svc-nodeport   NodePort    10.96.0.110   <none>        16789:31180/TCP   54s     app=tomcat
  5. # 查看详情
  6. [root@master01 ~/service]# kubectl describe svc tomcat-svc-nodeport
  7. Name:                     tomcat-svc-nodeport
  8. Namespace:                default
  9. Labels:                   <none>
  10. Annotations:              <none>
  11. Selector:                 app=tomcat
  12. Type:                     NodePort
  13. IP Family Policy:         SingleStack
  14. IP Families:              IPv4
  15. IP:                       10.96.0.110
  16. IPs:                      10.96.0.110
  17. Port:                     nodeport-tomcat  16789/TCP
  18. TargetPort:               8080/TCP
  19. NodePort:                 nodeport-tomcat  31180/TCP
  20. Endpoints:                <none>
  21. Session Affinity:         None
  22. External Traffic Policy:  Cluster
  23. Events:                   <none>
复制代码
访问service

访问nodeport的service可以通过集群内部的IPORT举行访问,也可以通过node节点的IPORT举行访问
通过所有node节点均可访问
  1. ## 查看service
  2. [root@master01 ~/service]# kubectl get svc -o wide
  3. NAME                  TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)           AGE     SELECTOR
  4. tomcat-svc-nodeport   NodePort    10.96.0.110   <none>        16789:31180/TCP   54s     app=tomcat
  5. # 通过集群内部
  6. curl 10.96.0.110:16789
  7. # 通过node节点进行访问
  8. curl 10.0.0.30:31180
  9. curl 10.0.0.31:31180
  10. curl 10.0.0.32:31180
复制代码
Service之ExternalName实战

ExternalName类型的Service用于引入集群外部的服务,它通过ExternalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。
创建service
  1. # 定义配置文件
  2. [root@master01 ~/service]# cat service-externalname.yaml
  3. apiVersion: v1
  4. kind: Service
  5. metadata:
  6.     name: baidu-externalname
  7. spec:
  8.     type: ExternalName
  9.     externalName: www.baidu.com
  10.     #ports:
  11.     #- name: baidu-name
  12.     #  port: 443            # 服务端口(集群内部使用)
  13.     #  targetPort: 443      # 外部服务实际端口
  14.     #  protocol: TCP
  15. # 创建service
  16. [root@master01 ~/service]# kubectl apply -f service-externalname.yaml
  17. service/baidu-externalname created
复制代码
查看详情
  1. # 查看service
  2. [root@master01 ~/service]# kubectl get svc
  3. NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)           AGE
  4. baidu-externalname    ExternalName   <none>        www.baidu.com   <none>            47s
  5. # 查看service详情
  6. [root@master01 ~/service]# kubectl describe svc baidu-externalname
  7. Name:              baidu-externalname
  8. Namespace:         default
  9. Labels:            <none>
  10. Annotations:       <none>
  11. Selector:          <none>
  12. Type:              ExternalName
  13. IP Families:       <none>
  14. IP:
  15. IPs:               <none>
  16. External Name:     www.baidu.com
  17. Session Affinity:  None
  18. Events:            <none>
复制代码
验证集群内部访问
  1. # 创建busybox容器进行访问测试
  2. [root@master01 ~/service]# kubectl run -it --rm dns-test --image=busybox:1.28
  3. If you don't see a command prompt, try pressing enter.
  4. # nslookup 验证
  5. / # nslookup baidu-externalname
  6. Server:    10.96.0.10
  7. Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
  8. Name:      baidu-externalname
  9. Address 1: 2409:8c00:6c21:118b:0:ff:b0e8:f003
  10. Address 2: 2409:8c00:6c21:11eb:0:ff:b0bf:59ca
  11. Address 3: 39.156.70.239
  12. Address 4: 39.156.70.46
  13. # ping进行访问
  14. / # ping  baidu-externalname
  15. PING baidu-externalname (39.156.70.239): 56 data bytes
  16. 64 bytes from 39.156.70.239: seq=0 ttl=127 time=15.301 ms
  17. 64 bytes from 39.156.70.239: seq=1 ttl=127 time=14.258 ms
  18. 64 bytes from 39.156.70.239: seq=2 ttl=127 time=29.040 ms
复制代码
Service之LoadBalancer(省略)

LoadBalancer现在没有云环境,在这儿先省略
Service的管理

查看Service

语法:
  1. kubectl get svc <svc-name> -n <namespace>
复制代码
示例:
  1. [root@master01 ~/service]# kubectl get svc
  2. NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)           AGE
  3. baidu-externalname    ExternalName   <none>        www.baidu.com   <none>            23m
  4. kubernetes            ClusterIP      10.96.0.1     <none>          443/TCP           13d
  5. nginx-svc-clusterip   ClusterIP      10.96.3.77    <none>          6789/TCP          4d20h
  6. tomcat-svc-nodeport   NodePort       10.96.0.110   <none>          16789:31180/TCP   49m
复制代码
修改Service

有两种方式,一种是通过kubectl edit svc 来举行修改,会打开一个雷同vim的界面,修改其对应的值即可,最后wq生存即可应用你的配置.
另一种方式则是修改对应的资源文件,最后利用kubectl apply -f 即可。
删除Service

语法:
  1. kubectl delete svc <svc-name> -n <namespace>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表