Объединение нескольких сетевых политик для детального контроля на основе флагов - PullRequest
0 голосов
/ 19 сентября 2019

Я хочу разработать сетевые политики в кластере Kubernetes, чтобы иметь детализированный общий контроль доступа между модулями.

Я подготовил настройку Kubernetes с 2 манифестами:

  1. Модуль nginx с 2 контейнерами, с 2 прослушивающими портами и возвращенными некоторыми общими данными, один - порт 80, другой - 81
  2. У меня есть 3 консольных модуля с 2 ярлыками включения / выключения: "allow80 "и" allow80 ".Таким образом, если присутствует «allow80», консольный модуль может получить доступ к dual-nginx через точку входа службы, порт 80. То же самое применяется для порта 81

У меня есть 3 консольных модуля:

  1. console-full - порты доступа 80 и 81, [allow80, allow81]
  2. console-part - порт 80 - включен, 81 - выкл, [allow80]
  3. console-no-доступ - как 80, так и 81 - ограничен []

Тестовая настройка.Он создаст все необходимые компоненты в пространстве имен «net-policy-test».

Для создания:

kubectl apply -f net_policy_test.yaml

Для очистки:

kubectl delete -f net_policy_test.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: net-policy-test
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx1
  namespace: net-policy-test
data:
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
    <title>nginx, instance1</title>
    </head>
    <body>
      <h1>nginx, instance 1, port 80</h1>
    </body>
    </html>
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx2
  namespace: net-policy-test
data:
  index.html: |
    <!DOCTYPE html>
    <html>
    <head>
    <title>nginx, instance2</title>
    </head>
    <body>
      <h1>nginx, instance 2, port 81</h1>
    </body>
    </html>
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf1
  namespace: net-policy-test
data:
  default.conf: |
    server {
        listen       80;
        server_name  localhost;


        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf2
  namespace: net-policy-test
data:
  default.conf: |
    server {
        listen       81;
        server_name  localhost;


        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dual-nginx
  namespace: net-policy-test
  labels:
    app: dual-nginx
    environment: test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dual-nginx
  template:
    metadata:
      labels:
        app: dual-nginx
        name: dual-nginx
    spec:
      containers:
      - image: nginx
        name: nginx1
        ports:
        - name: http1
          containerPort: 80
        volumeMounts:
          - name: html1
            mountPath: /usr/share/nginx/html
          - name: config1
            mountPath: /etc/nginx/conf.d
      - image: nginx
        name: nginx2
        ports:
        - name: http2
          containerPort: 81
        volumeMounts:
          - name: html2
            mountPath: /usr/share/nginx/html
          - name: config2
            mountPath: /etc/nginx/conf.d
      volumes:
        - name: html1
          configMap:
            name: nginx1
        - name: html2
          configMap:
            name: nginx2
        - name: config1
          configMap:
            name: nginx-conf1
        - name: config2
          configMap:
            name: nginx-conf2

---
apiVersion: v1
kind: Service
metadata:
  name: dual-nginx
  namespace: net-policy-test
spec:
  selector:
    app: dual-nginx
  ports:
  - name: web1
    port: 80
    targetPort: http1
  - name: web2
    port: 81
    targetPort: http2
---
# this console deployment will have full access to nginx
apiVersion: apps/v1
kind: Deployment
metadata:
  name: console-full
  namespace: net-policy-test
  labels:
    app: console-full
    environment: test
    nginx-access: full
spec:
  replicas: 1
  selector:
    matchLabels:
      app: console-full
  template:
    metadata:
      labels:
        app: console-full
        name: console-full
        allow80: "true"
        allow81: "true"
    spec:
      containers:
      - image: alpine:3.9
        name: main
        command: ["sh", "-c", "apk update && apk add curl && sleep 10000"]

---
# this console deployment will have partial access to nginx
apiVersion: apps/v1
kind: Deployment
metadata:
  name: console-partial
  namespace: net-policy-test
  labels:
    app: console-partial
    environment: test
    nginx-access: partial
spec:
  replicas: 1
  selector:
    matchLabels:
      app: console-partial
  template:
    metadata:
      labels:
        app: console-partial
        name: console-partial
        allow80: "true"

    spec:
      containers:
      - image: alpine:3.9
        name: main
        command: ["sh", "-c", "apk update && apk add curl && sleep 10000"]
---
# this console deployment will have no access to nginx
apiVersion: apps/v1
kind: Deployment
metadata:
  name: console-no-access
  namespace: net-policy-test
  labels:
    app: console-no-access
    environment: test
    nginx-access: none
spec:
  replicas: 1
  selector:
    matchLabels:
      app: console-no-access
  template:
    metadata:
      labels:
        app: console-no-access
        name: console-no-access
    spec:
      containers:
      - image: alpine:3.9
        name: main
        command: ["sh", "-c", "apk update && apk add curl && sleep 10000"]

И политики, опять же, применяются:

kubectl apply -f policies.yaml

Для очистки:

kubectl delete -f policies.yaml


kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: nginx-restrict80
spec:
  podSelector:
    matchLabels:
      app: "dual-nginx"
  policyTypes:
    - Ingress
  ingress:
  - from:
      - podSelector:
          matchLabels:
            allow80: "true"
    ports:
      - protocol: TCP
        port: 80
  - from:
      - podSelector:
          matchLabels:
            allow81: "true"
    ports:
      - protocol: TCP
        port: 81

Если я оставлю только одно условие с «from» для одного порта, оно будет работать как положено.У меня есть или нет доступ к порту, в зависимости от наличия соответствующей метки, allow80 или allow81

Если присутствуют 2 условия, частичный модуль имеет доступ к обоим портам 80 и 81:

  1. Переключиться в правое пространство имен:
kubectl config set-context --current --namespace=net-policy-test
Проверьте метки:
kubectl get pods -l allow80
NAME                               READY   STATUS    RESTARTS   AGE
console-full-78d5499959-p5kbb      1/1     Running   1          4h14m
console-partial-6679745d79-kbs5w   1/1     Running   1          4h14m

kubectl get pods -l allow81
NAME                            READY   STATUS    RESTARTS   AGE
console-full-78d5499959-p5kbb   1/1     Running   1          4h14m
Проверьте доступ из модуля «console-part -...», который должен иметь доступ к порту 80, а не 81:
kubectl exec -ti console-partial-6679745d79-kbs5w curl http://dual-nginx:80
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance1</title>
</head>
<body>
  <h1>nginx, instance 1, port 80</h1>
</body>
</html>

kubectl exec -ti console-partial-6679745d79-kbs5w curl http://dual-nginx:81
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance2</title>
</head>
<body>
  <h1>nginx, instance 2, port 81</h1>
</body>
</html>

Модуль с частичным доступом имеет доступ к портам 80 и 81.

Блок, не имеющий меток (console-no-access-), не имеющий доступа ни к одному из портов, что ожидается

Это похоже на то, что описано в этой презентации: YoutubeЗащита кластерной сети с помощью сетевых политик - Ахмет Балкан, Google .Таким образом, по крайней мере один флаг «allow80» или «allow81» дает доступ ко всему.Почему?

Теперь вопросы:

  1. Ожидаемое поведение?
  2. Как создать простой контроль доступа на основе флагов, чтобы автоматизировать его или передать администраторам?Кто может легко произвести их в большом количестве?

Ответы [ 2 ]

1 голос
/ 20 сентября 2019

TLDR : он работает на моем кластере именно так, как вы хотели, чтобы он работал.

Теперь немного пояснений и примеров.

Я создал кластерв GKE и включенных сетевых политиках с помощью следующей команды:

gcloud beta container clusters create test1 --enable-network-policy --zone us-cental1-a

Затем скопировал точный yaml развертывания и yaml сетевой политики без измененийи развернул их.

$ kubectl apply -f policy-test.yaml
namespace/net-policy-test created
configmap/nginx1 created
configmap/nginx2 created
configmap/nginx-conf1 created
configmap/nginx-conf2 created
deployment.apps/dual-nginx created
service/dual-nginx created
deployment.apps/console-full created
deployment.apps/console-partial created
deployment.apps/console-no-access created

$ kubectl apply -f policy.yaml
networkpolicy.networking.k8s.io/nginx-restrict80 configured

Сетевая политика, которую вы написали, работала именно так, как вы хотели.

console-part был способен получить доступ только к nginx через порт 80. console-no-access не имел доступа ни к одному nginx.

Я думаю, это потому, что GKE использует Calico, поскольку CNI

Google Container Engine (GKE) также обеспечивает бета-поддержку Сетевые политики с использованием сетевого подключаемого модуля Calico

Пока вы использовали --network-policy azure, то есть Azure-CNI .Я не могу проверить это на AKS, но вы можете попробовать изменить это на ситцевое.Это объясняется здесь: Создание кластера AKS и включение сетевой политики

  • Создает кластер AKS в определенной виртуальной сети и включает сетевую политику.
    • Используется опция сетевой политики azure .Чтобы использовать Calico в качестве параметра сетевой политики, используйте параметр --network-policy calico.

Что касается автоматизации флагов, возможно, это будет работать для вас.

Вы можете увидеть ярлыки здесь:

$ kubectl describe pods console-partial | grep -A3 Labels
Labels:             allow80=true
                    app=console-partial
                    name=console-partial
                    pod-template-hash=6c6dc7d94f

Когда я начал редактировать Labels, используя kubectl labels.

Удален ярлык allow80="true":

$ kubectl label pods console-partial-6c6dc7d94f-v8k5q allow80-
pod/console-partial-6c6dc7d94f-v8k5q labeled
$ kubectl describe pods console-partial | grep -A3 Labels
Labels:             app=console-partial
                    name=console-partial
                    pod-template-hash=6c6dc7d94f

и добавьте метку allow81= true

kubectl label pods console-partial-6c6dc7d94f-v8k5q "allow81=true"
pod/console-partial-6c6dc7d94f-v8k5q labeled

$ kubectl describe pods console-partial | grep -3 Labels
Labels:             allow81=true
                    app=console-partial
                    name=console-partial
                    pod-template-hash=6c6dc7d94f

Из теста видно, что политика работает так, как вы хотели.

$ kubectl exec -it console-partial-6c6dc7d94f-v8k5q curl http://dual-nginx:81
<!DOCTYPE html>
<html>
<head>
<title>nginx, instance2</title>
</head>
<body>
  <h1>nginx, instance 2, port 81</h1>
</body>
</html>
$ kubectl exec -it console-partial-6c6dc7d94f-v8k5q curl http://dual-nginx:80
^Ccommand terminated with exit code 130

Надеюсь, это поможет вам.

0 голосов
/ 24 сентября 2019

Я пытался воссоздать кластер в Azure с сетевыми политиками Calico и Azure CNI - он начал нормально работать для Linux -> Linux-коммуникации

network_plugin="azure" &&\
network_policy="calico"
az aks create ... \
--network-plugin ${network_plugin} \
--network-policy ${network_policy}

Теперь, когда контейнер Windows помещен на местона стороне клиента.Когда политики включены, ни один порт не доступен из оболочки Windows для тестирования контейнера Linux.Это начало другой истории, я полагаю

...