مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

ملحوظة. ترجمة.: مؤلف المقال - Reuven Harrison - لديه أكثر من 20 عامًا من الخبرة في تطوير البرمجيات ، وهو اليوم كبير التكنولوجيا والمؤسس المشارك لشركة Tufin ، وهي شركة حلول إدارة السياسات الأمنية. بينما يعتبر سياسات شبكة Kubernetes قوية بما يكفي لتقسيم الشبكة في مجموعة ، إلا أنه يعتقد أيضًا أنه ليس من السهل تنفيذها في الممارسة العملية. تهدف هذه المادة (الضخمة إلى حد ما) إلى تحسين وعي المتخصصين في هذا الأمر ومساعدتهم في إنشاء التكوينات اللازمة.

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

بالنسبة لمحترفي الأمن الذين حيرتهم العمل مع Kubernetes ، يمكن أن تكون السياسة الافتراضية لهذا النظام الأساسي اكتشافًا حقيقيًا: السماح بكل شيء.

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

سياسات شبكة Kubernetes

تتيح لك آلية سياسة شبكة Kubernetes إدارة تفاعل التطبيقات الموزعة على النظام الأساسي في طبقة الشبكة (الثالثة في نموذج OSI). تفتقر سياسات الشبكة إلى بعض الميزات المتقدمة لجدران الحماية الحديثة ، مثل التحكم في طبقة OSI 7 واكتشاف التهديدات ، ولكنها توفر طبقة أساسية من أمان الشبكة تمثل نقطة انطلاق جيدة.

تتحكم سياسات الشبكة في الاتصالات بين الكبسولات

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

تحديد سياسات الشبكة

مثل موارد Kubernetes الأخرى ، يتم تعيين سياسات الشبكة في YAML. في المثال أدناه ، التطبيق balance يفتح الوصول إلى postgres:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: balance
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

(ملحوظة. ترجمة.: لم يتم إنشاء لقطة الشاشة هذه ، مثل جميع لقطات الشاشة المماثلة اللاحقة ، باستخدام أدوات Kubernetes الأصلية ، ولكن باستخدام أداة Tufin Orca ، التي طورتها شركة مؤلف المقالة الأصلية والمذكورة في نهاية المادة.)

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

بعد وصف السياسة في YAML ، استخدم kubectlلإنشائه في الكتلة:

kubectl create -f policy.yaml

مواصفات نهج الشبكة

تتضمن مواصفات سياسة شبكة Kubernetes أربعة عناصر:

  1. podSelector: يحدد القرون المتأثرة بهذه السياسة (الأهداف) - مطلوب ؛
  2. policyTypes: يشير إلى أنواع السياسات المضمنة في هذا: الدخول و / أو الخروج - اختياري ، لكني أوصي بتحديده صراحة في جميع الحالات ؛
  3. ingress: يعرّف المسموح به الوارد حركة المرور لاستهداف القرون - اختياري ؛
  4. egress: يعرّف المسموح به منفتح حركة المرور من القرون المستهدفة اختيارية.

مثال مستعار من موقع Kubernetes (استبدلت role في app) ، يوضح كيفية استخدام العناصر الأربعة جميعها:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: 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، يمكن استخدام باقي المعلمات حسب الرغبة.

إذا أهملت policyTypes، سيتم تفسير السياسة على النحو التالي:

  • من المفترض بشكل افتراضي تحديد جانب الدخول. إذا كانت السياسة لا تشير صراحةً إلى ذلك ، فسيفترض النظام أن كل حركة المرور محظورة.
  • سيتم تحديد السلوك على جانب الخروج من خلال وجود أو عدم وجود معلمة الخروج المقابلة.

لتجنب الأخطاء ، أوصي كن صريحًا دائمًا policyTypes.

حسب المنطق أعلاه ، في حالة المعلمات ingress و / أو egress إذا تم حذفها ، سترفض السياسة كل حركة المرور (راجع "قاعدة المسح" أدناه).

السياسة الافتراضية - السماح

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

مساحات الأسماء

مساحات الأسماء هي آلية تعاون Kubernetes. وهي مصممة لعزل البيئات المنطقية عن بعضها البعض ، مع السماح بالاتصال بين المسافات افتراضيًا.

مثل معظم مكونات Kubernetes ، تعيش سياسات الشبكة في مساحة اسم محددة. في الكتلة metadata يمكنك تحديد المساحة التي تنتمي إليها السياسة:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

إذا لم يتم تحديد مساحة الاسم بشكل صريح في البيانات الوصفية ، فسيستخدم النظام مساحة الاسم المحددة في kubectl (افتراضي namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

أنا أوصي حدد مساحة الاسم بشكل صريح، إلا إذا كنت تكتب سياسة تستهدف مساحات أسماء متعددة في وقت واحد.

الرئيسية عنصر podSelector في السياسة ستحدد البودات من مساحة الاسم التي تنتمي إليها السياسة (ليس لديها حق الوصول إلى البودات من مساحة اسم أخرى).

وبالمثل ، podSelectors في كتل الدخول والخروج يمكن فقط تحديد البودات من مساحة الاسم الخاصة بهم ، ما لم تدمجهم بالطبع مع namespaceSelector (سيتم مناقشة هذا في قسم "التصفية حسب مساحات الاسم والقرون").

قواعد تسمية السياسة

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

أنا أحب بشكل خاص إحدى طرق التسمية. وهو يتألف من ربط اسم مساحة الاسم مع القرون الهدف. على سبيل المثال:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

تسميات

يمكن إرفاق الملصقات المخصصة بكائنات Kubernetes مثل القرون ومساحات الأسماء. تسميات (التسميات العلامات) مكافئة للعلامات في السحابة. تستخدم سياسات شبكة Kubernetes التصنيفات لتحديدها القرونالتي تنطبق عليهم:

podSelector:
  matchLabels:
    role: db

… أو مساحات الأسماءالتي تنطبق عليها. يحدد هذا المثال جميع الكبسولات في مساحات الأسماء ذات التسميات المتطابقة:

namespaceSelector:
  matchLabels:
    project: myproject

تحذير واحد: عند استخدام namespaceSelector تأكد من أن مساحات الأسماء التي تحددها تحتوي على التسمية الصحيحة. اعلم أن مساحات الأسماء المضمنة مثل default и kube-system، لا تحتوي على تسميات بشكل افتراضي.

يمكنك إضافة تسمية إلى مساحة مثل هذا:

kubectl label namespace default namespace=default

في هذه الحالة ، مساحة الاسم في القسم metadata يجب أن يشير إلى الاسم الفعلي للمساحة ، وليس التسمية:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

المصدر والوجهة

تتكون نُهج جدار الحماية من قواعد المصدر والوجهة. يتم تحديد سياسات شبكة Kubernetes لكل هدف ، ومجموعة البودات التي تنطبق عليها ، ثم تعيين قواعد لحركة مرور الدخول و / أو الخروج. في مثالنا ، سيكون هدف السياسة هو جميع الكبسولات في مساحة الاسم default مع التسمية الرئيسية app والمعنى db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: 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 لمتخصصي الأمان

القسم الفرعي ingress في هذه السياسة يفتح حركة المرور الواردة لاستهداف القرون. بمعنى آخر ، الدخول هو المصدر والهدف هو الوجهة المقابلة. وبالمثل ، فإن الخروج هو الوجهة ، والهدف هو مصدره.

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

هذا يعادل قاعدتين لجدار الحماية: Ingress → Target ؛ الهدف → الخروج.

الخروج و DNS (مهم!)

تقييد حركة المرور الصادرة إيلاء اهتمام خاص لنظام أسماء النطاقات - تستخدم Kubernetes هذه الخدمة لتعيين الخدمات إلى عناوين IP. على سبيل المثال ، لن تعمل السياسة التالية لأنك لم تسمح للتطبيق balance الوصول إلى DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

يمكنك إصلاحه عن طريق فتح الوصول إلى خدمة DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

العنصر الأخير to فارغ ، ولذا يختار بشكل غير مباشر جميع الكبسولات في جميع مساحات الأسماء، السماح balance إرسال استعلامات DNS إلى خدمة Kubernetes المناسبة (عادةً ما يتم تشغيلها في الفضاء kube-system).

هذا النهج يعمل ، مع ذلك مفرط في التساهل وغير آمن، لأنه يسمح لك بتوجيه استعلامات DNS خارج المجموعة.

يمكنك تحسينه في ثلاث خطوات متتالية.

1. السماح باستعلامات DNS فقط داخل الكتلة بإضافة namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

2. السماح باستعلامات DNS فقط في مساحة الاسم kube-system.

للقيام بذلك ، تحتاج إلى إضافة تسمية إلى مساحة الاسم kube-system: kubectl label namespace kube-system namespace=kube-system - وتسجيله في السياسة باستخدام namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

3. يمكن للمصابين بجنون الارتياب أن يذهبوا إلى أبعد من ذلك ويقيدون طلبات DNS لخدمة DNS محددة في kube-system. سيوضح لك قسم "التصفية حسب مساحات الأسماء والقرون" كيفية تحقيق ذلك.

خيار آخر هو حل DNS على مستوى مساحة الاسم. في هذه الحالة ، لن تحتاج إلى فتحه لكل خدمة:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

فارغة podSelector يختار كل البودات في مساحة الاسم.

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

المباراة الأولى وترتيب القاعدة

في جدران الحماية التقليدية ، يتم تحديد الإجراء (السماح أو الرفض) على الحزمة من خلال القاعدة الأولى التي تفي بها. في Kubernetes ، لا يهم ترتيب السياسات.

بشكل افتراضي ، عندما لا يتم تعيين أي سياسات ، يُسمح بالاتصال بين البودات ويمكنهم تبادل المعلومات بحرية. بمجرد أن تبدأ في صياغة السياسات ، تصبح كل مجموعة متأثرة بواحدة منها على الأقل معزولة وفقًا للفصل (أو المنطقي) لجميع السياسات التي حددتها. البودات التي لا تتأثر بأي سياسة تظل مفتوحة.

يمكنك تغيير هذا السلوك باستخدام قاعدة المسح.

قاعدة التنظيف ("محظورة")

عادةً ما ترفض سياسات جدار الحماية أي حركة مرور غير مسموح بها صراحةً.

Kubernetes ليس لديه إجراء "رفض"، ولكن يمكن تحقيق نفس التأثير من خلال سياسة عادية (متساهلة) عن طريق اختيار مجموعة فارغة من البودات المصدر (إدخال):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

تحدد هذه السياسة جميع الكبسولات في مساحة الاسم وتترك الإدخال غير محدد ، مما يؤدي إلى رفض كل حركة المرور الواردة.

وبالمثل ، يمكنك تقييد جميع حركات المرور الصادرة من مساحة الاسم:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

يرجى ملاحظة ذلك أي سياسات إضافية تسمح بالزيارات إلى pods في مساحة الاسم ستكون لها الأسبقية على هذه القاعدة (على غرار إضافة قاعدة سماح قبل قاعدة رفض في تكوين جدار الحماية).

السماح للجميع (أي-أي-أي-سماح)

لإنشاء سياسة "السماح للكل" ، تحتاج إلى استكمال سياسة الرفض المذكورة أعلاه بعنصر فارغ ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

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

يمكن تضييق القاعدة للسماح بالوصول إليها فقط مجموعة محددة من القرون (app:balance) في مساحة الاسم default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

تسمح السياسة التالية لكل حركة المرور الواردة (الدخول) والصادرة (الخروج) ، بما في ذلك الوصول إلى أي عنوان IP خارج المجموعة:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان
مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

الجمع بين سياسات متعددة

يتم ترتيب السياسات منطقيًا على ثلاثة مستويات ؛ يتم تعيين أذونات كل جراب وفقًا لفصل جميع السياسات التي تؤثر عليه:

1. في المجالات from и to يمكن تحديد ثلاثة أنواع من العناصر (كلها مدمجة مع OR):

  • namespaceSelector - يحدد مساحة الاسم بالكامل ؛
  • podSelector - يختار القرون.
  • ipBlock - يحدد شبكة فرعية.

في نفس الوقت ، عدد العناصر (حتى نفس العناصر) في الأقسام الفرعية from/to غير محدود. سيتم دمج كل منهم مع منطقي OR.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

2. قسم السياسة الداخلية ingress يمكن أن تحتوي على العديد من العناصر from (مجمعة بواسطة منطقي OR). وبالمثل ، القسم egress قد تتضمن العديد من العناصر to (يتم دمجه أيضًا عن طريق الانفصال):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

3. يتم أيضًا دمج السياسات المختلفة مع OR المنطقي

ولكن عندما يتم دمجها ، هناك قيد واحد على أشار بها كريس كوني: يمكن لـ Kubernetes فقط دمج السياسات مع سياسات مختلفة policyTypes (Ingress أو Egress). السياسات التي تحدد الإدخال (أو الخروج) ستحل محل بعضها البعض.

العلاقة بين مساحات الأسماء

افتراضيًا ، يُسمح بتبادل المعلومات بين مساحات الأسماء. يمكن تغيير ذلك بسياسة تقييدية تقيد حركة المرور الصادرة و / أو الواردة إلى مساحة الاسم (راجع "قاعدة المسح" أعلاه).

من خلال حظر الوصول إلى مساحة اسم (راجع "قاعدة المسح" أعلاه) ، يمكنك إجراء استثناءات لسياسة الرفض من خلال السماح بالاتصالات من مساحة اسم معينة باستخدام namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

ونتيجة لذلك ، فإن جميع البودات في مساحة الاسم default الوصول إلى القرون postgres في مساحة الاسم database. ولكن ماذا لو كنت تريد فتح الوصول إلى postgres فقط قرون محددة في مساحة الاسم default?

تصفية حسب مساحات الاسم والقرون

يسمح لك إصدار Kubernetes 1.11 وما بعده بدمج عوامل التشغيل namespaceSelector и podSelector باستخدام منطقية AND. يبدو كما يلي:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

لماذا يتم تفسيره على أنه AND بدلاً من OR المعتاد؟

يرجى ملاحظة أن podSelector لا تبدأ بشرطة. في YAML هذا يعني أن podSelector ويقف أمامه namespaceSelector تشير إلى نفس عنصر القائمة. لذلك ، يتم دمجها مع منطقية AND.

مضيفا شرطة من قبل podSelector سينتج عن عنصر قائمة جديد سيتم دمجه مع العنصر السابق namespaceSelector باستخدام منطقي OR.

لتحديد القرون ذات التسمية المحددة في جميع مساحات الأسماء، أدخل فارغة namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

تتحد التسميات المتعددة مع AND

يتم دمج قواعد جدار الحماية مع كيانات متعددة (مضيفات وشبكات ومجموعات) باستخدام OR المنطقي. سيتم إطلاق القاعدة التالية إذا تطابق مصدر الحزمة Host_1 OR Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

على العكس من ذلك ، في Kubernetes تسميات مختلفة في podSelector أو namespaceSelector مدموجة مع AND المنطقية. على سبيل المثال ، ستحدد القاعدة التالية الكبسولات التي تحتوي على كلا التصنيفين ، role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

ينطبق نفس المنطق على جميع أنواع العبارات: محددات هدف السياسة ومحددات pod ومحددات مساحة الاسم.

الشبكات الفرعية وعناوين IP (IPBlocks)

تستخدم جدران الحماية شبكات VLAN وعناوين IP والشبكات الفرعية لتقسيم الشبكة.

في Kubernetes ، يتم تعيين عناوين IP تلقائيًا إلى البودات ويمكن تغييرها بشكل متكرر ، لذلك تُستخدم التسميات لتحديد البودات ومساحات الأسماء في سياسات الشبكة.

الشبكات الفرعية (ipBlocks) عند إدارة الاتصالات الواردة (دخول) أو الصادرة (خروج) الخارجية (شمال - جنوب). على سبيل المثال ، تفتح هذه السياسة جميع البودات من مساحة الاسم default الوصول إلى خدمة Google DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

محدد البود الفارغ في هذا المثال يعني "تحديد كل البودات في مساحة الاسم".

تسمح هذه السياسة بالوصول إلى 8.8.8.8 فقط ؛ يحظر الوصول إلى أي IP آخر. لذلك ، في الأساس ، لقد قمت بحظر الوصول إلى خدمة Kubernetes DNS الداخلية. إذا كنت لا تزال تريد فتحه ، فحدده بشكل صريح.

عادة ipBlocks и podSelectors يتم استبعاد بعضهما البعض ، نظرًا لأن عناوين IP الداخلية للقرون لا تُستخدم في ipBlocks. لافتا قرون IP الداخلية، ستسمح بالفعل بالاتصالات من / إلى البودات التي تحتوي على هذه العناوين. من الناحية العملية ، لن تعرف عنوان IP الذي يجب استخدامه ، ولهذا السبب لا يجب عليك استخدامها لتحديد البودات.

كمثال مضاد ، تتضمن السياسة التالية جميع عناوين IP وبالتالي تسمح بالوصول إلى جميع البودات الأخرى:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

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

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

المنافذ والبروتوكولات

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

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

لاحظ أن المحدد ports ينطبق على جميع العناصر الموجودة في الكتلة to أو fromالذي يحتوي على. لتحديد منافذ مختلفة لمجموعات عناصر مختلفة ، فاصل ingress أو egress إلى عدة أقسام فرعية to أو from وفي كل منها اكتب المنافذ الخاصة بك:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

مقدمة لسياسات شبكة Kubernetes لمتخصصي الأمان

تعمل المنافذ الافتراضية:

  • إذا حذفت تعريف المنافذ بالكامل (ports) ، مما يعني جميع البروتوكولات وجميع المنافذ ؛
  • إذا حذفت تعريف البروتوكول (protocol) ، مما يعني TCP ؛
  • إذا حذفت تعريف المنفذ (port) ، مما يعني جميع المنافذ.

أفضل ممارسة: لا تعتمد على القيم الافتراضية ، حدد ما تحتاجه بوضوح.

لاحظ أنك تحتاج إلى استخدام منافذ البود وليس الخدمات (المزيد عن هذا في الفقرة التالية).

السياسات المحددة للبودات أو الخدمات؟

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

على سبيل المثال ، إذا استمعت إحدى الخدمات إلى المنفذ 80 ، لكنها أعادت توجيه حركة المرور إلى المنفذ 8080 من أجهزتها ، فيجب عليك تحديد 8080 في سياسة الشبكة.

يجب التعرف على مثل هذه الآلية على أنها دون المستوى الأمثل: إذا تغير الجهاز الداخلي للخدمة (المنافذ التي تستمع إلى البودات) ، فسيتعين تحديث سياسات الشبكة.

نهج معماري جديد باستخدام Service Mesh (على سبيل المثال ، انظر حول Istio أدناه - ترجمة تقريبًا.) يسمح لك بالتعامل مع هذه المشكلة.

هل من الضروري أن تكتب كلا من الدخول والخروج؟

الإجابة المختصرة هي نعم ، لكي يتواصل pod A مع pod B ، تحتاج إلى السماح له بإنشاء اتصال صادر (لهذا تحتاج إلى تكوين سياسة الخروج) ، ويجب أن يكون pod B قادرًا على قبول اتصال وارد (لهذا ، أنت بحاجة إلى سياسة دخول).

ومع ذلك ، من الناحية العملية ، يمكنك الاعتماد على السياسة الافتراضية للسماح بالاتصالات في اتجاه واحد أو كلا الاتجاهين.

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

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

انظر "الدولة أو عديمي الجنسية" أدناه.

السجلات

لا تعرف سياسات شبكة Kubernetes كيفية تسجيل حركة المرور. هذا يجعل من الصعب تحديد ما إذا كانت السياسة تعمل كما هو متوقع ويجعل تحليل الأمان صعبًا للغاية.

مراقبة حركة المرور للخدمات الخارجية

لا تسمح لك سياسات شبكة Kubernetes بتحديد اسم مجال مؤهل بالكامل (DNS) في أقسام الخروج. تؤدي هذه الحقيقة إلى إزعاج كبير عند محاولة تقييد حركة المرور إلى الوجهات الخارجية التي لا تحتوي على عنوان IP ثابت (مثل aws.com).

فحص السياسة

ستحذرك جدران الحماية أو حتى ترفض قبول سياسة خاطئة. يقوم Kubernetes ببعض التحقق أيضًا. عند تعيين سياسة شبكة عبر kubectl ، قد تعلن Kubernetes أن السياسة غير صحيحة وترفض قبولها. في حالات أخرى ، ستتخذ Kubernetes السياسة وتعبئها بالتفاصيل الناقصة. يمكنك رؤيتهم بالأمر:

kubernetes get networkpolicy <policy-name> -o yaml

ضع في اعتبارك أن نظام التحقق من صحة Kubernetes ليس معصومًا عن الخطأ وقد يفوتك بعض أنواع الأخطاء.

إعدام

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

لاحظ أن Kubernetes لن يحذرك إذا قمت بتعيين سياسة شبكة بدون CNI المساعد المناسب.

الدولة أم عديم الجنسية؟

جميع أرقام CNI الخاصة بـ Kubernetes التي صادفتها مصحوبة بالحالة (على سبيل المثال ، يستخدم Calico Linux conntrack). يسمح هذا للحجرة بتلقي استجابات على اتصال TCP الذي بدأته دون الحاجة إلى إعادة إنشائه. ومع ذلك ، فأنا لست على علم بمعيار Kubernetes الذي يضمن الالتزام بالحالة.

إدارة سياسة الأمان المتقدمة

فيما يلي بعض الطرق لتحسين كفاءة تطبيق سياسة الأمان في Kubernetes:

  1. يستخدم النمط المعماري لشبكة الخدمة أشرطة جانبية لتوفير قياس مفصل عن بُعد والتحكم في حركة المرور على مستوى الخدمة. كمثال ، يمكن للمرء أن يأخذ Istio.
  2. قام بعض بائعي CNI بتوسيع أدواتهم لتتجاوز سياسات شبكة Kubernetes.
  3. توفين أوركا يوفر الشفافية والأتمتة لسياسات شبكة Kubernetes.

تدير حزمة Tufin Orca سياسات شبكة Kubernetes (وهي مصدر لقطات الشاشة أعلاه).

معلومات إضافية

اختتام

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

آمل أن يساعد هذا الدليل في توضيح بعض الأسئلة وحل المشكلات التي قد تواجهها.

PS من المترجم

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

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

إضافة تعليق