默认情况下,服务网格内的工作负载可以互相访问。您可以使用授权策略设置工作负载的访问条件,仅符合要求的请求才能访问对应工作负载。本文以限制访问工作负载的请求路径、方法和客户端IP为例,介绍如何为工作负载设置访问策略。
背景信息
授权策略支持CUSTOM、DENY和ALLOW策略类型。规则的判断存在优先级关系,当CUSTOM、DENY和ALLOW策略同时用于同一个工作负载时,将首先验证CUSTOM策略,然后验证DENY策略,最后验证ALLOW策略,并且存在以下关系:
- 如果任何一个CUSTOM策略匹配了请求并验证结果为拒绝,则拒绝此请求。
- 如果任何一个DENY策略匹配了请求并验证结果为拒绝,则拒绝此请求。
- 如果此工作负载上没有配置ALLOW策略,允许此请求(默认允许)。
- 如果该工作负载配置了ALLOW策略,并且ALLOW策略匹配此请求,允许此请求。
- 如果都不满足以上要求,则拒绝此请求。
场景示例一:限制访问工作负载的请求路径
本示例中,所有命名空间下的应用仅支持访问foo命名空间下的httpbin应用的/headers路径,访问其他路径都将失败,foo命名空间下的应用访问httpbin应用不受任何限制。
步骤一:为default和foo命名空间注入Sidecar代理
- 创建default和foo命名空间。具体操作,请参见管理全局命名空间。
- 为default命名空间注入Sidecar代理。
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择。
- 在全局命名空间页面单击default命名空间右侧操作列下的启用Sidecar自动注入。
- 在确认对话框单击确定。
- 重复步骤2,为foo命名空间注入Sidecar代理。
步骤二:部署测试应用
- 在default和foo命名空间部署sleep应用。
- 使用以下内容,创建sleep.yaml。
apiVersion: v1
kind: ServiceAccount
metadata:
name: sleep
---
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
service: sleep
spec:
ports:
- port: 80
name: http
selector:
app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
terminationGracePeriodSeconds: 0
serviceAccountName: sleep
containers:
- name: sleep
image: curlimages/curl
command: ["/bin/sleep", "3650d"]
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /etc/sleep/tls
name: secret-volume
volumes:
- name: secret-volume
secret:
secretName: sleep-secret
optional: true
---
- 执行以下命令,在default命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n default
- 执行以下命令,在foo命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n foo
- 在foo命名空间部署httpbin应用。
- 使用以下内容,创建httpbin.yaml。
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
- 执行以下命令,在foo命名空间部署httpbin应用。
kubectl apply -f httpbin.yaml -n foo
步骤三:创建授权策略
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击创建。
- 在创建页面设置授权策略参数,然后单击创建。
配置项 | 说明 |
---|
名称 | 自定义授权策略名称。 |
策略类型 | 设置策略类型为允许。 |
命名空间 | 在工作负载生效页签,设置命名空间为foo。 |
生效范围 | 选择生效范围为Service。 |
工作负载 | 设置工作负载为httpbin。 |
命名空间(Namespaces) | 在添加请求来源区域,打开命名空间(Namespaces)开关,设置值为foo。 以上设置,使得foo命名空间下的应用都能访问httpbin应用。 |
HTTP路径(Paths) | 在添加请求目标区域,打开HTTP路径(Paths)开关,设置值为/headers。 以上设置,使得所有命名空间下的应用仅支持访问foo命名空间下的httpbin应用的/headers路径。 |
步骤四:验证限制访问请求路径是否成功
- 使用default命名空间下的sleep应用访问foo命名空间下的httpbin应用。
- 登录容器服务管理控制台。
- 在控制台左侧导航栏,单击集群。
- 在集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情。
- 在集群管理页左侧导航栏,选择。
- 在容器组页面顶部设置命名空间为default,单击sleep右侧操作列下的终端,选择容器:sleep。
- 在sleep容器终端中执行以下命令,访问httpbin应用的/headers路径。
curl httpbin.foo.svc.cluster.local:8000/headers
预期输出:
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.foo.svc.cluster.local:8000",
"User-Agent": "curl/7.82.0-DEV",
"X-Envoy-Attempt-Count": "1",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=f7ab4985563b5b1986314d5a36c6e46819213e2f38301f534f00afb7cd4b9164;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep"
}
}
- 在sleep容器终端中执行以下命令,访问httpbin应用的/ip路径。
curl httpbin.foo.svc.cluster.local:8000/ip
返回403,提示访问被拒绝。
- 使用foo命名空间下的sleep应用访问foo命名空间下的httpbin应用。
- 在集群管理页左侧导航栏,选择。
- 在容器组页面顶部设置命名空间为foo,单击sleep右侧操作列下的终端,选择容器:sleep。
- 在sleep容器终端中执行以下命令,访问httpbin应用的/headers路径。
curl httpbin.foo.svc.cluster.local:8000/headers
预期输出:
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.foo.svc.cluster.local:8000",
"User-Agent": "curl/7.82.0-DEV",
"X-Envoy-Attempt-Count": "1",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=f7ab4985563b5b1986314d5a36c6e46819213e2f38301f534f00afb7cd4b9164;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep"
}
}
- 在sleep容器终端中执行以下命令,访问httpbin应用的/ip路径。
curl httpbin.foo.svc.cluster.local:8000/ip
预期输出:
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.foo.svc.cluster.local:8000",
"User-Agent": "curl/7.82.0-DEV",
"X-Envoy-Attempt-Count": "1",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/foo/sa/httpbin;Hash=f7ab4985563b5b1986314d5a36c6e46819213e2f38301f534f00afb7cd4b9164;Subject=\"\";URI=spiffe://cluster.local/ns/foo/sa/sleep"
}
}
可以看到default命名空间中的应用仅能访问foo命名空间下的httpbin应用的/headers路径,访问其他路径失败,foo命名空间中的应用访问httpbin应用不受任何限制,说明限制访问工作负载的请求路径成功。
场景示例二:限制访问工作负载的请求路径和方法
本示例中,所有命名空间下的应用仅支持通过GET请求访问foo命名空间下的httpbin应用的/status路径,访问其他路径或使用其他请求方法都将失败。
步骤一:为default和foo命名空间注入Sidecar代理
- 创建default和foo命名空间。具体操作,请参见管理全局命名空间。
- 为default命名空间注入Sidecar代理。
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择。
- 在全局命名空间页面单击default命名空间右侧操作列下的启用Sidecar自动注入。
- 在确认对话框单击确定。
- 重复步骤2,为foo命名空间注入Sidecar代理。
步骤二:部署测试应用
- 在default和foo命名空间部署sleep应用。
- 使用以下内容,创建sleep.yaml。
apiVersion: v1
kind: ServiceAccount
metadata:
name: sleep
---
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
service: sleep
spec:
ports:
- port: 80
name: http
selector:
app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
terminationGracePeriodSeconds: 0
serviceAccountName: sleep
containers:
- name: sleep
image: curlimages/curl
command: ["/bin/sleep", "3650d"]
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /etc/sleep/tls
name: secret-volume
volumes:
- name: secret-volume
secret:
secretName: sleep-secret
optional: true
---
- 执行以下命令,在default命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n default
- 执行以下命令,在foo命名空间部署sleep应用。
kubectl apply -f sleep.yaml -n foo
- 在foo命名空间部署httpbin应用。
- 使用以下内容,创建httpbin.yaml。
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 80
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
version: v1
template:
metadata:
labels:
app: httpbin
version: v1
spec:
serviceAccountName: httpbin
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
- 执行以下命令,在foo命名空间部署httpbin应用。
kubectl apply -f httpbin.yaml -n foo
步骤三:创建授权策略
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击创建。
- 在创建页面设置授权策略参数,然后单击创建。
配置项 | 说明 |
---|
名称 | 自定义授权策略名称。 |
策略类型 | 设置策略类型为允许。 |
命名空间 | 在工作负载生效页签,设置命名空间为foo。 |
生效范围 | 选择生效范围为Service。 |
工作负载 | 设置工作负载为httpbin。 |
HTTP方法(Methods) | 在添加请求目标区域,打开HTTP方法(Methods)开关,设置值为GET。 |
HTTP路径(Paths) | 在添加请求目标区域,打开HTTP路径(Paths)开关,设置值为/status/*。 以上设置,使得所有命名空间下的应用仅支持使用GET方法访问foo命名空间下的httpbin应用的/status路径。 |
步骤四:验证限制访问工作负载的请求路径和方法是否成功
- 登录容器服务管理控制台。
- 在控制台左侧导航栏,单击集群。
- 在集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情。
- 在集群管理页左侧导航栏,选择。
- 在容器组页面顶部设置命名空间为default,单击sleep右侧操作列下的终端,选择容器:sleep。
- 在sleep容器终端中执行以下命令,使用POST的方式访问httpbin应用的/status路径。
curl -I -X POST "httpbin.foo.svc.cluster.local:8000/status/200" -H "accept: text/plain"
返回403,访问httpbin应用失败。
- 执行以下命令,使用GET的方式访问httpbin应用的/IP路径。
curl -I -X GET "httpbin.foo.svc.cluster.local:8000/IP/200" -H "accept: text/plain"
返回403,访问httpbin应用失败。
- 执行以下命令,使用GET的方式访问httpbin应用的/status路径。
curl -I -X GET "httpbin.foo.svc.cluster.local:8000/status/200" -H "accept: text/plain"
预期输出:
HTTP/1.1 200 OK
server: envoy
date: Fri, 29 Apr 2022 03:01:16 GMT
content-type: text/html; charset=utf-8
access-control-allow-origin: *
access-control-allow-credentials: true
content-length: 0
x-envoy-upstream-service-time: 5
根据以上结果,可以看到default命名空间下的应用只有使用GET方式访问httpbin应用的/status路径才能成功,说明限制访问工作负载的请求路径和方法成功。
场景示例三:限制访问工作负载的客户端IP
限制foo命名空间中的httpbin应用只能被许可的客户端IP访问。
步骤一:为foo命名空间注入Sidecar代理
- 创建foo命名空间。具体操作,请参见管理全局命名空间。
- 为foo命名空间注入Sidecar代理。
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择。
- 在全局命名空间页面单击default命名空间右侧操作列下的启用Sidecar自动注入。
- 在确认对话框单击确定。
步骤二:创建ASM网关
- 登录ASM控制台,在左侧导航栏,选择。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择。
- 在入口网关页面,单击创建。
- 设置网关的基本信息,以下介绍重点参数,其他参数采用默认配置。
参数 | 说明 |
---|
名称 | 自定义网关的名称。 |
部署集群 | 选择网关部署的集群。 |
网关类型 | 选择南北向-入口。 |
负载均衡类型 | 选择公网访问。 |
新建负载均衡 | 选择负载均衡,可选:- 使用已有负载均衡:从已有负载均衡列表中选择。
- 新建负载均衡:单击新建负载均衡,从下拉列表中选择所需的负载均衡规格。
|
端口映射 | 单击添加端口,在新增端口行中,选择协议,输入服务端口。 |
- 单击高级选项,设置外部流量策略为Local,单击创建。
步骤三:创建虚拟服务和网关规则
- 创建虚拟服务。
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击使用YAML创建。
- 设置命名空间为foo,场景模板采用默认设置,将以下内容输入到YAML文本框中,然后单击创建。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: httpbin
spec:
gateways:
- httpbin-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /headers
route:
- destination:
host: httpbin
port:
number: 8000
- 创建网关规则。
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击使用YAML创建。
- 设置命名空间为foo,场景模板采用默认设置,将以下内容输入到YAML文本框中,然后单击创建。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: http
number: 80
protocol: HTTP
步骤四:创建授权策略
- 获取ASM网关IP。具体操作,请参见创建入口网关服务。
- 获取客户端IP。
在浏览器地址栏中输入
http://{ASM网关IP}/headers,获取
X-Envoy-External-Address右侧的IP。

- 创建授权策略。
- 登录ASM控制台。
- 在左侧导航栏,选择。
- 在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
- 在网格详情页面左侧导航栏,选择,然后在右侧页面,单击创建。
- 在创建页面设置授权策略参数,然后单击创建。
配置项 | 说明 |
---|
名称 | 自定义授权策略名称。 |
策略类型 | 设置策略类型为拒绝。 |
命名空间 | 在工作负载生效页签,设置命名空间为foo。 |
生效范围 | 选择生效范围为Service。 |
工作负载 | 设置工作负载为httpbin。 |
原始源IP(RemoteIPBlocks) | 在添加请求来源区域,打开原始源IP(RemoteIPBlocks)开关,设置值为步骤2获取的客户端IP。 以上设置,使得客户端IP将无法访问httpbin应用。 |
步骤五:验证限制访问工作负载的客户端IP是否成功
在浏览器地址栏中输入
http://{ASM网关IP}/headers,返回
RBAC:access denied
,访问httpbin应用失败,说明限制访问工作负载的客户端IP成功。
