# GitLab Job Runner Operator Kubernetes operator for executing code from GitLab repositories as one-time Jobs or scheduled CronJobs. ## Features - Execute scripts from GitLab repositories as Kubernetes Jobs - Schedule recurring executions using CronJobs - Secure credential management through Kubernetes Secrets - Support for custom container images and service accounts - Automatic cleanup with finalizers ## Architecture The operator watches for `GitlabJobRunner` custom resources and: 1. Clones the specified GitLab repository using credentials from a Secret 2. Creates either a Job (one-time) or CronJob (scheduled) based on the spec 3. Executes the specified script from the repository 4. Manages lifecycle and status updates ## Prerequisites - Kubernetes cluster (1.24+) - kubectl configured - GitLab repository with scripts - GitLab access token with read permissions ## Installation ### Using Helm (Recommended) ```bash # Install from local chart helm install gitlab-job-runner ./helm/gitlab-job-runner \ --namespace gitlab-job-runner-system \ --create-namespace # Or with custom values helm install gitlab-job-runner ./helm/gitlab-job-runner \ --namespace gitlab-job-runner-system \ --create-namespace \ --set image.repository=your-registry/gitlab-job-runner \ --set image.tag=0.1.0 ``` ### Using Make ```bash # Apply CRDs make install # Deploy operator make deploy IMG=your-registry/gitlab-job-runner:latest ``` ### Create GitLab Credentials Secret ```bash kubectl create secret generic gitlab-credentials \ --from-literal=GITLAB_URL=https://gitlab.example.com \ --from-literal=GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx ``` ### Create Service Account for Script Execution If your scripts need to interact with Kubernetes API: ```bash kubectl apply -f config/samples/example_serviceaccount.yaml ``` ## Usage ### One-time Job Example ```yaml apiVersion: batch.rml.ru/v1alpha1 kind: GitlabJobRunner metadata: name: cleanup-job spec: gitlabSecretRef: gitlab-credentials repositoryURL: https://gitlab.example.com/mygroup/myrepo.git branch: main scriptPath: scripts/cleanup.sh serviceAccountName: backup-sa ``` ### CronJob Example ```yaml apiVersion: batch.rml.ru/v1alpha1 kind: GitlabJobRunner metadata: name: backup-cronjob spec: schedule: "0 2 * * *" gitlabSecretRef: gitlab-credentials repositoryURL: https://gitlab.example.com/mygroup/myrepo.git branch: main scriptPath: scripts/backup.sh serviceAccountName: backup-sa suspend: false concurrencyPolicy: Forbid ``` ### Apply the Resource ```bash kubectl apply -f your-gitlabjobrunner.yaml ``` ## Custom Resource Specification ### GitlabJobRunnerSpec | Field | Type | Required | Description | |----------------------|---------|----------|-------------------------------------------------------------------------------| | `schedule` | string | No | Cron schedule for recurring jobs. If empty, runs as one-time Job | | `gitlabSecretRef` | string | Yes | Name of Secret containing GITLAB_URL and GITLAB_TOKEN | | `repositoryURL` | string | Yes | GitLab repository (full URL or relative path like "group/project") | | `branch` | string | No | Git branch to checkout (default: "main") | | `scriptPath` | string | Yes | Relative path to script in repository | | `image` | string | No | Container image for git clone (default: "bitnami/git:latest") | | `serviceAccountName` | string | No | ServiceAccount for pod execution (default: "default") | | `suspend` | boolean | No | Suspend CronJob execution (CronJobs only) | | `concurrencyPolicy` | string | No | How to handle concurrent executions: Forbid, Allow, Replace (default: Forbid) | ### GitlabJobRunnerStatus | Field | Type | Description | |--------------------|-------------|----------------------------------------| | `conditions` | []Condition | Current state conditions | | `lastScheduleTime` | Time | Last time job was scheduled (CronJobs) | | `activeJobName` | string | Name of currently running job | ## Script Requirements Your script in the GitLab repository should: - Be executable (`chmod +x`) - Use `#!/bin/sh` or `#!/bin/bash` shebang - Have kubectl binary available (uses `bitnami/kubectl:latest` image) - Use service account permissions for Kubernetes operations ### Example Script ```bash #!/bin/bash set -e # Wait for resource deletion kubectl delete deployment old-app --ignore-not-found=true kubectl wait --for=delete deployment/old-app --timeout=300s # Apply new resources kubectl apply -f manifests/new-app.yaml kubectl wait --for=condition=available deployment/new-app --timeout=300s echo "Deployment complete" ``` ## Development ### Prerequisites - Go 1.24+ - Kubebuilder - Docker ### Build ```bash # Generate CRDs and manifests make generate make manifests # Build operator image make docker-build IMG=your-registry/gitlabjobrunner-operator:latest # Push image make docker-push IMG=your-registry/gitlabjobrunner-operator:latest ``` ### Testing ```bash # Run tests make test # Run e2e tests make test-e2e ``` ## Monitoring The operator exposes metrics on port 8443 (HTTPS) by default: - Custom resource reconciliation metrics - Job/CronJob creation status - GitLab access errors ## Security Considerations 1. **GitLab Token**: Store in Kubernetes Secret, use read-only tokens with minimal scope 2. **Service Account**: Grant only necessary permissions for script operations 3. **Network Policies**: Restrict pod network access if needed 4. **Image Security**: Use trusted container images, enable image scanning ## Troubleshooting ### Check Operator Logs ```bash kubectl logs -n cronjob-restore-system deployment/cronjob-restore-controller-manager ``` ### Check Job/CronJob Status ```bash kubectl get jobs,cronjobs kubectl describe job ``` ### Check GitlabJobRunner Status ```bash kubectl get gitlabjobrunner kubectl describe gitlabjobrunner ``` ### Common Issues - **Git clone fails**: Verify GitLab credentials in Secret - **Script not found**: Check repositoryURL, branch, and scriptPath - **Permission denied**: Ensure ServiceAccount has necessary RBAC permissions - **CronJob not triggering**: Verify schedule syntax and suspend field ## License Apache License 2.0