k8s之service用法

Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。

一、 Service的基本用法:

一般来说,对外提供服务的应用程序需要通过某种机制来实现,对于容器应用最简便的方式就是通过TCP/IP机制及监听IP和端口号来实现。

虽然直接通过Pod的IP地址和端口号可以访问到容器应用内的服务,但是Pod的IP地址是不可靠的,例如当Pod所在的Node发生故障时,Pod将被Kubernetes重新调度到另一个Node, Pod的IP地址将发生变化。更重要的是,如果容器应用本身是分布式的部署方式,通过多个实例共同提供服务,就需要在这些实例的前端设置一个负载均衡器来实现请求的分发。 Kubernetes中的Service就是用于解决这些问题的核心组件。

Service 与Pod 之间是通过Label 和Label 筛选器(selector)松耦合在一起的。Deployment
和Pod 之间也是通过这种方式进行关联的,这种松耦合方式是Kubernetes 具备足够的灵活性
的关键

随着Pod 的时常进出(扩容和缩容、故障、滚动升级等),Service 会动态更新其维护的
相匹配的健康Pod 列表。具体来说,其中的匹配关系是通过Label 筛选器和名为Endpoint
对象的结构共同完成的,每一个 Service 在被创建的时候,都会得到一个关联的Endpoint 对象。整个Endpoint对象其实就是一个动态的列表,其中包含集群中所有的匹配Service Label 筛选器的健康
Pod。Kubernetes 会不断地检查Service 的Label 筛选器和当前集群中健康Pod 的列表。如果有
新的能够匹配Label 筛选器的Pod 出现,它就会被加入Endpoint 对象,而消失的Pod 则会被
剔除。也就是说,Endpoint 对象始终是保持更新的。这时,当Service 需要将流量转发到Pod
的时候,就会到Endpoint 对象中最新的Pod 的列表中进行查找,下图中可以看到server和endpoint的对应关系

二、service类型:

Kubernetes的Service共有四种类型: ClusterIP 、 NodePort、 LoadBalancer和ExternalName

1、 ClusterIP :拥有固定的IP 地址和端口号,只要创建后名字、IP、端口都保持不变,直到删除,并且仅能够从集群内部访问得到,集群外部客户端无法访问(适合各个pod之间通信,可在service文件中定义多服务端口的方式)

2、 NodePort :此类型建立在clusterip之上,在每个节点的IP地址上的某静态端口暴露服务,端口范围(30000-32767),也会为集群分配ClusterIP地址,可以理解为,外部客户端通过NodePort访问进来,通过ClusterIP地址做路由转发到后台的pod服务中,同时NodePort也可以作为集群内部之间通信使用,如图:

3、 LoadBalancer :此类型构建在 ClusterIP 之上,通过cloud provider提供的负载均衡器将服务暴露在集群外部, LoadBalancer具有 ClusterIP 和 NodePort

4、 ExternalName :通过将Service映射至由 ExternalName 字段的内容指定的主机名来暴露服务,此主机名需要被DNS解析到CNAME类型的记录,可以理解为将集群外部的服务通过DNS CNAME的方式映射到集群内部,此类型没有 ClusterIP 和 NodePort ,也不存在标签选择器来选择pod资源,因此不会有Endpoints的存在。

因此,如果要将内部的资源暴露到外部客户端使用,需要配置 NodePort 或者 LoadBalancer 类型,如果要将外部资源发布到集群内部供pod调用 ,应该配置 ExternalName 类型

服务暴露

一、通过 NodePort 方式实现

1、通过deployment定义一个简单的pod,如图:

2、定义service.yaml文件,内容如下:

说明:定义服务发现方式为NodePort,节点端口为30000,根据标签nginx-pod去寻找pod,此文件的内容可以理解为:通过集群的任意节点的30000端口访问到ClusterIP地址的8088端口,进而转发到pod中的80端口

2、执行命令kubectl create -f service.yaml,查看service状态,如图:

从上图可以看到创建NodePort类型的Service的时候,也创建了ClusterIP的IP地址和端口(8088)

3、此时通过集群中的任意节点加端口都可以访问pod资源,如图:

2、ClusterIP方式实现内部访问

ClusterIP是不能通过集群外部访问的,只适用与集群内部的pod之间通讯,例如:现在集群内部已经存在了nginx应用,端口是80,集群内的其他pod想访问这个80端口,就可以通过ClusterIP 来访问,定义yml文件创建ClusterIP,如下:

apiVersion: v1
kind: Service
metadata:
  name: service-nginx-cluster
spec:
  type: ClusterIP
  ports:
  - port: 8081
    targetPort: 80
    protocol: TCP
  selector:
    app: nginx-pod

上面定义的Service类型为ClusterIP,这个ClusterIP的端口是8081,映射到目标pod的端口为80,并根据selector来找到目标pod,创建后如下:

最后在任意节点通过ClusterIP:8081端口访问即可,如图:

注:可以定义多个ClusterIP类型的Service,方便pod之间进行通信

Service的价值在哪?

在实际使用中最常见的就是对应用进行更新

标签