1、service简介前端
- 我的理解:service相似于一个前端代理,全部的访问经过代理分发,不管后端怎么变化,用户的访问方式始终保持不变
- service是一种为一组功能相同的pod提供单一不变的接入点的资源(如何保证service的高可用?service自己是否会成为瓶颈?)
- service也经过标签选择器来选择对应的pod
- service能够将特定客户端的请求每次都指向同一个pod(使用次属性须要考虑负载均衡的影响)
- service工做在TCP与UDP层,所以没法基于cookie来绑定pod
- service的服务发现:
1)全部的service都以环境变量的形式存放在pod中,pod经过环境变量获取service的IP和端口
2)DNS发现服务:
a、k8s自身在kubesystem命名空间有运行dns服务
b、其余全部在同一集群的pod都配置成使用该dns(k8s经过修改每一个容器的/etc/resolv.conf文件实现)
c、pod是否使用dns由pod中sepcd dnsPolicy属性决定
d、客户端pod在知道service的名称的状况下能够经过FQDN(全局限定域名)访问
访问格式:web-test.default.svc.cluster.local #service名称.命名空间名称.集群本地服务名称中使用的可配置的集群域后缀
在同一namespace的pod能够省略集群域后缀及命名空间,即只须要service_name
e、端口号依旧使用环境变量获取
- service的IP是没法ping的,由于service的clusterIP只是一个虚拟的IP,只有与service的port结合使用时才有意义
- 经过service访问服务没法记录客户端IP,因为node对数据包执行了SNAT(源网络地址转换),所以数据包的源IP会发生改变
2、endpoint(kubectl get svc svc_name #能够查看到endpoint)node
- Endpoint就是暴露一个服务的IP地址和端口的列表
- service的标签选择器是用与构建endpoint的IP、端口列表,而后存入endpoint资源中
- 手动建立endpoint(用于给没有标签选择器的service建立endpoint)
- 手动建立的endpoint须要与对应的service具备相同的名称,并包含该服务的目标IP和端口列表
- 建立完整的service后删除seletor选择器,service将不会自动更新endpoint列表,能够人为控制endpoint
3、使用service连接外部服务 web
- 使用endpoint写入外部服务器的IP和端口连接外部服务(默认服务发现只能连接集群内部的服务)
- 建立ExternalName类型的服务,经过externalname属性和ports属性指定外部服务器的IP和端口
- 经过service访问外部服务能够直接连接外部服务,隐藏了外部服务的名称、端口等信息
4、将服务暴露给外部客户端 后端
- 建立NodePort类型的service:每一个节0点都会打开一个相同的随机端口,用于将流量重定向到节点上的pod,外部经过node_ip:port访问(缺点:pod更换node节点会改变访问方式,或弄得节点故障从而致使服务不可访问)
- 建立LoadBalancer类型的service:经过一个专用的负载均衡器访问,客户端经过负载均衡器的IP链接到服务
(云服务商的k8s集群一般支撑从云基础架构自动提供负载均衡器,用户仅需将类型修改成LoadBalance模式便可,以后根据查看到的负载均衡IP访问服务)
实现须要负载均衡器+独有的公网IP
- 建立一个Ingress资源,经过一个IP地址公布多个service
一、Ingress须要一个公网IP
二、Ingress根据请求的主机名和路劲决定请求转发的服务
三、Ingress在网络栈(HTTP)的应用层操做,能够实现基于cookie的回话亲和性
四、只有Ingress控制器在集群中运行,Ingress资源才能正常工做
五、云供应商的Ingress控制器(例如:GKE)要求Ingress指向一个NodePort服务
六、ingress工做原理:客户端——》DNS——》返回ingress_IP——》客户端发出HTTP请求,并在Host头中指定域名——》控制器经过域名肯定客户端访问的服务——》经过该服务的Endpoint查看pod IP——》并将客户端的请求转发给其中一个pod(一般状况ingress只经过service选择pod,而不是转发给service)
七、一个Ingress能够暴露多个服务:经过不一样的域名指向不一样的service,所以在实际应用场景中,须要将Ingress用到的域名在Ingress所在的node上所有解析
- 小结:
1)Ingress决定访问的service(选择须要访问的服务)
2)service选择响应用户请求的pod
3)建立ingress的pod时注意使用replicas机制,(使用DNS解析到多个对应的Ingress节点,以避免当pod或node故障时,经过ingress的访问所有失效:仅我的理解)
2、service的yaml示例api
apiVersion: v1服务器
kind: Servicecookie
metadata:网络
name: svc-testsession
spec:架构
#type: ExternalName
#externalname: www.example.com #在externalname模式是的属性,指定外部服务器的FQDN,同时也须要指定ports属性
sessionAffinity: ClientIp #次属性用于使同一客户端的请求每次都指向同一个pod(有none和client两中选择,默认为none)
externalTrafficPolicy: local #负载均衡器——》service——》node——》pod(选择了node的时候可能响应的pod不在该node上(默认随机),此选即开启:接受到请求的node直接使用本地的pod直接响应;缺点,若此node上无pod响应,则该请求将被直接挂起,且node上的pod数量不一致的状况下,可能致使pod的负载不均衡
selector:
app: web
ports:
- name: http #映射多个端口时须要指定name属性,只须要映射一个端口时能够省略
port: 8080 #映射的端口
targetPort: 80 #pod端口
#nodePort: 30080 #节点端口,使用nodeport模式时能够指定的属性(不指定则自动生成随机端口)
- name: http
port: 8443
targetPort: 443 #pod端口在pod的yaml文件中也定义有name属性,此处能够直接引用,这样即便pod的端口发生变化,此处也无需修改
Ingress的yaml文件
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-test
spec:
tls: #使用HTTPS方式访问,将证书建立为secret资源使用
- hosts:
- test.example.com #使用HTTPS访问的域名
secretName: tls-secret #建立的secret名称
rules:
- host: test.example.com #对外暴露的域名
http:
paths:
- path: /web1 #访问的文件路径
backend:
service:Name: test-svc #service的名称
servicePort: 80 #service的端口
http:
paths:
- path: /web2 #在同一host下的不一样路径
backend:
service:Name: test-svc2
servicePort: 80
- host: test2.example.com
http:
paths:
- path: /web1
backend:
service:Name: test2-svc
servicePort: 80