ããŒãã 翻蚳ã: ãã®èšäºã¯ããšãŒãããäŒæ¥ Adevinta ã§äž»ä»»ãœãããŠã§ã¢ ãšã³ãžãã¢ã®è·ã«ãã Galo Navarro ã«ãã£ãŠæžããããã®ã§ãã€ã³ãã©ã¹ãã©ã¯ãã£éçšã®åéã«ãããé åçã§æçãªã調æ»ãã§ãã åé¡ã¯ãèè ãæåã«èª¬æããçç±ã«ããã翻蚳ã«ãããŠãããã«æ¡åŒµãããŸããã
èè
ããã®ã¡ã¢: ãã®æçš¿ã®ããã§ã
æ°é±éåãç§ã®ããŒã ã¯åäžã®ãã€ã¯ããµãŒãã¹ããCI/CDãKubernetes ããŒã¹ã®ã©ã³ã¿ã€ã ãã¡ããªã¯ã¹ããã®ä»ã®æ©èœãå«ãã³ã¢ ãã©ãããã©ãŒã ã«ç§»è¡ããŠããŸããã ãã®ç§»è¡ã¯è©Šéšçãªãã®ã§ãããç§ãã¡ã¯ãããåºç€ãšããŠãä»åŸæ°ãæéã§ããã«çŽ 150 ã®ãµãŒãã¹ã移è¡ããäºå®ã§ããã 圌ãã¯å
šå¡ãã¹ãã€ã³æ倧ã®ãªã³ã©ã€ã³ ãã©ãããã©ãŒã (InfojobsãFotocasa ãªã©) ã®éå¶ãæ
åœããŠããŸãã
ã¢ããªã±ãŒã·ã§ã³ã Kubernetes ã«ãããã€ããäžéšã®ãã©ãã£ãã¯ãããã«ãªãã€ã¬ã¯ãããåŸãé©ãã¹ãé©ããç§ãã¡ãåŸ ã£ãŠããŸããã é ã ïŒåŸ ã¡æéïŒ Kubernetes ã§ã®ãªã¯ãšã¹ã㯠EC10 ã® 2 åã§ããã äžè¬ã«ããã®åé¡ã®è§£æ±ºçãèŠã€ãããããã€ã¯ããµãŒãã¹ (å Žåã«ãã£ãŠã¯ãããžã§ã¯ãå šäœ) ã®ç§»è¡ãæŸæ£ããå¿ èŠããããŸããã
Kubernetes ã®ã¬ã€ãã³ã·ã EC2 ãããã¯ããã«é«ãã®ã¯ãªãã§ãã?
ããã«ããã¯ãèŠã€ããããã«ããªã¯ãšã¹ã ãã¹å
šäœã«æ²¿ã£ãŠã¡ããªã¯ã¹ãåéããŸããã ç§ãã¡ã®ã¢ãŒããã¯ãã£ã¯ã·ã³ãã«ã§ããAPI ã²ãŒããŠã§ã€ (Zuul) ã EC2 ãŸã㯠Kubernetes ã®ãã€ã¯ããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ã«ãªã¯ãšã¹ãããããã·ããŸãã Kubernetes ã§ã¯ NGINX Ingress Controller ã䜿çšããããã¯ãšã³ãã¯æ¬¡ã®ãããªéåžžã®ãªããžã§ã¯ãã§ãã
EC2
+---------------+
| +---------+ |
| | | |
+-------> BACKEND | |
| | | | |
| | +---------+ |
| +---------------+
+------+ |
Public | | |
-------> ZUUL +--+
traffic | | | Kubernetes
+------+ | +-----------------------------+
| | +-------+ +---------+ |
| | | | xx | | |
+-------> NGINX +------> BACKEND | |
| | | xx | | |
| +-------+ +---------+ |
+-----------------------------+
ãã®åé¡ã¯ããã¯ãšã³ãã®åæã¬ã€ãã³ã·ãŒã«é¢é£ããŠããããã§ã (ã°ã©ãäžã§åé¡ã®ããé åããxxããšããŠããŒã¯ããŸãã)ã EC2 ã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®å¿çã«çŽ 20 ããªç§ããããŸããã Kubernetes ã§ã¯ãã¬ã€ãã³ã·ã 100 ïœ 200 ããªç§ã«å¢å ããŸããã
ç§ãã¡ã¯ãã©ã³ã¿ã€ã ã®å€æŽã«é¢é£ããå¯èœæ§ã®ãã容çè ãããã«åŽäžããŸããã JVM ã®ããŒãžã§ã³ã¯å€ãããŸããã ã³ã³ããåã®åé¡ããããšã¯äœã®é¢ä¿ããããŸããã§ãããã¢ããªã±ãŒã·ã§ã³ã¯ãã§ã« EC2 äžã®ã³ã³ããå ã§æ£åžžã«å®è¡ãããŠããŸããã èªã¿èŸŒã¿äž? ãããã1 ç§ããã XNUMX ãªã¯ãšã¹ãã§ãé«ãã¬ã€ãã³ã·ã芳å¯ãããŸããã ã¬ããŒãž ã³ã¬ã¯ã·ã§ã³ã®äžæåæ¢ãç¡èŠãããå¯èœæ§ããããŸãã
Kubernetes 管çè ã® XNUMX 人ã¯ãDNS ã¯ãšãªã«ãã£ãŠéå»ã«åæ§ã®åé¡ãçºçãããããã¢ããªã±ãŒã·ã§ã³ã«å€éšäŸåé¢ä¿ãããã®ã§ã¯ãªãããšçåã«æããŸããã
仮説 1: DNS åå解決
ãªã¯ãšã¹ãããšã«ãã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ãããªãã¡ã€ã³å
ã® AWS Elasticsearch ã€ã³ã¹ã¿ã³ã¹ã« XNUMX ïœ XNUMX åã¢ã¯ã»ã¹ããŸãã 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 ã€ã³ã¹ã¿ã³ã¹ã® XNUMX ã€ããã®åæ§ã®ãªã¯ãšã¹ã:
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
ã«ãã¯ã¢ããã«çŽ 30 ããªç§ããã£ãããšãèæ ®ãããšãElasticsearch ã«ã¢ã¯ã»ã¹ãããšãã® DNS 解決ãå®éã«ã¬ã€ãã³ã·ã®å¢å ã«å¯äžããŠããããšãæããã«ãªããŸããã
ããããããã¯æ¬¡ã® XNUMX ã€ã®çç±ããå¥åŠã§ããã
- ç§ãã¡ã¯ãã§ã«ãé«ãã¬ã€ãã³ã·ãŒã«æ©ãŸãããããšãªã AWS ãªãœãŒã¹ãšéä¿¡ãã Kubernetes ã¢ããªã±ãŒã·ã§ã³ã倧éã«æã£ãŠããŸãã çç±ãäœã§ãããããã¯ç¹ã«ãã®äºä»¶ã«é¢é£ããŠããŸãã
- JVM ãã¡ã¢ãªå
DNS ãã£ãã·ã¥ãå®è¡ããããšãããã£ãŠããŸãã ç§ãã¡ã®ç»åã§ã¯ãTTL å€ã¯æ¬¡ã®ããã«æžãããŠããŸãã
$JAVA_HOME/jre/lib/security/java.security
ãã㊠10 ç§ã«èšå®ããŸããnetworkaddress.cache.ttl = 10
ã ã€ãŸããJVM ã¯ãã¹ãŠã® DNS ã¯ãšãªã 10 ç§éãã£ãã·ã¥ããå¿ èŠããããŸãã
æåã®ä»®èª¬ã確èªããããã«ãDNS ãžã®åŒã³åºãããã°ããåæ¢ããåé¡ã解æ¶ããããã©ããã確èªããããšã«ããŸããã ãŸãããã¡ã€ã³åã§ã¯ãªã IP ã¢ãã¬ã¹ã«ãã£ãŠ Elasticsearch ãšçŽæ¥éä¿¡ããããã«ã¢ããªã±ãŒã·ã§ã³ãåæ§æããããšã«ããŸããã ããã«ã¯ã³ãŒãã®å€æŽãšæ°ãããããã€ã¡ã³ããå¿
èŠãšãªããããåã«ãã¡ã€ã³ããã® IP ã¢ãã¬ã¹ã«ãããããŸããã /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 ã¯ãšãªã«ã¯äœãçããããã®ã¯ãããŸããã§ãã (åŸã§èª¬æãã XNUMX ã€ã®å°ããªç¹ãé€ããŠ)ã ããããç§ãã¡ã®ãµãŒãã¹ãåãªã¯ãšã¹ããåŠçããæ¹æ³ã«ã¯ãç¹å®ã®å¥åŠãªç¹ããããŸããã 以äžã¯ãå¿çãéå§ãããåã«ãªã¯ãšã¹ããåãå ¥ããããããšã瀺ããã£ããã£ã®ã¹ã¯ãªãŒã³ã·ã§ããã§ãã
ããã±ãŒãžçªå·ã¯æåã®åã«è¡šç€ºãããŸãã ããããããããããã«ãããŸããŸãª TCP ãããŒãè²åãããŸããã
ãã±ãã 328 ã§å§ãŸãç·è²ã®ã¹ããªãŒã ã¯ãã¯ã©ã€ã¢ã³ã (172.17.22.150) ãã³ã³ãã (172.17.36.147) ãžã® TCP æ¥ç¶ã確ç«ããæ¹æ³ã瀺ããŠããŸãã æåã®ãã³ãã·ã§ã€ã¯ (328-330) ã®åŸãããã±ãŒãž 331 ãæã¡èŸŒãŸããŸãã HTTP GET /v1/..
â åœç€Ÿã®ãµãŒãã¹ãžã®åä¿¡ãªã¯ãšã¹ãã ããã»ã¹å
šäœã« 1 ããªç§ããããŸããã
ç°è²ã®ã¹ããªãŒã (ãã±ãã 339 ãã) ã¯ããµãŒãã¹ã Elasticsearch ã€ã³ã¹ã¿ã³ã¹ã« HTTP ãªã¯ãšã¹ããéä¿¡ããããšã瀺ããŠããŸã (æ¢åã®æ¥ç¶ã䜿çšããŠãããããTCP ãã³ãã·ã§ã€ã¯ã¯ãããŸãã)ã ããã«ã¯ 18 ããªç§ããããŸããã
ãããŸã§ã¯ãã¹ãŠåé¡ãªããæéã¯äºæ³ãããé 延 (ã¯ã©ã€ã¢ã³ããã枬å®ããå Žå㯠20 ïœ 30 ããªç§) ã«ã»ãŒäžèŽããŠããŸãã
ãã ããéè²ã®ã»ã¯ã·ã§ã³ã«ã¯ 86 ããªç§ããããŸãã ãã®äžã§äœãèµ·ãã£ãŠããã®ã§ããããïŒ ãã±ãã 333 ã§ããµãŒãã¹ã¯ HTTP GET ãªã¯ãšã¹ãã次ã®å®å
ã«éä¿¡ããŸããã /latest/meta-data/iam/security-credentials
ããã®çŽåŸã«ãåã TCP æ¥ç¶ãä»ããŠãå¥ã® GET ãªã¯ãšã¹ãã /latest/meta-data/iam/security-credentials/arn:..
.
ãã¬ãŒã¹å šäœãéããŠããã¹ãŠã®ãªã¯ãšã¹ãã§ãããç¹°ãè¿ãããããšãããããŸããã 確ãã«ãã³ã³ãããŒã§ã¯ DNS 解決ãå°ãé ããªããŸã (ãã®çŸè±¡ã®èª¬æã¯éåžžã«èå³æ·±ãã§ãããå¥ã®èšäºã«åã£ãŠãããŸã)ã é·ãé 延ã®åå ã¯ãåãªã¯ãšã¹ãã§ã® AWS ã€ã³ã¹ã¿ã³ã¹ ã¡ã¿ããŒã¿ ãµãŒãã¹ã®åŒã³åºãã§ããããšãå€æããŸããã
仮説 2: AWS ãžã®äžèŠãªåŒã³åºã
äž¡æ¹ã®ãšã³ããã€ã³ããå±ããŠããŸã
/ # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
arn:aws:iam::<account_id>:role/some_role
XNUMX çªç®ã®ãªã¯ãšã¹ãã¯ãXNUMX çªç®ã®ãšã³ããã€ã³ãã«ãã®ã€ã³ã¹ã¿ã³ã¹ã®äžæçãªã¢ã¯ã»ã¹èš±å¯ãèŠæ±ããŸãã
/ # 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 ã§åé¡ãæ€çŽ¢ãããšãããåé¡ãèŠã€ãããŸãã
AWS SDK ã¯ã次ã®ããããã®ç¶æ³ãçºçããå Žåã«èšŒææžãæŽæ°ããŸãã
- æå¹æé ïŒ
Expiration
ïŒ ã«èœã¡ãEXPIRATION_THRESHOLD
ã15åã«ããŒãã³ãŒãã£ã³ã°ãããŠããŸãã - æåŸã«èšŒææžãæŽæ°ããŠããã次ã®æéãããé·ãæéãçµéããŸããã
REFRESH_THRESHOLD
ã60åéããŒãã³ãŒãã£ã³ã°ãããŠããŸãã
åãåã£ã蚌ææžã®å®éã®æå¹æéã確èªããããã«ãã³ã³ãããš EC2 ã€ã³ã¹ã¿ã³ã¹ã®äž¡æ¹ããäžèšã® cURL ã³ãã³ããå®è¡ããŸããã ã³ã³ããããåãåã£ã蚌ææžã®æå¹æéã¯ãã¯ããã«çããã¡ããã© 15 åã§ããããšãå€æããŸããã
ããã§ãã¹ãŠãæããã«ãªããŸãããæåã®ãªã¯ãšã¹ãã§ããµãŒãã¹ã¯äžæ蚌ææžãåãåããŸããã ããã㯠15 åãè¶ ããŠæå¹ã§ã¯ãªãã£ããããAWS SDK ã¯åŸç¶ã®ãªã¯ãšã¹ãã§ããããæŽæ°ããããšã決å®ããŸãã ãããŠãããã¯ãã¹ãŠã®ãªã¯ãšã¹ãã§èµ·ãããŸããã
蚌ææžã®æå¹æéãçããªã£ãã®ã¯ãªãã§ãã?
AWS ã€ã³ã¹ã¿ã³ã¹ ã¡ã¿ããŒã¿ã¯ãKubernetes ã§ã¯ãªã EC2 ã€ã³ã¹ã¿ã³ã¹ã§åäœããããã«èšèšãããŠããŸãã äžæ¹ã§ãã¢ããªã±ãŒã·ã§ã³ã®ã€ã³ã¿ãŒãã§ãŒã¹ã¯å€æŽããããããŸããã§ããã ãã®ããã«äœ¿çšããã®ã¯
KIAM ã¯ãããã«çæ蚌ææžãæäŸããŸãã ãããã®å¹³å寿åœã EC2 ã€ã³ã¹ã¿ã³ã¹ã®å¹³å寿åœããçãããšãèæ
®ãããšãããã¯åœç¶ã®ããšã§ãã 蚌ææžã®ããã©ã«ãã®æå¹æé
ãã®çµæãäž¡æ¹ã®ããã©ã«ãå€ãéãåããããšåé¡ãçºçããŸãã ã¢ããªã±ãŒã·ã§ã³ã«æäŸãããå蚌ææžã¯ 15 ååŸã«æéåãã«ãªããŸãã ãã ããAWS Java SDK ã¯ãæå¹æéãŸã§æ®ã 15 åãåã£ã蚌ææžã¯åŒ·å¶çã«æŽæ°ããŸãã
ãã®çµæãäžæ蚌ææžã¯ãªã¯ãšã¹ãããšã«åŒ·å¶çã«æŽæ°ãããããšã«ãªããAWS API ãžã®åŒã³åºããæ°åå¿
èŠãšãªããã¬ã€ãã³ã·ãŒã倧å¹
ã«å¢å ããŸãã AWS Java SDK ã§æ¬¡ã®ããšãããããŸããã
解決çã¯ç°¡åã§ããããšãããããŸããã ããé·ãæå¹æéã®èšŒææžãèŠæ±ããããã« KIAM ãåæ§æããã ãã§ãã ãããçºçãããšãAWS ã¡ã¿ããŒã¿ ãµãŒãã¹ã®åå ãªãã§ãªã¯ãšã¹ããæµããããã«ãªããã¬ã€ãã³ã·ã¯ EC2 ãããããã«äœãã¬ãã«ã«äœäžããŸããã
æèŠ
移è¡ã«é¢ããç§ãã¡ã®çµéšã«åºã¥ããšãæãäžè¬çãªåé¡ã®åå ã® XNUMX ã€ã¯ãKubernetes ããã©ãããã©ãŒã ã®ãã®ä»ã®èŠçŽ ã®ãã°ã§ã¯ãããŸããã ãŸãã移æ€ããŠãããã€ã¯ããµãŒãã¹ã®æ ¹æ¬çãªæ¬ é¥ã«ã察åŠããŠããŸããã ããŸããŸãªèŠçŽ ãçµã¿åããããšããã ãã®çç±ã§åé¡ãçºçããããšããããããŸãã
ç§ãã¡ã¯ããããŸã§çžäºäœçšããããšã®ãªãè€éãªã·ã¹ãã ãæ··ãåãããŠãããããåäžã®ãã倧ããªã·ã¹ãã ã圢æããããšãæåŸ ããŠããŸãã æ²ããããšã«ãèŠçŽ ãå¢ããã°å¢ããã»ã©ããšã©ãŒã®äœå°ãå¢ãããšã³ããããŒãé«ããªããŸãã
ç§ãã¡ã®å Žåãé«ãã¬ã€ãã³ã·ãŒã¯ãKubernetesãKIAMãAWS Java SDKããŸãã¯ãã€ã¯ããµãŒãã¹ã®ãã°ãééã£ã決å®ã®çµæã§ã¯ãããŸããã§ããã ããã¯ãKIAM ãš AWS Java SDK ã® XNUMX ã€ã®ç¬ç«ããããã©ã«ãèšå®ãçµã¿åãããçµæã§ãã åå¥ã«èãããšãAWS Java SDK ã®ã¢ã¯ãã£ããªèšŒææžæŽæ°ããªã·ãŒãš KAIM ã®èšŒææžã®çãæå¹æéãšããäž¡æ¹ã®ãã©ã¡ãŒã¿ãæå³ãæã¡ãŸãã ããããããããçµã¿åããããšãçµæã¯äºæž¬äžå¯èœã«ãªããŸãã XNUMX ã€ã®ç¬ç«ããè«ççãªãœãªã¥ãŒã·ã§ã³ãçµã¿åãããŠãæå³ããªãå¿ èŠã¯ãããŸããã
翻蚳è ããã®è¿œäŒž
AWS IAM ã Kubernetes ãšçµ±åããããã® KIAM ãŠãŒãã£ãªãã£ã®ã¢ãŒããã¯ãã£ã«ã€ããŠè©³ããã¯ã次㮠Web ãµã€ããã芧ãã ããã
ç§ãã¡ã®ããã°ããèªã¿ãã ãã:
- «
æ¬çªç°å¢ã§ã® Kubernetes ã®å€±æã«é¢ãã 3 ã€ã®ã¹ããŒãªãŒ: ã¢ã³ãã¢ãã£ããã£ãæ£åžžãªã·ã£ããããŠã³ãWebhook "; - «
Kubernetes ã®ãããã®åªå é äœã Grafana Labs ã§ããŠã³ã¿ã€ã ãåŒãèµ·ãããä»çµã¿ "; - «
Kubernetes ã®éçšã«ããã 6 ã€ã®èå³æ·±ãã·ã¹ãã ãã° [ããã³ãã®è§£æ±ºç] "; - «
SRE ã®æ¥åžžç掻ããåŸã 6 ã€ã®å®è·µçãªã¹ããŒãªãŒ 'ã
åºæïŒ habr.com