mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-13 10:00:56 +00:00
Merge branch 'master' into config-map-consistency
This commit is contained in:
@@ -1,38 +1,78 @@
|
||||
English | [简体中文](zh/README.md)
|
||||
|
||||
# Examples
|
||||
|
||||
These examples assume that `kustomize` is on your `$PATH`.
|
||||
To run these examples, your `$PATH` must contain `kustomize`.
|
||||
See the [installation instructions](../docs/INSTALL.md).
|
||||
|
||||
They are covered by [pre-commit](../bin/pre-commit.sh)
|
||||
tests, and should work with HEAD
|
||||
These examples are [tested](../hack/testExamplesAgainstKustomize.sh)
|
||||
to work with the latest _released_ version of kustomize.
|
||||
|
||||
<!-- @installkustomize @test -->
|
||||
```
|
||||
go get github.com/kubernetes-sigs/kustomize
|
||||
```
|
||||
Basic Usage
|
||||
|
||||
* [hello world](helloWorld/README.md) - Deploy multiple
|
||||
* [valueAdd](valueAdd.md) -
|
||||
Add a simple string value easily to various fields, including
|
||||
fields that happen to hold file paths.
|
||||
|
||||
* [configGenerations](configGeneration.md) -
|
||||
Rolling update when ConfigMapGenerator changes.
|
||||
|
||||
* [combineConfigs](combineConfigs.md) -
|
||||
Mixing configuration data from different owners
|
||||
(e.g. devops/SRE and developers).
|
||||
|
||||
* [generatorOptions](generatorOptions.md) -
|
||||
Modifying behavior of all ConfigMap and Secret generators.
|
||||
|
||||
* [vars](wordpress/README.md) - Injecting k8s runtime data into
|
||||
container arguments (e.g. to point wordpress to a SQL service) by vars.
|
||||
|
||||
* [image names and tags](image.md) - Updating image names and tags without applying a patch.
|
||||
|
||||
* [remote target](remoteBuild.md) - Building a kustomization from a github URL
|
||||
|
||||
* [json patch](jsonpatch.md) - Apply a json patch in a kustomization
|
||||
|
||||
* [patch multiple objects](patchMultipleObjects.md) - Apply a patch to multiple objects
|
||||
|
||||
Advanced Usage
|
||||
|
||||
- generator plugins:
|
||||
|
||||
* [last mile helm](chart.md) - Make last mile modifications to
|
||||
a helm chart.
|
||||
|
||||
* [secret generation](secretGeneratorPlugin.md) - Generating secrets from a plugin.
|
||||
|
||||
* [remote sources](goGetterGeneratorPlugin.md) - Generating from remote sources.
|
||||
|
||||
- transformer plugins:
|
||||
* [validation transformer](validationTransformer/README.md) -
|
||||
validate resources through a transformer
|
||||
|
||||
- customize builtin transformer configurations
|
||||
|
||||
* [transformer configs](transformerconfigs/README.md) - Customize transformer configurations
|
||||
|
||||
|
||||
Multi Variant Examples
|
||||
|
||||
* [hello world](helloWorld/README.md) - Deploy multiple
|
||||
(differently configured) variants of a simple Hello
|
||||
World server.
|
||||
|
||||
* [LDAP](ldap/README.md) - Deploy multiple
|
||||
(differently configured) variants of a LDAP server.
|
||||
* [LDAP](ldap/README.md) - Deploy multiple
|
||||
(differently configured) variants of a LDAP server.
|
||||
|
||||
* [mySql](mySql/README.md) - Create a MySQL production
|
||||
configuration from scratch.
|
||||
|
||||
* [springboot](springboot/README.md) - Create a Spring Boot
|
||||
* [springboot](springboot/README.md) - Create a Spring Boot
|
||||
application production configuration from scratch.
|
||||
|
||||
* [combineConfigs](combineConfigs.md) -
|
||||
Mixing configuration data from different owners
|
||||
(e.g. devops/SRE and developers).
|
||||
|
||||
* [configGenerations](configGeneration.md) -
|
||||
Rolling update when ConfigMapGenerator changes
|
||||
* [mySql](mySql/README.md) - Create a MySQL production
|
||||
configuration from scratch.
|
||||
|
||||
* [breakfast](breakfast.md) - Customize breakfast for
|
||||
Alice and Bob.
|
||||
|
||||
* [container args](wordpress/README.md) - Injecting k8s runtime data into container arguments (e.g. to point wordpress to a SQL service).
|
||||
|
||||
* [image tags](imageTags.md) - Updating image tags without applying a patch.
|
||||
* [breakfast](breakfast.md) - Customize breakfast for
|
||||
Alice and Bob.
|
||||
|
||||
* [multibases](multibases/README.md) - Composing three variants (dev, staging, production) with a common base.
|
||||
|
||||
* [components](components.md) - Compose three variants (community, enterprise, dev) with a common base, by reusing configuration between them.
|
||||
|
||||
152
examples/alphaTestExamples/MultipleDeployments.md
Normal file
152
examples/alphaTestExamples/MultipleDeployments.md
Normal file
@@ -0,0 +1,152 @@
|
||||
[kind]: https://github.com/kubernetes-sigs/kind
|
||||
|
||||
# Demo: Multiple Deployments
|
||||
|
||||
This demo helps you to multiple services on same kubenetes cluster using kustomize.
|
||||
|
||||
Steps:
|
||||
1. Create the resources files for wordpress service.
|
||||
2. Create the resources files for mysql service.
|
||||
3. Spin-up kubernetes cluster on local using [kind].
|
||||
4. Deploy the wordpress app using kustomize and verify the status.
|
||||
5. Deploy the mysql app using kustomize on same "kind" cluster and verify the status.
|
||||
6. Add and remove a resource to mysql service and verify prune.
|
||||
|
||||
First define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Alternatively, use
|
||||
|
||||
> ```
|
||||
> DEMO_HOME=~/hello
|
||||
> ```
|
||||
|
||||
## Establish the base
|
||||
|
||||
<!-- @createBase @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
OUTPUT=$DEMO_HOME/output
|
||||
mkdir -p $OUTPUT
|
||||
|
||||
mkdir $BASE/wordpress
|
||||
mkdir $BASE/mysql
|
||||
|
||||
curl -s -o "$BASE/wordpress/#1.yaml" "https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/wordpress/wordpress\
|
||||
/{deployment,kustomization,service}.yaml"
|
||||
|
||||
curl -s -o "$BASE/mysql/#1.yaml" "https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/wordpress/mysql\
|
||||
/{secret,deployment,kustomization,service}.yaml"
|
||||
```
|
||||
|
||||
Create a `grouping.yaml` resource. By this, you are defining the grouping of the current directory, `mysql`. Kustomize uses the unique label in this file to track any future state changes made to this directory. Make sure the label key is `kustomize.config.k8s.io/inventory-id` and give any unique label value and DO NOT change it in future.
|
||||
<!-- @createGroupingYaml @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
cat <<EOF >$BASE/mysql/grouping.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: inventory-map
|
||||
labels:
|
||||
kustomize.config.k8s.io/inventory-id: mysql-app
|
||||
EOF
|
||||
```
|
||||
|
||||
Delete any existing kind cluster and create a new one. By default the name of the cluster is "kind"
|
||||
<!-- @deleteAndCreateKindCluster @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
kind delete cluster
|
||||
kind create cluster
|
||||
```
|
||||
|
||||
Let's run the wordpress and mysql services.
|
||||
<!-- @RunWordpressAndMysql @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
export KUSTOMIZE_ENABLE_ALPHA_COMMANDS=true
|
||||
|
||||
kustomize resources apply $BASE/mysql --status;
|
||||
|
||||
status=$(mktemp);
|
||||
kustomize status fetch $BASE/mysql > $OUTPUT/status
|
||||
|
||||
test 1 == \
|
||||
$(grep "mysql" $OUTPUT/status | grep "Deployment is available. Replicas: 1" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "mysql-pass" $OUTPUT/status | grep "Resource is always ready" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "mysql" $OUTPUT/status | grep "Service is ready" | wc -l); \
|
||||
echo $?
|
||||
|
||||
kustomize resources apply $BASE/wordpress --status;
|
||||
|
||||
status=$(mktemp);
|
||||
kustomize status fetch $BASE/wordpress > $OUTPUT/status
|
||||
|
||||
test 1 == \
|
||||
$(grep "wordpress" $OUTPUT/status | grep "Deployment is available. Replicas: 1" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "wordpress" $OUTPUT/status | grep "Service is ready" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Let's replace the secret resource from mysql service and verify prune and addition of resource.
|
||||
<!-- @ReplaceResourceInMysql @testE2EAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat <<EOF >$BASE/mysql/secret2.yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: mysql-pass2
|
||||
type: Opaque
|
||||
data:
|
||||
# Default password is "admin".
|
||||
password: YWRtaW5=
|
||||
EOF
|
||||
|
||||
rm $BASE/mysql/secret.yaml
|
||||
|
||||
sed -i.bak 's/secret/secret2/' \
|
||||
$BASE/mysql/kustomization.yaml
|
||||
|
||||
sed -i.bak 's/mysql-pass/mysql-pass2/' \
|
||||
$BASE/mysql/deployment.yaml
|
||||
|
||||
kustomize resources apply $BASE/mysql --status;
|
||||
|
||||
status=$(mktemp);
|
||||
kustomize status fetch $BASE/mysql > $OUTPUT/status
|
||||
|
||||
test 1 == \
|
||||
$(grep "mysql" $OUTPUT/status | grep "Deployment is available. Replicas: 1" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "mysql-pass2" $OUTPUT/status | grep "Resource is always ready" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "mysql" $OUTPUT/status | grep "Service is ready" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Clean-up the cluster
|
||||
<!-- @deleteKindCluster @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
kind delete cluster
|
||||
```
|
||||
240
examples/alphaTestExamples/helloapp.md
Normal file
240
examples/alphaTestExamples/helloapp.md
Normal file
@@ -0,0 +1,240 @@
|
||||
[hello]: https://github.com/monopole/hello
|
||||
[kind]: https://github.com/kubernetes-sigs/kind
|
||||
[helloWorld]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/helloWorld
|
||||
|
||||
# Demo: hello app
|
||||
|
||||
This demo helps you to deploy an example hello app end-to-end using kustomize.
|
||||
|
||||
Steps:
|
||||
1. Create the resources files.
|
||||
2. Kustomize them.
|
||||
3. Spin-up kubernetes cluster on local using [kind].
|
||||
4. Deploy the app using kustomize and verify the status.
|
||||
|
||||
First define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Alternatively, use
|
||||
|
||||
> ```
|
||||
> DEMO_HOME=~/hello
|
||||
> ```
|
||||
|
||||
## Establish the base
|
||||
|
||||
Let's run the [hello] service.
|
||||
|
||||
<!-- @createBase @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
OUTPUT=$DEMO_HOME/output
|
||||
mkdir -p $OUTPUT
|
||||
```
|
||||
|
||||
Now lets add a simple config map resource to the `base`
|
||||
|
||||
<!-- @createConfigMapYaml @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
cat <<EOF >$BASE/configMap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
data:
|
||||
altGreeting: "Good Morning!"
|
||||
enableRisky: "false"
|
||||
EOF
|
||||
```
|
||||
|
||||
Create `deployment.yaml` with any image and with desired number of replicas
|
||||
|
||||
<!-- @createDeploymentYaml @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
cat <<EOF >$BASE/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
deployment: hello
|
||||
spec:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: monopole/hello:1
|
||||
command: ["/hello",
|
||||
"--port=8080",
|
||||
"--enableRiskyFeature=\$(ENABLE_RISKY)"]
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: ALT_GREETING
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: altGreeting
|
||||
- name: ENABLE_RISKY
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: enableRisky
|
||||
EOF
|
||||
```
|
||||
|
||||
Create `service.yaml` pointing to the deployment created above
|
||||
|
||||
<!-- @createServiceYaml @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
cat <<EOF >$BASE/service.yaml
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: the-service
|
||||
spec:
|
||||
selector:
|
||||
deployment: hello
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8666
|
||||
targetPort: 8080
|
||||
EOF
|
||||
```
|
||||
|
||||
Create a `grouping.yaml` resource. By this, you are defining the grouping of the current directory, `base`. Kustomize uses the unique label in this file to track any future state changes made to this directory. Make sure the label key is `kustomize.config.k8s.io/inventory-id` and give any unique label value and DO NOT change it in future.
|
||||
|
||||
<!-- @createGroupingYaml @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
cat <<EOF >$BASE/grouping.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: inventory-map
|
||||
labels:
|
||||
kustomize.config.k8s.io/inventory-id: hello-app
|
||||
EOF
|
||||
```
|
||||
|
||||
Now, create `kustomization.yaml` add all your resources.
|
||||
|
||||
<!-- @createKustomizationYaml @testE2EAgainstLatestRelease-->
|
||||
```
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
commonLabels:
|
||||
app: hello
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- configMap.yaml
|
||||
- grouping.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
### The Base Kustomization
|
||||
|
||||
The `base` directory has a kustomization file:
|
||||
|
||||
<!-- @showKustomization @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
more $BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
### Customize the base
|
||||
|
||||
A simple customization step could be to change the _app
|
||||
label_ applied to all resources:
|
||||
|
||||
<!-- @addLabel @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
sed -i.bak 's/app: hello/app: my-hello/' \
|
||||
$BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
The following requires installation of [kind].
|
||||
|
||||
Delete any existing kind cluster and create a new one. By default the name of the cluster is "kind"
|
||||
<!-- @deleteAndCreateKindCluster @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
kind delete cluster
|
||||
kind create cluster
|
||||
```
|
||||
|
||||
Use the kustomize binary in MYGOBIN to apply a deployment, fetch the status and verify the status.
|
||||
<!-- @runHelloApp @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
export KUSTOMIZE_ENABLE_ALPHA_COMMANDS=true
|
||||
|
||||
kustomize resources apply $BASE --status;
|
||||
|
||||
kustomize status fetch $BASE > $OUTPUT/status
|
||||
|
||||
test 1 == \
|
||||
$(grep "the-deployment" $OUTPUT/status | grep "Deployment is available. Replicas: 3" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "the-map" $OUTPUT/status | grep "Resource is always ready" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "the-service" $OUTPUT/status | grep "Service is ready" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Now let's replace the configMap with configMap2 apply the config, fetch and verify the status. This should delete the-map from deployment and add the-map2.
|
||||
<!-- @replaceConfigMapInHello @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$BASE/configMap2.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map2
|
||||
data:
|
||||
altGreeting: "Good Evening!"
|
||||
enableRisky: "false"
|
||||
EOF
|
||||
|
||||
rm $BASE/configMap.yaml
|
||||
|
||||
sed -i.bak 's/configMap/configMap2/' \
|
||||
$BASE/kustomization.yaml
|
||||
|
||||
sed -i.bak 's/the-map/the-map2/' \
|
||||
$BASE/deployment.yaml
|
||||
|
||||
kustomize resources apply $BASE --status;
|
||||
|
||||
status=$(mktemp);
|
||||
kustomize status fetch $BASE > $OUTPUT/status
|
||||
|
||||
test 1 == \
|
||||
$(grep "the-deployment" $OUTPUT/status | grep "Deployment is available. Replicas: 3" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "the-map2" $OUTPUT/status | grep "Resource is always ready" | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(grep "the-service" $OUTPUT/status | grep "Service is ready" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Clean-up the cluster
|
||||
<!-- @deleteKindCluster @testE2EAgainstLatestRelease -->
|
||||
```
|
||||
kind delete cluster
|
||||
```
|
||||
|
||||
### Next Exercise
|
||||
Create overlays as described in the [helloWorld] section and verify the results.
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
Define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Make a place to put the base breakfast configuration:
|
||||
|
||||
<!-- @baseDir @test -->
|
||||
<!-- @baseDir @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/breakfast/base
|
||||
```
|
||||
@@ -21,7 +21,7 @@ mkdir -p $DEMO_HOME/breakfast/base
|
||||
Make a `kustomization` to define what goes into
|
||||
breakfast. This breakfast has coffee and pancakes:
|
||||
|
||||
<!-- @baseKustomization @test -->
|
||||
<!-- @baseKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/breakfast/base/kustomization.yaml
|
||||
resources:
|
||||
@@ -34,7 +34,7 @@ Here's a _coffee_ type. Give it a `kind` and `metdata/name` field
|
||||
to conform to [kubernetes API object style]; no other
|
||||
file or definition is needed:
|
||||
|
||||
<!-- @coffee @test -->
|
||||
<!-- @coffee @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/breakfast/base/coffee.yaml
|
||||
kind: Coffee
|
||||
@@ -50,7 +50,7 @@ The `name` field merely distinguishes this instance of
|
||||
coffee from others (if there were any).
|
||||
|
||||
Likewise, define _pancakes_:
|
||||
<!-- @pancakes @test -->
|
||||
<!-- @pancakes @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/breakfast/base/pancakes.yaml
|
||||
kind: Pancakes
|
||||
@@ -64,16 +64,16 @@ EOF
|
||||
Make a custom [variant] of breakfast for Alice, who
|
||||
likes her coffee hot:
|
||||
|
||||
<!-- @aliceOverlay @test -->
|
||||
<!-- @aliceOverlay @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/breakfast/overlays/alice
|
||||
|
||||
cat <<EOF >$DEMO_HOME/breakfast/overlays/alice/kustomization.yaml
|
||||
commonLabels:
|
||||
who: alice
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- temperature.yaml
|
||||
EOF
|
||||
|
||||
@@ -87,16 +87,16 @@ EOF
|
||||
|
||||
And likewise a [variant] for Bob, who wants _five_ pancakes, with strawberries:
|
||||
|
||||
<!-- @bobOverlay @test -->
|
||||
<!-- @bobOverlay @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/breakfast/overlays/bob
|
||||
|
||||
cat <<EOF >$DEMO_HOME/breakfast/overlays/bob/kustomization.yaml
|
||||
commonLabels:
|
||||
who: bob
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- topping.yaml
|
||||
EOF
|
||||
|
||||
@@ -111,14 +111,14 @@ EOF
|
||||
|
||||
One can now generate the configs for Alice’s breakfast:
|
||||
|
||||
<!-- @generateAlice @test -->
|
||||
<!-- @generateAlice @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME/breakfast/overlays/alice
|
||||
```
|
||||
|
||||
Likewise for Bob:
|
||||
|
||||
<!-- @generateBob @test -->
|
||||
<!-- @generateBob @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME/breakfast/overlays/bob
|
||||
```
|
||||
|
||||
370
examples/chart.md
Normal file
370
examples/chart.md
Normal file
@@ -0,0 +1,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/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.
|
||||
@@ -92,9 +92,9 @@ secret holding them (not covering that here).
|
||||
<!--
|
||||
secretGenerator:
|
||||
- name: app-tls
|
||||
commands:
|
||||
tls.crt: "cat tls.cert"
|
||||
tls.key: "cat tls.key"
|
||||
files:
|
||||
tls.crt=tls.cert
|
||||
tls.key=tls.key
|
||||
type: "kubernetes.io/tls"
|
||||
EOF
|
||||
-->
|
||||
@@ -128,7 +128,7 @@ defined in the [helloworld] demo.
|
||||
|
||||
It will all live in this work directory:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
@@ -139,7 +139,7 @@ DEMO_HOME=$(mktemp -d)
|
||||
|
||||
Make a place to put the base configuration:
|
||||
|
||||
<!-- @baseDir @test -->
|
||||
<!-- @baseDir @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/base
|
||||
```
|
||||
@@ -150,7 +150,7 @@ environments. Here we're only defining a java
|
||||
properties file, and a `kustomization` file that
|
||||
references it.
|
||||
|
||||
<!-- @baseKustomization @test -->
|
||||
<!-- @baseKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/base/common.properties
|
||||
color=blue
|
||||
@@ -171,14 +171,14 @@ EOF
|
||||
Make an abbreviation for the parent of the overlay
|
||||
directories:
|
||||
|
||||
<!-- @overlays @test -->
|
||||
<!-- @overlays @testAgainstLatestRelease -->
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
```
|
||||
|
||||
Create the files that define the _development_ overlay:
|
||||
|
||||
<!-- @developmentFiles @test -->
|
||||
<!-- @developmentFiles @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $OVERLAYS/development
|
||||
|
||||
@@ -191,9 +191,10 @@ dbpassword=mothersMaidenName
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/development/kustomization.yaml
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
namePrefix: dev-
|
||||
nameSuffix: -v1
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
@@ -205,7 +206,7 @@ EOF
|
||||
|
||||
One can now generate the configMaps for development:
|
||||
|
||||
<!-- @runDev @test -->
|
||||
<!-- @runDev @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/development
|
||||
```
|
||||
@@ -215,11 +216,12 @@ kustomize build $OVERLAYS/development
|
||||
The name of the generated `ConfigMap` is visible in this
|
||||
output.
|
||||
|
||||
The name should be something like `dev-my-configmap-b5m75ck895`:
|
||||
The name should be something like `dev-my-configmap-v1-2gccmccgd5`:
|
||||
|
||||
* `"dev-"` comes from the `namePrefix` field,
|
||||
* `"my-configmap"` comes from the `configMapGenerator/name` field,
|
||||
* `"-b5m75ck895"` comes from a deterministic hash that `kustomize`
|
||||
* `"-v1"` comes from the `nameSuffix` field,
|
||||
* `"-2gccmccgd5"` comes from a deterministic hash that `kustomize`
|
||||
computes from the contents of the configMap.
|
||||
|
||||
The hash suffix is critical. If the configMap content
|
||||
@@ -249,8 +251,15 @@ specification of the cluster's desired state to
|
||||
point deployments to _new_ configMaps with _new_ names.
|
||||
`kustomize` makes this easy with its
|
||||
`configMapGenerator` directive and associated naming
|
||||
controls. A GC process in the k8s master eventually
|
||||
deletes unused configMaps.
|
||||
controls.
|
||||
|
||||
To remove outdated configMaps add a label
|
||||
to your resource, for example, kustomize-cleanup="true",
|
||||
and then you can use `kustomize` to prune old resources^
|
||||
|
||||
> ```
|
||||
> kustomize build | kubectl apply --prune -f- -l kustomize-cleanup="true"
|
||||
> ```
|
||||
|
||||
|
||||
### Create and use the overlay for _production_
|
||||
@@ -258,7 +267,7 @@ deletes unused configMaps.
|
||||
Next, create the files for the _production_ overlay:
|
||||
|
||||
|
||||
<!-- @productionFiles @test -->
|
||||
<!-- @productionFiles @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $OVERLAYS/production
|
||||
|
||||
@@ -271,7 +280,7 @@ dbpassword=thisShouldProbablyBeInASecretInstead
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/production/kustomization.yaml
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
namePrefix: prod-
|
||||
configMapGenerator:
|
||||
@@ -285,13 +294,13 @@ EOF
|
||||
|
||||
One can now generate the configMaps for production:
|
||||
|
||||
<!-- @runProd @test -->
|
||||
<!-- @runProd @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/production
|
||||
```
|
||||
|
||||
A CICD process could apply this directly to
|
||||
the cluser using:
|
||||
the cluster using:
|
||||
|
||||
> ```
|
||||
> kustomize build $OVERLAYS/production | kubectl apply -f -
|
||||
|
||||
794
examples/components.md
Normal file
794
examples/components.md
Normal file
@@ -0,0 +1,794 @@
|
||||
# Demo: Components
|
||||
|
||||
For more details regarding this feature you can read the
|
||||
[Kustomize Components KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-cli/1802-kustomize-components/README.md).
|
||||
|
||||
_This example requires Kustomize ``v3.7.0`` or newer_
|
||||
|
||||
Suppose you've written a very simple Web application:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: example
|
||||
image: example:1.0
|
||||
```
|
||||
|
||||
You want to deploy a **community** edition of this application as SaaS, so you
|
||||
add support for persistence (e.g. an external database), and bot detection
|
||||
(e.g. Google reCAPTCHA).
|
||||
|
||||
You've now attracted **enterprise** customers who want to deploy it
|
||||
on-premises, so you add LDAP support, and disable Google reCAPTCHA. At the same
|
||||
time, the **devs** need to be able to test parts of the application, so they
|
||||
want to deploy it with some features enabled and others not.
|
||||
|
||||
Here's a matrix with the deployments of this application and the features
|
||||
enabled for each one:
|
||||
|
||||
| | External DB | LDAP | reCAPTCHA |
|
||||
|------------|:------------------:|:------------------:|:------------------:|
|
||||
| Community | :heavy_check_mark: | | :heavy_check_mark: |
|
||||
| Enterprise | :heavy_check_mark: | :heavy_check_mark: | |
|
||||
| Dev | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
So, you want to make it easy to deploy your application in any of the above
|
||||
three environments. This seems like a work for [variants], so you try to create
|
||||
three overlays; a `community/`, an `enterprise/` and a `dev/` overlay, that each
|
||||
provides the appropriate features for their audience, i.e., public, customers and
|
||||
developers, respectfully.
|
||||
|
||||
## Variants example
|
||||
|
||||
Here's the common and most simplistic approach to solve this problem. As we will
|
||||
soon see, this approach does not scale well in more complex scenarios. However,
|
||||
it will help you get a better grasp of the problem we are about to tackle and
|
||||
demonstrate where there is room for improvement.
|
||||
|
||||
First, define a place to work:
|
||||
|
||||
```shell
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Define a common **base** that has a `Deployment` and a simple `ConfigMap`, that
|
||||
is mounted on the application's container.
|
||||
|
||||
```shell
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: conf
|
||||
literals:
|
||||
- main.conf=|
|
||||
color=cornflower_blue
|
||||
log_level=info
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: example
|
||||
image: example:1.0
|
||||
volumeMounts:
|
||||
- name: conf
|
||||
mountPath: /etc/config
|
||||
volumes:
|
||||
- name: conf
|
||||
configMap:
|
||||
name: conf
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a **community** overlay that:
|
||||
|
||||
- generates `Secrets` for external DB's password and reCAPTCHA's keys
|
||||
- patches the `ConfigMap` of the common base with configurations for external DB
|
||||
and reCAPTCHA
|
||||
- patches the `Deployment` of the common base to mount the generated `Secrets`
|
||||
for external DB and reCAPTCHA
|
||||
|
||||
```shell
|
||||
COMMUNITY=$DEMO_HOME/overlays/community
|
||||
mkdir -p $COMMUNITY
|
||||
|
||||
cat <<EOF >$COMMUNITY/kustomization.yaml
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
secretGenerator:
|
||||
- name: dbpass
|
||||
files:
|
||||
- dbpass.txt
|
||||
- name: recaptcha
|
||||
files:
|
||||
- site_key.txt
|
||||
- secret_key.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$COMMUNITY/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: dbpass
|
||||
secret:
|
||||
secretName: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/db/
|
||||
name: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: recaptcha
|
||||
secret:
|
||||
secretName: recaptcha
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/recaptcha/
|
||||
name: recaptcha
|
||||
EOF
|
||||
|
||||
cat <<EOF >$COMMUNITY/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
db.conf: |
|
||||
endpoint=127.0.0.1:1234
|
||||
name=app
|
||||
user=admin
|
||||
pass=/var/run/secrets/db/dbpass.txt
|
||||
recaptcha.conf: |
|
||||
enabled=true
|
||||
site_key=/var/run/secrets/recaptcha/site_key.txt
|
||||
secret_key=/var/run/secrets/recaptcha/secret_key.txt
|
||||
EOF
|
||||
```
|
||||
|
||||
Create local input files for external DB's password and reCAPTCHA's keys:
|
||||
|
||||
```shell
|
||||
|
||||
cat <<EOF >$COMMUNITY/dbpass.txt
|
||||
dbpass
|
||||
EOF
|
||||
|
||||
cat <<EOF >$COMMUNITY/site_key.txt
|
||||
sitekey
|
||||
EOF
|
||||
|
||||
cat <<EOF >$COMMUNITY/secret_key.txt
|
||||
secretkey
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a **enterprise** overlay that:
|
||||
|
||||
- generates `Secrets` for LDAP's password and external DB's password
|
||||
- patches the `ConfigMap` of the common base with configurations for LDAP and
|
||||
external DB
|
||||
- patches the `Deployment` of the common base to mount the generated `Secrets`
|
||||
for LDAP and external DB
|
||||
|
||||
```shell
|
||||
ENTERPRISE=$DEMO_HOME/overlays/enterprise
|
||||
mkdir -p $ENTERPRISE
|
||||
|
||||
cat <<EOF >$ENTERPRISE/kustomization.yaml
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
secretGenerator:
|
||||
- name: ldappass
|
||||
files:
|
||||
- ldappass.txt
|
||||
- name: dbpass
|
||||
files:
|
||||
- dbpass.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$ENTERPRISE/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: dbpass
|
||||
secret:
|
||||
secretName: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/db/
|
||||
name: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: ldappass
|
||||
secret:
|
||||
secretName: ldappass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/ldap/
|
||||
name: ldappass
|
||||
EOF
|
||||
|
||||
cat <<EOF >$ENTERPRISE/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
db.conf: |
|
||||
endpoint=127.0.0.1:1234
|
||||
name=app
|
||||
user=admin
|
||||
pass=/var/run/secrets/db/dbpass.txt
|
||||
ldap.conf: |
|
||||
endpoint=ldap://ldap.example.com
|
||||
bindDN=cn=admin,dc=example,dc=com
|
||||
pass=/var/run/secrets/ldap/ldappass.txt
|
||||
EOF
|
||||
```
|
||||
|
||||
Create local input files for LDAP's password and external DB's password:
|
||||
|
||||
```shell
|
||||
|
||||
cat <<EOF >$ENTERPRISE/ldappass.txt
|
||||
ldappass
|
||||
EOF
|
||||
|
||||
cat <<EOF >$ENTERPRISE/dbpass.txt
|
||||
dbpass
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a **dev** overlay that supports all three features(ExternalDB, LDAP,
|
||||
reCAPTCHA) and conditionally enables some or all of them. In this example, we
|
||||
define a dev overlay that supports all the features, but has disabled the LDAP
|
||||
support, by doing the following::
|
||||
|
||||
- generates `Secrets` for external DB's password and reCAPTCHA's keys
|
||||
- patches the `ConfigMap` of the common base with configurations for external DB
|
||||
and reCAPTCHA
|
||||
- patches the `Deployment` of the common base to mount the generated `Secrets`
|
||||
for external DB and reCAPTCHA
|
||||
|
||||
```shell
|
||||
DEV=$DEMO_HOME/overlays/dev
|
||||
mkdir -p $DEV
|
||||
|
||||
cat <<EOF >$DEV/kustomization.yaml
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
secretGenerator:
|
||||
# - name: ldappass <-- Commenting to disable LDAP support
|
||||
# files:
|
||||
# - ldappass.txt
|
||||
- name: dbpass
|
||||
files:
|
||||
- dbpass.txt
|
||||
- name: recaptcha
|
||||
files:
|
||||
- site_key.txt
|
||||
- secret_key.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEV/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: dbpass
|
||||
secret:
|
||||
secretName: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/db/
|
||||
name: dbpass
|
||||
# - op: add <-- Commenting to disable LDAP support
|
||||
# path: /spec/template/spec/volumes/0
|
||||
# value:
|
||||
# name: ldappass
|
||||
# secret:
|
||||
# secretName: ldappass
|
||||
# - op: add
|
||||
# path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
# value:
|
||||
# mountPath: /var/run/secrets/ldap/
|
||||
# name: ldappass
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: recaptcha
|
||||
secret:
|
||||
secretName: recaptcha
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/recaptcha/
|
||||
name: recaptcha
|
||||
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEV/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
db.conf: |
|
||||
endpoint=127.0.0.1:1234
|
||||
name=app
|
||||
user=admin
|
||||
pass=/var/run/secrets/db/dbpass.txt
|
||||
# ldap.conf: | <-- Commenting to disable LDAP support
|
||||
# endpoint=ldap://ldap.example.com
|
||||
# bindDN=cn=admin,dc=example,dc=com
|
||||
# pass=/var/run/secrets/ldap/ldappass.txt
|
||||
recaptcha.conf: |
|
||||
enabled=true
|
||||
site_key=/var/run/secrets/recaptcha/site_key.txt
|
||||
secret_key=/var/run/secrets/recaptcha/secret_key.txt
|
||||
EOF
|
||||
```
|
||||
|
||||
Create local input files for external DB's password and reCAPTCHA's keys:
|
||||
|
||||
```shell
|
||||
|
||||
cat <<EOF >$DEV/dbpass.txt
|
||||
dbpass
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEV/site_key.txt
|
||||
sitekey
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEV/secret_key.txt
|
||||
secretkey
|
||||
EOF
|
||||
```
|
||||
|
||||
The above commands result in the following structure:
|
||||
|
||||
```shell
|
||||
├── base
|
||||
│ ├── deployment.yaml
|
||||
│ └── kustomization.yaml
|
||||
└── overlays
|
||||
├── community
|
||||
│ ├── configmap.yaml
|
||||
│ ├── dbpass.txt
|
||||
│ ├── deployment.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ ├── secret_key.txt
|
||||
│ └── site_key.txt
|
||||
├── dev
|
||||
│ ├── configmap.yaml <-- Refers to multiple features and might contain comments
|
||||
│ ├── dbpass.txt
|
||||
│ ├── deployment.yaml <-- Refers to multiple features and might contain comments
|
||||
│ ├── kustomization.yaml <-- Refers to multiple features and might contain comments
|
||||
│ ├── secret_key.txt
|
||||
│ └── site_key.txt
|
||||
└── enterprise
|
||||
├── configmap.yaml
|
||||
├── dbpass.txt
|
||||
├── deployment.yaml
|
||||
├── kustomization.yaml
|
||||
└── ldappass.txt
|
||||
```
|
||||
|
||||
The main issues observed with this solution are:
|
||||
|
||||
1. Since some features are repeated in the `community/`, `enterprise/` and
|
||||
`dev/` overlays, one needs to manually define patches with content that is
|
||||
partially identical to patches of different overlays, that also enable this
|
||||
feature.
|
||||
2. The `dev/` overlay is dynamic, i.e., supports multiple optional features. To
|
||||
enable/disable any single feature one needs to uncomment/comment many lines
|
||||
of YAML which is cumbersome and hard to maintain. Alternatively, one needs
|
||||
to maintain a multitude of overlays and track all possible combinations of
|
||||
features.
|
||||
3. Overlays that combine more than one features define patches for resources
|
||||
whose content is not dedicated to a single feature. That is, there is no
|
||||
semantic isolation per feature, everything gets mixed into a single,
|
||||
multi-feature, resource-specific patch.
|
||||
|
||||
The variants approach may solve this simple example but it won't scale in the
|
||||
long run, as the number of features and deployments grow. What if you have `N`
|
||||
opt-in features and `M` real-world deployment scenarios that ship with `0-N` of
|
||||
these features?
|
||||
|
||||
Ideally, you want to move each feature under a separate, reusable overlay and
|
||||
enable them on-demand per deployment, i.e., in kustomization files of top-level
|
||||
overlays. Enter components.
|
||||
|
||||
## Components example
|
||||
|
||||
Here's an alternative and more [DRY] approach that solves this issue by using a
|
||||
Kustomize feature called "components". Each opt-in feature gets packaged as a
|
||||
component, so that it can be referred to from higher-level overlays.
|
||||
|
||||
First, define a place to work:
|
||||
|
||||
```shell
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Define a common **base** that has a `Deployment` and a simple `ConfigMap`, that
|
||||
is mounted on the application's container.
|
||||
|
||||
```shell
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
|
||||
configMapGenerator:
|
||||
- name: conf
|
||||
literals:
|
||||
- main.conf=|
|
||||
color=cornflower_blue
|
||||
log_level=info
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: example
|
||||
image: example:1.0
|
||||
volumeMounts:
|
||||
- name: conf
|
||||
mountPath: /etc/config
|
||||
volumes:
|
||||
- name: conf
|
||||
configMap:
|
||||
name: conf
|
||||
EOF
|
||||
```
|
||||
|
||||
Define an `external_db` component, using `kind: Component`, that creates a
|
||||
`Secret` for the DB password and a new entry in the `ConfigMap`:
|
||||
|
||||
```shell
|
||||
EXT_DB=$DEMO_HOME/components/external_db
|
||||
mkdir -p $EXT_DB
|
||||
|
||||
cat <<EOF >$EXT_DB/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1 # <-- Component notation
|
||||
kind: Component
|
||||
|
||||
secretGenerator:
|
||||
- name: dbpass
|
||||
files:
|
||||
- dbpass.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$EXT_DB/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: dbpass
|
||||
secret:
|
||||
secretName: dbpass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/db/
|
||||
name: dbpass
|
||||
EOF
|
||||
|
||||
cat <<EOF >$EXT_DB/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
db.conf: |
|
||||
endpoint=127.0.0.1:1234
|
||||
name=app
|
||||
user=admin
|
||||
pass=/var/run/secrets/db/dbpass.txt
|
||||
EOF
|
||||
```
|
||||
|
||||
Define an `ldap` component, that creates a `Secret` for the LDAP password
|
||||
and a new entry in the `ConfigMap`:
|
||||
|
||||
```shell
|
||||
LDAP=$DEMO_HOME/components/ldap
|
||||
mkdir -p $LDAP
|
||||
|
||||
cat <<EOF >$LDAP/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
|
||||
secretGenerator:
|
||||
- name: ldappass
|
||||
files:
|
||||
- ldappass.txt
|
||||
|
||||
patchesStrategicMerge:
|
||||
- configmap.yaml
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$LDAP/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: ldappass
|
||||
secret:
|
||||
secretName: ldappass
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/ldap/
|
||||
name: ldappass
|
||||
EOF
|
||||
|
||||
cat <<EOF >$LDAP/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: conf
|
||||
data:
|
||||
ldap.conf: |
|
||||
endpoint=ldap://ldap.example.com
|
||||
bindDN=cn=admin,dc=example,dc=com
|
||||
pass=/var/run/secrets/ldap/ldappass.txt
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a `recaptcha` component, that creates a `Secret` for the reCAPTCHA
|
||||
site/secret keys and a new entry in the `ConfigMap`:
|
||||
|
||||
```shell
|
||||
RECAPTCHA=$DEMO_HOME/components/recaptcha
|
||||
mkdir -p $RECAPTCHA
|
||||
|
||||
cat <<EOF >$RECAPTCHA/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||
kind: Component
|
||||
|
||||
secretGenerator:
|
||||
- name: recaptcha
|
||||
files:
|
||||
- site_key.txt
|
||||
- secret_key.txt
|
||||
|
||||
# Updating the ConfigMap works with generators as well.
|
||||
configMapGenerator:
|
||||
- name: conf
|
||||
behavior: merge
|
||||
literals:
|
||||
- recaptcha.conf=|
|
||||
enabled=true
|
||||
site_key=/var/run/secrets/recaptcha/site_key.txt
|
||||
secret_key=/var/run/secrets/recaptcha/secret_key.txt
|
||||
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: example
|
||||
path: deployment.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$RECAPTCHA/deployment.yaml
|
||||
- op: add
|
||||
path: /spec/template/spec/volumes/0
|
||||
value:
|
||||
name: recaptcha
|
||||
secret:
|
||||
secretName: recaptcha
|
||||
- op: add
|
||||
path: /spec/template/spec/containers/0/volumeMounts/0
|
||||
value:
|
||||
mountPath: /var/run/secrets/recaptcha/
|
||||
name: recaptcha
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a `community` variant, that bundles the external DB and reCAPTCHA
|
||||
components:
|
||||
|
||||
```shell
|
||||
COMMUNITY=$DEMO_HOME/overlays/community
|
||||
mkdir -p $COMMUNITY
|
||||
|
||||
cat <<EOF >$COMMUNITY/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
components:
|
||||
- ../../components/external_db
|
||||
- ../../components/recaptcha
|
||||
EOF
|
||||
```
|
||||
|
||||
Define an `enterprise` overlay, that bundles the external DB and LDAP
|
||||
components:
|
||||
|
||||
```shell
|
||||
ENTERPRISE=$DEMO_HOME/overlays/enterprise
|
||||
mkdir -p $ENTERPRISE
|
||||
|
||||
cat <<EOF >$ENTERPRISE/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
components:
|
||||
- ../../components/external_db
|
||||
- ../../components/ldap
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a `dev` overlay, that points to all the components and has LDAP
|
||||
disabled:
|
||||
|
||||
```shell
|
||||
DEV=$DEMO_HOME/overlays/dev
|
||||
mkdir -p $DEV
|
||||
|
||||
cat <<EOF >$DEV/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
components:
|
||||
- ../../components/external_db
|
||||
#- ../../components/ldap
|
||||
- ../../components/recaptcha
|
||||
EOF
|
||||
```
|
||||
|
||||
Now the workspace has following directories:
|
||||
|
||||
```shell
|
||||
├── base
|
||||
│ ├── deployment.yaml
|
||||
│ └── kustomization.yaml
|
||||
├── components
|
||||
│ ├── external_db
|
||||
│ │ ├── configmap.yaml
|
||||
│ │ ├── dbpass.txt
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ └── kustomization.yaml
|
||||
│ ├── ldap
|
||||
│ │ ├── configmap.yaml
|
||||
│ │ ├── deployment.yaml
|
||||
│ │ ├── kustomization.yaml
|
||||
│ │ └── ldappass.txt
|
||||
│ └── recaptcha
|
||||
│ ├── deployment.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ ├── secret_key.txt
|
||||
│ └── site_key.txt
|
||||
└── overlays
|
||||
├── community
|
||||
│ └── kustomization.yaml
|
||||
├── dev
|
||||
│ └── kustomization.yaml
|
||||
└── enterprise
|
||||
└── kustomization.yaml
|
||||
```
|
||||
|
||||
With this structure, you can create the YAML files for each deployment as
|
||||
follows:
|
||||
|
||||
```shell
|
||||
kustomize build overlays/community
|
||||
kustomize build overlays/enterprise
|
||||
kustomize build overlays/dev
|
||||
```
|
||||
|
||||
## Takeaway
|
||||
|
||||
At the end of the day, Kustomize components provide a more flexible way to
|
||||
enable/disable features and configurations for applications directly from the
|
||||
kustomization file. This results in more readable, concise and intuitive
|
||||
overlays.
|
||||
|
||||
[variants]: multibases/README.md
|
||||
[DRY principle]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
|
||||
@@ -1,22 +1,24 @@
|
||||
[patch]: ../../docs/glossary.md#patch
|
||||
[resource]: ../../docs/glossary.md#resource
|
||||
[variant]: ../../docs/glossary.md#variant
|
||||
[patch]: ../docs/glossary.md#patch
|
||||
[resource]: ../docs/glossary.md#resource
|
||||
[variant]: ../docs/glossary.md#variant
|
||||
|
||||
## ConfigMap generation and rolling updates
|
||||
|
||||
Kustomize provides two ways of adding ConfigMap in one `kustomization`, either by declaring ConfigMap as a [resource] or declaring ConfigMap from a ConfigMapGenerator. The formats inside `kustomization.yaml` are
|
||||
Kustomize provides two ways of adding ConfigMap in one `kustomization`, either by declaring ConfigMap as a [resource] or declaring ConfigMap from a ConfigMapGenerator. The formats inside `kustomization.yaml` are
|
||||
|
||||
> ```
|
||||
> # declare ConfigMap as a resource
|
||||
> resources:
|
||||
> - configmap.yaml
|
||||
>
|
||||
>
|
||||
> # declare ConfigMap from a ConfigMapGenerator
|
||||
> configMapGenerator:
|
||||
> - name: a-configmap
|
||||
> files:
|
||||
> # configfile is used as key
|
||||
> - configs/configfile
|
||||
> - configs/another_configfile
|
||||
> # configkey is used as key
|
||||
> - configkey=configs/another_configfile
|
||||
> ```
|
||||
|
||||
The ConfigMaps declared as [resource] are treated the same way as other resources. Kustomize doesn't append any hash to the ConfigMap name. The ConfigMap declared from a ConfigMapGenerator is treated differently. A hash is appended to the name and any change in the ConfigMap will trigger a rolling update.
|
||||
@@ -26,7 +28,7 @@ In this demo, the same [hello_world](helloWorld/README.md) is used while the Con
|
||||
### Establish base and staging
|
||||
|
||||
Establish the base with a `configMapGenerator`:
|
||||
<!-- @establishBase @test -->
|
||||
<!-- @establishBase @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
@@ -44,30 +46,33 @@ commonLabels:
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
- enableRisky="false"
|
||||
EOF
|
||||
```
|
||||
|
||||
Establish the staging with a patch applied to the ConfigMap
|
||||
<!-- @establishStaging @test -->
|
||||
|
||||
<!-- @establishStaging @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
|
||||
cat <<'EOF' >$OVERLAYS/staging/kustomization.yaml
|
||||
namePrefix: staging-
|
||||
nameSuffix: -v1
|
||||
commonLabels:
|
||||
variant: staging
|
||||
org: acmeCorporation
|
||||
commonAnnotations:
|
||||
note: Hello, I am staging!
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- map.yaml
|
||||
EOF
|
||||
|
||||
@@ -89,8 +94,8 @@ configured with data from a ConfigMap.
|
||||
|
||||
The deployment refers to this map by name:
|
||||
|
||||
<!-- @showDeployment @testAgainstLatestRelease -->
|
||||
|
||||
<!-- @showDeployment @test -->
|
||||
```
|
||||
grep -C 2 configMapKeyRef $BASE/deployment.yaml
|
||||
```
|
||||
@@ -103,20 +108,21 @@ changed, so such updates have no effect.
|
||||
The recommended way to change a deployment's
|
||||
configuration is to
|
||||
|
||||
1. create a new ConfigMap with a new name,
|
||||
1. patch the _deployment_, modifying the name value of
|
||||
1. create a new ConfigMap with a new name,
|
||||
1. patch the _deployment_, modifying the name value of
|
||||
the appropriate `configMapKeyRef` field.
|
||||
|
||||
This latter change initiates rolling update to the pods
|
||||
in the deployment. The older ConfigMap, when no longer
|
||||
referenced by any other resource, is eventually garbage
|
||||
collected.
|
||||
in the deployment. The older ConfigMap, when no longer
|
||||
referenced by any other resource, is eventually [garbage
|
||||
collected](/../../issues/242).
|
||||
|
||||
### How this works with kustomize
|
||||
|
||||
The _staging_ [variant] here has a ConfigMap [patch]:
|
||||
|
||||
<!-- @showMapPatch @test -->
|
||||
<!-- @showMapPatch @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
@@ -127,7 +133,8 @@ resource spec.
|
||||
|
||||
The ConfigMap it modifies is declared from a `configMapGenerator`.
|
||||
|
||||
<!-- @showMapBase @test -->
|
||||
<!-- @showMapBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 4 configMapGenerator $BASE/kustomization.yaml
|
||||
```
|
||||
@@ -136,11 +143,12 @@ For a patch to work, the names in the `metadata/name`
|
||||
fields must match.
|
||||
|
||||
However, the name values specified in the file are
|
||||
_not_ what gets used in the cluster. By design,
|
||||
kustomize modifies names of ConfigMaps declared from ConfigMapGenerator. To see the names
|
||||
_not_ what gets used in the cluster. By design,
|
||||
kustomize modifies names of ConfigMaps declared from ConfigMapGenerator. To see the names
|
||||
ultimately used in the cluster, just run kustomize:
|
||||
|
||||
<!-- @grepStagingName @test -->
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
@@ -150,21 +158,27 @@ The ConfigMap name is prefixed by _staging-_, per the
|
||||
`namePrefix` field in
|
||||
`$OVERLAYS/staging/kustomization.yaml`.
|
||||
|
||||
The ConfigMap name is suffixed by _-v1_, per the
|
||||
`nameSuffix` field in
|
||||
`$OVERLAYS/staging/kustomization.yaml`.
|
||||
|
||||
The suffix to the ConfigMap name is generated from a
|
||||
hash of the maps content - in this case the name suffix
|
||||
is _hhhhkfmgmk_:
|
||||
is _5276h4th55_:
|
||||
|
||||
<!-- @grepStagingHash @testAgainstLatestRelease -->
|
||||
|
||||
<!-- @grepStagingHash @test -->
|
||||
```
|
||||
kustomize build $OVERLAYS/staging | grep hhhhkfmgmk
|
||||
kustomize build $OVERLAYS/staging | grep 5276h4th55
|
||||
```
|
||||
|
||||
Now modify the map patch, to change the greeting
|
||||
the server will use:
|
||||
|
||||
<!-- @changeMap @test -->
|
||||
<!-- @changeMap @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
sed -i 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
|
||||
sed -i.bak 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
|
||||
See the new greeting:
|
||||
@@ -176,28 +190,30 @@ kustomize build $OVERLAYS/staging |\
|
||||
|
||||
Run kustomize again to see the new ConfigMap names:
|
||||
|
||||
<!-- @grepStagingName @test -->
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
```
|
||||
|
||||
Confirm that the change in ConfigMap content resulted
|
||||
in three new names ending in _khk45ktkd9_ - one in the
|
||||
in three new names ending in _c2g8fcbf88_ - one in the
|
||||
ConfigMap name itself, and two in the deployment that
|
||||
uses the map:
|
||||
|
||||
<!-- @countHashes @test -->
|
||||
<!-- @countHashes @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
test 3 == \
|
||||
$(kustomize build $OVERLAYS/staging | grep khk45ktkd9 | wc -l); \
|
||||
$(kustomize build $OVERLAYS/staging | grep c2g8fcbf88 | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Applying these resources to the cluster will result in
|
||||
a rolling update of the deployments pods, retargetting
|
||||
them from the _hhhhkfmgmk_ maps to the _khk45ktkd9_
|
||||
maps. The system will later garbage collect the
|
||||
them from the _5276h4th55_ maps to the _c2g8fcbf88_
|
||||
maps. The system will later garbage collect the
|
||||
unused maps.
|
||||
|
||||
## Rollback
|
||||
|
||||
333
examples/configureBuiltinPlugin.md
Normal file
333
examples/configureBuiltinPlugin.md
Normal file
@@ -0,0 +1,333 @@
|
||||
[builtin operations]: ../docs/plugins/builtins.md
|
||||
[builtin plugins]: ../docs/plugins/builtins.md
|
||||
[plugins]: ../docs/plugins
|
||||
[plugin]: ../docs/plugins
|
||||
[fields]: ../docs/fields.md
|
||||
[fields in a kustomization file]: ../docs/fields.md
|
||||
[TransformerConfig]: ../api/internal/plugins/builtinconfig/transformerconfig.go
|
||||
[kustomization]: ../docs/glossary.md#kustomization
|
||||
|
||||
# Customizing kustomize
|
||||
|
||||
The [fields in a kustomization file] allow the user to
|
||||
specify which resource files to use as input, how to
|
||||
_generate_ new resources, and how to _transform_ those
|
||||
resources - add labels, patch them, etc.
|
||||
|
||||
These fields are simple (low argument count) directives.
|
||||
For example, the `commonAnnotations` field demands only a
|
||||
list of _name:value_ pairs.
|
||||
|
||||
If using a field triggers behavior that pleases the user,
|
||||
everyone's happy.
|
||||
|
||||
If not, the user can ask for new behavior to be implemented
|
||||
in kustomize proper (and wait), or the user can write a
|
||||
transformer or generator [plugin]. This latter option
|
||||
generally means writing code; a Go plugin, a Go binary,
|
||||
a C++ binary, a `bash` script - something.
|
||||
|
||||
There's a third option. If one merely wants to tweak
|
||||
behavior that already exists in kustomize, one may be able
|
||||
to do so by just writing some YAML.
|
||||
|
||||
## Configure the builtin plugins
|
||||
|
||||
All of kustomize's [builtin operations] are implemented
|
||||
and usable as plugins.
|
||||
|
||||
Using the fields is convenient and brief, but necessarily
|
||||
specifies only part of the entire plugin specification. The
|
||||
unspecified part is defaulted to what are hopefully
|
||||
generally appealing values.
|
||||
|
||||
If, instead, one invokes the plugins directly using the
|
||||
`transformers` or `generators` field, one can (indeed
|
||||
_must_) specify the entire plugin configuration.
|
||||
|
||||
## Example: field vs plugin
|
||||
|
||||
Define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
### Using the `commonLabels` and `commonAnnotations` fields
|
||||
|
||||
In this simple example, we'll use just two resources: a deployment and a service.
|
||||
|
||||
Define them:
|
||||
|
||||
<!-- @makeRes1 @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment
|
||||
spec:
|
||||
replicas: 10
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: monopole/hello:1
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- @makeRes2 @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8666
|
||||
targetPort: 8080
|
||||
EOF
|
||||
```
|
||||
|
||||
Now make a kustomization file that causes them
|
||||
to be read and transformed:
|
||||
|
||||
<!-- @makeKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
namePrefix: hello-
|
||||
commonLabels:
|
||||
app: hello
|
||||
commonAnnotations:
|
||||
area: "51"
|
||||
greeting: Take me to your leader
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
And run kustomize:
|
||||
|
||||
<!-- @checkLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
The output will be something like
|
||||
|
||||
> ```
|
||||
> apiVersion: v1
|
||||
> kind: Service
|
||||
> metadata:
|
||||
> annotations:
|
||||
> area: "51"
|
||||
> greeting: Take me to your leader
|
||||
> labels:
|
||||
> app: hello
|
||||
> name: hello-service
|
||||
> spec:
|
||||
> ports:
|
||||
> - port: 8666
|
||||
> protocol: TCP
|
||||
> targetPort: 8080
|
||||
> selector:
|
||||
> app: hello
|
||||
> type: LoadBalancer
|
||||
> ---
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> annotations:
|
||||
> area: "51"
|
||||
> greeting: Take me to your leader
|
||||
> labels:
|
||||
> app: hello
|
||||
> name: hello-deployment
|
||||
> spec:
|
||||
> replicas: 10
|
||||
> selector:
|
||||
> matchLabels:
|
||||
> app: hello
|
||||
> template:
|
||||
> metadata:
|
||||
> annotations:
|
||||
> area: "51"
|
||||
> greeting: Take me to your leader
|
||||
> labels:
|
||||
> app: hello
|
||||
> spec:
|
||||
> containers:
|
||||
> - image: monopole/hello:1
|
||||
> name: the-container
|
||||
> ```
|
||||
|
||||
Let's say we are unhappy with this result.
|
||||
|
||||
We only want the annotations
|
||||
to be applied down in the pod templates,
|
||||
and don't want to see them in the metadata
|
||||
for Service or Deployment.
|
||||
|
||||
We like that the label _app: hello_ ended up in
|
||||
|
||||
- Service `spec.selector`
|
||||
- Deployment `spec.selector.matchLabels`
|
||||
- Deployment `spec.template.metadata.labels`
|
||||
|
||||
as this binds the Service (load balancer) to the pods,
|
||||
and the Deployment itself to its own pods -
|
||||
but we again don't care to see these labels in
|
||||
the metadata for the Service and the Deployment.
|
||||
|
||||
|
||||
### Configuring the builtin plugins instead
|
||||
|
||||
To fine tune this, invoke the same transformations
|
||||
using the plugin approach.
|
||||
|
||||
Change the kustomization file:
|
||||
|
||||
<!-- @makeKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
namePrefix: hello-
|
||||
transformers:
|
||||
- myAnnotator.yaml
|
||||
- myLabeller.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Then make the two plugin configuration files
|
||||
(`myAnnotator.yaml`, `myLabeller.yaml`)
|
||||
referred to by the `transformers` field above.
|
||||
For details about the fields to specify, see
|
||||
the documentation for the [builtin plugins].
|
||||
|
||||
<!-- @makeAnnotatorPluginConfig @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/myAnnotator.yaml
|
||||
apiVersion: builtin
|
||||
kind: AnnotationsTransformer
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
annotations:
|
||||
area: 51
|
||||
greeting: take me to your leader
|
||||
fieldSpecs:
|
||||
- kind: Deployment
|
||||
path: spec/template/metadata/annotations
|
||||
create: true
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- @makeLabelPluginConfig @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/myLabeller.yaml
|
||||
apiVersion: builtin
|
||||
kind: LabelTransformer
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
labels:
|
||||
app: hello
|
||||
fieldSpecs:
|
||||
- kind: Service
|
||||
path: spec/selector
|
||||
create: true
|
||||
- kind: Deployment
|
||||
path: spec/selector/matchLabels
|
||||
create: true
|
||||
- kind: Deployment
|
||||
path: spec/template/metadata/labels
|
||||
create: true
|
||||
EOF
|
||||
```
|
||||
|
||||
Finally, run kustomize again:
|
||||
|
||||
<!-- @checkLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
The output should resemble the following,
|
||||
with fewer labels and annotations.
|
||||
|
||||
> ```
|
||||
> apiVersion: v1
|
||||
> kind: Service
|
||||
> metadata:
|
||||
> name: hello-service
|
||||
> spec:
|
||||
> ports:
|
||||
> - port: 8666
|
||||
> protocol: TCP
|
||||
> targetPort: 8080
|
||||
> selector:
|
||||
> app: hello
|
||||
> type: LoadBalancer
|
||||
> ---
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: hello-deployment
|
||||
> spec:
|
||||
> replicas: 10
|
||||
> selector:
|
||||
> matchLabels:
|
||||
> app: hello
|
||||
> template:
|
||||
> metadata:
|
||||
> annotations:
|
||||
> area: "51"
|
||||
> greeting: take me to your leader
|
||||
> labels:
|
||||
> app: hello
|
||||
> spec:
|
||||
> containers:
|
||||
> - image: monopole/hello:1
|
||||
> name: the-container
|
||||
> ```
|
||||
|
||||
|
||||
## The old way to do this
|
||||
|
||||
The original (and still functional) way to customize
|
||||
kustomize is to specify a `configurations` field in the
|
||||
kustomization file.
|
||||
|
||||
This field, normally omitted because it overrides hardcoded
|
||||
data, accepts a list of file path arguments. The files, in
|
||||
turn, specify which fields in which k8s objects should be
|
||||
affected by particular builtin transformations. It's a
|
||||
global configuration cutting across transformations, and
|
||||
doesn't effect generators at all.
|
||||
|
||||
At `build` time, the configuration files are unmarshalled
|
||||
into one instance of [TransformerConfig]. This
|
||||
object, _plus_ the field values for `namePrefix`, etc. are
|
||||
fed into the transformation code to build the output.
|
||||
|
||||
The best way to write these custom configuration files is to
|
||||
generate the files from the hardcoded values built into
|
||||
kustomize via these commands:
|
||||
|
||||
> ```
|
||||
> mkdir /tmp/junk
|
||||
> kustomize config save -d /tmp/junk
|
||||
> ```
|
||||
|
||||
One can then edit those file or files, and specify the
|
||||
resulting edited files in a `configurations:`
|
||||
field in a kustomization file used in a `build`.
|
||||
|
||||
Using plugins _completely ignores_ both hard coded
|
||||
tranformer configuration, and any configuration loaded by
|
||||
the `configuration` field.
|
||||
244
examples/customOpenAPIschema.md
Normal file
244
examples/customOpenAPIschema.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# Using a Custom OpenAPI schema
|
||||
|
||||
For more details regarding this feature you can read the
|
||||
[Kustomize OpenAPI Features KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2206-openapi-features-in-kustomize).
|
||||
|
||||
A kustomization file supports adding your own
|
||||
OpenAPI schema to define merge keys and patch
|
||||
strategy.
|
||||
|
||||
Make a place to work:
|
||||
|
||||
<!-- @placeToWork @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
We'll be editing our own [custom resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
|
||||
|
||||
<!-- @customOpenAPI @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/my_resource.yaml
|
||||
apiVersion: example.com/v1alpha1
|
||||
kind: MyResource
|
||||
metadata:
|
||||
name: service
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: server
|
||||
image: server
|
||||
command: example
|
||||
ports:
|
||||
- name: grpc
|
||||
protocol: TCP
|
||||
containerPort: 8080
|
||||
EOF
|
||||
```
|
||||
|
||||
This resource has an image field. Let's change its value from server
|
||||
to nginx with a patch.
|
||||
|
||||
Kustomize gets its merge key information from the OpenAPI data
|
||||
provided by the kubernetes API server. It doesn't have information
|
||||
about custom resources, so we will have to provide our own
|
||||
schema file.
|
||||
|
||||
Note: CRDs support declarative validation using an OpenAPI v3 schema.
|
||||
See https://book.kubebuilder.io/reference/generating-crd.html#validation.
|
||||
|
||||
You can get an OpenAPI document like this by fetching the OpenAPI
|
||||
document from your locally favored cluster with the command
|
||||
`kustomize openapi fetch`. Kustomize will use the OpenAPI extensions
|
||||
`x-kubernetes-patch-merge-key` and `x-kubernetes-patch-strategy` to
|
||||
perform a strategic merge. `x-kubernetes-patch-strategy` should be set
|
||||
to "merge", and you can set your merge key to whatever you like. Below,
|
||||
our custom resource inherits merge keys from `PodTemplateSpec`.
|
||||
|
||||
<!-- @addCustomSchema @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >>$DEMO_HOME/mycr_schema.json
|
||||
{
|
||||
"definitions": {
|
||||
"v1alpha1.MyResource": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object"
|
||||
},
|
||||
"spec": {
|
||||
"properties": {
|
||||
"template": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"status": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"x-kubernetes-group-version-kind": [
|
||||
{
|
||||
"group": "example.com",
|
||||
"kind": "MyResource",
|
||||
"version": "v1alpha1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"io.k8s.api.core.v1.PodTemplateSpec": {
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"\$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta"
|
||||
},
|
||||
"spec": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.PodSpec"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": {
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.PodSpec": {
|
||||
"properties": {
|
||||
"containers": {
|
||||
"items": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.Container"
|
||||
},
|
||||
"type": "array",
|
||||
"x-kubernetes-patch-merge-key": "name",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.Container": {
|
||||
"properties": {
|
||||
"command": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"image": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"ports": {
|
||||
"items": {
|
||||
"\$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort"
|
||||
},
|
||||
"type": "array",
|
||||
"x-kubernetes-list-map-keys": [
|
||||
"containerPort",
|
||||
"protocol"
|
||||
],
|
||||
"x-kubernetes-list-type": "map",
|
||||
"x-kubernetes-patch-merge-key": "containerPort",
|
||||
"x-kubernetes-patch-strategy": "merge"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.ContainerPort": {
|
||||
"properties": {
|
||||
"containerPort": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"protocol": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
```
|
||||
|
||||
We'll of course need a `kustomization` file
|
||||
referring to the custom resource, and containing our patch:
|
||||
|
||||
<!-- @openAPIkustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- my_resource.yaml
|
||||
|
||||
openapi:
|
||||
path: mycr_schema.json
|
||||
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: example.com/v1alpha1
|
||||
kind: MyResource
|
||||
metadata:
|
||||
name: service
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: server
|
||||
image: nginx
|
||||
EOF
|
||||
```
|
||||
|
||||
Define the expected output:
|
||||
<!-- @expected @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/out_expected.yaml
|
||||
apiVersion: example.com/v1alpha1
|
||||
kind: MyResource
|
||||
metadata:
|
||||
name: service
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- command: example
|
||||
image: nginx
|
||||
name: server
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: grpc
|
||||
protocol: TCP
|
||||
EOF
|
||||
```
|
||||
|
||||
Run the build:
|
||||
<!-- @runExample @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME >$DEMO_HOME/out_actual.yaml
|
||||
```
|
||||
|
||||
Confirm they match:
|
||||
|
||||
<!-- @diffShouldBeEmpty @testAgainstLatestRelease -->
|
||||
```
|
||||
diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
|
||||
```
|
||||
60
examples/generatorOptions.md
Normal file
60
examples/generatorOptions.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Generator Options
|
||||
|
||||
Kustomize provides options to modify the behavior of ConfigMap and Secret generators. These options include
|
||||
|
||||
- disable appending a content hash suffix to the names of generated resources
|
||||
- adding labels to generated resources
|
||||
- adding annotations to generated resources
|
||||
|
||||
This demo shows how to use these options. First create a workspace.
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Create a kustomization and add a ConfigMap generator to it.
|
||||
|
||||
<!-- @createCMGenerator @testAgainstLatestRelease -->
|
||||
```
|
||||
cat > $DEMO_HOME/kustomization.yaml << EOF
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
literals:
|
||||
- foo=bar
|
||||
- baz=qux
|
||||
EOF
|
||||
```
|
||||
|
||||
Add following generatorOptions
|
||||
<!-- @addGeneratorOptions @testAgainstLatestRelease -->
|
||||
```
|
||||
cat >> $DEMO_HOME/kustomization.yaml << EOF
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
labels:
|
||||
kustomize.generated.resource: somevalue
|
||||
annotations:
|
||||
annotations.only.for.generated: othervalue
|
||||
EOF
|
||||
```
|
||||
Run `kustomize build` and make sure that the generated ConfigMap
|
||||
|
||||
- doesn't have name suffix
|
||||
<!-- @verify @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "name: my-configmap$" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
- has label `kustomize.generated.resource: somevalue`
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 1 "labels" | grep "kustomize.generated.resource" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
- has annotation `annotations.only.for.generated: othervalue`
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 1 "annotations" | grep "annotations.only.for.generated" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
132
examples/goGetterGeneratorPlugin.md
Normal file
132
examples/goGetterGeneratorPlugin.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Remote Sources
|
||||
|
||||
Kustomize supports building a [remote target], but the URLs are limited to common [Git repository specs].
|
||||
|
||||
To extend the supported format, Kustomize has a [plugin] system that allows one to integrate third-party tools such as [hashicorp/go-getter] to "download things from a string URL using a variety of protocols", extract the content and generated resources as part of kustomize build.
|
||||
|
||||
[remote target]: /examples/remoteBuild.md
|
||||
[Git repository specs]: /api/internal/git/repospec_test.go
|
||||
[plugin]: /docs/plugins
|
||||
[hashicorp/go-getter]: https://github.com/hashicorp/go-getter
|
||||
|
||||
## Make a place to work
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
```sh
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
mkdir -p $DEMO_HOME/base
|
||||
```
|
||||
|
||||
## Use a remote kustomize layer
|
||||
|
||||
Define a kustomization representing your _local_ variant (aka environment).
|
||||
|
||||
This could involve any number of kustomizations (see other examples), but in this case just add the name prefix `my-` to all resources:
|
||||
|
||||
<!-- @writeKustLocal @test -->
|
||||
```sh
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
namePrefix: my-
|
||||
resources:
|
||||
- base/
|
||||
EOF
|
||||
```
|
||||
|
||||
It refer a remote base defined as below:
|
||||
|
||||
<!-- @writeKustLocal @test -->
|
||||
```sh
|
||||
cat <<'EOF' >$DEMO_HOME/base/kustomization.yaml
|
||||
generators:
|
||||
- goGetter.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
The base refers to a generator configuration file called `goGetter.yaml`.
|
||||
|
||||
This file lets one specify the source URL, and other things like sub path in the package, defaulting to base directory, and command to run under the path, defaulting to `kustomize build`.
|
||||
|
||||
Create the config file `goGetter.yaml`, specifying the arbitrarily chosen name _example_:
|
||||
|
||||
<!-- @writeGeneratorConfig @test -->
|
||||
```sh
|
||||
cat <<'EOF' >$DEMO_HOME/base/goGetter.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: GoGetter
|
||||
metadata:
|
||||
name: example
|
||||
url: github.com/kustless/kustomize-examples.git
|
||||
EOF
|
||||
```
|
||||
|
||||
Because this particular YAML file is listed in the `generators:` stanza of a kustomization file, it is treated as the binding between a generator plugin - identified by the _apiVersion_ and _kind_ fields - and other fields that configure the plugin.
|
||||
|
||||
Download the plugin to your `DEMO_HOME` and make it executable:
|
||||
|
||||
<!-- @installPlugin @test -->
|
||||
```sh
|
||||
plugin=plugin/someteam.example.com/v1/gogetter/GoGetter
|
||||
curl -s --create-dirs -o \
|
||||
"$DEMO_HOME/kustomize/$plugin" \
|
||||
"https://raw.githubusercontent.com/\
|
||||
kubernetes-sigs/kustomize/master/$plugin"
|
||||
|
||||
chmod a+x $DEMO_HOME/kustomize/$plugin
|
||||
```
|
||||
|
||||
Define a helper function to run kustomize with the correct environment and flags for plugins:
|
||||
|
||||
<!-- @defineKustomizeIt @test -->
|
||||
```sh
|
||||
function kustomizeIt {
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build --enable_alpha_plugins \
|
||||
$DEMO_HOME/$1
|
||||
}
|
||||
```
|
||||
|
||||
Finally, build the local variant. Notice that all
|
||||
resource names now have the `my-` prefix:
|
||||
|
||||
<!-- @doLocal @test -->
|
||||
```sh
|
||||
clear
|
||||
kustomizeIt
|
||||
```
|
||||
|
||||
Compare local variant to remote base:
|
||||
|
||||
<!-- @doCompare @test-->
|
||||
```sh
|
||||
diff <(kustomizeIt) <(kustomizeIt base) | more
|
||||
|
||||
...
|
||||
< name: my-remote-cm
|
||||
---
|
||||
> name: remote-cm
|
||||
```
|
||||
|
||||
To see the unmodified but extracted sources, run kustomize on the base. Every invocation here is re-downloading and re-building the package.
|
||||
|
||||
<!-- @showBase @test -->
|
||||
```sh
|
||||
kustomizeIt base
|
||||
```
|
||||
|
||||
## Use non-kustomize remote sources
|
||||
|
||||
Sometimes the remote sources does not include `kustomization.yaml`. To use that in the plugin, set command to override the default build.
|
||||
|
||||
<!-- @setCommand @test -->
|
||||
```sh
|
||||
echo "command: cat resources.yaml" >>$DEMO_HOME/base/goGetter.yaml
|
||||
```
|
||||
|
||||
Finally, built it
|
||||
|
||||
<!-- @finalLocal @test -->
|
||||
```sh
|
||||
kustomizeIt
|
||||
```
|
||||
|
||||
and observe the output includes raw `resources.yaml` instead of building result of remote `kustomization.yaml`.
|
||||
@@ -1,9 +1,9 @@
|
||||
[base]: ../../docs/glossary.md#base
|
||||
[config]: https://github.com/kinflate/example-hello
|
||||
[config]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/helloWorld
|
||||
[gitops]: ../../docs/glossary.md#gitops
|
||||
[hello]: https://github.com/monopole/hello
|
||||
[kustomization]: ../../docs/glossary.md#kustomization
|
||||
[original]: https://github.com/kinflate/example-hello
|
||||
[original]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/helloWorld
|
||||
[overlay]: ../../docs/glossary.md#overlay
|
||||
[overlays]: ../../docs/glossary.md#overlay
|
||||
[patch]: ../../docs/glossary.md#patch
|
||||
@@ -22,7 +22,7 @@ Steps:
|
||||
|
||||
First define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
@@ -44,7 +44,7 @@ To keep this document shorter, the base resources are
|
||||
off in a supplemental data directory rather than
|
||||
declared here as HERE documents. Download them:
|
||||
|
||||
<!-- @downloadBase @test -->
|
||||
<!-- @downloadBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
@@ -57,7 +57,7 @@ curl -s -o "$BASE/#1.yaml" "https://raw.githubusercontent.com\
|
||||
|
||||
Look at the directory:
|
||||
|
||||
<!-- @runTree @test -->
|
||||
<!-- @runTree -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
@@ -78,7 +78,7 @@ One could immediately apply these resources to a
|
||||
cluster:
|
||||
|
||||
> ```
|
||||
> kubectl apply -f $DEMO_HOME/base
|
||||
> kubectl apply -k $DEMO_HOME/base
|
||||
> ```
|
||||
|
||||
to instantiate the _hello_ service. `kubectl`
|
||||
@@ -88,7 +88,7 @@ would only recognize the resource files.
|
||||
|
||||
The `base` directory has a [kustomization] file:
|
||||
|
||||
<!-- @showKustomization @test -->
|
||||
<!-- @showKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
more $BASE/kustomization.yaml
|
||||
```
|
||||
@@ -96,7 +96,7 @@ more $BASE/kustomization.yaml
|
||||
Optionally, run `kustomize` on the base to emit
|
||||
customized resources to `stdout`:
|
||||
|
||||
<!-- @buildBase @test -->
|
||||
<!-- @buildBase @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE
|
||||
```
|
||||
@@ -106,20 +106,14 @@ kustomize build $BASE
|
||||
A first customization step could be to change the _app
|
||||
label_ applied to all resources:
|
||||
|
||||
<!-- @addLabel @test -->
|
||||
<!-- @addLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
sed -i 's/app: hello/app: my-hello/' \
|
||||
sed -i.bak 's/app: hello/app: my-hello/' \
|
||||
$BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
On a Mac, use:
|
||||
```
|
||||
sed -i '' $pattern $file
|
||||
```
|
||||
to get in-place editing.
|
||||
|
||||
See the effect:
|
||||
<!-- @checkLabel @test -->
|
||||
<!-- @checkLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE | grep -C 3 app:
|
||||
```
|
||||
@@ -133,7 +127,7 @@ Create a _staging_ and _production_ [overlay]:
|
||||
* Web server greetings from these cluster
|
||||
[variants] will differ from each other.
|
||||
|
||||
<!-- @overlayDirectories @test -->
|
||||
<!-- @overlayDirectories @testAgainstLatestRelease -->
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
@@ -145,7 +139,7 @@ mkdir -p $OVERLAYS/production
|
||||
In the `staging` directory, make a kustomization
|
||||
defining a new name prefix, and some different labels.
|
||||
|
||||
<!-- @makeStagingKustomization @test -->
|
||||
<!-- @makeStagingKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$OVERLAYS/staging/kustomization.yaml
|
||||
namePrefix: staging-
|
||||
@@ -156,7 +150,7 @@ commonAnnotations:
|
||||
note: Hello, I am staging!
|
||||
bases:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- map.yaml
|
||||
EOF
|
||||
```
|
||||
@@ -168,7 +162,7 @@ greeting from _Good Morning!_ to _Have a pineapple!_
|
||||
|
||||
Also, enable the _risky_ flag.
|
||||
|
||||
<!-- @stagingMap @test -->
|
||||
<!-- @stagingMap @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$OVERLAYS/staging/map.yaml
|
||||
apiVersion: v1
|
||||
@@ -186,7 +180,7 @@ EOF
|
||||
In the production directory, make a kustomization
|
||||
with a different name prefix and labels.
|
||||
|
||||
<!-- @makeProductionKustomization @test -->
|
||||
<!-- @makeProductionKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$OVERLAYS/production/kustomization.yaml
|
||||
namePrefix: production-
|
||||
@@ -197,7 +191,7 @@ commonAnnotations:
|
||||
note: Hello, I am production!
|
||||
bases:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- deployment.yaml
|
||||
EOF
|
||||
```
|
||||
@@ -208,7 +202,7 @@ EOF
|
||||
Make a production patch that increases the replica
|
||||
count (because production takes more traffic).
|
||||
|
||||
<!-- @productionDeployment @test -->
|
||||
<!-- @productionDeployment @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$OVERLAYS/production/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -234,7 +228,7 @@ EOF
|
||||
|
||||
Review the directory structure and differences:
|
||||
|
||||
<!-- @listFiles @test -->
|
||||
<!-- @listFiles -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
@@ -294,12 +288,12 @@ something like
|
||||
|
||||
The individual resource sets are:
|
||||
|
||||
<!-- @buildStaging @test -->
|
||||
<!-- @buildStaging @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/staging
|
||||
```
|
||||
|
||||
<!-- @buildProduction @test -->
|
||||
<!-- @buildProduction @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/production
|
||||
```
|
||||
|
||||
@@ -4,6 +4,9 @@ metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
deployment: hello
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: arbitrary
|
||||
|
||||
# Example configuration for the webserver
|
||||
# at https://github.com/monopole/hello
|
||||
commonLabels:
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# Demo: change image tags
|
||||
# Demo: change image names and tags
|
||||
|
||||
|
||||
Define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Make a `kustomization` containing a pod resource
|
||||
|
||||
<!-- @createKustomization @test -->
|
||||
<!-- @createKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
@@ -20,7 +20,7 @@ EOF
|
||||
|
||||
Declare the pod resource
|
||||
|
||||
<!-- @createDeployment @test -->
|
||||
<!-- @createDeployment @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/pod.yaml
|
||||
apiVersion: v1
|
||||
@@ -42,34 +42,35 @@ EOF
|
||||
```
|
||||
|
||||
The `myapp-pod` resource declares an initContainer and a container, both use the image `busybox:1.29.0`.
|
||||
The tag `1.29.0` can be changed by adding `imageTags` in `kustomization.yaml`.
|
||||
The image `busybox` and tag `1.29.0` can be changed by adding `images` in `kustomization.yaml`.
|
||||
|
||||
|
||||
Add `imageTags`:
|
||||
<!-- @addImageTags @test -->
|
||||
Add `images`:
|
||||
<!-- @addImages @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit set imagetag busybox:1.29.1
|
||||
kustomize edit set image busybox=alpine:3.6
|
||||
```
|
||||
|
||||
The `kustomization.yaml` will be added following `imageTags`.
|
||||
The following `images` will be added to `kustomization.yaml`:
|
||||
> ```
|
||||
> imageTags:
|
||||
> images:
|
||||
> - name: busybox
|
||||
> newTag: 1.29.1
|
||||
> newName: alpine
|
||||
> newTag: 3.6
|
||||
> ```
|
||||
|
||||
Now build this `kustomization`
|
||||
<!-- @kustomizeBuild @test -->
|
||||
<!-- @kustomizeBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
Confirm that this replaces _both_ busybox tags:
|
||||
Confirm that this replaces _both_ busybox images and tags for `alpine:3.6`:
|
||||
|
||||
<!-- @confirmTags @test -->
|
||||
<!-- @confirmImages @testAgainstLatestRelease -->
|
||||
```
|
||||
test 2 == \
|
||||
$(kustomize build $DEMO_HOME | grep busybox:1.29.1 | wc -l); \
|
||||
test 2 = \
|
||||
$(kustomize build $DEMO_HOME | grep alpine:3.6 | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
265
examples/inlinePatch.md
Normal file
265
examples/inlinePatch.md
Normal file
@@ -0,0 +1,265 @@
|
||||
[Strategic Merge Patch]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md
|
||||
[JSON Patch]: https://tools.ietf.org/html/rfc6902
|
||||
|
||||
# Demo: Inline Patch
|
||||
|
||||
A kustomization file supports patching in three ways:
|
||||
- patchesStrategicMerge: A list of patch files where each file is parsed as a [Strategic Merge Patch].
|
||||
- patchesJSON6902: A list of patches and associated targets, where each file is parsed as a [JSON Patch] and can only be applied to one target resource.
|
||||
- patches: A list of patches and their associated targets. The patch can be applied to multiple objects. It auto detects whether the patch is a [Strategic Merge Patch] or [JSON Patch].
|
||||
|
||||
Since 3.2.0, all three support inline patch, where the patch content is put inside the kustomization file as a single string. With this feature, no separate patch files need to be created.
|
||||
|
||||
Make a base kustomization containing a Deployment resource.
|
||||
<!-- @createKustomization @test -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
resources:
|
||||
- deployments.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/deployments.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
args:
|
||||
- one
|
||||
- two
|
||||
EOF
|
||||
```
|
||||
|
||||
|
||||
## Inline Patch for PatchesStrategicMerge
|
||||
|
||||
Create an overlay and add an inline patch in `patchesStrategicMerge` field to the kustomization file
|
||||
to change the image from `nginx` to `nginx:latest`.
|
||||
|
||||
<!-- @addSMPatch @test -->
|
||||
```
|
||||
SMP_OVERLAY=$DEMO_HOME/smp
|
||||
mkdir $SMP_OVERLAY
|
||||
cat <<EOF >$SMP_OVERLAY/kustomization.yaml
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
|
||||
EOF
|
||||
```
|
||||
|
||||
Running `kustomize build $SMP_OVERLAY`, in the output confirm that image is updated successfully.
|
||||
|
||||
<!-- @confirmSMPatch @test -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $SMP_OVERLAY | grep "image: nginx:latest" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
The output is
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
args:
|
||||
- one
|
||||
- two
|
||||
```
|
||||
|
||||
`$patch: delete` and `$patch: replace` also work in the inline patch. Change the inline patch to delete the container `nginx`.
|
||||
|
||||
<!-- @addDeleteSMPatch @test -->
|
||||
```
|
||||
cat <<EOF >$SMP_OVERLAY/kustomization.yaml
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
$patch: delete
|
||||
|
||||
EOF
|
||||
```
|
||||
Running `kustomize build $SMP_OVERLAY`, in the output confirm that the `nginx` container has been deleted.
|
||||
|
||||
<!-- @confirmDeleteSMPatch @test -->
|
||||
```
|
||||
test 0 == \
|
||||
$(kustomize build $SMP_OVERLAY | grep "image: nginx" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
The output is
|
||||
```
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers: []
|
||||
```
|
||||
|
||||
## Inline Patch for PatchesJson6902
|
||||
|
||||
Create an overlay and add an inline patch in `patchesJSON6902` field to the kustomization file
|
||||
to change the image from `nginx` to `nginx:latest`.
|
||||
|
||||
<!-- @addJSONPatch @test -->
|
||||
```
|
||||
JSON_OVERLAY=$DEMO_HOME/json
|
||||
mkdir $JSON_OVERLAY
|
||||
cat <<EOF >$JSON_OVERLAY/kustomization.yaml
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
patchesJSON6902:
|
||||
- target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: deploy
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: nginx:latest
|
||||
EOF
|
||||
```
|
||||
|
||||
Running `kustomize build $JSON_OVERLAY`, in the output confirm that image is updated successfully.
|
||||
|
||||
<!-- @confirmJSONPatch @test -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $JSON_OVERLAY | grep "image: nginx:latest" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
The output is
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
args:
|
||||
- one
|
||||
- two
|
||||
```
|
||||
|
||||
## Inline Patch for Patches
|
||||
|
||||
Create an overlay and add an inline patch in `patches` field to the kustomization file
|
||||
to change the image from `nginx` to `nginx:latest`.
|
||||
|
||||
<!-- @addPatch @test -->
|
||||
```
|
||||
PATCH_OVERLAY=$DEMO_HOME/patch
|
||||
mkdir $PATCH_OVERLAY
|
||||
cat <<EOF > $PATCH_OVERLAY/kustomization.yaml
|
||||
resources:
|
||||
- ../base
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: deploy
|
||||
patch: |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
EOF
|
||||
```
|
||||
|
||||
Running `kustomize build $PATCH_OVERLAY`, in the output confirm that image is updated successfully.
|
||||
|
||||
<!-- @confirmPatch @test -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $PATCH_OVERLAY | grep "image: nginx:latest" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
The output is
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
args:
|
||||
- one
|
||||
- two
|
||||
```
|
||||
@@ -28,7 +28,7 @@
|
||||
# before running it.
|
||||
#
|
||||
# At time of writing, its 'call point' was in
|
||||
# https://github.com/kubernetes/test-infra/blob/master/jobs/config.json
|
||||
# https://github.com/kubernetes/test-infra/blob/master/config/jobs/kubernetes-sigs/kustomize/kustomize-config.yaml
|
||||
|
||||
function exitWith {
|
||||
local msg=$1
|
||||
@@ -48,12 +48,12 @@ function setUpEnv {
|
||||
[[ $? -eq 0 ]] || "Failed to cd to $repo"
|
||||
echo "pwd is " `pwd`
|
||||
|
||||
local expectedRepo=kubernetes-sigs/kustomize
|
||||
local expectedRepo=sigs.k8s.io/kustomize
|
||||
if [[ `pwd` != */$expectedRepo ]]; then
|
||||
exitWith "Script must be run from $expectedRepo"
|
||||
fi
|
||||
|
||||
go install . || \
|
||||
GO111MODULE=on go install ./cmd/kustomize || \
|
||||
{ exitWith "Failed to install kustomize."; }
|
||||
|
||||
PATH=$GOPATH/bin:$PATH
|
||||
|
||||
201
examples/jsonpatch.md
Normal file
201
examples/jsonpatch.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# JSON Patching
|
||||
|
||||
[JSON patches]: https://tools.ietf.org/html/rfc6902
|
||||
[JSON patch]: https://tools.ietf.org/html/rfc6902
|
||||
|
||||
A kustomization file supports customizing
|
||||
resources via [JSON patches].
|
||||
|
||||
Make a place to work:
|
||||
|
||||
<!-- @placeToWork @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
We'll be editting an `Ingress` object:
|
||||
|
||||
<!-- @ingress @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: my-ingress
|
||||
spec:
|
||||
rules:
|
||||
- host: foo.bar.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
backend:
|
||||
serviceName: homepage
|
||||
servicePort: 8888
|
||||
- path: /api
|
||||
backend:
|
||||
serviceName: my-api
|
||||
servicePort: 7701
|
||||
- path: /test
|
||||
backend:
|
||||
serviceName: hello
|
||||
servicePort: 7702
|
||||
EOF
|
||||
```
|
||||
|
||||
The edits we want to make are:
|
||||
|
||||
- change the value of `host` to _foo.bar.io_
|
||||
- change the port for `'/'` from _8888_ to _80_
|
||||
- insert an entirely new serving path `/healthz`
|
||||
at a particular point in the `paths` list,
|
||||
rather than at the end or the beginning.
|
||||
|
||||
Here's the patch file to do that:
|
||||
|
||||
<!-- @addJsonPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/ingress_patch.json
|
||||
[
|
||||
{"op": "replace",
|
||||
"path": "/spec/rules/0/host",
|
||||
"value": "foo.bar.io"},
|
||||
|
||||
{"op": "replace",
|
||||
"path": "/spec/rules/0/http/paths/0/backend/servicePort",
|
||||
"value": 80},
|
||||
|
||||
{"op": "add",
|
||||
"path": "/spec/rules/0/http/paths/1",
|
||||
"value": { "path": "/healthz", "backend": {"servicePort":7700} }}
|
||||
]
|
||||
EOF
|
||||
```
|
||||
|
||||
We'll of course need a `kustomization` file
|
||||
referring to the `Ingress`:
|
||||
|
||||
<!-- @kustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- ingress.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
To this same `kustomization` file, add a
|
||||
`patches` field refering to
|
||||
the patch file we just made and
|
||||
target it to the `Ingress` object:
|
||||
|
||||
<!-- @applyJsonPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
patches:
|
||||
- path: ingress_patch.json
|
||||
target:
|
||||
group: networking.k8s.io
|
||||
version: v1beta1
|
||||
kind: Ingress
|
||||
name: my-ingress
|
||||
EOF
|
||||
```
|
||||
|
||||
Define the expected output:
|
||||
<!-- @expected @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/out_expected.yaml
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: my-ingress
|
||||
spec:
|
||||
rules:
|
||||
- host: foo.bar.io
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: homepage
|
||||
servicePort: 80
|
||||
path: /
|
||||
- backend:
|
||||
servicePort: 7700
|
||||
path: /healthz
|
||||
- backend:
|
||||
serviceName: my-api
|
||||
servicePort: 7701
|
||||
path: /api
|
||||
- backend:
|
||||
serviceName: hello
|
||||
servicePort: 7702
|
||||
path: /test
|
||||
EOF
|
||||
```
|
||||
|
||||
Run the build:
|
||||
<!-- @runIt @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME >$DEMO_HOME/out_actual.yaml
|
||||
```
|
||||
|
||||
Confirm they match:
|
||||
|
||||
<!-- @diffShouldExitZero @testAgainstLatestRelease -->
|
||||
```
|
||||
diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
|
||||
```
|
||||
|
||||
If you prefer YAML to JSON, the patch can be expressed
|
||||
in YAML format (nevertheless following [JSON patch] rules):
|
||||
|
||||
<!-- @writeYamlPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/ingress_patch.yaml
|
||||
- op: add
|
||||
path: /spec/rules/0/http/paths/-
|
||||
value:
|
||||
path: '/canada'
|
||||
backend:
|
||||
serviceName: hoser
|
||||
servicePort: 7703
|
||||
EOF
|
||||
```
|
||||
|
||||
Now add this to the list of patches in the `kustomization` file:
|
||||
|
||||
<!-- @addYamlPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
- path: ingress_patch.yaml
|
||||
target:
|
||||
group: networking.k8s.io
|
||||
version: v1beta1
|
||||
kind: Ingress
|
||||
name: my-ingress
|
||||
EOF
|
||||
```
|
||||
|
||||
We expect the following at the end of the output:
|
||||
<!-- @expected @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/out_expected.yaml
|
||||
- backend:
|
||||
serviceName: hello
|
||||
servicePort: 7702
|
||||
path: /test
|
||||
- backend:
|
||||
serviceName: hoser
|
||||
servicePort: 7703
|
||||
path: /canada
|
||||
EOF
|
||||
```
|
||||
|
||||
Try it:
|
||||
|
||||
<!-- @runIt @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME | tail -n 8 |\
|
||||
diff $DEMO_HOME/out_expected.yaml -
|
||||
```
|
||||
|
||||
To see how to apply one JSON patch to many resources,
|
||||
see the [multi-patch](patchMultipleObjects.md) demo.
|
||||
@@ -18,7 +18,7 @@ Steps:
|
||||
|
||||
First define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
@@ -38,7 +38,7 @@ To keep this document shorter, the base resources are
|
||||
off in a supplemental data directory rather than
|
||||
declared here as HERE documents. Download them:
|
||||
|
||||
<!-- @downloadBase @test -->
|
||||
<!-- @downloadBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
@@ -53,7 +53,7 @@ curl -s -o "$BASE/#1" "$CONTENT/base\
|
||||
|
||||
Look at the directory:
|
||||
|
||||
<!-- @runTree @test -->
|
||||
<!-- @runTree -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
@@ -84,7 +84,7 @@ would only recognize the resource files.
|
||||
|
||||
The `base` directory has a [kustomization] file:
|
||||
|
||||
<!-- @showKustomization @test -->
|
||||
<!-- @showKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
more $BASE/kustomization.yaml
|
||||
```
|
||||
@@ -92,7 +92,7 @@ more $BASE/kustomization.yaml
|
||||
Optionally, run `kustomize` on the base to emit
|
||||
customized resources to `stdout`:
|
||||
|
||||
<!-- @buildBase @test -->
|
||||
<!-- @buildBase @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE
|
||||
```
|
||||
@@ -101,14 +101,14 @@ kustomize build $BASE
|
||||
|
||||
A first customization step could be to set the name prefix to all resources:
|
||||
|
||||
<!-- @namePrefix @test -->
|
||||
<!-- @namePrefix @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $BASE
|
||||
kustomize edit set nameprefix "my-"
|
||||
```
|
||||
|
||||
See the effect:
|
||||
<!-- @checkNameprefix @test -->
|
||||
<!-- @checkNameprefix @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE | grep -C 3 "my-"
|
||||
```
|
||||
@@ -121,7 +121,7 @@ Create a _staging_ and _production_ [overlay]:
|
||||
* _Production_ has a higher replica count and a persistent disk.
|
||||
* [variants] will differ from each other.
|
||||
|
||||
<!-- @overlayDirectories @test -->
|
||||
<!-- @overlayDirectories @testAgainstLatestRelease -->
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
@@ -132,7 +132,7 @@ mkdir -p $OVERLAYS/production
|
||||
|
||||
Download the staging customization and patch.
|
||||
|
||||
<!-- @downloadStagingKustomization @test -->
|
||||
<!-- @downloadStagingKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$OVERLAYS/staging/#1" "$CONTENT/overlays/staging\
|
||||
/{config.env,deployment.yaml,kustomization.yaml}"
|
||||
@@ -148,7 +148,7 @@ The staging customization adds a configMap.
|
||||
> ```
|
||||
as well as 2 replica
|
||||
> ```cat $OVERLAYS/staging/deployment.yaml
|
||||
> apiVersion: apps/v1beta2
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: ldap
|
||||
@@ -159,7 +159,7 @@ as well as 2 replica
|
||||
#### Production Kustomization
|
||||
|
||||
Download the production customization and patch.
|
||||
<!-- @downloadProductionKustomization @test -->
|
||||
<!-- @downloadProductionKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$OVERLAYS/production/#1" "$CONTENT/overlays/production\
|
||||
/{deployment.yaml,kustomization.yaml}"
|
||||
@@ -167,7 +167,7 @@ curl -s -o "$OVERLAYS/production/#1" "$CONTENT/overlays/production\
|
||||
|
||||
The production customization adds 6 replica as well as a consistent disk.
|
||||
> ```cat $OVERLAYS/production/deployment.yaml
|
||||
> apiVersion: apps/v1beta2
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: ldap
|
||||
@@ -196,7 +196,7 @@ The production customization adds 6 replica as well as a consistent disk.
|
||||
|
||||
Review the directory structure and differences:
|
||||
|
||||
<!-- @listFiles @test -->
|
||||
<!-- @listFiles -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
@@ -258,12 +258,12 @@ The difference output should look something like
|
||||
|
||||
The individual resource sets are:
|
||||
|
||||
<!-- @buildStaging @test -->
|
||||
<!-- @buildStaging @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/staging
|
||||
```
|
||||
|
||||
<!-- @buildProduction @test -->
|
||||
<!-- @buildProduction @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/production
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ldap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ldap
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- deployment.yaml
|
||||
namePrefix: production-
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ldap
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
bases:
|
||||
- ../../base
|
||||
patches:
|
||||
- deployment.yaml
|
||||
nameprefix: staging-
|
||||
resources:
|
||||
- ../../base
|
||||
patchesStrategicMerge:
|
||||
- deployment.yaml
|
||||
namePrefix: staging-
|
||||
configMapGenerator:
|
||||
- name: env-config
|
||||
files:
|
||||
- config.env
|
||||
- name: env-config
|
||||
files:
|
||||
- config.env
|
||||
|
||||
25
examples/loadHttp.md
Normal file
25
examples/loadHttp.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# load file from http
|
||||
|
||||
Resource and patch files could be loaded from http
|
||||
|
||||
<!-- @loadHttp -->
|
||||
```sh
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- @loadHttp -->
|
||||
```sh
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "Good Morning!" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Kustomize will try loading resource as a file either from local or http. If it
|
||||
fails, try to load it as a directory or git repository.
|
||||
|
||||
Http load applies to patches as well. See full example in [loadHttp](loadHttp/).
|
||||
15
examples/loadHttp/kustomization.yaml
Normal file
15
examples/loadHttp/kustomization.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/wordpress/wordpress/deployment.yaml
|
||||
- https://github.com/knative/serving/releases/download/v0.12.0/serving.yaml # redirects to s3
|
||||
patches:
|
||||
- https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/wordpress/patch.yaml
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: custom-metrics-auth-reader
|
||||
namespace: kube-system
|
||||
$patch: delete
|
||||
137
examples/multibases/README.md
Normal file
137
examples/multibases/README.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Demo: multibases with a common base
|
||||
|
||||
`kustomize` encourages defining multiple variants -
|
||||
e.g. dev, staging and prod,
|
||||
as overlays on a common base.
|
||||
|
||||
It's possible to create an additional overlay to
|
||||
compose these variants together - just declare the
|
||||
overlays as the bases of a new kustomization.
|
||||
|
||||
This is also a means to apply a common label or
|
||||
annotation across the variants, if for some reason
|
||||
the base isn't under your control. It also allows
|
||||
one to define a left-most namePrefix across the
|
||||
variants - something that cannot be
|
||||
done by modifying the common base.
|
||||
|
||||
The following demonstrates this using a base
|
||||
that is just a single pod.
|
||||
|
||||
Define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Define a common base:
|
||||
<!-- @makeBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
resources:
|
||||
- pod.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a dev variant overlaying base:
|
||||
<!-- @makeDev @testAgainstLatestRelease -->
|
||||
```
|
||||
DEV=$DEMO_HOME/dev
|
||||
mkdir $DEV
|
||||
|
||||
cat <<EOF >$DEV/kustomization.yaml
|
||||
resources:
|
||||
- ./../base
|
||||
namePrefix: dev-
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a staging variant overlaying base:
|
||||
<!-- @makeStaging @testAgainstLatestRelease -->
|
||||
```
|
||||
STAG=$DEMO_HOME/staging
|
||||
mkdir $STAG
|
||||
|
||||
cat <<EOF >$STAG/kustomization.yaml
|
||||
resources:
|
||||
- ./../base
|
||||
namePrefix: stag-
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a production variant overlaying base:
|
||||
<!-- @makeProd @testAgainstLatestRelease -->
|
||||
```
|
||||
PROD=$DEMO_HOME/production
|
||||
mkdir $PROD
|
||||
|
||||
cat <<EOF >$PROD/kustomization.yaml
|
||||
resources:
|
||||
- ./../base
|
||||
namePrefix: prod-
|
||||
EOF
|
||||
```
|
||||
|
||||
Then define a _Kustomization_ composing three variants together:
|
||||
<!-- @makeTopLayer @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- ./dev
|
||||
- ./staging
|
||||
- ./production
|
||||
|
||||
namePrefix: cluster-a-
|
||||
EOF
|
||||
```
|
||||
|
||||
Now the workspace has following directories
|
||||
> ```
|
||||
> .
|
||||
> ├── base
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── pod.yaml
|
||||
> ├── dev
|
||||
> │ └── kustomization.yaml
|
||||
> ├── kustomization.yaml
|
||||
> ├── production
|
||||
> │ └── kustomization.yaml
|
||||
> └── staging
|
||||
> └── kustomization.yaml
|
||||
> ```
|
||||
|
||||
Confirm that the `kustomize build` output contains three pod objects from dev, staging and production variants.
|
||||
|
||||
<!-- @confirmVariants @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep cluster-a-dev-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep cluster-a-stag-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep cluster-a-prod-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
Similarly to adding different `namePrefix` in different variants, one can also add different `namespace` and compose those variants in
|
||||
one _kustomization_. For more details, take a look at [multi-namespaces](multi-namespace.md).
|
||||
2
examples/multibases/base/kustomization.yaml
Normal file
2
examples/multibases/base/kustomization.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
resources:
|
||||
- pod.yaml
|
||||
10
examples/multibases/base/pod.yaml
Normal file
10
examples/multibases/base/pod.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9
|
||||
3
examples/multibases/dev/kustomization.yaml
Normal file
3
examples/multibases/dev/kustomization.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
resources:
|
||||
- ../base
|
||||
namePrefix: dev-
|
||||
5
examples/multibases/kustomization.yaml
Normal file
5
examples/multibases/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
resources:
|
||||
- dev
|
||||
- staging
|
||||
- production
|
||||
namePrefix: cluster-a-
|
||||
115
examples/multibases/multi-namespace.md
Normal file
115
examples/multibases/multi-namespace.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Demo: multi namespaces with a common base
|
||||
|
||||
`kustomize` supports defining multiple variants with different namespace, as overlays on a common base.
|
||||
|
||||
It's possible to create an additional overlay to compose these variants
|
||||
together - just declare the overlays as the bases of a new kustomization. The
|
||||
following demonstrates this using a base that's just one pod.
|
||||
|
||||
Define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Define a common base:
|
||||
<!-- @makeBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
resources:
|
||||
- pod.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a variant in namespace-a overlaying base:
|
||||
<!-- @makeNamespaceA @testAgainstLatestRelease -->
|
||||
```
|
||||
NSA=$DEMO_HOME/namespace-a
|
||||
mkdir $NSA
|
||||
|
||||
cat <<EOF >$NSA/kustomization.yaml
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- ../base
|
||||
namespace: namespace-a
|
||||
EOF
|
||||
|
||||
cat <<EOF >$NSA/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: namespace-a
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a variant in namespace-b overlaying base:
|
||||
<!-- @makeNamespaceB @testAgainstLatestRelease -->
|
||||
```
|
||||
NSB=$DEMO_HOME/namespace-b
|
||||
mkdir $NSB
|
||||
|
||||
cat <<EOF >$NSB/kustomization.yaml
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- ../base
|
||||
namespace: namespace-b
|
||||
EOF
|
||||
|
||||
cat <<EOF >$NSB/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: namespace-b
|
||||
EOF
|
||||
```
|
||||
|
||||
Then define a _Kustomization_ composing two variants together:
|
||||
<!-- @makeTopLayer @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- namespace-a
|
||||
- namespace-b
|
||||
EOF
|
||||
```
|
||||
|
||||
Now the workspace has following directories
|
||||
> ```
|
||||
> .
|
||||
> ├── base
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── pod.yaml
|
||||
> ├── kustomization.yaml
|
||||
> ├── namespace-a
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── namespace.yaml
|
||||
> └── namespace-b
|
||||
> ├── kustomization.yaml
|
||||
> └── namespace.yaml
|
||||
> ```
|
||||
|
||||
Confirm that the `kustomize build` output contains two pod objects from namespace-a and namespace-b.
|
||||
|
||||
<!-- @confirmVariants @testAgainstLatestRelease -->
|
||||
```
|
||||
test 2 == \
|
||||
$(kustomize build $DEMO_HOME| grep -B 4 "namespace: namespace-[ab]" | grep "name: myapp-pod" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
3
examples/multibases/production/kustomization.yaml
Normal file
3
examples/multibases/production/kustomization.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
resources:
|
||||
- ../base
|
||||
namePrefix: prod-
|
||||
3
examples/multibases/staging/kustomization.yaml
Normal file
3
examples/multibases/staging/kustomization.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
resources:
|
||||
- ../base
|
||||
namePrefix: staging-
|
||||
@@ -11,7 +11,7 @@ In the production environment we want:
|
||||
- MySQL to use persistent disk for storing data.
|
||||
|
||||
First make a place to work:
|
||||
<!-- @makeDemoHome @test -->
|
||||
<!-- @makeDemoHome @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
@@ -25,7 +25,7 @@ as HERE documents.
|
||||
|
||||
Download them:
|
||||
|
||||
<!-- @downloadResources @test -->
|
||||
<!-- @downloadResources @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" "https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
@@ -40,14 +40,14 @@ a file called `kustomization.yaml`.
|
||||
|
||||
Start this file:
|
||||
|
||||
<!-- @kustomizeYaml @test -->
|
||||
<!-- @kustomizeYaml @testAgainstLatestRelease -->
|
||||
```
|
||||
touch $DEMO_HOME/kustomization.yaml
|
||||
```
|
||||
|
||||
### Add the resources
|
||||
|
||||
<!-- @addResources @test -->
|
||||
<!-- @addResources @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
|
||||
@@ -73,7 +73,7 @@ Arrange for the MySQL resources to begin with prefix
|
||||
_prod-_ (since they are meant for the _production_
|
||||
environment):
|
||||
|
||||
<!-- @customizeLabel @test -->
|
||||
<!-- @customizeLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
|
||||
@@ -91,7 +91,7 @@ cat kustomization.yaml
|
||||
This `namePrefix` directive adds _prod-_ to all
|
||||
resource names.
|
||||
|
||||
<!-- @genNamePrefixConfig @test -->
|
||||
<!-- @genNamePrefixConfig @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
@@ -115,7 +115,7 @@ The output should contain:
|
||||
> spec:
|
||||
> ....
|
||||
> ---
|
||||
> apiVersion: apps/v1beta2
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> ....
|
||||
@@ -134,9 +134,9 @@ selector.
|
||||
`kustomize` does not have `edit set label` command to add
|
||||
a label, but one can always edit `kustomization.yaml` directly:
|
||||
|
||||
<!-- @customizeLabels @test -->
|
||||
<!-- @customizeLabels @testAgainstLatestRelease -->
|
||||
```
|
||||
sed -i 's/app: helloworld/app: prod/' \
|
||||
sed -i.bak 's/app: helloworld/app: prod/' \
|
||||
$DEMO_HOME/kustomization.yaml
|
||||
```
|
||||
|
||||
@@ -150,13 +150,13 @@ Off the shelf MySQL uses `emptyDir` type volume, which
|
||||
gets wiped away if the MySQL Pod is recreated, and that
|
||||
is certainly not desirable for production
|
||||
environment. So we want to use Persistent Disk in
|
||||
production. kustomize lets you apply `patches` to the
|
||||
production. kustomize lets you apply `patchesStrategicMerge` to the
|
||||
resources.
|
||||
|
||||
<!-- @createPatchFile @test -->
|
||||
<!-- @createPatchFile @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' > $DEMO_HOME/persistent-disk.yaml
|
||||
apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2
|
||||
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mysql
|
||||
@@ -173,14 +173,16 @@ EOF
|
||||
|
||||
Add the patch file to `kustomization.yaml`:
|
||||
|
||||
<!-- @specifyPatch @test -->
|
||||
<!-- @specifyPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >> $DEMO_HOME/kustomization.yaml
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- persistent-disk.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
A `mysql-persistent-storage` persistent disk needs to exist for it to run successfully.
|
||||
|
||||
Lets break this down:
|
||||
|
||||
- In the first step, we created a YAML file named
|
||||
@@ -188,7 +190,7 @@ Lets break this down:
|
||||
in deployment.yaml
|
||||
|
||||
- Then we added `persistent-disk.yaml` to list of
|
||||
`patches` in `kustomization.yaml`. `kustomize build`
|
||||
`patchesStrategicMerge` in `kustomization.yaml`. `kustomize build`
|
||||
will apply this patch to the deployment resource with
|
||||
the name `mysql` as defined in the patch.
|
||||
|
||||
@@ -197,7 +199,7 @@ The output of the following command can now be applied
|
||||
to the cluster (i.e. piped to `kubectl apply`) to
|
||||
create the production environment.
|
||||
|
||||
<!-- @finalInflation @test -->
|
||||
<!-- @finalInflation @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME # | kubectl apply -f -
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2
|
||||
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mysql
|
||||
|
||||
@@ -2,7 +2,7 @@ apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: mysql-pass-d2gtcm2t2k
|
||||
name: mysql-pass
|
||||
type: Opaque
|
||||
data:
|
||||
# Default password is "admin".
|
||||
|
||||
218
examples/patchMultipleObjects.md
Normal file
218
examples/patchMultipleObjects.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# Patching multiple resources at once.
|
||||
|
||||
kustomize supports patching via either a
|
||||
[strategic merge patch] (wherein you
|
||||
partially re-specify the thing you want to
|
||||
modify, with in-place changes) or a
|
||||
[JSON patch] (wherein you specify specific
|
||||
operation/target/value tuples in a particular
|
||||
syntax).
|
||||
|
||||
A kustomize file lets one specify many
|
||||
patches. Each patch must be associated with
|
||||
a _target selector_:
|
||||
|
||||
[strategic merge patch]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md
|
||||
[json patch]: jsonpatch.md
|
||||
|
||||
> ```yaml
|
||||
> patches:
|
||||
> - path: <relative path to file containing patch>
|
||||
> target:
|
||||
> group: <optional group>
|
||||
> version: <optional version>
|
||||
> kind: <optional kind>
|
||||
> name: <optional name>
|
||||
> namespace: <optional namespace>
|
||||
> labelSelector: <optional label selector>
|
||||
> annotationSelector: <optional annotation selector>
|
||||
> ```
|
||||
|
||||
E.g. select resources with _name_ matching `foo*`:
|
||||
|
||||
> ```yaml
|
||||
> target:
|
||||
> name: foo*
|
||||
> ```
|
||||
|
||||
Select all resources of _kind_ `Deployment`:
|
||||
|
||||
> ```yaml
|
||||
> target:
|
||||
> kind: Deployment
|
||||
> ```
|
||||
|
||||
[label/annotation selector rules]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
|
||||
|
||||
Using multiple fields just makes the target
|
||||
more specific. The following selects only
|
||||
Deployments that also have the _label_ `app=hello`
|
||||
(full [label/annotation selector rules]):
|
||||
|
||||
> ```yaml
|
||||
> target:
|
||||
> kind: Deployment
|
||||
> labelSelector: app=hello
|
||||
> ```
|
||||
|
||||
### Demo
|
||||
|
||||
The example below shows how to inject a
|
||||
sidecar container for multiple Deployment
|
||||
resources.
|
||||
|
||||
Make a place to work:
|
||||
|
||||
<!-- @demoHome @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Make a file describing two Deployments:
|
||||
|
||||
<!-- @createDeployments @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/deployments.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
old-label: old-value
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
args:
|
||||
- one
|
||||
- two
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy2
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
key: value
|
||||
spec:
|
||||
containers:
|
||||
- name: busybox
|
||||
image: busybox
|
||||
EOF
|
||||
```
|
||||
|
||||
Declare a [strategic merge patch] file
|
||||
to inject a sidecar container:
|
||||
|
||||
<!-- @definePatch @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: not-important
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: istio-proxy
|
||||
image: docker.io/istio/proxyv2
|
||||
args:
|
||||
- proxy
|
||||
- sidecar
|
||||
EOF
|
||||
```
|
||||
|
||||
Finally, define a kustomization file
|
||||
that specifies both a `patches` and `resources`
|
||||
entry:
|
||||
|
||||
<!-- @createKustomization @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- deployments.yaml
|
||||
|
||||
patches:
|
||||
- path: patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
EOF
|
||||
```
|
||||
|
||||
The expected result is:
|
||||
|
||||
<!-- @definedExpectedOutput @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/out_expected.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
old-label: old-value
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- proxy
|
||||
- sidecar
|
||||
image: docker.io/istio/proxyv2
|
||||
name: istio-proxy
|
||||
- args:
|
||||
- one
|
||||
- two
|
||||
image: nginx
|
||||
name: nginx
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy2
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
key: value
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- proxy
|
||||
- sidecar
|
||||
image: docker.io/istio/proxyv2
|
||||
name: istio-proxy
|
||||
- image: busybox
|
||||
name: busybox
|
||||
EOF
|
||||
```
|
||||
|
||||
Run the build:
|
||||
|
||||
<!-- @runIt @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $DEMO_HOME >$DEMO_HOME/out_actual.yaml
|
||||
```
|
||||
|
||||
Confirm expectations:
|
||||
|
||||
<!-- @diffShouldExitZero @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
|
||||
```
|
||||
|
||||
To see how to do this with JSON patches,
|
||||
try the [JSON patch] demo.
|
||||
98
examples/remoteBuild.md
Normal file
98
examples/remoteBuild.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# remote targets
|
||||
|
||||
`kustomize build` can be run on a URL.
|
||||
|
||||
A [lite version of go-getter module](https://github.com/yujunz/go-getter) is
|
||||
leveraged to get remote content, then running `kustomize build` against the
|
||||
desired directory in the local copy.
|
||||
|
||||
To try this immediately, run a build against the kustomization
|
||||
in the [multibases](multibases/README.md) example. There's
|
||||
one pod in the output:
|
||||
|
||||
<!-- @remoteOverlayBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
target="github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6"
|
||||
test 1 == \
|
||||
$(kustomize build $target | grep dev-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Run against the overlay in that example to get three pods
|
||||
(the overlay combines the dev, staging and prod bases for
|
||||
someone who wants to send them all at the same time):
|
||||
|
||||
<!-- @remoteBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
target="https://github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6"
|
||||
test 3 == \
|
||||
$(kustomize build $target | grep cluster-a-.*-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
The URL can be an archive
|
||||
|
||||
<!-- @remoteBuild -->
|
||||
```
|
||||
target="https://github.com/kustless/kustomize-examples/archive/master.zip//kustomize-examples-master"
|
||||
test 1 == \
|
||||
$(kustomize build $target | grep remote-cm | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Note the kustomize root path inside archive must be appended after `//`.
|
||||
|
||||
A base can be a URL:
|
||||
|
||||
<!-- @createOverlay @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6
|
||||
namePrefix: remote-
|
||||
EOF
|
||||
```
|
||||
|
||||
Build this to confirm that all three pods from the base
|
||||
have the `remote-` prefix.
|
||||
|
||||
<!-- @remoteBases @testAgainstLatestRelease -->
|
||||
```
|
||||
test 3 == \
|
||||
$(kustomize build $DEMO_HOME | grep remote-.*-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
## URL format
|
||||
|
||||
The url should follow
|
||||
[hashicorp/go-getter URL format](https://github.com/hashicorp/go-getter#url-format).
|
||||
|
||||
Note that using `//` in the url will only copy the directory specified by the path
|
||||
after `//`, which means some relative paths, like `../xxx`, may not work. Using `/` to copy
|
||||
entire repo. For more details please see [go-getter documentation](https://github.com/hashicorp/go-getter#subdirectories).
|
||||
|
||||
Note that S3 and GCS are NOT supported to avoid introducing massive dependency.
|
||||
|
||||
Here are some example urls
|
||||
|
||||
<!-- @createOverlay @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
# a repo with a root level kustomization.yaml
|
||||
- github.com/Liujingfang1/mysql
|
||||
# a repo with a root level kustomization.yaml on branch test
|
||||
- github.com/Liujingfang1/mysql?ref=test
|
||||
# a subdirectory in a repo on branch repoUrl2
|
||||
- github.com/Liujingfang1/kustomize/examples/helloWorld?ref=repoUrl2
|
||||
# a subdirectory in a repo on commit `7050a45134e9848fca214ad7e7007e96e5042c03`
|
||||
- github.com/Liujingfang1/kustomize/examples/helloWorld?ref=7050a45134e9848fca214ad7e7007e96e5042c03
|
||||
# a subdirectory in a remote archive
|
||||
- https://github.com/kustless/kustomize-examples/archive/master.zip//kustomize-examples-master
|
||||
EOF
|
||||
```
|
||||
67
examples/replicas.md
Normal file
67
examples/replicas.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Demo: change replicas
|
||||
|
||||
|
||||
Define a place to work:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
Make a `kustomization` containing a deployment resource with replicas
|
||||
|
||||
<!-- @createKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- deployment.yaml
|
||||
replicas:
|
||||
- name: myapp
|
||||
count: 3
|
||||
EOF
|
||||
```
|
||||
|
||||
Declare the deployment resource
|
||||
|
||||
<!-- @createDeployment @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app: myapp
|
||||
name: myapp
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: busybox:1.29.0
|
||||
EOF
|
||||
```
|
||||
|
||||
The `myapp` resource declares an deployment managing a pod running a busybox container.
|
||||
|
||||
|
||||
Now build this `kustomization`
|
||||
<!-- @kustomizeBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
Confirm that this replaces replicas for myapp:
|
||||
|
||||
<!-- @confirmImages @testAgainstLatestRelease -->
|
||||
```
|
||||
test 3 = \
|
||||
$(kustomize build $DEMO_HOME | grep replicas | awk '{print $2}'); \
|
||||
echo $?
|
||||
```
|
||||
221
examples/secretGeneratorPlugin.md
Normal file
221
examples/secretGeneratorPlugin.md
Normal file
@@ -0,0 +1,221 @@
|
||||
[ConfigMaps]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#configmap-v1-core
|
||||
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
[Go plugin]: https://golang.org/pkg/plugin
|
||||
[Secrets]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#secret-v1-core
|
||||
[base64]: https://tools.ietf.org/html/rfc4648#section-4
|
||||
[configuration directory]: https://wiki.archlinux.org/index.php/XDG_Base_Directory#Specification
|
||||
[grpc]: https://grpc.io
|
||||
[tag]: /../../releases
|
||||
[v2.0.3]: /../../releases/tag/v2.0.3
|
||||
[`exec.Command`]: https://golang.org/pkg/os/exec/#Command
|
||||
|
||||
# Generating Secrets
|
||||
|
||||
## What's a Secret?
|
||||
|
||||
Kubernetes [ConfigMaps] and [Secrets] are both
|
||||
key:value maps, but the latter is intended to
|
||||
signal that its values have a sensitive nature -
|
||||
e.g. pass phrases or ssh keys.
|
||||
|
||||
Kubernetes developers work in various ways to hide
|
||||
the information in a Secret more carefully than
|
||||
the information held by ConfigMaps, Deployments,
|
||||
etc.
|
||||
|
||||
## Make a place to work
|
||||
|
||||
<!-- @establishBase @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
## Secret values from local files
|
||||
|
||||
kustomize has three different (builtin) ways to
|
||||
generate a secret from local files:
|
||||
|
||||
* get them from so-called _env_ files (`NAME=VALUE`, one per line),
|
||||
* consume the entire contents of a file to make one secret value,
|
||||
* get literal values from the kustomization file itself.
|
||||
|
||||
Here's an example combining all three methods:
|
||||
|
||||
Make an env file with some short secrets:
|
||||
|
||||
<!-- @makeEnvFile @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/foo.env
|
||||
ROUTER_PASSWORD=admin
|
||||
DB_PASSWORD=iloveyou
|
||||
EOF
|
||||
```
|
||||
|
||||
Make a text file with a long secret:
|
||||
|
||||
<!-- @makeLongSecretFile @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/longsecret.txt
|
||||
Lorem ipsum dolor sit amet,
|
||||
consectetur adipiscing elit,
|
||||
sed do eiusmod tempor incididunt
|
||||
ut labore et dolore magna aliqua.
|
||||
EOF
|
||||
```
|
||||
|
||||
And make a kustomization file referring to the
|
||||
above and _additionally_ defining some literal KV
|
||||
pairs in line:
|
||||
|
||||
<!-- @makeKustomization1 @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
secretGenerator:
|
||||
- name: mysecrets
|
||||
envs:
|
||||
- foo.env
|
||||
files:
|
||||
- longsecret.txt
|
||||
literals:
|
||||
- FRUIT=apple
|
||||
- VEGETABLE=carrot
|
||||
EOF
|
||||
```
|
||||
|
||||
Now generate the Secret:
|
||||
|
||||
<!-- @build1 @testAgainstLatestRelease -->
|
||||
```
|
||||
result=$(kustomize build $DEMO_HOME)
|
||||
echo "$result"
|
||||
# Spot check the result:
|
||||
test 1 == $(echo "$result" | grep -c "FRUIT: YXBwbGU=")
|
||||
```
|
||||
|
||||
This emits something like
|
||||
|
||||
> ```
|
||||
> apiVersion: v1
|
||||
> kind: Secret
|
||||
> metadata:
|
||||
> name: mysecrets-hfb5df789h
|
||||
> type: Opaque
|
||||
> data:
|
||||
> FRUIT: YXBwbGU=
|
||||
> VEGETABLE: Y2Fycm90
|
||||
> ROUTER_PASSWORD: YWRtaW4=
|
||||
> DB_PASSWORD: aWxvdmV5b3U=
|
||||
> longsecret.txt: TG9yZW0gaXBzdW0gZG9sb3Igc2l0I... (elided)
|
||||
> ```
|
||||
|
||||
The name of the resource is the prefix `mysecrets`
|
||||
(as specfied in the kustomization file), followed
|
||||
by a hash of its contents.
|
||||
|
||||
Use your favorite base64 decoder to confirm the raw
|
||||
versions of any of these values.
|
||||
|
||||
The problem that these three approaches share is
|
||||
that the purported secrets must live on disk.
|
||||
|
||||
This adds additional security questions - who can
|
||||
see the files, who installs them, who deletes
|
||||
them, etc.
|
||||
|
||||
|
||||
## Secret values from anywhere
|
||||
|
||||
A general alternative is to enshrine secret
|
||||
value generation in a [plugin](../docs/plugins).
|
||||
|
||||
The values can then come in via, say, an
|
||||
authenticated and authorized RPC to a password
|
||||
vault service.
|
||||
|
||||
[sgp]: ../plugin/someteam.example.com/v1/secretsfromdatabase
|
||||
|
||||
Here's a [secret generator plugin][sgp]
|
||||
that pretends to pull the values of a map
|
||||
from a database.
|
||||
|
||||
|
||||
Download it
|
||||
|
||||
<!-- @copyPlugin @testAgainstLatestRelease -->
|
||||
```
|
||||
repo=https://raw.githubusercontent.com/kubernetes-sigs/kustomize
|
||||
pPath=plugin/someteam.example.com/v1/secretsfromdatabase
|
||||
dir=$DEMO_HOME/kustomize/$pPath
|
||||
|
||||
mkdir -p $dir
|
||||
|
||||
curl -s -o $dir/SecretsFromDatabase.go \
|
||||
${repo}/master/$pPath/SecretsFromDatabase.go
|
||||
```
|
||||
|
||||
Compile it
|
||||
|
||||
<!-- @compilePlugin @xtest -->
|
||||
```
|
||||
go build -buildmode plugin \
|
||||
-o $dir/SecretsFromDatabase.so \
|
||||
$dir/SecretsFromDatabase.go
|
||||
```
|
||||
|
||||
|
||||
Create a configuration file for it:
|
||||
|
||||
<!-- @makeConfiguration @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/secretFromDb.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: SecretsFromDatabase
|
||||
metadata:
|
||||
name: mySecretGenerator
|
||||
name: forbiddenValues
|
||||
namespace: production
|
||||
keys:
|
||||
- ROCKET
|
||||
- VEGETABLE
|
||||
EOF
|
||||
```
|
||||
|
||||
Create a new kustomization file
|
||||
referencing this plugin:
|
||||
|
||||
<!-- @makeKustomization2 @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
generators:
|
||||
- secretFromDb.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Finally, generate the secret, setting
|
||||
`XDG_CONFIG_HOME` so that the plugin
|
||||
can be found under `$DEMO_HOME`:
|
||||
|
||||
<!-- @build2 @xtest -->
|
||||
```
|
||||
result=$( \
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build --enable_alpha_plugins $DEMO_HOME )
|
||||
echo "$result"
|
||||
# Spot check the result:
|
||||
test 1 == $(echo "$result" | grep -c "FRUIT: YXBwbGU=")
|
||||
```
|
||||
|
||||
This should emit something like:
|
||||
|
||||
> ```
|
||||
> apiVersion: v1
|
||||
> kind: Secret
|
||||
> metadata:
|
||||
> name: mysecrets-bdt27dbkd6
|
||||
> type: Opaque
|
||||
> data:
|
||||
> FRUIT: YXBwbGU=
|
||||
> VEGETABLE: Y2Fycm90
|
||||
> ```
|
||||
|
||||
i.e. a subset of the same values as above.
|
||||
@@ -13,7 +13,7 @@ In the production environment we want to customize the following:
|
||||
- health check and readiness check.
|
||||
|
||||
First make a place to work:
|
||||
<!-- @makeDemoHome @test -->
|
||||
<!-- @makeDemoHome @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
@@ -27,7 +27,7 @@ as HERE documents.
|
||||
|
||||
Download them:
|
||||
|
||||
<!-- @downloadResources @test -->
|
||||
<!-- @downloadResources @testAgainstLatestRelease -->
|
||||
```
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
@@ -44,14 +44,14 @@ a file called `kustomization.yaml`.
|
||||
|
||||
Start this file:
|
||||
|
||||
<!-- @kustomizeYaml @test -->
|
||||
<!-- @kustomizeYaml @testAgainstLatestRelease -->
|
||||
```
|
||||
touch $DEMO_HOME/kustomization.yaml
|
||||
```
|
||||
|
||||
### Add the resources
|
||||
|
||||
<!-- @addResources @test -->
|
||||
<!-- @addResources @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
|
||||
@@ -71,7 +71,7 @@ cat kustomization.yaml
|
||||
|
||||
### Add configMap generator
|
||||
|
||||
<!-- @addConfigMap @test -->
|
||||
<!-- @addConfigMap @testAgainstLatestRelease -->
|
||||
```
|
||||
echo "app.name=Kustomize Demo" >$DEMO_HOME/application.properties
|
||||
|
||||
@@ -102,10 +102,10 @@ For Spring Boot application, we can set an active profile through the environmen
|
||||
the application will pick up an extra `application-<profile>.properties` file. With this, we can customize the configMap in two
|
||||
steps. Add an environment variable through the patch and add a file to the configMap.
|
||||
|
||||
<!-- @customizeConfigMap @test -->
|
||||
<!-- @customizeConfigMap @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/patch.yaml
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: sbdemo
|
||||
@@ -119,7 +119,7 @@ spec:
|
||||
value: prod
|
||||
EOF
|
||||
|
||||
kustomize edit add patch patch.yaml
|
||||
kustomize edit add patch --path patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
|
||||
cat <<EOF >$DEMO_HOME/application-prod.properties
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
@@ -149,7 +149,7 @@ Arrange for the resources to begin with prefix
|
||||
_prod-_ (since they are meant for the _production_
|
||||
environment):
|
||||
|
||||
<!-- @customizeLabel @test -->
|
||||
<!-- @customizeLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit set nameprefix 'prod-'
|
||||
@@ -165,7 +165,7 @@ This `namePrefix` directive adds _prod-_ to all
|
||||
resource names, as can be seen by building the
|
||||
resources:
|
||||
|
||||
<!-- @build1 @test -->
|
||||
<!-- @build1 @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME | grep prod-
|
||||
```
|
||||
@@ -180,7 +180,7 @@ selector.
|
||||
add a label, but one can always edit
|
||||
`kustomization.yaml` directly:
|
||||
|
||||
<!-- @customizeLabels @test -->
|
||||
<!-- @customizeLabels @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
commonLabels:
|
||||
@@ -191,7 +191,7 @@ EOF
|
||||
Confirm that the resources now all have names prefixed
|
||||
by `prod-` and the label tuple `env:prod`:
|
||||
|
||||
<!-- @build2 @test -->
|
||||
<!-- @build2 @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME | grep -C 3 env
|
||||
```
|
||||
@@ -205,7 +205,7 @@ set JVM options accordingly.
|
||||
|
||||
Download the patch `memorylimit_patch.yaml`. It contains the memory limits setup.
|
||||
|
||||
<!-- @downloadPatch @test -->
|
||||
<!-- @downloadPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/overlays/production/{memorylimit_patch}.yaml"
|
||||
@@ -216,7 +216,7 @@ cat $DEMO_HOME/memorylimit_patch.yaml
|
||||
The output contains
|
||||
|
||||
> ```
|
||||
> apiVersion: apps/v1beta2
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: sbdemo
|
||||
@@ -243,7 +243,7 @@ has end points such as `/actuator/health` for this. We can customize the k8s dep
|
||||
|
||||
Download the patch `healthcheck_patch.yaml`. It contains the liveness probes and readyness probes.
|
||||
|
||||
<!-- @downloadPatch @test -->
|
||||
<!-- @downloadPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/overlays/production/{healthcheck_patch}.yaml"
|
||||
@@ -254,7 +254,7 @@ cat $DEMO_HOME/healthcheck_patch.yaml
|
||||
The output contains
|
||||
|
||||
> ```
|
||||
> apiVersion: apps/v1beta2
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: sbdemo
|
||||
@@ -281,27 +281,42 @@ The output contains
|
||||
|
||||
Add these patches to the kustomization:
|
||||
|
||||
<!-- @addPatch @test -->
|
||||
<!-- @addPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit add patch memorylimit_patch.yaml
|
||||
kustomize edit add patch healthcheck_patch.yaml
|
||||
kustomize edit add patch --path memorylimit_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
kustomize edit add patch --path healthcheck_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
```
|
||||
|
||||
`kustomization.yaml` should have patches field:
|
||||
|
||||
> ```
|
||||
> patches:
|
||||
> - patch.yaml
|
||||
> - memorylimit_patch.yaml
|
||||
> - healthcheck_patch.yaml
|
||||
> - path: patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: memorylimit_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: healthcheck_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> ```
|
||||
|
||||
The output of the following command can now be applied
|
||||
to the cluster (i.e. piped to `kubectl apply`) to
|
||||
create the production environment.
|
||||
|
||||
<!-- @finalBuild @test -->
|
||||
<!-- @finalBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME # | kubectl apply -f -
|
||||
kustomize build $DEMO_HOME # | kubectl apply -f -
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: sbdemo
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: sbdemo
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
patchesStrategicMerge:
|
||||
- patch.yaml
|
||||
- healthcheck_patch.yaml
|
||||
- memorylimit_patch.yaml
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: sbdemo
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
bases:
|
||||
resources:
|
||||
- ../../base
|
||||
namePrefix: staging-
|
||||
configMapGenerator:
|
||||
|
||||
180
examples/transformerconfigs/README.md
Normal file
180
examples/transformerconfigs/README.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# Transformer Configurations
|
||||
|
||||
Kustomize creates new resources by applying a series of transformations to an original
|
||||
set of resources. Kustomize provides the following default transformers:
|
||||
|
||||
- annotations
|
||||
- images
|
||||
- labels
|
||||
- name reference
|
||||
- namespace
|
||||
- prefix/suffix
|
||||
- variable reference
|
||||
|
||||
A `fieldSpec` list, in a transformer's configuration, determines which resource types and which fields
|
||||
within those types the transformer can modify.
|
||||
|
||||
## FieldSpec
|
||||
|
||||
FieldSpec is a type that represents a path to a field in one kind of resource.
|
||||
|
||||
```yaml
|
||||
group: some-group
|
||||
version: some-version
|
||||
kind: some-kind
|
||||
path: path/to/the/field
|
||||
create: false
|
||||
```
|
||||
|
||||
If `create` is set to `true`, the transformer creates the path to the field in the resource if the path is not already found. This is most useful for label and annotation transformers, where the path for labels or annotations may not be set before the transformation.
|
||||
|
||||
## Images transformer
|
||||
|
||||
The default images transformer updates the specified image key values found in paths that include
|
||||
`containers` and `initcontainers` sub-paths.
|
||||
If found, the `image` key value is customized by the values set in the `newName`, `newTag`, and `digest` fields.
|
||||
The `name` field should match the `image` key value in a resource.
|
||||
|
||||
Example kustomization.yaml:
|
||||
|
||||
```yaml
|
||||
images:
|
||||
- name: postgres
|
||||
newName: my-registry/my-postgres
|
||||
newTag: v1
|
||||
- name: nginx
|
||||
newTag: 1.8.0
|
||||
- name: my-demo-app
|
||||
newName: my-app
|
||||
- name: alpine
|
||||
digest: sha256:25a0d4
|
||||
```
|
||||
|
||||
Image transformer configurations can be customized by creating a list of `images` containing the `path` and `kind` fields.
|
||||
The images transformation tutorial shows how to specify the default images transformer and customize the [images transformer configuration](images/README.md).
|
||||
|
||||
## Prefix/suffix transformer
|
||||
|
||||
The prefix/suffix transformer adds a prefix/suffix to the `metadata/name` field for all resources. Here is the default prefix transformer configuration:
|
||||
|
||||
```yaml
|
||||
namePrefix:
|
||||
- path: metadata/name
|
||||
```
|
||||
|
||||
Example kustomization.yaml:
|
||||
|
||||
```yaml
|
||||
|
||||
namePrefix:
|
||||
alices-
|
||||
|
||||
nameSuffix:
|
||||
-v2
|
||||
```
|
||||
|
||||
## Labels transformer
|
||||
|
||||
The labels transformer adds labels to the `metadata/labels` field for all resources. It also adds labels to the `spec/selector` field in all Service resources as well as the `spec/selector/matchLabels` field in all Deployment resources.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
commonLabels:
|
||||
- path: metadata/labels
|
||||
create: true
|
||||
|
||||
- path: spec/selector
|
||||
create: true
|
||||
version: v1
|
||||
kind: Service
|
||||
|
||||
- path: spec/selector/matchLabels
|
||||
create: true
|
||||
kind: Deployment
|
||||
```
|
||||
|
||||
Example kustomization.yaml:
|
||||
|
||||
```yaml
|
||||
commonLabels:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
```
|
||||
|
||||
## Annotations transformer
|
||||
|
||||
The annotations transformer adds annotations to the `metadata/annotations` field for all resources.
|
||||
Annotations are also added to `spec/template/metadata/annotations` for Deployment,
|
||||
ReplicaSet, DaemonSet, StatefulSet, Job, and CronJob resources, and `spec/jobTemplate/spec/template/metadata/annotations`
|
||||
for CronJob resources.
|
||||
|
||||
Example kustomization.yaml
|
||||
|
||||
```yaml
|
||||
commonAnnotations:
|
||||
oncallPager: 800-555-1212
|
||||
```
|
||||
|
||||
## Name reference transformer
|
||||
|
||||
Name reference transformer's configuration is different from all other transformers. It contains a list of `nameReferences`, which represent all of the possible fields that a type could be used as a reference in other types of resources. A `nameReference` contains a type such as ConfigMap as well as a list of `fieldSpecs` where ConfigMap is referenced in other resources. Here is an example:
|
||||
|
||||
```yaml
|
||||
kind: ConfigMap
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- kind: Pod
|
||||
version: v1
|
||||
path: spec/volumes/configMap/name
|
||||
- kind: Deployment
|
||||
path: spec/template/spec/volumes/configMap/name
|
||||
- kind: Job
|
||||
path: spec/template/spec/volumes/configMap/name
|
||||
```
|
||||
|
||||
Name reference transformer's configuration contains a list of `nameReferences` for resources such as ConfigMap, Secret, Service, Role, and ServiceAccount. Here is an example configuration:
|
||||
|
||||
```yaml
|
||||
nameReference:
|
||||
- kind: ConfigMap
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- path: spec/volumes/configMap/name
|
||||
version: v1
|
||||
kind: Pod
|
||||
- path: spec/containers/env/valueFrom/configMapKeyRef/name
|
||||
version: v1
|
||||
kind: Pod
|
||||
# ...
|
||||
- kind: Secret
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- path: spec/volumes/secret/secretName
|
||||
version: v1
|
||||
kind: Pod
|
||||
- path: spec/containers/env/valueFrom/secretKeyRef/name
|
||||
version: v1
|
||||
kind: Pod
|
||||
```
|
||||
|
||||
## Customizing transformer configurations
|
||||
|
||||
In addition to the default transformers, you can create custom transformer configurations.
|
||||
|
||||
This tutorial shows how to create custom transformer configurations:
|
||||
|
||||
- [support a CRD type](crd/README.md)
|
||||
- add extra fields for variable substitution
|
||||
- add extra fields for name reference
|
||||
|
||||
|
||||
## Supporting escape characters in CRD path
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
annotations:
|
||||
foo.k8s.io/bar: baz
|
||||
```
|
||||
Kustomize supports escaping special characters in path, e.g `metadata/annotations/foo.k8s.io\/bar`
|
||||
139
examples/transformerconfigs/crd/README.md
Normal file
139
examples/transformerconfigs/crd/README.md
Normal file
@@ -0,0 +1,139 @@
|
||||
## Supporting Custom Resources (defined by a CRD)
|
||||
|
||||
This tutorial shows how to add transformer configurations to support a custom resource.
|
||||
|
||||
Create a workspace by
|
||||
<!-- @createws @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
### Adding a custom resource
|
||||
|
||||
Consider a CRD of kind `MyKind` with fields
|
||||
- `.spec.secretRef.name` reference a Secret
|
||||
- `.spec.beeRef.name` reference an instance of CRD `Bee`
|
||||
- `.spec.containers.command` as the list of container commands
|
||||
- `.spec.selectors` as the label selectors
|
||||
|
||||
Add the following file to configure the transformers for the above fields
|
||||
<!-- @addConfig @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir $DEMO_HOME/kustomizeconfig
|
||||
cat > $DEMO_HOME/kustomizeconfig/mykind.yaml << EOF
|
||||
|
||||
commonLabels:
|
||||
- path: spec/selectors
|
||||
create: true
|
||||
kind: MyKind
|
||||
|
||||
nameReference:
|
||||
- kind: Bee
|
||||
fieldSpecs:
|
||||
- path: spec/beeRef/name
|
||||
kind: MyKind
|
||||
- kind: Secret
|
||||
fieldSpecs:
|
||||
- path: spec/secretRef/name
|
||||
kind: MyKind
|
||||
|
||||
varReference:
|
||||
- path: spec/containers/command
|
||||
kind: MyKind
|
||||
- path: spec/beeRef/action
|
||||
kind: MyKind
|
||||
|
||||
EOF
|
||||
```
|
||||
|
||||
### Apply config
|
||||
|
||||
Create a file with some resources that
|
||||
includes an instance of `MyKind`:
|
||||
|
||||
<!-- @createResource @testAgainstLatestRelease -->
|
||||
```
|
||||
cat > $DEMO_HOME/resources.yaml << EOF
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: crdsecret
|
||||
data:
|
||||
PATH: YmJiYmJiYmIK
|
||||
---
|
||||
apiVersion: v1beta1
|
||||
kind: Bee
|
||||
metadata:
|
||||
name: bee
|
||||
spec:
|
||||
action: fly
|
||||
---
|
||||
apiVersion: jingfang.example.com/v1beta1
|
||||
kind: MyKind
|
||||
metadata:
|
||||
name: mykind
|
||||
spec:
|
||||
secretRef:
|
||||
name: crdsecret
|
||||
beeRef:
|
||||
name: bee
|
||||
action: \$(BEE_ACTION)
|
||||
containers:
|
||||
- command:
|
||||
- "echo"
|
||||
- "\$(BEE_ACTION)"
|
||||
image: myapp
|
||||
EOF
|
||||
```
|
||||
|
||||
Create a kustomization referring to it:
|
||||
|
||||
<!-- @createKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat > $DEMO_HOME/kustomization.yaml << EOF
|
||||
resources:
|
||||
- resources.yaml
|
||||
|
||||
namePrefix: test-
|
||||
|
||||
commonLabels:
|
||||
foo: bar
|
||||
|
||||
vars:
|
||||
- name: BEE_ACTION
|
||||
objref:
|
||||
kind: Bee
|
||||
name: bee
|
||||
apiVersion: v1beta1
|
||||
fieldref:
|
||||
fieldpath: spec.action
|
||||
EOF
|
||||
```
|
||||
|
||||
Use the customized transformer configurations by specifying them
|
||||
in the kustomization file:
|
||||
<!-- @addTransformerConfigs @testAgainstLatestRelease -->
|
||||
```
|
||||
cat >> $DEMO_HOME/kustomization.yaml << EOF
|
||||
configurations:
|
||||
- kustomizeconfig/mykind.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Run `kustomize build` and verify that the namereference is correctly resolved.
|
||||
|
||||
<!-- @build @testAgainstLatestRelease -->
|
||||
```
|
||||
test 2 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 2 ".*Ref" | grep "test-" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
Run `kustomize build` and verify that the vars correctly resolved.
|
||||
|
||||
<!-- @verify @testAgainstLatestRelease -->
|
||||
```
|
||||
test 0 == \
|
||||
$(kustomize build $DEMO_HOME | grep "BEE_ACTION" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
16
examples/transformerconfigs/crd/kustomization.yaml
Normal file
16
examples/transformerconfigs/crd/kustomization.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
resources:
|
||||
- resources.yaml
|
||||
|
||||
namePrefix: test-
|
||||
|
||||
commonLabels:
|
||||
foo: bar
|
||||
|
||||
vars:
|
||||
- name: BEE_ACTION
|
||||
objref:
|
||||
kind: Bee
|
||||
name: bee
|
||||
apiVersion: v1beta1
|
||||
fieldref:
|
||||
fieldpath: spec.action
|
||||
29
examples/transformerconfigs/crd/resources.yaml
Normal file
29
examples/transformerconfigs/crd/resources.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: crdsecret
|
||||
data:
|
||||
PATH: YmJiYmJiYmIK
|
||||
---
|
||||
apiVersion: v1beta1
|
||||
kind: Bee
|
||||
metadata:
|
||||
name: bee
|
||||
spec:
|
||||
action: fly
|
||||
---
|
||||
apiVersion: jingfang.example.com/v1beta1
|
||||
kind: MyKind
|
||||
metadata:
|
||||
name: mykind
|
||||
spec:
|
||||
secretRef:
|
||||
name: crdsecret
|
||||
beeRef:
|
||||
name: bee
|
||||
action: $(BEE_ACTION)
|
||||
containers:
|
||||
- command:
|
||||
- "echo"
|
||||
- "$(BEE_ACTION)"
|
||||
image: myapp
|
||||
128
examples/transformerconfigs/images/README.md
Normal file
128
examples/transformerconfigs/images/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
## Images transformations
|
||||
|
||||
This tutorial shows how to modify images in resources, and create a custom images transformer configuration.
|
||||
|
||||
Create a workspace by
|
||||
<!-- @createws @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
### Adding a custom resource
|
||||
|
||||
Consider a Custom Resource Definition(CRD) of kind `MyKind` with field
|
||||
- `.spec.runLatest.container.image` referencing an image
|
||||
|
||||
Add the following file to configure the images transformer for the CRD:
|
||||
|
||||
<!-- @addConfig @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir $DEMO_HOME/kustomizeconfig
|
||||
cat > $DEMO_HOME/kustomizeconfig/mykind.yaml << EOF
|
||||
|
||||
images:
|
||||
- path: spec/runLatest/container/image
|
||||
kind: MyKind
|
||||
EOF
|
||||
```
|
||||
|
||||
### Apply config
|
||||
|
||||
Create a file with some resources that includes an instance of `MyKind`:
|
||||
|
||||
<!-- @createResource @testAgainstLatestRelease -->
|
||||
```
|
||||
cat > $DEMO_HOME/resources.yaml << EOF
|
||||
|
||||
apiVersion: config/v1
|
||||
kind: MyKind
|
||||
metadata:
|
||||
name: testSvc
|
||||
spec:
|
||||
runLatest:
|
||||
container:
|
||||
image: crd-image
|
||||
containers:
|
||||
- image: docker
|
||||
name: ecosystem
|
||||
- image: my-mysql
|
||||
name: testing-1
|
||||
---
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: nginx2
|
||||
image: my-app
|
||||
- name: init-alpine
|
||||
image: alpine:1.8.0
|
||||
EOF
|
||||
```
|
||||
|
||||
Create a kustomization.yaml referring to it:
|
||||
|
||||
<!-- @createKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat > $DEMO_HOME/kustomization.yaml << EOF
|
||||
resources:
|
||||
- resources.yaml
|
||||
|
||||
images:
|
||||
- name: crd-image
|
||||
newName: new-crd-image
|
||||
newTag: new-v1-tag
|
||||
- name: my-app
|
||||
newName: new-app-1
|
||||
newTag: MYNEWTAG-1
|
||||
- name: my-mysql
|
||||
newName: prod-mysql
|
||||
newTag: v3
|
||||
- name: docker
|
||||
newName: my-docker2
|
||||
digest: sha256:25a0d4
|
||||
EOF
|
||||
```
|
||||
|
||||
Use the customized transformer configurations by specifying them
|
||||
in the kustomization file:
|
||||
<!-- @addTransformerConfigs @testAgainstLatestRelease -->
|
||||
```
|
||||
cat >> $DEMO_HOME/kustomization.yaml << EOF
|
||||
configurations:
|
||||
- kustomizeconfig/mykind.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Run `kustomize build` and verify that the images have been updated.
|
||||
|
||||
<!-- @build @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "new-crd-image:new-v1-tag" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
<!-- @build @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "new-app-1:MYNEWTAG-1" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
<!-- @build @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "my-docker2@sha" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
<!-- @build @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 2 ".*image" | grep "prod-mysql:v3" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
19
examples/transformerconfigs/images/kustomization.yaml
Normal file
19
examples/transformerconfigs/images/kustomization.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
resources:
|
||||
- resources.yaml
|
||||
|
||||
configurations:
|
||||
- kustomizeconfig/mykind.yaml
|
||||
|
||||
images:
|
||||
- name: crd-image
|
||||
newName: new-crd-image
|
||||
newTag: new-v1-tag
|
||||
- name: my-app
|
||||
newName: new-app-1
|
||||
newTag: MYNEWTAG-1
|
||||
- name: my-mysql
|
||||
newName: prod-mysql
|
||||
newTag: v3
|
||||
- name: docker
|
||||
newName: my-docker2
|
||||
digest: sha256:25a0d4
|
||||
3
examples/transformerconfigs/images/mykind.yaml
Normal file
3
examples/transformerconfigs/images/mykind.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
images:
|
||||
- path: spec/runLatest/container/image
|
||||
kind: MyKind
|
||||
27
examples/transformerconfigs/images/resources.yaml
Normal file
27
examples/transformerconfigs/images/resources.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
apiVersion: config/v1
|
||||
kind: MyKind
|
||||
metadata:
|
||||
name: testSvc
|
||||
spec:
|
||||
runLatest:
|
||||
container:
|
||||
image: crd-image
|
||||
containers:
|
||||
- image: docker
|
||||
name: ecosystem
|
||||
- image: my-mysql
|
||||
name: testing-1
|
||||
---
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: nginx2
|
||||
image: my-app
|
||||
- name: init-alpine
|
||||
image: alpine:1.8.0
|
||||
221
examples/validationTransformer/README.md
Normal file
221
examples/validationTransformer/README.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# a transformer plugin performing validation
|
||||
|
||||
[base]: ../../docs/glossary.md#base
|
||||
[kubeval]: https://github.com/instrumenta/kubeval
|
||||
[plugin]: ../../docs/plugins
|
||||
|
||||
kustomize doesn't validate either its input or
|
||||
output beyond the validation provided by the
|
||||
marshalling/unmarshalling packages it depends on.
|
||||
|
||||
Another tool, [kubeval], goes beyond this to do
|
||||
k8s aware validation. Here's a usage example:
|
||||
|
||||
```shell
|
||||
$ kubeval my-invalid-rc.yaml
|
||||
The document my-invalid-rc.yaml contains an invalid ReplicationController
|
||||
--> spec.replicas: Invalid type. Expected: integer, given: string
|
||||
```
|
||||
|
||||
One can write a Kustomize transformer [plugin] to
|
||||
run [kubeval] against the resources that have been
|
||||
loaded by Kustomize.
|
||||
|
||||
|
||||
Make a place to work:
|
||||
|
||||
<!-- @makeWorkplace @kubevalTest -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
mkdir -p $DEMO_HOME/valid
|
||||
mkdir -p $DEMO_HOME/invalid
|
||||
PLUGINDIR=$DEMO_HOME/kustomize/plugin/someteam.example.com/v1/validator
|
||||
mkdir -p $PLUGINDIR
|
||||
```
|
||||
|
||||
## write a transformer plugin
|
||||
|
||||
Download the [kubeval] binary depending on the operating system
|
||||
and add it to $PATH.
|
||||
|
||||
<!-- @downloadKubeval @kubevalTest -->
|
||||
```
|
||||
OS=`uname | sed -e 's/Linux/linux/' -e 's/Darwin/darwin/'`
|
||||
wget https://github.com/instrumenta/kubeval/releases/download/0.9.2/kubeval-${OS}-amd64.tar.gz
|
||||
tar xf kubeval-${OS}-amd64.tar.gz
|
||||
export PATH=$PATH:`pwd`
|
||||
```
|
||||
|
||||
Kustomize has the following assumption of a transformer plugin:
|
||||
- The resources are passed to the transformer plugin from stdin.
|
||||
- The configuration file for the transformer plugin is passed in
|
||||
as the first argument.
|
||||
- The working directory of the plugin is the kustomization
|
||||
directory where it is used as a transformer.
|
||||
- The transformed resources are written to stdout by the plugin.
|
||||
- If the return code of the transformer plugin is non zero,
|
||||
Kustomize regards there is an error during the transformation.
|
||||
|
||||
A transformer plugin for the validation can be written as a
|
||||
bash script, which execute the [kubeval] binary and return proper
|
||||
output and exit code.
|
||||
|
||||
<!-- @writePlugin @kubevalTest -->
|
||||
```
|
||||
cat <<'EOF' > $PLUGINDIR/Validator
|
||||
#!/bin/bash
|
||||
|
||||
if ! [ -x "$(command -v kubeval)" ]; then
|
||||
echo "Error: kubeval is not installed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
temp_file=$(mktemp)
|
||||
output_file=$(mktemp)
|
||||
cat - > $temp_file
|
||||
|
||||
kubeval $temp_file > $output_file
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cat $temp_file
|
||||
rm $temp_file $output_file
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cat $output_file
|
||||
rm $temp_file $output_file
|
||||
exit 1
|
||||
|
||||
EOF
|
||||
chmod +x $PLUGINDIR/Validator
|
||||
```
|
||||
|
||||
## use the transformer plugin
|
||||
|
||||
Define a kustomization containing a valid ConfigMap
|
||||
and the transformer plugin.
|
||||
|
||||
<!-- @writeKustomization @kubevalTest -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/valid/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
foo: bar
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/valid/validation.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: Validator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/valid/kustomization.yaml
|
||||
resources:
|
||||
- configmap.yaml
|
||||
|
||||
transformers:
|
||||
- validation.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Define a kustomization containing an invalid ConfigMap
|
||||
and the transformer plugin.
|
||||
|
||||
<!-- @writeKustomization @kubevalTest -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/invalid/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
- foo: bar
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/invalid/validation.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: Validator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/invalid/kustomization.yaml
|
||||
resources:
|
||||
- configmap.yaml
|
||||
|
||||
transformers:
|
||||
- validation.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
The directory structure is as the following:
|
||||
|
||||
```
|
||||
/tmp/tmp.fAYMfLZJs4
|
||||
├── invalid
|
||||
│ ├── configmap.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ └── validation.yaml
|
||||
├── kustomize
|
||||
│ └── plugin
|
||||
│ └── someteam.example.com
|
||||
│ └── v1
|
||||
│ ├── kubeval
|
||||
│ └── Validator
|
||||
└── valid
|
||||
├── configmap.yaml
|
||||
├── kustomization.yaml
|
||||
└── validation.yaml
|
||||
```
|
||||
|
||||
Define a helper function to run kustomize with the
|
||||
correct environment and flags for plugins:
|
||||
|
||||
<!-- @defineKustomizeBd @kubevalTest -->
|
||||
```
|
||||
function kustomizeBd {
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build \
|
||||
--enable_alpha_plugins \
|
||||
$DEMO_HOME/$1
|
||||
}
|
||||
```
|
||||
|
||||
Build the valid variant
|
||||
|
||||
<!-- @buildValid @kubevalTest -->
|
||||
```
|
||||
kustomizeBd valid
|
||||
```
|
||||
The output contains a ConfigMap as
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
```
|
||||
|
||||
Build the invalid variant
|
||||
|
||||
```
|
||||
kustomizeBd invalid
|
||||
```
|
||||
|
||||
The output is an error as
|
||||
```shell
|
||||
data: Invalid type. Expected: object, given: array
|
||||
```
|
||||
|
||||
## cleanup
|
||||
|
||||
<!-- @cleanup @kubevalTest -->
|
||||
```shell
|
||||
rm -rf $DEMO_HOME
|
||||
```
|
||||
6
examples/validationTransformer/invalid.yaml
Normal file
6
examples/validationTransformer/invalid.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
- foo: bar
|
||||
6
examples/validationTransformer/valid.yaml
Normal file
6
examples/validationTransformer/valid.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
foo: bar
|
||||
224
examples/validatorPlugin.md
Normal file
224
examples/validatorPlugin.md
Normal file
@@ -0,0 +1,224 @@
|
||||
# Examples for Validator Plugin
|
||||
|
||||
Previously, Kustomize suggested to used a transformer plugin to [perform validation](https://github.com/kubernetes-sigs/kustomize/tree/master/examples/validationTransformer). Now we introduce a new type of plugin: validator. As the name says, validator is used to validate the result YAML output. It works in the same way with *transformers* but cannot *modify* the input YAML content. Let's take a look at how it works.
|
||||
|
||||
## Make a Place to Work
|
||||
|
||||
<!-- @makeWorkplace @validatorPlugin -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
mkdir -p $DEMO_HOME/valid
|
||||
PLUGINDIR=$DEMO_HOME/kustomize/plugin/someteam.example.com/v1/validator
|
||||
mkdir -p $PLUGINDIR
|
||||
```
|
||||
|
||||
## Write a Validator Plugin
|
||||
|
||||
Kustomize has the following assumption of a validator plugin:
|
||||
- The resources are passed to the validator plugin from stdin.
|
||||
- The configuration file for the validator plugin is passed in
|
||||
as the first argument.
|
||||
- The working directory of the plugin is the kustomization
|
||||
directory where it is used as a validator.
|
||||
- The validated resources are written to stdout by the plugin. Or the validator can print nothing to the stdout if there is no need to change the input.
|
||||
- Validator can **only** add a label named `validated-by` (case-sensitive) to the **top-level** resources. If there is any other modification in the validator, Kustomize will throw an error.
|
||||
- If the return code of the transformer plugin is non zero,
|
||||
Kustomize regards there is an error during the validation.
|
||||
|
||||
You can use either exec plugin or Go plugin as a validator. Here we use a bash script as an exec plugin.
|
||||
|
||||
<!-- @writePlugin @validatorPlugin -->
|
||||
```bash
|
||||
cat <<'EOF' > $PLUGINDIR/Validator
|
||||
#!/bin/bash
|
||||
|
||||
# Do whatever you want here. In this example we
|
||||
# just print out the input
|
||||
|
||||
cat
|
||||
|
||||
EOF
|
||||
chmod +x $PLUGINDIR/Validator
|
||||
```
|
||||
|
||||
## Use the Validator Plugin
|
||||
|
||||
Define a kustomization containing a valid ConfigMap
|
||||
and the transformer plugin.
|
||||
|
||||
<!-- @writeKustomization @validatorPlugin -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/valid/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
foo: bar
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/valid/validator.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: Validator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/valid/kustomization.yaml
|
||||
resources:
|
||||
- configmap.yaml
|
||||
|
||||
validators:
|
||||
- validator.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
The directory structure is as the following:
|
||||
|
||||
```
|
||||
/tmp/tmp.69tTCuXuYc
|
||||
├── kustomize
|
||||
│ └── plugin
|
||||
│ └── someteam.example.com
|
||||
│ └── v1
|
||||
│ └── validator
|
||||
│ └── Validator
|
||||
└── valid
|
||||
├── configmap.yaml
|
||||
├── kustomization.yaml
|
||||
└── validator.yaml
|
||||
```
|
||||
|
||||
Define a helper function to run kustomize with the
|
||||
correct environment and flags for plugins:
|
||||
|
||||
<!-- @defineKustomizeBd @validatorPlugin -->
|
||||
```bash
|
||||
function kustomizeBd {
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build \
|
||||
--enable_alpha_plugins \
|
||||
$DEMO_HOME/$1
|
||||
}
|
||||
```
|
||||
|
||||
Build the valid variant
|
||||
|
||||
<!-- @buildValid @validatorPlugin -->
|
||||
```bash
|
||||
kustomizeBd valid
|
||||
```
|
||||
The output contains a ConfigMap as
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
```
|
||||
|
||||
### Validator Failure
|
||||
|
||||
Now lets try a failed validator
|
||||
|
||||
```bash
|
||||
cat <<'EOF' > $PLUGINDIR/Validator
|
||||
#!/bin/bash
|
||||
|
||||
# Non-zero indicates a failed validation
|
||||
>&2 echo "Validation failed"
|
||||
exit 1
|
||||
|
||||
EOF
|
||||
chmod +x $PLUGINDIR/Validator
|
||||
```
|
||||
|
||||
Build the valid variant
|
||||
|
||||
```bash
|
||||
kustomizeBd valid
|
||||
```
|
||||
The output contains the error information that is printed to stderr
|
||||
by validator.
|
||||
|
||||
```
|
||||
Validation failed
|
||||
Error: failure in plugin configured via /tmp/kust-plugin-config-369137659; exit status 1: exit status 1
|
||||
```
|
||||
|
||||
### Input Modification
|
||||
|
||||
Typically a validator shouldn't modify the content to be validated. If it does, Kustomize will complain about it.
|
||||
|
||||
```bash
|
||||
cat <<'EOF' > $PLUGINDIR/Validator
|
||||
#!/bin/bash
|
||||
|
||||
# Modify the input content
|
||||
|
||||
sed 's/bar/baz/g'
|
||||
|
||||
EOF
|
||||
chmod +x $PLUGINDIR/Validator
|
||||
```
|
||||
|
||||
Then build
|
||||
|
||||
```
|
||||
kustomizeBd valid
|
||||
```
|
||||
|
||||
The error output will indicate you where is modified by the validator
|
||||
|
||||
```
|
||||
Error: validator shouldn't modify the resource map: kunstruct not equal:
|
||||
-- {"apiVersion":"v1","data":{"foo":"bar"},"kind":"ConfigMap","metadata":{"name":"cm"}}{nsfx:false,beh:unspecified},
|
||||
-- {"apiVersion":"v1","data":{"foo":"baz"},"kind":"ConfigMap","metadata":{"name":"cm"}}{nsfx:false,beh:unspecified}
|
||||
|
||||
--
|
||||
&resource.Resource{Kunstructured:(*kunstruct.UnstructAdapter)(0xc000118408), originalName:"cm", originalNs:"", options:(*types.GenArgs)(0xc00059e5e8), refBy:[]resid.ResId(nil), refVarNames:[]string(nil), namePrefixes:[]string{""}, nameSuffixes:[]string{""}}
|
||||
------
|
||||
&resource.Resource{Kunstructured:(*kunstruct.UnstructAdapter)(0xc000118510), originalName:"cm", originalNs:"", options:(*types.GenArgs)(0xc00059e5e8), refBy:[]resid.ResId(nil), refVarNames:[]string(nil), namePrefixes:[]string{""}, nameSuffixes:[]string{""}}
|
||||
```
|
||||
|
||||
There is an exception that the validator can add a `validated-by` label to the **top** level resources.
|
||||
|
||||
<!-- @validatedByLabel @validatorPlugin -->
|
||||
```bash
|
||||
cat <<'EOF' > $PLUGINDIR/Validator
|
||||
#!/usr/bin/bash
|
||||
|
||||
sed 's/^ name: cm$/ name: cm\n labels:\n validated-by: whatever/'
|
||||
|
||||
EOF
|
||||
chmod +x $PLUGINDIR/Validator
|
||||
```
|
||||
|
||||
Then build
|
||||
|
||||
<!-- @validatedByLabelBuild @validatorPlugin -->
|
||||
```
|
||||
kustomizeBd valid
|
||||
```
|
||||
|
||||
The output will be
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
validated-by: whatever
|
||||
name: cm
|
||||
```
|
||||
|
||||
## cleanup
|
||||
|
||||
<!-- @cleanup @validatorPlugin -->
|
||||
```
|
||||
rm -rf $DEMO_HOME
|
||||
```
|
||||
405
examples/valueAdd.md
Normal file
405
examples/valueAdd.md
Normal file
@@ -0,0 +1,405 @@
|
||||
# Simple addition of one string value
|
||||
|
||||
[DRY]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
|
||||
|
||||
Suppose you have several distinct cloud _projects_
|
||||
(on GCP or AWS or whatever) named:
|
||||
|
||||
* cat-111
|
||||
* dog-222
|
||||
* fox-333
|
||||
|
||||
These might be project names within the company,
|
||||
cloud billing identifiers, or both.
|
||||
|
||||
Further suppose
|
||||
|
||||
* You want to deploy these projects to different
|
||||
k8s namespaces, named after the projects.
|
||||
|
||||
* You need to specify the project name
|
||||
in various resource subfields.
|
||||
|
||||
* You want to name the configuration
|
||||
directories using the project name.
|
||||
|
||||
Additionally you might want to deploy the
|
||||
projects one at a time, or all at once.
|
||||
|
||||
Ideally, you'll want to avoid specifying
|
||||
the project name in more than one place
|
||||
(i.e. you want to stay [DRY]).
|
||||
|
||||
Here's a possible layout:
|
||||
|
||||
|
||||
> ```
|
||||
> ├── all
|
||||
> │ └── kustomization.yaml
|
||||
> │
|
||||
> ├── bases
|
||||
> │ └── iam-iap-tunnel
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── policymembers.yaml
|
||||
> │
|
||||
> └── projects
|
||||
> ├── cat-111
|
||||
> │ └── kustomization.yaml
|
||||
> ├── dog-222
|
||||
> │ └── kustomization.yaml
|
||||
> └── fox-333
|
||||
> └── kustomization.yaml
|
||||
> ```
|
||||
|
||||
This layout allows each project to be
|
||||
individually buildable:
|
||||
|
||||
> ```
|
||||
> kustomize build projects/cat-111
|
||||
> kustomize build projects/dog-222
|
||||
> kustomize build projects/fox-333
|
||||
> ```
|
||||
|
||||
or collectively buildable:
|
||||
|
||||
> ```
|
||||
> kustomize build all
|
||||
> ```
|
||||
|
||||
-----
|
||||
Make a place to work:
|
||||
|
||||
<!-- @makePlaceToWork @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
<!-- @defineLayout @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/bases/iam-iap-tunnel
|
||||
mkdir -p $DEMO_HOME/transformers/setProject
|
||||
mkdir -p $DEMO_HOME/projects/cat-111
|
||||
mkdir -p $DEMO_HOME/projects/dog-222
|
||||
mkdir -p $DEMO_HOME/projects/fox-333
|
||||
```
|
||||
|
||||
To ground this example with a common problem,
|
||||
assume a set of engineers:
|
||||
|
||||
* red@example.com
|
||||
* blue@example.com
|
||||
* yellow@example.com
|
||||
|
||||
who need particular access to one or more projects.
|
||||
|
||||
Define an instance of `IAMCustomRole`:
|
||||
|
||||
<!-- @customRole @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/customroles.yaml
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMCustomRole
|
||||
metadata:
|
||||
name: engineer
|
||||
spec:
|
||||
title: Colorful Engineer
|
||||
permissions:
|
||||
- iap.tunnelInstances.accessViaIAP
|
||||
stage: GA
|
||||
EOF
|
||||
```
|
||||
|
||||
Define corresponding instances of `IAMPolicyMember`.
|
||||
|
||||
The values in the `resourceRef/external` fields in these instances
|
||||
are only partially complete. kustomize will add projectIds to
|
||||
these below.
|
||||
|
||||
The boilerplate in these instances could be eliminated
|
||||
by making a _custom generator_, but that's for
|
||||
different tutorial, and with only three instances here
|
||||
it's not worth it the effort.
|
||||
|
||||
<!-- @policyMembers @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/policymembers.yaml
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMPolicyMember
|
||||
metadata:
|
||||
name: iap-tunnel-red
|
||||
spec:
|
||||
member: user:red@example.com
|
||||
role: roles/engineer
|
||||
resourceRef:
|
||||
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
||||
kind: Project
|
||||
external: projects
|
||||
---
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMPolicyMember
|
||||
metadata:
|
||||
name: iap-tunnel-blue
|
||||
spec:
|
||||
member: user:blue@example.com
|
||||
role: roles/engineer
|
||||
resourceRef:
|
||||
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
||||
kind: Project
|
||||
external: projects
|
||||
---
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMPolicyMember
|
||||
metadata:
|
||||
name: iap-tunnel-yellow
|
||||
spec:
|
||||
member: user:yellow@example.com
|
||||
role: roles/engineer
|
||||
resourceRef:
|
||||
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
||||
kind: Project
|
||||
external: projects
|
||||
EOF
|
||||
```
|
||||
|
||||
Make a base that combines these:
|
||||
|
||||
<!-- @makeBase @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/bases/iam-iap-tunnel/kustomization.yaml
|
||||
resources:
|
||||
- customroles.yaml
|
||||
- policymembers.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Make a transformer configuration file.
|
||||
|
||||
The transformer used is called `AddValueTransformer`. It's
|
||||
intended to implement the 'add' operation of
|
||||
[IETF RFC 6902 JSON]. The add operation is simple declaration
|
||||
of what value to add, and a powerful syntax for specifying where
|
||||
to add the value. The value can, for example, be inserted
|
||||
into an existing field holding a file path as either a prefix,
|
||||
a postfix, or some change
|
||||
in the middle (e.g. `/volume/data` becomes `/volume/projectId/data`).
|
||||
|
||||
[IETF RFC 6902 JSON]: https://tools.ietf.org/html/rfc6902
|
||||
|
||||
|
||||
At the time of writing, this transformer has no dedicated keyword
|
||||
in the kustomization file to hold it's config. This means
|
||||
the config must live in its own file:
|
||||
|
||||
<!-- @defineSetProjectTransformer @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/transformers/setProject/setProject.yaml
|
||||
apiVersion: builtin
|
||||
kind: ValueAddTransformer
|
||||
metadata:
|
||||
name: dirNameAdd
|
||||
|
||||
# Omitting the 'value:' field means that the current
|
||||
# kustomization root directory name will be used as
|
||||
# the value.
|
||||
# value: not specified!
|
||||
|
||||
targets:
|
||||
- fieldPath: metadata/namespace
|
||||
- selector:
|
||||
kind: IAMPolicyMember
|
||||
fieldPath: spec/resourceRef/external
|
||||
filePathPosition: 2
|
||||
EOF
|
||||
```
|
||||
|
||||
This file defined both the value to insert, and a list of places to
|
||||
insert it. It's saying 1) _take the name of the directory I am in_ and
|
||||
2) use the name as a namespace on all objects in scope, and 3) add that
|
||||
name to the 2nd position in the file path found in the `spec/resourceRef/external`
|
||||
field of all `IAMPolicyMember` instances.
|
||||
|
||||
|
||||
To be used, this transformer config file must be referenced
|
||||
from some kustomization file's `transformers:` field.
|
||||
|
||||
This field can contain a path directly to the transformer config file,
|
||||
or a path to an encapsulating kustomization root. The latter approach
|
||||
allows any number of transformers to be loaded as a group from a local
|
||||
or remote location.
|
||||
|
||||
Here an example of the latter case that uses a kustomization file to
|
||||
list pointers to transformer configs, although in this case it
|
||||
references only one transformer config.
|
||||
|
||||
<!-- @makeTransformerDir @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/transformers/setProject/kustomization.yaml
|
||||
resources:
|
||||
- setProject.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Now make the _cat_, _dog_ and _fox_ _variants_.
|
||||
|
||||
These are the targets that one could
|
||||
independently apply to a cluster.
|
||||
|
||||
<!-- @defineCat @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/projects/cat-111/kustomization.yaml
|
||||
resources:
|
||||
- ../../bases/iam-iap-tunnel
|
||||
transformers:
|
||||
- ../../transformers/setProject
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- @defineDog @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/projects/dog-222/kustomization.yaml
|
||||
resources:
|
||||
- ../../bases/iam-iap-tunnel
|
||||
transformers:
|
||||
- ../../transformers/setProject
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- @defineFox @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$DEMO_HOME/projects/fox-333/kustomization.yaml
|
||||
resources:
|
||||
- ../../bases/iam-iap-tunnel
|
||||
transformers:
|
||||
- ../../transformers/setProject
|
||||
EOF
|
||||
```
|
||||
|
||||
Then, optionally, a target to deploy all the projects at once:
|
||||
|
||||
<!-- @defineAllTarget @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/all
|
||||
cat <<'EOF' >$DEMO_HOME/all/kustomization.yaml
|
||||
resources:
|
||||
- ../projects/cat-111
|
||||
- ../projects/dog-222
|
||||
- ../projects/fox-333
|
||||
EOF
|
||||
```
|
||||
|
||||
The layout is now:
|
||||
|
||||
<!-- @showLayout -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
It should look like:
|
||||
|
||||
> ```
|
||||
> /tmp/someTmpDir
|
||||
> ├── all
|
||||
> │ └── kustomization.yaml
|
||||
> ├── bases
|
||||
> │ └── iam-iap-tunnel
|
||||
> │ ├── customroles.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── policymembers.yaml
|
||||
> ├── projects
|
||||
> │ ├── cat-111
|
||||
> │ │ └── kustomization.yaml
|
||||
> │ ├── dog-222
|
||||
> │ │ └── kustomization.yaml
|
||||
> │ └── fox-333
|
||||
> │ └── kustomization.yaml
|
||||
> └── transformers
|
||||
> └── setProject
|
||||
> ├── kustomization.yaml
|
||||
> └── setProject.yaml
|
||||
> ```
|
||||
|
||||
The expected output from building the dog project
|
||||
is as follows:
|
||||
|
||||
<!-- @definedExpectedOutput @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/out_expected.yaml
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMCustomRole
|
||||
metadata:
|
||||
name: engineer
|
||||
namespace: dog-222
|
||||
spec:
|
||||
permissions:
|
||||
- iap.tunnelInstances.accessViaIAP
|
||||
stage: GA
|
||||
title: Colorful Engineer
|
||||
---
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMPolicyMember
|
||||
metadata:
|
||||
name: iap-tunnel-blue
|
||||
namespace: dog-222
|
||||
spec:
|
||||
member: user:blue@example.com
|
||||
resourceRef:
|
||||
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
||||
external: projects/dog-222
|
||||
kind: Project
|
||||
role: roles/engineer
|
||||
---
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMPolicyMember
|
||||
metadata:
|
||||
name: iap-tunnel-red
|
||||
namespace: dog-222
|
||||
spec:
|
||||
member: user:red@example.com
|
||||
resourceRef:
|
||||
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
||||
external: projects/dog-222
|
||||
kind: Project
|
||||
role: roles/engineer
|
||||
---
|
||||
apiVersion: iam.cnrm.cloud.google.com/v1beta1
|
||||
kind: IAMPolicyMember
|
||||
metadata:
|
||||
name: iap-tunnel-yellow
|
||||
namespace: dog-222
|
||||
spec:
|
||||
member: user:yellow@example.com
|
||||
resourceRef:
|
||||
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
|
||||
external: projects/dog-222
|
||||
kind: Project
|
||||
role: roles/engineer
|
||||
EOF
|
||||
```
|
||||
|
||||
In this output, the namespace of all instances is the
|
||||
project name `dog-222`, and the project name also appears
|
||||
in the resourceRef field of the `IAMPolicyMember` instances.
|
||||
|
||||
This project name only appears in the project _directory name_,
|
||||
achieving our [DRY] goal.
|
||||
|
||||
Run the build:
|
||||
|
||||
<!-- @runIt @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME/projects/dog-222 >$DEMO_HOME/out_actual.yaml
|
||||
```
|
||||
|
||||
and confirm that the actual output matches the expected output:
|
||||
|
||||
<!-- @diffShouldExitZero @testAgainstLatestRelease -->
|
||||
```
|
||||
diff $DEMO_HOME/out_actual.yaml $DEMO_HOME/out_expected.yaml
|
||||
```
|
||||
|
||||
Build all the projects at once like this:
|
||||
|
||||
<!-- @buildAll @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME/all
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# Demo: Injecting k8s runtime data into containers
|
||||
|
||||
In this tutorial, you will learn how to use `kustomize` to declare a variable reference and substitute it in container's command.
|
||||
In this tutorial, you will learn how to use `kustomize` to declare a variable reference and substitute it in container's command. Note that, the substitution is not for arbitrary fields, it is only applicable to container env, args and command.
|
||||
|
||||
To run WordPress, it's necessary to
|
||||
|
||||
@@ -8,7 +8,7 @@ To run WordPress, it's necessary to
|
||||
- access the service name of MySQL database from WordPress container
|
||||
|
||||
First make a place to work:
|
||||
<!-- @makeDemoHome @test -->
|
||||
<!-- @makeDemoHome @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
MYSQL_HOME=$DEMO_HOME/mysql
|
||||
@@ -21,7 +21,7 @@ mkdir -p $WORDPRESS_HOME
|
||||
|
||||
Download the resources and `kustomization.yaml` for WordPress.
|
||||
|
||||
<!-- @downloadResources @test -->
|
||||
<!-- @downloadResources @testAgainstLatestRelease -->
|
||||
```
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
@@ -33,7 +33,7 @@ curl -s -o "$WORDPRESS_HOME/#1.yaml" \
|
||||
|
||||
Download the resources and `kustomization.yaml` for MySQL.
|
||||
|
||||
<!-- @downloadResources @test -->
|
||||
<!-- @downloadResources @testAgainstLatestRelease -->
|
||||
```
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
@@ -44,15 +44,19 @@ curl -s -o "$MYSQL_HOME/#1.yaml" \
|
||||
```
|
||||
|
||||
### Create kustomization.yaml
|
||||
Create a new kustomization with two bases:
|
||||
|
||||
<!-- @createKustomization @test -->
|
||||
Create a new kustomization with two bases,
|
||||
`wordpress` and `mysql`:
|
||||
|
||||
<!-- @createKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
bases:
|
||||
- wordpress
|
||||
- mysql
|
||||
resources:
|
||||
- wordpress
|
||||
- mysql
|
||||
namePrefix: demo-
|
||||
patchesStrategicMerge:
|
||||
- patch.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
@@ -61,18 +65,18 @@ In the new kustomization, apply a patch for wordpress deployment. The patch does
|
||||
- Add an initial container to show the mysql service name
|
||||
- Add environment variable that allow wordpress to find the mysql database
|
||||
|
||||
<!-- @downloadPatch @test -->
|
||||
<!-- @downloadPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/patch.yaml"
|
||||
/master/examples/wordpress"
|
||||
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/{patch}.yaml"
|
||||
```
|
||||
The patch has following content
|
||||
> ```
|
||||
> apiVersion: apps/v1beta2
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: wordpress
|
||||
@@ -82,9 +86,8 @@ The patch has following content
|
||||
> initContainers:
|
||||
> - name: init-command
|
||||
> image: debian
|
||||
> command:
|
||||
> - "echo $(WORDPRESS_SERVICE)"
|
||||
> - "echo $(MYSQL_SERVICE)"
|
||||
> command: ["/bin/sh"]
|
||||
> args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
|
||||
> containers:
|
||||
> - name: wordpress
|
||||
> env:
|
||||
@@ -101,7 +104,7 @@ $(WORDPRESS_SERVICE) and $(MYSQL_SERVICE).
|
||||
|
||||
### Bind the Variables to k8s Object Fields
|
||||
|
||||
<!-- @addVarRef @test -->
|
||||
<!-- @addVarRef @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
vars:
|
||||
@@ -124,7 +127,7 @@ EOF
|
||||
### Substitution
|
||||
Confirm the variable substitution:
|
||||
|
||||
<!-- @kustomizeBuild @test -->
|
||||
<!-- @kustomizeBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
@@ -134,11 +137,13 @@ Expect this in the output:
|
||||
> ```
|
||||
> (truncated)
|
||||
> ...
|
||||
> initContainers:
|
||||
> - command:
|
||||
> - echo demo-wordpress
|
||||
> - echo demo-mysql
|
||||
> image: debian
|
||||
> name: init-command
|
||||
> initContainers:
|
||||
> - args:
|
||||
> - -c
|
||||
> - echo demo-wordpress; echo demo-mysql
|
||||
> command:
|
||||
> - /bin/sh
|
||||
> image: debian
|
||||
> name: init-command
|
||||
>
|
||||
> ```
|
||||
> ```
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
bases:
|
||||
- wordpress
|
||||
- mysql
|
||||
patches:
|
||||
- patch.yaml
|
||||
resources:
|
||||
- wordpress
|
||||
- mysql
|
||||
patchesStrategicMerge:
|
||||
- patch.yaml
|
||||
namePrefix: demo-
|
||||
|
||||
vars:
|
||||
- name: WORDPRESS_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: wordpress
|
||||
apiVersion: v1
|
||||
- name: MYSQL_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: mysql
|
||||
apiVersion: v1
|
||||
- name: WORDPRESS_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: wordpress
|
||||
apiVersion: v1
|
||||
- name: MYSQL_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: mysql
|
||||
apiVersion: v1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2
|
||||
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mysql
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wordpress
|
||||
@@ -8,9 +8,8 @@ spec:
|
||||
initContainers:
|
||||
- name: init-command
|
||||
image: debian
|
||||
command:
|
||||
- "echo $(WORDPRESS_SERVICE)"
|
||||
- "echo $(MYSQL_SERVICE)"
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
|
||||
containers:
|
||||
- name: wordpress
|
||||
env:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2
|
||||
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wordpress
|
||||
|
||||
61
examples/zh/README.md
Normal file
61
examples/zh/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
[English](../README.md) | 简体中文
|
||||
|
||||
# 示例
|
||||
|
||||
这些示例默认 `kustomize` 在您的 `$PATH` 中。
|
||||
|
||||
这些示例通过了 [pre-commit](../../hack/testExamplesAgainstKustomize.sh) 测试,并且应该与 HEAD 一起使用。
|
||||
|
||||
```
|
||||
go get sigs.k8s.io/kustomize/v3/cmd/kustomize
|
||||
```
|
||||
|
||||
基本用法
|
||||
|
||||
* [configGenerations](configGeneration.md) - 当 ConfigMapGenerator 修改时进行滚动更新。
|
||||
|
||||
* [combineConfigs](combineConfigs.md) - 融合来自不同用户的配置数据(例如来自 devops/SRE 和 developers)。
|
||||
|
||||
* [generatorOptions](generatorOptions.md) -修改所有 ConfigMapGenerator 和 SecretGenerator 的行为。
|
||||
|
||||
* [vars](vars.md) - 通过 vars 将一个资源的数据注入另一个资源的容器参数 (例如,为 wordpress 指定 SQL 服务)。
|
||||
|
||||
* [image names and tags](image.md) - 在不使用 patch 的情况下更新镜像名称和标签。
|
||||
|
||||
* [remote target](remoteBuild.md) - 通过 github URL 来构建 kustomization 。
|
||||
|
||||
* [json patch](jsonpatch.md) -在 kustomization 中应用 json patch 。
|
||||
|
||||
* [patch multiple objects](patchMultipleObjects.md) - 通过一个patch来修改多个资源。
|
||||
|
||||
高级用法
|
||||
|
||||
- generator 插件:
|
||||
|
||||
* [last mile helm](chart.md) - 对 helm chart 进行 last mile 修改。
|
||||
|
||||
* [secret generation](secretGeneratorPlugin.md) - 生成 Secret。
|
||||
|
||||
- transformer 插件:
|
||||
|
||||
* [validation transformer](validationTransformer.md) - 通过 transformer 验证资源。
|
||||
|
||||
- 定制内建 transformer 配置
|
||||
|
||||
* [transformer configs](transformerconfigs.md) - 自定义 transformer 配置。
|
||||
|
||||
多 Variant 示例
|
||||
|
||||
* [hello world](helloWorld.md) - 部署多个不同配置的 Hello World 服务。
|
||||
|
||||
* [LDAP](ldap.md) - 部署多个配置不同的 LDAP 服务。
|
||||
|
||||
* [springboot](springboot.md) - 从头开始创建一个 Spring Boot 项目的生产配置。
|
||||
|
||||
* [mySql](mysql.md) - 从头开始创建一个 MySQL 的生产配置。
|
||||
|
||||
* [breakfast](breakfast.md) - 给 Alice 和 Bob 定制一顿早餐 :)
|
||||
|
||||
* [multibases](multibases.md) - 使用相同的 base 生成三个 variants(dev,staging,production)。
|
||||
|
||||
>声明:部分文档可能稍微滞后于英文版本,同步工作持续进行中
|
||||
118
examples/zh/breakfast.md
Normal file
118
examples/zh/breakfast.md
Normal file
@@ -0,0 +1,118 @@
|
||||
[kubernetes API 对象样式]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
|
||||
[variant]: ../../docs/glossary.md#variant
|
||||
|
||||
# 示例:早餐配置
|
||||
|
||||
定义一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
创建目录用于存放早餐的 base 配置:
|
||||
|
||||
<!-- @baseDir @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/breakfast/base
|
||||
```
|
||||
|
||||
创建一个 `kustomization` 来定义早餐所需的食物。包含咖啡和薄煎饼:
|
||||
|
||||
<!-- @baseKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/breakfast/base/kustomization.yaml
|
||||
resources:
|
||||
- coffee.yaml
|
||||
- pancakes.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
这里有一个 _coffee_ 类型。定义`kind`和 `metdata/name` 字段以符合 [kubernetes API 对象样式],不需要其他文件或定义:
|
||||
|
||||
<!-- @coffee @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/breakfast/base/coffee.yaml
|
||||
kind: Coffee
|
||||
metadata:
|
||||
name: morningCup
|
||||
temperature: lukewarm
|
||||
data:
|
||||
greeting: "Good Morning!"
|
||||
EOF
|
||||
```
|
||||
|
||||
`name` 字段仅将这种咖啡实例与其他实例(如果有的话)区分开
|
||||
|
||||
同样,定义 _pancakes_:
|
||||
<!-- @pancakes @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/breakfast/base/pancakes.yaml
|
||||
kind: Pancakes
|
||||
metadata:
|
||||
name: comfort
|
||||
stacksize: 3
|
||||
topping: none
|
||||
EOF
|
||||
```
|
||||
|
||||
为喜欢热咖啡的 Alice 定制她的早餐:
|
||||
|
||||
<!-- @aliceOverlay @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/breakfast/overlays/alice
|
||||
|
||||
cat <<EOF >$DEMO_HOME/breakfast/overlays/alice/kustomization.yaml
|
||||
commonLabels:
|
||||
who: alice
|
||||
resources:
|
||||
- ../../base
|
||||
patchesStrategicMerge:
|
||||
- temperature.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEMO_HOME/breakfast/overlays/alice/temperature.yaml
|
||||
kind: Coffee
|
||||
metadata:
|
||||
name: morningCup
|
||||
temperature: hot!
|
||||
EOF
|
||||
```
|
||||
|
||||
同样的,Bob 想要 _5_ 块薄煎饼和草莓:
|
||||
|
||||
<!-- @bobOverlay @testAgainstLatestRelease -->
|
||||
```
|
||||
mkdir -p $DEMO_HOME/breakfast/overlays/bob
|
||||
|
||||
cat <<EOF >$DEMO_HOME/breakfast/overlays/bob/kustomization.yaml
|
||||
commonLabels:
|
||||
who: bob
|
||||
resources:
|
||||
- ../../base
|
||||
patchesStrategicMerge:
|
||||
- topping.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEMO_HOME/breakfast/overlays/bob/topping.yaml
|
||||
kind: Pancakes
|
||||
metadata:
|
||||
name: comfort
|
||||
stacksize: 5
|
||||
topping: strawberries
|
||||
EOF
|
||||
```
|
||||
|
||||
现在,可以为 Alice 的早餐生成配置了:
|
||||
|
||||
<!-- @generateAlice @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME/breakfast/overlays/alice
|
||||
```
|
||||
|
||||
同样的,也为 Bob 的早餐生成配置:
|
||||
|
||||
<!-- @generateBob @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME/breakfast/overlays/bob
|
||||
```
|
||||
215
examples/zh/chart.md
Normal file
215
examples/zh/chart.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# 使用 kustomize 对 helm charts 进行修改
|
||||
|
||||
[last mile]: https://testingclouds.wordpress.com/2018/07/20/844/
|
||||
[stable chart]: https://github.com/helm/charts/tree/master/stable
|
||||
[Helm charts]: https://github.com/helm/charts
|
||||
[_minecraft_]: https://github.com/helm/charts/tree/master/stable/minecraft
|
||||
[插件]: ../../docs/plugins
|
||||
|
||||
kustomize 并不会读取 [Helm charts] ,但可以使用 generator 来访问 [Helm charts] 。
|
||||
|
||||
使用 [last mile] 模式来结合 kustomize 和 helm ,使用一个 inflated chart 作为基础,然后使用 kustomize 在部署到集群的途中进行修改。
|
||||
|
||||
以下示例中使用的 generator 仅适用于 [stable chart] 仓库中的 chart。该示例虽然使用 [_minecraft_] ,但可以应用于任何 chart。
|
||||
|
||||
假设 `helm` 已在你的 `$PATH` 中,建立一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
mkdir -p $DEMO_HOME/base
|
||||
mkdir -p $DEMO_HOME/dev
|
||||
mkdir -p $DEMO_HOME/prod
|
||||
```
|
||||
|
||||
## 使用远程 chart
|
||||
|
||||
定义 _development_ variant(环境)。
|
||||
|
||||
这可能涉及许多 kustomizations(参见其他示例),但在本示例中,将 `dev-` 名称前缀添加到所有资源:
|
||||
|
||||
<!-- @writeKustDev @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/dev/kustomization.yaml
|
||||
namePrefix: dev-
|
||||
resources:
|
||||
- ../base
|
||||
EOF
|
||||
```
|
||||
|
||||
同上,使用 `namePrefix: prod-` 定义生产 variant :
|
||||
|
||||
<!-- @writeKustProd @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/prod/kustomization.yaml
|
||||
namePrefix: prod-
|
||||
resources:
|
||||
- ../base
|
||||
EOF
|
||||
```
|
||||
|
||||
这两个 variants 指向同一个 base。
|
||||
|
||||
定义这个 base:
|
||||
|
||||
<!-- @writeKustDev @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/base/kustomization.yaml
|
||||
generators:
|
||||
- chartInflator.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
base 指向一个名为 `chartInflator.yaml` 的生成配置文件。
|
||||
|
||||
此文件允许指定 [stable chart] 的名称及其他内容,例如 values 文件的路径,默认为 `values.yaml` 。
|
||||
|
||||
创建配置文件 `chartInflator.yaml`,指定 chart 名称为 _minecraft_:
|
||||
|
||||
<!-- @writeGeneratorConfig @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/base/chartInflator.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: ChartInflator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
chartName: minecraft
|
||||
EOF
|
||||
```
|
||||
|
||||
因为这个特定的 YAML 文件列在 kustomization文件的 `generators:` 字段中,所以它被视为生成器插件(由 _apiVersion_ 和 _kind_ 字段标识)与配置插件的其他字段之间的绑定。
|
||||
|
||||
将插件下载到 `DEMO_HOME` 并赋予其执行权限:
|
||||
|
||||
<!-- @installPlugin @test -->
|
||||
```bash
|
||||
plugin=plugin/someteam.example.com/v1/chartinflator/ChartInflator
|
||||
curl -s --create-dirs -o \
|
||||
"$DEMO_HOME/kustomize/$plugin" \
|
||||
"https://raw.githubusercontent.com/\
|
||||
kubernetes-sigs/kustomize/master/$plugin"
|
||||
|
||||
chmod a+x $DEMO_HOME/kustomize/$plugin
|
||||
```
|
||||
|
||||
检查目录布局:
|
||||
|
||||
<!-- @tree -->
|
||||
```bash
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
将会得倒类似的目录及文件:
|
||||
|
||||
> ```bash
|
||||
> /tmp/whatever
|
||||
> ├── base
|
||||
> │ ├── chartInflator.yaml
|
||||
> │ └── kustomization.yaml
|
||||
> ├── dev
|
||||
> │ └── kustomization.yaml
|
||||
> ├── kustomize
|
||||
> │ └── plugin
|
||||
> │ └── someteam.example.com
|
||||
> │ └── v1
|
||||
> │ └── chartinflator
|
||||
> │ └── ChartInflator
|
||||
> └── prod
|
||||
> └── kustomization.yaml
|
||||
> ```
|
||||
|
||||
运行 kustomize 定义一个 helper function 来传入正确的环境和常见标志:
|
||||
|
||||
<!-- @defineKustomizeIt @test -->
|
||||
```
|
||||
function kustomizeIt {
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build --enable_alpha_plugins \
|
||||
$DEMO_HOME/$1
|
||||
}
|
||||
```
|
||||
|
||||
最终构建 `prod` variant。这里要注意的是,所有资源名称现在都具有 `prod-` 前缀:
|
||||
|
||||
<!-- @doProd @test -->
|
||||
```bash
|
||||
clear
|
||||
kustomizeIt prod
|
||||
```
|
||||
|
||||
比较 `dev` 和 `prod`:
|
||||
|
||||
<!-- @doCompare -->
|
||||
```bash
|
||||
diff <(kustomizeIt dev) <(kustomizeIt prod) | more
|
||||
```
|
||||
|
||||
在 base上 运行 kustomize 查看未修改但已展开的 chart。
|
||||
这里的每次调用都是重新下载并重新展开 chart。
|
||||
|
||||
<!-- @showBase @test -->
|
||||
```bash
|
||||
kustomizeIt base
|
||||
```
|
||||
|
||||
## 使用本地 chart
|
||||
|
||||
上面的示例由于未在配置中指定本地 chart 的主目录,所以kustomize会取得远程chart的副本并存在临时目录中。
|
||||
|
||||
要禁止 fetch,请明确指定 `charHome` ,并确保chart 已经被保存在该目录下
|
||||
|
||||
要进行演示,并且不会干扰您现有的 helm 环境,请执行以下操作:
|
||||
|
||||
<!-- @helmInit @test -->
|
||||
```bash
|
||||
helmHome=$DEMO_HOME/dothelm
|
||||
chartHome=$DEMO_HOME/base/charts
|
||||
|
||||
function doHelm {
|
||||
helm --home $helmHome $@
|
||||
}
|
||||
|
||||
# 在新位置创建 helm 配置文件。
|
||||
# 初始化命令比较复杂
|
||||
doHelm init --client-only >& /dev/null
|
||||
```
|
||||
|
||||
现在下载 chart ; 可以再次使用的 [_minecraft_] (也可以使用其他的 chart ):
|
||||
|
||||
<!-- @fetchChart @test -->
|
||||
```bash
|
||||
doHelm fetch --untar \
|
||||
--untardir $chartHome \
|
||||
stable/minecraft
|
||||
```
|
||||
|
||||
使用 tree 查看更多信息;helm 配置数据和完整的 chart 副本:
|
||||
|
||||
<!-- @tree -->
|
||||
```bash
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
将 `chartHome` 字段添加到生成器的配置文件中,以便可以查找本地 chart:
|
||||
|
||||
<!-- @modifyGenConfig @test -->
|
||||
```bash
|
||||
echo "chartHome: $chartHome" >>$DEMO_HOME/base/chartInflator.yaml
|
||||
```
|
||||
|
||||
更改 values 文件,用来展示本地 chart 的更改:
|
||||
|
||||
<!-- @valueChange @test -->
|
||||
```
|
||||
sed -i 's/CHANGEME!/SOMETHINGELSE/' $chartHome/minecraft/values.yaml
|
||||
sed -i 's/LoadBalancer/NodePort/' $chartHome/minecraft/values.yaml
|
||||
```
|
||||
|
||||
最后进行构建:
|
||||
|
||||
<!-- @finalProd @test -->
|
||||
```bash
|
||||
kustomizeIt prod
|
||||
```
|
||||
|
||||
观察结果中 `LoadBalancer` 变为 `NodePort`,并且加密的密码也有所不同。
|
||||
230
examples/zh/combineConfigs.md
Normal file
230
examples/zh/combineConfigs.md
Normal file
@@ -0,0 +1,230 @@
|
||||
[overlay]: ../docs/glossary.md#overlay
|
||||
[target]: ../docs/glossary.md#target
|
||||
|
||||
# 示例:devops和开发配合管理配置数据
|
||||
|
||||
场景:在生产环境中有一个基于 Java 由多个内部团队(注册、结账和搜索等)共同开发的商店服务。
|
||||
|
||||
这个服务在不同的环境中运行:_development_、 _testing_、 _staging_ 和 _production_,从 Java 的 properties 文件中读取配置。
|
||||
|
||||
为每个环境维护一个大的 properties 文件是很困难的。这个文件需要频繁的修改,并且这些修改都需要由 devops 工程师来进行,因为:
|
||||
|
||||
1. 这个文件包含 devops 工程师需要知道,而开发人员不必知道的值
|
||||
2. 比如生产环境的 properties 包含敏感数据,比如生产数据库的登录凭据。
|
||||
|
||||
## Property sharding
|
||||
|
||||
通过一些研究,我们注意到属性可以分为不同的类别。
|
||||
|
||||
### Property sharding
|
||||
|
||||
例如:国际化数据、物理常量,外部服务位置等静态数据。
|
||||
|
||||
_这些无论哪个环境,都一样的配置。_
|
||||
|
||||
这些都只需要一组配置。将这组配置放在一个文件中:
|
||||
|
||||
* `common.properties`
|
||||
|
||||
### Plumbing properties
|
||||
|
||||
例如:静态资源(HTML、CSS、JavaScript)的位置,产品和用户的数据表,负载均衡的端口,日志收集等。
|
||||
|
||||
_这些属性的不同,恰恰是环境的不同之处。_
|
||||
|
||||
DevOps 或 SRE 工程师需要完全控制生产环境中的这些配置;测试需要调整数据库来支持测试;而开发则希望尝试开发中遇到的各种不同的情景。
|
||||
|
||||
将这些值放入
|
||||
|
||||
* `development/plumbing.properties`
|
||||
* `staging/plumbing.properties`
|
||||
* `production/plumbing.properties`
|
||||
|
||||
|
||||
### Secret properties
|
||||
|
||||
例如:用户表的位置、数据库凭证、解密密钥等。
|
||||
|
||||
_这些需要 devops 工程师控制,其他人没有访问权限。_
|
||||
|
||||
将这些值放入
|
||||
|
||||
* `development/secret.properties`
|
||||
* `staging/secret.properties`
|
||||
* `production/secret.properties`
|
||||
|
||||
[kubernetes secret]: https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/
|
||||
|
||||
例如使用 unix 文件权限和模式来限制访问控制,或者使用更好的方法-使用专门用于存储密码的服务,并且使用 kustomize 中的 `secretGenerator` 字段在 Kubernetes 中创建 secret 来存储密码。
|
||||
|
||||
<!--
|
||||
secretGenerator:
|
||||
- name: app-tls
|
||||
files:
|
||||
tls.crt=tls.cert
|
||||
tls.key=tls.key
|
||||
type: "kubernetes.io/tls"
|
||||
EOF
|
||||
-->
|
||||
|
||||
## 混合管理方法
|
||||
|
||||
基于相同的 base 创建 _n_ 个 overlays 来创建 _n_ 个集群环境的方法。
|
||||
|
||||
在本例的其余部分,我们将使用 _n==2_,这里只使用 _development_ 和 _production_ ,可以使用相同的方法来增加更多的环境。
|
||||
|
||||
运行 `kustomize build` 基于 [overlay] 的 [target] 来创建集群环境。
|
||||
|
||||
[helloworld]: helloWorld.md
|
||||
|
||||
以下示例将执行此操作,但将侧重于 configMap 构建,而不用担心如何将 configMaps 关联到 Deployment([helloworld] 示例中介绍的)。
|
||||
|
||||
所有文件(包括共享 property 文件)都将在目录树中创建,目录中包含 base 和 overlay 文件的目录,这些都与 [helloworld] 中演示的一致。
|
||||
|
||||
它将全部存在于此工作目录中:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
### 创建 base
|
||||
|
||||
<!-- kubectl create configmap BOB --dry-run -o yaml --from-file db. -->
|
||||
|
||||
创建放置 base 配置的路径:
|
||||
|
||||
<!-- @baseDir @test -->
|
||||
```bash
|
||||
mkdir -p $DEMO_HOME/base
|
||||
```
|
||||
|
||||
向 base 中的插入数据,base 中应该包含所有环境共有的资源,这里我们只定义一个 java properties 文件,以及一个引用他们的 `kustomization` 文件。
|
||||
|
||||
<!-- @baseKustomization @test -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/base/common.properties
|
||||
color=blue
|
||||
height=10m
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEMO_HOME/base/kustomization.yaml
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
files:
|
||||
- common.properties
|
||||
EOF
|
||||
```
|
||||
|
||||
### 创建并使用 overlay 用于 _开发_
|
||||
|
||||
创建一个 overlays 目录:
|
||||
|
||||
<!-- @overlays @test -->
|
||||
```bash
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
```
|
||||
|
||||
创建 _development_ overlay:
|
||||
|
||||
<!-- @developmentFiles @test -->
|
||||
```bash
|
||||
mkdir -p $OVERLAYS/development
|
||||
|
||||
cat <<EOF >$OVERLAYS/development/plumbing.properties
|
||||
port=30000
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/development/secret.properties
|
||||
dbpassword=mothersMaidenName
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/development/kustomization.yaml
|
||||
resources:
|
||||
- ../../base
|
||||
namePrefix: dev-
|
||||
nameSuffix: -v1
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
files:
|
||||
- plumbing.properties
|
||||
- secret.properties
|
||||
EOF
|
||||
```
|
||||
|
||||
现在可以生成开发使用的 configMaps :
|
||||
|
||||
<!-- @runDev @test -->
|
||||
```bash
|
||||
kustomize build $OVERLAYS/development
|
||||
```
|
||||
|
||||
#### 检查 ConfigMap 名称
|
||||
|
||||
可以在输出中看到生成的 `ConfigMap` 名称。
|
||||
|
||||
名称应该是这样的:`dev-my-configmap-v1-2gccmccgd5`:
|
||||
|
||||
* `"dev-"` 来自 `namePrefix` 字段
|
||||
* `"my-configmap"` 来自 `configMapGenerator/name` 字段
|
||||
* `"-v1"` 来自 `nameSuffix` 字段
|
||||
* `"-2gccmccgd5"` 为哈希值,是 `kustomize` 根据 configMap 的内容计算的
|
||||
|
||||
哈希后缀很关键,如果 configMap 内容发生变化, configMap 的名称也会发生变化,以及从 `kustomize` 出现在 YAML 输出中的对该名称的所有引用。
|
||||
|
||||
名称更改意味着如果使用类似命令将此 YAML 应用于群集,则 Deployment 将执行滚动更新重启以获取新数据。
|
||||
|
||||
> ```bash
|
||||
> kustomize build $OVERLAYS/development | kubectl apply -f -
|
||||
> ```
|
||||
|
||||
Deployment 无法自动检测 ConfigMap 是否发生改变。
|
||||
|
||||
如果更改 configMap 的数据, 而不更改其名称以及对该名称的所有引用, 则必须重新启动Deployment中的那些Pods以获取更改。
|
||||
|
||||
最佳的做法就是将 configMap 视为不变的。
|
||||
|
||||
不去编辑 configMap ,而是使用 _新_ 的名称的 _新_ configMap,并在 Deployment 中引用新的 configMap 。而 `kustomize` 使用 `configMapGenerator` 指令和相关的命名控件使这很容易。
|
||||
|
||||
### 创建并且使用 overlay 用于 _生产_
|
||||
|
||||
接下来创建 _production_ overlay 的文件:
|
||||
|
||||
<!-- @productionFiles @test -->
|
||||
```bash
|
||||
mkdir -p $OVERLAYS/production
|
||||
|
||||
cat <<EOF >$OVERLAYS/production/plumbing.properties
|
||||
port=8080
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/production/secret.properties
|
||||
dbpassword=thisShouldProbablyBeInASecretInstead
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/production/kustomization.yaml
|
||||
resources:
|
||||
- ../../base
|
||||
namePrefix: prod-
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
behavior: merge
|
||||
files:
|
||||
- plumbing.properties
|
||||
- secret.properties
|
||||
EOF
|
||||
```
|
||||
|
||||
现在可以生成用于生产的 configMap:
|
||||
|
||||
<!-- @runProd @test -->
|
||||
```bash
|
||||
kustomize build $OVERLAYS/production
|
||||
```
|
||||
|
||||
可以直接在 CI/CD 流程中执行如下命令,将应用部署到集群:
|
||||
|
||||
> ```bash
|
||||
> kustomize build $OVERLAYS/production | kubectl apply -f -
|
||||
> ```
|
||||
197
examples/zh/configGeneration.md
Normal file
197
examples/zh/configGeneration.md
Normal file
@@ -0,0 +1,197 @@
|
||||
[patch]: ../../docs/glossary.md#patch
|
||||
[resource]: ../../docs/glossary.md#resource
|
||||
[variant]: ../../docs/glossary.md#variant
|
||||
|
||||
## ConfigMap 的生成和滚动更新
|
||||
|
||||
kustomize 提供了两种添加 ConfigMap 的方法:
|
||||
|
||||
- 将 ConfigMap 声明为 [resource]
|
||||
- 通过 ConfigMapGenerator 声明 ConfigMap
|
||||
|
||||
在 `kustomization.yaml` 中,这两种方法的格式分别如下:
|
||||
|
||||
> ```
|
||||
> # 将 ConfigMap 声明为 resource
|
||||
> resources:
|
||||
> - configmap.yaml
|
||||
>
|
||||
> # 在 ConfigMapGenerator 中声明 ConfigMap
|
||||
> configMapGenerator:
|
||||
> - name: a-configmap
|
||||
> files:
|
||||
> - configs/configfile
|
||||
> - configs/another_configfile
|
||||
> ```
|
||||
|
||||
声明为 [resource] 的 ConfigMaps 的处理方式与其他 resource 相同,Kustomize 不会在为 ConfigMap 的名称添加哈希后缀。而在 ConfigMapGenerator 中声明 ConfigMap 的处理方式则与之前不同,默认将为名称添加哈希后缀,ConfigMap 中的任何更改都将触发滚动更新。
|
||||
|
||||
在 [hello_world](helloWorld.md) 示例中,使用 ConfigmapGenerator 来替换将 ConfigMap 声明为 [resource] 的方法。由此生成的 ConfigMap 中的更改将导致哈希值更改和滚动更新。
|
||||
|
||||
### 建立 base 和 staging
|
||||
|
||||
使用 configMapGenerator 建立 base
|
||||
|
||||
<!-- @establishBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
|
||||
curl -s -o "$BASE/#1.yaml" "https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/helloWorld\
|
||||
/{deployment,service}.yaml"
|
||||
|
||||
cat <<'EOF' >$BASE/kustomization.yaml
|
||||
commonLabels:
|
||||
app: hello
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
configMapGenerator:
|
||||
- name: the-map
|
||||
literals:
|
||||
- altGreeting=Good Morning!
|
||||
- enableRisky="false"
|
||||
EOF
|
||||
```
|
||||
|
||||
通过应用 ConfigMap patch 的方式建立 staging
|
||||
|
||||
<!-- @establishStaging @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
|
||||
cat <<'EOF' >$OVERLAYS/staging/kustomization.yaml
|
||||
namePrefix: staging-
|
||||
nameSuffix: -v1
|
||||
commonLabels:
|
||||
variant: staging
|
||||
org: acmeCorporation
|
||||
commonAnnotations:
|
||||
note: Hello, I am staging!
|
||||
resources:
|
||||
- ../../base
|
||||
patchesStrategicMerge:
|
||||
- map.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$OVERLAYS/staging/map.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
data:
|
||||
altGreeting: "Have a pineapple!"
|
||||
enableRisky: "true"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Review
|
||||
|
||||
在集群中运行的 _hello-world_ 的 deployment 配置了来自 configMap 的数据。
|
||||
|
||||
deployment 按照名称引用此 ConfigMap :
|
||||
|
||||
<!-- @showDeployment @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 2 configMapKeyRef $BASE/deployment.yaml
|
||||
```
|
||||
|
||||
当 ConfigMap 中的数据需要更新时,更改群集中的实时 ConfigMap 的数据并不是一个好的做法。 由于 Deployment 无法知道其引用的 ConfigMap 已更改,这类更新是无效。
|
||||
|
||||
更改 Deployment 配置的推荐方法是:
|
||||
|
||||
1. 使用新名称创建一个新的 configMap
|
||||
2. 为*deployment* 添加 patch,修改相应 `configMapKeyRef` 字段的名称值。
|
||||
|
||||
后一种更改会启动对 deployment 中的 pod 的滚动更新。旧的 configMap 在不再被任何其他资源引用时最终会被[垃圾回收](/../../issues/242)。
|
||||
|
||||
### 如何使用 kustomize
|
||||
|
||||
_staging_ 的 [variant] 包含一个 configMap 的 [patch]:
|
||||
|
||||
<!-- @showMapPatch @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
cat $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
|
||||
根据定义,此 patch 是一个命名但不一定是完整的资源规范,旨在修改完整的资源规范。
|
||||
|
||||
在 ConfigMapGenerator 中声明 ConfigMap 的修改。
|
||||
|
||||
<!-- @showMapBase @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
grep -C 4 configMapGenerator $BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
要使这个 patch 正常工作,`metadata/name` 字段中的名称必须匹配。
|
||||
|
||||
但是,文件中指定的名称值不是群集中使用的名称值。根据设计,kustomize 修改从 ConfigMapGenerator 声明的 ConfigMaps 的名称。要查看最终在群集中使用的名称,只需运行 kustomize:
|
||||
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
```
|
||||
|
||||
根据 `$OVERLAYS/staging/kustomization.yaml` 中的 `namePrefix` 字段,configMap 名称以 _staging-_ 为前缀。
|
||||
|
||||
根据 `$OVERLAYS/staging/kustomization.yaml` 中的 `nameSuffix` 字段,configMap 名称以 _-v1_ 为后缀。
|
||||
|
||||
configMap 名称的后缀是由 map 内容的哈希生成的 - 在这种情况下,名称后缀是 _5276h4th55_ :
|
||||
|
||||
<!-- @grepStagingHash @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging | grep 5276h4th55
|
||||
```
|
||||
|
||||
现在修改 map patch ,更改该服务将使用的问候消息:
|
||||
|
||||
<!-- @changeMap @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
sed -i.bak 's/pineapple/kiwi/' $OVERLAYS/staging/map.yaml
|
||||
```
|
||||
|
||||
查看新的问候消息:
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 2 -A 3 kiwi
|
||||
```
|
||||
|
||||
再次运行 kustomize 查看新的 configMap 名称:
|
||||
|
||||
<!-- @grepStagingName @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
kustomize build $OVERLAYS/staging |\
|
||||
grep -B 8 -A 1 staging-the-map
|
||||
```
|
||||
|
||||
确认 configMap 内容的更改将会生成以 _c2g8fcbf88_ 结尾的三个新名称 - 一个在 configMap 的名称中,另两个在使用 ConfigMap 的 deployment 中:
|
||||
|
||||
<!-- @countHashes @testAgainstLatestRelease -->
|
||||
|
||||
```
|
||||
test 3 == \
|
||||
$(kustomize build $OVERLAYS/staging | grep c2g8fcbf88 | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
将这些资源应用于群集将导致 deployment pod 的滚动更新,将它们从 _5276h4th55_ map 重新定位到 _c2g8fcbf88_ map 。系统稍后将垃圾收集未使用的 map。
|
||||
|
||||
## 回滚
|
||||
|
||||
回滚,可以撤消对源码配置所做的任何编辑,然后在还原的配置上重新运行 kustomize 并将其应用于群集。
|
||||
60
examples/zh/generatorOptions.md
Normal file
60
examples/zh/generatorOptions.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Generator Options
|
||||
|
||||
Kustomize 提供了修改 ConfigMapGenerator 和 SecretGenerator 行为的选项,这些选项包括:
|
||||
|
||||
- 不再将基于内容生成的哈希后缀添加到资源名称后
|
||||
- 为生成的资源添加 labels
|
||||
- 为生成的资源添加 annotations
|
||||
|
||||
这个示例将展示如何运用这些选项,首先创建一个工作空间:
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
创建 kustomization 并且为其添加一个 ConfigMapGenerator
|
||||
|
||||
<!-- @createCMGenerator @test -->
|
||||
```bash
|
||||
cat > $DEMO_HOME/kustomization.yaml << EOF
|
||||
configMapGenerator:
|
||||
- name: my-configmap
|
||||
literals:
|
||||
- foo=bar
|
||||
- baz=qux
|
||||
EOF
|
||||
```
|
||||
|
||||
添加如下 generatorOptions
|
||||
<!-- @addGeneratorOptions @test -->
|
||||
```bash
|
||||
cat >> $DEMO_HOME/kustomization.yaml << EOF
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
labels:
|
||||
kustomize.generated.resource: somevalue
|
||||
annotations:
|
||||
annotations.only.for.generated: othervalue
|
||||
EOF
|
||||
```
|
||||
运行 `kustomize build` 并且确定生成的 ConfigMap 。
|
||||
|
||||
- 确定没有名称后缀
|
||||
<!-- @verify @test -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "name: my-configmap$" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
- 确定 label `kustomize.generated.resource: somevalue`
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 1 "labels" | grep "kustomize.generated.resource" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
- 确定 annotation `annotations.only.for.generated: othervalue`
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep -A 1 "annotations" | grep "annotations.only.for.generated" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
301
examples/zh/helloWorld.md
Normal file
301
examples/zh/helloWorld.md
Normal file
@@ -0,0 +1,301 @@
|
||||
[base]: ../../docs/glossary.md#base
|
||||
[config]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/helloWorld
|
||||
[gitops]: ../../docs/glossary.md#gitops
|
||||
[hello]: https://github.com/monopole/hello
|
||||
[kustomization]: ../../docs/glossary.md#kustomization
|
||||
[original]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/helloWorld
|
||||
[overlay]: ../../docs/glossary.md#overlay
|
||||
[overlays]: ../../docs/glossary.md#overlay
|
||||
[patch]: ../../docs/glossary.md#patch
|
||||
[variant]: ../../docs/glossary.md#variant
|
||||
[variants]: ../../docs/glossary.md#variant
|
||||
|
||||
# Demo: hello world with variants
|
||||
|
||||
步骤:
|
||||
|
||||
1. 下载 [base] 配置。
|
||||
2. 进行定制。
|
||||
3. 基于定制后的 base 新建2个不同的 [overlays] (_staging_ 和 _production_)。
|
||||
4. 运行 kustomize 和 kubectl 来部署 staging 和 production 。
|
||||
|
||||
首先创建一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
或者:
|
||||
|
||||
> ```
|
||||
> DEMO_HOME=~/hello
|
||||
> ```
|
||||
|
||||
## 创建 base
|
||||
|
||||
如果要使用 [overlays] 创建 [variants] ,必须先创建一个共同的 [base] 。
|
||||
|
||||
为了使本文档保持简洁,base 的资源位于补充目录中,并不在此处,请按照下面的方法下载它们:
|
||||
|
||||
<!-- @downloadBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
|
||||
curl -s -o "$BASE/#1.yaml" "https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/helloWorld\
|
||||
/{configMap,deployment,kustomization,service}.yaml"
|
||||
```
|
||||
|
||||
观察该目录:
|
||||
|
||||
<!-- @runTree -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
可以看到:
|
||||
|
||||
> ```
|
||||
> /tmp/tmp.IyYQQlHaJP
|
||||
> └── base
|
||||
> ├── configMap.yaml
|
||||
> ├── deployment.yaml
|
||||
> ├── kustomization.yaml
|
||||
> └── service.yaml
|
||||
> ```
|
||||
|
||||
这些 resources 可以立即在 k8s 集群中部署:
|
||||
|
||||
> ```
|
||||
> kubectl apply -f $DEMO_HOME/base
|
||||
> ```
|
||||
|
||||
实例化 _hello_ 服务, `kubectl` 只能识别 resources 文件。
|
||||
|
||||
|
||||
### The Base Kustomization
|
||||
|
||||
`base` 目录中包含一个 [kustomization] 文件:
|
||||
|
||||
<!-- @showKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
more $BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
(可选)在 base 目录上运行 `kustomize` 将定制过的 resources 打印到标准输出:
|
||||
|
||||
<!-- @buildBase @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE
|
||||
```
|
||||
|
||||
### 定制 base
|
||||
|
||||
定制 _app label_ 并应用于所有的 resources :
|
||||
|
||||
<!-- @addLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
sed -i.bak 's/app: hello/app: my-hello/' \
|
||||
$BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
查看效果:
|
||||
<!-- @checkLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE | grep -C 3 app:
|
||||
```
|
||||
|
||||
## 创建 Overlays
|
||||
|
||||
创建包含 _staging_ 和 _production_ 的 [overlay]:
|
||||
|
||||
* _Staging_ 包含生产环境中无法应用的带有风险的功能。
|
||||
* _Production_ 包含更多的副本数。
|
||||
* 来自这些集群 [variants] 的问候消息将与来自其他集群的不同。
|
||||
|
||||
<!-- @overlayDirectories @testAgainstLatestRelease -->
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
mkdir -p $OVERLAYS/production
|
||||
```
|
||||
|
||||
#### Staging Kustomization
|
||||
|
||||
在 `staging` 目录中创建一个 kustomization 文件,用来定义一个新的名称前缀和一些不同的 labels 。
|
||||
|
||||
<!-- @makeStagingKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >$OVERLAYS/staging/kustomization.yaml
|
||||
namePrefix: staging-
|
||||
commonLabels:
|
||||
variant: staging
|
||||
org: acmeCorporation
|
||||
commonAnnotations:
|
||||
note: Hello, I am staging!
|
||||
resources:
|
||||
- ../../base
|
||||
patchesStrategicMerge:
|
||||
- map.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
#### Staging Patch
|
||||
|
||||
新增一个自定义的 configMap 将问候消息从 _Good Morning!_ 改为 _Have a pineapple!_ 。
|
||||
|
||||
同时,将 _risky_ 标记设置为 true 。
|
||||
|
||||
<!-- @stagingMap @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$OVERLAYS/staging/map.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: the-map
|
||||
data:
|
||||
altGreeting: "Have a pineapple!"
|
||||
enableRisky: "true"
|
||||
EOF
|
||||
```
|
||||
|
||||
#### Production Kustomization
|
||||
|
||||
在 `production` 目录中创建一个 kustomization 文件,用来定义一个新的名称前缀和 labels 。
|
||||
|
||||
<!-- @makeProductionKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$OVERLAYS/production/kustomization.yaml
|
||||
namePrefix: production-
|
||||
commonLabels:
|
||||
variant: production
|
||||
org: acmeCorporation
|
||||
commonAnnotations:
|
||||
note: Hello, I am production!
|
||||
resources:
|
||||
- ../../base
|
||||
patchesStrategicMerge:
|
||||
- deployment.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
|
||||
#### Production Patch
|
||||
|
||||
因为生产环境需要处理更多的流量,新建一个 production patch 来增加副本数。
|
||||
|
||||
<!-- @productionDeployment @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$OVERLAYS/production/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 10
|
||||
EOF
|
||||
```
|
||||
|
||||
## 比较 overlays
|
||||
|
||||
|
||||
`DEMO_HOME` 现在包含:
|
||||
|
||||
- _base_ 目录:对拉取到的源配置进行了简单定制
|
||||
|
||||
- _overlays_ 目录:包含在集群中创建不同 _staging_ 和 _production_ [variants] 的 kustomizations 和 patches 。
|
||||
|
||||
查看目录结构和差异:
|
||||
|
||||
<!-- @listFiles -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
可以看到:
|
||||
|
||||
> ```
|
||||
> /tmp/tmp.IyYQQlHaJP1
|
||||
> ├── base
|
||||
> │ ├── configMap.yaml
|
||||
> │ ├── deployment.yaml
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── service.yaml
|
||||
> └── overlays
|
||||
> ├── production
|
||||
> │ ├── deployment.yaml
|
||||
> │ └── kustomization.yaml
|
||||
> └── staging
|
||||
> ├── kustomization.yaml
|
||||
> └── map.yaml
|
||||
> ```
|
||||
|
||||
直接比较 _staging_ 和 _production_ 输出的不同:
|
||||
|
||||
<!-- @compareOutput -->
|
||||
```
|
||||
diff \
|
||||
<(kustomize build $OVERLAYS/staging) \
|
||||
<(kustomize build $OVERLAYS/production) |\
|
||||
more
|
||||
```
|
||||
|
||||
部分比较输出:
|
||||
|
||||
> ```diff
|
||||
> < altGreeting: Have a pineapple!
|
||||
> < enableRisky: "true"
|
||||
> ---
|
||||
> > altGreeting: Good Morning!
|
||||
> > enableRisky: "false"
|
||||
> 8c8
|
||||
> < note: Hello, I am staging!
|
||||
> ---
|
||||
> > note: Hello, I am production!
|
||||
> 11c11
|
||||
> < variant: staging
|
||||
> ---
|
||||
> > variant: production
|
||||
> 13c13
|
||||
> (...truncated)
|
||||
> ```
|
||||
|
||||
|
||||
## 部署
|
||||
|
||||
输出不同 _overlys_ 的配置:
|
||||
|
||||
<!-- @buildStaging @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/staging
|
||||
```
|
||||
|
||||
<!-- @buildProduction @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/production
|
||||
```
|
||||
|
||||
将上述命令传递给 kubectl 进行部署:
|
||||
|
||||
> ```
|
||||
> kustomize build $OVERLAYS/staging |\
|
||||
> kubectl apply -f -
|
||||
> ```
|
||||
|
||||
> ```
|
||||
> kustomize build $OVERLAYS/production |\
|
||||
> kubectl apply -f -
|
||||
> ```
|
||||
|
||||
也可使用 `kubectl` (v1.14.0 以上版本):
|
||||
|
||||
> ```
|
||||
> kubectl apply -k $OVERLAYS/staging
|
||||
> ```
|
||||
|
||||
> ```
|
||||
> kubectl apply -k $OVERLAYS/production
|
||||
> ```
|
||||
74
examples/zh/image.md
Normal file
74
examples/zh/image.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# 示例: 改变镜像名称和标签
|
||||
|
||||
首先构建一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
创建包含pod资源的 `kustomization`
|
||||
|
||||
<!-- @testAgainstLatestRelease to @test -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- pod.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
创建 pod 资源pod.yaml
|
||||
|
||||
<!-- @createDeployment @test -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: busybox:1.29.0
|
||||
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
|
||||
initContainers:
|
||||
- name: init-mydb
|
||||
image: busybox:1.29.0
|
||||
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
|
||||
EOF
|
||||
```
|
||||
|
||||
`myapp-pod` 包含一个init容器和一个普通容器,两者都使用 `busybox:1.29.0` 镜像。
|
||||
|
||||
在 `kustomization.yaml` 中添加 `images` 字段来更改镜像 `busybox` 和标签 `1.29.0` 。
|
||||
|
||||
- 通过 `kustomize` 添加 `images`:
|
||||
<!-- @addImages @test -->
|
||||
```bash
|
||||
cd $DEMO_HOME
|
||||
kustomize edit set image busybox=alpine:3.6
|
||||
```
|
||||
|
||||
- 将`images`字段将被添加到`kustomization.yaml`:
|
||||
> ```yaml
|
||||
> images:
|
||||
> - name: busybox
|
||||
> newName: alpine
|
||||
> newTag: 3.6
|
||||
> ```
|
||||
|
||||
构建 `kustomization`
|
||||
<!-- @kustomizeBuild @testAgainstLatestRelease -->
|
||||
```bash
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
确认`busybox`镜像和标签是否被替换为`alpine:3.6`:
|
||||
<!-- @confirmImages @testAgainstLatestRelease -->
|
||||
```
|
||||
test 2 = \
|
||||
$(kustomize build $DEMO_HOME | grep alpine:3.6 | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
124
examples/zh/jsonpatch.md
Normal file
124
examples/zh/jsonpatch.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# 示例: 应用 json patch(json补丁)
|
||||
|
||||
kustomization文件支持通过[JSON patches](https://tools.ietf.org/html/rfc6902)来修改已有的资源.
|
||||
|
||||
下面的例子将会使用这个功能对`Ingress`加以修改.
|
||||
|
||||
首先,创建一个包含`ingress`的`kustomization`文件.
|
||||
|
||||
<!-- @createIngress @testAgainstLatestRelease -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- ingress.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEMO_HOME/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: my-ingress
|
||||
spec:
|
||||
rules:
|
||||
- host: foo.bar.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: my-api
|
||||
servicePort: 80
|
||||
EOF
|
||||
```
|
||||
|
||||
定义一个JSON patch文件,以更新`Ingress`对象的2个字段:
|
||||
|
||||
- 把 host 从 `foo.bar.com` 改为 `foo.bar.io`
|
||||
- 把 servicePort 从 `80` 改为 `8080`
|
||||
|
||||
<!-- @addJsonPatch @testAgainstLatestRelease -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/ingress_patch.json
|
||||
[
|
||||
{"op": "replace", "path": "/spec/rules/0/host", "value": "foo.bar.io"},
|
||||
{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/servicePort", "value": 8080}
|
||||
]
|
||||
EOF
|
||||
```
|
||||
|
||||
JSON patch 也可以写成 YAML 的格式.该例子顺便展示了“添加”操作:
|
||||
|
||||
<!-- @addYamlPatch @testAgainstLatestRelease -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/ingress_patch.yaml
|
||||
- op: replace
|
||||
path: /spec/rules/0/host
|
||||
value: foo.bar.io
|
||||
|
||||
- op: add
|
||||
path: /spec/rules/0/http/paths/-
|
||||
value:
|
||||
path: '/test'
|
||||
backend:
|
||||
serviceName: my-test
|
||||
servicePort: 8081
|
||||
EOF
|
||||
```
|
||||
|
||||
在kustomization.yaml文件中增加 _patchesJson6902_ 字段,以应用该补丁
|
||||
|
||||
<!-- @applyJsonPatch @testAgainstLatestRelease -->
|
||||
```bash
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: networking.k8s.io
|
||||
version: v1beta1
|
||||
kind: Ingress
|
||||
name: my-ingress
|
||||
path: ingress_patch.json
|
||||
EOF
|
||||
```
|
||||
|
||||
运行 `kustomize build $DEMO_HOME`, 在输出那里确认 host 已经被正确更新.
|
||||
|
||||
<!-- @confirmHost @testAgainstLatestRelease -->
|
||||
```bash
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "host: foo.bar.io" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
运行 `kustomize build $DEMO_HOME`, 在输出那里确认 servicePort 已经被正确更新.
|
||||
|
||||
<!-- @confirmServicePort @testAgainstLatestRelease -->
|
||||
|
||||
```bash
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "servicePort: 8080" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
如果 patch 是YAML格式的,就能正确解析:
|
||||
|
||||
<!-- @applyYamlPatch @testAgainstLatestRelease -->
|
||||
```bash
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
patchesJson6902:
|
||||
- target:
|
||||
group: networking.k8s.io
|
||||
version: v1beta1
|
||||
kind: Ingress
|
||||
name: my-ingress
|
||||
path: ingress_patch.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
运行 `kustomize build $DEMO_HOME`, 在输出那里确认有 `/test` 这个路径.
|
||||
|
||||
<!-- @confirmYamlPatch @testAgainstLatestRelease -->
|
||||
```bash
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep "path: /test" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
269
examples/zh/ldap.md
Normal file
269
examples/zh/ldap.md
Normal file
@@ -0,0 +1,269 @@
|
||||
[base]: ../../docs/glossary.md#base
|
||||
[gitops]: ../../docs/glossary.md#gitops
|
||||
[kustomization]: ../../docs/glossary.md#kustomization
|
||||
[overlay]: ../../docs/glossary.md#overlay
|
||||
[overlays]: ../../docs/glossary.md#overlay
|
||||
[variant]: ../../docs/glossary.md#variant
|
||||
[variants]: ../../docs/glossary.md#variant
|
||||
|
||||
# 示例:LDAP 服务
|
||||
|
||||
步骤:
|
||||
|
||||
1. 拉取已经存在的 [base] 配置
|
||||
2. 进行配置
|
||||
3. 基于 [base] 创建2个不同的 [overlays] (_staging_ 和 _production_)
|
||||
4. 运行 kustomize 或 kubectl 部署 staging 和 production
|
||||
|
||||
首先创建一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
> ```
|
||||
> DEMO_HOME=~/ldap
|
||||
> ```
|
||||
|
||||
## 创建 base
|
||||
|
||||
要使用 [overlays] 创建 [variant],首先需要创建一个 [base]。
|
||||
|
||||
为了保证文档的精简,基础资源都在补充目录中,如果需要请下载它们:
|
||||
|
||||
<!-- @downloadBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir -p $BASE
|
||||
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/ldap"
|
||||
|
||||
curl -s -o "$BASE/#1" "$CONTENT/base\
|
||||
/{deployment.yaml,kustomization.yaml,service.yaml,env.startup.txt}"
|
||||
```
|
||||
|
||||
检查这个目录:
|
||||
|
||||
<!-- @runTree -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
将会看到如下文件:
|
||||
|
||||
> ```
|
||||
> /tmp/tmp.IyYQQlHaJP
|
||||
> └── base
|
||||
> ├── deployment.yaml
|
||||
> ├── env.startup.txt
|
||||
> ├── kustomization.yaml
|
||||
> └── service.yaml
|
||||
> ```
|
||||
|
||||
这些资源可以由 kubectl 立刻部署到集群上来实例化 _ldap_ 服务:
|
||||
|
||||
> ```
|
||||
> kubectl apply -f $DEMO_HOME/base
|
||||
> ```
|
||||
|
||||
注意 `kubectl -f` 只能识别 k8s 资源文件。
|
||||
|
||||
### The Base Kustomization
|
||||
|
||||
`base` 目录包含一个 [kustomization] 文件:
|
||||
|
||||
<!-- @showKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
more $BASE/kustomization.yaml
|
||||
```
|
||||
|
||||
(可选)在 base 上运行 `kustomize`,并将结果打印到标准输出:
|
||||
|
||||
<!-- @buildBase @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE
|
||||
```
|
||||
|
||||
### Customize the base
|
||||
|
||||
为所有资源设置名称前缀:
|
||||
|
||||
<!-- @namePrefix @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $BASE
|
||||
kustomize edit set nameprefix "my-"
|
||||
```
|
||||
|
||||
查看变化:
|
||||
<!-- @checkNameprefix @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $BASE | grep -C 3 "my-"
|
||||
```
|
||||
|
||||
## 创建 Overlays
|
||||
|
||||
创建 _staging_ 和 _production_ 的 [overlay]:
|
||||
|
||||
* 为 _Staging_ 新增一个 ConfigMap
|
||||
* 为 _Production_ 添加持久化存储盘和更多的副本数
|
||||
* 现实两个 [variants] 的不同之处
|
||||
|
||||
<!-- @overlayDirectories @testAgainstLatestRelease -->
|
||||
```
|
||||
OVERLAYS=$DEMO_HOME/overlays
|
||||
mkdir -p $OVERLAYS/staging
|
||||
mkdir -p $OVERLAYS/production
|
||||
```
|
||||
|
||||
#### Staging Kustomization
|
||||
|
||||
下载 staging 配置
|
||||
|
||||
<!-- @downloadStagingKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$OVERLAYS/staging/#1" "$CONTENT/overlays/staging\
|
||||
/{config.env,deployment.yaml,kustomization.yaml}"
|
||||
```
|
||||
|
||||
在 staging 配置中增加一个 ConfigMap
|
||||
> ```cat $OVERLAYS/staging/kustomization.yaml
|
||||
> (...truncated)
|
||||
> configMapGenerator:
|
||||
> - name: env-config
|
||||
> files:
|
||||
> - config.env
|
||||
> ```
|
||||
和2个副本
|
||||
> ```cat $OVERLAYS/staging/deployment.yaml
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: ldap
|
||||
> spec:
|
||||
> replicas: 2
|
||||
> ```
|
||||
|
||||
#### Production Kustomization
|
||||
|
||||
下载 production 配置
|
||||
<!-- @downloadProductionKustomization @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$OVERLAYS/production/#1" "$CONTENT/overlays/production\
|
||||
/{deployment.yaml,kustomization.yaml}"
|
||||
```
|
||||
|
||||
在 production 的配置中增加为6副本和存储盘
|
||||
> ```cat $OVERLAYS/production/deployment.yaml
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: ldap
|
||||
> spec:
|
||||
> replicas: 6
|
||||
> template:
|
||||
> spec:
|
||||
> volumes:
|
||||
> - name: ldap-data
|
||||
> emptyDir: null
|
||||
> gcePersistentDisk:
|
||||
> pdName: ldap-persistent-storage
|
||||
> ```
|
||||
|
||||
## 比较 overlays
|
||||
|
||||
|
||||
`DEMO_HOME` 现在包括:
|
||||
|
||||
* 一个 _base_ 目录:对拉取原始配置进行少量的定制
|
||||
|
||||
* 一个 _overlays_ 目录:其中包含在集群中创建不同的 _staging_ 和 _production_ [variants] 所需的 kustomizations 文件和 patche 文件
|
||||
|
||||
查看目录结构和差异:
|
||||
|
||||
<!-- @listFiles -->
|
||||
```
|
||||
tree $DEMO_HOME
|
||||
```
|
||||
|
||||
将会得到类似的内容:
|
||||
|
||||
> ```
|
||||
> /tmp/tmp.IyYQQlHaJP1
|
||||
> ├── base
|
||||
> │ ├── deployment.yaml
|
||||
> │ ├── env.startup.txt
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── service.yaml
|
||||
> └── overlays
|
||||
> ├── production
|
||||
> │ ├── deployment.yaml
|
||||
> │ └── kustomization.yaml
|
||||
> └── staging
|
||||
> ├── config.env
|
||||
> ├── deployment.yaml
|
||||
> └── kustomization.yaml
|
||||
> ```
|
||||
|
||||
直接对输出内容进行比较,以查看 _staging_ 和 _production_ 的不同之处:
|
||||
|
||||
<!-- @compareOutput -->
|
||||
```
|
||||
diff \
|
||||
<(kustomize build $OVERLAYS/staging) \
|
||||
<(kustomize build $OVERLAYS/production) |\
|
||||
more
|
||||
```
|
||||
|
||||
输出的差异内容
|
||||
|
||||
> ```diff
|
||||
> (...truncated)
|
||||
> < name: staging-my-ldap-configmap-kftftt474h
|
||||
> ---
|
||||
> > name: production-my-ldap-configmap-k27f7hkg4f
|
||||
> 85c75
|
||||
> < name: staging-my-ldap-service
|
||||
> ---
|
||||
> > name: production-my-ldap-service
|
||||
> 97c87
|
||||
> < name: staging-my-ldap
|
||||
> ---
|
||||
> > name: production-my-ldap
|
||||
> 99c89
|
||||
> < replicas: 2
|
||||
> ---
|
||||
> > replicas: 6
|
||||
> (...truncated)
|
||||
> ```
|
||||
|
||||
|
||||
## 部署
|
||||
|
||||
查看各个资源集:
|
||||
|
||||
<!-- @buildStaging @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/staging
|
||||
```
|
||||
|
||||
<!-- @buildProduction @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $OVERLAYS/production
|
||||
```
|
||||
|
||||
将上述命令通过管道传递给 kubectl 以进行部署:
|
||||
|
||||
> ```
|
||||
> kustomize build $OVERLAYS/staging |\
|
||||
> kubectl apply -f -
|
||||
> ```
|
||||
|
||||
> ```
|
||||
> kustomize build $OVERLAYS/production |\
|
||||
> kubectl apply -f -
|
||||
> ```
|
||||
113
examples/zh/multi-namespace.md
Normal file
113
examples/zh/multi-namespace.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# 示例:使用通用的 base 应用多 namespace
|
||||
|
||||
`kustomize` 支持基于同一base具有不同 namespace 的多个 variants。
|
||||
|
||||
只需将 overlay 作为新的 kustomization 的 base,就可以创建一个额外的 overlay 将这些 variants 组合在一起。下面使用一个 pod 作为 base 来进行演示。
|
||||
|
||||
创建一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
定义一个通用的 base:
|
||||
<!-- @makeBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
resources:
|
||||
- pod.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9
|
||||
EOF
|
||||
```
|
||||
|
||||
定义 namespace-a 的 variant:
|
||||
<!-- @makeNamespaceA @testAgainstLatestRelease -->
|
||||
```
|
||||
NSA=$DEMO_HOME/namespace-a
|
||||
mkdir $NSA
|
||||
|
||||
cat <<EOF >$NSA/kustomization.yaml
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- ../base
|
||||
namespace: namespace-a
|
||||
EOF
|
||||
|
||||
cat <<EOF >$NSA/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: namespace-a
|
||||
EOF
|
||||
```
|
||||
|
||||
定义 namespace-b 的 variant:
|
||||
<!-- @makeNamespaceB @testAgainstLatestRelease -->
|
||||
```
|
||||
NSB=$DEMO_HOME/namespace-b
|
||||
mkdir $NSB
|
||||
|
||||
cat <<EOF >$NSB/kustomization.yaml
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- ../base
|
||||
namespace: namespace-b
|
||||
EOF
|
||||
|
||||
cat <<EOF >$NSB/namespace.yaml
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: namespace-b
|
||||
EOF
|
||||
```
|
||||
|
||||
然后定义一个 _Kustomization_,将两个 variants 组合在一起:
|
||||
<!-- @makeTopLayer @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- namespace-a
|
||||
- namespace-b
|
||||
EOF
|
||||
```
|
||||
|
||||
现在工作空间有如下目录:
|
||||
> ```
|
||||
> .
|
||||
> ├── base
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── pod.yaml
|
||||
> ├── kustomization.yaml
|
||||
> ├── namespace-a
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── namespace.yaml
|
||||
> └── namespace-b
|
||||
> ├── kustomization.yaml
|
||||
> └── namespace.yaml
|
||||
> ```
|
||||
|
||||
输出两个 namespace 的 pod 对象,分别在 namespace-a 和 namespace-b。
|
||||
|
||||
<!-- @confirmVariants @testAgainstLatestRelease -->
|
||||
```
|
||||
test 2 == \
|
||||
$(kustomize build $DEMO_HOME| grep -B 4 "namespace: namespace-[ab]" | grep "name: myapp-pod" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
127
examples/zh/multibases.md
Normal file
127
examples/zh/multibases.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# 示例:多 Overlay 使用相同 base
|
||||
|
||||
`kustomize` 鼓励定义多个 variants:例如在通用的 base 上使用 dev、staging 和 prod overlay。
|
||||
|
||||
可以创建其他 overlay 来将这些 variants 组合在一起:只需将 overlay 声明为新 kustomization 的 base 即可。
|
||||
|
||||
如果 base 由于某种原因无法控制,将多个 variants 组合在一起也可以为他们添加通用的 label 或 annotation。
|
||||
|
||||
下面使用一个 pod 作为 base 来进行演示。
|
||||
|
||||
首先创建一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
定义一个通用的 base:
|
||||
<!-- @makeBase @testAgainstLatestRelease -->
|
||||
```
|
||||
BASE=$DEMO_HOME/base
|
||||
mkdir $BASE
|
||||
|
||||
cat <<EOF >$BASE/kustomization.yaml
|
||||
resources:
|
||||
- pod.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$BASE/pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.7.9
|
||||
EOF
|
||||
```
|
||||
|
||||
定义 dev variant:
|
||||
<!-- @makeDev @testAgainstLatestRelease -->
|
||||
```
|
||||
DEV=$DEMO_HOME/dev
|
||||
mkdir $DEV
|
||||
|
||||
cat <<EOF >$DEV/kustomization.yaml
|
||||
resources:
|
||||
- ./../base
|
||||
namePrefix: dev-
|
||||
EOF
|
||||
```
|
||||
|
||||
定义 staging variant:
|
||||
<!-- @makeStaging @testAgainstLatestRelease -->
|
||||
```
|
||||
STAG=$DEMO_HOME/staging
|
||||
mkdir $STAG
|
||||
|
||||
cat <<EOF >$STAG/kustomization.yaml
|
||||
resources:
|
||||
- ./../base
|
||||
namePrefix: stag-
|
||||
EOF
|
||||
```
|
||||
|
||||
定义 production variant:
|
||||
<!-- @makeProd @testAgainstLatestRelease -->
|
||||
```
|
||||
PROD=$DEMO_HOME/production
|
||||
mkdir $PROD
|
||||
|
||||
cat <<EOF >$PROD/kustomization.yaml
|
||||
resources:
|
||||
- ./../base
|
||||
namePrefix: prod-
|
||||
EOF
|
||||
```
|
||||
|
||||
然后定义一个 _Kustomization_,将三个 variants 组合在一起:
|
||||
<!-- @makeTopLayer @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- ./dev
|
||||
- ./staging
|
||||
- ./production
|
||||
|
||||
namePrefix: cluster-a-
|
||||
EOF
|
||||
```
|
||||
|
||||
现在工作空间有如下目录:
|
||||
> ```
|
||||
> .
|
||||
> ├── base
|
||||
> │ ├── kustomization.yaml
|
||||
> │ └── pod.yaml
|
||||
> ├── dev
|
||||
> │ └── kustomization.yaml
|
||||
> ├── kustomization.yaml
|
||||
> ├── production
|
||||
> │ └── kustomization.yaml
|
||||
> └── staging
|
||||
> └── kustomization.yaml
|
||||
> ```
|
||||
|
||||
输出包含三个 pod 对象,分别来自 dev、staging 和 production variants。
|
||||
|
||||
<!-- @confirmVariants @testAgainstLatestRelease -->
|
||||
```
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep cluster-a-dev-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep cluster-a-stag-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
|
||||
test 1 == \
|
||||
$(kustomize build $DEMO_HOME | grep cluster-a-prod-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
与在不同的 variants 中添加不同的 `namePrefix` 类似,也可以添加不同的 `namespace` 并在一个 _kustomization_ 中组成这些 variants。更多的详细信息,请查看[multi-namespaces](multi-namespace.md)。
|
||||
171
examples/zh/mysql.md
Normal file
171
examples/zh/mysql.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# 示例:MySql
|
||||
|
||||
本示例采用现成的专为 MySql 设计的 k8s 资源,并对其进行定制使其适合生产环境。
|
||||
|
||||
在生产环境中,我们希望:
|
||||
|
||||
- 以 'prod-' 为前缀的 MySQL 资源
|
||||
- MySQL 资源具有 'env: prod' label
|
||||
- 使用持久化磁盘来存储 MySQL 数据
|
||||
|
||||
首先创建一个工作空间:
|
||||
<!-- @makeDemoHome @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
### 下载资源
|
||||
|
||||
为了保证文档的精简,基础资源都在补充目录中,如果需要请下载它们:
|
||||
|
||||
<!-- @downloadResources @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" "https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/mySql\
|
||||
/{deployment,secret,service}.yaml"
|
||||
```
|
||||
|
||||
### 初始化 kustomization.yaml
|
||||
|
||||
`kustomize` 会从 `kustomization.yaml` 文件中获取指令,创建这个文件:
|
||||
|
||||
<!-- @kustomizeYaml @testAgainstLatestRelease -->
|
||||
```
|
||||
touch $DEMO_HOME/kustomization.yaml
|
||||
```
|
||||
|
||||
### 添加资源
|
||||
|
||||
<!-- @addResources @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
|
||||
kustomize edit add resource secret.yaml
|
||||
kustomize edit add resource service.yaml
|
||||
kustomize edit add resource deployment.yaml
|
||||
|
||||
cat kustomization.yaml
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 resources 字段如下:
|
||||
|
||||
> ```
|
||||
> resources:
|
||||
> - secret.yaml
|
||||
> - service.yaml
|
||||
> - deployment.yaml
|
||||
> ```
|
||||
|
||||
### 定制名称
|
||||
|
||||
为 MySQL 资源添加 _prod-_ 前缀(这些资源将用于生产环境):
|
||||
|
||||
<!-- @customizeLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
|
||||
kustomize edit set nameprefix 'prod-'
|
||||
|
||||
cat kustomization.yaml
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 namePrefix 字段将会被更新:
|
||||
|
||||
> ```
|
||||
> namePrefix: prod-
|
||||
> ```
|
||||
|
||||
`namePrefix` 将在所有资源的名称前添加 _prod-_ 的前缀,可以通过如下命令查看:
|
||||
|
||||
<!-- @genNamePrefixConfig @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
输出内容:
|
||||
|
||||
> ```
|
||||
> apiVersion: v1
|
||||
> data:
|
||||
> password: YWRtaW4=
|
||||
> kind: Secret
|
||||
> metadata:
|
||||
> ....
|
||||
> name: prod-mysql-pass-d2gtcm2t2k
|
||||
> ---
|
||||
> apiVersion: v1
|
||||
> kind: Service
|
||||
> metadata:
|
||||
> ....
|
||||
> name: prod-mysql
|
||||
> spec:
|
||||
> ....
|
||||
> ---
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> ....
|
||||
> name: prod-mysql
|
||||
> spec:
|
||||
> selector:
|
||||
> ....
|
||||
> ```
|
||||
|
||||
### 定制 Label
|
||||
|
||||
我们希望生产环境的资源包含某些 Label,这样我们就可以通过 label selector 来查询到这些资源。
|
||||
|
||||
`kustomize` 没有 `edit set label` 命令来添加 label,但是可以通过编辑 `kustomization.yaml` 文件来实现:
|
||||
|
||||
<!-- @customizeLabels @testAgainstLatestRelease -->
|
||||
```
|
||||
sed -i.bak 's/app: helloworld/app: prod/' \
|
||||
$DEMO_HOME/kustomization.yaml
|
||||
```
|
||||
|
||||
这时,执行 `kustomize build` 命令将会生成包含 `prod-` 前缀和 `env:prod` label 的 MySQL 配置。
|
||||
|
||||
### 存储定制
|
||||
|
||||
现成的 MySQL 使用 `emptyDir` 类型的 volume,如果 MySQL Pod 被重新部署,则该类型的 volume 将会消失,这是不能应用于生产环境的,因此在生产环境中我们需要使用持久化磁盘。在 kustomize 中可以使用`patchesStrategicMerge` 来应用资源。
|
||||
|
||||
<!-- @createPatchFile @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' > $DEMO_HOME/persistent-disk.yaml
|
||||
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mysql
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
volumes:
|
||||
- name: mysql-persistent-storage
|
||||
emptyDir: null
|
||||
gcePersistentDisk:
|
||||
pdName: mysql-persistent-storage
|
||||
EOF
|
||||
```
|
||||
|
||||
将 patch 文件添加到 `kustomization.yaml` 中:
|
||||
|
||||
<!-- @specifyPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<'EOF' >> $DEMO_HOME/kustomization.yaml
|
||||
patchesStrategicMerge:
|
||||
- persistent-disk.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
`mysql-persistent-storage` 必须存在一个持久化磁盘才能使其成功运行,分为两步:
|
||||
|
||||
1. 创建一个名为 `persistent-disk.yaml` 的 YAML 文件,用于修改 deployment.yaml 的定义。
|
||||
2. 在 `kustomization.yaml` 中添加 `persistent-disk.yaml` 到 `patchesStrategicMerge` 列表中。运行 `kustomize build` 将 patch 应用于 Deployment 资源。
|
||||
|
||||
现在就可以将完整的配置输出并在集群中部署(将结果通过管道输出给 `kubectl apply`),在生产环境创建MySQL 应用。
|
||||
|
||||
<!-- @finalInflation @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME # | kubectl apply -f -
|
||||
```
|
||||
186
examples/zh/patchMultipleObjects.md
Normal file
186
examples/zh/patchMultipleObjects.md
Normal file
@@ -0,0 +1,186 @@
|
||||
[Strategic Merge Patch]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md
|
||||
[JSON patches]: https://tools.ietf.org/html/rfc6902
|
||||
[label selector]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
|
||||
|
||||
|
||||
# 示例:通过一个 patch 来修改多个资源
|
||||
|
||||
kustomization.yaml 支持通过 [Strategic Merge Patch] 和 [JSON patch] 来自定义资源。自 3.1.0 起,一个 patch 可以修改多个资源。
|
||||
|
||||
这可以通过指定 patch 和它所修改的 target 来完成,如下所示:
|
||||
```yaml
|
||||
patches:
|
||||
- path: <PatchFile>
|
||||
target:
|
||||
group: <Group>
|
||||
version: <Version>
|
||||
kind: <Kind>
|
||||
name: <Name>
|
||||
namespace: <Namespace>
|
||||
labelSelector: <LabelSelector>
|
||||
annotationSelector: <AnnotationSelector>
|
||||
```
|
||||
`labelSelector` 和 `annotationSelector` 都应遵循 [label selector] 中的约定。Kustomize 选择匹配`target`中所有字段的目标来应用 patch 。
|
||||
|
||||
下面的示例展示了如何为所有部署资源注入 sidecar 容器。
|
||||
|
||||
创建一个包含 Deployment 资源的 `kustomization` 。
|
||||
|
||||
<!-- @createDeployment @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- deployments.yaml
|
||||
EOF
|
||||
|
||||
cat <<EOF >$DEMO_HOME/deployments.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
old-label: old-value
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
args:
|
||||
- one
|
||||
- two
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy2
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
key: value
|
||||
spec:
|
||||
containers:
|
||||
- name: busybox
|
||||
image: busybox
|
||||
EOF
|
||||
```
|
||||
|
||||
声明 [Strategic Merge Patch] 文件以注入 sidecar 容器:
|
||||
|
||||
<!-- @addPatch @test -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: not-important
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: istio-proxy
|
||||
image: docker.io/istio/proxyv2
|
||||
args:
|
||||
- proxy
|
||||
- sidecar
|
||||
EOF
|
||||
```
|
||||
|
||||
在 kustomization.yaml 中添加 _patches_ 字段
|
||||
|
||||
<!-- @applyPatch @testAgainstLatestRelease -->
|
||||
```bash
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
patches:
|
||||
- path: patch.yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
EOF
|
||||
```
|
||||
|
||||
运行 `kustomize build $DEMO_HOME`,可以在输出中确认两个 Deployment 资源都已正确应用。
|
||||
|
||||
<!-- @confirmPatch @test -->
|
||||
```bash
|
||||
test 2 == \
|
||||
$(kustomize build $DEMO_HOME | grep "image: docker.io/istio/proxyv2" | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
输出如下:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy1
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
old-label: old-value
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- proxy
|
||||
- sidecar
|
||||
image: docker.io/istio/proxyv2
|
||||
name: istio-proxy
|
||||
- args:
|
||||
- one
|
||||
- two
|
||||
image: nginx
|
||||
name: nginx
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deploy2
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
key: value
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- proxy
|
||||
- sidecar
|
||||
image: docker.io/istio/proxyv2
|
||||
name: istio-proxy
|
||||
- image: busybox
|
||||
name: busybox
|
||||
```
|
||||
|
||||
## Target 选择
|
||||
|
||||
- 选择名称与 `name*` 匹配的资源
|
||||
```yaml
|
||||
target:
|
||||
name: name*
|
||||
```
|
||||
- 选择所有 Deployment 资源
|
||||
```yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
```
|
||||
- 选择 label 与 `app=hello` 匹配的资源
|
||||
```yaml
|
||||
target:
|
||||
labelSelector: app=hello
|
||||
```
|
||||
- 选择 annotation 与 `app=hello` 匹配的资源
|
||||
```yaml
|
||||
target:
|
||||
annotationSelector: app=hello
|
||||
```
|
||||
- 选择所有 label 与 `app=hello` 匹配的 Deployment 资源
|
||||
```yaml
|
||||
target:
|
||||
kind: Deployment
|
||||
labelSelector: app=hello
|
||||
```
|
||||
68
examples/zh/remoteBuild.md
Normal file
68
examples/zh/remoteBuild.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# remote targets
|
||||
|
||||
`kustomize build` 可以将 URL 作为参数传入并运行.
|
||||
|
||||
运行效果与如下操作相同:
|
||||
|
||||
如果想要要立即尝试此操作,可以按照 [multibases](../multibases/README.md) 示例运行 kustomization 运行构建。然后查看输出中的pod:
|
||||
|
||||
<!-- @remoteOverlayBuild @test -->
|
||||
|
||||
```bash
|
||||
target="github.com/kubernetes-sigs/kustomize/examples/multibases/dev/?ref=v1.0.6"
|
||||
test 1 == \
|
||||
$(kustomize build $target | grep dev-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
在该示例中运行 overlay 将获得三个 pod(在此 overlay 结合了dev、staging 和 prod 的 bases,以便同时将它们全部发送给所有人):
|
||||
|
||||
<!-- @remoteBuild @test -->
|
||||
```bash
|
||||
target="https://github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6"
|
||||
test 3 == \
|
||||
$(kustomize build $target | grep cluster-a-.*-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
将 URL 作为 base :
|
||||
|
||||
<!-- @createOverlay @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6
|
||||
namePrefix: remote-
|
||||
EOF
|
||||
```
|
||||
|
||||
构建该 base 以确定所有的三个 pod 都有 `remote-` 前缀。
|
||||
|
||||
<!-- @remoteBases @testAgainstLatestRelease -->
|
||||
```bash
|
||||
test 3 == \
|
||||
$(kustomize build $DEMO_HOME | grep remote-.*-myapp-pod | wc -l); \
|
||||
echo $?
|
||||
```
|
||||
|
||||
## URL format
|
||||
|
||||
URL 需要遵循 [hashicorp/go-getter URL 格式](https://github.com/hashicorp/go-getter#url-format) 。下面是一些遵循此约定的 Github repos 示例url。
|
||||
|
||||
- kustomization.yaml 在根目录
|
||||
|
||||
`github.com/Liujingfang1/mysql`
|
||||
- kustomization.yaml 在 test 分支的根目录
|
||||
|
||||
`github.com/Liujingfang1/mysql?ref=test`
|
||||
- kustomization.yaml 在 v1.0.6 版本的子目录
|
||||
|
||||
`github.com/kubernetes-sigs/kustomize/examples/multibases?ref=v1.0.6`
|
||||
- kustomization.yaml repoUrl2 分支的子目录
|
||||
|
||||
`github.com/Liujingfang1/kustomize/examples/helloWorld?ref=repoUrl2`
|
||||
- kustomization.yaml commit `7050a45134e9848fca214ad7e7007e96e5042c03` 的子目录
|
||||
|
||||
`github.com/Liujingfang1/kustomize/examples/helloWorld?ref=7050a45134e9848fca214ad7e7007e96e5042c03`
|
||||
193
examples/zh/secretGeneratorPlugin.md
Normal file
193
examples/zh/secretGeneratorPlugin.md
Normal file
@@ -0,0 +1,193 @@
|
||||
[ConfigMaps]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#configmap-v1-core
|
||||
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
[Go plugin]: https://golang.org/pkg/plugin
|
||||
[Secrets]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#secret-v1-core
|
||||
[base64]: https://tools.ietf.org/html/rfc4648#section-4
|
||||
[configuration directory]: https://wiki.archlinux.org/index.php/XDG_Base_Directory#Specification
|
||||
[grpc]: https://grpc.io
|
||||
[tag]: /../../releases
|
||||
[v2.0.3]: /../../releases/tag/v2.0.3
|
||||
[`exec.Command`]: https://golang.org/pkg/os/exec/#Command
|
||||
|
||||
# 生成 Secrets
|
||||
|
||||
## Secret 是什么?
|
||||
|
||||
Kubernetes 的 [ConfigMaps] 和 [Secrets] 都是key:value map,但 [Secrets] 的内容更为敏感,比如:密码或者 ssh 秘钥。
|
||||
|
||||
Kubernetes 开发者以各种方式工作,Secrets 保存的信息相比 ConfigMaps,Deployments 等的配置信息需要更谨慎的隐藏。
|
||||
|
||||
## 创建一个工作空间
|
||||
|
||||
<!-- @establishBase @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
## 来自本地文件的 Secret
|
||||
|
||||
kustomize 可以通过三种不同的方式生成来自本地文件的 Secret 。
|
||||
|
||||
* 从 _env_ 文件中获取(`NAME = VALUE`,每行一个)
|
||||
* 使用文件内容来生成一个 secret
|
||||
* 从 kustomization.yaml 文件获取 secret
|
||||
|
||||
这里有一个示例结合所有的三种方式:
|
||||
|
||||
创建一个包含一些短密码的 env 文件:
|
||||
|
||||
<!-- @makeEnvFile @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/foo.env
|
||||
ROUTER_PASSWORD=admin
|
||||
DB_PASSWORD=iloveyou
|
||||
EOF
|
||||
```
|
||||
|
||||
创建一个长密码的文本文件:
|
||||
|
||||
<!-- @makeLongSecretFile @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/longsecret.txt
|
||||
Lorem ipsum dolor sit amet,
|
||||
consectetur adipiscing elit,
|
||||
sed do eiusmod tempor incididunt
|
||||
ut labore et dolore magna aliqua.
|
||||
EOF
|
||||
```
|
||||
|
||||
创建一个kustomization.yaml 文件, 其中包含引用上面文件的 secretGenerator, 并且另外定义一些文字 KV 对:
|
||||
|
||||
<!-- @makeKustomization1 @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
secretGenerator:
|
||||
- name: mysecrets
|
||||
envs:
|
||||
- foo.env
|
||||
files:
|
||||
- longsecret.txt
|
||||
literals:
|
||||
- FRUIT=apple
|
||||
- VEGETABLE=carrot
|
||||
EOF
|
||||
```
|
||||
|
||||
生成 Secret :
|
||||
|
||||
<!-- @build1 @test -->
|
||||
```bash
|
||||
result=$(kustomize build $DEMO_HOME)
|
||||
echo "$result"
|
||||
# Spot check the result:
|
||||
test 1 == $(echo "$result" | grep -c "FRUIT: YXBwbGU=")
|
||||
```
|
||||
|
||||
将会得到类似的内容:
|
||||
|
||||
> ```yaml
|
||||
> apiVersion: v1
|
||||
> kind: Secret
|
||||
> metadata:
|
||||
> name: mysecrets-hfb5df789h
|
||||
> type: Opaque
|
||||
> data:
|
||||
> FRUIT: YXBwbGU=
|
||||
> VEGETABLE: Y2Fycm90
|
||||
> ROUTER_PASSWORD: YWRtaW4=
|
||||
> DB_PASSWORD: aWxvdmV5b3U=
|
||||
> longsecret.txt: TG9yZW0gaXBzdW0gZG9sb3Igc2l0I... (elided)
|
||||
> ```
|
||||
|
||||
资源名称的前缀为 `mysecrets`(在 kustomization.yaml 中指定),后跟其内容的哈希值。
|
||||
|
||||
使用 base64 解码器确认这些值的原始版本。
|
||||
|
||||
这三种方法共同的问题是创建 Secret 所使用的敏感数据必须保存磁盘上。
|
||||
|
||||
这会增加额外的安全问题:对本地存储的敏感文件的查看、安装和删除权限的控制等。
|
||||
|
||||
## 来自任何地方的 Secret
|
||||
|
||||
一般的替代方案是在[generator](../../docs/plugins)中生成 secrets 。
|
||||
|
||||
然后,这些值可以通过经过身份验证和授权的 RPC 进入密码保险库服务。
|
||||
|
||||
[sgp]: ../../plugin/someteam.example.com/v1/secretsfromdatabase
|
||||
|
||||
这里有一个[secret 生成器][sgp],它模拟从数据库中拉取 map 中的值。
|
||||
|
||||
下载
|
||||
|
||||
<!-- @copyPlugin @test -->
|
||||
```bash
|
||||
repo=https://raw.githubusercontent.com/kubernetes-sigs/kustomize
|
||||
pPath=plugin/someteam.example.com/v1/secretsfromdatabase
|
||||
dir=$DEMO_HOME/kustomize/$pPath
|
||||
|
||||
mkdir -p $dir
|
||||
|
||||
curl -s -o $dir/SecretsFromDatabase.go \
|
||||
${repo}/master/$pPath/SecretsFromDatabase.go
|
||||
```
|
||||
|
||||
运行 kustomize build 生成结果
|
||||
|
||||
<!-- @compilePlugin @xtest -->
|
||||
```bash
|
||||
go build -buildmode plugin \
|
||||
-o $dir/SecretsFromDatabase.so \
|
||||
$dir/SecretsFromDatabase.go
|
||||
```
|
||||
|
||||
创建一个配置文件:
|
||||
|
||||
<!-- @makeConfiguration @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/secretFromDb.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: SecretsFromDatabase
|
||||
metadata:
|
||||
name: mySecretGenerator
|
||||
name: forbiddenValues
|
||||
namespace: production
|
||||
keys:
|
||||
- ROCKET
|
||||
- VEGETABLE
|
||||
EOF
|
||||
```
|
||||
|
||||
创建一个引用此生成器的新 kustomization.yaml 文件:
|
||||
|
||||
<!-- @makeKustomization2 @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/kustomization.yaml
|
||||
generators:
|
||||
- secretFromDb.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
最终生成 secret ,设置 `XDG_CONFIG_HOME` 以便可以在 `$DEMO_HOME` 中找到该生成器:
|
||||
|
||||
<!-- @build2 @xtest -->
|
||||
```bash
|
||||
result=$( \
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build --enable_alpha_plugins $DEMO_HOME )
|
||||
echo "$result"
|
||||
# Spot check the result:
|
||||
test 1 == $(echo "$result" | grep -c "FRUIT: YXBwbGU=")
|
||||
```
|
||||
|
||||
将会得到类似的内容:
|
||||
|
||||
> ```yaml
|
||||
> apiVersion: v1
|
||||
> kind: Secret
|
||||
> metadata:
|
||||
> name: mysecrets-bdt27dbkd6
|
||||
> type: Opaque
|
||||
> data:
|
||||
> FRUIT: YXBwbGU=
|
||||
> VEGETABLE: Y2Fycm90
|
||||
> ```
|
||||
296
examples/zh/springboot.md
Normal file
296
examples/zh/springboot.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# 示例:SpringBoot
|
||||
|
||||
在本教程中,您将学会如何使用 `kustomize` 定制一个运行 Spring Boot 应用的 k8s 配置。
|
||||
|
||||
在生产环境中,我们需要定制如下内容:
|
||||
|
||||
- 为 Spring Boot 应用添加特定配置
|
||||
- 配置数据库连接
|
||||
- 以 'prod-' 前缀命名资源
|
||||
- 资源具有 'env: prod' label
|
||||
- 设置合适的 JVM 内存
|
||||
- 健康检查和就绪检查
|
||||
|
||||
首先创建一个工作空间:
|
||||
<!-- @makeDemoHome @testAgainstLatestRelease -->
|
||||
```
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
```
|
||||
|
||||
### 下载资源
|
||||
|
||||
为了保证文档的精简,基础资源都在补充目录中,如果需要请下载它们:
|
||||
<!-- @downloadResources @testAgainstLatestRelease -->
|
||||
```
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/springboot"
|
||||
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/base/{deployment,service}.yaml"
|
||||
```
|
||||
|
||||
### 初始化 kustomization.yaml
|
||||
|
||||
`kustomize` 会从 `kustomization.yaml` 文件中获取指令,创建这个文件:
|
||||
|
||||
<!-- @kustomizeYaml @testAgainstLatestRelease -->
|
||||
```
|
||||
touch $DEMO_HOME/kustomization.yaml
|
||||
```
|
||||
|
||||
### 添加资源
|
||||
|
||||
<!-- @addResources @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
|
||||
kustomize edit add resource service.yaml
|
||||
kustomize edit add resource deployment.yaml
|
||||
|
||||
cat kustomization.yaml
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 resources 字段如下:
|
||||
|
||||
> ```
|
||||
> resources:
|
||||
> - service.yaml
|
||||
> - deployment.yaml
|
||||
> ```
|
||||
|
||||
### 添加 configMap 生成器
|
||||
|
||||
<!-- @addConfigMap @testAgainstLatestRelease -->
|
||||
```
|
||||
echo "app.name=Kustomize Demo" >$DEMO_HOME/application.properties
|
||||
|
||||
kustomize edit add configmap demo-configmap \
|
||||
--from-file application.properties
|
||||
|
||||
cat kustomization.yaml
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 configMapGenerator 字段如下:
|
||||
|
||||
> ```
|
||||
> configMapGenerator:
|
||||
> - files:
|
||||
> - application.properties
|
||||
> name: demo-configmap
|
||||
> ```
|
||||
|
||||
### 定制 configMap
|
||||
|
||||
我们将为生产环境添加数据库连接凭证。通常这些凭据被存放在 `application.properties` 中,然而在有些时候,我们希望将这些凭证保存在其他文件中,而将应用的其他配置保存在 `application.properties` 中。通过这种清晰的分离,这些凭证和应用配置可由不同的团队管理和维护。例如,应用开发人员可以在 `application.properties` 中调整应用程序的配置,而数据库的连接凭证则由运维或 SRE 团队管理和维护。
|
||||
|
||||
对于 Spring Boot 应用,我们可以通过环境变量动态的设置 `spring.profiles.active`,然后应用将获取一个额外的 `application-<profile>.properties` 文件,我们可以分为两步定制这个 ConfigMap:
|
||||
|
||||
1. 通过 patch 添加一个环境变量
|
||||
2. 将文件添加到 ConfigMap 中
|
||||
|
||||
<!-- @customizeConfigMap -->
|
||||
```
|
||||
cat <<EOF >$DEMO_HOME/patch.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: sbdemo
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: sbdemo
|
||||
env:
|
||||
- name: spring.profiles.active
|
||||
value: prod
|
||||
EOF
|
||||
|
||||
kustomize edit add patch --path patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
|
||||
cat <<EOF >$DEMO_HOME/application-prod.properties
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.datasource.url=jdbc:mysql://<prod_database_host>:3306/db_example
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=admin
|
||||
EOF
|
||||
|
||||
kustomize edit add configmap \
|
||||
demo-configmap --from-file application-prod.properties
|
||||
|
||||
cat kustomization.yaml
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 configMapGenerator 字段如下:
|
||||
|
||||
> ```
|
||||
> configMapGenerator:
|
||||
> - files:
|
||||
> - application.properties
|
||||
> - application-prod.properties
|
||||
> name: demo-configmap
|
||||
> ```
|
||||
|
||||
### 定制名称
|
||||
|
||||
为资源添加 _prod-_ 前缀(这些资源将用于生产环境):
|
||||
|
||||
<!-- @customizeLabel @testAgainstLatestRelease -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit set nameprefix 'prod-'
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 namePrefix 字段将会被更新:
|
||||
|
||||
> ```
|
||||
> namePrefix: prod-
|
||||
> ```
|
||||
|
||||
`namePrefix` 将在所有资源的名称前添加 _prod-_ 的前缀,可以通过如下命令查看:
|
||||
|
||||
<!-- @build1 @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME | grep prod-
|
||||
```
|
||||
|
||||
### 定制 Label
|
||||
|
||||
我们希望生产环境的资源包含某些 Label,这样我们就可以通过 label selector 来查询到这些资源。
|
||||
|
||||
`kustomize` 没有 `edit set label` 命令来添加 label,但是可以通过编辑 `kustomization.yaml` 文件来实现:
|
||||
|
||||
<!-- @customizeLabels @testAgainstLatestRelease -->
|
||||
```
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
commonLabels:
|
||||
env: prod
|
||||
EOF
|
||||
```
|
||||
|
||||
现在所有资源都包含 `prod-` 前缀和 `env:prod` label,可以通过下面的命令来查看:
|
||||
|
||||
<!-- @build2 @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME | grep -C 3 env
|
||||
```
|
||||
|
||||
### 下载调整 JVM 内存的 Patch
|
||||
|
||||
当 Spring Boot 应用部署在 k8s 集群中时,JVM 会运行在容器中。我们要为容器设置内存限制,并确保 JVM 知道容器的内存限制。在 k8s 的 Deployment 中,我们可以设置资源容器的资源限制,并将限制注入到一些环境变量中,当容器启动时,其可以获取环境变量并设置相应的 JVM 选项。
|
||||
|
||||
下载 `memorylimit_patch.yaml` 其包含内存限制设置的 patch:
|
||||
|
||||
<!-- @downloadPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/overlays/production/{memorylimit_patch}.yaml"
|
||||
|
||||
cat $DEMO_HOME/memorylimit_patch.yaml
|
||||
```
|
||||
|
||||
输出内容
|
||||
|
||||
> ```
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: sbdemo
|
||||
> spec:
|
||||
> template:
|
||||
> spec:
|
||||
> containers:
|
||||
> - name: sbdemo
|
||||
> resources:
|
||||
> limits:
|
||||
> memory: 1250Mi
|
||||
> requests:
|
||||
> memory: 1250Mi
|
||||
> env:
|
||||
> - name: MEM_TOTAL_MB
|
||||
> valueFrom:
|
||||
> resourceFieldRef:
|
||||
> resource: limits.memory
|
||||
> ```
|
||||
|
||||
### 下载健康检查的 Patch
|
||||
|
||||
我们还可以在生产环境中添加健康检查和就绪检查,Spring Boot 应用都具有类似 `/actuator/health` 的接口用于健康检查,我们可以定制 k8s 的 Deployment 资源来进行健康检查和就绪检查。
|
||||
|
||||
下载 `memorylimit_patch.yaml` 其包含存活和就绪探针的 patch:
|
||||
|
||||
<!-- @downloadPatch @testAgainstLatestRelease -->
|
||||
```
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/overlays/production/{healthcheck_patch}.yaml"
|
||||
|
||||
cat $DEMO_HOME/healthcheck_patch.yaml
|
||||
```
|
||||
|
||||
输出内容
|
||||
|
||||
> ```
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: sbdemo
|
||||
> spec:
|
||||
> template:
|
||||
> spec:
|
||||
> containers:
|
||||
> - name: sbdemo
|
||||
> livenessProbe:
|
||||
> httpGet:
|
||||
> path: /actuator/health
|
||||
> port: 8080
|
||||
> initialDelaySeconds: 10
|
||||
> periodSeconds: 3
|
||||
> readinessProbe:
|
||||
> initialDelaySeconds: 20
|
||||
> periodSeconds: 10
|
||||
> httpGet:
|
||||
> path: /actuator/info
|
||||
> port: 8080
|
||||
> ```
|
||||
|
||||
### 添加 patches
|
||||
|
||||
将这些 patch 添加到 `kustomization.yaml` 中:
|
||||
|
||||
<!-- @addPatch -->
|
||||
```
|
||||
cd $DEMO_HOME
|
||||
kustomize edit add patch --path memorylimit_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
kustomize edit add patch --path healthcheck_patch.yaml --name sbdemo --kind Deployment --group apps --version v1
|
||||
```
|
||||
|
||||
执行上面的命令后,`kustomization.yaml` 的 patches 字段如下:
|
||||
|
||||
> ```
|
||||
> patches:
|
||||
> - path: patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: memorylimit_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> - path: healthcheck_patch.yaml
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: sbdemo
|
||||
> ```
|
||||
|
||||
现在就可以将完整的配置输出并在集群中部署(将结果通过管道输出给 `kubectl apply`),在生产环境创建 Spring Boot 应用。
|
||||
|
||||
<!-- @finalBuild @testAgainstLatestRelease -->
|
||||
```
|
||||
kustomize build $DEMO_HOME # | kubectl apply -f -
|
||||
```
|
||||
171
examples/zh/transformerconfigs.md
Normal file
171
examples/zh/transformerconfigs.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# 自定义 transformer 配置
|
||||
|
||||
Kustomize 通过对原始资源集进行一系列转换来创建新资源。Kustomize 提供以下默认的 transformers :
|
||||
|
||||
- annotations
|
||||
- images
|
||||
- labels
|
||||
- name reference
|
||||
- namespace
|
||||
- prefix/suffix
|
||||
- variable reference
|
||||
|
||||
transformer 配置的 `fieldSpec` 列表,用来确定哪些资源类型和这些类型的 transformer 可以修改哪些字段。
|
||||
|
||||
## FieldSpec
|
||||
|
||||
FieldSpec 是一种表示资源中字段路径的类型。
|
||||
|
||||
```yaml
|
||||
group: some-group
|
||||
version: some-version
|
||||
kind: some-kind
|
||||
path: path/to/the/field
|
||||
create: false
|
||||
```
|
||||
|
||||
如果 `create` 设置为 `true`,表示如果尚未找到该路径,则 transformer 将在资源中创建该路径。这对于 label 和 annotation 转换器最有用,因为在转换之前可能未设置 label 或 annotation 的路径。
|
||||
|
||||
## Images transformer
|
||||
|
||||
默认的 images transformer 会更新包含 `containers` 和 `initcontainers` 子路径的路径中找到的指定镜像的键值 。如果找到,则更新 `image` 的 `newName`,`newTag` 和 `digest` 等字段。该 `name` 字段应与 `image` 资源中的键值匹配。
|
||||
|
||||
kustomization.yaml 示例:
|
||||
|
||||
```yaml
|
||||
images:
|
||||
- name: postgres
|
||||
newName: my-registry/my-postgres
|
||||
newTag: v1
|
||||
- name: nginx
|
||||
newTag: 1.8.0
|
||||
- name: my-demo-app
|
||||
newName: my-app
|
||||
- name: alpine
|
||||
digest: sha256:25a0d4
|
||||
```
|
||||
可以通过创建 `images` 包含 `path` 和 `kind` 字段的列表来自定义镜像 transformer 配置。[镜像 transformer 教程](image.md) 展示了如何指定默认镜像 transformer 和自定义镜像 transformer 配置。
|
||||
|
||||
## Prefix/suffix transformer
|
||||
|
||||
prefix/suffix transformer 为所有资源的 `metadata/name` 字段添加前缀/后缀。默认的 prefix transformer 配置如下:
|
||||
|
||||
```yaml
|
||||
namePrefix:
|
||||
- path: metadata/name
|
||||
```
|
||||
|
||||
kustomization.yaml 示例:
|
||||
|
||||
```yaml
|
||||
|
||||
namePrefix:
|
||||
alices-
|
||||
|
||||
nameSuffix:
|
||||
-v2
|
||||
```
|
||||
|
||||
## Labels transformer
|
||||
|
||||
labels transformer 将 labels 添加到所有资源的 `metadata/labels` 字段。它还将 labels 添加到 `spec/selector` 和 `spec/selector/matchLabels` 字段以及所有 Deployment 资源中的字段。
|
||||
|
||||
示例:
|
||||
|
||||
```yaml
|
||||
commonLabels:
|
||||
- path: metadata/labels
|
||||
create: true
|
||||
|
||||
- path: spec/selector
|
||||
create: true
|
||||
version: v1
|
||||
kind: Service
|
||||
|
||||
- path: spec/selector/matchLabels
|
||||
create: true
|
||||
kind: Deployment
|
||||
```
|
||||
|
||||
kustomization.yaml 示例:
|
||||
|
||||
```yaml
|
||||
commonLabels:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
```
|
||||
|
||||
## Annotations transformer
|
||||
|
||||
annotations transformer 可以:
|
||||
|
||||
- 将 annotations 添加到所有资源的 `metadata/annotations` 字段
|
||||
- 将 annotations 添加到Deployment,ReplicaSet,DaemonSet,StatefulSet,Job 和 CronJob 等资源的 `spec/template/metadata/annotations`
|
||||
- 将 annotations 添加到CronJob 资源的 `spec/jobTemplate/spec/template/metadata/annotations`字段。
|
||||
|
||||
kustomization.yaml 示例:
|
||||
|
||||
```yaml
|
||||
commonAnnotations:
|
||||
oncallPager: 800-555-1212
|
||||
```
|
||||
|
||||
## Name reference transformer
|
||||
|
||||
Name reference transformer 的配置不同于其他所有的 transformer。`nameReferences` 列表代表一种可以用作其他类型资源中的引用的所有可能字段。一个 `nameReference` 包含一个类型如 ConfigMap 以及 `fieldSpecs` 列表,其中 `ConfigMap` 其他资源被引用。下面是一个例子:
|
||||
|
||||
```yaml
|
||||
kind: ConfigMap
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- kind: Pod
|
||||
version: v1
|
||||
path: spec/volumes/configMap/name
|
||||
- kind: Deployment
|
||||
path: spec/template/spec/volumes/configMap/name
|
||||
- kind: Job
|
||||
path: spec/template/spec/volumes/configMap/name
|
||||
```
|
||||
|
||||
Name reference transformer 的配置为 `nameReferences` 列表包含 ConfigMap,Secret,Service,Role和ServiceAccount等资源。下面是一个示例配置:
|
||||
|
||||
```yaml
|
||||
nameReference:
|
||||
- kind: ConfigMap
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- path: spec/volumes/configMap/name
|
||||
version: v1
|
||||
kind: Pod
|
||||
- path: spec/containers/env/valueFrom/configMapKeyRef/name
|
||||
version: v1
|
||||
kind: Pod
|
||||
# ...
|
||||
- kind: Secret
|
||||
version: v1
|
||||
fieldSpecs:
|
||||
- path: spec/volumes/secret/secretName
|
||||
version: v1
|
||||
kind: Pod
|
||||
- path: spec/containers/env/valueFrom/secretKeyRef/name
|
||||
version: v1
|
||||
kind: Pod
|
||||
```
|
||||
|
||||
## Customizing transformer configurations
|
||||
|
||||
除默认 transformers 外,您还可以创建自定义的 transformers 配置。通过调用将默认的 transformers 配置保存到本地目录`kustomize config save -d`,然后修改和使用这些配置。本教程显示了如何创建自定义 transformers 配置:
|
||||
|
||||
- [support a CRD type](../transformerconfigs/crd/README.md)
|
||||
- 添加额外的字段以进行变量替换
|
||||
- 添加额外的字段以供名称参考
|
||||
|
||||
## Supporting escape characters in CRD path
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
annotations:
|
||||
foo.k8s.io/bar: baz
|
||||
```
|
||||
Kustomize 支持在路径中转义特殊字符,例如: `metadata/annotations/foo.k8s.io\/bar`
|
||||
207
examples/zh/validationTransformer.md
Normal file
207
examples/zh/validationTransformer.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# 通过 transformer 验证资源
|
||||
|
||||
[kubeval]: https://github.com/instrumenta/kubeval
|
||||
[插件]: ../../docs/plugins
|
||||
|
||||
kustomize 不会验证其输入或输出是否符合资源要求。
|
||||
|
||||
而另一个工具 [kubeval] 提供了验证 k8s 资源的功能,例如:
|
||||
|
||||
```shell
|
||||
$ kubeval my-invalid-rc.yaml
|
||||
The document my-invalid-rc.yaml contains an invalid ReplicationController
|
||||
--> spec.replicas: Invalid type. Expected: integer, given: string
|
||||
```
|
||||
|
||||
可以创建一个 Kustomize transformer [插件] 通过运行 [kubeval] 来进行验证资源。
|
||||
|
||||
创建一个工作空间:
|
||||
|
||||
<!-- @makeWorkplace @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
mkdir -p $DEMO_HOME/valid
|
||||
mkdir -p $DEMO_HOME/invalid
|
||||
PLUGINDIR=$DEMO_HOME/kustomize/plugin/someteam.example.com/v1/validator
|
||||
mkdir -p $PLUGINDIR
|
||||
```
|
||||
|
||||
## 创建 transformer 插件
|
||||
|
||||
根据操作系统下载 [kubeval] 的二进制文件并将其添加到 $PATH。
|
||||
|
||||
<!-- @downloadKubeval @test -->
|
||||
```bash
|
||||
OS=`uname | sed -e 's/Linux/linux/' -e 's/Darwin/darwin/'`
|
||||
wget https://github.com/instrumenta/kubeval/releases/download/0.9.2/kubeval-${OS}-amd64.tar.gz
|
||||
tar xf kubeval-${OS}-amd64.tar.gz
|
||||
export PATH=$PATH:`pwd`
|
||||
```
|
||||
|
||||
transformer 插件将执行逻辑如下:
|
||||
|
||||
- 从 stdin 中读取资源并传递到 transformer 插件。
|
||||
- transformer 插件的配置文件作为第一个参数传入。
|
||||
- transformer 插件的工作目录是 kustomization 所在目录。
|
||||
- 转换后的资源由插件写入 stdout 。
|
||||
- transformer 返回值为0,则转化成功;如果 transformer 插件的返回值不为0,则 kustomize 认为转化期间存在错误。
|
||||
|
||||
我们可以写一个 bash 脚本作为用于验证资源的 transformer 插件,该脚本执行 [kubeval] 二进制文件并返回正确的输出和退出码。
|
||||
<!-- @writePlugin @test -->
|
||||
```bash
|
||||
cat <<'EOF' > $PLUGINDIR/Validator
|
||||
#!/bin/bash
|
||||
|
||||
if ! [ -x "$(command -v kubeval)" ]; then
|
||||
echo "Error: kubeval is not installed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
temp_file=$(mktemp)
|
||||
output_file=$(mktemp)
|
||||
cat - > $temp_file
|
||||
|
||||
kubeval $temp_file > $output_file
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cat $temp_file
|
||||
rm $temp_file $output_file
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cat $output_file
|
||||
rm $temp_file $output_file
|
||||
exit 1
|
||||
|
||||
EOF
|
||||
chmod +x $PLUGINDIR/Validator
|
||||
```
|
||||
|
||||
## 使用 transformer 插件
|
||||
|
||||
创建一个包含有效 ConfigMap 和 transformer 插件的 Kustomization。
|
||||
|
||||
<!-- @writeKustomization @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/valid/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
foo: bar
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/valid/validation.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: Validator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/valid/kustomization.yaml
|
||||
resources:
|
||||
- configmap.yaml
|
||||
|
||||
transformers:
|
||||
- validation.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
创建一个包含无效 ConfigMap 和 transformer 插件的 Kustomization。
|
||||
|
||||
<!-- @writeKustomization @test -->
|
||||
```bash
|
||||
cat <<'EOF' >$DEMO_HOME/invalid/configmap.yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
data:
|
||||
- foo: bar
|
||||
EOF
|
||||
# ConfigMap 的 data 字段需要传入的数据类型为 object,这里传入一个 array
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/invalid/validation.yaml
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: Validator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
EOF
|
||||
|
||||
cat <<'EOF' >$DEMO_HOME/invalid/kustomization.yaml
|
||||
resources:
|
||||
- configmap.yaml
|
||||
|
||||
transformers:
|
||||
- validation.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
目录结构如下:
|
||||
|
||||
```bash
|
||||
/tmp/tmp.fAYMfLZJs4
|
||||
├── invalid
|
||||
│ ├── configmap.yaml
|
||||
│ ├── kustomization.yaml
|
||||
│ └── validation.yaml
|
||||
├── kustomize
|
||||
│ └── plugin
|
||||
│ └── someteam.example.com
|
||||
│ └── v1
|
||||
│ ├── kubeval
|
||||
│ └── Validator
|
||||
└── valid
|
||||
├── configmap.yaml
|
||||
├── kustomization.yaml
|
||||
└── validation.yaml
|
||||
```
|
||||
|
||||
定义一个 helper 函数在正确的的环境和插件标记运行 kustomize 。
|
||||
|
||||
<!-- @defineKustomizeBd @test -->
|
||||
```bash
|
||||
function kustomizeBd {
|
||||
XDG_CONFIG_HOME=$DEMO_HOME \
|
||||
kustomize build \
|
||||
--enable_alpha_plugins \
|
||||
$DEMO_HOME/$1
|
||||
}
|
||||
```
|
||||
|
||||
构建有效的 variant
|
||||
|
||||
<!-- @buildValid @test -->
|
||||
```bash
|
||||
kustomizeBd valid
|
||||
```
|
||||
输出的 ConfigMap 内容为:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm
|
||||
```
|
||||
|
||||
构建无效的 variant
|
||||
|
||||
```bash
|
||||
kustomizeBd invalid
|
||||
```
|
||||
|
||||
可以查看到输出错误日志为:
|
||||
|
||||
```shell
|
||||
data: Invalid type. Expected: object, given: array
|
||||
```
|
||||
|
||||
## 清理
|
||||
|
||||
<!-- @cleanup @test -->
|
||||
```shell
|
||||
rm -rf $DEMO_HOME
|
||||
```
|
||||
149
examples/zh/vars.md
Normal file
149
examples/zh/vars.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# 示例: 将 k8s runtime 数据注入容器
|
||||
|
||||
本教程将会介绍如何声明变量以及如何在容器中的命令使用变量。要注意的是,变量的查找和替换并不适用于任意字段,默认仅适用于容器的env,args和command。
|
||||
|
||||
运行WordPress,以下是必须的:
|
||||
|
||||
- WordPress 连接 MySQL 数据库
|
||||
- MySQL 服务可以被 WordPress 容器访问
|
||||
|
||||
首先构建一个工作空间:
|
||||
<!-- @makeDemoHome @test -->
|
||||
```bash
|
||||
DEMO_HOME=$(mktemp -d)
|
||||
MYSQL_HOME=$DEMO_HOME/mysql
|
||||
mkdir -p $MYSQL_HOME
|
||||
WORDPRESS_HOME=$DEMO_HOME/wordpress
|
||||
mkdir -p $WORDPRESS_HOME
|
||||
```
|
||||
|
||||
### 下载 resources
|
||||
|
||||
下载 WordPress 的 resources 和 `kustomization.yaml` 。
|
||||
|
||||
<!-- @downloadResources @test -->
|
||||
```bash
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/wordpress/wordpress"
|
||||
|
||||
curl -s -o "$WORDPRESS_HOME/#1.yaml" \
|
||||
"$CONTENT/{deployment,service,kustomization}.yaml"
|
||||
```
|
||||
|
||||
下载 MySQL 的 resources 和 `kustomization.yaml` 。
|
||||
|
||||
<!-- @downloadResources @test -->
|
||||
```bash
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/wordpress/mysql"
|
||||
|
||||
curl -s -o "$MYSQL_HOME/#1.yaml" \
|
||||
"$CONTENT/{deployment,service,secret,kustomization}.yaml"
|
||||
```
|
||||
|
||||
### 创建 kustomization.yaml
|
||||
|
||||
基于 `wordpress` 和 `mysql` 的两个 bases 创建一个新的 `kustomization.yaml` :
|
||||
|
||||
<!-- @createKustomization @test -->
|
||||
```bash
|
||||
cat <<EOF >$DEMO_HOME/kustomization.yaml
|
||||
resources:
|
||||
- wordpress
|
||||
- mysql
|
||||
namePrefix: demo-
|
||||
patchesStrategicMerge:
|
||||
- patch.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
### 下载 WordPress 的 patchs
|
||||
|
||||
在新的 kustomization 中应用 WordPress Deployment 的 patch ,该 patch 包含:
|
||||
- 添加初始容器来显示mysql的服务名称
|
||||
- 添加允许 wordpress 查找到 mysql 数据库的环境变量
|
||||
|
||||
<!-- @downloadPatch @test -->
|
||||
```bash
|
||||
CONTENT="https://raw.githubusercontent.com\
|
||||
/kubernetes-sigs/kustomize\
|
||||
/master/examples/wordpress"
|
||||
|
||||
curl -s -o "$DEMO_HOME/#1.yaml" \
|
||||
"$CONTENT/{patch}.yaml"
|
||||
```
|
||||
该 patch 内容如下:
|
||||
> ```yaml
|
||||
> apiVersion: apps/v1
|
||||
> kind: Deployment
|
||||
> metadata:
|
||||
> name: wordpress
|
||||
> spec:
|
||||
> template:
|
||||
> spec:
|
||||
> initContainers:
|
||||
> - name: init-command
|
||||
> image: debian
|
||||
> command: ["/bin/sh"]
|
||||
> args: ["-c", "echo $(WORDPRESS_SERVICE); echo $(MYSQL_SERVICE)"]
|
||||
> containers:
|
||||
> - name: wordpress
|
||||
> env:
|
||||
> - name: WORDPRESS_DB_HOST
|
||||
> value: $(MYSQL_SERVICE)
|
||||
> - name: WORDPRESS_DB_PASSWORD
|
||||
> valueFrom:
|
||||
> secretKeyRef:
|
||||
> name: mysql-pass
|
||||
> key: password
|
||||
> ```
|
||||
初始化容器的命令需要依赖于k8s资源对象字段的信息,由占位符变量 $(WORDPRESS_SERVICE) 和 $(MYSQL_SERVICE) 表示。
|
||||
|
||||
### 将变量绑定到k8s对象字段
|
||||
|
||||
<!-- @addVarRef @test -->
|
||||
```bash
|
||||
cat <<EOF >>$DEMO_HOME/kustomization.yaml
|
||||
vars:
|
||||
- name: WORDPRESS_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: wordpress
|
||||
apiVersion: v1
|
||||
fieldref:
|
||||
fieldpath: metadata.name
|
||||
- name: MYSQL_SERVICE
|
||||
objref:
|
||||
kind: Service
|
||||
name: mysql
|
||||
apiVersion: v1
|
||||
EOF
|
||||
```
|
||||
`WORDPRESS_SERVICE` 来自 `wordpress` 服务的 `metadata.name` 字段。如果不指定 `fieldref` ,则使用默认的 `metadata.name` 。因此 `MYSQL_SERVICE` 来自 `mysql` 服务的 `metadata.name` 字段。
|
||||
|
||||
### 替换
|
||||
|
||||
运行命令查看替换结果:
|
||||
|
||||
<!-- @kustomizeBuild @test -->
|
||||
```bash
|
||||
kustomize build $DEMO_HOME
|
||||
```
|
||||
|
||||
预期的输出为:
|
||||
|
||||
> ```yaml
|
||||
> (truncated)
|
||||
> ...
|
||||
> initContainers:
|
||||
> - args:
|
||||
> - -c
|
||||
> - echo demo-wordpress; echo demo-mysql
|
||||
> command:
|
||||
> - /bin/sh
|
||||
> image: debian
|
||||
> name: init-command
|
||||
>
|
||||
> ```
|
||||
Reference in New Issue
Block a user