前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在 istio 中使用 namespace 进行资源/租户隔离

在 istio 中使用 namespace 进行资源/租户隔离

原创
作者头像
谢正伟
修改2020-08-12 13:16:17
2.1K0
修改2020-08-12 13:16:17
举报
文章被收录于专栏:泛互云原生

PaaS 场景中,需要在集群中给客户提供容器部署他们自己开发的代码,如果使用 命名空间 来表示租户,则需要有效隔离租户,让隔壁的租户无法访问本租户的资源。下面的一些策略可以用来实现这种能力。

实验准备

计划部署 2 个租户,tn1 和 tn2,分别部署 httpbin 服务端应用和 wget 测试工具。

以下代码可以直接拷贝食用:

代码语言:txt
复制
apiVersion: v1
kind: Namespace
metadata:
  name: tn1
  labels:
    name: tn1
spec:
  finalizers:
    - kubernetes

---
apiVersion: v1
kind: Namespace
metadata:
  name: tn2
  labels:
    name: tn2
spec:
  finalizers:
    - kubernetes
---
# 在 tn1 中部署 httpbin
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: tn1
  labels:
    app: httpbin
    tenant: tn1
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: httpbin
    tenant: tn1
---   
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: tn1
  labels: 
    app: httpbin
    tenant: tn1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      tenant: tn1
  template:
    metadata:
      labels:
        app: httpbin
        tenant: tn1
    spec:
      containers:
      - image: kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80
          protocol: TCP


---
# 在 tn2 中部署 httpbin
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: tn2
  labels:
    app: httpbin
    tenant: tn2
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: httpbin
    tenant: tn2
---   
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: tn2
  labels: 
    app: httpbin
    tenant: tn2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      tenant: tn2
  template:
    metadata:
      labels:
        app: httpbin
        tenant: tn2
    spec:
      containers:
      - image: kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80
          protocol: TCP

---
# 分别在两个命名空间中部署 alpine/wget 测试程序
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wget
  namespace: tn1
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: wget
  template:
    metadata:
      labels:
        app: wget
    spec:
      containers:
      - image: alpine
        imagePullPolicy: IfNotPresent
        name: wget
        command: ["tail", "-f", "/dev/null"]


---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wget
  namespace: tn2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wget
  template:
    metadata:
      labels:
        app: wget
    spec:
      containers:
      - image: alpine
        imagePullPolicy: IfNotPresent
        name: wget
        command: ["tail", "-f", "/dev/null"]

使用 NetworkPolicy 隔离命名空间网络

如果要在 k8s 中使用 NetworkPolicy,需要安装相应的网络组件,在腾讯云 TKE 中,建议安装 kube-router ,只启用其中的 firewall 功能,用于实现 NetworkPolicy。kube-router 是腾讯云 TKE 官方建议的网络插件。

在腾讯云 TKE 上安装 kube-router 请参考这篇文章:https://cloud.tencent.com/developer/article/1583707

1、禁止非当前命名空间的 pod 访问(不同租户之间不能横向穿透)

代码语言:txt
复制
apiVersion: extensions/v1beta1
kind: NetworkPolicy
metadata:
  name: deny-others
  namespace: tn1
spec:
  ingress: 
  - from:
    - podSelector: {} 
  podSelector: {} 
  policyTypes:
  - Ingress

测试结果

代码语言:txt
复制
# 在 tn1 的 wget 上测试
# wget -qSO- http://httpbin.tn1/headers
  HTTP/1.1 200 OK
  server: envoy...
  
# wget -qSO- http://httpbin.tn2/headers
  HTTP/1.1 200 OK
  server: envoy...
  
# 在 tn2 的 wget 上测试
# wget -qSO- http://httpbin.tn1/headers
wget: cant connect to remote host (172.24.253.145): Connection refused...
  
# wget -qSO- http://httpbin.tn2/headers
  HTTP/1.1 200 OK
  server: envoy...
  

2、设置租户之间的东西向访问白名单

在某些情况下,需要让某些租户之间互访,如:同一个公司申请了多个租户。这个也可以是用 NetworkPolicy 来实现。

下面的例子指定了命名空间 tn1 和 tn2 中的 pod 可以访问 tn1 下的 pod,配置如下:

代码语言:txt
复制
apiVersion: extensions/v1beta1
kind: NetworkPolicy
metadata:
  name: deny-others
  namespace: tn1
spec:
  ingress: 
  - from:
    - namespaceSelector: 
        matchLabels: 
          name: tn1
    - namespaceSelector: 
        matchLabels: 
          name: tn2
  podSelector: {} 
  policyTypes:
  - Ingress

注意:以上配置在 tke 1.16 和 kube-router 0.2.4,并且没有自动注入 sidecar 的情况下测试通过。

目前 kube-router 测试在 istio 中测试有 bug。

建议在纯的 K8S 环境下使用 NetworkPoclicy ,在 Istio 中使用 AuthorizationPolicy,这将在下一节中探讨。

附:在 TKE 安装最新版的 kube-router

可以基于官网的配置 https://github.com/cloudnativelabs/kube-router/blob/master/daemonset/kube-router-firewall-daemonset.yaml 需要修改配置文件的地址,具体有:

  • 文件名 10-kuberouter.conflist 修改为 10-kuberouter.conf (?)
  • /var/lib/kube-router/kubeconfig 修改为 /root/.kube/config

使用 Istio AuthorizationPolicy 隔离资源

使用 istio 的认证策略,前提是有 sidecar。下面的例子中,需要在 namespace 中增加 label: “istio-injection: enabled ”。

禁止命名空间内的 pod 被访问

下面的配置定义了 tn1 中的pod无法被访问:

代码语言:txt
复制
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: tn1
spec:
  {}

上述配置,在所有的 pod 无法都访问 tn1 里的服务,他限制了所有的流量:

代码语言:txt
复制
# wget -qSO- httpbin.tn1/get
  HTTP/1.1 403 Forbidden
wget: server returned error: HTTP/1.1 403 Forbidden

租户间横向打通

通过 AuthorizationPolicy 可以轻松对命名空间进行配置:

代码语言:txt
复制
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: tn1
spec:
  action: ALLOW
  rules: 
  - from:
    - source:
        namespaces: ['tn1']
  

上面的配置放开了 tn1 命名空间内的 pod 对 本命名空间的访问。如果需要打通更多指定的命名空间,只需要将相应的名字加入 配置中即可。

更精细的控制

使用 AuthorizationPolicy ,可以针对 http 的 url,method 进行更精细的控制,下面的例子中,仅仅租户 tn1 的 /get api 才允许被 tn2 访问:

代码语言:txt
复制
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: tn1
spec:
  action: ALLOW
  rules: 
  - from:
    - source:
        namespaces: ['tn1']
  - from:
    - source:
        namespaces: ['tn2']
    to:
    - operation:
        methods: ["GET"]
        paths: ["/get"]

更详细的权限控制可以参考官方文档:https://istio.io/latest/docs/reference/config/security/authorization-policy/

在 istio 中开放出口流量白名单

在本小节,我们尝试使用 istio 中的 ServiceEntry 来完成对指定命名空间的的出集群流量控制。

场景:在 istio 集群中,需要使用 namespace 来隔离资源,为特定 namespace 开放集群外访问白名单。

在 istio 的 Service Entry 文档中,我们可以找到相关的功能,关键字是 exportTo,以下是试验过程:

首先将 Istio 集群的外部访问设置为 REGISTRY_ONLY(修改 ConfigMap 的 istio 配置),腾讯云 TCM 可以直接在控制台设置。

代码语言:txt
复制
outboundTrafficPolicy:
  mode: REGISTRY_ONLY

创建 Service Entry,开放 tn1 命名空间对 baidu 的访问权限。

代码如下:

代码语言:txt
复制
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: baidu-external
  namespace: tn1
spec:
  hosts:
  - www.baidu.com
  exportTo:
  - "."
  ports:
  - number: 443
    name: https
    protocol: TLS
  resolution: DNS
  location: MESH_EXTERNAL

通过测试:

1 带有 sidecar 的 tn1 命名空间下的 pod 可以访问 (没有 sidecar 的 pod 也可以访问 )。

代码语言:txt
复制
# wget -qSO- https://www.baidu.com
  HTTP/1.1 200 OK
  Content-Length: 2443
  Content-Type: text/html
  Server: bfe
  Date: Wed, 05 Aug 2020 08:09:24 GMT
  Connection: close
  
<!DOCTYPE html>
...

2 带有 sidecar 的 其他命名空间下的 pod 不可以访问

代码语言:txt
复制
# wget -qSO- https://www.baidu.com
ssl_client: www.baidu.com: handshake failed: unexpected EOF
wget: error getting response: Connection reset by peer

达到访问外部资源隔离的目的。

上面的配置中,起到关键作用的是 namespace 和 exportTo 两项配置。

按照官方文档:当前 exportTo 只可以为 “.” 或 “*”,分别对应着 当前命名空间 和 所有命名空间 有效。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实验准备
  • 使用 NetworkPolicy 隔离命名空间网络
    • 1、禁止非当前命名空间的 pod 访问(不同租户之间不能横向穿透)
      • 2、设置租户之间的东西向访问白名单
        • 附:在 TKE 安装最新版的 kube-router
        • 使用 Istio AuthorizationPolicy 隔离资源
          • 禁止命名空间内的 pod 被访问
            • 租户间横向打通
              • 更精细的控制
              • 在 istio 中开放出口流量白名单
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档