Menyusun Deployment Manager untuk digunakan dalam skala besar

Saat sistem "Infrastruktur sebagai kode" tumbuh melampaui contoh "Halo Dunia" tanpa perencanaan, kode cenderung menjadi tidak terstruktur. Konfigurasi yang tidak terencana di-hardcode. Kemudahan pemeliharaan turun drastis.

Gunakan dokumen ini, beserta contoh kode yang menyertainya, untuk menyusun deployment Anda dengan lebih efisien dan dalam skala besar.

Selain itu, terapkan konvensi penamaan dan praktik terbaik internal di seluruh tim Anda. Dokumen ini ditujukan untuk audience tingkat lanjut secara teknis, dan mengasumsikan bahwa Anda memiliki pemahaman dasar tentang Python, infrastruktur Google Cloud, Deployment Manager, dan, secara umum, Infrastructure as Code.

Sebelum memulai

  • Jika Anda ingin menggunakan contoh command line dalam panduan ini, instal alat command line`gcloud`.
  • Jika Anda ingin menggunakan contoh API dalam panduan ini, siapkan akses API.

Beberapa lingkungan dengan satu codebase

Untuk deployment besar dengan lebih dari selusin resource, praktik terbaik standar meminta Anda untuk menggunakan sejumlah besar properti eksternal (parameter konfigurasi), sehingga Anda dapat menghindari string dan logika hardcode ke template generik. Banyak dari properti ini diduplikasi sebagian karena lingkungan yang serupa, seperti lingkungan pengembangan, pengujian, atau produksi, dan layanan serupa. Misalnya, semua layanan standar berjalan pada stack LAMP yang serupa. Dengan mengikuti praktik terbaik ini, Anda akan menghasilkan kumpulan besar properti konfigurasi dengan banyak duplikasi yang tinggi dan sulit dikelola, sehingga meningkatkan kemungkinan kesalahan manusia.

Tabel berikut adalah contoh kode untuk menggambarkan perbedaan antara hierarki dan konfigurasi tunggal per deployment. Tabel ini menyoroti duplikasi umum dalam konfigurasi tunggal. Dengan menggunakan konfigurasi hierarkis, tabel ini menunjukkan cara memindahkan bagian berulang ke level yang lebih tinggi dalam hierarki untuk menghindari pengulangan dan mengurangi kemungkinan kesalahan manusia.

Template Konfigurasi hierarkis tanpa redundansi Konfigurasi tunggal dengan redundansi

project_config.py

config = { 'ProjectId': 'qwerty123456', 'ProjectOwner': 'Bob', 'ProjectAbbrevation': 'SNP' }

T/A

frontend_config.py

config = {'ServiceName': 'frontend'}

config = { 'ProjectId': 'qwerty123456', 'ProjectOwner': 'Bob', 'ProjectAbbrevation': 'SNP', 'ServiceName': 'frontend' }

backend_config.py

config = {'ServiceName': 'backend'}

config = { 'ProjectId': 'qwerty123456', 'ProjectOwner': 'Bob', 'ProjectAbbrevation': 'SNP', 'ServiceName': 'backend' }

db_config.py

config = {'ServiceName': 'db'}

config = { 'ProjectId': 'qwerty123456', 'ProjectOwner': 'Bob', 'ProjectAbbrevation': 'SNP', 'ServiceName': 'db' }

Untuk menangani codebase besar dengan lebih baik, gunakan tata letak hierarkis terstruktur dengan penggabungan properti konfigurasi secara bertingkat. Untuk melakukannya, Anda menggunakan banyak file untuk konfigurasi, bukan hanya satu. Selain itu, Anda akan bekerja dengan fungsi bantuan dan membagikan sebagian codebase ke seluruh organisasi.

Contoh kode yang menyertai dokumen ini, Organization_with_departments, berisi codebase dengan struktur yang telah ditentukan tetapi dapat disesuaikan, skrip helper untuk menggabungkan konfigurasi, fungsi bantuan untuk penamaan, dan kumpulan lengkap contoh konfigurasi. Anda dapat menemukan contoh yang berfungsi ini di repositori GitHub contoh Deployment Manager.

Penyusunan dan penurunan kode secara hierarkis menawarkan beberapa manfaat:

  • Dengan membagi konfigurasi menjadi beberapa file, Anda akan meningkatkan struktur dan keterbacaan properti. Anda juga menghindari duplikasinya.
  • Anda mendesain penggabungan hierarkis untuk mengalirkan nilai secara logis, membuat file konfigurasi tingkat atas yang dapat digunakan kembali di seluruh project atau komponen.
  • Anda hanya perlu menentukan setiap properti sekali (selain penimpaan), sehingga tidak perlu menangani spasi nama dalam nama properti.
  • Template Anda tidak perlu mengetahui lingkungan yang sebenarnya, karena konfigurasi yang sesuai dimuat berdasarkan variabel yang sesuai.

Menyusun codebase Anda secara hierarkis

Deployment Deployment Manager berisi konfigurasi YAML atau file skema, beserta beberapa file Python. Bersama-sama, file-file ini membentuk codebase deployment. File Python dapat memiliki fungsi yang berbeda. Anda dapat menggunakan file Python sebagai template deployment, sebagai file kode umum (class helper), atau sebagai file kode yang menyimpan properti konfigurasi.

Untuk membuat struktur codebase secara hierarkis, Anda menggunakan beberapa file Python sebagai file konfigurasi, bukan file konfigurasi standar. Pendekatan ini memberi Anda fleksibilitas yang lebih besar daripada menautkan deployment ke satu file YAML.

Memperlakukan infrastruktur Anda sebagai kode nyata

Prinsip penting untuk kode yang bersih adalah Don't Repeat Yourself (DRY)). Tentukan semuanya sekali saja. Pendekatan ini membuat codebase lebih bersih, lebih mudah ditinjau dan divalidasi, serta lebih mudah dikelola. Jika properti hanya perlu diubah di satu tempat, risiko kesalahan manusia akan berkurang.

Untuk codebase yang lebih ringan dengan file konfigurasi yang lebih kecil dan duplikasi yang minimal, gunakan panduan ini untuk membuat struktur konfigurasi agar mengikuti prinsip DRY.

Organisasi, departemen, lingkungan, dan modul

Prinsip dasar untuk menata struktur codebase Anda secara bersih dan hierarkis adalah menggunakan organisasi, departemen, lingkungan, dan modul. Prinsip ini bersifat opsional dan dapat diperluas. Untuk diagram hierarki contoh codebase yang mengikuti prinsip-prinsip ini, lihat hierarki konfigurasi.

Dalam diagram berikut, modul di-deploy di lingkungan. Penggabungan konfigurasi akan memilih file konfigurasi yang sesuai di setiap level berdasarkan konteks tempat file tersebut digunakan. {i>Metadata<i} secara otomatis juga menentukan sistem dan departemen.

Modul yang di-deploy di lingkungan

Dalam daftar berikut, angka-angka tersebut menunjukkan urutan penimpaan:

  1. Properti organisasi

    Ini adalah level tertinggi dalam struktur Anda. Di level ini, Anda dapat menyimpan properti konfigurasi seperti organization_name, organization_abbreviation, yang digunakan dalam konvensi penamaan Anda, serta fungsi bantuan yang ingin dibagikan dan diterapkan ke seluruh tim.

  2. Properti departemen

    Organisasi berisi departemen, jika Anda memiliki departemen di struktur. Di setiap file konfigurasi departemen, bagikan properti yang tidak digunakan oleh departemen lain, misalnya, department_name atau cost_center.

  3. Properti sistem (project)

    Setiap departemen berisi sistem. Sistem adalah tumpukan software yang didefinisikan dengan baik, misalnya, platform e-commerce Anda. Project ini bukan project Google Cloud, melainkan ekosistem layanan yang berfungsi.

    Di tingkat sistem, tim Anda memiliki lebih banyak otonomi daripada di tingkat di atasnya. Di sini, Anda dapat menentukan fungsi bantuan (seperti project_name_generator(), instance_name_generator(), atau instance_label_generator()) untuk parameter tim dan seluruh sistem (misalnya, system_name, default_instance_size, atau naming_prefix).

  4. Properti lingkungan

    Sistem Anda mungkin memiliki beberapa lingkungan, seperti Dev, Test, atau Prod (dan, jika perlu, QA dan Staging), yang cukup mirip satu sama lain. Idealnya, keduanya menggunakan codebase yang sama, dan hanya berbeda pada tingkat konfigurasi. Pada tingkat lingkungan, Anda dapat menimpa properti seperti default_instance_size untuk konfigurasi Prod dan QA.

  5. Properti Modul

    Jika sistem Anda besar, bagi sistem menjadi beberapa modul, bukan menyimpannya sebagai satu blok monolitik besar. Anda dapat, misalnya, memindahkan jaringan dan keamanan inti ke dalam blok yang terpisah. Anda juga dapat memisahkan lapisan backend, frontend, dan database ke dalam modul terpisah. Modul adalah template yang dikembangkan oleh pihak ketiga, yang Anda gunakan untuk menambahkan konfigurasi yang sesuai saja. Pada level modul, Anda dapat menentukan properti yang relevan hanya untuk modul tertentu, termasuk properti yang didesain untuk menimpa properti level sistem yang diwarisi. Tingkat lingkungan dan modul adalah divisi paralel dalam sistem, tetapi modul mengikuti lingkungan dalam proses penggabungan.

  6. Properti modul khusus lingkungan

    Beberapa properti modul Anda mungkin juga bergantung pada lingkungannya, misalnya ukuran instance, image, endpoint. Properti modul khusus lingkungan adalah tingkat yang paling spesifik, dan poin terakhir dalam penggabungan bertingkat untuk menimpa nilai yang ditentukan sebelumnya.

Class helper untuk menggabungkan konfigurasi

Class config_merger adalah class helper yang otomatis memuat file konfigurasi yang sesuai dan menggabungkan kontennya menjadi satu kamus.

Untuk menggunakan class config_merger, Anda harus memberikan informasi berikut:

  • Nama modul.
  • Konteks global, yang berisi nama lingkungan.

Memanggil fungsi statis ConfigContext akan menampilkan kamus konfigurasi gabungan.

Kode berikut menunjukkan cara menggunakan class ini:

  • module = "frontend" menentukan konteks, tempat file properti dimuat.
  • Lingkungan secara otomatis diambil dari context.properties["envName"].
  • Konfigurasi global.

    cc = config_merger.ConfigContext(context.properties, module)
    
    print cc.configs['ServiceName']
    

Di balik layar, class helper ini harus menyelaraskan dengan struktur konfigurasi Anda, memuat semua level dalam urutan yang benar, dan menimpa nilai konfigurasi yang sesuai. Untuk mengubah level atau urutan penimpaan, Anda dapat mengubah class penggabung konfigurasi.

Dalam penggunaan sehari-hari dan rutin, Anda biasanya tidak perlu menyentuh class ini. Biasanya, Anda mengedit template dan file konfigurasi yang sesuai, lalu menggunakan kamus output bersama semua konfigurasi di dalamnya.

Contoh codebase berisi tiga file konfigurasi hardcode berikut:

  • org_config.py
  • department_config.py
  • system_config.py

Anda dapat membuat file konfigurasi organisasi dan departemen sebagai link simbolis selama inisiasi repositori. File ini dapat berada di repositori kode terpisah, karena secara logis bukan bagian dari codebase tim project, tetapi dibagikan ke seluruh organisasi dan departemen.

Penggabungan konfigurasi juga mencari file yang cocok dengan level struktur Anda yang tersisa:

  • envs/[environment name].py
  • [environment name]/[module name].py
  • modules/[module name].py

File konfigurasi

Deployment Manager menggunakan satu file konfigurasi, yang merupakan satu file untuk deployment tertentu. dan tidak dapat dibagikan di seluruh deployment.

Saat Anda menggunakan class config-merger, properti konfigurasi akan sepenuhnya dilepaskan dari file konfigurasi ini karena Anda tidak menggunakannya. Sebagai gantinya, Anda menggunakan kumpulan file Python, yang memberi Anda lebih banyak fleksibilitas dalam deployment. File-file ini juga dapat dibagikan ke seluruh deployment.

Setiap file Python dapat berisi variabel, sehingga Anda dapat menyimpan konfigurasi dengan cara yang terstruktur, tetapi terdistribusi. Pendekatan terbaik adalah menggunakan kamus dengan struktur yang telah disepakati. Penggabungan konfigurasi akan mencari kamus yang disebut configs di setiap file dalam rantai penggabungan. configs yang terpisah tersebut digabungkan menjadi satu.

Selama penggabungan, jika sebuah properti dengan jalur dan nama yang sama muncul di kamus beberapa kali, penggabungan konfigurasi akan menimpa properti tersebut. Dalam beberapa kasus, perilaku ini berguna, seperti saat nilai default ditimpa oleh nilai spesifik per konteks. Namun, ada banyak kasus lain saat Anda tidak ingin menimpa properti. Untuk mencegah penimpaan properti, tambahkan namespace terpisah ke properti tersebut agar unik. Pada contoh berikut, Anda menambahkan namespace dengan membuat level tambahan dalam kamus konfigurasi, yang akan membuat subkamus.

config = {
    'Zip_code': '1234'
    'Count': '3'
    'project_module': {
        'admin': 'Joe',
    }
}

config = {
    'Zip_code': '5555'
    'Count': '5'
    'project_module_prod': {
        'admin': 'Steve',
    }
}

Class helper dan konvensi penamaan

Konvensi penamaan adalah cara terbaik untuk menjaga agar infrastruktur Deployment Manager Anda tetap terkendali. Anda tidak ingin menggunakan nama yang tidak jelas atau umum, seperti my project atau test instance.

Contoh berikut adalah konvensi penamaan di seluruh organisasi untuk instance:

def getInstanceName(self, name):
  return '-'.join(self.configs['Org_level_configs']['Org_Short_Name'],
                  self.configs['Department_level_configs']['Department_Short_Name'],
                  self.configs['System_short_name'],
                  name,
                  self.configs["envName"])

Menyediakan fungsi bantuan akan memudahkan Anda menamai setiap instance berdasarkan konvensi yang telah disetujui. Hal ini juga memudahkan peninjauan kode karena tidak ada nama instance yang berasal dari mana pun selain fungsi ini. Fungsi ini secara otomatis mengambil nama dari konfigurasi tingkat yang lebih tinggi. Pendekatan ini membantu menghindari input yang tidak diperlukan.

Anda dapat menerapkan konvensi penamaan ini untuk sebagian besar resource Google Cloud dan untuk label. Fungsi yang lebih kompleks bahkan dapat menghasilkan satu set label default.

Struktur folder codebase contoh

Struktur folder codebase contoh fleksibel dan dapat disesuaikan. Namun, kode ini di-hardcode sebagian ke penggabungan konfigurasi dan file skema Deployment Manager. Artinya, jika melakukan modifikasi, Anda harus mencerminkan perubahan tersebut dalam file skema dan penggabungan konfigurasi.

├── global
│   ├── configs
│   └── helper
└── systems
    └── my_ecom_system
        ├── configs
        │   ├── dev
        │   ├── envs
        │   ├── modules
        │   ├── prod
        │   └── test
        ├── helper
        └── templates
    

Folder global berisi file yang dibagikan ke seluruh tim project yang berbeda. Untuk mempermudah, folder konfigurasi berisi konfigurasi organisasi dan semua file konfigurasi departemen. Dalam contoh ini, tidak ada class helper terpisah untuk departemen. Anda dapat menambahkan class helper apa pun di tingkat organisasi atau sistem.

Folder global dapat berada di repositori Git terpisah. Anda dapat merujuk filenya dari setiap sistem. Anda juga dapat menggunakan {i>symbolic link<i}, tetapi mereka dapat menimbulkan kebingungan atau gangguan dalam sistem operasi tertentu.

├── configs
│   ├── Department_Data_config.py
│   ├── Department_Finance_config.py
│   ├── Department_RandD_config.py
│   └── org_config.py
└── helper
    ├── config_merger.py
    └── naming_helper.py

Folder sistem berisi satu atau beberapa sistem yang berbeda. Sistem dipisahkan satu sama lain, dan tidak berbagi konfigurasi.

├── configs
│   ├── dev
│   ├── envs
│   ├── modules
│   ├── prod
│   └── test
├── helper
└── templates

Folder konfigurasi berisi semua file konfigurasi yang unik untuk sistem ini, juga mereferensikan konfigurasi global melalui link simbol.

├── department_config.py -> ../../../global/configs/Department_Data_config.py
├── org_config.py -> ../../../global/configs/org_config.py
├── system_config.py
├── dev
│   ├── frontend.py
│   └── project.py
├── prod
│   ├── frontend.py
│   └── project.py
├── test
│   ├── frontend.py
│   └── project.py
├── envs
│   ├── dev.py
│   ├── prod.py
│   └── test.py
└── modules
    ├── frontend.py
    └── project.py

Org_config.py:

config = {
  'Org_level_configs': {
    'Org_Name': 'Sample Inc.',
    'Org_Short_Name': 'sampl',
    'HQ_Address': {
      'City': 'London',
      'Country': 'UK'
    }
  }
}

Dalam folder helper, Anda dapat menambahkan class helper lebih lanjut dan mereferensikan class global.

├── config_merger.py -> ../../../global/helper/config_merger.py
└── naming_helper.py -> ../../../global/helper/naming_helper.py

Dalam folder template, Anda dapat menyimpan atau mereferensikan template Deployment Manager. Link simbolis juga berfungsi di sini.

├── project_creation -> ../../../../../../examples/v2/project_creation
└── simple_frontend.py

Menggunakan contoh codebase

Cara terbaik untuk mulai menerapkan praktik hierarkis ini sebagai dasar infrastruktur Anda sebagai kode adalah dengan meng-clone codebase contoh dan menyalin konten folder Hierarchy_configuration.

  1. Lihat repositori contoh.

    git clone https://github.com/GoogleCloudPlatform/deploymentmanager-samples.git
    cd deploymentmanager-samples/community/hierarchical_configuration/Organization_with_departments/systems/my_ecom_system
    gcloud config set deployment_manager/glob_imports True
    
  2. Untuk menyiapkan sistem, gunakan link simbolis berikut untuk mereferensikan file global ke konteks lokal.

    ln -sf ../../../global/helper/config_merger.py helper/config_merger.py
    ln -sf ../../../global/helper/naming_helper.py helper/naming_helper.py
    ln -sf ../../../global/configs/org_config.py configs/org_config.py
    
  3. Pilih departemen yang sesuai dari daftar global.

    ln -sf ../../../global/configs/Department_Data_config.py configs/department_config.py
    
  4. Untuk menetapkan konteks lingkungan yang tepat, gunakan flag --properties untuk menentukan properti envName. Properti ini memungkinkan Anda menjalankan kode yang sama, yang menargetkan lingkungan yang berbeda, dengan perintah yang sama. [MY-PROJECT-ID] mewakili project ID dari project Google Cloud Anda sendiri.

    [MY-PROJECT-ID]
    gcloud deployment-manager deployments create hierarchy-org-example-dev
    --template env_demo_project.py --properties=envName:dev
    gcloud deployment-manager deployments create hierarchy-org-example-test
    --template env_demo_project.py --properties=envName:test
    gcloud deployment-manager deployments create hierarchy-org-example-prod
    --template env_demo_project.py --properties=envName:prod
    

Praktik terbaik

Praktik terbaik berikut bisa membantu Anda menyusun kode secara hierarkis.

File skema

Dalam file skema, Deployment Manager harus mencantumkan setiap file yang Anda gunakan dengan cara apa pun selama deployment. Menambahkan seluruh folder akan membuat kode Anda lebih pendek dan lebih umum.

  • Kelas helper:
- path: helper/*.py
  • File konfigurasi:
- path: configs/*.py
- path: configs/*/*.py
  • Impor massal (gaya glob)
gcloud config set deployment_manager/glob_imports True

Beberapa deployment

Ini adalah praktik terbaik bagi sistem untuk memuat beberapa deployment, yang berarti sistem tersebut menggunakan set konfigurasi yang sama, meskipun modulnya berbeda, misalnya jaringan, firewall, backend, frontend. Anda mungkin perlu mengakses output deployment ini dari deployment lain. Anda dapat membuat kueri output deployment setelah siap dan menyimpannya di folder konfigurasi. Anda dapat menambahkan file konfigurasi ini selama proses penggabungan.

Link simbolis didukung oleh perintah gcloud deployment-manager, dan file tertaut dimuat dengan benar. Namun, link simbolis tidak didukung di setiap OS.

Hierarki konfigurasi

Diagram berikut adalah ringkasan mengenai berbagai level dan hubungannya. Setiap persegi panjang merepresentasikan file properti, seperti yang ditunjukkan oleh nama file yang berwarna merah.

Hierarki konfigurasi dengan tingkat dan relasi yang berbeda-beda.

Urutan penggabungan kontekstual

Penggabungan konfigurasi memilih file konfigurasi yang sesuai di setiap level berdasarkan konteks penggunaan setiap file. Konteksnya adalah modul yang Anda deploy dalam lingkungan. Konteks ini menentukan sistem dan departemen secara otomatis.

Dalam diagram berikut, angka-angka tersebut mewakili urutan penimpaan dalam hierarki:

Diagram pesanan penimpaan

Langkah selanjutnya