Bagaimana kami menempatkan manajemen infrastruktur di Terraform - dan mulai hidup

gambar
Kami memiliki 4 akun Amazon, 9 VPC dan 30 lingkungan pengembangan paling kuat, tahapan, regresi - total lebih dari 1000 EC2 contoh dari semua warna dan nuansa. Sejak saya mulai mengumpulkan solusi cloud untuk bisnis, saya harus menjalani hobi saya sampai akhir dan berpikir tentang cara mengotomatisasi semua ini.

Hai Nama saya Kirill Kazarin, saya bekerja sebagai insinyur di DINS. Kami sedang mengembangkan solusi komunikasi bisnis berbasis cloud. Dalam pekerjaan kami, kami secara aktif menggunakan Terraform, yang dengannya kami secara fleksibel mengelola infrastruktur kami. Saya akan membagikan pengalaman saya dengan solusi ini.

Artikel ini panjang, jadi siapkan teh popcorn dan pergi!

Dan satu lagi nuansa - artikel ditulis berdasarkan versi 0.11, segar 0.12 banyak yang telah berubah tetapi praktik utama dan tips masih relevan. Masalah migrasi dari 0,11 ke 0,12 layak mendapatkan artikel terpisah!

Apa itu Terraform?


Terraform adalah alat Hashicorp populer yang muncul pada tahun 2014.

Utilitas ini memungkinkan Anda untuk mengelola infrastruktur cloud Anda dalam Infrastruktur sebagai paradigma Kode dalam bahasa deklaratif yang sangat ramah dan mudah dibaca. Aplikasinya memberi Anda jenis sumber daya terpadu dan penerapan praktik kode untuk manajemen infrastruktur, yang telah lama dikembangkan oleh komunitas pengembang. Terraform mendukung semua platform cloud modern, memungkinkan Anda mengubah infrastruktur dengan aman dan dapat diprediksi.

Saat diluncurkan, Terraform membaca kode dan, menggunakan plug-in yang disediakan oleh penyedia layanan cloud, membawa infrastruktur Anda ke keadaan yang dijelaskan dengan melakukan panggilan API yang diperlukan.

Proyek kami sepenuhnya terletak di Amazon, dikerahkan berdasarkan layanan AWS, dan oleh karena itu saya menulis tentang penggunaan Terraform dalam nada ini. Secara terpisah, saya perhatikan bahwa itu dapat digunakan tidak hanya untuk Amazon. Ini memungkinkan Anda untuk mengelola semua yang memiliki API.

Selain itu, kami mengelola pengaturan VPC, kebijakan IAM, dan peran. Kami mengelola tabel routing, sertifikat, ACL jaringan. Kami mengelola pengaturan firewall aplikasi web kami, S3-bucket, antrian SQS - semua yang dapat digunakan layanan kami di Amazon. Saya belum melihat fitur dengan Amazon yang Terraform tidak dapat menggambarkan dalam hal infrastruktur.

Ternyata infrastrukturnya agak besar, dengan tangan Anda mudah untuk didukung. Tetapi dengan Terraform itu mudah dan sederhana.

Terbuat dari apa Terraform


Penyedia adalah pengaya untuk bekerja dengan API suatu layanan. Saya menghitungnya lebih dari 100 . Diantaranya adalah penyedia untuk Amazon, Google, DigitalOcean, VMware Vsphere, Docker. Saya bahkan menemukan penyedia di daftar resmi ini yang memungkinkan Anda mengelola aturan untuk Cisco ASA !

Antara lain, Anda dapat mengontrol:


Dan ini hanya penyedia resmi, bahkan ada lebih banyak penyedia tidak resmi. Selama percobaan, saya menemukan di GitHub pihak ketiga, tidak termasuk dalam penyedia daftar resmi, yang memungkinkan bekerja dengan DNS dari GoDaddy , serta dengan sumber daya Proxmox .

Dalam satu proyek Terraform, Anda dapat menggunakan penyedia yang berbeda dan, dengan demikian, sumber daya dari penyedia layanan atau teknologi yang berbeda. Misalnya, Anda dapat mengelola infrastruktur Anda di AWS, dengan DNS eksternal dari GoDaddy. Dan besok, perusahaan Anda membeli startup yang dihosting di DO atau Azure. Dan sementara Anda memutuskan untuk memigrasi ini ke AWS atau tidak, Anda juga dapat mendukung ini dengan alat yang sama!

Sumber daya. Ini adalah entitas cloud yang dapat Anda buat menggunakan Terraform. Daftar, sintaks, dan properti mereka bergantung pada penyedia yang digunakan, pada kenyataannya - pada cloud yang digunakan. Atau bukan hanya awan.

Modul Ini adalah entitas yang memungkinkan Terraform Anda untuk membuat templat konfigurasi Anda. Dengan demikian, template memungkinkan Anda untuk membuat kode Anda lebih kecil, memungkinkan Anda untuk menggunakannya kembali. Ya, mereka membantu bekerja dengan nyaman bersamanya.

Mengapa kami memilih Terraform


Bagi kami sendiri, kami mengidentifikasi 5 alasan utama. Mungkin dari sudut pandang Anda, tidak semuanya akan tampak signifikan:

  • Terraform adalah utilitas dukungan cloud beberapa Agnostik Cloud (terima kasih atas komentar berharga dalam komentar) . Ketika kami memilih alat ini, kami berpikir: - Dan apa yang akan terjadi jika manajemen besok atau seminggu mendatangi kami dan berkata: "Teman-teman , kami pikir - jangan hanya menyebarkan ke Amazon. Kami memiliki beberapa jenis proyek, di mana kita perlu mendapatkan infrastruktur di Google Cloud. Atau di Azure - yah, Anda tidak pernah tahu . " Kami memutuskan bahwa kami ingin memiliki alat yang tidak akan terikat secara kaku dengan layanan cloud apa pun.
  • Sumber terbuka . Terraform adalah solusi open source . Repositori proyek memiliki peringkat lebih dari 16 ribu bintang, ini adalah konfirmasi yang baik tentang reputasi proyek.

    Kami telah menemukan lebih dari sekali atau dua kali fakta bahwa dalam beberapa versi ada bug atau perilaku yang tidak terlalu dimengerti. Memiliki repositori terbuka memungkinkan Anda untuk memastikan bahwa ini benar-benar bug, dan kami dapat menyelesaikan masalah hanya dengan memperbarui mesin atau versi plugin. Atau ini bug, tapi "Guys, tunggu, dua hari kemudian versi baru akan dirilis dan kami akan memperbaikinya." Atau: "Ya, ini adalah sesuatu yang tidak dapat dimengerti, aneh, mereka mengatasinya, tetapi ada yang bisa diatasi." Sangat nyaman.
  • Kontrol . Terraform sebagai utilitas sepenuhnya di bawah kendali Anda. Ini dapat diinstal pada laptop, pada server, dapat dengan mudah diintegrasikan ke dalam pipa Anda, yang dapat dilakukan berdasarkan alat apa pun. Sebagai contoh, kami menggunakannya di GitLab CI.
  • Memeriksa status infrastruktur . Terraform dapat dan melakukan pemeriksaan yang baik pada kondisi infrastruktur Anda.

    Misalkan Anda mulai menggunakan Terraform di tim Anda. Anda membuat deskripsi beberapa sumber daya di Amazon, misalnya, Grup Keamanan, menerapkannya - itu dibuat untuk Anda, semuanya baik-baik saja. Dan di sini - bam! Kolega Anda yang kembali dari liburan kemarin dan belum menyadari bahwa Anda telah mengatur semuanya dengan sangat indah di sini, atau bahkan seorang kolega dari departemen lain masuk dan mengubah pengaturan untuk Grup Keamanan ini dengan menggunakan pegangan.

    Dan tanpa bertemu dengannya, tanpa berbicara, atau tanpa mengasumsikan masalah tertentu nanti, Anda tidak akan pernah tahu tentang ini dalam situasi normal. Tetapi, jika Anda menggunakan Terraform, bahkan menjalankan rencana idle pada sumber daya ini akan menunjukkan kepada Anda bahwa ada perubahan di lingkungan kerja.

    Ketika Terraform melihat kode Anda, ia secara bersamaan memanggil API penyedia cloud, menerima status objek dari itu dan membandingkan: "Dan sekarang ada hal yang sama yang saya lakukan sebelumnya, apa yang saya ingat?" Kemudian dia membandingkannya dengan kode, melihat apa lagi yang perlu diubah. Dan, misalnya, jika semuanya sama dalam ceritanya, dalam ingatannya, dan dalam kode Anda, tetapi ada perubahan di sana, dia akan menunjukkan kepada Anda dan menawarkan untuk mengembalikannya. Menurut pendapat saya, properti juga sangat bagus. Jadi, ini adalah langkah lain, secara pribadi bagi kami, untuk memastikan bahwa kami memiliki infrastruktur yang tidak dapat diubah.
  • Fitur lain yang sangat penting adalah modul yang saya sebutkan, dan penting. Saya akan membicarakannya nanti. Kapan saya akan membandingkan dengan alat.

Dan juga ceri pada kue: Terraform memiliki daftar fungsi bawaan yang agak besar . Fungsi-fungsi ini, terlepas dari bahasa deklaratif, memungkinkan kami untuk mengimplementasikan beberapa, tidak untuk mengatakan program, tetapi logika.

Misalnya, beberapa kalkulasi otomatis, garis terbagi, casting ke huruf kecil dan besar, menghapus karakter dari baris ini. Kami cukup aktif menggunakannya. Mereka membuat hidup jauh lebih mudah, terutama ketika Anda menulis modul yang nantinya akan digunakan kembali di lingkungan yang berbeda.

Terraform vs CloudFormation


Jaringan sering membandingkan Terraform dengan CloudFormation. Kami juga menanyakan pertanyaan ini ketika memilihnya. Dan inilah hasil perbandingan kami.

PerbandinganBentuk TerraCloudformation
Dukungan cloud bergandaMelalui penggunaan berbagai penyedia, plug-in dapat berfungsi dengan penyedia cloud besar apa pun.
Tertempel kuat di Amazon.
Ubah pelacakanJika Anda memiliki perubahan
bukan dalam kode TF, tetapi pada sumber daya yang ia buat, TF akan dapat mendeteksi ini dan memungkinkan Anda untuk memperbaiki situasi
Fungsi serupa muncul
hanya pada bulan November 2018 .
KetentuanTidak ada dukungan untuk kondisi (hanya
dalam bentuk operator ternary).
Ketentuan didukung.
Penyimpanan
menyatakan
Memungkinkan Anda memilih beberapa jenis backend, misalnya, secara lokal
pada mesin Anda (ini adalah perilaku default), pada berbagi file,
dalam S3 dan di tempat lain.

Ini kadang-kadang berguna karena tfstate Terraform disajikan sebagai file teks besar dengan struktur mirip JSON. Dan kadang-kadang kadang berguna untuk membacanya, membacanya - dan setidaknya bisa membuatnya cadangan, karena Anda tidak pernah tahu apa. Secara pribadi, misalnya, saya lebih tenang dari kenyataan bahwa ini ada di suatu tempat yang dikendalikan oleh saya.
Menyimpan status hanya di suatu tempat di dalam AWS
Impor Sumber DayaTerraform memudahkan pengimporan sumber daya. Anda dapat mengambil semua sumber daya di bawah kendali Anda. Anda cukup menulis kode yang akan mencirikan objek ini, atau menggunakan Terraforming .
Dia pergi ke Amazon yang sama, mengambil informasi tentang lingkungan dari sana, dan kemudian membuangnya dalam bentuk kode.
Ini dibuat oleh mesin, tidak dioptimalkan, tetapi ini adalah langkah pertama yang baik untuk memulai migrasi. Dan kemudian Anda hanya memberikan perintah impor. Terraform membandingkan, membawa lingkungan ini ke dalam keadaannya - dan sekarang ia mengendalikannya.
CloudFormation tidak tahu caranya. Jika
Anda telah melakukan sesuatu dengan tangan Anda sebelumnya, Anda membenturkannya dan membuatnya kembali dengan CloudFormation, atau hidup terus. Sayangnya, tidak ada opsi.

Bagaimana cara memulai dengan Terraform


Secara umum, memulai cukup sederhana. Inilah langkah-langkah pertama secara singkat:

  1. Pertama-tama, buat repositori Git dan segera mulai menyimpan semua perubahan, percobaan, dan semuanya.
  2. Baca panduan Memulai . Ini kecil, sederhana, cukup rinci, dan menjelaskan dengan baik bagaimana memulai dengan utilitas ini.
  3. Tulis beberapa demo, kode kerja. Anda bahkan dapat menyalin beberapa contoh untuk dimainkan nanti.

Latihan kami dengan Terraform


Kode sumber


Anda memulai proyek pertama Anda dan menyimpan semuanya dalam satu file main.tf besar. Ini adalah contoh khas (saya jujur ​​mengambil yang pertama saya dapatkan dari GitHub).

Tidak ada yang salah, tetapi ukuran basis kode cenderung bertambah seiring waktu. Ketergantungan antara sumber daya juga meningkat. Setelah beberapa waktu, file menjadi besar, kompleks, tidak dapat dibaca, tidak dirawat dengan baik - dan perubahan yang ceroboh di satu tempat dapat menyebabkan masalah.

Hal pertama yang saya sarankan adalah untuk menyoroti apa yang disebut repositori inti, atau keadaan inti dari proyek Anda, lingkungan Anda. Segera setelah Anda mulai membuat infrastruktur menggunakan Terraform, atau mengimpornya, Anda akan segera menemukan kenyataan bahwa Anda memiliki beberapa entitas yang, setelah digunakan, dikonfigurasikan, jarang berubah. Misalnya, ini adalah pengaturan VPC, atau VPC itu sendiri. Ini adalah jaringan, kelompok keamanan dasar, umum seperti akses SSH - Anda dapat menyusun daftar yang cukup besar.

Tidak masuk akal untuk menyimpan ini di repositori yang sama dengan layanan yang sering Anda ubah. Pilih mereka dalam repositori yang terpisah dan dokkan melalui fitur Terraform seperti keadaan jauh.

  • Anda mengurangi basis kode bagian proyek yang sering Anda kerjakan secara langsung.
  • Alih-alih satu file besar yang berisi deskripsi kondisi infrastruktur Anda, dua file lebih kecil, dan pada titik waktu tertentu Anda bekerja dengan salah satunya.

Apa masalahnya? Ketika Terraform membangun sebuah rencana, yaitu menghitung, menghitung apa yang harus diubah, menerapkan - itu sepenuhnya menceritakan keadaan ini, memeriksa terhadap kode, memeriksa terhadap status dalam AWS. Semakin besar status Anda, semakin lama rencananya.

Kami sampai pada praktik ini ketika kami membutuhkan waktu 20 menit untuk membangun rencana untuk seluruh lingkungan dalam produksi. Karena fakta bahwa kami menarik ke dalam inti yang terpisah segala sesuatu yang kami tidak dapat sering berubah, kami mengurangi waktu untuk membangun rencana hingga setengahnya. Kami memiliki ide bagaimana hal itu dapat dikurangi lebih lanjut, tidak hanya memecah menjadi inti dan non-inti, tetapi juga oleh subsistem, karena kami memiliki mereka terhubung dan biasanya berubah bersama. Jadi, kita katakan, kita akan mengubah 10 menit menjadi 3. Tetapi kita masih dalam proses menerapkan solusi seperti itu.

Lebih sedikit kode - lebih mudah dibaca


Kode kecil lebih mudah dipahami dan lebih nyaman digunakan. Jika Anda memiliki tim besar dan ada orang-orang dengan tingkat pengalaman berbeda di dalamnya - keluarkan apa yang jarang Anda ubah, tetapi secara global, dalam lobak terpisah, dan sediakan akses yang lebih sempit untuknya.

Katakanlah Anda memiliki junior di tim Anda dan Anda tidak memberi mereka akses ke repositori global yang menjelaskan pengaturan VPC - dengan cara ini Anda memastikan diri Anda dari kesalahan. Jika seorang insinyur membuat kesalahan dalam menulis contoh, dan sesuatu dibuat salah - itu tidak menakutkan. Dan jika dia membuat kesalahan dalam opsi yang diinstal pada semua mesin, istirahat, atau melakukan sesuatu dengan pengaturan subnet, dengan routing - ini jauh lebih menyakitkan.

Pemilihan repositori inti dilakukan dalam beberapa langkah.

Tahap 1 . Buat repositori terpisah. Simpan semua kode di dalamnya, secara terpisah - dan jelaskan entitas yang harus digunakan kembali dalam repositori pihak ketiga menggunakan output ini. Katakanlah kita membuat sumber daya subnet AWS di mana kita menggambarkan di mana ia berada, zona ketersediaan mana, ruang alamat.

resource "aws_subnet" "lab_pub1a" { vpc_id = "${aws_vpc.lab.id}" cidr_block = "10.10.10.0/24" Availability_zone = "us-east-1a" ... } output "sn_lab_pub1a-id" { value = "${aws_subnet.lab_pub1a.id}" } 

Dan kemudian kita mengatakan bahwa kita mengirim id dari objek ini ke output. Anda dapat melakukan output untuk setiap parameter yang Anda butuhkan.

Apa masalahnya di sini? Saat Anda menggambarkan nilai, Terraform menyimpannya secara terpisah di inti tfstate. Dan ketika Anda menoleh padanya, dia tidak perlu menyinkronkan, menceritakan kembali - dia akan dapat segera memberikan masalah ini kepada Anda dari keadaan ini. Lebih jauh, dalam repositori, yang bukan-inti, Anda menggambarkan koneksi seperti itu dengan keadaan jauh: Anda memiliki keadaan jauh ini dan itu, itu terletak di bucket S3 ini dan itu, kunci ini dan itu serta kunci dan wilayah.

Tahap 2 . Dalam proyek non-inti, kami membuat tautan ke status proyek inti, sehingga kami dapat merujuk ke parameter yang diekspor melalui output.

 data "terraform_remote_state" "lab_core" { backend = "s3" config { bucket = "lab-core-terraform-state" key = "terraform.tfstate" region = "us-east-1" } } 

Tahap 3 . Mulai! Ketika saya perlu menggunakan antarmuka jaringan baru untuk contoh di subnet tertentu, saya katakan: di sini adalah negara data jarak jauh, cari nama negara ini di dalamnya, cari parameter ini di dalamnya, yang, pada kenyataannya, cocok dengan nama ini.

 resource "aws_network_interface" "fwl01" { ... subnet_id = "${data.terraform_remote_state.lab_core.sn_lab_pub1a-id}" } 

Dan ketika saya membangun rencana perubahan di repositori non-inti saya, nilai untuk Terraform ini akan menjadi konstan untuk itu. Jika Anda ingin mengubahnya, Anda harus melakukannya di repositori ini, tentu saja, inti. Tetapi karena ini jarang berubah, itu tidak mengganggu Anda.

Modul


Biarkan saya mengingatkan Anda bahwa modul adalah konfigurasi mandiri yang terdiri dari satu atau lebih sumber daya terkait. Itu dikelola sebagai grup:

Modul adalah hal yang sangat nyaman karena Anda jarang membuat satu sumber daya begitu saja, dalam ruang hampa, biasanya itu terhubung secara logis dengan sesuatu.

 module "AAA" { source = "..." count = "3" count_offset = "0" host_name_prefix = "XXX-YYY-AAA" ami_id = "${data.terraform_remote_state.lab_core.ami-base-ami_XXXX-id}" subnet_ids = ["${data.terraform_remote_state.lab_core.sn_lab_pub1a-id}", "${data.terraform_remote_state.lab_core.sn_lab_pub1b-id}"] instance_type = "t2.large" sgs_ids = [ "${data.terraform_remote_state.lab_core.sg_ssh_lab-id}", "${aws_security_group.XXX_lab.id}" ] boot_device = {volume_size = "50" volume_type = "gp2"} root_device = {device_name = "/dev/sdb" volume_size = "50" volume_type = "gp2" encrypted = "true"} tags = "${var.gas_tags}" } 

Sebagai contoh: ketika kita menggunakan instance EC2 baru, kita membuat antarmuka jaringan dan lampiran untuk itu, kita sering membuat alamat IP elastis untuk itu, kita membuat catatan rute-53, dan sesuatu yang lain. Artinya, kita mendapatkan setidaknya 4 entitas.

Setiap kali, menggambarkannya dalam empat potong kode tidak nyaman. Apalagi mereka cukup khas. Itu memohon - membuat templat, dan kemudian hanya merujuk ke templat ini, memberikan parameter padanya: beberapa nama, ke dalam kotak mana yang akan didorong, grup keamanan mana yang akan digantung. Sangat nyaman.

Terraform memiliki fitur Hitung, yang memungkinkan Anda untuk lebih mengurangi kondisi Anda. Anda dapat menggambarkan sekumpulan besar instance dengan sepotong kode. Katakanlah saya perlu menggunakan 20 mesin dari jenis yang sama. Saya tidak akan menulis 20 lembar kode bahkan dari template, saya akan menulis 1 lembar kode, saya akan menunjukkan Hitung dan nomor di dalamnya - berapa banyak yang harus saya lakukan.

Misalnya, ada beberapa modul yang mereferensikan templat. Saya hanya melewati parameter spesifik: ID subnet; AMI untuk digunakan bersama; jenis contoh; pengaturan grup keamanan; hal lain, dan tunjukkan berapa banyak dari hal-hal ini yang harus saya lakukan. Hebat, bawa mereka dan balikkan!

Besok, pengembang mendatangi saya dan berkata: "Dengar, kami ingin bereksperimen dengan muatan, tolong beri kami dua lagi." Yang perlu saya lakukan: Saya mengubah satu digit menjadi 5. Jumlah kode tetap sama persis.

Secara konvensional, modul dapat dibagi menjadi dua jenis - sumber daya dan infrastruktur. Dari sudut pandang kode, tidak ada perbedaan, melainkan konsep tingkat tinggi yang diperkenalkan oleh operator.
Modul sumber daya menyediakan kumpulan sumber daya yang terstandarisasi dan parameter, terkait secara logis. Contoh di atas adalah modul sumber daya yang khas. Cara bekerja dengan mereka:

  • Kami menunjukkan jalur ke modul - sumber konfigurasinya, melalui arahan Sumber.
  • Kami menunjukkan versi - ya, dan operasi pada prinsip "terbaru dan terhebat" bukanlah pilihan terbaik di sini. Anda tidak memasukkan versi terbaru perpustakaan setiap kali dalam proyek Anda? Tetapi lebih lanjut tentang itu nanti.
  • Kami memberikan argumen padanya.

Kami dilampirkan ke versi modul, dan kami hanya mengambil yang terakhir - infrastruktur harus diversiasikan (sumber daya tidak dapat diversiasikan, tetapi kode dapat). Sumber daya dapat dibuat dihapus atau diciptakan kembali. Itu saja! Kita juga harus tahu dengan jelas versi mana yang telah kita buat masing-masing infrastruktur.

Modul infrastruktur cukup sederhana. Mereka terdiri dari sumber daya, dan termasuk standar perusahaan (misalnya, tag, daftar nilai standar, standar yang diterima, dan sebagainya).

Mengenai proyek dan pengalaman kami, kami telah lama dan dengan tegas beralih ke penggunaan modul sumber daya untuk segala sesuatu yang mungkin dengan proses pembuatan versi dan peninjauan yang sangat ketat. Dan sekarang kami secara aktif memperkenalkan praktik modul infrastruktur di tingkat laboratorium dan pementasan.

Rekomendasi untuk menggunakan modul

  1. Jika Anda tidak bisa menulis, tetapi gunakan yang sudah jadi, jangan menulis. Apalagi jika Anda baru dalam hal ini. Percayai modul yang sudah jadi, atau setidaknya lihat bagaimana mereka melakukannya untuk Anda. Namun, jika Anda masih perlu menulis sendiri, jangan gunakan panggilan ke penyedia secara internal dan berhati-hatilah dengan penyedia layanan.
  2. Periksa bahwa Terraform Registry tidak mengandung modul sumber daya yang sudah jadi.
  3. Jika Anda menulis modul Anda, sembunyikan spesifik di bawah tenda. Pengguna akhir tidak perlu khawatir tentang apa dan bagaimana Anda menerapkannya secara internal.
  4. Lakukan parameter input dan nilai output dari modul Anda. Dan lebih baik jika mereka file terpisah. Sangat nyaman.
  5. Jika Anda menulis modul, simpan dalam repositori dan versi. Lebih baik repositori terpisah untuk modul.
  6. Jangan menggunakan modul lokal - mereka tidak diversi atau digunakan kembali.
  7. Hindari menggunakan deskripsi penyedia dalam modul, karena kredensial koneksi dapat dikonfigurasi dan diterapkan secara berbeda untuk orang yang berbeda. Seseorang menggunakan variabel lingkungan untuk ini, dan seseorang menyiratkan menyimpan kunci dan rahasia mereka dalam file dengan jalur yang ditentukan untuk mereka. Ini harus ditunjukkan pada tingkat yang lebih tinggi.
  8. Gunakan penyedia lokal dengan hati-hati. Itu dijalankan secara lokal, pada mesin yang menjalankan Terraform, tetapi lingkungan eksekusi untuk pengguna yang berbeda mungkin berbeda. Sampai Anda menanamkannya di CI, Anda dapat menemukan berbagai artefak: misalnya eksekutif lokal dan menjalankan yang mungkin. Dan seseorang memiliki distribusi yang berbeda, shell yang lain, versi yang berbeda dari yang dimungkinkan, atau bahkan Windows.

Tanda-tanda modul yang baik (di sini sedikit lebih rinci ):

  • Modul yang baik memiliki dokumentasi dan contoh. Jika masing-masing dirancang sebagai repositori terpisah, ini lebih mudah dilakukan.
  • Mereka tidak memiliki pengaturan hardcoded (misalnya, wilayah AWS).
  • Gunakan standar wajar, dirancang sebagai standar. Sebagai contoh, modul untuk instance EC2 secara default tidak akan membuat mesin virtual bertipe m5d.24xlarge untuk Anda, ia menggunakan salah satu dari jenis t2 atau t3 minimum untuk ini.
  • Kode ini "bersih" - terstruktur, disediakan dengan komentar, tidak perlu bingung, dirancang dengan gaya yang sama.
  • Sangat diinginkan untuk dilengkapi dengan tes, meskipun sulit. Sayangnya, kami belum sampai pada hal ini.

Memberi tag


Tag itu penting.

Tagging adalah penagihan. AWS memiliki alat yang memungkinkan Anda melihat berapa banyak uang yang Anda habiskan untuk infrastruktur Anda. Dan manajemen kami benar-benar ingin memiliki alat di mana mereka dapat melihatnya secara deterministik. Misalnya, berapa banyak uang yang dikonsumsi komponen ini dan itu, atau subsistem ini dan itu, tim ini dan itu, lingkungan ini dan itu

gambar

Pemberian tag adalah dokumentasi sistem Anda. Dengan itu, Anda menyederhanakan pencarian Anda. Bahkan hanya di konsol AWS, di mana tag ini ditampilkan dengan rapi di layar Anda, menjadi lebih mudah bagi Anda untuk memahami apa yang dimaksud dengan jenis ini atau itu. Jika kolega baru datang, lebih mudah bagi Anda untuk menjelaskan ini dengan menunjukkan: "Lihat, ini dia - ini." Kami mulai membuat tag sebagai berikut - kami membuat array tag untuk setiap jenis sumber daya.

Contoh:

 variable "XXX_tags" { description = "The set of XXX tags." type = "map" default = { "TerminationDate" = "03.23.2018", "Environment" = "env_name_here", "Department" = "dev", "Subsystem" = "subsystem_name", "Component" = "XXX", "Type" = "application", "Team" = "team_name" } } 

Kebetulan di perusahaan kami lebih dari satu tim kami menggunakan AWS, dan ada beberapa daftar tag yang diperlukan.

  1. Tim - tim mana yang menggunakan berapa banyak sumber daya.
  2. Departemen - mirip dengan departemen.
  3. Lingkungan - sumber daya mengalahkan dalam "lingkungan", tetapi Anda, misalnya, dapat menggantinya dengan proyek atau sesuatu seperti itu.
  4. Subsistem - subsistem tempat komponen berada. Komponen dapat dimiliki oleh satu subsistem. Sebagai contoh, kami ingin melihat seberapa banyak subsistem yang kami miliki dan entitasnya mulai konsumsi. Tiba-tiba, misalnya, untuk bulan sebelumnya, itu telah tumbuh secara signifikan. Kita harus pergi ke pengembang dan berkata: "Guys, itu mahal. Anggaran sudah dekat satu sama lain, mari kita optimalkan logikanya. ”
  5. Jenis - jenis komponen: penyeimbang, penyimpanan, aplikasi atau database.
  6. Komponen - komponen itu sendiri, namanya dalam notasi internal.
  7. Tanggal pengakhiran - waktu kapan harus dihapus, dalam format tanggal. Jika penghapusannya tidak diharapkan, setel ke "Permanen". Kami memperkenalkannya karena di lingkungan pengembangan, dan bahkan di beberapa lingkungan panggung, kami memiliki tahap pengujian stres yang meningkat selama sesi stres, yaitu, kami tidak menjaga mesin ini secara teratur. Kami menunjukkan tanggal kapan sumber daya harus dihancurkan. Selanjutnya, Anda dapat mempercepat otomatisasi berdasarkan lambda, beberapa skrip eksternal yang bekerja melalui AWS Command Line Interface, yang akan menghancurkan sumber daya ini secara otomatis.

Sekarang - cara memberi tag.

Kami memutuskan bahwa kami akan melakukan tag-map kami sendiri untuk setiap komponen, di mana kami akan mencantumkan semua tag yang ditentukan: kapan harus menghentikannya, apa yang dimaksud. Mereka dengan cepat menyadari bahwa itu tidak nyaman. Karena basis kode bertambah, karena kami memiliki lebih dari 30 komponen, dan 30 keping kode seperti itu tidak nyaman. Jika Anda perlu mengubah sesuatu, maka Anda jalankan dan ubah.

Untuk memberi tag dengan baik, kami menggunakan entitas Lokal .

 locals { common_tags = {"TerminationDate" = "XX.XX.XXXX", "Environment" = "env_name", "Department" = "dev", "Team" = "team_name"} subsystem_1_tags = "${merge(local.common_tags, map("Subsystem", "subsystem_1_name"))}" subsystem_2_tags = "${merge(local.common_tags, map("Subsystem", "subsystem_2_name"))}" } 

Di dalamnya Anda dapat membuat daftar subset, dan kemudian menggunakannya satu sama lain.

Sebagai contoh, kami menghapus beberapa tag umum ke dalam struktur seperti itu, dan kemudian yang spesifik dengan subsistem. Kami mengatakan: "Ambil blok ini dan tambahkan, misalnya, subsistem 1. Dan untuk subsistem 2, tambahkan subsistem 2". Kami mengatakan: "Tag, tolong, ambil yang umum dan tambahkan jenis, aplikasi, nama, komponen, dan siapa yang memilikinya." Ternyata perubahannya sangat singkat, jelas dan tersentralisasi, jika tiba-tiba diperlukan.

 module "ZZZ02" { count = 1 count_offset = 1 name = "XXX-YYY-ZZZ" ... tags = "${merge(local.core_tags, map("Type", "application", "Component", "XXX"))}" } 

gambar

Kontrol versi


Modul template Anda, jika Anda menggunakannya, harus disimpan di suatu tempat. Cara termudah yang paling mungkin dilakukan setiap orang adalah penyimpanan lokal. Hanya di direktori yang sama, hanya beberapa subdirektori di mana Anda menggambarkan, misalnya, templat untuk beberapa jenis layanan. Ini bukan cara yang baik. Ini nyaman, dapat dengan cepat diperbaiki dan diuji dengan cepat, tetapi sulit untuk menggunakannya kembali nanti dan sulit untuk dikendalikan

 module "ZZZ02" { source = "./modules/srvroles/ZZZ" name = "XXX-YYY-ZZZ" } 

Misalkan pengembang mendatangi Anda dan berkata: "Jadi, kami membutuhkan entitas ini dan itu dalam konfigurasi ini dan itu, dalam infrastruktur kami." Anda menulisnya, membuatnya dalam bentuk modul lokal di repositori proyek mereka. Dikerahkan - sangat baik. Mereka menguji, mengatakan: "Itu akan! Dalam produksi. " Kami datang ke panggung, pengujian stres, produksi. Setiap kali Ctrl-C, Ctrl-V; Ctrl-C, Ctrl-V. Ketika kami sampai di penjualan, rekan kami mengambilnya, menyalin kode dari lingkungan laboratorium, memindahkannya ke tempat lain dan mengubahnya di sana. Dan kita mendapatkan kondisi yang sudah tidak konsisten. Dengan penskalaan horizontal, ketika Anda memiliki lingkungan laboratorium sebanyak yang kami miliki, itu hanya adish.

Oleh karena itu, cara yang baik adalah membuat repositori Git yang terpisah untuk masing-masing modul Anda, dan kemudian rujuk saja. Kami mengubah segalanya di satu tempat - baik, nyaman, terkontrol.

 module "ZZZ" { source = "git::ssh://git@GIT_SERVER_FQDN/terraform/modules/general-vm/2-disks.git" host_name_prefix = "XXX-YYY-ZZZ" 

Mengantisipasi pertanyaan, bagaimana kode Anda mencapai produksi. Untuk ini, proyek terpisah dibuat yang menggunakan kembali modul yang disiapkan dan diuji.

Hebat, kami memiliki satu sumber kode yang berubah secara terpusat. Saya mengambil, menulis, menyiapkan, dan mengatur diri sendiri bahwa besok pagi saya akan menyebarkan produksi. Buat rencana, teruji - hebat, ayo pergi. Pada saat ini, kolega saya, dibimbing secara eksklusif oleh niat baik, pergi dan mengoptimalkan sesuatu, ditambahkan ke modul ini. Dan kebetulan bahwa perubahan ini merusak kompatibilitas.

Misalnya, dia menambahkan parameter yang diperlukan, yang harus dia lewati, jika tidak, modul tidak akan berkumpul. Atau dia mengubah nama parameter ini. Saya datang di pagi hari, saya benar-benar membatasi waktu untuk perubahan, mulai membangun rencana, dan Terraform mengeluarkan modul negara dari Git, mulai membangun rencana dan berkata: "Ups, saya tidak bisa. Tidak cukup untuk Anda, Anda berganti nama. " Saya terkejut: "Tapi saya tidak melakukannya, bagaimana menghadapinya?" Dan jika ini adalah sumber daya yang dibuat sejak lama, maka setelah perubahan seperti itu Anda harus menjalankan semua lingkungan, entah bagaimana berubah dan mengarah ke satu tampilan. Ini tidak nyaman.

Ini dapat diperbaiki menggunakan tag Git. Kami memutuskan sendiri bahwa kami akan menggunakan notasi SemVer dan menyusun aturan sederhana: segera setelah konfigurasi modul kami mencapai kondisi stabil tertentu, yaitu, kami dapat menggunakannya, kami memberi tag pada komit ini. Jika kami melakukan perubahan dan tidak merusak kompatibilitas, kami mengubah nomor minor pada tag, jika rusak, kami mengubah nomor utama.

Jadi, di alamat sumber, lampirkan ke tag tertentu dan jika setidaknya memberikan sesuatu yang Anda miliki sebelumnya, itu akan selalu dikumpulkan. Biarkan versi modul berjalan, tetapi pada saat yang tepat kita akan datang, dan ketika kita benar-benar membutuhkannya, kita akan mengubahnya. Dan apa yang berhasil sebelum itu, setidaknya tidak akan rusak. Ini nyaman. Ini seperti apa yang terlihat di GitLab kami.

gambar

Bercabang


Menggunakan percabangan adalah praktik penting lainnya. Kami telah mengembangkan aturan untuk diri kami sendiri bahwa Anda harus membuat perubahan hanya dari master. Tetapi untuk setiap perubahan yang ingin Anda buat dan uji, silakan buat cabang terpisah, bermain dengannya, bereksperimen, buat rencana, dan lihat bagaimana hasilnya. Dan kemudian lakukan permintaan gabungan, dan biarkan seorang rekan melihat kode dan bantuan.

gambar

Tempat menyimpan tfstate


Anda tidak boleh menyimpan negara Anda secara lokal. Anda seharusnya tidak menyimpan status Anda di Git.

Kita terbakar pada ini ketika seseorang, ketika meluncurkan cabang-cabang non-master, mendapatkan statusnya, di mana negara diselamatkan - kemudian dia menyalakannya melalui penggabungan, seseorang menambahkan miliknya, ternyata menggabungkan konflik. Atau ternyata tanpa mereka, tetapi keadaan yang tidak konsisten, karena "dia sudah memilikinya, saya belum memilikinya," dan kemudian memperbaikinya semua adalah praktik yang tidak menyenangkan. Oleh karena itu, kami memutuskan bahwa kami akan menyimpannya di tempat yang aman, versi, tetapi itu akan berada di luar Git.

S3 sangat cocok di bawah ini: ini tersedia, memiliki HA, sejauh yang saya ingat empat sembilan tepat, mungkin lima . Ini memberi versi keluar dari kotak, bahkan jika Anda memecahkan tfstate Anda, Anda selalu dapat memutar kembali. Dan dia juga memberikan hal yang sangat penting dalam kombinasi dengan DynamoDB, yang, menurut pendapat saya, telah mempelajari Terraform ini sejak versi 0.8. Di DynamoDB, Anda memiliki papan nama di mana Terraform mencatat bahwa itu memblokir negara.

Yaitu, misalkan saya ingin membuat beberapa perubahan. Saya mulai membangun rencana atau mulai menerapkannya, Terraform pergi ke DynamoDB dan mengatakan bahwa itu membuat informasi dalam pelat ini bahwa keadaan ini diblokir; pengguna, komputer, waktu. Pada saat ini, kolega saya, yang bekerja dari jarak jauh atau mungkin beberapa meja dari saya, tetapi fokus pada pekerjaan dan tidak melihat apa yang saya lakukan, juga memutuskan bahwa sesuatu perlu diubah. Dia membuat rencana, tetapi meluncurkannya sedikit kemudian.

Terraform masuk ke dinamika, lihat - Kunci, terputus, memberi tahu pengguna: "Maaf, tfstate diblokir oleh sesuatu." Seorang kolega melihat bahwa saya sedang bekerja sekarang, dia dapat mendatangi saya dan berkata, "Dengar, changer saya lebih penting, tolong beri saya." Saya berkata: "Bagus", saya membatalkan paket, menghapus blok, lebih tepatnya, bahkan secara otomatis dihapus jika Anda melakukannya dengan benar, tanpa mengganggu Ctrl-C. Seorang kolega pergi dan melakukannya. Jadi, kami memastikan diri kami terhadap situasi ketika Anda berdua mengubah sesuatu.

Gabungkan permintaan


Kami menggunakan percabangan di Git. Kami memberikan permintaan penggabungan kepada kolega. Selain itu, di Gitlab kami menggunakan hampir semua alat yang tersedia bagi kami untuk bekerja bersama, untuk menggabungkan permintaan atau bahkan hanya beberapa kumpulan: mendiskusikan kode Anda, meninjaunya, menetapkan sedang dalam proses atau masalah, hal lain seperti itu. Ini sangat berguna, sangat membantu dalam pekerjaan.

Plus, dalam hal ini, rollback juga lebih mudah, Anda dapat kembali ke komit sebelumnya atau, jika Anda, katakanlah, memutuskan bahwa Anda tidak hanya akan menerapkan perubahan dari wizard, Anda cukup beralih ke cabang stabil. Misalnya, Anda membuat cabang fitur dan memutuskan bahwa Anda akan melakukan perubahan terlebih dahulu dari cabang fitur. Dan kemudian perubahan, setelah semuanya bekerja dengan baik, lakukan pada master. Anda menerapkan perubahan di cabang Anda, menyadari bahwa ada sesuatu yang salah, beralih ke master - tidak ada perubahan, kata mereka berlaku - dia kembali.

Jaringan pipa


gambar

Kami memutuskan bahwa kami perlu menggunakan proses CI untuk menerapkan perubahan kami. Untuk melakukan ini, berdasarkan Gitlab CI, kami sedang menulis saluran pipa yang mengotomatiskan aplikasi perubahan. Sejauh ini, kami memiliki dua jenis:

  • Pipa untuk cabang utama (pipa induk)
  • Pipa untuk semua cabang lainnya (pipa cabang)

Apa yang dilakukan pipa brunch?Itu mulai verifikasi kode otomatis (bodoh memeriksa untuk kesalahan ketik, misalnya). Dan kemudian mulai membangun rencana. Dan kolega yang akan menonton permintaan gabungan Anda dapat segera membuka paket yang telah dibuat dan tidak hanya melihat kode - tetapi juga apa yang Anda tambahkan. Dia juga akan melihat bagaimana itu akan jatuh pada infrastruktur Anda. Jelas dan bermanfaat.

gambar

Di wisaya, satu langkah lagi ditambahkan di sini. Perbedaannya adalah bahwa rencana Anda tidak hanya dihasilkan, tetapi juga disimpan sebagai artefak. Fitur lain yang sangat berguna dari Terraform adalah paket dapat disimpan sebagai file, dan kemudian menerapkannya. Katakanlah Anda membuat permintaan gabungan dan mengesampingkannya. Sebulan kemudian mereka mengingatnya dan memutuskan untuk kembali. Kode Anda sudah jauh di depan. Karena kenyataan bahwa Anda menyimpan artefak rencana tersebut, Anda dapat menerapkannya pada apa yang Anda inginkan pada saat itu.

gambar

Dalam kasus kami, artefak ini kemudian ditransfer ke langkah berikutnya, yang dilakukan dengan tangan. Artinya, kita mendapat satu poin penerapan perubahan kita.

Kekurangan dari Terraform


Fungsi Terlepas dari kenyataan bahwa Terraform memiliki sejumlah fungsi bawaan yang cukup besar, tidak semuanya berfungsi sebaik yang ingin kita pikirkan.

Ini memiliki fungsi tidak nyaman di dalamnya, misalnya, "Elemen" - dalam beberapa situasi, dengan kurangnya pengalaman, perilakunya mungkin tidak persis seperti yang Anda harapkan.

Misalnya, Anda menggunakan modul, hitungan diteruskan ke modul - berapa banyak instance untuk digunakan, dan, katakanlah, daftar subnet yang dikelompokkan berdasarkan zona ketersediaan ditransmisikan. Ditransfer, diterapkan, tambah hitungan, masih diterapkan. Dan sekarang Anda memutuskan untuk mentransfer daftar subnet yang lebih banyak ke sana. Anda punya kotak, Anda memutuskan untuk menggunakan satu lagi AZ. Anda memiliki bagian kedua dari daftar yang berubah, dan hitungan dipetakan ke daftar ini melalui elemen.

Katakanlah Anda memiliki 4 AZ sebelum ini dan 5 kali, dan kemudian Anda menambahkan AZ lain - itu akan meninggalkan 4 AZ pertama, yang sudah dalam urutan. Dan sekitar yang kelima ia akan berkata: "Dan sekarang aku akan membuatnya kembali." Dan kamu tidak mau! Anda hanya menginginkan yang baru datang. Bug semacam itu datang dari sifat karya Terraform dengan daftar.

Operator ternary. Suatu kondisi hanyalah operator ternary . Kami benar-benar kekurangan kondisi. Tetap saja, saya ingin If dan Else yang lebih akrab. Sayang sekali bahwa mereka tidak - mungkin mereka akan memberikan tumpangan.

Tantangan kerja tim . Jika Anda memiliki tim besar, atau proyek besar, untuk sejumlah besar lingkungan, atau keduanya, Terraform akan menjadi sulit bagi Anda untuk digunakan tanpa menggunakan beberapa CI.

CI . , , , — merge, . .

, . . , , Terraform , , tfstate Terraform : «, , ». , , .

Ketika Anda memiliki CI, ada beberapa entitas tunggal, misalnya, dalam wadah pipa Anda - Anda memastikan sendiri bahwa Anda tidak akan memiliki versi seperti itu di sekitar utilitas.

Dan akhirnya, kode yang rusak atau tidak terpakai dapat menumpuk di wizard. Setiap kali Anda akan terlalu malas dari tempat Anda untuk menunggu sampai rencana untuk seluruh lingkungan dibangun. Anda akan sampai pada titik mencoba membangun melalui opsi target aplikasi hanya pada apa yang Anda ubah. Misalnya, Anda menambahkan beberapa instance dan berkata: "Terraform apply target instance", atau grup keamanan. Tetapi dalam kasus ini, jika sesuatu rusak (misalnya, beberapa konfigurasi sudah usang), Anda akan melihatnya ketika membangun paket lengkap.

Anda harus menghabiskan banyak usaha dan waktu untuk memperbarui ini. Tidak perlu membahas ini. Jika ada CI - di dalamnya kami hanya dengan paksa mengatakan bahwa Terraform akan membangun rencana sepenuhnya, Anda mendorong perubahan. Dan biarkan dia membangun rencananya, Anda pergi dan melakukan sesuatu yang lain. Dia membangunnya, Anda melihatnya, Anda memilikinya dalam bentuk artefak, dan Anda pergi untuk menerapkannya. Itu disiplin.

Terraform bukan peluru perak


Apa yang tidak akan dia izinkan Anda lakukan:

  • Terraform , . , , . , , , . , , , .

    , — Tfstate, , . . « , » — .

    , -, , - — . , . , — .
  • Terraform , . Terraform . Mengapa , . . , , AZ - -. , North Virginia, 6 . . , , : «, ». — . — , , Terraform .
  • Terraform . , — 200 , 198 , 5. . , API . Sayang
  • , . , S3 bucket. , — , - . Terraform – , , : «, - ». . - , .

, Terraform — , . , .

Source: https://habr.com/ru/post/id470543/


All Articles