Zum Inhalt springen

CI/CD with GitHub Actions

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

The classic way to deploy to Kubernetes from CI is to paste an admin kubeconfig into a repository secret and hope nobody ever leaks it. That credential is cluster-admin, lives for years, gets copied into forks and artifacts, and can’t be revoked without re-keying the cluster.

paasbox is built for a better pattern: the API key is the durable secret; kubeconfigs are disposable. Your workflow holds one revocable API key, uses it to fetch a short-lived admin kubeconfig at the start of each run — with a TTL sized to the job — deploys, and lets the credential expire on its own.

In the console, create an API key (see teams & API keys) — it’s shown once, looks like pbx_live_…, and can be revoked at any time. For CI, consider creating it from a dedicated machine-user account, so pipeline actions are clearly attributable in the activity log.

Store it as a repository secret, e.g. PAASBOX_API_KEY (GitHub → Settings → Secrets and variables → Actions).

A complete deploy workflow — fetch credential, apply manifests, verify the rollout:

name: deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
env:
TEAM: my-team
CLUSTER: production
steps:
- uses: actions/checkout@v4
- name: Fetch a short-lived kubeconfig
run: |
curl -sf -X POST \
-H "Authorization: Token ${{ secrets.PAASBOX_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"ttlSeconds": 1800}' \
"https://console.paasbox.com/api/v1/teams/$TEAM/clusters/$CLUSTER/kubeconfig/" \
| jq -r .kubeconfig > "$RUNNER_TEMP/kubeconfig"
chmod 600 "$RUNNER_TEMP/kubeconfig"
echo "KUBECONFIG=$RUNNER_TEMP/kubeconfig" >> "$GITHUB_ENV"
- name: Deploy
run: kubectl apply -k deploy/overlays/production
- name: Wait for the rollout
run: kubectl -n myapp rollout status deploy/web --timeout=180s

Thirty minutes of validity (ttlSeconds: 1800) comfortably covers a deploy job; the response’s expiresAt field lets longer pipelines renew mid-run if they ever need to. The API reference documents the endpoint.

If your release includes an immutable migration Job — like the Django SaaS guide’s — the same delete-then-apply step slots in between fetch and rollout:

- name: Run migrations
run: |
kubectl -n myapp delete job myapp-migrate --ignore-not-found
kubectl apply -f deploy/overlays/production/migrate-job.yaml
kubectl -n myapp wait --for=condition=complete job/myapp-migrate --timeout=300s

It’s worth being explicit about what this pattern buys you:

  • Leaks age out. A kubeconfig accidentally printed to a log, cached in an artifact, or left on a runner is worthless within the hour — a stored one is cluster-admin until someone notices.
  • Revocation is one click, and it’s not your cluster. Rotating a leaked API key is instant and self-service. Rotating a long-lived cluster credential means re-keying the cluster.
  • Every issuance is audited. Each fetch lands in your team’s activity log with actor, time, and TTL — “what deployed at 02:00” has an answer.
  • Offboarding stays clean. Remove a person, revoke their keys — nothing they ever exported keeps working past the TTL. The full story is in access your cluster.
  • Never upload the kubeconfig as an artifact and never cat it in a step — it’s short-lived, not public.
  • Size the TTL to the job, not to “just in case”. 30–60 minutes covers almost any deploy.
  • One key per pipeline (staging vs. production, per repo) so revocation is surgical and the audit trail is legible.
  • Pin image tags (sha-…, not latest) so what CI deploys is exactly what CI built.

The same pattern works in any CI system — GitLab CI, Forgejo Actions, Jenkins — since it’s just curl and kubectl: hold the key, fetch fresh, deploy, let it expire.