Terapkan aplikasi di beberapa cluster Kubernetes dengan Helm

Bagaimana Dailymotion menggunakan Kubernetes: Penerapan Aplikasi

Kami di Dailymotion mulai menggunakan Kubernetes dalam produksi 3 tahun lalu. Namun menerapkan aplikasi di beberapa cluster adalah hal yang menyenangkan, jadi selama beberapa tahun terakhir kami telah mencoba meningkatkan alat dan alur kerja kami.

Di mana itu dimulai

Di sini kami akan membahas cara kami menerapkan aplikasi kami di beberapa cluster Kubernetes di seluruh dunia.

Untuk menerapkan beberapa objek Kubernetes sekaligus, kami menggunakan Kemudi, dan semua grafik kami disimpan dalam satu repositori git. Untuk menyebarkan tumpukan aplikasi lengkap dari beberapa layanan, kami menggunakan apa yang disebut bagan ringkasan. Pada dasarnya, ini adalah bagan yang mendeklarasikan dependensi dan memungkinkan Anda menginisialisasi API dan layanannya dengan satu perintah.

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

Mari kita langsung ke intinya.

Catatan. Saat Anda membaca ini, kandidat rilis pertama untuk Helm 3 telah diumumkan. Versi utama berisi sejumlah perbaikan untuk mengatasi beberapa masalah yang kami temui di masa lalu.

Alur kerja pengembangan bagan

Kami menggunakan percabangan untuk aplikasi, dan kami memutuskan untuk menerapkan pendekatan yang sama pada grafik.

  • Cabang dev digunakan untuk membuat grafik yang akan diuji pada cluster pengembangan.
  • Saat permintaan tarik dikirimkan ke menguasai, mereka diperiksa dalam pementasan.
  • Terakhir, kami membuat permintaan tarik untuk melakukan perubahan pada cabang melecut dan menerapkannya dalam produksi.

Setiap lingkungan memiliki repositori pribadinya sendiri yang menyimpan grafik kami, dan kami menggunakannya Museum Grafik dengan API yang sangat berguna. Dengan cara ini kami memastikan isolasi ketat antara lingkungan dan pengujian grafik di dunia nyata sebelum menggunakannya dalam produksi.

Repositori bagan di lingkungan yang berbeda

Perlu dicatat bahwa ketika pengembang mendorong cabang dev, versi bagan mereka secara otomatis dikirim ke Chartmuseum dev. Oleh karena itu, semua pengembang menggunakan repositori dev yang sama, dan Anda perlu menentukan versi bagan Anda dengan hati-hati agar tidak menggunakan perubahan orang lain secara tidak sengaja.

Selain itu, skrip Python kecil kami memvalidasi objek Kubernetes terhadap spesifikasi Kubernetes OpenAPI yang digunakan Kubeval, sebelum menerbitkannya di Chartmusem.

Gambaran umum alur kerja pengembangan bagan

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

Mengelola perbedaan antar cluster

Federasi Cluster

Ada suatu masa ketika kita menggunakannya federasi cluster Kubernetes, tempat objek Kubernetes dapat dideklarasikan dari satu titik akhir API. Namun masalah muncul. Misalnya, beberapa objek Kubernetes tidak dapat dibuat di titik akhir federasi, sehingga menyulitkan pemeliharaan objek gabungan dan objek lain untuk cluster individual.

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

Platform terdistribusi secara geografis

Platform kami saat ini didistribusikan di 6 wilayah - 3 secara lokal dan 3 di cloud.


Penerapan Terdistribusi

Nilai-nilai Helm Global

4 nilai Helm global memungkinkan Anda mengidentifikasi perbedaan antar cluster. Semua grafik kami memiliki nilai minimum default.

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

Nilai-nilai global

Nilai-nilai ini membantu menentukan konteks aplikasi kita dan digunakan untuk berbagai tujuan: pemantauan, penelusuran, pencatatan, melakukan panggilan eksternal, penskalaan, dll.

  • "cloud": Kami memiliki platform Kubernetes hybrid. Misalnya, API kami diterapkan di zona GCP dan di pusat data kami.
  • "env": Beberapa nilai mungkin berubah untuk lingkungan non-produksi. Misalnya, definisi sumber daya dan konfigurasi penskalaan otomatis.
  • "wilayah": Informasi ini membantu menentukan lokasi klaster dan dapat digunakan untuk menentukan titik akhir terdekat untuk layanan eksternal.
  • "clusterName": jika dan kapan kita ingin menentukan nilai untuk sebuah cluster individual.

Berikut ini contoh spesifiknya:

{{/* 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 pembantu untuk menghindari kekacauan Kubernetes YAML.

Pengumuman Aplikasi

Alat penerapan kami didasarkan pada beberapa file YAML. Di bawah 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: [email protected]:dailymotion/foobar
      contexts:
        prod-europe-west1:
          deployments:
            - name: foo-bar-baz
              replicas: 18
            - name: another-deployment
              replicas: 3

Definisi Layanan

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


Langkah Penerapan Jenkins

Bagaimana dengan rahasia?

Mengenai keamanan, kami melacak semua rahasia dari berbagai tempat dan menyimpannya di brankas unik Kubah di Paris.

Alat penerapan kami mengekstrak nilai rahasia dari Vault dan, ketika waktu penerapan tiba, memasukkannya ke dalam Helm.

Untuk melakukan hal ini, kami menetapkan pemetaan antara rahasia di Vault dan rahasia yang dibutuhkan 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 menetapkan aturan umum yang harus diikuti saat mencatat rahasia di Vault.
  • Jika rahasianya berlaku pada konteks atau klaster tertentu, Anda perlu menambahkan entri tertentu. (Di sini konteks cluster1 memiliki nilainya sendiri untuk kata sandi stack-app1 rahasia).
  • Jika tidak, nilainya akan digunakan secara default.
  • Untuk setiap item dalam daftar ini di Rahasia Kubernet pasangan nilai kunci dimasukkan. Oleh karena itu, template rahasia di grafik 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 banyak repositori

Sekarang kami memisahkan pengembangan grafik dan aplikasi. Artinya, pengembang harus bekerja di dua repositori git: satu untuk aplikasi, dan satu lagi untuk menentukan penerapannya ke Kubernetes. 2 repositori git berarti 2 alur kerja, dan pemula mudah bingung.

Mengelola grafik umum memang merepotkan

Seperti yang telah kami katakan, diagram generik sangat berguna untuk mengidentifikasi dependensi dan menerapkan beberapa aplikasi dengan cepat. Tapi kami menggunakan --reuse-valuesuntuk menghindari meneruskan semua nilai setiap kali kita menerapkan aplikasi yang merupakan bagian dari bagan umum ini.

Dalam alur kerja pengiriman berkelanjutan, kami hanya memiliki dua nilai yang berubah secara berkala: jumlah replika dan tag gambar (versi). Nilai lain yang lebih stabil diubah secara manual, dan ini cukup sulit. Selain itu, satu kesalahan dalam menerapkan bagan umum dapat menyebabkan kegagalan serius, seperti yang telah kita lihat dari pengalaman kami sendiri.

Memperbarui beberapa file konfigurasi

Ketika seorang pengembang menambahkan aplikasi baru, dia harus mengubah beberapa file: deklarasi aplikasi, daftar rahasia, menambahkan aplikasi sebagai ketergantungan jika termasuk dalam bagan umum.

Izin Jenkins terlalu diperluas di Vault

Sekarang kita punya satu Peran Aplikasi, yang membaca semua rahasia dari Vault.

Proses rollback tidak otomatis

Untuk melakukan rollback, Anda perlu menjalankan perintah di beberapa cluster, dan ini penuh dengan kesalahan. Kami melakukan operasi ini secara manual untuk memastikan bahwa ID versi yang benar telah ditentukan.

Kami bergerak menuju GitOps

Tujuan kita

Kami ingin mengembalikan grafik ke repositori aplikasi yang disebarkannya.

Alur kerjanya akan sama dengan pengembangan. Misalnya, ketika sebuah cabang didorong ke master, penerapan akan dipicu secara otomatis. Perbedaan utama antara pendekatan ini dan alur kerja saat ini adalah semuanya akan dikelola di git (aplikasi itu sendiri dan cara penerapannya di Kubernetes).

Ada beberapa keuntungan:

  • Banyak lebih jelas untuk pengembang. Lebih mudah mempelajari cara menerapkan perubahan pada diagram lokal.
  • Definisi penerapan layanan dapat ditentukan tempat yang sama dengan kodenya melayani.
  • Mengelola penghapusan grafik umum. Layanan ini akan memiliki rilis Helmnya sendiri. Ini akan memungkinkan Anda untuk mengelola siklus hidup aplikasi (rollback, upgrade) pada tingkat terkecil, agar tidak mempengaruhi layanan lainnya.
  • Manfaat git untuk manajemen bagan: membatalkan perubahan, mengaudit log, dll. Jika Anda perlu membatalkan perubahan pada bagan, Anda dapat melakukannya menggunakan git. Penerapan dimulai secara otomatis.
  • Anda mungkin mempertimbangkan untuk meningkatkan alur kerja pengembangan Anda dengan alat seperti Perancah, yang dengannya pengembang dapat menguji perubahan dalam konteks yang mendekati produksi.

Migrasi dua langkah

Pengembang kami telah menggunakan alur kerja ini selama 2 tahun, jadi kami ingin migrasi berjalan semudah mungkin. Oleh karena itu, kami memutuskan untuk menambahkan langkah perantara menuju tujuan tersebut.
Tahap pertama sederhana:

  • Kami mempertahankan struktur serupa untuk menyiapkan penerapan aplikasi, tetapi dalam satu objek yang disebut 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).
  • Bagan di repositori git aplikasi.

Kami sudah berbicara dengan semua pengembang, jadi proses migrasi sudah dimulai. Tahap pertama masih dikontrol menggunakan platform CI. Saya akan segera menulis postingan lain tentang fase kedua: bagaimana kami berpindah ke alur kerja GitOps Aliran. Saya akan memberi tahu Anda bagaimana kami mengatur semuanya dan kesulitan apa yang kami temui (banyak repositori, rahasia, dll.). Ikuti beritanya.

Di sini kami mencoba menggambarkan kemajuan kami dalam alur kerja penerapan aplikasi selama beberapa tahun terakhir, yang mengarah pada pemikiran tentang pendekatan GitOps. Kami belum mencapai tujuan dan akan melaporkan hasilnya, namun sekarang kami yakin bahwa kami melakukan hal yang benar dengan memutuskan untuk menyederhanakan segalanya dan mendekatkannya pada kebiasaan pengembang.

Sumber: www.habr.com

Tambah komentar