目录
2.6.2 LoadBalancer类型的Service资源
2.7 Headless类型的Service资源 (无头service)
1.为什么需要Service资源:
- Pod对象得动态性会给客户端带来困扰
- pod资源对象存在生命周期且不可重现,必要时仅能创建一个新的替代者;
- pod对象在其控制器进行应用规模伸缩时,同一应用程序的Pod对象会增加或减少;
- Service资源为动态管理的Pod对象添加一个有着固定访问入口的抽象层
- Service通过标签选择器关联至拥有相关标签的Pod对象;
- 客户端向Service进行请求,而非目标Pod对象
2、 Service
2.1 Service资源概述
2.2 虚拟IP和服务代理
同前一种代理模型类似,iptables代理模型中,kube-proxy负责跟踪API Server上Service和Endpoints对象的变动(创建或移除),并据此做 出Service资源定义的变动。同时,对于每个Service,它都会创建iptables 规则直接捕获到达ClusterIP和Port的流量,并将其重定向至当前Service的后端,如图6-6所示。对于每个Endpoints对象,Service资源会为其创建iptables规则并关联至挑选的后端Pod资源,默认算法是随机调度 (random)。iptables代理模式由Kubernetes 1.1版本引入,并自1.2版开始成为默认的类型。
在创建Service资源时,集群中每个节点上的kube-proxy都会收到通 知并将其定义为当前节点上的iptables规则,用于转发工作接口接收到的与此Service资源的ClusterIP和端口的相关流量。客户端发来的请求被相 关的iptables规则进行调度和目标地址转换(DNAT)后再转发至集群内 的Pod象之上。
相对于用户空间模型来说,iptables模型无须将流量在用户空间和内核空间来回切换,因而更加高效和可靠。不过,其缺点是iptables代理模 型不会在被挑中的后端Pod资源无响应时自动进行重定向,而userspace 模型则可以
Kubernetes自1.9-alpha版本起引入了ipvs代理模型,且自1.11版本起成为默认设置。此种模型中,kube-proxy跟踪API Server上Service和 Endpoints对象的变动,据此来调用netlink接口创建ipvs规则,并确保与API Server中的变动保持同步,如图6-7所示。它与iptables规则的不同之处仅在于其请求流量的调度功能由ipvs实现,余下的其他功能仍由iptables完成。
类似于iptables模型,ipvs构建于netfilter的钩子函数之上,但它使用hash表作为底层数据结构并工作于内核空间,因此具有流量转发速度快、规则同步性能好的特性。另外,ipvs支持众多调度算法,例如rr、lc、dh、sh、sed和nq等。
2.3 Service资源的基础应用
2.4 创建Service资源
[root@master chapter6]# vim myapp-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: myapp-svc
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
[root@master chapter6]# kubectl apply -f myapp-svc.yaml
service/myapp-svc created[root@master chapter6]# kubectl get svc myapp-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-svc ClusterIP 10.107.27.178 <none> 80/TCP 39s[root@master chapter6]# curl 10.107.27.178
Hello MyApp | Version: v3 | <a href="hostname.html">Pod Name</a>
[root@master chapter6]# kubectl get endpoints myapp-svc
NAME ENDPOINTS AGE
myapp-svc 10.244.1.19:80,10.244.1.6:80,10.244.2.23:80 + 1 more... 2m33s # 10.244.1.19:80,10.244.1.6:80,10.244.2.23:80这三个地址分别指向了后端的三个pod可以通过下面的命令查看下pod的地址[root@master chapter6]# kubectl get pods -o wide|grep myapp
myapp-deploy-77dcc456d9-5hpg7 1/1 Running 0 47h 10.244.1.19 node1 <none> <none>
myapp-deploy-77dcc456d9-lqzpt 1/1 Running 0 47h 10.244.2.23 node2 <none> <none>
myapp-deploy-77dcc456d9-nprbj 1/1 Running 0 47h 10.244.2.24 node2 <none> <none>[root@master chapter6]# kubectl describe svc myapp
Name: myapp-svc
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=myapp
Type: ClusterIP
IP: 10.107.27.178
Port: <unset> 80/TCP
TargetPort: 80/TCP #本地80端口
Endpoints: 10.244.1.19:80,10.244.1.6:80,10.244.2.23:80 + 1 more... #创建svc时会默认去创建endpoints,而这里关联的则是endpoints的地址
Session Affinity: None
Events: <none>
2.5 向Service对象请求服务
[root@master chapter6]# kubectl run cirros-$RANDOM --rm -it --image=cirros -- sh
If you don't see a command prompt, try pressing enter.
/ #
/ # curl http://10.107.27.178:80/
Hello MyApp | Version: v3 | <a href="hostname.html">Pod Name</a>
/ # for loop in 1 2 3 ; do curl http://10.107.27.178:80/hostname.html;done
myapp-deploy-77dcc456d9-5hpg7
myapp-deploy-77dcc456d9-nprbj
myapp-deploy-77dcc456d9-nprbj
2.6 Service类型
- Kubernetes的Service共有四种类型:ClusterIP、NodePort、LoadBalancer和ExternalName
- ClusterIP:通过集群内部IP地址暴露服务,此地址仅在集群内部可达,而无法被集群外部的客户端访问,如图6-8所示。此为默认的Service类型。
- NodePort:这种类型建立在ClusterIP类型之上,其在每个节点的IP地址的某静态端口(NodePort)暴露服务,因此,它依然会为Service分配集群IP地址,并将此作为NodePort的路由目标。简单来说,NodePort类型就是在工作节点的IP地址上选择一个端口用于将集群外部的用户请求转发至目标Service的ClusterIP和Port,因此,这种类型的Service既可如ClusterIP一样受到集群内部客户端Pod的访问,也会受到集群外部客 户端通过套接字<NodeIP>: <NodePort>进行的请求。
- LoadBalancer:这种类型建构在NodePort类型之上,其通过cloudprovider提供的负载均衡器将服务暴露到集群外部,因此LoadBalancer一 样具有NodePort和ClusterIP。简而言之,一个LoadBalancer类型的 Service会指向关联至Kubernetes集群外部的、切实存在的某个负载均衡 设备,该设备通过工作节点之上的NodePort向集群内部发送请求流量,如图6-9所示。例如Amazon云计算环境中的ELB实例即为此类的负载均 衡设备。此类型的优势在于,它能够把来自于集群外部客户端的请求调 度至所有节点(或部分节点)的NodePort之上,而不是依赖于客户端自 行决定连接至哪个节点,从而避免了因客户端指定的节点故障而导致的服务不可用。
- ExternalName:其通过将Service映射至由externalName字段的内容指定的主机名来暴露服务,此主机名需要被DNS服务解析至CNAME类 型的记录。换言之,此种类型并非定义由Kubernetes集群提供的服务, 而是把集群外部的某服务以DNS CNAME记录的方式映射到集群内,从而让集群内的Pod资源能够访问外部的Service的一种实现方式,如图6-10所示。因此,这种类型的Service没有ClusterIP和NodePort,也没有标签选择器用于选择Pod资源,因此也不会有Endpoints存在。
2.6.1 NodePort类型的Service资源
[root@master chapter6]# vim myapp-svc-nodeport.yaml
kind: Service
apiVersion: v1
metadata:
name: myapp-svc-nodeport
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 32223[root@master chapter6]# kubectl apply -f myapp-svc-nodeport.yaml
service/myapp-svc-nodeport created
[root@master chapter6]# kubectl get svc myapp-svc-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-svc-nodeport NodePort 10.96.205.132 <none> 80:32223/TCP 19s
2.6.2 LoadBalancer类型的Service资源
[root@master chapter6]# vim myapp-svc-lb.yaml
kind: Service
apiVersion: v1
metadata:
name: myapp-svc-lb
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
2.6.3 ExternalName Service
[root@master chapter6]# vim external-redis.yaml
kind: Service
apiVersion: v1
metadata:
name: external-www-svc
namespace: default
spec:
type: ExternalName
externalName: www.kubernetes.io
ports:
- protocol: TCP
port: 6379
targetPort: 6379
nodePort: 0
selector: {}[root@master chapter6]# kubectl apply -f external-redis.yaml
service/external-www-svc created
[root@master chapter6]# nslookup www.kubernetes.io
Server: 183.60.83.19
Address: 183.60.83.19#53Non-authoritative answer:
www.kubernetes.io canonical name = kubernetes.io.
Name: kubernetes.io
Address: 147.75.40.148
2.7 Headless类型的Service资源 (无头service)
Service对象隐藏了各Pod资源,并负责将客户端的请求流量调度至该组Pod对象之上。不过,偶尔也会存在这样一类需求:客户端需要直 接访问Service资源后端的所有Pod资源,这时就应该向客户端暴露每个 Pod资源的IP地址,而不再是中间层Service对象的ClusterIP,这种类型 的Service资源便称为Headless Service。
Headless Service对象没有ClusterIP,于是kube-proxy便无须处理此 类请求,也就更没有了负载均衡或代理它的需要。在前端应用拥有自有 的其他服务发现机制时,Headless Service即可省去定义ClusterIP的需 求。至于如何为此类Service资源配置IP地址,则取决于它的标签选择器的定义。
- 具有标签选择器:端点控制器(Endpoints Controller)会在API中为其创建Endpoints记录,并将ClusterDNS服务中的A记录直接解析到此 Service后端的各Pod对象的IP地址上。
- 没有标签选择器:端点控制器(Endpoints Controller)不会在API中为其创建Endpoints记录,ClusterDNS的配置分为两种情形,对 ExternalName类型的服务创建CNAME记录,对其他三种类型来说,为 那些与当前Service共享名称的所有Endpoints对象创建一条记录。
2.7.1 创建 Headless Service资源
[root@master chapter6]# vim myapp-headless-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: myapp-headless-svc
spec:
clusterIP: None
selector:
app: myapp
ports:
- port: 80
targetPort: 80
name: httpport[root@master chapter6]# kubectl apply -f myapp-headless-svc.yaml
service/myapp-headless-svc created
[root@master chapter6]# kubectl get svc myapp-headless-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-headless-svc ClusterIP None <none> 80/TCP 45s
[root@master chapter6]# kubectl exec -it myapp-pod -- /bin/sh
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
/ # nslookup myapp-headless-svc
nslookup: can't resolve '(null)': Name does not resolveName: myapp-headless-svc
Address 1: 10.244.1.6 myapp-pod
Address 2: 10.244.1.19 10-244-1-19.myapp-headless-svc.default.svc.cluster.local
Address 3: 10.244.2.23 10-244-2-23.myapp-headless-svc.default.svc.cluster.local
Address 4: 10.244.2.24 10-244-2-24.myapp-svc.default.svc.cluster.local
/ #