Menyebarkan aplikasi pada beberapa kluster Kubernet dengan Helm


Bagaimana Dailymotion menggunakan Kubernetes: Penerapan Aplikasi


Kami di Dailymotion mulai menggunakan Kubernetes dalam produksi 3 tahun yang lalu. Tetapi penerapan aplikasi pada banyak kluster masih menyenangkan, jadi dalam beberapa tahun terakhir kami telah mencoba meningkatkan alat dan alur kerja kami.


Di mana itu dimulai


Di sini kami menunjukkan bagaimana kami menyebarkan aplikasi kami di beberapa kluster Kubernetes di seluruh dunia.


Untuk menggunakan beberapa objek Kubernet sekaligus, kami menggunakan Helm , dan semua grafik kami disimpan dalam satu repositori git. Untuk menyebarkan tumpukan aplikasi lengkap dari beberapa layanan, kami menggunakan apa yang disebut bagan umum. Intinya, ini adalah bagan yang menyatakan dependensi dan memungkinkan Anda untuk menginisialisasi API dan layanannya dengan satu perintah.


Kami juga menulis skrip Python kecil di atas Helm untuk melakukan pengecekan, membuat bagan, menambah rahasia dan menyebarkan aplikasi. Semua tugas ini dilakukan pada platform CI pusat menggunakan gambar buruh pelabuhan.


Mari kita langsung ke intinya.


Catatan Ketika Anda membaca ini, kandidat rilis Helm 3 pertama telah diumumkan. Versi utama berisi serangkaian perbaikan yang dirancang untuk memecahkan beberapa masalah yang kami temui di masa lalu.

Alur Kerja Pengembangan Grafik


Untuk aplikasi, kami menggunakan percabangan, dan kami memutuskan untuk menerapkan pendekatan yang sama pada bagan.


  • Cabang dev digunakan untuk membuat grafik yang akan diuji pada kelompok pengembangan.
  • Ketika permintaan kumpulan ditransfer ke master , mereka diperiksa dalam pementasan.
  • Akhirnya, kami membuat permintaan kumpulan untuk mendorong perubahan ke cabang prod dan menerapkannya dalam produksi.

Setiap lingkungan memiliki repositori pribadinya yang menyimpan grafik kami, dan kami menggunakan Chartmuseum dengan API yang sangat berguna. Dengan demikian, kami menjamin isolasi yang ketat antara lingkungan dan memeriksa grafik dalam kondisi nyata sebelum menggunakannya dalam produksi.



Bagan repositori di lingkungan yang berbeda


Perlu dicatat bahwa ketika pengembang mengirim cabang dev, versi bagan mereka secara otomatis dikirim ke dev Chartmuseum. Dengan demikian, semua pengembang menggunakan repositori dev yang sama, dan Anda perlu menunjukkan versi bagan Anda dengan hati-hati agar tidak secara tidak sengaja menggunakan perubahan orang lain.


Selain itu, skrip Python kecil kami memeriksa objek Kubernetes terhadap spesifikasi OpenAPI Kubernetes menggunakan Kubeval sebelum menerbitkannya ke Chartmusem.


Alur Umum Pengembangan Alur Kerja



  1. Menyiapkan tugas pipa sesuai dengan spesifikasi gazr.io untuk kontrol kualitas (lint, unit-test).
  2. Mengirimkan gambar buruh pelabuhan dengan alat Python yang menggunakan aplikasi kami.
  3. Menyiapkan lingkungan dengan nama cabang.
  4. Periksa file yaml Kubernetes dengan Kubeval.
  5. Secara otomatis meningkatkan versi bagan dan bagan induknya (bagan yang bergantung pada bagan yang sedang diubah).
  6. Mengirimkan bagan ke Chartmuseum yang cocok dengan lingkungannya

Manajemen Perbedaan Cluster


Federasi Cluster


Ada saat ketika kami menggunakan Kubernetes Cluster Federation , di mana Anda dapat mendeklarasikan objek Kubernetes dari satu titik akhir API. Tapi ada masalah. Sebagai contoh, beberapa objek Kubernetes tidak dapat dibuat pada titik akhir federasi, sehingga sulit untuk mempertahankan objek gabungan dan objek lain untuk cluster individu.


Untuk menyelesaikan masalah, kami mulai mengelola cluster secara mandiri, yang sangat menyederhanakan prosesnya (kami menggunakan versi federasi pertama; yang kedua, sesuatu dapat berubah).


Platform yang didistribusikan secara geografis


Sekarang platform kami didistribusikan di 6 wilayah - 3 secara lokal dan 3 di cloud.



Penempatan terdistribusi


Nilai-Nilai Helm Global


4 nilai global Helm memungkinkan Anda untuk menentukan perbedaan di antara kluster. Untuk semua grafik kami, ada standar minimum.


global: cloud: True env: staging region: us-central1 clusterName: staging-us-central1 

Nilai global


Nilai-nilai ini membantu menentukan konteks untuk aplikasi kami dan digunakan untuk berbagai tugas: memantau, melacak, mencatat, membuat panggilan eksternal, penskalaan, dll.


  • "Cloud": kami memiliki platform hybrid Kubernetes. Misalnya, API kami digunakan di zona GCP dan di pusat data kami.
  • "Env": beberapa nilai dapat bervariasi untuk lingkungan yang tidak bekerja. Misalnya, definisi sumber daya dan konfigurasi skala otomatis.
  • "Wilayah": informasi ini membantu menentukan lokasi cluster dan dapat digunakan untuk menentukan titik akhir terdekat untuk layanan eksternal.
  • "ClusterName": jika dan kapan kami ingin menentukan nilai untuk masing-masing cluster.

Ini adalah contoh nyata:


 {{/* Returns Horizontal Pod Autoscaler replicas for GraphQL*/}} {{- define "graphql.hpaReplicas" -}} {{- if eq .Values.global.env "prod" }} {{- if eq .Values.global.region "europe-west1" }} minReplicas: 40 {{- else }} minReplicas: 150 {{- end }} maxReplicas: 1400 {{- else }} minReplicas: 4 maxReplicas: 20 {{- end }} {{- end -}} 

Contoh template helm


Logika ini didefinisikan dalam template helper agar tidak menyumbat Kubernetes YAML.


Pengumuman Aplikasi


Alat penyebaran kami didasarkan pada beberapa file YAML. Berikut ini adalah contoh bagaimana kami mendeklarasikan layanan dan topologi penskalaannya (jumlah replika) dalam sebuah cluster.


 releases: - foo.world foo.world: # Release name services: # List of dailymotion's apps/projects foobar: chart_name: foo-foobar repo: git@github.com:dailymotion/foobar contexts: prod-europe-west1: deployments: - name: foo-bar-baz replicas: 18 - name: another-deployment replicas: 3 

Definisi Layanan


Ini adalah diagram dari semua langkah yang menentukan alur kerja penerapan kami. Langkah terakhir menyebarkan aplikasi ke beberapa cluster kerja secara bersamaan.



Langkah Penempatan Jenkins


Bagaimana dengan rahasianya?


Dalam hal keamanan, kami melacak semua rahasia dari berbagai tempat dan menyimpannya di repositori Vault unik di Paris.


Alat penyebaran kami mengekstraksi nilai-nilai rahasia dari Vault dan, ketika waktu penyebaran datang, masukkan mereka ke Helm.


Untuk melakukan ini, kami menentukan pemetaan antara rahasia di Vault dan rahasia yang diperlukan aplikasi kami:


 secrets: - secret_id: "stack1-app1-password" contexts: - name: "default" vaultPath: "/kv/dev/stack1/app1/test" vaultKey: "password" - name: "cluster1" vaultPath: "/kv/dev/stack1/app1/test" vaultKey: "password" 

  • Kami telah mengidentifikasi aturan umum yang harus Anda ikuti saat menulis rahasia ke Vault.
  • Jika rahasianya merujuk pada konteks atau cluster tertentu , Anda perlu menambahkan entri tertentu. (Di sini, konteks cluster1 memiliki nilai sendiri untuk stack-app1-password rahasia).
  • Jika tidak, nilai default digunakan.
  • Untuk setiap item dalam daftar ini, pasangan nilai kunci dimasukkan ke dalam rahasia Kubernetes . Oleh karena itu, pola rahasia dalam bagan kami sangat sederhana.

 apiVersion: v1 data: {{- range $key,$value := .Values.secrets }} {{ $key }}: {{ $value | b64enc | quote }} {{ end }} kind: Secret metadata: name: "{{ .Chart.Name }}" labels: chartVersion: "{{ .Chart.Version }}" tillerVersion: "{{ .Capabilities.TillerVersion.SemVer }}" type: Opaque 

Masalah dan keterbatasan


Bekerja dengan beberapa repositori


Sekarang kami berbagi pengembangan grafik dan aplikasi. Ini berarti bahwa pengembang harus bekerja dalam dua repositori git: satu untuk aplikasi, dan yang kedua untuk menentukan penyebarannya di Kubernetes. Repositori 2 git adalah 2 alur kerja dan mudah bagi pemula untuk bingung.


Mengelola bagan yang diringkas itu merepotkan


Seperti yang telah kami katakan, grafik generik sangat mudah untuk mendefinisikan dependensi dan dengan cepat menyebarkan beberapa aplikasi. Tapi kami menggunakan --reuse-values untuk menghindari melewatkan semua nilai setiap kali kami menyebarkan aplikasi yang termasuk dalam bagan umum ini.


Dalam alur kerja pengiriman berkelanjutan, kami hanya memiliki dua nilai yang berubah secara teratur: jumlah replika dan tag gambar (versi). Lainnya, nilai yang lebih stabil diubah secara manual, dan ini agak rumit. Selain itu, satu kesalahan dalam menyebarkan grafik umum dapat menyebabkan kegagalan serius, seperti yang telah kita lihat dari pengalaman kita sendiri.


Memperbarui beberapa file konfigurasi


Ketika seorang pengembang menambahkan aplikasi baru, ia harus mengubah beberapa file: pengumuman aplikasi, daftar rahasia, menambahkan aplikasi tergantung pada apakah itu termasuk dalam bagan umum.


Izin Jenkins terlalu diperluas di Vault


Sekarang kami memiliki satu AppRole yang membaca semua rahasia dari Vault.


Proses rollback tidak otomatis


Untuk memutar kembali, Anda perlu menjalankan perintah pada beberapa cluster, dan ini penuh dengan kesalahan. Kami melakukan operasi ini secara manual untuk memastikan bahwa pengidentifikasi versi yang benar telah ditentukan.


Kami bergerak menuju GitOps


Tujuan kami


Kami ingin mengembalikan grafik ke repositori aplikasi yang digunakannya.


Alur kerjanya akan sama dengan untuk pengembangan. Misalnya, ketika cabang dikirim ke wizard, penyebaran akan dimulai secara otomatis. Perbedaan utama antara pendekatan ini dan alur kerja saat ini adalah bahwa semuanya akan dikelola di git (aplikasi itu sendiri dan bagaimana cara menggunakannya di Kubernetes).


Ada beberapa keuntungan:


  • Jauh lebih jelas untuk pengembang. Lebih mudah untuk mempelajari cara menerapkan perubahan pada bagan lokal.
  • Definisi penyebaran layanan dapat ditentukan di mana kode layanan berada .
  • Manajemen penghapusan grafik umum . Layanan ini akan memiliki rilis Helm sendiri. Ini akan memungkinkan Anda untuk mengelola siklus hidup aplikasi (rollback, upgrade) pada tingkat terkecil, sehingga tidak mempengaruhi layanan lain.
  • Manfaat git untuk mengelola grafik adalah: membatalkan perubahan, jejak audit, dll. Jika Anda perlu membatalkan perubahan pada grafik, Anda dapat melakukan ini dengan git. Penyebaran dimulai secara otomatis.
  • Anda dapat mempertimbangkan untuk meningkatkan alur kerja pengembangan Anda dengan alat-alat seperti Skaffold , yang dengannya pengembang dapat menguji perubahan dalam konteks seperti produksi.

Migrasi dua tahap


Pengembang kami telah menggunakan alur kerja ini selama 2 tahun sekarang, jadi kami membutuhkan migrasi yang paling tidak menyakitkan. Karena itu, kami memutuskan untuk menambahkan tahap perantara dalam perjalanan ke tujuan.
Langkah pertama adalah sederhana:


  • Kami mempertahankan struktur yang sama untuk mengonfigurasi penyebaran aplikasi, tetapi pada objek yang sama bernama DailymotionRelease.

 apiVersion: "v1" kind: "DailymotionRelease" metadata: name: "app1.ns1" environment: "dev" branch: "mybranch" spec: slack_channel: "#admin" chart_name: "app1" scaling: - context: "dev-us-central1-0" replicas: - name: "hermes" count: 2 - context: "dev-europe-west1-0" replicas: - name: "app1-deploy" count: 2 secrets: - secret_id: "app1" contexts: - name: "default" vaultPath: "/kv/dev/ns1/app1/test" vaultKey: "password" - name: "dev-europe-west1-0" vaultPath: "/kv/dev/ns1/app1/test" vaultKey: "password" 

  • 1 rilis per aplikasi (tanpa grafik umum).
  • Grafik dalam repositori aplikasi git.

Kami berbicara dengan semua pengembang, sehingga proses migrasi sudah dimulai. Fase pertama masih dikendalikan menggunakan platform CI. Segera saya akan menulis posting lain tentang tahap kedua: bagaimana kita beralih ke alur kerja GitOps dengan Flux . Saya akan memberi tahu Anda bagaimana kami semua mengatur dan kesulitan apa yang kami temui (beberapa repositori, rahasia, dll.). Ikuti beritanya.


Di sini, kami mencoba menggambarkan kemajuan kami dalam alur kerja penerapan aplikasi dalam beberapa tahun terakhir, yang mengarah pada pemikiran tentang pendekatan GitOps. Kami belum mencapai tujuan dan akan melaporkan hasilnya, tetapi sekarang kami yakin bahwa kami melakukannya dengan benar ketika kami memutuskan untuk menyederhanakan semuanya dan membawanya lebih dekat dengan kebiasaan para pengembang.

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


All Articles