文章目录
1.简介
pod的生命是短暂的,所以他的ip是琢磨不定的,而这时候就需要有一个对外的服务,他有固定的ip和端口,客户端可以通过该服务来访问那些处在该服务作用域的pod。
服务的作用域,操作哪些pod,也是通过标签选择器来决定的。
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
sessionAffinity: ClientIP #将来自同一ip的请求转发至同一个pod,类似hash负载均衡,默认none
ports: #可暴露多个接口
- name: http
port: 80 #服务监听的端口
targetPort: 8080 #路由到服务作用域内的pod的8083端口上,如果容器给端口起别称为http,也可用http代替
- name: https
port: 443
targetPort: 8043
selector:
app: kubia
2.服务发现
2.1 通过环境变量发现服务
一个pod在运行的时候,kubernetes会初始化一系列的环境变量指向现在存在的服务,然后pod通过环境变量获取服务的ip地址和端口号,如果服务比pod晚创建,则需要将现有的pod全部删除,让资源自动去创建新的pod,初始化新的服务列表。
2.2 通过DNS+FQDN(全限定域名)来发现服务
kube-system命名空间下有个运行着dns服务的pod,集群中其他的pod都被配置为使用这个pod作为dns服务器(通过修改容器的/etc/resolv.conf文件实现)。该dns服务器知道所有服务,其他的pod可对该服务器进行dns查询从而得到响应。
是否使用内部的DNS服务器是根据pod模板中的dnsPolicy属性决定的
域名组成:[服务名].[服务所在命名空间].[所有集群本地服务名称中使用的可配置集群域后缀]
- 通过域名访问只可访问标准的端口号(如http 80或Postgres的5432),如果不是这样的标准端口,则还是需要从环境变量中去获取端口号
- 如果两个pod处在同一个命名空间,则互相访问的域名则只需要服务名即可
- 集群的ip是虚拟ip,无法ping通,需要与端口结合才有意义
3.连接集群外服务
3.1 通过Endpoint访问外部服务
服务并不是和pod直接相连的,而是通过介于两者之间的资源—endpoint。
创建服务的时候,会根据服务的标签选择器创建Endpoint资源(这是个独立资源,并不是服务的属性),而记载的内容就是服务作用域下的pod ip以及端口,表示访问服务时最终会将请求去重定向到这些列表。
- 创建不带标签选择器的服务
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
ports:
- port: 80
- 创建Endpoint
- endpint需要与服务同名
- 之后创建的pod的环境变量就会有该服务的ip和port,通过该服务重定向到目标服务。
apiVersion: v1
kind: Endpoints
metadata:
name: external-service
subsets:
- addresses:
- ip: 11.11.11.11 #外部的目标服务ip
- ip: 22.22.22.22
ports:
- port: 80
3.2 通过FQDN(完全限定域名)访问
- 新建externalName服务,通过访问该服务来重定向到目标服务
- 之后pod可通过服务的 FQDN 访问外部服务 ,对于pod来说外部服务的域名是隐藏的
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: ExternalName #创建类型为ExternalName的服务
externalName: api.somecompany.com #目标服务域名,更改目标服务域名只需要更改这个属性
ports:
- port: 80
4.将服务暴露给外部客户端
4.1 使用NodePort类型的服务(比较适用于demo应用)
新建NodePort监听节点接口,此时可以通过集群内所有节点的任意一个IP+端口,将请求转发重定向到指定到标签选择器的基础服务
可通过集群虚拟ip:80或节点ip:30123访问到具体服务
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort #创建NodePort类型服务
ports:
- port: 80 #服务集群内的端口,集群内pod访问的端口
targetPort: 8080 #背后pod的目标端口,服务进行重定向的端口
nodePort: 30123 #集群节点的端口,节点外客户端访问的端口
selector:
app: kubia
4.2 通过负载均衡器(Loadbalance)
效果像NodePort,但是不同的是,客户端访问的是负载均衡器,然后再将流量转发给服务节点,服务节点ip列表对客户端来说是隐藏的
apiVersion: v1
kind: Service
metadata:
name: kubia-loadbalancer
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
会话亲和性:表示的是多次请求打到了同一个pod,原因是因为keep-alive的建立了长连接,从而表现出多次请求达到一个pod的情况
减少网络跳数:避免请求—>负载均衡器—>服务—>非本地pod,正确的走向是服务->本地pod,减少连接跳转次数
使用该属性需要注意的问题:
- 如果连接到服务本地没有pod,不会将连接转发给其他由pod的服务节点,而是会将连接挂起,不跳越是为了保留客户端ip
- 确保负载均衡器将连接转发给至少具有一个pod的节点
- 弊端:服务节点的pod数量不同会导致pod接收的流量相差较大
- 保留查看客户端ip
.spec.externalTrafficPolicy: Local .spec.healthCheckNodePort: 端口号(可以不指定)
spec:
type: LoadBalancer
externalTrafficPolicy: Local //表示流量给集群范围内的端点(Cluster)还是节点本地
4.3 使用Ingress类型的服务
4.3.1 与Loadbalancer的区别
每个LoadBalancer都有自己的负载均衡器以及独有的公网ip,但是Ingress只需要一个公网ip就能为许多服务提供访问,根据域名和请求路径来决定请求流量的转发,类似nginx反向代理
4.3.2 工作原理
Ingress并不是通过服务来间接访问pod的,而是获取服务的endpoints列表,然后选择一个pod进行访问。(大多数控制器都是这样工作的)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- host: xxx.xxx.com #将域名与 服务进行映射
http:
paths:
- path: /testpath #转发到域名的某个路径
pathType: Prefix
backend:
service:
name: test #服务名
port:
number: 80 #服务端口
4.3.3 安装
需要自己做调整
docker pull registry.cn-hangzhou.aliyuncs.com/yutao517/ingress_nginx_controller:v1.1.0 docker tag registry.cn-hangzhou.aliyuncs.com/yutao517/ingress_nginx_controller:v1.1.0 k8s.gcr.io/ingress-nginx/controller:v1.1.1 docker pull registry.cn-hangzhou.aliyuncs.com/yutao517/kube_webhook_certgen:v1.1.1 docker tag registry.cn-hangzhou.aliyuncs.com/yutao517/ingress_nginx_controller:v1.1.0 k8s.gcr.io/ingress-nginx/controller:v1.1.1
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- host: xxx.xxx.com #将域名与 服务进行映射
http:
paths:
- path: /testpath #转发到域名的某个路径
pathType: Prefix
backend:
service:
name: test #服务名
port:
number: 80 #服务端口
5.就绪探针
5.1 作用
避免pod初始化未完成就开始接受请求,导致响应过慢或超时。如果pod初始化过慢,只要一创建pod,几乎会立即成为服务端点
不要将停止pod 的逻辑纳入就绪探针,保证程序停止的时候,就绪探针就应该返回失败结果,确保从所有服务中移除该容器
5.2 存活vs就绪
存活探针如果失败,会删除并重建容器。而就绪探针则是将pod从服务的Endpoint中移除,保证流量不流向未准备好的pod。
5.3 就绪探针类型
- Exec探针:执行进程的地方。容器的状态由进程退出的状态码决定。
- HTTP GET探针:通过响应码判断容器是否准备好。
- TCP socket探针:打开一个TCP连接到容器的指定端口,如果建立连接,则代表容器准备就绪。
spec:
nodeSelector: #节点选择器,将pod部署到包含以下标签的工作节点
gpu: "true"
containers:
- image: linzd/test:kubia-js #镜像
name: kubia #容器名
readinessProbe: #存活探针
httpGet: #http探针
path: /
port: 8080