Environments and GitOps
An environment is a folder in a Git repository, connected to a Kubernetes cluster. Your CI writes each new image digest into the folder, the cluster’s own Frazer GitOps syncs it, and admission checks the digest’s signature. Staging moves on a commit, production on a pull request you approve. One cluster can run any number of environments from any number of repositories, each inside its own fence.
Product overview: Environments and GitOps.
How it works
Section titled “How it works”Keep code and deployment configuration in separate repositories. A code repository holds source, tests and the CI workflow; a commit there builds, signs and pushes an image to Frazer Registry. An environment repository holds what runs where: Helm values, image digests, databases and raw manifests, one folder per environment. A commit there is synced by the cluster.
acme/storefront ──CI: test, build, sign──► Frazer Registry api@sha256:… │ └──CI commits the digest──► acme/platform-envs envs/staging/apps/core/api/images.yaml │ webhook ▼ cluster acme-staging-1: GitOps syncs; admission checks the signatureThe console follows each image by its digest through five stages: Built, Written to Git, Synced, Rolled out, Verified. Nobody presses “new app”: a new service is a new folder in the environment repository.
Frazer reads your repositories through the read-only Frazer Reader GitHub App, installed on the repositories you pick. Each cluster gets a 60-minute read token, refreshed every 20 minutes, that covers only the repositories connected to it.
- Environment: a repository, a revision (branch, tag or commit), a path, a set of namespaces, a permission profile, the gateways and hostnames its routes may use, and a sync policy. An API resource on a cluster.
- Namespace ownership: a namespace belongs to exactly one environment. The plan fails if two environments claim the same one.
- Fence: each environment gets its own GitOps namespace
env-<name>and AppProjectenv-<name>, which see only its repository and Frazer Registry, and only its namespaces. - Permission profile: what kinds of objects the environment may create:
standard,platformorpreview. - Mode:
managed(Frazer reads the folder convention) orrepo-defined(your own ApplicationSets, applied inside the fence).
Lay out your repositories
Section titled “Lay out your repositories”| Layout | Good for |
|---|---|
One repository, a folder per environment (envs/staging, envs/production) |
Most teams, up to dozens of services. The default. |
One repository per team (payments-envs, data-platform-envs) |
Several teams with their own owners and approval rules. |
One repository per environment (envs-staging, envs-production) |
A hard production boundary, where only release managers merge to production. |
Environments are folders on one branch, not branches. Branches drift through merge order, cherry-picks and fixes that land in one branch only; a pull request between folders shows exactly what changes in production. You can still pin an environment’s revision to a tag or a commit, but Frazer never creates environment branches. A deploy/ folder inside a code repository also works for a team with one service.
Connect an environment
Section titled “Connect an environment”You need a cluster (create one) and an environment repository on GitHub.
-
Install the Frazer Reader GitHub App on the environment repository. In the console, open your organization’s Settings › Integrations, choose GitHub and select the repositories Frazer may read. It asks for Contents: read and Metadata: read, nothing else.
-
Lay out the environment’s folder:
envs/production/ # the path you connect├── environment.yaml # optional: labels, namespace defaults├── _shared-values.yaml # environment-wide Helm values├── apps/<family>/<app>/│ ├── values.yaml # written by people│ └── images.yaml # written by CI only├── databases/<name>/database.yaml # Postgres, with backups└── manifests/<name>/ # raw YAML or a Kustomization: operators, tools -
Connect the path to the cluster. Frazer computes a plan from the repository’s current contents.
Terminal window frazer releases environments connect data --project acme-production --cluster acme-production-1 \--repo acme/data-platform-envs --path envs/production \--namespaces data-airflow,data-clickhouse --profile platform --dry-runOutput Plan: connect environment "data" to cluster acme-production-1 (acme-production)+ Namespaces env-data, data-airflow, data-clickhouse+ AppProject env-data source acme/data-platform-envs + Frazer Registry · profile platform (elevated)cluster-scoped allowed: CRDs clickhouse.altinity.com+ Applications 4 from commit 3f9c2e1: clickhouse-operator, clickhouse, airflow, superset~ Git token acme-production-1 also reads acme/data-platform-envs✓ Namespaces no conflict (environment "platform" owns checkout-api, web)✓ Policy Policy dry run: 0 violations · schemas validCost (expected) +6 vCPU, +24 GiB requested on acme-production-1; no fee (own servers)Approval org admin (profile platform)Read the plan, then run the command again without
--dry-runto connect.Open the cluster, go to Environments and choose Connect. Pick the repository from the Frazer Reader installation (or extend the installation), then the branch, path, namespaces, permission profile, sync policy and hostnames. Review the plan and apply it.
-
If the plan says Approval: org admin, an organization admin approves it. The
platformprofile is elevated;standardneeds no approval. -
Watch the first sync under Engineering › Environments. Each app folder becomes a GitOps Application in the environment’s AppProject.
Folders and values
Section titled “Folders and values”What Frazer reads in managed mode:
- A family is a chart. Each
apps/<family>/<app>/folder becomes one Application from the family’s chart. Frazer ships a generalappchart, and you can push your own chart families to Frazer Registry. - Values are layered, lowest first: the chart’s defaults, then
_shared-values.yaml, then the app’svalues.yaml, thenimages.yaml. Each app is an Application with two sources: the chart from Frazer Registry and your repository as$values. images.yamlis CI’s. People editvalues.yaml; CI writes only image digests. (Writing the digest intovalues.yamlalso works.)- Databases and manifests.
databases/<name>/database.yamlcreates a Postgres database with backups through Frazer’s database chart.manifests/<name>/holds raw YAML or a Kustomization for operators and extra tools.
In repo-defined mode, the repository’s own ApplicationSets are applied into env-<name> instead, and any Application that names another GitOps project is refused.
Roll out a new image from CI
Section titled “Roll out a new image from CI”Your CI builds once, pushes to Frazer Registry with a short-lived token (how), and Frazer signs the digest on push. Then CI writes the digest into the environment repository: to staging by commit, to production by pull request.
# written by CI only; production gets the same digest by pull requestapp: image: repository: registry.frazer.ai/acme-staging/build-images/billing tag: v0.1.46 digest: sha256:c3c9…Frazer GitOps syncs on the repository’s webhook, and admission verifies the signature before a pod starts. The rollout appears under Engineering › Rollouts, joined to the commit, the digest and whoever wrote it. Syncs and rollouts also reach your webhooks, for example frazer.rollout.succeeded.v1; the full list is under Reference.
Promote to production
Section titled “Promote to production”Promotion is a pull request that copies a digest, or a values change, from envs/staging to envs/production. The diff is exactly what changes in production.
Engineering › Rollouts shows staging and production side by side for each service. When staging is ahead, Promote opens that pull request for you. Opening pull requests needs the opt-in Frazer writer GitHub App; without it, open the pull request yourself.
To roll back, revert the commit or the pull request. Git moves forward, Frazer GitOps follows, and the rollback is in the audit log like any other change.
Permission profiles
Section titled “Permission profiles”| Profile | What the environment may create | Who chooses it |
|---|---|---|
standard (default) |
Namespaced kinds in its own namespaces. No cluster-scoped kinds, no Gateways, no network-plugin, gateway-controller or GitOps kinds. | Developer |
platform |
Also an allowlist of cluster-scoped kinds: CRDs, ClusterRoles bound to its namespaces, its operators’ webhooks. Components Frazer guarantees stay blocked. | Organization admin; the plan marks it elevated |
preview |
What a preview policy runs: one namespace per pull request, deleted on merge, close or TTL. See Templates and previews. | Developer |
Check pull requests before they merge
Section titled “Check pull requests before they merge”On every pull request that touches a connected path, the Frazer Reviewer GitHub App posts one check per environment, such as Frazer / acme-production / data. Frazer asks the target cluster’s own Frazer GitOps to render the pull request’s head commit and compares it with the live state, so the check uses the same chart versions and plugins as the real sync. The check shows:
- the objects added, changed and deleted, per Application, with the full diff in the details;
- anything the environment may not do: a Gateway, another environment’s namespace, a cluster-scoped kind under
standard; - a
Secretwith data in it; - Frazer Policy dry-run results;
- whether each new image digest is signed;
- the change in requested resources and cost.
Make the check required in your repository’s branch rules to stop a change that fails it from merging. A changed source policy runs in evaluate mode first: for a set time it lists the deploys it would have refused, then it enforces.
Keep secrets out of Git
Section titled “Keep secrets out of Git”Git holds ExternalSecret objects only. The values live in Frazer Secrets and reach the cluster through its own identity, with the frazer-secrets ClusterSecretStore:
apiVersion: external-secrets.io/v1kind: ExternalSecretmetadata: name: stripe namespace: checkout-apispec: secretStoreRef: kind: ClusterSecretStore name: frazer-secrets target: name: stripe data: - secretKey: STRIPE_SECRET_KEY remoteRef: key: payments/stripe-secret-keyThe pull request check and an admission policy both reject a Secret with data or stringData; empty placeholders on an allowlist pass. Frazer does not keep encrypted secrets in Git: encrypted values would stay in Git history forever, and every cluster would need one more key. Git, registry and image pull tokens are minted per cluster and never stored in Git.
Sync defaults
Section titled “Sync defaults”- Automated sync with prune and self-heal, Server-Side Apply and server-side diff.
FailOnSharedResource, so no two Applications own the same object.- Namespaces, PersistentVolumeClaims, CRDs and databases are never pruned or deleted without a confirm (
Prune=confirm,Delete=false). - Replicas owned by an autoscaler are ignored in the diff.
- Charts and remote bases are pinned, never
latest. - Sync waves:
manifests/first, thendatabases/, then apps. - Production can add a sync window that refuses automated syncs outside the maintenance window; a manual sync still works.
Access and audit
Section titled “Access and audit”- Developer: connects an environment with the
standardorpreviewprofile. - Organization admin: approves the
platformprofile. - CI: writes image digests into
images.yaml, nothing else. - Frazer: reads the selected repositories through the read-only Frazer Reader App. Writing pull requests (promote and restore) takes the separate Frazer App; agent branches and pull requests take the Frazer Agents App; checks and review comments come from Frazer Reviewer. You install each one only if you want it.
Frazer logs connecting, changing and disconnecting an environment, each as a plan, and every rollout with its digest, commit and author. Git itself records every change to what runs.
Limits and quotas
Section titled “Limits and quotas”| Setting | Default |
|---|---|
| Environments per cluster | Any number, from any number of repositories |
| Owners per namespace | Exactly one environment |
| Cluster Git read token | 60 minutes, refreshed every 20 minutes, limited to connected repositories |
| Prune of namespaces, volume claims, CRDs, databases | Waits for a confirm |
| Sync window | Off; production can add one |
The plan shows the vCPU and memory an environment adds to the cluster, and its quota impact, before you apply.
Pricing
Section titled “Pricing”Environments have no fee of their own: every cluster comes with Frazer GitOps, gateways, DNS and certificates. On servers you bring, what your environments run is part of the per-core server fee.
| Kubernetes | On your servers | On the Frazer fleet |
|---|---|---|
| Price | $0 per cluster | $0 per cluster |
Every line, with the estimator: pricing.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Fix |
|---|---|---|
| The connect plan fails with a namespace conflict | Another environment already owns one of the namespaces. | Pick other namespaces, or move the objects and disconnect the other environment first. |
| The repository is not in the connect list | The Frazer Reader App is not installed on it. | Extend the installation to the repository under Settings › Integrations. |
| The pull request check flags a Gateway or a cluster-scoped kind | The environment’s profile is standard. |
Remove the object, or have an organization admin approve the platform profile. |
An Application is refused in repo-defined mode |
It names a GitOps project other than the environment’s. | Set its project to the environment’s own AppProject, env-<name>. |
| A pod is refused at admission | The image digest is not signed by an accepted signer, or the deploy policy blocks a fixable Critical. | Check the digest with frazer registry images describe. See Registry. |
| A sync does not start in production | A sync window refuses automated syncs outside maintenance. | Wait for the window, or start a manual sync. |
| A deletion is pending | Namespaces, volume claims, CRDs and databases wait for a confirm. | Confirm it in the console if the deletion is intended. |
A Secret in the repository is rejected |
Secret values are not allowed in Git. | Store the value in Frazer Secrets and commit an ExternalSecret. |
Reference
Section titled “Reference”CLI
| Command | What it does |
|---|---|
frazer releases environments connect | Connect a repository path to a cluster as an environment, with its namespaces, permission profile and sync policy, as a plan. |
All of them: CLI reference.
Events
| Event type | When it is sent |
|---|---|
frazer.environment.synced.v1 | An environment finished a sync. |
frazer.environment.sync_failed.v1 | An environment's sync failed. |
ai.frazer.releases.rollout.v1.started | A rollout started in an environment. |
ai.frazer.releases.rollout.v1.succeeded | A rollout finished successfully. |
ai.frazer.releases.rollout.v1.failed | A rollout failed. |
ai.frazer.releases.rollout.v1.rolledback | A rollout was rolled back. |
All of them: Events reference.
Related
Section titled “Related”- Connect your environment repo: the quickstart.
- Kubernetes: the clusters environments run on.
- Registry: push and sign the images environments run.
- Templates and previews: a preview environment per pull request.
- Reviewer: the pull request checks.
- Environments and GitOps product page