Skip to main content
RunBook Academy

Git, CI/CD & GitOpsLXXIII · Push versus Pull DeploymentFoundations

The push model — CI holds credentials and reaches out to the cluster

Advanced⏱ ~20 mingitkubectl

What you'll learn

  • Describe how the push model moves state from CI to the cluster
  • Identify the credentials a CI runner must hold in the push model
  • Trace the request path of a typical kubectl apply from a CI job
  • Recognise why the push model is the natural default for traditional CI/CD

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

The push model is the way CI/CD has worked since before the term “GitOps” existed. A pipeline runs on a runner somewhere, the runner authenticates to a target system, and the runner pushes state into that system. The direction of change is from outside to inside; the credentials live with whoever is doing the pushing. Most teams run this model long before they ever consider pulling.

The shape of the model in one picture:

flowchart LR
    Dev["Developer"] -->|"git push"| Repo["Git repository"]
    Repo -->|"webhook"| CI["CI runner"]
    CI -->|"hold kubeconfig"| CI
    CI -->|"kubectl apply -f deployment.yaml"| Cluster["Cluster API"]
    Cluster --> K8s["Desired state in cluster"]

The CI runner is the active agent. It reads the manifest, resolves any templating, authenticates to the cluster’s API server, and issues the write. The cluster’s API server is the passive recipient; it does not pull from CI, it accepts what CI sends.

What the runner holds

In a push-based pipeline the CI runner must hold every credential required to apply the change:

  • A kubeconfig with write access to the cluster API. The scope is whatever the manifest needs: namespace-scoped for an application, cluster-scoped for a CRD, sometimes full cluster-admin for bootstrap.
  • Cloud-provider credentials if the manifest references out-of-cluster resources: an AWS access key for an IAM role update, a GitHub token for a webhook, a Vault token for a secret.
  • Image registry credentials if the runner needs to pull private base images during the build or apply phase.

The credentials are mounted into the runner’s environment as environment variables or as files. They are short-lived by default in mature setups (OIDC federation, IRSA, Workload Identity) but they are push credentials: they let the holder reach out and write.

kubectl apply -f deployment.yaml

This is the canonical push-model command. A human or a CI job runs it from outside the cluster; the runner’s kubeconfig is what makes the API server accept the write. The same command, run from inside the cluster against the in-cluster API, is a different trust boundary entirely.

Why the push model is the default

Three reasons push-based CD is what most teams build first:

  1. The runner is where the build already lives. CI runners already exist, already hold secrets, already run scripts. Adding kubectl apply to the end of an existing pipeline is a one-line change.
  2. The cluster is reachable. A Kubernetes API server with a public endpoint, an SSH-reachable server, or a cloud-provider API endpoint is the norm. The push model assumes this reachability.
  3. The mental model matches imperative operations. Engineers who learned operations before learning declarative state think in terms of “run this command against this target”. The push model is the imperative model.

The push model is not wrong. It is the right tool for a wide range of systems, especially ones that are not Kubernetes-shaped and ones where the cluster is not the system of record.

Where the trust boundary sits

In the push model, the trust boundary is between CI and the cluster. The cluster must trust CI enough to accept its writes. CI must hold credentials powerful enough to make those writes happen. Every actor who can influence what CI does - a developer who can modify the pipeline definition, a third-party action that executes inside the runner, a malicious dependency - is an actor who can potentially drive a write to the cluster.

flowchart LR
    subgraph TB["Trust boundary"]
        CI2["CI runner"] -->|"kubeconfig"| API["Cluster API"]
    end
    subgraph Inside["Cluster"]
        API --> NS["Namespaces, workloads, RBAC"]
    end

This boundary is why the push model has a reputation for being risky: the boundary is wide, the credentials are powerful, and the path from “compromised runner” to “compromised cluster” is short. The next lesson describes the model that inverts this.

Production discipline

  1. No personal credentials in the runner. The runner authenticates as a deploy identity, never as a developer. A personal access key in CI is a credential that outlives the developer’s employment.
  2. Kubeconfig scope is the manifest scope. A pipeline that updates Deployment objects in prod does not need cluster-admin; it needs a namespaced Role with get, list, watch, update, patch on deployments.apps.
  3. Audit log names the identity. Every apply leaves a trace in the cluster’s audit log (and, for cloud-provider writes, in CloudTrail or its equivalent). The audit entry must identify the pipeline run, not just the runner host.

Cross-course references

  • Ansible for Production Sysadmins - Parts covering ansible-playbook from a runner describe the push model for configuration management.
  • Terraform for Production Sysadmins - Parts on terraform apply from CI describe the push model for infrastructure provisioning.
  • Kubernetes for Production Sysadmins - Parts on RBAC and ServiceAccounts cover the credential side of the push model.

Quiz

Knowledge check · 4 questions

  1. Q1. In a push-based CI/CD pipeline, where do the cluster credentials live?

  2. Q2. The push model requires the cluster's API server to be reachable from the CI runner.

  3. Q3. Name two kinds of credentials a push-based CI runner typically holds.

  4. Q4. Identify the credential that escaped and what it can do.

    Team P runs push-based CD for a Kubernetes workload. The CI runner authenticates to the cluster with a service-account token mounted from a Kubernetes Secret in the CI namespace. A previous engineer committed a debugging step to the pipeline that `echo`s all environment variables to the build log. An external auditor inspecting the runner logs finds the service-account token printed in cleartext. The token is still within its 24-hour rotation window.

Passing score: 75%. Answers are checked in this browser.