Saya mulai bekerja dengan
cloudformation 4 tahun yang lalu. Sejak itu, saya telah merusak banyak infrastruktur, bahkan yang sudah berproduksi. Tetapi setiap kali saya merusak sesuatu, saya belajar hal-hal baru. Berkat pengalaman ini, saya akan membagikan beberapa pelajaran paling penting yang telah saya pelajari.

Pelajaran 1: Validasi Perubahan Sebelum Menyebarkan
Saya belajar pelajaran ini segera setelah saya mulai bekerja dengan
cloudformation . Saya tidak ingat persis apa yang saya hancurkan saat itu, tetapi saya ingat persis bahwa saya menggunakan
perintah pembaruan aws cloudformation . Perintah ini hanya meluncurkan template tanpa verifikasi perubahan yang akan digunakan. Saya tidak berpikir bahwa diperlukan penjelasan, untuk itu Anda perlu memeriksa semua perubahan sebelum menerapkannya.
Setelah kegagalan ini, saya segera mengubah
pipa penyebaran , mengganti perintah pembaruan dengan perintah
buat-ubah-atur# OPERATION is either "UPDATE" or "CREATE" changeset_id=$(aws cloudformation create-change-set \ --change-set-name "$CHANGE_SET_NAME" \ --stack-name "$STACK_NAME" \ --template-body "$TPL_PATH" \ --change-set-type "$OPERATION" \ --parameters "$PARAMETERS" \ --output text \ --query Id) aws cloudformation wait \ change-set-create-complete --change-set-name "$changeset_id"
Ketika set perubahan dibuat, itu tidak mempengaruhi tumpukan yang ada. Tidak seperti perintah pembaruan, pendekatan perubahan set tidak benar-benar digunakan. Alih-alih, itu membuat daftar perubahan yang dapat Anda tinjau sebelum penempatan. Anda dapat melihat perubahan di antarmuka konsol aws. Tetapi jika Anda lebih memilih untuk mengotomatiskan segala sesuatu yang mungkin, maka periksa di CLI:
# this command is presented only for demonstrational purposes. # the real command should take pagination into account aws cloudformation describe-change-set \ --change-set-name "$changeset_id" \ --query 'Changes[*].ResourceChange.{Action:Action,Resource:ResourceType,ResourceId:LogicalResourceId,ReplacementNeeded:Replacement}' \ --output table
Perintah ini harus menghasilkan keluaran yang serupa dengan yang berikut:
-------------------------------------------------------------------- | DescribeChangeSet | +---------+--------------------+----------------------+------------+ | Action | ReplacementNeeded | Resource | ResourceId | +---------+--------------------+----------------------+------------+ | Modify | True | AWS::ECS::Cluster | MyCluster | | Replace| True | AWS::RDS::DBInstance| MyDB | | Add | None | AWS::SNS::Topic | MyTopic | +---------+--------------------+----------------------+------------+
Berikan perhatian khusus pada perubahan di mana Tindakan
Diganti ,
Hapus, atau di mana
ReplacementNeeded Benar . Ini adalah perubahan paling berbahaya dan biasanya menyebabkan hilangnya informasi.
Ketika perubahan dilihat, mereka dapat diperluas
aws cloudformation execute-change-set --change-set-name "$changeset_id" operation_lowercase=$(echo "$OPERATION" | tr '[:upper:]' '[:lower:]') aws cloudformation wait "stack-${operation_lowercase}-complete" \ --stack-name "$STACK_NAME"
Pelajaran 2: gunakan kebijakan tumpukan untuk mencegah penggantian atau penghapusan sumber daya secara sah
Terkadang hanya melihat perubahan saja tidak cukup. Kita semua manusia dan kita semua membuat kesalahan. Tak lama setelah kami mulai menggunakan set perubahan, rekan tim saya tanpa sadar melakukan penyebaran, yang menyebabkan peningkatan basis data. Tidak ada yang mengerikan terjadi, karena itu adalah lingkungan pengujian.
Terlepas dari kenyataan bahwa skrip kami menampilkan daftar perubahan dan meminta konfirmasi, perubahan Ganti dilewati karena daftar perubahan begitu besar sehingga tidak dapat masuk ke layar. Dan karena ini adalah pembaruan rutin di lingkungan pengujian, tidak banyak perhatian diberikan pada perubahan.
Ada sumber daya yang tidak akan pernah ingin Anda ganti atau hapus. Ini adalah layanan statefull, seperti instance dari database RDS atau cluster penelitian elastich, dll. Akan lebih baik jika aws secara otomatis akan menolak untuk menggunakan, jika operasi yang dilakukan akan memerlukan penghapusan sumber daya seperti itu. Untungnya, cloudformation memiliki cara bawaan untuk melakukan ini. Ini disebut kebijakan tumpukan, dan Anda dapat membaca lebih lanjut tentang ini di
dokumentasi :
STACK_NAME=$1 RESOURCE_ID=$2 POLICY_JSON=$(cat <<EOF { "Statement" : [{ "Effect" : "Deny", "Action" : [ "Update:Replace", "Update:Delete" ], "Principal": "*", "Resource" : "LogicalResourceId/$RESOURCE_ID" }] } EOF ) aws cloudformation set-stack-policy --stack-name "$STACK_NAME" \ --stack-policy-body "$POLICY_JSON"
Pelajaran 3: gunakan UsePreviousValue saat memperbarui tumpukan dengan parameter rahasia
Saat Anda membuat entitas RDS, mysql AWS mengharuskan Anda untuk memberikan MasterUsername dan MasterUserPassword. Karena lebih baik tidak menyimpan rahasia dalam kode sumber, dan saya ingin mengotomatiskan semuanya, saya menerapkan "mekanisme cerdas" di mana kredensial diperoleh dari s3 sebelum penyebaran, dan jika kredensial tidak ditemukan, kredensial baru dihasilkan dan disimpan di s3 .
Kredensial ini kemudian akan diteruskan sebagai parameter ke perintah create-change-set cloudformation. Selama percobaan dengan skrip, kebetulan koneksi ke s3 hilang, dan "mekanisme cerdas" saya menganggapnya sebagai sinyal untuk menghasilkan kredensial baru.
Jika saya mulai menggunakan skrip ini di lingkungan produksi dan masalah koneksi muncul lagi, itu akan memperbarui tumpukan dengan kredensial baru. Dalam kasus khusus ini, tidak ada hal buruk yang akan terjadi. Namun, saya meninggalkan pendekatan ini dan mulai menggunakan yang lain, memberikan kredensial hanya sekali - saat membuat stack. Dan kemudian, ketika stack membutuhkan pembaruan, alih-alih menentukan nilai rahasia dari parameter, saya hanya akan menggunakan
UsePreviousValue = true :
aws cloudformation create-change-set \ --change-set-name "$CHANGE_SET_NAME" \ --stack-name "$STACK_NAME" \ --template-body "$TPL_PATH" \ --change-set-type "UPDATE" \ --parameters "ParameterKey=MasterUserPassword,UsePreviousValue=true"
Pelajaran 4: gunakan konfigurasi rollback
Tim lain yang bekerja dengan saya menggunakan fungsi
cloudformation yang disebut
konfigurasi rollback . Saya belum pernah bertemu dengannya sebelumnya dan dengan cepat menyadari bahwa ini akan membuat penyebaran tumpukan saya menjadi lebih baik. Sekarang saya menggunakan setiap kali saya menyebarkan kode saya di lambda atau ECS menggunakan cloudformation.
Cara kerjanya: Anda menentukan
alarm CloudWatch dan dalam parameter
--rollback-configuration ketika Anda membuat set perubahan. Kemudian, ketika Anda menyelesaikan set perubahan, aws melacak alarm selama setidaknya satu menit. Ini memutar kembali penyebaran jika selama waktu ini alarm berubah status menjadi ALARM.
Berikut ini adalah contoh kutipan dari template
cloudformation di mana saya membuat
alarm cloudwatch yang melacak metrik cloud pengguna sebagai jumlah kesalahan dalam log cloud (metrik dibuat melalui
MetricFilter ):
Resources: # this metric tracks number of errors in the cloudwatch logs. In this # particular case it's assumed logs are in json format and the error logs are # identified by level "error". See FilterPattern ErrorMetricFilter: Type: AWS::Logs::MetricFilter Properties: LogGroupName: !Ref LogGroup FilterPattern: !Sub '{$.level = "error"}' MetricTransformations: - MetricNamespace: !Sub "${AWS::StackName}-log-errors" MetricName: Errors MetricValue: 1 DefaultValue: 0 ErrorAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: !Sub "${AWS::StackName}-errors" Namespace: !Sub "${AWS::StackName}-log-errors" MetricName: Errors Statistic: Maximum ComparisonOperator: GreaterThanThreshold Period: 1 # 1 minute EvaluationPeriods: 1 Threshold: 0 TreatMissingData: notBreaching ActionsEnabled: yes
Sekarang
alarm dapat digunakan sebagai pemicu
kembalikan saat menjalankan seperangkat alat:
ALARM_ARN=$1 ROLLBACK_TRIGGER=$(cat <<EOF { "RollbackTriggers": [ { "Arn": "$ALARM_ARN", "Type": "AWS::CloudWatch::Alarm" } ], "MonitoringTimeInMinutes": 1 } EOF ) aws cloudformation create-change-set \ --change-set-name "$CHANGE_SET_NAME" \ --stack-name "$STACK_NAME" \ --template-body "$TPL_PATH" \ --change-set-type "UPDATE" \ --rollback-configuration "$ROLLBACK_TRIGGER"
Pelajaran 5: Pastikan Anda Menyebarkan Versi Terbaru Templat
Tidak mudah untuk menggunakan versi terbaru dari template cloudformation, tetapi itu akan melakukan banyak kerusakan. Setelah itu bersama kami: pengembang tidak mengirim perubahan terbaru dari Git dan tanpa sadar menyebarkan versi stack sebelumnya. Ini menyebabkan aplikasi sederhana yang menggunakan tumpukan ini.
Sesuatu yang sederhana, seperti menambahkan tanda centang untuk melihat apakah cabang relevan sebelum digunakan, akan baik-baik saja (dengan asumsi git adalah alat kontrol versi Anda):
git fetch HEADHASH=$(git rev-parse HEAD) UPSTREAMHASH=$(git rev-parse master@{upstream}) if [[ "$HEADHASH" != "$UPSTREAMHASH" ]] ; then echo "Branch is not up to date with origin. Aborting" exit 1 fi
Pelajaran 6: jangan menemukan kembali roda
Menyebarkan dengan
cloudformation mungkin tampak mudah. Anda hanya perlu banyak skrip bash yang menjalankan perintah aws cli.
4 tahun yang lalu, saya mulai dengan skrip sederhana yang disebut aws cloudformation create-stack command. Segera, naskah itu tidak lagi sederhana. Setiap pelajaran yang dipelajari membuat naskah semakin kompleks. Itu tidak hanya sulit, tetapi juga dengan banyak bug.
Sekarang saya bekerja di departemen IT kecil. Pengalaman telah menunjukkan bahwa masing-masing tim memiliki caranya sendiri dalam menyebarkan tumpukan cloudformation. Dan ini buruk. Akan lebih baik jika semua orang menggunakan pendekatan tunggal. Untungnya, ada banyak alat yang membantu Anda menggunakan dan mengkonfigurasi tumpukan cloudformation.
Pelajaran ini akan membantu Anda menghindari kesalahan.