{"id":2368,"date":"2022-03-21T22:54:39","date_gmt":"2022-03-21T20:54:39","guid":{"rendered":"https:\/\/guven.atbakan.com\/blog\/?p=2368"},"modified":"2022-09-02T18:39:26","modified_gmt":"2022-09-02T16:39:26","slug":"zero-downtime-deployment","status":"publish","type":"post","link":"https:\/\/guven.atbakan.com\/blog\/tr\/zero-downtime-deployment\/","title":{"rendered":"Zero Downtime Deployment"},"content":{"rendered":"<p>Zero downtime deployment, yani benim \u00e7evirimle &quot;projede hi\u00e7 problem ya\u015famadan yeni s\u00fcr\u00fcm\u00fc yay\u0131na almak&quot; \u00e7ok\u00e7a kullan\u0131lan ve \u00e7o\u011fu ki\u015finin kavramsal ve teknik olarak ka\u00e7\u0131nd\u0131\u011f\u0131 bir konu. Bunun temelinde, bu kavram\u0131n sadece belli ba\u015fl\u0131 ara\u00e7lar ile sa\u011fland\u0131\u011f\u0131n\u0131n d\u00fc\u015f\u00fcn\u00fclmesi yat\u0131yor. \u00c7o\u011fu ki\u015fi bunun i\u00e7in uygulaman\u0131n bulutta olmas\u0131 gerekti\u011fini veya \u00f6\u011frenmek i\u00e7in bilgi ve vakit gerektiren bir arac\u0131n kullan\u0131lmas\u0131 gerekti\u011fini d\u00fc\u015f\u00fcn\u00fcyor. <\/p>\n<h2>Ba\u015flamadan \u00f6nce<\/h2>\n<p>Sizleri y\u0131llar \u00f6nce yaz\u0131lm\u0131\u015f ve benim bu konuyla ilgili hemen her sunumumda referans verdi\u011fim bir yaz\u0131ya g\u00f6t\u00fcrmek istiyorum. FileZilla ile Continuous Integration: <a href=\"https:\/\/www.sonsuzdongu.com\/blog\/filezilla-ile-continuous-integration\">https:\/\/www.sonsuzdongu.com\/blog\/filezilla-ile-continuous-integration<\/a><br \/>\nA\u00e7\u0131k konu\u015fmam gerekirse, benim de bilgisayar\u0131ma ilk y\u00fckledi\u011fim ara\u00e7lardan birtanesi FileZilla oluyor. <\/p>\n<h2>\u015eaka bir yana<\/h2>\n<p>Zero-downtime deployment, \u00e7e\u015fitli y\u00f6ntemlerle uygulanabiliyor &#8211; FileZilla ile uygulanmad\u0131\u011f\u0131nda mutab\u0131k kalm\u0131\u015f\u0131zd\u0131r. Biz Moneo olarak, her projede o projeye uygun bir y\u00f6ntem belirleyerek veya varolan y\u00f6ntemi uyarlayarak\/geli\u015ftirerek kullan\u0131yoruz. Projenin b\u00fcy\u00fckl\u00fc\u011f\u00fc farketmeksizin t\u00fcm projelerimizde bu y\u00f6ntemi kullan\u0131yoruz. <\/p>\n<p>Bunun i\u00e7in elbette hayat\u0131 kolayla\u015ft\u0131ran \u00e7ok\u00e7a ara\u00e7 var. S\u0131kl\u0131kla kulland\u0131\u011f\u0131m\u0131z ara\u00e7lar\u0131n ba\u015f\u0131nda <a href=\"https:\/\/deployer.org\/\">Deployer<\/a> ve SaaS servis olarak <a href=\"https:\/\/envoyer.io\/\">Envoyer.io<\/a> geliyor. Veya do\u011frudan Gitlab CI s\u00fcre\u00e7lerine ba\u011flayabiliyoruz. AWS taraf\u0131nda ise <a href=\"https:\/\/aws.amazon.com\/tr\/codebuild\/\">CodeBuild<\/a>&#8216;i aktif olarak kullan\u0131yoruz. Bunlara daha sonra de\u011finiriz. Bu yaz\u0131da biraz daha kavramsal olarak ilerleyece\u011fiz. <\/p>\n<h2>Deploy esnas\u0131nda hata olu\u015fturabilecek noktalar<\/h2>\n<h3>Dosya senkronizasyonu<\/h3>\n<p>Deploylarda ya\u015fanan en b\u00fcy\u00fck problem \u00e7o\u011funlukla dosyalar\u0131n senkron bi\u00e7imde y\u00fcklenmemesinden kaynaklan\u0131yor. Ftp veya rsync ile dosyalar\u0131 uzak sunuculara y\u00fckledi\u011fimizi varsayal\u0131m. Bu senaryoda birbirine ba\u011f\u0131ml\u0131l\u0131k i\u00e7eren iki dosyadan birisi hen\u00fcz y\u00fcklenmemi\u015f olabilir! Bu noktada sistem hata verecektir ve deploy tamamlanana kadar projenin \u00e7al\u0131\u015fmas\u0131 aksayabilir. <\/p>\n<p>Tabi <code>git pull<\/code> gibi bir y\u00f6ntem kulland\u0131\u011f\u0131m\u0131zda bu durumla pek kar\u015f\u0131la\u015f\u0131lm\u0131yor \u00e7\u00fcnk\u00fc t\u00fcm dosyalar bir paket olarak indiriliyor ve a\u00e7\u0131l\u0131yor (yine de \u00e7ok k\u0131sa downtime ya\u015fanabilir). <\/p>\n<h3>3. Parti k\u00fct\u00fcphaneler<\/h3>\n<p>Bu problemi 3.parti k\u00fct\u00fcphaneler takip ediyor. PHP \u00fczerinden \u00f6rnekleyecek olursak, projeye eklenen yeni paketler ya da g\u00fcncellenen paketler y\u00fcklenene kadar projenin \u00e7al\u0131\u015fmas\u0131 aksayabilir. Bir \u00f6nceki maddeyle asl\u0131nda benzer bir konu bu.<\/p>\n<pre><code>git pull\ncomposer install --prefer-dist --no-dev --optimize-autoloader<\/code><\/pre>\n<h3>Veritaban\u0131 de\u011fi\u015fiklikleri<\/h3>\n<p>Veritaban\u0131na yeni eklenen bir kolon, hen\u00fcz olu\u015fturulmadan kullan\u0131lmak istendi\u011finde takdir edersiniz ki hata verecektir. Bu sefer dosya ba\u011f\u0131ml\u0131l\u0131\u011f\u0131m\u0131z yok ama veritaban\u0131na bir ba\u011f\u0131ml\u0131l\u0131\u011f\u0131m\u0131z var. <\/p>\n<pre><code>git pull\ncomposer install --prefer-dist --no-dev --optimize-autoloader\nphp artisan migrate --force<\/code><\/pre>\n<p>Migration i\u015flemini git pull \u00f6ncesinde yapam\u0131yoruz. \u00c7\u00fcnk\u00fc yeni de\u011fi\u015fiklikler ile birlikte geliyor. Sonras\u0131nda migration yapt\u0131\u011f\u0131m\u0131zda da downtime ya\u015fayabiliyoruz. Bunun \u00e7\u00f6z\u00fcm\u00fc i\u00e7in yeni \u00f6zelli\u011fi 2 par\u00e7a halinde deploy edebilirsiniz. <\/p>\n<pre><code># repoya sadece migration dosyas\u0131 g\u00f6nderili. \ngit pull\ncomposer install --prefer-dist --no-dev --optimize-autoloader\nphp artisan migrate --force\n# repoya kodsal de\u011fi\u015fiklikler de g\u00f6nderilir\ngit pull\ncomposer install --prefer-dist --no-dev --optimize-autoloader<\/code><\/pre>\n<p>Takdir edersiniz ki bu olduk\u00e7a yorucu ve zahmetli bir i\u015f. Yapt\u0131\u011f\u0131n\u0131z geli\u015ftirmeyi 2 seferde deploy etmek i\u00e7in 2 ayr\u0131 PR a\u00e7\u0131p, ilkine sadece migration dosyalar\u0131n\u0131 koymak ikincisinde ise kodlar\u0131 koymak ger\u00e7ekten u\u011fra\u015ft\u0131r\u0131c\u0131. Migration i\u015flemini reponuz i\u00e7erisinden yapm\u0131yorsan\u0131z biraz daha kolay olabilir. \u00d6rne\u011fin biz bir projemizde <a href=\"https:\/\/flywaydb.org\/\">FlywayDB<\/a> kullan\u0131yoruz. Tabi bunun takibi i\u00e7in de farkl\u0131 bir repo kullan\u0131yoruz ve DB de\u011fi\u015fikliklerini bu repoya pushluyoruz. Bir kodsal de\u011fi\u015fiklik i\u00e7in Pre-MR ve Post-MR migrationlar tan\u0131mlayabiliyoruz. Ama tabi bunun y\u00f6netimini de do\u011fru yapmak gerekiyor ve a\u00e7\u0131k\u00e7as\u0131 bazen konforlu olmayabiliyor. <\/p>\n<h3>Compile edilecek konular<\/h3>\n<p>Asl\u0131nda bu konu 3.parti k\u00fct\u00fcphaneler alt\u0131nda da i\u015flenebilirdi. Ama ayr\u0131 bir paragraf\u0131 hakediyor. \u015eu ana kadar yapt\u0131\u011f\u0131m\u0131z yay\u0131na alma i\u015flemlerinde en \u00e7ok s\u00fcreyi npm paketlerinin y\u00fcklenmesi ve derlenmesi al\u0131yor. Elbette bu s\u00fcreler kullan\u0131ma g\u00f6re azalabilir. Ama genel olarak <code>npm install<\/code> ve <code>MARKDOWN_HASH3d5b25a38b4cc172dbcdb8c6ceecc0ddMARKDOWN<em>HASH<\/code> <\/em>(elbette bu komutlar projeye g\u00f6re de\u011fi\u015fkenlik g\u00f6sterirler)_ i\u015flemlerinde uzunca vakit ge\u00e7iyor.<br \/>\nBu y\u00fczden bu kodlar\u0131n &quot;\u00f6nceden derlenmesi&quot; ve yay\u0131na al\u0131nmas\u0131 gerekiyor. Bunun i\u00e7in <code>dist<\/code> (derlenmi\u015f hali) klas\u00f6r\u00fcn\u00fc <code>git<\/code> i\u00e7erisine mi atmal\u0131y\u0131z? Tabi ki hay\u0131r!<\/p>\n<p>Asl\u0131nda zero-downtime deployment&#8217;\u0131n \u00f6ne \u00e7\u0131kt\u0131\u011f\u0131 yer de buras\u0131 oluyor. <\/p>\n<h2>Zero downtime proje derleme<\/h2>\n<p>\u00c7ok basit\u00e7e, projenin ba\u015fka bir ortamda\/klas\u00f6rde derlenmesi ve derlenmi\u015f halinin yay\u0131na al\u0131nmas\u0131 olarak d\u00fc\u015f\u00fcnebiliriz. Diyelim ki projeniz <code>\/var\/www\/html<\/code> klas\u00f6r\u00fc i\u00e7erisinde yay\u0131nlan\u0131yor. Biz yay\u0131na alaca\u011f\u0131m\u0131z versiyonu ba\u015fka bir klas\u00f6r i\u00e7erisine \u00e7ekip t\u00fcm i\u015flemleri yap\u0131p bitti\u011finde yay\u0131na alaca\u011f\u0131z. <\/p>\n<pre><code class=\"language-bash\">cd \/var\/www\/build\ngit checkout your-repository-url\ncomposer install --prefer-dist --no-dev --optimize-autoloader\nphp artisan migrate --force\nnpm install\nnpm build<\/code><\/pre>\n<p>Yukar\u0131daki sat\u0131rlar\u0131 \u00e7al\u0131\u015ft\u0131rd\u0131\u011f\u0131m\u0131zda, projenin son halinin <code>build<\/code> klas\u00f6r\u00fcnde durdu\u011funu g\u00f6rebiliyoruz. Art\u0131k tek yapmam\u0131z gereken bu de\u011fi\u015fiklikleri <code>\/var\/www\/html<\/code> alt\u0131na almak. <\/p>\n<p>Bunun i\u00e7in basit\u00e7e <code>cp -R \/var\/www\/build \/var\/www\/html<\/code> komutunu kullanabilirsiniz. Ama bu ilk bahsetti\u011fimiz dosya senkronizasyonuna yol a\u00e7abilir. Benzer \u015fekilde <code>rsync<\/code> kullanabilirsiniz fakat bu da ayn\u0131 kap\u0131ya \u00e7\u0131kar. Bunun i\u00e7in g\u00fczel bir \u00e7\u00f6z\u00fcm\u00fcm\u00fcz var.<\/p>\n<h3>Symlink<\/h3>\n<p>Linux&#8217;ta sembolik link olarak ge\u00e7en <code>symlink<\/code> bu tarz deploylarda en \u00e7ok kullan\u0131lan y\u00f6ntemlerden birisi olarak ge\u00e7iyor. Bunun i\u00e7in yapmam\u0131z gereken bir \u00f6n konu var. Her build i\u00e7in bir build numaras\u0131 (numara olmak zorunda de\u011fil, ayr\u0131\u015ft\u0131r\u0131c\u0131 olabilir) eklememiz gerekiyor. Yani <code>\/var\/www\/build<\/code> klas\u00f6r\u00fc i\u00e7erisinde de\u011fil de, her bir deployu farkl\u0131 bir klas\u00f6rde yapaca\u011f\u0131z.<br \/>\n\u00d6rne\u011fin <code>\/var\/www\/build-2022-03-19-09-25<\/code> gibi bir klas\u00f6r olu\u015fturabiliriz. Zero-downtime konseptinde bu klas\u00f6rlere &quot;releases&quot; ad\u0131 veriliyor.<\/p>\n<p>Bu klas\u00f6r\u00fc olu\u015fturduktan sonra yapman\u0131z gereken \u00e7ok basit:<br \/>\n<code>ln -s \/var\/www\/build-2022-03-19-09-25 \/var\/www\/html<\/code>. Bu komutla birlikte Linux sembolik linki yenileyecek ve art\u0131k yay\u0131ndaki klas\u00f6r\u00fcn\u00fcz istedi\u011finiz klas\u00f6r alt\u0131ndan \u00e7al\u0131\u015fmaya ba\u015flayacak. <\/p>\n<h3>Rollback &#8211; Ge\u00e7mi\u015fe d\u00f6n\u00fc\u015f<\/h3>\n<p><code>releases<\/code> klas\u00f6rleriniz sayesinde, art\u0131k s\u00fcr\u00fcmler aras\u0131 ge\u00e7i\u015f yapabilir duruma geleceksiniz. Yani herhangi bir anda istedi\u011finiz release klas\u00f6r\u00fcn\u00fc yay\u0131ndaki klas\u00f6r\u00fcn\u00fcz ile linkleyebilirsiniz. B\u00f6ylece yay\u0131na ald\u0131ktan sonra bir hatayla kar\u015f\u0131la\u015fman\u0131z durumunda \u00e7ok \u00e7ok h\u0131zl\u0131 bir bi\u00e7imde geri d\u00f6nebilirsiniz. Zero downtime deployment konusundaki en \u00f6nemli noktalardan birisi bence bu. Zero downtime rollback!<\/p>\n<p>Elbette yaz\u0131lan kodun veya veritaban\u0131 de\u011fi\u015fikliklerinin de buna uyumlu olmas\u0131 gerekiyor. \u00d6rne\u011fin bir kolonun ismini <code>a<\/code> yerine <code>b<\/code> yapt\u0131\u011f\u0131n\u0131zda, art\u0131k eski release klas\u00f6rleri kullan\u0131lamaz hale gelecek. \u00c7\u00fcnk\u00fc bu klas\u00f6rlerdeki s\u00fcr\u00fcmlerde <code>a<\/code> kolonu bir ba\u011f\u0131ml\u0131l\u0131k. Bu noktada rollback migration \u00e7al\u0131\u015ft\u0131rabilirsiniz veya daha &quot;safe&quot; migrationlar yazabilirsiniz. <\/p>\n<h2>Sonu\u00e7<\/h2>\n<p>Zero downtime deployment i\u00e7in hayat\u0131n\u0131z\u0131 kolayla\u015ft\u0131racak ve hem deploy hem de rollback i\u015flerini yapacak onlarca ara\u00e7 var. Ama bunlar\u0131 kullansan\u0131z dahi, \u00f6ncesinde konsept olarak anlaman\u0131z faydal\u0131 olacakt\u0131r. Bir m\u00fc\u015fterimizin projesinde \u00e7ok basit bir <code>bash script<\/code> kullanarak zero-downtime deployment yap\u0131yoruz. Hem de 12 farkl\u0131 app sunucusuna. <\/p>\n<p>Edge case ya da problem mutlaka ya\u015fanacakt\u0131r. Bunlar da zamanla tecr\u00fcbe ile \u00e7\u00f6z\u00fclecektir ve hem kodu yazarken, hem 3.parti paket eklerken, hem ba\u011f\u0131ml\u0131l\u0131klar\u0131 kurgularken deployment d\u00fc\u015f\u00fcnerek geli\u015ftirme yapacaks\u0131n\u0131z. K\u00fc\u00e7\u00fck b\u00fcy\u00fck demeden t\u00fcm projelerinizde uygulamaya ba\u015flay\u0131n!<\/p>\n<h3>Extra Not<\/h3>\n<p>Bu yaz\u0131 i\u00e7erisinde sizlerle bir sunucu i\u00e7erisinde klas\u00f6r bazl\u0131 zero-downtime deployment nas\u0131l olur g\u00f6stermek istedim. \u00c7ok farkl\u0131 y\u00f6ntemler oldu\u011funu bilmenizi isterim. \u00d6rne\u011fin her bir deployment i\u00e7in bir sunucu aya\u011fa kald\u0131rabilir, sunucular aras\u0131 ge\u00e7i\u015f dahi yapabilirsiniz. \u00d6nemli olan bu i\u015fin mant\u0131\u011f\u0131n\u0131 kavramak!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Zero downtime deployment, yani benim \u00e7evirimle &quot;projede hi\u00e7 problem ya\u015famadan yeni s\u00fcr\u00fcm\u00fc yay\u0131na almak&quot; \u00e7ok\u00e7a kullan\u0131lan ve \u00e7o\u011fu ki\u015finin kavramsal ve teknik olarak ka\u00e7\u0131nd\u0131\u011f\u0131 bir konu. Bunun temelinde, bu kavram\u0131n sadece belli ba\u015fl\u0131 ara\u00e7lar ile sa\u011fland\u0131\u011f\u0131n\u0131n d\u00fc\u015f\u00fcn\u00fclmesi yat\u0131yor. \u00c7o\u011fu ki\u015fi bunun i\u00e7in uygulaman\u0131n bulutta olmas\u0131 gerekti\u011fini veya \u00f6\u011frenmek i\u00e7in bilgi ve vakit gerektiren bir arac\u0131n [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4],"tags":[384],"class_list":["post-2368","post","type-post","status-publish","format-standard","hentry","category-yazilim","tag-zero-downtime-deployment"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/comments?post=2368"}],"version-history":[{"count":2,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2368\/revisions"}],"predecessor-version":[{"id":2407,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/posts\/2368\/revisions\/2407"}],"wp:attachment":[{"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/media?parent=2368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/categories?post=2368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/guven.atbakan.com\/blog\/wp-json\/wp\/v2\/tags?post=2368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}