共计 4671 个字符,预计需要花费 12 分钟才能阅读完成。
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: v1
kind: Service
metadata:
name: service-python
spec:
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: v1
kind: Service
metadata:
name: service-python
spec:
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: v1
kind: Service
metadata:
name: service-python
spec:
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: Service
apiVersion: v1
metadata:
name: service-python
spec:
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: Service
apiVersion: v1
metadata:
name: test-service
namespace: default
spec:
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: Service
apiVersion: v1
metadata:
name: test-service-1
namespace: namespace-a
spec:
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 头条!回复关键词“材料合集”即可收费支付!