前言:
现在你们对“traefiknginx”大体比较关怀,朋友们都需要分析一些“traefiknginx”的相关内容。那么小编也在网上搜集了一些对于“traefiknginx””的相关资讯,希望朋友们能喜欢,兄弟们快快来了解一下吧!之前有说过,我用traefik做网关,无论是内外网请求都会经过网关。
请求
但是我们有一部分API是只有内网会用,为了安全,我们要保证这些内网的API只有内网可以访问到。
但是由于之前的设置,这些API是匿名访问的,如果修改为需要权限,那么需要其他依赖于我们服务的team来做对应的修改,是由于一些原因,这条路走不通。
摆在我面前的就只有一条路,那就是安装两个traefik,一个对内,一个对外。安装两个traefik很容易,由于traefik安装采用的是DaemonSet的方式,所以两个traefik的访问端口必须不同
--entryPoints.traefik.address=:8080
比如internet(外网)的traefik的端口是8080,那么internal的traefik就可以是9090。
traefik安装请看我之前的文章--在 kubernetes 中安装 traefik2。
然后就可以啦?当然没有那么容易,为了实现下面的效果,
请求
对应的IngressRoute也同样需要修改
以前的IngressRoute如下
apiVersion: traefik.containo.us/v1alpha1kind: IngressRoutemetadata: name: my-service-traefik-ingressspec: entryPoints: - websecure routes: - match: Host(`think123.com`) && PathPrefix(`/api/anon/health`, `/api/anon/article`) kind: Rule services: - name: my-service port: 9000
我想要/api/anon/article这个request path只能内网访问,那么需要将配置修改如下
apiVersion: traefik.containo.us/v1alpha1kind: IngressRoutemetadata: name: my-service-traefik-ingressspec: entryPoints: - websecure routes: - match: Host(`think123.com`) && PathPrefix(`/api/anon/health`) kind: Rule services: - name: my-service port: 9000apiVersion: traefik.containo.us/v1alpha1kind: IngressRoutemetadata: name: my-service-internal-traefik-ingressspec: entryPoints: - websecure routes: - match: Host(`think123-internal.com`) && PathPrefix(`/api/anon/article`) kind: Rule services: - name: my-service port: 9000
看上去没问题了,配置好LoadBalance之后,访问对应的域名就可以了。但是这样还存在一个问题
curl -H 'Host:; -X GET ;
通过指定header的方式,我们发现它匹配了 my-service-internal-traefik-ingress这个ingressRoute,最终返回了只有内网用户才能访问的API。
为啥我做了一大堆,安全性问题仍然存在?
实际上是因为无论是内网的traefik还是只监控外网的traefik,它们两个都会加载所有的IngressRoute,所以就有了上面的那个问题。
必须想个办法让它们只加载属于自己的IngressRoute,我去翻阅了下Traefik的文档,发现有3个参数可以用。
第一个是可以指定要监视哪些namespaces,则traefik就只处理它监控下的namespaces请求
--providers.kubernetescrd.namespaces=default,production
第二个是给资源打上label,但是只对Traefik Custom Resources起作用,对Kubernetes的Service,Secrets这些不起作用
--providers.kubernetescrd.labelselector="app=traefik"
第三个是指定ingressClass
--providers.kubernetescrd.ingressclass=traefik-internal
我们需要在对应的资源上加上kubernetes.io/ingress.class注解,用于标识要处理的资源对象。
由于我们处理的是同一个namespace下的资源,所以namespace的方式不合适。
而对于第二种或者第三种而言,由于我们对IngressRoute进行处理,所以都是合适的。但是考虑到其他环境存在nginx和traefik共存的情况,我们决定使用ingressClass的方式,实际上nginx也是建议我们这么做的。
multi ingress controller
最开始我的修改是这样的,首先在DaemonSet模板中添加ingressClass设定
--providers.kubernetescrd.ingressclass=$(ingress_class)
接下来只需要在不同的traefik中配置不同的环境变量(configMap)即可。比如internet traefik设置ingress_class=traefik-internet,而intranet traefik该值为空,它被当成默认的ingress controller。
然后在相应的ingressRoute中指定 kubernetes.io/ingress.class: traefik-internet就可以了。其他IngressRoute不指定该注解。
看上去很棒,给自己点个赞。
可是想象是美好的,现实却给了我无情一击。这样修改完成之后,我发现当我访问 这个api的时候,没有traefik来处理我的请求。
internal traefik不是我的默认traefik吗?我看官方文档还这样写的呀
If the parameter is non-empty, only resources containing an annotation with the same value are processed.Otherwise, resources missing the annotation, having an empty value, or the value traefik are processed
难道这个空不是空串,而是不指定的意思?真是不讲武德!
所以,我只能换一种修改方式,在DaemonSet的模板中不指定ingressClass,而是在通过kustomize来动态添加。kustomize的使用请参考我的这篇文章
注意,两个traefik只有些许配置不一样,所以,我们安装的时候一般指定一个模板,动态的值则由不同的traefik来指定
patches: - target: version: v1beta2 kind: DaemonSet name: traefik patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --providers.kubernetescrd.ingressclass=traefik-internet
在我的配置中,internet traefik名字叫做traefik,internal traefik名字叫做traefik-internal,区分内外网是逻辑区分,而不仅仅是通过名字。
我们只在internet traefik中指定ingressClass,intranet traefik则不指定。
同样的,IngressRoute也需要动态修改的。
# kustomization.yamlpatchesJson6902:- target: group: traefik.containo.us version: v1alpha1 kind: IngressRoute name: my-service-traefik-ingress path: patches/patch-internet-ingressroute.yaml# patch-internet-ingressroute.yaml- op: add path: /metadata/annotations value: kubernetes.io/ingress.class: traefik-internet
这样,internet traefik就只会处理 kubernetes.io/ingress.class: traefik-internet的ingressRoute了。之前的安全性问题也就不存在了。
参考文档
作者|think123|公众号
标签: #traefiknginx