File: chart.md

package info (click to toggle)
kustomize 5.6.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,572 kB
  • sloc: makefile: 162; sh: 123
file content (370 lines) | stat: -rw-r--r-- 9,681 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# kustomization of a helm chart

[`helm`]: https://helm.sh
[last mile]: https://testingclouds.wordpress.com/2018/07/20/844/
[artifact hub]: https://artifacthub.io
[_minecraft_]: https://artifacthub.io/packages/helm/minecraft-server-charts/minecraft
[plugin]: ../docs/plugins
[built]: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization

Kustomize is [built] from _generators_ and
_transformers_; the former make kubernetes YAML, the
latter transform said YAML.

Kustomize, via the `helmCharts` field, has the ability to
use the [`helm`] command line program in a subprocess to
inflate a helm chart, generating YAML as part of (or as the
entirety of) a kustomize base.

This YAML can then be modified either in the base directly
(transformers always run _after_ generators), or via
a kustomize overlay.

Either approach can be viewed as [last mile] modification
of the chart output before applying it to a cluster.

The example below arbitrarily uses the
[_minecraft_] chart pulled from the [artifact hub]
chart repository.

## Preparation

This example defines the `helm` command as
<!-- @defineHelmCommand @testHelm -->
```
helmCommand=${MYGOBIN:-~/go/bin}/helmV3
```

This value is needed for testing this example in CI/CD.
A user doesn't need this if their binary is called
`helm` and is on their shell's `PATH`.


Make a place to work:

<!-- @makeWorkplace @testHelm -->
```
DEMO_HOME=$(mktemp -d)
mkdir -p $DEMO_HOME/base $DEMO_HOME/dev $DEMO_HOME/prod
```

## Define some variants

Define a kustomization representing your _development_
variant.

This could involve any number of kustomizations (see
other examples), but in this case just add the name
prefix '`dev-`' to all resources:

<!-- @writeKustDev @testHelm -->
```
cat <<'EOF' >$DEMO_HOME/dev/kustomization.yaml
namePrefix:  dev-
resources:
- ../base
EOF
```

Likewise define a _production_ variant, with a name
prefix '`prod-`':

<!-- @writeKustProd @testHelm -->
```
cat <<'EOF' >$DEMO_HOME/prod/kustomization.yaml
namePrefix:  prod-
resources:
- ../base
EOF
```

These two variants refer to a common base.

Define this base the usual way by creating a
`kustomization` file:

<!-- @writeKustBase @testHelm -->
```
cat <<'EOF' >$DEMO_HOME/base/kustomization.yaml
helmCharts:
- name: minecraft
  includeCRDs: false
  valuesInline:
    minecraftServer:
      eula: true
      difficulty: hard
      rcon:
        enabled: true
  releaseName: moria
  version: 3.1.3
  repo: https://itzg.github.io/minecraft-server-charts
EOF
```

The only thing in this particular file is a `helmCharts`
field, specifying a single chart.

The `valuesInline` field overrides some native chart values.

The `includeCRDs` field instructs Helm to generate 
`CustomResourceDefinitions`. 
See [the Helm documentation](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/) for details.

Check the directory layout:

<!-- @tree -->
```
tree $DEMO_HOME
```

Expect something like:

> ```
> /tmp/whatever
> ├── base
> │  └── kustomization.yaml
> ├── dev
> │  └── kustomization.yaml
> └── prod
>    └── kustomization.yaml
> ```

### Helm related flags

Attempt to build the `base`:

<!-- @checkFailure @testHelm -->
```
cmd="kustomize build --helm-command $helmCommand $DEMO_HOME/base"
if ($cmd); then
   echo "Build should fail!" && false  # Force test to fail.
else
   echo "Build failed because no --enable-helm flag (desired outcome)."
fi
```

This `build` fails and complains about a missing
`--enable-helm` flag.

The flag `--enable-helm` exists to have the user
acknowledge that kustomize is running an external program as
part of the `build` step.  It's like the
`--enable-plugins` flag, but with a helm focus.

The flag `--helm-command` has a default value (`helm` of
course) so it's not suitable as an enablement flag.  A user
with `helm` on their `PATH` need not awkwardly specify
`'--helm-command helm'`.

Given the above, define a helper function to run `kustomize` with the
flags required for `helm` use in this demo:

<!-- @defineKustomizeIt @testHelm -->
```
function kustomizeIt {
  kustomize build \
    --enable-helm \
    --helm-command $helmCommand \
    $DEMO_HOME/$1
}
```
### Build the base and the variants

Now build the `base`:

<!-- @showBase @testHelm -->
```
kustomizeIt base
```

This works, and you see an inflated chart complete
with a `Secret`, `Service`, `Deployment`, etc.

As a side effect of this build, kustomize pulled the chart
and placed it in the `charts` subdirectory of the base.
Take a look:

<!-- @tree -->
```
tree $DEMO_HOME
```

If the chart had already been there, kustomize would
not have tried to pull it.

To change the location of the charts, use this
in your kustomization file:

> ```
> helmGlobals:
>  chartHome: charts
> ```

Change `charts` as desired, but it's best to keep it
in (or below) the same directory as the `kustomization.yaml` file.
If it's outside the kustomization root, the `build` command will
fail unless given the flag `'--load-restrictor=none'` to
disable file loading restrictions.

Now build the two variants `dev` and `prod`
and compare their differences:

<!-- @doCompare -->
```
diff <(kustomizeIt dev) <(kustomizeIt prod) | more
```

This shows so-called _last mile hydration_ of two variants
made from a common base that happens to be generated from a
helm chart.

## How does the pull work?

The command kustomize used to download the chart
is something like

> ```
> $helmCommand pull \
>    --untar \
>    --untardir $DEMO_HOME/base/charts \
>    --repo https://itzg.github.io/minecraft-server-charts \
>    --version 3.1.3 \
>    minecraft
> ```

The first use of kustomize above (when the `base` was
expanded) fetched the chart and placed it in the `charts`
directory next to the `kustomization.yaml` file.

This chart was reused, _not_ re-fetched, with the variant
expansions `prod` and `dev`.

If a chart exists, kustomize will not overwrite it (so to
suppress a pull, simply assure the chart is already in your
kustomization root).  kustomize won't check dates or version
numbers or do anything that smells like cache management.

> kustomize is a YAML manipulator.  It's not a manager
> of a cache of things downloaded from the internet.

## The pull happens once.

To show that the locally stored chart is being re-used, modify
its _values_ file.

First make note of the password encoded in the production
inflation:

<!-- @checkPassword @testHelm -->
```
test 1 == $(kustomizeIt prod | grep -c "rcon-password: Q0hBTkdFTUUh")
```

The above command succeeds if the value of the generated
password is as shown (`Q0hBTkdFTUUh`).

Now change the password in the local values file:

<!-- @valueChange @testHelm -->
```
values=$DEMO_HOME/base/charts/minecraft-3.1.3/minecraft/values.yaml

grep CHANGEME $values
sed -i 's/CHANGEME/SOMETHING_ELSE/' $values
grep SOMETHING_ELSE $values
```

Run the build, and confirm that the same `rcon-password`
field in the output has a new value, confirming that the
chart used was a _local_ chart, not a chart freshly
downloaded from the internet:


<!-- @checkPassword2 @testHelm -->
```
test 1 == $(kustomizeIt prod | grep -c "rcon-password: U09NRVRISU5HX0VMU0Uh")
```

Finally, clean up:

<!-- @showBase @testHelm -->
```
rm -r $DEMO_HOME
```

## Performance

To recap, the helm-related kustomization fields make
kustomize run

> ```
> helm pull ...
> helm template ...
> ```

_as a convenience for the user_ to generate YAML from a helm chart.

Helm's `pull` command downloads the chart.  Helm's `template`
command inflates the chart template, spitting the inflated
template to stdout (where kustomize captures it) rather than
immediately sending it to a cluster as `helm install`
would.

To improve performance, a user can retain the chart after
the first pull, and commit the chart to their configuration
repository (below the `kustomization.yaml` file that refers
to it).  kustomize only tries to pull the chart if it's not
already there.

To further improve performance, a user can inflate the
chart themselves at the command line, e.g.

> ```
> helm template {releaseName} \
>     --values {valuesFile} \
>     --version {version} \
>     --repo {repo} \
>     {chartName} > {chartName}.yaml
> ```

then commit the resulting `{chartName}.yaml` file to a git
repo as a configuration base, mentioning that file as a
`resource` in a `kustomization.yaml` file, e.g.

> ```
> resources:
> - minecraft_v3.1.3_Chart.yaml
> ```

The user should choose when or if to refresh their local
copy of the chart's inflation.  kustomize would have no
awareness that the YAML was generated by helm, and kustomize
wouldn't run `helm` during the `build`.  This is analogous
to `Go` module vendoring.

### But it's not really about performance.

Although the `helm` related fields discussed above are handy
for experimentation and development, it's best to avoid them
in production.

The same argument applies to using _remote_ git URL's in
other kustomization fields.  Handy for experimentation,
but ill-advised in production.

It's irresponsible to depend on a remote configuration
that's _not under your control_.  Annoying enablement flags
like `'--enable-helm'` are intended to _remind_ one of a
risk, but offer zero protection from risk.  Further, they
are useless are reminders, since __annoying things are
immediately scripted away and forgotten__, as was done above
in the `kustomizeIt` shell function.

## Best practice

Don't use remote configuration that you don't control in
production.

Maintain a _local, inflated fork_ of a remote configuration,
and have a human rebase / reinflate that fork from time to
time to capture upstream changes.