Webinar · Oct 20: The migration takes 2 weeks. Deciding to do it takes 6 months.

Self-Service Kubernetes Deploys Without kubectl: The 5 Layers That Actually Work

Developers can deploy to Kubernetes through GitOps without ever holding a kubeconfig. Here are the five layers that make it safe - GitOps reconciliation, developer abstraction, a self-service surface, policy-as-code, and tenant isolation - which tools cover each layer, and when to build versus buy.

Alessandro Carrano
Head of Product
OCT 15, 2026 · 9 MIN
Self-Service Kubernetes Deploys Without kubectl: The 5 Layers That Actually Work

Key Points:

  • The architecture that works has three parts. Developers get write access to a Git repository only, a GitOps controller (Argo CD or Flux) holds the sole identity with write access to the cluster, and an admission policy engine (Kyverno or OPA Gatekeeper) rejects anything that breaks platform rules. No developer, and no CI runner, needs a kubeconfig.
  • Git access alone is an audit trail, not a guardrail. Without admission policies and schema-constrained templates, a developer can merge YAML that requests 64 vCPUs, mounts hostPath, or runs as root, and the GitOps controller will apply it exactly as written within seconds.
  • Guardrailed self-service is five layers: reconciliation (Argo CD, Flux), developer abstraction (Crossplane XRDs, a golden Helm chart, Score), a self-service surface (Backstage, Port, Humanitec, Qovery Console), policy-as-code (Kyverno, OPA Gatekeeper, Pod Security Admission), and isolation (namespaces + RBAC + ResourceQuota, or vCluster). Most teams need at least three of the five, and no single open-source project covers all of them.
  • Assembling those layers yourself is a multi-quarter project with permanent ownership, including a Kubernetes minor upgrade roughly every four months. Qovery is the pre-assembled version that provisions and operates Kubernetes inside your own AWS, GCP, Azure or Scaleway account, or on the cluster you already run.
  • Give developers scoped read access (logs, events, pod status, rollout state) plus self-service restart and rollback. That removes most of the reason they ask for kubectl in the first place, without opening a write path to the API server.

Qovery · Agentic Infrastructure Platform
A control plane for platform teams and their coding agents
Learn more

A kubeconfig with edit rights on a shared cluster is the ability to delete someone else's production pod. Most teams hand one out anyway, usually because the developer got tired of filing tickets and someone on the platform side got tired of answering them.

The uncomfortable part is what happens next. The Red Hat State of Kubernetes Security report found that 45% of respondents' most impactful Kubernetes security incidents traced back to a misconfiguration, not a CVE and not a targeted attacker. When everyone can write to the API server, every typo is a potential incident.

I have talked to more than 200 CTOs and platform leads over the last few years, and the request is almost always the same: let developers ship on their own, without turning the cluster into a shooting gallery. That is a solved problem now. Developers can deploy to Kubernetes through GitOps and never hold a kubeconfig. Here is the architecture, the tools that cover each layer, and where it makes sense to buy the whole thing pre-assembled.

What architecture lets developers deploy to Kubernetes without kubectl access?

Three components. Developers write only to a Git repository, a GitOps controller (Argo CD or Flux) is the single identity holding write access to the cluster, and an admission policy engine (Kyverno or OPA Gatekeeper) validates every resource before the API server persists it. Neither developers nor CI runners are issued a kubeconfig, because pull-based reconciliation removes the need for one.

The flow, in order:

  1. A developer opens a pull request.
  2. CI builds the image and pushes it to an allowlisted registry.
  3. Automation updates the image tag (or renders the manifest) in the config repo.
  4. Argo CD or Flux pulls the change and reconciles it into the target namespace.
  5. Kyverno or OPA Gatekeeper admits or rejects the resource at the API server.
  6. The developer watches rollout state in a portal.

The shift that makes this work: the cluster's only write identity becomes the reconciler's service account. kubectl access becomes unnecessary rather than forbidden. You remove the need, not just the permission, which is why the model survives contact with an impatient engineer at 6pm who would otherwise go find a way around it.

Pull-based reconciliation matters for security beyond convenience. No CI runner holds cluster credentials, so you delete the most common leak path: long-lived kubeconfigs and service-account tokens sitting in CI secrets. That is not a hypothetical. The Verizon Data Breach Investigations Report attributes 22% of breaches to the use of stolen credentials, and a token with cluster-admin in a CI variable is exactly the kind of credential that leaks. The OpenGitOps principles spell out why a pulled, continuously reconciled desired state beats a pushed one here.

Developers still legitimately need things: logs, events, pod status, rollout state, and the ability to restart or roll back their own service. Deliver those through the platform UI, through the Argo CD UI with scoped SSO plus AppProjects, or through a narrowly scoped read-only ClusterRole. Never cluster-admin, never a shared kubeconfig in 1Password.

Decide the break-glass question before you need it. Someone holds emergency write access, that access is time-bound through short-lived credentials or just-in-time elevation, and every use is captured in the Kubernetes audit log plus the cloud provider trail (CloudTrail on AWS, Cloud Audit Logs on GCP, Azure Monitor). The measurable outcome: the number of humans with standing write access to the production API server should be a single-digit number you can name out loud, and every change should trace back to a merged commit.

Why isn't Git access alone enough of a guardrail?

A Git repository gives you review and history, not enforcement. If a developer can merge arbitrary YAML, they can request 64 vCPUs, mount hostPath, run a privileged container, pull an unsigned image, or target another team's namespace, and the GitOps controller will apply it faithfully within seconds. Enforcement has to happen at admission, and authoring has to be constrained by a schema.

The concrete failure modes are boring and common: resource requests with no ceiling, missing limits that cause noisy-neighbor evictions, privileged or root containers, hostPath and hostNetwork mounts, :latest tags nobody can roll back, images from registries you never approved, secrets committed in plaintext, and manifests pointed at the wrong namespace or the wrong cluster.

These are not edge cases. The Datadog container report found that over 65% of containers use less than half of their requested CPU and memory, which is the fingerprint of resource requests nobody polices. On the security side, the Sysdig Cloud-Native Security and Usage Report has repeatedly found most containers run as root (76% in one widely cited edition). Both of those merge straight through a GitOps pipeline that only checks "did a human approve the PR."

Pull request review does not scale as a control either. If every manifest needs a platform engineer's sign-off, you have rebuilt the ticket queue with extra Git steps and slower feedback. The reviewer also cannot reliably eyeball a resource limit or a registry hostname at 50 PRs a week.

There are two fixes, and you want both.

Fix one is enforcement at admission. Kyverno or OPA Gatekeeper enforce required labels, resource ceilings, registry allowlists, and the Pod Security Standards. The free baseline is built in: Pod Security Admission has been GA since Kubernetes 1.25, which also removed the old PodSecurityPolicy. ResourceQuota and LimitRange give you the capacity ceiling per namespace. Shift the same policies left into CI with the Kyverno CLI or conftest, so the rejection shows up in the PR within seconds instead of 20 minutes later as a failed sync nobody is watching.

Fix two is constraining what can be authored at all. A golden Helm chart with a locked values.schema.json, a Crossplane XRD, or a Score workload spec means developers fill in fields instead of writing raw Kubernetes objects. You cannot request hostPath through a form that has no hostPath field.

One guardrail most teams skip: lock down the reconciler itself. Argo CD AppProjects restrict allowed destinations, source repos, and resource kinds, and they are the cheapest control on this list. Argo CD has had RBAC and AppProject-related CVEs (see the Argo CD security docs and advisories), which is precisely why you configure AppProjects deliberately rather than leaving the default wide open.

ControlWhat it blocksWhat it does NOT blockEnforced atEffort
PR reviewObvious mistakes a human catchesResource limits, registries, anything subtle at volumeGitHours
Branch protection + CODEOWNERSUnreviewed merges to protected pathsThe content of an approved manifestGitHours
Argo CD AppProject restrictionsWrong destination cluster/namespace, stray resource kindsIn-spec abuse (limits, root) within allowed scopeReconcilerHours
Pod Security AdmissionPrivileged, root, hostPath, hostNetworkResource limits, registries, custom rulesAdmissionHours
ResourceQuota / LimitRangeNamespace-level CPU/memory/object ceilingsSecurity posture, images, destinationsAdmissionHours
Kyverno / OPA GatekeeperLabels, limits, registries, signatures, custom rulesOnly what you write policies forAdmissionDays
Constrained Helm chart / Crossplane XRDEverything not exposed as a fieldMisuse of the fields you do exposeCI / authoringWeeks
Namespace RBACCross-tenant reads/writes in the APIA compromised in-namespace workloadRuntimeDays
Image signing admission (cosign/Sigstore)Unsigned or untrusted imagesA signed image that is still vulnerableAdmissionDays

Read any row on its own and it tells you where the hole is. No single row closes the gap, which is the whole point.

Which tools cover which layer of guardrailed self-service?

No single open-source project covers the whole problem. Guardrailed self-service is five layers - reconciliation, developer abstraction, self-service surface, policy-as-code, tenant isolation - and real stacks combine three to five tools. Here is which tool owns which layer, and where each one stops.

Layer 1, GitOps reconciliation. Argo CD and Flux, both CNCF Graduated in late 2022. Argo CD ships a UI plus AppProjects and RBAC, which makes it the easier starting point for most teams. Flux is controller-first and composes cleanly with Flagger for progressive delivery.

Layer 2, developer abstraction. Crossplane XRDs and composite resources when you want to author your own platform APIs, a constrained Helm chart or Kustomize overlay for simpler cases, and Score or Humanitec workload specs for workload-level portability across environments.

Layer 3, self-service surface. Backstage with scaffolder templates and the software catalog, Port, Humanitec Portal, or the Qovery Console. This is where the developer actually clicks or pushes. Backstage is CNCF Incubating and has over 270 public adopters, so it is proven at scale, but it is a framework you assemble, not a product you turn on.

Layer 4, policy-as-code. Kyverno writes policies as Kubernetes-native YAML, is CNCF Incubating, and ships a large library of ready-to-use policies. OPA Gatekeeper uses Rego and builds on OPA, which graduated the CNCF back in 2021. Pod Security Admission and Argo CD AppProject allow-lists round out the layer. Pick Kyverno if your team would rather write YAML than learn Rego; pick Gatekeeper if you already run OPA elsewhere.

Layer 5, isolation. Namespaces plus RBAC plus ResourceQuota is the baseline (soft multi-tenancy). vCluster when teams genuinely need their own CRDs or cluster-scoped objects. A cluster per team or per environment at the strict end. The Kubernetes multi-tenancy docs lay out the soft-versus-hard distinction clearly.

Qovery collapses layers 1 through 5 into one product that runs inside your own cloud account. That is less composable than a Crossplane plus Backstage build, and far less to build and keep upgraded. Where each option genuinely wins: Crossplane for authoring your own platform APIs, Backstage for catalog breadth at large scale when you have staff to own it, Argo CD plus Kyverno for a team that already runs the cluster, vCluster for hard tenancy, and Qovery when the golden path needs to exist next week without hiring.

ToolGitOps reconcileDev abstractionSelf-service UIPolicy enforcementTenant isolationOperates the clusterRuns in your cloud accountModel
Argo CDYes, pull-based + UINoPartial, app-focused UIPartial, AppProject scopingNoNoYes, you install itOSS, CNCF Graduated
FluxYes, controller-firstNoNo, controllers onlyPartial, via policies you addNoNoYes, you install itOSS, CNCF Graduated
CrossplaneNoYes, author platform APIsNoPartial, via compositionsNoPartial, provisions cloud infraYes, you install itOSS, CNCF Graduated
BackstageNoPartial, scaffolder templatesYes, catalog + portalNoNoNoYes, you host itOSS framework, CNCF Incubating
PortNoPartial, actions + blueprintsYes, catalog + actionsNoNoNoSaaS control planeCommercial SaaS
HumanitecPartial, via orchestratorYes, workload specsYes, portalPartial, via config rulesNoNo, runs on your clusterYes, on your clusterCommercial
KyvernoNoNoNoYes, YAML policiesNoNoYes, you install itOSS, CNCF Incubating
OPA GatekeeperNoNoNoYes, Rego policiesNoNoYes, you install itOSS, built on CNCF OPA
vClusterNoNoNoNoYes, virtual clustersNoYes, you install itOSS + commercial
ScoreNoYes, workload specNoNoNoNoN/A, spec formatOSS spec
QoveryYes, managedYes, service abstractionYes, console + git pushPartial, platform RBAC + guardrailsYes, namespace per envYes, provisions + upgradesYes, BYOCCommercial

What does it really cost to build guardrailed self-service in-house?

Expect a multi-quarter build plus permanent ownership. Argo CD, Crossplane, Backstage, and Kyverno each need bootstrapping, a policy library, an RBAC model, secrets plumbing, and upgrades, on top of Kubernetes itself. Kubernetes ships roughly three minor releases a year with a 14-month support window per release, so a cluster you never touch goes unsupported in a little over a year, and a minor upgrade lands on your desk roughly every four months. The managed control planes do not save you here: EKS, GKE, and AKS all force upgrades on their own end-of-support schedules.

The work is real and it does not end. Cluster bootstrap, repo layout and app-of-apps, template authoring, the RBAC model, secrets management (External Secrets or SOPS), the policy library, preview-environment plumbing (DNS, TLS, databases, seed data, teardown), onboarding docs, and upgrades for every component plus the cluster. Gartner expects 80% of large software engineering organizations to run platform teams by 2026, up from 45% in 2022, and in practice that means staffing a dedicated team and keeping it staffed. In my CTO conversations the line I hear most is some version of "we built our own IDP and now two engineers do nothing else." The parts they cut first are almost always the catalog and the custom portal, rarely the policy engine.

The payoff is real too, and worth being honest about. DORA research consistently shows elite performers deploying far more frequently and with far shorter change lead times than low performers, and it credits internal platforms and developer self-service with lifting throughput. DORA is also careful to note the nuance: a platform can raise throughput while adding friction if the golden path is too narrow and developers keep hitting its walls. Build the escape hatch, not just the happy path.

Be fair about the alternatives. Backstage is a framework, not a product; plugin maintenance and upgrade churn are a standing cost, and it is still the right answer for large orgs with staff to own it. Humanitec and Port are the credible "don't build the portal" commercial options: Humanitec's Platform Orchestrator with dynamic configuration management and Port's catalog plus self-service actions are both strong. Both of them sit on top of a cluster you still operate and upgrade yourself.

Where Qovery differs is the layer underneath. It provisions and operates the cluster itself (managed cluster upgrades, networking, databases backed by managed cloud services) inside your own AWS, GCP, Azure, or Scaleway account, or it plugs into the Kubernetes cluster you already run. The platform team stops owning the reconciliation plumbing and the upgrade treadmill.

DIY (Argo CD + Crossplane + Backstage + Kyverno)Portal-only (Humanitec or Port on your cluster)Qovery
Time to first golden pathQuartersWeeks to a couple of monthsDays
Components to maintainMany (reconciler, abstraction, portal, policy, secrets)The portal, plus your cluster stackThe product; Qovery maintains the plumbing
Who operates the cluster + upgradesYouYouQovery, in your account
Policy enforcement includedNo, you assemble itPartial, via config rulesPartial, platform RBAC + guardrails
Preview envs per PR includedNo, you build itPartial, depends on your setupYes, built in
Cost modelPeople-heavy, OSS licences, cloudLicence + your cluster cost + peopleLicence + your own cloud bill
Platform headcount neededA dedicated teamOne or two, plus the portal vendorMinimal
Escape hatch to raw KubernetesFullFullYes, it is your cluster
Runs in your own cloud accountYesYesYes, BYOC
Best fitMany teams, custom platform APIs, staff to own itYou want the portal, not the buildStandard services shipping safely, small or no platform team

How does Qovery give developers self-service deploys without a kubeconfig?

Qovery provisions and operates Kubernetes inside your own GCP, Azure, Scaleway, or AWS account, or on the cluster you already run, and makes the cluster an implementation detail. Developers deploy by pushing to Git or from the Qovery Console, Qovery reconciles into a namespace per environment, and no developer is ever issued a kubeconfig. The platform team keeps the cloud account, the VPC, the audit trail, and the cloud bill.

The mechanics are simple. Connect a repository, and Qovery builds and deploys into a namespace per environment. The platform team defines the cluster, the cloud account, and who can do what. Per-environment RBAC decides who may deploy to production versus staging versus preview, and it is enforced in the platform rather than through cluster RoleBindings a developer could escalate.

Preview environments per pull request are, in practice, the highest-value self-service feature and the hardest one to build yourself on raw Argo CD, because of DNS, TLS, databases, seed data, and teardown. Qovery ships them. It also auto-stops non-production environments, which is the cost guardrail that keeps self-service from quietly tripling a cloud bill. That matters: the Flexera State of the Cloud Report puts wasted cloud spend at 27%, and idle preview environments running over a weekend are a textbook contributor.

BYOC is the point for this question. The cluster lives in your GCP, Azure, Scaleway, or AWS account, or it is the cluster you already run, so your security team keeps the VPC, the audit trail, and the cloud bill including existing committed-use discounts and Savings Plans. That is the difference from a fully hosted PaaS.

Honest limits: if you need arbitrary CRDs, bespoke operators, or your own internal platform API, Crossplane plus Backstage gives you more control. Qovery is the answer when you want standard services shipping safely without staffing a platform team.

How do you choose between Argo CD, Backstage, Crossplane, and a full IDP?

Choose on two variables: how many engineers you can permanently dedicate to owning the platform, and how much of Kubernetes your developers genuinely need to express. Zero dedicated engineers points to an IDP that also operates the cluster. One or two points to Argo CD plus a golden Helm chart plus Kyverno. Three or more with heterogeneous infrastructure points to Crossplane plus Backstage or Port.

A short checklist to paste into a doc before you decide. Do developers need logs? Create databases? Define their own CRDs? Deploy to production unsupervised? Get an environment per pull request? Roll back without a ticket? Each yes moves you one row down the table.

SituationRecommended stackWhat you still ownTime to first golden pathMain risk
0 platform engineers, standard servicesAn IDP that operates the cluster (Qovery) in your own accountThe cloud account and costDaysLess control over bespoke CRDs
1-2 platform engineers, existing cluster, standard workloadsArgo CD + golden Helm chart + Kyverno + AppProjects (or Qovery on that cluster)The full stack and upgradesWeeksThe two engineers become the bottleneck
3+ platform engineers, many teams, heterogeneous infraCrossplane + Argo CD/Flux + Backstage or PortEverything, as a productQuartersBuild cost and ongoing plugin churn
Hard multi-tenancy, teams need own CRDsAdd vCluster, or a cluster per team/environmentTenant lifecycle and costWeeks to monthsOperational sprawl across clusters
Regulated or EU data residency (e.g. GCP or Scaleway in-region)Anything that runs in your own account with a full audit trail; rule out hosted PaaSData boundary and compliance evidenceVariesPicking a hosted PaaS and failing an audit

For the common middle case, I will say it plainly: if you already run a cluster and have one or two platform engineers, Argo CD plus a golden Helm chart plus Kyverno plus AppProject restrictions is genuinely the right call. Run Qovery on that same existing cluster only if you would rather not own the plumbing.

How do I set this up with Qovery from Claude Code or Cursor?

Install the Qovery Agent Skills once with a single command, then ask your coding agent in plain language to provision the cluster, deploy the service, and set per-environment permissions. The agent runs the same guardrailed flow a developer would and asks you to approve each action, and like the developer it never receives a kubeconfig.

Install globally for every compatible agent (Claude Code, Cursor, Codex, OpenCode, Gemini CLI):

BASH
curl -fsSL https://skill.qovery.com/install.sh | bash

Keep it scoped to a single repository instead:

BASH
curl -fsSL https://skill.qovery.com/install.sh | bash -s -- --project

Add the MCP Server for Claude Code, read-only by default, so the agent can inspect what already exists:

BASH
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242

Enable write access only when you want the agent to change things (this also requires enabling write access in the Qovery Console):

BASH
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242

The skills cover the lifecycle: qovery-onboard, qovery-deploy, qovery-troubleshoot, qovery-optimize, qovery-speedup, qovery-preview, and qovery-terraform. Skills deploy; the MCP Server operates what already exists. After install, you ask in plain language, for example: "deploy this service to my GCP account with Qovery and give the backend team deploy rights on staging only."

Full walkthroughs are in the Qovery AI agent quickstart and the Claude Code integration docs. The guardrail parallel is worth noticing: the agent acts through Qovery's API with only the permissions you approved, which is the same principle as the five layers above applied to a non-human actor.

How do you give developers self-service access to deploy to Kubernetes through GitOps without giving them kubectl access?

Give developers write access to a Git repository only, make a GitOps controller (Argo CD or Flux) the single identity with write access to the cluster, and enforce platform rules with an admission policy engine (Kyverno or OPA Gatekeeper). Developers push code or config, the controller reconciles it, and policies reject anything out of bounds. Nobody is issued a kubeconfig because pull-based reconciliation removes the need for one.

Is Argo CD enough on its own, or do I also need a policy engine like Kyverno or OPA Gatekeeper?

Argo CD alone is not enough. It faithfully applies whatever is merged, including a privileged container or an unbounded resource request. You need a policy engine (Kyverno or OPA Gatekeeper) at admission plus Pod Security Admission as a baseline, and ideally Argo CD AppProjects to restrict destinations. Argo CD handles reconciliation; the policy engine handles enforcement.

Should developers ever get read-only kubectl access to a production cluster?

Scoped read-only access is reasonable and usually a good idea, because it removes most of the reason developers ask for kubectl at all. Grant logs, events, pod status, and rollout state through a narrowly scoped read-only ClusterRole, the Argo CD UI with SSO, or a platform UI, and add self-service restart and rollback. Never grant cluster-admin and never share a single kubeconfig.

What is the difference between Crossplane, Backstage, Humanitec, Port, and Qovery for guardrailed self-service?

They cover different layers. Crossplane authors your own platform APIs, Backstage and Port are self-service surfaces (catalog and actions) you host or configure, and Humanitec is a platform orchestrator plus portal that runs on your cluster. All of them sit on top of a cluster you still operate. Qovery is the one that also provisions and operates the cluster inside your own cloud account, collapsing reconciliation, policy, and preview environments into one product.

How do I stop developers from requesting unlimited CPU and memory or running privileged containers through GitOps?

Enforce it at admission, not in review. Use ResourceQuota and LimitRange for capacity ceilings, Pod Security Admission to block privileged and root containers, and Kyverno or OPA Gatekeeper for required limits, registry allowlists, and custom rules. Constrain authoring with a golden Helm chart (a locked values.schema.json) or a Crossplane XRD so the dangerous fields are not even exposed, and run the same checks in CI so rejections appear in the PR.

Can I get self-service deployments and preview environments on a Kubernetes cluster I already run myself?

Yes. You can build it with Argo CD plus a golden Helm chart plus Kyverno plus ApplicationSets for previews, which is the right call if you have one or two platform engineers. Or run Qovery on your existing cluster so it handles git-push deployments, preview environments per pull request, auto-stop, and per-environment RBAC without you owning the plumbing. Either way the cluster stays yours.


The goal is a developer who ships on a Friday afternoon without filing a ticket and without a kubeconfig, on a cluster your security team still controls. You can assemble that from Argo CD, Kyverno, and a golden Helm chart if you have the people, or you can get it pre-assembled inside your own cloud account. Either way, the kubeconfig stays in the drawer.

Alessandro Carrano
About the author
Alessandro Carrano

Alessandro leads product at Qovery. He drives the changelog, roadmap, and product strategy - turning customer feedback into platform capabilities.

Next step

Ship faster on infrastructure you control.

Qovery gives your team self-service deployments and preview environments on your own AWS, GCP, Azure or Scaleway account, or on the Kubernetes cluster you already run. No kubeconfig handed out. Start deploying in under 10 minutes.