Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

La celo de la artikolo estas prezenti la leganton al la bazoj de interkonektado kaj administrado de retaj politikoj en Kubernetes, same kiel la triaparta Calico-kromaĵo kiu etendas normajn kapablojn. Survoje, la facileco de agordo kaj iuj funkcioj estos pruvitaj uzante realajn ekzemplojn de nia operacia sperto.

Rapida enkonduko al Kubernetes-reto-aparato

Kubernetes-areo ne povas esti imagita sen reto. Ni jam publikigis materialojn pri iliaj bazoj: "Ilustrita gvidilo al interkonektado en Kubernetes"Kaj"Enkonduko al Kubernetes Retaj Politikoj por Sekurecaj Profesiuloj".

En la kunteksto de ĉi tiu artikolo, estas grave noti, ke K8s mem ne respondecas pri retkonektebleco inter ujoj kaj nodoj: por tio, diversaj CNI-kromaĵoj (Uja Reta Interfaco). Pli pri ĉi tiu koncepto ni ili ankaŭ diris al mi.

Ekzemple, la plej ofta el ĉi tiuj kromprogramoj estas Fandalo — provizas plenan retan konekteblecon inter ĉiuj grapolnodoj levante pontojn sur ĉiu nodo, asignante subreton al ĝi. Tamen, kompleta kaj nereguligita alirebleco ne ĉiam estas utila. Por provizi ian minimuman izolitecon en la areto, necesas interveni en la agordo de la fajroŝirmilo. En la ĝenerala kazo, ĝi estas metita sub la kontrolon de la sama CNI, tial ajnaj triaj intervenoj en iptables povas esti malĝuste interpretitaj aŭ ignoritaj entute.

Kaj "el la skatolo" por organizi retan politikan administradon en Kubernetes-areto estas provizita NetworkPolicy API. Ĉi tiu rimedo, distribuita tra elektitaj nomspacoj, povas enhavi regulojn por diferencigi aliron de unu aplikaĵo al alia. Ĝi ankaŭ permesas al vi agordi alireblecon inter specifaj podoj, medioj (nomspacoj) aŭ blokoj de IP-adresoj:

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

Ĉi tio ne estas la plej primitiva ekzemplo de oficiala dokumentaro eble iam por ĉiam malinstigi la deziron kompreni la logikon de kiel funkcias retaj politikoj. Tamen, ni ankoraŭ provos kompreni la bazajn principojn kaj metodojn de prilaborado de trafikfluoj uzante retajn politikojn...

Estas logike, ke ekzistas 2 specoj de trafiko: eniro de la pod (Eniro) kaj eliro de ĝi (Eliro).

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Fakte, politiko estas dividita en ĉi tiujn 2 kategoriojn surbaze de la direkto de movado.

La sekva postulata atributo estas elektilo; tiu al kiu la regulo validas. Ĉi tio povas esti balgo (aŭ grupo de balgoj) aŭ medio (t.e. nomspaco). Grava detalo: ambaŭ specoj de ĉi tiuj objektoj devas enhavi etikedon (etikedo en terminologio de Kubernetes) - tiuj estas tiuj kun kiuj politikistoj funkcias.

Krom finia nombro da elektiloj kunigitaj per ia etikedo, eblas skribi regulojn kiel "Permesi/malkonfesi ĉion/ĉiujn" en malsamaj variaĵoj. Por tiu celo, konstruoj de la formo estas uzataj:

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

— en ĉi tiu ekzemplo, ĉiuj podoj en la medio estas blokitaj de envenanta trafiko. La kontraŭa konduto povas esti atingita per la sekva konstruo:

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

Simile por eksiĝinta:

  podSelector: {}
  policyTypes:
  - Egress

- malŝalti ĝin. Kaj jen kion inkludi:

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

Revenante al la elekto de CNI-kromaĵo por grapolo, indas rimarki tion ne ĉiu reto kromaĵo subtenas NetworkPolicy. Ekzemple, la jam menciita Flannel ne scias kiel agordi retajn politikojn, kio oni diras rekte en la oficiala deponejo. Tie mencias ankaŭ alternativo - projekto Open Source Kalico, kiu signife vastigas la norman aron de Kubernetes API-oj laŭ retaj politikoj.

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Konatiĝi kun Calico: teorio

La Calico-aldonaĵo povas esti uzata en integriĝo kun Flannel (subprojekto Kanalo) aŭ sendepende, kovrante kaj retkonektecon kaj haveblecadministradkapablojn.

Kiajn ŝancojn donas la uzado de la "boksita" solvo K8s kaj la API-aro de Calico?

Jen kio estas enkonstruita en NetworkPolicy:

  • politikistoj estas limigitaj de la medio;
  • politikoj estas aplikataj al podoj markitaj per etikedoj;
  • reguloj povas esti aplikataj al podoj, medioj aŭ subretoj;
  • reguloj povas enhavi protokolojn, nomitajn aŭ simbolajn havenspecifojn.

Jen kiel Calico etendas ĉi tiujn funkciojn:

  • politikoj povas esti aplikataj al iu ajn objekto: pod, ujo, virtuala maŝino aŭ interfaco;
  • reguloj povas enhavi specifan agon (malpermeso, permeso, protokolado);
  • la celo aŭ fonto de reguloj povas esti haveno, gamo da havenoj, protokoloj, HTTP aŭ ICMP-atributoj, IP aŭ subreto (4-a aŭ 6-a generacio), ajnaj elektiloj (nodoj, gastigantoj, medioj);
  • Aldone, vi povas reguligi la trafikon per DNAT-agordoj kaj trafikaj plusendaj politikoj.

La unuaj engaĝiĝoj en GitHub en la deponejo Calico datiĝas de julio 2016, kaj jaron poste la projekto prenis gvidan pozicion en organizado de la reto-konekteco de Kubernetes - tio estas pruvita, ekzemple, de la rezultoj de la enketo, kondukita fare de La Nova Stako:

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Multaj grandaj administritaj solvoj kun K8s, kiel ekzemple Amazon EX, Lazura AKS, Google GKE kaj aliaj komencis rekomendi ĝin por uzo.

Koncerne agadon, ĉio estas bonega ĉi tie. Testante sian produkton, la disvolva teamo de Calico montris astronomian agadon, kurante pli ol 50000 ujojn sur 500 fizikaj nodoj kun krea indico de 20 ujoj sekundo. Neniuj problemoj estis identigitaj kun skalo. Tiaj rezultoj estis anoncitaj jam ĉe la anonco de la unua versio. Sendependaj studoj temigantaj trairon kaj resursan konsumon ankaŭ konfirmas, ke la agado de Calico estas preskaŭ same bona kiel tiu de Flannel. Ekzemple:

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

La projekto disvolviĝas tre rapide, ĝi subtenas laboron en popularaj solvoj administritaj K8s, OpenShift, OpenStack, eblas uzi Calico'n kiam oni disvastigas grapolon uzante kops, estas referencoj al la konstruado de Service Mesh-retoj (jen ekzemplo uzata lige kun Istio).

Praktiku kun Calico

En la ĝenerala kazo de uzado de vanilo Kubernetes, instali CNI signifas uzi la dosieron calico.yaml, elŝutite de la oficiala retejo, uzante kubectl apply -f.

Kiel regulo, la nuna versio de la kromaĵo kongruas kun la plej novaj 2-3 versioj de Kubernetes: funkciado en pli malnovaj versioj ne estas provita kaj ne estas garantiita. Laŭ la programistoj, Calico funkcias per Linukso-kernoj super 3.10 kurante CentOS 7, Ubuntu 16 aŭ Debian 8, krom iptables aŭ IPVS.

Izoliĝo ene de la medio

Por ĝenerala kompreno, ni rigardu simplan kazon por kompreni kiel retaj politikoj en la Calico-notacio diferencas de normaj kaj kiel la aliro al kreado de reguloj simpligas ilian legeblecon kaj agordan flekseblecon:

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Estas 2 TTT-aplikoj deplojitaj en la areto: en Node.js kaj PHP, unu el kiuj uzas Redis. Por bloki aliron al Redis de PHP, konservante konekteblecon kun Node.js, simple apliku la sekvan politikon:

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

Esence ni permesis alvenantan trafikon al la haveno Redis de Node.js. Kaj ili klare ne malpermesis ion alian. Tuj kiam NetworkPolicy aperas, ĉiuj elektiloj menciitaj en ĝi komencas esti izolitaj, krom se alie specifita. Tamen, la izolaj reguloj ne validas por aliaj objektoj ne kovritaj de la elektilo.

La ekzemplo uzas apiVersion Kubernetes el la skatolo, sed nenio malhelpas vin uzi ĝin rimedo de la sama nomo de la Calico-livero. La sintakso tie estas pli detala, do vi devos reverki la regulon por la supra kazo en la sekva formo:

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

La supre menciitaj konstrukcioj por permesi aŭ nei ĉian trafikon per la regula NetworkPolicy API enhavas konstrukciojn kun krampoj malfacile kompreneblaj kaj memoreblaj. En la kazo de Calico, por ŝanĝi la logikon de firewall regulo al la malo, simple ŝanĝi action: Allow sur action: Deny.

Izoliĝo laŭ medio

Nun imagu situacion kie aplikaĵo generas komercajn metrikojn por kolekto en Prometheus kaj plia analizo uzante Grafana. La alŝuto povas enhavi sentemajn datumojn, kiuj denove estas publike videblaj defaŭlte. Ni kaŝu ĉi tiujn datumojn de malklaraj okuloj:

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Prometeo, kiel regulo, estas metita en apartan servan medion - en la ekzemplo ĝi estos nomspaco kiel ĉi tio:

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

kampo metadata.labels tio montriĝis ne akcidento. Kiel menciite supre, namespaceSelector (kaj ankaŭ podSelector) funkcias kun etikedoj. Tial, por permesi mezurojn preni de ĉiuj podoj sur specifa haveno, vi devos aldoni ian etikedon (aŭ preni de ekzistantaj), kaj poste apliki agordon kiel:

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

Kaj se vi uzas Calico-politikojn, la sintakso estos tia:

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

Ĝenerale, aldonante ĉi tiujn specojn de politikoj por specifaj bezonoj, vi povas protekti kontraŭ malica aŭ hazarda enmiksiĝo en la funkciado de aplikoj en la areto.

La plej bona praktiko, laŭ la kreintoj de Calico, estas la aliro "Bloku ĉion kaj eksplicite malfermu tion, kion vi bezonas", dokumentita en oficiala dokumentaro (aliaj sekvas similan aliron - precipe, en jam menciita artikolo).

Uzante Pliajn Calico-Objektojn

Mi memorigu vin, ke per la etendita aro de Calico-API-oj vi povas reguligi la haveblecon de nodoj, ne limigitaj al podoj. En la sekva ekzemplo uzante GlobalNetworkPolicy la kapablo pasigi ICMP-petojn en la areto estas fermita (ekzemple, pings de pod al nodo, inter podoj, aŭ de nodo al 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

En ĉi-supra kazo, estas ankoraŭ eble ke grapolnodoj "atingu" unu la alian per ICMP. Kaj ĉi tiu afero estas solvita per rimedoj GlobalNetworkPolicy, aplikita al ento 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"]

La VPN-Kazo

Fine, mi donos tre realan ekzemplon de uzado de Calico-funkcioj por la kazo de interago de proksime de areto, kiam norma aro de politikoj ne sufiĉas. Por aliri la TTT-aplikaĵon, klientoj uzas VPN-tunelon, kaj ĉi tiu aliro estas strikte kontrolita kaj limigita al specifa listo de servoj permesitaj por uzo:

Calico por interkonektado en Kubernetes: enkonduko kaj iom da sperto

Klientoj konektas al la VPN per norma UDP-haveno 1194 kaj, kiam li estas konektitaj, ricevas itinerojn al la aretaj subretoj de podoj kaj servoj. Tutaj subretoj estas puŝitaj por ne perdi servojn dum rekomencoj kaj adresŝanĝoj.

La haveno en la agordo estas norma, kio trudas iujn nuancojn al la procezo de agordo de la aplikaĵo kaj translokigo de ĝi al la Kubernetes-grupo. Ekzemple, en la sama AWS LoadBalancer por UDP aperis laŭvorte fine de la pasinta jaro en limigita listo de regionoj, kaj NodePort ne povas esti uzata pro ĝia plusendado sur ĉiuj grapolnodoj kaj estas neeble grimpi la nombron da servilaj petskriboj por faŭltoleremo celoj. Krome, vi devos ŝanĝi la defaŭltan gamon de havenoj...

Kiel rezulto de serĉado tra eblaj solvoj, la jena estis elektita:

  1. Pods kun VPN estas planitaj per nodo en hostNetwork, tio estas, al la reala IP.
  2. La servo estas afiŝita ekstere tra ClusterIP. Haveno estas fizike instalita sur la nodo, kiu estas alirebla de ekstere kun negravaj rezervoj (kondiĉa ĉeesto de vera IP-adreso).
  3. Determini la nodon sur kiu la balgo leviĝis preter la amplekso de nia rakonto. Mi nur diros, ke vi povas firme "najli" la servon al nodo aŭ skribi malgrandan kromservon, kiu kontrolos la nunan IP-adreson de la VPN-servo kaj redaktos la DNS-rekordojn registritajn ĉe klientoj - kiu havas sufiĉe da imago.

De envojiga perspektivo, ni povas unike identigi VPN-klienton per ĝia IP-adreso eldonita de la VPN-servilo. Malsupre estas primitiva ekzemplo de limigo de la aliro de tia kliento al servoj, ilustrita sur la supre menciita 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]

Ĉi tie, konekti al la haveno 6379 estas strikte malpermesita, sed samtempe konserviĝas la funkciado de la DNS-servo, kies funkciado sufiĉe ofte suferas dum ellaborado de reguloj. Ĉar, kiel antaŭe menciite, kiam elektilo aperas, la defaŭlta rifuzo politiko estas aplikata al ĝi krom se alie specifita.

Rezultoj

Tiel, uzante la altnivelan API de Calico, vi povas flekseble agordi kaj dinamike ŝanĝi vojigon en kaj ĉirkaŭ la areto. Ĝenerale, ĝia uzo povas aspekti kiel pafado de paseroj per kanono, kaj efektivigo de L3-reto kun tuneloj BGP kaj IP-IP aspektas monstra en simpla instalado de Kubernetes sur plata reto... Tamen, alie la ilo aspektas sufiĉe realigebla kaj utila. .

Izoli areton por plenumi sekurecajn postulojn eble ne ĉiam estas farebla, kaj ĉi tie estas kie Calico (aŭ simila solvo) venas al la savo. La ekzemploj donitaj en ĉi tiu artikolo (kun malgrandaj modifoj) estas uzataj en pluraj instalaĵoj de niaj klientoj en AWS.

PS

Legu ankaŭ en nia blogo:

fonto: www.habr.com

Aldoni komenton