Helm ile uygulamaları birden çok Kubernetes kümesine dağıtın

Dailymotion Kubernetes'i nasıl kullanıyor: Uygulama Dağıtımı

Dailymotion olarak üretimde Kubernetes'i 3 yıl önce kullanmaya başladık. Ancak uygulamaları birden fazla kümeye dağıtmak eğlencelidir, bu nedenle son birkaç yıldır araçlarımızı ve iş akışlarımızı geliştirmeye çalışıyoruz.

Nerede başladı

Burada uygulamalarımızı dünya çapındaki birden fazla Kubernetes kümesine nasıl dağıttığımızı ele alacağız.

Aynı anda birden fazla Kubernetes nesnesini dağıtmak için şunu kullanırız: Dümenve tüm grafiklerimiz tek bir git deposunda saklanır. Çeşitli hizmetlerden tam bir uygulama yığınını dağıtmak için özet grafiği denilen şeyi kullanırız. Temel olarak bu, bağımlılıkları bildiren ve API'yi ve hizmetlerini tek komutla başlatmanıza olanak tanıyan bir grafiktir.

Ayrıca Helm'in üzerine kontroller yapmak, grafikler oluşturmak, sırlar eklemek ve uygulamaları dağıtmak için küçük bir Python betiği yazdık. Tüm bu görevler, bir docker görüntüsü kullanılarak merkezi bir CI platformunda gerçekleştirilir.

Gelelim asıl meseleye.

Not. Siz bunu okurken Helm 3'ün ilk sürüm adayı zaten açıklandı. Ana sürüm, geçmişte karşılaştığımız sorunların bazılarını çözecek bir dizi iyileştirme içeriyor.

Grafik geliştirme iş akışı

Uygulamalar için dallanmayı kullanıyoruz ve aynı yaklaşımı grafiklere de uygulamaya karar verdik.

  • Dal dev Geliştirme kümelerinde test edilecek grafikler oluşturmak için kullanılır.
  • Bir çekme isteği gönderildiğinde usta, evrelemede kontrol edilirler.
  • Son olarak değişiklikleri şubeye göndermek için bir çekme isteği oluşturuyoruz. dürtme ve bunları üretimde uygulayın.

Her ortamın grafiklerimizi saklayan kendi özel deposu vardır ve biz bunu kullanırız. Harita Müzesi çok kullanışlı API'lerle. Bu şekilde, ortamlar arasında sıkı bir izolasyon sağlıyor ve grafikleri üretimde kullanmadan önce gerçek dünyada test ediyoruz.

Farklı ortamlardaki grafik depoları

Geliştiriciler bir geliştirme dalını yönlendirdiğinde grafiklerinin bir versiyonunun otomatik olarak geliştirici Chartmuseum'a aktarıldığını belirtmekte fayda var. Bu nedenle, tüm geliştiriciler aynı geliştirme deposunu kullanır ve başka birinin değişikliklerini yanlışlıkla kullanmamak için grafiğin sürümünüzü dikkatlice belirtmeniz gerekir.

Üstelik küçük Python betiğimiz, Kubernetes nesnelerini Kubernetes OpenAPI spesifikasyonlarına göre doğrular. KubevalChartmusem'de yayınlamadan önce.

Grafik geliştirme iş akışının genel açıklaması

  1. İşlem hattı görevlerini spesifikasyona göre ayarlama gazr.io kalite kontrolü için (tüysüz, birim testi).
  2. Uygulamalarımızı dağıtan Python araçlarıyla bir liman işçisi görüntüsünü itmek.
  3. Ortamın şube adına göre ayarlanması.
  4. Kubeval kullanarak Kubernetes yaml dosyalarını doğrulama.
  5. Bir grafiğin ve üst grafiklerinin (değiştirilen grafiğe bağlı grafikler) sürümünü otomatik olarak artırın.
  6. Çevresine uygun bir haritayı Chartmuseum'a göndermek

Kümeler arasındaki farklılıkları yönetme

Kümeler Federasyonu

Kullandığımız bir zaman vardı Kubernetes kümeleri federasyonuKubernetes nesnelerinin tek bir API uç noktasından bildirilebildiği yer. Ancak sorunlar ortaya çıktı. Örneğin, bazı Kubernetes nesneleri federasyon uç noktasında oluşturulamadı, bu da federe nesnelerin ve bireysel kümeler için diğer nesnelerin bakımını zorlaştırdı.

Sorunu çözmek için kümeleri bağımsız olarak yönetmeye başladık, bu da süreci büyük ölçüde basitleştirdi (federasyonun ilk versiyonunu kullandık; ikincisinde bir şeyler değişmiş olabilir).

Coğrafi olarak dağıtılmış platform

Platformumuz şu anda 6'ü yerel ve 3'ü bulutta olmak üzere 3 bölgeye dağıtılmıştır.


Dağıtılmış Dağıtım

Küresel Helm değerleri

4 global Helm değeri, kümeler arasındaki farkları tanımlamanıza olanak tanır. Tüm grafiklerimiz varsayılan minimum değerlere sahiptir.

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

Küresel değerler

Bu değerler uygulamalarımızın bağlamını tanımlamaya yardımcı olur ve çeşitli amaçlarla kullanılır: izleme, izleme, günlüğe kaydetme, harici arama yapma, ölçeklendirme vb.

  • "bulut": Hibrit bir Kubernetes platformumuz var. Örneğin API'miz GCP bölgelerinde ve veri merkezlerimizde konuşlandırılmıştır.
  • "env": Üretim dışı ortamlar için bazı değerler değişebilir. Örneğin, kaynak tanımları ve otomatik ölçeklendirme yapılandırmaları.
  • "bölge": Bu bilgi kümenin konumunun belirlenmesine yardımcı olur ve harici hizmetler için yakındaki uç noktaların belirlenmesinde kullanılabilir.
  • "clusterName": bireysel bir küme için bir değer tanımlamak istiyorsak ve ne zaman.

İşte spesifik bir örnek:

{{/* 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 -}}

Dümen şablonu örneği

Bu mantık, Kubernetes YAML'de karışıklığı önlemek için bir yardımcı şablonda tanımlanmıştır.

Başvuru Duyurusu

Dağıtım araçlarımız birden fazla YAML dosyasını temel alır. Aşağıda bir kümedeki bir hizmeti ve ölçeklendirme topolojisini (kopyalama sayısı) nasıl bildirdiğimize dair bir örnek verilmiştir.

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

Hizmet Tanımı

Bu, dağıtım iş akışımızı tanımlayan tüm adımların bir özetidir. Son adım, uygulamayı aynı anda birden fazla çalışan kümesine dağıtır.


Jenkins Dağıtım Adımları

Peki sırlar?

Güvenlik konusunda, tüm sırları farklı yerlerden takip ediyor ve bunları benzersiz bir kasada saklıyoruz Tonoz Paris’te

Dağıtım araçlarımız Vault'tan gizli değerleri çıkarır ve dağıtım zamanı geldiğinde bunları Helm'e ekler.

Bunu yapmak için Vault'taki gizli diziler ile uygulamalarımızın ihtiyaç duyduğu gizli diziler arasında bir eşleme tanımladık:

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"

  • Apps Kasası'nda gizli dizileri kaydederken uyulması gereken genel kuralları tanımladık.
  • Eğer sır geçerliyse belirli bir bağlama veya kümeye, belirli bir giriş eklemeniz gerekir. (Burada bağlam kümesi1'in gizli yığın-uygulama1-şifresi için kendi değeri vardır).
  • Aksi takdirde değer kullanılır Varsayılan olarak.
  • Bu listedeki her öğe için Kubernetes sırrı bir anahtar/değer çifti eklenir. Bu nedenle grafiklerimizdeki gizli şablon çok basittir.

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

Zorluklar ve sınırlamalar

Birden fazla depoyla çalışma

Artık grafiklerin ve uygulamaların gelişimini ayırıyoruz. Bu, geliştiricilerin iki git deposunda çalışması gerektiği anlamına gelir: biri uygulama için, diğeri ise Kubernetes'e dağıtımını tanımlamak için. 2 git deposu, 2 iş akışı anlamına gelir ve yeni başlayan birinin kafasının karışması kolaydır.

Genelleştirilmiş grafikleri yönetmek bir güçlüktür

Daha önce de söylediğimiz gibi, genel grafikler bağımlılıkları belirlemek ve birden fazla uygulamayı hızlı bir şekilde dağıtmak için çok faydalıdır. Ama kullanıyoruz --reuse-valuesBu genelleştirilmiş grafiğin parçası olan bir uygulamayı her dağıttığımızda tüm değerlerin iletilmesini önlemek için.

Sürekli teslimat iş akışında düzenli olarak değişen yalnızca iki değerimiz vardır: kopya sayısı ve resim etiketi (sürüm). Diğer, daha kararlı değerler manuel olarak değiştirilir ve bu oldukça zordur. Üstelik genelleştirilmiş bir grafiğin uygulanmasındaki bir hata, kendi deneyimlerimizden de gördüğümüz gibi, ciddi başarısızlıklara yol açabilir.

Birden fazla yapılandırma dosyasını güncelleme

Bir geliştirici yeni bir uygulama eklediğinde birkaç dosyayı değiştirmek zorundadır: uygulama bildirimi, sırlar listesi, uygulamanın genelleştirilmiş grafikte yer alması durumunda bağımlılık olarak eklenmesi.

Vault'ta Jenkins izinleri çok genişletilmiş

Artık elimizde bir tane var Uygulama RolüVault'taki tüm sırları okuyan.

Geri alma işlemi otomatik değildir

Geri almak için komutu birkaç kümede çalıştırmanız gerekir ve bu hatalarla doludur. Doğru sürüm kimliğinin belirtildiğinden emin olmak için bu işlemi manuel olarak gerçekleştiriyoruz.

GitOps'a doğru ilerliyoruz

Hedefimiz

Grafiği dağıttığı uygulamanın deposuna döndürmek istiyoruz.

İş akışı geliştirmedekiyle aynı olacaktır. Örneğin, bir dal ana konuma gönderildiğinde dağıtım otomatik olarak tetiklenecektir. Bu yaklaşım ile mevcut iş akışı arasındaki temel fark şu olacaktır: her şey git'te yönetilecek (uygulamanın kendisi ve Kubernetes'te konuşlandırılma şekli).

Birkaç avantajı vardır:

  • daha daha net geliştirici için. Yerel grafikte değişikliklerin nasıl uygulanacağını öğrenmek daha kolaydır.
  • Hizmet dağıtım tanımı belirtilebilir kodla aynı yer hizmet.
  • Genelleştirilmiş grafiklerin kaldırılmasını yönetme. Hizmetin kendi Helm sürümü olacak. Bu, diğer hizmetleri etkilemeyecek şekilde uygulama yaşam döngüsünü (geri alma, yükseltme) en küçük düzeyde yönetmenize olanak sağlayacaktır.
  • Git'in faydaları grafik yönetimi için: değişiklikleri geri alma, denetim günlüğü vb. Bir grafikte yapılan değişikliği geri almanız gerekiyorsa bunu git'i kullanarak yapabilirsiniz. Dağıtım otomatik olarak başlar.
  • Aşağıdaki gibi araçlarla geliştirme iş akışınızı iyileştirmeyi düşünebilirsiniz: iskelegeliştiricilerin değişiklikleri üretime yakın bir bağlamda test edebilmelerini sağlar.

İki adımlı geçiş

Geliştiricilerimiz bu iş akışını 2 yıldır kullanıyor, bu nedenle geçişin mümkün olduğunca sorunsuz olmasını istiyoruz. Bu nedenle hedefe giden yolda bir ara adım eklemeye karar verdik.
İlk aşama basittir:

  • Uygulama dağıtımını ayarlamak için benzer bir yapıyı koruyoruz, ancak bunu DailymotionRelease adlı tek bir nesnede tutuyoruz.

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"

  • Uygulama başına 1 sürüm (genelleştirilmiş grafikler olmadan).
  • Uygulamanın git deposundaki grafikler.

Tüm geliştiricilerle konuştuk, dolayısıyla geçiş süreci çoktan başladı. İlk aşama hâlâ CI platformu kullanılarak kontrol ediliyor. Yakında ikinci aşama hakkında başka bir yazı yazacağım: GitOps iş akışına nasıl geçtik? Akı. Size her şeyi nasıl kurduğumuzu ve ne gibi zorluklarla karşılaştığımızı anlatacağım (çoklu depolar, sırlar, vb.). Haberleri takip edin.

Burada GitOps yaklaşımı hakkında düşüncelere yol açan, uygulama dağıtım iş akışında son yıllardaki ilerlememizi anlatmaya çalıştık. Henüz hedefe ulaşmadık ve sonuçları rapor edeceğiz ancak artık her şeyi basitleştirmeye ve geliştiricilerin alışkanlıklarına yaklaştırmaya karar vererek doğru şeyi yaptığımıza ikna olduk.

Kaynak: habr.com

Yorum ekle