K8S四层代理service

艺帆风顺 发布于 2025-04-02 24 次阅读


一、四层负载均衡Service基本介绍

    Kubernetes 中,四层代理(Layer 4 Proxy)是指基于网络层(传输层)的代理,用于将网络请 求从一个源地址路由到一个目标地址。在 Kubernetes 中,Service(服务)作为四层代理的一种实现方 式,用于实现服务的负载均衡和服务发现。 Service 是 Kubernetes 中的一个资源对象,它定义了一组具有相同标签的 Pod 的逻辑集合,并为 这组 Pod 分配了一个虚拟 IP(Cluster IP)。Service 充当了网络终结点,客户端可以通过访问 Service 的虚拟 IP 来访问后端的 Pod。 以下是 Service 的基本介绍:     ClusterIP:每个 Service 都分配了一个 Cluster IP,它是一个虚拟的内部 IP 地址,用于在集群内 部进行访问。这个虚拟 IP 是由 Kubernetes 自动分配的,并且与 Service 对象一一对应。     端口映射:Service 可以映射一个或多个端口到后端 Pod 的端口。这意味着客户端可以通过访问 Service 的某个端口来访问后端 Pod 的应用程序。     负载均衡:Service 使用四层代理实现负载均衡,将来自客户端的请求均匀地分发到后端的 Pod。当 多个 Pod 属于同一个 Service 时,Service 会自动将请求路由到可用的 Pod 上,以实现负载均衡。     DNS 解析:每个 Service 都会自动注册到 Kubernetes 集群的内置 DNS 中,通过服务名称可以解 析出 Service 的虚拟 IP。这样,客户端可以使用服务名称作为域名来访问 Service,而无需知道具体的 虚拟 IP 地址。k8s集群中的IP地址1、Pod IP 地址:每个运行的 Pod 都会分配一个独立的 IP 地址。Pod IP 地址是集群内部的 IP 地址,用于 Pod 之间的通信。2、Service Cluster IP 地址:Service 对象分配的虚拟 IP 地址称为 Cluster IP。Cluster IP 是集群内部的 IP 地址,用于在集群内部进行服务发现和访问。客户端可以通过访问 Service 的Cluster IP 地址来访问与该 Service 相关联的一组 Pod。3、Node IP 地址:Node(节点)是 Kubernetes 集群中的工作节点,每个节点都有一个 IP 地址。Node IP 地址用于与集群外部的网络进行通信,例如从外部访问集群中的服务。Node IP 地址可以是物理节点的 IP 地址或云提供商分配的虚拟 IP 地址。这三类 IP 地址在 Kubernetes 集群中扮演不同的角色:1、Pod IP 地址用于 Pod 之间的通信,实现了容器间的网络互通。2、Service Cluster IP 地址用于提供服务的访问入口,客户端可以通过访问 Service 的 Cluster IP 地址来访问与之关联的一组 Pod。3、Node IP 地址用于与集群外部的网络进行通信,允许外部流量进入集群或从集群中流出。

    二、创建service资源

    1.创建ClusterIP类型的Service

      简介ClusterIP(默认模式):为Service分配一个Cluster IP地址,该地址仅在集群内部可访问。使用Kubernetes内部代理(kube-proxy)来将连接路由到Service的后端Pod。这是最常用的模式。创建nginx Pod---apiVersion: apps/v1kind: Deploymentmetadata: name: nginx labels: test_pod: nginxspec: replicas: 3 selector: matchLabels: run: nginx template: metadata: name: nginx labels: run: nginx spec: containers: - name: nginx image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 #开发Pod的80端口 protocol: TCP创建ClusterIP类型的Service---apiVersion: v1kind: Servicemetadata: name: clusterip-test labels: app: svcspec: type: ClusterIP ports: - name: nginx port: 80 protocol: TCP targetPort: 80 selector: run: nginx检查:查看podIP[root@lx100 svc]# kubectl get pods -owide -l run=nginxNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnginx-569fc689f9-4mpns 1/1 Running 0 3h8m 10.247.66.151 lx120 nginx-569fc689f9-9hzsv 1/1 Running 0 3h8m 10.246.71.89 lx110 nginx-569fc689f9-h2lpq 1/1 Running 0 3h8m 10.246.71.88 lx110 #查看service信息[root@lx100 svc]# kubectl get svc -owideNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTORclusterip-test ClusterIP 10.109.26.178 80/TCP 157m run=nginx#查看负载均衡ipvsadm -LnIP Virtual Server version 1.2.1 (size=4096)Prot LocalAddress:Port Scheduler Flags  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn   TCP 10.109.26.178:80 rr -> 10.246.71.88:80 Masq 1 0 0  -> 10.246.71.89:80 Masq 1 0 0  -> 10.247.66.151:80 Masq 1 0 0 #查看服务端点信息[root@lx100 svc]# kubectl get endpoints -l app=svcNAME ENDPOINTS AGEclusterip-test   10.246.71.88:80,10.246.71.89:80,10.247.66.151:80   163m

      2.创建 NodePort 类型的 Service

        NodePort:将Service公开为集群节点上的特定端口。在每个节点上监听Service的特定端口,并将流量转发到后端Pod。可以通过任何集群节点的IP地址和指定的端口访问Service。创建nginx Pod---apiVersion: apps/v1kind: Deploymentmetadata: name: node-portspec: replicas: 3 selector: matchLabels: run: NodePort-nginx template: metadata: labels: run: NodePort-nginx spec: containers: - name: nginx image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80创建NodePort类型的Service---apiVersion: v1kind: Servicemetadata: name: nginx-nodeportspec: type: NodePort selector: run: NodePort-nginx ports: - name: web port: 80 nodePort: 30180 targetPort: 80 protocol: TCP查看Pod IP[root@lx100 svc]# kubectl get pods -owide -l run=NodePort-nginxNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnode-port-778c484869-n86sb 1/1 Running 0 26m 10.246.71.91 lx110 node-port-778c484869-qcqp7 1/1 Running 0 26m 10.247.66.153 lx120 node-port-778c484869-xpfsh 1/1 Running 0 26m 10.247.66.152 lx120 查看service信息[root@lx100 svc]# kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEclusterip-test ClusterIP 10.109.26.178 80/TCP 3h47mkubernetes ClusterIP 10.96.0.1 443/TCP 28dnginx-nodeport NodePort 10.105.50.230 80:30180/TCP 22m查看负载均衡ipvsadm -LnIP Virtual Server version 1.2.1 (size=4096)Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConnTCP 172.17.0.1:30180 rr -> 10.246.71.91:80 Masq 1 0 0  -> 10.247.66.152:80 Masq 1 0 0  -> 10.247.66.153:80 Masq 1 0 0 TCP 192.168.1.100:30180 rr -> 10.246.71.91:80 Masq 1 0 0  -> 10.247.66.152:80 Masq 1 0 0  -> 10.247.66.153:80 Masq 1 0 0 TCP 192.168.122.1:30180 rr -> 10.246.71.91:80 Masq 1 0 0  -> 10.247.66.152:80 Masq 1 0 0   -> 10.247.66.153:80             Masq    1      0          0         TCP 10.246.73.128:30180 rr -> 10.246.71.91:80 Masq 1 0 0  -> 10.247.66.152:80 Masq 1 0 0  -> 10.247.66.153:80 Masq 1 0 0 #查看服务端点信息[root@lx100 svc]# kubectl get endpointsNAME ENDPOINTS AGEclusterip-test 10.246.71.88:80,10.246.71.89:80,10.247.66.151:80 3h53mkubernetes 192.168.1.100:6443 28dnginx-nodeport 10.246.71.91:80,10.247.66.152:80,10.247.66.153:80 29m集群内访问:curl http://10.105.50.230:80集群外访问(192.168.1.100为K8S节点IP,所有节点都可以):curl http://192.168.1.100:30180

        3.创建 ExternalName 类型的 Service

            要实现在不同命名空间下的 Pod 之间进行跨命名空间访问

          ExternalName:将Service映射到集群外部的某个外部域名。不会为Service分配Cluster IP或任何负载均衡器IP。只会返回由ExternalName指定的外部域名的CNAME记录。1、在nginx命名空间创建pod和service资源创建名为nginx的命名空间kubectl create ns nginx编写nginx命名空间pod的yaml---apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-pod namespace: nginxspec: replicas: 3 selector: matchLabels: name: nginxnginx template: metadata: labels: name: nginxnginx spec: containers: - name: nginx image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80编写nginx命名空间service的yaml文件---apiVersion: v1kind: Servicemetadata: name: nginx-svc namespace: nginxspec: selector: name: nginxnginx ports: - port: 80 protocol: TCP targetPort: 80default命名空间下创建pod和service创建pod:---apiVersion: apps/v1kind: Deploymentmetadata: name: busybox namespace: defaultspec: replicas: 1 selector: matchLabels: app: busybox template: metadata: labels: app: busybox spec: containers: - name: busybox image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","sleep 3600"]创建serviceapiVersion: v1kind: Servicemetadata: name: client-svcspec: type: ExternalName externalName: nginx-svc.nginx.svc.cluster.local ports: - name: http port: 80 targetPort: 80验证:进入default命名空间中的pod[root@lx100 svc]# kubectl get podsNAME READY STATUS RESTARTS AGEbusybox-6bb56cf754-sx2dt 1/1 Running 0 6m12s[root@lx100 svc]# kubectl exec -it busybox-6bb56cf754-sx2dt /bin/sh/ # wget -q -O - client-svc.default.svc.cluster.local返回nginx页面则成功

          三、代理外部服务

            在节点上安装MariaDB数据库yum install mariadb-server.x86_64 -ysystemctl start mariadb创建service---apiVersion: v1kind: Servicemetadata: name: mysqlspec: type: ClusterIP ports: - port: 3306创建Endpoint---apiVersion: v1kind: Endpointsmetadata: name: mysqlsubsets:- addresses:  - ip: 192.168.1.110 ports:  - port: 3306查看service详细信息kubectl describe svc mysqlName: mysqlNamespace: defaultLabels: none>Annotations: none>Selector: none>Type: ClusterIPIP Family Policy: SingleStackIP Families: IPv4IP: 10.105.22.22IPs: 10.105.22.22Port: 3306/TCPTargetPort: 3306/TCPEndpoints:         192.168.1.110:3306 #已经加入Session Affinity: NoneEvents: none>创建一个空的pod尝试连接---apiVersion: apps/v1kind: Deploymentmetadata: name: busybox namespace: defaultspec: replicas: 1 selector: matchLabels: app: busybox template: metadata: labels: app: busybox spec: containers: - name: busybox image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","sleep 3600"]进入podkubectl exec -it busybox-6bb56cf754-sx2dt /bin/sh/ # telnet mysql 3306Connected to mysql@Host 'lx120' is not allowed to connect to this MariaDB serverConnection closed by foreign host连接成功;输出信息为@Host 'lx120'不允许连接到被外部主机关闭的MariaDB服务器