من الحياة مع Kubernetes: كيف لم يشتك خادم Spaniards HTTP



واجه ممثل عملائنا ، الذي يعيش مكدس تطبيقاته في السحابة من Microsoft (Azure) ، مشكلة: في الآونة الأخيرة ، بدأ جزء من طلبات بعض العملاء من أوروبا ينتهي بالخطأ 400 ( طلب غير صحيح). تتم كتابة جميع التطبيقات في. NET ، نشرت في Kubernetes ...

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



الخطأ في Ingress يشبه هذا:

{ "number_fields":{ "status":400, "request_time":0.001, "bytes_sent":465, "upstream_response_time":0, "upstream_retries":0, "bytes_received":2328 }, "stream":"stdout", "string_fields":{ "ingress":"app", "protocol":"HTTP/1.1", "request_id":"f9ab8540407208a119463975afda90bc", "path":"/api/sign-in", "nginx_upstream_status":"400", "service":"app", "namespace":"production", "location":"/front", "scheme":"https", "method":"POST", "nginx_upstream_response_time":"0.000", "nginx_upstream_bytes_received":"120", "vhost":"api.app.example.com", "host":"api.app.example.com", "user":"", "address":"83.41.81.250", "nginx_upstream_addr":"10.240.0.110:80", "referrer":"https://api.app.example.com/auth/login?long_encrypted_header", "service_port":"http", "user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36", "time":"2019-03-06T18:29:16+00:00", "content_kind":"cache-headers-not-present", "request_query":"" }, "timestamp":"2019-03-06 18:29:16", "labels":{ "app":"nginx", "pod-template-generation":"6", "controller-revision-hash":"1682636041" }, "namespace":"kube-nginx-ingress", "nsec":6726612, "source":"kubernetes", "host":"k8s-node-55555-0", "pod_name":"nginx-v2hcb", "container_name":"nginx", "boolean_fields":{} } 

في الوقت نفسه ، أعطى كيستريل:

 HTTP/1.1 400 Bad Request Connection: close Date: Wed, 06 Mar 2019 12:34:20 GMT Server: Kestrel Content-Length: 0 

حتى مع الحد الأقصى للفظ ، فإن خطأ Kestrel يحتوي على معلومات مفيدة للغاية:

 { "number_fields":{"ThreadId":76}, "stream":"stdout", "string_fields":{ "EventId":"{\"Id\"=>17, \"Name\"=>\"ConnectionBadRequest\"}", "SourceContext":"Microsoft.AspNetCore.Server.Kestrel", "ConnectionId":"0HLL2VJSST5KV", "@mt":"Connection id \"{ConnectionId}\" bad request data: \"{message}\"", "@t":"2019-03-07T13:06:48.1449083Z", "@x":"Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers.\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequestsAsync>d__185`1.MoveNext()", "message":"Malformed request: invalid headers." }, "timestamp":"2019-03-07 13:06:48", "labels":{ "pod-template-hash":"2368795483", "service":"app" }, "namespace":"production", "nsec":145341848, "source":"kubernetes", "host":"k8s-node-55555-1", "pod_name":"app-67bdcf98d7-mhktx", "container_name":"app", "boolean_fields":{} } 

يبدو أن tcpdump فقط هو الذي سيساعد في حل هذه المشكلة ... لكنني سأكررها حول سلسلة المرور:



تحقيق


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

 GET /back/user HTTP/1.1 Host: api.app.example.com X-Request-ID: 27ceb14972da8c21a8f92904b3eff1e5 X-Real-IP: 83.41.81.250 X-Forwarded-For: 83.41.81.250 X-Forwarded-Host: api.app.example.com X-Forwarded-Port: 443 X-Forwarded-Proto: https X-Original-URI: /front/back/user X-Scheme: https X-Original-Forwarded-For: 83.41.81.250 X-Nginx-Geo-Client-Country: Spain X-Nginx-Geo-Client-City: M.laga Accept-Encoding: gzip CF-IPCountry: ES CF-RAY: 4b345cfd1c4ac691-MAD CF-Visitor: {"scheme":"https"} pragma: no-cache cache-control: no-cache accept: application/json, text/plain, */* origin: https://app.example.com user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36 referer: https://app.example.com/auth/login accept-language: en-US,en;q=0.9,en-GB;q=0.8,pl;q=0.7 cookie: many_encrypted_cookies; .AspNetCore.Identity.Application=something_encrypted; CF-Connecting-IP: 83.41.81.250 True-Client-IP: 83.41.81.250 CDN-Loop: cloudflare HTTP/1.1 400 Bad Request Connection: close Date: Wed, 06 Mar 2019 12:34:20 GMT Server: Kestrel Content-Length: 0 

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

  ingress.kubernetes.io/configuration-snippet: | proxy_set_header X-Nginx-Geo-Client-Country $geoip_country_name; proxy_set_header X-Nginx-Geo-Client-City $geoip_city; 

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

الآن دعونا ننظر إلى المشكلة بطريقة أكثر عمومية . يمكن إعادة إنتاجه بسهولة داخل التطبيق إذا قمت بتقديم طلب telnet إلى localhost:80 :

 GET /back/user HTTP/1.1 Host: api.app.example.com cache-control: no-cache accept: application/json, text/plain, */* origin: https://app.example.com Cookie: test=Desiree 

... 401 Unauthorized عوائد 401 Unauthorized ، كما هو متوقع. وماذا يحدث إذا فعلنا:

 GET /back/user HTTP/1.1 Host: api.app.example.com cache-control: no-cache accept: application/json, text/plain, */* origin: https://app.example.com Cookie: test=Désirée 

؟

سيعود 400 Bad request - في سجل التطبيق ، سوف نحصل على الخطأ الذي نعرفه بالفعل:

 { "@t":"2019-03-31T12:59:54.3746446Z", "@mt":"Connection id \"{ConnectionId}\" bad request data: \"{message}\"", "@x":"Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers.\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection.TryParseRequest(ReadResult result, Boolean& endConnection)\n at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<ProcessRequestsAsync>d__185`1.MoveNext()", "ConnectionId":"0HLLLR1J974L9", "message":"Malformed request: invalid headers.", "EventId":{ "Id":17, "Name":"ConnectionBadRequest" }, "SourceContext":"Microsoft.AspNetCore.Server.Kestrel", "ThreadId":71 } 

النتائج


على وجه التحديد ، لا يمكن لـ Kestrel معالجة رؤوس HTTP بشكل صحيح مع الأحرف الصحيحة في UTF-8 ، والمضمنة في أسماء عدد كبير إلى حد ما من المدن.

هناك عامل إضافي في حالتنا هو أن العميل لا يخطط حاليًا لتغيير تطبيق Kestrel في التطبيق. ومع ذلك ، تقول المشكلات في AspNetCore نفسها ( رقم 4318 ، رقم 7707 ) أن هذا لن يساعد ...

للتلخيص: لم تعد الملاحظة تدور حول المشكلات المحددة لـ Kestrel أو UTF-8 (في عام 2019 ، السنة؟!) ، ولكن الاهتمام والدراسة المتسقة لكل خطوة أثناء البحث عن مشكلة ستؤتي ثمارها عاجلاً أم آجلاً. حظا سعيدا

PS


اقرأ أيضًا في مدونتنا:

Source: https://habr.com/ru/post/ar448420/


All Articles