Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Makalenin amacı okuyucuya Kubernetes'te ağ oluşturma ve ağ politikalarını yönetmenin temellerinin yanı sıra standart yetenekleri genişleten üçüncü taraf Calico eklentisini tanıtmaktır. Yol boyunca, yapılandırma kolaylığı ve bazı özellikler, işletim deneyimimizden alınan gerçek örnekler kullanılarak gösterilecektir.

Kubernetes ağ cihazına hızlı bir giriş

Bir Kubernetes kümesi ağ olmadan hayal edilemez. Temelleri hakkında zaten materyaller yayınladık: “Kubernetes'te ağ oluşturmaya yönelik resimli bir kılavuz"Ve"Güvenlik Profesyonelleri için Kubernetes Ağ Politikalarına Giriş'.

Bu makale bağlamında, konteynerler ve düğümler arasındaki ağ bağlantısından K8s'in kendisinin sorumlu olmadığını belirtmek önemlidir: bunun için çeşitli CNI eklentileri (Konteyner Ağ Arayüzü). Bu konsept hakkında daha fazla bilgi bana da söylediler.

Örneğin bu eklentilerden en yaygın olanı flanel — her düğümdeki köprüleri yükselterek ve ona bir alt ağ atayarak tüm küme düğümleri arasında tam ağ bağlantısı sağlar. Ancak tam ve düzenlenmemiş erişilebilirlik her zaman faydalı değildir. Kümede bir nevi minimal izolasyon sağlamak için güvenlik duvarının konfigürasyonuna müdahale etmek gerekir. Genel durumda, aynı CNI'nin kontrolü altındadır, bu nedenle iptables'a yapılan üçüncü taraf müdahaleleri yanlış yorumlanabilir veya tamamen göz ardı edilebilir.

Ve bir Kubernetes kümesinde ağ politikası yönetimini düzenlemek için "kutudan çıktığı gibi" sağlanır Ağ Politikası API'si. Seçilen ad alanlarına dağıtılan bu kaynak, bir uygulamadan diğerine erişimi farklılaştıracak kurallar içerebilir. Ayrıca belirli bölmeler, ortamlar (ad alanları) veya IP adresi blokları arasındaki erişilebilirliği yapılandırmanıza da olanak tanır:

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 en ilkel örnek değil resmi belgeler ağ politikalarının nasıl çalıştığının mantığını anlama isteğini kesin olarak caydırabilir. Ancak yine de ağ politikalarını kullanarak trafik akışlarını işlemenin temel ilkelerini ve yöntemlerini anlamaya çalışacağız...

2 tür trafik olması mantıklıdır: bölmeye girme (Giriş) ve bölmeden çıkış (Çıkış).

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Aslında siyaset hareket yönüne göre bu 2 kategoriye ayrılır.

Bir sonraki gerekli özellik bir seçicidir; kuralın kendisine uygulandığı kişi. Bu bir bölme (veya bir bölme grubu) veya bir ortam (ör. bir ad alanı) olabilir. Önemli bir ayrıntı: Bu nesnelerin her iki türü de bir etiket içermelidir (etiket Kubernetes terminolojisinde) - bunlar politikacıların birlikte çalıştığı kişilerdir.

Bir tür etiketle birleştirilen sınırlı sayıda seçicinin yanı sıra, “Her şeye/herkese izin ver/reddet” gibi kuralların farklı varyasyonlarda yazılması da mümkün. Bu amaçla formun yapıları kullanılır:

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

— bu örnekte ortamdaki tüm bölmelerin gelen trafiğe erişimi engellenmiştir. Aşağıdaki yapıyla tam tersi davranış elde edilebilir:

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

Benzer şekilde gidenler için:

  podSelector: {}
  policyTypes:
  - Egress

- kapatmak için. Ve işte şunları eklemelisiniz:

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

Bir küme için CNI eklentisi seçimine dönersek şunu belirtmekte fayda var: her ağ eklentisi NetworkPolicy'yi desteklemez. Örneğin, daha önce bahsedilen Flannel, ağ politikalarının nasıl yapılandırılacağını bilmiyor; doğrudan söylendi resmi depoda. Burada bir alternatiften de bahsediliyor: Açık Kaynak projesi patiskaAğ politikaları açısından standart Kubernetes API kümesini önemli ölçüde genişleten.

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Calico'yu tanımak: teori

Calico eklentisi Flannel (alt proje) ile entegre olarak kullanılabilir. Kanal) veya bağımsız olarak hem ağ bağlantısını hem de kullanılabilirlik yönetimi özelliklerini kapsar.

K8'in “kutulu” çözümünü ve Calico'nun API setini kullanmak ne gibi fırsatlar sağlar?

NetworkPolicy'de yerleşik olanlar şunlardır:

  • politikacılar çevreyle sınırlıdır;
  • politikalar etiketlerle işaretlenmiş bölmelere uygulanır;
  • kurallar bölmelere, ortamlara veya alt ağlara uygulanabilir;
  • kurallar protokoller, adlandırılmış veya sembolik bağlantı noktası özellikleri içerebilir.

Calico'nun bu işlevleri nasıl genişlettiği aşağıda açıklanmıştır:

  • ilkeler herhangi bir nesneye uygulanabilir: bölme, kapsayıcı, sanal makine veya arayüz;
  • kurallar belirli bir eylemi içerebilir (yasaklama, izin, günlüğe kaydetme);
  • kuralların hedefi veya kaynağı bir bağlantı noktası, bir dizi bağlantı noktası, protokol, HTTP veya ICMP öznitelikleri, IP veya alt ağ (4. veya 6. nesil), herhangi bir seçici (düğümler, ana bilgisayarlar, ortamlar) olabilir;
  • Ayrıca DNAT ayarlarını ve trafik yönlendirme politikalarını kullanarak trafiğin geçişini düzenleyebilirsiniz.

Calico deposundaki GitHub'a ilişkin ilk taahhütler Temmuz 2016'ya kadar uzanıyor ve bir yıl sonra proje Kubernetes ağ bağlantısının düzenlenmesinde lider bir konuma geldi - bu, örneğin anket sonuçlarıyla kanıtlanıyor, The New Stack tarafından yürütülen:

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

K8'lerle birçok büyük yönetilen çözüm, örneğin Amazon EKS'si, Azure AKS'si, Google GKE ve diğerleri bunu kullanılmasını tavsiye etmeye başladı.

Performansa gelince, burada her şey harika. Calico geliştirme ekibi, ürünlerini test ederken, saniyede 50000 konteyner oluşturma hızıyla 500 fiziksel düğümde 20'den fazla konteyner çalıştırarak astronomik bir performans gösterdi. Ölçeklendirmede herhangi bir sorun tespit edilmedi. Bu tür sonuçlar duyuruldu zaten ilk versiyonun duyurusunda. Verim ve kaynak tüketimine odaklanan bağımsız çalışmalar da Calico'nun performansının neredeyse Flannel'inki kadar iyi olduğunu doğruluyor. Örneğin:

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Proje çok hızlı gelişiyor, K8'ler, OpenShift, OpenStack tarafından yönetilen popüler çözümlerde çalışmayı destekliyor, bir kümeyi dağıtırken Calico'yu kullanmak mümkün. kop, Service Mesh ağlarının oluşturulmasına ilişkin referanslar vardır (İşte bir örnek Istio ile birlikte kullanılır).

Calico ile pratik yapın

Genel olarak Vanilya Kubernetes'in kullanılması durumunda, CNI'nın kurulumu dosyayı kullanmaya gelir. calico.yaml, resmi web sitesinden indirildiс помощью kubectl apply -f.

Kural olarak, eklentinin mevcut sürümü Kubernetes'in en son 2-3 sürümüyle uyumludur: eski sürümlerde çalışması test edilmemiştir ve garanti edilmemektedir. Geliştiricilere göre Calico, iptables veya IPVS'nin yanı sıra CentOS 3.10, Ubuntu 7 veya Debian 16 çalıştıran 8'un üzerindeki Linux çekirdeklerinde çalışıyor.

Ortamda izolasyon

Genel bir anlayış sağlamak amacıyla Calico gösterimindeki ağ politikalarının standart politikalardan ne kadar farklı olduğunu ve kural oluşturma yaklaşımının kuralların okunabilirliğini ve yapılandırma esnekliğini nasıl basitleştirdiğini anlamak için basit bir örneğe bakalım:

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Kümede dağıtılan 2 web uygulaması vardır: Node.js ve PHP'de, bunlardan biri Redis'i kullanıyor. Node.js ile bağlantıyı korurken PHP'den Redis'e erişimi engellemek için aşağıdaki politikayı uygulamanız yeterlidir:

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

Temel olarak Node.js'den Redis bağlantı noktasına gelen trafiğe izin verdik. Ve açıkça başka hiçbir şeyi yasaklamadılar. NetworkPolicy belirir belirmez, aksi belirtilmedikçe, içinde bahsedilen tüm seçiciler yalıtılmaya başlar. Ancak izolasyon kuralları seçicinin kapsamadığı diğer nesnelere uygulanmaz.

Örnek şunu kullanır: apiVersion Kubernet'ler kullanıma hazır ancak hiçbir şey onu kullanmanızı engellemiyor Calico teslimatından aynı adı taşıyan kaynak. Buradaki sözdizimi daha ayrıntılı olduğundan yukarıdaki durum için kuralı aşağıdaki biçimde yeniden yazmanız gerekecektir:

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

Normal NetworkPolicy API'si üzerinden tüm trafiğe izin vermek veya trafiği reddetmek için yukarıda belirtilen yapılar, anlaşılması ve hatırlanması zor olan parantezli yapılar içerir. Calico durumunda, bir güvenlik duvarı kuralının mantığını tersine değiştirmek için, yalnızca action: Allow üzerinde action: Deny.

Çevreye göre izolasyon

Şimdi bir uygulamanın Prometheus'ta toplama ve Grafana kullanarak daha fazla analiz için iş ölçümleri oluşturduğu bir durumu hayal edin. Yükleme, varsayılan olarak yine herkese açık olarak görüntülenebilen hassas veriler içerebilir. Bu verileri meraklı gözlerden saklayalım:

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

Prometheus, kural olarak ayrı bir hizmet ortamına yerleştirilir; örnekte, şöyle bir ad alanı olacaktır:

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

Tarla metadata.labels bunun bir tesadüf olmadığı ortaya çıktı. Yukarıda belirtildiği gibi, namespaceSelector (birlikte podSelector) etiketlerle çalışır. Bu nedenle, belirli bir bağlantı noktasındaki tüm bölmelerden metriklerin alınmasına izin vermek için bir tür etiket eklemeniz (veya mevcut olanlardan almanız) ve ardından aşağıdaki gibi bir yapılandırma uygulamanız gerekir:

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 politikalarını kullanırsanız sözdizimi şu şekilde olacaktır:

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

Genel olarak belirli ihtiyaçlara yönelik bu tür politikaları ekleyerek, kümedeki uygulamaların çalışmasına kötü niyetli veya kazara müdahaleye karşı koruma sağlayabilirsiniz.

Calico'nun yaratıcılarına göre en iyi uygulama, şu belgede belgelenen "Her şeyi engelleyin ve ihtiyacınız olanı açıkça açın" yaklaşımıdır. resmi belgeler (diğerleri de benzer bir yaklaşım izliyor - özellikle daha önce bahsedilen makale).

Ek Calico Nesnelerini Kullanma

Genişletilmiş Calico API seti aracılığıyla, kapsüllerle sınırlı değil, düğümlerin kullanılabilirliğini düzenleyebileceğinizi hatırlatmama izin verin. Aşağıdaki örnekte kullanılarak GlobalNetworkPolicy kümedeki ICMP isteklerini iletme yeteneği kapalıdır (örneğin, bir bölmeden bir düğüme, bölmeler arasında veya bir düğümden bir IP bölmesine pingler):

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

Yukarıdaki durumda, küme düğümlerinin ICMP aracılığıyla birbirlerine "ulaşması" hâlâ mümkündür. Ve bu sorun şu şekilde çözüldü: GlobalNetworkPolicy, bir varlığa uygulanan 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 Davası

Son olarak, standart bir dizi politikanın yeterli olmadığı durumlarda, kümeye yakın etkileşim durumunda Calico işlevlerinin kullanımına ilişkin çok gerçek bir örnek vereceğim. İstemciler web uygulamasına erişmek için bir VPN tüneli kullanır ve bu erişim sıkı bir şekilde kontrol edilir ve kullanımına izin verilen belirli bir hizmet listesiyle sınırlıdır:

Kubernetes'te ağ oluşturmak için Calico: giriş ve küçük bir deneyim

İstemciler VPN'ye standart UDP bağlantı noktası 1194 aracılığıyla bağlanır ve bağlandıklarında bölmelerin ve hizmetlerin küme alt ağlarına giden yolları alır. Yeniden başlatmalar ve adres değişiklikleri sırasında hizmetlerin kaybedilmemesi için alt ağların tamamı itilir.

Yapılandırmadaki bağlantı noktası standarttır ve bu, uygulamanın yapılandırılması ve Kubernetes kümesine aktarılması sürecine bazı nüanslar getirir. Örneğin, aynı AWS'de UDP için LoadBalancer tam anlamıyla geçen yılın sonunda sınırlı bir bölge listesinde göründü ve NodePort, tüm küme düğümlerine iletilmesi nedeniyle kullanılamaz ve sunucu örneklerinin sayısını ölçeklendirmek imkansızdır. hata toleransı amaçları. Ayrıca, varsayılan bağlantı noktası aralığını da değiştirmeniz gerekecektir...

Olası çözümlerin araştırılması sonucunda aşağıdakiler seçildi:

  1. VPN'li bölmeler düğüm başına planlanır hostNetworkyani gerçek IP'ye.
  2. Hizmet dışarıda yayınlanır. ClusterIP. Düğüme, dışarıdan küçük rezervasyonlarla (gerçek bir IP adresinin koşullu varlığı) erişilebilen bir bağlantı noktası fiziksel olarak kurulur.
  3. Kapsülün yükseldiği düğüm noktasını belirlemek hikayemizin kapsamı dışındadır. Sadece, hizmeti bir düğüme bağlayabileceğinizi veya VPN hizmetinin mevcut IP adresini izleyecek ve istemcilerde kayıtlı DNS kayıtlarını - kimin yeterli hayal gücü varsa - düzenleyecek küçük bir sepet hizmeti yazabileceğinizi söyleyeceğim.

Yönlendirme açısından bakıldığında, bir VPN istemcisini, VPN sunucusu tarafından verilen IP adresine göre benzersiz bir şekilde tanımlayabiliriz. Aşağıda, yukarıda bahsedilen Redis'te gösterilen, böyle bir müşterinin hizmetlere erişimini kısıtlamanın ilkel bir örneği verilmiştir:

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]

Burada, 6379 numaralı bağlantı noktasına bağlanmak kesinlikle yasaktır, ancak aynı zamanda, kurallar hazırlanırken işleyişi sıklıkla zarar gören DNS hizmetinin çalışması da korunur. Çünkü daha önce de belirttiğimiz gibi bir seçici göründüğünde, aksi belirtilmediği sürece ona varsayılan reddetme politikası uygulanır.

sonuçlar

Böylece Calico'nun gelişmiş API'sini kullanarak küme içindeki ve çevresindeki yönlendirmeyi esnek bir şekilde yapılandırabilir ve dinamik olarak değiştirebilirsiniz. Genel olarak, kullanımı serçeleri topla vurmak gibi görünebilir ve BGP ve IP-IP tünelleriyle bir L3 ağının uygulanması, düz bir ağ üzerinde basit bir Kubernetes kurulumunda korkunç görünüyor... Bununla birlikte, aksi takdirde araç oldukça uygulanabilir ve kullanışlı görünüyor .

Güvenlik gereksinimlerini karşılamak için bir kümeyi izole etmek her zaman mümkün olmayabilir ve Calico'nun (veya benzer bir çözümün) kurtarmaya geldiği yer burasıdır. Bu makalede verilen örnekler (küçük değişikliklerle birlikte) müşterilerimizin AWS'deki çeşitli kurulumlarında kullanılmaktadır.

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle