在kubernets中,Pod是应用程序的载体,Pod你可以想象成就是容器,为动态的一组Pod提供一个固定的访问入口,它是以一种叫ClusterIP地址来进行标识,而ClusterIP就位于我们集群网络(Cluster Network)当中,我们可以通过Pod的IP地址来进行访问,但是会遇到问题:
为了解决这个问题,K8s提供了Service资源,Service为动态的一组Pod提供一个固定的访问入口;这个固定的访问入口可以理解为是一组应用的前端的负载均衡器;就像LVS或Nginx为一组ReadyServer做负载均衡器是一样的,你是看不见的,可以理解为Service就是负载均衡器,但是这种负载均衡器比传统的负载均衡器要强大;Service资源通过"标签选择器Label Selector"把筛选出来的符合条件的一组Pod对象定义成一个逻辑集合,而后Service对外提供自己的IP和端口。

当客户端请求Service的IP和端口时,Service将请求调度给标签匹配的所有的Pod,Service向客户端隐藏了真实处理请求的Pod资源,使得客户端的请求看上去是由Service直接处理并进行响应。
Service对象的IP地址(Cluster IP或Service IP)是虚拟IP地址,由kubernetes系统在Service对象创建时在专有网络(Service Network)地址中自动分配或由用户手动指定,其次Service是基于端口过滤,并根据事先定义好的规则将请求转发至其后端Pod对应的端口上,因此这种代理机制也称为"端口代理"或"四层代理"工作在TCP/IP协议栈的传输层;
1.7.1UserSpace
apiVersion: v1 # API的版本
kind: Service # 资源类型定义为Service
metadata:
name: ... # Serivce的名称
namespace: ... # 默认的default
labels:
key1: value1 # 标签 key:value格式;
key2: value2
spec:
type <string> # Service类型,默认为ClusterIP;
selector <map[string]string> # 标签选择器
ports: # ClusterIP:ServicePort
targetPort: <string> #后端目标进程的端口号或名称。
nodePort: <integer> # 节点端口号,仅适用于NodePort和loadbalancer类型。 "建议动态选择30000-32767"
clusterIP <string> # Service的集群IP,建议由系统自动分配
externalTrafficPolicy <string> # 外部流量策略处理方式,local表示由当前节点处理,cluster表示向集群范围调度
loadBalancerIP <string> # 外部负载均衡器使用的IP地址,仅适用于loadbalancer,前提是你的公有云得支持你自己指定;
externalName <string> # 外部服务名称,该名称作为Service的DNS CNAME值
ClusterIP: 通过集群内部IP暴露服务,选择ServiceIP只能够在集群内部访问,这也是默认的Service类型;该地址仅在集群内部可见、可达。无法被集群外部客户端访问;而且是默认类型,创建的任何Service默认就是ClusterIP类型,而且只能接受集群内部客户端的访问。
root@kubernetes-master01:~# cat services-clusterip-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-clusterip
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: default
spec:
clusterIP:
selector: # 标签选择器
app: nginx
ports:
- name: http # 端口名称
protocol: TCP # 协议类型,目前支持TCP、UDP、SCTP默认为TCP
port: 80 # Service的端口号
targetPort: 80 # 后端目标进程的端口号
root@kubernetes-master01:~# kubectl apply -f services-clusterip-nginx.yaml
pod/nginx-clusterip created
service/nginx-svc created
2.2.1.1查看Service;
root@kubernetes-master01:~# kubectl get svc
nginx-svc ClusterIP 10.106.70.164 <none> 80/TCP 3m
2.2.1.2 可以看到后端就一个Pod;
root@kubernetes-master01:~# kubectl get pods --show-labels -l app=nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-clusterip 1/1 Running 0 8m58s 10.244.4.49 kubernetes-node01 <none> <none> app=nginx
2.2.1.3查看Endpoint资源,Endpoints可以简写为ep;
root@kubernetes-master01:~# kubectl get endpoints
nginx-svc 10.244.4.49:80 10m
2.2.1.4测试访问;只能在集群内部访问,外部无法访问;
root@kubernetes-master01:~# curl -I 10.106.70.164
HTTP/1.1 200 OK
Server: nginx/1.21.5
Content-Type: text/html
Content-Length: 615
Connection: keep-alive
ETag: "61cb5be0-267"
Accept-Ranges: bytes
NodePort即是节点Port,通常在安装集群系统会预留一个端口范围用于NodePort,默认是3000-32767之间,与ClusterIP类型的可省略.spec.type属性所不同的是,定义NodePort类似的Service资源时,需要通过此属性明确指定其类型名称,示例如下:
root@kubernetes-master01:~# cat services-nodeport-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport-svc
namespace: default
spec:
type: NodePort
clusterIP:
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80 # 后端Pod监听什么端口就写什么端口。要不然到达Service的请求转发给Pod,Pod没有那个端口也没用。一定真正转发到后端程序监听的端口。如果没有特殊情况的话,ServicePort和TargetPort保持一致。NodePort可以不用指定。
nodePort: # 正常情况下应由系统自己分配,除非事先能够明确知道它不会与某个现存的Service资源产生冲突,没有特别需求,留给系统自动配置总是好的选择。
root@kubernetes-master01:~# kubectl apply -f services-nodeport-nginx.yaml
service/nginx-nodeport-svc created
2.3.1.1查看Service,意味着访问宿主机任一节点的IP+NodePort端口就可以访问服务;对于集群内的Pod客户端来说,依然可以通过ClusterIP对其进行访问;
root@kubernetes-master01:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 36d
nginx-nodeport-svc NodePort 10.111.124.121 <none> 80:32049/TCP 5s
nginx-svc ClusterIP 10.106.70.164 <none> 80/TCP 34m
2.3.1.2 测试,这是windows的命令行,也是没有问题;
C:\Users\海棠>curl -I 10.0.0.1xx:30824
HTTP/1.1 200 OK
Server: nginx/1.21.5
Content-Type: text/html
Content-Length: 615
Connection: keep-alive
ETag: "61cb5be0-267"
Accept-Ranges: bytes
loadBalancer: 这类Service依赖云厂商,需要通过云厂商调用API接口创建软件负载均衡将服务暴露到集群外部,当创建LoadBalancer类型的Service对象时,它会在集群上自动创建一个NodePort类型的Service,集群外部的请求流量会先路由至该负载均衡,并由该负载均衡调度至各个节点的NodePort;
root@kubernetes-master01:~# cat services-loadbalancer-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer-svc
namespace: default
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
loadBalancerIP: 1.2.3.4
2.4.1.2测试访问;
# 我们还是只能是通过NodePort来访问,因为没有LoadBalancer的IP;
# LoadBalancer其实就是一个增强的NodePort。而LoadBalancer没有限制流量调度策略的。外部流量策略对loadbalancer依然使用,因为LoadBalancer首先是一个NodePort的Service。
C:\Users\冷雨夜>curl -I 10.0.0.1XX:31943
HTTP/1.1 200 OK
Server: nginx/1.21.5
Content-Type: text/html
Content-Length: 615
Connection: kep-alive
ETag: "61cb5be0-267"
Accept-Ranges: bytes
此类型不是用来定义如何访问集群内服务的,而是把集群外部的某些服务以DNS CANME方式映射到集群内,从而让集群内的Pod资源能够访问外部服务的一种实现方式。
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or