service四层负载均衡(负载均衡4层和7层的区别)

service四层负载均衡service-四层负载均衡
概念、原理解读
为什么要有 Service
​ 在 kubernetes 中,Pod 是有生命周期的,如果 Pod 重启它的 IP 很有可能会发生变化

service-四层负载均衡

概念、原理解读

为什么要有 Service

在Kubernetes 中,Pod 具有生命周期。如果pod 重新启动,其IP 可能会发生变化。所有服务都有Pod 的硬编码IP 地址,如果某个Pod 挂起或重新启动,与刚刚重新启动的Pod 关联的其他服务将无法找到与其关联的Pod。为了解决这个问题,定义:服务可以通过服务访问入口访问该服务背后的应用集群实例。该服务可以访问这组pod。通常通过标签选择器实现。

Pod IP 经常变化。当客户端访问它时,它只需要访问服务,并且请求被代理到pod,因此它无法访问k8s集群之外的任何内容。可以从k8s 集群外部访问该服务。

概述

该服务是固定访问层。客户端可以通过访问服务的IP 和端口来访问与您的服务关联的后端Pod。该服务依赖于部署到Kubernetes 集群的附件:Kubernetes DNS 服务。 Kubernetes 版本默认使用不同的DNS。 1.11 之前的版本使用kubeDN,较新的版本使用coredns。因此,您必须重新安装k8s 才能部署DNS 附件。您必须依赖第三方网络插件(flannel、calico 等)来为您的客户端提供网络功能。每个K8s 节点都有一个名为kube-proxy 的组件,它不断监控apiserver 的服务资源的变化信息,并且必须随时连接到apiserver。要在服务资源的内容发生更改(创建、删除等)时获取有关apiserver 的信息,请使用Kubernetes 特定的请求方法watch(监视)使用kube-proxy。这些规则实现了当前节点上的服务资源调度,并允许您将请求调度到后端特定的Pod资源。该规则可以是iptables 或ipvs,具体取决于服务的实现方式。

工作原理

k8s 创建Service 时,会根据标签选择器搜索Pod,并创建与Service 同名的Endpoint 对象。如果Pod 地址发生变化,端点也会相应变化。当服务发出请求时,它会接收前端客户端并使用端点来定位地址转发到的Pod 进行访问。 (负载均衡kube-proxy决定Pod转发到哪个节点。)

三类 IP 地址

节点网络:物理或虚拟节点的网络(例如ens33接口的网络地址)

Pod网络,创建的Pod的IP地址

[root@k8s01 控制器]# kubectl get pods -o Wide

名称就绪状态重启年龄IP 节点指定节点就绪门

myapp-v1-75fb478d6c-4j2sx 1/1 运行0 27 米10.244.236.165 k8s02 无无

myapp-v1-75fb478d6c-4j8p6 1/1 运行0 27 米10.244.236.164 k8s02 无无

集群网络(集群地址,也称为服务网络)。该地址是虚拟地址(virtual lip),没有在特定接口上配置,仅出现在服务规则中。

[root@k8s01 控制器]# kubectl 获取svc

名称类型集群IP 外部IP 端口期限

kubernetes ClusterIP 10.96.0.1 无443/TCP 2d21h

创建 Service 资源

#检查定义服务资源所需的字段

[root@k8s01 控制器]# kubectl 解释服务

KIND:服务

版本: v1

描述:

服务是软件服务的命名抽象(例如mysql)

配置代理侦听的本地端口(例如3306),

确定哪个pod 将响应提交的请求的选择器

代理人。

字段:

API版本字符串

#service 资源使用的API 组

输入字符串

#创建的资源类型

元数据对象

#定义元数据

规格对象

状态对象

#检查服务规范字段是如何定义的

[root@k8s01 控制器]# kubectl 解释service.spec

KIND:服务

版本: v1

RESOURCE: 规范对象

描述:

规范定义了服务的行为。

https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

ServiceSpec 描述您在服务上创建的属性。

字段:

分配LoadBalancerNodePortsboolean

集群ip字符串

*动态分配的地址可以在创建时指定,但创建后不能更改。

集群IP[] 字符串

externalIPs[] 字符串

外部名称字符串

外部流量策略字符串

healthCheckNodePortinteger

ipFamilies[] 字符串

ipFamilyPolicy字符串

负载均衡器IP 字符串

loadBalancerSourceRanges[]字符串

端口[]对象

#定义与后端pod建立连接的服务端口

publicNotReadyAddresses 布尔值

选择器映射[字符串] 字符串

#使用标签选择器选择相关的pod

会话关联字符串

#service在实现负载均衡时也支持sessionAffinity。 sessionAffinity是什么意思?会话联系。默认为无,随机调度(基于iptables 规则)。为sessionAffinity 定义客户端IP 可确保来自同一客户端的IP 请求被调度到同一pod。

会话亲和性配置对象

sessionAffinityConfig 包含会话亲和性配置。

拓扑键[]字符串

输入字符串

#定义服务类型

Service 的四种类型

检查#Service.spec.type 定义所需的字段

[root@k8s01 控制器]# kubectl 解释service.spec.type

KIND:服务

版本: v1

FIELD: 类型字符串

描述:

类型决定了服务的公开方式。默认为ClusterIP。

选项包括ExternalName、ClusterIP、NodePort 和LoadBalancer。

“ClusterIP”分配集群内部IP地址以实现负载平衡。

端点由选择器或其他方式确定。

通过手动构造Endpoints 对象或EndpointSlice 来指定。

目的。如果clusterIP 为“None”,则不分配虚拟IP,并且

端点作为一组端点而不是虚拟IP 公开。

“NodePort”构建在ClusterIP 之上,为每个节点分配一个端口。

路由到构建“LoadBalancer”的同一端点。

使用NodePort 创建外部负载均衡器(如果当前负载均衡器支持)

Cloud)路由到与clusterIP 相同的端点。

其他几个字段将此服务别名为指定的externalName。

不适用于外部名称服务。 详细信息:

https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

外部名称:

适合k8s集群内部容器访问外部资源,没有选择器,也没有定义端口或端点。 *以下服务定义将prod 命名空间中的my-service 服务映射到my.database.example.com。

api版本: v1

kind:服务

元数据:

name: 我的服务

命名空间:产品

规格:

type: 外部名称

externalName: my.database.example.com

当您查询主机my-service.prod.svc.cluster.local 时,集群DNS 返回值为my.database.example.com 的CNAME 记录。

服务的FQDN 为:service_name.svc.cluster.local

例如上面的例子:my-service.prod.svc.cluster.local

集群IP:

通过k8s集群内部IP公开服务如果选择该值,则该服务只能在集群内部访问。这也是默认的服务类型。

节点端口:

Node 通过每个节点的IP和静态端口暴露k8s集群中的服务。您可以通过请求: 将请求代理到内部Pod。

客户端—–NodeIP:NodePort—-服务Ip:ServicePort—-PodIP:ContainerPort。

负载平衡器:

可以使用云提供商的负载均衡器向外部公开服务。外部负载均衡器可以路由到NodePort 和ClusterIP 服务。

Service 的端口

#检查服务的spec.ports字段是如何定义的

[root@k8s01controller]# kubectl 解释service.spec.ports

KIND:服务

版本: v1

RESOURCE: 端口[] 对象

描述:

此服务公开的端口列表。详细信息:

https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies

ServicePort 包含有关服务端口的信息。

字段:

应用程序协议字符串

名称字符串

#定义端口名称

节点端口整数

|#主机上的映射端口。例如,如果您的Web 应用程序需要由k8s 集群外部的其他用户访问,则必须配置type=NodePort。如果配置nodePort=30001,则其他机器可以访问scheme : //k8s可以使用ip:30001(例如http://192.168.1.63:30001)通过浏览器访问服务。如果在k8s上部署MySQL数据库,则不需要配置NodePort,因为MySQL不需要外部访问,只需从内部服务访问即可。

端口整数-必填-

#服务端口。这是可以访问k8s集群内部服务的端口。

协议字符串

此端口的IP 协议支持“TCP”、“UDP”和“SCTP”。

这是TCP。

目标端口字符串

# targetPort 是pod 上的端口。来自端口和节点端口的流量通过kube-proxy 到达后端pod 的targetPort,最后进入容器。例如nginx官方暴露了80端口,与创建容器时暴露的端口一致(使用DockerFile中的EXPOSE)。

ClusterIP

创建一个Pod

podtest.yaml

apiVersion: 应用程序/v1

kind:的部署

元数据:

name: my-nginx

规格:

复制品: 2

选择器:

匹配标签:

run: my-nginx

模板:

元数据:

标签:

run: my-nginx

规格:

集装箱:

– name: my-nginx

图片: nginx:最新

imagePullPolicy: 如果不存在

端口:

-containerPort: 80 # Pod 中的容器必须公开的端口

[root@k8s01服务]# kubectl apply -f pod_test.yaml

已创建deployment.apps/my-nginx

#显示刚刚创建的Pod IP地址

[root@k8s01 服务]# kubectl get pods -o Wide

名称就绪状态重启年龄IP 节点指定节点就绪门

my-nginx-65fc647b5d-gc5zh 1/1 运行0 29 秒10.244.236.167 k8s02 无无

my-nginx-65fc647b5d-tf2vz 1/1 运行0 29 秒10.244.236.166 k8s02 无无

请求pod 的IP 地址并查看结果

[root@k8s01服务]# kubectl exec -it my-nginx-65fc647b5d-tf2vz — /bin/bash

请注意,尽管Pod 定义了容器端口,但未使用为该节点安排的端口80,也未使用任何特定NAT 规则将流量路由到该Pod。 这意味着您可以使用同一容器端口在同一节点上运行多个Pod,并使用集群中其他Pod 或节点的IP 访问它们。

其中一个Pod 被意外删除:

[root@k8s01 服务]# kubectl get pods -o Wide

名称就绪状态重启年龄IP 节点指定节点就绪门

my-nginx-65fc647b5d-gc5zh 1/1 运行0 8 分38 秒10.244.236.167 k8s02 无无

my-nginx-65fc647b5d-tf2vz 1/1 运行0 8 分38 秒10.244.236.166 k8s02 无无

[root@k8s01 服务]# kubectl 删除pod my-nginx-65fc647b5d-gc5zh

Pod \’my-nginx-65fc647b5d-gc5zh\’ 已被删除

[root@k8s01 服务]# kubectl get pods -o Wide

名称就绪状态重启年龄IP 节点指定节点就绪门

my-nginx-65fc647b5d-mp5t2 1/1 运行0 13 秒10.244.236.168 k8s02 无无

my-nginx-65fc647b5d-tf2vz 1/1 运行0 9 分5 秒10.244.236.166 k8s02 无无

从上面可以看到pod已经重新生成:my-nginx-65fc647b5d-mp5t2,IP为10.244.236.168,并在k8s上创建了一个pod。当Pod 被删除时,重新生成的Pod 的IP 地址会发生变化。因此,您需要在pod 前端添加固定的接入层。

接下来,创建服务。

#显示Pod 标签:

[root@k8s01 服务]# get kubectl pod –show-labels

姓名就绪状态恢复年龄标签

my-nginx-65fc647b5d-mp5t2 1/1 运行0 4m2s pod-template-hash=65fc647b5d,run=my-nginx

我的Nginx

-65fc647b5d-tf2vz 1/1 Running 0 12m pod-template-hash=65fc647b5d,run=my-nginx
创建 Service
service_test.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: ClusterIP
ports:
– port: 80 # service的端口,暴露给k8s集群内部服务访问
protocol: TCP
targetPort: 80 # pod容器中定义的端口
selector:
run: my-nginx # 选择拥有run=my-nginx标签的pod
​ 上述 yaml 文件将创建一个 Service,具有标签 run=my-nginx 的 Pod,目标 TCP 端口 80,并且在一个抽象的 Service 端口(targetPort:容器接收流量的端口;port:抽象的 Service 端口,可以使任何其它 Pod 访问该 Service 的端口)上暴露
[root@k8s01 service]# kubectl apply -f service-test.yaml
service/my-nginx created
[root@k8s01 service]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d22h
my-nginx ClusterIP 10.106.190.4 <none> 80/TCP 4s
#在 k8s 控制节点访问 service 的 ip:端口就可以把请求代理到后端 pod
[root@k8s01 service]# curl 10.106.190.4:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
#通过上面可以看到请求 service IP:port 跟直接访问 pod ip:port 看到的结果一样,这就说明service 可以把请求代理到它所关联的后端 pod
**注意:**上面的 10.106.190.4:80 地址只能是在 k8s 集群内部可以访问,在外部无法访问,比方说我们想要通过浏览器访问,那么是访问不通的,如果想要在 k8s 集群之外访问,是需要把 service type 类型改成 nodePort 的
#查看 service 详细信息
[root@k8s01 service]# kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: run=my-nginx
Annotations: <none>
Selector: run=my-nginx
Type: ClusterIP
IP Families: <none>
IP: 10.106.190.4
IPs: 10.106.190.4
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.236.166:80,10.244.236.168:80
Session Affinity: None
Events: <none>
[root@k8s01 service]# kubectl get ep my-nginx
NAME ENDPOINTS AGE
my-nginx 10.244.236.166:80,10.244.236.168:80 4m25s
​ service 可以对外提供统一固定的 ip 地址,并将请求重定向至集群中的 pod。其中“将请求重定向至集群中的 pod”就是通过 endpoint 与 selector 协同工作实现。selector 是用于选择 pod,由selector 选择出来的 pod 的 ip 地址和端口号,将会被记录在 endpoint 中。endpoint 便记录了所有 pod的 ip 地址和端口号。当一个请求访问到 service 的 ip 地址时,就会从 endpoint 中选择出一个 ip 地址和端口号,然后将请求重定向至 pod 中。具体把请求代理到哪个 pod,需要的就是 kube-proxy 的轮询实现的。service 不会直接到 pod,service 是直接到 endpoint 资源,就是地址加端口,再由 endpoint 再关联到 pod。
​ service 只要创建完成,我们就可以直接解析它的服务名,每一个服务创建完成后都会在集群 dns 中动态添加一个资源记录,添加完成后我们就可以解析了,资源记录格式是:
SVC_NAME.NS_NAME.DOMAIN.LTD.
服务名.命名空间.域名后缀
集群默认的域名后缀是 svc.cluster.local
就像我们上面创建的 my-nginx 这个服务,它的完整名称解析就是:my-nginx.default.svc.cluster.local
[root@k8s01 service]# kubectl get pods
NAME READY STATUS RESTARTS AGE
my-nginx-65fc647b5d-mp5t2 1/1 Running 0 15m
my-nginx-65fc647b5d-tf2vz 1/1 Running 0 24m
[root@k8s01 service]# kubectl exec -it my-nginx-65fc647b5d-tf2vz — /bin/bash
root@my-nginx-65fc647b5d-tf2vz:/# curl my-nginx.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

NodePort

创建一个 pod 资源
pod-nodeport.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-nodeport
spec:
selector:
matchLabels:
run: my-nginx-nodeport
replicas: 2
template:
metadata:
labels:
run: my-nginx-nodeport
spec:
containers:
– name: my-nginx-nodeport-container
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
– containerPort: 80
#更新资源清单文件
[root@k8s01 service]# kubectl apply -f pod-nodeport.yaml
deployment.apps/my-nginx-nodeport created
#查看 pod 是否创建成功
[root@k8s01 service]# kubectl get pods -l run=my-nginx-nodeport -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-nodeport-69d7b95994-h79t8 1/1 Running 0 32s 10.244.236.169 k8s02 <none> <none>
my-nginx-nodeport-69d7b95994-ljw46 1/1 Running 0 32s 10.244.235.143 k8s03 <none> <none>
创建 service,代理 pod
service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx-nodeport
labels:
run: my-nginx-nodeport
spec:
type: NodePort
ports:
– port: 80
protocol: TCP
targetPort: 80
nodePort: 30380
selector:
run: my-nginx-nodeport
[root@k8s01 service]# kubectl apply -f service-nodeport.yaml
service/my-nginx-nodeport created
[root@k8s01 service]# kubectl get svc -l run=my-nginx-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-nodeport NodePort 10.106.116.28 <none> 80:30380/TCP 13s
#访问 service
[root@k8s01 service]# curl 10.106.116.28:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
注意:
10.106.116.28 是 k8s 集群内部的 service ip 地址,只能在 k8s 集群内部访问,在集群外无法访问。
在集群外访问 service
[root@ajie102 ~]# curl 10.106.116.28:30380
curl: (7) Failed connect to 10.106.116.28:30380; No route to host
[root@ajie102 ~]# curl 125.124.155.47:30380
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
在浏览器访问 service

服务请求走向:
Client→node ip:30380->service ip:80→pod ip:container port
Client ->125.124.155.47:30380->10.106.116.28:80->pod ip:80

ExternalName

应用场景:跨名称空间访问

需求:default 名称空间下的 client 服务想要访问 nginx-ns 名称空间下的 nginx-svc 服务

client.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: client
spec:
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
containers:
– name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command:
– \’/bin/sh\’
– \’-c\’
– \’sleep 3600\’

clinet_svc.yaml

apiVersion: v1
kind: Service
metadata:
name: client-svc
spec:
type: ExternalName
externalName: nginx-svc.nginx-ns.svc.cluster.local
ports:
– port: 80
targetPort: 80
name: http

该文件中指定了到 nginx-svc 的软链,让使用者感觉就好像调用自己命名空间的服务一样。

[root@k8s01 service]# kubectl create ns nginx-ns
namespace/nginx-ns created

server_nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: nginx-ns
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent

[root@k8s01 service]# kubectl apply -f server_nginx.yaml
deployment.apps/nginx created
#查看 pod 是否创建成功
[root@k8s01 service]# kubectl get pods -n nginx-ns
NAME READY STATUS RESTARTS AGE
nginx-bb957bbb5-65kxd 1/1 Running 0 25s

nginx_svc.yaml

apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: nginx-ns

spec:
selector:
app: nginx
ports:
– port: 80
targetPort: 80
name: http
protocol: TCP

[root@k8s01 service]# kubectl apply -f nginx_svc.yaml
service/nginx-svc created
#登录到 client pod
[root@k8s01 service]# kubectl get pods
NAME READY STATUS RESTARTS AGE
client-57875f4ddb-srfwc 1/1 Running 0 8m43s
[root@k8s01 service]# kubectl exec -it client-57875f4ddb-srfwc — /bin/sh
/ # wget -q -O – nginx-svc.nginx-ns.svc.cluster.local
/ # wget -q -O – client-svc.default.svc.cluster.local

上面两个请求的结果一样

kube-proxy 组件详解

ginx-ns

spec:
selector:
app: nginx
ports:
– port: 80
targetPort: 80
name: http
protocol: TCP

“`shell
[root@k8s01 service]# kubectl apply -f nginx_svc.yaml
service/nginx-svc created
#登录到 client pod
[root@k8s01 service]# kubectl get pods
NAME READY STATUS RESTARTS AGE
client-57875f4ddb-srfwc 1/1 Running 0 8m43s
[root@k8s01 service]# kubectl exec -it client-57875f4ddb-srfwc — /bin/sh
/ # wget -q -O – nginx-svc.nginx-ns.svc.cluster.local
/ # wget -q -O – client-svc.default.svc.cluster.local

上面两个请求的结果一样

#以上关于service四层负载均衡的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92790.html

Like (0)
CSDN的头像CSDN
Previous 2024年7月4日
Next 2024年7月4日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注