大家好!我是一个热衷于分享IT技术的up主。在这个公众号里,我将为大家带来最新、最实用的技术干货,从编程语言到前沿科技,从软件开发到网络安全。希望通过我的分享,能够帮助更多的小伙伴提升技术水平,共同成长!欢迎关注,一起探索科技的魅力吧!

概念介绍

Kubernetes是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用。在Kubernetes中,Service是一种抽象,它定义了一组Pod的逻辑集合,并且能够在这些Pod之间实现负载均衡。Service 使得我们可以通过一个固定的IP地址或DNS名称访问Pod,即使这些Pod的数量和位置在不断变化。

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_Pod

Service实现方式

userspace

userspace模式下,kube-proxy会为每个Service创建一个监听端口。通过Iptables规则,发往Cluster IP的请求被重定向到kube-proxy监听的端口。kube-proxy根据负载均衡算法选择一个服务的Pod,与其建立连接并将请求转发给该Pod。在这种模式下,kube-proxy充当四层负载均衡器的角色。由于kube-proxy在用户空间运行,转发过程中涉及内核与用户空间之间的数据拷贝,虽然这种方式较为稳定,但效率相对较低。

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_nginx_02

iptables

iptables模式下,kube-proxy为每个Service的后端Pod创建相应的iptables规则,将发往Cluster IP的请求直接重定向到一个Pod IP。这种模式下,kube-proxy并不充当四层负载均衡器的角色,只负责创建和维护iptables规则。相比于userspace模式,iptables模式的效率更高,但无法提供灵活的负载均衡策略,并且当后端Pod不可用时也无法进行请求重试。

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_IP_03

ipvs

IPVS模式与 iptables 类似,kube-proxy通过监控Pod的变化来创建相应的IPVS规则。与 iptables 相比,IPVS转发效率更高,并且支持更多的负载均衡算法。

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_IP_04

Service 的类型

Service的资源清单文件:

kind: Service  # 资源类型
apiVersion: v1  # 资源版本
metadata: # 元数据
  name: service # 资源名称
  namespace: dev # 命名空间
spec: # 描述
  selector: # 标签选择器,用于确定当前service代理哪些pod
    app: nginx
  type: # Service类型,指定service的访问方式
  clusterIP:  # 虚拟服务的ip地址
  sessionAffinity: # session亲和性,支持ClientIP、None两个选项
  ports: # 端口信息
    - protocol: TCP 
      port: 3017  # service端口
      targetPort: 5003 # pod端口
      nodePort: 31122 # 主机端口

Kubernetes 提供了几种类型的 Service,以满足不同的需求:

  1. ClusterIP:默认类型,创建一个只能在集群内部访问的虚拟IP。
  2. NodePort:在每个Node上打开一个特定的端口,并将流量转发到ClusterIP。
  3. LoadBalancer:使用云提供商的负载均衡器,将外部流量分发到NodePort和ClusterIP。
  4. ExternalName:将服务映射到外部的DNS名称。

部署一个简单的 Web 应用

接下来,我们通过一个实际案例来展示如何创建和使用 Service。假设我们有一个简单的 Nginx Web 应用,我们将使用 Kubernetes 部署它,并通过 Service 进行访问。

Step 1: 创建 Deployment

首先,我们需要创建一个 Deployment 来部署 Nginx 容器。创建一个名为 nginx-deployment.yaml 的文件,内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1
        ports:
        - containerPort: 80

使用以下命令来应用这个 Deployment:

kubectl apply -f nginx-deployment.yaml

创建完成后,查看每个pod的IP地址,如下图所示:

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_IP_05

Step 2: 创建 Service

现在,我们创建一个 Service 来暴露这个 Deployment。创建一个名为 nginx-service.yaml 的文件,内容如下:

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

使用以下命令来应用这个 Service:

kubectl apply -f nginx-service.yaml

Step 3: 验证 Service

应用成功后,我们可以使用以下命令来查看 Service 的详情:

kubectl get services

你应该会看到类似如下的输出:

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_IP_06

通过 Service 的CLUSTER-IP,我们可以在集群内部访问 Nginx 服务。

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_IP_07

HeadlessService的概念和应用

在某些应用场景中,客户端应用不需要通过Kubernetes内置 Service 实现的负载均衡功能,或需要自行完成对服务后端各实例的服务发现机制,或者自行实现负载均衡功能。这时,可以创建一种特殊的服务类型,称为 Headless Service

Headless Service的特点是,这种服务没有入口访问地址(即没有 ClusterIP 地址),kube-proxy不会为其创建负载转发规则。其服务名(DNS 域名)的解析机制则取决于该 Headless Service 是否设置了 Label Selector

已设置Label Selector

如果Headless Service设置了Label Selector,Kubernetes则将根据Label Selector查询后端Pod列表,自动创建Endpoint列表,将服务名(DNS域名)的解析机制设置为:当客户端访问该服务名时,得到的是全部Endpoint列表(而不是一个确定的IP地址)。 以下面的Headless Service为例,其设置了Label Selector:

apiversion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
  clusterIP: None
  selector:
    app: nginx

使用kubectl create命令创建完之后,可以查看该Headless Service的详细信息,可以看到后端的Endpoint列表:

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_IP_08

用nslookup工具对Headless Service名称尝试域名解析,将会看到DNS系统返回的全部Endpoint的IP地址,例如:

【云原生|K8S系列】K8s新手必看,不可不知的K8s技能,Service发现全解析!_nginx_09

结论

通过本教程,我们学习了如何在 Kubernetes 中创建和使用 Service 来暴露应用。我们通过一个简单的 Nginx 部署案例,演示了如何使用 ClusterIP 和 NodePort 类型的 Service。掌握这些基本概念和操作后,可以更轻松地管理和扩展 Kubernetes 集群中的应用服务。

推荐文章