"Kubernetes tambah latensi kaping 10": sapa sing kudu disalahake?

Cathetan. nerjemahake.: Artikel iki, ditulis dening Galo Navarro, sing nyekel posisi Engineer Perangkat Lunak Utama ing perusahaan Eropa Adevinta, minangka "investigasi" sing menarik lan instruktif ing bidang operasi infrastruktur. Judhul asline rada ditambahi ing terjemahan amarga alasan sing diterangake dening penulis ing wiwitan.

"Kubernetes tambah latensi kaping 10": sapa sing kudu disalahake?

Cathetan saka penulis: Katon kaya postingan iki kepincut manungsa waé luwih saka samesthine. Aku isih njaluk komentar duka sing judhul artikel mblusukake lan sawetara maca sedih. Aku ngerti alasan apa sing kedadeyan, mula, sanajan ana risiko ngrusak kabeh intrik, aku pengin langsung ngandhani babagan apa artikel iki. Bab sing aneh sing dakdeleng nalika tim pindhah menyang Kubernetes yaiku yen ana masalah (kayata tambah latensi sawise migrasi), sing pisanan disalahake yaiku Kubernetes, nanging ternyata orkestra kasebut ora bener. nyalahke. Artikel iki nyritakake babagan siji kasus kasebut. Jeneng kasebut mbaleni seru salah sawijining pangembang (mengko sampeyan bakal weruh yen Kubernetes ora ana hubungane). Sampeyan ora bakal nemokake wahyu sing nggumunake babagan Kubernetes ing kene, nanging sampeyan bisa nyana sawetara pelajaran sing apik babagan sistem kompleks.

Sawetara minggu kepungkur, timku migrasi layanan mikro siji menyang platform inti sing kalebu CI / CD, runtime basis Kubernetes, metrik, lan barang liyane. Pamindhahan kasebut minangka uji coba: kita ngrancang kanggo njupuk minangka basis lan nransfer kira-kira 150 layanan liyane ing sasi sing bakal teka. Kabeh mau tanggung jawab kanggo operasi sawetara platform online paling gedhe ing Spanyol (Infojobs, Fotocasa, lsp.).

Sawise kita nyebarake aplikasi kasebut menyang Kubernetes lan ngarahake sawetara lalu lintas menyang kasebut, kejutan sing nguwatirake nunggu kita. Tundha (latensi) panjalukan ing Kubernetes 10 kaping luwih dhuwur tinimbang ing EC2. Umumé, perlu kanggo nemokake solusi kanggo masalah iki, utawa ninggalake migrasi microservice (lan, bisa uga, kabeh proyek).

Napa latensi luwih dhuwur ing Kubernetes tinimbang ing EC2?

Kanggo nemokake bottleneck, kita ngumpulake metrik ing sadawane path panjalukan. Arsitèktur kita prasaja: gateway API (Zuul) njaluk proxy menyang instans layanan mikro ing EC2 utawa Kubernetes. Ing Kubernetes, kita nggunakake NGINX Ingress Controller, lan backend minangka obyek biasa penyebaran prajurit karo aplikasi JVM ing platform Spring.

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

Masalah kasebut ana hubungane karo latensi awal ing backend (Aku menehi tandha area masalah ing grafik minangka "xx"). Ing EC2, respon aplikasi njupuk udakara 20ms. Ing Kubernetes, latensi tambah dadi 100-200 ms.

Kita cepet ngilangi tersangka sing ana gandhengane karo owah-owahan runtime. Versi JVM tetep padha. Masalah kontainerisasi uga ora ana hubungane: aplikasi kasebut wis sukses ing wadhah ing EC2. Loading? Nanging kita mirsani latensi dhuwur sanajan 1 panyuwunan saben detik. Ngaso kanggo ngumpulake sampah uga bisa diabaikan.

Salah sawijining admin Kubernetes kepingin weruh apa aplikasi kasebut duwe dependensi eksternal amarga pitakon DNS wis nyebabake masalah sing padha sadurunge.

Hipotesis 1: résolusi jeneng DNS

Kanggo saben panjalukan, aplikasi kita ngakses conto AWS Elasticsearch kaping telu ing domain kaya elastic.spain.adevinta.com. Nang wadhah kita ana cangkang, supaya kita bisa mriksa yen nggoleki domain pancen butuh wektu suwe.

Pitakonan DNS saka wadhah:

[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

Panjaluk sing padha saka salah sawijining conto EC2 nalika aplikasi kasebut mlaku:

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

Ngelingi yen panelusur njupuk udakara 30ms, dadi jelas manawa resolusi DNS nalika ngakses Elasticsearch pancen nyumbang kanggo nambah latensi.

Nanging, iki aneh amarga rong alasan:

  1. Kita wis duwe ton aplikasi Kubernetes sing sesambungan karo sumber daya AWS tanpa nandhang latensi dhuwur. Punapa mawon alasanipun, punika gadhah khusus kanggo kasus iki.
  2. Kita ngerti manawa JVM nindakake cache DNS ing memori. Ing gambar kita, nilai TTL ditulis ing $JAVA_HOME/jre/lib/security/java.security lan disetel kanggo 10 detik: networkaddress.cache.ttl = 10. Ing tembung liyane, JVM kudu cache kabeh pitakon DNS kanggo 10 detik.

Kanggo ngonfirmasi hipotesis pisanan, kita mutusake kanggo mandheg nelpon DNS sedhela lan ndeleng manawa masalah kasebut ilang. Kaping pisanan, kita mutusake kanggo ngatur ulang aplikasi kasebut supaya bisa komunikasi langsung karo Elasticsearch kanthi alamat IP, tinimbang liwat jeneng domain. Iki mbutuhake owah-owahan kode lan panyebaran anyar, mula kita mung nggawe peta domain menyang alamat IP /etc/hosts:

34.55.5.111 elastic.spain.adevinta.com

Saiki wadhah nampa IP meh langsung. Iki nyebabake sawetara perbaikan, nanging kita mung rada nyedhaki tingkat latensi sing dikarepake. Sanajan résolusi DNS butuh wektu sing suwe, alesan nyata isih ora bisa ditindakake.

Diagnostik liwat jaringan

Kita mutusaké kanggo njelasno lalu lintas saka wadhah nggunakake tcpdumpkanggo ndeleng apa sing kedadeyan ing jaringan:

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

Kita banjur ngirim sawetara panjalukan lan ngundhuh sing dijupuk (kubectl cp my-service:/capture.pcap capture.pcap) kanggo analisis luwih lanjut ing Wireshark.

Ora ana sing curiga babagan pitakon DNS (kajaba ana perkara cilik sing bakal dakkandhakake mengko). Nanging ana keanehan tartamtu babagan cara layanan kita nangani saben panjaluk. Ing ngisor iki minangka gambar tangkapan sing nuduhake panyuwunan ditampa sadurunge respon diwiwiti:

"Kubernetes tambah latensi kaping 10": sapa sing kudu disalahake?

Nomer paket ditampilake ing kolom pisanan. Kanggo gamblang, Aku wis werna-kode aliran TCP beda.

Stream ijo miwiti karo paket 328 nuduhake carane klien (172.17.22.150) nggawe sambungan TCP kanggo wadhah (172.17.36.147). Sawise jabat tangan dhisikan (328-330), paket 331 digawa HTTP GET /v1/.. - panjalukan mlebu kanggo layanan kita. Kabeh proses njupuk 1 ms.

Aliran abu-abu (saka paket 339) nuduhake yen layanan kita ngirim panjalukan HTTP menyang conto Elasticsearch (ora ana jabat tangan TCP amarga nggunakake sambungan sing wis ana). Iki njupuk 18ms.

Nganti saiki kabeh apik, lan wektu kira-kira cocog karo telat sing dikarepake (20-30 ms nalika diukur saka klien).

Nanging, bagean biru njupuk 86ms. Apa sing kedadeyan ing kono? Kanthi paket 333, layanan kita ngirim panjalukan HTTP GET menyang /latest/meta-data/iam/security-credentials, lan sanalika sawise iku, liwat sambungan TCP padha, request GET liyane kanggo /latest/meta-data/iam/security-credentials/arn:...

We found sing iki bola karo saben request saindhenging tilak. Resolusi DNS pancen rada alon ing wadhah kita (panjelasan babagan fenomena iki cukup menarik, nanging aku bakal nyimpen kanggo artikel sing kapisah). Ternyata penyebab telat sing dawa yaiku telpon menyang layanan Metadata AWS Instance ing saben panyuwunan.

Hipotesis 2: panggilan sing ora perlu menyang AWS

Loro-lorone titik pungkasan kagungane AWS Instance Metadata API. Layanan mikro kita nggunakake layanan iki nalika mbukak Elasticsearch. Kaloro telpon kasebut minangka bagean saka proses wewenang dhasar. Titik pungkasan sing diakses ing panjalukan pisanan ngetokake peran IAM sing ana gandhengane karo conto kasebut.

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

Panyuwunan kapindho njaluk idin sauntara titik pungkasan kapindho kanggo conto iki:

/ # 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"
}

Klien bisa nggunakake wektu sing cendhak lan kudu entuk sertifikat anyar (sadurunge Expiration). Model kasebut prasaja: AWS kerep muter tombol sauntara kanggo alasan keamanan, nanging klien bisa nyimpen sawetara menit kanggo ngimbangi paukuman kinerja sing digandhengake karo entuk sertifikat anyar.

AWS Java SDK kudu njupuk tanggung jawab kanggo ngatur proses iki, nanging sakperangan alesan iki ora kelakon.

Sawise nggoleki masalah ing GitHub, kita nemokake masalah #1921. Dheweke mbantu kita nemtokake arah sing bakal "digali" luwih lanjut.

AWS SDK nganyari sertifikat nalika ana salah siji saka kahanan ing ngisor iki:

  • Tanggal kadaluwarsa (Expiration) Tiba ing EXPIRATION_THRESHOLD, hardcoded kanggo 15 menit.
  • More wektu wis liwati wiwit nyoba pungkasan kanggo gawe anyar sertifikat saka REFRESH_THRESHOLD, hardcoded kanggo 60 menit.

Kanggo ndeleng tanggal kadaluwarsa sertifikat sing ditampa, kita nglakokake perintah cURL ing ndhuwur saka wadhah lan conto EC2. Wektu validitas sertifikat sing ditampa saka wadhah dadi luwih cendhek: persis 15 menit.

Saiki kabeh wis jelas: kanggo panjalukan pisanan, layanan kita nampa sertifikat sementara. Wiwit padha ora bener kanggo luwih saka 15 menit, AWS SDK mutusaké kanggo nganyari ing request sakteruse. Lan iki kedadeyan karo saben panyuwunan.

Napa wektu validitas sertifikat dadi luwih cendhak?

Metadata Instance AWS dirancang kanggo nggarap instance EC2, dudu Kubernetes. Ing tangan liyane, kita ora pengin ngganti antarmuka aplikasi. Kanggo iki kita digunakake KIAM - alat sing, nggunakake agen ing saben simpul Kubernetes, ngidini pangguna (insinyur nyebarake aplikasi menyang kluster) kanggo nemtokake peran IAM menyang wadhah ing pods kaya-kaya EC2. KIAM nyegat telpon menyang layanan AWS Instance Metadata lan ngolah saka cache, sing sadurunge ditampa saka AWS. Saka sudut pandang aplikasi, ora ana owah-owahan.

KIAM nyedhiyakake sertifikat jangka pendek kanggo polong. Iki nggawe akal amarga umur rata-rata pod luwih cendhek tinimbang conto EC2. Periode validitas standar kanggo sertifikat padha karo 15 menit.

Akibaté, yen sampeyan overlay loro nilai standar ing ndhuwur saben liyane, ana masalah. Saben sertifikat sing diwenehake kanggo aplikasi kadaluwarsa sawise 15 menit. Nanging, AWS Java SDK meksa nganyari maneh sertifikat sing isih ana kurang saka 15 menit sadurunge tanggal kadaluwarsa.

Akibaté, certificate sak wentoro dipeksa kanggo gawe anyar karo saben request, kang entails saperangan saka telpon kanggo API AWS lan nimbulaké Tambah pinunjul ing latensi. Ing AWS Java SDK kita nemokake panjaluk fitur, sing nyebutake masalah sing padha.

Solusi kasebut dadi prasaja. Kita mung ngatur ulang KIAM kanggo njaluk sertifikat kanthi wektu validitas luwih suwe. Sawise kedadeyan kasebut, panjaluk wiwit mili tanpa partisipasi layanan Metadata AWS, lan latensi mudhun nganti tingkat sing luwih murah tinimbang ing EC2.

temonan

Adhedhasar pengalaman kita babagan migrasi, salah sawijining sumber masalah sing paling umum yaiku dudu bug ing Kubernetes utawa unsur liyane ing platform kasebut. Uga ora ngatasi cacat dhasar ing layanan mikro sing kita porting. Masalah asring muncul mung amarga kita nggabungake unsur sing beda.

Kita nyampur bebarengan sistem Komplek sing wis tau sesambungan karo saben liyane sadurunge, dikarepake sing bebarengan bakal mbentuk siji, sistem luwih gedhe. Alas, luwih akeh unsur, luwih akeh ruang kanggo kesalahan, luwih dhuwur entropi.

Ing kasus kita, latensi dhuwur dudu asil saka bug utawa keputusan sing ora becik ing Kubernetes, KIAM, AWS Java SDK, utawa layanan mikro kita. Iki minangka asil nggabungake rong setelan standar independen: siji ing KIAM, liyane ing AWS Java SDK. Dijupuk kanthi kapisah, loro paramèter nggawe pangertèn: kabijakan nganyari maneh sertifikat aktif ing AWS Java SDK, lan wektu validitas sertifikat sing cendhak ing KAIM. Nanging nalika sampeyan gabungke, asil dadi ora bisa diramal. Loro solusi independen lan logis ora kudu nggawe akal nalika digabungake.

PS saka penerjemah

Sampeyan bisa sinau luwih lengkap babagan arsitektur sarana KIAM kanggo nggabungake AWS IAM karo Kubernetes ing artikel iki saka pangripta.

Uga maca ing blog kita:

Source: www.habr.com

Add a comment