Kubernetes ilə həyatdan: HTTP serveri ispanlara necə üstünlük vermədi

Kubernetes ilə həyatdan: HTTP serveri ispanlara necə üstünlük vermədi

Tətbiq yığını Microsoft buludunda (Azure) yerləşən müştərimizin nümayəndəsi bir problemə müraciət etdi: bu yaxınlarda Avropadan bəzi müştərilərin bəzi sorğuları 400 xətası ilə bitməyə başladı (Pis istək). Bütün proqramlar .NET-də yazılıb, Kubernetes-də yerləşdirilib...

Tətbiqlərdən biri bütün trafikin sonda gəldiyi API-dir. Bu trafik HTTP serveri tərəfindən dinlənir Ləzzət, .NET müştərisi tərəfindən konfiqurasiya edilmiş və podda yerləşdirilmişdir. Sazlama ilə, problemi ardıcıl olaraq təkrarlayan xüsusi bir istifadəçinin olması mənasında şanslı idik. Bununla birlikdə, hər şey trafik zənciri ilə çətinləşdi:

Kubernetes ilə həyatdan: HTTP serveri ispanlara necə üstünlük vermədi

Ingress-də səhv belə görünürdü:

{
   "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":{}
}

Eyni zamanda Kestrel verdi:

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

Maksimum təfərrüatla belə, Kestrel səhvi həddindən artıq idi az faydalı məlumat:

{
   "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":{}
}

Görünür ki, yalnız tcpdump bu problemi həll etməyə kömək edəcək ... amma trafik zənciri haqqında təkrar edəcəyəm:

Kubernetes ilə həyatdan: HTTP serveri ispanlara necə üstünlük vermədi

İstintaq

Aydındır ki, trafikə qulaq asmaq daha yaxşıdır həmin xüsusi qovşaqda, Kubernetes bir pod yerləşdirdiyi yerdə: zibilin həcmi elə olacaq ki, ən azı olduqca tez bir şey tapmaq mümkün olacaq. Və həqiqətən də, onu araşdırarkən aşağıdakı çərçivə diqqət çəkdi:

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

Zibilliyə daha yaxından baxanda söz diqqət çəkdi M.laga. İspaniyada M.laga şəhərinin olmadığını təxmin etmək asandır (amma var Malaga). Bu ideyadan istifadə edərək, bir ay əvvəl daxil edilmişi gördük (müştərinin istəyi ilə) Ingress konfiqurasiyalarına baxdıq. "zərərsiz" parça:

    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;

Bu başlıqların yönləndirilməsini söndürdükdən sonra hər şey yaxşı oldu! (Tezliklə aydın oldu ki, tətbiqin özü artıq bu başlıqlara ehtiyac duymur.)

İndi problemə baxaq daha ümumi. Telnet sorğusu edərək proqram daxilində asanlıqla təkrarlana bilər 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

... qayıdır 401 Unauthorized, gözlənildiyi kimi. Etsək nə olar:

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

?

Geri dönəcək 400 Bad request — tətbiq jurnalında artıq bizə tanış olan xəta alacağıq:

{
   "@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
}

Nəticələri

Xüsusilə Kestrel edə bilməz kifayət qədər çox sayda şəhərin adlarında olan UTF-8-də düzgün simvollarla HTTP başlıqlarını düzgün şəkildə emal edin.

Bizim vəziyyətimizdə əlavə bir amil müştərinin hazırda tətbiqdə Kestrel tətbiqini dəyişdirməyi planlaşdırmamasıdır. Bununla belə, AspNetCore-un özündə problemlər (№ 4318, № 7707) deyirlər ki, bu kömək etməyəcək...

Xülasə etmək üçün: qeyd artıq Kestrel və ya UTF-8-in spesifik problemləri haqqında deyil (2019-cu ildə?!), lakin faktdır ki, zehinlilik və ardıcıl öyrənmə Problemləri axtararkən atdığınız hər addım gec-tez öz bəhrəsini verəcək. Uğurlar!

PS

Bloqumuzda da oxuyun:

Mənbə: www.habr.com

Добавить комментарий