两个应用,foo 和 bar,应用 foo 只允许 IP 地址为 1.2.3.4 访问,应用 bar 只允许 IP 地址为 5.6.7.8 访问。
基于 istio 的 AuthorizationPolicy 实现。
假设,现在 K8s 集群中已经安装 istio,并且有一个正在运行着的 istio-ingressgateway 转发应用 foo 和 bar:
通过:https://www.example.com/foo 访问
foo;通过:https://www.example.com/bar 访问
bar;
按照 istio 官方文档,使用 AuthorizationPolicy 即可实现基于应用层级的访问白名单设置:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: foo
spec:
selector:
matchLabels:
app: foo
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["1.2.3.4"]
想让以上AuthorizationPolicy生效,需要在
foo工作负载所在的命名空间注入istio-proxy,通过给命名空间添加 label,添加 lable 后,工作负载启动新的 Pod 会自动注入istio-proxy容器:kubectl label namespace default istio-injection=enabled
但是,你会发现你使用 https://www.example.com/foo 一直返回的信息都是 RBAC: access denied。为什么会这样呢?
如果你在 ipBlocks 中加入 istio-ingressgateway(是一个 Deployment)Pod 的 IP,你会发现这时候是可以成功访问的。
分析流量的转发路径应该就能知道,实际上到达目标应用 foo 的请求,都由istio-ingressgateway转发了,所以源 IP 都会是 istio-ingressgateway Pod 的 IP,从而导致外部访问 IP 的白名单设置无法生效。
那么如果获取外部IP呢。
Step 0: 获取客户端源IP:
如果使用 AWS-EKS 创建
istio-ingressgateway服务时默认创建的classic类型的 LoadBalancer,需要修改成network类型:通过向 istio-ingressgateway Service 添加 annotation:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
更新 istio-gateway Service:spec.externalTrafficPolicy: Local,现在访问工作负载可以获取到源 IP,这就为我们设置 IP 白名单造就了条件。
现在只需要为这个 istio-ingressgateway 应用上 AuthorizationPolicy 即可:
Step 1: 默认允许所有 IP 访问 istio-ingressgateway:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-all-for-istio-ingressgateway
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["0.0.0.0/0"]
默认是允许所有
IP都可以访问istio-ingressgateway下转发的服务的,如果有服务例如foo和bar需要单独添加IP访问百名单则继续参考下面的步骤。
Step 2: 只允许 IP 1.2.3.4 访问 foo:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: foo
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notIpBlocks: ["1.2.3.4"]
to:
- operation:
hosts:
- www.example.com
paths:
- /foo
- /foo/*
由于默认是允许所有
IP都可以访问istio-ingressgateway下转发的服务,所以为单独应用设置访问百名的时候使用DENY+notIpBlocks来完成。
ipBlocks和notIpBlocks允许配置IP和IP的CIDR,例如:1.2.3.4或1.2.3.4/24。
Step 3: 只允许 IP 5.6.7.8 访问 bar:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: bar
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
action: DENY
rules:
- from:
- source:
notIpBlocks: ["5.6.7.8"]
to:
- operation:
hosts:
- www.example.com
paths:
- /bar
- /bar/*
如果相同的 LoadBalancer 下的服务都是用同一白名单设置的话,则没必要这么麻烦的设置 AuthorizationPolicy 了,只需要为 Service 设置参数即可:
apiVersion: v1
kind: Service
metadata:
name: istio-gateway
...
spec:
type: LoadBalancer
loadBalancerSourceRanges:
- "1.2.3.4/24"
...