【问题标题】:Whitelist "kube-system" namespace using NetworkPolicy使用 NetworkPolicy 将“kube-system”命名空间列入白名单
【发布时间】:2018-11-21 06:51:01
【问题描述】:

我有一个多租户集群,其中多租户是通过命名空间实现的。每个租户都有自己的命名空间。一个租户的 Pod 不能与其他租户的 Pod 通信。但是,每个租户中的一些 pod 必须使用 Ingress 向 Internet 公开服务。

这我走了多远(我正在使用 Calico):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tenant1-isolate-namespace
  namespace: tenant1
spec:
  policyTypes:
  - Ingress
  podSelector: {} # Select all pods in this namespace
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: tenant1 # white list current namespace

为每个命名空间(tenant1tenant2、...)部署,这限制了其命名空间内 pod 之间的通信。但是,这会阻止 kube-system 命名空间中的 pod 与此命名空间中的 pod 通信。

但是,kube-system 命名空间默认没有任何标签,所以我不能专门将该命名空间列入白名单。

我通过手动给它一个标签找到了一个(肮脏的)解决方法:

kubectl label namespace/kube-system permission=talk-to-all

并将白名单规则添加到networkpolicy:

...
  - from:
    - namespaceSelector:
        matchLabels:
          permission: talk-to-all # allow namespaces that have the "talk-to-all privilege"

有没有更好的解决方案,不用手动给kube-system打标签?

编辑:我尝试另外添加一个“OR”规则,以专门允许来自标签为“app=nginx-ingress”的 pod 进行通信,但没有运气:

  - from
    ...
    - podSelector:
        matchLabels:
          app: nginx-ingress # Allow pods that have the app=nginx-ingress label

【问题讨论】:

  • 您是否设法将每个 ns 中的专用 pod 暴露给互联网,但仍然阻止命名空间之间的任何集群间通信?我尝试了你肮脏的解决方法,但我的专用 pod 无法从互联网(AWS ELB)访问......在我的入口网络策略中,我有 - podSelector:{} - namespaceSelector:matchLabels:permission:kube-system 我可以访问我的来自 kube-system 命名空间中 pod 的受保护命名空间不允许我访问受保护命名空间中的 ELB 公开 pod - 似乎来自 ELB 的外部流量不通过 kube-system 命名空间

标签: kubernetes project-calico kubernetes-networkpolicy


【解决方案1】:

apiVersion: networking.k8s.io/v1

namespaceSelector 旨在仅通过标签匹配命名空间。无法按名称选择命名空间。

podSelector 只能选择与 NetworkPolicy 对象在同一命名空间中的 pod。对于位于不同命名空间的对象,只能选择整个命名空间。

这是 Kubernetes 网络策略实施的示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

关注link 阅读有关网络政策整个概念的精彩解释,或关注link 观看讲座。

apiVersion: projectcalico.org/v3

Calico API 为您提供了更多编写 NetworkPolicy 规则的选项,因此,在某些时候,您可以用更少的精力和精力来实现您的目标。

例如,使用网络策略的 Calico 实现,您可以:

  • 为规则设置操作(允许、拒绝、记录、通过),
  • 使用负匹配(协议、notProtocol、选择器、notSelector),
  • 应用更复杂的标签选择器(has(k), k not in { ‘v1’, ‘v2’ }),
  • 将选择器与运算符 && 结合,
  • 使用端口范围(端口:[8080, "1234:5678", "named-port"]),
  • 匹配其他命名空间中的 pod。

但是,您仍然只能通过标签来匹配命名空间。

请考虑阅读 Calico documentation 了解详情。

这是 Calico 网络策略实施的示例:

apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: allow-tcp-6379
  namespace: production
spec:
  selector: role == 'database'
  types:
  - Ingress
  - Egress
  ingress:
  - action: Allow
    protocol: TCP
    source:
      selector: role == 'frontend'
    destination:
      ports:
      - 6379
  egress:
  - action: Allow

【讨论】:

  • 在 calico 中,您现在还可以按名称匹配命名空间:“使用 projectcalico.org/name 标签按名称选择特定的命名空间。”检查 namespaceSelector 的documentation
  • 所以,它是标签,等于命名空间名称,但选择器仍然只能使用标签。对吗?
  • selector 按标签(即 pod、服务)选择资源。 namespaceSelector 通过名称空间的标签选择资源。它们也可以一起使用。是的,afaik projectcalico.org/name 是一个指向命名空间名称的特殊标识符
【解决方案2】:

确实,tenant1 pod 需要专门访问 kube-system 命名空间中的 kube-dns

一种不需要标记kube-system 命名空间的方法是以下策略。 尽管kube-dns 可以使用这种方法在任何命名空间中,因此它可能不适合您。

---                                                                                                                                                                                                           
# Default deny all ingress & egress policy, except allow kube-dns                                                                                                                                             
# All traffic except this must be explicity allowed.                                                                                                                                                          
kind: NetworkPolicy                                                                                                                                                                                           
apiVersion: networking.k8s.io/v1                                                                                                                                                                              
metadata:                                                                                                                                                                                                     
  name: default-deny-all-except-kube-dns                                                                                                                                                                      
  namespace: tenant1                                                                                                                                                                                        
spec:                                                                                                                                                                                                         
  podSelector: {}                                                                                                                                                                                             
  egress:                                                                                                                                                                                                     
  - to:                                                                                                                                                                                                       
    - podSelector:                                                                                                                                                                                            
        matchLabels:                                                                                                                                                                                          
          k8s-app: kube-dns                                                                                                                                                                                   
 - ports:             
   - protocol: TCP                                                                                                                                                                                         
     port: 53                                                                                                                                                                                                                                                                                     
   - protocol: UDP                                                                                                                                                                                           
     port: 53                                                                                                                                                                                                
 policyTypes:                                                                                                                                                                                                
 - Ingress                                                                                                                                                                                                   
 - Egress   

然后,您还需要一个“允许所有在命名空间内的策略”,如下所示:

---                                                                                                                                                                                                           
# Allow intra namespace traffic for development purposes only.                                                                                                                                                
kind: NetworkPolicy                                                                                                                                                                                           
apiVersion: networking.k8s.io/v1                                                                                                                                                                              
metadata:                                                                                                                                                                                                     
  name: allow-intra-namespace                                                                                                                                                                                 
  namespace: tenant1                                                                                                                                                                                        
spec:                                                                                                                                                                                                         
  podSelector:                                                                                                                                                                                                
    matchLabels:                                                                                                                                                                                              
  ingress:                                                                                                                                                                                                    
  - from:                                                                                                                                                                                                     
    - podSelector: {}                                                                                                                                                                                         
  egress:                                                                                                                                                                                                     
  - to:                                                                                                                                                                                                       
    - podSelector: {}                                                                                                                                                                                         
  policyTypes:                                                                                                                                                                                                
  - Ingress                                                                                                                                                                                                   
  - Egress

最后,您需要添加特定策略,例如入口规则。 最好将 allow-intra-namespace 策略替换为适合各个 pod 的特定规则,您的 tenant1 可以这样做。

这些内容改编自本网站:https://github.com/ahmetb/kubernetes-network-policy-recipes

【讨论】:

  • 我已经为此奋斗了一段时间 - 你的 kube-dns 规则成功了。非常感谢!
【解决方案3】:

我在使用默认法兰绒 CNI 的 k3os 上。它在 kube-system 命名空间上有默认标签:

$ kubectl describe ns kube-system
Name:         kube-system
Labels:       kubernetes.io/metadata.name=kube-system
Annotations:  <none>
Status:       Active

这对我有用:

- namespaceSelector:
    matchLabels:
      kubernetes.io/metadata.name: kube-system

这是我的完整 yaml,它允许 kube-system 命名空间中的所有外部流量和 kube-dns 用于出口:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-egress
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
      - port: 53
        protocol: UDP
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.0.0.0/8
        - 172.16.0.0/12
        - 192.168.0.0/16

【讨论】:

    【解决方案4】:

    如果我理解正确,您使用的是印花布。只需使用他们的示例来了解如何在不破坏 kube-dns 通信的情况下实现默认拒绝。 找到here

    apiVersion: projectcalico.org/v3
    kind: GlobalNetworkPolicy
    metadata:
      name: deny-app-policy
    spec:
      namespaceSelector: has(projectcalico.org/name) && projectcalico.org/name not in {"kube-system", "calico-system"}
      types:
      - Ingress
      - Egress
      egress:
      # allow all namespaces to communicate to DNS pods
      - action: Allow
        protocol: UDP
        destination:
          selector: 'k8s-app == "kube-dns"'
          ports:
          - 53
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-16
      • 2020-03-24
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 2021-03-17
      相关资源
      最近更新 更多