2 puan yazan GN⁺ 2024-01-24 | 1 yorum | WhatsApp'ta paylaş
  • Kubernetes gibi yapılandırma hedeflerinin arttığı ortamlarda YAML dosyalarını elle çoğaltma yaklaşımı kısa sürede sınırına ulaşır; YAML şablonları yerine yapılandırma verisi üretme yaklaşımı daha uygun hâle gelir
  • Helm chart, değerleri values.yaml ve Go şablonlarıyla enjekte eder; ancak isteğe bağlı alanlar, diziler ve map’ler devreye girdiği anda koşullu ifadeler ve girinti yükü artar
  • YAML’in boşluk kuralları katıdır; Helm şablon ayrıştırıcısı YAML yapısını anlamadığı için toYaml ve indent kombinasyonu kolayca kırılgan yapılandırma üretimine yol açar
  • YAML, JSON’ın üst kümesi olduğundan karşılıklı dönüşüm basittir; Jsonnet dış değişkenler, koşullu alanlar, map birleştirme ve nesne birleştirme ile yapılandırma nesnesi üretimini kod yazar gibi ele alır
  • kr8, Jsonnet tabanlı bir akışla birden çok Kubernetes kümesinin yapılandırmasını oluşturur ve işler; karmaşık YAML string’leri birleştirmek yerine nesneleri doğrudan oluşturup dönüştürmeyi seçer

Yapılandırma karmaşıklığı YAML dosyalarının sayısı arttığında başlar

  • Uygulama ve altyapı belli bir ölçeği aştığında yapılandırma karmaşıklığı hızla artar
  • Dağıtım hedefi 1-2 adetse YAML yapılandırma dosyalarını elle yazmak yeterli olabilir; ancak bunun ötesine geçildiğinde yapılandırmayı sistematik biçimde yönetmek gerekir
  • Birden fazla yapılandırma dosyasına ihtiyaç duyulmasının nedeni genellikle aynı hedef için bile bazı değerlerin birbirinden farklı olmasıdır
    • dev, stg, prod gibi ortama göre dağıtımlar
    • Europe, North America gibi bölgeye göre dağıtımlar
  • Tüm yapılandırmalar farklı değildir; ancak farklar yeterince büyükse ortak kısımları ve farklı kısımları ayırarak yönetmek gerekir
  • Yapılandırma yönetimi alanı bu tür sorunlarla uzun zamandır uğraşıyor ve çeşitli araçlar YAML’i kendi yöntemleriyle kullanıyor
  • Puppet içinde yer alan hiera, değişkenleri hiyerarşik olarak sorgulayabildiği için güçlü ve esnektir; YAML’in kendisini şablonlaştırma ihtiyacını büyük ölçüde azaltır

Helm chart’larda ortaya çıkan YAML şablonu sorunu

  • Bulut bilişim ve Kubernetes ile yapılandırma hedefleri işletim sistemi üzerindeki katmanlara kadar genişledikçe CloudFormation ve Helm gibi araçlar ortaya çıktı
  • Helm chart, values.yaml içinde tanımlanan dış parametreleri alıp render edebilir
  • Basit string değerleri görece kolaydır
image: "{{ .Values.image }}"
  • values.yaml içinde image değeri belirtildiğinde bu değer şablona girer
  • İsteğe bağlı alanlar gibi daha karmaşık yapılandırmaları ele almaya başladığınızda sorun büyür
{{- with .resourceGroup  }}
    resourceGroup: {{ .  }}
{{- end }}
  • İsteğe bağlı değerler boş bırakılamayacağı için koşullu ifadeler ve döngüler gerekir; şablon kolayca dağınık hâle gelir
  • Dizi veya map eklerken toYaml ile indent kombinasyonunu kullanmak gerekir
{{- with .Values.podAnnotations  }}
      annotations:
{{ toYaml . | indent 8  }}
{{- end  }}
  • toYaml ile YAML’i yeniden YAML’e çeviren bir fonksiyon çağrısı yapmak zaten tuhaf görünür; ancak daha büyük sorun boşluk işlemedir

YAML boşluk kuralları ile şablon motorunun çatışması

  • YAML’in girinti ve boşluk kuralları katıdır
  • Aşağıdaki örnek geçerli ya da eksiksiz YAML değildir
something: nothing
  hello: goodbye
  • Bunu bir insan elle yazıyorsa birkaç kez backspace’e basıp düzeltebilir; ancak bir şablon sistemiyle YAML üretirken iş bu kadar basit değildir
  • Yapılandırma dosyalarının sayısı 5-10’u aşan bir düzeye geldiyse elle yazmak yerine yapılandırma üretimi gerekir
  • .Values.podAnnotations değerini zaten girintilenmiş annotations altına koymak için değerin kendisi de tam doğru seviyede girintilenmelidir
  • Go şablon ayrıştırıcısı YAML’i anlamadığı için, şablon söz dizimini okunabilir olacak şekilde girintilemeye çalışmak bile sorun çıkarır
{{- with .Values.podAnnotations }}
      annotations:
      {{ toYaml . | indent 6 }}
{{- end  }}
  • Şablon sistemi YAML yapısını bilmeden boşlukları ve koşulları birlikte ele aldığında, karmaşık yapılandırma üretimi giderek zorlaşır
  • JSON’ı doğrudan yazma yaklaşımı da yorum eksikliği ve virgül unutma sorunları nedeniyle uygun değildir; bu rahatsızlıklar yüzünden YAML kullanılmaya başlanmıştır

Jsonnet, JSON yapılandırması üreten bir veri şablonlama dilidir

  • YAML, JSON’ın üst kümesi olduğundan JSON ile YAML arasındaki dönüşüm basittir
  • Birçok uygulama ve programlama dili JSON ve YAML’i doğal olarak ayrıştırabilir ya da dönüştürebilir
  • Python’da da YAML okunup JSON olarak çıktı alınabilir
python -c 'import json, sys, yaml ; y=yaml.safe_load(sys.stdin.read()) ; print(json.dumps(y))'
  • Jsonnet kendisini veri şablonlama dili olarak tanımlar; temel amacı JSON yapılandırmaları üretmektir
  • Jsonnet’in tasarım arka planı design rationale belgesinde görülebilir

Dış değişkenler ve isteğe bağlı alanları işleme

  • Jsonnet, yapılandırma değerlerini enjekte etmek için dış değişkenler kullanabilir
{

  image: std.extVar('image'),

}
  • CLI’dan dış değişken verildiğinde JSON sonucu üretilir
jsonnet image.jsonnet -V image="my-image"
{
   "image": "my-image"
}
  • İsteğe bağlı alanlar, şablon koşullarını string içine sıkıştırmadan kodun koşullu ifadeleriyle temsil edilebilir
// define a variable - yes, jsonnet also has comments
local rg = null;
{

  image: std.extVar('image'),
  // if the variable is null, this will be blank
  [if rg != null then 'resourceGroup']: rg,

}
  • rg null ise resourceGroup alanı sonuca dahil edilmez
  • Değer belirtilirse ilgili alan çıktıya eklenir

Map ve nesne işlemleri YAML girintisinden daha basittir

  • Kubernetes pod annotation’ı gibi bir map’i yapılandırmaya eklerken Jsonnet’te değer bir değişken olarak tanımlanıp nesneye yerleştirilebilir
local annotations = {
  'nginx.ingress.kubernetes.io/app-root': '/',
  'nginx.ingress.kubernetes.io/enable-cors': true,
};

{
  metadata: { // annotations are nested under the metadata of a pod
    annotations: annotations,
  },

}
  • Bu yöntem, YAML şablonlarında girintiyi tutturmaktan çok daha basittir
  • Üretilen sonuç, metadata.annotations altında annotation map’i bulunan bir JSON nesnesidir
{
   "metadata": {
      "annotations": {
         "nginx.ingress.kubernetes.io/app-root": "/",
         "nginx.ingress.kubernetes.io/enable-cors": true
      }
   }
}
  • Mevcut bir nesneye annotation ekleme işi de Jsonnet’te + operatörüyle yapılabilir
local annotations = {
  'nginx.ingress.kubernetes.io/app-root': '/',
  'nginx.ingress.kubernetes.io/enable-cors': true,
};

{
  metadata: {
    annotations: annotations,
  },
} + { // this adds another JSON object
  metadata+: { // I'm using the + operator, so we'll append to the existing metadata
    annotations+: { // same as above
      something: 'nothing',
    },
  },
}
  • Sonuç nesnesinde mevcut annotation’lara something: "nothing" eklenir
{
   "metadata": {
      "annotations": {
         "nginx.ingress.kubernetes.io/app-root": "/",
         "nginx.ingress.kubernetes.io/enable-cors": true,
         "something": "nothing"
      }
   }
}
  • Basit örnekte kod daha uzun görünebilir; ancak yapılandırma karmaşıklaştıkça nesneleri bu şekilde işleyebilme özelliği kullanışlı hâle gelir

kr8, Kubernetes yapılandırmasını Jsonnet yöntemiyle ele alır

  • kr8, birden çok Kubernetes kümesinin yapılandırmasını kolay ve basit biçimde oluşturup işlemek için bu yöntemleri kullanır
  • Temel akış, YAML şablonlarını boşluklar ve koşullu ifadelerle birleştirmek yerine JSON yapılandırma nesneleri üretmek ve bunları gerekli biçimde dönüştürmektir

1 yorum

 
GN⁺ 2024-01-24
Hacker News yorumları
  • YAML ile yazılmış yapılandırmalardan artık tamamen bıktım. GitHub Actions’ta en sevmediğim kısım bu; kararlılıktan bile daha kötü
    Harika bir aracın yapılandırma için YAML dosyası istemesini görünce hemen huzursuz oluyorum. Terraform’un HCL’i, AWS Step Functions’ın ASL’i gibi özel yapılandırma dilleri için de aynısı geçerli
    Bildirimsel API istemek sorun değil; ama o bildirimin programatik olarak üretilmesine izin verseler keşke. Kodla bildirip üretilen yapılandırmalar çok daha iyi bir deneyimdi ve AWS CDK bunu gerçekten iyi yaptı
    Tip güvenli bir dil ve iyi IDE desteğiyle bulut altyapısı tanımlarını yazabiliyorsunuz; iki yıldır güncellenmemiş eklentilere bel bağlamak zorunda kalmıyorsunuz

    • Bu noktada YAML’dan çok saf JSON daha iyi geliyor. Bardağı taşıran damla, deno fmt içinde JSON biçimlendiricisi varken YAML biçimlendiricisi olmamasıydı
      JSON biçimlendiricisi milisaniyeler içinde çalışan tek bir binary iken, YAML’ı otomatik biçimlendirmek için fiilen Prettier kullanmak gerekiyor; Prettier da NPM’in yarısına bağımlı ve başlatılıp çalışması yaklaşık 2 saniye sürüyor
      Bu yüzden şirket deposunda JSON’a çevrilebilecek tüm YAML dosyalarını JSON’a taşıdım; en azından ben çok daha memnunum. Kimse de şikâyet etmedi
      Birçok editör JSON’daki $schema etiketini de destekliyor. Ürüne bu özelliği ekledim; dokümanları okumadan sadece Tab’a basarak yapılandırma dosyası oluşturabilmek gerçekten güzel
      YAML’da da YAML language server ile bu mümkün, ama Tab tuşu girintileme için de gerektiğinden kullanılabilirliği pek iyi değil. JSON da mükemmel değil; ama en azından "no" metni doğru değerine dönüşmüyor
    • YAML kullanmanın avantajı olarak JSON’da yorum yok denildiğini sıkça duyuyorum; ama neden bambaşka bir dile geçmek gerektiğini anlamıyorum
      Yapılandırmayı okumadan önce yorumları kaldıran bir filtre ekleseniz olmaz mı? Bunun YAML’a geçmekten daha zor olması mümkün değil
      YAML’ın okunması kolay olduğu iddiasını da pek anlayamıyorum. Yapılandırmayla uğraşmanın acısı, süslü parantezleri ve köşeli parantezleri birkaç saniye daha az ayrıştırmaktan değil; yüzlerce satırlık yapılandırma içinde eksik bir boşluk ya da tab yüzünden neyin yanlış olduğunu anlamanın zor olmasından geliyor
    • GitHub Actions hangi şeyle yapılandırılsa da kötü olurdu. Çünkü bir programı veri yapısıyla tarif etmeye çalışıyor
      Ansible da aynı hatayı yapıyor; sayısız araç da öyle
    • AWS CloudFormation günlerinden beri benzer düşünüyorum. 4 yıl önce AWS’nin yayımladığı JSON dosyasından tüm kaynakları ve Python tip ipuçlarını üreten deneysel bir CloudFormation üreticisi yaptım ve oldukça iyi çalışıyordu: https://github.com/weberc2/nimbus/blob/master/examples/src/n...
      CDK’nın bu şekilde çalışıp çalışmadığından pek emin değilim. Biraz kurcaladığımda, benim yaptığım “CloudFormation üretme” deneyiminden epey farklıydı ve CDK’nın avantajını tam kavrayamadım
      YAML/şablon sorununu kalıtım/sihir sorunuyla değiştiriyor gibi hissettirdi. AWS CDK, Terraform CDK ve Pulumi kullanmış olanların deneyimlerini daha fazla duymak isterim
    • GitHub Actions’ta YAML anchor desteği olmadığı için daha da acı verici. Bu en azından asgari düzeyde birleştirilebilirlik sağlardı; olmaması üzücü
      https://github.com/actions/runner/issues/1182
  • YAML şablonlarının epey çılgınca bir iş olduğuna katılıyorum, ama sahte dilleri bırakıp neden gerçek bir programlama dili kullanmadığımızı hep anlayamıyorum.
    Karmaşık mantık gerekiyorsa, bir programlama diliyle YAML/JSON/ne gerekiyorsa üretilebilir. Ruby, Python ya da başka herhangi bir dil; Jsonnet veya Go şablonları gibi tuhaf sözde dillere gerek kalmadan gerekeni sağlar.
    Doğrudan kod yazarsanız şablon motorlarının opak ve tuhaf sorunlarına çok daha az takılırsınız. Hangi gerçek dili kullanırsanız kullanın çok daha iyi olur.

    • Eskiden çok büyük sayıda sunucuda bootstrap ve yama işleri için periyodik çalışan Ansible playbooklarını yönetmekle görevliydim.
      Benzer işler için Chef kullanmıştım; Ruby olduğu için istediğim mantığı kolayca tanımlayabilmek, döngüler ve düzgün değişkenler kullanabilmek güzeldi.
      Ansible’ın programcı olmayanlar için tasarlandığını anlıyorum, ama temel programlamaya aşina biri için koşullu işler ve yinelemelerle dolu Ansible playbook’larını Jinja şablonlarının laf kalabalığı yapan söz dizimine hapsetmekten daha büyük cehennem yok.
    • Günümüz yığınlarında dil gömme mimarisi neredeyse unutulmuş gibi. Eskiden yeterince karmaşık bir uygulamanın çekirdeği C/C++/Java vb. ile yazılır, betikleme gerekiyorsa üstüne LISP veya Lua gibi bir şey gömülürdü.
      Ama şimdi genelde bir JSON/TOML/YAML ayrıştırıcısı alıp readConfig fonksiyonu yazıyoruz; gömülü bir yorumlayıcının daha uygun olacağı yerlerde bile böyle yapılıyor.
      Geliştirici açısından, tam teşekküllü bir dil gömme ve uygulama bağlama sağlamaktansa bir yapılandırma formatına karmaşıklık eklemek daha kolay. Bu yüzden yöntemin kendisini unutmuşlar ya da bunun mümkün olduğunu bile düşünmüyorlar gibi.
    • Pulumi, tercih ettiğiniz dilde yazıp HCL’den kurtulabildiğiniz için çekici; ama kişisel olarak bunun açıkça daha kötü olduğunu düşünüyorum. Altyapı kodu öngörülebilirliği, yeniden üretilebilirliği ve bakımı artırmak için bildirime dayalı olmalı.
      Chef/Puppet döneminde IaC’ye mantık eklemeye başlayıp yükseltmesi de bakımı da imkânsız devasa bir karmaşaya dönüşen çok yer oldu. Chef/Pulumi yaklaşımı da mümkün, ama stil ve bakım konusunda çok katı birine ihtiyaç duyuyor.
      Büyük ekipler ve uzun vadeli bakım için Terraform/Puppet modelinin daha iyi olduğunu düşünüyorum. HCL sinir bozucu olsa ve Python/TypeScript vb. kullanmak özgürleştirici hissettirse de, saf bildirime dayalı kod çok fazla spagettiyi engeller.
    • Sorun, dil meraklılarının başka dil meraklıları için dil yapmasında.
      O an moda olan dil tasarımı unsurlarını eklemek istiyorlar, self-hosting istiyorlar, hızlı çok iş parçacıklı web sunucusu da yazılabilsin istiyorlar; sonuçta kavramsal olarak karmaşıklaşıyor.
      Sistem mühendisleri/DevOps için Logo gibi basit bir oyuncak dile ihtiyaç var. İdeal olarak K&R C kitabı büyüklüğünde tek bir kitapla açıklanabilmeli.
      Dinamik tipler, bir hafta sonunda öğrenilebilecek kontrol yapıları, iş parçacığı veya eşzamanlılık yok, nesne yönelimlilik veya kalıtım yok, fonksiyonel/modüler tasarım ve başka diller ile framework’ler tarafından kolayca çağrılıp onları çağırabilecek bir FFI modeli gerekiyor.
      Sorun şu ki dil meraklıları kendilerini kontrol edemeyip sürekli özellik ekliyor; bunlar da çekirdek kütüphanelere ve stil kılavuzlarına giriyor, böylece yeni başlayanların bile hepsini öğrenmesi gerekiyor.
      Ben de dizilere/hashmap’lere each/map türü fonksiyonlar eklemek, birinci sınıf fonksiyonlar ve closure’lar koymak isterdim; ama bu bir hata olabilir. Zaten yapılandırma için değişmez fonksiyonel diller var, fakat şablon YAML kullananların %95’ten fazlası programlamayı bu şekilde öğrenmek istemediği için yaygınlaşmaları zor.
    • Yapılandırma dosyasını üretme noktasını vurgulamak istiyorum. Yapılandırmanın kendisini JSON dosyalarına vb. konabilecek bir biçimle sınırlamak çok faydalı.
      Yapılandırma daha basit, tüketmesi daha kolay ve belgelemesi daha iyi olur. Ama yapılandırma dosyasını yazarken bir programlama dili kullanılmalı; mümkünse hata denetimi, otomatik tamamlama ve satır içi dokümantasyon sağlayan statik tipli bir dil daha iyi.
      AWS CDK iyi bir örnek. Saf CloudFormation yazmak acı verici, ama CDK CloudFormation’a programlama özellikleri eklemez; CloudFormation üretir. AWS’nin tükettiği girdi hâlâ nispeten basit ve kararlı CloudFormation’dır.
  • Başlığı görür görmez Kubernetes’ten bahsedeceğini sandım
    Kubernetes API oldukça sezgisel ve iyi tanımlanmış bir JSON şemasına sahip. k8s öğrenme süresinin büyük kısmının API’nin nasıl kullanılacağını anlamaya gitmesi gerekirken, pratikte Helm chart’larının nasıl kullanılacağını çözmeye gidiyor
    Jsonnet, Ksonnet, Nu, CUE’nun o kadar büyük popülerlik kazandığını sanmıyorum. Çoğu kişi Kustomize kullanıyor gibi; nedeni de görece sezgisel olması ve kubectl içine gömülü gelmesi
    İstediğim araç, tanım yazan kişiye k8s şeması için tip denetimi, doğrulama ve sürümden kaldırma uyarıları sunmalı; kullanıcının kolayca inceleyebileceği tek bir çıktı üretmeli; küme herhangi bir nesneyi/sürümü desteklemiyorsa atomik olarak başarısız olmalı ve temel araç zincirine yerleşik olmalı
    Bun veya Deno TypeScript betiğinin argüman alan bir fonksiyon dışa aktarıp tanım listesi döndürmesini sağlamak, deno compile vb. ile iyi uyacak gibi; ama temel araç zincirine yerleşik olma şartını ihlal ediyor

    • Bu, yazılım genelinde görülen bir kalıp. Sistemin dayandığı ilkel öğeleri ve temel bilgileri öğrenmek yerine, çok zor diye bunların üzerindeki soyutlamalardan bir sürü öğreniyoruz
      Alt seviye ayrıntılardan korunuyorsunuz, ama sorun çıkınca teşhis ve hata ayıklamayı zorlaştıran dev bir soyutlama yığınıyla uğraşmak zorunda kalıyorsunuz
      Gerçekte ne olduğunu anlamak çok daha zorlaşıyor; soyutlama katmanına bağımlı hale gelip sağlayıcının çıkardığı güncellemeleri ve bağımlılık grafiğindeki diğer sorunları da üstleniyorsunuz
    • Bizim sistemimizde jsonnet kullanıyoruz ve k8s ile hiçbir ilgisi yok. Büyük popülerlik kazanmış olmaktan ziyade, karmaşık yapılandırmalar için niş bir araç; çok pazarlanan bir araç da değil
      İhtiyacımız olan işi neredeyse sorunsuz yapıyor, çapraz platform ve birden fazla dilde kullanılabiliyor. C++, .NET ve JVM çalıştırılabilir dosyalarına gömdüm
      Ortaya çıkan JSON yapılandırması, toml/yaml/hocon/ini gibi alternatiflerde bulması zor olan geniş bir araç ekosistemiyle kullanılabiliyor. HOCON’u JVM dışı dillerde kullanmaya çalıştım ama her zaman bir uç durum takılıyordu
    • İkinci gereksinimi muhtemelen karşılamaz, üçüncüyü ise kesinlikle karşılamaz ama: https://cdk8s.io/docs/latest/
    • Basit tutma fikri iyi; kurulum yöntemi olarak da mümkün olduğunca kustomize veya saf yaml kullanmaya çalışıyorum
      Ama pratikte büyük sistemler yönetirken eninde sonunda şablonların faydasından kaçamıyorsunuz
    • kustomize ve özellikle helm çok kafa karıştırıcı; oysa Kubernetes YAML dosyalarını yazmak ve anlamak çok kolay
  • Geliştiricilerin yapılandırmayı doğru ele alma yöntemi üzerine ne kadar az kafa yorduğunu görmek komik
    Sadece bir dosyada saklanan veya kodla üretilen anahtar-değer kümeleri gibi görünüyor, ama aslında her şey bu. Programlamanın kendisi
    Her şey yapılandırmadır; her fonksiyon argümanı da bir tür yapılandırmadır. Dış dosyalardaki tüm yapılandırmalar sonunda bir şekilde fonksiyon argümanı olur
    Sorun, kodun düz metin temsilidir. Bildirimsel yapılandırma dosyaları her şeyi tek yerde görebildiğiniz için iyi görünür; ama yapılandırmayı program haline getirirseniz nereyi değiştirmeniz gerektiğini bulmak zorlaşır
    Kod gerçek zamanlı çalışıp nihai yapılandırmanın temsilini gösterse ve her nihai yapılandırma değerinin nasıl üretildiğini izleyebilseydi bu sorun olmazdı. Oysa bu özellik oldukça basit olmasına rağmen bu şekilde tasarlanmış sistem yok. Yapılandırma her zaman sonradan düşünülen bir şey
    Bu kavramı programlamanın tamamına genişletirsek, tek bir yapılandırma değerine bağlı olan tüm kodu ve dönüşümlerini görebilmeliyiz
    Ayrıca çoğu yapılandırma ilişkisel/graf tabanlıdır; bu yüzden merkezi bir veritabanında tutmak daha iyi olabilir. Farklı yapılandırma değerleri birbiriyle ilişkilidir. Bu nedenle yapılandırmaya bir veritabanı/graf düzenleyicisinden bakmalıyız
    Düz metinden uzaklaştığınızda işler çok daha basitleşmeye başlar; ama yukarıda bahsettiğim dil özelliklerine hâlâ ihtiyaç var

    • Benzer bir şeyi bir müşteride gerçekten ciddi biçimde deniyoruz. Ürün başına 1500 satırı aşan “yapılandırma” dosyaları var ve bunlar teknik çizimler ile üretim dosyaları oluşturmak için kullanılıyor
      Yapılandırmalar, ilişkili değişkenleri gruplamak için adlandırma kuralları kullanmaya çalışıyor
      Gerçek iç içe veri yapılarına, muhtemelen JSON’a geçmek istiyorum; ama mühendisler kesinlikle kod yazmak istemediği için kod olarak yapılandırma mümkün değil. Yukarıda söylenen dezavantajlar da var
      Sonraki fikir, yapılandırmayı daha iyi gösterecek ve düzenleyecek bir yöntem olması gerektiği. Nihai ürünün temsilini gezmeyi, parçaları seçip parametreleri o şekilde düzenlemeyi sağlayan görsel bir UI düşündüm
      Bu yönün doğru olup olmadığını merak ediyorum. Değilse biraz daha açıklamanızı isterim. Bu uygulamanın özü yapılandırma
  • Daha da kötüsü, CI/CD gibi yerlerde YAML’ın neredeyse bir programlama dili haline gelmesi. Üstelik çok laf kalabalığı yapan, sezgisel olmayan, kötü tanımlanmış ve sağlayıcıya göre değişen bir dil

    • Bu neredeyse 2010’ların başındaki Java hatalarını tekrarlamak gibi. O dönemde uygulamaların tamamı çoğu zaman bağımlılık enjeksiyonunu yapılandıran dev XML yığınlarıyla birbirine tutturulurdu
      DTD ve XML doğrulaması olmasına rağmen geç patlayan ve yorumlaması zor hata mesajları üreten tanıdık özelliklere sahipti
      O zamanlar hayal kırıklığının çoğu XML’e yönelmişti; ama 2020’lerin ortasındaki YAML cehennemine bakınca sorunun işaretleme dilinin kendisi olmadığı görülüyor
    • Aynen öyle. Biz ytt[0] kullanıyoruz; “Python lehçesi olan Starlark programlama dilinin biraz değiştirilmiş bir sürümü”
      YAML şablonunun bir yerlerine mantık gömmekten gerçekten nefret ediyorum
      [0] https://tanzu.vmware.com/developer/guides/ytt-gs/
    • Kubernetes ile çalışan bazı ortamlarda ciddi ciddi YAML mühendisi ifadesi kullanılıyor
    • YAML, serileştirme biçimleri dünyasının Bradford Pear ağacı gibi. Başta güzel görünür; ama proje yaşlanıp YAML büyüdükçe kendi dallarının ağırlığı altında çöker
    • Daha da kötüsü, her neslin bu hatayı tekrarlaması. S-ifadelerinin cevap olup olmadığını bilmiyorum ama Terraform HCL en başta hiç yapılmamalıydı
  • Helm’in kazanmış olması gerçekten üzücü. Şirkette açık kaynak k8s ile ilgili işler yapıyorum; kullanıcıların %100’ü Helm chart hazırlamamızı istediği için sonunda yapmak zorunda kaldık
    Üzerinde çalışmak berbat. Dosya adı foo.yaml gibi ama aslında YAML değil, bu yüzden editör yardımcı olamıyor. YAML hizalamasını tutturmak için tüm verileri indent 4 üzerinden akıtmak gerekiyor
    En moral bozucu tarafı, Kubernetes özelliklerinin tamamını kendi yönteminizle yeniden dışa açmanız gerekmesi. Birisi deployment.spec.template.spec.fooBars eklemek isterse values.yaml içine deploymentFooBars ekleyip bağlamanız gerekiyor. Her özellik için aynı şey tekrarlanıyor
    Gerçekten “kötü olan iyidir” yaklaşımının raydan çıkmış bir örneği. Ben de bir ara şablon uygulamak için sed -e s/$FOO/foo/g gibi korkunç şeyler yapmıştım; muhtemelen Helm de böyle başlamıştır. Sonuç karmakarışık
    Kişisel olarak Kustomize’ı kubectl içine girmeden önce bile kullanıyordum ve hep oldukça memnun kaldım. Tuhaf yanları çok ama en azından ürettiği nesnelerin anlamını anladığı için zaman kazandırıyor
    Jsonnet çok daha iyi. k8s uygulamamızın bir parçası olarak karmaşık trafik yönlendirmesi için Envoy dağıtımını da birlikte sunuyoruz; Envoy yapılandırması laf kalabalığıyla dolu ama Jsonnet ile ele almak kolay: https://github.com/pachyderm/pachyderm/blob/master/etc/gener...
    Ciddi ciddi jsonnet’i Go şablon diline transpile edip her şeyi Jsonnet ile uygulamayı düşünüyorum. En azından biraz daha sürdürülebilir olur ve helm install olduğu gibi çalışacağı için kimse anlamaz
    Ama Helm’in Kubernetes’in sonunu getireceğini düşünüyorum. Ayarlar için düzgün bir dille gelen rakip bir bilgisayar tahsisi/konteyner çalıştırma aracı çıkarsa herkes bir gecede ona geçer

    • sed -e s/$FOO/foo/g kullanma isteği geldiğinde, biraz daha standart ve daha iyi bir çözüm olarak envsubst’e bakmak iyi olabilir
      Helm chart’larını jsonnet ile şablonlamak veya değiştirmek konusundaysa Tanka da yardımcı olabilir: https://tanka.dev/helm
    • Helm’in Kubernetes’in sonu olacağı öngörüsüne inanmak istiyorum
      Ancak çalıştığım yerler hâlâ değişimden korktukları için tf/hcl ve helm’i aynen kullanıyor. En azından kişisel projelerde biraz nefes alınıyor
  • Burada bir sorun olduğunu düşünüyorum. Yine de yapılandırma dili olarak YAML seçen tipte birinin bunu sorun olarak görüp görmeyeceğinden emin değilim
    İnsan odaklı veri gösterimi ile bilgisayar odaklı veri gösterimi arasında doğrudan bir çatışma var. Bilgisayar Lisp’e benzer şeyleri sever, insan ise Python’a benzer şeyleri sever
    Kubernetes yapılandırmasını bilgisayarla manipüle etmek isteyen biri için Kubernetes’in YAML kullanması içten içe sinir bozucu olacaktır. Ama Kubernetes topluluğu çoğunlukla YAML tarafındaki insanlara benziyor; o hâlde programlama mantığı girince yapılandırma dosyalarıyla çalışmanın berbat hâle gelmesini neden umursasınlar ki?
    YAML’in dezavantajı tam da bu durum ve k8s ile uğraşanların çoğunun bunu öngörebilecek kadar zeki olduğunu düşünüyorum
    “YAML, JSON’ın üst kümesidir” sözü, belirtim yazarları belgeye ne yazarsa yazsın pratikte doğru değil bence. Tüm YAML yapılandırmasını JSON’a çevirirseniz DevOps ekibi sinirlenir
    İki veri biçimi aynı anlam temsiline sahip olabilir; aynı CPU mimarisine derlenen tüm diller için de bu geçerli. JSON ve YAML pratikte ayrıdır, ikisini karıştırmak iyi bir fikir değil

    • İronik olarak, doğru hatırlıyorsam k8s manifest’leri baştan beri makine tarafından üretilmek üzere tasarlanmıştı, insanların elle yazması için değil
      Elbette insanlar sonunda elle yazdı ve katlanılamaz hâle gelince şablon eklemeye başladılar. İşler hep böyle ilerliyor gibi
      Elle yazılmış metin, makine tarafından üretilen yapılandırma serileştirme metniyle değiştirilmek yerine, aslında yine elle yazılmış metnin üzerine şablon eklenmiş hâliyle değiştiriliyor
    • “YAML, JSON’ın üst kümesidir” sözü yalnızca her JSON belgesinin geçerli bir YAML belgesi olduğu anlamına gelir. YAML’in JSON ile aynı olduğu anlamına gelmez
  • Kişisel ilkem, makinelerin okuyacağı kodu üretmek için string interpolation kullanılmaması gerektiği. Şablon dilleri, havalı bir string interpolation’dan ibaret
    SQL injection ve cross-site scripting’in sonuçlarını gördüm. Yorumlayıcıya rastgele metin sokmaya devam ettiğimiz sürece bunlar olmaya devam edecek
    Bu yüzden HTML üretirken de şablon dosyaları kullanılmaması gerektiğini düşünüyorum
    HTML için şablon dili alternatifleri olarak Ruby’de Haml, JavaScript’te Pug var. Bu diller etiketler, öznitelikler ve metin düğümlerinden oluşan tüm ağacı tanımlamak için belirlenmiş bir yöntem sunar
    Python tarzı anlamlı girintilemeyi sevmiyorsanız JavaScript’te JSX var. JSX’in HTML’e benzeyen kısmı, web belge ağacını oluşturan createElement ifadelerine derlenir; bu ağaç da gerekirse HTML olarak çıktı verilebilir
    Haml, Pug, JSX HTML çıktısı üretebilse de şablon dili değildir. Aynı şekilde JSON.stringify(myObj) da JSON için bir şablon dili değildir
    Makinelerin okuyacağı kod, mümkünse hedef dilin bilinen yapısını anlayan ve kullanan araçlarla üretilmelidir

    • Haml, Pug, JSX’in şablon dili olmadığını söylemek, şablon dilini “havalı string interpolation” olarak gören kişisel tanımı kullanmadığınız sürece mantıklı değil
      Haml, web belgesindeki inline koddan kaçınmak ve HTML’i daha temiz hale getirmek için bir şablon sistemidir; Pug ise Node.js için zengin özellikli bir şablon motorudur
      JSX’in teknik olarak bir şablon dili olmadığına katılabilirim
      Sonuçta bunların hepsi HTML’e derlenir. Ancak string interpolation değil; sözdizim ağacı olarak ayrıştırılan ve geçerli yapıya dair içsel bir anlayışa dayanarak HTML’e render edilen dillerdir
      YAML şablonları havalı string interpolation’dır; şablon dili değildir ya da en azından berbat uygulanmış bir şablon dilidir
    • Tüm şablon dilleri string şablon dilleri değildir. Örneğin PHP’yi metin için bir şablon dili olarak görüyorsak, aynı mantıkla XQuery de XML için bir şablon dilidir
    • Sorunun özü bu. YAML ve şablonlar sadece dikkat dağıtıcı. Nihayetinde string’in fazla genel bir tür olmasına ve bizim onu tembelce kullanmamıza dayanıyor
      Kişisel kuralım, bir değer bir string’in içine her girdiğinde mutlaka doğru şekilde encode edilmesi gerektiği
      Daha önce bu konuda yazmıştım: https://kevincox.ca/2022/02/08/escape-everything/
      Özetle, her string’in HTML, SQL, insanların okuyacağı terminal çıktısı gibi uyması gereken bir biçimi vardır. Bir değeri bir string’e her koyduğumuzda o biçime uygun şekilde doğru encode etmeliyiz; ama bunu neredeyse hiç yapmıyoruz
  • cuelang’e geçiyoruz [1]. Şahsen tasarımının Jsonette’ten daha iyi olduğunu düşünüyorum
    Kubernetes’te zaten durum uzlaştırma var; bu yapılandırmada eksik olan tek şey silmeydi, o da artık prune özelliğiyle çözülebiliyor [2]
    [1] https://cuelang.org/docs/integrations/k8s/
    [2] https://kubernetes.io/blog/2023/05/09/introducing-kubectl-ap...

    • cuelang’i önerebilirim. Şirkette kullanmaya başladık ve gerçekten iyi
      Bazı hata mesajlarını yorumlamak biraz zor, ama önceden yakaladığı hata sayısı o kadar fazla ki kabul edilebilir. Artık doğrudan yaml yazmak zorunda kaldığım birkaç an, kıyaslayınca fazlasıyla sıkıcı geliyor
  • Böyle durumlarda genelde “Kurtarıcımız CUELang’i duydunuz mu?” diye araya giriyorum: https://cuelang.org/
    Henüz Turing-complete değil, ama tekrarları gidermek için yeterince ifade gücüne sahip; aynı dilde şema ve veriyi aynı dosyada ya da ayrı dosyalarda tanımlayabiliyorsunuz ve union type’lar da var
    YAML veya JSON üretebiliyor; kendisini ya da YAML/JSON dosyalarını doğrulayabiliyor
    En büyük dezavantajı, mevcut uygulamanın yalnızca Go’da olması; bu yüzden alt süreç veya FFI gerekebilir

    • Çok kısa cuelang dosyalarını kabul eden bir pipeline’ımız var
      Ardından her uygulama için JSON dosyaları üretiyor, bir araç XML tanımları oluşturuyor; bu tanımlar mimarların sahip olduğu XLS’e uygulanıyor ve oradan Helm chart’larına uygulanacak YAML çıkarılıyor
      Chart, k8s istemcisini deploy ediyor; bu istemci de API üzerinden JSON ile ana cluster’la etkileşime giriyor
      Biraz zaman aldı, ama her iş için en iyi aracı kullanıyoruz
    • dhall ile karşılaştırınca nasıl?