Google Kubernetes Engine: NetworkPolicy, разрешающий выход на k8s-metadata-proxy

Контекст

У меня есть кластер Google Kubernetes Engine (GKE) с идентификатором рабочей нагрузки включен. Как часть идентификатора рабочей нагрузки, в кластере работает DaemonSet k8s-metadata-proxy. У меня есть пространство имен my-namespace, и я хочу запретить весь исходящий трафик модулей в пространстве имен, кроме исходящего к DaemonSet k8s-metadata-proxy. Таким образом, у меня есть следующая 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 вместо того, чтобы просто выходить на DaemonSet k8s-metadata-proxy, но я не могу найти способ указать .spec.egress[0].to для достижения желаемой степени детализации.

Я пробовал следующие tos:

  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.

Вопрос

Как я могу выбрать DaemonSet k8s-metadata-proxy в to части правила выхода в networking.k8s.io/v1/NetworkPolicy?


person Jasper Brekelmans    schedule 01.10.2020    source источник
comment
Привет. Вы можете добавить в свое Egress определение podSelector.matchLabels, чтобы позволить вашему модулю подключаться только к Pods с определенным label. Подробнее об этом можно прочитать здесь: cloud.google.com/ kubernetes-engine / docs / tutorials /   -  person Dawid Kruk    schedule 02.10.2020


Ответы (1)


Как я сказал в комментарии:

Привет. Вы можете добавить в определение Egress podSelector.matchLabels, чтобы позволить вашему модулю подключаться только к модулям с определенной меткой. Подробнее об этом можно прочитать здесь: cloud.google.com/ kubernetes-engine / docs / tutorials /…

Этот комментарий может ввести в заблуждение, поскольку общение с gke-metadata-server описано в официальной документации:

Сосредоточившись на части приведенной выше документации:

Понимание сервера метаданных GKE

Сервер метаданных GKE - это новый сервер метаданных, предназначенный для использования с Kubernetes. . Он работает как демон с одним модулем на каждом узле кластера. Сервер метаданных перехватывает HTTP-запросы к http://metadata.google.internal (169.254.169.254:80), включая такие запросы, как GET /computeMetadata/v1/instance/service-accounts/default/token для получения токена для учетной записи службы Google, в качестве которой настроен модуль. Трафик на сервер метаданных никогда не покидает экземпляр виртуальной машины, на котором размещен Pod.

Примечание. Если у вас строгий политика сети кластера, вы должны разрешить выход на 127.0.0.1/32 на порт 988, чтобы ваш Pod мог взаимодействовать с сервером метаданных GKE.

Правило, разрешающее трафик только на 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 

При условии, что:

  • You have a Kubernetes cluster with:
    • Network Policy enabled
    • 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, не предназначенный для сервера метаданных!

Вы можете создать и exec в модуль с меткой app=nginx:

kubectl run -it --rm nginx \
--image=nginx \
--labels="app=nginx" \
--namespace=restricted-namespace \
-- /bin/bash

Совет!

Используется образ nginx, поскольку он curl установлен по умолчанию!

В этом примере вы не сможете связаться с DNS-сервером. Вы также можете:

  • разрешить вашим модулям связываться с DNS-сервером
  • установить переменную env для сервера метаданных (169.254.169.254)

Пример общения с GKE Metadata Server:

  • $ 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
person Dawid Kruk    schedule 05.10.2020
comment
Спасибо, белый список 127.0.0.1:988 в соответствии с документацией, которую вы связали, работает - person Jasper Brekelmans; 08.10.2020