Kubernetes服务发布基础

Kubernetes 服务发布基础

本章要点

  • Service 的概念和原理
  • ClusterIP 类型 service
  • NodePort 类型的 service
  • LoadBalancer 类型的 service
  • ExternalName 类型的 service
  • Service 的多端口设置
  • Kubernetes 服务发现

前言

在当今的云计算和微服务架构中,Kubernetes(简称 K8s)已经成为了容器编排和管理的事实标准。通过 Kubernetes,我们可以轻松地将应用部署到集群中,并确保其高可用性和可扩展性。然而,应用部署完成后,如何将这些服务暴露给外部用户访问,成为了一个关键问题。

在传统的架构中,用户访问公司内部服务通常需要经过多层代理、网关和防火墙等组件。这些组件可能包括 Nginx、Haproxy、LVS 等负载均衡工具,或者公有云提供的 SLB、ELB 等服务。虽然 Kubernetes 在实现负载均衡和域名路由时也采用了类似的技术,但其内部的实现方式与传统架构并无本质区别,只是名称和配置方式有所不同。

在 Kubernetes 中,Service 和 Ingress 是两个核心概念,分别用于实现负载均衡和域名路由。Service 通过为一组 Pod 提供稳定的虚拟 IP 地址,实现了服务的负载均衡和服务发现;而 Ingress 则通过配置域名路由规则,使得外部用户可以通过域名访问集群中的服务。通过这两个组件,Kubernetes 能够有效地管理服务的暴露和访问,确保应用的高可用性和可扩展性。

本章将详细介绍 Kubernetes 中 Service 的概念、工作原理及其不同类型的应用场景,帮助读者深入理解如何通过 Service 将应用暴露给外部用户,并实现高效的负载均衡和服务发现。

一、Service 的定义

service 是 kubernetes 中的一种抽象,用于定义一组 pod 以及访问这一组 pod 的策略。service 的作用是将一组 pod 封装为一个虚拟的服务,并提供一个统一的入口,供客户端访问。service 支持负载均衡、服务发现、服务暴露等功能。

Service 用于为一组提供服务的 Pod 抽象一个稳定的网络访问地址,是 k8s 实现微服务的核心概念。通过 Service 的定义设置的访问地址是 DNS 域名格式的服务名称,对于客户端应用来说,网络访问方式并没有改变。Service 还提供了负载均衡器的功能,将客户端请求负载分发到后端提供具体服务的各个 Pod 上。

Service 主要用于提供网络服务,通过 Service 的定义,能够为客户端应用提供稳定的访问地址(域名或 IP 地址)和负载均衡功能,以及屏蔽后端 EndPoint 的变化,是 Kubernetes 实现微服务的核心资源。

总之,service 是 kubernetes 中一个非常重要的概念,service 用于将外部请求代理到内部 pod 上,提供 4 层负载均衡和服务发现的功能,使得我们可以构建高可用和可扩展的应用程序。

二、Service 工作原理

1. service 基本原理介绍

在 kubernetes 中,pod 的 IP 地址是动态变化的,因此无法直接通过 pod 的 IP 地址进行访问。service 的出现正是为了解决这个问题的。service 会为一组 pod 创建一个虚拟的 IP 地址,通过这个 IP 地址可以访问这组 pod 中的任意一个 pod。当客户端请求这个虚拟 IP 地址时,请求会被负载均衡到一组 pod 中的某一个 pod 上,从而完成对 pod 的访问。

service 的实现依赖于 kube-proxy 组件。kube-proxy 会在每个节点上监听 service 的变化,一旦有 service 发生变化,kube-proxy 会更新本地的 iptables 规则,从而实现流量的转发和负载均衡。

另外,service 还与 CoreDNS 有关。CoreDNS 是 kubernetes 集群中的 DNS 解析服务。在 kubernetes 中 service 的虚拟 IP 地址还会注册到 CoreDNS 中,从而使得客户端还可以通过 service 名称访问 service 的虚拟 IP 地址。在 service 的定义中,可以通过 spec.selector 字段指定哪些 pod 属于这个 service,这样,就可以将请求负载均衡到这些 pod 中。

总之,service 是 kubernetes 中一种非常重要的资源对象,它可以让 pod 对外提供服务,并提供负载均衡、服务发现等功能 。service 的实现依赖于 kube-proxy 和 CoreDNS 组件,他们共同协作,将 service 与 pod 连接起来,实现对 pod 的代理访问。

(Service 代理 Pod 流程图)

2. Service 的负载均衡机制

当一个 Service 对象在 Kubernetes 集群中被定义出来时,集群内的客户端应用就可以通过服务 IP 访问到具体的 Pod 容器提供的服务了。从服务 IP 到后端 Pod 的负载均衡机制,则是由每个 node 上的 kube-proxy 代理来负责实现的。

kube-proxy 的代理模式有:userspace、iptables、ipvs 和 kernelspace。

  • (1)userspace
    起初,kube-proxy 进程是一个真实的 TCP/UDP 代理,当某个 pod 以 clusterIP 方式访问某个 service 的时候,这个流量会被 pod 所在的本机的 iptables 转发到本机的 kube-proxy 进程,然后将请求转发到后端某个 pod 上。具体过程为:
    kube-proxy 为每个 service 在 node 上打开一个随机端口作为代理端口
    建立 iptables 规则,将 clusterip 的请求重定向到代理端口(用户空间)
    到达代理端口的请求再由 kubeproxy 转发到后端
    clusterip 重定向到 kube-proxy 服务的过程存在内核态到用户态的切换,开销很大,因此有了 iptables 模式,而 userspace 模式也被废弃了。
  • (2)iptables
    kubernets 从 1.2 版本开始将 iptabels 模式作为默认模式,这种模式下 kube-proxy 不再起到 proxy 的作用。其核心功能:通过 API Server 的 Watch 接口实时跟踪 Service 和 Endpoint 的变更信息,并更新对应的 iptables 规则,Client 的请求流量通过 iptables 的 NAT 机制 “直接路由” 到目标 Pod。
    不同于 userspace,在 iptables 的模式中,kube-proxy 不再负责转发数据包,kube-proxy 主要完成对 iptables 策略的动态管理。数据包的走向完全由 iptables 规则决定,这样的过程不存在内核态到用户态的切换,效率明显会高很多。但是随着 service 的增加,iptables 规则会不断增加,导致内核十分繁忙(等于在读一张很大的没建索引的表)
  • (3)ipvs
    从 kubernetes 1.8 版本开始引入第三代的 IPVS 模式,它也是基于 netfilter 实现的,但定位不同:iptables 是为防火墙设计的,IPVS 则专门用于高性能负载均衡,并使用高效的数据结构 Hash 表,允许几乎无限的规模扩张。
    ipvs 为负载均衡提供了更多的算法:
    rr: 轮训
    lc: 最小连接数
    df: 目标哈希
    sh: 源哈希
    sed: 预计延迟最短
    nq: 从不排队

ipvs 使用 ipset 存储 iptables 规则,在查找时类似 hash 表查找,时间复杂度为 0 (1),而 iptables 时间复杂度则为 O (n)。时间复杂度用字母 0 表示。
可以将 ipset 简单理解为 ip 集合,这个集合的内容可以是 Ip 地址、Ip 网段、端口等,iptabels 可以直接添加规则对这个可变集合进行操作,这样做的好处可以大大减少 iptables 规则的数量,从而减少性能损耗。
如果操作系统没有启用 IPVS 内核模块,kube-proxy 会自动运行为 iptables 模式,如果操作系统启用了 ipvs 模块,则 kube-proxy 会运行为 ipvs 模式。查看系统是否开启了 ipvs 模块,可以使用命令:lsmod | grep ip_vs

  • (4)kernelspace
    Windows Server 上的代理模式,此处不作介绍。

3. service 的 4 种类型

kubernetes 支持 4 种 service 类型。

  • (1)ClusterIP
    这是最常用的 Service 类型,它为 Pod 提供了一个虚拟的 IP 地址。当其他 Pod 需要访问该 Service 时,它们只需要使用该虚拟 IP 地址即可。Kubernetes 会自动将请求路由到相应的 Pod 上
  • (2)NodePort
    这种 Service 类型将 Pod 公开为集群中所有节点上的某个端口。当外部请求到达任何一个节点上的该端口时,Kubernetes 会将请求路由到相应的 Pod 上。
  • (3)LoadBalancer
    LoadBalancer Service: 这种 Service 类型使用云提供商的负载均衡器将请求路由到后端 Pod。Kubernetes 会自动创建和配置负载均衡器,并将其绑定到 Service 上。
  • (4)ExternalName
    ExternalName Service: 这种 Service 类型允许你将 Service 映射到集群外部的某个名称。当 Pod 需要访问该 Service 时,它们将使用该名称来解析出相应的 IP 地址。

三、生成用于测试 service 的 Deployment

编写 Deployment,用于各种 service 的验证。

在应用 Service 概念之前,先创建一个提供 web 服务的 Pod 集合,有两个 Tomcat 容器副本组成,每个容器提供的服务端口都为 8080。

  1. 编辑 deployment
apiVersion: apps/v1  # 指定API版本,Deployment属于apps/v1 API组
kind: Deployment     # 指定资源类型为Deployment,用于管理Pod副本集
metadata:
  name: webapp       # Deployment的名称,在命名空间内必须唯一
spec:
  replicas: 2        # 定义Pod的副本数量,确保始终有2个Pod运行
  selector:          # 标签选择器,用于确定Deployment管理哪些Pod
    matchLabels:     # 精确匹配标签
      app: webapp    # 匹配带有"app: webapp"标签的Pod
  template:          # Pod模板,定义新建Pod的配置
    metadata:
      labels:        # 为Pod添加标签,必须与selector匹配
        app: webapp  # 标签用于将Pod与Deployment关联
    spec:
      containers:    # 容器配置列表
      - name: webapp # 容器名称,在Pod内必须唯一
        image: kubeguide/tomcat-app:v1  # 使用的Docker镜像及版本
        ports:       # 容器暴露的端口配置
        - name: http # 端口名称,用于标识端口用途
          containerPort: 8080  # 容器内部监听的端口号
          protocol: TCP       # 协议类型,可选TCP或UDP

selector(选择器)主要用于资源的匹配,只有符合条件的资源才会被调用或使用,可以使用该方式对集群中的各类资源进行分配。Kubernetes 和核心资源 Deployment、StatefulSet 管理的 Pod 是通过选择器字段决定的,通过 Service 访问这些后端 Pod 也是通过选择器字段决定的。

label(标签)可以对 Kubernetes 的其他资源进行配置,当 Kubernetes 对系统的任何 API 对象如 Pod 进行分组时,会对其添加标签,用以精准的选择对应的 API 对象。

  1. 创建该 Deployment
[root@k8s-master ~]# kubectl create -f webapp-deployment.yaml
  1. 查看 pod 创建情况
[root@k8s-master ~]# kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
webapp-8554f77548-9xwmm     1/1     Running   0          93s
webapp-8554f77548-jrw7f     1/1     Running   0          93s
  1. 查看各个 pod 的 IP 地址
[root@k8s-master ~]# kubectl get pods -l app=webapp -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES
webapp-8554f77548-9xwmm     1/1     Running   0          2m55s   172.17.125.3     k8s-node01   <none>           <none>
webapp-8554f77548-jrw7f     1/1     Running   0          2m55s   172.27.14.195    k8s-node02   <none>           <none>
  1. 访问这两个地址
[root@k8s-master ~]# curl 172.17.125.3:8080
[root@k8s-master ~]# curl 172.27.14.195:8080

四、service 的创建

1. 创建一个 ClusterIP 类型 service

描述:ClusterIP 是默认的 Service 类型。它将创建一个虚拟的 ClusterIP 地址,用于在集群内部访问 Service。

使用场景:适用于集群内部的服务通信,例如将前端服务和后端服务连接起来,供内部其他服务使用。

  • 方法一:通过 expose 命令创建 ClusterIP 类型的 Service

为了让客户端应用能够访问到前面创建的两个 Tomcat Pod 实例,需要创建一个 Service 来提供服务。k8s 提供了一种快速地方法,即通过 kubectl expose 命令来创建 Service。

(1)执行 expose 命令暴露端口

[root@k8s-master ~]# kubectl expose deployment webapp

(2)查看创建的 Service

[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    9d
webapp       ClusterIP   10.104.162.209  <none>        8080/TCP   32s

这里可以看到,系统为他分配了一个虚拟 IP 地址,Service 的端口号,从 pod 中复制而来。我们就可以通过这个虚拟 IP 地址,和端口号来访问这个 Service 了。

(3)访问测试

[root@k8s-master ~]# curl 10.104.162.209:8080

客户端对 Service 的访问被自动负载分发到了后端的两个 pod 之一。Kubernetes 自动完成将客户端请求转发到后端多个 EndPoint 的负载分发的工作。通过负载均衡机制,Kubernetes 实现了一种分布式应用的统一入口,免去了客户端应用获知后端服务实例列表和变化的复杂度。

(4)删除此 Service

[root@k8s-master ~]# kubectl delete service webapp
  • 方法二:使用 yaml 文件创建 Service

除了使用 expose 的命令创建 Service,更便于管理的方式是 yaml 文件来创建 Service。

(1)编辑 service 文件

apiVersion: v1       # 指定API版本,Service属于v1核心API组
kind: Service        # 指定资源类型为Service,用于负载均衡和服务发现
metadata:
  name: webapp       # Service的名称,在命名空间内必须唯一
spec:
  ports:             # 端口映射配置列表
  - protocol: TCP    # 协议类型,可选TCP或UDP
    port: 8080       # Service暴露的端口,集群内部通过此端口访问
    targetPort: 8080 # 后端Pod的目标端口,请求会转发到此端口
  selector:          # 标签选择器,用于确定Service代理哪些Pod
    app: webapp      # 匹配带有"app: webapp"标签的Pod
  # 未指定type时,默认使用ClusterIP类型
  # ClusterIP会分配集群内部的虚拟IP,仅集群内可访问

本案例中的 ports 定义的是 Service 本身的端口号 8080(用于提供给外部用户访问的端口),targetPort 则用来指定后端 Pod 的容器端口号,selector 定义的是后端 Pod 所拥有的 label。

(2)利用 yaml 创建此服务

[root@k8s-master ~]# kubectl create -f webapp-service.yaml

(3)查看创建的 Service,并访问测试

[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    9d
webapp       ClusterIP   10.108.79.50    <none>        8080/TCP   9s
[root@k8s-master ~]# curl 10.108.79.50:8080

(4)查看 EndPoint 列表
一个 Service 对应的后端由 Pod 的 IP 地址和容器的端口号组成,即一个完成的 IP:Port 访问地址,这在 k8s 中叫做 EndPoint。通过查看 Service 的详细信息,可以看到其后端的 EndPoint 列表

# 查看名为webapp的Service详细信息
[root@k8s-master ~]# kubectl describe svc webapp

Name:              webapp                  # Service的名称
Namespace:         default                 # 所属命名空间
Labels:            <none>                  # 没有为Service设置标签
Annotations:       <none>                  # 没有设置注解信息
Selector:          app=webapp              # 标签选择器,关联带有app=webapp标签的Pod
Type:              ClusterIP               # Service类型为ClusterIP(默认),仅集群内部可访问
IP Family Policy:  SingleStack             # IP协议族策略为单栈(仅IPv4或IPv6)
IP Families:       IPv4                    # 使用IPv4协议
IP:                10.108.79.50            # 分配的虚拟IP地址(ClusterIP)
IPs:               10.108.79.50            # 支持的IP地址列表
Port:              <unset>  8080/TCP       # Service端口(未命名),协议为TCP
TargetPort:        8080/TCP                # 目标端口,对应后端Pod的端口
Endpoints:         172.17.125.4:8080,172.27.14.196:8080  # 后端Pod的IP和端口列表
Session Affinity:  None                    # 会话亲和性设置(None表示不保持会话)
Events:            <none>                  # 没有相关事件记录

(5)查看 EndPoint 资源对象
实际上,k8s 自动创建了与 Service 关联的 EndPoint 资源对象,这可以通过 EndPoint 对象进行查看

[root@k8s-master ~]# kubectl get endpoints
NAME         ENDPOINTS                                      AGE
kubernetes   192.168.10.101:6443                            9d
webapp       172.17.125.4:8080,172.27.14.196:8080           6m19s

(6)删除这个 Service

[root@k8s-master ~]# kubectl delete -f webapp-service.yaml
# 或
[root@k8s-master ~]# kubectl delete service webapp

2. 创建 NodePort 类型的 service

NodePort 将在每个节点上公开一个端口,并将流量转发到 Service。它会创建一个 ClusterIP,并将指定的端口映射到每个节点上的相同端口。

这种 service 适用于需要从外部访问集群中的服务时,可以通过节点的 IP 地址和映射的端口进行访问。这对于开发和测试环境非常有用。

(1)创建 Service 文件
设置 Service 类型为 NodePort,并设置具体的 nodePort 端口号为 30008

apiVersion: v1       # 指定API版本,Service属于v1核心API组
kind: Service        # 指定资源类型为Service
metadata:
  name: webapp       # Service的名称,在命名空间内必须唯一
spec:
  type: NodePort     # 指定Service类型为NodePort,可通过节点IP+端口暴露服务
  ports:             # 端口映射配置列表
  - port: 8080       # Service内部端口,集群内通过此端口访问
    targetPort: 8080 # 后端Pod的目标端口,请求会转发到此端口
    nodePort: 30008  # 节点上暴露的端口(范围30000-32767),外部可通过<节点IP>:30008访问
  selector:          # 标签选择器,用于确定Service代理哪些Pod
    app: webapp      # 匹配带有"app: webapp"标签的Pod

各关键字的含义如下:

  • port: 8080: 这是 Service 的内部端口,即在 Service 内部暴露的端口。客户端请求会发送到这个端口,并由 Kubernetes 负载均衡到后端的 Pods 上。
  • targetPort:8080: 这是指向后端 Pods 上的实际容器端口。当流量通过 Service 到达后端 Pods 时,将被转发到这个端口。
  • nodePort:30008: 这是在每个节点上打开的端口,用于外部流量进入集群。外部客户端可以通过 : 访问该 Service。

nodePort 端口的范围在 1.23.6 的版本中为 30000-32767

(2)创建此 Service
继续使用刚才的 webapp 的 Deployment,为此 Deployment 创建一个 NodePort 类型的 service。

[root@k8s-master ~]# kubectl create -f webapp-svc-nodeport.yaml

(3)查看创建的 Service

[root@k8s-master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          9d
webapp       NodePort    10.98.184.252   <none>        8080:30008/TCP   119s

(4)在 windows 宿主机上用浏览器测试访问
http://192.168.10.101:30008

因为 NodePort 的方式可以在每个 Node 节点创建出这个端口,所以在任何一个节点使用 netstat -anpt|grep 30008 命令查询,都可以看到此端口,在访问的时候,IP 地址可以使用任何一个主机的 IP 地址。

(5)删除该 Service

[root@k8s-master ~]# kubectl delete -f webapp-svc-nodeport.yaml

3. 创建 LoadBalancer 类型的 service

通常在公有云的环境中会使用 LoadBalancer 的类型,可以将 Service 映射到公有云提供的某个负载均衡器的 IP 地址上,客户端通过负载均衡器的 Ip 和 Service 的端口号就可以访问到具体的服务。

描述:LoadBalancer 为 Service 创建一个外部负载均衡器,并分配一个外部 IP 地址。它通常由云提供商的负载均衡服务实现。

使用场景:适用于需要将流量从外部负载均衡器分发到集群内部的服务,例如在生产环境中暴露 Web 应用程序。

(1)编写 LoadBalancer 类型的 Service 文件

apiVersion: v1                  # API版本,Service属于v1核心组
kind: Service                   # 资源类型为Service
metadata:
  name: webapp                  # Service名称(必须唯一)
  namespace: default            # 所属命名空间(默认命名空间)
  labels:                       # 为Service添加标签,用于分类和筛选
    app: webapp
spec:
  type: LoadBalancer            # Service类型为LoadBalancer,依赖云厂商负载均衡器
  ports:
  - port: 8080                  # Service暴露的端口(集群内部访问)
    targetPort: http            # 目标端口名称(对应Pod中定义的端口名)
    protocol: TCP               # 协议类型
    name: http                  # 端口名称(用于标识)
  nodePort: 31771               # 节点端口(可选),范围30000-32767,若不指定系统会自动分配
  selector:                     # 标签选择器,关联后端Pod
    app: webapp                 # 匹配带有"app: webapp"标签的Pod

这个 Service 创建好后,云服务商会在 Service 定义中补充 LoadBalancer 的 IP 地址,之后就可以在客户端访问该 Service 了。nodePort 的端口范围在 30000-32767 之间。

(2)创建此 Service

[root@k8s-master ~]# kubectl create -f webapp-svc-loadbalancer.yaml

(3)查看创建结果

[root@k8s-master ~]# kubectl get svc
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          9d
webapp       LoadBalancer   10.111.51.212   <pending>     8080:31458/TCP   2m56s

(4)在 windows 宿主机上访问
http://192.168.10.101:31458

(5)删除此 Service

[root@k8s-master ~]# kubectl delete -f webapp-svc-loadbalancer.yaml

4. 创建 ExternalName 类型的 service

ExternalName 允许 Service 通过返回 CNAME 记录来引用集群外部的服务。它没有 ClusterIP,NodePort 或 LoadBalancer。

适用于需要将 K8s 内部的服务与集群外的现有服务进行关联,例如连接到外部的数据库或其他资源。ExternalName 类型是 Service 的特例,用于将集群外的服务定义为 Kubernetes 的集群 Service,并通过 ExternalName 字段指定外部服务的地址,可以使用域名或 IP 格式。集群内客户端应用通过访问这个 Service 就能访问外部服务了。他没有选择器,没有定义任何端口和 EndPoint,他通过返回该外部服务的别名来提供服务。

也可以用于两个不同的 namespace 之间的不同 pod 可以通过 name 的形式访问。

两个不同的命名空间中的 pod,可以直接使用他们的 IP 地址进行通信,但是 pod 的 IP 地址是随机分配的,重建 pod 后其 IP 地址就改变了,因此我们要用 pod 对应的 service 名称进行通信。但是跨命名空间是不能解析其他命名空间中创建的 service 名称的。这个时候就可以使用 ExternalName 实现两个不同命名空间中的各个 pod 间的通信。接下来,我们以两个命名空间内 Pod 之间的访问为例,讲解 ExternalName 的使用方法。

(1)创建命名空间为 test02 的 Pod

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp02
  namespace: test02
spec:
  replicas: 1
  selector:  #标签选择器
    matchLabels:  #匹配的标签为
      app: myapp02
      release: canary
  template:
    metadata:
      labels:
        app: myapp02  #和上面的 myapp 要匹配
        release: canary
    spec:
      containers:
      - name: myapp02
        image: ikubernetes/myapp:v1
        ports:
        - name: http02
          containerPort: 80
[root@k8s-master ~]# kubectl create -f myapp02.yaml

(2)创建一个无头 (headless) Service

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc02
  namespace: test02
spec:
  selector:
    #挑选的 pod 还是 myapp。一个 pod 可以有多个 service
    app: myapp02
    release: canary
  clusterIP: None  #None 表示是无头 service
  ports:
  - port: 39320  #service ip 中的端口
    targetPort: 80  #容器 ip 中的端口
[root@k8s-master ~]# kubectl create -f myapp-svc-headless02.yaml

(3)创建 extername

kind: Service
apiVersion: v1
metadata:
  name: myapp-svcname01
  namespace: test02
spec:
  type: ExternalName
  externalName: myapp-svc01.test01.svc.cluster.local
[root@k8s-master ~]# kubectl create -f myapp-svc-extername02.yaml

五、service 的其他应用

1. Service 的多端口设置

一个容器应用可以提供多个端口的服务,在 Service 的定义中也可以相应的设置多个端口号。

(1)创建 service 文件

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - port: 8080
    targetPort: 8080
    name: web
    protocol: TCP
  - port: 8005
    targetPort: 8005
    name: management
    protocol: TCP
  selector:
    app: webapp

注意: selector 中的 app:webapp 的标签对应的是 webapp-deployment.yaml 中的 pod 的标签

(2)创建 service

[root@k8s-master ~]# kubectl create -f service-multiple-ports.yaml

(3)查看 EndPoint 列表

[root@k8s-master ~]# kubectl describe svc webapp

(4)查看创建的 Service

[root@k8s-master ~]# kubectl get svc webapp

(5)删除这个 Service

[root@k8s-master ~]# kubectl delete -f webapp-service.yaml
# 或
[root@k8s-master ~]# kubectl delete service webapp

2. Kubernetes 服务发现

服务发现机制是指客户端如何在一个 kubernetes 集群中获知后端服务的访问地址。

Kubernetes 的服务发现有两种方式:环境变量和 DNS

(1)基于环境变量的服务发现
当 Pod 部署到一个 node 节点后,该 node 节点上的 kubelet 会在该 pod 内部设置一组环境变量,这些环境变量是根据活跃的 Service 生成的,所以,要使用基于环境变量的服务发现,需要先创建对应的 Service 后再创建所需的 Pod。在一个 Pod 运行起来的时候,系统会自动为其容器运行环境注入所有集群中有效 Service 的信息,Service 的相关信息包括服务 IP、服务端口号、各端口号相关的协议等。然后,客户端应用就能够根据 Service 相关环境变量的命名规则,从环境变量中获取需要访问的目标服务(Pod)的地址了。

先创建出之前用的 service

[root@k8s-master ~]# kubectl create -f service-multiple-ports.yaml
[root@k8s-master ~]# kubectl create -f webapp-deployment.yaml
[root@k8s-master ~]# kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
webapp-86b5d9fc88-cv6qq     1/1     Running   0          82s
webapp-86b5d9fc88-s4smp     1/1     Running   0          82s

任意的 Pod 都会根据这些 Service 创建一组变量用于服务发现。

[root@k8s-master ~]# kubectl exec -it webapp-86b5d9fc88-cv6qq -- env
PATH=/usr/local/tomcat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=webapp-86b5d9fc88-cv6qq
TERM=xterm
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
MYNGINX_SERVICE_PORT_HTTP=80
MYNGINX_PORT_80_TCP_PORT=80
MYNGINX_PORT_80_TCP_ADDR=10.109.164.93
KUBERNETES_PORT_443_TCP_PORT=443
MYNGINX_SERVICE_PORT=80
MYNGINX_PORT_80_TCP=tcp://10.109.164.93:80
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
MYNGINX_PORT_80_TCP_PROTO=tcp

四、案例练习

1. 案例一

apiVersion: v1
kind: Service
metadata:
  name: mynginx
  namespace: default
  labels:
    app: mynginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: mynginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mynginx-deployment
  namespace: default
  labels:
    # 此处省略部分内容

本章总结

本章详细介绍了 Kubernetes 中 Service 的概念、工作原理及其不同类型的应用场景。Service 是 Kubernetes 中用于定义一组 Pod 及其访问策略的核心抽象,它通过为 Pod 提供稳定的虚拟 IP 地址,实现了服务的负载均衡、服务发现和服务暴露功能。Service 的主要作用是将一组 Pod 封装为一个虚拟服务,并为客户端提供统一的访问入口,屏蔽后端 Pod 的动态变化。

本章首先介绍了 Service 的基本原理,解释了 Service 如何通过 kube-proxy 和 CoreDNS 组件实现流量转发和负载均衡。kube-proxy 负责监听 Service 的变化并更新本地的 iptables 或 ipvs 规则,而 CoreDNS 则负责将 Service 的虚拟 IP 地址注册到集群的 DNS 系统中,使得客户端可以通过 Service 名称进行访问。接着,本章详细讲解了 Service 的四种类型:ClusterIP、Nodeport、LoadBalancer 和 ExternalName,分别适用于不同的应用场景。ClusterIP 用于集群内部的服务通信,NodePort 允许通过节点 IP 和端口访问服务,LoadBalancer 则通过云提供商的负载均衡器将流量分发到后端 Pod,而 ExternalName 用于将 Service 映射到集群外部的服务。

此外,本章还介绍了 Service 的多端口设置和 Kubernetes 的服务发现机制,包括基于环境变量和 DNS 的服务发现方式。通过这些机制,Kubernetes 能够有效地管理服务的暴露和访问,确保应用的高可用性和可扩展性。最后,本章通过多个实际案例,演示了如何创建和配置不同类型的 Service,帮助读者更好地理解和应用这些概念。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值