Etkili Bir İlk Dağıtım İşlem Hattı Nasıl Oluşturulur
Yayınlanan: 2022-03-11Bir şeyler inşa etmeyi seviyorum - hangi geliştirici yapmaz? İlginç sorunlara çözümler bulmayı, uygulamalar yazmayı ve güzel kodlar oluşturmayı seviyorum. Ancak, sevmediğim şey operasyonlar . Operasyonlar, harika bir yazılım oluşturmaya dahil olmayan her şeydir - sunucuları kurmaktan kodunuzun üretime gönderilmesine kadar her şey.
Bu ilginç, çünkü serbest çalışan bir Ruby on Rails geliştiricisi olarak sık sık yeni web uygulamaları oluşturmam ve şeylerin DevOps tarafını çözme sürecini tekrarlamam gerekiyor. Neyse ki, düzinelerce uygulama oluşturduktan sonra, sonunda mükemmel bir ilk dağıtım hattına karar verdim. Ne yazık ki, herkes benim gibi çözemedi - sonunda, bu bilgi beni dalmaya ve sürecimi belgelemeye yönlendirdi.
Bu makalede, projenizin başında kullanmak için mükemmel boru hattımda size yol göstereceğim. Benim ardışık düzenimle, her gönderme test edilir, ana dal üretimden yeni bir veritabanı dökümü ile hazırlamaya dağıtılır ve sürümlendirilmiş etiketler, yedeklemeler ve geçişlerin otomatik olarak gerçekleşmesiyle üretime dağıtılır.
Not, benim hattım olduğu için, aynı zamanda fikir sahibi ve ihtiyaçlarıma uygun; Bununla birlikte, beğenmediğiniz herhangi bir şeyi değiştirmekte ve hoşunuza giden herhangi bir şeyle değiştirmekte özgürsünüz. Boru hattım için kullanacağız:
- Kodu barındırmak için GitLab .
- Neden: Müşterilerim kodlarının gizli kalmasını tercih ediyor ve GitLab'ın ücretsiz katmanı harika. Ayrıca, entegre ücretsiz CI harika. Teşekkürler GitLab!
- Alternatifler: GitHub, BitBucket, AWS CodeCommit ve çok daha fazlası.
- Kodumuzu oluşturmak, test etmek ve dağıtmak için GitLab CI .
- Neden: GitLab ile entegredir ve ücretsizdir!
- Alternatifler: TravisCI, Codeship, CircleCI, Fabric8 ile DIY ve çok daha fazlası.
- Uygulamamızı barındırmak için Heroku .
- Nedeni: Kutudan çıktığı gibi çalışır ve başlamak için mükemmel bir platformdur. Bunu gelecekte değiştirebilirsiniz, ancak her yeni uygulamanın amaca yönelik olarak oluşturulmuş bir Kubernetes kümesinde çalışması gerekmez. Coinbase bile Heroku'da başladı.
- Alternatifler: AWS, DigitalOcean, Vultr, Kubernetes ile DIY ve çok daha fazlası.
Eski tarz: Temel Bir Uygulama Oluşturun ve Heroku'ya Dağıtın
İlk olarak, süslü CI/CD işlem hatları kullanmayan ve yalnızca uygulamalarını dağıtmak isteyen biri için tipik bir uygulamayı yeniden oluşturalım.
Ne tür bir uygulama oluşturduğunuz önemli değil, ancak Yarn veya npm'ye ihtiyacınız olacak. Örneğimde, geçişler ve bir CLI ile birlikte geldiği için bir Ruby on Rails uygulaması oluşturuyorum ve bunun için zaten yazılı bir konfigürasyona sahibim. Tercih ettiğiniz herhangi bir çerçeveyi veya dili kullanabilirsiniz, ancak daha sonra yapacağım sürüm oluşturma işlemini yapmak için Yarn'a ihtiyacınız olacak. Yalnızca birkaç komut kullanarak ve kimlik doğrulama olmadan basit bir CRUD uygulaması oluşturuyorum.
Ve uygulamamızın beklendiği gibi çalışıp çalışmadığını test edelim. Devam ettim ve emin olmak için birkaç gönderi oluşturdum.
Ve kodumuzu zorlayarak ve geçişleri çalıştırarak onu Heroku'ya dağıtalım.
$ heroku create toptal-pipeline Creating ⬢ toptal-pipeline... done https://toptal-pipeline.herokuapp.com/ | https://git.heroku.com/toptal-pipeline.git $ git push heroku master Counting objects: 132, done. ... To https://git.heroku.com/toptal-pipeline.git * [new branch] master -> master $ heroku run rails db:migrate Running rails db:migrate on ⬢ toptal-pipeline... up, run.9653 (Free) ...
Sonunda üretimde test edelim
Ve bu kadar! Tipik olarak, çoğu geliştiricinin operasyonlarını bıraktığı yer burasıdır. Gelecekte, değişiklik yaparsanız yukarıdaki dağıtım ve geçiş adımlarını tekrarlamanız gerekir. Akşam yemeğine geç kalmıyorsanız testler bile yapabilirsiniz. Bu bir başlangıç noktası olarak harika, ancak bu yöntem hakkında biraz daha düşünelim.
Artıları
- Kurulumu hızlı.
- Dağıtımlar kolaydır.
Eksileri
- KURU DEĞİL: Her değişiklikte aynı adımların tekrarlanmasını gerektirir.
- Sürüm oluşturulmadı: “Dünkü dağıtımı geçen haftanın dağıtımına geri alıyorum” bundan üç hafta sonra çok belirgin değil.
- Kötü kod geçirmez değil: Testler yapmanız gerektiğini biliyorsunuz, ancak kimse bakmıyor, bu nedenle ara sıra bozulan testlere rağmen zorlayabilirsiniz.
- Kötü oyuncuya dayanıklı değil: Ya hoşnutsuz bir geliştirici, ekibiniz için nasıl yeterince pizza sipariş etmediğinize dair bir mesajla kodu zorlayarak uygulamanızı bozmaya karar verirse?
- Ölçeklendirmez: Her geliştiriciye dağıtma yeteneği vermek, onlara uygulamaya üretim düzeyinde erişim sağlayarak En Az Ayrıcalık İlkesini ihlal eder.
- Hazırlama ortamı yok: Üretim ortamına özgü hatalar, üretime kadar görünmez.
Mükemmel İlk Dağıtım Hattı
Bugün farklı bir şey deneyeceğim: Varsayımsal bir konuşma yapalım. “Sana” bir ses vereceğim ve bu mevcut akışı nasıl iyileştirebileceğimizi konuşacağız. Devam et, bir şey söyle.
Ne dedin? Bekle - konuşabilir miyim?
Evet, sana ses vermekten kastım buydu. Nasılsınız?
İyiyim. Bu garip hissettiriyor
Anlıyorum, ama sadece onunla yuvarlan. Şimdi boru hattımızdan bahsedelim. Dağıtımları çalıştırmanın en can sıkıcı kısmı nedir?
Bu kolay. Boşa harcadığım zaman miktarı. Hiç Heroku'yu zorlamayı denedin mi?
Evet, git push
bir parçası olarak bağımlılıklarınızın indirilmesini ve uygulamanın oluşturulmasını izlemek korkunç!
Doğruyu biliyorum? Bu çılgınca. Keşke bunu yapmak zorunda olmasaydım. Ayrıca dağıtımdan *sonra* geçişleri çalıştırmam gerektiği gerçeği de var, bu nedenle gösteriyi izlemem ve dağıtımımın çalıştığından emin olmak için kontrol etmem gerekiyor.
Tamam, bu son sorunu, git push heroku master && heroku run rails db:migrate
gibi &&
ile iki komutu zincirleyerek veya sadece bir bash betiği oluşturup kodunuza koyarak çözebilirsiniz, ama yine de harika bir cevap, zaman ve tekrar gerçek bir acıdır.
Evet, gerçekten berbat
Peki ya size bu parçayı bir CI/CD ardışık düzeni ile hemen düzeltebileceğinizi söylesem?
Ne şimdi? Bu nedir?
CI/CD, sürekli entegrasyon (CI) ve sürekli teslim/dağıtım (CD) anlamına gelir. Başlarken tam olarak ne olduğunu anlamak benim için oldukça zordu çünkü herkes “geliştirme ve operasyonların birleştirilmesi” gibi belirsiz terimler kullandı, ancak basitçe şöyle ifade etti:
- Sürekli Entegrasyon: Tüm kodunuzun tek bir yerde birleştirildiğinden emin olun. Ekibinizin Git'i kullanmasını sağlayın ve CI kullanacaksınız.
- Sürekli Teslimat: Kodunuzun sürekli olarak gönderilmeye hazır olduğundan emin olun. Yani ürününüzün dağıtılmak üzere okunan sürümünü hızlı bir şekilde üretmek.
- Sürekli Dağıtım: Ürünü kesintisiz teslimattan sorunsuz bir şekilde alıp sunucularınıza dağıtmak.
Ah, şimdi anladım. Bu, uygulamamı sihirli bir şekilde dünyaya yaymakla ilgili!
CI/CD'yi açıklayan favori makalem burada Atlassian'a ait. Bu, sahip olduğunuz tüm soruları gidermelidir. neyse soruna dönelim.
Evet, buna geri dönelim. Manuel dağıtımlardan nasıl kaçınırım?
Push to master
dağıtmak için bir CI/CD ardışık düzeni kurma
Peki ya size bu parçayı bir CI/CD ile hemen düzeltebileceğinizi söylesem? GitLab uzaktan kumandanıza ( origin
) basabilirsiniz ve bir bilgisayar doğrudan yukarıya doğru kodunuzu Heroku'ya itin.
Mümkün değil!
Evet yol! Tekrar koda geri dönelim.
Heroku uygulamanızın adı için toptal-pipeline
değiştirerek, aşağıdaki içeriklerle bir .gitlab-ci.yml
oluşturun:
image: ruby:2.4 before_script: - > : "${HEROKU_EMAIL:?Please set HEROKU_EMAIL in your CI/CD config vars}" - > : "${HEROKU_AUTH_TOKEN:?Please set HEROKU_AUTH_TOKEN in your CI/CD config vars}" - curl https://cli-assets.heroku.com/install-standalone.sh | sh - | cat >~/.netrc <<EOF machine api.heroku.com login $HEROKU_EMAIL password $HEROKU_AUTH_TOKEN machine git.heroku.com login $HEROKU_EMAIL password $HEROKU_AUTH_TOKEN EOF - chmod 600 ~/.netrc - git config --global user.email "[email protected]" - git config --global user.name "CI/CD" variables: APPNAME_PRODUCTION: toptal-pipeline deploy_to_production: stage: deploy environment: name: production url: https://$APPNAME_PRODUCTION.herokuapp.com/ script: - git remote add heroku https://git.heroku.com/$APPNAME_PRODUCTION.git - git push heroku master - heroku pg:backups:capture --app $APPNAME_PRODUCTION - heroku run rails db:migrate --app $APPNAME_PRODUCTION only: - master
Bunu yukarı itin ve projenizin Pipelines sayfasında başarısız olmasını izleyin. Bunun nedeni, Heroku hesabınızın kimlik doğrulama anahtarlarının eksik olmasıdır. Bunu düzeltmek oldukça basit olsa da. Öncelikle Heroku API anahtarınıza ihtiyacınız olacak. Hesabı Yönet sayfasından alın ve ardından GitLab deponuzun CI/CD ayarlarına aşağıdaki gizli değişkenleri ekleyin:
-
HEROKU_EMAIL
: Heroku'da oturum açmak için kullandığınız e-posta adresi -
HEROKU_AUTH_KEY
: Heroku'dan aldığınız anahtar
Bu, çalışan bir GitLab'dan Heroku'ya her basışta konuşlandırılmasıyla sonuçlanmalıdır. Neler olduğuna gelince:
- Ustaya bastıktan sonra
- Heroku CLI bir kapsayıcıya kurulur ve kimliği doğrulanır.
- Kodunuz Heroku'ya gönderilir.
- Veritabanınızın bir yedeği Heroku'da yakalanır.
- Göçler çalıştırılır.
Zaten, her şeyi git push
otomatikleştirerek zamandan tasarruf etmekle kalmayıp, aynı zamanda her dağıtımda veritabanınızın bir yedeğini oluşturduğunuzu görebilirsiniz! Bir şeyler ters giderse, geri dönmek için veritabanınızın bir kopyasına sahip olacaksınız.
Bir Aşama Ortamı Oluşturma
Ama bekle, hızlı soru, üretime özgü sorunlarına ne oluyor? Geliştirme ortamınız üretimden çok farklı olduğu için garip bir hatayla karşılaşırsanız ne olur? Bir geçiş yaptığımda bir keresinde bazı garip SQLite 3 ve PostgreSQL sorunlarıyla karşılaştım. Ayrıntılar benden kaçıyor, ancak bu oldukça mümkün.

Geliştirme aşamasında kesinlikle PostgreSQL kullanıyorum, bunun gibi veritabanı motorlarını asla eşleştirmem ve yığınımı olası uyumsuzluklar için özenle izliyorum.
Bu sıkıcı bir iş ve disiplinini takdir ediyorum. Şahsen, bunu yapmak için çok tembelim. Ancak, gelecekteki tüm potansiyel geliştiriciler, ortak çalışanlar veya katkıda bulunanlar için bu düzeyde bir özeni garanti edebilir misiniz?
Errrr- Evet, hayır. Beni yakaladın. Diğer insanlar onu mahvedecek. Ama amacın ne?
Demek istediğim, bir hazırlık ortamına ihtiyacın var. Üretim gibi ama değil. Hazırlama ortamı, üretime dağıtım için prova yaptığınız ve tüm hatalarınızı erkenden yakaladığınız yerdir. Hazırlama ortamlarım genellikle üretimi yansıtır ve can sıkıcı köşe vakalarının geçişlerimi mahvetmemesini sağlamak için üretim veritabanının bir kopyasını hazırlama dağıtımına dökerim. Hazırlama ortamıyla, kullanıcılarınıza kobay gibi davranmayı bırakabilirsiniz.
Bu mantıklı! Peki bunu nasıl yaparım?
İşte burada ilginçleşiyor. master
doğrudan evrelemeye yerleştirmeyi seviyorum.
Bekle, şu anda üretimi dağıttığımız yer orası değil mi?
Evet öyle, ama şimdi bunun yerine sahnelemeye geçeceğiz.
Ancak master
hazırlamaya dağıtılırsa, üretime nasıl dağıtırız?
Yıllar önce yapmanız gereken bir şeyi kullanarak: Kodumuzu sürümlendirmek ve Git etiketlerini zorlamak.
Git etiketleri? Git etiketlerini kim kullanır?! Bu çok iş gibi gelmeye başladı.
Kesinlikle öyleydi, ama neyse ki, tüm bu işleri zaten yaptım ve siz sadece kodumu bırakabilirsiniz ve işe yarayacaktır.
İlk olarak, .gitlab-ci.yml
dosyanıza hazırlama dağıtımı hakkında bir blok ekleyin, toptal-pipeline-staging
adlı yeni bir Heroku uygulaması oluşturdum:
… variables: APPNAME_PRODUCTION: toptal-pipeline APPNAME_STAGING: toptal-pipeline-staging deploy_to_staging: stage: deploy environment: name: staging url: https://$APPNAME_STAGING.herokuapp.com/ script: - git remote add heroku https://git.heroku.com/$APPNAME_STAGING.git - git push heroku master - heroku pg:backups:capture --app $APPNAME_PRODUCTION - heroku pg:backups:restore `heroku pg:backups:url --app $APPNAME_PRODUCTION` --app $APPNAME_STAGING --confirm $APPNAME_STAGING - heroku run rails db:migrate --app $APPNAME_STAGING only: - master - tags ...
Ardından, üretim bloğunuzun son satırını ana dal yerine anlamsal olarak sürümlendirilmiş Git etiketlerinde çalışacak şekilde değiştirin:
deploy_to_production: ... only: - /^v(?'MAJOR'(?:0|(?:[1-9]\d*)))\.(?'MINOR'(?:0|(?:[1-9]\d*)))\.(?'PATCH'(?:0|(?:[1-9]\d*)))(?:-(?'prerelease'[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?(?:\+(?'build'[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$/ # semver pattern above is adapted from https://github.com/semver/semver.org/issues/59#issuecomment-57884619
GitLab, yalnızca "korunan" dalların gizli değişkenlerimize erişmesine izin verecek kadar akıllı olduğundan, bunu şu anda çalıştırmak başarısız olacaktır. Sürüm etiketleri eklemek için GitLab projenizin depo ayarları sayfasına gidin ve korumalı etiketlere v*
ekleyin.
Şimdi neler olduğunu özetleyelim:
- Master'a basıldığında veya etiketli bir taahhüde basıldığında
- Heroku CLI bir kapsayıcıya kurulur ve kimliği doğrulanır.
- Kodunuz Heroku'ya gönderilir.
- Veritabanı üretiminizin bir yedeği Heroku'da yakalanır.
- Yedekleme, hazırlama ortamınıza atılır.
- Geçişler, hazırlama veritabanında çalıştırılır.
- Anlamsal olarak etiketlenmiş bir taahhüdün itilmesi üzerine
- Heroku CLI bir kapsayıcıya kurulur ve kimliği doğrulanır.
- Kodunuz Heroku'ya gönderilir.
- Veritabanı üretiminizin bir yedeği Heroku'da yakalanır.
- Geçişler, üretim veritabanında çalıştırılır.
Şimdi güçlü hissediyor musun? Kendimi güçlü hissediyorum. Hatırlıyorum, bu kadar uzağa ilk geldiğimde karımı aradım ve tüm bu boru hattını dayanılmaz ayrıntılarla anlattım. Ve o teknik bile değil. Kendimden çok etkilendim ve sen de öyle olmalısın! Buraya kadar gelen harika iş!
Her Basmayı Test Etme
Ama dahası da var, bir bilgisayar zaten sizin için bir şeyler yaptığına göre, sizin yapmaya üşendiğiniz her şeyi de çalıştırabilir: Testler, linting hataları, yapmak istediğiniz hemen hemen her şey ve bunlardan herhangi biri başarısız olursa, kazandılar. konuşlandırmaya geç.
Bunu boru hattımda bulundurmayı seviyorum, kod incelemelerimi eğlenceli hale getiriyor. Bir birleştirme isteği tüm kod kontrollerimi geçerse, gözden geçirilmeyi hak eder.
Bir test
bloğu ekleyin:
test: stage: test variables: POSTGRES_USER: test POSTGRES_PASSSWORD: test-password POSTGRES_DB: test DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSSWORD}@postgres/${POSTGRES_DB} RAILS_ENV: test services: - postgres:alpine before_script: - curl -sL https://deb.nodesource.com/setup_8.x | bash - apt-get update -qq && apt-get install -yqq nodejs libpq-dev - curl -o- -L https://yarnpkg.com/install.sh | bash - source ~/.bashrc - yarn - gem install bundler --no-ri --no-rdoc - bundle install -j $(nproc) --path vendor - bundle exec rake db:setup RAILS_ENV=test script: - bundle exec rake spec - bundle exec rubocop
Şimdi neler olduğunu özetleyelim:
- Her itme veya birleştirme isteği üzerine
- Ruby ve Node bir kapsayıcıda kurulur.
- Bağımlılıklar yüklenir.
- Uygulama test edildi.
- Master'a zorlandığında veya etiketli bir taahhüdün verildiğinde ve yalnızca tüm testler geçerse
- Heroku CLI bir kapsayıcıya kurulur ve kimliği doğrulanır.
- Kodunuz Heroku'ya gönderilir.
- Veritabanı üretiminizin bir yedeği Heroku'da yakalanır.
- Yedekleme, hazırlama ortamınıza atılır.
- Geçişler, hazırlama veritabanında çalıştırılır.
- Anlamsal olarak etiketlenmiş bir taahhüdün itilmesi üzerine ve yalnızca tüm testler geçerse
- Heroku CLI bir kapsayıcıya kurulur ve kimliği doğrulanır.
- Kodunuz Heroku'ya gönderilir.
- Veritabanı üretiminizin bir yedeği Heroku'da yakalanır.
- Geçişler, üretim veritabanında çalıştırılır.
Bir adım geri atın ve başardığınız otomasyon düzeyine hayran kalın. Şu andan itibaren tek yapmanız gereken kod yazmak ve basmak. Uygulamanızı istediğiniz zaman hazırlama aşamasında manuel olarak test edin ve onu dünyaya yaymak için yeterince kendinize güvendiğinizde, anlamsal sürüm oluşturma ile etiketleyin!
Otomatik Anlamsal Sürüm Oluşturma
Evet, mükemmel ama bir şey eksik. Uygulamanın son sürümünü arayıp açıkça etiketlemeyi sevmiyorum. Bu, birden fazla komut alır ve birkaç saniyeliğine dikkatimi dağıtır.
Tamam dostum, dur! Bu yeterli. Artık onu fazla mühendislik yapıyorsun. İşe yarıyor, harika, aşırıya kaçarak iyi bir şeyi mahvetme.
Tamam, yapmak üzere olduğum şeyi yapmak için iyi bir nedenim var.
Dua et beni aydınlat.
Ben de senin gibiydim. Bu kurulumdan memnundum, ama sonra berbat ettim. git tag
, etiketleri alfabetik sırayla listeler, v0.0.11
, v0.0.2
üzerindedir. Bir keresinde yanlışlıkla bir yayını etiketledim ve hatamı görene kadar yaklaşık yarım düzine yayın boyunca bunu yapmaya devam ettim. O zaman bunu da otomatikleştirmeye karar verdim.
Yine başlıyoruz
Tamam, çok şükür, elimizde npm'nin gücü var, bu yüzden uygun bir paket buldum: yarn add --dev standard-version
dosyasını çalıştırın ve aşağıdakileri package.json
dosyanıza ekleyin:
"scripts": { "release": "standard-version", "major": "yarn release --release-as major", "minor": "yarn release --release-as minor", "patch": "yarn release --release-as patch" },
Şimdi son bir şey yapmanız gerekiyor, Git'i varsayılan olarak etiketleri itecek şekilde yapılandırın. Şu anda, bir etiketi yukarı itmek için git push --tags
çalıştırmanız gerekir, ancak bunu normal git push
push'ta otomatik olarak yapmak git config --global push.followTags true
çalıştırmak kadar basittir.
Bir yayın çalıştırması oluşturmak istediğinizde yeni işlem hattınızı kullanmak için:
- yama sürümleri için
yarn patch
- küçük sürümler için küçük
yarn minor
- büyük sürümler için
yarn major
“Majör”, “minör” ve “yama” sözcüklerinin ne anlama geldiğinden emin değilseniz, anlamsal sürüm oluşturma sitesinde bununla ilgili daha fazla bilgi edinin.
Artık boru hattınızı nihayet tamamladığınıza göre, onu nasıl kullanacağınızı özetleyelim!
- Kod yaz.
- Test etmek ve evrelemeye dağıtmak için taahhüt edin ve zorlayın.
- Bir yama yayınını etiketlemek için
yarn patch
kullanın. - üretime itmek için
git push
.
Özet ve Diğer Adımlar
CI/CD ardışık düzenleriyle mümkün olanın yalnızca yüzeyini kazıdım. Bu oldukça basit bir örnek. Heroku'yu Kubernetes ile değiştirerek çok daha fazlasını yapabilirsiniz. GitLab CI'yi kullanmaya karar verirseniz, yaml belgelerini okuyun çünkü dağıtımlar arasında dosyaları önbelleğe alarak veya yapıları kaydederek yapabileceğiniz çok daha fazla şey var!
Bu ardışık düzende yapabileceğiniz bir diğer büyük değişiklik, anlamsal sürüm oluşturma ve yayınlamayı çalıştırmak için harici tetikleyiciler eklemektir. Şu anda ChatOps, ücretli planlarının bir parçası ve umarım bunu ücretsiz planlara sunarlar. Ancak bir sonraki görüntüyü tek bir Slack komutuyla tetikleyebildiğinizi hayal edin!
Sonunda, uygulamanız karmaşıklaşmaya başladığından ve sistem düzeyinde bağımlılıklar gerektirdiğinden, bir kapsayıcı kullanmanız gerekebilir. Bu olduğunda, kılavuzumuza göz atın: Docker'a Başlarken: Devops'u Basitleştirme .
Bu örnek uygulama gerçekten yayında ve bunun için kaynak kodunu burada bulabilirsiniz.