Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Заўв. перав.: Аўтар артыкула - Reuven Harrison - мае больш за 20 гадоў вопыту ў распрацоўцы праграмнага забеспячэння, а на сённяшні дзень з'яўляецца тэхнічным дырэктарам і сузаснавальнікам кампаніі Tufin, якая стварае рашэнні для кіравання палітыкамі бяспекі. Разглядаючы сеткавыя палітыкі Kubernetes як дастаткова магутны сродак для сегментацыі сеткі ў кластары, ён у той жа час лічыць, што яны не так простыя ва ўжыванні на практыцы. Дадзены матэрыял (даволі аб'ёмны) закліканы палепшыць дасведчанасць спецыялістаў у гэтым пытанні і дапамагчы ім у стварэнні неабходных канфігурацый.

Сёння шматлікія кампаніі ўсё гушчару выбіраюць Kubernetes для запуску сваіх прыкладанняў. Цікавасць да гэтага ПЗ настолькі высокая, што некаторыя называюць Kubernetes "новай аперацыйнай сістэмай для цэнтраў апрацоўкі дадзеных". Паступова Kubernetes (ці k8s) пачынае ўспрымацца як крытычна важная частка бізнэсу, якая патрабуе арганізацыі спелых бізнэс-працэсаў, у тым ліку забеспячэнні сеткавай бяспекі.

Для спецыялістаў па бяспецы, якіх збянтэжылі працай з Kubernetes, сапраўдным адкрыццём можа стаць палітыка гэтай платформы па змаўчанні: дазволіць усё.

Гэта кіраўніцтва дапаможа разабрацца ва ўнутранай прыладзе сеткавых палітык; зразумець, чым яны адрозніваюцца ад правіл для звычайных брандмаўэраў. Таксама будзе расказана аб некаторых падводных камянях і будуць дадзены рэкамендацыі, якія дапамогуць абараніць прыкладанні ў Kubernetes.

Сеткавыя палітыкі Kubernetes

Механізм сеткавых палітык Kubernetes дазваляе кіраваць узаемадзеяннем разгорнутых на платформе прыкладанняў на сеткавым узроўні (трэцім у мадэлі OSI). Сеткавыя палітыкі пазбаўленыя некаторых перадавых функцый сучасных брандмаўэраў, такіх як кантроль на 7 узроўні OSI і выяўленне пагроз, аднак яны забяспечваюць базавы ўзровень сеткавай бяспекі, які выступае нядрэннай адпраўной кропкай.

Сеткавыя палітыкі кантралююць камунікацыі паміж pod'амі

Рабочыя нагрузкі ў Kubernetes размяркоўваюцца па pod'ах, якія складаюцца з аднаго або некалькіх кантэйнераў, разгорнутых сумесна. Kubernetes прысвойвае кожнаму pod'у IP-адрас, даступны з іншых pod'аў. Сеткавыя палітыкі Kubernetes задаюць правы доступу для груп pod'ов такім жа чынам, як групы бяспекі ў воблаку выкарыстоўваюцца для кіравання доступам да асобнікаў віртуальных машын.

Вызначэнне сеткавых палітык

Як і астатнія рэсурсы Kubernetes, сеткавыя палітыкі задаюцца на мове YAML. У прыведзеным ніжэй прыкладзе з дадаткам balance адкрываецца доступ да postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

(Заўв. перав.: гэты скрыншот, як і ўсе наступныя аналагічныя, створаны не роднымі сродкамі Kubernetes, а з дапамогай інструмента Tufin Orca, за распрацоўкай якога стаіць кампанія аўтара арыгінальнага артыкула і які згадваецца ў канцы матэрыялу.)

Для вызначэння ўласнай сеткавай палітыкі запатрабуюцца базавыя веды YAML. Гэтая мова заснавана на водступах (якія задаюць прабеламі, а не табуляцыяй). Элемент з водступам прыналежыць найблізкаму элементу з водступам над ім. Новы элемент спісу пачынаецца з злучка, усе астатнія элементы маюць выгляд ключ-значэнне.

Апісаўшы палітыку на YAML, выкарыстоўвайце кубектль, Каб стварыць яе ў кластары:

kubectl create -f policy.yaml

Спецыфікацыя сеткавай палітыкі

Спецыфікацыя сеткавай палітыкі Kubernetes уключае ў сябе чатыры элемента:

  1. podSelector: вызначае pod'ы, якія закранаюцца гэтай палітыкай (мэты) - абавязковы;
  2. policyTypes: паказвае, якія тыпы палітык уключаны ў дадзеную: ingress і/ці egress - неабавязковы, аднак я рэкамендую яго відавочна прапісваць ва ўсіх выпадках;
  3. ingress: вызначае дазволены які ўваходзіць трафік у мэтавыя pod'ы - неабавязковы;
  4. egress: вызначае дазволены выходны трафік з мэтавых pod'аў - неабавязковы.

Прыклад, запазычаны з сайта Kubernetes (я замяніў role на app), паказвае, як выкарыстоўваюцца ўсе чатыры элементы:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: db
  policyTypes:    # <<<
  - Ingress
  - Egress
  ingress:        # <<<
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:         # <<<
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы
Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Звярніце ўвагу, што ўсе чатыры элементы ўключаць неабавязкова. Абавязковым з'яўляецца толькі podSelector, астатнія параметры можна выкарыстоўваць па жаданні.

Калі апусціць policyTypes, палітыка будзе інтэрпрэтавацца наступным чынам:

  • Па змаўчанні мяркуецца, што яна вызначае ingress-бок. Калі відавочных указанняў на гэты конт у палітыцы не ўтрымліваецца, сістэма будзе лічыць, што ўвесь трафік забаронены.
  • Паводзіны на egress-боку будуць вызначацца наяўнасцю або адсутнасцю адпаведнага egress-параметра.

Каб пазбегнуць памылак, я рэкамендую заўсёды відавочна паказваць policyTypes.

У адпаведнасці з прыведзенай вышэй логікай у выпадку, калі параметры ingress і / або egress апушчаныя, палітыка будзе забараняць увесь трафік (гл. "Правіла зачысткі" ніжэй).

Палітыка па змаўчанні - дазволіць

Калі палітыкі не вызначаны, Kubernetes па змаўчанні дазваляе ўвесь трафік. Усе pod'ы свабодна могуць абменьвацца інфармацыяй паміж сабой. З пункту гледжання бяспекі гэта можа здацца нелагічным, але ўспомніце аб тым, што Kubernetes першапачаткова ствараўся распрацоўшчыкамі з мэтай забяспечыць узаемадзеянне прыкладанняў. Сеткавыя палітыкі былі дададзены пазней.

Прасторы імёнаў

Прасторы імёнаў (Namespaces) - механізм калектыўнай працы Kubernetes. Яны прызначаны для ізалявання лагічных асяроддзяў сябар ад сябра, пры гэтым абмен дадзенымі паміж прасторамі па змаўчанні дазволены.

Як і большасць кампанентаў Kubernetes, сеткавыя палітыкі насяляюць у вызначанай прасторы імёнаў. У блоку metadata можна прапісаць, якой менавіта прасторы належыць палітыка:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

Калі прастора імёнаў у метададзеных відавочна не прапісана, сістэма будзе выкарыстоўваць namespace, паказанае ў kubectl (па змаўчанні namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

Я рэкамендую відавочна паказваць namespace, калі толькі вы не пішаце палітыку, прызначаную адразу для некалькіх прастор імёнаў.

Асноўны элемент podSelector у палітыцы будзе выбіраць pod'ы з прасторы імёнаў, да якога прыналежыць палітыка (ён пазбаўлены доступу да pod'аў з іншай прасторы імёнаў).

Аналагічнай выявай podSelector'ы у блоках ingress і egress могуць выбіраць pod'ы толькі са сваёй прасторы імёнаў, калі, вядома, вы не аб'яднаеце іх з дапамогай namespaceSelector (пра гэта пойдзе гаворка ў раздзеле "Фільтр па прасторах імёнаў і pod'ам").

Правілы наймення палітык

Назвы палітык унікальныя ў рамках адной прасторы імёнаў. Двух палітык з аднолькавай назвай у адной прасторы быць не можа, але могуць быць палітыкі з аднолькавымі назвамі ў розных прасторах. Гэта зручна, калі вы хочаце паўторна прымяніць адну і тую ж палітыку на некалькіх прасторах.

Мне асабліва падабаецца адзін са спосабаў наймення. Ён складаецца ў тым, каб аб'ядноўваць назву прасторы імёнаў з мэтавымі pod'амі. Напрыклад:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Лэйблы

Да аб'ектаў Kubernetes, такім як pod'ы і прасторы імёнаў, можна прымацоўваць карыстацкія лэйблы. Лэйблы (этыкеткі - пазнакі) з'яўляюцца эквівалентам тэгаў у воблаку. Сеткавыя палітыкі Kubernetes выкарыстоўваюць лэйблы для выбару pod'аў, да якіх яны прымяняюцца:

podSelector:
  matchLabels:
    role: db

… Або прастор імёнаў, да якіх яны прымяняюцца. У гэтым прыкладзе выбіраюцца ўсе pod'ы ў прасторах імёнаў з адпаведнымі лэйбламі:

namespaceSelector:
  matchLabels:
    project: myproject

Адна перасцярога: пры выкарыстанні namespaceSelector пераканайцеся, што абіраныя прасторы імёнаў утрымоўваюць у сабе патрэбны лэйбл.. Майце на ўвазе, што убудаваныя прасторы імёнаў, такія як default и kube-system, па змаўчанні не ўтрымліваюць у сабе лэйблаў.

Дадаць лэйбл да прасторы можна наступным чынам:

kubectl label namespace default namespace=default

Пры гэтым namespace у раздзеле metadata павінен спасылацца на фактычнае імя прасторы, а не на лэйбл:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

Крыніца і адрасат

Палітыкі для брандмаўэраў складаюцца з правілаў з крыніцамі і адрасатамі. Сеткавыя палітыкі Kubernetes вызначаюцца для мэты - набору з pod'ов, да якіх яны ўжываюцца, а затым усталёўваюць правілы для ўваходнага (ingress) і/ці выходнага (egress) трафіку. У нашым прыкладзе мэтай палітыкі будуць усе pod'ы ў прасторы імёнаў. default з лэйблам з ключом app і значэннем db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: db   # <<<
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы
Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Падраздзел ingress у гэтай палітыцы адкрывае ўваходны трафік да мэтавым pod'ам. Іншымі словамі, ingress выступае крыніцай, а мэта - адпаведным адрасатам. Аналагічным чынам egress з'яўляецца адрасатам, а мэта - яго крыніцай.

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Гэта эквівалентна двум правілам для брандмаўэра: Ingress → Мэта; Мэта → Egress.

Egress і DNS (важна!)

Абмяжоўваючы выходны трафік, асаблівую ўвагу звернеце на DNS - Kubernetes выкарыстоўвае гэтую службу для супастаўлення сэрвісаў з IP-адрасамі. Напрыклад, наступная палітыка не спрацуе, паколькі вы не дазволілі з дадаткам balance звяртацца да DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Выправіць яе можна, адкрыўшы доступ да сэрвісу DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Апошні элемент to - пусты, і таму ён ускосна выбірае усе pod'ы ва ўсіх прасторах імёнаў, дазваляючы balance пасылаць DNS-запыты ў адпаведную службу Kubernetes (звычайна яна працуе ў прасторы kube-system).

Гэты падыход працуе, аднак ён празмерна дазваляльны і небяспечны, паколькі дазваляе накіроўваць DNS-запыты за межы кластара.

Палепшыць яго можна трыма паслядоўнымі крокамі.

1. Дазволіць DNS-запыты толькі ўнутры кластара, дадаўшы namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

2. Дазволіць DNS-запыты толькі ў прасторы імёнаў kube-system.

Для гэтага трэба дадаць лэйбл у прастору імёнаў kube-system: kubectl label namespace kube-system namespace=kube-system - і прапісаць яе ў палітыцы з дапамогай namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

3. Параноікі могуць пайсці яшчэ далей і абмежаваць DNS-запыты вызначанай DNS-службай у kube-system. У раздзеле «Фільтр па прасторах імёнаў І pod'ам» будзе расказана, як гэтага дабіцца.

Іншы варыянт - дазволіць DNS на ўзроўні прасторы імёнаў. У гэтым выпадку яго не трэба будзе адчыняць для кожнай службы:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

пусты podSelector выбірае ўсе pod'ы ў прасторы імёнаў.

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Першая адпаведнасць і парадак правіл

У звычайных брандмаўэрах дзеянне ("Дазволіць" ці "Забараніць") у стаўленні пакета вызначаецца першым правілам, якому ён задавальняе. У Kubernetes парадак палітык ня мае ніякага значэньня.

Па змаўчанні, калі палітыкі не зададзены, камунікацыі паміж pod'амі дазволеныя і яны могуць свабодна абменьвацца інфармацыяй. Як толькі вы пачынаеце фармуляваць палітыкі, кожны pod, закрануты хаця б адной з іх, становіцца ізаляваным у адпаведнасці з дыз'юнкцыяй (лагічным АБО) усіх палітык, якія яго абралі. Pod'ы, не закранутыя якой-небудзь палітыкай, застаюцца адчыненымі.

Змяніць падобныя паводзіны можна з дапамогай правіла зачысткі.

Правіла зачысткі («Забараніць»)

Палітыкі брандмаўэраў звычайна забараняюць любой яўнай выявай не дазволены трафік.

У Kubernetes няма дзеяння "забараніць" (deny), аднак аналагічнага эфекту можна дамагчыся з звычайнай (дазваляльнай) палітыкай, абраўшы пустую групу pod'аў-крыніц (ingress):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Гэтая палітыка выбірае ўсе pod'ы ў прасторы імёнаў і пакідае ingress нявызначаным, забараняючы ўвесь уваходны трафік.

Падобнай выявай можна абмежаваць увесь выходны трафік з прасторы імёнаў:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Улічыце, што любыя дадатковыя палітыкі, якія дазваляюць трафік да pod'аў у прасторы імёнаў, будуць мець прыярытэт над гэтым правілам. (аналагічна даданню дазвольнага правіла перад забараняльным у канфігурацыі брандмаўэра).

Дазволіць усе (Any-Any-Any-Allow)

Каб стварыць палітыку «Дазволіць усё», неабходна дапоўніць прыведзеную вышэй забаронную палітыку пустым элементам ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Яна адкрывае доступ са усіх pod'аў ва ўсіх прасторах імёнаў (і ўсіх IP) да любога pod'у ў прасторы імёнаў default. Падобныя паводзіны ўключаны па змаўчанні, таму звычайна яго не трэба вызначаць дадаткова. Аднак часам можа спатрэбіцца часова адключыць некаторыя канкрэтныя дазволы для дыягностыкі праблемы.

Правіла можна звузіць і дазволіць доступ толькі да вызначанаму набору pod'аў (app:balance) у прасторы імёнаў default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Наступная палітыка дазваляе ўвесь уваходны (ingress) І выходны (egress) трафік, уключаючы доступ да любога IP за межамі кластара:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы
Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Аб'яднанне некалькіх палітык

Палітыкі аб'ядноўваюцца з дапамогай лагічнага АБО на трох узроўнях; дазволы кожнага pod'а ўсталёўваюцца ў адпаведнасці з дыз'юнкцыяй усіх палітык, якія яго закранаюць:

1. У палях from и to можна вызначыць тры тыпу элементаў (усе яны камбінуюцца з дапамогай АБО):

  • namespaceSelector - выбірае прастору імёнаў цалкам;
  • podSelector - Выбірае pod'ы;
  • ipBlock - выбірае падсетку.

Пры гэтым колькасць элементаў (нават аднолькавых) у падраздзелах from/to не абмежавана. Усе яны будуць аб'яднаны лагічным АБО.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

2. Унутры палітыкі раздзел ingress можа мець мноства элементаў from (Аб'ядноўваюцца лагічным АБО). Аналагічным чынам раздзел egress можа ўключаць мноства элементаў to (таксама аб'ядноўваюцца дыз'юнкцыяй):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

3. Розныя палітыкі таксама аб'ядноўваюцца лагічным АБО

Але пры іх аб'яднанні існуе адно абмежаванне, на якое паказаў Chris Cooney: Kubernetes можа камбінаваць палітыкі толькі з рознымі policyTypes (Ingress або Egress). Палітыкі, якія вызначаюць ingress (ці egress), перазапішуць адна адну.

Сувязь паміж прасторамі імёнаў

Па змаўчанні абмен інфармацыяй паміж прасторамі імёнаў дазволены. Змяніць гэта можна з дапамогай забароннай палітыкі, якая абмяжуе выходны і/ці ўваходны трафік у прастору імёнаў (гл. «Правіла зачысткі» вышэй).

Заблакаваўшы доступ у прастору імёнаў (гл. «Правіла зачысткі» вышэй), вы можаце ўнесці выключэнні ў забаронную палітыку, дазволіўшы падлучэнні з вызначанай прасторы імёнаў з дапамогай namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

У выніку ўсе pod'ы ў прасторы імёнаў default атрымаюць доступ да pod'ам postgres у прасторы імёнаў database. Але што, калі вы хочаце адкрыць доступ да postgres толькі канкрэтным pod'ам у прасторы імёнаў default?

Фільтр па прасторах імёнаў І pod'ам

Kubernetes версіі 1.11 і вышэй дазваляе камбінаваць аператары namespaceSelector и podSelector з дапамогай лагічнага І. Выглядае гэта наступным чынам:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Чаму гэта трактуецца як І замест звыклага АБО?

Звярніце ўвагу, што podSelector не пачынаецца з злучка. У YAML гэта азначае, што podSelector і які стаіць перад ім namespaceSelector адносяцца да аднаго і таго ж элементу спісу. Таму яны аб'ядноўваюцца лагічным І.І.

Даданне злучка перад podSelector прывядзе да ўзнікнення новага элемента спісу, які будзе камбінавацца з папярэднім namespaceSelector з дапамогай лагічнага АБО.

Каб абраць pod'ы з вызначаным лэйблам ва ўсіх прасторах імёнаў, упішыце пусты namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Множныя лэйблы аб'ядноўваюцца з І

Правілы для брандмаўэра са мноствам аб'ектаў (хастамі, сеткамі, групамі) камбінуюцца з дапамогай лагічнага АБО. Наступнае правіла спрацуе, калі крыніца пакета супадае з Host_1 АБО Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

Наадварот, у Kubernetes розныя лэйблы ў podSelector або namespaceSelector аб'ядноўваюцца лагічным І. Напрыклад, наступнае правіла абярэ pod'ы, якія валодаюць абедзвюма лэйбламі, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

Тая ж логіка ўжываецца да ўсіх тыпаў аператараў: селектарам мэт палітыкі, селектарам pod'аў і селектарам прастор імёнаў.

Падсеткі і IP-адрасы (IPBlocks)

Для сегментавання сеткі брандмаўэры выкарыстоўваюць VLAN, IP-адрасы і падсеткі.

У Kubernetes IP-адрасы прысвойваюцца pod'ам аўтаматычна і могуць часта змяняцца, таму для выбару pod'аў і прастор імёнаў у сеткавых палітыках выкарыстоўваюцца лэйблы.

Падсеткі (ipBlocks) выкарыстоўваюцца пры кіраванні ўваходнымі (ingress) або выходнымі (egress) вонкавымі (North-South) падлучэннямі. Да прыкладу, гэтая палітыка адчыняе ўсім pod'ам з прасторы імёнаў. default доступ да DNS-сэрвісу Google:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Пусты селектар pod'ов у гэтым прыкладзе азначае выбраць усе pod'ы ў прасторы імёнаў .

Дадзеная палітыка адчыняе доступ толькі да 8.8.8.8; доступ да любога іншаму IP забаронены. Такім чынам, па сутнасці, вы заблакавалі доступ да ўнутранай службы DNS Kubernetes. Калі вы ўсё ж хочаце яго адкрыць, укажыце гэта відавочна.

Звычайна ipBlocks и podSelectors з'яўляюцца ўзаемавыключальнымі, паколькі ўнутраныя IP-адрасы pod'ов не выкарыстоўваюцца ў ipBlocks. Указаўшы унутраныя IP pod'аў, вы фактычна дазволіце падлучэнні да/ад pod'аў з гэтымі адрасамі. На практыцы вы не будзеце ведаць, які IP-адрас выкарыстоўваць, менавіта таму іх не варта ўжываць для выбару pod'ов.

У якасці контр-прыкладу наступная палітыка ўключае ўсе IP і, такім чынам, дазваляе доступ да ўсіх іншых pod'ам:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Можна адкрыць доступ толькі да вонкавых IP, выключыўшы ўнутраныя IP-адрасы pod'ов. Напрыклад, калі падсетку вашага pod'а 10.16.0.0/14:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Парты і пратаколы

Звычайна pod'ы слухаюць адзін порт. Гэта азначае, што можна проста не ўказваць нумары партоў у палітыках і пакінуць усё па змаўчанні. Зрэшты, палітыкі рэкамендуецца рабіць максімальна абмежавальнымі, таму ў некаторых выпадках усё ж можна ўказваць парты:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Заўважце, што селектар ports прымяняецца да ўсіх элементаў у блоку to або from, у якім змяшчаецца. Каб паказаць розныя парты для розных набораў элементаў, разбіце ingress або egress на некалькі падраздзелаў з to або from і ў кожным прапішыце свае парты:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

Увядзенне ў сеткавыя палітыкі Kubernetes для спецыялістаў па бяспецы

Праца партоў па змаўчанні:

  • Калі вы цалкам апускаеце вызначэнне партоў (ports), гэта азначае ўсе пратаколы і ўсе парты;
  • Калі вы апускаеце вызначэнне пратакола (protocol), гэта азначае TCP;
  • Калі вы апускаеце вызначэнне порта (port), гэта азначае ўсе парты.

Лепшая практыка: не належце на значэнні па змаўчанні, паказвайце патрэбнае вам відавочна.

Звярніце ўвагу, што неабходна выкарыстоўваць парты pod'аў, а не сэрвісаў (падрабязней пра гэта ў наступным параграфе).

Палітыкі вызначаны для pod'аў ці сэрвісаў?

Звычайна pod'ы ў Kubernetes звяртаюцца сябар да сябра праз сэрвіс — віртуальны балансавальнік нагрузкі, які перанакіроўвае трафік да pod'аў, якія рэалізуюць сэрвіс. Можна падумаць, што сеткавыя палітыкі кантралююць доступ да сервісаў, але гэта не так. Сеткавыя палітыкі Kubernetes працуюць з партамі pod'аў, а не сэрвісаў.

Напрыклад, калі сэрвіс слухае 80-й порт, але перанакіроўвае трафік на порт 8080 сваіх pod'ов, у сеткавай палітыцы неабходна ўказаць менавіта 8080.

Падобны механізм варта прызнаць неаптымальным: пры змене ўнутранай прылады сэрвісу (парты якога слухаюць pod'ы) прыйдзецца абнаўляць сеткавыя палітыкі.

Новы архітэктурны падыход з выкарыстаннем Service Mesh (напрыклад, гл. пра Istio ніжэй - заўв. перакл.) дазваляе зладзіцца з гэтай праблемай.

Ці неабходна прапісваць як Ingress, так і Egress?

Кароткі адказ - так, каб pod А мог звязацца з pod'ам В, неабходна дазволіць яму ствараць выходнае злучэнне (для гэтага варта наладзіць egress-палітыку), а pod В павінен мець магчымасць прымаць уваходнае злучэнне (для гэтага, адпаведна, патрэбна ingress- палітыка).

Аднак на практыцы можна пакласціся на палітыку па змаўчанні, якая дазваляе злучэнні ў адным або абодвух напрамках.

Калі нейкі pod-крыніца будзе абраны адной ці некалькімі выход-палітыкамі, якія накладаюцца на яго абмежаванні будуць вызначацца іх дыз'юнкцыяй. У гэтым выпадку запатрабуецца відавочна дазволіць падлучэнне да pod'у-адрасату. Калі pod не абраны якой-небудзь палітыкай, яго выходны (egress) трафік дазволены па змаўчанні.

Аналагічнай выявай лёс pod'а-адрасата, Выбранага адной або некалькімі ўваходжанне-палітыкамі, будзе вызначацца іх дыз'юнкцыяй. У гэтым выпадку неабходна відавочна дазволіць яму атрымліваць трафік ад pod'а-крыніцы. Калі pod не абраны якой-небудзь палітыкай, увесь уваходны (ingress) трафік для яго дазволены па змаўчанні.

Глядзіце пункт «Stateful або Stateless» ніжэй.

Логі

Сеткавыя палітыкі Kubernetes не ўмеюць часопісаваць трафік. Гэта ўскладняе вызначэнне таго, ці працуе палітыка належным чынам, і моцна ўскладняе аналіз у галіне бяспекі.

Кантроль за трафікам да знешніх сэрвісаў

Сеткавыя палітыкі Kubernetes не дазваляюць паказваць паўнавартаснае даменнае імя (DNS) у раздзелах egress. Гэты факт прыводзіць да значнай нязручнасці пры спробе абмежаваць трафік да вонкавых адрасатаў, пазбаўленым фіксаванага IP-адрасы (такім як aws.com).

Праверка палітыкі

Брандмаўэры папярэдзяць вас ці нават адмовяцца прыняць памылковую палітыку. Kubernetes таксама праводзіць некаторую верыфікацыю. Пры заданні сеткавай палітыкі праз kubectl Kubernetes можа заявіць, што яна няправільная, і адмовіцца яе прыняць. У іншых выпадках Kubernetes прыме палітыку і дапоўніць яе адсутнымі дэталямі. Іх можна ўбачыць з дапамогай каманды:

kubernetes get networkpolicy <policy-name> -o yaml

Майце на ўвазе, што сістэма праверкі Kubernetes не бясхібная і можа прапускаць некаторыя тыпы памылак.

Выкананне

Kubernetes не займаецца рэалізацыяй сеткавых палітык самастойна, а з'яўляецца толькі API-шлюзам, якія ўскладаюць цяжкай працы па кантролі на ніжэйлеглую сістэму, званую Container Networking Interface (CNI). Заданне палітык у кластары Kubernetes без прызначэння адпаведнага CNI аналагічна стварэнню палітык на серверы кіравання брандмаўарам без іх наступнай усталёўкі ў брандмаўэры. Вы самі павінны пераканацца ў наяўнасці годнага CNI ці, у выпадку платформаў Kubernetes, размешчаных у воблаку (са спісам правайдэраў можна азнаёміцца тут - заўв. зав.), задзейнічаць сеткавыя палітыкі, якія ўсталююць CNI для вас.

Звярніце ўвагу, што Kubernetes не папярэдзіць вас, калі вы задасце сеткавую палітыку без адпаведнага дапаможнага CNI.

Stateful ці Stateless?

Усе CNI Kubernetes, з якімі мне даводзілася сутыкацца, захоўваюць станы (напрыклад, Calico выкарыстоўвае Linux conntrack). Гэта дазваляе pod'у атрымліваць адказы па ініцыяваным ім TCP-злучэнні без неабходнасці ўсталёўваць яго нанова. Пры гэтым мне невядома аб стандарце Kubernetes, які гарантаваў бы захоўванне стану (statefulness).

Прасунутае кіраванне палітыкай бяспекі

Вось некалькі спосабаў павысіць эфектыўнасць выканання палітыкі бяспекі ў Kubernetes:

  1. Архітэктурны патэрн Service Mesh выкарыстоўвае sidecar-кантэйнеры для забеспячэння падрабязнай тэлеметрыі і кантролю за трафікам на ўзроўні сэрвісаў. У якасці прыкладу можна ўзяць Ісціё.
  2. Некаторыя з пастаўшчыкоў CNI дапоўнілі свае прылады, каб тыя выйшлі за рамкі сеткавых палітык Kubernetes.
  3. Tufin Orca забяспечвае празрыстасць і аўтаматызацыю сеткавых палітык Kubernetes.

Пакет Tufin Orca кіруе сеткавымі палітыкамі Kubernetes (і служыць крыніцай скрыншотаў, прыведзеных вышэй).

Дадатковая інфармацыя

Заключэнне

Сеткавыя палітыкі Kubernetes прапануюць нядрэнны набор прылад для сегментацыі кластараў, аднак яны інтуітыўна незразумелыя і маюць мноства тонкасцяў. Я лічу, што з-за гэтай складанасці палітыкі многіх кластараў змяшчаюць памылкі. Магчымымі рашэннямі гэтай праблемы з'яўляюцца аўтаматызацыя азначэнняў палітык ці ўжыванне іншых сродкаў сегментацыі.

Спадзяюся, што гэтае кіраўніцтва дапаможа растлумачыць некаторыя пытанні і вырашыць праблемы, з якімі вы можаце сутыкнуцца.

PS ад перакладчыка

Чытайце таксама ў нашым блогу:

Крыніца: habr.com

Дадаць каментар