D25 kubernetes Service资源对象{简介/定义/类型/Endpoint对象}

1、Service概述

	Service是kubernetes中的一种资源对象,用于定义一组pod的网络访问规则,它为pod提供了一个稳定的统一访问入口,允许客户端始终使用同一个ip地址进行访问,避免了直接使用podip地址导致的不稳定性
  • Service主要有以下两种功能:
负载均衡:当多个pod提供服务时,Service通过负载均衡算法将请求分发到这些pod上,从而实现应用的负载均衡
服务发现:Service提供了一种服务发现机制,自动维护后端podip的变化,从而保障客户端访问应用程序不受后端pod变化的影响

2、Service定义

  • 假设集群中有一组由Deployment管理的pod,这些pod在tcp的80端口上提供服务,pod标签为app=ningx,如下所示:
[root@k8s-master k8s]# kubectl get pods --show-labels
NAME           READY   STATUS    RESTARTS        AGE   LABELS
pod-nginx      1/1     Running   0               7s    app=pod-nginx
  • 为了将这组pod对外,创建一个Service资源,配置如下:
[root@k8s-master k8s]# cat service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  # 端口映射列表
  - port: 80
    # 端口映射协议,支持TCP、UDP、和SCTP,默认为TCP
    protocol: TCP
	# 目标端口,既容器中应用程序监听的端口
    targetPort: 80
  # 标签选择器(Label Selector),用于定义Service应该将流量转发到哪个pod上。这里表示只有带有app=nginx标签的pod才会被改Service转发流量
  selector:
    app: pod-nginx
  • 创建Service资源
[root@k8s-master k8s]# kubectl apply -f service.yaml
service/nginx created
  • 查看Service资源
[root@k8s-master k8s]# kubectl get service
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP   29d
nginx           ClusterIP   10.99.169.247   <none>        180/TCP   27s
NAME:名称
TYPE:公开类型,默认为ClusterIP
CLUSTER-IP:集群IP地址,也成为虚拟IP地址
EXTERNAL-IP:外部IP地址。当使用loadbalance或externalname类型时,才会显示外部ip地址,否则会显示为none或pending
PORT(S):公开端口和协议
AGE:创建时间
	综上所述,该Service分配的虚拟IP地址为10.99.169.247,监听tcp协议的180端口,该Service可以在集群中的任意pod或节点上通过地址10.99.169.247:180访问这组pod。
  • 如果pod在多个端口上提供服务,可以为每个端口定义一个端口映射规则,并为每个规则制定一个唯一的名称,以便对他们进行区分。配置实例如下
[root@k8s-master k8s]# cat service-pods.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: pod-nginx
	在上述实例中,定义了两个端口映射规则。其中,第一个规则将180端口映射到pod的80端口,第二个规则将443端口映射到目标pod上的443端口
  • 在Service对象的PORT(S)列也会显示这两个规则公开的端口
[root@k8s-master k8s]# kubectl get services
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP   29d
nginx           ClusterIP   10.99.169.247   <none>        180/TCP   66m
  • Service的虚拟IP地址是从kubernetes集群的Service网络的CIDR地址范围(在kubeadm init命令中指定)中分配的。如果想查看该CIDR地址范围,可以使用以下命令:
[root@k8s-master k8s]# kubectl cluster-info dump | grep -i service-cluster-ip-range
                            "--service-cluster-ip-range=10.96.0.0/12",
                            "--service-cluster-ip-range=10.96.0.0/12",

3、Service公开类型

  • Service的公开类型定义了Service如何对外部网络公开,支持四种公开类型
ClusterIP:默认类型。Service会被分配一个虚拟IP地址。集群中的应用程序可以通过IP地址访问Service
NodePort:在每个节点上开放一个固定端口,并将该端口映射到Service上。这允许集群外部的用户可以用过节点IP地址和固定端口访问Service
LoadBalance:在底层云提供商创建一个负载均衡器,并将外部流量转发集群中的Service
ExternalName:将Service的名称映射到指定的外部域名

3.1 ClusterIP

  • ClusterIP适用于应用程序仅需要在集群内部访问的场景
    假设集群中部署了一个搜索接口服务,并且该服务仅有集群中的其他应用程序调用。在这种情况下,我们可以使用Service ClusterIP类型来公开相关pod
  • Service ClusterIP类型的配置示例如下
[root@k8s-master k8s]# cat service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
   name: search-api
spec:
  type: ClusterIP
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: search-api
上述实例中定义了一个ClusterIP类型的Service,集群中的其他应用程序可以通过访问该Service的虚拟IP地址来访问搜索接口服务

3.2 NodePort

  • NodePort类型适用于应用程序需要集群外部访问的场景
    假设集群中部署了一个网站,该网站对集群外部的用户提供了访问权限。在这种情况下,我们可以使用nodeport Service来公开相关的pod
  • Service NodePort类型的配置示例如下
[root@k8s-master k8s]# cat service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: portal
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: portal
  • 创建 Service
[root@k8s-master k8s]# kubectl apply -f service-nodeport.yaml
service/portal created
  • 查看Service
[root@k8s-master k8s]# kubectl get service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
portal          NodePort    10.103.236.157   <none>        80:32491/TCP   57s
 PORT(S) 的值显示为80:32491,其中冒号左侧是访问虚拟IP地址对应的端口,右侧表示节点开放的固定端口(既nodeport端口)。用户通过任意node节点的IP地址和32491端口来访问网站,如http://172.16.99.71:32491
	默认情况下,kubernetes为nodeport类型的Service分配一个固定端口。该端口取值范围为3000~32767。我们可以通过nodeport字段指定端口,如指定30002端口,配置示例如下
apiVersion: v1
kind: Service
metadata:
  name: portal
spec:
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30002
  selector:
    app: portal

3.3、LoadBalance

	LoadBalance类型是针对云提供商(如阿里云、aws、azure)涉及的一种类型。当创建一个LoadBalance类型的Service时,云提供商的控制器从kubernetes API中感知到该Service,然后调用云提供商API来创建一个负载均衡器,并将节点IP地址和nodeport端口作为后端添加到该负载均衡其中,这意味着用户可以通过访问云厂商的负载均衡器访问集群中的Service
  • Service LoadBalance类型的配置示例如下:
[root@k8s-master k8s]# cat service-loadbalance.yaml
apiVersion: v1
kind: Service
metadata:
  name: portal
spec:
  type: LoadBalancer
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30002
  selector:
    app: portal
	创建Loadbalancer类型的Service资源后,Service对象的External-IP列将显示云厂商分配的负载均衡器IP地址。通过该IP地址,应用程序只能访问Service名称,从而访问应用程序
	需要注意的是,使用Loadbalancer类型的前提是云厂商的控制器已经被部署在集群中。可以从云厂商获取有关控制器的详细内容

3.4 ExternalName

	ExternalName是一个特殊的类型,与其他类型不同的是。它不提供负载均衡和服务发现功能,而是专用于将Service的名称映射到指定的外部域名上。因此不需要为ExternalName类型Service定义selector字段,也不会为他分配虚拟IP地址。应用程序只能通过Service名称访问该外部域名。
	ExternalName类型只有在集群中需要使用Service名称来访问外部域名时才会被用到,Service ExternalName类型的配置示例如下
apiVersion: v1
kind: Service
metadata:
  name: syj
spec:
  type: ExternalName
  externalName: test.syj.cn
通过这样的配置,集群中的应用程序可以通过Service名称syj.default.svc.cluster.local来访问外部域名test.syj.cn

4、Endpoints对象

	当创建一个Service时,kubernetes会根据Service创建一个Endpoints对象,该对象负责维护与Service相关的后端pod信息,并确保Service可以被正确的转发到后端pod。
  • 查看Endpoints对象
[root@k8s-master k8s]# kubectl get endpoints
NAME            ENDPOINTS           AGE
kubernetes      172.16.99.71:6443   29d
nginx           10.244.85.200:80    22h
pod-readiness   <none>              29d
portal          <none>              13m
search-api      <none>              33m
Name:显示的名称与Service名称相对应
ENDPOINTS:显示了关联的pod IP地址和端口,其中超出三个显示为省略号
	Endpoints对象还可以手动创建,自定义关联的IP地址和端口,以满足特定网络代理需求。例如,通过Service代理集群外部的MySQL服务,配置示例如下
[root@k8s-master k8s]# cat service-mysql-proxy.yaml
apiVersion: v1
kind: Endpoints
metadata:
  name: mysql-proxy
subsets:
- addresses:
  - ip: 172.16.99.70
  ports:
  - port: 3306
    protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-proxy
spec:
  ports:
    - port: 3306
      targetPort: 3306
上述示例首先定义了一个名为mysql-proxy的Endpoints资源,其中subsets(子集)字段包含了一个MySQL服务的IP地址和端口,然后定义了一个名为mysql-proxy的Service资源,将访问3306端口的流量转发到目标端口3306.这里不需要定义selector字段,表明Service不是通过标签选择器来发现pod的
  • 创建资源
[root@k8s-master k8s]# kubectl apply -f service-mysql-proxy.yaml
endpoints/mysql-proxy created
service/mysql-proxy unchanged
  • 查看Service和Endpoints
[root@k8s-master k8s]# kubectl get service,endpoints mysql-proxy
NAME                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/mysql-proxy   ClusterIP   10.98.237.25   <none>        3306/TCP   39s

NAME                    ENDPOINTS           AGE
endpoints/mysql-proxy   172.16.99.70:3306   19s
	集群中的应用程序可以通过Service的虚拟IP地址10.98.237.25和3306端口来访问外部的MySQL服务
posted @   Hello_worlds  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示