Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Bu məqalənin məqsədi oxucunu Kubernetes-də şəbəkə qarşılıqlı əlaqələrinin və şəbəkə siyasətinin idarə olunmasının əsasları ilə tanış etməkdir, eləcə də standart imkanları artıran Calico adlı üçüncü tərəf plaginini təqdim etməkdir. Eyni zamanda, konfiqurasiyanın rahatlığı və real istifadə təcrübələrimizdən bəzi xüsusiyyətlər nümayiş etdiriləcək.

Kubernetes şəbəkə qurğusuna sürətli giriş

Kubernetes klasteri şəbəkəsiz təsəvvür edilə bilməz. Biz artıq onların əsasları ilə bağlı materiallar dərc etmişik: "Kubernetes şəbəkə qurğusunun vizual bələdçisi» və «Təhlükəsizlik mütəxəssisləri üçün Kubernetes şəbəkə siyasətlərinə giriş».

Bu məqalənin kontekstində qeyd etmək vacibdir ki, konteynerlər və düyünlər arasında şəbəkə bağlantısına Kubernetes özü cavabdeh deyil: bunun üçün müxtəlif CNI plaginləri (Container Networking Interface). Biz bu konsepsiyanı da ətraflı danışmışdıq.

Məsələn, belə plaginlərdən ən çox istifadə edilənlərdən biri — Flannel — klasterin bütün düyünləri arasında tam şəbəkə bağlantısı təmin edir, hər bir düyündə körpülər qaldıraraq ona bir alt şəbəkə təyin edir. Lakin tam və tənzimlənməyən əlçatanlıq həmişə faydalı olmur. Klasterdə müəyyən bir izolyasiya təmin etmək üçün firewall konfiqurasiyasına müdaxilə etmək lazımdır. Ümumiyyətlə, bu, həmin CNI-nin idarəsinə verilir, buna görə də iptables-dakı hər hansı bir üçüncü tərəf müdaxiləsi yanlış anlamaya və ya tamamilə görməməzliyə səbəb ola bilər.

Kubernetes klasterində şəbəkə siyasətlərinin idarə olunmasını təşkil etmək üçün "qutudan çıxarılan" NetworkPolicy APImövcuddur. Bu qaynaq seçilmiş ad sahələrinə yayılır və bir tətbiqdən digərinə girişin ayrılması üçün qaydalar saxlayır. Həmçinin, müəyyən pod-lar, mühitlər (ad sahələri) və ya IP ünvanları arasında əlçatanlığı tənzimləməyə imkan verir:

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

Bu, şəbəkə siyasətinin işləmə məntiqini anlamaq istəməməyə səbəb ola biləcək çox sadə olmayan bir nümunədir. Ancaq yükləri şəbəkə siyasətləri vasitəsilə yönləndirmə prinsipləri və metodları başa düşməyə çalışacağıq... rəsmi sənədləşməyə Məntiqlidir ki, 2 tip trafik var: pod-a daxil olan (Ingress) və ondan çıxan (Egress).

Həqiqətən də, bu 2 kateqoriya hərəkət istiqamətinə görə ayrı-ayrılıqda şəbəkə siyasətini təşkil edir.

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Həqiqətən də, bu 2 kateqoriya hərəkət istiqamətinə görə bölünür.

Növbəti məcburi atribut seçicidir; tətbiq olunan qaydanın kiminə aid olduğunu göstərir. Bu, pod (və ya pod qrupları) ya da mühit ola bilər (yəni ad boşluğu). Vacib detal: bu obyektlərin hər ikisi etiket içerməlidir (etiket ) — məhz bunlar siyasətlərin işlədiyi terminologiyada Kubernetes-də.

Yalnızca müəyyən bir etiket ilə birləşdirilmiş seçicilərin son sayı ilə yanaşı, "Hər şeyi icazə ver / qadağan et" kimi müxtəlif variantlarda qaydalar yazmaq imkanı da var. Bunun üçün aşağıdakı strukturlar istifadə olunur:

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

— bu nümunədə mühitdəki bütün pod-ların daxil olan trafiki qadağandır. Əks hərəkətə belə bir quruluşla nail olmaq mümkündür:

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

Eynilə çıxan üçün:

  podSelector: {}
  policyTypes:
  - Egress

— onu deaktiv etmək üçün. Və aktiv etmək üçün belədir:

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

CNI-plugin seçiminə geri dönərək, qeyd etmək lazımdır ki, hər şəbəkə plugin-i NetworkPolicy ilə işləməyə imkan vermir. Məsələn, artıq qeyd olunan Flannel şəbəkə siyasətlərini konfiqurasiya edə bilmir, bu barədə rəsmi depozitorda açıq şəkildə qeyd olunur . Həmçinin alternativ — Açıq Mənbə layihəsi Calico, Kubernetes-in şəbəkə siyasətləri haqqında standart API zımbasının əhəmiyyətli dərəcədə genişləndirir.

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Calico ilə tanış olaq: nəzəriyyə

Calico plugin-i Flannel ilə inteqrasiya şəklində (alt layihə Canal) yaxud ayrıca istifadə oluna bilər, həm şəbəkə bağlılığını təmin edən funksiyaları, həm də əninə idarəetmə imkanlarını əhatə edir.

K8s-in "qutudan çıxmış" həllini və Calico-dan olan API zımbasını istifadə etmənin nələri təqdim etdiyini düşünək?

NetworkPolicy-də nələr var:

  • siyasətlər mühitlə məhdudlaşır;
  • siyasətlər etiketlərə işarələnmiş pod-lara tətbiq olunur;
  • qaydalar pod-lara, mühitlərə və ya alt şəbəkələrə tətbiq oluna bilər;
  • qaydalar protokollar, adlandırılmış və ya simvolik port göstərişlərini ehtiva edə bilər.

Calico bu funksiyaları necə artırır:

  • siyasətlər hər hansı bir obyektə tətbiq oluna bilər: pod, konteyner, virtual maşın və ya interfeys;
  • qaydalar konkret bir tədbiri (qadağa, icazə, qeyd etmək) ehtiva edə bilər;
  • qaydaların hədəfi və ya mənbəyi port, port aralığı, protokollar, HTTP və ya ICMP atributları, IP və ya alt şəbəkə (4 və ya 6 nəsil), hər hansı seçicilər (düyün, ev sahibi, mühit);
  • əlavə olaraq, DNAT parametrləri və trafikin keçirilməsi siyasətləri ilə trafikin keçirilməsini tənzimləmək olar.

Calico-nun GitHub’daki depozitindəki ilk komitələrin tarixi iyul 2016-cı ilə gedir və artıq bir il sonra layihə Kubernetes şəbəkə bağlılığında lider mövcudiyyət qazanmışdır — bunu, məsələn, The New Stack tərəfindən keçirilmiş sorğunun nəticələri göstərir, bu sorğu da:

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Bir çox böyük idarə olunan K8s həlləri, məsələn, Amazon EKS, Azure AKS, Google GKE və digərləri, onun istifadəsini tövsiyə etməyə başladılar.

Performans məsələsinə gəldikdə, hər şey mükəmməldir. Calico inkişaf komandası məhsulunu test edərkən 500 fiziki nodda 50000-dən çox konteyneri saniyədə 20 konteyner yarada biləcək şəkildə işə saldığını nümayiş etdirdi. Şkalalaşdırmada heç bir problem aşkar edilmədi. Bu cür nəticələr ilk versiya təqdimatı zamanı bəyan edilmişdi. Müstəqil tədqiqatlar, keçid qabiliyyəti və resurs istehlakının həcmini ölçən tədqiqatlar Calico-nun Flannel-a demək olar ki, bərabər performansını da təsdiq edir. Məsələn:

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Layihə çox sürətlə inkişaf edir, məşhur managed K8s, OpenShift, OpenStack həllərində dəstəklənir, Calico-nun klasterin yerləşdirilməsində istifadəsi mümkün olub kops, Service Mesh şəbəkələrinin yaradılması haqqında da məlumatlar var (bu, bir nümunədir Istio ilə birgə istifadənin).

Calico ilə praktikalar

Vanil Kubernetes-da CNI qurulması ümumiyyətlə aşağıdakı faylın tətbiqinə əsaslanır calico.yaml, rəsmi saytdan yüklənmişdir, kubectl apply -f.

Adətən, plugin-in cari versiyası Kubernetes-in son 2-3 versiyası ilə uyğun gəlir: daha köhnə versiyalarda işləməsi test edilmir və zəmanət verilmir. İnkişaf etdiricilərin bildirdiklərinə görə, Calico, CentOS 7, Ubuntu 16 ya da Debian 8 üzərində 3.10-dan yuxarı Linux kernelində işləyir, iptables ya da IPVS üzərində.

Mühit içində izolyasiya

Ümumi başa düşmək üçün şəbəkə siyasətinin Calico notasında standartlardan necə fərqləndiyini anlamaq üçün bir sadə vəziyyəti nəzərdən keçirək və qaydaların tərtib edilməsini necə asanlaşdırdığını başa düşək:

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Klasterdə 2 veb tətbiqi yerləşdirilib: biri Node.js, digəri PHP-dır, bunlardan biri Redis istifadə edir. PHP-dən Redis-ə girişi bağlayaraq, Node.js ilə əlaqəni saxlamaq üçün yalnız aşağıdakı siyasəti tətbiq etmək kifayətdir:

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

Əslində, Node.js-dən Redis portuna daxil olan trafiki icazə verdik. Və açıq şəkildə başqa şeylərə qadağa qoymadıq. NetworkPolicy meydana çıxdıqda, orada qeyd olunan bütün seletorlar izolyasiya olunmağa başlayır, əgər əksinə göstərilməyibsə. Eyni zamanda, izolyasiya qaydaları seletorla əhatə olunmayan digər obyektlərə tətbiq olunmur.

Nümunədə istifadə olunur apiVersion Kubernetes-dən "çıxan", amma Calico-nun təqdim etdiyi eyniadlı resursu istifadə etməyə heç bir əngəl yoxdur. Burada sintaksis daha genişdir, buna görə yuxarıda təsvir edilən halda qaydanı aşağıdakı şəkildə yenidən yazmaq lazım olacaq: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

Yuxarıda qeyd olunan adımlardan istifadə edərək, adi NetworkPolicy API vasitəsilə bütün trafikin icazə verilməsi və ya qadağan edilməsi üçün istifadə olunan strukturlar, başa düşülməsi və yadda saxlanması çətin olan parantezli qurğulardan ibarətdir. Calico ilə firewall qaydasının iş prinsipi əksinə dəyişmək üçün sadəcə action: Allow buna action: Deny.

Mühitə görə izolyasiya

İndi bir vəziyyəti təsəvvür edək, burada proqram, Prometheus-da toplanması və sonradan Grafana vasitəsilə analizi üçün biznes metrikaları yaradır. İxracatda, standart olaraq hamıya açıq olan həssas məlumatlar ola bilər. Bu məlumatları xarici gözlərdən qoruyuruq:

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Prometheus, ümumiyyətlə, ayrı bir xidmət mühitindədir - nümunədə bu, aşağıdakı növ namespace olacaq:

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

Alan metadata.labels burada təsadüfi deyil. Yuxarıda qeyd olunduğu kimi, namespaceSelector (kimi podSelector) etiketlərlə işləyir. Buna görə də, müəyyən bir portda bütün pod'lardan metrikaları almağa icazə vermək üçün, ya yeni bir etiket əlavə etməli (ya da mövcudlardan götürməli), daha sonra aşağıdakı konfiqurasiyanı tətbiq etməlisiniz:

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 siyasətləri təsviri üçün sintaksis isə belə olacaq:

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

Ümumiyyətlə, bu cür siyasətləri spesifik ehtiyaclar üçün əlavə etməklə, klasterdə olan tətbiqlərin işinə zərərli və ya təsadüfi müdaxilədən qorumaq mümkündür.

Calico yaradıcılığının fikrincə, 'Hər şeyi qadağan et və mütləq lazım olanları aç' yanaşması ən yaxşı təcrübədir, bu da rəsmi sənədləşməyə (həmçinin digər — xüsusilə, yuxarıda qeyd olunan məqalədə).

Calico-nun əlavə obyektlərinin tətbiqi

Xatırlatmaq istəyirəm ki, genişləndirilmiş API komplekti vasitəsilə Calico, pod'larla məhdudlaşmadan node-ların əlçatanlığını tənzimləməyə imkan verir. Aşağıdakı nümunədə GlobalNetworkPolicy klasterdə ICMP sorğularının keçməsini qadağan edir (məsələn, pod'dan node'a, pod'lardan arasında və ya node-dan pod IP-ə pinglər):

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

Yuxarıda göstərilən nümunədə, klaster node-ları arasında ICMP ilə 'əlaqə' qurma imkanı qalır. Bu məsələ isə GlobalNetworkPolicy, varlığın tətbiqinə yönlənmiş 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 ilə bağlı vəziyyət

Nəhayət, standart siyasətlərin kifayət etmədiyi klaster ətrafı qarşılıqlı əlaqə üçün Calico funksiyalarının istifadəsi ilə tam real bir nümunəni təqdim edirəm. Müştərilər veb tətbiqinə VPN tuneli vasitəsilə daxil olurlar və bu giriş ciddi şəkildə müəyyən edilmiş icazə verilmiş xidmətlər siyahısı ilə məhdudlaşdırılır:

Kubernetes-də şəbəkə üçün Calico: tanışlıq və bir az təcrübə

Müştərilər VPN-ə standart UDP 1194 portu vasitəsilə qoşulur və qoşularkən pod və xidmət klaster altşəbəkələrinə yol alır. Altşəbəkələr tamamilə təqdim edilir ki, serverlərin yenidən başladılması və adreslərin dəyişməsi zamanı xidmətlər itirilməsin.

Konfiqurasiyadakı port standartdır, bu, tətbiqin konfiqurasiyası və Kubernetes klasterinə köçürülməsi prosesinə müəyyən çətinliklər yaradır. Məsələn, eyni AWS LoadBalancer-i üçün UDP yalnız keçən ilin sonunda məhdud bölgələr siyahısında meydana çıxdı, NodePort-lardan istifadə edilə bilmir, çünki bunlar bütün klaster düyünlərinə yönləndirilir və server instansiyalarının sayını artırmaq üçün miqyası genişləndirmək mümkün deyil. Üstəlik, varsayılan olaraq seçilən portların diapazonunu dəyişmək məcburiyyətində qalacaqsınız...

Mümkün olan həllərin araşdırılması nəticəsində aşağıdakı seçim seçildi:

  1. VPN podları düyünə aşağıdakı rejimdə planlaşdırılır: hostNetwork, yəni faktiki IP üzərində.
  2. Xidmət, aşağıdakı vasitəsilə yerləşdirilir: ClusterIP. Düyündə, müəyyən şərtlərlə (şərti olaraq real IP-un olması) xaricdən əlçatan olan bir port açılır.
  3. Podun yerləşdiyi düyünü müəyyən etmək bizim hekayəmizin sərhədindən kənardadır. Yalnız onu qeyd edim ki, xidməti düyünə sərt bağlamaq və ya VPN xidmətinin aktiv IP ünvanını izləyən və müştərilərdə qeyd olunan DNS qeydlərini düzəldən kiçik bir sidecar xidmət yazmaq mümkündür — hər kəsin yaradıcılığına asılıdır.

Marşrutlaşdırma perspektivindən, VPN tərəfindən verilən IP ünvanı vasitəsilə müştəriyi dəqiq qeyd edə bilərik. Aşağıda — müştərinin yuxarıda qeyd olunmuş Redis xidmətlərinə girişini məhdudlaşdıran primitiv bir nümunə:

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]

Port 6379 is strictly prohibited, but the DNS service remains operational, which often suffers from rule configurations. As previously mentioned, when a selector appears, a restrictive policy is applied by default unless stated otherwise.

Yekunlar

Thus, with the extended Calico API, you can flexibly configure and dynamically change routing within the cluster and around it. Generally, its usage can seem like using a cannon to shoot sparrows, and implementing an L3 network with BGP and IP-IP tunnels looks monstrous in a simple Kubernetes installation on a flat network... However, the tool appears quite viable and useful otherwise.

Cluster isolation to meet security requirements cannot always be implemented, and it is in such situations that Calico (or similar solutions) comes to the rescue. The examples provided in the article (with some modifications) are used in several installations by our clients in AWS.

P.S.

Blogumuzda oxuyun:

Mənbə: habr.com

DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər 🔥 DDoS qoruması olan saytlara etibarlı hosting satın alın, VPS VDS serverlər | ProHoster