Кубернетес менен болгон жашоодон: HTTP сервери испандарга кантип жактырган жок

Кубернетес менен болгон жашоодон: HTTP сервери испандарга кантип жактырган жок

Тиркеме стеки Microsoft булутунда (Azure) жайгашкан биздин кардарыбыздын өкүлү көйгөйдү чечти: жакында Европадан келген кээ бир кардарлардын суроо-талаптары 400 катасы менен аяктай баштады (Жаман өтүнүч). Бардык тиркемелер .NETте жазылган, Kubernetesте...

Тиркемелердин бири API болуп саналат, ал аркылуу бардык трафик акыры келет. Бул трафик HTTP сервери тарабынан угулуп турат кестрел, .NET кардары тарабынан конфигурацияланган жана подкастка жайгаштырылган. Мүчүлүштүктөрдү оңдоо менен биз көйгөйдү ырааттуу түрдө кайра чыгарган белгилүү бир колдонуучу бар экенин түшүндүк. Бирок, баары жол чынжыр менен татаал болгон:

Кубернетес менен болгон жашоодон: HTTP сервери испандарга кантип жактырган жок

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

Кестрел катасы эң көп сөз менен да камтылган аз пайдалуу маалымат:

{
   "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 гана жардам берет окшойт... бирок мен трафик чынжыры жөнүндө кайталайм:

Кубернетес менен болгон жашоодон: HTTP сервери испандарга кантип жактырган жок

изилдөө

Албетте, жол кыймылын уккан жакшы ошол конкреттүү түйүндө, бул жерде Кубернетес поддонду орноткон: таштандынын көлөмү жок дегенде бир нерсени тез табууга мүмкүн болот. Чынында эле, аны карап жатканда, төмөнкү кадр байкалган:

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 шаары жок экенин божомолдоо оңой (бирок бар Малага). Бул идеяны колго алып, биз 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, күтүлгөндөй. Эгер кылсак эмне болот:

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 мүмкүн эмес, бир кыйла көп шаарлардын аталыштарында камтылган UTF-8деги туура символдор менен HTTP баштарын туура иштетүү.

Биздин учурда кошумча фактор - кардар учурда колдонмодо Kestrel ишке ашырууну өзгөртүүнү пландабайт. Бирок, AspNetCore'дун өзүндөгү маселелер (№4318, №7707) бул жардам бербейт деп айтышат...

Кыскача айтканда: эскертүү мындан ары Kestrel же UTF-8дин конкреттүү көйгөйлөрү жөнүндө эмес (2019-жылы?!), бирок бул жөнүндө эстүүлүк жана ырааттуу изилдөө Көйгөйлөрдү издеп жүрүп жасаган ар бир кадамыңыз эртеби-кечпи жемишин берет. Жолуңуз ачык болсун!

PS

Биздин блогдон дагы окуңуз:

Source: www.habr.com

Комментарий кошуу