Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Syftet med den hÀr artikeln Àr att introducera lÀsaren till grunderna för nÀtverks- och nÀtverkspolicyhantering i Kubernetes, samt till tredjeparts plugin Calico, som utökar standardfunktionerna. LÀngs vÀgen kommer bekvÀmligheten med konfiguration och vissa funktioner att demonstreras med hjÀlp av verkliga exempel frÄn vÄr driftserfarenhet.

En snabb introduktion till Kubernetes Networking

Det Àr omöjligt att förestÀlla sig ett Kubernetes-kluster utan ett nÀtverk. Vi har redan publicerat material om deras grunder: "En illustrerad guide till Kubernetes-nÀtverk"Och"En introduktion till Kubernetes nÀtverkspolicyer för sÀkerhetspersonal".

I samband med denna artikel Àr det viktigt att notera att K8s sjÀlv inte Àr ansvarig för nÀtverksanslutning mellan behÄllare och noder: den anvÀnder olika CNI-plugins (Container Networking Interface). Vi kommer att lÀra oss mer om detta koncept de berÀttade ocksÄ för mig.

Till exempel Àr den vanligaste av dessa plugins Flanell - ger full nÀtverksanslutning mellan alla klusternoder genom att höja bryggor pÄ varje nod, tilldela ett subnÀt till den. Men fullstÀndig och oreglerad tillgÀnglighet Àr inte alltid fördelaktigt. För att ge en viss minimal isolering i klustret Àr det nödvÀndigt att ingripa i brandvÀggskonfigurationen. I allmÀnhet ges den under kontroll av samma CNI, pÄ grund av vilken tredje parts ingripanden i iptables kan tolkas felaktigt eller ignoreras helt.

Och "out of the box" för att organisera nÀtverkspolicyhantering i ett Kubernetes-kluster tillhandahÄlls NetworkPolicy API. Den hÀr resursen, som strÀcker sig över utvalda namnutrymmen, kan innehÄlla regler för att begrÀnsa Ätkomst frÄn ett program till ett annat. Det lÄter dig ocksÄ konfigurera tillgÀnglighet mellan specifika pods, miljöer (namnutrymmen) eller IP-adressblock:

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

Detta Àr inte det mest primitiva exemplet pÄ officiell dokumentation kan en gÄng för alla avskrÀcka dig frÄn att försöka förstÄ logiken bakom hur nÀtverkspolicyer fungerar. Men vi kommer fortfarande att försöka förstÄ de grundlÀggande principerna och metoderna för att behandla trafikflöden med hjÀlp av nÀtverkspolicyer...

Det Àr logiskt att det finns tvÄ typer av trafik: inkommande till podden (Ingress) och utgÄende frÄn den (Egress).

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Faktum Àr att politiken delas in i dessa tvÄ kategorier efter rörelseriktningen.

NĂ€sta obligatoriska attribut Ă€r vĂ€ljaren; den som regeln gĂ€ller. Detta kan vara en pod (eller grupp av pods) eller en miljö (dvs. ett namnomrĂ„de). Viktig detalj: bĂ„da typerna av dessa objekt mĂ„ste innehĂ„lla en etikett (etikett i Kubernetes terminologi) — det Ă€r de som policyer fungerar med.

Förutom det Àndliga antalet vÀljare förenade av nÄgon etikett, finns det möjlighet att skriva regler som "TillÄt/neka alla/alla" i olika varianter. För detta ÀndamÄl anvÀnds konstruktioner av följande typ:

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

- i det hÀr exemplet nekas alla poddar i miljön inkommande trafik. Det motsatta beteendet kan uppnÄs med denna konstruktion:

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

LikasÄ för utgÄende:

  podSelector: {}
  policyTypes:
  - Egress

– för att stĂ€nga av den. Och hĂ€r Ă€r vad du ska aktivera:

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

För att ÄtergÄ till valet av CNI-plugin för klustret Àr det vÀrt att notera det Inte alla nÀtverksplugin stöder arbete med NetworkPolicy. Till exempel kan den redan nÀmnda Flannel inte konfigurera nÀtverkspolicyer, vilket Àr det sÀgs direkt i det officiella arkivet. DÀr nÀmns ocksÄ ett alternativ - Open Source-projektet KalikÄ, vilket avsevÀrt utökar standarden Kubernetes API nÀr det gÀller nÀtverkspolicyer.

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

LÀr kÀnna Calico: Teori

Calico plugin kan anvÀndas i integration med Flannel (delprojekt Canal) eller oberoende, som tÀcker bÄde funktionerna att sÀkerstÀlla nÀtverksanslutning och funktionerna för tillgÀnglighetshantering.

Vilka möjligheter ger anvÀndningen av den fÀrdiga K8s-lösningen och API-setet frÄn Calico?

HÀr Àr vad som Àr inbyggt i NetworkPolicy:

  • politiker begrĂ€nsas av sin omgivning;
  • policyer tillĂ€mpas pĂ„ kapslar mĂ€rkta med etiketter;
  • regler kan tillĂ€mpas pĂ„ pods, miljöer eller subnĂ€t;
  • Regler kan innehĂ„lla protokoll, namngivna eller symboliska portreferenser.

SÄ hÀr utökar Calico dessa funktioner:

  • policyer kan tillĂ€mpas pĂ„ alla objekt: pod, container, virtuell maskin eller grĂ€nssnitt;
  • regler kan innehĂ„lla en specifik Ă„tgĂ€rd (förbud, tillstĂ„nd, loggning);
  • mĂ„let eller kĂ€llan till regler kan vara en port, portintervall, protokoll, HTTP- eller ICMP-attribut, IP eller subnĂ€t (4:e eller 6:e ​​generationen), valfri vĂ€ljare (noder, vĂ€rdar, miljöer);
  • Dessutom kan du reglera trafikflödet med hjĂ€lp av DNAT-instĂ€llningar och policyer för vidarebefordran av trafik.

De första commits pÄ GitHub i Calico-förvaret gÄr tillbaka till juli 2016, och ett Är senare tog projektet en ledande position nÀr det gÀller att organisera Kubernetes nÀtverksanslutning - detta framgÄr till exempel av resultaten av en undersökning, under ledning av The New Stack:

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

MÄnga stora hanterade lösningar med K8:or, som t.ex Amazon EX, Azure AKS, Googla GKE och andra började rekommendera den för anvÀndning.

NÀr det gÀller prestanda Àr allt bra. NÀr de testade sin produkt visade Calicos utvecklingsteam astronomiska prestanda och lanserade över 50000 500 behÄllare pÄ 20 fysiska noder med en hastighet av XNUMX behÄllare per sekund. Inga skalningsproblem hittades. Det hÀr Àr resultaten röstades redan vid tillkÀnnagivandet av den första versionen. Oberoende studier med fokus pÄ genomströmning och resursförbrukning bekrÀftar ocksÄ att Calicos prestanda Àr nÀstan lika bra som Flannels. Till exempel:

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Projektet utvecklas mycket snabbt, stöder arbete i populÀra lösningar som hanteras K8s, OpenShift, OpenStack, det Àr möjligt att anvÀnda Calico nÀr du distribuerar ett kluster med sparka, det nÀmns om att bygga Service Mesh-nÀtverk (hÀr Àr ett exempel (för anvÀndning tillsammans med Istio).

TrÀna med Calico

I det allmÀnna fallet med att anvÀnda vanilla Kubernetes, kommer installationen av CNI till att anvÀnda filen calico.yaml, laddas ner frÄn den officiella webbplatsen, genom att anvÀnda kubectl apply -f.

Vanligtvis Àr den nuvarande versionen av pluginet kompatibel med de tvÄ eller tre senaste versionerna av Kubernetes; kompatibilitet med Àldre versioner Àr inte testad eller garanterad. Enligt utvecklarna körs Calico pÄ kÀrnan. Linux över 3.10 under kontroll CentOS 7, Ubuntu 16 eller Debian 8, över iptables eller IPVS.

Isolering inom miljön

För en allmÀn förstÄelse, lÄt oss titta pÄ ett enkelt fall för att förstÄ hur nÀtverkspolicyer i Calico-notation skiljer sig frÄn standard och hur tillvÀgagÄngssÀttet för att komponera regler förenklar deras lÀsbarhet och konfigurationsflexibilitet:

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Klustret har tvÄ webbapplikationer utplacerade: Node.js och PHP, varav en anvÀnder Redis. För att stÀnga Ätkomsten till Redis frÄn PHP samtidigt som du bibehÄller anslutning till Node.js, tillÀmpa helt enkelt följande policy:

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

I huvudsak har vi tillÄtit inkommande trafik till Redis-hamnen frÄn Node.js. Och de förbjöd uppenbarligen inget annat. NÀr en nÀtverkspolicy dyker upp Àr alla vÀljare som nÀmns i den isolerade om inte annat anges. Isoleringsreglerna gÀller dock inte andra objekt som inte omfattas av vÀljaren.

Exemplet anvÀnder apiVersion Kubernetes ur lÄdan, men ingenting hindrar dig frÄn att anvÀnda den resurs med samma namn frÄn Calico-leveransen. Syntaxen dÀr Àr mer detaljerad, sÄ du mÄste skriva om regeln för ovanstÄende fall enligt följande:

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

Ovan nÀmnda konstruktioner för att tillÄta eller neka all trafik via det vanliga NetworkPolicy API innehÄller konstruktioner med parenteser som Àr svÄra att förstÄ och komma ihÄg. NÀr det gÀller Calico, för att Àndra logiken i en brandvÀggsregel till det motsatta, rÀcker det att Àndra action: Allow pÄ action: Deny.

Isolering av miljön

LÄt oss nu förestÀlla oss en situation dÀr applikationen genererar affÀrsmÄtt för insamling i Prometheus och vidare analys via Grafana. Nedladdningen kan innehÄlla kÀnslig data, som Äterigen Àr allmÀnt tillgÀnglig som standard. LÄt oss dölja denna information frÄn nyfikna ögon:

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Prometheus placeras vanligtvis i en separat tjÀnstemiljö - i exemplet skulle detta vara ett namnomrÄde av följande typ:

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

FÀlt metadata.labels Det visade sig att detta inte var en slump. Som nÀmnts ovan, namespaceSelector (liksom podSelector) driver etiketter. SÄ för att tillÄta att mÀtvÀrden samlas in frÄn alla pods pÄ en specifik port, mÄste du lÀgga till en etikett (eller ta en frÄn de befintliga) och sedan tillÀmpa en konfiguration som:

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

Och om du anvÀnder Calico-policyer blir syntaxen:

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

I allmÀnhet, genom att lÀgga till policyer av detta slag för specifika behov, kan du skydda mot skadlig eller oavsiktlig störning i driften av applikationer i klustret.

Den bÀsta praxisen, enligt skaparna av Calico, Àr "Förbjud allt och öppna uttryckligen vad som Àr nödvÀndigt", som dokumenterats i officiell dokumentation (Ett liknande tillvÀgagÄngssÀtt anvÀnds av andra, i synnerhet, redan nÀmnda artikel).

AnvÀnda ytterligare Calico-objekt

LÄt mig pÄminna dig om att genom den utökade uppsÀttningen av Calico API:er kan du reglera tillgÀngligheten av noder, inte begrÀnsat till pods. I följande exempel anvÀnder du GlobalNetworkPolicy möjligheten att skicka ICMP-förfrÄgningar i klustret Àr stÀngd (till exempel pingar frÄn en pod till en nod, mellan pods eller frÄn en nod till en pods IP):

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

I fallet ovan Àr det fortfarande möjligt för klusternoder att "nÄ" varandra via ICMP. Och detta problem löses med hjÀlp av medel GlobalNetworkPolicy, tillÀmpas pÄ enheten 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-fallet

Slutligen kommer jag att ge ett mycket verkligt exempel pÄ att anvÀnda Calico-funktioner för ett fall av nÀra-klusterinteraktion, nÀr standarduppsÀttningen policyer inte rÀcker. Klienter anvÀnder en VPN-tunnel för att komma Ät webbapplikationen, och denna Ätkomst Àr strikt kontrollerad och begrÀnsad till en specifik lista över tjÀnster som Àr tillÄtna att anvÀndas:

Calico för nÀtverk i Kubernetes: introduktion och lite erfarenhet

Klienter ansluter till VPN via standard UDP-port 1194 och tar vid anslutning emot rutter till klusterundernÀten av pods och tjÀnster. SubnÀt pushas i sin helhet för att undvika att förlora tjÀnster vid omstarter och adressÀndringar.

Porten i konfigurationen Àr standard, vilket lÀgger vissa nyanser pÄ processen att konfigurera applikationen och överföra den till Kubernetes-klustret. Till exempel, i samma AWS dök LoadBalancer för UDP upp bokstavligen i slutet av förra Äret i en begrÀnsad lista över regioner, och NodePort kan inte anvÀndas eftersom den vidarebefordras till alla klusternoder och det Àr omöjligt att skala antalet serverinstanser för feltoleransÀndamÄl. Dessutom mÄste du Àndra standardportintervallet...

Som ett resultat av att rÀkna upp möjliga lösningar valdes följande:

  1. Pods med VPN Àr schemalagda till en nod i lÀget hostNetwork, det vill sÀga till den faktiska IP-adressen.
  2. TjÀnsten postas utanför genom ClusterIP. En port Àr fysiskt upphöjd pÄ noden, som Àr tillgÀnglig frÄn utsidan med vissa reservationer (villkorad nÀrvaro av en riktig IP-adress).
  3. Att bestÀmma noden pÄ vilken podden körs ligger utanför ramen för vÄr diskussion. Jag kommer bara att sÀga att du kan koppla tjÀnsten till noden eller skriva en liten sidovagnstjÀnst som kommer att övervaka den aktuella IP-adressen för VPN-tjÀnsten och redigera DNS-posterna som registrerats av klienter - vad din fantasi Àn tillÄter.

Ur ett routingperspektiv kan vi unikt identifiera en klient bakom ett VPN genom dess IP-adress som tillhandahÄlls av VPN-servern. Nedan Àr ett primitivt exempel pÄ begrÀnsning av Ätkomst till tjÀnster för en sÄdan klient, illustrerad med ovannÀmnda 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]

HÀr Àr anslutningar till port 6379 strÀngt förbjudna, men DNS-tjÀnsten, som ofta blir lidande nÀr regler skapas, Àr fortfarande i drift. Eftersom, som tidigare nÀmnts, nÀr en vÀljare dyker upp, tillÀmpas den förinstÀllda förbudspolicyn pÄ den om inte annat anges.

Resultat av

Med hjÀlp av Calicos utökade API kan du alltsÄ flexibelt konfigurera och dynamiskt Àndra routing i och runt ditt kluster. Generellt sett kan dess anvÀndning se ut som att skjuta en kanon mot sparvar, och implementeringen av ett L3-nÀtverk med BGP- och IP-IP-tunnlar ser monstruöst ut i en enkel Kubernetes-installation i ett platt nÀtverk... Men i andra avseenden ser verktyget ganska lönsamt och anvÀndbart ut.

Det Àr kanske inte alltid möjligt att isolera ett kluster för att uppfylla sÀkerhetskraven, och det Àr hÀr Calico (eller en liknande lösning) kommer till undsÀttning. Exemplen som ges i artikeln (med mindre modifieringar) anvÀnds i flera av vÄra kunders installationer i AWS.

PS

LÀs Àven pÄ vÄr blogg:

KĂ€lla: will.com

Köp pĂ„litlig hosting för webbplatser med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster