我们说k8s 的服务(service)时说暴露了service的三种方式ClusterIP、NodePort与LoadBalance,这几种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:
所幸k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。
举个例子,现在集群有api、文件存储、前端3个service,可以通过一个ingress对象来实现图中的请求转发:
ingress规则是很灵活的,可以根据不同域名、不同path转发请求到不同的service,并且支持https/http。
要理解ingress,需要区分两个概念,ingress和ingress-controller:
简单来说,ingress-controller才是负责具体转发的组件,通过各种方式将它暴露在集群入口,外部对集群的请求流量会先到ingress-controller,而ingress对象是用来告诉ingress-controller该如何转发请求,比如哪些域名哪些path要转发到哪些服务等等。
ingress-controller并不是k8s自带的组件,实际上ingress-controller只是一个统称,用户可以选择不同的ingress-controller实现,目前,由k8s维护的ingress-controller只有google云的GCE与ingress-nginx两个,其他还有很多第三方维护的ingress-controller,具体可以参考官方文档。但是不管哪一种ingress-controller,实现的机制都大同小异,只是在具体配置上有差异。一般来说,ingress-controller的形式都是一个pod,里面跑着daemon程序和反向代理程序。daemon负责不断监控集群的变化,根据ingress对象生成配置并应用新配置到反向代理,比如nginx-ingress就是动态生成nginx配置,动态更新upstream,并在需要的时候reload程序应用新配置。为了方便,后面的例子都以k8s官方维护的nginx-ingress为例。
ingress是一个API对象,和其他对象一样,通过yaml文件来配置。ingress通过http或https暴露集群内部service,给service提供外部URL、负载均衡、SSL/TLS能力以及基于host的方向代理。ingress要依靠ingress-controller来具体实现以上功能。前一小节的图如果用ingress来表示,大概就是如下配置:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: abc-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
tls:
- hosts:
- api.abc.com
secretName: abc-tls
rules:
- host: api.abc.com
http:
paths:
- backend:
serviceName: apiserver
servicePort: 80
- host: www.abc.com
http:
paths:
- path: /image/*
backend:
serviceName: fileserver
servicePort: 80
- host: www.abc.com
http:
paths:
- backend:
serviceName: feserver
servicePort: 8080
与其他k8s对象一样,ingress配置也包含了apiVersion、kind、metadata、spec等关键字段。有几个关注的在spec字段中,tls用于定义https密钥、证书。rule用于指定请求路由规则。这里值得关注的是metadata.annotations字段。在ingress配置中,annotations很重要。前面有说ingress-controller有很多不同的实现,而不同的ingress-controller就可以根据"kubernetes.io/ingress.class:"来判断要使用哪些ingress配置,同时,不同的ingress-controller也有对应的annotations配置,用于自定义一些参数。列如上面配置的'nginx.ingress.kubernetes.io/use-regex: "true"',最终是在生成nginx配置中,会采用location ~来表示正则匹配。
虽然 minikube 支持 LoadBalancer 类型的服务,但它并不会创建外部的负载均衡器,而是为这些服务开放一个 NodePort。这在使用 Ingress 时需要注意。
3.1 启动 Ingress Controller
minikube 已经内置了 ingress addon,只需要开启一下即可
$ minikube addons enable ingress
稍等一会,nginx-ingress-controller 和 default-http-backend 就会起来
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
default-http-backend-5374j 1/1 Running 0 1m
kube-addon-manager-minikube 1/1 Running 0 2m
kube-dns-268032401-rhrx6 3/3 Running 0 1m
kubernetes-dashboard-xh74p 1/1 Running 0 2m
nginx-ingress-controller-78mk6 1/1 Running 0 1m
3.2 创建 Ingress
首先启用一个 echo server 服务
$ kubectl run echoserver --image=gcr.io/google_containers/echoserver:1.4 --port=8080
$ kubectl expose deployment echoserver --type=NodePort
$ minikube service echoserver --url
http://192.168.64.36:31957
然后创建一个 Ingress,将 http://mini-echo.io
和 http://mini-web.io/echo
转发到刚才创建的 echoserver 服务上
$ cat <
为了访问 mini-echo.io
和 mini-web.io
这两个域名,手动在 hosts 中增加一个映射
$ echo "$(minikube ip) mini-echo.io mini-web.io" | sudo tee -a /etc/hosts
然后,就可以通过 http://mini-echo.io
和 http://mini-web.io/echo
来访问服务了。
3.3 使用 xip.io
前面的方法需要每次在使用不同域名时手动配置 hosts,借助 xip.io
可以省掉这个步骤。
跟前面类似,先启动一个 nginx 服务
$ kubectl run nginx --image=nginx --port=80
$ kubectl expose deployment nginx --type=NodePort
然后创建 Ingress,与前面不同的是 host 使用 nginx.$(minikube ip).xip.io
:
$ cat <
然后就可以直接访问该域名了
$ curl nginx.$(minikube ip).xip.io
1、k8s ingress原理及ingress-nginx部署测试
2、minikube使用ingress
3、马哥_K8s进阶实战(4)Service/Ingress