问题描述
上下文
我有一个启用了Workload Identity的Google Kubernetes Engine(GKE)集群。作为工作负载身份的一部分,k8s-metadata-proxy DaemonSet在群集上运行。我有一个命名空间my-namespace
,并且要拒绝该命名空间中Pod的所有出口流量,除了向k8s-Metadata-proxy DaemonSet的出口。因此,我具有以下NetworkPolicy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
Metadata:
name: test-network-policy
namespace: my-namespace
spec:
# Apply to all pods.
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
# This is needed to whitelist k8s-Metadata-proxy. See https://github.com/GoogleCloudplatform/k8s-Metadata-proxy
- protocol: TCP
port: 988
问题
NetworkPolicy太宽泛,因为它允许将TCP流量出口到端口988上的任何主机,而不仅仅是出口到k8s-Metadata-proxy DaemonSet,但我似乎找不到办法指定.spec.egress[0].to
以达到我想要的粒度。
我尝试了以下to
:
egress:
- to:
- namespaceSelector:
matchLabels:
namespace: kube-system
ports:
- protocol: TCP
port: 988
- to:
- ipBlock:
cidr: <cidr of pod IP range>
- ipBlock:
cidr: <cidr of services IP range>
ports:
- protocol: TCP
port: 988
但是这些规则导致到k8s-Metadata-proxy的流量被阻止。
问题
如何在to
的出口规则的networking.k8s.io/v1/NetworkPolicy
部分中选择k8s-Metadata-proxy DaemonSet?
解决方法
正如我在评论中所说:
你好您可以将“ podSelector.matchLabels”添加到“出口”定义中,以允许您的Pod仅连接到具有特定标签的Pod。您可以在这里了解更多信息:cloud.google.com/kubernetes-engine/docs/tutorials/…
此注释可能会误导您,因为官方文档中描述了与gke-metadata-server
的通信:
着眼于上述文档:
了解GKE元数据服务器
GKE元数据服务器是一个新的metadata server,设计用于Kubernetes。它作为daemonset运行,每个群集节点上都有一个Pod。元数据服务器拦截对http://metadata.google.internal(
169.254.169.254:80
)的HTTP请求,包括诸如GET /computeMetadata/v1/instance/service-accounts/default/token
之类的请求,以检索Pod配置为充当其服务的Google服务帐户的令牌。到元数据服务器的流量永远不会离开承载Pod的VM实例。注意:如果您使用严格的cluster network policy,则必须允许出口到端口988上的127.0.0.1/32,以便Pod可以与GKE元数据服务器通信。 / p>
上面引用的最后一段中描述了仅允许流量进入GKE Metadata server
的规则。 YAML
的定义应如下所示:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: egress-rule
namespace: restricted-namespace # <- namespace your pod is in
spec:
policyTypes:
- Egress
podSelector:
matchLabels:
app: nginx # <- label used by pods trying to communicate with metadata server
egress:
- to:
- ipBlock:
cidr: 127.0.0.1/32 # <- allow communication with metadata server #1
- ports:
- protocol: TCP
port: 988 # <- allow communication with metadata server #2
假设:
- 您有一个Kubernetes集群,其中包含:
-
Network Policy
已启用 -
Workload Identity
已启用
-
- 您的
Pods
试图通过restricted-namespace
名称空间进行通信
用于描述所需的NetworkPolicy
的输出:
-
$ kubectl describe networkpolicy -n restricted-namespace egress-rule
Name: egress-rule
Namespace: restricted-namespace
Created on: 2020-10-04 18:31:10 +0200 CEST
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"networking.k8s.io/v1","kind":"NetworkPolicy","metadata":{"annotations":{},"name":"egress-rule","namespace":"restricted-name...
Spec:
PodSelector: app=nginx
Allowing ingress traffic:
<none> (Selected pods are isolated for ingress connectivity)
Allowing egress traffic:
To Port: <any> (traffic allowed to all ports)
To:
IPBlock:
CIDR: 127.0.0.1/32
Except:
----------
To Port: 988/TCP
To: <any> (traffic not restricted by source)
Policy Types: Egress
免责声明!
应用这些规则将拒绝带有
app=nginx
标签且未发往元数据服务器的Pod的所有流量!
您可以通过以下方式创建exec
并app=nginx
到带有标签kubectl run -it --rm nginx \
--image=nginx \
--labels="app=nginx" \
--namespace=restricted-namespace \
-- /bin/bash
的吊舱中:
nginx
提示!
使用图像
curl
是因为它默认安装了env
!
在此示例中,您将无法与DNS服务器通信。您可以:
- 允许您的Pod与DNS服务器通信
- 设置元数据服务器的
GKE Metadata Server
变量(169.254.169.254)
与$ curl 169.254.169.254/computeMetadata/v1/instance/ -H 'Metadata-Flavor: Google'
通信的示例:
-
attributes/ hostname id service-accounts/ zone
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: egress-rule
namespace: restricted-namespace # <- namespace of "source" pod
spec:
policyTypes:
- Egress
podSelector:
matchLabels:
app: ubuntu # <- label for "source" pod
egress:
- to:
- podSelector:
matchLabels:
app: nginx # <- label for "destination" pod
- ports:
- protocol: TCP
port: 80 # <- allow only port 80
其他资源:
要允许特定Pod仅将流量发送到特定端口上的特定Pod,可以使用以下策略:
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// Do something on UiThread
}
});