Ինչպես հասանք deploy-ների զրո 502 սխալի
Մեր backend-ը deploy անելիս մի քանի հարցում ձախողվում էր 502 Bad Gateway-ով։ Ոչ շատ, բայց deploy-ի ընթացքում 502-ը նշանակում է, որ ինչ-որ մեկի սեղմումը ոչինչ չի արել, կամ ինչ-որ build, որ նա դիտում էր, մի պահ կանգնել է։ Մենք այն հետևեցինք երկու առանձին խնդրի․ ինքնաբուժող watchdog, որ կռվում էր մեր deploy-ների դեմ, և բացը այն պահի միջև, երբ սերվերը դադարում է լսել, և երբ load balancer-ը դադարում է նրան երթևեկություն ուղարկել։ Շտկումներից հետո արտադրության երեք հաջորդական deploy-ի ընթացքում թիվը իջավ 10-ից 6-ի, իսկ հետո՝ 0-ի։
Կարգավորումը
ԱPI-ն և orchestrator-ը աշխատում են որպես կոնտեյներներ սերվերների փոքր խմբում, AWS Application Load Balancer-ի (ALB) հետևում։ Deploy-ը թարմացնում է մեկ սերվեր մեկ անգամ․ դադարեցնում է հին կոնտեյներները, գործարկում նորերը և անցնում հաջորդին։ Յուրաքանչյուր սերվերի վրա watchdog-ը ստուգում է, որ կոնտեյներները բարձրացած են, և վերամեկնարկում է ցանկացած, որ չի աշխատում։ Այն գոյություն ունի, որպեսզի գիշերային 3-ին խափանված պրոցեսը վերադառնա, առանց որևէ մեկին արթնացնելու։
Ամենք առանձին ողջամիտ են։ Միասին՝ ոչ։
Խնդիր 1․ watchdog-ը մրցեց deploy-ի հետ
Watchdog-ը աշխատում էր րոպեն մեկ անգամ և «բուժում» էր մեկ ձախողված առողջության ստուգումից հետո։ Deploy-ը միտումնավոր դադարեցնում է ծառայությունները մինչև 150 վայրկյան՝ այդ ընթացքում առողջության ստուգումը պետք է ձախողվի։ Ուստի watchdog-ը գործարկվում էր յուրաքանչյուր deploy-ի ժամանակ։
Այն մեծամասամբ անվնաս կորցնում էր մրցումը։ Մեկ անգամ շահեց․ deploy-ի մեջտեղում վերագրեց compose ֆայլը (նկարագրությունը, թե որ կոնտեյներները պետք է աշխատեն) և թողեց սերվերը առանց gateway կոնտեյների ընդհանրապես՝ միաժամանակ deploy աշխատանքը հայտնում էր հաջողություն։
Շտկումները․
- Մեկ կողպեք։ Deploy-ն այժմ վերցնում է նույն ֆայլի կողպեքը, ինչ սերվերի bootstrap սկրիպտը, ուստի watchdog-ը և deploy-ը երբեք չեն աշխատում միաժամանակ։
- Չորս հարված, ոչ մեկ։ Watchdog-ը պահանջում է չորս հաջորդական ձախողված ստուգում, նախքան գործելը։ Ժամանակավորապես դադարեցվող ծառայությունը այլևս մեռած չի թվում։
- Մեկ սահմանում։ Compose ֆայլն այժմ ունի ճիշտ մեկ աղբյուր, որը հրապարակվում է սերվերներին, այլ ոչ թե պատճեններ, որոնք կարող էին շեղվել։
- Ստուգել, ոչ թե վստահել։ Deploy աշխատանքը այլևս չի անցնում, որովհետև հրամանը վերադարձել է։ Այն ստուգում է յուրաքանչյուր սերվերի API-ն, orchestrator-ը, gateway-ը և հրապարակման աշխատողը, նախքան հաջողության հասնելը։
Խնդիր 2․ սերվերը հեռացավ, նախքան երթևեկությունը
Երկրորդ խնդիրն ավելի անաղմուկ էր։ Երբ deploy-ը դադարեցնում է սերվերը, սերվերը սկսում է պատասխանել իր առողջության endpoint-ին 503-ով, որպեսզի load balancer-ը այն դուրս բերի շրջանառությունից։ Մերը դա անում էր 5 վայրկյան, ապա անջատվում։
Բայց ALB-ը առողջությունը ստուգում էր միայն երբեմն և պահանջում էր մի քանի ձախողված ստուգում հաջորդաբար, նախքան թիրախին երթևեկությունը դադարեցնելը՝ մոտ 60 վայրկյան ընդհանուր։ Այսպիսով, մոտ 55 վայրկյան, load balancer-ը շարունակում էր իրական հարցումներ ուղարկել սերվերին, որը արդեն դադարել էր լսել։ Դրանք էին մեր 502-երը։
Շտկումը երկու ժամանակացույցները համաձայնեցնելն էր․
- Թիրախային խումբը ստուգում է յուրաքանչյուր 5 վայրկյան և թիրախը անառողջ է նշում 2 ձախողումից հետո՝ մոտ 10 վայրկյանում նկատելու համար։
- Դադարեցումը շարունակում է սպասարկել իրական երթևեկությունը 15 վայրկյան այն բանից հետո, երբ սկսում է ձախողել առողջության ստուգումները, ուստի միշտ կա համընկում։
- Այս կարգավորումները ապրում են ենթակառուցվածքը տրամադրող սկրիպտում, ոչ թե մի կոնսոլում, որ ինչ-որ մեկը մի անգամ սեղմել է։
Թվերը միմյանց պահել
Նման ժամանակային սահմանները միմյանց են կախված։ Դադարեցումը պետք է ավելի երկար լինի, քան balancer-ին անհրաժեշտ ժամանակը նկատելու համար․ դադարեցումը գումարած անջատումը պետք է ավարտվեն, մինչև կոնտեյները ստիպողաբար չսպանվի։ Հեշտ է, որ ինչ-որ մեկը վեց ամսից փոխի մի թիվ և անշուշտ վերադարձնի սխալը։
Ուստի այդ կապերը գրել ենք որպես թեստեր․ դադարեցումը պետք է լինի ավելի երկար, քան առողջության ստուգման ընդմիջումը՝ բազմապատկած ձախողման շեմով․ առողջ վերադառնալու ժամանակը պետք է մնա կարճ․ ամբողջ դադարեցումը պետք է տեղավորվի կոնտեյների կանգնեցման սպասման ժամանակի մեջ։ Փոխեք մի թիվ՝ առանց մյուսների, և CI-ը ձախողվում է։ Մենք նաև թեստավորեցինք թեստերը՝ յուրաքանչյուր թիվ փոխելով սխալ արժեքի և ստուգելով, որ թեստը բռնում է այն։
Չափելը հեշտ է սխալվել
Մեր առաջին չափումը ասաց, որ մաքուր deploy-ը մոտ 3% կոտրված է։ Դա չէր։ Մենք հաշվում էինք 200-ից տարբեր յուրաքանչյուր պատասխան, իսկ առողջության endpoint-ից դադարեցման ընթացքում 503-ը ձախողում չէ․ դա դադարեցման աշխատանքն է, որ ասում է balancer-ին չընտրել այդ սերվերը, մինչ այն շարունակում է սպասարկել իրական հարցումները։
Օգտատերը զգում է 502-ը․ հարցումը ոչ մի տեղ չհասավ։ Միայն դրանք հաշվելը տվեց իրական պատկերը՝ 10, ապա 6, ապա 0՝ երեք արտադրական deploy-ի ընթացքում։
Ինչ սովորեցինք
- Ինքնաբուժումը պետք է իմանա պլանավորված պարապուրդի մասին։ Watchdog-ը, որ չի կարող տարբերել deploy-ը խափանումից, ի վերջո կկռվի deploy-ի հետ։
- Դադարեցումը ձեռքսեղմում է։ Սերվերը պետք է շարունակի սպասարկել, մինչև load balancer-ը ապացուցված կերպով դադարի երթևեկություն ուղարկել, և այդ ժամանակացույցը սահմանվում է balancer-ի վրա, ոչ սերվերի։
- Ինվարիանտները կոդավորեք թեստերով։ Գործառնական թվերը շեղվում են։ Թեստերը, որ դրանք միմյանց հետ կապում են, չեն շեղվում։
- Որոշեք, թե ինչ եք չափում, նախքան չափելը։ «Սխալները» սխալ չափանիշ էր․ «հարցումները, որ ոչինչ չհասան» ճիշտն էր։
Եթե հրապարակում եք հավելված Mythex-ում, սա ոչ մի կերպ տեսանելի չէ ձեզ համար՝ և դա է կետը։ Առնչվող․ ինչպես է ձեր հրապարակված հավելվածը մնում ակտիվ, երբ նորից եք հրապարակում։