kubernetes service 服务

news/2024/7/8 6:29:43 标签: kubernetes, service

1 service作用

使用kubernetes集群运行工作负载时,由于Pod经常处于用后即焚状态,Pod经常被重新生成,因此Pod对应的IP地址也会经常变化,导致无法直接访问Pod提供的服务,Kubernetes中使用了Service来解决这一问题,即在Pod前面使用Service对Pod进行代理,无论Pod怎样变化,只要有Label,就可以让Service能够联系上Pod,把PodIP地址添加到Service对应的端点列表(Endpoints)实现对PodIP跟踪,进而实现通过Service访问Pod目的。

  • 通过service为pod客户端提供访问pod方法,即可客户端访问pod入口
  • 通过标签动态感知podIP地址变化等
  • 防止pod失联
  • 定义访问pod访问策略
  • 通过label-selector相关联通过Service实现Pod的负载均衡(TCP/UDP 4层)
  • 底层实现由kube-proxy通过userspace、iptables、ipvs三种代理模式

2 Kube-proxy三种代理模式

2.1 userspace 模式

userspace 模式是 kube-proxy 的最早实现方式,主要工作原理如下:

(1)kube-proxy 监听 Kubernetes API 服务器中 Service 和 Endpoint 的变化。

(2)当有新的 Service 创建时,kube-proxy 会在节点上打开一个端口,并将这个端口映射到 Service 对应的后端 Pod。

(3)任何对这个端口的访问请求,都会被 kube-proxy 捕捉,并转发到后端的 Pod。kube-proxy 使用用户空间程序来进行这些转发操作。

这种模式的优点是实现简单,但缺点是性能较低,因为每个数据包都需要经过用户空间的处理,增加了额外的开销和延迟。

2.2 iptables 模式

iptables 模式是 kube-proxy 的改进版,相比 userspace 模式有显著的性能提升。其工作原理如下:

(1)kube-proxy 同样监听 Kubernetes API 服务器中 Service 和 Endpoint 的变化。

不同的是,kube-proxy 使用 iptables 来设置网络规则。这些规则会直接在内核空间进行处理,而不是通过用户空间。

(2)当有新的 Service 创建时,kube-proxy 会生成相应的 iptables 规则,定义从 Service IP 和端口到后端 Pod 的 NAT 转发规则。

(3)数据包在内核空间直接被转发到相应的后端 Pod,减少了上下文切换,提高了转发性能。

iptables 模式的优点是性能更好,但在处理大量规则时,规则管理和更新可能会变得复杂。

2.3 ipvs 模式

ipvs 模式是 kube-proxy 的最新实现方式,使用 Linux 内核中的 IP Virtual Server (IPVS) 技术。其工作原理如下:

(1)kube-proxy 监听 Kubernetes API 服务器中 Service 和 Endpoint 的变化

(2)kube-proxy 使用 IPVS 来创建和维护负载均衡规则。IPVS 是内核中的一个模块,专门用于负载均衡,支持多种调度算法。

(3)当有新的 Service 创建时,kube-proxy 会使用 IPVS 创建相应的负载均衡规则,定义从 Service IP 和端口到后端 Pod 的转发规则。

(4)数据包在内核空间通过 IPVS 直接转发,性能更高,同时支持更多的负载均衡算法(如轮询、最小连接数、最短延迟等)。

(5)ipvs 模式的优点是性能最佳,支持更多的负载均衡算法和更复杂的网络规则,但需要内核支持 IPVS 模块。

2.4 iptables与ipvs对比

iptables

  • 优点:灵活,功能强大(可以在数据包不同阶段对包进行操作)
  • 缺点:表中规则过多时,响应变慢,即规则遍历匹配和更新,呈线性时延。

ipvs

  • 优点:转发效率高。调度算法丰富:rr,wrr,lc,wlc,ip hash...。
  • 缺点:内核支持不全,低版本内核不能使用,需要升级到4.0或5.0以上。

3 service类型

3.1 类型

ClusterlP

  • 默认,分配一个集群内部可以访问的虚拟IP

NodePort

  • 在每个Node上分配一个端口作为外部访问入口
  • nodePort端口范围为:30000-32767

LoadBalancer

  • 工作在特定的Cloud Provider上,例如Google Cloud,AWS,OpenStack

ExternalName

  • 表示把集群外部的服务引入到集群内部中来,即实现了集群内部pod和集群外部的服务进行通信

3.2 service参数

port:访问service使用的端口

targetPort:Pod中容器端口

nodePort:通过Node实现外网用户访问k8s集群内service(30000-32767)

4 service创建

4.1 ClusterIP类型

ClusterlP根据是否生成ClusterlP又可分为普通service和handless service

普通Service:

为Kubernetes的Service分配一个集群内部可访问的固定虚拟IP(ClusterIP),实现集群内的访问。

Headless Service:

该服务不会分配ClusterIP,也不通过kube-proxy做反向代理和负载均衡。而是通过DNS提供稳定的网络ID来访问,DNS会将headless service的后端直接解析为pod IP列表。

4.1.1 普通ClusterIP service创建

通过命令行从Deployment创建Service

如果你有一个名为my-deployment的Deployment,你可以使用以下命令为其创建一个Service:

kubectl expose deployment my-deployment --port=80 --type=ClusterIP

再使用get和describe查看svc

通过IP地址访问:

service可以实现负载均衡的效果

创建一个拥有三个副本的deployment

[root@easzlab ~]# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-55f598f8d-gcszt   1/1     Running   0          22m
nginx-deployment-55f598f8d-kj5nz   1/1     Running   0          22m
nginx-deployment-55f598f8d-p2dsr   1/1     Running   0          22m

以其中一个pod为例

[root@easzlab ~]# kubectl exec -it nginx-deployment-55f598f8d-p2dsr  -- /bin/bash
root@nginx-deployment-55f598f8d-p2dsr:/# cd /usr/share/nginx/html
root@nginx-deployment-55f598f8d-p2dsr:/usr/share/nginx/html# echo "web1" > index.html
root@nginx-deployment-55f598f8d-p2dsr:/usr/share/nginx/html# exit

三个pod设置好后,使用curl访问,可以看到每次访问的都是不同的pod,可以实现出负载均衡的效果。

通过资源清单创建service

1.创建Deployment的YAML文件

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

2.创建Service的YAML文件

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

验证资源是否创建成功

kubectl get deployments
kubectl get services

查看资源详情

kubectl describe deployment my-nginx-deployment
kubectl describe service my-nginx-service
4.1.2 Headless Service
  • 普通的ClusterlP serviceservice name解析为cluster ip,然后cluster ip对应到后面pod ip
  • Headless service是指service name直接解析为后面的pod ip

特点和行为

  • DNS记录:Headless Service会在Kubernetes DNS中为每个匹配的Pod创建一个A记录(Address Record),直接指向Pod的IP地址。
  • 无负载均衡:由于没有ClusterIP,Headless Service不提供内置的负载均衡。
  • 适用于StatefulSets:Headless Service非常适合与StatefulSets一起使用,因为StatefulSets为每个Pod提供了一个稳定的网络标识和持久存储。

创建Service的YAML文件

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None  # 设置为None以创建Headless Service
  selector:
    app: my-app    # 设置标签,对应deployment
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

DNS解析

在集群内部,可以使用nslookup或dig命令来解析Headless Service的DNS记录:

kubectl run -it --rm --image=tutum/dnsutils dnsutils -- nslookup headless-service.default.svc.cluster.local.

这将显示与Service选择器匹配的Pods的IP地址列表。

4.2 NodePort类型

NodePort Service通常用于以下场景:

  • 当你需要从集群外部访问服务,但不想使用外部负载均衡器时。
  • 作为临时解决方案,直到设置好外部负载均衡器。
  • 允许外部流量直接进入集群,但通过特定的节点端口。

创建NodePort Service

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  type: NodePort  # 指定Service类型为NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80  # Service端口,集群内部访问的端口
      targetPort: 80  # 转发到Pod的端口
      nodePort: 30080  # 节点上的静态端口,外部访问的端口

应用Service

kubectl apply -f nginx-nodeport.yaml

验证Service

kubectl get services

访问Service

一旦NodePort Service创建成功,你可以通过任何节点的IP地址加上nodePort来访问服务。

http://<任一节点IP>:30080

4.3 LoadBalancer类型

LoadBalancer是Kubernetes Service的一种类型,它为服务提供了一个外部可访问的IP地址。这个IP地址是通过云服务提供商的负载均衡器实现的,它可以将流量分发到服务背后的多个Pod。

创建LoadBalancer Service

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

应用Service

kubectl apply -f nginx-lb-service.yaml

检查Service状态

kubectl get services

访问LoadBalancer服务

http://<EXTERNAL-IP>

4.4 ExternalName类型

ExternalName 是一种特殊类型的Service,它不是用来创建一个集群内部的服务代理或负载均衡器,而是用于将服务名映射到一个外部的DNS名称。这种服务类型通常用于引用集群外的服务,例如指向一个外部的数据库、API服务或其他基础设施服务。

4.4.1 将公网域名引入

1. 创建ExternalName Service的YAML定义

创建一个名为externalname-service.yaml的YAML文件,定义一个ExternalName类型的Service:

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: www.baidu.com  # 外部DNS名称

2. 应用Service定义

kubectl apply -f externalname-service.yaml

3. 验证Service

kubectl get services
NAME               TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
external-service   ExternalName   <none>         www.baidu.com   <none>         15h

4. 访问Service

在集群内的Pod可以通过Service名称访问外部服务。例如,如果集群内的Pod需要访问www.baidu.com,它们可以使用external-service.default.svc.cluster.local来解析DNS。

5. DNS解析

在集群内部,可以使用nslookup或dig命令来解析ExternalName Service的DNS记录:

kubectl run -it expod --image=busybox:1.28
# nslookup www.baidu.com
# nslookup external-service.default.svc.cluster.local.

这将显示外部DNS名称www.baidu.com。

4.5 sessionAffinity

sessionAffinity 是 Service 资源的一个属性,它用来控制在一个客户端的多个请求是否应该始终路由到同一个Pod。这种特性被称为会话亲和性(Session Affinity),它对于需要保持用户会话状态的应用非常有用,例如在Web应用程序中。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  sessionAffinity: ClientIP # 启用基于客户端IP的会话亲和性
  type: ClusterIP
  1. sessionAffinity: ClientIP
  • 当设置为 ClientIP 时,启用基于客户端IP地址的会话亲和性。这意味着来自同一个客户端IP地址的所有请求将始终被路由到同一个Pod,只要该Pod仍然健康并且可用。
  • 这个特性对于需要保持用户会话状态的应用非常有用,例如,用户登录状态或购物车信息。
  • 会话亲和性持续时间由 sessionAffinityConfig 中的 timeoutSeconds 属性控制,如果Pod不可用,超时后客户端请求可以被路由到其他Pod。
  1. sessionAffinity: None
  • 当设置为 None 或者不设置 sessionAffinity 属性时,表示不启用会话亲和性。客户端请求将不会被限制到特定的Pod,而是根据Service的负载均衡算法(通常是轮询)分配到可用的Pod。
  • 这种方式适用于无状态的应用,其中每个请求都是独立的,不需要保持会话状态。


http://www.niftyadmin.cn/n/5536643.html

相关文章

SHELL脚本学习(十三)初识 gawk 编辑器

概述 gawk提供了一种编程语言&#xff0c;而不仅仅是编辑器命令。 在gawk语言中&#xff0c;可以实现如下操作&#xff1a; 定义变量保存数据使用算数和字符串运算符处理数据使用结构化编程概念 为数据处理添加处理逻辑提取文件中的数据并将其重新排列组合&#xff0c;最后生…

Flume集群部署(手把手部署图文详细版)

前景概要&#xff1a; Kafka消息订阅系统在大数据业务中有着重要运用&#xff0c;尤其在实时业务中&#xff0c;kafka是必不可少的组件之一。 Flume是大数据组件中重要的数据采集工具&#xff0c;我们常利用Flume采集各种数据源的数据供其他组件分析使用。例如在实时业务中&…

Flutter本地数据持久化的几种方式

目录 前言 一、shared_preferences 1.添加依赖 2.保存数据 3.读取数据 4.移除数据 5.Shared_preferences的优缺点 6.完整的示例代码 二、path_provider 1.导入path_provider 2.创建文件读写的目录 3.向文件中写入数据 4.从文件中读取数据 5.完整的示例代码 三、…

opencv 图像的缩放(放大,缩小),翻转与旋转

目录 opencv 图像的缩放(放大&#xff0c;缩小)&#xff0c;翻转&#xff0c;旋转1、图像的缩放&#xff0c;旋转过程中为什么需要插值&#xff1a;2、常见的插值算法包括&#xff1a;3、图像的缩放&#xff0c;翻转&#xff0c;旋转&#xff1a;&#xff08;1&#xff09;图像…

R 绘图 - 饼图

R 绘图 - 饼图 饼图是一种常用的数据可视化工具&#xff0c;用于展示数据集中各个类别的相对比例。在R语言中&#xff0c;饼图可以通过多种方式绘制&#xff0c;其中最常用的是pie()函数。本文将详细介绍如何在R中创建和定制饼图&#xff0c;包括基本饼图的绘制、添加标签、调…

【安全攻防】网络安全中的序列化与反序列

1.序列化与反序列化 首先要了解序列化与反序列化的定义&#xff0c;以及序列化反序列化所用到的基本函数。 序列化&#xff1a;把对象转换为字节序列的过程称为对象的序列化&#xff0c;相当于游戏中的存档。 PHP中的序列化函数serialize() **serialize()**函数用于序列化对…

Spring:Spring中分布式事务解决方案

一、前言 在Spring中&#xff0c;分布式事务是指涉及多个数据库或系统的事务处理&#xff0c;其中事务的参与者、支持事务的服务器、资源管理器以及事务管理器位于分布式系统的不同节点上。这样的架构使得两个或多个网络计算机上的数据能够被访问并更新&#xff0c;同时将这些操…

adb shell ps -T打印出来参数的含义,以及D,T,Z代表的状态含义是什么?

在Android系统中&#xff0c;使用adb shell ps命令可以查看当前系统中运行的进程信息。当你添加-T选项时&#xff08;注意&#xff0c;标准的ps命令在Android的adb shell中可能不直接支持-T选项&#xff0c;这通常与Linux中的ps命令略有不同&#xff09;&#xff0c;你可能是想…