İçeriğe geç

Tekton Pipelines Nedir? Tekton ile CI/CD Süreçlerine Giriş

Merhabalar.

Günümüzdeki yazılım dünyası artık fazlasıyla hızlı ve dinamik. Her gün yüzlerce kere tekrar eden işlemlerde insan kaynaklı doğabilecek hataları bertaraf etmek, tutarlı sonuçlar almak için CI/CD süreçlerini kurgulamayı ve bu süreçleri geliştirmeyi işimizin bir parçası olarak kabul etmiş durumdayız.

Böylelikle aynı işleri her seferinde aynı tutarlılıkla ve tamamen otomatize bir şekilde yapabilmekteyiz.

Bu bağlamda şu an okumakta olduğunuz ve takibindeki bir kaç blogta Tekton Pipelines çözümünü irdeleyecegiz.

Daha hızlı bir gezintiye ihtiyacınız varsa; ☺️

1. Tekton Pipelines Nedir? Tekton ile CI/CD Süreçlerine Giriş (okumakta olduğunuz blog)

2. Tekton Pipelines ile Docker Image Build ve Registry Push

3. Tekton Pipelines ile Event Driven CI/CD Süreci Kurgulama

Tekton nedir?

Tekton açık kaynak kodlu, Linux Foundation çatısı altındaki başka bir kuruluş olan Continous Delivery Foundation bünyesinden çıkmış; esnek, modüler ve Kubernetes tabanlı bir CI/CD toolu’dur.

Tekton’un avantajları nedir?

  • Kubernetes tabanlıdır. 

Varolan K8s clusterına bir eklenti olarak kurulur ve kullanılır. Tekton’ın biraz sonra bahsedeceğimiz komponentleri aynı birer K8s nesnesi gibi tanımlanabilir. K8s’in custom resource yapısına uygundur. Bu da doğrudan Tekton’ın yapacağı işlemlerin cluster içinde yürütülmesini ve gözlenebilmesini sağlar. Yapılacak işlemler tahmin edebileceğimiz gibi podlar ve onların içerisindeki containerlarda çalıştırılır.

  • Esnek, modüler ve yeniden kullanılabilirlik.

Tekton, pipeline’ları küçük bloklara (task’ler) ayırmanıza ve tekrar kullanılabilir bileşenler olarak oluşturmanıza olanak tanır. Böylelikle kendini tekrar etmenin önüne geçer. Aynı zamanda ortak bloklar kullanıp farklı amaçlara hizmet eden pipeline’lar oluşturulabilir.

Bunun yanında Tekton bir HUB a sahiptir ki buda oluşturulan blokların geliştiriciler arasında paylaşılabilmesine ve yüklenerek direkt kullanımına olanak verir.

Ki sanıyorum HUB farklı amaçlar için ortak blokların kullanımını çok güzel bir şekilde özetler.

  • Ölçeklenebilirlik, yönetilebilirlik ve gözlenebilirlik.

Tekton doğrudan K8s native olduğundan, ve doğrudan cluster üstünde çalışmasından ötürü ekstra bir CI/CD sunucusu yönetmeyi zorunluluğunu kaldırır. İş yapmak koşan tüm pipelinelar esasında cluster içerisinde podlar ve onların sahip olduğu containerlardır. Buda bir şeylerin ters gitmesi halinde, cluster üstünde kullandığınız mevcut troubleshooting yaklaşımlarını kullanabilmeniz demektir. Bunun yanında pipeline yürütme talepleriniz arttığında bu aslında daha fazla pod yürütmeniz gerek demek olduğundan cluster scaling yaparak talebin altından kalkabilirsiniz. Kim bilir belki yeni bir node eklenmesi 🙂‍↔️

  • Yardımcı diğer araçlar.

Aslında yukarıda HUB ile biraz bahsettik fakat Tekton ekosistemi içerisinde kullanımını kolaylaştıracak bazı opsiyonel araçlara da sahiptir. Örneğin Tekton dashboard ile clusterınız üzerindeki Tekton objelerini ve yürütme zamanlarındaki davranışlarını web arayüzünden takip edebilirsiniz. CLI (tkn) ile Tekton bileşenlerini komut satırından yönetebilirsiniz. Tekton Hub‘ı zaten yukarıda açıklamıştık. Bir bileşen marketi gibi düşünebiliriz. Bunun yanında Triggers ile birlikte event driven olan bir yapı kurgulanabilir,  Pipelineları dış kaynaklarda oluşan eventlere göre yürütebiliriz.

Tekton Temel Komponentleri ve Çalışma Modeli

Öncelikle yazının bundan sonraki kısmı ve takip edecek yazılar için bir K8s clusterına sahip olmamız ve temel tekton bileşenleri yüklememiz gerekiyor. Minikube veya Kubeadm ile bir lokal clusterınız bulunuyor ve cluster-admin yetkisine sahip bir contexte’de sahipseniz aşağıdaki şekilde Tekton’ı clustera yükleyebilirsiniz.

$ kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

tekton-pipelinesaltındaki tüm podlar Running state’e geçtiğinde kurulum tamam demektir.


kubectl get pods -n tekton-pipelines
NAME                                           READY   STATUS    RESTARTS   AGE
tekton-events-controller-7589957c44-pvwq7      1/1     Running   0          2m39s
tekton-pipelines-controller-59f45c5dcd-2pnps   1/1     Running   0          2m39s
tekton-pipelines-webhook-569b966dff-54fkq      1/1     Running   0          2m39s

Kurulum tamamsa devam edebiliriz.

Tasks and Pipelines

Yukarıdaki görsel Tekton’ın bir pipeline yapısının modellenmiş hali ve genel akışı canlandırması adına güzel bir örnek. Şimdi tek tek bu kavramlara göz atalım.

Step.

Tekton’da oluşturulabilen en atomik birimdir. Adındanda çağrım yapacağı üzere bir pipeline üzerinde yürütülen her step gerçekleştirilen bir eylemdir. Örnek olarak bir Python uygulamasının testlerinin yürütülmesi işlemi verilebilir.

Task.

Birden fazla step’in bir araya gelerek oluşturduğu ve Tekton tarafından yürütülebilen en küçük birimdir. Bir çok step bir araya gelerek task kavramı etrafında çalışarak işlemini tamamlar. Her task bir pod tarafından temsil edilir. Tasklerin yürütülmesi sırasında oluşturulan pod içinde çalışan containerler ise taski oluşturan steplerdir.

Örneğin uzaktaki git reposunun build için klonlaması verilebilir. Burada aklınıza şu soru gelmiş olabilir, bu işlem bir step olamaz mıydı? Pekala olabilir gibi geliyor fakat bir reponun sadece klonlanması günümüz yazılım dünyasında pek isterleri karşılamayacaktır. Klonlama sırasında reponun çekildiğini belirli bir branch yada tag checkout ettiğimizi ve varsa submodule’leri de konfigüre ettiğimizi düşünelim. Task’imiz klonlamak fakat yaptığımız birden fazla işlem var. Bu yaklaşımla düşünülürse task ve step arasındaki ilişkiyi daha net görebiliriz.

TaskRun.

Tekton’da bir task her çalıştırıldığında buna karşılık bir TaskRun objesi oluşturulur. Bu sayede aynı task her çalıştırmada ayrı bir TaskRun ile temsil edilir. Her TaskRun, ilgili yürütmenin sürecini ve çıktısını izlemek için kullanılır.

Pipeline.

Pipeline’lar, birden fazla task’in belirli bir sırayla ya da paralel şekilde yürütülmesini sağlayan ve tüm sürecin akışını yöneten yapılardır. Tekton, pipeline üstünde tanımlanan tüm task’leri bir araya getirerek bu süreci baştan sona kontrol eder.

Her task, bir pod olarak çalışır ve gerekli durumlarda önceki task’in başarılı olmasını bekleyerek ilerler. Beklememesi gerektiği durumlarda paralelize çalışmasını sağlayabilir veya akış sırasında bir hata oluştuğunda fallback olarak nasıl bir işlem gerçekleşeceğini yapılandırabilir.

Örneğin; bir pipeline, bir Git reposunun klonlanmasını, Dockerfile kullanılarak imajın build edilmesini, yeni imajın registrye push edilmesini ve son olarak bu imajla K8s üzerinde yeni bir deployment başlatılmasını kapsayabilir.

PipelineRun.

PipelineRun, belirli bir Pipeline’ın her bir yürütmesini temsil eden objedir. Bir Pipeline çalıştırıldığında Tekton otomatik olarak bir PipelineRun oluşturur. TaskRun ile benzer şekilde, bu obje yürütmenin sürecini ve çıktısını izlemek için kullanılır.

Peki Tekton bu akışı nasıl takip eder?

Tekton, her step container’ına kendi entrypoint binary’sini enjekte eder. Bu binary, container içinde tanımladığınız komutu hemen çalıştırmaz, öncelikle sistemin hazır olmasını bekler. Hazır olma durumu ise Kubernetes annotation’larıyla belirlenir ve kontrol edilir.

Tekton, annotation’ları Downward API aracılığıyla step container’larına dosya olarak yazar. Entrypoint binary bu dosyaları izler; önceki step’in tamamlandığını belirten bir annotation dosyası oluştuğunda, step çalıştırılır. Böylece örneğin bir task içindeki iki adım ardışık şekilde çalışacaksa, ikinci adım birinci tamamlanmadan başlamaz.

Ayrıca bazı tasklerde, stepler arası paylaşım gerektiren durumlar olabilir. Örneğin bir git reposunun barındırdığı dosyaların bir sonraki build stepinin işlemi tamamlayabilmesi için aktarılması; yani ortak bir volume üzerinden erişilebilmesi gerekir. Workspaces ve results kavramlarını bu yazının ileriki versiyonlarında incelediğimizde daha iyi bir kavrama sağlayacağız.

Bu durumlarda, step’lerden önce veya sonra otomatik olarak yardımcı container’lar (örneğin init ya da sidecar) çalıştırılır; bu container’lar, step’lerin paylaşacağı kaynakları hazırlar.  Bu işlemlerin durumu da yine TaskRun ve PipelineRun üstünden gözlenebilir.


İlk task’imizi yazalım.

İlk task olarak basit bir merhaba uygulaması için söyle bir tanım yapılabilir.

# first-task.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: first-task
  namespace: tekton-blog-demo
spec:
  steps:
    - name: echoing-hello
      image: alpine
      command:
        - /bin/sh
      args: ['-c', 'echo "hello for your first task"']

apiVersion, kind, metadata ve spec alanları tanıdık gelmiş olmalı ☺️

Tekton, Kubernetes’in CRD (Custom Resource Definition) yaklaşımıyla uyumlu ve native olarak herhangi bir K8s objesi gibi tanımlanabilir. Bu da öğrenmeyi, oluşturmayı ve takip etmeyi oldukça kolaylaştırır.

Task’lerin step’ler içerdiğini biliyoruz; bu yapı aslında bir pod tanımına oldukça benzemekte. Yani, bir adım (step) tanımlarken aslında bir container’ın nasıl çalışacağını belirtmiş oluyoruz.

Step ismini verdikten sonra, task çalıştırıldığında:

  • Hangi imajdan bir container oluşturulacağı,

  • Container başladığında hangi komutun çalışacağı
    belirtilmiş oluyor.

Bu örnekte, Alpine imajını kullanan echoing-hello isimli bir container oluşturulacak ve içinde bir shell ortamında echo "hello for your first task" komutu çalıştırılacak.

En yalın haliyle bir task bu şekilde oluşturulabilir.

Bunu K8s üstüne apply etmek için;

tekton-blog-demo adlı bir namespace oluşturmayı unutmayın! 😄
$ kubectl apply -f first-task.yaml

kubectl ile de oluşturulan objeyi listelemek için;

$ kubectl get tasks.tekton.dev -n tekton-blog-demo
NAME         AGE
first-task   40m

Taski yürütmek için?

Bir task yarattık fakat bu taskin yürütülmesi için bir TaskRun objesinin de yaratılması gerektiğini biliyoruz. Yine TaskRun objeside bir K8s objesi gibi aşağıdaki tanımla oluşturulabilir;

# first-task-run.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  generateName: first-task-run-
  namespace: tekton-blog-demo
spec:
  taskRef:
    name: first-task

spec alanındaki taskRef bu  TaskRun objesinin esasen hangi task ile ilişkili olduğunu belirtmekte ve generateName ilede bu Task‘in her yürütülmesinde oluşan TaskRunobjesinin sonuna – itibariyle bir suffix eklenmesini sağlamakta.

Eğer $ watch kubectl get pods -n tekton-blog-example ile ayrık bir terminalde podları izliyorsak, yukarıdaki dosyayı K8s API’sine kubectl ile gönderdigimiz anda yeni bir podun yaratıldığını görebiliriz.

$ kubectl create -f first-task-run.yaml
taskrun.tekton.dev/first-task-run4x7td created

Pod Completed statüsüne eriştiğinde task başarılı bir şekilde görevini yapmış olacaktır.

Loglara erişmek isteseydik?

K8s üzerinde log basabilen bir nesneden nasıl log alabiliyorsak aynı şekilde bir TaskRun(pod) dan’da log alabiliriz.

$ kubectl logs first-task-run4x7td-pod -n tekton-blog-demo
Defaulted container "step-echo" out of: step-echo, prepare (init)
hello for your first task

Harika! Pek bir işlevi olmayan fakat çalışan bir Tekton taski oluşturup bunu yürütebildik.

Burada Tekton’ın yapısı gereği podları oluştururken bazı init veya sidecar containerlar çalıştırdığını hatırlayalım. Loglarda da bunun sağlamasını görebiliriz.


İlk Pipeline’inimizi oluşturalım.

Taskve TaskRunkavramlarına göz attıktan sonra asıl yürüteceğimiz CI/CD süreçleri için gerekli olan ve taskleri kullanan bir Pipeline nasıl oluşturulabilir ona göz atalım.

Bize 2. bir adımı simüle etmesi için aşağıdaki gibi ikinci bir echo taski oluşturalım.

$ kubectl create -f - <<EOF
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: second-task
  namespace: tekton-blog-demo
spec:
  steps:
    - name: echo2
      image: alpine
      command: ["/bin/sh"]
      args: ["-c", 'echo "hello for your second task"']
EOF

Sonrasında Pipeline tanımını aşağıdaki gibi oluşturabiliriz.

# first-pipeline.yaml
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: first-pipeline
  namespace: tekton-blog-demo
spec:
  tasks:
    - name: echo-first
      taskRef:
        name: first-task
    - name: echo-second
      taskRef:
        name: second-task
      runAfter: [echo-first]

Klasik bir K8s obje manifesti tanımından farklı değil. taskRef anahtarının değerinin daha önce oluşturmuş olduğumuz tasklerin isimleriyle aynı olduğuna ve sadece onu refere ettiğine dikkat edelim.

Bu durum ilk baştada üzerinde durduğumuz tekrar kullanılabilirlik ilkesiyle örtüşmekte. Farklı bağlamlarda farklı amaçlar için çalışan Pipeline’lar ortak taskleri paylaşabilirler.

Pipeline’ini yürütelim.

Bir Pipeline’nin yürütülebilmesi için PipelineRun objesine ihtiyacımız olduğunu biliyoruz. Bunu da aşağıdaki gibi oluşturabiliriz.

# first-pipeline-run.yaml
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: my-first-pipeline-run-
  namespace: tekton-blog-demo
spec:
  pipelineRef:
    name: first-pipeline

Bu manifesti oluşturduğumuz anda $ kubectl get pods -n tekton-blog-demokomutunu çalıştırırsak iki yeni podun bu namespace icerisinde çalıştığını görebiliriz. Dilerseniz Completed  statüye geçtikten sonra loglarını kontrol edebilirsiniz.

Burada aklınıza şu soru gelmiş olabilir. Evet Pipeline’i yürüttük harika! Podlar oluştu fakat neyin ters gittiğini görmem gerek veya kümülatif çıktıları almam gerekiyor yada her seferinde bir TaskRun veya PipelineRunoluşturmak bu kadar zorlayıcı mı olacak soruları gelmiş olabilir. Ki haklısınızda.

Bu noktada Tekton’ın bir diğer bileşeni olan olan CLI aracına göz atalım ve ilk blogu kapatalım.

Tekton CLI.

CLI ile birlikte Tekton komponentlerini yönetebilir onlarla etkileşebiliriz. Tasklerin listelenmesi, gözlenmesi,  Pipelineların yürütülmesi veya henüz göz atmadığımız diğer objeler olan TriggerBinding, TriggerTemplate, EventListener bunların yönetimi vs.

Kurulumu için mevcut işletim sisteminin paket yöneticisini kullanabilirsiniz. Brew ile macOS üstünde kurulumu;

$ brew install tektoncd-cli ile sağlanabilir. Diğer sistemler içinse döküman linki burada.

Artık sıklıkla kullanmanız olası bir kaç komuta göz atarak kullanımını kavrayıp bu blogu kapatabiliriz.

Örneğin current-namespace içindeki taskleri listelemek;

$ tkn task list

Tüm namespaceler için listeleme;

$ tkn task list --all-namespaces

PipelineRun objelerini tüm nslerde listeleme;

$ tkn pipelinerun list --all-namespaces
NAMESPACE          NAME                          STARTED          DURATION   STATUS
tekton-blog-demo   my-first-pipeline-run-92x9r   24 minutes ago   6s         Succeeded

Az önce bahsettiğimiz kümülatif log alma sorununu da doğrudan PipelineRun objesinin loglarını alarak aşağıdaki gibi aşabiliriz;

$ tkn pipelinerun logs -n tekton-blog-demo my-first-pipeline-run-92x9r
[echo-first : echo] hello for your first task
[echo-second : echo2] hello for your second task

Yada spesifik bir Task veya Pipeline’i manifest dosyası oluşturmadan doğrudan başlatmak için;

$ tkn pipeline start -n tekton-blog-demo first-pipeline
PipelineRun started: first-pipeline-run-5kf8n
In order to track the PipelineRun progress run:
tkn pipelinerun logs first-pipeline-run-5kf8n -f -n tekton-blog-demo

Bir taski silmek;

$ tkn task delete -n tekton-blog-demo first-task

Pek tabii etkileşimde bulunulabilecek nesneler ve komutlar bunlarla sınırlı değil. Fakat kullanım mantığını ve aslında bir kubectl wrapperi olduğunu olduğunu keşfedebilmemiz önemli.

Daha fazla komut için man sayfasını bu linke ekliyorum.


Temizlik.

Sonuca geçmeden hemen önce tek tek resource silmek yerine namespacei kaldıralım.

$ kubectl delete namespace tekton-blog-demo

Sonuç.

Bu blog serisinin ilki olan bu blogda Tekton’ın modern uygulama geliştirme süreçlerinde CI/CD süreçlerinde nasıl görev alabileceğine, sağladığı avantajlara, kullanımına ve ekosistemindeki önemli araçlardan olan CLI’a göz attık.

Bir giriş niteliğindeki bu blog, ardından takip edecek olan 2-3 serilik bir seriye umarım iyi bir temel olacak.

Bir sonraki yazıda daha işlevsel olan ve günlük hayatta sıklıkla karşılaşılabilen bir image build push süreci kurgulayacak daha ileri seviye kullanımlara ve Tekton Hub’a göz atacağız.

Blog serisinin kaynak koduna aşağıdaki Github adresinden ulaşabilirsiniz.

https://github.com/EgehanGundogdu/tekton-pipeline-blog-series

Görüşmek üzere!

Tarih:Blog

İlk Yorumu Siz Yapın

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

Göster
Gizle