Introduction à Tekton

Photo by Jannes Glas from Unsplash

TL;DR Tekton Pipelines est un projet open-source qui permet de configurer et d'exécuter des pipelines CI/CD sur Kubernetes. C'est un projet porté par la CD Foundation. Il sert de base à plusieurs solutions comme Google Cloud Build ou OpenShift Pipelines. Tekton Pipelines permet de construire, tester et déployer toute sorte d'artefacts, y compris des binaires, des VM, des fonctions serverless ou biensur des images de containers pour Kubernetes. Cet article montre comment installer et utiliser Tekton._

La démonstration ci-dessous est disponible dans le projet easyteam-fr/side-effect dans le répertoire blog/tekton-introduction ; Vous y trouverez en particulier l'ensemble des fichiers d'exemple. N'hésitez pas à le consulter.

Les référentiels de Tekton Pipelines sont disponibles sur github.com/tektoncd, y compris la documentation qui explique comment les différents composants fonctionnent. Dans les sections ci-dessous, vous trouverez:

  • Une description des éléments principaux de Tekton
  • Une présentation de l'installation de Tekton
  • La création d'une PipelineResource
  • La création d'une Task
  • Une déclaration d'informations d'authentification
  • La création d'une TaskRun pour exécuter une opération simple

Les principaux éléments de Tekton

La figure suivante vous présente les différents composants d'un pipeline Tekton:

Tekton Pipelines

Tekton est une application Kubernetes. A ce titre, elle crée des resources personnalisées ou Custom Resources qui définissent les composants qui forment les pipelines CI/CD. Les différentes Custom Resources de Tekton sont:

  • Une PipelineResource, de type input comme un référentiel git ou output comme un référentiel d'images docker, permet de lier les pipelines aux composants sources et cibles de ceux-ci.
  • Une Task définit un ensemble d'étapes telles que la compilation d'un programme, l'exécution de tests ou la création d'un artefact
  • Un Pipeline un ensemble de tâches qui peuvent s'exécuter successivement ou en parallèle
  • Une TaskRun et un PipelineRun correspondent à l'exécution d'une Task ou d'un Pipeline. Ils font référence à différents composants comme les PipelineResource à utiliser ou certains paramètres.

Avant d'installer Tekton

Tekton suppose que vous disposez d'un environnement Kubernetes relativement récent. Pour faire un test, vous pourrez installer Kind comme dans l'article Kind et build Kubernetes. Quoiqu'il en soit, vous devrez avoir accès à un client kubectl et un cluster Kubernetes comme ci-dessous:

kubectl version --short
Client Version: v1.17.2
Server Version: v1.17.0

Installation de Tekton

Pour installer Tekton il suffit de se rendre sur la documentation d'installation. Il n'est pas nécessaire de cloner le projet ; il suffit d'appliquer le fichier manifeste mis à disposition sur GCP comme ci-dessous:

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

Vous pouvez vérifier que les pods correspondants au controller et au webhook sont correctement démarrés à l'aide de la commande ci-dessous:

kubectl get pods --namespace tekton-pipelines

Vous pouvez également vérifier que les définitions des ressources Tekton on été correctement créées à l'aide de la commande ci-dessous:

kubectl api-resources --api-group=tekton.dev

NAME                SHORTNAMES   APIGROUP     NAMESPACED   KIND
clustertasks                     tekton.dev   false        ClusterTask
conditions                       tekton.dev   true         Condition
pipelineresources                tekton.dev   true         PipelineResource
pipelineruns        pr,prs       tekton.dev   true         PipelineRun
pipelines                        tekton.dev   true         Pipeline
taskruns            tr,trs       tekton.dev   true         TaskRun
tasks                            tekton.dev   true         Task

Dans les sections qui suivent vous pourrez trouver comment utiliser une Task simple pour un premier aperçu de son fonctionnement.

Ressources Github et Docker

Pour connecter Tekton à des référentiels externes, il convient de créer des PipelineResources. Par exemple, on pourra créer:

  • la connexion à un référentiel Github pour télécharger le code d'une application
  • la connexion à une registry docker pour stocker des images

Ci-dessous un exemple de ressource pour le référentiel Github easyteam-fr/side-effects

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: side-effects
spec:
  type: git
  params:
    - name: revision
      value: master
    - name: url
      value: https://github.com/easyteam-fr/side-effects/

Une seconde ressource correspond à un repository sur le hub docker. Vous pouvez remplacer la propriété value avec l'URL de votre repository docker Hub mais aussi selon le besoin celle de ECR, GCR ou encore Quay.io:

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: hi-image
spec:
  type: image
  params:
    - name: url
      value: easyteam/hi:tekton

Pour créer ces ressources, vous pourrez lancer les commandes ci-dessous:

kubectl apply -f github.yaml
kubectl apply -f docker-registry.yaml

Definition d'une Task

Une Task est un ensemble d'étapes séquentielles qui s'exécutent. Elle contient différentes étapes ou Steps ainsi que des références à des Inputs et Output. Lorsqu'elle s'exécute, une task s'exécute entièrement dans un Pod.

L'exemple qui suit présente une Task qui s'appuie sur le projet Kaniko pour construire une image Docker à partir d'un repository. Celle-ci inclut en entrée:

  • Une ressource qui permettra de faire le lien avec un projet Git
  • Un paramètre indiquant le contexte ou répertoire dans lequel le docker doit être construit
  • Un paramètre indiquant l'emplacement du fichier Dockerfile
# task.yaml
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: build-docker-image-from-git-source
spec:
  inputs:
    resources:
      - name: myproject
        type: git
    params:
      - name: pathToDockerFile
        type: string
        description: The path to the dockerfile to build
        default: /workspace/docker-source/Dockerfile
      - name: pathToContext
        type: string
        description:
          The build context used by Kaniko
        default: /workspace/docker-source
  outputs:
    resources:
      - name: builtImage
        type: image
  steps:
    - name: build-and-push
      image: gcr.io/kaniko-project/executor:v0.18.0
      # specifying DOCKER_CONFIG is required to allow kaniko
      # to detect docker credential
      env:
        - name: "DOCKER_CONFIG"
          value: "/tekton/home/.docker/"
      command:
        - /kaniko/executor
      args:
        - --dockerfile=$(inputs.params.pathToDockerFile)
        - --destination=$(outputs.resources.builtImage.url)
        - --context=$(inputs.params.pathToContext)

Appliquer le fichier de manifest ci-dessus pour créer la Task:

kubectl apply -f task.yaml

Secret et ServiceAccount

La méthode pour se connecter à la registry docker peut varier selon la solution. Dans le cas du Hub docker, vous pouvez simplement créer un Token associé à votre profile et l'ajouter dans un secret que l'on nommera par exemple dockerhub comme ci-dessous:

apiVersion: v1
kind: Secret
metadata:
  name: dockerhub
  annotations:
    tekton.dev/docker-0: https://index.docker.io/v1/
type: kubernetes.io/basic-auth
stringData:
  username: <username>
  password: <password>

Vous pouvez créer un fichier docker-credentials.yaml à partir du fichier docker-credentials-template.yaml, le modifier et l'appliquer comme ci-dessous:

kubectl apply -f secret.yaml

Les composants d'exécution utilisent les secrets auxquels ils ont accès tels que définis dans le ServiceAccount pour se connecter à la registry docker. On créera donc un compte de service à l'aide du manifeste ci-dessous:

# serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton
secrets:
  - name: dockerhub

Pour créer le compte de service, exécutez:

kubectl apply -f serviceaccount.yaml

Création d'une TaskRun

Une TaskRun est une instance d'exécution d'une Task. A ce titre, elle doit référencer la Task mais aussi les ressources et les paramètres en entrée et en sortie. Le fichier ci-dessous propose un exemple d'exécution de tâche:

apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  name: build-01
spec:
  serviceAccountName: tekton
  taskRef:
    name: build-docker-image-from-git-source
  inputs:
    resources:
      - name: myproject
        resourceRef:
          name: side-effects
    params:
      - name: pathToDockerFile
        value: /workspace/myproject/blog/go-hi/Dockerfile
      - name: pathToContext
        value: /workspace/myproject/blog/go-hi
  outputs:
    resources:
      - name: builtImage
        resourceRef:
          name: hi-image
  • serviceAccountName correspond compte de service utilisé qui donne notamment accès au secret pour accéder à la registry docker
  • taskRef référence le nom de la Task créée précédemment
  • inputs.resources.resourceRef.name correspond à la PipelineResource du projet easyteam-fr/side-effects sur Github
  • inputs.params.value correspond au chemin et au contexte Docker pour le répertoire dans le projet Github
  • output.resources.resourceRef.name correspond à la registry docker créé à l'aide de la PipelineResource.

Pour créer la TaskRun, lancez la commande ci-dessous:

kubectl apply -f taskrun.yaml

Superviser l'exécution

Vous pouvez vérifier que l'exécution de la tâche est bien démarrée à l'aide de la commande ci-dessous:

kubectl get tr

Pour superviser l'exécution des différents containers du Pod qui crée l'image docker avec Kaniko, vous pouvez lancez la commande ci-dessous:

kubectl logs \
  $(kubectl get tr -o custom-columns=pod:status.podName --no-headers) \
  -c step-build-and-push

Vous trouverez ci-dessous un exemple de message associé:

INFO[0000] Resolved base name golang to golang          
INFO[0000] Resolved base name debian to debian          
INFO[0000] Resolved base name golang to golang          
INFO[0000] Resolved base name debian to debian          
INFO[0000] Retrieving image manifest golang             
INFO[0000] Retrieving image manifest golang             
INFO[0000] Retrieving image manifest debian             
INFO[0000] Retrieving image manifest debian             
INFO[0001] Built cross stage deps: map[0:[/src/hi]]     
INFO[0001] Retrieving image manifest golang             
INFO[0001] Retrieving image manifest golang             
INFO[0001] Unpacking rootfs as cmd COPY . /src/ requires it. 
INFO[0014] Taking snapshot of full filesystem...        
INFO[0017] Resolving paths                              
INFO[0020] COPY . /src/                                 
INFO[0020] Resolving paths                              
INFO[0020] Taking snapshot of files...                  
INFO[0020] RUN cd /src && GO111MODULE=on go build -o hi . 
INFO[0020] cmd: /bin/sh                                 
INFO[0020] args: [-c cd /src && GO111MODULE=on go build -o hi .] 
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: downloading github.com/labstack/gommon v0.3.0
go: downloading golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
go: downloading github.com/valyala/fasttemplate v1.1.0
go: downloading github.com/dgrijalva/jwt-go v3.2.0+incompatible
go: downloading github.com/valyala/bytebufferpool v1.0.0
go: downloading github.com/mattn/go-colorable v0.1.2
go: downloading github.com/mattn/go-isatty v0.0.9
go: downloading golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a
go: downloading golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
go: downloading golang.org/x/text v0.3.0
INFO[0025] Taking snapshot of full filesystem...        
INFO[0025] Resolving paths                              
INFO[0029] Saving file /src/hi for later use            
INFO[0029] Deleting filesystem...                       
INFO[0030] Retrieving image manifest debian             
INFO[0030] Retrieving image manifest debian             
INFO[0030] Unpacking rootfs as cmd COPY --from=build /src/hi /app/ requires it. 
INFO[0032] Taking snapshot of full filesystem...        
INFO[0033] Resolving paths                              
INFO[0034] WORKDIR /app                                 
INFO[0034] cmd: workdir                                 
INFO[0034] Changed working directory to /app            
INFO[0034] Creating directory /app                      
INFO[0034] Resolving paths                              
INFO[0034] Taking snapshot of files...                  
INFO[0034] COPY --from=build /src/hi /app/              
INFO[0034] Resolving paths                              
INFO[0034] Taking snapshot of files...                  
INFO[0034] ENTRYPOINT ./hi                              

Vous pouvez vérifier les logs de autres containers du pod si besoin. Si votre configuration est correcte, la TaskRun réussi après quelques secondes d'exécution.

Pour aller plus loin

Cet article montre comment installer et utiliser Tekton avec un exemple simple. Ainsi, vous pouvez créer des modèles réutilisables sur d'autres projets.

Si vous voulez en savoir plus, n'hésitez pas:

Easyteam DevOps

Easyteam DevOps