入口网关
此任务向您展示如何使用授权策略在 Istio 入口网关上实施基于 IP 的访问控制。
开始之前
在开始此任务之前,请执行以下操作:
阅读 Istio 授权概念。
使用 Istio 安装指南 安装 Istio。
在命名空间中部署工作负载
httpbin
,例如foo
,并使用以下命令通过 Istio 入口网关公开它:$ kubectl create ns foo $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin-gateway.yaml@) -n foo
在 Envoy 中为入口网关打开 RBAC 调试:
$ kubectl get pods -n istio-system -o name -l istio=ingressgateway | sed 's|pod/||' | while read -r pod; do istioctl proxy-config log "$pod" -n istio-system --level rbac:debug; done
Follow the instructions in 确定入口 IP 和端口 to define the
INGRESS_HOST
andINGRESS_PORT
environment variables.Verify that the
httpbin
workload and ingress gateway are working as expected using this command:$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
将流量引入 Kubernetes 和 Istio
所有将流量引入 Kubernetes 的方法都涉及在所有工作节点上打开一个端口,实现这一点的主要功能是NodePort
服务和LoadBalancer
服务,甚至 Kubernetes 的Ingress
资源也必须由 Ingress 控制器支持,该控制器将创建NodePort
或LoadBalancer
服务。
NodePort
只是在每个工作节点上打开一个 30000-32767 范围内的端口,并使用标签选择器来识别将流量发送到哪些 Pod。 您必须在工作节点前面手动创建某种负载均衡器或使用轮询模式的 DNS。LoadBalancer
就像NodePort
一样,除了它还创建一个特定于环境的外部负载均衡器来处理将流量分配到工作节点。 例如,在 AWS EKS 中,LoadBalancer
服务将创建一个以您的工作程序节点为目标的经典 ELB。 如果您的 Kubernetes 环境没有LoadBalancer
实现,那么它的行为就像NodePort
。 Istio 入口网关创建一个LoadBalancer
服务。
如果处理来自 NodePort
或 LoadBalancer
的流量的 Pod 没有在接收流量的工作节点上运行怎么办? Kubernetes 有自己的内部代理,称为 kube-proxy,它接收数据包并将它们转发到正确的节点。
原始客户端的源IP地址
如果数据包通过外部代理负载均衡器和/或 kube-proxy,则客户端的原始源 IP 地址会丢失。 以下是一些保留原始客户端 IP 以用于日志记录或安全目的的策略。
作为参考,以下是 Istio 在流行的托管 Kubernetes 环境中使用LoadBalancer
服务创建的负载均衡器类型:
Cloud Provider | Load Balancer Name | Load Balancer Type |
---|---|---|
AWS EKS | Classic Elastic Load Balancer | TCP Proxy |
GCP GKE | TCP/UDP Network Load Balancer | Network |
Azure AKS | Azure Load Balancer | Network |
DO DOKS | Load Balancer | Network |
基于 IP 的允许列表和拒绝列表
何时使用 ipBlocks
与 remoteIpBlocks
: 如果您使用 X-Forwarded-For HTTP 标头或代理协议来确定原始客户端 IP 地址,那么您应该在您的 AuthorizationPolicy
中使用 remoteIpBlocks
. 如果您使用的是 externalTrafficPolicy: Local
,那么您应该在 AuthorizationPolicy
中使用 ipBlocks
。
Load Balancer Type | Source of Client IP | ipBlocks vs. remoteIpBlocks |
---|---|---|
TCP Proxy | Proxy Protocol | remoteIpBlocks |
Network | packet source address | ipBlocks |
HTTP/HTTPS | X-Forwarded-For | remoteIpBlocks |
- 以下命令为 Istio 入口网关创建授权策略
ingress-policy
。 以下策略将action
字段设置为ALLOW
,以允ipBlocks
中指定的 IP 地址访问入口网关。 不在列表中的 IP 地址将被拒绝。ipBlocks
支持单个 IP 地址和 CIDR 表示法。
验证对入口网关的请求是否被拒绝:
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 403
更新
ingress-policy
以包含您的客户端 IP 地址:
验证是否允许对入口网关的请求:
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
更新
ingress-policy
授权策略,将action
键设置为DENY
,从而不允许ipBlocks
中指定的 IP 地址访问入口网关:
验证对入口网关的请求是否被拒绝:
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 403
您可以使用在线代理服务使用不同的客户端 IP 访问入口网关,以验证请求是否被允许。
如果您没有得到预期的响应,请查看应显示 RBAC 调试信息的入口网关日志:
$ kubectl get pods -n istio-system -o name -l istio=ingressgateway | sed 's|pod/||' | while read -r pod; do kubectl logs "$pod" -n istio-system; done
清理
删除命名空间
foo
:$ kubectl delete namespace foo
删除授权策略:
$ kubectl delete authorizationpolicy ingress-policy -n istio-system