Pelajaran yang diperoleh dari pengujian Lebih dari 200.000 baris Kode Infrastruktur


IaC (Infrastructure as Code) adalah pendekatan modern dan saya percaya bahwa infrastruktur adalah kode. Ini berarti bahwa kita harus menggunakan filosofi yang sama untuk infrastruktur seperti untuk pengembangan perangkat lunak. Jika kita berbicara bahwa infrastruktur adalah kode, maka kita harus menggunakan kembali praktik dari pengembangan untuk infrastruktur, yaitu pengujian unit, pemrograman pasangan, tinjauan kode. Harap ingat ide ini saat membaca artikel.


Versi Rusia


Ini adalah terjemahan dari pidato saya ( video RU ) di DevopsConf 2019-05-28 .



Infrastruktur sebagai bash history



Mari kita bayangkan bahwa Anda sedang berada dalam suatu proyek dan Anda mendengar sesuatu seperti: "Kami menggunakan Infrastruktur sebagai pendekatan Kode ". Sayangnya, yang mereka maksud adalah Infrastruktur sebagai bash history atau Dokumentasi sebagai bash history . Ini hampir merupakan situasi nyata. Sebagai contoh, Denis Lysenko menggambarkan situasi ini dalam pidatonya Cara mengganti infrastruktur dan berhenti mengkhawatirkan (RU) . Denis berbagi cerita tentang bagaimana mengubah sejarah bash menjadi infrastruktur kelas atas.


Mari kita periksa definisi kode sumber: a text listing of commands to be compiled or assembled into an executable computer program . Jika mau, kami dapat menyajikan Infrastruktur sebagai kode bash history like. Ini adalah teks & daftar perintah. Ini menjelaskan bagaimana server dikonfigurasi. Apalagi itu adalah:


  1. Reproducible : Anda bisa mendapatkan bash history, menjalankan perintah dan mungkin mendapatkan infrastruktur yang berfungsi.
  2. Versi : Anda tahu siapa yang masuk, kapan dan apa yang dilakukan.
    Sayangnya, jika Anda kehilangan server, Anda tidak dapat melakukan apa-apa karena tidak ada bash history, Anda kehilangan itu dengan server.

Apa yang harus dilakukan?


Infrastruktur sebagai kode



Di satu sisi, kasus abnormal ini, Infrastruktur sebagai bash history , dapat disajikan sebagai Infrastruktur sebagai Kode , tetapi di sisi lain, jika Anda ingin melakukan sesuatu yang lebih kompleks daripada server LAMP, Anda harus mengelola, memelihara, dan memodifikasi kode . Mari kita ngobrol tentang paralel antara Infrastruktur sebagai pengembangan Kode dan pengembangan perangkat lunak.


KERING



Kami sedang mengembangkan SDS (penyimpanan yang ditentukan perangkat lunak). SDS terdiri dari OS kustom distributif, server kelas atas, banyak logika bisnis, sehingga harus menggunakan perangkat keras nyata. Secara berkala, ada sub-tugas menginstal SDS . Sebelum menerbitkan rilis baru, kami harus menginstal dan memeriksa. Pada awalnya, itu tampak seperti tugas yang sangat sederhana:


  • SSH menjadi tuan rumah dan menjalankan perintah.
  • SCP file.
  • Ubah konfigurasi.
  • Jalankan layanan.
  • ...
  • KEUNTUNGAN!

Saya percaya bahwa Make CM, bukan bash adalah pendekatan yang baik. Namun, bash hanya digunakan dalam kasus yang ekstrem dan terbatas, seperti pada awal proyek. Jadi, bash adalah pilihan yang cukup bagus dan masuk akal di awal proyek. Waktu terus berjalan. Kami menghadapi berbagai permintaan untuk membuat instalasi baru dalam konfigurasi yang sedikit berbeda. Kami SSHing ke instalasi, dan menjalankan perintah untuk menginstal semua perangkat lunak yang diperlukan, mengedit file konfigurasi dengan skrip dan, akhirnya, mengkonfigurasi SDS melalui API sisa HTTP Web. Lagi pula instalasi itu sudah dikonfigurasi dan berfungsi. Ini adalah praktik yang cukup umum, tetapi ada banyak skrip bash dan logika instalasi menjadi lebih kompleks setiap hari.


Sayangnya, setiap skrip seperti kepingan salju kecil tergantung pada siapa yang menyalinnya. Itu juga sangat menyakitkan ketika kami membuat atau menciptakan kembali instalasi.


Saya harap Anda sudah mendapat ide utama, bahwa pada tahap ini kami harus terus-menerus mengubah logika skrip hingga layanan OK. Tapi, ada solusi untuk itu. Itu KERING



Ada pendekatan KERING (Jangan Ulangi Diri Sendiri). Gagasan utamanya adalah menggunakan kembali kode yang sudah ada. Kedengarannya sangat sederhana. Dalam kasus kami, KERING artinya: pisahkan konfigurasi dan skrip.


SOLID untuk CFM



Proyek itu berkembang, sebagai hasilnya, kami memutuskan untuk menggunakan Ansible. Ada beberapa alasan untuk itu:


  1. Bash seharusnya tidak mengandung logika kompleks .
  2. Kami memiliki sejumlah keahlian dalam Ansible.

Ada sejumlah logika bisnis di dalam kode Ansible. Ada pendekatan untuk meletakkan berbagai hal dalam kode sumber selama proses pengembangan perangkat lunak. Ini disebut SOLID . Dari sudut pandang saya, kita dapat menggunakan kembali SOLID untuk Infrastruktur sebagai Kode . Biarkan saya jelaskan langkah demi langkah.


Prinsip Tanggung Jawab Tunggal



Kelas seharusnya hanya memiliki satu tanggung jawab, yaitu, hanya perubahan pada satu bagian dari spesifikasi perangkat lunak yang dapat mempengaruhi spesifikasi kelas.


Anda tidak boleh membuat Kode Spaghetti di dalam kode infrastruktur Anda. Infrastruktur Anda harus dibuat dari batu bata sederhana yang dapat diprediksi. Dengan kata lain, mungkin ide yang baik untuk membagi buku pedoman Ansible yang sangat besar menjadi peran Ansible yang independen. Akan lebih mudah dirawat.


Prinsip terbuka-tertutup



Entitas perangkat lunak ... harus terbuka untuk ekstensi, tetapi ditutup untuk modifikasi.


Pada awalnya, kami menyebarkan SDS di mesin virtual, sedikit kemudian kami menambahkan penyebaran ke server bare metal . Kami telah melakukannya. Itu semudah pie bagi kami karena kami baru saja menambahkan implementasi untuk bagian khusus bare metal tanpa memodifikasi logika instalasi SDS.


Prinsip Substitusi Liskov



Objek dalam suatu program harus diganti dengan instance subtipe mereka tanpa mengubah kebenaran program itu.


Mari kita berpikiran terbuka. SOLID mungkin digunakan dalam CFM secara umum, itu bukan proyek yang beruntung. Saya ingin menggambarkan proyek lain. Ini adalah solusi out of box enterprise. Ini mendukung berbagai basis data, server aplikasi dan antarmuka integrasi dengan sistem pihak ketiga. Saya akan menggunakan contoh ini untuk menggambarkan sisa SOLID


Misalnya dalam kasus kami, ada kesepakatan di dalam tim infrastruktur: jika Anda menggunakan ibm java role atau oracle java atau openjdk, Anda akan memiliki java binary yang dapat dieksekusi. Kami membutuhkannya karena tingkat atas * Peran yang dimungkinkan bergantung pada itu. Juga, ini memungkinkan kita untuk menukar implementasi java tanpa memodifikasi logika pemasangan aplikasi.


Sayangnya, tidak ada gula sintaks untuk itu di buku pedoman Ansible. Ini berarti bahwa Anda harus mengingatnya sambil mengembangkan peran yang Mungkin.


Prinsip Pemisahan Antarmuka



Banyak antarmuka khusus klien lebih baik dari satu antarmuka tujuan umum.


Pada awalnya, kami menempatkan logika instalasi aplikasi ke dalam buku pedoman tunggal, kami mencoba untuk menutupi semua kasus dan memotong ujungnya. Kami telah menghadapi masalah yang sulit untuk dipertahankan, jadi kami mengubah pendekatan kami. Kami memahami bahwa klien membutuhkan antarmuka dari kami (yaitu https di port 443) dan kami dapat menggabungkan peran Ansible kami untuk setiap lingkungan spesifik.


Prinsip Pembalikan Ketergantungan



Seseorang harus "bergantung pada abstraksi, [bukan] konkret."


  • Modul tingkat tinggi tidak harus bergantung pada modul tingkat rendah. Keduanya harus bergantung pada abstraksi (misalnya antarmuka).
  • Abstraksi tidak harus bergantung pada detail. Detail (implementasi konkret) harus bergantung pada abstraksi.

Saya ingin menjelaskan prinsip ini melalui anti-pola.


  1. Ada pelanggan dengan cloud pribadi.
  2. Kami meminta VM di cloud.
  3. Logika penerapan kami bergantung pada hypervisor mana VM berada.

Dengan kata lain, kami tidak dapat menggunakan kembali IaC kami di cloud lain karena logika penggunaan tingkat atas bergantung pada implementasi tingkat yang lebih rendah. Tolong jangan lakukan itu


Interaksi



Infrastruktur bukan hanya kode, ini juga tentang kode interaksi <-> DevOps, DevOps <-> DevOps, IaC <-> orang.


Faktor bus



Mari kita bayangkan, ada insinyur DevOps John. John tahu segalanya tentang infrastruktur Anda. Jika John ditabrak bus, apa yang akan terjadi dengan infrastruktur Anda? Sayangnya, ini hampir merupakan kasus nyata. Beberapa waktu terjadi sesuatu. Jika itu terjadi dan Anda tidak berbagi pengetahuan tentang IaC, Infrastruktur di antara anggota tim Anda, Anda akan menghadapi banyak konsekuensi yang tidak terduga & canggung. Ada beberapa pendekatan untuk mengatasinya. Mari kita ngobrol tentang mereka.


Pasangkan DevOpsing



Ini seperti pemrograman pasangan. Dengan kata lain, ada dua insinyur DevOps dan mereka menggunakan laptop \ keyboard tunggal untuk mengkonfigurasi infrastruktur: mengkonfigurasi server, membuat peran yang memungkinkan, dll. Kedengarannya hebat, bagaimanapun, itu tidak berhasil untuk kita. Ada beberapa kasus khusus ketika sebagian berfungsi.


  • Onboarding : Mentor & orang baru mendapatkan tugas nyata dari jaminan dan bekerja bersama - mentransfer pengetahuan dari mentor ke orang tersebut.
  • Panggilan Insiden : Selama pemecahan masalah, ada sekelompok insinyur, mereka mencari solusi. Poin kuncinya adalah ada orang yang memimpin insiden ini. Orang tersebut membagikan layar & ide. Orang lain dengan hati-hati mengikutinya dan memperhatikan trik bash, kesalahan, log parsing dll.

Ulasan kode



Dari sudut pandang saya, tinjauan Kode adalah salah satu cara paling efisien untuk berbagi pengetahuan di dalam tim tentang infrastruktur Anda. Bagaimana cara kerjanya?


  • Ada repositori yang berisi deskripsi infrastruktur Anda.
  • Setiap orang melakukan perubahan di cabang khusus.
  • Saat permintaan penggabungan, Anda dapat meninjau delta perubahan infrastruktur Anda.

Yang paling menarik adalah kami memutar resensi. Ini berarti bahwa setiap beberapa hari kami memilih resensi baru dan pengulas melihat semua permintaan penggabungan. Akibatnya, secara teoritis, setiap orang harus menyentuh bagian baru dari infrastruktur dan memiliki pengetahuan rata-rata tentang infrastruktur kami secara umum.


Gaya Kode



Waktu terus berjalan, kami terkadang berdebat selama peninjauan karena peninjau dan committer mungkin menggunakan gaya kode yang berbeda: 2 spasi atau 4, camelCase atau snake_case . Kami menerapkannya, tapi itu bukan piknik.


  • Gagasan pertama adalah merekomendasikan menggunakan linter. Setiap orang memiliki lingkungan pengembangannya sendiri: IDE, OS ... sulit untuk menyinkronkan & menyatukan semuanya.
  • Idenya berkembang menjadi bot kendur. Setelah setiap komit, bot sedang memeriksa kode sumber & mendorong ke pesan slack dengan daftar masalah. Sayangnya, dalam sebagian besar kasus, tidak ada perubahan kode sumber setelah pesan.

Tuan bangunan hijau



Selanjutnya, langkah paling menyakitkan adalah membatasi mendorong ke cabang master untuk semua orang. Hanya melalui permintaan gabungan & uji hijau harus ok. Ini disebut Green Build Master . Dengan kata lain, Anda 100% yakin bahwa Anda dapat menggunakan infrastruktur Anda dari cabang utama. Ini adalah praktik yang cukup umum dalam pengembangan perangkat lunak:


  • Ada repositori yang berisi deskripsi infrastruktur Anda.
  • Setiap orang melakukan perubahan di cabang khusus.
  • Untuk setiap cabang, kami menjalankan tes.
  • Anda tidak dapat bergabung ke cabang master jika tes gagal.

Itu adalah keputusan yang sulit. Semoga, sebagai hasil selama proses peninjauan, tidak ada perdebatan tentang gaya kode dan jumlah bau kode berkurang.


Pengujian IaC



Selain memeriksa gaya kode, Anda dapat memeriksa apakah Anda dapat menggunakan atau menciptakan kembali infrastruktur Anda di kotak pasir. Untuk apa Ini adalah pertanyaan yang rumit dan saya ingin membagikan sebuah cerita alih-alih jawaban. Itu adalah scaler otomatis khusus untuk AWS yang ditulis dalam Powershell. Auto-scaler tidak memeriksa edge input untuk param input, sebagai hasilnya, ia menciptakan banyak mesin virtual dan pelanggan tidak senang. Ini adalah situasi yang canggung, mudah-mudahan, mungkin untuk menangkapnya pada tahap paling awal.


Di satu sisi, dimungkinkan untuk menguji skrip & infrastruktur, tetapi di sisi lain, Anda meningkatkan jumlah kode dan membuat infrastruktur lebih kompleks. Namun, alasan sebenarnya untuk itu adalah karena Anda menempatkan pengetahuan Anda tentang infrastruktur untuk pengujian. Anda menggambarkan bagaimana hal-hal seharusnya bekerja bersama.


IaC Menguji Piramida



Pengujian IaC: Analisis Statis


Anda dapat membuat seluruh infrastruktur dari awal untuk setiap komit, tetapi, biasanya, ada beberapa kendala:


  • Harganya stratosfer.
  • Itu membutuhkan banyak waktu.

Semoga ada beberapa trik. Anda harus memiliki banyak tes sederhana, cepat, primitif di yayasan Anda.


Bash itu rumit


Mari kita lihat contoh yang sangat sederhana. Saya ingin membuat skrip cadangan:


  • Dapatkan semua file dari direktori saat ini.
  • Salin file ke direktori lain dengan nama yang dimodifikasi.

Ide pertama adalah:


 for i in * ; do cp $i /some/path/$i.bak done 

Cukup bagus. Namun, bagaimana jika nama file mengandung spasi ? Kami adalah orang pintar, kami menggunakan kutipan:


 for i in * ; do cp "$i" "/some/path/$i.bak" done 

Apakah kita sudah selesai? Tidak! Bagaimana jika direktori tersebut kosong? Globing gagal dalam kasus ini.


 find . -type f -exec mv -v {} dst/{}.bak \; 

Sudahkah kita selesai? Belum ... Kami lupa bahwa nama file mungkin mengandung \n karakter.


 touch x mv x "$(printf "foo\nbar")" find . -type f -print0 | xargs -0 mv -t /path/to/target-dir 

Alat analisis statis


Anda dapat menangkap beberapa masalah dari contoh sebelumnya melalui Shellcheck . Ada banyak alat seperti itu, mereka disebut linter dan Anda dapat menemukan yang paling cocok untuk IDE, stack, dan lingkungan Anda.


BahasaAlat
bashShellcheck
RubyRubocop
ular sancaPylint
MungkinSerat yang memungkinkan

Pengujian IaC: Tes Unit



Seperti yang Anda lihat, linter tidak bisa menangkap semuanya, mereka hanya bisa memprediksi. Jika kita terus memikirkan persamaan antara pengembangan perangkat lunak dan Infrastruktur sebagai Kode, kita harus menyebutkan uji unit. Ada banyak sistem unit test seperti shunit , JUnit , RSpec , pytest . Tetapi apakah Anda pernah mendengar tentang unit test untuk Ansible, Chef, Saltstack, CFengine?


Ketika kami berbicara tentang SOLID untuk CFM, saya menyebutkan bahwa infrastruktur kami harus dibuat dari batu bata / modul sederhana. Sekarang waktunya telah tiba:


  1. Pisahkan infrastruktur menjadi modul / istirahat sederhana, mis. Peran yang dimungkinkan.
  2. Buat lingkungan yaitu Docker atau VM.
  3. Terapkan satu istirahat / modul sederhana Anda ke lingkungan.
  4. Periksa apakah semuanya baik-baik saja atau tidak.
    ...
  5. KEUNTUNGAN!

IaC Testing: Alat Unit Testing


Apa tes untuk CFM dan infrastruktur Anda? yaitu Anda hanya dapat menjalankan skrip atau Anda dapat menggunakan solusi siap produksi seperti:


CFMAlat
MungkinTestinfra
KokiInspec
KokiServerspec
tumpukan garamGoss

Mari kita lihat testinfra, saya ingin memeriksa bahwa pengguna test1 , test2 ada dan mereka adalah bagian dari kelompok sshusers :


 def test_default_users(host): users = ['test1', 'test2' ] for login in users: assert host.user(login).exists assert 'sshusers' in host.user(login).groups 

Apa solusi terbaik? Tidak ada jawaban tunggal untuk pertanyaan itu, namun, saya membuat peta panas dan membandingkan perubahan dalam proyek ini selama 2018-2019:



Kerangka Pengujian IaC


Setelah itu, Anda bisa menghadapi pertanyaan bagaimana menjalankannya bersama? Di satu sisi, Anda dapat melakukan semuanya sendiri jika Anda memiliki cukup insinyur hebat, tetapi di sisi lain, Anda dapat menggunakan solusi siap-pakai opensource:


CFMAlat
MungkinMolekul
KokiDapur uji
Bentuk TerraTerratest

Saya membuat peta panas dan membandingkan perubahan dalam proyek ini selama 2018-2019:



Molekul vs Testkitchen



Pada awalnya, kami mencoba menguji peran yang mungkin melalui testkitchen di dalam hyper-v :


  1. Buat VM.
  2. Terapkan peran yang Mungkin.
  3. Jalankan Inspec.

Butuh 40-70 menit untuk 25-35 Peran yang mungkin. Itu terlalu lama bagi kami.



Langkah selanjutnya adalah menggunakan Jenkins / docker / Ansible / molekul. Itu kira-kira ide yang sama:


  1. Buku pedoman Lint Ansible.
  2. Lint peran yang mungkin.
  3. Jalankan wadah buruh pelabuhan.
  4. Terapkan peran yang Mungkin.
  5. Jalankan testinfra.
  6. Periksa idempotensi.


Mengintip untuk 40 peran dan menguji sepuluh dari mereka membutuhkan waktu sekitar 15 menit.



Apa solusi terbaik? Di satu sisi, saya tidak ingin menjadi otoritas terakhir, tetapi di sisi lain, saya ingin berbagi pandangan saya. Tidak ada peluru perak yang ada, namun, jika molekul Ansible adalah solusi yang lebih cocok maka uji dapur.


Pengujian IaC: Tes Integrasi



Pada tingkat berikutnya piramida uji IaC , ada tes integrasi . Tes integrasi untuk infrastruktur terlihat seperti tes unit:


  1. Pisahkan infrastruktur menjadi modul / istirahat sederhana, mis. Peran yang dimungkinkan.
  2. Buat lingkungan yaitu Docker atau VM.
  3. Terapkan kombinasi istirahat sederhana / modul ke lingkungan.
  4. Periksa apakah semuanya baik-baik saja atau tidak.
    ...
  5. KEUNTUNGAN!

Dengan kata lain, selama pengujian unit, kami memeriksa satu modul sederhana (yaitu peran yang mungkin, skrip python, modul yang mungkin, dll) dari suatu infrastruktur, tetapi dalam kasus pengujian integrasi, kami memeriksa seluruh konfigurasi server.


Pengujian IaC: Tes ujung ke ujung



Di atas piramida uji IaC , ada Tes ujung ke ujung . Dalam hal ini, kami tidak memeriksa server khusus, skrip, modul infrastruktur kami; Kami memeriksa seluruh infrastruktur bekerja dengan baik. Sayangnya, tidak ada solusi di luar kotak untuk itu atau saya belum pernah mendengar tentang mereka (tolong, tandai saya jika Anda tahu tentang mereka). Biasanya, orang menemukan kembali roda, karena, ada permintaan dari ujung ke ujung tes untuk infrastruktur. Jadi, saya ingin membagikan pengalaman saya, semoga bermanfaat bagi seseorang.



Pertama-tama, saya ingin menggambarkan konteksnya. Ini adalah solusi di luar kotak perusahaan, mendukung database yang berbeda, server aplikasi dan antarmuka integrasi dengan sistem pihak ketiga. Biasanya, klien kami adalah perusahaan besar dengan lingkungan yang sangat berbeda. Kami memiliki pengetahuan tentang kombinasi lingkungan yang berbeda dan kami menyimpannya sebagai file pembuatan docker yang berbeda. Juga, ada yang cocok antara file dan pengujian yang disusun oleh buruh pelabuhan, kami menyimpannya sebagai pekerjaan Jenkins.



Skema ini telah berfungsi dengan tenang saat periode log ketika selama penelitian openshift kami mencoba untuk memigrasikannya ke dalam openshift. Kami menggunakan wadah yang kira-kira sama (neraka KERING lagi) dan hanya mengubah lingkungan sekitarnya.



Kami terus meneliti dan menemukan APB (Ansible Playbook Bundle). Ide utamanya adalah Anda mengemas semua barang yang dibutuhkan ke dalam wadah dan menjalankannya di dalam OpenShift. Ini berarti bahwa Anda memiliki solusi yang dapat direproduksi dan dapat diuji.



Semuanya baik-baik saja sampai kami menghadapi satu masalah lagi: kami harus memelihara infrastruktur yang heterogen untuk lingkungan pengujian. Sebagai hasilnya, kami menyimpan pengetahuan kami tentang cara membuat infrastruktur dan menjalankan tes di pekerjaan Jenkins.


Kesimpulan



Infrastruktur sebagai Kode itu adalah kombinasi dari:


  • Kode
  • Interaksi orang.
  • Pengujian infrastruktur.

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


All Articles