on
Secretless deployments from GitHub Actions to Kubernetes with OIDC and Argo Rollouts
Deploying to Kubernetes from CI used to mean stuffing long-lived cloud credentials into secrets, then hoping they never leaked. Today you can avoid that risk by using GitHub Actions’ OpenID Connect (OIDC) support to obtain short-lived cloud credentials at runtime, and combine that with a progressive delivery controller (Argo Rollouts) to automate safe canary releases. This article walks through the architecture, a concrete GitHub Actions workflow for AWS + EKS, how Argo Rollouts fits in, and practical security and observability tips.
Why this matters
- Secrets in repositories or long-lived service account keys are high-risk and hard to rotate.
- OIDC lets a GitHub workflow exchange a short-lived identity token for cloud credentials only when a run actually executes.
- Progressive delivery (canaries, blue/green) limits blast radius for deployment problems while making deployments automated and repeatable.
GitHub Actions exposes OIDC tokens that cloud providers can trust; several clouds support workload identity/federation so you don’t need to store provider credentials in the repo. (docs.github.com)
How the pieces fit together
- GitHub Actions issues an OIDC token scoped to the workflow run.
- The cloud provider (AWS/GCP/Azure) is configured to trust tokens from token.actions.githubusercontent.com for specific repositories / workflows.
- The workflow requests temporary cloud credentials (STS, Workload Identity Federation, or federated credential) and uses them to configure kubectl/helm and target the cluster.
- The deployment is applied to Kubernetes; Argo Rollouts (installed in-cluster) orchestrates canary steps and promotion/rollback based on pre-defined rules or external metrics.
Configuring OIDC (high level)
- On the cloud side, create an identity provider for GitHub’s OIDC issuer and a role / service account mapping that restricts which repo/branch/workflow can assume it.
- On GitHub, keep the workflow code in the repo; the OIDC handshake happens at runtime—no static keys required in Secrets. See GitHub’s OIDC reference and provider-specific guides for details. (docs.github.com)
Concrete example: GitHub Actions -> AWS EKS -> Argo Rollouts Below is a focused, practical CI job that: 1) Uses GitHub Actions OIDC to obtain temporary AWS credentials. 2) Updates kubeconfig for EKS. 3) Uses Helm (or kubectl) to update the image on a Rollout CR. 4) Triggers Argo Rollouts operations to drive a canary.
.github/workflows/deploy.yml (excerpt)
name: deploy
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write # allow OIDC token to be minted
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
aws-region: us-west-2
- name: Update kubeconfig for EKS
run: aws eks update-kubeconfig --name my-eks-cluster --region $
- name: Install kubectl / argo-rollouts plugin / helm
run: |
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
curl -sSL -o /usr/local/bin/kubectl-argo-rollouts https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
chmod +x /usr/local/bin/kubectl-argo-rollouts
- name: Set image on Rollout (triggers canary)
run: |
kubectl argo rollouts set image rollout/my-app my-container=$:$
kubectl argo rollouts get rollout my-app -n production -w
Notes on the above:
- The aws-actions/configure-aws-credentials action supports the OIDC flow when your IAM role’s trust policy accepts GitHub’s OIDC provider and the role’s permissions are scoped to what the job needs. (github.com)
- aws eks update-kubeconfig populates kubeconfig using the assumed role for cluster authentication. That avoids shipping a kubeconfig file or cluster tokens as secrets. (docs.aws.amazon.com)
- The kubectl argo rollouts set image step updates the Rollout resource in place and kicks off the canary strategy defined in the Rollout CR. The get rollout -w helps the job monitor progression. (argoproj.github.io)
Rollout CR: a minimal canary snippet A Rollout replaces a Deployment and encodes canary steps (weights, pauses, analysis). Here’s the essence of a canary strategy (paraphrased):
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
strategy:
canary:
steps:
- setWeight: 20
- pause: { duration: 60s }
- setWeight: 50
- pause: {}
template:
spec:
containers:
- name: my-container
image: myregistry/my-app:old-tag
- The controller will shift traffic to the canary according to setWeight, wait for the pause step (automated analysis or manual), and continue or rollback. See Argo Rollouts documentation for full examples and analysis templates. (argoproj.github.io)
Why use Argo Rollouts (short list)
- Declarative progressive delivery: rollout steps live in Git alongside manifests.
- Integrates with common service meshes and traffic managers to perform percent-based traffic shifting. (argoproj.github.io)
- CLI integrates with CI: the workflow can update image and optionally promote or abort based on checks or human approval. (argo-rollouts.readthedocs.io)
Monitoring and automated analysis
- To make canaries useful, plug in observability: Prometheus metrics, Istio/Traefik metrics, SLO-based analysis templates, or external checks. Argo Rollouts can run analysis templates (e.g., query Prometheus) before continuing a rollout. CNCF and Argo docs include canary demos wired to Prometheus and Istio. (cncf.io)
Security and best practices
- Principle of least privilege: restrict the assumed role/service account to the minimal IAM/Kubernetes RBAC actions needed (e.g., update image on specific Rollout, push to image repo). Avoid broad admin rights. (github.com)
- Narrow the OIDC subject condition: in the cloud trust policy, require the subject to match a specific repo and optionally branch or environment so only intended workflows can assume the role. GitHub’s OIDC docs show the relevant claims you can use. (docs.github.com)
- Protect production workflows: use GitHub Environments with protection rules (required reviewers, checks) for jobs that can deploy to production. That adds a human gate before OIDC tokens grant high-privilege access. (docs.github.com)
- Audit and rotate: OIDC reduces the need to rotate keys, but audit role trusts and monitor token usage logs in the cloud (CloudTrail, Cloud Audit Logs, Azure AD logs). (docs.github.com)
Cloud portability and alternatives
- GCP: use Workload Identity Federation to exchange GitHub OIDC tokens for service account access—recommended over service account keys. GitHub provides a google-github-actions/auth action to make this flow straightforward. (github.com)
- Azure: Microsoft Entra supports federated identity credentials for GitHub workflows; Azure’s docs show how to configure identity federation for deployments. (learn.microsoft.com)
- If you run a hybrid or multi-cloud strategy, the same model applies: configure each provider to trust tokens from GitHub and scope permissions tightly. (docs.github.com)
Common pitfalls and troubleshooting
- Missing id-token permission: the job must grant id-token: write in its permissions so the OIDC token can be minted.
- Trust policy mismatch: if the cloud role’s trust policy doesn’t match the subject claim (repo/branch/workflow), assume-role will fail—inspect the token claims and the trust condition during setup. GitHub provides tools and docs to debug OIDC claims. (docs.github.com)
- Kubeconfig or cluster RBAC: even when you obtain cloud credentials, the EKS/GKE/AKS cluster must accept them (cluster role bindings or aws eks update-kubeconfig usage). Check cluster-side auth mappings and the cloud provider’s examples. (docs.aws.amazon.com)
- Argo Rollouts CLI availability: CI job must install the kubectl argo-rollouts plugin or use a container image that already includes it. (argoproj.github.io)
Wrapping up Using OIDC with GitHub Actions eliminates long-lived deployment keys in your repo and gives you per-run, inspectable credentials. Pairing that flow with Argo Rollouts’ declarative canary/blue-green strategies gives you automated, low-risk deployments that are both secure and observable. The modern CI → cloud → Kubernetes pipeline is now short-lived, auditable, and designed for progressive delivery.
References and further reading
- GitHub Actions OIDC reference and security hardening guide. (docs.github.com)
- GitHub’s guide to configuring OIDC in AWS (how-to + examples). (docs.github.com)
- aws-actions/configure-aws-credentials Action (OIDC-enabled examples). (github.com)
- Google Cloud Workload Identity Federation guide and google-github-actions/auth action. (docs.cloud.google.com)
- Azure documentation on federated identity credentials and Kubernetes integration. (learn.microsoft.com)
- Argo Rollouts docs (getting started, canary strategy, kubectl plugin). (argoproj.github.io)
Implementing the pattern above gives you a deployment pipeline that’s more secure by default and better suited to run safe, observable canary releases in Kubernetes.