mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-11 17:12:51 +00:00
Remove duplicate kustomize docs content
This commit is contained in:
@@ -9,4 +9,6 @@ menu:
|
||||
description: >
|
||||
Reference for Kustomize usage and best practices
|
||||
---
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/config_management" />
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/config_management" />
|
||||
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -9,76 +9,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/config_management/bespoke/" />
|
||||
|
||||
|
||||
In this workflow, all configuration (resource YAML) files are owned by the user.
|
||||
No content is incorporated from version control repositories owned by others.
|
||||
|
||||
![bespoke config workflow image][workflowBespoke]
|
||||
|
||||
#### 1) create a directory in version control
|
||||
|
||||
Speculate some overall cluster application called _ldap_;
|
||||
we want to keep its configuration in its own repo.
|
||||
|
||||
> ```
|
||||
> git init ~/ldap
|
||||
> ```
|
||||
|
||||
#### 2) create a [base]
|
||||
|
||||
> ```
|
||||
> mkdir -p ~/ldap/base
|
||||
> ```
|
||||
|
||||
In this directory, create and commit a [kustomization]
|
||||
file and a set of [resources].
|
||||
|
||||
#### 3) create [overlays]
|
||||
|
||||
> ```
|
||||
> mkdir -p ~/ldap/overlays/staging
|
||||
> mkdir -p ~/ldap/overlays/production
|
||||
> ```
|
||||
|
||||
Each of these directories needs a [kustomization]
|
||||
file and one or more [patches].
|
||||
|
||||
The _staging_ directory might get a patch
|
||||
that turns on an experiment flag in a configmap.
|
||||
|
||||
The _production_ directory might get a patch
|
||||
that increases the replica count in a deployment
|
||||
specified in the base.
|
||||
|
||||
#### 4) bring up [variants]
|
||||
|
||||
Run kustomize, and pipe the output to [apply].
|
||||
|
||||
> ```
|
||||
> kustomize build ~/ldap/overlays/staging | kubectl apply -f -
|
||||
> kustomize build ~/ldap/overlays/production | kubectl apply -f -
|
||||
> ```
|
||||
|
||||
You can also use [kubectl-v1.14.0] to apply your [variants].
|
||||
>
|
||||
> ```
|
||||
> kubectl apply -k ~/ldap/overlays/staging
|
||||
> kubectl apply -k ~/ldap/overlays/production
|
||||
> ```
|
||||
|
||||
[OTS]: /kustomize/api-reference/glossary#off-the-shelf-configuration
|
||||
[apply]: /kustomize/api-reference/glossary#apply
|
||||
[applying]: /kustomize/api-reference/glossary#apply
|
||||
[base]: /kustomize/api-reference/glossary#base
|
||||
[fork]: https://guides.github.com/activities/forking/
|
||||
[variants]: /kustomize/api-reference/glossary#variant
|
||||
[kustomization]: /kustomize/api-reference/glossary#kustomization
|
||||
[off-the-shelf]: /kustomize/api-reference/glossary#off-the-shelf-configuration
|
||||
[overlays]: /kustomize/api-reference/glossary#overlay
|
||||
[patch]: /kustomize/api-reference/glossary#patch
|
||||
[patches]: /kustomize/api-reference/glossary#patch
|
||||
[rebase]: https://git-scm.com/docs/git-rebase
|
||||
[resources]: /kustomize/api-reference/glossary#resource
|
||||
[workflowBespoke]: /kustomize/images/workflowBespoke.jpg
|
||||
[workflowOts]: /kustomize/images/workflowOts.jpg
|
||||
[kubectl-v1.14.0]:https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement/
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "Command Line Options"
|
||||
linkTitle: "Command Line Options"
|
||||
type: docs
|
||||
description: >
|
||||
Usage of command line options
|
||||
---
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "build"
|
||||
linkTitle: "build"
|
||||
type: docs
|
||||
description: >
|
||||
Print configuration per contents of kustomization.yaml
|
||||
---
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "cfg"
|
||||
linkTitle: "cfg"
|
||||
type: docs
|
||||
description: >
|
||||
Commands for reading and writing configuration.
|
||||
---
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "create"
|
||||
linkTitle: "create"
|
||||
type: docs
|
||||
description: >
|
||||
Create a new kustomization in the current directory
|
||||
---
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "edit"
|
||||
linkTitle: "edit"
|
||||
type: docs
|
||||
description: >
|
||||
Edits a kustomization file
|
||||
---
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "fn"
|
||||
linkTitle: "fn"
|
||||
type: docs
|
||||
description: >
|
||||
Commands for running functions against configuration
|
||||
---
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
title: "help"
|
||||
linkTitle: "help"
|
||||
type: docs
|
||||
description: >
|
||||
Help about any command
|
||||
---
|
||||
|
||||
> ```
|
||||
> kustomize help
|
||||
>
|
||||
> Manages declarative configuration of Kubernetes.
|
||||
> See https://sigs.k8s.io/kustomize
|
||||
>
|
||||
> Usage:
|
||||
> kustomize [command]
|
||||
>
|
||||
> Available Commands:
|
||||
> build Print configuration per contents of kustomization.yaml
|
||||
> cfg Commands for reading and writing configuration.
|
||||
> create Create a new kustomization in the current directory
|
||||
> edit Edits a kustomization file
|
||||
> fn Commands for running functions against configuration.
|
||||
> help Help about any command
|
||||
> install-completion Install shell completion.
|
||||
> live Commands for reading and writing resources to a cluster.
|
||||
> version Prints the kustomize version
|
||||
>
|
||||
> Flags:
|
||||
> -h, --help help for kustomize
|
||||
> --stack-trace print a stack-trace on error
|
||||
>
|
||||
> Additional help topics:
|
||||
> kustomize docs-fn [Alpha] Documentation for developing and invoking Configuration Functions.
|
||||
> kustomize docs-fn-spec [Alpha] Documentation for Configuration Functions Specification.
|
||||
> kustomize docs-io-annotations [Alpha] Documentation for annotations used by io.
|
||||
> kustomize docs-merge [Alpha] Documentation for merging Resources (2-way merge).
|
||||
> kustomize docs-merge3 [Alpha] Documentation for merging Resources (3-way merge).
|
||||
> kustomize tutorials-command-basics [Alpha] Tutorials for using basic config commands.
|
||||
> kustomize tutorials-function-basics [Alpha] Tutorials for using functions.
|
||||
>
|
||||
> Use "kustomize [command] --help" for more information about a command.
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "install-completion"
|
||||
linkTitle: "install-completion"
|
||||
type: docs
|
||||
description: >
|
||||
Installs shell completion
|
||||
---
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
title: "live"
|
||||
linkTitle: "live"
|
||||
type: docs
|
||||
description: >
|
||||
Commands for reading and writing resources to a cluster.
|
||||
---
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
title: "version"
|
||||
linkTitle: "version"
|
||||
type: docs
|
||||
description: >
|
||||
Prints the kustomize version
|
||||
---
|
||||
|
||||
Prints the current kustomize version
|
||||
|
||||
> ```
|
||||
> kustomize version
|
||||
> {Version:kustomize/v3.8.1 GitCommit:0b359d0ef0272e6545eda0e99aacd63aef99c4d0 BuildDate:2020-07-16T00:58:46Z GoOs:linux GoArch:amd64}
|
||||
> ```
|
||||
@@ -8,365 +8,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/config_management/components/" />
|
||||
|
||||
|
||||
As of ``v3.7.0`` Kustomize supports a special type of kustomization that allows
|
||||
one to define reusable pieces of configuration logic that can be included from
|
||||
multiple overlays.
|
||||
|
||||
Components come in handy when dealing with applications that support multiple
|
||||
optional features and you wish to enable only a subset of them in different
|
||||
overlays, i.e., different features for different environments or audiences.
|
||||
|
||||
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.md).
|
||||
|
||||
## Use case
|
||||
|
||||
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 | ✔️ | | ✔️ |
|
||||
| Enterprise | ✔️ | ✔️ | |
|
||||
| Dev | ✅ | ✅ | ✅ |
|
||||
|
||||
(✔️ enabled, ✅: optional)
|
||||
|
||||
So, you want to make it easy to deploy your application in any of the above
|
||||
three environments. Here's how you can do this with Kustomize components: each
|
||||
opt-in feature gets packaged as a component, so that it can be referred to from
|
||||
multiple 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 the 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 generate the YAML manifests for each deployment
|
||||
using `kustomize build`:
|
||||
|
||||
```shell
|
||||
kustomize build overlays/community
|
||||
kustomize build overlays/enterprise
|
||||
kustomize build overlays/dev
|
||||
```
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -9,78 +9,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/config_management/offtheshelf/" />
|
||||
|
||||
|
||||
In this workflow, all files are owned by the user and maintained in a repository under their control, but
|
||||
they are based on an [off-the-shelf] configuration that is periodically consulted for updates.
|
||||
|
||||
![off-the-shelf config workflow image][workflowOts]
|
||||
|
||||
#### 1) find and [fork] an [OTS] config
|
||||
|
||||
#### 2) clone it as your [base]
|
||||
|
||||
The [base] directory is maintained in a repo whose upstream is an [OTS] configuration, in this case
|
||||
some user's `ldap` repo:
|
||||
|
||||
> ```
|
||||
> mkdir ~/ldap
|
||||
> git clone https://github.com/$USER/ldap ~/ldap/base
|
||||
> cd ~/ldap/base
|
||||
> git remote add upstream git@github.com:$USER/ldap
|
||||
> ```
|
||||
|
||||
#### 3) create [overlays]
|
||||
|
||||
As in the bespoke case above, create and populate an _overlays_ directory.
|
||||
|
||||
The [overlays] are siblings to each other and to the [base] they depend on.
|
||||
|
||||
> ```
|
||||
> mkdir -p ~/ldap/overlays/staging
|
||||
> mkdir -p ~/ldap/overlays/production
|
||||
> ```
|
||||
|
||||
The user can maintain the `overlays` directory in a
|
||||
distinct repository.
|
||||
|
||||
#### 4) bring up [variants]
|
||||
|
||||
> ```
|
||||
> kustomize build ~/ldap/overlays/staging | kubectl apply -f -
|
||||
> kustomize build ~/ldap/overlays/production | kubectl apply -f -
|
||||
> ```
|
||||
|
||||
You can also use [kubectl-v1.14.0] to apply your [variants].
|
||||
>
|
||||
> ```
|
||||
> kubectl apply -k ~/ldap/overlays/staging
|
||||
> kubectl apply -k ~/ldap/overlays/production
|
||||
> ```
|
||||
|
||||
#### 5) (optionally) capture changes from upstream
|
||||
|
||||
The user can periodically [rebase] their [base] to
|
||||
capture changes made in the upstream repository.
|
||||
|
||||
> ```
|
||||
> cd ~/ldap/base
|
||||
> git fetch upstream
|
||||
> git rebase upstream/master
|
||||
> ```
|
||||
|
||||
[OTS]: /kustomize/api-reference/glossary#off-the-shelf-configuration
|
||||
[apply]: /kustomize/api-reference/glossary#apply
|
||||
[applying]: /kustomize/api-reference/glossary#apply
|
||||
[base]: /kustomize/api-reference/glossary#base
|
||||
[fork]: https://guides.github.com/activities/forking/
|
||||
[variants]: /kustomize/api-reference/glossary#variant
|
||||
[kustomization]: /kustomize/api-reference/glossary#kustomization
|
||||
[off-the-shelf]: /kustomize/api-reference/glossary#off-the-shelf-configuration
|
||||
[overlays]: /kustomize/api-reference/glossary#overlay
|
||||
[patch]: /kustomize/api-reference/glossary#patch
|
||||
[patches]: /kustomize/api-reference/glossary#patch
|
||||
[rebase]: https://git-scm.com/docs/git-rebase
|
||||
[resources]: /kustomize/api-reference/glossary#resource
|
||||
[workflowBespoke]: /kustomize/images/workflowBespoke.jpg
|
||||
[workflowOts]: /kustomize/images/workflowOts.jpg
|
||||
[kubectl-v1.14.0]:https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement/
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -9,372 +9,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/extending_kustomize/plugins" />
|
||||
|
||||
Kustomize offers a plugin framework allowing people to write their own resource _generators_
|
||||
and _transformers_.
|
||||
|
||||
[generator options]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/generatorOptions.md
|
||||
[transformer configs]: https://github.com/kubernetes-sigs/kustomize/tree/master/examples/transformerconfigs
|
||||
|
||||
Write a plugin when changing [generator options]
|
||||
or [transformer configs] doesn't meet your needs.
|
||||
|
||||
[12-factor]: https://12factor.net
|
||||
|
||||
* A _generator_ plugin could be a helm chart
|
||||
inflator, or a plugin that emits all the
|
||||
components (deployment, service, scaler,
|
||||
ingress, etc.) needed by someone's [12-factor]
|
||||
application, based on a smaller number of free
|
||||
variables.
|
||||
|
||||
* A _transformer_ plugin might perform special
|
||||
container command line edits, or any other
|
||||
transformation beyond those provided by the
|
||||
builtin (`namePrefix`, `commonLabels`, etc.)
|
||||
transformers.
|
||||
|
||||
## Specification in `kustomization.yaml`
|
||||
|
||||
Start by adding a `generators` and/or `transformers`
|
||||
field to your kustomization.
|
||||
|
||||
Each field accepts a string list:
|
||||
|
||||
> ```
|
||||
> generators:
|
||||
> - relative/path/to/some/file.yaml
|
||||
> - relative/path/to/some/kustomization
|
||||
> - /absolute/path/to/some/kustomization
|
||||
> - https://github.com/org/repo/some/kustomization
|
||||
>
|
||||
> transformers:
|
||||
> - {as above}
|
||||
> ```
|
||||
|
||||
The value of each entry in a `generators` or
|
||||
`transformers` list must be a relative path to a
|
||||
YAML file, or a path or URL to a [kustomization].
|
||||
This is the same format as demanded by the
|
||||
`resources` field.
|
||||
|
||||
[kustomization]: /kustomize/api-reference/glossary#kustomization
|
||||
|
||||
YAML files are read from disk directly. Paths or
|
||||
URLs leading to kustomizations trigger an
|
||||
in-process kustomization run. Each of the
|
||||
resulting objects is now further interpreted by
|
||||
kustomize as a _plugin configuration_ object.
|
||||
|
||||
## Configuration
|
||||
|
||||
A kustomization file could have the following lines:
|
||||
|
||||
```
|
||||
generators:
|
||||
- chartInflator.yaml
|
||||
```
|
||||
|
||||
Given this, the kustomization process would expect
|
||||
to find a file called `chartInflator.yaml` in the
|
||||
kustomization [root](/kustomize/api-reference/glossary#kustomization-root).
|
||||
|
||||
This is the plugin's configuration file;
|
||||
it contains a YAML configuration object.
|
||||
|
||||
The file `chartInflator.yaml` could contain:
|
||||
|
||||
```
|
||||
apiVersion: someteam.example.com/v1
|
||||
kind: ChartInflator
|
||||
metadata:
|
||||
name: notImportantHere
|
||||
chartName: minecraft
|
||||
```
|
||||
|
||||
__The `apiVersion` and `kind` fields are
|
||||
used to locate the plugin.__
|
||||
|
||||
[k8s object]: /kustomize/api-reference/glossary#kubernetes-style-object
|
||||
|
||||
Thus, these fields are required. They are also
|
||||
required because a kustomize plugin configuration
|
||||
object is also a [k8s object].
|
||||
|
||||
To get the plugin ready to generate or transform,
|
||||
it is given the entire contents of the
|
||||
configuration file.
|
||||
|
||||
[NameTransformer]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/builtin/prefixsuffixtransformer/PrefixSuffixTransformer_test.go
|
||||
[ChartInflator]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/chartinflator/ChartInflator_test.go
|
||||
[plugins]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/builtin
|
||||
|
||||
For more examples of plugin configuration YAML,
|
||||
browse the unit tests below the [plugins] root,
|
||||
e.g. the tests for [ChartInflator] or
|
||||
[NameTransformer].
|
||||
|
||||
## Placement
|
||||
|
||||
Each plugin gets its own dedicated directory named
|
||||
|
||||
[`XDG_CONFIG_HOME`]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
|
||||
```
|
||||
$XDG_CONFIG_HOME/kustomize/plugin
|
||||
/${apiVersion}/LOWERCASE(${kind})
|
||||
```
|
||||
|
||||
The default value of [`XDG_CONFIG_HOME`] is
|
||||
`$HOME/.config`.
|
||||
|
||||
The one-plugin-per-directory requirement eases
|
||||
creation of a plugin bundle (source, tests, plugin
|
||||
data files, etc.) for sharing.
|
||||
|
||||
In the case of a [Go plugin](#go-plugins), it also
|
||||
allows one to provide a `go.mod` file for the
|
||||
single plugin, easing resolution of package
|
||||
version dependency skew.
|
||||
|
||||
When loading, kustomize will first look for an
|
||||
_executable_ file called
|
||||
|
||||
```
|
||||
$XDG_CONFIG_HOME/kustomize/plugin
|
||||
/${apiVersion}/LOWERCASE(${kind})/${kind}
|
||||
```
|
||||
|
||||
If this file is not found or is not executable,
|
||||
kustomize will look for a file called `${kind}.so`
|
||||
in the same directory and attempt to load it as a
|
||||
[Go plugin](#go-plugins).
|
||||
|
||||
If both checks fail, the plugin load fails the overall
|
||||
`kustomize build`.
|
||||
|
||||
## Execution
|
||||
|
||||
Plugins are only used during a run of the
|
||||
`kustomize build` command.
|
||||
|
||||
Generator plugins are run after processing the
|
||||
`resources` field (which itself can be viewed as a
|
||||
generator, simply reading objects from disk).
|
||||
|
||||
The full set of resources is then passed into the
|
||||
transformation pipeline, wherein builtin
|
||||
transformations like `namePrefix` and
|
||||
`commonLabel` are applied (if they were specified
|
||||
in the kustomization file), followed by the
|
||||
user-specified transformers in the `transformers`
|
||||
field.
|
||||
|
||||
The order specified in the `transformers` field is
|
||||
respected, as transformers cannot be expected to
|
||||
be commutative.
|
||||
|
||||
#### No Security
|
||||
|
||||
Kustomize plugins do not run in any kind of
|
||||
kustomize-provided sandbox. There's no notion
|
||||
of _"plugin security"_.
|
||||
|
||||
A `kustomize build` that tries to use plugins but
|
||||
omits the flag
|
||||
|
||||
> `--enable_alpha_plugins`
|
||||
|
||||
will not load plugins and will fail with a
|
||||
warning about plugin use.
|
||||
|
||||
The use of this flag is an opt-in acknowledging
|
||||
the unstable (alpha) plugin API, the absence of
|
||||
plugin provenance, and the fact that a plugin
|
||||
is not part of kustomize.
|
||||
|
||||
To be clear, some kustomize plugin downloaded
|
||||
from the internet might wonderfully transform
|
||||
k8s config in a desired manner, while also
|
||||
quietly doing anything the user could do to the
|
||||
system running `kustomize build`.
|
||||
|
||||
## Authoring
|
||||
|
||||
There are two kinds of plugins, [exec](#exec-plugins) and [Go](#go-plugins).
|
||||
|
||||
### Exec plugins
|
||||
|
||||
A _exec plugin_ is any executable that accepts a
|
||||
single argument on its command line - the name of
|
||||
a YAML file containing its configuration (the file name
|
||||
provided in the kustomization file).
|
||||
|
||||
> TODO: restrictions on plugin to allow the _same exec
|
||||
> plugin_ to be targeted by both the
|
||||
> `generators` and `transformers` fields.
|
||||
>
|
||||
> - first arg could be the fixed string
|
||||
> `generate` or `transform`,
|
||||
> (the name of the configuration file moves to
|
||||
> the 2nd arg), or
|
||||
> - or by default an exec plugin behaves as a tranformer
|
||||
> unless a flag `-g` is provided, switching the
|
||||
> exec plugin to behave as a generator.
|
||||
|
||||
[helm chart inflator]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/chartinflator
|
||||
[bashed config map]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/bashedconfigmap
|
||||
[sed transformer]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/sedtransformer
|
||||
[hashicorp go-getter]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/gogetter
|
||||
|
||||
#### Examples
|
||||
|
||||
* [helm chart inflator] - A generator that inflates a helm chart.
|
||||
* [bashed config map] - Super simple configMap generation from bash.
|
||||
* [sed transformer] - Define your unstructured edits using a
|
||||
plugin like this one.
|
||||
* [hashicorp go-getter] - Download kustomize layes and build it to generate resources
|
||||
|
||||
A generator plugin accepts nothing on `stdin`, but emits
|
||||
generated resources to `stdout`.
|
||||
|
||||
A transformer plugin accepts resource YAML on `stdin`,
|
||||
and emits those resources, presumably transformed, to
|
||||
`stdout`.
|
||||
|
||||
kustomize uses an exec plugin adapter to provide
|
||||
marshalled resources on `stdin` and capture
|
||||
`stdout` for further processing.
|
||||
|
||||
#### Generator Options
|
||||
|
||||
A generator exec plugin can adjust the generator options for the resources it emits by setting one of the following internal annotations.
|
||||
|
||||
> NOTE: These annotations are local to kustomize and will not be included in the final output.
|
||||
|
||||
**`kustomize.config.k8s.io/needs-hash`**
|
||||
|
||||
Resources can be marked as needing to be processed by the internal hash transformer by including the `needs-hash` annotation. When set valid values for the annotation are `"true"` and `"false"` which respectively enable or disable hash suffixing for the resource. Omitting the annotation is equivalent to setting the value `"false"`.
|
||||
|
||||
Hashes are determined as follows:
|
||||
|
||||
* For `ConfigMap` resources, hashes are based on the values of the `name`, `data`, and `binaryData` fields.
|
||||
* For `Secret` resources, hashes are based on the values of the `name`, `type`, `data`, and `stringData` fields.
|
||||
* For any other object type, hashes are based on the entire object content (i.e. all fields).
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-test
|
||||
annotations:
|
||||
kustomize.config.k8s.io/needs-hash: "true"
|
||||
data:
|
||||
foo: bar
|
||||
```
|
||||
|
||||
**`kustomize.config.k8s.io/behavior`**
|
||||
|
||||
The `behavior` annotation will influence how conflicts are handled for resources emitted by the plugin. Valid values include "create", "merge", and "replace" with "create" being the default.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cm-test
|
||||
annotations:
|
||||
kustomize.config.k8s.io/behavior: "merge"
|
||||
data:
|
||||
foo: bar
|
||||
```
|
||||
|
||||
### Go plugins
|
||||
|
||||
Be sure to read [Go plugin caveats](goplugincaveats/).
|
||||
|
||||
[Go plugin]: https://golang.org/pkg/plugin/
|
||||
|
||||
A `.go` file can be a [Go plugin] if it declares
|
||||
'main' as it's package, and exports a symbol to
|
||||
which useful functions are attached.
|
||||
|
||||
It can further be used as a _kustomize_ plugin if
|
||||
the symbol is named 'KustomizePlugin' and the
|
||||
attached functions implement the `Configurable`,
|
||||
`Generator` and `Transformer` interfaces.
|
||||
|
||||
A Go plugin for kustomize looks like this:
|
||||
|
||||
> ```
|
||||
> package main
|
||||
>
|
||||
> import (
|
||||
> "sigs.k8s.io/kustomize/api/resmap"
|
||||
> ...
|
||||
> )
|
||||
>
|
||||
> type plugin struct {...}
|
||||
>
|
||||
> var KustomizePlugin plugin
|
||||
>
|
||||
> func (p *plugin) Config(
|
||||
> h *resmap.PluginHelpers,
|
||||
> c []byte) error {...}
|
||||
>
|
||||
> func (p *plugin) Generate() (resmap.ResMap, error) {...}
|
||||
>
|
||||
> func (p *plugin) Transform(m resmap.ResMap) error {...}
|
||||
> ```
|
||||
|
||||
Use of the identifiers `plugin`, `KustomizePlugin`
|
||||
and implementation of the method signature
|
||||
`Config` is required.
|
||||
|
||||
Implementing the `Generator` or `Transformer`
|
||||
method allows (respectively) the plugin's config
|
||||
file to be added to the `generators` or
|
||||
`transformers` field in the kustomization file.
|
||||
Do one or the other or both as desired.
|
||||
|
||||
[secret generator]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/secretsfromdatabase
|
||||
[service generator]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/someservicegenerator
|
||||
[string prefixer]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/stringprefixer
|
||||
[date prefixer]: https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/someteam.example.com/v1/dateprefixer
|
||||
[sops encoded secrets]: https://github.com/monopole/sopsencodedsecrets
|
||||
[SOPSGenerator]: https://github.com/omninonsense/kustomize-sopsgenerator
|
||||
|
||||
#### Examples
|
||||
|
||||
* [service generator] - generate a service from a name and port argument.
|
||||
* [string prefixer] - uses the value in `metadata/name` as the prefix.
|
||||
This particular example exists to show how a plugin can
|
||||
transform the behavior of a plugin. See the
|
||||
`TestTransformedTransformers` test in the `target` package.
|
||||
* [date prefixer] - prefix the current date to resource names, a simple
|
||||
example used to modify the string prefixer plugin just mentioned.
|
||||
* [secret generator] - generate secrets from a toy database.
|
||||
* [sops encoded secrets] - a more complex secret generator that converts SOPS files into Kubernetes Secrets
|
||||
* [SOPSGenerator] - another generator that decrypts SOPS files into Secrets
|
||||
* [All the builtin plugins](https://github.com/kubernetes-sigs/kustomize/tree/master/plugin/builtin).
|
||||
User authored plugins are
|
||||
on the same footing as builtin operations.
|
||||
|
||||
A Go plugin can be both a generator and a
|
||||
transformer. The `Generate` method will run along
|
||||
with all the other generators before the
|
||||
`Transform` method runs.
|
||||
|
||||
Here's a build command that sensibly assumes the
|
||||
plugin source code sits in the directory where
|
||||
kustomize expects to find `.so` files:
|
||||
|
||||
```
|
||||
d=$XDG_CONFIG_HOME/kustomize/plugin\
|
||||
/${apiVersion}/LOWERCASE(${kind})
|
||||
|
||||
go build -buildmode plugin \
|
||||
-o $d/${kind}.so $d/${kind}.go
|
||||
```
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -8,793 +8,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/extending_kustomize/builtins" />
|
||||
|
||||
|
||||
# Builtin Plugins
|
||||
|
||||
A list of kustomize's builtin plugins - both
|
||||
generators and transformers.
|
||||
|
||||
For each plugin, an example is given for
|
||||
|
||||
- implicitly triggering
|
||||
the plugin via a dedicated kustomization
|
||||
file field (e.g. the `AnnotationsTransformer` is
|
||||
triggered by the `commonAnnotations` field).
|
||||
|
||||
- explicitly triggering the plugin
|
||||
via the `generators` or `transformers` field
|
||||
(by providing a config file specifying the
|
||||
plugin).
|
||||
|
||||
The former method is convenient but limited in
|
||||
power as most of the plugins arguments must
|
||||
be defaulted. The latter method allows for
|
||||
complete plugin argument specification.
|
||||
|
||||
[types.generatoroptions]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/generatoroptions.go
|
||||
[types.secretargs]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/secretargs.go
|
||||
[types.configmapargs]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/configmapargs.go
|
||||
[config.fieldspec]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go
|
||||
[types.objectmeta]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/objectmeta.go
|
||||
[types.selector]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/selector.go
|
||||
[types.replica]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/replica.go
|
||||
[types.patchstrategicmerge]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/patchstrategicmerge.go
|
||||
[types.patchtarget]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/patchtarget.go
|
||||
[image.image]: https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/image.go
|
||||
|
||||
## _AnnotationTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `commonAnnotations`
|
||||
|
||||
Adds annotions (non-identifying metadata) to add
|
||||
all resources. Like labels, these are key value
|
||||
pairs.
|
||||
|
||||
```
|
||||
commonAnnotations:
|
||||
oncallPager: 800-555-1212
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Annotations map\[string\]string
|
||||
>
|
||||
> FieldSpecs \[\][config.FieldSpec]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: AnnotationsTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> annotations:
|
||||
> app: myApp
|
||||
> greeting/morning: a string with blanks
|
||||
> fieldSpecs:
|
||||
> - path: metadata/annotations
|
||||
> create: true
|
||||
> ```
|
||||
|
||||
## _ConfigMapGenerator_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `configMapGenerator`
|
||||
|
||||
Each entry in this list results in the creation of
|
||||
one ConfigMap resource (it's a generator of n maps).
|
||||
|
||||
The example below creates three ConfigMaps. One with the names and contents of
|
||||
the given files, one with key/value as data, and a third which sets an
|
||||
annotation and label via `options` for that single ConfigMap.
|
||||
|
||||
Each configMapGenerator item accepts a parameter of
|
||||
`behavior: [create|replace|merge]`.
|
||||
This allows an overlay to modify or
|
||||
replace an existing configMap from the parent.
|
||||
|
||||
Also, each entry has an `options` field, that has the
|
||||
same subfields as the kustomization file's `generatorOptions` field.
|
||||
|
||||
This `options` field allows one to add labels and/or
|
||||
annotations to the generated instance, or to individually
|
||||
disable the name suffix hash for that instance.
|
||||
Labels and annotations added here will not be overwritten
|
||||
by the global options associated with the kustomization
|
||||
file `generatorOptions` field. However, due to how
|
||||
booleans behave, if the global `generatorOptions` field
|
||||
specifies `disableNameSuffixHash: true`, this will
|
||||
trump any attempt to locally override it.
|
||||
|
||||
```
|
||||
# These labels are added to all configmaps and secrets.
|
||||
generatorOptions:
|
||||
labels:
|
||||
fruit: apple
|
||||
|
||||
configMapGenerator:
|
||||
- name: my-java-server-props
|
||||
behavior: merge
|
||||
files:
|
||||
- application.properties
|
||||
- more.properties
|
||||
- name: my-java-server-env-vars
|
||||
literals:
|
||||
- JAVA_HOME=/opt/java/jdk
|
||||
- JAVA_TOOL_OPTIONS=-agentlib:hprof
|
||||
options:
|
||||
disableNameSuffixHash: true
|
||||
labels:
|
||||
pet: dog
|
||||
- name: dashboards
|
||||
files:
|
||||
- mydashboard.json
|
||||
options:
|
||||
annotations:
|
||||
dashboard: "1"
|
||||
labels:
|
||||
app.kubernetes.io/name: "app1"
|
||||
```
|
||||
|
||||
It is also possible to
|
||||
[define a key](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#define-the-key-to-use-when-creating-a-configmap-from-a-file)
|
||||
to set a name different than the filename.
|
||||
|
||||
The example below creates a ConfigMap
|
||||
with the name of file as `myFileName.ini`
|
||||
while the _actual_ filename from which the
|
||||
configmap is created is `whatever.ini`.
|
||||
|
||||
```
|
||||
configMapGenerator:
|
||||
- name: app-whatever
|
||||
files:
|
||||
- myFileName.ini=whatever.ini
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> [types.ConfigMapArgs]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: ConfigMapGenerator
|
||||
> metadata:
|
||||
> name: mymap
|
||||
> envs:
|
||||
> - devops.env
|
||||
> - uxteam.env
|
||||
> literals:
|
||||
> - FRUIT=apple
|
||||
> - VEGETABLE=carrot
|
||||
> ```
|
||||
|
||||
## _ImageTagTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `images`
|
||||
|
||||
Images modify the name, tags and/or digest for images
|
||||
without creating patches. E.g. Given this
|
||||
kubernetes Deployment fragment:
|
||||
|
||||
```
|
||||
containers:
|
||||
- name: mypostgresdb
|
||||
image: postgres:8
|
||||
- name: nginxapp
|
||||
image: nginx:1.7.9
|
||||
- name: myapp
|
||||
image: my-demo-app:latest
|
||||
- name: alpine-app
|
||||
image: alpine:3.7
|
||||
```
|
||||
|
||||
one can change the `image` in the following ways:
|
||||
|
||||
- `postgres:8` to `my-registry/my-postgres:v1`,
|
||||
- nginx tag `1.7.9` to `1.8.0`,
|
||||
- image name `my-demo-app` to `my-app`,
|
||||
- alpine's tag `3.7` to a digest value
|
||||
|
||||
all with the following _kustomization_:
|
||||
|
||||
```
|
||||
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:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> ImageTag [image.Image]
|
||||
>
|
||||
> FieldSpecs \[\][config.FieldSpec]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: ImageTagTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> imageTag:
|
||||
> name: nginx
|
||||
> newTag: v2
|
||||
> ```
|
||||
|
||||
## _LabelTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `commonLabels`
|
||||
|
||||
Adds labels to all resources and selectors
|
||||
|
||||
```
|
||||
commonLabels:
|
||||
someName: someValue
|
||||
owner: alice
|
||||
app: bingo
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Labels map\[string\]string
|
||||
>
|
||||
> FieldSpecs \[\][config.FieldSpec]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: LabelTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> labels:
|
||||
> app: myApp
|
||||
> env: production
|
||||
> fieldSpecs:
|
||||
> - path: metadata/labels
|
||||
> create: true
|
||||
> ```
|
||||
|
||||
## _NamespaceTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `namespace`
|
||||
|
||||
Adds namespace to all resources
|
||||
|
||||
```
|
||||
namespace: my-namespace
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> [types.ObjectMeta]
|
||||
>
|
||||
> FieldSpecs \[\][config.FieldSpec]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: NamespaceTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> namespace: test
|
||||
> fieldSpecs:
|
||||
> - path: metadata/namespace
|
||||
> create: true
|
||||
> - path: subjects
|
||||
> kind: RoleBinding
|
||||
> group: rbac.authorization.k8s.io
|
||||
> - path: subjects
|
||||
> kind: ClusterRoleBinding
|
||||
> group: rbac.authorization.k8s.io
|
||||
> ```
|
||||
|
||||
## _PatchesJson6902_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `patchesJson6902`
|
||||
|
||||
Each entry in this list should resolve to
|
||||
a kubernetes object and a JSON patch that will be applied
|
||||
to the object.
|
||||
The JSON patch is documented at <https://tools.ietf.org/html/rfc6902>
|
||||
|
||||
target field points to a kubernetes object within the same kustomization
|
||||
by the object's group, version, kind, name and namespace.
|
||||
path field is a relative file path of a JSON patch file.
|
||||
The content in this patch file can be either in JSON format as
|
||||
|
||||
```
|
||||
[
|
||||
{"op": "add", "path": "/some/new/path", "value": "value"},
|
||||
{"op": "replace", "path": "/some/existing/path", "value": "new value"}
|
||||
]
|
||||
```
|
||||
|
||||
or in YAML format as
|
||||
|
||||
```
|
||||
- op: add
|
||||
path: /some/new/path
|
||||
value: value
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: new value
|
||||
```
|
||||
|
||||
```
|
||||
patchesJson6902:
|
||||
- target:
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: my-deployment
|
||||
path: add_init_container.yaml
|
||||
- target:
|
||||
version: v1
|
||||
kind: Service
|
||||
name: my-service
|
||||
path: add_service_annotation.yaml
|
||||
```
|
||||
|
||||
The patch content can be an inline string as well:
|
||||
|
||||
```
|
||||
patchesJson6902:
|
||||
- target:
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: my-deployment
|
||||
patch: |-
|
||||
- op: add
|
||||
path: /some/new/path
|
||||
value: value
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: "new value"
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Target [types.PatchTarget]
|
||||
>
|
||||
> Path string
|
||||
>
|
||||
> JsonOp string
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: PatchJson6902Transformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> target:
|
||||
> group: apps
|
||||
> version: v1
|
||||
> kind: Deployment
|
||||
> name: my-deploy
|
||||
> path: jsonpatch.json
|
||||
> ```
|
||||
|
||||
## _PatchesStrategicMerge_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `patchesStrategicMerge`
|
||||
|
||||
Each entry in this list should be either a relative
|
||||
file path or an inline content
|
||||
resolving to a partial or complete resource
|
||||
definition.
|
||||
|
||||
The names in these (possibly partial) resource
|
||||
files must match names already loaded via the
|
||||
`resources` field. These entries are used to
|
||||
_patch_ (modify) the known resources.
|
||||
|
||||
Small patches that do one thing are best, e.g. modify
|
||||
a memory request/limit, change an env var in a
|
||||
ConfigMap, etc. Small patches are easy to review and
|
||||
easy to mix together in overlays.
|
||||
|
||||
```
|
||||
patchesStrategicMerge:
|
||||
- service_port_8888.yaml
|
||||
- deployment_increase_replicas.yaml
|
||||
- deployment_increase_memory.yaml
|
||||
```
|
||||
|
||||
The patch content can be a inline string as well.
|
||||
|
||||
```
|
||||
patchesStrategicMerge:
|
||||
- |-
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nignx:latest
|
||||
```
|
||||
|
||||
Note that kustomize does not support more than one patch
|
||||
for the same object that contain a _delete_ directive. To remove
|
||||
several fields / slice elements from an object create a single
|
||||
patch that performs all the needed deletions.
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Paths \[\][types.PatchStrategicMerge]
|
||||
>
|
||||
> Patches string
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: PatchStrategicMergeTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> paths:
|
||||
> - patch.yaml
|
||||
> ```
|
||||
|
||||
## _PatchTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `patches`
|
||||
|
||||
Each entry in this list should resolve to an Patch
|
||||
object, which includes a patch and a target selector.
|
||||
The patch can be either a strategic merge patch or a
|
||||
JSON patch. it can be either a patch file or an inline
|
||||
string. The target selects
|
||||
resources by group, version, kind, name, namespace,
|
||||
labelSelector and annotationSelector. A resource
|
||||
which matches all the specified fields is selected
|
||||
to apply the patch.
|
||||
|
||||
```
|
||||
patches:
|
||||
- path: patch.yaml
|
||||
target:
|
||||
group: apps
|
||||
version: v1
|
||||
kind: Deployment
|
||||
name: deploy.*
|
||||
labelSelector: "env=dev"
|
||||
annotationSelector: "zone=west"
|
||||
- patch: |-
|
||||
- op: replace
|
||||
path: /some/existing/path
|
||||
value: new value
|
||||
target:
|
||||
kind: MyKind
|
||||
labelSelector: "env=dev"
|
||||
```
|
||||
|
||||
The `name` and `namespace` fields of the patch target selector are
|
||||
automatically anchored regular expressions. This means that the value `myapp`
|
||||
is equivalent to `^myapp$`.
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Path string
|
||||
>
|
||||
> Patch string
|
||||
>
|
||||
> Target \*[types.Selector]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: PatchTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> patch: '[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "nginx:latest"}]'
|
||||
> target:
|
||||
> name: .*Deploy
|
||||
> kind: Deployment
|
||||
> ```
|
||||
|
||||
## _PrefixSuffixTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field names: `namePrefix`, `nameSuffix`
|
||||
|
||||
Prepends or postfixes the value to the names
|
||||
of all resources.
|
||||
|
||||
E.g. a deployment named `wordpress` could
|
||||
become `alices-wordpress` or `wordpress-v2`
|
||||
or `alices-wordpress-v2`.
|
||||
|
||||
```
|
||||
namePrefix: alices-
|
||||
nameSuffix: -v2
|
||||
```
|
||||
|
||||
The suffix is appended before the content hash if
|
||||
the resource type is ConfigMap or Secret.
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Prefix string
|
||||
>
|
||||
> Suffix string
|
||||
>
|
||||
> FieldSpecs \[\][config.FieldSpec]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: PrefixSuffixTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> prefix: baked-
|
||||
> suffix: -pie
|
||||
> fieldSpecs:
|
||||
> - path: metadata/name
|
||||
> ```
|
||||
|
||||
## _ReplicaCountTransformer_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `replicas`
|
||||
|
||||
Replicas modified the number of replicas for a resource.
|
||||
|
||||
E.g. Given this kubernetes Deployment fragment:
|
||||
|
||||
```
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: deployment-name
|
||||
spec:
|
||||
replicas: 3
|
||||
```
|
||||
|
||||
one can change the number of replicas to 5
|
||||
by adding the following to your kustomization:
|
||||
|
||||
```
|
||||
replicas:
|
||||
- name: deployment-name
|
||||
count: 5
|
||||
```
|
||||
|
||||
This field accepts a list, so many resources can
|
||||
be modified at the same time.
|
||||
|
||||
As this declaration does not take in a `kind:` nor a `group:`
|
||||
it will match any `group` and `kind` that has a matching name and
|
||||
that is one of:
|
||||
|
||||
- `Deployment`
|
||||
- `ReplicationController`
|
||||
- `ReplicaSet`
|
||||
- `StatefulSet`
|
||||
|
||||
For more complex use cases, revert to using a patch.
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> Replica [types.Replica]
|
||||
>
|
||||
> FieldSpecs \[\][config.FieldSpec]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: ReplicaCountTransformer
|
||||
> metadata:
|
||||
> name: not-important-to-example
|
||||
> replica:
|
||||
> name: myapp
|
||||
> count: 23
|
||||
> fieldSpecs:
|
||||
> - path: spec/replicas
|
||||
> create: true
|
||||
> kind: Deployment
|
||||
> - path: spec/replicas
|
||||
> create: true
|
||||
> kind: ReplicationController
|
||||
> ```
|
||||
|
||||
## _SecretGenerator_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `secretGenerator`
|
||||
|
||||
Each entry in the argument list
|
||||
results in the creation of
|
||||
one Secret resource
|
||||
(it's a generator of n secrets).
|
||||
|
||||
This works like the `configMapGenerator` field
|
||||
described above.
|
||||
|
||||
```
|
||||
secretGenerator:
|
||||
- name: app-tls
|
||||
files:
|
||||
- secret/tls.cert
|
||||
- secret/tls.key
|
||||
type: "kubernetes.io/tls"
|
||||
- name: app-tls-namespaced
|
||||
# you can define a namespace to generate
|
||||
# a secret in, defaults to: "default"
|
||||
namespace: apps
|
||||
files:
|
||||
- tls.crt=catsecret/tls.cert
|
||||
- tls.key=secret/tls.key
|
||||
type: "kubernetes.io/tls"
|
||||
- name: env_file_secret
|
||||
envs:
|
||||
- env.txt
|
||||
type: Opaque
|
||||
- name: secret-with-annotation
|
||||
files:
|
||||
- app-config.yaml
|
||||
type: Opaque
|
||||
options:
|
||||
annotations:
|
||||
app_config: "true"
|
||||
labels:
|
||||
app.kubernetes.io/name: "app2"
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> [types.ObjectMeta]
|
||||
>
|
||||
> [types.SecretArgs]
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: SecretGenerator
|
||||
> metadata:
|
||||
> name: my-secret
|
||||
> namespace: whatever
|
||||
> behavior: merge
|
||||
> envs:
|
||||
> - a.env
|
||||
> - b.env
|
||||
> files:
|
||||
> - obscure=longsecret.txt
|
||||
> literals:
|
||||
> - FRUIT=apple
|
||||
> - VEGETABLE=carrot
|
||||
> ```
|
||||
|
||||
## _HelmChartInflationGenerator_
|
||||
|
||||
### Usage via `kustomization.yaml`
|
||||
|
||||
#### field name: `helmChartInflationGenerator`
|
||||
|
||||
Each entry in the argument list results in the pulling
|
||||
and rendering of a helm chart.
|
||||
|
||||
Each entry can have following fields:
|
||||
|
||||
- `chartName`: The name of the chart that you want to use.
|
||||
- `chartRepoUrl`: [Optional] The URL of the repository which contains the chart. If
|
||||
this is provided, the plugin will try to fetch remote charts. Otherwise it will
|
||||
try to load local chart in `chartHome`.
|
||||
- `chartVersion`: [Optional] Version of the chart. Will use latest version
|
||||
if this is omitted.
|
||||
- `chartHome`: [Optional] Provide the path to the parent directory for local chart.
|
||||
- `chartRelease`: [Optional] The name of the repo where to find the chart.
|
||||
- `values`: [Optional] A path to the values file.
|
||||
- `releaseName`: [Optional] The release name that will be set in the chart.
|
||||
- `releaseNamespace`: [Optional] The namespace which will be used by `--namespace`
|
||||
flag in `helm template` command.
|
||||
- `helmBin`: [Optional] Path to helm binary. Default is `helm`.
|
||||
- `helmHome`: [Optional] Path to helm home directory.
|
||||
|
||||
```
|
||||
helmChartInflationGenerator:
|
||||
- chartName: minecraft
|
||||
chartRepoUrl: https://kubernetes-charts.storage.googleapis.com
|
||||
chartVersion: v1.2.0
|
||||
releaseName: test
|
||||
releaseNamespace: testNamespace
|
||||
```
|
||||
|
||||
### Usage via plugin
|
||||
|
||||
#### Arguments
|
||||
|
||||
> ChartName string
|
||||
>
|
||||
> ChartVersion string
|
||||
>
|
||||
> ChartRepoURL string
|
||||
>
|
||||
> ChartHome string
|
||||
>
|
||||
> ChartRepoName string
|
||||
>
|
||||
> HelmBin string
|
||||
>
|
||||
> HelmHome string
|
||||
>
|
||||
> Values string
|
||||
>
|
||||
> ReleaseName string
|
||||
>
|
||||
> ReleaseNamespace string
|
||||
|
||||
#### Example
|
||||
|
||||
> ```
|
||||
> apiVersion: builtin
|
||||
> kind: HelmChartInflationGenerator
|
||||
> metadata:
|
||||
> name: myMap
|
||||
> chartName: minecraft
|
||||
> chartRepoUrl: https://kubernetes-charts.storage.googleapis.com
|
||||
> chartVersion: v1.2.0
|
||||
> helmBin: /usr/bin/helm
|
||||
> helmHome: /tmp/helmHome
|
||||
> releaseName: test
|
||||
> releaseNamespace: testNamespace
|
||||
> values: values.yaml
|
||||
> ```
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -8,230 +8,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/extending_kustomize/execpluginguidedexample" />
|
||||
|
||||
|
||||
This is a (no reading allowed!) 60 second copy/paste guided
|
||||
example. Full plugin docs [here](..).
|
||||
|
||||
This demo writes and uses a somewhat ridiculous
|
||||
_exec_ plugin (written in bash) that generates a
|
||||
`ConfigMap`.
|
||||
|
||||
This is a guide to try it without damaging your
|
||||
current setup.
|
||||
|
||||
#### requirements
|
||||
|
||||
* linux, git, curl, Go 1.13
|
||||
|
||||
## Make a place to work
|
||||
|
||||
```
|
||||
DEMO=$(mktemp -d)
|
||||
```
|
||||
|
||||
## Create a kustomization
|
||||
|
||||
Make a kustomization directory to
|
||||
hold all your config:
|
||||
|
||||
```
|
||||
MYAPP=$DEMO/myapp
|
||||
mkdir -p $MYAPP
|
||||
```
|
||||
|
||||
Make a deployment config:
|
||||
|
||||
```
|
||||
cat <<'EOF' >$MYAPP/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: the-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: the-container
|
||||
image: monopole/hello:1
|
||||
command: ["/hello",
|
||||
"--port=8080",
|
||||
"--date=$(THE_DATE)",
|
||||
"--enableRiskyFeature=$(ENABLE_RISKY)"]
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: THE_DATE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: today
|
||||
- name: ALT_GREETING
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: altGreeting
|
||||
- name: ENABLE_RISKY
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: the-map
|
||||
key: enableRisky
|
||||
EOF
|
||||
```
|
||||
|
||||
Make a service config:
|
||||
|
||||
```
|
||||
cat <<EOF >$MYAPP/service.yaml
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: the-service
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8666
|
||||
targetPort: 8080
|
||||
EOF
|
||||
```
|
||||
|
||||
Now make a config file for the plugin
|
||||
you're about to write.
|
||||
|
||||
This config file is just another k8s resource
|
||||
object. The values of its `apiVersion` and `kind`
|
||||
fields are used to _find_ the plugin code on your
|
||||
filesystem (more on this later).
|
||||
|
||||
```
|
||||
cat <<'EOF' >$MYAPP/cmGenerator.yaml
|
||||
apiVersion: myDevOpsTeam
|
||||
kind: SillyConfigMapGenerator
|
||||
metadata:
|
||||
name: whatever
|
||||
argsOneLiner: Bienvenue true
|
||||
EOF
|
||||
```
|
||||
|
||||
Finally, make a kustomization file
|
||||
referencing all of the above:
|
||||
|
||||
```
|
||||
cat <<EOF >$MYAPP/kustomization.yaml
|
||||
commonLabels:
|
||||
app: hello
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
generators:
|
||||
- cmGenerator.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Review the files
|
||||
|
||||
```
|
||||
ls -C1 $MYAPP
|
||||
```
|
||||
|
||||
## Make a home for plugins
|
||||
|
||||
Plugins must live in a particular place for
|
||||
kustomize to find them.
|
||||
|
||||
This demo will use the ephemeral directory:
|
||||
|
||||
```
|
||||
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
||||
```
|
||||
|
||||
The plugin config defined above in
|
||||
`$MYAPP/cmGenerator.yaml` specifies:
|
||||
|
||||
> ```
|
||||
> apiVersion: myDevOpsTeam
|
||||
> kind: SillyConfigMapGenerator
|
||||
> ```
|
||||
|
||||
This means the plugin must live in a directory
|
||||
named:
|
||||
|
||||
```
|
||||
MY_PLUGIN_DIR=$PLUGIN_ROOT/myDevOpsTeam/sillyconfigmapgenerator
|
||||
|
||||
mkdir -p $MY_PLUGIN_DIR
|
||||
```
|
||||
|
||||
The directory name is the plugin config's
|
||||
_apiVersion_ followed by its lower-cased _kind_.
|
||||
|
||||
A plugin gets its own directory to hold itself,
|
||||
its tests and any supplemental data files it
|
||||
might need.
|
||||
|
||||
## Create the plugin
|
||||
|
||||
There are two kinds of plugins, _exec_ and _Go_.
|
||||
|
||||
Make an _exec_ plugin, installing it to the
|
||||
correct directory and file name. The file name
|
||||
must match the plugin's _kind_ (in this case,
|
||||
`SillyConfigMapGenerator`):
|
||||
|
||||
```
|
||||
cat <<'EOF' >$MY_PLUGIN_DIR/SillyConfigMapGenerator
|
||||
#!/bin/bash
|
||||
# Skip the config file name argument.
|
||||
shift
|
||||
today=`date +%F`
|
||||
echo "
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: the-map
|
||||
data:
|
||||
today: $today
|
||||
altGreeting: "$1"
|
||||
enableRisky: "$2"
|
||||
"
|
||||
EOF
|
||||
```
|
||||
|
||||
By definition, an _exec_ plugin must be executable:
|
||||
|
||||
```
|
||||
chmod a+x $MY_PLUGIN_DIR/SillyConfigMapGenerator
|
||||
```
|
||||
|
||||
## Install kustomize
|
||||
|
||||
Per the [instructions](/kustomize/installation):
|
||||
|
||||
```
|
||||
curl -s "https://raw.githubusercontent.com/\
|
||||
kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
|
||||
mkdir -p $DEMO/bin
|
||||
mv kustomize $DEMO/bin
|
||||
```
|
||||
|
||||
## Review the layout
|
||||
|
||||
```
|
||||
tree $DEMO
|
||||
```
|
||||
|
||||
## Build your app, using the plugin
|
||||
|
||||
```
|
||||
XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||||
```
|
||||
|
||||
Above, if you had set
|
||||
|
||||
> ```
|
||||
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
||||
> ```
|
||||
|
||||
there would be no need to use `XDG_CONFIG_HOME` in the
|
||||
_kustomize_ command above.
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -8,120 +8,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/extending_kustomize/goplugincaveats" />
|
||||
|
||||
[plugin package]: https://golang.org/pkg/plugin
|
||||
[Go modules]: https://github.com/golang/go/wiki/Modules
|
||||
[ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
|
||||
[tensorflow plugin]: https://www.tensorflow.org/guide/extend/op
|
||||
|
||||
A _Go plugin_ is a compilation artifact described
|
||||
by the Go [plugin package]. It is built with
|
||||
special flags and cannot run on its own.
|
||||
It must be loaded into a running Go program.
|
||||
|
||||
> A normal program written in Go might be usable
|
||||
> as _exec plugin_, but is not a _Go plugin_.
|
||||
|
||||
Go plugins allow kustomize extensions that run
|
||||
without the cost marshalling/unmarshalling all
|
||||
resource data to/from a subprocess for each plugin
|
||||
run. The Go plugin API assures a certain level of
|
||||
consistency to avoid confusing downstream
|
||||
transformers.
|
||||
|
||||
Go plugins work as described in the [plugin
|
||||
package], but fall short of common notions
|
||||
associated with the word _plugin_.
|
||||
|
||||
## The skew problem
|
||||
|
||||
Go plugin compilation creates an [ELF] formatted
|
||||
`.so` file, which by definition has no information
|
||||
about the provenance of the object code.
|
||||
|
||||
Skew between the compilation conditions (versions
|
||||
of package dependencies, `GOOS`, `GOARCH`) of the
|
||||
main program ELF and the plugin ELF will cause
|
||||
plugin load failure, with non-helpful error
|
||||
messages.
|
||||
|
||||
Exec plugins also lack provenance, but won't fail
|
||||
due to compilation skew.
|
||||
|
||||
In either case, the only sensible way to share a
|
||||
plugin is as some kind of _bundle_ (a git repo
|
||||
URL, a git archive file, a tar file, etc.)
|
||||
containing source code, tests and associated data,
|
||||
unpackable under
|
||||
`$XDG_CONFIG_HOME/kustomize/plugin`.
|
||||
|
||||
In the case of a Go plugin, an _end user_
|
||||
accepting a shared plugin _must compile both
|
||||
kustomize and the plugin_.
|
||||
|
||||
This means a one-time run of
|
||||
|
||||
```
|
||||
# Or whatever is appropriate at time of reading
|
||||
GOPATH=${whatever} GO111MODULE=on go get sigs.k8s.io/kustomize/api
|
||||
```
|
||||
|
||||
and then a normal development cycle using
|
||||
|
||||
```
|
||||
go build -buildmode plugin \
|
||||
-o ${wherever}/${kind}.so ${wherever}/${kind}.go
|
||||
```
|
||||
|
||||
with paths and the release version tag (e.g. `v3.0.0`)
|
||||
adjusted as needed.
|
||||
|
||||
For comparison, consider what one
|
||||
must do to write a [tensorflow plugin].
|
||||
|
||||
## Why support Go plugins
|
||||
|
||||
### Safety
|
||||
|
||||
The Go plugin developer sees the same API offered
|
||||
to native kustomize operations, assuring certain
|
||||
semantics, invariants, checks, etc. An exec
|
||||
plugin sub-process dealing with this via
|
||||
stdin/stdout will have an easier time screwing
|
||||
things up for downstream transformers and
|
||||
consumers.
|
||||
|
||||
Minor point: if the plugin reads files via
|
||||
the kustomize-provided file `Loader` interface, it
|
||||
will be constrained by kustomize file loading
|
||||
restrictions. Of course, nothing but a code audit
|
||||
prevents a Go plugin from importing the `io` package
|
||||
and doing whatever it wants.
|
||||
|
||||
### Debugging
|
||||
|
||||
A Go plugin developer can debug the plugin _in
|
||||
situ_, setting breakpoints inside the plugin and
|
||||
elsewhere while running a plugin in feature tests.
|
||||
|
||||
To get the best of both worlds (shareability and safety),
|
||||
a developer can write an `.go` program that functions
|
||||
as an _exec plugin_, but can be processed by `go generate`
|
||||
to emit a _Go plugin_ (or vice versa).
|
||||
|
||||
### Unit of contribution
|
||||
|
||||
All the builtin generators and transformers
|
||||
are themselves Go plugins. This means that
|
||||
the kustomize maintainers can promote a contributed
|
||||
plugin to a builtin without needing code changes
|
||||
(beyond those mandated by normal code review).
|
||||
|
||||
### Ecosystems grow through use
|
||||
|
||||
Tooling could ease Go plugin _sharing_, but this
|
||||
requires some critical mass of Go plugin
|
||||
_authoring_, which in turn is hampered by
|
||||
confusion around sharing. [Go modules], once they
|
||||
are more widely adopted, will solve the
|
||||
biggest plugin sharing difficulty: ambiguous
|
||||
plugin vs host dependencies.
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
@@ -8,371 +8,4 @@ description: >
|
||||
|
||||
<meta http-equiv="refresh" content="0; url=https://kubectl.docs.kubernetes.io/guides/extending_kustomize/gopluginguidedexample" />
|
||||
|
||||
|
||||
# Go Plugin Guided Example for Linux
|
||||
|
||||
[SopsEncodedSecrets repository]: https://github.com/monopole/sopsencodedsecrets
|
||||
[Go plugin]: https://golang.org/pkg/plugin
|
||||
[Go plugin caveats]: goPluginCaveats.md
|
||||
|
||||
This is a (no reading allowed!) 60 second copy/paste guided
|
||||
example.
|
||||
|
||||
Full plugin docs [here](README.md).
|
||||
Be sure to read the [Go plugin caveats].
|
||||
|
||||
This demo uses a Go plugin, `SopsEncodedSecrets`,
|
||||
that lives in the [sopsencodedsecrets repository].
|
||||
This is an inprocess [Go plugin], not an
|
||||
sub-process exec plugin that happens to be written
|
||||
in Go (which is another option for Go authors).
|
||||
|
||||
This is a guide to try it without damaging your
|
||||
current setup.
|
||||
|
||||
#### requirements
|
||||
|
||||
* linux, git, curl, Go 1.13
|
||||
|
||||
For encryption
|
||||
|
||||
* gpg
|
||||
|
||||
Or
|
||||
|
||||
* Google cloud (gcloud) install
|
||||
* a Google account with KMS permission
|
||||
|
||||
## Make a place to work
|
||||
|
||||
```shell
|
||||
# Keeping these separate to avoid cluttering the DEMO dir.
|
||||
DEMO=$(mktemp -d)
|
||||
tmpGoPath=$(mktemp -d)
|
||||
```
|
||||
|
||||
## Install kustomize
|
||||
|
||||
Need v3.0.0 for what follows, and you must _compile_
|
||||
it (not download the binary from the release page):
|
||||
|
||||
```shell
|
||||
GOPATH=$tmpGoPath go install sigs.k8s.io/kustomize/kustomize
|
||||
```
|
||||
|
||||
## Make a home for plugins
|
||||
|
||||
A kustomize plugin is fully determined by
|
||||
its configuration file and source code.
|
||||
|
||||
[required fields]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields
|
||||
|
||||
Kustomize plugin configuration files are formatted
|
||||
as kubernetes resource objects, meaning
|
||||
`apiVersion`, `kind` and `metadata` are [required
|
||||
fields] in these config files.
|
||||
|
||||
The kustomize program reads the config file
|
||||
(because the config file name appears in the
|
||||
`generators` or `transformers` field in the
|
||||
kustomization file), then locates the Go plugin's
|
||||
object code at the following location:
|
||||
|
||||
> ```shell
|
||||
> $XDG_CONFIG_HOME/kustomize/plugin/$apiVersion/$lKind/$kind.so
|
||||
> ```
|
||||
|
||||
where `lKind` holds the lowercased kind. The
|
||||
plugin is then loaded and fed its config, and the
|
||||
plugin's output becomes part of the overall
|
||||
`kustomize build` process.
|
||||
|
||||
The same plugin might be used multiple times in
|
||||
one kustomize build, but with different config
|
||||
files. Also, kustomize might customize config
|
||||
data before sending it to the plugin, for whatever
|
||||
reason. For these reasons, kustomize owns the
|
||||
mapping between plugins and config data; it's not
|
||||
left to plugins to find their own config.
|
||||
|
||||
This demo will house the plugin it uses at the
|
||||
ephemeral directory
|
||||
|
||||
```shell
|
||||
PLUGIN_ROOT=$DEMO/kustomize/plugin
|
||||
```
|
||||
|
||||
and ephemerally set `XDG_CONFIG_HOME` on a command
|
||||
line below.
|
||||
|
||||
### What apiVersion and kind
|
||||
|
||||
At this stage in the development of kustomize
|
||||
plugins, plugin code doesn't know or care what
|
||||
`apiVersion` or `kind` appears in the config file
|
||||
sent to it.
|
||||
|
||||
The plugin could check these fields, but it's the
|
||||
remaining fields that provide actual configuration
|
||||
data, and at this point the successful parsing of
|
||||
these other fields are the only thing that matters
|
||||
to a plugin.
|
||||
|
||||
This demo uses a plugin called _SopsEncodedSecrets_,
|
||||
and it lives in the [SopsEncodedSecrets repository].
|
||||
|
||||
Somewhat arbitrarily, we'll chose to install
|
||||
this plugin with
|
||||
|
||||
```shell
|
||||
apiVersion=mygenerators
|
||||
kind=SopsEncodedSecrets
|
||||
```
|
||||
|
||||
### Define the plugin's home dir
|
||||
|
||||
By convention, the ultimate home of the plugin
|
||||
code and supplemental data, tests, documentation,
|
||||
etc. is the lowercase form of its kind.
|
||||
|
||||
```shell
|
||||
lKind=$(echo $kind | awk '{print tolower($0)}')
|
||||
```
|
||||
|
||||
### Download the SopsEncodedSecrets plugin
|
||||
|
||||
In this case, the repo name matches the lowercase
|
||||
kind already, so we just clone the repo and get
|
||||
the proper directory name automatically:
|
||||
|
||||
```shell
|
||||
mkdir -p $PLUGIN_ROOT/${apiVersion}
|
||||
cd $PLUGIN_ROOT/${apiVersion}
|
||||
git clone git@github.com:monopole/sopsencodedsecrets.git
|
||||
```
|
||||
|
||||
Remember this directory:
|
||||
|
||||
```shell
|
||||
MY_PLUGIN_DIR=$PLUGIN_ROOT/${apiVersion}/${lKind}
|
||||
```
|
||||
|
||||
### Try the plugin's own test
|
||||
|
||||
Plugins may come with their own tests.
|
||||
This one does, and it hopefully passes:
|
||||
|
||||
```shell
|
||||
cd $MY_PLUGIN_DIR
|
||||
go test SopsEncodedSecrets_test.go
|
||||
```
|
||||
|
||||
Build the object code for use by kustomize:
|
||||
|
||||
```shell
|
||||
cd $MY_PLUGIN_DIR
|
||||
GOPATH=$tmpGoPath go build -buildmode plugin -o ${kind}.so ${kind}.go
|
||||
```
|
||||
|
||||
This step may succeed, but kustomize might
|
||||
ultimately fail to load the plugin because of
|
||||
dependency [skew].
|
||||
|
||||
[skew]: /docs/plugins/README.md#caveats
|
||||
[used in this demo]: #install-kustomize
|
||||
|
||||
On load failure
|
||||
|
||||
* be sure to build the plugin with the same
|
||||
version of Go (_go1.13_) on the same `$GOOS`
|
||||
(_linux_) and `$GOARCH` (_amd64_) used to build
|
||||
the kustomize being [used in this demo].
|
||||
|
||||
* change the plugin's dependencies in its `go.mod`
|
||||
to match the versions used by kustomize (check
|
||||
kustomize's `go.mod` used in its tagged commit).
|
||||
|
||||
Lacking tools and metadata to allow this to be
|
||||
automated, there won't be a Go plugin ecosystem.
|
||||
|
||||
Kustomize has adopted a Go plugin architecture as
|
||||
to ease accept new generators and transformers
|
||||
(just write a plugin), and to be sure that native
|
||||
operations (also constructed and tested as
|
||||
plugins) are compartmentalized, orderable and
|
||||
reusable instead of bizarrely woven throughout the
|
||||
code as a individual special cases.
|
||||
|
||||
## Create a kustomization
|
||||
|
||||
Make a kustomization directory to
|
||||
hold all your config:
|
||||
|
||||
```shell
|
||||
MYAPP=$DEMO/myapp
|
||||
mkdir -p $MYAPP
|
||||
```
|
||||
|
||||
Make a config file for the SopsEncodedSecrets plugin.
|
||||
|
||||
Its `apiVersion` and `kind` allow the plugin to be
|
||||
found:
|
||||
|
||||
```shell
|
||||
cat <<EOF >$MYAPP/secGenerator.yaml
|
||||
apiVersion: ${apiVersion}
|
||||
kind: ${kind}
|
||||
metadata:
|
||||
name: mySecretGenerator
|
||||
name: forbiddenValues
|
||||
namespace: production
|
||||
file: myEncryptedData.yaml
|
||||
keys:
|
||||
- ROCKET
|
||||
- CAR
|
||||
EOF
|
||||
```
|
||||
|
||||
This plugin expects to find more data in
|
||||
`myEncryptedData.yaml`; we'll get to that shortly.
|
||||
|
||||
Make a kustomization file referencing the plugin
|
||||
config:
|
||||
|
||||
```shell
|
||||
cat <<EOF >$MYAPP/kustomization.yaml
|
||||
commonLabels:
|
||||
app: hello
|
||||
generators:
|
||||
- secGenerator.yaml
|
||||
EOF
|
||||
```
|
||||
|
||||
Now generate the real encrypted data.
|
||||
|
||||
### Assure you have an encryption tool installed
|
||||
|
||||
We're going to use [sops](https://github.com/mozilla/sops) to encode a file. Choose either GPG or Google Cloud KMS as the secret provider to continue.
|
||||
|
||||
#### GPG
|
||||
|
||||
Try this:
|
||||
|
||||
```shell
|
||||
gpg --list-keys
|
||||
```
|
||||
|
||||
If it returns a list, presumably you've already created keys. If not, try import test keys from sops for dev.
|
||||
|
||||
```shell
|
||||
curl https://raw.githubusercontent.com/mozilla/sops/master/pgp/sops_functional_tests_key.asc | gpg --import
|
||||
SOPS_PGP_FP="1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A"
|
||||
```
|
||||
|
||||
#### Google Cloude KMS
|
||||
|
||||
Try this:
|
||||
|
||||
```shell
|
||||
gcloud kms keys list --location global --keyring sops
|
||||
```
|
||||
|
||||
If it succeeds, presumably you've already created keys and placed them in a keyring called sops. If not, do this:
|
||||
|
||||
```shell
|
||||
gcloud kms keyrings create sops --location global
|
||||
gcloud kms keys create sops-key --location global \
|
||||
--keyring sops --purpose encryption
|
||||
```
|
||||
|
||||
Extract your keyLocation for use below:
|
||||
|
||||
```shell
|
||||
keyLocation=$(\
|
||||
gcloud kms keys list --location global --keyring sops |\
|
||||
grep GOOGLE | cut -d " " -f1)
|
||||
echo $keyLocation
|
||||
```
|
||||
|
||||
### Install `sops`
|
||||
|
||||
```shell
|
||||
GOPATH=$tmpGoPath go install go.mozilla.org/sops/cmd/sops
|
||||
```
|
||||
|
||||
### Create data encrypted with your private key
|
||||
|
||||
Create raw data to encrypt:
|
||||
|
||||
```shell
|
||||
cat <<EOF >$MYAPP/myClearData.yaml
|
||||
VEGETABLE: carrot
|
||||
ROCKET: saturn-v
|
||||
FRUIT: apple
|
||||
CAR: dymaxion
|
||||
EOF
|
||||
```
|
||||
|
||||
Encrypt the data into file the plugin wants to read:
|
||||
|
||||
With PGP
|
||||
|
||||
```shell
|
||||
$tmpGoPath/bin/sops --encrypt \
|
||||
--pgp $SOPS_PGP_FP \
|
||||
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
|
||||
```
|
||||
|
||||
Or GCP KMS
|
||||
|
||||
```shell
|
||||
$tmpGoPath/bin/sops --encrypt \
|
||||
--gcp-kms $keyLocation \
|
||||
$MYAPP/myClearData.yaml >$MYAPP/myEncryptedData.yaml
|
||||
```
|
||||
|
||||
Review the files
|
||||
|
||||
```shell
|
||||
tree $DEMO
|
||||
```
|
||||
|
||||
This should look something like:
|
||||
|
||||
> ```shell
|
||||
> /tmp/tmp.0kIE9VclPt
|
||||
> ├── kustomize
|
||||
> │ └── plugin
|
||||
> │ └── mygenerators
|
||||
> │ └── sopsencodedsecrets
|
||||
> │ ├── go.mod
|
||||
> │ ├── go.sum
|
||||
> │ ├── LICENSE
|
||||
> │ ├── README.md
|
||||
> │ ├── SopsEncodedSecrets.go
|
||||
> │ ├── SopsEncodedSecrets.so
|
||||
> │ └── SopsEncodedSecrets_test.go
|
||||
> └── myapp
|
||||
> ├── kustomization.yaml
|
||||
> ├── myClearData.yaml
|
||||
> ├── myEncryptedData.yaml
|
||||
> └── secGenerator.yaml
|
||||
> ```
|
||||
|
||||
## Build your app, using the plugin
|
||||
|
||||
```shell
|
||||
XDG_CONFIG_HOME=$DEMO $tmpGoPath/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||||
```
|
||||
|
||||
This should emit a kubernetes secret, with
|
||||
encrypted data for the names `ROCKET` and `CAR`.
|
||||
|
||||
Above, if you had set
|
||||
|
||||
> ```shell
|
||||
> PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
||||
> ```
|
||||
|
||||
there would be no need to use `XDG_CONFIG_HOME` in the
|
||||
_kustomize_ command above.
|
||||
Moved to https://github.com/kubernetes-sigs/cli-experimental
|
||||
Reference in New Issue
Block a user