SPIFFE، SPIRE، اور Cilium کا استعمال کرتے ہوئے Kubernetes پر زیرو ٹرسٹ ورک بوجھ کی شناخت کو کیسے نافذ کیا جائے

نیٹ ورک کی پالیسی درج ذیل ٹریفک کی اجازت دیتی ہے: 10.0.1.45.

کل، 10.0.1.45 یہ آپ کی ادائیگی کی خدمت تھی۔ موجودہ رولنگ تعیناتی کے بعد، یہ لاگنگ ایجنٹ بن جائے گا۔ آپ کی ادائیگی کی خدمت فی الحال ہے۔ 10.0.1.89.

Kubernetes نے پہلے ہی تمام اینڈ پوائنٹس اور سروس ریکارڈز کو اپ ڈیٹ کر دیا ہے، لیکن نیٹ ورک کی پالیسیوں کا کوئی علم نہیں ہے۔ خودکار طور پر IP پتوں پر مبنی ٹریفک کی اجازت دیتا ہے جو اب اس کام کے بوجھ سے تعلق نہیں رکھتے جس پر آپ بھروسہ کرنا چاہتے ہیں۔

یہ کام کے بوجھ کی شناخت کا مسئلہ ہے۔ آپ کا IP پتہ آپ کا مقام ہے، آپ کی شناخت نہیں۔ اور Kubernetes کلسٹرز میں، مقام مسلسل بدلتا رہتا ہے۔ آئی پی ایڈریسز کے اوپر سیکیورٹی پالیسیاں بنانے سے، جب بھی کوئی پوڈ شیڈول، ری شیڈول، یا بڑھایا جاتا ہے تو آپ کی سیکیورٹی پوزیشن خود بخود گر جاتی ہے۔

جواب کرپٹوگرافک ورک لوڈ آئیڈینٹیٹی ہے۔ ہر کام کے بوجھ کو سرٹیفکیٹ کی حمایت یافتہ شناخت ملتی ہے جو ثابت کرتی ہے کہ وہ کون ہیں، نہ کہ وہ کہاں ہیں۔ سروسز ڈیٹا کے تبادلے سے پہلے ایک دوسرے کی تصدیق کے لیے اپنے سرٹیفکیٹ کا استعمال کرتی ہیں۔ اگر سرٹیفکیٹ مماثل نہیں ہوتے ہیں، تو کنکشن اس کے IP ایڈریس سے قطع نظر مسترد کر دیا جائے گا۔

یہ وہی ہے جو SPIFFE اور SPIRE پیش کرتے ہیں۔ اس طرح Cilium eBPF کا استعمال کرتے ہوئے ہر پوڈ میں سائیڈ کار کو انجیکشن لگائے بغیر اسے نافذ کرتا ہے۔

اس آرٹیکل میں، آپ سمجھیں گے کہ SPIFFE شناختی ماڈل کس طرح کام کرتا ہے، اپنے کام کے بوجھ پر خفیہ شناخت جاری کرنے کے لیے SPIRE کو کیسے تعینات کیا جائے، اور آپ کے ایپلیکیشن کوڈ کو چھوئے بغیر خدمات کے درمیان باہمی TLS کو نافذ کرنے کے لیے Cilium کے بلٹ ان SPIRE انٹیگریشن کو کیسے استعمال کیا جائے۔

شرطیں

  • Kubernetes RBAC اور پوڈ سیکیورٹی سے واقفیت – یہ ہینڈ بک بنیادی باتوں کا احاطہ کرتی ہے۔

  • TLS سرٹیفکیٹس اور Kubernetes کے رازوں سے اپنے آپ کو واقف کریں – یہ ہینڈ بک سرٹیفکیٹ مینیجرز اور سرٹیفکیٹ کے تصورات کا احاطہ کرتی ہے۔

  • Helm 3 اور Cilium CLI انسٹال کریں۔

  • دوستانہ کلسٹر — اس مضمون میں، ہم CLI کو بطور CNI استعمال کرتے ہوئے ایک نیا کلسٹر بنائیں گے۔

  • صبر: یہ سب سے پیچیدہ ڈیمو ہے جس کا میں نے مضامین کے اس گروپ میں احاطہ کیا ہے۔ SPIRE میں کسی بھی چیز سے زیادہ متحرک حصے ہیں جو ہم نے اب تک کور کیے ہیں۔

تمام ڈیمو فائلیں ساتھ والے GitHub ریپوزٹری میں ہیں۔

انڈیکس

کام کے بوجھ کی شناخت کے مسائل

افتتاحی منظر نامہ نظریاتی نہیں ہے۔ Kubernetes میں، pods عارضی ہیں. شیڈیولر کسی بھی نوڈ پر پوڈ رکھ سکتا ہے، اور پوڈ کا آئی پی ایڈریس شیڈولنگ کے وقت نوڈ کے آئی پی پول سے تفویض کیا جاتا ہے۔

جب کسی پوڈ کو رولنگ تعیناتی، نوڈ ڈرین، یا آٹو اسکیل ایونٹ کے ذریعے حذف اور دوبارہ بنایا جاتا ہے، تو یہ ایک نیا IP ایڈریس حاصل کرتا ہے۔ اگر آپ نے ایک نیٹ ورک پالیسی لکھی ہے جس میں لکھا ہے کہ "اس آئی پی سے ٹریفک کی اجازت دیں”، تو وہ پالیسی اب کچھ بھی نہیں، یا اس سے بھی بدتر، ایک مختلف کام کے بوجھ کی طرف اشارہ کرے گی۔

Kubernetes سروس کے نام یہاں مشرق و مغرب کی ٹریفک میں مدد کرتے ہیں۔ سروس کے ناموں کو مستقل طور پر حل کیا جاتا ہے اس سے قطع نظر کہ کون سا پوڈ ان کی حمایت کرتا ہے۔ تاہم، سروس کے نام پر مبنی نیٹ ورک پالیسی اب بھی ایک کرپٹوگرافک دعوے کے بجائے لیبل سلیکٹر میچ ہے۔ کوئی بھی پوڈ جو صحیح لیبل کو دھوکہ دے سکتا ہے وہ اسے نظرانداز کرنے کے قابل ہوگا۔

آپ واقعی کیا چاہتے ہیں کہ سروس B کو خفیہ طور پر اپنی شناخت ثابت کرنا ہے اس سے پہلے کہ سروس A سروس B کو درخواست بھیجے۔ اگر سروس B یہ ثابت نہیں کر سکتا کہ وہ وہی ہیں جس کا وہ دعویٰ کرتے ہیں، سروس A کنکشن سے انکار کر دے گی۔ یہ باہمی TLS ہے اور اہم سوال یہ ہے کہ شناخت کہاں سے آتی ہے؟

SPIFFE اس سوال کا جواب دیتا ہے۔

SPIFFE کیسے کام کرتا ہے۔

SPIFFE (Secure Production Identity Framework for everyone) ایک CNCF معیار ہے جو کام کے بوجھ کی شناخت کے ماڈل کی وضاحت کرتا ہے۔ بذات خود یہ کچھ بھی نافذ نہیں کرتا۔ یہ شناختی فارمیٹ، اس کی درخواست کرنے کے لیے API، اور ٹرسٹ ماڈل کی وضاحت کرتا ہے جو خدمات، کلسٹرز اور کلاؤڈز میں شناخت کو قابل تصدیق بناتا ہے۔ SPIRE اس تصریح کا حوالہ نفاذ ہے۔

SPIFFE شناخت اور اعتماد کا ڈومین

ایک SPIFFE ID ایک مخصوص فارمیٹ میں URI ہے۔

spiffe:///

ٹرسٹ ڈومین ایک سٹرنگ ہے جو ایک انتظامی حد (عام طور پر ایک تنظیم، کلسٹر، یا ماحول) کی نشاندہی کرتی ہے۔ ایک ہی ٹرسٹ ڈومین کے اندر ہر چیز ایک دوسرے کی شناخت کی تصدیق کر سکتی ہے۔ مختلف ٹرسٹ ڈومینز سے شناخت کے لیے واضح فیڈریشن کنفیگریشن کی ضرورت ہوتی ہے۔

کچھ مخصوص مثالیں:

spiffe://payments.corp/ns/production/sa/checkout
spiffe://analytics.corp/ns/data/sa/pipeline-worker
spiffe://cluster.local/ns/monitoring/sa/prometheus

ٹرسٹ ڈومین کے پیچھے کا راستہ بے ترتیب ہے۔ اس کی وضاحت SPIRE کنفیگریشن سے ہوتی ہے اور عام طور پر کام کے بوجھ کے Kubernetes نام کی جگہ اور سروس اکاؤنٹ کو انکوڈ کرتا ہے۔

SVID: کرپٹوگرافک شناختی دستاویز

SPIFFE قابل تصدیق شناختی دستاویز (SVID) یہ ہے کہ کس طرح ایک SPIFFE شناخت کو کسی ایسی چیز میں تبدیل کیا جاتا ہے جو درحقیقت کسی سروس پر استعمال کیا جا سکتا ہے۔

دو SVID فارمیٹس ہیں:

نہیں X.509 SWID سبجیکٹ متبادل نام (SAN) URI فیلڈ میں شامل SPIFFE ID کے ساتھ معیاری TLS سرٹیفکیٹ۔ چونکہ یہ ایک معیاری X.509 سرٹیفکیٹ ہے، اس لیے اسے کسی بھی TLS لائبریری میں ترمیم کے بغیر استعمال کیا جا سکتا ہے۔

کام کا بوجھ اس سرٹیفکیٹ کو TLS ہینڈ شیک کے ذریعے پیش کرتا ہے، اور ساتھی تصدیق کرتا ہے کہ سرٹیفکیٹ پر ایک قابل اعتماد SPIRE سرور کے ذریعے دستخط کیے گئے ہیں۔ یہ وہ فارمیٹ ہے جو طویل المدت رابطوں کے لیے استعمال ہوتا ہے، جیسے کہ gRPC اسٹریمز۔

کوئی راستہ نہیں JWT SVID ایک دستخط شدہ JSON ویب ٹوکن جس میں SPIFFE ID بطور دعوی ہے۔ HTTP پر درخواست پر مبنی توثیق کے لیے موزوں ہے۔ اسے اجازت نامے کے ہیڈر میں پاس کریں اور وصول کرنے والی سروس دستخط کی تصدیق کرے گی۔

JWT SVIDs کی عمر X.509 SVIDs سے کم ہوتی ہے اور ان کا دائرہ ایک مخصوص ہدف تک ہوتا ہے تاکہ تمام سروسز میں ٹوکن کے دوبارہ استعمال کو روکا جا سکے۔

Cilium میں باہمی تصدیق X.509 SVID استعمال کرتی ہے۔ اس مضمون کا بقیہ حصہ X.509 پر مرکوز ہے۔

اعتماد بنڈل

سروس A کے لیے سروس B کے سرٹیفکیٹ کی تصدیق کرنے کے لیے، سروس A کو یہ جاننے کی ضرورت ہے کہ کس سرٹیفکیٹ اتھارٹی نے اس پر دستخط کیے ہیں۔ SPIFFE میں، اسے ٹرسٹ بنڈل کہا جاتا ہے، جو کہ CA سرٹیفیکیٹس کا ایک سیٹ ہے جو کہ ٹرسٹ ڈومین کے اندر بھروسہ کیا جاتا ہے۔

SPIRE ورک لوڈ API کے ذریعے ٹرسٹ بنڈلز فراہم کرتا ہے۔ جب کام کا بوجھ ایک شناخت کی درخواست کرتا ہے، تو اسے موجودہ اعتماد کا بنڈل بھی ملتا ہے۔ جب SPIRE سرور CA کی جگہ لے لیتا ہے، تو یہ نئے ٹرسٹ بنڈل کو تمام ایجنٹوں میں تقسیم کرتا ہے اور اسے تمام کام کے بوجھ میں دھکیل دیتا ہے۔ درخواستوں کو ٹرسٹ بنڈلز کو دستی طور پر منظم کرنے کی ضرورت نہیں ہے۔

SPIRE کیسے کام کرتا ہے۔

SPIRE وہ انجن ہے جو SVID جاری کرتا ہے اور ID لائف سائیکل کا انتظام کرتا ہے۔ فن تعمیر کو سمجھنا Cilium کے انضمام کو معنی خیز بناتا ہے۔

SPIRE سرور اور SPIRE ایجنٹ

SPIRE کے دو اہم اجزاء ہیں: وہ اسپائر سرور سینٹرل CA کام کے بوجھ کے اندراجات کی رجسٹری کو برقرار رکھتا ہے (ریکارڈ جو یہ بیان کرتے ہیں کہ کون سے SPIFFE IDs کو کام کے بوجھ کو جاری کیا جانا چاہئے)۔ کام کے بوجھ کی طرف سے ایجنٹوں کو SVID جاری کرتا ہے اور پورے ٹرسٹ ڈومین کے لیے اعتماد کی جڑ ہے۔

کہ اسپائر ایجنٹ یہ تمام نوڈس پر ڈیمون سیٹ کے طور پر چلتا ہے۔ میرے پاس دو کام ہیں۔ سب سے پہلے، یہ SPIRE سرور کو ثابت کرتا ہے کہ یہ ایک جائز نوڈ پر چل رہا ہے۔ اسے نوڈ پروف کہا جاتا ہے۔ دوسرا، یہ نوڈ پر یونکس ساکٹ پر SPIFFE ورک لوڈ API کو بے نقاب کرتا ہے جسے کام کا بوجھ SVIDs کی درخواست کرنے کے لیے استعمال کرتا ہے۔

ایجنٹ SVIDs کو مقامی طور پر کیش کرتا ہے تاکہ SPIRE سرور سے رابطے کے عارضی نقصان کی وجہ سے کام کے بوجھ کی شناخت میں فوری خلل سے بچا جا سکے۔

یہ تقسیم (مرکزی سرور، ایجنٹ فی نوڈ) جان بوجھ کر ہے۔ کام کا بوجھ براہ راست SPIRE سرور سے مربوط نہیں ہوتا ہے۔ وہ صرف اپنے نوڈس پر ایجنٹوں سے بات کرتے ہیں۔ ایجنٹ تمام ID درخواستوں میں ثالثی کرتا ہے، کسی نوڈ سے سمجھوتہ ہونے کی صورت میں دھماکے کے رداس کو محدود کرتا ہے۔

نوڈ ثبوت

جب ایک SPIRE ایجنٹ نئے نوڈ پر شروع ہوتا ہے، تو اسے کام کے بوجھ کو اپنی شناخت فراہم کرنے سے پہلے SPIRE سرور کو اپنی شناخت ثابت کرنی ہوگی۔ یہ نوڈ پروف ہے۔

کبرنیٹس پر اسپائر استعمال کرتا ہے: پی ایس اے ٹی – متوقع سروس اکاؤنٹ ٹوکن – نوڈ پروفنگ کے لیے۔ ایجنٹ ایک Kubernetes سروس اکاؤنٹ ٹوکن فراہم کرتا ہے جس کی توقع خاص طور پر SPIRE سرور کے ہدف کے لیے ہوتی ہے۔ SPIRE سرور Kubernetes API سے رابطہ کرتا ہے، ٹوکن کی تصدیق کرتا ہے، تصدیق کرتا ہے کہ ایجنٹ متوقع سروس اکاؤنٹ کے ساتھ متوقع نام کی جگہ پر چل رہا ہے، اور پھر ایجنٹ کو اپنا SVID جاری کرتا ہے۔

یہی وجہ ہے کہ SPIRE کو مخصوص Kubernetes API جھنڈوں کی ضرورت ہے۔ kube-apiserver کو مناسب اہداف کے ساتھ متوقع سروس اکاؤنٹ ٹوکن کی حمایت کرنے کے لیے ترتیب دیا جانا چاہیے۔ یہی وجہ ہے کہ ذیل میں ڈیمو میں کلسٹر کنفیگریشن کی قسم ترتیب دی گئی ہے۔ --api-audiences اور --service-account-issuer.

کام کے بوجھ کا ثبوت

ایک بار جب نوڈ کی تصدیق ہو جاتی ہے، تو اس کے ایجنٹ اپنے کام کے بوجھ کی تصدیق کر سکتے ہیں۔ جب کام کا بوجھ کسی ورک لوڈ API ساکٹ سے جڑتا ہے اور SVID کی درخواست کرتا ہے، تو ایجنٹ اس کام کے بوجھ کے بارے میں معلومات اکٹھا کرنے کے لیے Kubernetes API سے استفسار کرتا ہے (Kubernetes namespace، سروس اکاؤنٹ، Pod name، label، وغیرہ)۔ یہ اس حقیقت سے میل کھاتا ہے SPIRE سرور پر رجسٹرڈ ورک لوڈ اندراجات سے۔ اگر کوئی مماثلت پائی جاتی ہے، تو ایجنٹ متعلقہ SVID جاری کرتا ہے۔

کام کے بوجھ کی اشیاء میں شامل ہیں:

SPIFFE ID: spiffe://example.org/ns/production/sa/checkout
Parent ID: spiffe://example.org/spire/agent/k8s_psat/default/
Selectors:
  k8s:ns:production
  k8s:sa:checkout

ایک سلیکٹر ایک Kubernetes حقیقت بیان کرتا ہے جس کا مماثل ہونا ضروری ہے۔ پھلیاں چل رہی ہیں۔ production سروس اکاؤنٹ کے ساتھ نام کی جگہ checkout آپ کو ایک SPIFFE ID موصول ہوگی۔ spiffe://example.org/ns/production/sa/checkout. دوسرے فورڈ نہیں کرتے۔

SVID کا اجراء اور گردش

SVID ڈیزائن کے لحاظ سے قلیل المدت ہے۔ SPIRE میں X.509 SVID کے لیے ڈیفالٹ TTL 1 گھنٹہ ہے۔ اسپائر ایجنٹ پس منظر میں خود بخود اس کے ذریعے چکر لگاتا ہے۔ اس کا مطلب ہے ایک نیا کلیدی جوڑا بنانا، سرور سے ایک نئے SVID کی درخواست کرنا، اور پرانے SVID کی میعاد ختم ہونے سے پہلے نئے SVID کو Workload API کو دستیاب کرانا ہے۔

ورک بوجھ جو ورک لوڈ API کا براہ راست استعمال کرتے ہیں یا ٹولز جیسے کہ SPIFFE CSI ڈرائیور نیا SVID شفاف طریقے سے حاصل کرتے ہیں۔

قلیل مدتی اسناد ایک زیرو ٹرسٹ اپروچ ہیں۔ اگر کسی کام کے بوجھ کے SVID سے سمجھوتہ کیا جاتا ہے، تو یہ صرف ایک گھنٹے کے لیے درست ہے۔ اس کا موازنہ Kubernetes سروس اکاؤنٹ ٹوکنز سے کریں، جو تاریخی طور پر ہمیشہ کے لیے درست ہیں۔

کس طرح Cilium SPIFFE کا استعمال کرتے ہوئے باہمی TLS کو لاگو کرتا ہے۔

سروس میش ایم ٹی ایل ایس (جیسے اسٹیو یا لنکرڈ) کے روایتی طریقے ہر پوڈ میں سائڈ کار پراکسی داخل کرتے ہیں۔ پراکسی تمام ٹریفک کو روکتی ہے اور TLS ہینڈ شیک کو ہینڈل کرتی ہے۔ ایپلیکیشن کو کوئی اندازہ نہیں ہے کہ TLS ہو رہا ہے۔ سائیڈ کارز میموری اوور ہیڈ (Envoy کے لیے تقریباً 50 سے 100 MB فی پوڈ)، ہر درخواست کے لیے ایک اضافی نیٹ ورک ہاپ، اور ایک پیچیدہ سرٹیفکیٹ انجیکشن میکانزم شامل کرتے ہیں۔

Cilium ایک مختلف راستہ لیتا ہے. پراکسی انجیکشن لگانے کے بجائے، ہم نیٹ ورک پرت پر تصدیق کو سنبھالنے کے لیے eBPF کا استعمال کرتے ہیں۔ ہر نوڈ پر چلنے والا ایک Cilium ایجنٹ کنکشن کو روکتا ہے، SPIFFE SVID کا استعمال کرتے ہوئے باہمی TLS ہینڈ شیک کرتا ہے، اور تصدیق کے نتائج کو لاگو کرتا ہے۔ یہ سب کچھ یوزر اسپیس پراکسی کے بغیر کرنل میں ہوتا ہے۔

طریقہ کار اس طرح کام کرتا ہے: جب Pod A Pod B سے کنکشن شروع کرتا ہے، Pod A نوڈ پر Cilium ایجنٹ کنکشن کو روکتا ہے۔ SPIRE Workload API سے Pod A کی SVID بازیافت کریں۔ چیک کریں کہ آیا یہ موجود ہے۔ CiliumNetworkPolicy اس کنکشن کے لیے باہمی تصدیق کی ضرورت ہے۔ اگر موجود ہو، تو یہ Pod B نوڈ پر Cilium ایجنٹ کے ساتھ TLS ہینڈ شیک کرتا ہے، Pod A کا SVID پیش کرتا ہے اور بدلے میں Pod B کے SVID کی درخواست کرتا ہے۔

دونوں ایجنٹ SPIRE ٹرسٹ بنڈل کے خلاف SVID چیک کرتے ہیں۔ اگر دونوں SVIDs درست ہیں اور پالیسی کنکشن کی اجازت دیتی ہے تو یہ جاری رہتا ہے۔ اگر SVID غلط ہے یا غائب ہے تو کنکشن منقطع ہو جائے گا۔

Pod A میں ایپلی کیشن Pod B میں موجود ایپلیکیشن سے ڈیٹا حاصل کرتی ہے۔ نہ ہی ایپلیکیشن نے کوئی TLS کوڈ لکھا ہے۔ نہ ہی کوئی سائیڈ کار ہے۔ تصدیق مکمل طور پر اس نوڈ پر Cilium ایجنٹ کے ذریعہ کی گئی تھی۔

Cilium ماڈل میں، Cilium ایجنٹ خود SPIRE سے SPIFFE ID حاصل کرتا ہے۔ ایک ڈیلیگیٹ ID کے طور پر کام کرتا ہے جو کام کے بوجھ کی جانب سے SVIDs کی درخواست کر سکتا ہے۔

یہ اسٹینڈ اسٹون SPIRE ماڈل سے قدرے مختلف ہے، جہاں ہر کام کا بوجھ براہ راست اپنے SVID کی درخواست کرتا ہے۔ Cilium آپریٹرز SPIRE کے ساتھ کام کے بوجھ کے اندراجات کو خود بخود رجسٹر کرتے ہیں جو کہ وہ Kubernetes IDs کا انتظام کرتے ہیں، جس سے ہر پوڈ کے لیے دستی طور پر SPIRE اندراجات بنانے کی ضرورت ختم ہو جاتی ہے۔

ڈیمو 1 – SPIRE انضمام کے ساتھ Cilium انسٹال کرنا

Cilium کو اپنے CNI کے طور پر استعمال کرتے ہوئے ایک قسم کا کلسٹر بنائیں اور ایک ہیلم کمانڈ کے ساتھ بلٹ ان SPIRE انٹیگریشن کو فعال کریں۔

مرحلہ 1: Cilium CLI انسٹال کریں۔

# macOS
brew install cilium-cli

# Linux
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --remote-name-all 
  https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz
sudo tar -xzf cilium-linux-amd64.tar.gz -C /usr/local/bin

مرحلہ 2: ڈیفالٹ CNI کے بغیر ایک قسم کا کلسٹر بنائیں

آپ کو اس قسم کے ڈیفالٹ CNI (kindnet) کو غیر فعال کرنے کی ضرورت ہوگی تاکہ Cilium اسے سنبھال سکے۔ اس کو بطور محفوظ کریں۔ kind-cilium.yaml:

# kind-cilium.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
networking:
  disableDefaultCNI: true   # Required: let Cilium be the CNI
  kubeProxyMode: none       # Cilium replaces kube-proxy too
kind create cluster --name k8s-mtls --config kind-cilium.yaml

نوڈ ہے NotReady Cilium انسٹال ہونے تک یہ اسی حالت میں رہے گا۔ یہ متوقع ہے، کیونکہ ابھی تک کوئی CNI نہیں ہے۔

مرحلہ 3: SPIRE فعال کے ساتھ Cilium انسٹال کریں۔

کیونکہ مرحلہ 2 سیٹ ہے۔ kubeProxyMode: noneCilium کو خود ایک کیوب پراکسی کے طور پر کام کرنا چاہیے۔ اس کا مطلب یہ ہے کہ بوٹسٹریپ پوڈ API سرور تک نہیں پہنچ سکتے بذریعہ: kubernetes کلسٹر آئی پی سروس۔ اس کی وجہ یہ ہے کہ ابھی تک کچھ بھی نہیں ہے۔

آپ کو API سرور کا اصل پتہ پہلے سے پاس کرنا ہوگا۔ Docker میں قسم کے کنٹرول طیارے کا IP حاصل کریں۔

API_SERVER_IP=$(docker inspect k8s-mtls-control-plane 
  --format="{{ .NetworkSettings.Networks.kind.IPAddress }}")
echo "API_SERVER_IP=$API_SERVER_IP"

پھر SPIRE کے ساتھ Cilium انسٹال کریں۔

helm repo add cilium https://helm.cilium.io/
helm repo update

helm upgrade cilium cilium/cilium 
  --install 
  --namespace kube-system 
  --set kubeProxyReplacement=true 
  --set k8sServiceHost=${API_SERVER_IP} 
  --set k8sServicePort=6443 
  --set authentication.enabled=true 
  --set authentication.mutual.spire.enabled=true 
  --set authentication.mutual.spire.install.enabled=true 
  --set authentication.mutual.spire.install.server.dataStorage.enabled=false

ان میں سے کچھ جھنڈوں کو یاد کرنا آسان ہے، لیکن ہر ایک پر بوجھ ہے۔

  • kubeProxyReplacement=true: Cilium kube-proxy کے لیے eBPF پر مبنی متبادل انسٹال کرتا ہے۔ جب بھی قسم کی کنفیگریشن سیٹ کی جاتی ہے تو اس کی ضرورت ہوتی ہے۔ kubeProxyMode: none.

  • k8sServiceHost / k8sServicePort: Cilium سروس ClusterIP کو روٹ کرنے سے پہلے بوٹسٹریپنگ کے دوران استعمال ہونے والا ڈائریکٹ API سرور ایڈریس۔ EKS/GKE/AKS میں یہ ضروری نہیں ہے کیونکہ kube-proxy اب بھی انسٹالیشن کے دوران موجود ہے۔

  • authentication.enabled=true: کے ساتھ درکار ہے۔ authentication.mutual.spire.enabled=true. چارٹ کے validate.yaml استعمال کرتے ہوئے انسٹالیشن سے انکار کریں: SPIRE integration requires .Values.authentication.enabled=true and .Values.authentication.mutual.spire.enabled=true اگر صرف باہمی جھنڈا قائم کیا جائے۔

  • dataStorage.enabled=false: SPIRE سرور کو PVC کی حمایت یافتہ ڈیٹا اسٹوریج سے ان میموری میں تبدیل کریں۔ یہ لیب کلسٹرز کے لیے ٹھیک ہے، لیکن پروڈکشن میں اسے فعال رہنے دیں اور یقینی بنائیں کہ آپ کے کلسٹر پر PertantVolume کی سہولت ہے۔

براہ کرم نوٹ کریں کہ نہیں ہے۔ --wait یہاں اپنا جھنڈا لگائیں۔ نئے کلسٹر میں --wait ایسا لگتا ہے کہ یہ ناکام ہو جائے گا context deadline exceeded اس کی وجہ یہ ہے کہ اس کے ڈیزائن کی وجہ سے تنصیب مشکل ہے۔ SPIRE سرورز کو مندرجہ ذیل طور پر محفوظ کیا جانا چاہیے: NotReady اجازت کا شکریہ، نوڈ فعال ہو جاتا ہے، ایک Cilium ایجنٹ SPIRE کا استعمال کرتے ہوئے ابھرتا ہے، اور پھر نوڈ اس پر سوئچ کرتا ہے: Ready. انسٹالیشن کو فوری طور پر واپس آنے دیں اور اگلے ~2 منٹ میں پوڈز کو نمودار ہوتے دیکھیں۔

kubectl get pods -A -w

مرحلہ 4: تنصیب کی تصدیق کریں۔

cilium status --wait
    /¯¯
 /¯¯__/¯¯    Cilium:             OK
 __/¯¯__/    Operator:           OK
 /¯¯__/¯¯    Envoy DaemonSet:    OK
 __/¯¯__/    Hubble Relay:       disabled
    __/       ClusterMesh:        disabled

DaemonSet              cilium             Desired: 3, Ready: 3/3, Available: 3/3
DaemonSet              cilium-envoy       Desired: 3, Ready: 3/3, Available: 3/3
Deployment             cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2

SPIRE اجزاء کو چیک کریں: 3 Cilium ایجنٹس، ایک فی نوڈ، بشمول کنٹرول جہاز (قسم کی ترتیب میں کوئی آلودگی نہیں)۔ cilium-spire نام کی جگہ:

kubectl get all -n cilium-spire
NAME                    READY   STATUS    RESTARTS   AGE
pod/spire-agent-2cpsr   1/1     Running   0          3m
pod/spire-agent-klhjx   1/1     Running   0          3m
pod/spire-agent-vhsnc   1/1     Running   0          3m
pod/spire-server-0      2/2     Running   0          3m

NAME                              TYPE        CLUSTER-IP    PORT(S)    AGE
service/spire-server              ClusterIP   10.96.x.x     8081/TCP   3m

NAME                          DESIRED   CURRENT   READY   AGE
daemonset.apps/spire-agent    3         3         3       3m

NAME                             READY   AGE
statefulset.apps/spire-server    1/1     3m

ایک SPIRE ایجنٹ فی نوڈ۔ SPIRE سرور دو کنٹینرز کے ساتھ ایک اسٹیٹفول سیٹ ہے: سرور خود اور SPIRE کنٹرولر مینیجر، جو خود کار طریقے سے Cilium ID کے لیے ورک لوڈ رجسٹریشن اندراجات تخلیق کرتا ہے۔

SPIRE سرور پر ہیلتھ چیک چلائیں۔

kubectl exec -n cilium-spire spire-server-0 -c spire-server -- 
  /opt/spire/bin/spire-server healthcheck
Server is healthy.

تصدیق کریں کہ SPIRE ایجنٹ کی تصدیق ہے۔

kubectl exec -n cilium-spire spire-server-0 -c spire-server -- 
  /opt/spire/bin/spire-server agent list
Found 3 attested agents:

SPIFFE ID         : spiffe://spiffe.cilium/spire/agent/k8s_psat/default/
Attestation type  : k8s_psat
Expiration time   : 2026-05-17 21:08:47 +0000 UTC
Serial number     : 91532884191503307904684123063465502141
Can re-attest     : true

SPIFFE ID         : spiffe://spiffe.cilium/spire/agent/k8s_psat/default/
...

تینوں ایجنٹس، ایک فی نوڈ، Kubernetes PSAT کے ساتھ تصدیق شدہ ہیں۔ SPIRE سرور تمام نوڈس پر بھروسہ کرتا ہے اور SVIDs کو ان نوڈس پر چلنے والے ورک بوجھ کے لیے جاری کرتا ہے۔

اس وقت، شناخت کا پلیٹ فارم مکمل طور پر تیار ہے، لیکن ابھی تک اسے کچھ بھی استعمال نہیں کر رہا ہے۔ ڈیمو 1 میں ہم نے مندرجہ ذیل مشین بنائی: مسئلہ کرپٹو شناخت۔ ڈیمو 2، جسے ہم آگے دیکھیں گے، اس نظام کو حرکت میں لاتا ہے، اور اس SVID کو دو حقیقی خدمات کے درمیان زبردستی باہمی TLS پالیسی میں بدل دیتا ہے۔ ڈیمو 1 سے کلسٹر چلانا جاری رکھیں کیونکہ ڈیمو 2 براہ راست کلسٹر پر بنتا ہے۔

ڈیمو 2 – CiliumNetworkپالیسی کا استعمال کرتے ہوئے باہمی TLS کو نافذ کرنا

ڈیمو 1 میں، ہم دو خدمات کو تعینات کرنے کے لیے ایک ہی کلسٹر کو منتخب کرتے ہیں۔ CiliumNetworkPolicyیقینی بنائیں کہ تصدیق شدہ ٹریفک کا بہاؤ ہے اور یہ کہ غیر تصدیق شدہ کنکشن مسدود ہیں۔

یہاں کی تمام درخواستیں SPIRE سرور کے ذریعے پاس کردہ SVID سے تصدیق شدہ ہیں جسے ہم نے ابھی چیک کیا ہے۔ یہ دونوں ڈیمو ایک مسلسل ورزش ہیں، اسٹینڈ اکیلے مشقیں نہیں۔

مرحلہ 1: کلائنٹس اور سرورز کو تعینات کریں۔

اس فائل میں سرور اور کلائنٹ دونوں شامل ہیں۔ کلائنٹ ایک سلیپنگ کلپڈ ہے جو پھانسی کے لیے استعمال کیا جائے گا۔

# echo-workloads.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-server
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo-server
  template:
    metadata:
      labels:
        app: echo-server
    spec:
      containers:
        - name: echo-server
          image: ealen/echo-server:latest
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: echo-server
  namespace: default
spec:
  selector:
    app: echo-server
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-client
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo-client
  template:
    metadata:
      labels:
        app: echo-client
    spec:
      containers:
        - name: client
          image: curlimages/curl:latest
          command: ["sleep", "infinity"]
kubectl apply -f echo-workloads.yaml
# kubectl rollout status only takes one resource at a time
kubectl rollout status deployment/echo-server -n default
kubectl rollout status deployment/echo-client -n default

مرحلہ 2: بغیر تصدیق کے ٹریفک کے بہاؤ کی تصدیق کریں۔

ایم ٹی ایل ایس کو نافذ کرنے سے پہلے، یقینی بنائیں کہ آپ کے کلائنٹ آپ کے سرور سے جڑ سکتے ہیں۔

CLIENT=$(kubectl get pod -l app=echo-client -o jsonpath="{.items[0].metadata.name}")
kubectl exec $CLIENT -- curl -s http://echo-server/

آپ کو ایکو سرور سے JSON جواب موصول ہونا چاہئے۔ بغیر تصدیق کے ٹریفک آزادانہ طور پر رواں دواں ہے۔

مرحلہ 3: CiliumNetworkPolicy کا اطلاق کریں جس کے لیے باہمی تصدیق کی ضرورت ہو۔

شامل کرنا authentication.mode: required کو CiliumNetworkPolicy Cilium کو مماثل ٹریفک کے لیے باہمی TLS نافذ کرنے کی ہدایت کرتا ہے۔ کنکشن کے دونوں اطراف کو ایک درست SPIFFE SVID پیش کرنا چاہیے۔

# mtls-policy.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: echo-server-mtls
  namespace: default
spec:
  endpointSelector:
    matchLabels:
      app: echo-server
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: echo-client
      authentication:
        mode: required     # Require mutual TLS for this traffic
kubectl apply -f mtls-policy.yaml

مرحلہ 4: تصدیق کریں کہ تصدیق شدہ ٹریفک جاری ہے۔

kubectl exec $CLIENT -- curl -s http://echo-server/

کنکشن کامیاب ہے۔ Cilium نے اسے روکا اور دونوں پوڈ نوڈس پر Cilium ایجنٹوں کے درمیان SPIFFE mTLS ہینڈ شیک کیا، دونوں SVIDs کی تصدیق کی اور ٹریفک کو گزرنے دیا۔ کلائنٹ کی درخواست نے ایک سادہ HTTP درخواست بھیجی اور جواب موصول ہوا۔ نیٹ ورک پرت پر باہمی تصدیق شفاف ہے۔

مرحلہ 5: ہبل کے ساتھ سرٹیفیکیشن کا مشاہدہ کریں (اختیاری)

ہبل Cilium کی قابل مشاہدہ تہہ ہے۔ آپ کو اپنے CLI کی ضرورت ہوگی۔

# macOS
brew install hubble

# Linux
HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --remote-name-all 
  https://github.com/cilium/hubble/releases/download/${HUBBLE_VERSION}/hubble-linux-amd64.tar.gz
sudo tar -xzf hubble-linux-amd64.tar.gz -C /usr/local/bin

اپنے کلسٹر پر ہبل کو چالو کریں اور بہاؤ دیکھیں۔ cilium hubble enable ہبل ریلے کی تعیناتی۔ اور Cilium ایجنٹ کو اس کے اندر موجود ہبل سرور کو آن کرنے کے لیے دوبارہ شروع کریں، لہذا پورٹ فارورڈنگ سے پہلے اس کے مستحکم ہونے کا انتظار کریں۔ اگر آپ انتظار کرنا چھوڑ دیتے ہیں، تو ریلے کے سننے اور باہر نکلنے سے پہلے پورٹ فارورڈنگ منسلک ہو جاتی ہے: connection reset by peer / rpc error … EOF:

cilium hubble enable
cilium status --wait          # wait for "Hubble Relay: OK" before continuing

cilium hubble port-forward &

# Watch flows for the echo-server (Ctrl-C to stop)
hubble observe --namespace default --pod echo-server --follow

یہ دوسرے ٹرمینل میں ایک اور درخواست کو متحرک کرتا ہے۔

kubectl exec $CLIENT -- curl -s http://echo-server/

ہبل آؤٹ پٹ میں ہم دیکھ سکتے ہیں:


ℹ  Hubble Relay is available at 127.0.0.1:4245
Jul  7 12:44:42.380: default/echo-client-86d446b8f-9bn5v:47500 (ID:2822) -> default/echo-server-7467b4b54d-5tvkz:80 (ID:30854) policy-verdict:none TRAFFIC_DIRECTION_UNKNOWN ALLOWED (TCP Flags: SYN)
Jul  7 12:44:42.380: default/echo-client-86d446b8f-9bn5v:47500 (ID:2822) -> default/echo-server-7467b4b54d-5tvkz:80 (ID:30854) to-endpoint FORWARDED (TCP Flags: SYN)
Jul  7 12:44:42.381: default/echo-client-86d446b8f-9bn5v:47500 (ID:2822) <- default/echo-server-7467b4b54d-5tvkz:80 (ID:30854) to-endpoint FORWARDED (TCP Flags: SYN, ACK)

کہ ALLOWED پر فیصلہ policy-verdict وجہ یہ ہے کہ CiliumNetworkPolicy مماثل ہے اور تصدیق کی ہے۔ کوئی سائڈ کار شامل نہیں ہے۔ یہ Cilium ایجنٹ کے ساتھ ہوا.

گرافیکل منظر کو ترجیح دیں؟ ہبل UI کو فعال کریں۔ مذکورہ بالا سبھی API + ٹرمینل راستے ہیں (پورٹ 4245 پر ریلے ہے۔ hubble CLI)۔ ہبل ریئل ٹائم سروس میپس کے ساتھ ایک ویب ڈیش بورڈ بھی پیش کرتا ہے۔ cilium hubble enable کرو ~ نہیں پہلے سے طے شدہ طور پر یہ اس سے شروع ہوتا ہے:

# Add the UI (re-runs enable, keeps Relay, adds the hubble-ui deployment)
cilium hubble enable --ui

# Wait for it to be Ready before opening — same race as Relay. Skip this and
# `cilium hubble ui` fails with "connection refused" on port 8081, because the
# UI's frontend container isn't listening yet.
kubectl -n kube-system rollout status deployment/hubble-ui --timeout=90s

# Port-forwards hubble-ui and opens http://localhost:12000 in your browser
cilium hubble ui

منتخب کریں default ڈراپ ڈاؤن سے نام کی جگہ منتخب کریں۔ یہ وہ جگہ ہے جہاں ڈیمو پوڈز اور پالیسیاں واقع ہیں۔ نقشہ ہے زندہ: بیکار نام کی جگہ خالی دکھائی دیتی ہے کیونکہ جب بہاؤ ہوتا ہے تو یہ کناروں کو پیش کرتا ہے۔ لائٹ آن کرنے کی درخواست کو متحرک کریں۔

kubectl exec $CLIENT -- curl -s http://echo-server/

اہم کنارہ دکھائی دے رہا ہے۔ echo-client → echo-server. پڑھنے کے لیے کلک کریں (یا نیچے فلو چارٹ کھولیں)۔ policy-verdict: ALLOWED. UI کو مرحلہ 6 تک کھلا چھوڑ دیں۔ اگر آپ وہاں ایک بدمعاش کلائنٹ ٹیسٹ چلاتے ہیں، تو کنکشن کو سرخ رنگ میں نشان زد کیا جائے گا۔ گر گیا کنارے، بصری ہم منصب curl ٹائم آؤٹ

UI تین حصوں پر مشتمل ہے:

کہ سروس کا نقشہ سب سے اوپر، ہم ہر کام کے بوجھ کی شناخت کو ایک باکس کے طور پر اور ہر مشاہدہ کنکشن کو اس کے فیصلے کے مطابق رنگین کنارے کے طور پر کھینچتے ہیں۔ echo-client → echo-server:80 سبز (ڈیلیور شدہ) کنارے ہیں اور باکس پر لیبل لگا ہوا ہے۔ default (بس unauthorized ایک پوڈ جو صرف نام کی جگہ ID کو پاس کرتا ہے کیونکہ کوئی نام کی جگہ ID نہیں ہے۔ app چونکہ یہ ایک لیبل ہے، اس لیے ہبل کا نام اس کے نام پر رکھا گیا ہے) echo-server سرخ نقطے والی (گرا ہوا) لائن پر لاک کریں۔ echo-serverایس → 80 TCP پورٹ اپنے اختتامی نقطہ کو پالیسی کے ذریعہ باہمی طور پر تصدیق شدہ کے طور پر نشان زد کرتا ہے۔

کہ بہاؤ کی میز ذیل میں، ایک قطار فی بہاؤ (ذریعہ ID، منزل کی ID، منزل کی بندرگاہ، L7 معلومات) ریکارڈ کی گئی ہے۔ Verdictاور ٹائم سٹیمپ. یہ آپ کو دونوں نتائج کو ساتھ ساتھ پڑھنے کی اجازت دیتا ہے۔ echo-client → echo-server نشان زد قطار پہنچایا اور default → echo-server نشان زد قطار گر گیا. یہ CLI (ایک لائن فی پیکٹ) کی طرح تقسیم کی اجازت/انکار ہے۔

کہ سب سے اوپر بار نام کی جگہ سلیکٹر، فلو فلٹر، Any verdict / Visual ٹوگل کریں، اور لائیو flows/s رپورٹنگ نوڈس کی تعداد کے ساتھ، تناسب (3/3

مرحلہ 6: تصدیق کریں کہ مماثل لیبل کے بغیر پوڈز مسدود ہیں۔

اس کے بغیر تیسرا پوڈ تعینات کریں۔ echo-client ایک لیبل کی وضاحت کریں اور سرور سے جڑنے کی کوشش کریں۔

# unauthorized-client.yaml
apiVersion: v1
kind: Pod
metadata:
  name: unauthorized
  namespace: default
spec:
  containers:
    - name: client
      image: curlimages/curl:latest
      command: ["sleep", "infinity"]
kubectl apply -f unauthorized-client.yaml
kubectl wait --for=condition=Ready pod/unauthorized --timeout=60s
kubectl exec unauthorized -- curl -sS --max-time 5 http://echo-server/
curl: (28) Connection timed out after 5000 milliseconds

کنکشن کا وقت ختم ہو گیا۔ کہ CiliumNetworkPolicy صرف ان پوڈوں سے استقبال کی اجازت دیں جن میں شامل ہیں: app: echo-client. اس لیبل کے بغیر پوڈز کو SVID میچنگ اور پالیسی میچنگ نہیں ملے گی۔ Cilium خود بخود ٹریفک کو گرا دیتا ہے۔

یہاں دو مسائل سے آگاہ ہونا ضروری ہے۔ چلائیں kubectl wait چلانے سے پہلے۔ exec بہت تیزی سے چل رہا ہے apply اور آپ کو ملتا ہے container not found ("client") اس کی وجہ یہ ہے کہ پوڈ کا کنٹینر ابھی شروع نہیں ہوا ہے۔

اور استعمال کریں curl -sSعام نہیں -s. صرف -scurl غلطی کے متن کو نگلتا ہے اور آپ صرف دیکھ سکتے ہیں۔ command terminated with exit code 28. نتیجہ ایک ہی ہے - 28 ہے کرل کا ٹائم آؤٹ کوڈ - لیکن -S پڑھنے کے قابل پیغامات کو بحال کریں۔ حقیقت یہ ہے کہ ٹائم آؤٹ ہوا ("کنکشن سے انکار" کے بجائے) پالیسی کا دستخط ہے۔ اتر جاؤ:پیکٹس کو فعال طور پر مسترد کرنے کے بجائے خود بخود بلیک ہول کر دیا جاتا ہے۔ اگر میں انکار کرتا ہوں تو مجھے فوری طور پر ایک اور غلطی ہو جاتی ہے۔

مرحلہ 7: SPIRE میں کام کے بوجھ کے اندراجات کو چیک کریں۔

Cilium کے SPIRE کنٹرولر مینیجر نے اس کلسٹر کی Cilium سیکورٹی شناخت کے لیے خود بخود ایک SPIFFE ID بنائی ہے۔ آپ انہیں دیکھ سکتے ہیں:

kubectl exec -n cilium-spire spire-server-0 -c spire-server -- 
  /opt/spire/bin/spire-server entry show 
  -selector cilium:mutual-auth

ہر اندراج Cilium سیکورٹی ID کو SPIFFE ID سے نقشہ بناتا ہے۔ Cilium آپریٹرز خود بخود اس رجسٹری کا نظم کرتے ہیں، لہذا Cilium کے بلٹ ان انٹیگریشنز کا استعمال کرتے وقت آپ کو کام کے بوجھ کو دستی طور پر رجسٹر کرنے کی ضرورت نہیں ہے۔

نتیجہ

آپ کا IP پتہ آپ کا مقام ہے، آپ کی شناخت نہیں۔ اور Kubernetes میں، مقامات ہر تعیناتی کے ساتھ تبدیل ہوتے ہیں، اس لیے ایڈریس کے ملاپ پر مبنی کوئی بھی پالیسی وقت کے ساتھ ساتھ خود بخود تنزلی کا شکار ہو جاتی ہے۔

کرپٹوگرافک ورک بوجھ کی شناخت بنیادی طور پر اسے ٹھیک کرتی ہے۔ SPIFFE ماڈل کی وضاحت کرتا ہے (SPIFFE ID ٹرسٹ ڈومین کے اندر کام کے بوجھ کو نام دیتا ہے، اور X.509 SVID اسے ایک سرٹیفکیٹ میں تبدیل کرتا ہے جس کی کوئی بھی TLS لائبریری تصدیق کر سکتی ہے) اور SPIRE اسے نافذ کرتا ہے۔ سرورز CA اور رجسٹری ہیں، اور فی نوڈ ایجنٹ Kubernetes PSAT کے ذریعے تصدیق کرتے ہیں اور قلیل المدتی، خودکار گھومنے والی SVIDs جاری کرتے ہیں۔

Cilium تہوں کی شناخت کرتا ہے اور انہیں نیٹ ورک سے جوڑتا ہے۔ شامل کریں authentication.mode: required CiliumNetworkPolicy اور اس کا eBPF ایجنٹ دونوں کام کے بوجھ کے SVIDs حاصل کرتے ہیں، باہمی TLS ہینڈ شیک کرتے ہیں، اور نتائج کو نافذ کرتے ہیں۔ سروس میش کے مقابلے میں کوئی سائیڈ کارز نہیں ہیں، کوئی ایپلیکیشن تبدیلیاں نہیں ہیں، اور تقریبا صفر اوور ہیڈ ہیں۔ اور ہم نے ایک ہی ہیلم کمانڈ کے ساتھ پورے اسٹیک کو تعینات کیا۔ پیچیدگی بنیادی ڈھانچے میں ہے، کوڈ میں نہیں۔

صفائی (قسم)

# Delete demo workloads
kubectl delete deployment echo-server echo-client -n default
kubectl delete service echo-server -n default
kubectl delete pod unauthorized -n default
kubectl delete ciliumnetworkpolicy echo-server-mtls -n default

# Uninstall Cilium (helm doesn't delete the cilium-spire namespace it created)
helm uninstall cilium -n kube-system
kubectl delete namespace cilium-spire

# Delete the cluster (easiest reset on kind)
kind delete cluster --name k8s-mtls

Scroll to Top