Kubernetes Service

1、service简介
service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务。这组pod能够被service访问到,通常是通过Label Selector。

service能够提供负载均衡的能力,但是在使用上有以下限制:
只提供4层负载均衡能力,而没有7层功能,但有时可能需要更多的匹配规则来转发请求,这点上4层负载均衡是不支持的。

2、service的类型
service在k8s中有4中类型:
1)、ClusterIP: 默认方式。根据是否生成ClusterIP又可分为普通Service和Headless Service两类
(1)普通Service:通过为Kubernetes的Service分配一个集群内部可访问的固定虚拟IP(Cluster IP),实现集群内的访问。为最常见的方式。
(2)Headless Service:该服务不会分配Cluster IP,也不通过kube-proxy做反向代理和负载均衡。而是通过DNS提供稳定的ID来访问,DNS会将headless service的后端直接解析为podIP列表。主要供StatefulSet使用。
2)、NodePort:除了使用Cluster IP之外,还通过将service的port映射到集群内每个节点的相同一个端口,实现通过nodeIP:nodePort从集群外访问服务。
3)、LoadBalancer:和nodePort类似,不过除了使用一个Cluster IP和nodePort之外,还会向所使用的公有云申请一个负载均衡器(负载均衡器后端映射到各节点的nodePort),实现从集群外通过LB访问服务。
4)、ExternalName:创建一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用。

备注:
前3种模式,定义服务的时候通过selector指定服务对应的pods,根据pods的地址创建出endpoints作为服务后端;Endpoints Controller会watch Service以及pod的变化,维护对应的Endpoint信息。kube-proxy根据Service和Endpoint来维护本地的路由规则。当Endpoint发生变化,即Service以及关联的pod发生变化,kube-proxy都会在每个节点上更新iptables,实现一层负载均衡。而ExternalName模式则不指定selector,相应的也就没有port和endpoints。

ExternalName和ClusterIP中的Headles Service同属于Headless Service的两种情况。Headless Service主要是指不分配Service IP,且不通过kube-proxy做反向代理和负载均衡的服务。

ClusterIP的普通Service例子
[root@k8smaster test]# more deployment.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcat
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: tomcat
    spec:
      containers:
      - name: tomcat
        image: 192.168.23.100:5000/tomcat:v2
        ports:
        - containerPort: 8080
[root@k8smaster test]#
[root@k8smaster test]# kubectl apply -f deployment.yaml 
deployment.extensions/tomcat created
[root@k8smaster test]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
tomcat-6674546955-5pn2x   1/1     Running   0          2m44s   10.244.1.15   k8snode01   <none>           <none>
tomcat-6674546955-nftxx   1/1     Running   0          2m44s   10.244.2.17   k8snode02   <none>           <none>
[root@k8smaster test]# curl "http://10.244.2.17:8080"
tomcat-6674546955-nftxx
Hello world
[root@k8smaster test]# curl "http://10.244.1.15:8080"
tomcat-6674546955-5pn2x
Hello world
[root@k8smaster test]# more service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  selector:
    app: tomcat
  ports:
  - protocol: TCP
    port: 8080   #外部映射端口
    targetPort: 8080  #pod容器端口
[root@k8smaster test]#
[root@k8smaster test]# kubectl create -f service.yaml 
service/tomcat-service created
[root@k8smaster test]# kubectl get service
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP    3d20h
tomcat-service   ClusterIP   10.101.163.140   <none>        8080/TCP   24s
[root@k8smaster test]# kubectl describe service tomcat-service
Name:              tomcat-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=tomcat
Type:              ClusterIP
IP:                10.101.163.140
Port:              <unset>  8080/TCP
TargetPort:        8080/TCP
Endpoints:         10.244.1.15:8080,10.244.2.17:8080
Session Affinity:  None
Events:            <none>
[root@k8smaster test]# 
[root@k8smaster test]# curl "http://10.101.163.140:8080"
tomcat-6674546955-nftxx
Hello world
[root@k8smaster test]# curl "http://10.101.163.140:8080"
tomcat-6674546955-5pn2x

NodePort例子:
[root@k8smaster test]# more service-nodeport.yaml 
apiVersion: v1
kind: Service
metadata:
  name: tomcat-service
spec:
  type: NodePort
  selector:
    app: tomcat
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
[root@k8smaster test]# kubectl create -f service-nodeport.yaml 
service/tomcat-service created
[root@k8smaster test]# kubectl get service
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          3d23h
tomcat-service   NodePort    10.107.222.21   <none>        8080:30003/TCP   2m42s
[root@k8smaster test]# curl "http://192.168.23.100:30003"
tomcat-6674546955-nftxx
Hello world
[root@k8smaster test]# curl "http://192.168.23.101:30003"
tomcat-6674546955-nftxx
Hello world
[root@k8smaster test]# curl "http://192.168.23.102:30003"
tomcat-6674546955-nftxx
Hello world

3、服务代理
为什么不使用DNS轮询?
时不时会有人问道,就是为什么 Kubernetes 依赖代理将入站流量转发到后端。 那其他方法呢? 例如,是否可以配置具有多个A值(或IPv6为AAAA)的DNS记录,并依靠轮询名称解析?
使用服务代理有以下几个原因:
DNS 实现的历史由来已久,它不遵守记录 TTL,并且在名称查找结果到期后对其进行缓存。
•有些应用程序仅执行一次 DNS 查找,并无限期地缓存结果。
•即使应用和库进行了适当的重新解析,DNS 记录上的 TTL 值低或为零也可能会给 DNS 带来高负载,从而使管理变得困难。

版本兼容性
从Kubernetes v1.0开始,已经可以使用userspace代理模式。Kubernetes v1.1添加了 iptables 模式代理,在 Kubernetes v1.2 中,kube-proxy的iptables模式成为默认设置。Kubernetes v1.8添加了ipvs代理模式。

userspace代理模式
这种模式,kube-proxy会监视Kubernetes master对Service对象和Endpoints对象的添加和移除对每个Service,它会在本地 Node上打开一个端口(随机选择)。任何连接到"代理端口"的请求,都会被代理到Service的backend Pods中的某个上面(如 Endpoints 所报告的一样)。使用哪个backend Pod,是kube-proxy基于SessionAffinity来确定的。最后,它安装iptables规则,捕获到达该Service的clusterIP(是虚拟 IP)和 Port 的请求,并重定向到代理端口,代理端口再代理请求到backend Pod。默认情况下,用户空间模式下的kube-proxy通过循环算法选择后端。默认的策略是,通过round-robin 算法来选择 backend Pod。

 

iptbales代理模式
这种模式,kube-proxy会监视Kubernetes控制节点对Service对象和Endpoints对象的添加和移除。对每个Service,它会安装iptables规则,从而捕获到达该Service的clusterIP和端口的请求,进而将请求重定向到Service 的一组backend 中的某个上面。对于每个Endpoints对象,它也会安装 iptables 规则,这个规则会选择一个backend 组合。默认的策略是,kube-proxy在iptables模式下随机选择一个backend。使用 iptables处理流量具有较低的系统开销,因为流量由Linux netfilter处理,而无需在用户空间和内核空间之间切换。这种方法也可能更可靠。如果kube-proxy在iptables模式下运行,并且所选的第一个 Pod 没有响应,则连接失败。这与用户空间模式不同:在这种情况下,kube-proxy 将检测到与第一个 Pod 的连接已失败,并会自动使用其他后端Pod重试。您可以使用 Pod readiness探测器验证后端Pod可以正常工作,以便iptables模式下的kube-proxy仅看到测试正常的后端。这样做意味着您避免将流量通过kube-proxy发送到已知已失败的Pod。

 

ipvs代理模式
在ipvs 模式下,kube-proxy监视Kubernetes服务和端点,调用netlink接口相应地创建IPVS规则,并定期将IPVS规则与Kubernetes服务和端点同步。该控制循环可确保IPVS状态与所需状态匹配。访问服务时,IPVS将流量定向到后端Pod之一。IPVS代理模式基于类似于iptables模式的netfilter挂钩函数,但是使用哈希表作为基础数据结构,并且在内核空间中工作。 这意味着,与iptables模式下的kube-proxy相比,IPVS模式下的kube-proxy重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS模式还支持更高的网络流量吞吐量。

IPVS提供了更多选项来平衡后端Pod的流量。 这些是:
•rr: round-robin轮询调度
•lc: least connection (smallest number of open connections)最小连接数
•dh: destination hashing目标哈希
•sh: source hashing源哈希
•sed: shortest expected delay最短期望延迟
•nq: never queue不排队调度

注意:
要在IPVS模式下运行kube-proxy,必须在启动 kube-proxy之前使IPVS Linux在节点上可用。
当kube-proxy以IPVS代理模式启动时,它将验证IPVS内核模块是否可用。如果未检测到IPVS内核模块,则kube-proxy将退回到以iptables代理模式运行。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值