გაუშვი მეორე, უფრო პატარა სერვერი იგივე პროგრამული ვერსიებით, რეალური მონაცემების ახალი ასლით, რომელშიც პირადი ნაწილი აჩხრეკილია, და საკუთარი credentials-ით, რომლებიც რეალურ არაფერთან მიდის. deploy ჯერ იქ გააკეთე, ყოველთვის, და ტესტის გასატარებლად მას ხელით არასოდეს შეეხო. ეს არის staging გარემო და პანელზე ის ერთ დამატებით პატარა გეგმას ჯდება - app ხაზებზე დაწერის დროისთვის თვეში $4-დან - რაც ერთ ცუდ საღამოზე ნაკლებია ცოცხალ სერვერზე.
განახლების ტესტირება ცოცხალ სერვერზე ნორმალურია იმ საღამომდე, როცა აღარ არის. staging-ის ღირებულება ის კი არ არის, რომ bug-ებს პოულობს, რადგან უმეტესად ვერ იპოვის. ღირებულება ისაა, რომ ის ერთადერთი ადგილია, სადაც განახლება შეიძლება ჩავარდეს ისე, რომ არავინ უყურებდეს, და რომ გაიძულებს, ჩაწერო, რისგან შედგება "deploy" სინამდვილეში.
რისთვის არის staging სერვერი და რისთვის არა#
ზუსტად განსაზღვრე ამოცანა, რადგან ბუნდოვანი staging სერვერი ისეთია, რომელსაც ერთ თვეში აღარ გამოიყენებ.
ეს deploy-ის რეპეტიციაა და არა კოდის. კოდი შენს ლეპტოპზე გატესტილია. რაც არასოდეს გატესტილა, ეს კონკრეტული თანმიმდევრობაა: runtime-ის ეს ვერსია, ეს კონფიგურაციის ფაილები, ეს migration, რეალური მონაცემების ფორმის მქონე მონაცემებზე, ამდენი მეხსიერების მქონე მანქანაზე. სწორედ ეს თანმიმდევრობა ტყდება და სწორედ ამის გამეორება არ შეუძლია ლეპტოპს.
აქ მიდის პირველად ვერსიის განახლებები. თამაშის ახალი ვერსია, ახალი Java, ახალი plugin, მონაცემთა ბაზის ახალი major ვერსია. ყველაფერი, რისი ჩავარდნის სახეც არის "სამყარო იხსნება და ჩუმად შეცვლილია", ორიგინალს შეხებამდე ასლზე უნდა გაიაროს.
ეს დეველოპმენტის მანქანა არ არის. თუ ხალხი staging-ზე ფაილებს პირდაპირ ასწორებს, ის production-ის სარკე აღარ არის და გახდა მეორე production უარესი uptime-ით. ცვლილებები იმავე გზით უნდა მოვიდეს, რითაც production-ზე მოვა, თორემ ტესტმა არაფერი დაამტკიცა.
ეს წარმადობის ტესტი არ არის. ერთი პატარა სერვერი, რომელზეც სამი ტესტერია, არ გეტყვის, როგორ იქცევა ორმოცი მოთამაშე. ერთხელ ხმამაღლა თქვი, რომ არავინ ელოდოს.
ეს ზუსტად გადააკოპირე#
staging-ის აზრი ერთნაირობაა, ამიტომ გადასაკოპირებელი სია მოკლე და შეუბრალებელია:
- ყველა ვერსიის ნომერი. თამაშის ან runtime-ის ვერსია და ზუსტი build. "Paper 1.21.1" ვერსია არ არის,
paper-1.21.1-132არის. აპლიკაციისთვის ეს ნიშნავს Node-ის ან Python-ის იგივე minor ვერსიას და ინსტალაციას lockfile-იდან და არაpackage.json-ში მოცემული დიაპაზონიდან. განსხვავებაnpm ci-სა დაnpm install-ს შორის ზუსტად ისაა, რაც staging სერვერს, რომელიც production-ს ასახავს, ყოფს სერვერისგან, რომელიც ერთ მომენტს ასახავს - npm ci vs npm install გრძელი ვერსიაა. - ყველა mod, plugin ან დამოკიდებულება, იმავე ვერსიით, იმავე ჩატვირთვის თანმიმდევრობით.
- კონფიგურაციის ფაილები, ყველაფრის გარეშე, რაც credential-ს შეიცავს. იგივე tick პარამეტრები, იგივე view distance, იგივე worker-ების რაოდენობა, იგივე მეხსიერების ფლაგები, სადაც ისინი პატარა გეგმას ეგუება.
- სამყაროს ან მონაცემთა ბაზის ახალი ასლი, რომ ტესტი რეალური მონაცემების ფორმებზე გაიაროს: ბაზა 900 plugin ცხრილით, ბაზა 40 000 ბლოკით, მოთამაშე ინვენტარით, რომელიც სასაზღვრო შემთხვევებით არის სავსე. სინთეტიკური მონაცემები საინტერესო არაფერს ამოწმებს.
- გაშვების ბრძანება და მისი არგუმენტები, რაც პანელზე Startup tab-ის ველებს ნიშნავს და სადაც "staging-ზე მუშაობს" საიდუმლოებების ნახევარი სინამდვილეში ცხოვრობს.
ჭეშმარიტი ასლის მიღების ყველაზე სწრაფი გზა backup-ია. გააკეთე production-ზე, გადმოწერე, ატვირთე staging-ზე და ადგილზე ამოაარქივე. ამას სასიამოვნო გვერდითი ეფექტი აქვს - შენი აღდგენის გზა განრიგით მუშაობს - იხილე აღდგენის ტესტი სანამ დაგჭირდება, რატომ არის ეს backup-ის ქონაზე მეტად მნიშვნელოვანი.
განზრახ განსხვავდეს ეს#
ცალკე credentials, ცალკე მონაცემთა ბაზა და კავშირი არაფერთან, რაც რეალურ ადამიანებს შეტყობინებებს უგზავნის. staging სერვერი, რომელსაც შეუძლია შენს მომხმარებლებს მეილი გაუგზავნოს ან production ბაზაში ჩაწეროს, production სერვერია შეცდომაში შემყვანი სახელით. კონკრეტულად:
| რა | Production | Staging |
|---|---|---|
| მონაცემთა ბაზა | საკუთარი instance და მომხმარებელი | ცალკე instance, ცალკე პაროლი |
| მეილი | რეალური SMTP | catch-all inbox, ან არაფერი |
| გადახდები | Live გასაღებები | მხოლოდ test ან sandbox გასაღებები |
| Discord ან Telegram bot | რეალური token, რეალური guild | მეორე bot, კერძო სატესტო guild |
| Webhook-ები | რეალური არხები | მკვდარი არხი, რომელსაც არასოდეს კითხულობ |
| დომენი | app.example.com | staging.example.com, noindex |
| Backup-ები | სრული განრიგი | არჩევითი. ის განზრახ გასაყრელია |
| წვდომა | Least privilege | ყველა, ვისაც ტესტირება სჭირდება |
ორი მათგანი ცხრილის სტრიქონზე მეტს იმსახურებს.
მონაცემთა ბაზა. ამ მთელ სფეროში ყველაზე გავრცელებული კატასტროფული შეცდომა ისაა, როცა staging deploy-ს გარემოს ცვლადში ჯერ კიდევ production-ის connection string უწერია, რომელიც ვიღაცამ დაავიწყდა გადაეფარა, და migration შემდეგ ცოცხალ მონაცემებზე სრულდება. დაცვა სიფრთხილე კი არა, მოწყობაა: staging-ს თავიდანვე საკუთარი მონაცემთა ბაზა მიეცი და production-ის credentials staging სერვერიდან საერთოდ მიუწვდომელი გახადე. სხვა მომხმარებელი, სხვა პაროლი, და თუ ბაზა ქსელიდან მისაწვდომია, შეზღუდე მისამართით. გარემოს ცვლადები და საიდუმლოები ფარავს, როგორ დააშორო ორი ნაკრები.
პირადი მონაცემები. production-ის მონაცემების ასლი შენი მომხმარებლების მონაცემების ასლია, რომელიც უფრო თავისუფალი წვდომის სერვერზე დევს. აჩხრიკე ის იმპორტის ნაწილად და არა მოგვიანებით:
UPDATE users SET email = 'user' || id || '@example.invalid', phone = NULL, password_hash = '$2y$12$notarealhashnotarealhashnotarealhash1234567890ab';DELETE FROM sessions;DELETE FROM api_tokens;UPDATE payment_methods SET last4 = '0000', token = NULL;გაუშვი ეს აღდგენის იმავე transaction-ში, თუ შეგიძლია, რომ არასოდეს იყოს მომენტი, როცა სრული ასლი აჩხრეკის გარეშე არსებობს. თამაშის სერვერისთვის ექვივალენტი უფრო პატარაა, მაგრამ ნამდვილი: სტაფის სია მხოლოდ შენამდე შეამცირე, plugin კონფიგურაციებში ნებისმიერი Discord webhook URL გააცარიელე და ნებისმიერი შენახული გადახდის ან Tebex გასაღები წაშალე.
მეორე სერვერის ზომა#
პატარა არის მთელი აზრი - სწორედ ამიტომ არის ის ხელმისაწვდომი - მაგრამ პატარობის სამი სახე ტესტს აუქმებს და ღირს იმის ცოდნა, რომელი.
უსაფრთხოა შემცირება: დისკი, სანამ მონაცემების ასლი ეტევა; გამოყოფილი პორტების რაოდენობა; backup სლოტები; და CPU, რაც ყველაფერს ნელს გახდის ქცევის შეცვლის გარეშე.
არ არის უსაფრთხო შემცირება: მეხსიერება, როცა ტესტირებადი რამ მეხსიერებასთან არის დაკავშირებული. modpack, რომელსაც 6 GB სჭირდება, 2 GB-ზე არ ავა და "staging-ზე ჩავარდა" მაშინ არაფერს გეუბნება. worker-ების რაოდენობა, თუ შეამცირებ, ყველა concurrency bug-ს დამალავს. და ნებისმიერი მყარი ლიმიტი, რომელთანაც production-ზე ახლოს ხარ - connection pool-ის ზომა, heap-ის ჭერი - იგივე რიცხვი უნდა იყოს, თორემ ტესტი სხვა სისტემას ზომავს. Connection pool-ები და ლიმიტები ჩვეულებრივი ადგილია, სადაც ეს გვკბენს.
აპლიკაციისთვის გონივრული ნაგულისხმევი იგივე გეგმაა ერთი tier-ით დაბლა: იგივე runtime, ნახევარი მეხსიერება და იგივე გარემოს ცვლადები იმათ გარდა, რომლებიც უნდა განსხვავდებოდეს. თამაშის სერვერისთვის მეხსიერება დააკავშირე და დისკი შეამცირე, რადგან ტესტი ჩვეულებრივ მეხსიერებას ეხება. RE:NODE-ის app, web და მონაცემთა ბაზის ხაზები tier-ის მიუხედავად ერთსა და იმავე პანელს იღებს - კონსოლი, ფაილების მმართველი, SFTP, backup სლოტები, განრიგები, subuser-ები - ამიტომ პატარა staging გეგმა პანელის შემცირებული ვერსია არ არის, მხოლოდ აპარატურისა.
როგორ არ დააშორო ისინი ერთმანეთს#
Drift არის რეჟიმი, რომელიც staging გარემოებს კლავს. ის ყოველთვის ერთნაირად ხდება: რაღაც production-ზე 23:00-ზე ტყდება, ვიღაც მას ფაილის პირდაპირ რედაქტირებით ასწორებს და არავინ აკეთებს იმავე რედაქტირებას staging-ზე. სამი კვირის შემდეგ staging ამბობს, რომ release კარგია, production არ ეთანხმება, ყველა ასკვნის, რომ staging უსარგებლოა და ის უქმდება.
სამი ჩვევა მას პატიოსანს ინახავს.
ცვლილებები ერთი მიმართულებით მიედინება. ყველაფერი, რაც production-ს ცვლის, ჯერ staging-ზე უნდა შეიძლებოდეს იგივე მექანიზმით. app ხაზებზე ეს მექანიზმი Git-ია: RE:NODE-ის deploy არის GitHub, GitHub App-ით მოკლევადიანი token-ებით, ამიტომ კერძო repository-ები მუშაობს, ორი გადამრთველით - pull ყოველ გაშვებაზე და deploy on push. Deploy on push მხოლოდ უკვე გაშვებულ სერვერს უკეთებს restart-ს, რაც staging-ისთვის სასარგებლო თვისებაა: ტესტებს შორის გაჩერებული დატოვე და ის ყველაფერს შემდეგ გაშვებაზე აიღებს. Node აპლიკაციის deploy GitHub-იდან გადის მოწყობას.
გადაუდებელი შესწორებები დღეში ხელახლა სრულდება. არა "როცა ხელი მივალწევთ". ჩაწერე ინციდენტის ჩანაწერში: შესწორება დასრულებული არ არის, სანამ repository-შიც და staging-ზეც არ იარსებებს.
შეადარე ისინი განრიგით. ეს ათწუთიანი საქმეა, რომელიც drift-ს მანამ პოულობს, სანამ შეგარცხვენს. თამაშის სერვერისთვის შეადარე plugin-ების სია და კონფიგურაცია:
$ ls -1 plugins/*.jar | xargs -n1 basename | sort > prod-plugins.txt$ ls -1 plugins/*.jar | xargs -n1 basename | sort > staging-plugins.txt$ diff prod-plugins.txt staging-plugins.txt$ diff <(sort prod-server.properties) <(sort staging-server.properties)აპლიკაციისთვის ექვივალენტი არის lockfile-ის, runtime-ის ვერსიისა და გარემოს ცვლადების სახელების სიის შედარება - მხოლოდ სახელები, მნიშვნელობები არასოდეს:
$ node --version && cat package-lock.json | head -5$ printenv | cut -d= -f1 | sort > env-names.txtცვლადების სახელების ნაკრებში სხვაობა არსებული საუკეთესო ადრეული გაფრთხილებაა. ცვლადი, რომელიც production-ზე არსებობს და staging-ზე არა, ნიშნავს, რომ შემდეგი deploy პროცესს გაუშვებს, რომელიც undefined-ს წაიკითხავს და ისე იმოქმედებს, როგორც არავის უნახავს.
რას ვერ დაიჭერს staging#
თქვი ეს გარკვევით, რომ ამაზე ცრუ თავდაჯერებულობა არავინ ააგოს.
დატვირთვა. სამი ადამიანის ირგვლივ დაწკაპუნება 19:00-ზე ორმოცი მოთამაშის შესვლა არ არის. concurrency bug-ები, lock contention, connection pool-ის ამოწურვა და მეხსიერების ზრდა მუდმივი ტრაფიკის დროს უმოქმედო staging სერვერზე უხილავია.
მონაცემების მოცულობა. მოთხოვნა, რომელიც 400 MB-ზე მყისიერია, 40 GB-ზე შეიძლება ცხრილის სრული სკანირება იყოს. თუ staging ასლი შემცირებული ქვენაკრებია, მისგან ყოველი წარმადობის დასკვნა არასწორია. გადააკოპირე მთელი, ან შეეგუე, რომ წარმადობას არ ტესტავ.
დრო. ნელი მეხსიერების გაჟონვა, log დირექტორიების შევსება, სერტიფიკატის ვადის გასვლა, cron ამოცანები, რომლებიც მხოლოდ თვის პირველ რიცხვში ეშვება. staging ჩვეულებრივ ძალიან ახალგაზრდა და ძალიან უმოქმედოა, რომ რომელიმე მათგანი აჩვენოს.
მესამე მხარის ქცევა. Sandbox API-ები ნამდვილი API არ არის. Rate limit-ები, ნაწილობრივი გათიშვები და payload-ები ველებით, რომლებსაც დოკუმენტაცია არ ახსენებს, მხოლოდ production-ზე ხდება.
ერთჯერადი. plugin, რომელიც ფაილს კითხულობს, რომელიც მხოლოდ production-ზე არსებობს, DNS ჩანაწერი, რომელიც განსხვავებულია, firewall-ის წესი, რომელიც ვიღაცამ ხელით დაამატა. ეს ზუსტად ზემოთ აღწერილი drift-ის პრობლემაა, სწორედ ამიტომ არის შედარების რუტინა ტესტირებაზე მნიშვნელოვანი.
ამ სიის გათვალისწინებით, პატიოსანი ფორმულირებაა: staging იჭერს ჩავარდნილ deploy-ს, ჩავარდნილ migration-ს, არასწორ კონფიგურაციას და შეუთავსებელ ვერსიას. ეს ხუთიდან ოთხია იმ ნივთებიდან, რაც release-ის საღამოს არასწორად მიდის. მეხუთე დატვირთვაა, დატვირთვისთვის კი backup-ები და rollback გეგმაა.
როგორ გამოიყურება release სინამდვილეში#
ქვემოთ მოცემული რუტინა არის შედეგი. ღირს შენი საკუთარიც ჩაწერო repository-ში, თუნდაც ამაზე მოკლე იყოს.
- Merge გააკეთე ცვლილებაზე. Staging repository-დან deploy-დება, ავტომატურად ან შენს შემდეგ გაშვებაზე.
- გაუშვი staging და წაიკითხე log თავიდან. გაშვების banner გეუბნება ვერსიებს, რომლებიც რეალურად ჩაიტვირთა. შეადარე production-ისას.
- Migration ჯერ staging-ზე გაუშვი და დრო გაზომე. migration, რომელიც 40 წამს გრძელდება staging-ზე მონაცემების მეათედით, production-ზე ოთხწუთიანი გათიშვაა, თუ ის ისე არ დაწერე, რომ locking-ს აარიდოს - migration-ები გათიშვის გარეშე ფარავს ნიმუშებს.
- Smoke test. ექვსი რამ, ყოველთვის იგივე ექვსი: შესვლა, მთავარი მოქმედება, ის, რასაც ცვლილება შეეხო, ერთი ის, რასაც აუცილებლად არ უნდა შეხებოდა, admin გზა, log-ში ახალი გაფრთხილებები.
- გააკეთე production backup. ყველაფერზე ადრე, ყოველ ჯერზე. ეს არის rollback.
- Production-ზე იგივე build გაუშვი. არა rebuild, არა "იგივე commit ხელახლა აგებული" - იგივე artefact, თუ შეგიძლია, იგივე commit hash მინიმუმ.
- უყურე პირველ ხუთ წუთს. ახალი გაფრთხილებები log-ში, მეხსიერება და გრაფიკი. თუ ცუდია, rollback გააკეთე ახლავე და არა ცოცხლად დიაგნოსტიკა.
- ჩაწერე ყველაფერი, რაც ხელით გააკეთე, და იმავე დღეს გაიმეორე staging-ზე.
იმ ნაწილისთვის, როცა restart მომხმარებლებს თვალსაჩინოა, zero-downtime deploy პატარა სერვერზე ფარავს დაცარიელების დახურვას load balancer-ის გარეშე.
ერთი შენიშვნა წვდომაზე: ხალხს, ვინც ტესტავს, billing უფლებები ან სერვერის წაშლის შესაძლებლობა არ სჭირდება. RE:NODE-ს აქვს subuser-ები, როლები და გუნდები დეტალური უფლებებით - მხოლოდ კონსოლი, მხოლოდ ფაილები, billing-ის გარეშე - დროში შეზღუდული წვდომით და თითო სერვერზე აქტივობის log-ით, რაც staging გარემოსთვის სწორი ფორმაა, რომელსაც რამდენიმე ადამიანი ეჩრება. Subuser-ები და least privilege შეიცავს დანაწილებას.
FAQ#
მართლა მჭირდება staging სერვერი პატარა community სერვერისთვის?
vanilla სერვერისთვის ხუთი მეგობრით - არა. იმ მომენტიდან, როცა mod-ები, plugin-ები, მონაცემთა ბაზა გაქვს, ან ვინმე, ვისაც საღამოს დაკარგვა ეწყინება - დიახ. გამომწვევი მოთამაშეების რაოდენობა კი არა, ის არის, რამდენად ძვირი იქნება state-ის დაკარგვა და რამდენ მოძრავ ნაწილს ეხება ვერსიის განახლება.
შეიძლება staging-მა და production-მა ერთი მონაცემთა ბაზა გაიზიაროს, თუ ფრთხილად ვარ?
არა. ეს ერთადერთი წესია ამ პოსტში გამონაკლისის გარეშე. გაზიარებული ბაზები ნიშნავს, რომ staging migration-მა შეიძლება production მონაცემები გაანადგუროს, staging bug-მა კი უაზრობა ჩაწეროს, რომელსაც შემდეგ production მიაწვდის. ცალკე instance-ები, ცალკე credentials, და staging-ს production-ისას საერთოდ არ უნდა შეეძლოს მისწვდომა.
როგორ ავიცილო თავიდან, რომ staging თვეებით ძველი იყოს?
განაახლე მონაცემები განრიგით და არა მოთხოვნით - თვეში ერთხელ ჩვეულებრივ საკმარისია - და ყოველი ცვლილება ჯერ staging-ზე deploy-ე, მაშინაც კი, როცა დარწმუნებული ხარ. მონაცემების განახლება არის გადმოწერა, ატვირთვა და აჩხრეკის სკრიპტი, რაც თხუთმეტწუთიანი საქმეა და კალენდარში ჩაწერა შეიძლება.
უნდა იყოს staging production-ის ზომის?
მეხსიერება და ნებისმიერი მყარი ლიმიტი, რომლის წინააღმდეგაც ტესტავ, შეუსაბამე, დანარჩენი შეამცირე. ნახევარი CPU staging-ს ნელს ხდის, რაც უვნებელია. ნახევარი მეხსიერება ქცევას ცვლის, რაც უვნებელი არ არის, განსაკუთრებით modded თამაშის სერვერისთვის ან JVM-ისთვის, სადაც heap-ის ზომა სწორედ ის არის, რასაც ტესტავ.
ღირს თუ არა მეორე სერვერის ფასის გადახდა მხოლოდ სატესტოდ?
ერთხელ შეადარე ალტერნატივის ფასს. პატარა app ან თამაშის გეგმა თვეში რამდენიმე დოლარია, ხოლო უფრო გრძელი ვადები თვეში უფრო იაფია. ერთი დაკარგული საღამო, ერთი დაზიანებული სამყარო ან ერთი migration, რომელიც ცოცხალ მონაცემებზე გაეშვა, მეორე სერვერის ერთ წელზე მეტი ღირს. აქ უფასო გეგმა არ არსებობს, ამიტომ ეს ნამდვილი ხარჯია, უბრალოდ პატარა.
შემიძლია ერთი staging სერვერი რამდენიმე პროექტისთვის გამოვიყენო?
დიახ, თუ ისინი ერთდროულად არ მუშაობს და გაწმენდაში დისციპლინირებული ხარ. ეს ცალ-ცალკე სერვერზე უარესია, რადგან წინა პროექტის ნარჩენები ზუსტად ის სხვაობაა, რაც ტესტს ატყუებს, მაგრამ staging-ის არქონაზე ბევრად უკეთესია.




კომენტარები
სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.