Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

هدف از این مقاله این است که خواننده را با اصول شبکه سازی و مدیریت سیاست های شبکه در Kubernetes و همچنین افزونه شخص ثالث Calico که قابلیت های استاندارد را گسترش می دهد، آشنا کند. در طول مسیر، سهولت پیکربندی و برخی ویژگی ها با استفاده از نمونه های واقعی از تجربه عملیاتی ما نشان داده می شود.

معرفی سریع ابزار شبکه Kubernetes

خوشه Kubernetes بدون شبکه قابل تصور نیست. ما قبلاً مطالبی را در مورد اصول اولیه آنها منتشر کرده ایم:راهنمای مصور شبکه سازی در Kubernetes"و"مقدمه ای بر سیاست های شبکه Kubernetes برای حرفه ای های امنیتی'.

در زمینه این مقاله، توجه به این نکته مهم است که K8s خود مسئول اتصال شبکه بین کانتینرها و گره ها نیست: برای این، موارد مختلفی وجود دارد. پلاگین های CNI (رابط شبکه کانتینر). بیشتر در مورد این مفهوم ما به من هم گفتند.

به عنوان مثال، رایج ترین این افزونه ها است فلنج - اتصال کامل شبکه را بین تمام گره های خوشه ای با بالا بردن پل ها روی هر گره و اختصاص یک زیرشبکه به آن فراهم می کند. با این حال، دسترسی کامل و غیرقانونی همیشه سودمند نیست. برای ارائه نوعی ایزوله حداقلی در خوشه، لازم است در پیکربندی فایروال مداخله شود. در حالت کلی، تحت کنترل همان CNI قرار می گیرد، به همین دلیل است که هر گونه مداخله شخص ثالث در iptables می تواند به اشتباه تفسیر شود یا به طور کلی نادیده گرفته شود.

و "خارج از جعبه" برای سازماندهی مدیریت خط مشی شبکه در یک خوشه Kubernetes ارائه شده است NetworkPolicy API. این منبع، که در فضای نام انتخاب شده توزیع شده است، ممکن است حاوی قوانینی باشد که دسترسی را از یک برنامه به برنامه دیگر متمایز کند. همچنین به شما امکان می‌دهد دسترسی بین پادها، محیط‌ها (فضای نام) یا بلوک‌های آدرس 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

این بدوی ترین نمونه نیست اسناد رسمی ممکن است یک بار و برای همیشه تمایل به درک منطق نحوه عملکرد سیاست های شبکه را از بین ببرد. با این حال، ما همچنان سعی خواهیم کرد تا اصول و روش های اساسی پردازش جریان های ترافیکی را با استفاده از سیاست های شبکه درک کنیم...

منطقی است که 2 نوع ترافیک وجود دارد: ورود به پاد (Ingress) و خروج از آن (Egress).

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

در واقع سیاست بر اساس جهت حرکت به این 2 دسته تقسیم می شود.

ویژگی مورد نیاز بعدی یک انتخابگر است. کسی که این قانون در مورد او اعمال می شود. این می تواند یک غلاف (یا گروهی از غلاف ها) یا یک محیط (به عنوان مثال یک فضای نام) باشد. یک جزئیات مهم: هر دو نوع این اشیا باید دارای یک برچسب (برچسب در اصطلاح Kubernetes) - اینها کسانی هستند که سیاستمداران با آنها کار می کنند.

علاوه بر تعداد محدودی از انتخابگرها که توسط نوعی برچسب متحد شده‌اند، می‌توان قوانینی مانند "اجازه دادن/انکار همه چیز/همه" را در انواع مختلف نوشت. برای این منظور از ساختارهای فرم استفاده می شود:

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

- در این مثال، تمام پادهای موجود در محیط از ترافیک ورودی مسدود شده اند. رفتار مخالف را می توان با ساخت زیر به دست آورد:

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

به طور مشابه برای خروجی:

  podSelector: {}
  policyTypes:
  - Egress

- برای خاموش کردن آن و در اینجا چیزی است که باید شامل شود:

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

با بازگشت به انتخاب یک پلاگین CNI برای یک کلاستر، شایان ذکر است که هر افزونه شبکه از NetworkPolicy پشتیبانی نمی کند. به عنوان مثال، Flannel قبلاً ذکر شده نمی داند چگونه سیاست های شبکه را پیکربندی کند مستقیم گفته شده است در مخزن رسمی یک جایگزین نیز در آنجا ذکر شده است - یک پروژه منبع باز چلوار، که به طور قابل توجهی مجموعه استاندارد API های Kubernetes را از نظر خط مشی های شبکه گسترش می دهد.

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

آشنایی با کالیکو: نظریه

پلاگین Calico را می توان در ادغام با Flannel (زیر پروژه کانال) یا به طور مستقل، هم قابلیت اتصال به شبکه و هم قابلیت های مدیریت در دسترس بودن را پوشش می دهد.

استفاده از راه حل "جعبه دار" K8s و مجموعه API از Calico چه فرصت هایی را فراهم می کند؟

آنچه در NetworkPolicy تعبیه شده است:

  • سیاستمداران توسط محیط زیست محدود شده اند.
  • خط‌مشی‌ها برای غلاف‌هایی که با برچسب‌ها مشخص شده‌اند اعمال می‌شوند.
  • قوانین را می توان برای غلاف ها، محیط ها یا زیرشبکه ها اعمال کرد.
  • قوانین می توانند شامل پروتکل ها، مشخصات پورت نامدار یا نمادین باشند.

در اینجا نحوه گسترش این توابع توسط Calico آمده است:

  • سیاست ها را می توان برای هر شی اعمال کرد: pod، کانتینر، ماشین مجازی یا رابط.
  • قوانین می تواند شامل یک عمل خاص (ممنوعیت، مجوز، ورود به سیستم) باشد.
  • هدف یا منبع قوانین می تواند یک پورت، طیفی از پورت ها، پروتکل ها، ویژگی های HTTP یا ICMP، IP یا زیرشبکه (نسل چهارم یا ششم)، هر انتخابگر (گره ها، میزبان ها، محیط ها) باشد.
  • علاوه بر این، می توانید با استفاده از تنظیمات DNAT و سیاست های حمل و نقل ترافیک، عبور ترافیک را تنظیم کنید.

اولین تعهدات در GitHub در مخزن Calico به ژوئیه 2016 برمی گردد و یک سال بعد این پروژه در سازماندهی اتصال شبکه Kubernetes جایگاه پیشرو را به دست آورد - به عنوان مثال، نتایج نظرسنجی این را نشان می دهد. توسط The New Stack انجام شد:

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

بسیاری از راه حل های مدیریت شده بزرگ با K8، مانند آمازون EKS, آژور AKS, Google GKE و دیگران شروع به توصیه آن برای استفاده کردند.

در مورد عملکرد، همه چیز اینجا عالی است. تیم توسعه Calico در آزمایش محصول خود، عملکرد نجومی را نشان داد و بیش از 50000 کانتینر را روی 500 گره فیزیکی با سرعت ایجاد 20 کانتینر در ثانیه اجرا کرد. هیچ مشکلی در مقیاس بندی مشخص نشد. چنین نتایجی اعلام شدند در حال حاضر در اعلام نسخه اول. مطالعات مستقل با تمرکز بر توان عملیاتی و مصرف منابع نیز تأیید می‌کند که عملکرد Calico تقریباً به خوبی عملکرد Flannel است. مثلا:

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

این پروژه بسیار سریع در حال توسعه است، از کار در راه حل های محبوب K8s، OpenShift، OpenStack پشتیبانی می کند، امکان استفاده از Calico هنگام استقرار یک خوشه با استفاده از لگد زدن، اشاراتی به ساخت شبکه های سرویس مش وجود دارد (در اینجا یک مثال است همراه با ایستیو استفاده می شود).

با Calico تمرین کنید

در مورد کلی استفاده از وانیلی Kubernetes، نصب CNI به استفاده از فایل خلاصه می شود calico.yaml, از وب سایت رسمی دانلود شده است، با استفاده از kubectl apply -f.

به عنوان یک قاعده، نسخه فعلی افزونه با آخرین 2-3 نسخه Kubernetes سازگار است: عملکرد در نسخه های قدیمی آزمایش نشده و تضمین نمی شود. به گفته توسعه دهندگان، Calico بر روی هسته های لینوکس بالای 3.10 اجرا می شود که دارای CentOS 7، Ubuntu 16 یا Debian 8 هستند، در بالای iptables یا IPVS.

انزوا در محیط

برای درک کلی، اجازه دهید به یک مورد ساده نگاه کنیم تا بفهمیم که چگونه خط‌مشی‌های شبکه در نماد Calico با موارد استاندارد متفاوت است و چگونه رویکرد ایجاد قوانین خوانایی و انعطاف‌پذیری پیکربندی آنها را ساده می‌کند:

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

2 برنامه وب در این کلاستر مستقر شده اند: در 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 API معمولی حاوی ساختارهایی با پرانتز هستند که درک و به خاطر سپردن آنها دشوار است. در مورد Calico، برای تغییر منطق قانون فایروال به خلاف، فقط تغییر دهید action: Allow بر action: Deny.

جداسازی توسط محیط

حال شرایطی را تصور کنید که در آن یک برنامه معیارهای تجاری را برای جمع آوری در Prometheus و تجزیه و تحلیل بیشتر با استفاده از Grafana ایجاد می کند. آپلود ممکن است حاوی داده های حساسی باشد که به طور پیش فرض مجدداً برای عموم قابل مشاهده است. بیایید این داده ها را از چشمان کنجکاو پنهان کنیم:

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

Prometheus، به عنوان یک قاعده، در یک محیط سرویس جداگانه قرار می گیرد - در مثال، فضای نامی مانند این خواهد بود:

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

و اگر از سیاست های Calico استفاده می کنید، نحو به این صورت خواهد بود:

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، رویکرد "همه چیز را مسدود کنید و آنچه را که نیاز دارید به صراحت باز کنید" است، مستند در اسناد رسمی (بقیه از رویکرد مشابهی پیروی می کنند - به ویژه در مقاله قبلا ذکر شد).

استفاده از اشیاء کالیکو اضافی

اجازه دهید به شما یادآوری کنم که از طریق مجموعه گسترده Calico API ها می توانید در دسترس بودن گره ها را تنظیم کنید، نه محدود به پادها. در مثال زیر با استفاده از GlobalNetworkPolicy توانایی ارسال درخواست های ICMP در خوشه بسته است (به عنوان مثال، پینگ از یک pod به یک گره، بین پادها، یا از یک گره به یک IP pod):

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

در نهایت، من یک مثال بسیار واقعی از استفاده از توابع Calico برای مورد تعامل نزدیک به خوشه ارائه می‌دهم، زمانی که یک مجموعه استاندارد از سیاست‌ها کافی نیست. برای دسترسی به برنامه وب، مشتریان از یک تونل VPN استفاده می کنند و این دسترسی به شدت کنترل شده و محدود به لیست خاصی از خدمات مجاز برای استفاده است:

Calico برای شبکه سازی در Kubernetes: مقدمه و کمی تجربه

کلاینت ها از طریق پورت استاندارد UDP 1194 به VPN متصل می شوند و در صورت اتصال، مسیرهایی را به زیرشبکه های خوشه ای پادها و سرویس ها دریافت می کنند. کل زیرشبکه ها فشار داده می شوند تا در هنگام راه اندازی مجدد و تغییر آدرس، سرویس ها را از دست ندهند.

پورت در پیکربندی استاندارد است، که برخی تفاوت های ظریف را بر روند پیکربندی برنامه و انتقال آن به خوشه 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 حفظ می شود که عملکرد آن اغلب هنگام تنظیم قوانین آسیب می بیند. زیرا همانطور که قبلا ذکر شد، هنگامی که یک انتخابگر ظاهر می شود، سیاست انکار پیش فرض برای آن اعمال می شود، مگر اینکه خلاف آن مشخص شده باشد.

نمایش نتایج: از

بنابراین، با استفاده از API پیشرفته Calico، می‌توانید مسیریابی را در داخل و اطراف خوشه به‌صورت انعطاف‌پذیر پیکربندی و تغییر دهید. به طور کلی، استفاده از آن می تواند شبیه تیراندازی به گنجشک ها با توپ باشد، و پیاده سازی یک شبکه L3 با تونل های BGP و IP-IP در نصب ساده Kubernetes در یک شبکه مسطح هیولا به نظر می رسد ... با این حال، در غیر این صورت ابزار کاملاً قابل اجرا و مفید به نظر می رسد. .

جداسازی یک خوشه برای برآورده کردن الزامات امنیتی ممکن است همیشه امکان پذیر نباشد، و اینجاست که Calico (یا راه حلی مشابه) به کمک می آید. نمونه های ارائه شده در این مقاله (با تغییرات جزئی) در چندین نصب از مشتریان ما در AWS استفاده می شود.

PS

در وبلاگ ما نیز بخوانید:

منبع: www.habr.com

اضافه کردن نظر