Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

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

Կարճ ներկայացում Kubernetes-ի ցանցային սարքի վերաբերյալ

Kubernetes կլաստերն անհնար է պատկերացնել առանց ցանցի: Մենք արդեն հրապարակել ենք դրանց հիմունքների մասին նյութեր: «Illustrated Guide to Networking in Kubernetes» և «Kubernetes-ի ցանցային քաղաքականություններին նվիրված ուղեցույց անվտանգություն մասնագետների համար».

Այս հոդվածի համատեքստում կարևոր է նշել, որ ցանցային կապը կոնտեյներների և հանգույցների միջև ապահովում է ոչ թե K8s-ը, այլ տարբեր CNI լրացումներ (Container Networking Interface). Մենք այդ կոնցեպտի մասին նույնպես պատմել ենք: Ինչպիսի օրինակ, ամենատարածված այդպիսի լրացումը՝.

Flannel — ապահովում է լիակատար ցանցային փոխազդեցություն բոլոր կլաստերային հանգույցների միջև, բարձրացնելով կամուրջներ յուրաքանչյուր հանգույցում, ապահովելով ենթանց միացումը: Սակայն լիակատարում և չկառավարվող հասանելիությունը միշտ օգտակար չէ: Կլաստերում նվազագույն մեկուսացման ապահովման համար անհրաժեշտ է միջամտել firewall-ի համակենտրոնացմանը: Ընդհանուր առմամբ, սա հանձնվում է այդ նույն CNI-ին, որի արդյունքում iptables-ում ցանկացած արտաքին միջամտություն կարող է որոշվել սխալ կամ ընդհանրապես անտեսվել: Եվ «ճիշտ արկղից» ցանցային քաղաքականությունների կառավարման կազմակերպման համար Kubernetes կլաստերում տրամադրվում է

NetworkPolicy API . Այս ռեսուրսը տարածվում է ընտրված անվան տարածքներին և կարող է պարունակել կանոններ, որոնք սահմանափակում են մուտքը մի հավելվածից մյուսը: Այն նաև թույլ է տալիս կարգավորել հասանելիությունը կոնկրետ pod-երրի, միջավայրերի (անվան տարածքներ) կամ IP-հասցեային բլոկների միջև:apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: test-network-policy namespace: default spec: podSelector: matchLabels: role: 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

Այս ոչ բոլոր ամպի օրինակները կարող են միանգամից բաժանել ցանկությունը հասկանալ ցանցային քաղաքականությունների աշխատանքը։ Սակայն մենք դեռ կփորձենք հասկացնել հիմնական սկզբունքներն ու ռեժիմի բեռնափոխադրումների ապահովումը ցանցային քաղաքականությունների միջոցով…

Տրամաբանական է, որ կան 2 տիպի հաղորդակցություններ. վերնախավին եկող (Ingress) և վերադարձրող (Egress): պաշտոնական փաստաթղթերի Ինձնից, այս երկու կատեգորայի հիման վրա էլ բաժանվում է քաղաքականություն։

Ֆիզիկապես պարտադիր հատկանիշներն են՝ ընտրողը; նա, ում կիրառվում է կանոնը։ Սա կարող է լինել pod (կամ pod-երի խումբ) կամ միջավայր (այսինքն՝ անվան տարածք): Տարածական մանրամասներ՝ երկուսն էլ պարտադիր պետք է պարունակեն պիտակ (

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

label

Հաջորդ պարտադիր ատրիբուտը ընտրիչն է, այն, ինչին կիրառվում է կանոնը։ Սա կարող է լինել pod (կամ pod-երի խումբ) կամ միջավայր (սա նշանակում է անունների տարածք)։ Կարևոր Detail՝ այս երկու տեսակի օբյեկտները պարտադիր պետք է ունենան պիտակ (label Kubernetes-ի terminologiyada) — հենց դրանք են, որոնցով կառավարում են քաղաքականություններ։

Վերջնական ընտրության թվի սելեկտորներից, որոնք միավորվում են որոշ բացականչությամբ, կա նաև գործիքի հնարավորությունը՝ «Թույլատրել/արգելել ամեն ինչ/բոլորին» տարբերակներով։ Dafür verwendet Methoden wie:

  podSelector: {}
  ingress: []
  policyTypes:
  - Ingress

— այս օրինակով բոլոր pod-երին հասանելիությունը փակվում է։ Ընդհանուր գործում հակառակ վարքագիծ ստանալու համար կարելի է օգտագործել հետևյալ կառուցվածքը:

  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

Նման կերպ ելքայինի համար:

  podSelector: {}
  policyTypes:
  - Egress

— նրա փակման համար։ Իսկ ահա ինչ-որ բան ընդգրկելու համար:

  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

Վերադառնալով CNI-plugin-ի ընտրության հարցին, հարկ է նշել, որ չի կարելի ասել, որ յուրաքանչյուր ցանցային plugin աջակցում է NetworkPolicy-ի հետ աշխատելուն։ Օրինակ, արդեն նշված Flannel-ը չի կարող config անել ցանցային քաղաքականություններ, ինչի մասին տոկոսավորապես ասված է официальном хранилище։ Там же упоминается альтернатива — Open Source-проект Calico, который значительно расширяет стандартный набор API Kubernetes в плане сетевых политик.

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

Calico-ով ծանոթանում ենք՝ տեսություն

Calico plugin-ը կարող է օգտագործվել Flannel-ի հետ ինտեգրված (մասնաճյուղի Canal) կամ ինքնուրույն, ընդգրկելով ինչպես ցանցային կապի ապահովման, այնպես էլ հասանելիության կառավարման ֆունկցիաներ։

Որպեսզի Calico-ի API-ների «տուփային» որոշումների օգտագործումը ինչ հնարավորություններ է տալիս K8s-ի վրա:

Ահա թե ինչն է ինտեգրված NetworkPolicy-ում:

  • քաղաքականությունները սահմանափակված են միջավայրի շրջապատներով;
  • քաղաքականությունները կիրառվում են լեյբոլերով նշված pod-ների նկատմամբ;
  • կարգերը կարելի է կիրառել pod-ներին, միջավայրերին կամ ենթանցքերին;
  • կարգերը կարող են պարունակել պրոտոկոլներ, անվանված կամ խորհրդանշանային պորտերի ցույցեր։

Նկատեք, թե ինչպես է Calico-ն ընդլայնում այս ֆունկցիաները:

  • քաղաքականությունները կարող են կիրառվել ցանկացած օբյեկտի համար՝ pod, կոնտեյներ, վիրտուալ մեքենա կամ ինտերֆեյս;
  • կարգերը կարող են պարունակել կոնկրետ գործողություն (արգելք, թույլտվություն, պատճառով պատասխանատու)։
  • Կամ որպես կարգ կամ աղբյուրը կարող է լինել պորտը, պորտերի տիրույթը, պրոտոկոլները, HTTP կամ ICMP հատկությունները, IP կամ ենթանցք (4 կամ 6-րդ սերունդ), ցանկացած սելեկտորներ (հուշարձանների, հոստերի, միջավայրերի);
  • Լրացուցիչ հնարավոր է կարգավորել միջանցքով երթևեկությունը DNAT կարգավորումների և երթևեկության քաղաքականությունների միջոցով։

Calico-ի GitHub-ում առաջին կոմիտները թվագրվում են 2016-ի հուլիսին, իսկ արդեն մեկ տարի անց նախագիծը զբաղեցրեց առաջնորդող դիրքեր Kubernetes-ի ցանցային կապի կազմակերպման մեջ՝ ինչպես վկայում են, օրինակ, The New Stack-ի հարցումները, проведенные The New Stack:

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

Կարող են լինել մեծ managed լուծումներ K8s-ի, ինչպիսիք են Amazon EKS, Azure AKS, Google GKE և այլերը, սկսեցին խորհուրդ տալ դրա օգտագործումը։

Անկախ շահագործման որակից, այստեղ ամեն ինչ հրաշալի է: Calico ծրագրի թիմը իր արտադրանքը փորձարկելու ընթացքում ցույց է տվել աստղային ցուցանիշներ՝ շահագործելով 50000-ից ավելի կոնտեյներներ 500 ֆիզիկական հանգույցներում, 20 կոնտեյներ մեկ վայրկյանում ստեղծելու արագությամբ: Մեծացման ժամանակ խնդիրներ չեն հայտնաբերվել: Այդպիսի արդյունքներ գնահատվել են լայնորեն առաջին տարբերակի հանրահռչակում: Ընդհանուր մտածված անկախ հետազոտությունները, որոնք ուղղված են պարունակության տարածումներին և ռեսուրսների սպառմանը, նույնպես հաստատում են Calico-ի արդյունավետությունը, որը գրեթե չի զիջում Flannel-ին: Օրինակ:

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

Ծրագիրը շատ արագ զարգանում է, աջակցում է հայտնի լուծումների – managed K8s, OpenShift, OpenStack, ունի Calico-ն արագացնելիս իրացման հնարավորություն kops, հանդիպում են Service Mesh ցանցերի կառուցման նշումներ (սա օրինակ է Istio-ի հետ համատեղ օգտագործելու):

Calico-ի փորձը

Ընդհանուր առմամբ, վանիլ Kubernetes-ի օգտագործման դեպքում CNI-ի տեղադրմանը վերաբերում է calico.yaml ֆայլի կիրառումը, որն անհրաժեշտ է ներբեռնել պաշտոնական կայքից, , օգտագործելովkubectl apply -f Բոլոր դեպքերում, ընթացիկ պլագինի նոր տարբերակը սովորաբար համատեղելի է Kubernetes-ի վերջին 2-3 տարբերություններով. ավելի հին տարբերություններում աշխատանքի ամրագրումն ու երաշխավորումը չի իրականացվում: Աշխատակազմի հայտարարությունների համաձայն, Calico-ն աշխատում է Linux միջուկով, որը ավելի բարձր է 3.10 CentOS 7, Ubuntu 16 կամ Debian 8-ի ներքո, iptables կամ IPVS մակերևույթին:.

Կրիտիկայում

Ունենալով ընդհանուր պատկերացում, եկեք դիտարկենք պարզ դեպք, որպեսզի հասկանալ, թե ինչով են Calico-ի ցանցային քաղաքականությունները տարբերվում ստանդարտներից և ինչպես կանոնակարգի կազմումը պարզեցնում է դրանց ընթերցելիությունը և կարգարկվածությունը:

Կլաստերում տեղադրված են 2 վեբ հավելվածներ՝ Node.js և PHP, որոնցից մեկը օգտագործում է Redis: Պահպանելու համար PHP-ից Redis մուտքը փակելու՝ Node.js-ի հետ կապերով, բավարար է կիրառել հետևյալ քաղաքականությունը:

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: allow-redis-nodejs spec: podSelector: matchLabels: service: redis ingress: - from: - podSelector: matchLabels: service: nodejs ports: - protocol: TCP port: 6379

Փաստորեն, մենք թույլ տվեցինք Redis-ի պորտի մուտքն Node.js-ից: Եվ մենք համապատասխանաբար ոչ մի բան փակել չենք արգելել: NetworkPolicy- ի հետ մեկտեղ բոլոր նշված սելեկտորները սկսում են առանձնացնել, եթե հակառակը նշված չէ: Այդ ընթացքում առանձնացման կանոնները չեն տարածվում այլ օբյեկտների վրա, որոնք չեն ընդգրկվում սելեկտորի մեջ:

Օրինակն օգտագործում է

apiVersion Kubernetes-ի «պայմանագրին» համաձայն, բայց ոչինչ չի խանգարում օգտագործել Calico-ի մատուցման համանուն ռեսուրսը . Սինտաքսը ավելի մանրամասն է, հետևաբար պետք է վերաձևակերպել վերոհիշյալ դեպքի կանոնը հետևյալ կերպ:apiVersion: crd.projectcalico.org/v1 kind: NetworkPolicy metadata: name: allow-redis-nodejs spec: selector: service == 'redis' ingress: - action: Allow protocol: TCP source: selector: service == 'nodejs' destination: ports: - 6379

apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
  name: allow-redis-nodejs
spec:
  selector: service == 'redis'
  ingress:
  - action: Allow
    protocol: TCP
    source:
      selector: service == 'nodejs'
    destination:
      ports:
      - 6379

Ինչպես արդեն բարձրացնելս նշված կոնցեպտները, ամբողջ ողնակների թույլտվության կամ արգելքի հարցում սովորական NetworkPolicy API կողմից պարունակում են բարդ հասկացողություններ փակագծեր պարունակող: Calico-ով, արգելակման կանոնի տրամաբանությունը հակառակ ուղղությամբ փոխելու համար բավարար է փոխել գործողություն: Թույլատրել ըստ գործողություն: արգելել.

Չափորոշիչներով առանձնացնել

Հիմա պատկերացնենք մի իրավիճակ, երբ ծրագիրը բիզնես մետրիկաներ է արտադրում Prometheus համակարգում հավաքելու և դրանք հետագա վերլուծության համար Grafana-ով: Ապրանքներում կարող է ներառվել զգայուն տվյալներ, որոնք ըստ այնմ հասանելի են հանրային դիտման: Վերջին մոռացած մթերքները կփակենք սկզբում այս տվյալներից:

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

Prometheus-ը, որպես կանոն, տեղակայված է առանձին ծառայողական սեռում — օրինակ, դա կլինի հետևյալ տեսակի namespace:

apiVersion: v1
kind: Namespace
metadata:
  labels:
    module: prometheus
  name: kube-prometheus

Դաշտը metadata.labels այստեղ դա պատահական չէ: Ինչպես արդեն նշվել է վերևում, namespaceSelector (ինչպես և podSelector) աշխատում են լեյբլներով: Ինչպես ուներ մետրիկները բոլոր pod-ներից որոշակի պորտում հավաքելու համար, ստիպված կլինեք ավելացնել որևէ լեյբլ (կամ վերցնել առկաներից), այնուհետև կիրառեք նման կարգավորում:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-metrics-prom
spec:
  podSelector: {}
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          module: prometheus
    ports:
    - protocol: TCP
      port: 9100

Նմանապես, եթե օգտագործվում են Calico քաղաքականություններ, ապա տեսքը կլինի հետևյալ:

apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
  name: allow-metrics-prom
spec:
  ingress:
  - action: Allow
    protocol: TCP
    source:
      namespaceSelector: module == 'prometheus'
    destination:
      ports:
      - 9100

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

Calico մշակողների կարծիքով, լավագույն պրակտիկան է «Արգելեք բոլորը և հստակ բացեք անհրաժեշտը», որը արձանագրված է պաշտոնական փաստաթղթերի (այլ էլ նույն մոտեցումը հետևում են, մասնավորապես, վերը նշված հոդվածում).

Calico հավելյալ օբյեկտների կիրառումը

Հիշեցնում եմ, որ Calico-ի ընդլայնված API-ի միջոցով հնարավոր է կարգավորել узловերի հասանելիությունը, առանց pod-ների սահմանափակման: Վ siguiente օրինակով, մեկ GlobalNetworkPolicy արգելվում է ICMP-հարցումների անցնում կլաստերում (օրինակ, ping-եր pod-ից узловի, pod-ների միջև կամ узловից IP pod-ի վրա):

apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
  name: block-icmp
spec:
  order: 200
  selector: all()
  types:
  - Ingress
  - Egress
  ingress:
  - action: Deny
    protocol: ICMP
  egress:
  - action: Deny
    protocol: ICMP

Վերը ներկայացված դեպքում узловերը կլաստերում «նման կցելով» միմյանց հասանելիություն ունեն ICMP-ի վրա: Եվ այս խնդիրն լուծվում է GlobalNetworkPolicy, կիրառելով այն էակին HostEndpoint:

apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
  name: deny-icmp-kube-02
spec:
  selector: "role == 'k8s-node'"
  order: 0
  ingress:
  - action: Allow
    protocol: ICMP
  egress:
  - action: Allow
    protocol: ICMP
---
apiVersion: crd.projectcalico.org/v1
kind: HostEndpoint
metadata:
  name: kube-02-eth0
  labels:
    role: k8s-node
spec:
  interfaceName: eth0
  node: kube-02
  expectedIPs: ["192.168.2.2"]

VPN-ի դեպք

Վերջապես, ներկայացնեմ բավականին իրական օրինակ Calico-ի գործառույթների օգտագործման համար, երբ ստանդարտ քաղաքականության հավաքածուի աջակցությունը մանական է: Վեբ-հաղորդակցման հասանելիության համար հաճախորդները օգտագործում են VPN-տունություն և այս հասանելիությունը խիստ վերահսկվում է` օգտագործման թույլատրված ծառայությունների կոնկրետ ցանկով:

Calico Kubernetes ցանցի համար՝ ծանոթացում և մի քանի փորձառություններ

Հաճախորդները միանում են VPN-ին ստանդարտ UDP-պորտ 1194-ի միջոցով և միանալու պահին ստանում են միջանցքներ տնակային ենթաճյուղերի ու ծառայությունների համար: Միջանձնային հասցեները ամբողջությամբ բաշխվում են, որպեսզի չկորցնեն ծառայությունները կրկին վերագործարկումների և հասցեների փոփոխությունների ժամանակ:

Պորտը կոնֆիգուրացվել է ստանդարտ, ինչը որոշակի հատկանիշներ է ավելացնում ծրագրի կոնֆիգուրացման գործընթացին և դրա տեղափոխմանը Kubernetes-կլաստեր: Օրինակ, AWS LoadBalancer-ում UDP-ն հայտնվել է միայն անցյալ տարվա վերջում մի սահմանափակ տարածաշրջանում, իսկ NodePort-ը չի կարելի օգտագործել, քանի որ դա փոխանցվում է բոլոր կլաստերների узлу և անհնար է մետ ապային չկախվածությամբ ծառայությունների ինտերֆեյսների քանակը: Եվ պետք է փոխել նախկինում ընտրված պորտերի տպաքանակը:

Հնարավոր լուծումների վերանայման արդյունքում հետևյալը ընտրվեց:

  1. VPN-իPods-ն ծրագրավորվում են узлу եզակի միջավայրում hostNetwork, այսինքն՝ իրական IP-ով:
  2. Ծառայությունը ներկայացվում է դրսում ClusterIP. Узлу հասարակաց տեղադրվում է պորտ, որը հասանելի է դրսից որոշակի նկատառումներով (ստեղծված իրական IP-հասցեների առկայություն):
  3. Uzlu, որտեղ կազմավորվել է pod-ը, մեր պատմության սահմաններից դուրս է: Պետք է նշել, որ ծառայությունը հնարավոր է պինդ կապել узлу կամ գրել մի փոքր sidecar-ծառայություն, որը հետևելու է VPN-ծառայության ներկայիս IP-հասցեին և փոփոխություններ կատարում DNS-գրառումներին, որոնք առաջ ետ են տվել հաճախորդներին` ով ինչի կարող է երևակայել:

Ռուսհավաքման տեսանկյունից մենք կարող ենք անհամեմատելիորեն հաստատել հաճախորդին VPN-ի միջոցով նրա IP-հասցեի հիման վրա, որը տրամադրվում է VPN-ի ծառի կողմից: Ստորև ներկայացված է պարզ օրինակ մի հաճախորդի հասանելիության սահմանափակման վրա, որի ծառայությունները, օրինակ, հայտարարել են Redis-ի վերոնշյալ պատվերով:

apiVersion: crd.projectcalico.org/v1
kind: HostEndpoint
metadata:
  name: vpnclient-eth0
  labels:
    role: vpnclient
    environment: production
spec:
  interfaceName: "*"
  node: kube-02
  expectedIPs: ["172.176.176.2"]
---
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
  name: vpn-rules
spec:
  selector: "role == 'vpnclient'"
  order: 0
  applyOnForward: true
  preDNAT: true
  ingress:
  - action: Deny
    protocol: TCP
    destination:
      ports: [6379]
  - action: Allow
    protocol: UDP
    destination:
      ports: [53, 67]

Ահա խիստ արգելվում է 6379 պորտին միացում, բայց DNS ծառայության աշխատանքը պահպանվում է, որի գործունեությունը հաճախ տուժում է կանոնների կազմման ժամանակ: Քանի որ, ինչպես արդեն նշվել է, եթե ընտրիչը առաջանում է, այն ենթարկվում է վաղ Default արգելման քաղաքականության, եթե այլ կերպ չի նշվել:

Եզրակացություններ

Այսպիսով, Calico-ի ընդլայնված API-ի միջոցով հնարավոր է ճկուն կարգավորումներ կատարել և դինամիկ կերպով փոխել մասշտաբը կլաստերում և դրա շուրջ: Ընդհանուր առմամբ, դրա օգտագործումը կարող է նմանվել գնդակի արձակում, իսկ L3 ցանցի ներդրումը BGP- և IP-IP-տուննեյններով պարզապես հսկայական է սովորական Kubernetes-instsallում հարթ ցանցի դեպքում... Այնուամենայնիվ, մյուս կողմից գործի միջոցը շատ կենսունակ և օգտակար է:

Կլաստերի մեկուսացումը անվտանգություն պահպանելու պահանջները իրականացնելը միշտ չէ, որ հնարավոր է, ու հենց այդ դեպքերում Calico-ն (օրինակ, նման լուծում) կարող է օգտակար լինել: Գործս օրինակները, որոնք ներկայացված են հոդվածում (քիչ փոփոխություններով) կիրառվում են մեր հաճախորդների մի քանի ինստալացիաներում AWS-ում:

P.S.

Նաեւ կարդացեք մեր բլոգում:

Ընտանիք: habr.com

Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով 🔥 Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster