Services 和 Pods
KubernetesPods是有生命周期的。他们能够被创立,而且销毁不会再启动。如果您应用Deployment来运行您的应用程序,则它能够动态创建和销毁 Pod。
一个Kubernetes的Service是一种形象,它定义了一组Pods的逻辑汇合和一个用于拜访它们的策略 - 有的时候被称之为微服务。一个Service的指标Pod汇合通常是由Label Selector 来决定的(上面有讲一个没有选择器的Service 有什么用途)。
举个例子,设想一个解决图片的后端运行了三个正本。这些正本都是能够代替的 - 前端不关怀它们应用的是哪一个后端。只管理论组成后端汇合的Pod可能会变动,前端的客户端却不须要晓得这个变动,也不须要本人有一个列表来记录这些后端服务。Service形象能让你达到这种解耦。
不像 Pod 的 IP 地址,它理论路由到一个固定的目的地,Service 的 IP 实际上不能通过单个主机来进行应答。相同,咱们应用 iptables(Linux 中的数据包解决逻辑)来定义一个虚构IP地址(VIP),它能够依据须要通明地进行重定向。当客户端连贯到 VIP 时,它们的流量会主动地传输到一个适合的 Endpoint。环境变量和 DNS,实际上会依据 Service 的 VIP 和端口来进行填充。
kube-proxy反对三种代理模式: 用户空间,iptables和IPVS;它们各自的操作略有不同。
Userspace
作为一个例子,思考后面提到的图片解决应用程序。当创立 backend Service 时,Kubernetes master 会给它指派一个虚构 IP 地址,比方 10.0.0.1。假如 Service 的端口是 1234,该 Service 会被集群中所有的 kube-proxy 实例察看到。当代理看到一个新的 Service, 它会关上一个新的端口,建设一个从该 VIP 重定向到新端口的 iptables,并开始接管申请连贯。
当一个客户端连贯到一个 VIP,iptables 规定开始起作用,它会重定向该数据包到 Service代理 的端口。Service代理 抉择一个 backend,并将客户端的流量代理到 backend 上。
这意味着 Service 的所有者可能抉择任何他们想应用的端口,而不存在抵触的危险。客户端能够简略地连贯到一个 IP 和端口,而不须要晓得理论拜访了哪些 Pod。
iptables
再次思考后面提到的图片解决应用程序。当创立 backend Service 时,Kubernetes 控制面板会给它指派一个虚构 IP 地址,比方 10.0.0.1。假如 Service 的端口是 1234,该 Service 会被集群中所有的 kube-proxy 实例察看到。当代理看到一个新的 Service, 它会配置一系列的 iptables 规定,从 VIP 重定向到 per-Service 规定。该 per-Service 规定连贯到 per-Endpoint 规定,该 per-Endpoint 规定会重定向(指标 NAT)到 backend。
当一个客户端连贯到一个 VIP,iptables 规定开始起作用。一个 backend 会被抉择(或者依据会话亲和性,或者随机),数据包被重定向到这个 backend。不像 userspace 代理,数据包从来不拷贝到用户空间,kube-proxy 不是必须为该 VIP 工作而运行,并且客户端 IP 是不可更改的。当流量打到 Node 的端口上,或通过负载均衡器,会执行雷同的根本流程,然而在那些案例中客户端 IP 是能够更改的。
IPVS
在大规模集群(例如10,000个服务)中,iptables 操作会显着升高速度。IPVS 专为负载平衡而设计,并基于内核内哈希表。因而,您能够通过基于 IPVS 的 kube-proxy 在大量服务中实现性能一致性。同时,基于 IPVS 的 kube-proxy 具备更简单的负载平衡算法(最小连贯,局部性,加权,持久性)。
上面咱们具体说下k8s反对的4种类型的Service。
ClusterIP
创立ClusterIP的Service yaml如下:
apiVersion: v1kind: Servicemetadata: name: service-pythonspec: ports: - port: 3000 protocol: TCP targetPort: 443 selector: run: pod-python type: ClusterIP
应用 kuebctl get svc :
类型为ClusterIP的service,这个service有一个Cluster-IP,其实就一个VIP。具体实现原理依附kubeproxy组件,通过iptables或是ipvs实现。
这种类型的service 只能在集群内拜访。
NodePort
咱们的场景不全是集群内拜访,也须要集群外业务拜访。那么ClusterIP就满足不了了。NodePort当然是其中的一种实现计划。
创立NodePort 类型service 如下:
apiVersion: v1kind: Servicemetadata: name: service-pythonspec: ports: - port: 3000 protocol: TCP targetPort: 443 nodePort: 30080 selector: run: pod-python type: NodePort
应用 kuebctl get svc :
此时咱们能够通过http://4.4.4.1:30080或http://4.4.4.2:30080 对pod-python拜访。该端口有肯定的范畴,比方默认Kubernetes 管制立体将在--service-node-port-range标记指定的范畴内调配端口(默认值:30000-32767)。
LoadBalancer
LoadBalancer类型的service 是能够实现集群内部拜访服务的另外一种解决方案。不过并不是所有的k8s集群都会反对,大多是在私有云托管集群中会反对该类型。负载均衡器是异步创立的,对于被提供的负载均衡器的信息将会通过Service的status.loadBalancer字段被公布进来。
创立 LoadBalancer service 的yaml 如下:
apiVersion: v1kind: Servicemetadata: name: service-pythonspec: ports: - port: 3000 protocol: TCP targetPort: 443 nodePort: 30080 selector: run: pod-python type: LoadBalancer
应用 kuebctl get svc :
能够看到external-ip。咱们就能够通过该ip来拜访了。
当然各家私有云反对诸多的其余设置。大多是私有云负载均衡器的设置参数,都能够通过svc的注解来设置,例如上面的aws:
metadata: name: my-service annotations: service.beta.kubernetes.io/aws-load-balancer-access-log-enabled: "true" service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval: "60" service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name: "my-bucket" service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix: "my-bucket-prefix/prod"
ExternalName
类型为 ExternalName 的service将服务映射到 DNS 名称,而不是典型的选择器,例如my-service或者cassandra。您能够应用spec.externalName参数指定这些服务。
创立 ExternalName 类型的服务的 yaml 如下:
kind: ServiceapiVersion: v1metadata: name: service-pythonspec: ports: - port: 3000 protocol: TCP targetPort: 443 type: ExternalName externalName: remote.server.url.com
阐明: 您须要 CoreDNS 1.7 或更高版本能力应用ExternalName类型。当查找主机 service-python.default.svc.cluster.local时,集群DNS服务返回CNAME记录,其值为my.database.example.com。拜访service-python的形式与其余服务的形式雷同,但次要区别在于重定向产生在 DNS 级别,而不是通过代理或转发。
将生产工作负载迁徙到Kubernetes集群并不容易。大多数咱们不能够进行所有服务并在Kubernetes集群上启动它们。有时,尝试迁徙轻量且不会毁坏你服务的服务是很好的。在此过程中,一个可能不错的解决方案是应用现有的有状态服务(例如DB),并首先从无状态容器开始。
从Pod中拜访内部服务的最简略正确的办法是创立ExternalName service。例如,如果您决定保留AWS RDS,但您还心愿可能将MySQL容器用于测试环境。让咱们看一下这个例子:
kind: ServiceapiVersion: v1metadata: name: test-service namespace: defaultspec: type: ExternalName externalName: test.database.example.com
你已将Web应用程序配置为应用URL测试服务拜访数据库,然而在生产集群上,数据库位于AWS RDS上,并且具备以下URL test.database.example.com。创立ExternalName service 并且你的Web Pod尝试拜访test-service上的数据库之后,Kubernetes DNS服务器将返回值为test.database.example.com的CNAME记录。问题解决了。
ExternalName service 也能够用于从其余名称空间拜访服务。例如:kind: ServiceapiVersion: v1metadata: name: test-service-1 namespace: namespace-aspec: type: ExternalName externalName: test-service-2.namespace-b.svc.cluster.local ports: - port: 80
在这里,我能够应用名称空间a中定义的test-service-1拜访命名空间b中的服务 test-service-2。
这个意义在哪里?
ExternalName service 也是一种service,那么ingress controller 会反对,那么就能够实现跨namespace的ingress。
如果您感觉本篇文章还不错记得点赞分享哦!近期失去了一个不错的材料分享给大家《阿里云Kubernetes我的项目实战手册》,间接点击就可支付!
福利:豆花同学为大家精心整顿了一份对于linux和python的学习材料大合集!有须要的小伙伴们,关注豆花集体公众号:python头条!回复关键词“材料合集”即可收费支付!