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 影响了客户端输入