我的K8s之路(2)-ingress实现k8s服务访问
上回写了一篇入门级的小文,做为这一系列的开始,毕竟什么都是从部署做起的。从k8s本身来说,无论是pod、控制器、svc,还是配置运行条件等等,都是基本内容,只要是接触过,多少都有了解,这也是我每回讲课带班必讲的。但是有一个配置,严格上来说不能算是k8s本身提供的功能,应该说是k8s与其它软件配合实现的,这一部分在CKA考试是没有的,但在实际生产环境是经常会用到的,一般的k8s培训也都会讲到,这回就跟大伙简单说说:ingress。
ingress英译过来的意思是进入或入境权,这与它要实现的功能很是帖切。为什么会有它的存在呢?这与k8s本身提供的服务暴露功能有关,k8s存在的意义在于容器编排,容器的意义是运行应用,所以k8s实际的功能是根据不同的业务需求编排运行应用。而应用运行的意义是要能被访问,这就牵扯到了如何将服务暴露出去接受访问。
承
k8s本身能够创建services资源暴露服务,目前来说提供三种服务暴露方式:
1. clusterIP,这种方式只提供k8s集群内部访问,如果应用之间要通讯,或做测试是很方便的,但无法提供外部访问。
2. nodePort,这种方式是能够提供集群外部访问的,但是有个先天不足,这种暴露服务需要集群内每个节点都提供相同的服务端口,无论访问哪个节点的IP:PORT,都可以通过service指向后端运行的控制器或POD。其端口是随机的,范围在30000到32767之间。既然是随机的,就有不确定性,很多路由、防火墙等这些网络设备配置上有一定困难,而且也并不是标准访问端口。个人认为最大的不足还不是端口号,是一个服务导致每个节点都要暴露端口,实用性不是很高。
3. 负载均衡,这种方式k8s只提供内部支持,真正的实现要靠外部云供应商提供的负载均衡器技术,功能落地是没有问题,但会有产生费用,客户还是希望少花多办事的。
基于以上几点,这才有了第三方解决方案,即ingress。ingress的功能实现在于能够将外部的访问,准备路由到对应的service服务,由两部分组成:
1、 Kubernetes Ingress
2、 Kubernetes Ingress Controller
Kubernetes Ingress是k8s的源生资源,也提供API访问。主要定义了外部通过IP或域名、或加路径访问集群内部的service。但是光有它还不够,具体实现要靠Ingress Controller来做。
Ingress Controller即ingess控制器,是在定义ingress资源之前,手动部署在k8s集群的,与其它应用一样也是一个POD,它的作用是随时与k8s的ingress API进行通讯,检查是否要为外部访问路由到service创建规则。
网上找了张图,简单了点,不过基本上是这样的(懒得自己画了:)
这两个说白了等于是一个定义了访问规则,一个来实现路由访问。
转
上述说的是概念定义,现在业界实现ingress功能的有那么几种,比较多的是用nginx来实现,还有Traefik、HAproxy,包括GKE等等,这次的测试就以nginx来做。
还是用上次部署的源生k8s,先将ingress controller的部署文件搞到,在github的仓库里有
我git的是kubernetes提供的ingress-nginx,全下载大约有个100兆多点。其实还有nginx提供的,不过那个没咋用过。
在老版本中,是分成多个yaml文件,由mandatory.yaml统一执行,新版本(2.1.0)合成一个yaml,除了对应k8s部署外,还有对公有云的。
另外,老版本中要自行添加节点选择器,新版本中已经配了选择条件
ingress-ready=true
所以在执行之前,要先给一个节点配上label
kubectl label nodes k8s-node01 ingress-ready=true
执行部署:
会自动创建namespace,名为ingress-nginx。在这个ns内创建角色、控制器、服务等等等等。。。。。。
创建好之后查看执行结果
现在开始测试,首先创建服务,再将其暴露出来,这个用命令或者yaml都可以,本次测试主要针对ingress,所以其它的就简单实现了
kubectl run --image=nginx test01
kubectl run --image=nginx test02
先用命令创建两个服务,查看创建结果
再将两个服务暴露出来
kubectl expose pod test01 --port=80 --target-port=80
kubectl expose pod test02 --port=80 --target-port=80
用curl命令验证上图中两个clusterIP能否访问,访问正常的情况下,我将test01与test02内nginx的index.html更换内容以便于区分,以test01为例:
:~# kubectl exec -it test01 bash
:~# cd /usr/share/nginx/
echo "test01-curl" > index.html
测试访问
好,接下来部署ingress,制定访问规则,编写yaml之前先查看ingess的API 版本
kubectl explain ingress
编写ingress的YAML
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: test.redflag.com
http:
paths:
- path: /red
backend:
serviceName: test01
servicePort: 80- path: /flag
backend:
serviceName: test02
servicePort: 80
(也许是编辑器原因,记得将o都换成-)
其中,ingress的API是用的刚查到的版本,访问域名为test.redflag.com,刚创建的两个服务与端口分别对应/red与/flag两路径访问,查看部署结果。
查看详细信息
kubectl describe ingress ingress-example
其中访问路径对应的IP地址,是cailico网络插件的地址,这是上回部署环境时装的网络插件。再查看service服务的后端IP,看是否一致。
kubectl get endpoints
好,现在开始验证部署结果,看是否能访问,简单实现我不配外部DNS解析了,就用本地解析,修改master节点的/etc/hosts文件,在节点1或节点2后边配本地解析都可以。
在master节点测试访问
到这里还没完,再看看ingress-controller的实现方式,进入ingress-controller的pod
kubectl -n ingress-nginx exec -it ingress-nginx-controller-cc8dd9868-lr5xf bash
查看nginx.conf文件
cat /etc/nginx/nginx.conf
找到下图这段
这段就是访问test.redflag.com的配置部分的开始。
下边分别是/red与/flag的访问配置
结
根据以上配置,nginx的ingress-controller的配置访问,是由nginx访问代理来实现的,当ingress创建后,ingress-controller通过监控与ingress API交互,根据ingress定义的访问规则,自动配置nginx访问代理,不只是一个域名两个路径,多个域名多路径也可以实现。