Deploy Kubernetes-native CI/CD pipelines on RamNode VPS. Build flexible, cloud-native pipelines with reusable Tasks and Kubernetes primitives.
Tekton is a powerful, Kubernetes-native CI/CD framework that provides a flexible and extensible platform for building continuous integration and delivery systems. Unlike traditional CI/CD tools, Tekton leverages Kubernetes primitives to create cloud-native pipelines that are portable, scalable, and vendor-neutral.
Built specifically for Kubernetes environments
Share pipeline tasks across multiple projects
No lock-in to specific cloud providers
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install required utilities
sudo apt install -y curl wget git apt-transport-https ca-certificates gnupg lsb-release
# Disable swap (required for Kubernetes)
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstabConfigure firewall:
# Install UFW if not already installed
sudo apt install -y ufw
# Allow SSH
sudo ufw allow 22/tcp
# Allow Kubernetes API server
sudo ufw allow 6443/tcp
# Allow NodePort services range
sudo ufw allow 30000:32767/tcp
# Enable firewall
sudo ufw --force enableK3s is ideal for VPS environments - lightweight while maintaining full Kubernetes compatibility.
# Install K3s
curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
# Verify installation
sudo systemctl status k3s
# Set up kubectl access for non-root user
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
export KUBECONFIG=~/.kube/config
# Verify cluster is running
kubectl get nodesTekton Pipelines is the core component that provides the CI/CD engine:
# Install Tekton Pipelines
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
# Wait for Tekton components to be ready
kubectl wait --for=condition=Ready pods --all -n tekton-pipelines --timeout=300s
# Verify installation
kubectl get pods -n tekton-pipelinesYou should see tekton-pipelines-controller and tekton-pipelines-webhook in Running state.
Tekton Triggers enables event-driven pipelines from webhooks:
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
# Install Tekton Triggers Interceptors
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml
# Wait for components to be ready
kubectl wait --for=condition=Ready pods --all -n tekton-pipelines --timeout=300s
# Verify installation
kubectl get pods -n tekton-pipelineskubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml
# Wait for dashboard to be ready
kubectl wait --for=condition=Ready pods -l app=tekton-dashboard -n tekton-pipelines --timeout=300s
# Verify dashboard is running
kubectl get pods -n tekton-pipelines -l app=tekton-dashboardkubectl port-forward -n tekton-pipelines svc/tekton-dashboard 9097:9097 --address 0.0.0.0
# Access at: http://your-vps-ip:9097cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: tekton-dashboard-nodeport
namespace: tekton-pipelines
spec:
type: NodePort
selector:
app: tekton-dashboard
ports:
- port: 9097
targetPort: 9097
nodePort: 30080
EOF
# Access at: http://your-vps-ip:30080# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.3/cert-manager.yaml
kubectl wait --for=condition=Ready pods --all -n cert-manager --timeout=300s
# Create ClusterIssuer
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: traefik
EOF
# Create Ingress with TLS
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tekton-dashboard-ingress
namespace: tekton-pipelines
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
tls:
- hosts:
- tekton.yourdomain.com
secretName: tekton-dashboard-tls
rules:
- host: tekton.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tekton-dashboard
port:
number: 9097
EOF# Download and install tkn
curl -LO https://github.com/tektoncd/cli/releases/download/v0.33.0/tkn_0.33.0_Linux_x86_64.tar.gz
# Extract and install
sudo tar xvzf tkn_0.33.0_Linux_x86_64.tar.gz -C /usr/local/bin/ tkn
# Verify installation
tkn version
# Clean up
rm tkn_0.33.0_Linux_x86_64.tar.gzCreate a Task (building block of pipelines):
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone-and-list
spec:
params:
- name: repo-url
type: string
description: The Git repository URL to clone
- name: revision
type: string
description: The Git revision to checkout
default: main
workspaces:
- name: source
description: Workspace to clone repo into
steps:
- name: clone
image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2
script: |
#!/usr/bin/env sh
set -ex
cd \$(workspaces.source.path)
git clone \$(params.repo-url) .
git checkout \$(params.revision)
- name: list-files
image: alpine:latest
script: |
#!/usr/bin/env sh
echo "Repository contents:"
ls -la \$(workspaces.source.path)
EOFCreate a Pipeline:
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: clone-and-build
spec:
params:
- name: repo-url
type: string
description: Repository URL to clone
- name: revision
type: string
description: Git revision to checkout
default: main
workspaces:
- name: shared-data
description: Shared workspace for tasks
tasks:
- name: fetch-source
taskRef:
name: git-clone-and-list
params:
- name: repo-url
value: \$(params.repo-url)
- name: revision
value: \$(params.revision)
workspaces:
- name: source
workspace: shared-data
EOFRun the Pipeline:
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: clone-and-build-run-1
spec:
pipelineRef:
name: clone-and-build
params:
- name: repo-url
value: https://github.com/tektoncd/pipeline.git
- name: revision
value: main
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
EOF
# Monitor pipeline execution
tkn pipelinerun logs clone-and-build-run-1 -fCreate Docker registry secret:
kubectl create secret docker-registry docker-credentials \
--docker-server=https://index.docker.io/v1/ \
--docker-username=your-dockerhub-username \
--docker-password=your-dockerhub-password \
--docker-email=your-email@example.comCreate build and push Task:
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-and-push
spec:
params:
- name: image-name
type: string
description: The name of the image to build
- name: dockerfile
type: string
description: Path to the Dockerfile
default: ./Dockerfile
workspaces:
- name: source
description: Workspace containing the source code
steps:
- name: build-and-push
image: gcr.io/kaniko-project/executor:latest
env:
- name: DOCKER_CONFIG
value: /kaniko/.docker
command:
- /kaniko/executor
args:
- --dockerfile=\$(params.dockerfile)
- --context=\$(workspaces.source.path)
- --destination=\$(params.image-name)
volumeMounts:
- name: docker-credentials
mountPath: /kaniko/.docker
volumes:
- name: docker-credentials
secret:
secretName: docker-credentials
items:
- key: .dockerconfigjson
path: config.json
EOFCreate complete CI/CD Pipeline:
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: full-cicd-pipeline
spec:
params:
- name: repo-url
type: string
- name: revision
default: main
- name: image-name
type: string
workspaces:
- name: shared-workspace
tasks:
- name: clone-repository
taskRef:
name: git-clone-and-list
params:
- name: repo-url
value: \$(params.repo-url)
- name: revision
value: \$(params.revision)
workspaces:
- name: source
workspace: shared-workspace
- name: build-push-image
taskRef:
name: build-and-push
runAfter:
- clone-repository
params:
- name: image-name
value: \$(params.image-name)
workspaces:
- name: source
workspace: shared-workspace
EOFEnable automatic pipeline execution from Git webhooks:
# Create Service Account
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: tekton-triggers-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: tekton-triggers-clusterrole
rules:
- apiGroups: ["triggers.tekton.dev"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["tekton.dev"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tekton-triggers-binding
subjects:
- kind: ServiceAccount
name: tekton-triggers-sa
namespace: default
roleRef:
kind: ClusterRole
name: tekton-triggers-clusterrole
apiGroup: rbac.authorization.k8s.io
EOF
# Create TriggerBinding
cat <<EOF | kubectl apply -f -
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-push-binding
spec:
params:
- name: gitrevision
value: \$(body.head_commit.id)
- name: gitrepositoryurl
value: \$(body.repository.clone_url)
EOF
# Create TriggerTemplate
cat <<EOF | kubectl apply -f -
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: github-pipeline-template
spec:
params:
- name: gitrevision
- name: gitrepositoryurl
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: github-run-
spec:
pipelineRef:
name: clone-and-build
params:
- name: repo-url
value: \$(tt.params.gitrepositoryurl)
- name: revision
value: \$(tt.params.gitrevision)
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
EOF
# Create EventListener
cat <<EOF | kubectl apply -f -
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: github-listener
spec:
serviceAccountName: tekton-triggers-sa
triggers:
- name: github-push
bindings:
- ref: github-push-binding
template:
ref: github-pipeline-template
EOFExpose EventListener:
# Get EventListener service
kubectl get svc el-github-listener
# Expose via NodePort
kubectl patch svc el-github-listener -p '{"spec":{"type":"NodePort"}}'
# Get the NodePort
kubectl get svc el-github-listener -o jsonpath='{.spec.ports[0].nodePort}'
# Configure GitHub webhook to: http://your-vps-ip:NODEPORTSet resource limits for tasks:
spec:
steps:
- name: build
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 1Gi
cpu: 500mRun independent tasks in parallel:
tasks:
- name: test-unit
taskRef:
name: run-tests
- name: test-integration
taskRef:
name: run-integration-tests
# Both run in parallel - no runAfter dependencyUse persistent workspaces:
workspaces:
- name: source
persistentVolumeClaim:
claimName: tekton-workspace-pvcCreate dedicated service accounts:
kubectl create serviceaccount pipeline-sa
# Bind necessary permissions
kubectl create rolebinding pipeline-sa-binding \
--clusterrole=edit \
--serviceaccount=default:pipeline-saUse Kubernetes secrets for sensitive data:
# Create secret
kubectl create secret generic api-key --from-literal=token=your-api-key
# Reference in task
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: api-key
key: tokenApply network policies:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tekton-pipeline-policy
namespace: tekton-pipelines
spec:
podSelector:
matchLabels:
app: tekton-pipelines
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector: {}
egress:
- to:
- namespaceSelector: {}kubectl get pods -n tekton-pipelines
kubectl describe pod <pod-name> -n tekton-pipelines
kubectl logs <pod-name> -n tekton-pipelineskubectl top nodes
kubectl top pods -n tekton-pipelines
kubectl describe pod <pod-name> -n tekton-pipelineskubectl get pvc
kubectl describe pvc <pvc-name>
# Clean up old PVCs
kubectl delete pvc --all
# Or delete old pipeline runs (keeps last 5)
tkn pipelinerun delete --keep 5# Update Tekton components
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
# Restart components
kubectl rollout restart deployment -n tekton-pipelines
# List all pipeline runs
tkn pipelinerun list
# View detailed pipeline run
tkn pipelinerun describe <pipelinerun-name>
# View pipeline logs
tkn pipelinerun logs <pipelinerun-name>
# Export for backup
kubectl get tasks,pipelines,pipelineruns -o yaml > tekton-backup.yaml