当前位置: 首页 > news >正文

kubernetes中service探讨

文章目录

  • 序言
  • kube-proxy代理模型
    • userspace代理模型
    • iptables代理模型
    • ipvs代理模型
    • 修改代理模型
  • Service资源类型
    • ClusterIP
    • NodePort
    • LoadBalancer
    • ExternalName
  • 应用Service资源
    • 应用ClusterIP Service资源
    • 应用NodePort Service资源
    • 应用LoadBalancer Service资源
    • 外部IP

序言

在Kubernetes应用编排的动态、弹性管理模型下,Service资源用于为Pod对象提供一个固定、统一的访问接口及负载均衡能力,并支持新一代DNS系统的服务发现功能,解决了客户端发现并访问容器化应用的难题。

Service对象的IP地址都仅在Kubernetes集群内可达,它们无法接入集群外部的访问流量。在解决此类问题时,除了可以在单一节点上做端口(hostPort)暴露及让Pod资源共享使用工作节点的网络名称空间(hostNetwork)之外,更推荐用户使用NodePort或LoadBalancer类型的Service资源,或者是有七层负载均衡能力的Ingress资源。

本质上来讲,一个Service对象对应于工作节点内核之中的一组iptables或/和ipvs规则,这些规则能够将到达Service对象的ClusterIP的流量调度转发至相应Endpoint对象指向的IP地址和端口之上。内核中的iptables或ipvs规则的作用域仅为其所在工作节点的一个主机,因而生效于集群范围内的Service对象就需要在每个工作节点上都生成相关规则,从而确保任一节点上发往该Service对象请求的流量都能被正确转发。

kube-proxy代理模型

Service对象的ClusterIP事实上是用于生成iptables或ipvs规则时使用的IP地址,它仅用于实现Kubernetes集群网络内部通信,且仅能够以规则中定义的转发服务的请求作为目标地址予以响应,这也是它之所以被称作虚拟IP的原因之一(iptables方式下clusterIP无法ping通,但是ipvs方式clusterIP可以ping通)。kube-proxy把请求代理至相应端点的方式有3种:userspace、iptables和ipvs

userspace代理模型

此处的userspace是指Linux操作系统的用户空间。在这种模型中,kube-proxy负责跟踪API Server上Service和Endpoints对象的变动(创建或移除),并据此调整Service资源的定义。对于每个Service对象,它会随机打开一个本地端口(运行于用户空间的kubeproxy进程负责监听),任何到达此代理端口的连接请求都将被代理至当前Service资源后端的各Pod对象,至于哪个Pod对象会被选中则取决于当前Service资源的调度方式,默认调度算法是轮询(round-robin),另外,此类Service对象还会创建iptables规则以捕获任何到达ClusterIP和端口的流量。在Kubernetes 1.1版本之前,userspace是默认的代理模型。

在这种代理模型中,请求流量到达内核空间后经由套接字送往用户空间中的kube-proxy进程,而后由该进程送回内核空间,发往调度分配的目标后端Pod对象。因请求报文在内核空间和用户空间来回转发,所以必然导致模型效率不高,因此现在已经被弃用。

iptables代理模型

创建Service对象的操作会触发集群中的每个kube-proxy并将其转换为定义在所属节点上的iptables规则,用于转发工作接口接收到的、与此Service资源ClusterIP和端口相关的流量。客户端发来请求将直接由相关的iptables规则进行目标地址转换(DNAT)后根据算法调度并转发至集群内的Pod对象之上,而无须再经由kube-proxy进程进行处理,因而称为iptables代理模型。对于每个Endpoints对象,Service资源会为其创建iptables规则并指向其iptables地址和端口,而流量转发到多个Endpoint对象之上的默认调度机制是随机算法。iptables代理模型由Kubernetes v1.1版本引入,并于v1.2版本成为默认的类型。

在iptables代理模型中,Service的服务发现和负载均衡功能都使用iptables规则实现,而无须将流量在用户空间和内核空间来回切换,因此更为高效和可靠,但是性能一般,而且受规模影响较大,仅适用于少量Service规模的集群

ipvs代理模型

Kubernetes自v1.9版本起引入ipvs代理模型,且自v1.11版本起成为默认设置。在此种模型中,kube-proxy跟踪API Server上Service和Endpoints对象的变动,并据此来调用netlink接口创建或变更ipvs(NAT)规则。它与iptables规则的不同之处仅在于客户端请求流量的调度功能由ipvs实现,余下的其他功能仍由iptables完成

ipvs代理模型中Service的服务发现和负载均衡功能均基于内核中的ipvs规则实现。类似于iptables,ipvs也构建于内核中的netfilter之上,但它使用hash表作为底层数据结构且工作于内核空间,因此具有流量转发速度快、规则同步性能好的特性,适用于存在大量Service资源且对性能要求较高的场景。ipvs代理模型支持rr、lc、dh、sh、sed和nq等多种调度算法。

修改代理模型

正常使用kubeadm部署的集群会在kube-system命名空间下生成一个kube-proxy的config,里面会记录代理模型。kubeadm部署默认是iptables,如需要修改可以编辑configmap并逐个重启kube-proxy的pod,当然建议在kubeadm init之前就定义为ipvs或者在集群刚部署完成的时候进行修改,修改完成之后再运行业务pod

[root@k81 yaml]# kubectl -n kube-system edit configmaps kube-proxy 
Edit cancelled, no changes made.
[root@k81 yaml]# kubectl -n kube-system get configmaps kube-proxy -oyaml|grep modemode: ipvs
[root@k81 yaml]# kubectl -n kube-system logs kube-proxy-9rrxd |grep Using
I0222 09:56:25.969094       1 server_others.go:269] "Using ipvs Proxier"

Service资源类型

无论哪一种代理模型,Service资源都可统一根据其工作逻辑分为ClusterIP、NodePort、LoadBalancer和ExternalName这4种类型。

ClusterIP

通过集群内部IP地址暴露服务,ClusterIP地址仅在集群内部可达,因而无法被集群外部的客户端访问。此为默认的Service类型。

NodePort

NodePort类型是对ClusterIP类型Service资源的扩展,它支持通过特定的节点端口接入集群外部的请求流量,并分发给后端的ServerPod处理和响应。因此,这种类型的Service既可以被集群内部客户端通过ClusterIP直接访问,也可以通过套接字<NodeIP>: <NodePort>与集群外部客户端进行通信。显然,若集群外部的请求报文首先到的节点并非Service调度的目标Server Pod所在的节点,该请求必然因需要额外的转发过程(跃点)和更多的处理步骤而产生更多延迟。

另外,集群外部客户端对NodePort发起的请求报文源地址并非集群内部地址,而请求报文又可能被收到报文的节点转发至集群中的另一个节点上的Pod对象,因此,为避免X节点直接将响应报文发送给外部客户端,Y节点需要先将收到的报文的源地址转为请求报文的目标IP(自身的节点IP)后再进行后续处理过程。

LoadBalancer

这种类型的Service依赖于部署在IaaS云计算服务之上并且能够调用其API接口创建软件负载均衡器的Kubernetes集群环境。LoadBalancer Service构建在NodePort类型的基础上,通过云服务商提供的软负载均衡器将服务暴露到集群外部,因此它也会具有NodePort和ClusterIP。简言之,创建LoadBalancer类型的Service对象时会在集群上创建一个NodePort类型的Service,并额外触发Kubernetes调用底层的IaaS服务的API创建一个软件负载均衡器,而集群外部的请求流量会先路由至该负载均衡器,并由该负载均衡器调度至各节点上该Service对象的NodePort。该Service类型的优势在于,它能够把来自集群外部客户端的请求调度至所有节点(或部分节点)的NodePort之上,而不是让客户端自行决定连接哪个节点,也避免了因客户端指定的节点故障而导致的服务不可用。

ExternalName

通过将Service映射至由externalName字段的内容指定的主机名来暴露服务,此主机名需要被DNS服务解析至CNAME类型的记录中。换言之,此种类型不是定义由Kubernetes集群提供的服务,而是把集群外部的某服务以DNS CNAME记录的方式映射到集群内,从而让集群内的Pod资源能够访问外部服务的一种实现方式。因此,这种类型的Service没有ClusterIP和NodePort,没有标签选择器用于选择Pod资源,也不会有Endpoints存在。

总体来说,若需要将Service资源发布至集群外部,应该将其配置为NodePort或Load-Balancer类型,而若要把外部的服务发布于集群内部供Pod对象使用,则需要定义一个ExternalName类型的Service资源,只是这种类型的实现要依赖于v1.7及更高版本的Kubernetes。

应用Service资源

Service是Kubernetes核心API群组(core)中的标准资源类型之一,其管理操作的基本逻辑类似于Namespace和ConfigMap等资源,支持基于命令行和配置清单的管理方式,Service资源配置规范中常用的字段及意义如下所示。

apiVersion: v1
kind: Service
metadata:name:namespace: …labels:<map[string]string>xxx: xxxx
spec:type <string> # Service类型,默认为ClusterIPselector <map[string]string> # 等值类型的标签选择器,内含“与”逻辑ports: # Service的端口对象列表- name <string> # 端口名称protocol <string> # 协议,目前仅支持TCP、UDP和SCTP,默认为TCPport <integer> # Service的端口号targetPort <string> # 后端目标进程的端口号或名称,名称需由Pod规范定义nodePort <integer> # 节点端口号,仅适用于NodePort和LoadBalancer类型clusterIP <string> # Service的集群IP,建议由系统自动分配避免冲突externalTrafficPolicy <string> # 外部流量策略处理方式,Local表示由当前节点处理, Cluster表示向集群范围内调度loadBalancerIP <string> # 外部负载均衡器使用的IP地址,仅适用于LoadBlancerexternalName <string> # 外部服务名称,该名称将作为Service的DNS CNAME值

不同Service类型所支持使用的配置字段有着明显的区别,具体使用时应该根据计划使用的类型进行选择。

应用ClusterIP Service资源

创建Service对象的常用方法有两种:一是利用此前曾使用过的kubectl create servicekubectl expose命令创建,另一个则是利用资源配置清单创建。Service资源对象的期望状态定义在spec字段中,较为常用的内嵌字段为selector和ports,用于定义标签选择器和服务端口。下面的配置清单是定义在services-clusterip-demo.yaml中的一个Service资源示例:

kind: Service
apiVersion: v1
metadata:name: demoapp-svcnamespace: test
spec:selector:app: demoappports:- name: http # 端口名称标识protocol: TCP # 协议,支持TCP、UDP和SCTPport: 80 # Service自身的端口号targetPort: 80 # 目标端口号,即Endpoint上定义的端口号

我们可以将示例中的Service对象创建于集群中,通过其详细描述了解其特性,如下面的命令及结果所示。

[root@k81 yaml]# kubectl apply -f services-clusterip-demo.yaml 
service/demoapp-svc created                             
[root@k81 yaml]# kubectl -n test describe service demoapp-svc 
Name:              demoapp-svc
Namespace:         test
Labels:            <none>
Annotations:       <none>
Selector:          app=demoapp
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                192.168.209.4
IPs:               192.168.209.4
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

上面命令中的结果显示,demoapp-svc默认设定为ClusterIP类型,并得到一个自动分配的IP地址192.168.209.4。创建Service对象的同时会创建一个与之同名且拥有相同标签选择器的Endpoint对象,若该标签选择器无法匹配到任何Pod对象的标签,则Endpoint对象无任何可用端点数据,于是Service对象的Endpoints字段值便成了。我们知道,Service对象自身只是iptables或ipvs规则,它并不能处理客户端的服务请求,而是需要把请求报文通过目标地址转换(DNAT)后转发至后端某个Server Pod,这意味着没有可用的后端端点的Service对象是无法响应客户端任何服务请求的,如下面从集群节点上发起的请求命令结果所示。

[root@k81 yaml]# curl  192.168.209.4
curl: (7) Failed connect to 192.168.209.4:80; Connection refused

下面使用命令式命令手动创建一个与该Service对象具有相同标签选择器的Deployment对象demoapp,它默认会自动创建一个拥有标签app:demoapp的Pod对象。

[root@k81 yaml]#  kubectl create deploy demoapp --image=ikubernetes/demoapp:v1.0 -n test 
deployment.apps/demoapp created
[root@k81 yaml]# kubectl -n test get pod -l app=demoapp -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP             NODE   NOMINATED NODE   READINESS GATES
demoapp-5748b7ccfc-2vq8x   1/1     Running   0          3m20s   172.32.60.52   k82    <none>           <none>
[root@k81 yaml]# kubectl -n test get endpoints demoapp-svc 
NAME          ENDPOINTS         AGE
demoapp-svc   172.32.60.52:80   5m58s
[root@k81 yaml]# kubectl -n test describe service demoapp-svc |grep -i endpoints
Endpoints:         172.32.60.52:80
[root@k81 yaml]# curl  192.168.209.4
iKubernetes demoapp v1.0 !! ClientIP: 172.32.219.0, ServerName: demoapp-5748b7ccfc-2vq8x, ServerIP: 172.32.60.52!

Service对象demoapp-svc通过API Server获知这种匹配变动后,会立即创建一个以该Pod对象的IP和端口为列表项的名为demoapp-svc的Endpoints对象,而该Service对象详细描述信息中的Endpoint字段便以此列表项为值。

扩展Deployment对象demoapp的应用规模引起的变动也将立即反映到相关的Endpoint和Service对象之上,例如将deployments/demoapp对象的副本扩展至3个,再来验证services/demoapp-svc的端点信息,如下面的命令及结果所示。

[root@k81 yaml]# kubectl -n test scale deployment demoapp --replicas=3
deployment.apps/demoapp scaled
[root@k81 yaml]# kubectl -n test get endpoints demoapp-svc 
NAME          ENDPOINTS                                         AGE
demoapp-svc   172.32.105.1:80,172.32.60.52:80,172.32.60.53:80   12m
[root@k81 yaml]# kubectl -n test describe service demoapp-svc |grep -i endpoints 
Endpoints:         172.32.105.1:80,172.32.60.52:80,172.32.60.53:80

接下来可于集群中的某节点上再次向服务对象demoapp-svc发起访问请求以进行测试,多次的访问请求还可评估负载均衡算法的调度效果,如下面的命令及结果所示。

[root@k81 yaml]# while true; do curl -s 192.168.209.4:80/hostname; sleep 1;done
ServerName: demoapp-5748b7ccfc-lmdtm
ServerName: demoapp-5748b7ccfc-246kj
ServerName: demoapp-5748b7ccfc-2vq8x
ServerName: demoapp-5748b7ccfc-lmdtm
ServerName: demoapp-5748b7ccfc-246kj
ServerName: demoapp-5748b7ccfc-2vq8x
ServerName: demoapp-5748b7ccfc-lmdtm

应用NodePort Service资源

部署Kubernetes集群系统时会预留一个端口范围,专用于分配给需要用到NodePort的Service对象,该端口范围默认为30000~32767。与Cluster类型的Service资源的一个显著不同之处在于,NodePort类型的Service资源需要显式定义.spec.type字段值为NodePort,必要时还可以手动指定具体的节点端口号。例如下面的配置清单(services-nodeport-demo.yaml)中定义的Service资源对象demoapp-nodeport-svc,它使用了NodePort类型,且人为指定了32223这个节点端口。

kind: Service
apiVersion: v1
metadata:name: demoapp-nodeport-svcnamespace: test
spec:type: NodePortselector:app: demoappports:- name: httpprotocol: TCPport: 80targetPort: 80nodePort: 32223

将配置清单中定义的Service对象demoapp-nodeport-svc创建于集群之上,以便通过详细描述了解其状态细节。

[root@k81 yaml]# kubectl apply -f demoapp-nodeport-svc.yaml 
service/demoapp-nodeport-svc created
[root@k81 yaml]# kubectl -n test describe service demoapp-nodeport-svc 
Name:                     demoapp-nodeport-svc
Namespace:                test
Labels:                   <none>
Annotations:              <none>
Selector:                 app=demoapp
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       192.168.249.97
IPs:                      192.168.249.97
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  32223/TCP
Endpoints:                172.32.105.1:80,172.32.60.52:80,172.32.60.53:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

命令结果显示,该Service对象用于调度集群外部流量时使用默认的Cluster策略,该策略优先考虑负载均衡效果,哪怕目标Pod对象位于另外的节点之上而带来额外的网络跃点,因而针对该NodePort的请求将会被分散调度至该Serivce对象关联的所有端点之上。可以在集群外的某节点上对任一工作节点的NodePort端口发起HTTP请求以进行测试。以节点k83为例,我们以如下命令向它的IP地址10.10.21.251的32223端口发起多次请求。

[root@k81 yaml]# while true ;do curl -s 10.10.21.251:32223 ;sleep 0.3 ;done
iKubernetes demoapp v1.0 !! ClientIP: 172.32.105.0, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!
iKubernetes demoapp v1.0 !! ClientIP: 172.32.105.0, ServerName: demoapp-5748b7ccfc-2vq8x, ServerIP: 172.32.60.52!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.251, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!
iKubernetes demoapp v1.0 !! ClientIP: 172.32.105.0, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!
iKubernetes demoapp v1.0 !! ClientIP: 172.32.105.0, ServerName: demoapp-5748b7ccfc-2vq8x, ServerIP: 172.32.60.52!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.251, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!
iKubernetes demoapp v1.0 !! ClientIP: 172.32.105.0, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!

上面命令的结果显示出外部客户端的请求被调度至该Service对象的每一个后端Pod之上,而这些Pod对象可能会分散于集群中的不同节点。命令结果还显示,请求报文的客户端IP地址是最先接收到请求报文的节点上用于集群内部通信的IP地址,而非外部客户端地址,这也能在pod应用日志中进一步验证。

[root@k81 yaml]# kubectl -n test logs demoapp-5748b7ccfc-lmdtm |tail -n 5
172.32.219.0 - - [10/Mar/2023 13:26:57] "GET /hostname HTTP/1.1" 200 -
172.32.105.0 - - [10/Mar/2023 13:41:42] "GET / HTTP/1.1" 200 -
172.32.105.0 - - [10/Mar/2023 13:41:43] "GET / HTTP/1.1" 200 -
172.32.105.0 - - [10/Mar/2023 13:41:44] "GET / HTTP/1.1" 200 -
172.32.105.0 - - [10/Mar/2023 13:41:45] "GET / HTTP/1.1" 200 -

确保Server Pod的响应报文必须由最先接收到请求报文的节点进行响应,因此NodePort类型的Service对象会对请求报文同时进行源地址转换(SNAT)和目标地址转换(DNAT)操作

另一个外部流量策略Local则仅会将流量调度至请求的目标节点本地运行的Pod对象之上,以减少网络跃点,降低网络延迟,但当请求报文指向的节点本地不存在目标Service相关的Pod对象时将直接丢弃该报文。下面先把demoapp-nodeport-svc的外部流量策略修改为Local,而后再进行访问测试。这里使用kubectl patch命令来修改Service对象的流量策略。

[root@k81 yaml]# kubectl -n test patch service demoapp-nodeport-svc -p '{"spec":{"externalTrafficPolicy": "Local"}}'
service/demoapp-nodeport-svc patched
[root@k81 yaml]# kubectl -n test get service demoapp-nodeport-svc -oyaml
apiVersion: v1
kind: Service
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"demoapp-nodeport-svc","namespace":"test"},"spec":{"ports":[{"name":"http","nodePort":32223,"port":80,"protocol":"TCP","targetPort":80}],"selector":{"app":"demoapp"},"type":"NodePort"}}creationTimestamp: "2023-03-10T13:38:30Z"name: demoapp-nodeport-svcnamespace: testresourceVersion: "4083129"uid: 7121506b-8ef1-4735-a188-a1f2f22cf5ba
spec:clusterIP: 192.168.249.97clusterIPs:- 192.168.249.97externalTrafficPolicy: Local    # 这里已经通过patch改过来了,如果不习惯用这个命令直接edit也是一样的效果internalTrafficPolicy: ClusteripFamilies:- IPv4ipFamilyPolicy: SingleStackports:- name: httpnodePort: 32223port: 80protocol: TCPtargetPort: 80selector:app: demoappsessionAffinity: Nonetype: NodePort
status:loadBalancer: {}

配置完成后,我们再次发起测试请求时会看到,请求都被调度给了目标节点本地运行的Pod对象。另外,Local策略下无须在集群中转发流量至其他节点,也就不用再对请求报文进行源地址转换,Server Pod所看到的客户端IP就是外部客户端的真实地址。

[root@k81 yaml]# while true ;do curl -s 10.10.21.251:32223 ;sleep 0.3 ;done
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-246kj, ServerIP: 172.32.105.1!^C
[root@k81 yaml]# while true ;do curl -s 10.10.21.250:32223 ;sleep 0.3 ;done
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-2vq8x, ServerIP: 172.32.60.52!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-2vq8x, ServerIP: 172.32.60.52!
iKubernetes demoapp v1.0 !! ClientIP: 10.10.21.249, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!
^C
[root@k81 yaml]# while true ;do curl -s 10.10.21.249:32223 ;sleep 0.3 ;done   # 这里访问的是master节点的地址,由于污点存在,master节点未运行业务pod导致访问失败
^C

应用LoadBalancer Service资源

NodePort类型的Service资源虽然能够在集群外部访问,但外部客户端必须事先得知NodePort和集群中至少一个节点IP地址,一旦被选定的节点发生故障,客户端还得自行选择请求访问其他的节点,因而一个有着固定IP地址的固定接入端点将是更好的选择。此外,集群节点很可能是某IaaS云环境中仅具有私有IP地址的虚拟主机,这类地址对互联网客户端不可达,为此类节点接入流量也要依赖于集群外部具有公网IP地址的负载均衡器,由其负责接入并调度外部客户端的服务请求至集群节点相应的NodePort之上

Service对象的loadBalancerIP负责承接外部发来的流量,该IP地址通常由云服务商系统动态配置,或者借助.spec.loadBalancerIP字段显式指定,但有些云服务商不支持用户设定该IP地址,这种情况下,即便提供了也会被忽略。外部负载均衡器的流量会直接调度至Service后端的Pod对象之上,而如何调度流量则取决于云服务商,有些环境可能还需要为Service资源的配置定义添加注解,必要时请自行参考云服务商文档说明。另外,LoadBalancer Service还支持使用.spec.loadBalancerSourceRanges字段指定负载均衡器允许的客户端来源的地址范围。我这边由于暂时没有云厂商的IaaS环境就只能先写一个简单的demo了。

kind: Service
apiVersion: v1
metadata:name: demoapp-lb-svcnamespace: test
spec:type: LoadBalancerselector:app: demoappports:- name: httpprotocol: TCPport: 80targetPort: 80
[root@k81 yaml]# kubectl get svc demoapp-lb-svc -n test 
NAME             TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
demoapp-lb-svc   LoadBalancer   192.168.101.64   <pending>     80:31816/TCP   3m4s

外部IP

若集群中部分或全部节点除了有用于集群通信的节点IP地址之外,还有可用于外部通信的IP地址(例如云厂商的EIP),那么我们还可以在Service资源上启用spec.externalIPs字段来基于这些外部IP地址向外发布服务。所有路由到指定的外部IP(externalIP)地址某端口的请求流量都可由该Service代理到后端Pod对象之上。从这个角度来说,请求流量到达外部IP与节点IP并没有本质区别,但外部IP却可能仅存在于一部分的集群节点之上,而且它不受Kubernetes集群管理,需要管理员手动介入其配置和回收等操作任务中。

外部IP地址可结合ClusterIP、NodePort或LoadBalancer任一类型的Service资源使用,而到达外部IP的请求流量会直接由相关联的Service调度转发至相应的后端Pod对象进行处理。假设示例Kubernetes集群中的k81节点上拥有一个可被路由到的IP地址10.10.21.249,我们期望能够将demoapp的服务通过该外部IP地址发布到集群外部,则可以使用下列配置清单(services-externalip-demo.yaml)中的Service资源实现。

kind: Service
apiVersion: v1
metadata:name: demoapp-externalip-svcnamespace: test
spec:type: ClusterIPselector:app: demoappports:- name: httpprotocol: TCPport: 80targetPort: 80externalIPs:- 10.10.21.249

现在找集群外的一个节点进行访问测试

[zettakit@rocky1 ~]$ curl 10.10.21.249
iKubernetes demoapp v1.0 !! ClientIP: 172.32.219.0, ServerName: demoapp-5748b7ccfc-lmdtm, ServerIP: 172.32.60.53!
[zettakit@rocky1 ~]$ curl 10.10.21.250
curl: (7) Failed to connect to 10.10.21.250 port 81: Connection refused
[zettakit@rocky1 ~]$ curl 10.10.21.251
curl: (7) Failed to connect to 10.10.21.251 port 81: Connection refused

可以看到只有定义了的地址能成功访问,其他集群中未定义的节点是访问不了的。不难猜测,节点k81故障也必然导致该外部IP上公开的服务不再可达,除非该IP地址可以浮动到其他节点上。如今,大多数云服务商都支持浮动IP的功能,该IP地址可绑定在某个主机,并在其故障时通过某种触发机制自动迁移至其他主机。

相关文章:

kubernetes中service探讨

文章目录序言kube-proxy代理模型userspace代理模型iptables代理模型ipvs代理模型修改代理模型Service资源类型ClusterIPNodePortLoadBalancerExternalName应用Service资源应用ClusterIP Service资源应用NodePort Service资源应用LoadBalancer Service资源外部IP序言 在Kuberne…...

Python3实现“美颜”功能

导语利用Python实现美颜。。。这是之前在GitHub上下载的一个项目。。。似乎有些日子了。。。所以暂时找不到原项目的链接了。。。今天抽空看了下它源代码的主要思想&#xff0c;似乎挺简单的。。。于是决定用Python3自己复现一下。。。T_T感觉还是挺有趣的。。。Just have a tr…...

【创建“待选项”按钮02计算坐标 Objective-C语言】

一、之前,我们已经把“待选项”按钮,创建好了,但是唯一的问题是,坐标都是一样的,所以都显示在一起了 1.下面,我们来设置一下,这些“待选项”按钮的坐标, 现在,“待选项”按钮的坐标,是不是都在同一个位置啊, 回忆一下,这个待选项按钮,是怎么生成的, 首先,是在…...

自组织( Self-organization),自组织临界性(Self-organized criticality)

文章目录1. 自组织概述原则历史按领域物理化学生物学2. 自组织临界性概述3. 自组织临界性的特征4. 自组织临界模型5. 自然界中的自组织临界6. 自组织临界性和优化7. 自组织临界性的控制7.1 方案7.2 应用1. 自组织 wiki: Self-organization 图 200 C 水热处理过程中微米级 Nb3O…...

Elasticsearch:集群管理

在今天的文章中&#xff0c;我们应该学习如何管理我们的集群。 备份和分片分配是我们应该能够执行的基本任务。 分片分配过滤 Elasticsearch 将索引配到一个或多个分片中&#xff0c;我们可以将这些分片保存在特定的集群节点中。 例如&#xff0c;假设你有多个数据集群节点&am…...

华为OD机试题 - 非严格递增连续数字序列(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:非严格递增连续数字序列题目输入输出示例一输入输出说明Code解题…...

lc23. 合并K个升序链表

题目描述给你一个链表数组&#xff0c;每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。示例 1&#xff1a;输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]]输出&#xff1a;[1,1,2,3,4,4,5,6]解释&#xff1a;链表数组如下&…...

Java笔记029-泛型

泛型泛型的理解和好处看一个需求请编写程序&#xff0c;在ArrayList中&#xff0c;添加3个Dog对象Dog对象含有name和age&#xff0c;并输出name和age(要求使用getXxx)先用传统的方法来解决->引出泛型package com15.generic;import java.util.ArrayList;/*** author 甲柒* ve…...

港科夜闻|香港科大与中国联通成立联合实验室,推动智慧社会研究发展

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、香港科大与中国联通成立联合实验室&#xff0c;推动智慧社会研究发展。香港科大与中国联通于3月9日签署两份协议以加强战略合作&#xff0c;并成立「香港科技大学 - 中国联通智慧社会联合实验室」&#xff0c;就香港科大建构…...

制作一个简单的信用卡验证表

下载:https://download.csdn.net/download/mo3408/87559584 效果图: 您可以从文章顶部附近的下载按钮获取该项目的完整代码。这些文件的概述如下所示: 我们需要将两个 .css 文件和两个 .js 文件包含在我们的 HTML 中。所有其他资源,例如 Bootstrap 框架、jQuery 和 Web 字…...

牛客小白月赛68

牛客小白月赛68A Tokitsukaze and New OperationB Tokitsukaze and Order Food DeliveryC Tokitsukaze and Average of SubstringD Tokitsukaze and Development TaskE Tokitsukaze and Colorful ChessboardF Tokitsukaze and New RenKinKama题目链接A Tokitsukaze and New Ope…...

【id:21】【20分】A. DS单链表--类实现

题目描述用C语言和类实现单链表&#xff0c;含头结点属性包括&#xff1a;data数据域、next指针域操作包括&#xff1a;插入、删除、查找注意&#xff1a;单链表不是数组&#xff0c;所以位置从1开始对应首结点&#xff0c;头结点不放数据类定义参考输入n第1行先输入n表示有n个…...

【实习_面试全程辅导分享】简历篇

🎋🎋哈喽,大家好,我是辰柒。快有一个月没有更新博文啦,那么这一个月不是在偷懒,而是在全心准备找实习的过程中。那么最终也是拿到了心仪的大厂offer——海康威视!!经过这次找实习的经历,我想就在校大学生找实习这件事情开设一个专栏,帮助大家在找实习的过程中减少焦…...

【学习笔记】CF1305 Kuroni and Antihype

想了一下&#xff0c;觉得还是发单篇的题解比较合理 怎么感觉这题之前做过 先抛开建边方式不管 这一步其实挺重要的&#xff0c;但是可能大多数人独立做这道题的时候都在想用位运算的性质&#xff0c;而没有想到分开考虑吧&#xff1f;&#xff0c;考虑新建000号节点&#xf…...

json-server单独使用或者在react中进行使用

json-serverjson-server使用教程修改json-server端口号启动1、全局安装json-server2、在根目录生成一个db.json3、启动 访问react中进行使用react中修改json-server启动端口号1、 第一步也是安装&#xff0c;和第一种一样2、在根路径下定义一个__json_server_mock__文件夹3、在…...

【6G 新技术】6G数据面介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…...

【AI绘图学习笔记】深度前馈网络(一)

有关深度前馈网络的部分知识&#xff0c;我们已经在吴恩达的机器学习课程中有过了解了&#xff0c;本章主要是对《深度学习》花书中第六章&#xff1a;深度前馈网络的总结笔记。我希望你在看到这一章的时候&#xff0c;能回忆起机器学习课程中的一些环节或者细节&#xff0c;这…...

目标检测笔记合集

目标检测笔记合集1. 必看的两篇目标检测论文2. 必速看的深度学习目标检测的论文集及概述2.1 一份Slide&#xff08;PPT)两张表格带你快速了解目标检测2.2 最新目标检测算法回顾2022笔记合集3.目标检测的应用与需求4.目标检测的定义与挑战5.目标检测损失函数的进展6.目标检测IOU…...

《计算机网络》期末复习笔记

文章目录一、一些英文名词的标签&#xff08;方便记忆&#xff09;二、OSI七层协议三、综合题3.0 知识点储备3.1 在Internet 网中&#xff0c;某计算机的IP 地址是11001010.01100000.00101100.01011000 &#xff0c;请回答下列问题3.2 假定发送方要发送的数据为10000101。采用C…...

linux下安装SonarQube

目录1. 准备安装环境2. 安装postgres数据库3. 安装SonarQube4. 使用SonarQube1. 准备安装环境 这里安装SonarQube的系统环境是Red Hat Enterprise Linux release 8.7 &#xff0c;然后将jdk的压缩包&#xff08;jdk-17.0.2_linux-x64_bin.tar.gz&#xff09;和sonarQube的压缩…...

MyBatis-Plus(狂神)

一.特点 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响&#xff0c;如丝般顺滑损耗小&#xff1a;启动即会自动注入基本 CURD&#xff0c;性能基本无损耗&#xff0c;直接面向对象操作强大的 CRUD 操作&#xff1a;内置通用 Mapper、通用 Serv…...

Python3实现写作

导语T_T没有科研梦想的人半夜过来水篇文章~~~让Python学会写写歌&#xff0c;创创作~~~纯属娱乐~~~改编自PyTorch官网的一个教程&#xff0c;不过我用TF写的&#xff0c;然后生成英文变成了生成中文~~~Lets Go~~~相关文件百度网盘下载链接: https://pan.baidu.com/s/1VUEFR82Cq…...

UEFI实战--------HII之uni文件

uni文件 HII的实现涉及到多种不同类型的文件&#xff0c;uni文件是其中最简单的一种&#xff0c;它用来存放各种语言的字符串以实现本地化。本节主要参考自《edk-ii-uni-specification.pdf》&#xff0c;后面简称为参考文档。 关于uni文件的作用&#xff0c;在参考文档中做了如…...

基于Spring Boot集成MyBatis-3.5.9操作数据库

记录&#xff1a;382场景&#xff1a;在Spring Boot 2.6.3中集成MyBatis 3.5.9操作数据库。实现MyBatis的查、增、改、删操作数据库示例。MyBatis官网&#xff1a;http://www.mybatis.org/MyBatis源码&#xff1a;https://github.com/mybatis/1.初始化准备1.1创建Maven工程使用…...

了解国外SEO负面压制的现状与应对策略!

随着全球化的发展&#xff0c;越来越多的企业和品牌开始将目光转向海外市场&#xff0c;而谷歌作为全球最大的搜索引擎之一&#xff0c;也成为了外贸企业最主要的搜索引擎之一。 然而&#xff0c;随着谷歌的不断发展&#xff0c;国外SEO负面压制的现状也愈发严峻&#xff0c;外…...

Yolov5-交通标志检测与识别

项目介绍 上一篇文章介绍了基于卷积神经网络的交通标志分类识别Python交通标志识别基于卷积神经网络的保姆级教程&#xff08;Tensorflow&#xff09;&#xff0c;并且最后实现了一个pyqt5的GUI界面&#xff0c;并且还制作了一个简单的Falsk前端网页实现了前后端的一个简单交互…...

Linux内核Thermal框架详解五、Thermal Core(4)

本文部分内容参考Linux Thermal 学习笔记 - 爱码网。特此致谢&#xff01; 接前一篇文章Linux内核Thermal框架详解四、Thermal Core&#xff08;3&#xff09; 三、相关源码及分析 2. thermal_register_governors 上一回说到这一段代码&#xff1a; for (__governor __gove…...

gcc 编译的过程

#include <stdio.h> #define PI 3.14 int main(int argc, char const *argv[]) { //打印IP的值printf("PI %lf\n", PI);return 0; }编译的过程&#xff1a;预处理、编译、汇编、链接1.预处理&#xff1a;宏替换、删除注释、头文件包含、条件编译 -E &#xf…...

Hadoop入个门

文章目录1️⃣、Hadoop概述1.1、Hadoop是什么1.2、三大发行版本1.3、优势1.4、组成HDFSYARNMapReduceHDFS、YARN、MapReduce三者关系1.6、大数据技术生态体系image-202303111027195802️⃣、Hadoop运行环境搭建2.1、虚拟机环境准备2.2、克隆虚拟机2.3、在hadoop2上安装JDK2.4、…...

python 从0到批量下载某站视频

简介&#xff1a;真实从0到1&#xff0c;童叟无欺&#xff5e; 目标&#xff1a;用python批量下载某站搜索视频&#xff0c;以“CG 服装”为例 本章主要介绍如何用python把搜索到的视频直接下载到自己的本地文件夹中&#xff5e; 介绍一下工作流1. 下载并安装python2. 测试pyt…...

【深度学习】神经网络和深度学习--卷积和池化的作用

深度学习通常指训练大型深度的神经网络的过程。 与传统的神经网络模型相比&#xff0c;深度学习模型在结构上与之非常相似&#xff1b;不同的是&#xff0c;深度学习模型的“深度”更大&#xff0c;“深度”的体现就是神经网络层数多&#xff0c;神经网络每一层的结点数多。 本…...

锦正茂风冷系列电源JCP-10-80的技术参数

JCP-10-80为高稳定度的双极性恒流电源&#xff0c;广泛应用于电磁铁、亥姆霍兹线圈等感性负载的励磁。电源采用线性电源结构&#xff0c;输出电流稳定度高&#xff0c;纹波和噪声低。电源输出电流可在正负额定电流*值之间连续变化&#xff0c;电流平滑连续过零&#xff0c;可使…...

Idea+maven+spring-cloud项目搭建系列--11-1 dubbo(zookeeper,nacos)注册中心

前言&#xff1a;dubbo rpc 服务需要将服务提供者和消费者信息进行注册&#xff0c;以便于消费端可以完成远程接口调用&#xff1b;注册中心是 Dubbo 服务治理的核心组件&#xff0c;Dubbo 依赖注册中心的协调实现服务&#xff08;地址&#xff09;发现&#xff0c;自动化的服务…...

Python3入门教程||Python3 迭代器与生成器||Python3 函数

Python3 迭代器与生成器 迭代器 迭代是 Python 最强大的功能之一&#xff0c;是访问集合元素的一种方式。。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问&#xff0c;直到所有的元素被访问完结束。迭代器只能往前不会后退。 迭代器有两…...

快速幂算法

快速幂算法 文章目录快速幂算法一、简单介绍二、计算7107^{10}710三、一般化1、计算ana^nan的快速方法&#xff1a;2、时间复杂度分析&#xff1a;四、代码五、参考资料一、简单介绍 ​ 快速幂&#xff08;Exponentiation by squaring&#xff0c;平方求幂&#xff09;是一种简…...

Hudi:问题总结(2)Flink-1.13.1消费kafka并插入hudi

问题一&#xff1a;java.lang.ClassNotFoundException: com.google.protobuf.MessageOrBuilder) 解决&#xff1a;字面意思&#xff0c;没找到类&#xff0c;将protobuf-java-3.2.0-jar包放到fink/lib/下 如果报commons-cli相关的错&#xff0c;就将commons-cli-1.4.jar放到f…...

Application工具方法

//注册这个接口registerActivityLifecycleCallbacks(activityLifecycleCallbacks);}Overridepublic void onTerminate() {//注销这个接口。unregisterActivityLifecycleCallbacks(activityLifecycleCallbacks);super.onTerminate();}public static List<Activity> activi…...

电脑游戏怎么录屏?其实很简单,只需要简单3步

电脑游戏一直是游戏爱好者最热衷的游戏之一。但是&#xff0c;有时候我们想分享我们在游戏中的精彩时刻&#xff0c;或者记录我们的游戏过程以便后续观看和学习。在这种情况下&#xff0c;录屏就成了必不可少的工具。但是&#xff0c;许多人可能不知道电脑游戏怎么录屏。在本文…...

【设计模式】go语言中的 [函数选项,单例,工厂,责任链] 常用的设计模式

文章目录前言一、函数选项模式二、单例模式三、工厂模式四、责任链模式前言 宿舍每人 温度38℃&#xff0b; 大寄 设计模式很重要&#xff0c;设计模式其实就是为了解决某一类问题而形成的代码写法&#xff0c;设计模式很多&#xff0c;但是并不是每个都很常用&#xff0c;我们…...

2017系统分析师案例分析真题背记内容

前言 以下内容仅为个人根据当年系分案例真题问题整理的偏需要记背的考点答案&#xff0c;方便个人背诵和记忆使用。方便文字转语音&#xff0c;所以内容全为纯文字内容&#xff0c;以下内容仅供参考。 背记内容 微服务 微服务中应该包含的内容有&#xff1a;资源、对资源的…...

C++和C的区别

答&#xff1a;从宏观角度和微观角度分析微观角度&#xff1a;函数原型有区别&#xff0c;在c中&#xff0c;函数原型有参数和没有参数是不同的&#xff0c;并且允许申明多个同名的函数&#xff0c;只要他们的参数列表不同或者返回值不同即可&#xff0c;但是在c语言中不能。C引…...

【React教程】一、React简介

一、React简介 React是一个用于构建用户界面的JavaScript库&#xff0c;它是Facebook的内部项目&#xff0c;用来架设Instagram的网站,并于2013年5月开源。React主要用于构建Ul&#xff0c;很多人认为React 是 MVC 中的 V&#xff08;视图&#xff09;。由于拥有较高的性能&…...

运动蓝牙耳机什么牌子好,比较好的运动蓝牙耳机推荐

现在市面上的运动蓝牙耳机越来越多&#xff0c;在选择耳机的时候应该如何入手呢&#xff1f;最重要的是需要按照自己的需求来选择&#xff0c;但在耳机的配置上不能忽视的是耳机的防水等级&#xff0c;运动耳机对防水等级的要求更高&#xff0c;这样能够更好地防御汗水浸湿耳机…...

[深入理解SSD系列 闪存实战2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?

前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...

DJI ROS dji_sdk 源码分析|整体框架

DJI ROS dji_sdk 源码分析|整体框架launch文件CMakeLists.txtcpp文件main.cppOSDK 是一个用于开发无人机应用程序的开发工具包&#xff0c;基于OSDK 开发的应用程序能够运行在机载计算机上&#xff08;如Manifold 2&#xff09;&#xff0c;开发者通过调用OSDK 中指定的接口能够…...

HT32合泰单片机开发环境搭建和配置教程

HT32合泰(Holtek)单片机开发环境搭建安装教程 前言 最近在准备合泰杯的比赛&#xff0c;在看合泰官方的PPT和数据手册学习&#xff0c;顺便做个合泰单片机的开发环境搭建教程。 合泰杯比赛发放的开发板是ESK32-30501&#xff0c;用的单片机是HT32F52352。 合泰杯官网地址&a…...

动态内存分配之伙伴算法

伙伴算法 伙伴算法是一种在计算机内存管理中使用的算法&#xff0c;用于分配和释放内存。它是一种基于二叉树的动态内存分配算法&#xff0c;可以高效地分配和合并内存块。伙伴算法是一种按照固定大小分配内存的算法&#xff0c;例如&#xff0c;每个内存块的大小为2的n次幂&a…...

CGAL 根据扫描线方向和角度对法向量进行重定向

目录一、算法原理1、主要函数二、代码实现一、算法原理 最小生成树对法向量定向的结果在具有许多尖锐特征和遮挡的机载点云数据中结果并不理想。scanline_orient_normals()是专门用于具有扫描线特性的点云法向量重定向的替代方法。它充分利用了某些激光雷达扫描器的LAS特性&…...

一个C#开发的开源的快速启动工具

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 平常计算机安装软件比较多、或者工作涉及的文件比较多&#xff0c;很多人都会直接放在桌面&#xff0c;一方面不安全&#xff0c;还不容易查找&#xff0c;这时候我们往往&#xff0c;都会放在其他硬盘内&#x…...

Paddle项目调试记录

PaddlePaddle是百度公司提出的深度学习框架。近年来深度学习在很多机器学习领域都有着非常出色的表现&#xff0c;在图像识别、语音识别、自然语言处理、机器人、网络广告投放、医学自动诊断和金融等领域有着广泛应用。面对繁多的应用场景&#xff0c;深度学习框架有助于建模者…...