kubernetes Services

功能概述
kubernetes Services服务提供VIP访问对应的POD的功能,这种做法是非常好的,因为后台的POD不会是一成不变的,比如升级服务的时候POD的IP会改变,要访问到对应的服务的POD那就得改对应的IP,而kubernetes Services正是为此而生,很好得解决了这个问题。

对于Kubernetes原生应用程序,Kubernetes提供了一个简单的Endpoints API,只要服务中的Pod集合发生更改,该API就会更新。 对于非本机应用程序,Kubernetes提供了一个基于虚拟IP的网桥,用于重定向到后端Pod的服务。

定义Service

kind: Service
apiVersion: v1
metadata:
  name: my-service //名字
spec:
  selector:
    app: MyApp //选择带有label 为app: MyApp的值的pods
  ports:
  - protocol: TCP //协议
    port: 80  //内部端口
    targetPort: 9376  //暴露的端口 默认port的值相同

kubernetes Services支持TCP UDP协议,默认是TCP协议

kubernetes Services通常抽象化访问Kubernetes Pods,但它也可以抽象其他种类的后端。 例如:

  1. 您想要在生产中使用外部数据库群集,但在测试中您使用自己的数据库。
  2. 您希望将您的服务指向另一个名称空间或另一个群集中的服务。
  3. 您正在将工作负载迁移到Kubernetes,而您的一些后端运行在Kubernetes之外。

在以上三种情况下,可以做如下处理:
定义一个没有selector的Service

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

由于这些Services没有选择对应的PODS,因此 Endpoints是没有生成的,因此可以手动将服务映射到您自己的特定端点:

kind: Endpoints
apiVersion: v1
metadata:
  name: my-service
subsets:
  - addresses:
      - ip: 1.2.3.4
    ports:
      - port: 9376

在没有选择器的情况下访问服务就像它有一个选择器一样工作。 流量将被路由到用户定义的端点

ExternalName服务是没有选择器的特殊服务。 它没有定义任何端口或端点。 相反,它可以作为将别名返回到驻留在群集外部的外部服务的一种方式。
例如:

kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

对于这种Service,查找主机my-service.prod.svc.CLUSTER时,集群DNS服务将返回值为my.database.example.com的CNAME记录。 访问这种服务的方式与其他服务一样,唯一的区别在于重定向发生在DNS级别,并且没有代理或转发发生。 如果您稍后决定将数据库移动到群集中,则可以启动它的容器,添加适当的选择器或端点并更改服务类型。

虚拟IP和服务代理

Proxy-mode: userspace
在此模式下,kube-proxy监视Kubernetes master 以添加和删除Service和Endpoints对象。 对于每个服务,它会在本地节点上打开一个端口(随机选择)。 与此“代理端口”的任何连接都将代理到服务的后端Pod之一(如端点中所报告的)。 根据服务的SessionAffinity决定使用哪个后端Pod。 最后,它安装了iptables规则,这些规则将流量捕获到服务的clusterIP(这是虚拟的)和Port,并将该流量重定向到代理后端Pod的代理端口。 默认情况下,后端的选择是循环法。

Proxy-mode: iptables
在此模式下,kube-proxy监视Kubernetes master以添加和删除Service和Endpoints对象。 对于每个服务,它都会安装iptables规则,这些规则将流量捕获到服务的clusterIP(这是虚拟的)和端口,并将该流量重定向到服务的后端集合之一。 对于每个Endpoints对象,它都会安装选择后端Pod的iptables规则。 默认情况下,后端的选择是随机的。

显然,iptables不需要在用户空间和内核空间之间切换,它应该比用户空间代理更快,更可靠。 但是,与用户空间连接器不同,如果iptables连接器最初选择的连接器不响应,iptables连接器不能自动重试另一个连接,因此它依赖于正在工作的准备就绪探测器。

Proxy-mode: ipvs
在这种模式下,Kubernetes Services和Endpoints调用netlink接口来相应地创建ipvs规则,并定期与Kubernetes Services和Endpoints同步ipvs规则,以确保ipvs状态与预期一致。当访问服务时,流量将被重定向到其中一个后端Pod。

与iptables类似,Ipvs基于netfilter钩子函数,但使用散列表作为基础数据结构并在内核空间中工作。这意味着ipvs可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs为负载均衡算法提供了更多选项,例如:

rr:循环法
lc:最少连接
dh:目标哈希
sh:源哈希
sed:预计的最短延迟
nq:从不排队
注意:在运行kube-proxy之前,ipvs模式假定在节点上安装了IPVS内核模块。当kube-proxy以ipvs代理模式启动时,kube-proxy会验证节点上是否安装了IPVS模块,如果未安装,kube-proxy将回退到iptables代理模式。

Multi-Port Services
许多服务需要公开多个端口。 对于这种情况,Kubernetes支持Service对象上的多个端口定义。 使用多个端口时,您必须提供所有端口名称,以便可以消除端点的歧义,例如:

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 9376
  - name: https
    protocol: TCP
    port: 443
    targetPort: 9377

Choosing your own IP address

您可以将自己的群集IP地址指定为服务创建请求的一部分。设置spec.clusterIP字段。例如,如果您已经有一个想要替换的现有DNS条目,或者已配置了特定IP地址并且难以重新配置的旧系统。用户选择的IP地址必须是有效的IP地址,并且位于由API标记指定给API服务器的service-cluster-ip-range CIDR范围内。如果IP地址值无效,则apiserver将返回一个422 HTTP状态码,以指示该值无效。

为什么不使用循环法DNS?
一个不时出现的问题就是为什么我们用虚拟IP来完成所有这些工作,而不仅仅是使用标准的循环法DNS。有几个原因:

DNS库不不支持DNS TTL并缓存名称查找的结果有很长的历史。
许多应用程序只执行一次DNS查找并缓存结果。
即使应用程序和库进行了适当的重新解析,每个客户端重复解析DNS的负载也难以管理。

Discovering services
Kubernetes支持2种主要模式来查找服务: 环境变量和DNS。

环境变量
当Pod在节点上运行时,kubelet将为每个活动的服务添加一组环境变量。 它支持Docker链接兼容变量(请参阅makeLinkVariables)和更简单的{SVCNAME} _SERVICE_HOST{SVCNAME} _SERVICE_PORT变量,其中服务名称为上限,破折号转换为下划线。

例如,暴露TCP端口6379且已分配了群集IP地址10.0.0.11的服务“redis-master”会生成以下环境变量:

REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11

但是这种方式有种限制:
任何Pod想要访问的服务都必须在Pod本身之前创建,否则环境变量将不会被填充。 DNS没有这个限制。

DNS

DNS服务器是k8s集群插件。 DNS服务器为watch new Service Kubernetes API并为每个服务创建一组DNS记录。 如果在整个集群中启用了DNS,则所有的Pod应该能够自动进行服务的名称解析。

例如,如果您在Kubernetes命名空间“my-ns”中有一个名为“my-service”的服务,则会创建“my-service.my-ns”的DNS记录。 存在于“my-ns”命名空间中的Pod应该能够通过简单地为“my-service”进行名称查找来找到它。 存在于其他命名空间中的Pod必须将该名称限定为“my-service.my-ns”。 这些名称查找的结果是群集IP。

Kubernetes还支持命名端口的DNS SRV(服务)记录。 如果“my-service.my-ns”服务的TCP端口名为“http”,则可以对“_http._tcp.my-service.my-ns”执行DNS SRV查询以发现端口号“HTTP”。

Headless services

有时你不需要或不需要负载平衡和单一服务IP。 在这种情况下,您可以通过为群集IP(spec.clusterIP)指定 None来创建 Headless services 服务。

该选项允许开发人员通过允许他们自由发现自己的方式来减少与Kubernetes系统的耦合。 应用程序仍然可以使用自注册模式,而其他发现系统的适配器可以轻松构建在此API上。

对于此类服务,群集IP未分配,kube-proxy不处理这些服务,并且平台没有为它们执行负载平衡或代理。 DNS如何自动配置取决于服务是否具有已定义的选择器。

Publishing services - service types

对于应用程序的某些部分(例如前端),您可能希望将服务公开到外部(群集外部)IP地址。

Kubernetes ServiceTypes允许您指定您想要的服务类型。默认是ClusterIP

Type值:

ClusterIP:将服务公开在集群内部的IP上。选择此值将使该服务仅在群集内可访问。这是默认的ServiceType
NodePort:在静态端口(NodePort)上公开每个节点的IP上的服务。将自动创建NodeIP服务将路由到的ClusterIP服务。您可以通过请求<NodeIP>:<NodePort>,从集群外部联系NodePort服务。
LoadBalancer:使用云提供商的负载均衡器在外部公开服务。将自动创建外部负载平衡器将路由到的NodePortClusterIP服务。
ExternalName:通过返回CNAME记录及其值,将服务映射到externalName字段的内容(例如foo.bar.example.com)。没有任何代理设置。

注意:1.7版或更高版本的kube-dns。

end
更多内容请访问官网kubernetes-Services

参考:
kubernetes-Services

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值