Kubernetes 详解-Replica Sets 和Service

1.1 Replica Sets

下一代的Replication Controller,两者的区别主要在选择器selector,Replica 支持集合级别的选择器,而前期的Replication Controller,支持在等号描述的选择器,kubectl命令支持使用replica sets (目前kubectl命令中的rolling-update 还不支持),目前replica sets主要用于deployment中

Replica Sets 能够确保在某个时间点上,一定数量的Pod在运行。然而Deployment 是Replica Sets更高一层的抽象,用于更新Pods 以及其他一些特性。推荐使用Deployment而不是直接使用Replica Set进行编排Pods。

1.2 Service

由于Pod的IP会变化,提供某些功能的POD如果IP发生变化,会导致其他Pod无法发现这些功能,因此 引入了Service的功能。

Service是一组逻辑Pod的抽象,定义了一个访问这些Pod的策略(或者叫做微服务),这些Service 通常通过Label Selector指向这些Pod。

举个例子:一个提供镜像处理的后端有三个运行的副本,这些副本是可以取代的,但是前端并不需要感知,这时就需要Service作为抽象

对于可以部署在K8s内部应用,K8s通过Endpoints Api更新Service对应的Pod集合,对于那些没K8s外部的应用,K8s提供了虚拟IP桥接到Service,然后Service重定向到Pod集合。

1.2.1 Service 定义

{

“kind”**:** “Service”**,**

“apiVersion”**:** “v1”**,**

“metadata”**:** {

“name”**:** “my-service”

},

“spec”**:** {

“selector”**:** {

“app”**:** “MyApp”

},

“ports”**:** [

{

“protocol”**:** “TCP”**,**

“port”**:** 80**,**

“targetPort”**:** 9376

}

]

}

}

该Service 对应的Pod集合:带有label app=Myapp,对外暴露端口9376

Service 能将任意的流入Port 重定向到targetPort,默认情况下,targetPort和Port为相同值,不同的Pod 可以对应不同的端口号(例如,在你应用的下一个版本中会使用不同的端口号,但是并不应用之前版本的使用)

Service 支持UDP和TCP,默认是TCP

1.2.2 Service without selector

Service可以抽象访问Pod集群,同时 Service也可以抽象其他后端

1、 在生产环境中使用外部数据库,在测试环境中使用自己的数据库

2、 将自己的Service指向其他集群或者其他命名空间的Service

3、 迁移应用到k8s,但是还是有些应用运行在k8s之外

通过定义不包含selector的Service实现

{

“kind”**:** “Service”**,**

“apiVersion”**:** “v1”**,**

“metadata”**:** {

“name”**:** “my-service”

},

“spec”**:** {

“ports”**:** [

{

“protocol”**:** “TCP”**,**

“port”**:** 80**,**

“targetPort”**:** 9376

}

]

}

}

Service 没有Selector,K8s不会创建Endpoints,你可以通过手动创建Endpoint指向自己的endpoint

{

“kind”**:** “Endpoints”**,**

“apiVersion”**:** “v1”**,**

“metadata”**:** {

“name”**:** “my-service”

},

“subsets”**:** [

{

“addresses”**:** [

{ “ip”**:** “1.2.3.4” }

],

“ports”**:** [

{ “port”**:** 9376 }

]

}

]

}

Endpoint的IP不能是loopback(127.0.0.1/8),link-local(169.254.0.0/16), link-local multicast (224.0.0.0/24).

访问不含有selector的Service和访问含有Selector的Service 方式一样,都会讲流向重定向的endpoint

 其他命名空间的服务是一个特例,他不会定义ports和endpoint,他只是返回一个访问外部服务的别名

{

“kind”**:** “Service”**,**

“apiVersion”**:** “v1”**,**

“metadata”**:** {

“name”**:** “my-service”**,**

“namespace”**:** “prod”

},

“spec”**:** {

“type”**:** “ExternalName”**,**

“externalName”**:** “my.database.example.com”

}

}

当你访问服务my-service.prod.svc.CLUSTER**时,**cluster**的**dns**服务会返回记录**my.database.example.com 的**CNAME**,这个重定向是发生在**dns**解析阶段。

1.2.3 虚拟IP 和服务代理

1.2.3.1 代理

K8s集群内每个节点都会运行kube-proxy,负责实现服务的虚拟机IP(不是externalName)。1.0版本的代理模式在是userspace,1.1增加了iptables proxy,从1.2开始 iptables 代理是默认的模式

K8s 1.0的service是四层(TCP/UDP),从k8s1.1开始,增加了Ingress,实现七层(HTTP)服务

用户空间的代理模式

Kube-proxy监控k8s master节点来发现Service、Endpointd的增加和删除,对于Service,在本地打开一个随机端口作为代理端口,任何访问改代理端口的连接都会被指向Service对象的Pod集合,最终指向哪个Pod取决于Service的SessionAffinity,最后,他会配置iptables,捕获流向Service 的Cluster IP 和Port的连接,并重定向到这个代理端口。

最终结果,任何到Service Cluster Ip 和port的流量都会指向合适的Pod

默认情况下,都是轮训算法选择后端,也可以通过设置service.spec.sessionAffinity 为ClientIP,将选择算法改为Client-IP based session affinity

Iptables**的代理模式**

该模式与userspace模式类似,只是没有这个代理端口

比userspace方式更快更可靠,然后与userspace方式不同,当选择的pod异常时,该方式无法自动尝试选择其他Pod。

1、userspace模式只不适合大规模集群使用(数千个服务)

2、userspace模式隐藏了访问服务的源IP,iptables模式虽然没有隐藏源IP,但是也是通过负载均衡或者nodeport 影响了客户端输入