Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Նշում. թարգմ.Հոդվածի հեղինակ Ռեուվեն Հարիսոնն ունի ծրագրային ապահովման մշակման ավելի քան 20 տարվա փորձ, և այսօր հանդիսանում է CTO և Tufin ընկերության համահիմնադիրը, որը ստեղծում է անվտանգության քաղաքականության կառավարման լուծումներ: Թեև նա դիտարկում է Kubernetes-ի ցանցային քաղաքականությունը որպես կլաստերի ցանցի սեգմենտավորման բավականին հզոր գործիք, նա նաև կարծում է, որ դրանք գործնականում այնքան էլ հեշտ չեն իրականացնել: Այս նյութը (բավականին ծավալուն) նպատակ ունի բարելավելու մասնագետների տեղեկացվածությունը այս խնդրի վերաբերյալ և օգնելու նրանց ստեղծել անհրաժեշտ կոնֆիգուրացիաներ:

Այսօր շատ ընկերություններ ավելի ու ավելի են ընտրում Kubernetes-ը՝ իրենց հավելվածները գործարկելու համար: Այս ծրագրաշարի նկատմամբ հետաքրքրությունն այնքան մեծ է, որ ոմանք Kubernetes-ին անվանում են «տվյալների կենտրոնի նոր օպերացիոն համակարգ»: Աստիճանաբար Kubernetes-ը (կամ k8-ը) սկսում է ընկալվել որպես բիզնեսի կարևոր մաս, որը պահանջում է հասուն բիզնես գործընթացների կազմակերպում, ներառյալ ցանցային անվտանգությունը։

Անվտանգության մասնագետների համար, ովքեր տարակուսած են Kubernetes-ի հետ աշխատելով, իրական բացահայտումը կարող է լինել հարթակի լռելյայն քաղաքականությունը՝ թույլ տալ ամեն ինչ:

Այս ուղեցույցը կօգնի ձեզ հասկանալ ցանցային քաղաքականության ներքին կառուցվածքը. հասկանալ, թե ինչպես են դրանք տարբերվում սովորական firewalls-ի կանոններից: Այն նաև կներառի որոշ թակարդներ և կտրամադրի առաջարկություններ՝ օգնելու պաշտպանել հավելվածները Kubernetes-ում:

Kubernetes ցանցային քաղաքականություն

Kubernetes ցանցային քաղաքականության մեխանիզմը թույլ է տալիս կառավարել ցանցի շերտում հարթակում տեղակայված հավելվածների փոխազդեցությունը (երրորդը՝ OSI մոդելում): Ցանցային քաղաքականությանը բացակայում են ժամանակակից firewalls-ի որոշ առաջադեմ առանձնահատկություններ, ինչպիսիք են OSI Layer 7-ի կիրառումը և սպառնալիքների հայտնաբերումը, սակայն դրանք ապահովում են ցանցի անվտանգության հիմնական մակարդակ, որը լավ մեկնարկային կետ է:

Ցանցային քաղաքականությունը վերահսկում է կապի կապը պատիճների միջև

Kubernetes-ում աշխատանքային ծանրաբեռնվածությունը բաշխված է բլոկների վրա, որոնք բաղկացած են մեկ կամ մի քանի բեռնարկղերից՝ տեղակայված միասին: Kubernetes-ը յուրաքանչյուր pod-ին վերագրում է IP հասցե, որը հասանելի է այլ պատյաններից: Kubernetes ցանցի քաղաքականությունը սահմանում է մուտքի իրավունքներ խմբերի համար, այնպես, ինչպես ամպի անվտանգության խմբերն օգտագործվում են վիրտուալ մեքենաների օրինակների հասանելիությունը վերահսկելու համար:

Ցանցային քաղաքականության սահմանում

Ինչպես 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: սահմանում է այս քաղաքականության ազդեցության տակ գտնվող պատյանները (թիրախները) - պարտադիր;
  2. policyTypesցույց է տալիս, թե ինչ տեսակի քաղաքականություններ են ներառված սա. մուտք և/կամ ելք՝ կամընտիր, բայց ես խորհուրդ եմ տալիս հստակորեն նշել այն բոլոր դեպքերում.
  3. ingress: սահմանում է թույլատրված մուտքային երթևեկություն դեպի թիրախային պատյաններ - կամընտիր;
  4. egress: սահմանում է թույլատրված արտագնա Թիրախային պատյաններից երթևեկությունը պարտադիր չէ:

Օրինակ՝ վերցված 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, քաղաքականությունը կմեկնաբանվի հետևյալ կերպ.

  • Լռելյայնորեն ենթադրվում է, որ այն սահմանում է մուտքի կողմը: Եթե ​​քաղաքականությունը բացահայտորեն չի նշում դա, համակարգը կենթադրի, որ ամբողջ երթևեկությունն արգելված է:
  • Ելքի կողմի վարքագիծը որոշվելու է համապատասխան ելքի պարամետրի առկայությամբ կամ բացակայությամբ:

Սխալներից խուսափելու համար խորհուրդ եմ տալիս միշտ դա բացահայտ արա policyTypes.

Ըստ վերը նշված տրամաբանության, եթե պարամետրերը ingress եւ / կամ egress բաց թողնված, քաղաքականությունը կհրաժարվի ամբողջ երթևեկությունից (տե՛ս ստորև «Հեռացման կանոնը»):

Կանխադրված քաղաքականությունը Թույլատրել է

Եթե ​​որևէ քաղաքականություն սահմանված չէ, Kubernetes-ը լռելյայն թույլ է տալիս ամբողջ տրաֆիկը: Բոլոր պատյանները կարող են ազատորեն տեղեկատվություն փոխանակել միմյանց միջև: Սա կարող է հակասական թվալ անվտանգության տեսանկյունից, բայց հիշեք, որ Kubernetes-ը ի սկզբանե նախագծվել է մշակողների կողմից՝ հավելվածների փոխգործունակությունը միացնելու համար: Ցանցի քաղաքականությունը ավելացվել է ավելի ուշ:

Անվան տարածքներ

Անվանատարածքները Kubernetes-ի համագործակցության մեխանիզմն են: Դրանք նախագծված են տրամաբանական միջավայրերը միմյանցից մեկուսացնելու համար, մինչդեռ տարածությունների միջև հաղորդակցությունը լռելյայն թույլատրված է:

Ինչպես Kubernetes-ի բաղադրիչներից շատերը, ցանցային քաղաքականությունը ապրում է որոշակի անվանատարածքում: Բլոկում metadata Դուք կարող եք նշել, թե որ տարածքին է պատկանում քաղաքականությունը.

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

Եթե ​​մետատվյալներում անունների տարածքը հստակորեն նշված չէ, համակարգը կօգտագործի kubectl-ում նշված անվանատարածքը (լռելյայն namespace=default):

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

Խորհուրդ եմ տալիս հստակորեն նշեք անունների տարածքը, եթե դուք քաղաքականություն չեք գրում, որը թիրախավորում է միանգամից մի քանի անվանատարածք:

Հիմնական տարր podSelector քաղաքականության մեջ կընտրի պատյաններ այն անվանատարածքից, որին պատկանում է քաղաքականությունը (արգելված է մուտք գործել այլ անվանատարածքների պատյաններ):

Նմանապես, podSelectors մուտքի և ելքի բլոկներում կարող են ընտրել միայն պատիճներ իրենց սեփական անվանատարածքից, եթե իհարկե դրանք չհամատեղեք namespaceSelector (սա կքննարկվի «Զտել ըստ անվանատարածքների և պատիճների» բաժնում):

Քաղաքականության անվանման կանոններ

Քաղաքականության անունները եզակի են նույն անվանատարածքում: Նույն տարածության մեջ չի կարող լինել նույն անունով երկու քաղաքականություն, բայց տարբեր բացատներում կարող են լինել նույն անունով քաղաքականություններ: Սա օգտակար է, երբ ցանկանում եք կրկին կիրառել նույն քաղաքականությունը մի քանի տարածություններում:

Ինձ հատկապես դուր է գալիս անվանման մեթոդներից մեկը. Այն բաղկացած է անվանատարածքի անվանումը թիրախային պատյանների հետ համատեղելուց: Օրինակ:

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-ի օբյեկտներին, ինչպիսիք են պատյանները և անունների տարածքները: Պիտակներ (պիտակները - պիտակներ) ամպի պիտակների համարժեքն են: Kubernetes ցանցի քաղաքականությունը ընտրելու համար օգտագործում է պիտակներ պատիճներորոնց նկատմամբ նրանք դիմում են.

podSelector:
  matchLabels:
    role: db

… կամ անունների տարածքներորին նրանք դիմում են։ Այս օրինակը ընտրում է բոլոր պատյանները անունների տարածքներում՝ համապատասխան պիտակներով.

namespaceSelector:
  matchLabels:
    project: myproject

Մի զգուշություն. օգտագործելիս namespaceSelector համոզվեք, որ ձեր ընտրած անունների տարածքները պարունակում են ճիշտ պիտակ. Իմացեք, որ ներկառուցված անունների տարածքները, ինչպիսիք են default и kube-system, լռելյայնորեն չեն պարունակում պիտակներ:

Դուք կարող եք պիտակ ավելացնել հետևյալ տարածության մեջ.

kubectl label namespace default namespace=default

Միևնույն ժամանակ, անվանատարածք բաժնում metadata պետք է վերաբերի իրական տարածության անվանը, ոչ թե պիտակին.

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

Աղբյուրը և նպատակակետը

Firewall-ի քաղաքականությունը բաղկացած է աղբյուրներից և ուղղություններով կանոններից: Kubernetes ցանցի քաղաքականությունը սահմանվում է թիրախի համար՝ մի շարք պատյանների, որոնց վրա նրանք կիրառվում են, և այնուհետև սահմանվում են կանոններ մուտքի և/կամ արտագնա տրաֆիկի համար: Մեր օրինակում քաղաքականության թիրախը լինելու է անվանատարածքի բոլոր պատյանները 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 այս քաղաքականության մեջ բացում է մուտքային երթևեկությունը դեպի թիրախային պատյաններ: Այլ կերպ ասած, մուտքը աղբյուրն է, իսկ թիրախը՝ համապատասխան նպատակակետը։ Նմանապես, ելքը նպատակակետն է, իսկ թիրախը՝ դրա աղբյուրը:

Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Սա համարժեք է երկու firewall կանոնների. Ingress → Target; Նպատակ → Ելք.

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 դատարկ է, և հետևաբար այն անուղղակիորեն ընտրում է բոլոր պատյանները բոլոր անվանատարածքներում, թույլ տալով 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. «Զտել ըստ անվանատարածքների և պատիճների» բաժինը ձեզ կպատմի, թե ինչպես հասնել դրան:

Մեկ այլ տարբերակ 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 ընտրում է բոլոր պատյանները անունների տարածքում:

Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Առաջին համընկնումը և կանոնների կարգը

Պայմանական firewalls-ում գործողությունը (Թույլատրել կամ մերժել) փաթեթի վրա որոշվում է այն առաջին կանոնով, որը այն բավարարում է: Kubernetes-ում քաղաքականության կարգը նշանակություն չունի:

Լռելյայնորեն, երբ որևէ քաղաքականություն սահմանված չէ, պոդերների միջև հաղորդակցությունը թույլատրվում է, և նրանք կարող են ազատորեն տեղեկատվություն փոխանակել: Հենց որ սկսեք ձևակերպել քաղաքականություն, յուրաքանչյուր պատիճ, որի վրա ազդում է դրանցից առնվազն մեկը, դառնում է մեկուսացված՝ ըստ այն ընտրած բոլոր քաղաքականության բաժանման (տրամաբանական ԿԱՄ): Որևէ քաղաքականությունից չազդված պատյանները մնում են բաց:

Դուք կարող եք փոխել այս վարքագիծը՝ օգտագործելով մերկացման կանոնը:

Մերկացման կանոն («Մերժում»)

Firewall-ի քաղաքականությունը սովորաբար մերժում է ցանկացած երթևեկություն, որը բացահայտորեն թույլատրված չէ:

Kubernetes-ում ժխտողական գործողություն չկա, սակայն, նմանատիպ էֆեկտի կարելի է հասնել կանոնավոր (թույլտվական) քաղաքականության դեպքում՝ ընտրելով աղբյուրի բլոկների դատարկ խումբ (մուտք).

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

Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Այս քաղաքականությունը ընտրում է բոլոր բլոկները անունների տարածքում և թողնում է ներթափանցումը անորոշ՝ մերժելով բոլոր մուտքային տրաֆիկը:

Նմանապես, դուք կարող եք սահմանափակել բոլոր ելքային երթևեկությունը անունների տարածքից.

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

Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Խնդրում ենք նկատի ունենալ, որ Ցանկացած լրացուցիչ քաղաքականություն, որը թույլ է տալիս երթևեկությունը դեպի բլոկներ անունների տարածքում, գերակայություն կունենա այս կանոնից (նման է firewall-ի կազմաձևման մեջ թույլատրելի կանոն ավելացնելուց առաջ մերժման կանոնը):

Թույլ տալ ամեն ինչ (Any-Any-Any-Allow)

Թույլատրել բոլորին քաղաքականություն ստեղծելու համար դուք պետք է լրացնեք վերը նշված մերժման քաղաքականությունը դատարկ տարրով ingress:

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

Անվտանգության մասնագետների համար Kubernetes ցանցային քաղաքականության ներածություն

Այն թույլ է տալիս մուտք գործել բոլոր պատիճները բոլոր անվանատարածքներում (և բոլոր IP-ն) դեպի անունների տարածքի ցանկացած պատիճ default. Այս վարքագիծը լռելյայն միացված է, ուստի այն սովորաբար հետագա սահմանման կարիք չունի: Այնուամենայնիվ, երբեմն ձեզ հարկավոր է ժամանակավորապես անջատել որոշ հատուկ թույլտվություններ՝ խնդիրը ախտորոշելու համար:

Կանոնը կարող է կրճատվել՝ թույլ տալով միայն մուտք գործել պատիճների հատուկ հավաքածու (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 ցանցային քաղաքականության ներածություն

Հետևյալ քաղաքականությունը թույլ է տալիս բոլոր մուտքային և ելքային տրաֆիկները, ներառյալ կլաստերից դուրս ցանկացած 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 Կարելի է սահմանել երեք տեսակի տարրեր (որոնք բոլորը համակցված են OR-ի միջոցով).

  • namespaceSelector — ընտրում է ամբողջ անվանատարածքը.
  • podSelector - ընտրում է պատյաններ;
  • 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 (զուգակցված տրամաբանական OR-ով): Նմանապես, բաժին 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. Տարբեր քաղաքականությունները զուգակցվում են նաև տրամաբանական ԿԱՄ-ի հետ

Բայց դրանք համատեղելիս կա մեկ սահմանափակում, որի վրա նշվեց Քրիս ՔունիKubernetes-ը կարող է միայն համատեղել քաղաքականությունը տարբերի հետ policyTypes (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 ցանցային քաղաքականության ներածություն

Արդյունքում, բոլոր պատիճները անունների տարածքում default մուտք կունենան պատյաններ postgres անունների տարածքում database. Բայց ինչ, եթե ցանկանում եք բացել մուտքը postgres միայն կոնկրետ պատյաններ անունների տարածքում default?

Զտել ըստ անվանատարածքների և պատիճների

Kubernetes 1.11 և ավելի բարձր տարբերակը թույլ է տալիս համատեղել օպերատորները namespaceSelector и podSelector օգտագործելով տրամաբանական AND-ը: Այն կարծես հետևյալն է.

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 վերաբերեք նույն ցանկի տարրին: Հետեւաբար, դրանք զուգակցվում են տրամաբանական AND-ի հետ:

Նախկինում գծիկ ավելացնելը podSelector կհանգեցնի ցուցակի նոր տարրի առաջացմանը, որը կմիավորվի նախորդի հետ namespaceSelector օգտագործելով տրամաբանական OR.

Հատուկ պիտակով պատյաններ ընտրելու համար բոլոր անվանատարածքներում, մուտքագրեք դատարկ 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 ցանցային քաղաքականության ներածություն

Բազմաթիվ պիտակներ միավորվում են I-ի հետ

Բազմաթիվ օբյեկտներով (հոսթներ, ցանցեր, խմբեր) firewall-ի կանոնները համակցվում են տրամաբանական OR-ի միջոցով: Հետևյալ կանոնը կաշխատի, եթե փաթեթի աղբյուրը համընկնի Host_1 OR Host_2:

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

Ընդհակառակը, Kubernetes-ում տարբեր պիտակներ են podSelector կամ namespaceSelector զուգակցվում են տրամաբանական AND-ի հետ: Օրինակ, հետևյալ կանոնը կընտրի պատյաններ, որոնք ունեն երկու պիտակներ, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

Նույն տրամաբանությունը կիրառվում է բոլոր տեսակի օպերատորների համար՝ քաղաքականության թիրախ ընտրողներ, pod ընտրիչներ և անվանատարածքների ընտրիչներ:

Ենթացանցեր և IP հասցեներ (IPBlocks)

Firewall-ներն օգտագործում են VLAN-ներ, IP հասցեներ և ենթացանցեր՝ ցանցը սեգմենտավորելու համար:

Kubernetes-ում IP հասցեներն ավտոմատ կերպով նշանակվում են պատյաններին և կարող են հաճախակի փոփոխվել, ուստի պիտակները օգտագործվում են ցանցային քաղաքականության մեջ պատյաններ և անունների տարածքներ ընտրելու համար:

Ենթացանցեր (ipBlocks) օգտագործվում են մուտքային (մուտք) կամ ելքային (ելք) արտաքին (Հյուսիս-Հարավ) կապերը կառավարելիս։ Օրինակ՝ այս քաղաքականությունը բացվում է անվանատարածքի բոլոր պատյանների համար default մուտք դեպի Google DNS ծառայություն.

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 ցանցային քաղաքականության ներածություն

Այս օրինակում դատարկ պատիճ ընտրիչը նշանակում է «ընտրել բոլոր բլոկները անունների տարածքում»:

Այս քաղաքականությունը թույլ է տալիս մուտք գործել միայն 8.8.8.8; ցանկացած այլ IP մուտքն արգելված է: Այսպիսով, ըստ էության, դուք արգելափակել եք մուտքը ներքին Kubernetes DNS ծառայության: Եթե ​​դեռ ցանկանում եք բացել այն, հստակ նշեք սա:

Սովորաբար ipBlocks и podSelectors փոխադարձ բացառիկ են, քանի որ pods-ի ներքին IP հասցեները չեն օգտագործվում ipBlocks. Նշելով ներքին IP պատյաններ, դուք իրականում թույլ կտաք կապեր այս հասցեներով պատյաններից/պոդներից: Գործնականում դուք չեք իմանա, թե որ IP հասցեն օգտագործել, այդ իսկ պատճառով դրանք չպետք է օգտագործվեն pods ընտրելու համար:

Որպես հակաօրինակ, հետևյալ քաղաքականությունը ներառում է բոլոր IP-ները և, հետևաբար, թույլ է տալիս մուտք գործել բոլոր այլ պոդեր.

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-ներին՝ բացառելով pods-ի ներքին IP հասցեները: Օրինակ, եթե ձեր 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 ցանցային քաղաքականության ներածություն

Նավահանգիստներ և արձանագրություններ

Սովորաբար պատիճները լսում են մեկ նավահանգիստ: Սա նշանակում է, որ դուք պարզապես կարող եք չնշել նավահանգիստների համարները քաղաքականության մեջ և թողնել ամեն ինչ որպես լռելյայն: Այնուամենայնիվ, խորհուրդ է տրվում քաղաքականությունը հնարավորինս սահմանափակել, այնպես որ որոշ դեպքերում դուք դեռ կարող եք նշել նավահանգիստները.

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 նավահանգիստները, այլ ոչ թե սպասարկման նավահանգիստները (այս մասին ավելին հաջորդ պարբերությունում):

Արդյո՞ք կանոնները սահմանված են փոդերի կամ ծառայությունների համար:

Սովորաբար, Kubernetes-ի բլոկները միմյանց մուտք են գործում ծառայության միջոցով՝ վիրտուալ բեռի հավասարակշռող, որը վերահղում է երթևեկությունը դեպի այն պատյանները, որոնք իրականացնում են ծառայությունը: Կարող եք մտածել, որ ցանցային քաղաքականությունը վերահսկում է ծառայությունների հասանելիությունը, բայց դա այդպես չէ: Kubernetes ցանցի քաղաքականությունը աշխատում է ոչ թե սպասարկման նավահանգիստների, այլ pod նավահանգիստների վրա:

Օրինակ, եթե ծառայությունը լսում է 80-րդ նավահանգիստը, բայց վերահղում է երթևեկությունը դեպի 8080 պորտ, դուք պետք է ցանցային քաղաքականության մեջ նշեք հենց 8080-ը:

Նման մեխանիզմը պետք է համարվի ոչ օպտիմալ. եթե ծառայության ներքին կառուցվածքը (որի պորտերը լսում են) փոխվի, ցանցի քաղաքականությունը պետք է թարմացվի:

Նոր ճարտարապետական ​​մոտեցում՝ օգտագործելով Service Mesh (օրինակ, տե՛ս Իստիոյի մասին ստորև - մոտավորապես թարգմ.) թույլ է տալիս հաղթահարել այս խնդիրը:

Արդյո՞ք անհրաժեշտ է գրանցել և՛ Ingress, և՛ Egress:

Կարճ պատասխանն է՝ այո, որպեսզի A pod B-ի հետ շփվի, պետք է թույլատրվի ստեղծել ելքային կապ (դրա համար անհրաժեշտ է կարգավորել արտագաղթի քաղաքականությունը), իսկ pod B-ն պետք է կարողանա ընդունել մուտքային կապ ( դրա համար, համապատասխանաբար, անհրաժեշտ է մուտքի քաղաքականություն):

Այնուամենայնիվ, գործնականում դուք կարող եք ապավինել լռելյայն քաղաքականությանը՝ թույլ տալու միացումներ մեկ կամ երկու ուղղություններով:

Եթե ​​որոշ պատիճ-աղբյուր կընտրվի մեկ կամ մի քանիսի կողմից ելք-Քաղաքական գործիչներ, դրա նկատմամբ կիրառվող սահմանափակումները որոշվելու են նրանց տարանջատմամբ։ Այս դեպքում ձեզ հարկավոր է հստակորեն թույլատրել կապը պատի հետ.հասցեատիրոջը. Եթե ​​pod-ն ընտրված չէ որևէ քաղաքականության կողմից, ապա դրա ելքային (ելքային) տրաֆիկը լռելյայն թույլատրվում է:

Նմանապես, պատիճի ճակատագիրն էհասցեատեր, ընտրված մեկի կամ մի քանիսի կողմից մուտք-Քաղաքական գործիչները կորոշվեն իրենց տարանջատմամբ: Այս դեպքում, դուք պետք է բացահայտորեն թույլ տաք, որ այն ստանա տրաֆիկ աղբյուրի փոդից: Եթե ​​պատիճը ընտրված չէ որևէ քաղաքականության կողմից, ապա դրա համար նախատեսված ամբողջ մուտքային տրաֆիկը թույլատրվում է լռելյայն:

Ստորև տե՛ս Պետական ​​կամ քաղաքացիություն չունեցող անձինք:

Տեղեկամատյանները

Kubernetes ցանցի քաղաքականությունը չի կարող գրանցել տրաֆիկը: Սա դժվարացնում է որոշել, թե արդյոք քաղաքականությունն աշխատում է այնպես, ինչպես նախատեսված է, և մեծապես բարդացնում է անվտանգության վերլուծությունը:

Արտաքին ծառայությունների երթևեկության վերահսկում

Kubernetes-ի ցանցային քաղաքականությունը թույլ չի տալիս արտագնա բաժիններում նշել լիովին որակավորված տիրույթի անուն (DNS): Այս փաստը հանգեցնում է զգալի անհարմարությունների, երբ փորձում են սահմանափակել տրաֆիկը դեպի արտաքին ուղղություններ, որոնք չունեն ֆիքսված IP հասցե (օրինակ՝ aws.com):

Քաղաքականության ստուգում

Firewall-ները կզգուշացնեն ձեզ կամ նույնիսկ կհրաժարվեն ընդունել սխալ քաղաքականությունը: Kubernetes-ը նաև որոշակի ստուգում է կատարում: Kubectl-ի միջոցով ցանցային քաղաքականություն սահմանելիս Kubernetes-ը կարող է հայտարարել, որ այն սխալ է և հրաժարվել ընդունել այն: Մնացած դեպքերում Kubernetes-ը կվերցնի քաղաքականությունը և կլրացնի այն բացակայող մանրամասներով: Դրանք կարելի է տեսնել՝ օգտագործելով հրամանը.

kubernetes get networkpolicy <policy-name> -o yaml

Հիշեք, որ Kubernetes վավերացման համակարգը անսխալական չէ և կարող է բաց թողնել որոշ տեսակի սխալներ:

Исполнение

Kubernetes-ը ինքնին չի իրականացնում ցանցային քաղաքականություն, այլ ընդամենը API դարպաս է, որը վերահսկողության բեռը փոխանցում է հիմքում ընկած համակարգին, որը կոչվում է Container Networking Interface (CNI): Kubernetes կլաստերի վրա քաղաքականություն սահմանելը առանց համապատասխան CNI նշանակելու նույնն է, ինչ ստեղծելու քաղաքականություն firewall-ի կառավարման սերվերի վրա՝ առանց այնուհետև դրանք firewalls-ում տեղադրելու: Ձեզնից է կախված՝ ապահովելու, որ դուք կունենաք պատշաճ CNI կամ, Kubernetes-ի պլատֆորմների դեպքում, ամպի մեջ տեղակայված: (կարող եք տեսնել մատակարարների ցանկը այստեղ - մոտ. տրանս.), միացրեք ցանցային քաղաքականությունները, որոնք ձեզ համար կսահմանեն CNI:

Նկատի ունեցեք, որ Kubernetes-ը ձեզ չի զգուշացնի, եթե դուք ցանցային քաղաքականություն սահմանեք առանց համապատասխան օգնականի CNI-ի:

Պետական, թե քաղաքացիություն չունեցող.

Բոլոր Kubernetes CNI-ները, որոնց ես հանդիպել եմ, պետական ​​են (օրինակ, Calico-ն օգտագործում է Linux conntrack): Սա թույլ է տալիս pod-ին պատասխաններ ստանալ իր նախաձեռնած TCP կապի վրա՝ առանց այն վերահաստատելու: Այնուամենայնիվ, ես տեղյակ չեմ Kubernetes ստանդարտի մասին, որը երաշխավորում է պետականությունը:

Անվտանգության քաղաքականության առաջադեմ կառավարում

Ահա մի քանի ուղիներ՝ բարելավելու անվտանգության քաղաքականության կիրարկումը Kubernetes-ում.

  1. Service Mesh ճարտարապետական ​​օրինաչափությունը օգտագործում է կողային բեռնարկղեր՝ ծառայության մակարդակում մանրամասն հեռաչափություն և երթեւեկության վերահսկում ապահովելու համար: Որպես օրինակ կարող ենք վերցնել Իստիո.
  2. CNI վաճառողներից ոմանք ընդլայնել են իրենց գործիքները՝ դուրս գալ Kubernetes ցանցի քաղաքականությունից:
  3. Թուֆին Օրկա Ապահովում է Kubernetes ցանցային քաղաքականության տեսանելիություն և ավտոմատացում:

Tufin Orca փաթեթը կառավարում է Kubernetes ցանցի քաղաքականությունը (և վերը նշված սքրինշոթերի աղբյուրն է):

Լրացուցիչ տեղեկություններ

Ամփոփում

Kubernetes ցանցային քաղաքականությունը առաջարկում է գործիքների լավ փաթեթ՝ կլաստերների հատվածավորման համար, սակայն դրանք ինտուիտիվ չեն և ունեն բազմաթիվ նրբություններ: Այս բարդության պատճառով, ես կարծում եմ, որ շատ գոյություն ունեցող կլաստերային քաղաքականություններ սխալ են: Այս խնդրի հնարավոր լուծումները ներառում են քաղաքականության սահմանումների ավտոմատացում կամ սեգմենտավորման այլ գործիքների օգտագործում:

Հուսով եմ, որ այս ուղեցույցը կօգնի պարզել որոշ հարցեր և լուծել այն խնդիրները, որոնց կարող եք հանդիպել:

PS թարգմանչից

Կարդացեք նաև մեր բլոգում.

Source: www.habr.com

Добавить комментарий