Setup Tekton Pipelines 0.62 for Kubernetes CI/CD with security scanning integration

Advanced 45 min Apr 25, 2026 123 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure Tekton Pipelines for cloud-native CI/CD with automated security scanning, Git webhooks, and production-ready RBAC policies. Build secure container pipelines with integrated vulnerability detection and compliance checks.

Prerequisites

  • Running Kubernetes cluster (1.24+) with cluster-admin access
  • kubectl configured and authenticated
  • Container registry credentials
  • Git repository with application source code

What this solves

Tekton Pipelines provides Kubernetes-native CI/CD automation with reusable tasks, parallel execution, and built-in security scanning. Unlike traditional CI/CD tools, Tekton runs entirely on Kubernetes, scaling automatically and integrating deeply with container workflows. This tutorial sets up Tekton 0.62 with security scanning, Git triggers, and production hardening for enterprise container deployments.

Prerequisites

  • Running Kubernetes cluster (1.24+) with cluster-admin access
  • kubectl configured to access your cluster
  • Git repository with container application source code
  • Docker registry credentials for image storage

Step-by-step installation

Install Tekton Pipelines core components

Deploy the Tekton Pipelines operator and CRDs to your Kubernetes cluster.

kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.62.0/release.yaml

Verify the installation completed successfully:

kubectl get pods --namespace tekton-pipelines
kubectl get crd | grep tekton

Install Tekton Triggers for Git webhook integration

Tekton Triggers enables automatic pipeline execution from Git events like push and pull requests.

kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/previous/v0.27.0/release.yaml
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/previous/v0.27.0/interceptors.yaml

Wait for all trigger components to be ready:

kubectl get pods --namespace tekton-pipelines-resolvers
kubectl get pods --namespace tekton-pipelines

Install Tekton Dashboard for web interface

The dashboard provides a graphical interface for managing pipelines and viewing execution logs.

kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/previous/v0.43.0/release.yaml

Create a service to access the dashboard:

apiVersion: v1
kind: Service
metadata:
  name: tekton-dashboard-external
  namespace: tekton-pipelines
spec:
  type: NodePort
  ports:
  - port: 9097
    targetPort: 9097
    nodePort: 32000
  selector:
    app.kubernetes.io/name: dashboard
    app.kubernetes.io/component: dashboard
kubectl apply -f /tmp/tekton-dashboard-service.yaml

Configure RBAC for pipeline execution

Create service accounts with minimal permissions for secure pipeline runs.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-build-sa
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: tekton-build-role
rules:
  • apiGroups: [""]
resources: ["pods", "services", "endpoints", "persistentvolumeclaims", "configmaps", "secrets"] verbs: ["get", "list", "create", "update", "delete"]
  • apiGroups: ["apps"]
resources: ["deployments", "replicasets"] verbs: ["get", "list", "create", "update", "delete"]
  • apiGroups: [""]
resources: ["pods/log"] verbs: ["get", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tekton-build-binding namespace: default subjects:
  • kind: ServiceAccount
name: tekton-build-sa namespace: default roleRef: kind: Role name: tekton-build-role apiGroup: rbac.authorization.k8s.io
kubectl apply -f /tmp/tekton-rbac.yaml

Create Docker registry secret

Configure credentials for pushing built images to your container registry.

kubectl create secret docker-registry docker-registry-secret \
  --docker-server=registry.example.com \
  --docker-username=your-username \
  --docker-password=your-password \
  --docker-email=your-email@example.com

Link the secret to the service account:

kubectl patch serviceaccount tekton-build-sa -p '{"secrets":[{"name":"docker-registry-secret"}]}'

Install security scanning tasks

Add Tekton tasks for container vulnerability scanning with Trivy and code analysis with SonarQube.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: trivy-scanner
  namespace: default
spec:
  description: Scan container images for vulnerabilities using Trivy
  params:
  - name: image-url
    description: Image URL to scan
    type: string
  - name: severity
    description: Severity levels to report
    default: "HIGH,CRITICAL"
    type: string
  steps:
  - name: scan
    image: aquasec/trivy:latest
    command:
    - trivy
    args:
    - image
    - --severity
    - $(params.severity)
    - --no-progress
    - --format
    - table
    - $(params.image-url)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: sonarqube-scanner
  namespace: default
spec:
  description: Analyze code quality with SonarQube
  params:
  - name: sonar-host-url
    description: SonarQube server URL
    type: string
  - name: sonar-project-key
    description: Project key in SonarQube
    type: string
  workspaces:
  - name: source
    description: Source code workspace
  steps:
  - name: scan
    image: sonarsource/sonar-scanner-cli:latest
    workingDir: $(workspaces.source.path)
    env:
    - name: SONAR_HOST_URL
      value: $(params.sonar-host-url)
    - name: SONAR_SCANNER_OPTS
      value: "-Xmx512m"
    command:
    - sonar-scanner
    args:
    - -Dsonar.projectKey=$(params.sonar-project-key)
    - -Dsonar.sources=.
kubectl apply -f /tmp/security-tasks.yaml

Create build and test tasks

Define reusable tasks for Git operations, container building, and application testing.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
  namespace: default
spec:
  description: Clone Git repository
  params:
  - name: url
    description: Git repository URL
    type: string
  - name: revision
    description: Git revision to check out
    default: main
    type: string
  workspaces:
  - name: output
    description: Cloned repository output
  steps:
  - name: clone
    image: alpine/git:latest
    workingDir: $(workspaces.output.path)
    command:
    - git
    args:
    - clone
    - --branch
    - $(params.revision)
    - --single-branch
    - --depth
    - "1"
    - $(params.url)
    - .
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: kaniko-build
  namespace: default
spec:
  description: Build and push container image using Kaniko
  params:
  - name: image
    description: Name of the image to build
    type: string
  - name: dockerfile
    description: Path to Dockerfile
    default: ./Dockerfile
    type: string
  workspaces:
  - name: source
    description: Source code workspace
  steps:
  - name: build-and-push
    image: gcr.io/kaniko-project/executor:latest
    workingDir: $(workspaces.source.path)
    env:
    - name: DOCKER_CONFIG
      value: /kaniko/.docker
    command:
    - /kaniko/executor
    args:
    - --dockerfile=$(params.dockerfile)
    - --context=dir://$(workspaces.source.path)
    - --destination=$(params.image)
    - --cache=true
    - --compressed-caching
    volumeMounts:
    - name: docker-config
      mountPath: /kaniko/.docker
  volumes:
  - name: docker-config
    secret:
      secretName: docker-registry-secret
      items:
      - key: .dockerconfigjson
        path: config.json
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: run-tests
  namespace: default
spec:
  description: Run application unit tests
  params:
  - name: test-command
    description: Command to run tests
    default: "npm test"
    type: string
  workspaces:
  - name: source
    description: Source code workspace
  steps:
  - name: test
    image: node:18-alpine
    workingDir: $(workspaces.source.path)
    command:
    - sh
    args:
    - -c
    - |
      npm install
      $(params.test-command)
kubectl apply -f /tmp/build-tasks.yaml

Create CI/CD pipeline with security integration

Define a complete pipeline that clones code, runs tests, builds images, performs security scans, and deploys to staging.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: secure-build-deploy
  namespace: default
spec:
  description: Secure CI/CD pipeline with vulnerability scanning
  params:
  - name: git-url
    description: Git repository URL
    type: string
  - name: git-revision
    description: Git revision
    default: main
    type: string
  - name: image-name
    description: Container image name
    type: string
  - name: sonar-host
    description: SonarQube server URL
    type: string
  - name: sonar-project
    description: SonarQube project key
    type: string
  workspaces:
  - name: shared-data
    description: Shared workspace for pipeline data
  tasks:
  - name: fetch-source
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
    params:
    - name: url
      value: $(params.git-url)
    - name: revision
      value: $(params.git-revision)
  
  - name: code-analysis
    taskRef:
      name: sonarqube-scanner
    runAfter:
    - fetch-source
    workspaces:
    - name: source
      workspace: shared-data
    params:
    - name: sonar-host-url
      value: $(params.sonar-host)
    - name: sonar-project-key
      value: $(params.sonar-project)
  
  - name: run-unit-tests
    taskRef:
      name: run-tests
    runAfter:
    - fetch-source
    workspaces:
    - name: source
      workspace: shared-data
    params:
    - name: test-command
      value: "npm test -- --coverage"
  
  - name: build-image
    taskRef:
      name: kaniko-build
    runAfter:
    - code-analysis
    - run-unit-tests
    workspaces:
    - name: source
      workspace: shared-data
    params:
    - name: image
      value: $(params.image-name):$(params.git-revision)
  
  - name: security-scan
    taskRef:
      name: trivy-scanner
    runAfter:
    - build-image
    params:
    - name: image-url
      value: $(params.image-name):$(params.git-revision)
    - name: severity
      value: "HIGH,CRITICAL"
  
  - name: deploy-staging
    runAfter:
    - security-scan
    taskSpec:
      params:
      - name: image
        type: string
      steps:
      - name: deploy
        image: bitnami/kubectl:latest
        command:
        - kubectl
        args:
        - set
        - image
        - deployment/app-staging
        - app=$(params.image)
        - --namespace=staging
    params:
    - name: image
      value: $(params.image-name):$(params.git-revision)
kubectl apply -f /tmp/secure-pipeline.yaml

Configure Git webhook triggers

Set up automatic pipeline execution when code is pushed to your Git repository.

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: github-listener
  namespace: default
spec:
  serviceAccountName: tekton-build-sa
  triggers:
  - name: github-push-trigger
    interceptors:
    - ref:
        name: "github"
      params:
      - name: "secretRef"
        value:
          secretName: github-webhook-secret
          secretKey: secretToken
      - name: "eventTypes"
        value: ["push"]
    bindings:
    - ref: github-push-binding
    template:
      ref: secure-pipeline-template
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
  name: github-push-binding
  namespace: default
spec:
  params:
  - name: git-url
    value: $(body.repository.clone_url)
  - name: git-revision
    value: $(body.head_commit.id)
  - name: image-name
    value: registry.example.com/myapp
  - name: sonar-host
    value: https://sonarqube.example.com
  - name: sonar-project
    value: myapp
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: secure-pipeline-template
  namespace: default
spec:
  params:
  - name: git-url
    description: Git repository URL
  - name: git-revision
    description: Git revision
  - name: image-name
    description: Container image name
  - name: sonar-host
    description: SonarQube server URL
  - name: sonar-project
    description: SonarQube project key
  resourcetemplates:
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: secure-build-deploy-run-
      namespace: default
    spec:
      serviceAccountName: tekton-build-sa
      pipelineRef:
        name: secure-build-deploy
      params:
      - name: git-url
        value: $(tt.params.git-url)
      - name: git-revision
        value: $(tt.params.git-revision)
      - name: image-name
        value: $(tt.params.image-name)
      - name: sonar-host
        value: $(tt.params.sonar-host)
      - name: sonar-project
        value: $(tt.params.sonar-project)
      workspaces:
      - name: shared-data
        volumeClaimTemplate:
          spec:
            accessModes:
            - ReadWriteOnce
            resources:
              requests:
                storage: 2Gi
kubectl apply -f /tmp/git-trigger.yaml

Create GitHub webhook secret

Configure webhook authentication for secure communication between GitHub and Tekton.

kubectl create secret generic github-webhook-secret \
  --from-literal=secretToken=$(openssl rand -hex 20)

Get the webhook secret for GitHub configuration:

kubectl get secret github-webhook-secret -o jsonpath='{.data.secretToken}' | base64 -d

Expose webhook endpoint

Create an ingress or service to make the EventListener accessible from GitHub.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tekton-webhook
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - tekton-webhooks.example.com
    secretName: tekton-webhook-tls
  rules:
  - host: tekton-webhooks.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: el-github-listener
            port:
              number: 8080
kubectl apply -f /tmp/webhook-ingress.yaml

Configure monitoring and alerting

Set up Prometheus monitoring for pipeline metrics and failure alerts.

apiVersion: v1
kind: ServiceMonitor
metadata:
  name: tekton-pipelines
  namespace: tekton-pipelines
  labels:
    app: tekton-pipelines
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: controller
  endpoints:
  - port: http-metrics
    path: /metrics
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: tekton-pipeline-alerts
  namespace: tekton-pipelines
spec:
  groups:
  - name: tekton.rules
    rules:
    - alert: TektonPipelineFailure
      expr: increase(tekton_pipelinerun_count{status="failed"}[5m]) > 0
      for: 0m
      labels:
        severity: warning
      annotations:
        summary: "Tekton pipeline failure detected"
        description: "Pipeline {{ $labels.pipeline }} has failed in namespace {{ $labels.namespace }}"
    - alert: TektonHighFailureRate
      expr: |
        (
          rate(tekton_pipelinerun_count{status="failed"}[30m]) /
          rate(tekton_pipelinerun_count[30m])
        ) > 0.5
      for: 10m
      labels:
        severity: critical
      annotations:
        summary: "High Tekton pipeline failure rate"
        description: "Pipeline failure rate is {{ $value | humanizePercentage }} over the last 30 minutes"
kubectl apply -f /tmp/tekton-monitoring.yaml

Configure security scanning integration

Set up SonarQube integration

Configure SonarQube authentication and quality gates for automated code analysis.

kubectl create secret generic sonarqube-auth \
  --from-literal=token=your-sonarqube-token

Update the SonarQube scanner task with authentication:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: sonarqube-scanner
  namespace: default
spec:
  description: Analyze code quality with SonarQube authentication
  params:
  - name: sonar-host-url
    description: SonarQube server URL
    type: string
  - name: sonar-project-key
    description: Project key in SonarQube
    type: string
  workspaces:
  - name: source
    description: Source code workspace
  steps:
  - name: scan
    image: sonarsource/sonar-scanner-cli:latest
    workingDir: $(workspaces.source.path)
    env:
    - name: SONAR_HOST_URL
      value: $(params.sonar-host-url)
    - name: SONAR_TOKEN
      valueFrom:
        secretKeyRef:
          name: sonarqube-auth
          key: token
    - name: SONAR_SCANNER_OPTS
      value: "-Xmx1024m"
    command:
    - sonar-scanner
    args:
    - -Dsonar.projectKey=$(params.sonar-project-key)
    - -Dsonar.sources=.
    - -Dsonar.qualitygate.wait=true
kubectl apply -f /tmp/sonarqube-auth-patch.yaml

Configure vulnerability scanning policies

Set up Trivy scanning with severity thresholds and policy enforcement. Learn more about container security in our Trivy security scanning guide.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: trivy-policy-scanner
  namespace: default
spec:
  description: Scan images and enforce security policies
  params:
  - name: image-url
    description: Image URL to scan
    type: string
  - name: fail-on-severity
    description: Fail pipeline on severity level
    default: "CRITICAL"
    type: string
  - name: max-critical
    description: Maximum critical vulnerabilities allowed
    default: "0"
    type: string
  - name: max-high
    description: Maximum high vulnerabilities allowed
    default: "5"
    type: string
  results:
  - name: scan-result
    description: Scan result summary
  steps:
  - name: scan
    image: aquasec/trivy:latest
    env:
    - name: TRIVY_NO_PROGRESS
      value: "true"
    - name: TRIVY_CACHE_DIR
      value: /tmp/trivy-cache
    script: |
      #!/bin/sh
      set -e
      
      echo "Scanning image $(params.image-url)..."
      
      # Perform scan and save results
      trivy image --format json --output /tmp/scan-results.json $(params.image-url)
      trivy image --format table $(params.image-url)
      
      # Parse results and enforce policies
      critical=$(jq '.Results[].Vulnerabilities[]? | select(.Severity=="CRITICAL") | .VulnerabilityID' /tmp/scan-results.json | wc -l || echo "0")
      high=$(jq '.Results[].Vulnerabilities[]? | select(.Severity=="HIGH") | .VulnerabilityID' /tmp/scan-results.json | wc -l || echo "0")
      
      echo "Found $critical CRITICAL and $high HIGH vulnerabilities"
      
      # Check against thresholds
      if [ "$critical" -gt "$(params.max-critical)" ]; then
        echo "❌ CRITICAL vulnerabilities ($critical) exceed limit ($(params.max-critical))"
        exit 1
      fi
      
      if [ "$high" -gt "$(params.max-high)" ]; then
        echo "❌ HIGH vulnerabilities ($high) exceed limit ($(params.max-high))"
        exit 1
      fi
      
      echo "✅ Security scan passed policy checks"
      echo -n "PASSED: $critical critical, $high high vulnerabilities" > $(results.scan-result.path)
    volumeMounts:
    - name: trivy-cache
      mountPath: /tmp/trivy-cache
  volumes:
  - name: trivy-cache
    emptyDir: {}
kubectl apply -f /tmp/trivy-policy-task.yaml

Production security hardening

Configure network policies

Implement Kubernetes network policies to restrict traffic between pipeline components.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tekton-pipelines-netpol
  namespace: tekton-pipelines
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/part-of: tekton-pipelines
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: tekton-pipelines
    - namespaceSelector:
        matchLabels:
          name: default
  egress:
  - to: []
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  - to: []
    ports:
    - protocol: TCP
      port: 443
    - protocol: TCP
      port: 80
  - to:
    - namespaceSelector:
        matchLabels:
          name: tekton-pipelines
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tekton-builds-netpol
  namespace: default
spec:
  podSelector:
    matchLabels:
      tekton.dev/pipeline: secure-build-deploy
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: tekton-pipelines
  egress:
  - to: []
    ports:
    - protocol: TCP
      port: 443
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
kubectl apply -f /tmp/tekton-network-policy.yaml

Configure Pod Security Standards

Enforce Pod Security Standards to prevent privilege escalation and ensure secure container execution.

apiVersion: v1
kind: Namespace
metadata:
  name: tekton-secure
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tekton-restricted-sa
  namespace: tekton-secure
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: tekton-restricted-psp
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
  - ALL
  volumes:
  - 'configMap'
  - 'emptyDir'
  - 'projected'
  - 'secret'
  - 'downwardAPI'
  - 'persistentVolumeClaim'
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'RunAsAny'
  fsGroup:
    rule: 'RunAsAny'
  seccompProfile:
    type: RuntimeDefault
kubectl apply -f /tmp/tekton-pod-security.yaml

Configure resource limits and quotas

Set resource limits to prevent resource exhaustion and ensure fair resource allocation.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: tekton-pipeline-quota
  namespace: default
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "10"
    persistentvolumeclaims: "5"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: tekton-pipeline-limits
  namespace: default
spec:
  limits:
  - default:
      cpu: 500m
      memory: 1Gi
    defaultRequest:
      cpu: 100m
      memory: 256Mi
    type: Container
  - max:
      cpu: "2"
      memory: 4Gi
    min:
      cpu: 50m
      memory: 128Mi
    type: Container
kubectl apply -f /tmp/tekton-resource-limits.yaml

Verify your setup

Test the complete pipeline installation and security integration:

# Check all Tekton components are running
kubectl get pods -n tekton-pipelines
kubectl get pods -n tekton-pipelines-resolvers

Verify CRDs are installed

kubectl get crd | grep tekton

Test pipeline execution

kubectl create -f - <

Check pipeline execution status:

# Monitor pipeline runs
kubectl get pipelinerun
kubectl describe pipelinerun $(kubectl get pipelinerun -o name | head -1)

View pipeline logs

tkn pipelinerun logs --last -f

Check security scan results

kubectl get taskrun -l tekton.dev/task=trivy-policy-scanner

Access the Tekton Dashboard:

# Forward dashboard port
kubectl port-forward -n tekton-pipelines svc/tekton-dashboard 9097:9097

Open browser to http://localhost:9097

Common issues

Symptom Cause Fix
Pipeline fails with "unauthorized" error Insufficient RBAC permissions Check service account permissions: kubectl describe rolebinding tekton-build-binding
Image push fails during build Invalid registry credentials Verify secret: kubectl get secret docker-registry-secret -o yaml
Security scan task times out Network policies blocking egress Add registry access to network policy: kubectl edit networkpolicy tekton-builds-netpol
Webhook not receiving events EventListener service not exposed Check ingress: kubectl get ingress tekton-webhook and verify GitHub webhook URL
SonarQube analysis fails Missing authentication token Update secret: kubectl create secret generic sonarqube-auth --from-literal=token=new-token --dry-run=client -o yaml | kubectl apply -f -
Pod creation blocked Pod Security Standards violation Review security context: kubectl describe pod failing-pod-name

Next steps

Running this in production?

Running CI/CD at scale? Setting up Tekton once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle managed devops services for businesses that depend on uptime. From initial setup to ongoing operations.