使用网络策略将 kube-apiserver 列入白名单

Whitelist kube-apiserver with Network Policy

使用网络策略定义仅允许出口到 kube-apiserver 的规则的最佳方法是什么?

虽然 kube-apiserver 有一个 Service 资源,但没有 Pods,据我所知这不能用标签来完成。使用 IP 白名单,这不能保证跨集群工作。这里有什么推荐的做法吗?

我想到了两个选项。

1) 创建 NetworkPolicy 默认拒绝所有 egress 流量 Kubernetes-apiservice IP 范围异常。

由于某些重启,服务 IP 可能会更改,以便更好地使用 IP 范围。 在这种情况下,您需要将 kubernetes service IPEndpoint IP.

列入白名单

This docs 提供拒绝所有 egress 流量的示例。您将需要修改此示例以将此地址添加为例外。 它看起来像这样。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  #optional namespace
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress
  - to:
    - ipBlock:
      cidr: <kube-apiserver-IP-range>
    - port: <svc-port>
      protocol: <svc-protocol>

我建议您查看 this 文章。

2) 使用静态 IP 创建 service,它将流量转发到 kubernetes-apiserver

将 运行 kubectl proxy 到 apiserver 的服务。

如何判断kube-apiserver

默认情况下,在每个集群中您将能够看到一项服务。例如在 kubeadm 中是 kubernetes

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   15d

如果你会描述它,你会得到endpoint

$ kubectl describe svc kubernetes
Name:              kubernetes
Namespace:         default
Labels:            component=apiserver
                   provider=kubernetes
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.96.0.1
Port:              https  443/TCP
TargetPort:        6443/TCP
Endpoints:         10.166.0.30:6443
Session Affinity:  None
Events:            <none>

如果您从 kube-system 命名空间检查 pods,他们中的大多数都有 IP,这是 kubernetes 服务端点。

$ kubectl get pods -n kube-system -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP            NODE           NOMINATED NODE   READINESS GATES
coredns-5644d7b6d9-7sm4d               1/1     Running   3          15d   10.32.0.3     ubus-kubeadm   <none>           <none>
coredns-5644d7b6d9-g42g6               1/1     Running   3          15d   10.32.0.2     ubus-kubeadm   <none>           <none>
etcd-ubus-kubeadm                      1/1     Running   3          15d   10.166.0.30   ubus-kubeadm   <none>           <none>
kube-apiserver-ubus-kubeadm            1/1     Running   3          15d   10.166.0.30   ubus-kubeadm   <none>           <none>
kube-controller-manager-ubus-kubeadm   1/1     Running   3          15d   10.166.0.30   ubus-kubeadm   <none>           <none>
kube-proxy-57r9m                       1/1     Running   3          15d   10.166.0.30   ubus-kubeadm   <none>           <none>
kube-scheduler-ubus-kubeadm            1/1     Running   3          15d   10.166.0.30   ubus-kubeadm   <none>           <none>
weave-net-l6b5x                        2/2     Running   9          15d   10.166.0.30   ubus-kubeadm   <none>           <none>

您必须使用 apiserver 的 IP 地址。您不能使用标签。
查找 apiserver 的 IP 地址 运行:
kubectl cluster-info

在输出中寻找这样一行:
Kubernetes master is running at https://<ip>
这是你的apiserver IP的IP地址。

网络策略应该是这样的(假设 apiserver IP 是 34.76.197.27):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-apiserver
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 34.76.197.27/32
    ports:
    - protocol: TCP
      port: 443

The policy above applies to all pods in the namespaces it is applied to.
对于 select 具体 pods,使用需要 apiserver 访问的 pods 的标签编辑 podSelector 部分:

  podSelector:
    matchLabels:
      app: apiserver-allowed

请记住,默认的出口策略是 ALLOW ALL,这意味着其他 pods 仍然可以访问 apiserver。
You can change this behavior by adding a "BLOCK ALL" egress policy per namespace 但切记不要阻止对 DNS 服务器和其他基本服务的访问。
For more info see "Egress and DNS (Pitfall!)" in this post.

请注意,在某些情况下,可能有多个 apiserver(为了可扩展性),在这种情况下,您需要添加所有 IP 地址。