24. Service——基本概念入门

本章讲解知识点

  • 什么是 Service
  • Endpoint
  • Service 的域名形式
  • Pod 的 DNS 域名相关特性
  • Service 是如何与 Pod 关联的

<br>

1. 什么是 Service

1.1 基本概念

在 Kubernetes 中,Service 是一种用来暴露一组 Pod 的网络服务的抽象机制,可以通过 Service 作为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上

更详细地说,Service 是一个抽象的逻辑实体,它定义了一组 Pod 的逻辑集合以及访问它们的策略。Service 提供了一个稳定的 IP 地址DNS 名称,这使得服务可以被客户端通过这些统一的方式访问。Service 可以将多个 Pod 组合成一个虚拟的服务,使得应用程序可以透明地访问到后端的多个 Pod 实例,而无需关注实际的 Pod 实例数目和位置。

Service 的主要作用是服务发现负载均衡。它允许客户端通过一个服务名来访问一组具有相同标签的 Pod,这些 Pod 可以分布在 Kubernetes 集群中的不同节点上。Service 使用负载均衡器将请求分发到后端的 Pod 实例,从而实现了负载均衡。

Service 定义文件如下:

apiVersion: v1         // required
kind: Service          // required
metadata:            // required
  name: string         // required
  namespace: string      // required,默认default
spec:               // required
  selector: []         // required
  type: string         // required
  ports:
    - name: string
      protocol: string
      port: int
      targetPort: int

  • version:版本号,例如 v1。参数必选
  • kind:Service。参数必选
  • metadata:元数据。
  • metadata.name:Service 名称。参数必选
  • metadata.namespace:Service 命名空间。参数必选。默认为 default。
  • metadata.labels:用于标记 Service 的标签。
  • metadata.annotations:用于注释 Service 的注释。
  • spec:Service 的详细定义。
  • spec.selector:Label Seclector 配置,将选择具有指定 Label 标签的 Pod 作为管理范围参数必选
  • spec.type:Service 的类型,指定 Service 的访问方式,默认值为 ClusterIP。参数必选

1.2 扩展

这里为了帮助初学者理解什么是 Service 以及它的作用,我们多讲一些内容。

在应用 Service 概念之前,我们先看看如何访问一个多副本的应用容器组提供的服务。

我们还是以之前的 deployment 为例,定义为 my-first-deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-first-deploy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-first-deploy
  template:
    metadata:
      labels:
        app: my-first-deploy
    spec:
      containers:
      - name: my-first-container
        image: tomcat:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

创建该应用:

[root@master mtuser]# kubectl create -f my-first-deploy.yaml
deployment.apps/my-first-deploy created

查看每个pod的地址:

[root@master mtuser]# kubectl get pod -owide
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
my-first-deploy-785c6c79d9-4jpsh   1/1     Running   0          11s   10.244.1.136   node1   <none>           <none>
my-first-deploy-785c6c79d9-7bgf5   1/1     Running   0          11s   10.244.1.137   node1   <none>           <none>

客户端可以之间通过这两个 Pod 的 IP 地址和端口号 8080 来访问 Web 服务:

[root@master mtuser]# curl 10.244.1.136:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.0.14</h3></body></html>
[root@master mtuser]#
[root@master mtuser]# curl 10.244.1.137:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.0.14</h3></body></html>

在容器应用中,服务通常是通过多个 Pod 副本共同提供的分布式应用。在应用运行过程中,Pod 副本的数量可能会动态变化(例如执行水平扩展/收缩),并且单个 Pod 的 IP 地址可能会发生变化(例如出现故障)。

为了解决客户端应用程序的复杂性,需要实现动态感知服务后端实例的变化以及将请求发送到多个后端实例的负载平衡机制。 Kubernetes 的 Service 组件就是用于解决这些问题的核心组件。 通过定义 Service,可以对客户端应用屏蔽后端 Pod 实例数量和 Pod IP 地址的变化,并通过负载均衡策略将请求转发到后端 Pod 实例,为客户端应用提供稳定的服务访问入口地址。那接下来让我们看看 Service 具体是怎么做到的以上几点。

以前面创建的 my-first-deploy 应用为例,为了让客户端应用访问到两个 Tomcat Pod 实例,需要创建一个 Service 来提供服务。Kubernetes 提供了一种快速的方法,即通过 kubernetes expose命令来创建 Service:

[root@master mtuser]# kubectl expose deploy my-first-deploy
service/my-first-deploy exposed

查看新创建的 Service:

[root@master mtuser]# kubectl get svc
NAME              TYPE        CLUSTER-IP     EXTERNAL
my-first-deploy   ClusterIP   10.97.139.74   <none>        8080/TCP   44s

可以看到系统为它分配了一个虚拟 IP 地址(ClusterIP 地址),Service 的端口号则从 Pod 中的 containerPort 复制而来

接下来就可以通过 Service 的 IP 地址和端口好访问该 Service 了。

[root@master mtuser]# curl 10.97.139.74:8080
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.0.14</h3></body></html>

客户端对 Service 地址 10.97.139.74:8080 的访问被自动负载分发到了后端两个 Pod 之一:10.244.1.136:8080 或 10.244.1.137:8080。

我们来思考下,是不是这样就实现了我们预期的效果?

  • 1. 有一个固定的 IP 或域名向外部提供了一个稳定的访问入口,客户端不需要感知后端的 Pod 的 IP 是否发生变化
  • 2. 实现了负载均衡,Service 将客户端请求分发到后端 Pod 上,当然可以采用不同的分发策略,如轮询、随机、哈希等方式。

再说直白一点,就是我们最好不要直接去访问 Pod IP,因为 Pod IP 可能会变,我们要的是一个稳定的访问入口,至于后端怎么去分发到哪个 Pod,我作为客户端我不关心。这就是 Service 的意义所在

除了使用 kubectl expose 命令创建 Service,更便于管理的方式是通过 YAML 文件来创建 Service,代码如下:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-first-deploy
  ports:
    - name: http
      protocol: TCP
      port: 8080
      targetPort: 8080

Service 定义中的关键字段是 ports 和 selector。

本例中的 ports 定义部分指定了 Service 本身的端口号为 8080,targetPort 则用来指定后端 Pod 的容器端口号,selector 定义部分设置的是后端 Pod 所拥有的标签 label:app=my-first-deploy

<br>

2. Endpoint

虽然我们有了 Service 这个有效的资源,但如果 Pod IP 列表真发生了变化,Service 是如何感知的并做出相应变

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

云计算面试题全解析 文章被收录于专栏

本专刊适合于立志转行云计算的小白,有一定的编程、操作系统、计算机网络、数据结构、算法基础。 本专刊同时也适合于面向云计算(Docker + Kubernetes)求职的从业者。 本专刊囊括了云计算、VMWare、Docker、Kubernetes、Containerd等一系列知识点的讲解,并且最后总

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务