Skip to content

Commit b1b08a8

Browse files
Merge pull request #4369 from Jaisheesh-2006/docs/ci-user-guide
Fix #3756-added CI user guide in docs
2 parents c1831da + a0feca0 commit b1b08a8

4 files changed

Lines changed: 297 additions & 1 deletion

File tree

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
---
2+
title: "Chapter 9: CI user guide"
3+
linkTitle: "Chapter 9: CI user guide"
4+
description:
5+
This chapter provides a practical guide for using kpt in CI/CD workflows,
6+
including rendering (with validators) and gated apply steps.
7+
toc: true
8+
menu:
9+
main:
10+
parent: "Book"
11+
weight: 90
12+
---
13+
14+
## Overview: Using kpt in CI/CD
15+
16+
Continuous integration (CI) is the practice of running automated checks on every change so that teams can validate
17+
configuration early and consistently. In a CI/CD pipeline, kpt fits naturally because it operates on local files and
18+
produces deterministic output. This makes it easy to run in ephemeral build environments and validate changes before
19+
they reach a cluster.
20+
21+
In CI, kpt is typically used to render packages (including validators), and in some workflows to apply configuration in a
22+
gated step. CI does not author or mutate packages; it consumes versioned packages from source control and verifies that they
23+
render correctly and meet policy requirements.
24+
25+
## CI Responsibilities vs. Developer Responsibilities
26+
27+
kpt follows the configuration-as-data model: Git is the source of truth, and packages represent declared intent. The
28+
division of responsibilities exists to preserve that intent and to keep automation predictable. Developers author and
29+
declare intent in the repository, while CI renders (including validators) and optionally applies that intent in controlled
30+
environments.
31+
32+
At developer time (outside CI), teams create and evolve packages. This includes writing the `Kptfile`, declaring
33+
pipelines, and version-controlling configuration. Changes are reviewed and merged in Git so the repository remains the
34+
authoritative record.
35+
36+
At CI time, the pipeline consumes the versioned package, runs the declared pipeline with `kpt fn render`, fails fast when
37+
validators fail, and optionally applies the rendered configuration using `kpt live apply` when explicit gates are satisfied.
38+
CI should never mutate the package source as part of the build; doing so breaks the source-of-truth model and makes
39+
changes harder to audit and reproduce.
40+
41+
| Area | Developer responsibilities | CI responsibilities |
42+
| ------------------ | ------------------------------------------------------ | ----------------------------------------------------------- |
43+
| Source of truth | Author configuration in Git and manage version history | Treat Git as authoritative input |
44+
| Package definition | Create packages and write the `Kptfile` | Consume packages as-is |
45+
| Pipelines | Declare `pipeline` steps in the `Kptfile` | Execute declared pipelines with `kpt fn render` |
46+
| Validation | Choose validators and policies | Fail fast on validation results |
47+
| Apply | Decide when packages are ready to deploy | Optionally apply with `kpt live apply` under explicit gates |
48+
| Mutations | Make intentional edits in Git | Do not mutate package sources in CI (anti-pattern) |
49+
50+
## Typical kpt CI workflow (conceptual)
51+
52+
This section provides a system-agnostic mental model for how kpt is typically used in CI. The flow is intentionally
53+
simple and does not assume any specific CI platform or YAML configuration. The same steps should behave the same way
54+
when run locally or in CI, which helps keep automation deterministic and easy to debug.
55+
56+
At a high level, a CI run follows this sequence:
57+
58+
1. Check out the repository that contains the kpt package.
59+
2. Install kpt in the build environment.
60+
3. Run `kpt fn render` to execute the declared pipeline.
61+
4. Observe results and fail fast if any checks fail.
62+
5. Optionally apply the rendered resources when explicit deployment gates are satisfied.
63+
64+
![img](/images/ci-kpt-workflow.svg)
65+
66+
This flow emphasizes determinism and no hidden state: the repository is the source of truth, the rendered output is
67+
derived entirely from the checked-out files, and the results should be consistent across developer machines and CI
68+
runners.
69+
70+
## Rendering in CI
71+
72+
Rendering is the most important CI step in a kpt workflow. The `kpt fn render` command executes the package pipeline
73+
declared in the `Kptfile`, running mutators and validators in a predictable order. The output is the fully hydrated
74+
configuration that CI can use for downstream steps.
75+
76+
### Prerequisites
77+
78+
Since kpt functions run as containers, your CI environment must have access to a container runtime (for example,
79+
Podman).
80+
81+
Podman is preferred in CI because it supports rootless operation and does not require a daemon.
82+
83+
- Podman socket: Ensure your CI step can access the Podman socket (for example, `/run/podman/podman.sock` or rootless
84+
`$XDG_RUNTIME_DIR/podman/podman.sock`).
85+
- Privileges: The CI runner requires permissions to pull images and run containers.
86+
87+
### Why render (including validation)
88+
89+
Render is the default CI action because it catches configuration errors early. Validators in the pipeline fail the build
90+
when schemas, policies, or constraints are not met. This makes CI a reliable safety net before any configuration is
91+
applied to a cluster.
92+
93+
Run `kpt fn render` on every change so CI always tests the exact package state stored in Git. This keeps results
94+
deterministic and avoids hidden state between runs.
95+
96+
### `kpt fn render` vs `kpt fn eval`
97+
98+
It is important to distinguish `kpt fn render` from `kpt fn eval`:
99+
100+
- `kpt fn render`: Runs the declared pipeline from the `Kptfile`. Use this in CI to ensure the rendered output matches
101+
the intent declared in Git.
102+
- `kpt fn eval`: Runs an ad-hoc function. In CI, this is useful for extra validation (like a separate linter step), but
103+
it does not represent the package's definition.
104+
105+
## Applying configuration in CI (optional and gated)
106+
107+
Applying configuration from CI should be treated as optional and tightly controlled to prevent accidental cluster
108+
changes. In most pipelines, [kpt live apply](/reference/cli/live/apply/) runs only when a deployment is explicitly
109+
authorized.
110+
111+
Run apply only under these conditions:
112+
113+
- The pipeline is executing on the main branch.
114+
- The pipeline is part of a release workflow.
115+
- A manual approval gate has been satisfied.
116+
117+
Avoid running apply on pull requests. PRs are for review and validation, not for changing live clusters. Applying from
118+
unmerged changes makes it difficult to audit what was deployed and can introduce drift between Git and the cluster.
119+
120+
Scope cluster credentials to the minimum permissions needed for the target environment. Use separate credentials for
121+
different environments and avoid sharing production access with non-deployment jobs.
122+
123+
Always render before apply. The `kpt fn render` step produces the exact, validated output that should be deployed, and
124+
it ensures the apply step reflects the intent stored in Git.
125+
126+
Pruning & inventory (critical safety note): `kpt live apply` tracks an inventory of deployed resources and will
127+
prune resources that exist in the cluster but are missing from the current package. Unlike `kubectl apply`, it will
128+
delete resources that are absent from the rendered input. If a CI pipeline accidentally renders an empty directory and
129+
runs apply, it can delete the application. Guard apply with explicit gates and verify rendered output before
130+
deployment.
131+
132+
## Handling secrets in CI
133+
134+
Handling secrets is often the most challenging part of automation. The core principle for kpt is simple: secrets are
135+
runtime inputs, not configuration data. Git is the source of truth for declared configuration, but secrets should never
136+
be stored in the repository.
137+
138+
### The golden rules
139+
140+
- Never in Git: Secrets must not appear in YAML files, the `Kptfile`, or `functionConfig`.
141+
- Runtime only: Inject secrets only at render or apply time, and keep them in memory or a temporary filesystem.
142+
143+
### Where to store secrets
144+
145+
Do not rely on the kpt package to store sensitive data. Use one of the following:
146+
147+
- CI native stores (for example, GitHub Secrets or GitLab CI/CD Variables).
148+
- External vaults (for example, HashiCorp Vault, Google Secret Manager, AWS Secrets Manager, or Azure Key Vault).
149+
150+
### How to inject secrets
151+
152+
Because kpt separates configuration from execution, secrets must be supplied to kpt commands at runtime.
153+
154+
#### Environment variables (for functions)
155+
156+
If a function requires credentials (for example, a validator that calls an external API), pass them as environment
157+
variables. Fetch the secret in a setup step and export it so the container runtime can pass it to the function.
158+
159+
```shell
160+
$ export API_TOKEN=$(vault read -field=token secret/my-api)
161+
```
162+
163+
```shell
164+
$ kpt fn render
165+
```
166+
167+
#### File mounts (for `kpt live apply`)
168+
169+
Applying to a cluster requires credentials such as a kubeconfig file or service account token. Mount the credential
170+
file from your secret store into the CI runner's filesystem and point `kpt live apply` to it.
171+
172+
```shell
173+
$ echo "$KUBECONFIG_CONTENT" > /tmp/kubeconfig
174+
```
175+
176+
```shell
177+
$ KUBECONFIG=/tmp/kubeconfig kpt live apply
178+
```
179+
180+
### Integration with external vaults
181+
182+
When using an external vault, the standard pattern is fetch-then-run:
183+
184+
1. Authenticate: The CI job authenticates to the vault (OIDC, AppRole, or similar).
185+
2. Fetch: The job retrieves only the secrets required for this pipeline.
186+
3. Inject: Secrets are exported as environment variables or written to a tmpfs volume.
187+
4. Execute: kpt runs using the injected credentials.
188+
5. Cleanup: The CI runner is destroyed, wiping the secrets.
189+
190+
## Example: Using kpt in a Cloud Build pipeline
191+
192+
Cloud Build is a concise way to demonstrate the CI pattern, but the same structure applies to any CI system. The
193+
examples below are intentionally small and focus on the critical steps: install, render (including validators), and an
194+
optional gated apply.
195+
196+
To keep the example concrete, we use the WordPress package. You can fetch it locally with:
197+
198+
```shell
199+
$ kpt pkg get https://github.com/kptdev/kpt/package-examples/wordpress@v1.0.0-beta.59
200+
```
201+
202+
### Render-only build
203+
204+
This build renders configuration on every change and runs validators as part of the pipeline. It does not deploy.
205+
206+
```yaml
207+
steps:
208+
# Install step: install kpt into the Docker builder
209+
- name: gcr.io/cloud-builders/docker
210+
entrypoint: bash
211+
args:
212+
- -c
213+
- |
214+
curl -L https://github.com/kptdev/kpt/releases/download/${_KPT_VERSION}/kpt_linux_amd64 -o /usr/local/bin/kpt
215+
chmod +x /usr/local/bin/kpt
216+
217+
# Render step: execute declared pipeline
218+
# Validators run as part of the pipeline and fail the build when checks fail.
219+
- name: gcr.io/cloud-builders/docker
220+
entrypoint: bash
221+
args:
222+
- -c
223+
- |
224+
kpt fn render ${_PACKAGE_DIR}
225+
226+
substitutions:
227+
_KPT_VERSION: v1.0.0-beta.59
228+
_PACKAGE_DIR: wordpress
229+
```
230+
231+
### Deployment build (gated)
232+
233+
This build is intended for main or release workflows and assumes a manual approval gate. It renders first, then
234+
applies only after credentials are injected. The example uses the `package-examples/wordpress` package.
235+
236+
```yaml
237+
steps:
238+
# Install step
239+
- name: gcr.io/cloud-builders/docker
240+
entrypoint: bash
241+
args:
242+
- -c
243+
- |
244+
curl -L https://github.com/kptdev/kpt/releases/download/${_KPT_VERSION}/kpt_linux_amd64 -o /usr/local/bin/kpt
245+
chmod +x /usr/local/bin/kpt
246+
247+
# Render step
248+
- name: gcr.io/cloud-builders/docker
249+
entrypoint: bash
250+
args:
251+
- -c
252+
- |
253+
kpt fn render ${_PACKAGE_DIR}
254+
255+
# Apply step: gated deployment with secrets
256+
- name: gcr.io/cloud-builders/docker
257+
entrypoint: bash
258+
secretEnv: ["KUBECONFIG_CONTENT"]
259+
args:
260+
- -c
261+
- |
262+
# Write secret to a file for use
263+
echo "$$KUBECONFIG_CONTENT" > /workspace/kubeconfig
264+
265+
# Apply with the kubeconfig
266+
KUBECONFIG=/workspace/kubeconfig kpt live apply ${_PACKAGE_DIR}
267+
268+
substitutions:
269+
_KPT_VERSION: v1.0.0-beta.59
270+
_PACKAGE_DIR: wordpress
271+
272+
# Define where the secret comes from
273+
availableSecrets:
274+
secretManager:
275+
- versionName: projects/$PROJECT_ID/secrets/my-kubeconfig/versions/latest
276+
env: "KUBECONFIG_CONTENT"
277+
```
278+
279+
## Common mistakes and anti-patterns
280+
281+
This section highlights practices that commonly lead to CI failures, drift, or unintended cluster changes. Avoid the
282+
following:
283+
284+
- Running `kpt pkg init` in CI. Packages and `Kptfile` metadata should be authored by developers, not created during
285+
CI runs.
286+
- Mutating packages in CI. CI should validate and render the declared intent, not change the source of truth.
287+
- Storing secrets in configuration. Secrets must not appear in YAML files, the `Kptfile`, or `functionConfig`.
288+
- Applying on pull requests. PRs should validate only; deployment belongs in gated, mainline workflows.
289+
- Committing rendered output back to the source package. Rendered results are derived artifacts and should not be
290+
committed to the source repository in CI.

documentation/content/en/book/_index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ This book is organized as follows:
2121
- [Chapter 5] guides you through developing custom functions.
2222
- [Chapter 6] covers how to deploy a package to a Kubernetes cluster.
2323
- [Chapter 7] covers effective customizations techniques.
24+
- [Chapter 9] provides a practical guide for using kpt in CI/CD workflows.
2425

2526
Let's get started!
2627

@@ -31,4 +32,5 @@ Let's get started!
3132
[chapter 5]: /book/05-developing-functions/
3233
[chapter 6]: /book/06-deploying-packages/
3334
[chapter 7]: /book/07-effective-customizations/
34-
[chapter 8]: /book/08-package-orchestration/
35+
[chapter 8]: /book/08-package-orchestration/
36+
[chapter 9]: /book/09-ci-user-guide/
5.95 MB
Loading

documentation/static/images/ci-kpt-workflow.svg

Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)