Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Ang layunin ng artikulo ay ipakilala ang mambabasa sa mga pangunahing kaalaman sa networking at pamamahala ng mga patakaran sa network sa Kubernetes, pati na rin ang third-party na Calico plugin na nagpapalawak ng mga karaniwang kakayahan. Kasabay nito, ang kadalian ng pagsasaayos at ilang mga tampok ay ipapakita gamit ang mga tunay na halimbawa mula sa aming karanasan sa pagpapatakbo.

Isang mabilis na pagpapakilala sa Kubernetes networking appliance

Ang isang Kubernetes cluster ay hindi maiisip nang walang network. Nai-publish na namin ang mga materyales sa kanilang mga pangunahing kaalaman: "Isang may larawang gabay sa networking sa Kubernetes"At"Isang Panimula sa Mga Patakaran sa Network ng Kubernetes para sa Mga Propesyonal sa Seguridad'.

Sa konteksto ng artikulong ito, mahalagang tandaan na ang K8s mismo ay hindi mananagot para sa koneksyon ng network sa pagitan ng mga lalagyan at mga node: para dito, iba't ibang Mga plugin ng CNI (Container Networking Interface). Higit pa tungkol sa konseptong ito namin sinabi rin nila sa akin.

Halimbawa, ang pinakakaraniwan sa mga plugin na ito ay pranela β€” nagbibigay ng buong koneksyon sa network sa pagitan ng lahat ng cluster node sa pamamagitan ng pagtataas ng mga tulay sa bawat node, na nagtatalaga ng subnet dito. Gayunpaman, hindi palaging kapaki-pakinabang ang kumpleto at hindi kinokontrol na accessibility. Upang matiyak ang ilang uri ng minimal na paghihiwalay sa cluster, kinakailangan na makialam sa pagsasaayos ng firewall. Sa pangkalahatang kaso, ito ay inilalagay sa ilalim ng kontrol ng parehong CNI, kaya naman ang anumang mga interbensyon ng third-party sa iptables ay maaaring mabigyang-kahulugan nang mali o balewalain nang buo.

At ibinibigay ang "out of the box" para sa pag-aayos ng pamamahala ng patakaran sa network sa isang cluster ng Kubernetes NetworkPolicy API. Ang mapagkukunang ito, na ipinamahagi sa mga napiling namespace, ay maaaring maglaman ng mga panuntunan upang maiba ang pag-access mula sa isang application patungo sa isa pa. Nagbibigay-daan din ito sa iyo na i-configure ang pagiging naa-access sa pagitan ng mga partikular na pod, kapaligiran (mga namespace) o mga bloke ng mga IP address:

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

Hindi ito ang pinaka primitive na halimbawa ng opisyal na dokumentasyon maaaring minsan at magpakailanman ay mapahina ang pagnanais na maunawaan ang lohika kung paano gumagana ang mga patakaran sa network. Gayunpaman, susubukan pa rin naming maunawaan ang mga pangunahing prinsipyo at pamamaraan ng pagproseso ng mga daloy ng trapiko gamit ang mga patakaran sa network...

Ito ay lohikal na mayroong 2 uri ng trapiko: pagpasok sa pod (Ingress) at palabas mula dito (Egress).

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Sa totoo lang, nahahati ang pulitika sa 2 kategoryang ito batay sa direksyon ng paggalaw.

Ang susunod na kinakailangang katangian ay isang tagapili; ang isa kung kanino nalalapat ang panuntunan. Ito ay maaaring isang pod (o isang pangkat ng mga pod) o isang kapaligiran (ibig sabihin, isang namespace). Isang mahalagang detalye: ang parehong uri ng mga bagay na ito ay dapat maglaman ng isang label (etiketa sa terminolohiya ng Kubernetes) - ito ang mga ginagamit ng mga pulitiko.

Bilang karagdagan sa isang limitadong bilang ng mga tagapili, na pinagsama ng ilang uri ng label, posibleng magsulat ng mga panuntunan tulad ng "Payagan/tanggihan ang lahat/lahat" sa iba't ibang mga variation. Para sa layuning ito, ginagamit ang mga konstruksyon ng form:

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

β€” sa halimbawang ito, ang lahat ng pod sa kapaligiran ay hinarangan mula sa papasok na trapiko. Ang kabaligtaran na pag-uugali ay maaaring makamit sa sumusunod na pagtatayo:

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

Katulad nito para sa papalabas:

  podSelector: {}
  policyTypes:
  - Egress

- upang patayin ito. At narito ang dapat isama:

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

Pagbabalik sa pagpili ng isang CNI plugin para sa isang kumpol, ito ay nagkakahalaga ng pagpuna na hindi lahat ng network plugin ay sumusuporta sa NetworkPolicy. Halimbawa, ang nabanggit na Flannel ay hindi alam kung paano i-configure ang mga patakaran sa network, na diretsong sabi nito sa opisyal na imbakan. Ang isang alternatibo ay binanggit din doon - isang Open Source na proyekto kalenkor, na makabuluhang nagpapalawak sa karaniwang hanay ng mga Kubernetes API sa mga tuntunin ng mga patakaran sa network.

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Pagkilala sa Calico: teorya

Ang Calico plugin ay maaaring gamitin sa pagsasama sa Flannel (subproject Channel) o nang nakapag-iisa, na sumasaklaw sa parehong network connectivity at availability sa pamamahala ng mga kakayahan.

Anong mga pagkakataon ang ibinibigay gamit ang K8s na β€œboxed” solution at ang API set mula sa Calico?

Narito kung ano ang nakapaloob sa NetworkPolicy:

  • ang mga pulitiko ay nalilimitahan ng kapaligiran;
  • inilalapat ang mga patakaran sa mga pod na may markang label;
  • maaaring ilapat ang mga panuntunan sa mga pod, kapaligiran o subnet;
  • Ang mga panuntunan ay maaaring maglaman ng mga protocol, pinangalanan o simbolikong mga detalye ng port.

Narito kung paano pinapalawak ng Calico ang mga function na ito:

  • maaaring ilapat ang mga patakaran sa anumang bagay: pod, lalagyan, virtual machine o interface;
  • Ang mga panuntunan ay maaaring maglaman ng isang tiyak na aksyon (pagbabawal, pahintulot, pag-log);
  • ang target o pinagmumulan ng mga panuntunan ay maaaring isang port, isang hanay ng mga port, protocol, HTTP o ICMP attribute, IP o subnet (ika-4 o ika-6 na henerasyon), anumang mga tagapili (node, host, kapaligiran);
  • Bilang karagdagan, maaari mong i-regulate ang pagpasa ng trapiko gamit ang mga setting ng DNAT at mga patakaran sa pagpapasa ng trapiko.

Ang unang commit sa GitHub sa Calico repository ay petsa pabalik noong Hulyo 2016, at makalipas ang isang taon, ang proyekto ay nakakuha ng nangungunang posisyon sa pag-aayos ng koneksyon sa network ng Kubernetes - ito ay napatunayan, halimbawa, sa mga resulta ng survey, isinagawa ng The New Stack:

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Maraming malalaking pinamamahalaang solusyon sa mga K8, gaya ng Amazon EKS, Azure AKS, Google GKE at ang iba ay nagsimulang magrekomenda nito para magamit.

Kung tungkol sa pagganap, lahat ay mahusay dito. Sa pagsubok ng kanilang produkto, ang Calico development team ay nagpakita ng astronomical performance, na nagpapatakbo ng higit sa 50000 container sa 500 physical node na may rate ng paggawa na 20 container bawat segundo. Walang natukoy na problema sa scaling. Mga ganyang resulta ay inihayag na sa anunsyo ng unang bersyon. Ang mga independiyenteng pag-aaral na nakatuon sa throughput at pagkonsumo ng mapagkukunan ay nagpapatunay din na ang pagganap ng Calico ay halos kasing ganda ng Flannel. Halimbawa:

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Mabilis na umuunlad ang proyekto, sinusuportahan nito ang trabaho sa mga sikat na solusyon na pinamamahalaang K8, OpenShift, OpenStack, posibleng gumamit ng Calico kapag nagde-deploy ng cluster gamit ang sipa, may mga sanggunian sa pagtatayo ng mga network ng Service Mesh (narito ang isang halimbawa ginamit kasabay ng Istio).

Magsanay sa Calico

Sa pangkalahatang kaso ng paggamit ng vanilla Kubernetes, ang pag-install ng CNI ay bumababa sa paggamit ng file calico.yaml, na-download mula sa opisyal na website, sa pamamagitan ng paggamit kubectl apply -f.

Bilang panuntunan, ang kasalukuyang bersyon ng plugin ay tugma sa pinakabagong 2-3 bersyon ng Kubernetes: ang pagpapatakbo sa mga mas lumang bersyon ay hindi nasubok at hindi ginagarantiyahan. Ayon sa mga developer, ang Calico ay tumatakbo sa Linux kernels sa itaas ng 3.10 na tumatakbo sa CentOS 7, Ubuntu 16 o Debian 8, sa ibabaw ng iptables o IPVS.

Paghihiwalay sa loob ng kapaligiran

Para sa pangkalahatang pag-unawa, tingnan natin ang isang simpleng kaso para maunawaan kung paano naiiba ang mga patakaran sa network sa Calico notation sa mga karaniwan at kung paano pinapasimple ng diskarte sa paggawa ng mga panuntunan ang kanilang pagiging madaling mabasa at flexibility ng configuration:

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Mayroong 2 web application na naka-deploy sa cluster: sa Node.js at PHP, isa sa mga ito ay gumagamit ng Redis. Para harangan ang access sa Redis mula sa PHP, habang pinapanatili ang pagkakakonekta sa Node.js, ilapat lang ang sumusunod na patakaran:

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

Talagang pinayagan namin ang papasok na trapiko sa Redis port mula sa Node.js. At malinaw na hindi nila ipinagbabawal ang anumang bagay. Sa sandaling lumitaw ang NetworkPolicy, ang lahat ng mga tagapili na binanggit dito ay magsisimulang ihiwalay, maliban kung tinukoy. Gayunpaman, ang mga panuntunan sa paghihiwalay ay hindi nalalapat sa iba pang mga bagay na hindi sakop ng tagapili.

Ang halimbawa ay gumagamit ng apiVersion Kubernetes out of the box, ngunit walang pumipigil sa iyong gamitin ito mapagkukunan ng parehong pangalan mula sa paghahatid ng Calico. Ang syntax doon ay mas detalyado, kaya kakailanganin mong muling isulat ang panuntunan para sa kaso sa itaas sa sumusunod na form:

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

Ang mga nabanggit na konstruksyon para sa pagpapahintulot o pagtanggi sa lahat ng trapiko sa pamamagitan ng regular na NetworkPolicy API ay naglalaman ng mga konstruksyon na may mga panaklong na mahirap maunawaan at matandaan. Sa kaso ng Calico, upang baguhin ang lohika ng isang panuntunan sa firewall sa kabaligtaran, baguhin lamang action: Allow sa action: Deny.

Paghihiwalay ng kapaligiran

Ngayon isipin ang isang sitwasyon kung saan ang isang application ay bumubuo ng mga sukatan ng negosyo para sa koleksyon sa Prometheus at karagdagang pagsusuri gamit ang Grafana. Ang pag-upload ay maaaring maglaman ng sensitibong data, na muling makikita ng publiko bilang default. Itago natin ang data na ito mula sa prying eyes:

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Ang Prometheus, bilang panuntunan, ay inilalagay sa isang hiwalay na kapaligiran ng serbisyo - sa halimbawa ito ay magiging isang namespace tulad nito:

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

Field metadata.labels ito pala ay hindi aksidente. Gaya ng nabanggit sa itaas, namespaceSelector (pati na rin ang podSelector) ay gumagana gamit ang mga label. Samakatuwid, upang payagan ang mga sukatan na makuha mula sa lahat ng mga pod sa isang partikular na port, kakailanganin mong magdagdag ng ilang uri ng label (o kumuha mula sa mga umiiral na), at pagkatapos ay maglapat ng configuration tulad ng:

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

At kung gagamit ka ng mga patakaran ng Calico, ang syntax ay magiging ganito:

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

Sa pangkalahatan, sa pamamagitan ng pagdaragdag ng mga ganitong uri ng mga patakaran para sa mga partikular na pangangailangan, maaari mong protektahan laban sa nakakahamak o hindi sinasadyang panghihimasok sa pagpapatakbo ng mga application sa cluster.

Ang pinakamahusay na kasanayan, ayon sa mga tagalikha ng Calico, ay ang "I-block ang lahat at tahasang buksan kung ano ang kailangan mo", na nakadokumento sa opisyal na dokumentasyon (ang iba ay sumusunod sa isang katulad na diskarte - sa partikular, sa nabanggit na artikulo).

Paggamit ng Karagdagang Mga Bagay ng Calico

Hayaan mong ipaalala ko sa iyo na sa pamamagitan ng pinahabang hanay ng mga Calico API maaari mong i-regulate ang pagkakaroon ng mga node, hindi limitado sa mga pod. Sa sumusunod na halimbawa gamit ang GlobalNetworkPolicy ang kakayahang ipasa ang mga kahilingan ng ICMP sa cluster ay sarado (halimbawa, mga ping mula sa isang pod patungo sa isang node, sa pagitan ng mga pod, o mula sa isang node patungo sa isang 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

Sa kaso sa itaas, posible pa rin para sa mga cluster node na "maabot" sa isa't isa sa pamamagitan ng ICMP. At ang isyung ito ay nalutas sa pamamagitan ng paraan GlobalNetworkPolicy, inilapat sa isang entity 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"]

Ang Kaso ng VPN

Sa wakas, magbibigay ako ng isang tunay na halimbawa ng paggamit ng mga function ng Calico para sa kaso ng malapit-kumpol na pakikipag-ugnayan, kapag ang isang karaniwang hanay ng mga patakaran ay hindi sapat. Upang ma-access ang web application, ang mga kliyente ay gumagamit ng VPN tunnel, at ang access na ito ay mahigpit na kinokontrol at limitado sa isang partikular na listahan ng mga serbisyong pinapayagang gamitin:

Calico para sa networking sa Kubernetes: panimula at kaunting karanasan

Kumokonekta ang mga kliyente sa VPN sa pamamagitan ng karaniwang UDP port 1194 at, kapag nakakonekta, tumatanggap ng mga ruta sa mga cluster subnet ng mga pod at serbisyo. Ang buong subnet ay itinutulak upang hindi mawalan ng mga serbisyo kapag nag-restart at nagbabago ng mga address.

Ang port sa configuration ay karaniwan, na nagpapataw ng ilang mga nuances sa proseso ng pag-configure ng application at paglilipat nito sa Kubernetes cluster. Halimbawa, sa parehong AWS LoadBalancer para sa UDP ay literal na lumitaw sa pagtatapos ng nakaraang taon sa isang limitadong listahan ng mga rehiyon, at ang NodePort ay hindi magagamit dahil sa pagpapasa nito sa lahat ng mga cluster node at imposibleng sukatin ang bilang ng mga instance ng server para sa fault tolerance layunin. Dagdag pa, kailangan mong baguhin ang default na hanay ng mga port...

Bilang resulta ng paghahanap sa mga posibleng solusyon, napili ang mga sumusunod:

  1. Ang mga pod na may VPN ay naka-iskedyul bawat node in hostNetwork, iyon ay, sa aktwal na IP.
  2. Ang serbisyo ay nai-post sa labas sa pamamagitan ng ClusterIP. Ang isang port ay pisikal na naka-install sa node, na naa-access mula sa labas na may maliliit na reserbasyon (kondisyon na presensya ng isang tunay na IP address).
  3. Ang pagtukoy sa node kung saan ang pod rose ay lampas sa saklaw ng aming kuwento. Sasabihin ko lang na maaari mong mahigpit na "ipako" ang serbisyo sa isang node o magsulat ng isang maliit na serbisyo ng sidecar na susubaybayan ang kasalukuyang IP address ng serbisyo ng VPN at i-edit ang mga tala ng DNS na nakarehistro sa mga kliyente - sinuman ang may sapat na imahinasyon.

Mula sa isang pananaw sa pagruruta, maaari naming natatanging makilala ang isang VPN client sa pamamagitan ng IP address nito na ibinigay ng VPN server. Nasa ibaba ang isang primitive na halimbawa ng paghihigpit sa access ng isang kliyente sa mga serbisyo, na inilalarawan sa nabanggit na 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]

Dito, ang pagkonekta sa port 6379 ay mahigpit na ipinagbabawal, ngunit sa parehong oras ang pagpapatakbo ng serbisyo ng DNS ay napanatili, ang paggana kung saan ay madalas na naghihirap kapag gumuhit ng mga panuntunan. Dahil, tulad ng naunang nabanggit, kapag lumitaw ang isang tagapili, ang default na patakaran sa pagtanggi ay inilalapat dito maliban kung tinukoy.

Mga resulta ng

Kaya, gamit ang advanced na API ng Calico, maaari mong flexible na i-configure at dynamic na baguhin ang pagruruta sa loob at paligid ng cluster. Sa pangkalahatan, ang paggamit nito ay maaaring magmukhang pagbaril sa mga maya gamit ang isang kanyon, at ang pagpapatupad ng isang L3 network na may BGP at IP-IP tunnels ay mukhang napakapangit sa isang simpleng pag-install ng Kubernetes sa isang patag na network... Gayunpaman, kung hindi man ang tool ay mukhang mabubuhay at kapaki-pakinabang. .

Ang pagbubukod ng isang cluster upang matugunan ang mga kinakailangan sa seguridad ay maaaring hindi palaging magagawa, at ito ay kung saan ang Calico (o isang katulad na solusyon) ay dumating sa pagsagip. Ang mga halimbawang ibinigay sa artikulong ito (na may maliliit na pagbabago) ay ginagamit sa ilang mga pag-install ng aming mga kliyente sa AWS.

PS

Basahin din sa aming blog:

Pinagmulan: www.habr.com

Magdagdag ng komento