AWS'de Terraform ile Sıfır Kesinti Süresi Jenkins Sürekli Dağıtımı

Yayınlanan: 2022-03-11

Kelimenin tam anlamıyla her şeyin 7/24 hazır olması gereken günümüz internet dünyasında, güvenilirlik çok önemlidir. Bu, web siteleriniz için sıfıra yakın kapalı kalma süresi anlamına gelir, korkunç "Bulunamadı: 404" hata sayfasından veya en yeni sürümünüzü sunarken diğer hizmet kesintilerinden kaçınır.

Müşteriniz veya belki kendiniz için yeni bir uygulama oluşturduğunuzu ve uygulamanızı beğenen iyi bir kullanıcı tabanı elde etmeyi başardığınızı varsayalım. Kullanıcılarınızdan geri bildirim topladınız ve geliştiricilerinize giderek onlardan yeni özellikler oluşturmalarını ve uygulamayı dağıtıma hazır hale getirmelerini istediniz. Bu hazır durumdayken, tüm uygulamayı durdurabilir ve yeni sürümü dağıtabilir veya yeni bir sürümü kullanıcılara manuel müdahale olmadan göndermenin tüm sıkıcı işlerini yapacak sıfır kesintili bir CI/CD dağıtım hattı oluşturabilirsiniz.

Bu makalede, tam olarak ikincisi hakkında konuşacağız, bir altyapı düzenleyicisi olarak Terraform kullanarak AWS Cloud üzerinde Node.js'de yerleşik üç katmanlı bir web uygulamasının sürekli dağıtım hattına nasıl sahip olabileceğimiz hakkında. Sürekli dağıtım bölümü için Jenkins'i ve kod tabanımızı barındırmak için Bitbucket'i kullanacağız.

Kod Deposu

Kodu burada bulabileceğiniz üç katmanlı bir demo web uygulaması kullanacağız.

Depo, hem web hem de API katmanı için kod içerir. Bu, web modülünün API katmanındaki uç noktalardan birini çağırdığı ve veri tabanından geçerli saat hakkında dahili olarak bilgi aldığı ve web katmanına geri döndüğü basit bir uygulamadır.

Deponun yapısı aşağıdaki gibidir:

  • API: API katmanı için kod
  • Web: Web katmanı için kod
  • Terraform: Terraform kullanarak altyapı düzenlemesi için kod
  • Jenkins: CI/CD ardışık düzeni için kullanılan Jenkins sunucusunun altyapı düzenleyicisi kodu.

Artık neyi dağıtmamız gerektiğini anladığımıza göre, bu uygulamayı AWS'de dağıtmak için yapmamız gerekenleri tartışalım ve ardından CI/CD ardışık düzeninin bu bölümünün nasıl yapılacağı hakkında konuşalım.

Pişirme Resimleri

Altyapı düzenleyicisi için Terraform kullandığımızdan, dağıtmak istediğiniz her katman veya uygulama için önceden hazırlanmış görüntülere sahip olmak en mantıklısı. Ve bunun için Hashicorp'tan başka bir ürün, yani Packer kullanıyor olacağız.

Packer, AWS'de dağıtım için kullanılacak bir Amazon Machine Image veya AMI oluşturmaya yardımcı olan açık kaynaklı bir araçtır. EC2, VirtualBox, VMware ve diğerleri gibi farklı platformlar için görüntüler oluşturmak için kullanılabilir.

API katmanı için bir AMI oluşturmak için Packer yapılandırma dosyasının ( terraform/packer-ami-api.json ) nasıl kullanıldığına dair bir pasaj burada.

 { "builders": [{ "type": "amazon-ebs", "region": "eu-west-1", "source_ami": "ami-844e0bf7", "instance_type": "t2.micro", "ssh_username": "ubuntu", "ami_name": "api-instance {{timestamp}}" }], "provisioners": [ { "type": "shell", "inline": ["mkdir api", "sudo apt-get update", "sudo apt-get -y install npm nodejs-legacy"], "pause_before": "10s" }, { "type": "file", "source" : "../api/", "destination" : "api" }, { "type": "shell", "inline": ["cd api", "npm install"], "pause_before": "10s" } ] }

AMI'yi oluşturmak için aşağıdaki komutu çalıştırmanız gerekir:

 packer build -machine-readable packer-ami-api.json

Bu komutu bu makalenin ilerleyen bölümlerinde Jenkins derlemesinden çalıştıracağız. Benzer şekilde, web katmanı için de Packer yapılandırma dosyasını ( terraform/packer-ami-web.json ) kullanacağız.

Yukarıdaki Packer yapılandırma dosyasını inceleyelim ve ne yapmaya çalıştığını anlayalım.

  1. Daha önce bahsedildiği gibi, Packer birçok platform için imajlar oluşturmak için kullanılabilir ve uygulamamızı AWS'ye dağıttığımız için “amazon-ebs” oluşturucusunu kullanıyor olacağız, çünkü bu, başlaması en kolay oluşturucudur.
  2. Yapılandırmanın ikinci kısmı, görüntünüzü yapılandırmak için kullanabileceğiniz daha çok komut dosyalarına veya kod bloklarına benzeyen hazırlayıcıların bir listesini alır.
    • Adım 1 , bir API klasörü oluşturmak ve çalıştırmak istediğiniz bir dizi komut olan inline özelliğini kullanarak Node.js'yi görüntüye yüklemek için bir kabuk hazırlayıcı çalıştırır.
    • Adım 2 , kaynak kodumuzu API klasöründen örneğe kopyalamak için bir dosya hazırlayıcı çalıştırır.
    • Adım 3 yine bir kabuk hazırlayıcı çalıştırır, ancak bu sefer çalıştırılması gereken komutlarla bir dosya (terraform/scripts/install_api_software.sh) belirtmek için bir komut dosyası özelliği kullanır.
    • Adım 4 , bir sonraki adımda kurulan Cloudwatch için gerekli olan örneğe bir yapılandırma dosyası kopyalar.
    • Adım 5 , AWS Cloudwatch aracısını yüklemek için bir kabuk sağlayıcı çalıştırır. Bu komutun girişi, önceki adımda kopyalanan yapılandırma dosyası olacaktır. Cloudwatch hakkında daha sonra makalenin ilerleyen bölümlerinde ayrıntılı olarak konuşacağız.

Bu nedenle, özünde, Packer yapılandırması, istediğiniz oluşturucu ve ardından görüntünüzü nasıl yapılandırmak istediğinize bağlı olarak herhangi bir sırayla tanımlayabileceğiniz bir dizi hazırlayıcı hakkında bilgi içerir.

Jenkins Sürekli Dağıtımını Ayarlama

Ardından, CI/CD ardışık düzenimiz için kullanılacak bir Jenkins sunucusu kurmaya bakacağız. Bunu ayarlamak için de Terraform ve AWS kullanacağız.

Jenkins'i ayarlamak için Terraform kodu, jenkins/setup klasörünün içindedir. Bu kurulumla ilgili bazı ilginç şeyleri gözden geçirelim.

  1. AWS kimlik bilgileri: AWS erişim anahtarı kimliğini ve gizli erişim anahtarını Terraform AWS sağlayıcısına ( instance.tf ) sağlayabilir veya kimlik bilgilerinin konumunu AWS sağlayıcısındaki shared_credentials_file özelliğine verebilirsiniz.
  2. IAM rolü: Packer ve Terraform'u Jenkins sunucusundan çalıştıracağımız için AWS'de S3, EC2, RDS, IAM, yük dengeleme ve otomatik ölçeklendirme hizmetlerine erişecekler. Bu nedenle, bu hizmetlere erişmek için ya Jenkins for Packer & Terraform ile ilgili kimlik bilgilerimizi sağlarız ya da bir Jenkins örneği oluşturacağımız bir IAM Profili ( iam.tf ) oluşturabiliriz.
  3. Terraform durumu: Terraform, altyapının durumunu bir dosyada bir yerde korumalıdır ve S3 ( backend.tf ) ile onu orada koruyabilirsiniz, böylece diğer iş arkadaşlarınızla işbirliği yapabilirsiniz ve durumdan bu yana herkes değiştirebilir ve dağıtabilir uzak bir yerde tutulur.
  4. Genel/özel anahtar çifti: Jenkins örneğine bir kez ssh gönderebilmeniz için anahtar çiftinizin ortak anahtarını örnekle birlikte yüklemeniz gerekir. Terraform değişkenlerini kullanarak ortak anahtarınızın konumunu belirttiğiniz bir aws_key_pair kaynağı ( key.tf ) tanımladık.

Jenkins'i kurma adımları:

Adım 1: Terraform'un uzak durumunu korumak için, S3'te Terraform tarafından kullanılabilecek bir kovayı manuel olarak oluşturmanız gerekir. Bu, Terraform dışında atılan tek adım olacaktır. AWS kimlik bilgilerinizi belirtmek için aşağıdaki komutu çalıştırmadan önce AWS configure çalıştırdığınızdan emin olun.

 aws s3api create-bucket --bucket node-aws-jenkins-terraform --region eu-west-1 --create-bucket-configuration LocationConstraint=eu-west-1

Adım 2: terraform init çalıştırın. Bu, durumu başlatacak ve S3'te depolanacak şekilde yapılandıracak ve AWS sağlayıcı eklentisini indirecektir.

Adım 3: terraform apply çalıştırın. Bu, tüm Terraform kodunu kontrol edecek ve bir plan oluşturacak ve bu adım tamamlandıktan sonra kaç tane kaynak oluşturulacağını gösterecektir.

Adım 4: yes yazın, ardından önceki adım tüm kaynakları oluşturmaya başlayacaktır. Komut bittikten sonra Jenkins sunucusunun genel IP adresini alacaksınız.

Adım 5: Özel anahtarınızı kullanarak Jenkins sunucusuna Ssh. ubuntu , AWS EBS destekli bulut sunucuları için varsayılan kullanıcı adıdır. terraform apply komutu tarafından döndürülen IP adresini kullanın.

 ssh -i mykey [email protected]

Adım 6: http://34.245.4.73:8080 adresine giderek Jenkins web kullanıcı arayüzünü başlatın. Parola /var/lib/jenkins/secrets/initialAdminPassword .

7. Adım: “Önerilen Eklentileri Yükle”yi seçin ve Jenkins için bir Yönetici kullanıcı oluşturun.

Jenkins ve Bitbucket Arasında CI Boru Hattını Ayarlama

  1. Bunun için Jenkins'e Bitbucket eklentisini kurmamız gerekiyor. Jenkins'i Yönet → Eklentileri Yönet'e gidin ve Mevcut eklentilerden Bitbucket eklentisini yükleyin.
  2. Bitbucket deposu tarafında, Ayarlar → Web kancaları seçeneğine gidin, yeni bir web kancası ekleyin. Bu kanca, depodaki tüm değişiklikleri Jenkins'e gönderecek ve bu, boru hatlarını tetikleyecektir.
    Bitbucker aracılığıyla Jenkins sürekli dağıtımına bir web kancası ekleme

Görüntüleri Pişirmek/Oluşturmak için Jenkins Boru Hattı

  1. Bir sonraki adım, Jenkins'te boru hatları oluşturmak olacaktır.
  2. İlk boru hattı, Packer kullanarak uygulamanın AMI'sini oluşturmak için kullanılacak olan bir Freestyle projesi olacak.
  3. Bitbucket deponuz için kimlik bilgilerini ve URL'yi belirtmeniz gerekir.
    Bitbucket'e kimlik bilgileri ekleyin
  4. Oluşturma tetikleyicisini belirtin.
    Derleme tetikleyicisini yapılandırma
  5. Biri uygulama modülü için AMI oluşturmak ve diğerleri web modülü için AMI oluşturmak için olmak üzere iki oluşturma adımı ekleyin.
    AMI derleme adımları ekleme
  6. Bu yapıldıktan sonra, Jenkins projesini kaydedebilirsiniz ve şimdi, Bitbucket deponuza herhangi bir şey gönderdiğinizde, Jenkins'te AMI'yi oluşturacak ve o Görüntünün AMI numarasını içeren bir Terraform dosyasını gönderecek yeni bir yapıyı tetikleyecektir. Oluşturma adımındaki son iki satırdan görebileceğiniz S3 kovası.
 echo 'variable "WEB_INSTANCE_AMI" { default = "'${AMI_ID_WEB}'" }' > amivar_web.tf aws s3 cp amivar_web.tf s3://node-aws-jenkins-terraform/amivar_web.tf

Terraform Komut Dosyasını Tetiklemek için Jenkins Boru Hattı

Artık API ve web modülleri için AMI'lere sahip olduğumuza göre, tüm uygulamayı kurmak için Terraform kodunu çalıştırmak için bir yapıyı tetikleyeceğiz ve daha sonra bu işlem hattının değişiklikleri sıfır hizmet kesintisi ile dağıtmasını sağlayan Terraform kodundaki bileşenleri gözden geçireceğiz.

  1. Uygulamayı dağıtmak için Terraform kodunu çalıştıracak olan nodejs-terraform başka bir serbest Jenkins projesi oluşturuyoruz.
  2. İlk olarak, Terraform betiğine bir girdi olarak kullanılacak global kimlik bilgisi alanında bir "gizli metin" tipi kimlik bilgisi oluşturacağız. RDS hizmetinin parolasını Terraform ve Git içinde sabit kodlamak istemediğimizden, bu özelliği Jenkins kimlik bilgilerini kullanarak iletiyoruz.
    Terraform ci cd ile kullanım için bir sır oluşturma
  3. Diğer projeye benzer kimlik bilgilerini ve URL'yi tanımlamanız gerekir.
  4. İnşa tetikleme bölümünde, bu projeyi bir önceki proje bittiğinde başlayacak şekilde bu projeyi diğerine bağlayacağız.
    Projeleri birbirine bağlayın
  5. Ardından, projeye daha önce eklediğimiz kimlik bilgilerini bağlamaları kullanarak yapılandırabiliriz, böylece derleme adımında kullanılabilir.
    Bağlamaları yapılandırma
  6. Şimdi, önceki proje tarafından S3'e yüklenen Terraform betik dosyalarını ( amivar_api.tf ve amivar_web.tf ) indirecek ve ardından tüm uygulamayı AWS'de oluşturmak için Terraform kodunu çalıştıracak bir derleme adımı eklemeye hazırız.
    Derleme komut dosyasını ekleme

Her şey düzgün bir şekilde yapılandırılmışsa, şimdi Bitbucket deponuza herhangi bir kod gönderirseniz, ilk Jenkins projesini ve ardından ikincisini tetiklemeli ve uygulamanızı AWS'ye dağıtmış olmalısınız.

AWS için Terraform Zero Kesinti Süresi Yapılandırması

Şimdi, Terraform kodunda, bu ardışık düzenin kodu sıfır kesinti ile dağıtmasını sağlayan şeyin ne olduğunu tartışalım.

İlk şey, Terraform'un bu yaşam döngüsü yapılandırma bloklarını, içinde create_before_destroy seçeneğine sahip olduğunuz kaynaklar için bir bayrak olarak sağlamasıdır; bu, kelimenin tam anlamıyla, Terraform'un mevcut kaynağı yok etmeden önce aynı türde yeni bir kaynak yaratması gerektiği anlamına gelir.

Şimdi bu özelliği aws_autoscaling_group ve aws_launch_configuration kaynaklarında kullanıyoruz. Bu nedenle, aws_launch_configuration , hangi tür EC2 bulut sunucusunun sağlanması gerektiğini ve bu bulut sunucusuna yazılımı nasıl yükleyeceğimizi yapılandırır ve aws_autoscaling_group kaynağı, bir AWS otomatik ölçeklendirme grubu sağlar.

Buradaki ilginç bir yakalama, Terraform'daki tüm kaynakların benzersiz bir ad ve tür kombinasyonuna sahip olması gerektiğidir. Dolayısıyla, yeni aws_autoscaling_group ve aws_launch_configuration için farklı bir adınız yoksa, mevcut olanı yok etmek mümkün olmayacaktır.

Terraform, aws_launch_configuration kaynağına bir name_prefix özelliği sağlayarak bu kısıtlamayı ele alır. Bu özellik tanımlandıktan sonra, Terraform tüm aws_launch_configuration kaynaklarına benzersiz bir son ek ekler ve ardından bu benzersiz adı bir aws_autoscaling_group kaynağı oluşturmak için kullanabilirsiniz.

Yukarıdakilerin tümü için kodu terraform/autoscaling-api.tf adresinde kontrol edebilirsiniz.

 resource "aws_launch_configuration" "api-launchconfig" { name_prefix = "api-launchconfig-" image_ instance_type = "t2.micro" security_groups = ["${aws_security_group.api-instance.id}"] user_data = "${data.template_file.api-shell-script.rendered}" iam_instance_profile = "${aws_iam_instance_profile.CloudWatchAgentServerRole-instanceprofile.name}" connection { user = "${var.INSTANCE_USERNAME}" private_key = "${file("${var.PATH_TO_PRIVATE_KEY}")}" } lifecycle { create_before_destroy = true } } resource "aws_autoscaling_group" "api-autoscaling" { name = "${aws_launch_configuration.api-launchconfig.name}-asg" vpc_zone_identifier = ["${aws_subnet.main-public-1.id}"] launch_configuration = "${aws_launch_configuration.api-launchconfig.name}" min_size = 2 max_size = 2 health_check_grace_period = 300 health_check_type = "ELB" load_balancers = ["${aws_elb.api-elb.name}"] force_delete = true lifecycle { create_before_destroy = true } tag { key = "Name" value = "api ec2 instance" propagate_at_launch = true } }

Ve sıfır kesintili dağıtımlarla ilgili ikinci zorluk, yeni dağıtımınızın isteği almaya hazır olduğundan emin olmaktır. Sadece yeni bir EC2 bulut sunucusunu dağıtmak ve başlatmak bazı durumlarda yeterli değildir.

Bu sorunu çözmek için, aws_launch_configuration , otomatik ölçeklendirme grubunun bir parçası olarak yeni örneklerin başlangıcında çalıştırmak istediğiniz herhangi bir komut dosyasını iletebileceğiniz yerel AWS otomatik ölçeklendirme user_data özelliğini destekleyen user_data özelliğine sahiptir. Örneğimizde, uygulama sunucusunun günlüğünü takip ediyoruz ve başlangıç ​​mesajının orada olmasını bekliyoruz. Ayrıca HTTP sunucusunu kontrol edebilir ve ne zaman hazır olduklarını görebilirsiniz.

 until tail /var/log/syslog | grep 'node ./bin/www' > /dev/null; do sleep 5; done

Bununla birlikte, aws_autoscaling_group kaynak düzeyinde bir ELB kontrolünü de etkinleştirebilirsiniz; bu, Terraform eski örnekleri yok etmeden önce yeni örneğin ELB denetimini geçmesi için eklendiğinden emin olur. API katmanı için ELB denetimi şöyle görünür; /api/status bitiş noktasının başarılı olup olmadığını kontrol eder.

 resource "aws_elb" "api-elb" { name = "api-elb" subnets = ["${aws_subnet.main-public-1.id}"] security_groups = ["${aws_security_group.elb-securitygroup.id}"] listener { instance_port = "${var.API_PORT}" instance_protocol = "http" lb_port = 80 lb_protocol = "http" } health_check { healthy_threshold = 2 unhealthy_threshold = 2 timeout = 3 target = "HTTP:${var.API_PORT}/api/status" interval = 30 } cross_zone_load_balancing = true connection_draining = true connection_draining_timeout = 400 tags { Name = "my-elb" } }

Özet ve Sonraki Adımlar

Bu da bizi bu makalenin sonuna getiriyor; Umarım şimdiye kadar, ya Jenkins dağıtımı ve Terraform en iyi uygulamaları kullanarak sıfır kesintili bir CI/CD ardışık düzeni ile uygulamanızı dağıtmış ve çalıştırmışsınızdır ya da bu bölgeyi keşfetmek ve dağıtımlarınızın olabildiğince az manuel müdahaleye ihtiyaç duymasını sağlamak için biraz daha rahatsınızdır. olası.

Bu makalede, kullanılan dağıtım stratejisine Mavi-Yeşil dağıtım adı verilir, burada yeni sürümü (Yeşil) dağıtırken ve test ederken canlı trafik alan mevcut bir kurulumumuz (Mavi) vardır ve yeni sürüm olduğunda bunları değiştiririz. her şey hazır. Bu stratejinin yanı sıra, Uygulamanızı dağıtmanın başka yolları da vardır; bu, Dağıtım Stratejilerine Giriş başlıklı bu makalede güzel bir şekilde açıklanmıştır. Başka bir stratejiyi uyarlamak artık Jenkins boru hattınızı yapılandırmak kadar basit.

Ayrıca, bu makalede, API, web ve veri katmanlarındaki tüm yeni değişikliklerin uyumlu olduğunu varsaydım, böylece eski bir sürümle konuşurken yeni sürüm hakkında endişelenmenize gerek yok. Ancak gerçekte durum her zaman böyle olmayabilir. Bu sorunu çözmek için, yeni sürümünüzü/özelliklerinizi tasarlarken her zaman geriye dönük uyumluluk katmanını düşünün, aksi takdirde bu durumu da ele almak için dağıtımlarınızda ince ayar yapmanız gerekecektir.

Entegrasyon testi, bu dağıtım hattında da eksik olan bir şey. Hiçbir şeyin test edilmeden son kullanıcıya sunulmasını istemediğiniz için, bu stratejileri kendi projelerinize uygulama zamanı geldiğinde kesinlikle akılda tutulması gereken bir şey.

Terraform'un nasıl çalıştığı ve teknolojiyi kullanarak AWS'ye nasıl dağıtabileceğiniz hakkında daha fazla bilgi edinmek istiyorsanız, Toptaler Radoslaw Szalski'nin Terraform'u açıkladığı ve ardından size bir çoklu yapılandırma yapılandırması için gereken adımları gösterdiği Terraform AWS Cloud: Sane Infrastructure Management'ı öneririm. -Bir ekip için çevre ve üretime hazır Terraform kurulumu

İlgili: Terraform vs. CloudFormation: Kesin Kılavuz