"Kubernetes نے تاخیر میں 10 گنا اضافہ کیا": اس کا ذمہ دار کون ہے؟

نوٹ. ترجمہ: یہ مضمون، Galo Navarro کا لکھا ہوا، جو یورپی کمپنی Adevinta میں پرنسپل سافٹ ویئر انجینئر کے عہدے پر فائز ہیں، انفراسٹرکچر آپریشنز کے شعبے میں ایک دلچسپ اور سبق آموز "تحقیقات" ہے۔ اس کا اصل عنوان ترجمے میں اس وجہ سے قدرے بڑھایا گیا تھا جس کی وضاحت مصنف نے شروع ہی میں کی ہے۔

"Kubernetes نے تاخیر میں 10 گنا اضافہ کیا": اس کا ذمہ دار کون ہے؟

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

چند ہفتے پہلے، میری ٹیم ایک واحد مائیکرو سروس کو ایک بنیادی پلیٹ فارم پر منتقل کر رہی تھی جس میں CI/CD، Kubernetes پر مبنی رن ٹائم، میٹرکس، اور دیگر سامان شامل تھے۔ یہ اقدام آزمائشی نوعیت کا تھا: ہم نے اسے بنیاد کے طور پر لینے اور آنے والے مہینوں میں تقریباً 150 مزید خدمات منتقل کرنے کا منصوبہ بنایا۔ یہ سب اسپین کے سب سے بڑے آن لائن پلیٹ فارمز (Infojobs، Fotocasa، وغیرہ) کے کام کے لیے ذمہ دار ہیں۔

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

EC2 کے مقابلے Kubernetes میں تاخیر اتنی زیادہ کیوں ہے؟

رکاوٹ تلاش کرنے کے لیے، ہم نے درخواست کے پورے راستے کے ساتھ میٹرکس اکٹھا کیا۔ ہمارا فن تعمیر آسان ہے: ایک API گیٹ وے (Zuul) پراکسیز EC2 یا Kubernetes میں مائیکرو سرویس مثالوں کی درخواست کرتی ہیں۔ Kubernetes میں ہم NGINX Ingress کنٹرولر استعمال کرتے ہیں، اور بیک اینڈز عام اشیاء ہیں جیسے تعیناتی اسپرنگ پلیٹ فارم پر JVM ایپلیکیشن کے ساتھ۔

                                  EC2
                            +---------------+
                            |  +---------+  |
                            |  |         |  |
                       +-------> BACKEND |  |
                       |    |  |         |  |
                       |    |  +---------+  |                   
                       |    +---------------+
             +------+  |
Public       |      |  |
      -------> ZUUL +--+
traffic      |      |  |              Kubernetes
             +------+  |    +-----------------------------+
                       |    |  +-------+      +---------+ |
                       |    |  |       |  xx  |         | |
                       +-------> NGINX +------> BACKEND | |
                            |  |       |  xx  |         | |
                            |  +-------+      +---------+ |
                            +-----------------------------+

ایسا لگتا ہے کہ مسئلہ پسدید میں ابتدائی تاخیر سے متعلق ہے (میں نے گراف پر مسئلہ کے علاقے کو "xx" کے بطور نشان زد کیا)۔ EC2 پر، درخواست کے جواب میں تقریباً 20ms لگے۔ Kubernetes میں، تاخیر 100-200 ms تک بڑھ گئی۔

ہم نے رن ٹائم تبدیلی سے متعلق ممکنہ مشتبہ افراد کو فوری طور پر برخاست کر دیا۔ JVM ورژن وہی رہتا ہے۔ کنٹینرائزیشن کے مسائل کا بھی اس سے کوئی تعلق نہیں تھا: ایپلیکیشن EC2 پر کنٹینرز میں پہلے ہی کامیابی سے چل رہی تھی۔ لوڈ ہو رہا ہے؟ لیکن ہم نے فی سیکنڈ 1 درخواست پر بھی زیادہ تاخیر کا مشاہدہ کیا۔ کچرا اٹھانے کے وقفوں کو بھی نظر انداز کیا جا سکتا ہے۔

ہمارے Kubernetes کے منتظمین میں سے ایک نے حیرت کا اظہار کیا کہ آیا ایپلیکیشن کا بیرونی انحصار ہے کیونکہ DNS سوالات نے ماضی میں اسی طرح کے مسائل پیدا کیے تھے۔

مفروضہ 1: DNS نام کی قرارداد

ہر درخواست کے لیے، ہماری ایپلیکیشن AWS Elasticsearch مثال تک ایک سے تین بار ڈومین میں رسائی حاصل کرتی ہے جیسے elastic.spain.adevinta.com. ہمارے کنٹینرز کے اندر ایک شیل ہے، لہذا ہم چیک کر سکتے ہیں کہ آیا کسی ڈومین کی تلاش میں درحقیقت زیادہ وقت لگتا ہے۔

کنٹینر سے DNS سوالات:

[root@be-851c76f696-alf8z /]# while true; do dig "elastic.spain.adevinta.com" | grep time; sleep 2; done
;; Query time: 22 msec
;; Query time: 22 msec
;; Query time: 29 msec
;; Query time: 21 msec
;; Query time: 28 msec
;; Query time: 43 msec
;; Query time: 39 msec

EC2 مثالوں میں سے ایک سے ملتی جلتی درخواستیں جہاں درخواست چل رہی ہے:

bash-4.4# while true; do dig "elastic.spain.adevinta.com" | grep time; sleep 2; done
;; Query time: 77 msec
;; Query time: 0 msec
;; Query time: 0 msec
;; Query time: 0 msec
;; Query time: 0 msec

اس بات پر غور کرتے ہوئے کہ تلاش میں لگ بھگ 30ms کا وقت لگا، یہ واضح ہو گیا کہ Elasticsearch تک رسائی کے دوران DNS ریزولوشن درحقیقت تاخیر میں اضافے میں معاون ثابت ہو رہا ہے۔

تاہم، یہ دو وجوہات کی بناء پر عجیب تھا:

  1. ہمارے پاس پہلے سے ہی ایک ٹن Kubernetes ایپلی کیشنز موجود ہیں جو AWS وسائل کے ساتھ اعلیٰ تاخیر کا شکار ہوئے بغیر تعامل کرتی ہیں۔ وجہ کچھ بھی ہو، اس کا تعلق خاص طور پر اس کیس سے ہے۔
  2. ہم جانتے ہیں کہ JVM ان میموری DNS کیچنگ کرتا ہے۔ ہماری تصاویر میں، TTL قدر لکھی ہوئی ہے۔ $JAVA_HOME/jre/lib/security/java.security اور 10 سیکنڈ پر سیٹ کریں: networkaddress.cache.ttl = 10. دوسرے لفظوں میں، JVM کو تمام DNS سوالات کو 10 سیکنڈ کے لیے کیش کرنا چاہیے۔

پہلے مفروضے کی تصدیق کرنے کے لیے، ہم نے کچھ دیر کے لیے DNS کو کال کرنا بند کرنے کا فیصلہ کیا اور دیکھیں کہ آیا مسئلہ دور ہو گیا ہے۔ سب سے پہلے، ہم نے ایپلیکیشن کو دوبارہ ترتیب دینے کا فیصلہ کیا تاکہ یہ ڈومین نام کے بجائے، IP ایڈریس کے ذریعے Elasticsearch کے ساتھ براہ راست رابطہ کرے۔ اس کے لیے کوڈ میں تبدیلی اور ایک نئی تعیناتی کی ضرورت ہوگی، اس لیے ہم نے بس ڈومین کو اس کے آئی پی ایڈریس میں میپ کیا۔ /etc/hosts:

34.55.5.111 elastic.spain.adevinta.com

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

نیٹ ورک کے ذریعے تشخیص

ہم نے کنٹینر کا استعمال کرتے ہوئے ٹریفک کا تجزیہ کرنے کا فیصلہ کیا۔ tcpdumpیہ دیکھنے کے لیے کہ نیٹ ورک پر بالکل کیا ہو رہا ہے:

[root@be-851c76f696-alf8z /]# tcpdump -leni any -w capture.pcap

پھر ہم نے کئی درخواستیں بھیجیں اور ان کی گرفتاری کو ڈاؤن لوڈ کیا (kubectl cp my-service:/capture.pcap capture.pcap) میں مزید تجزیہ کے لیے ویرشکر.

DNS سوالات کے بارے میں کچھ بھی مشکوک نہیں تھا (سوائے ایک چھوٹی سی چیز کے جس کے بارے میں میں بعد میں بات کروں گا)۔ لیکن ہماری سروس کے ہر درخواست کو سنبھالنے کے طریقے میں کچھ عجیب و غریب چیزیں تھیں۔ ذیل میں کیپچر کا ایک اسکرین شاٹ ہے جس میں دکھایا گیا ہے کہ جواب شروع ہونے سے پہلے درخواست کو قبول کیا جا رہا ہے:

"Kubernetes نے تاخیر میں 10 گنا اضافہ کیا": اس کا ذمہ دار کون ہے؟

پیکیج نمبر پہلے کالم میں دکھائے گئے ہیں۔ وضاحت کے لیے، میں نے مختلف TCP اسٹریمز کو کلر کوڈ کیا ہے۔

پیکٹ 328 سے شروع ہونے والی سبز ندی یہ ظاہر کرتی ہے کہ کس طرح کلائنٹ (172.17.22.150) نے کنٹینر (172.17.36.147) سے TCP کنکشن قائم کیا۔ ابتدائی مصافحہ (328-330) کے بعد، پیکیج 331 لایا گیا۔ HTTP GET /v1/.. - ہماری خدمت میں آنے والی درخواست۔ پورے عمل میں 1 ایم ایس لگا۔

گرے اسٹریم (پیکٹ 339 سے) ظاہر کرتا ہے کہ ہماری سروس نے Elasticsearch مثال کو HTTP درخواست بھیجی ہے (کوئی TCP ہینڈ شیک نہیں ہے کیونکہ یہ موجودہ کنکشن استعمال کر رہا ہے)۔ اس میں 18ms لگے۔

اب تک سب کچھ ٹھیک ہے، اور اوقات تقریباً متوقع تاخیر کے مساوی ہیں (20-30 ms جب کلائنٹ سے ماپا جاتا ہے)۔

تاہم، نیلے حصے میں 86ms لگتے ہیں۔ اس میں کیا ہو رہا ہے؟ پیکٹ 333 کے ساتھ، ہماری سروس نے ایک HTTP GET درخواست بھیجی۔ /latest/meta-data/iam/security-credentials، اور اس کے فوراً بعد، اسی TCP کنکشن پر، ایک اور GET کی درخواست /latest/meta-data/iam/security-credentials/arn:...

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

مفروضہ 2: AWS کو غیر ضروری کالز

دونوں اختتامی نقطوں کا تعلق ہے۔ AWS انسٹینس میٹا ڈیٹا API. ہماری مائیکرو سروس اس سروس کو Elasticsearch چلاتے ہوئے استعمال کرتی ہے۔ دونوں کالیں بنیادی اجازت کے عمل کا حصہ ہیں۔ اختتامی نقطہ جس تک پہلی درخواست پر رسائی حاصل کی جاتی ہے مثال کے ساتھ وابستہ IAM کردار کو جاری کرتی ہے۔

/ # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
arn:aws:iam::<account_id>:role/some_role

دوسری درخواست اس مثال کے لئے عارضی اجازتوں کے لئے دوسرے اختتامی نقطہ سے پوچھتی ہے:

/ # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/arn:aws:iam::<account_id>:role/some_role`
{
    "Code" : "Success",
    "LastUpdated" : "2012-04-26T16:39:16Z",
    "Type" : "AWS-HMAC",
    "AccessKeyId" : "ASIAIOSFODNN7EXAMPLE",
    "SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
    "Token" : "token",
    "Expiration" : "2017-05-17T15:09:54Z"
}

کلائنٹ انہیں مختصر مدت کے لیے استعمال کر سکتا ہے اور اسے وقتاً فوقتاً نئے سرٹیفکیٹ حاصل کرنا ہوں گے (اس سے پہلے کہ وہ ہوں۔ Expiration)۔ ماڈل آسان ہے: سیکیورٹی وجوہات کی بنا پر AWS عارضی کلیدوں کو بار بار گھماتا ہے، لیکن کلائنٹ نئے سرٹیفکیٹس کے حصول سے وابستہ کارکردگی کے جرمانے کی تلافی کے لیے انہیں چند منٹ کے لیے کیش کر سکتے ہیں۔

AWS Java SDK کو اس عمل کو منظم کرنے کی ذمہ داری سنبھالنی چاہیے، لیکن کسی وجہ سے ایسا نہیں ہوتا ہے۔

GitHub پر مسائل تلاش کرنے کے بعد، ہمیں ایک مسئلہ درپیش آیا 1921 #. اس نے ہمیں اس سمت کا تعین کرنے میں مدد کی جس میں مزید "کھدائی" کرنا ہے۔

AWS SDK سرٹیفکیٹس کو اپ ڈیٹ کرتا ہے جب درج ذیل میں سے کوئی ایک حالت ہوتی ہے:

  • خاتمے کی تاریخ (Expiration) میں گرنا EXPIRATION_THRESHOLD15 منٹ پر ہارڈ کوڈ کیا گیا۔
  • سرٹیفکیٹس کی تجدید کی آخری کوشش کے بعد سے زیادہ وقت گزر چکا ہے۔ REFRESH_THRESHOLD60 منٹ کے لیے ہارڈ کوڈ کیا گیا۔

ہمیں موصول ہونے والے سرٹیفکیٹس کی اصل میعاد ختم ہونے کی تاریخ دیکھنے کے لیے، ہم نے کنٹینر اور EC2 مثال دونوں سے اوپر دیے گئے cURL کمانڈز کو چلایا۔ کنٹینر سے موصول ہونے والے سرٹیفکیٹ کی میعاد کی مدت بہت کم نکلی: بالکل 15 منٹ۔

اب سب کچھ واضح ہو گیا ہے: پہلی درخواست کے لیے، ہماری سروس کو عارضی سرٹیفکیٹ موصول ہوئے۔ چونکہ وہ 15 منٹ سے زیادہ کے لیے درست نہیں تھے، اس لیے AWS SDK بعد کی درخواست پر انہیں اپ ڈیٹ کرنے کا فیصلہ کرے گا۔ اور یہ ہر درخواست کے ساتھ ہوا۔

سرٹیفکیٹس کی میعاد کم کیوں ہو گئی ہے؟

AWS انسٹینس میٹا ڈیٹا کو EC2 مثالوں کے ساتھ کام کرنے کے لیے ڈیزائن کیا گیا ہے، نہ کہ Kubernetes۔ دوسری طرف، ہم ایپلیکیشن انٹرفیس کو تبدیل نہیں کرنا چاہتے تھے۔ اس کے لیے ہم نے استعمال کیا۔ KIAM - ایک ایسا ٹول جو ہر Kubernetes نوڈ پر ایجنٹوں کا استعمال کرتے ہوئے، صارفین کو (ایک کلسٹر میں ایپلی کیشنز تعینات کرنے والے انجینئرز) کو پوڈز میں کنٹینرز کو IAM رولز تفویض کرنے کی اجازت دیتا ہے گویا وہ EC2 مثالیں ہیں۔ KIAM AWS انسٹینس میٹا ڈیٹا سروس کو کالوں کو روکتا ہے اور انہیں اپنے کیشے سے پروسیس کرتا ہے، جو پہلے انہیں AWS سے موصول ہوا تھا۔ درخواست کے نقطہ نظر سے، کچھ بھی تبدیل نہیں ہوتا.

KIAM pods کو مختصر مدت کے سرٹیفکیٹ فراہم کرتا ہے۔ یہ سمجھ میں آتا ہے کہ پوڈ کی اوسط عمر EC2 مثال سے کم ہے۔ سرٹیفکیٹس کے لیے پہلے سے طے شدہ میعاد کی مدت اسی 15 منٹ کے برابر.

نتیجے کے طور پر، اگر آپ دونوں ڈیفالٹ اقدار کو ایک دوسرے کے اوپر چڑھاتے ہیں، تو ایک مسئلہ پیدا ہوتا ہے۔ درخواست کو فراہم کردہ ہر سرٹیفکیٹ 15 منٹ کے بعد ختم ہو جاتا ہے۔ تاہم، AWS Java SDK کسی بھی سرٹیفکیٹ کی تجدید پر مجبور کرتا ہے جس کی میعاد ختم ہونے سے پہلے 15 منٹ سے بھی کم وقت باقی ہے۔

نتیجتاً، عارضی سرٹیفکیٹ کو ہر درخواست کے ساتھ تجدید کرنے پر مجبور کیا جاتا ہے، جس میں AWS API کو چند کالیں کرنا پڑتی ہیں اور اس کے نتیجے میں تاخیر میں نمایاں اضافہ ہوتا ہے۔ AWS Java SDK میں ہمیں ملا خصوصیت کی درخواست، جس میں اسی طرح کے مسئلے کا ذکر ہے۔

حل آسان نکلا۔ ہم نے صرف ایک طویل مدت کے ساتھ سرٹیفکیٹس کی درخواست کرنے کے لیے KIAM کو دوبارہ ترتیب دیا۔ ایک بار ایسا ہونے کے بعد، AWS میٹا ڈیٹا سروس کی شرکت کے بغیر درخواستیں آنا شروع ہو گئیں، اور تاخیر EC2 کے مقابلے میں بھی کم سطح پر آ گئی۔

نتائج

ہجرت کے بارے میں ہمارے تجربے کی بنیاد پر، مسائل کے سب سے عام ذرائع میں سے ایک Kubernetes یا پلیٹ فارم کے دیگر عناصر میں کیڑے نہیں ہیں۔ یہ مائیکرو سروسز میں کسی بنیادی خامی کو بھی دور نہیں کرتا ہے جو ہم پورٹ کر رہے ہیں۔ مسائل اکثر اس لیے پیدا ہوتے ہیں کہ ہم مختلف عناصر کو ایک ساتھ رکھتے ہیں۔

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

ہمارے معاملے میں، زیادہ تاخیر Kubernetes، KIAM، AWS Java SDK، یا ہماری مائیکرو سروس میں کیڑے یا خراب فیصلوں کا نتیجہ نہیں تھی۔ یہ دو آزاد ڈیفالٹ ترتیبات کو یکجا کرنے کا نتیجہ تھا: ایک KIAM میں، دوسری AWS Java SDK میں۔ علیحدہ طور پر لیا جائے تو، دونوں پیرامیٹرز معنی خیز ہیں: AWS Java SDK میں فعال سرٹیفکیٹ کی تجدید کی پالیسی، اور KAIM میں سرٹیفکیٹس کی مختصر میعاد کی مدت۔ لیکن جب آپ ان کو اکٹھا کرتے ہیں تو نتائج غیر متوقع ہو جاتے ہیں۔ دو آزاد اور منطقی حلوں کو جوڑنے پر کوئی معنی نہیں رکھتا۔

مترجم سے PS

آپ AWS IAM کو Kubernetes کے ساتھ مربوط کرنے کے لیے KIAM یوٹیلیٹی کے فن تعمیر کے بارے میں مزید جان سکتے ہیں۔ یہ مضمون اس کے تخلیق کاروں سے۔

ہمارے بلاگ پر بھی پڑھیں:

ماخذ: www.habr.com

نیا تبصرہ شامل کریں