一、前言
继上篇文章所言,我们在AWS EKS中使用 Ingress+ALB 对外暴露服务,在上篇文章中我测试了Ingress+NLB方案并取得了成功,但对当前环境改动较大(修改DNS解析、域名和服务的绑定全部都要切到新Ingress上)最终还是作为备选方案。
二、方案思考
虽然 Ingress+NLB 方案只能作为备选,但我们团队也提出了其它方案的思考:
- ALB是否支持插件,这样我们只需要在插件中配置白名单,如果是允许的来源IP就返回给ALB放行;
- AWS WAF是一项Web应用程序防火墙服务,可以调研下看看是否可以用在当前环境;
带着这样两个问题,又重新翻阅了AWS的文档,然而并没有找到ALB是否支持插件的相关说明;于是将目标转向了AWS WAF服务,在对WAF服务进行测试中发现WAF只能绑定ALB并不支持ALB后端的虚拟主机(规则),在来看看AWS WAF服务功能说明:AWS WAF是一项Web应用程序防火墙服务,可让您监视转发到Amazon API Gateway API,Amazon CloudFront发行版或应用程序负载均衡器的Web请求。您可以根据指定的条件(例如,请求源的IP地址)来保护那些资源。
WAF这个服务可以看作是Web应用程序防火墙,它位于ALB等资源的前端,可以用它来保护我们的API Gateway、ALB、AWS AppSync等资源可以用它来防范DDoS攻击、SQL注入等。
既然以上两个方案都行不通,那有没有其它可行的方案呢?
三、灵机一动
这时,我从之前的 Ingress+NLB 方案中有了启发,那需要怎么进行调整呢,通过下图我们一起来看看:
这是调整前服务暴露方式
这是调整后的服务暴露方式
首先:有服务A.service.com和B.service.com 两个服务,我们需要对B.service.com配置白名单访问,由于ALB只支持5个白名单配置,图1 中当白名单超过5个时便达到了瓶颈;
同样:在图2 中我们只需要将配置白名单的服务B.service.com从ALB转发给自建Ingress 由该Ingress服务进行白名单审核之后将流量再转发给后端的service-B,我们只需要在自建Ingress中配置白名单,而且自建Ingress内部是nginx服务理论上支持的白名单数量无限。
这样一来,就可以完美解决ALB白名单不够用的问题了。
那么,具体要怎么实现呢
四、实施过程
4.1 部署Ingress+ALB
这里已经部署好了 EKS Ingress+ALB 就不在进行阐述了,可以参考AWS官方文档进行部署
4.2 部署自建Ingress
自建Ingress我选择的是nginx-ingress,部署和上篇文章差不多但,但在部署Service时略有差异,具体我们一起来看下:
4.2.1 部署deployment
首先从GitHub克隆下来代码,切换到最新的tag
1 | $ git clone https://github.com/kubernetes/ingress-nginx.git |
接下来部署deploy/static
目录下的mandatory.yaml
,生产环境建把pod副本数设置为2以上
1 | $ cd deploy/static/ |
修改时区
1 | $ vim mandatory.yaml |
如果有需要特殊调整(例如:修改Ingress健康检测路径与ALB一致),可以参考https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/
我这里是测试环境,将mandatory.yaml
文件的namespace都改成了qa
1 | $ kubectl apply -f mandatory.yaml |
部署完后查看deployment部署状态
1 | $ kubectl get pod -n qa | grep ingress |
如果有多namespace部署Ingress的需求,需要把ClusterRoleBinding 的 name 修改为不同名称(否则容器会启动失败),我这里将原来的nginx-ingress-clusterrole-nisa-binding
改为了nginx-ingress-clusterrole-nisa-binding-qa
最好是ClusterRole 的 name 也一起修改。
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole-qa…………忽略部分内容…………
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding-qa
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole-qa
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: qa
4.2.2 部署service
在上篇文章中我们创建Service是为了让它自动去创建相应的NLB服务然后自动和Service关联上。
但在这里,我调整了架构(将ALB流量转发到自建Ingress),所以要把Service创建NLB部分的配置去掉,让我们自建的Ingress对接ALB的转发规则。后面我们只需要ALB把客户端的真实IP传过来就可以做白名单限制了。
修改service.yaml,或者直接使用没有云服务商配置的service.yaml
1 | $ cd provider/baremetal/ |
部署完后查看service状态
1 | $ kubectl get service -n qa| grep ingress |
4.3 测试白名单
4.3.1 部署测试服务
部署nginx服务
1 | $ cat nginx-deployment-service.yaml |
4.3.2 配置Ingress转发规则
这里需要配置两个Ingress规则(AWS Ingress和自建Ingress)
AWS Ingress:将需要配置白名单的服务转发给自建Ingress
自建Ingress:配置白名单,将流量转发给后端服务
配置 AWS Ingress规则
1 | - host: au-nginx.qa.service.com |
只需要将原先backend转发到
服务
的Service改为我们部署的ingress-nginx
Service即可
配置自建Ingress规则1
1 | kind: Ingress |
- nginx.ingress.kubernetes.io/server-snippet:在nginx 的 server 配置块中添加自定义配置;
- nginx.ingress.kubernetes.io/whitelist-source-range:允许的客户端IP源范围,该值是逗号分隔的CIDR列表,例如
10.0.0.0/24,172.10.0.1
。
如果不知道上一级代理的IP地址或者IP段,可以使用下面第二种方式
配置自建Ingress规则2
修改 nginx-igres
s 的 configmap
配置 nginx-configuration
,增加以下配置
1 | data: |
该配置对所在 namespace
下的所有 ingress
都生效,所以在该 namespace
下的 ingress
只需要配置允许访问的白名单IP即可
然后配置ingress规则
1 | kind: Ingress |
以上便是架构调整部分的具体实施步骤(实际就修改了两个Ingress配置),现在我们来验证服务是否可以访问,以及白名单是否生效。
4.3.3 测试白名单配置
以上配置好后,当我们在白名单所在服务器上访问时
1 | [root@host ~]# curl -Ik http://au-nginx.qa.service.com |
在其它服务器上访问时
1 | $ curl -Ik http://au-nginx.qa.service.com |
到这里已经把原先ALB的白名单移到了我们自建的Ingress上,以后再也不用为ALB的白名单配额不够而发愁了。