كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

الغرض من هذه المقالة هو تعريف القارئ بأساسيات الشبكات وإدارة سياسات الشبكة في Kubernetes، بالإضافة إلى البرنامج الإضافي Calico التابع لجهة خارجية والذي يعمل على توسيع الإمكانات القياسية. على طول الطريق، سيتم توضيح سهولة التكوين وبعض الميزات باستخدام أمثلة حقيقية من تجربة التشغيل لدينا.

مقدمة سريعة لجهاز الشبكات Kubernetes

لا يمكن تصور مجموعة Kubernetes بدون شبكة. لقد قمنا بالفعل بنشر مواد حول أساسياتها: "دليل مصور للتواصل في Kubernetes"و"مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان".

في سياق هذه المقالة، من المهم ملاحظة أن K8s نفسها ليست مسؤولة عن اتصال الشبكة بين الحاويات والعقد: ولهذا الغرض، هناك العديد من الإضافات CNI (واجهة شبكة الحاويات). المزيد عن هذا المفهوم نحن قالوا لي أيضا.

على سبيل المثال، الأكثر شيوعا من هذه الإضافات هو الفانيلي — يوفر اتصالاً كاملاً بالشبكة بين جميع عقد المجموعة عن طريق رفع الجسور على كل عقدة، وتعيين شبكة فرعية لها. ومع ذلك، فإن الوصول الكامل وغير المنظم ليس مفيدًا دائمًا. لتوفير نوع من الحد الأدنى من العزلة في المجموعة، من الضروري التدخل في تكوين جدار الحماية. في الحالة العامة، يتم وضعها تحت سيطرة نفس CNI، ولهذا السبب يمكن تفسير أي تدخلات من طرف ثالث في iptables بشكل غير صحيح أو تجاهلها تمامًا.

ويتم توفير "خارج الصندوق" لتنظيم إدارة سياسة الشبكة في مجموعة Kubernetes واجهة برمجة تطبيقات سياسة الشبكة. قد يحتوي هذا المورد، الموزع على مساحات أسماء محددة، على قواعد لتمييز الوصول من تطبيق إلى آخر. كما يسمح لك أيضًا بتكوين إمكانية الوصول بين وحدات أو بيئات (مساحات أسماء) محددة أو مجموعات من عناوين IP:

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

هذا ليس المثال الأكثر بدائية الوثائق الرسمية قد يثبط مرة واحدة وإلى الأبد الرغبة في فهم منطق كيفية عمل سياسات الشبكة. ومع ذلك، سنظل نحاول فهم المبادئ والأساليب الأساسية لمعالجة تدفقات حركة المرور باستخدام سياسات الشبكة...

من المنطقي أن يكون هناك نوعان من حركة المرور: الدخول إلى الكبسولة (الدخول) والخروج منها (الخروج).

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

في الواقع، تنقسم السياسة إلى هاتين الفئتين بناءً على اتجاه الحركة.

السمة المطلوبة التالية هي محدد؛ الذي تنطبق عليه القاعدة. يمكن أن يكون هذا حجرة (أو مجموعة من القرون) أو بيئة (أي مساحة اسم). تفصيل مهم: يجب أن يحتوي كلا النوعين من هذه الكائنات على ملصق (ملصق في مصطلحات Kubernetes) - هؤلاء هم الذين يعمل معهم السياسيون.

بالإضافة إلى العدد المحدود من المحددات الموحدة بواسطة نوع ما من التصنيفات، من الممكن كتابة قواعد مثل "السماح/رفض كل شيء/الجميع" بأشكال مختلفة. لهذا الغرض، يتم استخدام إنشاءات النموذج:

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

- في هذا المثال، يتم حظر جميع البودات الموجودة في البيئة من حركة المرور الواردة. يمكن تحقيق السلوك المعاكس من خلال البناء التالي:

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

وبالمثل بالنسبة للصادرة:

  podSelector: {}
  policyTypes:
  - Egress

- لإيقاف تشغيله. وإليك ما يجب تضمينه:

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

بالعودة إلى اختيار مكون CNI الإضافي للمجموعة، تجدر الإشارة إلى ذلك لا يدعم كل مكون إضافي للشبكة سياسة الشبكة. على سبيل المثال، لا يعرف Flannel المذكور بالفعل كيفية تكوين سياسات الشبكة، والتي يقال مباشرة في المستودع الرسمي . تم ذكر البديل أيضًا هناك - مشروع مفتوح المصدر كاليكو، والذي يوسع بشكل كبير المجموعة القياسية لواجهات برمجة تطبيقات Kubernetes من حيث سياسات الشبكة.

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

التعرف على كاليكو: النظرية

يمكن استخدام البرنامج الإضافي Calico بالتكامل مع Flannel (المشروع الفرعي قناة) أو بشكل مستقل، يغطي كلاً من إمكانيات الاتصال بالشبكة وإدارة التوفر.

ما هي الفرص التي يوفرها استخدام حل K8s "المعبأ" ومجموعة واجهة برمجة التطبيقات من كاليكو؟

إليك ما تم تضمينه في NetworkPolicy:

  • السياسيون مقيدون بالبيئة.
  • يتم تطبيق السياسات على القرون المميزة بالملصقات؛
  • يمكن تطبيق القواعد على القرون أو البيئات أو الشبكات الفرعية؛
  • يمكن أن تحتوي القواعد على بروتوكولات أو مواصفات منفذ مسماة أو رمزية.

وإليك كيفية توسيع كاليكو لهذه الوظائف:

  • يمكن تطبيق السياسات على أي كائن: حاوية أو حاوية أو جهاز افتراضي أو واجهة؛
  • يمكن أن تحتوي القواعد على إجراء محدد (حظر، إذن، تسجيل)؛
  • يمكن أن يكون الهدف أو مصدر القواعد منفذًا، أو مجموعة من المنافذ، أو البروتوكولات، أو سمات HTTP أو ICMP، أو IP أو الشبكة الفرعية (الجيل الرابع أو السادس)، أو أي محددات (العقد، المضيفين، البيئات)؛
  • بالإضافة إلى ذلك، يمكنك تنظيم مرور حركة المرور باستخدام إعدادات DNAT وسياسات إعادة توجيه حركة المرور.

يعود تاريخ الالتزام الأول على GitHub في مستودع Calico إلى يوليو 2016، وبعد مرور عام، احتل المشروع مكانة رائدة في تنظيم اتصال شبكة Kubernetes - ويتجلى ذلك، على سبيل المثال، في نتائج الاستطلاع، أجراه The New Stack:

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

العديد من الحلول المُدارة الكبيرة مع K8s، مثل أمازون EKS, أزور AKS, جوجل جي كي إي وبدأ آخرون في التوصية باستخدامه.

أما بالنسبة للأداء، فكل شيء رائع هنا. أثناء اختبار منتجهم، أظهر فريق تطوير Calico أداءً فلكيًا، حيث قام بتشغيل أكثر من 50000 حاوية على 500 عقدة فعلية بمعدل إنشاء 20 حاوية في الثانية. لم يتم تحديد أي مشاكل مع التحجيم. مثل هذه النتائج تم الإعلان عن بالفعل عند الإعلان عن النسخة الأولى. تؤكد الدراسات المستقلة التي تركز على الإنتاجية واستهلاك الموارد أيضًا أن أداء كاليكو يكاد يكون جيدًا مثل أداء فلانيل. مثلا:

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

يتطور المشروع بسرعة كبيرة، وهو يدعم العمل في الحلول الشائعة المُدارة K8s وOpenShift وOpenStack، ومن الممكن استخدام Calico عند نشر مجموعة باستخدام ركلة، هناك إشارات إلى بناء شبكات شبكة الخدمة (هنا مثال تستخدم بالتزامن مع Istio).

تدرب مع كاليكو

في الحالة العامة لاستخدام Vanilla Kubernetes، فإن تثبيت CNI يعني استخدام الملف calico.yaml, تحميلها من الموقع الرسمي، عبر kubectl apply -f.

كقاعدة عامة، يتوافق الإصدار الحالي من البرنامج الإضافي مع أحدث 2-3 إصدارات من Kubernetes: لم يتم اختبار التشغيل في الإصدارات الأقدم وليس مضمونًا. وفقًا للمطورين، يعمل Calico على نواة Linux أعلى من 3.10 ويعمل بنظام CentOS 7 أو Ubuntu 16 أو Debian 8، بالإضافة إلى iptables أو IPVS.

العزلة داخل البيئة

للحصول على فهم عام، دعونا نلقي نظرة على حالة بسيطة لفهم كيفية اختلاف سياسات الشبكة في تدوين كاليكو عن السياسات القياسية وكيف يعمل النهج المتبع في إنشاء القواعد على تبسيط سهولة القراءة ومرونة التكوين:

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

يوجد تطبيقان للويب منتشران في المجموعة: في Node.js وPHP، أحدهما يستخدم Redis. لمنع الوصول إلى Redis من PHP، مع الحفاظ على الاتصال مع Node.js، ما عليك سوى تطبيق السياسة التالية:

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

لقد سمحنا بشكل أساسي بحركة المرور الواردة إلى منفذ Redis من Node.js. ومن الواضح أنهم لم يحظروا أي شيء آخر. بمجرد ظهور NetworkPolicy، يبدأ عزل كافة المحددات المذكورة فيه، ما لم يتم تحديد خلاف ذلك. ومع ذلك، لا تنطبق قواعد العزل على الكائنات الأخرى التي لا يغطيها المحدد.

يستخدم المثال apiVersion Kubernetes خارج الصندوق، لكن لا شيء يمنعك من استخدامه مورد يحمل نفس الاسم من تسليم كاليكو. بناء الجملة هناك أكثر تفصيلا، لذلك سوف تحتاج إلى إعادة كتابة القاعدة للحالة المذكورة أعلاه في النموذج التالي:

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

تحتوي التركيبات المذكورة أعلاه للسماح أو رفض كل حركة المرور من خلال واجهة برمجة تطبيقات NetworkPolicy العادية على بنيات ذات أقواس يصعب فهمها وتذكرها. في حالة كاليكو، لتغيير منطق قاعدة جدار الحماية إلى العكس، ما عليك سوى التغيير action: Allow في action: Deny.

العزلة عن طريق البيئة

تخيل الآن موقفًا يقوم فيه أحد التطبيقات بإنشاء مقاييس أعمال لتجميعها في Prometheus وإجراء مزيد من التحليل باستخدام Grafana. قد يحتوي التحميل على بيانات حساسة، والتي يمكن عرضها بشكل عام مرة أخرى بشكل افتراضي. دعونا نخفي هذه البيانات عن أعين المتطفلين:

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

يتم وضع بروميثيوس، كقاعدة عامة، في بيئة خدمة منفصلة - في المثال ستكون مساحة الاسم كما يلي:

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

حقل metadata.labels تبين أن هذا ليس من قبيل الصدفة. كما ذكر أعلاه، namespaceSelector (إلى جانب podSelector) يعمل مع التسميات. لذلك، للسماح بأخذ المقاييس من جميع البودات الموجودة على منفذ معين، سيتعين عليك إضافة نوع من التصنيفات (أو أخذها من التصنيفات الموجودة)، ثم تطبيق تكوين مثل:

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

وإذا كنت تستخدم سياسات كاليكو، فإن بناء الجملة سيكون مثل هذا:

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

بشكل عام، من خلال إضافة هذه الأنواع من السياسات لاحتياجات محددة، يمكنك الحماية من التدخل الضار أو العرضي في تشغيل التطبيقات في المجموعة.

أفضل الممارسات، وفقًا لمنشئي كاليكو، هي نهج "حظر كل شيء وفتح ما تحتاجه بشكل صريح"، الموثق في الوثائق الرسمية (يتبع آخرون نهجا مماثلا - على وجه الخصوص، في المادة المذكورة بالفعل).

استخدام كائنات كاليكو إضافية

اسمحوا لي أن أذكركم أنه من خلال المجموعة الموسعة من واجهات برمجة تطبيقات Calico، يمكنك تنظيم مدى توفر العقد، وليس يقتصر على القرون. في المثال التالي باستخدام GlobalNetworkPolicy تم إغلاق القدرة على تمرير طلبات ICMP في المجموعة (على سبيل المثال، أوامر ping من حاوية إلى عقدة، أو بين الحاويات، أو من عقدة إلى حاوية 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

في الحالة المذكورة أعلاه، لا يزال من الممكن لعقد المجموعة "التواصل" مع بعضها البعض عبر ICMP. ويتم حل هذه المشكلة بالوسائل GlobalNetworkPolicy، تنطبق على كيان 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

أخيرًا، سأقدم مثالًا حقيقيًا جدًا لاستخدام وظائف كاليكو في حالة التفاعل بالقرب من المجموعة، عندما لا تكون مجموعة السياسات القياسية كافية. للوصول إلى تطبيق الويب، يستخدم العملاء نفق VPN، ويتم التحكم في هذا الوصول بإحكام ويقتصر على قائمة محددة من الخدمات المسموح باستخدامها:

كاليكو للتواصل في Kubernetes: مقدمة وقليل من الخبرة

يتصل العملاء بشبكة VPN عبر منفذ UDP القياسي 1194، وعند الاتصال، يتلقون مسارات إلى الشبكات الفرعية للمجموعة من القرون والخدمات. يتم دفع الشبكات الفرعية بالكامل حتى لا تفقد الخدمات أثناء إعادة التشغيل وتغييرات العناوين.

المنفذ في التكوين قياسي، مما يفرض بعض الفروق الدقيقة في عملية تكوين التطبيق ونقله إلى مجموعة Kubernetes. على سبيل المثال، في نفس AWS LoadBalancer لـ UDP، ظهر حرفيًا في نهاية العام الماضي في قائمة محدودة من المناطق، ولا يمكن استخدام NodePort بسبب إعادة توجيهه على جميع عقد المجموعة ومن المستحيل قياس عدد مثيلات الخادم لـ أغراض التسامح مع الخطأ. بالإضافة إلى ذلك، سيتعين عليك تغيير النطاق الافتراضي للمنافذ...

ونتيجة البحث عن الحلول الممكنة تم اختيار ما يلي:

  1. تتم جدولة البودات المزودة بـ VPN لكل عقدة hostNetwork، وهذا هو، إلى IP الفعلي.
  2. يتم نشر الخدمة في الخارج من خلال ClusterIP. يتم تثبيت المنفذ فعليًا على العقدة، ويمكن الوصول إليه من الخارج مع حجوزات بسيطة (الوجود المشروط لعنوان IP الحقيقي).
  3. تحديد العقدة التي ارتفعت عليها الكبسولة هو خارج نطاق قصتنا. سأقول فقط أنه يمكنك "تثبيت" الخدمة بإحكام على عقدة أو كتابة خدمة جانبية صغيرة تراقب عنوان IP الحالي لخدمة VPN وتحرير سجلات DNS المسجلة لدى العملاء - من لديه ما يكفي من الخيال.

من منظور التوجيه، يمكننا تحديد عميل VPN بشكل فريد من خلال عنوان IP الخاص به الصادر عن خادم VPN. فيما يلي مثال بدائي لتقييد وصول هذا العميل إلى الخدمات، كما هو موضح في 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]

هنا يُمنع منعًا باتًا الاتصال بالمنفذ 6379، ولكن في نفس الوقت يتم الحفاظ على تشغيل خدمة DNS، والتي غالبًا ما يتأثر عملها عند وضع القواعد. لأنه، كما ذكرنا سابقًا، عندما يظهر محدد، يتم تطبيق سياسة الرفض الافتراضية عليه ما لم يتم تحديد خلاف ذلك.

نتائج

وبالتالي، باستخدام واجهة برمجة التطبيقات المتقدمة الخاصة بـ Calico، يمكنك تكوين التوجيه وتغييره ديناميكيًا داخل المجموعة وحولها بمرونة. بشكل عام، يمكن أن يبدو استخدامه مثل إطلاق النار على العصافير بمدفع، ويبدو تنفيذ شبكة L3 باستخدام أنفاق BGP وIP-IP أمرًا وحشيًا في تثبيت Kubernetes بسيط على شبكة مسطحة... ومع ذلك، تبدو الأداة قابلة للحياة ومفيدة تمامًا .

قد لا يكون عزل مجموعة لتلبية متطلبات الأمان ممكنًا دائمًا، وهنا يأتي دور كاليكو (أو حل مشابه) للإنقاذ. يتم استخدام الأمثلة الواردة في هذه المقالة (مع تعديلات طفيفة) في العديد من عمليات التثبيت لعملائنا في AWS.

PS

اقرأ أيضًا على مدونتنا:

المصدر: www.habr.com

إضافة تعليق