首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes出口网络策略指南

Kubernetes出口网络策略指南

作者头像
CNCF
发布2020-02-20 17:00:53
1.8K0
发布2020-02-20 17:00:53
举报
文章被收录于专栏:CNCFCNCF

访客文章最初由Viswajith Venugopal在StackRox上发布

https://www.stackrox.com/post/2020/01/kubernetes-egress-network-policies/

几个月前,我们发布了一份建立Kubernetes网络策略指南,专门介绍了入口(ingress)网络策略。这篇后续文章将解释如何增强你的网络策略来控制允许的出口(egress)。

https://www.stackrox.com/post/2019/04/setting-up-kubernetes-network-policies-a-detailed-guide/

简要回顾:网络策略是什么?

Kubernetes使用网络策略来指定允许豆荚组(groups of pods)相互通信,以及与外部网络端点通信的方式。它们可以被看作是Kubernetes的防火墙。与大多数Kubernetes对象一样,网络策略非常灵活和强大——如果你知道应用程序中服务的确切通信模式,就可以使用网络策略将通信限制在所需的范围内。

入口(Ingress)和出口(Egress)

可以使用网络策略来指定允许豆荚的入口和允许豆荚的出口。这些规范的工作方式正如人们所期望的:

  • 如果允许从集群外部网络端点到豆荚的入口,则允许从该端点到豆荚的流量。
  • 如果允许从豆荚到集群外部网络端点的出口,则允许从豆荚到该端点的流量。
  • 允许流量从一个豆荚(A)到另一个(B)当且仅当从A到B允许出口,以及允许从A到B的入口。 注意控制单向——允许流量从B被连接到到A,必须允许从B出口到A,以及从A入口到B。

先建立入口!

首先,我们建议在建立出口网络策略之前,先建立入口网络策略,并成功实施。

为什么?首先,不同时做这两件事比较简单,否则很难知道网络连接是否因为入口或出口配置而被阻塞。第二,也是更重要的一点,出口网络策略通常更难实施。限制出口常常会以意想不到的方式破坏应用程序。虽然通常比较容易确定我们希望从哪个网络端点与豆荚通信,但是在实践中,通常很难确定从豆荚连接到哪个网络端点。出现这种挑战的原因是:

  1. 作为常规功能的一部分,部署通常会查询一组外部服务。根据他们在接触这些服务时处理超时的方式,功能可能会受到微妙而难以观察的影响。
  2. 部署需要能够与DNS服务器通信,以便能够与任何其他服务器通信,除非它们直接通过IP访问服务。

要建立入口策略,你可以遵循我们前面提到的指南。

https://www.stackrox.com/post/2019/04/setting-up-kubernetes-network-policies-a-detailed-guide

给豆荚做出口隔离

每个网络策略都有一个podSelector字段,它选择一组(0个或多个)豆荚。当一个豆荚被一个网络策略选择时,该网络策略被称为应用于它。

此外,根据policyTypes字段的值,每个网络策略可以应用于入口、出口或两者(如果在YAML中没有指定该字段,则其值默认为策略中存在的入口和出口规则;由于默认逻辑很微妙,我们建议总是显式地指定它)。

在下文中,我们将使用术语“出口网络策略”来表示适用于出口的任何网络策略(无论该策略是否也适用于入口)。

默认情况下,如果没有出口网络策略适用于豆荚,那么出口就是非隔离的。(注意隔离是单独评估入口和出口;一个豆荚有可能是两者也没隔离,单个做了隔离,或者两者都做了隔离)。当一个豆荚没有隔离出口时,所有的网络出口都允许从豆荚中出来。

一旦一个出口网络策略适用于一个豆荚,豆荚为出口隔离。对于隔离的豆荚,只有在至少一个适用于它的安全出口网络策略允许的情况下,才允许网络出口(即,网络策略仅为白名单)。

因此,建立出口网络的第一步是给豆荚做出口隔离。我们建议一开始就采用“默认拒绝所有”的策略,这将隔离所有给豆荚的出口。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
spec:
  podSelector: {}
  egress:
  - to:
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

请注意,此策略默认允许连接到任何IP上的端口53,以方便DNS查找。因此,虽然它可以防止意外的出口,但它不能防止数据泄漏,因为攻击者能将数据发送到端口53。

如果你确定地知道你的豆荚将使用什么DNS服务器,你可以进一步确定访问范围。

例如,要将DNS范围缩小到只提供kube-dns服务,你可以执行以下操作:

  1. 标记kube-system命名空间: kubectl label namespace kube-system networking/namespace=kube-system
  2. 适用以下网络策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
spec:
  podSelector: {}
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          networking/namespace: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

重要提示:由于网络策略是带命名空间的资源,因此需要为每个命名空间创建此策略。你可以通过为每个命名空间运行来做到这一点。

kubectl -n <namespace> create -f <filename> 

除非你知道自己在做什么,否则不要将此应用于kube-system命名空间,因为它会破坏集群功能。

明确允许有需要的豆荚通到互联网的出口

在每个命名空间中都采用了default-deny-all-egress策略,你的豆荚将无法连接到Internet,但在大多数应用程序中,至少有一些豆荚需要连接到Internet。为了允许这种设置,一种方法是为允许互联网出口的豆荚指定标签,并创建针对这些标签的网络策略。例如,下面的网络策略允许来自具有networking/allow-internet-egress=true标签的豆荚的流量到达所有网络端点(包括集群外部的端点)。请再次注意,与前一节一样,你必须为每个命名空间创建此策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: internet-egress
spec:
  podSelector:
    matchLabels:
      networking/allow-internet-egress: "true"
  egress:
  - {}
  policyTypes:
  - Egress

对于更锁定的策略集,理想情况下应该指定更细粒度的CIDR块,并显式地列出允许的端口和协议。但是,该策略提供了一个良好的起点,安全性比默认值高得多。

明确允许必要的点对点通信

如果你将你的豆荚隔离起来,然后明确地允许豆荚之间的通信,直到你的应用程序正常工作,你可能会发现,当你应用了“默认拒绝所有出口”策略时,所有的通信都被阻塞了。这种行为是预期的:每一个连接,你在入口方向的白名单,你现在需要在出口方向的白名单。无论你是遵循我们的建议(例如允许所有命名空间通信、使用源接收方法或在各个豆荚之间建立白名单连接),还是使用自定义方法,只需对构建的每个入口策略遵循以下算法,以构建相应的出口策略。

构建配套的出口策略

对于允许从一组豆荚到另一组豆荚通信的入口策略,配套的出口策略的构建相当简单。首先,将policyTypes字段更改为仅包含Egress的数组。将spec.podSelector放在spec.egress.to.podSelector中。移除ingress.from,但是从那里获取ingress.from.podselector,并放到新的出口策略的spec.podSelector里。如果入口策略是一个命名空间以内的策略,那么就完成了!

对于跨命名空间的策略,假设你已经按照我们在入口指南中建议的那样使用network/namespace: <ns-name>标签标记了每个命名空间(回想一下,你可以通过运行以下的来做到这一点)

kubectl label namespace <name> networking/namespace=<name>

你需要将在入口策略中选择的ingress.from.namespaceselector的命名空间作为出口策略的metadata.namespace,并将在入口策略的metadata.namespace中指定的名称空间,放到出口策略的egress.to.namespaceSelector字段中。

这里有一个例子:

总结

正如我们在入口中提到的,这些建议提供了一个很好的起点,但是网络策略要复杂得多。如果你有兴趣更详细地研究它们,一定要查看Kubernetes教程以及一些方便的网络策略配方。

https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/

https://github.com/ahmetb/kubernetes-network-policy-recipes

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档