mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-05-18 12:42:19 +00:00
1075 lines
62 KiB
XML
1075 lines
62 KiB
XML
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||
<channel>
|
||
<title>Kustomize – Kustomize Plugins</title>
|
||
<link>https://kubernetes-sigs.github.io/kustomize/guides/plugins/</link>
|
||
<description>Recent content in Kustomize Plugins on Kustomize</description>
|
||
<generator>Hugo -- gohugo.io</generator>
|
||
|
||
<atom:link href="https://kubernetes-sigs.github.io/kustomize/guides/plugins/index.xml" rel="self" type="application/rss+xml" />
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<item>
|
||
<title>Guides: Builtin Plugins</title>
|
||
<link>https://kubernetes-sigs.github.io/kustomize/guides/plugins/builtins/</link>
|
||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||
|
||
<guid>https://kubernetes-sigs.github.io/kustomize/guides/plugins/builtins/</guid>
|
||
<description>
|
||
|
||
|
||
<h1 id="builtin-plugins">Builtin Plugins</h1>
|
||
<p>A list of kustomize&rsquo;s builtin plugins - both
|
||
generators and transformers.</p>
|
||
<p>For each plugin, an example is given for</p>
|
||
<ul>
|
||
<li>
|
||
<p>implicitly triggering
|
||
the plugin via a dedicated kustomization
|
||
file field (e.g. the <code>AnnotationsTransformer</code> is
|
||
triggered by the <code>commonAnnotations</code> field).</p>
|
||
</li>
|
||
<li>
|
||
<p>explicitly triggering the plugin
|
||
via the <code>generators</code> or <code>transformers</code> field
|
||
(by providing a config file specifying the
|
||
plugin).</p>
|
||
</li>
|
||
</ul>
|
||
<p>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.</p>
|
||
<h2 id="_annotationtransformer_"><em>AnnotationTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-commonannotations">field name: <code>commonAnnotations</code></h4>
|
||
<p>Adds annotions (non-identifying metadata) to add
|
||
all resources. Like labels, these are key value
|
||
pairs.</p>
|
||
<pre><code>commonAnnotations:
|
||
oncallPager: 800-555-1212
|
||
</code></pre><h3 id="usage-via-plugin">Usage via plugin</h3>
|
||
<h4 id="arguments">Arguments</h4>
|
||
<blockquote>
|
||
<p>Annotations map[string]string</p>
|
||
<p>FieldSpecs []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go">config.FieldSpec</a></p>
|
||
</blockquote>
|
||
<h4 id="example">Example</h4>
|
||
<blockquote>
|
||
<pre><code>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
|
||
</code></pre></blockquote>
|
||
<h2 id="_configmapgenerator_"><em>ConfigMapGenerator</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-1">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-configmapgenerator">field name: <code>configMapGenerator</code></h4>
|
||
<p>Each entry in this list results in the creation of
|
||
one ConfigMap resource (it&rsquo;s a generator of n maps).</p>
|
||
<p>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 <code>options</code> for that single ConfigMap.</p>
|
||
<p>Each configMapGenerator item accepts a parameter of
|
||
<code>behavior: [create|replace|merge]</code>.
|
||
This allows an overlay to modify or
|
||
replace an existing configMap from the parent.</p>
|
||
<p>Also, each entry has an <code>options</code> field, that has the
|
||
same subfields as the kustomization file&rsquo;s <code>generatorOptions</code> field.</p>
|
||
<p>This <code>options</code> 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 <code>generatorOptions</code> field. However, due to how
|
||
booleans behave, if the global <code>generatorOptions</code> field
|
||
specifies <code>disableNameSuffixHash: true</code>, this will
|
||
trump any attempt to locally override it.</p>
|
||
<pre><code># 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: &quot;1&quot;
|
||
labels:
|
||
app.kubernetes.io/name: &quot;app1&quot;
|
||
</code></pre><p>It is also possible to
|
||
<a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#define-the-key-to-use-when-creating-a-configmap-from-a-file">define a key</a>
|
||
to set a name different than the filename.</p>
|
||
<p>The example below creates a ConfigMap
|
||
with the name of file as <code>myFileName.ini</code>
|
||
while the <em>actual</em> filename from which the
|
||
configmap is created is <code>whatever.ini</code>.</p>
|
||
<pre><code>configMapGenerator:
|
||
- name: app-whatever
|
||
files:
|
||
- myFileName.ini=whatever.ini
|
||
</code></pre><h3 id="usage-via-plugin-1">Usage via plugin</h3>
|
||
<h4 id="arguments-1">Arguments</h4>
|
||
<blockquote>
|
||
<p><a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/configmapargs.go">types.ConfigMapArgs</a></p>
|
||
</blockquote>
|
||
<h4 id="example-1">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: ConfigMapGenerator
|
||
metadata:
|
||
name: mymap
|
||
envs:
|
||
- devops.env
|
||
- uxteam.env
|
||
literals:
|
||
- FRUIT=apple
|
||
- VEGETABLE=carrot
|
||
</code></pre></blockquote>
|
||
<h2 id="_imagetagtransformer_"><em>ImageTagTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-2">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-images">field name: <code>images</code></h4>
|
||
<p>Images modify the name, tags and/or digest for images
|
||
without creating patches. E.g. Given this
|
||
kubernetes Deployment fragment:</p>
|
||
<pre><code>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
|
||
</code></pre><p>one can change the <code>image</code> in the following ways:</p>
|
||
<ul>
|
||
<li><code>postgres:8</code> to <code>my-registry/my-postgres:v1</code>,</li>
|
||
<li>nginx tag <code>1.7.9</code> to <code>1.8.0</code>,</li>
|
||
<li>image name <code>my-demo-app</code> to <code>my-app</code>,</li>
|
||
<li>alpine&rsquo;s tag <code>3.7</code> to a digest value</li>
|
||
</ul>
|
||
<p>all with the following <em>kustomization</em>:</p>
|
||
<pre><code>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
|
||
</code></pre><h3 id="usage-via-plugin-2">Usage via plugin</h3>
|
||
<h4 id="arguments-2">Arguments</h4>
|
||
<blockquote>
|
||
<p>ImageTag <a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/image.go">image.Image</a></p>
|
||
<p>FieldSpecs []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go">config.FieldSpec</a></p>
|
||
</blockquote>
|
||
<h4 id="example-2">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: ImageTagTransformer
|
||
metadata:
|
||
name: not-important-to-example
|
||
imageTag:
|
||
name: nginx
|
||
newTag: v2
|
||
</code></pre></blockquote>
|
||
<h2 id="_labeltransformer_"><em>LabelTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-3">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-commonlabels">field name: <code>commonLabels</code></h4>
|
||
<p>Adds labels to all resources and selectors</p>
|
||
<pre><code>commonLabels:
|
||
someName: someValue
|
||
owner: alice
|
||
app: bingo
|
||
</code></pre><h3 id="usage-via-plugin-3">Usage via plugin</h3>
|
||
<h4 id="arguments-3">Arguments</h4>
|
||
<blockquote>
|
||
<p>Labels map[string]string</p>
|
||
<p>FieldSpecs []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go">config.FieldSpec</a></p>
|
||
</blockquote>
|
||
<h4 id="example-3">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: LabelTransformer
|
||
metadata:
|
||
name: not-important-to-example
|
||
labels:
|
||
app: myApp
|
||
env: production
|
||
fieldSpecs:
|
||
- path: metadata/labels
|
||
create: true
|
||
</code></pre></blockquote>
|
||
<h2 id="_namespacetransformer_"><em>NamespaceTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-4">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-namespace">field name: <code>namespace</code></h4>
|
||
<p>Adds namespace to all resources</p>
|
||
<pre><code>namespace: my-namespace
|
||
</code></pre><h3 id="usage-via-plugin-4">Usage via plugin</h3>
|
||
<h4 id="arguments-4">Arguments</h4>
|
||
<blockquote>
|
||
<p><a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/objectmeta.go">types.ObjectMeta</a></p>
|
||
<p>FieldSpecs []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go">config.FieldSpec</a></p>
|
||
</blockquote>
|
||
<h4 id="example-4">Example</h4>
|
||
<blockquote>
|
||
<pre><code>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
|
||
</code></pre></blockquote>
|
||
<h2 id="_patchesjson6902_"><em>PatchesJson6902</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-5">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-patchesjson6902">field name: <code>patchesJson6902</code></h4>
|
||
<p>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 <a href="https://tools.ietf.org/html/rfc6902">https://tools.ietf.org/html/rfc6902</a></p>
|
||
<p>target field points to a kubernetes object within the same kustomization
|
||
by the object&rsquo;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</p>
|
||
<pre><code> [
|
||
{&quot;op&quot;: &quot;add&quot;, &quot;path&quot;: &quot;/some/new/path&quot;, &quot;value&quot;: &quot;value&quot;},
|
||
{&quot;op&quot;: &quot;replace&quot;, &quot;path&quot;: &quot;/some/existing/path&quot;, &quot;value&quot;: &quot;new value&quot;}
|
||
]
|
||
</code></pre><p>or in YAML format as</p>
|
||
<pre><code>- op: add
|
||
path: /some/new/path
|
||
value: value
|
||
- op: replace
|
||
path: /some/existing/path
|
||
value: new value
|
||
</code></pre><pre><code>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
|
||
</code></pre><p>The patch content can be an inline string as well:</p>
|
||
<pre><code>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: &quot;new value&quot;
|
||
</code></pre><h3 id="usage-via-plugin-5">Usage via plugin</h3>
|
||
<h4 id="arguments-5">Arguments</h4>
|
||
<blockquote>
|
||
<p>Target <a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/patchtarget.go">types.PatchTarget</a></p>
|
||
<p>Path string</p>
|
||
<p>JsonOp string</p>
|
||
</blockquote>
|
||
<h4 id="example-5">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: PatchJson6902Transformer
|
||
metadata:
|
||
name: not-important-to-example
|
||
target:
|
||
group: apps
|
||
version: v1
|
||
kind: Deployment
|
||
name: my-deploy
|
||
path: jsonpatch.json
|
||
</code></pre></blockquote>
|
||
<h2 id="_patchesstrategicmerge_"><em>PatchesStrategicMerge</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-6">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-patchesstrategicmerge">field name: <code>patchesStrategicMerge</code></h4>
|
||
<p>Each entry in this list should be either a relative
|
||
file path or an inline content
|
||
resolving to a partial or complete resource
|
||
definition.</p>
|
||
<p>The names in these (possibly partial) resource
|
||
files must match names already loaded via the
|
||
<code>resources</code> field. These entries are used to
|
||
<em>patch</em> (modify) the known resources.</p>
|
||
<p>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.</p>
|
||
<pre><code>patchesStrategicMerge:
|
||
- service_port_8888.yaml
|
||
- deployment_increase_replicas.yaml
|
||
- deployment_increase_memory.yaml
|
||
</code></pre><p>The patch content can be a inline string as well.</p>
|
||
<pre><code>patchesStrategicMerge:
|
||
- |-
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
metadata:
|
||
name: nginx
|
||
spec:
|
||
template:
|
||
spec:
|
||
containers:
|
||
- name: nginx
|
||
image: nignx:latest
|
||
</code></pre><p>Note that kustomize does not support more than one patch
|
||
for the same object that contain a <em>delete</em> directive. To remove
|
||
several fields / slice elements from an object create a single
|
||
patch that performs all the needed deletions.</p>
|
||
<h3 id="usage-via-plugin-6">Usage via plugin</h3>
|
||
<h4 id="arguments-6">Arguments</h4>
|
||
<blockquote>
|
||
<p>Paths []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/patchstrategicmerge.go">types.PatchStrategicMerge</a></p>
|
||
<p>Patches string</p>
|
||
</blockquote>
|
||
<h4 id="example-6">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: PatchStrategicMergeTransformer
|
||
metadata:
|
||
name: not-important-to-example
|
||
paths:
|
||
- patch.yaml
|
||
</code></pre></blockquote>
|
||
<h2 id="_patchtransformer_"><em>PatchTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-7">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-patches">field name: <code>patches</code></h4>
|
||
<p>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.</p>
|
||
<pre><code>patches:
|
||
- path: patch.yaml
|
||
target:
|
||
group: apps
|
||
version: v1
|
||
kind: Deployment
|
||
name: deploy.*
|
||
labelSelector: &quot;env=dev&quot;
|
||
annotationSelector: &quot;zone=west&quot;
|
||
- patch: |-
|
||
- op: replace
|
||
path: /some/existing/path
|
||
value: new value
|
||
target:
|
||
kind: MyKind
|
||
labelSelector: &quot;env=dev&quot;
|
||
</code></pre><p>The <code>name</code> and <code>namespace</code> fields of the patch target selector are
|
||
automatically anchored regular expressions. This means that the value <code>myapp</code>
|
||
is equivalent to <code>^myapp$</code>.</p>
|
||
<h3 id="usage-via-plugin-7">Usage via plugin</h3>
|
||
<h4 id="arguments-7">Arguments</h4>
|
||
<blockquote>
|
||
<p>Path string</p>
|
||
<p>Patch string</p>
|
||
<p>Target *<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/selector.go">types.Selector</a></p>
|
||
</blockquote>
|
||
<h4 id="example-7">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: PatchTransformer
|
||
metadata:
|
||
name: not-important-to-example
|
||
patch: '[{&quot;op&quot;: &quot;replace&quot;, &quot;path&quot;: &quot;/spec/template/spec/containers/0/image&quot;, &quot;value&quot;: &quot;nginx:latest&quot;}]'
|
||
target:
|
||
name: .*Deploy
|
||
kind: Deployment
|
||
</code></pre></blockquote>
|
||
<h2 id="_prefixsuffixtransformer_"><em>PrefixSuffixTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-8">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-names-nameprefix-namesuffix">field names: <code>namePrefix</code>, <code>nameSuffix</code></h4>
|
||
<p>Prepends or postfixes the value to the names
|
||
of all resources.</p>
|
||
<p>E.g. a deployment named <code>wordpress</code> could
|
||
become <code>alices-wordpress</code> or <code>wordpress-v2</code>
|
||
or <code>alices-wordpress-v2</code>.</p>
|
||
<pre><code>namePrefix: alices-
|
||
nameSuffix: -v2
|
||
</code></pre><p>The suffix is appended before the content hash if
|
||
the resource type is ConfigMap or Secret.</p>
|
||
<h3 id="usage-via-plugin-8">Usage via plugin</h3>
|
||
<h4 id="arguments-8">Arguments</h4>
|
||
<blockquote>
|
||
<p>Prefix string</p>
|
||
<p>Suffix string</p>
|
||
<p>FieldSpecs []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go">config.FieldSpec</a></p>
|
||
</blockquote>
|
||
<h4 id="example-8">Example</h4>
|
||
<blockquote>
|
||
<pre><code>apiVersion: builtin
|
||
kind: PrefixSuffixTransformer
|
||
metadata:
|
||
name: not-important-to-example
|
||
prefix: baked-
|
||
suffix: -pie
|
||
fieldSpecs:
|
||
- path: metadata/name
|
||
</code></pre></blockquote>
|
||
<h2 id="_replicacounttransformer_"><em>ReplicaCountTransformer</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-9">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-replicas">field name: <code>replicas</code></h4>
|
||
<p>Replicas modified the number of replicas for a resource.</p>
|
||
<p>E.g. Given this kubernetes Deployment fragment:</p>
|
||
<pre><code>kind: Deployment
|
||
metadata:
|
||
name: deployment-name
|
||
spec:
|
||
replicas: 3
|
||
</code></pre><p>one can change the number of replicas to 5
|
||
by adding the following to your kustomization:</p>
|
||
<pre><code>replicas:
|
||
- name: deployment-name
|
||
count: 5
|
||
</code></pre><p>This field accepts a list, so many resources can
|
||
be modified at the same time.</p>
|
||
<p>As this declaration does not take in a <code>kind:</code> nor a <code>group:</code>
|
||
it will match any <code>group</code> and <code>kind</code> that has a matching name and
|
||
that is one of:</p>
|
||
<ul>
|
||
<li><code>Deployment</code></li>
|
||
<li><code>ReplicationController</code></li>
|
||
<li><code>ReplicaSet</code></li>
|
||
<li><code>StatefulSet</code></li>
|
||
</ul>
|
||
<p>For more complex use cases, revert to using a patch.</p>
|
||
<h3 id="usage-via-plugin-9">Usage via plugin</h3>
|
||
<h4 id="arguments-9">Arguments</h4>
|
||
<blockquote>
|
||
<p>Replica <a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/replica.go">types.Replica</a></p>
|
||
<p>FieldSpecs []<a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/fieldspec.go">config.FieldSpec</a></p>
|
||
</blockquote>
|
||
<h4 id="example-9">Example</h4>
|
||
<blockquote>
|
||
<pre><code>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
|
||
</code></pre></blockquote>
|
||
<h2 id="_secretgenerator_"><em>SecretGenerator</em></h2>
|
||
<h3 id="usage-via-kustomizationyaml-10">Usage via <code>kustomization.yaml</code></h3>
|
||
<h4 id="field-name-secretgenerator">field name: <code>secretGenerator</code></h4>
|
||
<p>Each entry in the argument list
|
||
results in the creation of
|
||
one Secret resource
|
||
(it&rsquo;s a generator of n secrets).</p>
|
||
<p>This works like the <code>configMapGenerator</code> field
|
||
described above.</p>
|
||
<pre><code>secretGenerator:
|
||
- name: app-tls
|
||
files:
|
||
- secret/tls.cert
|
||
- secret/tls.key
|
||
type: &quot;kubernetes.io/tls&quot;
|
||
- name: app-tls-namespaced
|
||
# you can define a namespace to generate
|
||
# a secret in, defaults to: &quot;default&quot;
|
||
namespace: apps
|
||
files:
|
||
- tls.crt=catsecret/tls.cert
|
||
- tls.key=secret/tls.key
|
||
type: &quot;kubernetes.io/tls&quot;
|
||
- name: env_file_secret
|
||
envs:
|
||
- env.txt
|
||
type: Opaque
|
||
- name: secret-with-annotation
|
||
files:
|
||
- app-config.yaml
|
||
type: Opaque
|
||
options:
|
||
annotations:
|
||
app_config: &quot;true&quot;
|
||
labels:
|
||
app.kubernetes.io/name: &quot;app2&quot;
|
||
</code></pre><h3 id="usage-via-plugin-10">Usage via plugin</h3>
|
||
<h4 id="arguments-10">Arguments</h4>
|
||
<blockquote>
|
||
<p><a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/objectmeta.go">types.ObjectMeta</a></p>
|
||
<p><a href="https://github.com/kubernetes-sigs/kustomize/tree/master/api/types/secretargs.go">types.SecretArgs</a></p>
|
||
</blockquote>
|
||
<h4 id="example-10">Example</h4>
|
||
<blockquote>
|
||
<pre><code>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
|
||
</code></pre></blockquote>
|
||
|
||
</description>
|
||
</item>
|
||
|
||
<item>
|
||
<title>Guides: Exec plugin on linux</title>
|
||
<link>https://kubernetes-sigs.github.io/kustomize/guides/plugins/execpluginguidedexample/</link>
|
||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||
|
||
<guid>https://kubernetes-sigs.github.io/kustomize/guides/plugins/execpluginguidedexample/</guid>
|
||
<description>
|
||
|
||
|
||
<p>This is a (no reading allowed!) 60 second copy/paste guided
|
||
example. Full plugin docs <a href="..">here</a>.</p>
|
||
<p>This demo writes and uses a somewhat ridiculous
|
||
<em>exec</em> plugin (written in bash) that generates a
|
||
<code>ConfigMap</code>.</p>
|
||
<p>This is a guide to try it without damaging your
|
||
current setup.</p>
|
||
<h4 id="requirements">requirements</h4>
|
||
<ul>
|
||
<li>linux, git, curl, Go 1.13</li>
|
||
</ul>
|
||
<h2 id="make-a-place-to-work">Make a place to work</h2>
|
||
<pre><code>DEMO=$(mktemp -d)
|
||
</code></pre><h2 id="create-a-kustomization">Create a kustomization</h2>
|
||
<p>Make a kustomization directory to
|
||
hold all your config:</p>
|
||
<pre><code>MYAPP=$DEMO/myapp
|
||
mkdir -p $MYAPP
|
||
</code></pre><p>Make a deployment config:</p>
|
||
<pre><code>cat &lt;&lt;'EOF' &gt;$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: [&quot;/hello&quot;,
|
||
&quot;--port=8080&quot;,
|
||
&quot;--date=$(THE_DATE)&quot;,
|
||
&quot;--enableRiskyFeature=$(ENABLE_RISKY)&quot;]
|
||
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
|
||
</code></pre><p>Make a service config:</p>
|
||
<pre><code>cat &lt;&lt;EOF &gt;$MYAPP/service.yaml
|
||
kind: Service
|
||
apiVersion: v1
|
||
metadata:
|
||
name: the-service
|
||
spec:
|
||
type: LoadBalancer
|
||
ports:
|
||
- protocol: TCP
|
||
port: 8666
|
||
targetPort: 8080
|
||
EOF
|
||
</code></pre><p>Now make a config file for the plugin
|
||
you&rsquo;re about to write.</p>
|
||
<p>This config file is just another k8s resource
|
||
object. The values of its <code>apiVersion</code> and <code>kind</code>
|
||
fields are used to <em>find</em> the plugin code on your
|
||
filesystem (more on this later).</p>
|
||
<pre><code>cat &lt;&lt;'EOF' &gt;$MYAPP/cmGenerator.yaml
|
||
apiVersion: myDevOpsTeam
|
||
kind: SillyConfigMapGenerator
|
||
metadata:
|
||
name: whatever
|
||
argsOneLiner: Bienvenue true
|
||
EOF
|
||
</code></pre><p>Finally, make a kustomization file
|
||
referencing all of the above:</p>
|
||
<pre><code>cat &lt;&lt;EOF &gt;$MYAPP/kustomization.yaml
|
||
commonLabels:
|
||
app: hello
|
||
resources:
|
||
- deployment.yaml
|
||
- service.yaml
|
||
generators:
|
||
- cmGenerator.yaml
|
||
EOF
|
||
</code></pre><p>Review the files</p>
|
||
<pre><code>ls -C1 $MYAPP
|
||
</code></pre><h2 id="make-a-home-for-plugins">Make a home for plugins</h2>
|
||
<p>Plugins must live in a particular place for
|
||
kustomize to find them.</p>
|
||
<p>This demo will use the ephemeral directory:</p>
|
||
<pre><code>PLUGIN_ROOT=$DEMO/kustomize/plugin
|
||
</code></pre><p>The plugin config defined above in
|
||
<code>$MYAPP/cmGenerator.yaml</code> specifies:</p>
|
||
<blockquote>
|
||
<pre><code>apiVersion: myDevOpsTeam
|
||
kind: SillyConfigMapGenerator
|
||
</code></pre></blockquote>
|
||
<p>This means the plugin must live in a directory
|
||
named:</p>
|
||
<pre><code>MY_PLUGIN_DIR=$PLUGIN_ROOT/myDevOpsTeam/sillyconfigmapgenerator
|
||
|
||
mkdir -p $MY_PLUGIN_DIR
|
||
</code></pre><p>The directory name is the plugin config&rsquo;s
|
||
<em>apiVersion</em> followed by its lower-cased <em>kind</em>.</p>
|
||
<p>A plugin gets its own directory to hold itself,
|
||
its tests and any supplemental data files it
|
||
might need.</p>
|
||
<h2 id="create-the-plugin">Create the plugin</h2>
|
||
<p>There are two kinds of plugins, <em>exec</em> and <em>Go</em>.</p>
|
||
<p>Make an <em>exec</em> plugin, installing it to the
|
||
correct directory and file name. The file name
|
||
must match the plugin&rsquo;s <em>kind</em> (in this case,
|
||
<code>SillyConfigMapGenerator</code>):</p>
|
||
<pre><code>cat &lt;&lt;'EOF' &gt;$MY_PLUGIN_DIR/SillyConfigMapGenerator
|
||
#!/bin/bash
|
||
# Skip the config file name argument.
|
||
shift
|
||
today=`date +%F`
|
||
echo &quot;
|
||
kind: ConfigMap
|
||
apiVersion: v1
|
||
metadata:
|
||
name: the-map
|
||
data:
|
||
today: $today
|
||
altGreeting: &quot;$1&quot;
|
||
enableRisky: &quot;$2&quot;
|
||
&quot;
|
||
EOF
|
||
</code></pre><p>By definition, an <em>exec</em> plugin must be executable:</p>
|
||
<pre><code>chmod a+x $MY_PLUGIN_DIR/SillyConfigMapGenerator
|
||
</code></pre><h2 id="install-kustomize">Install kustomize</h2>
|
||
<p>Per the <a href="https://kubernetes-sigs.github.io/kustomize/kustomize/installation">instructions</a>:</p>
|
||
<pre><code>curl -s &quot;https://raw.githubusercontent.com/\
|
||
kubernetes-sigs/kustomize/master/hack/install_kustomize.sh&quot; | bash
|
||
mkdir -p $DEMO/bin
|
||
mv kustomize $DEMO/bin
|
||
</code></pre><h2 id="review-the-layout">Review the layout</h2>
|
||
<pre><code>tree $DEMO
|
||
</code></pre><h2 id="build-your-app-using-the-plugin">Build your app, using the plugin</h2>
|
||
<pre><code>XDG_CONFIG_HOME=$DEMO $DEMO/bin/kustomize build --enable_alpha_plugins $MYAPP
|
||
</code></pre><p>Above, if you had set</p>
|
||
<blockquote>
|
||
<pre><code>PLUGIN_ROOT=$HOME/.config/kustomize/plugin
|
||
</code></pre></blockquote>
|
||
<p>there would be no need to use <code>XDG_CONFIG_HOME</code> in the
|
||
<em>kustomize</em> command above.</p>
|
||
|
||
</description>
|
||
</item>
|
||
|
||
<item>
|
||
<title>Guides: Go plugin Caveats</title>
|
||
<link>https://kubernetes-sigs.github.io/kustomize/guides/plugins/goplugincaveats/</link>
|
||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||
|
||
<guid>https://kubernetes-sigs.github.io/kustomize/guides/plugins/goplugincaveats/</guid>
|
||
<description>
|
||
|
||
|
||
<p>A <em>Go plugin</em> is a compilation artifact described
|
||
by the Go <a href="https://golang.org/pkg/plugin">plugin package</a>. It is built with
|
||
special flags and cannot run on its own.
|
||
It must be loaded into a running Go program.</p>
|
||
<blockquote>
|
||
<p>A normal program written in Go might be usable
|
||
as <em>exec plugin</em>, but is not a <em>Go plugin</em>.</p>
|
||
</blockquote>
|
||
<p>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.</p>
|
||
<p>Go plugins work as described in the <a href="https://golang.org/pkg/plugin">plugin
|
||
package</a>, but fall short of common notions
|
||
associated with the word <em>plugin</em>.</p>
|
||
<h2 id="the-skew-problem">The skew problem</h2>
|
||
<p>Go plugin compilation creates an <a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">ELF</a> formatted
|
||
<code>.so</code> file, which by definition has no information
|
||
about the provenance of the object code.</p>
|
||
<p>Skew between the compilation conditions (versions
|
||
of package dependencies, <code>GOOS</code>, <code>GOARCH</code>) of the
|
||
main program ELF and the plugin ELF will cause
|
||
plugin load failure, with non-helpful error
|
||
messages.</p>
|
||
<p>Exec plugins also lack provenance, but won&rsquo;t fail
|
||
due to compilation skew.</p>
|
||
<p>In either case, the only sensible way to share a
|
||
plugin is as some kind of <em>bundle</em> (a git repo
|
||
URL, a git archive file, a tar file, etc.)
|
||
containing source code, tests and associated data,
|
||
unpackable under
|
||
<code>$XDG_CONFIG_HOME/kustomize/plugin</code>.</p>
|
||
<p>In the case of a Go plugin, an <em>end user</em>
|
||
accepting a shared plugin <em>must compile both
|
||
kustomize and the plugin</em>.</p>
|
||
<p>This means a one-time run of</p>
|
||
<pre><code># Or whatever is appropriate at time of reading
|
||
GOPATH=${whatever} GO111MODULE=on go get sigs.k8s.io/kustomize/api
|
||
</code></pre><p>and then a normal development cycle using</p>
|
||
<pre><code>go build -buildmode plugin \
|
||
-o ${wherever}/${kind}.so ${wherever}/${kind}.go
|
||
</code></pre><p>with paths and the release version tag (e.g. <code>v3.0.0</code>)
|
||
adjusted as needed.</p>
|
||
<p>For comparison, consider what one
|
||
must do to write a <a href="https://www.tensorflow.org/guide/extend/op">tensorflow plugin</a>.</p>
|
||
<h2 id="why-support-go-plugins">Why support Go plugins</h2>
|
||
<h3 id="safety">Safety</h3>
|
||
<p>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.</p>
|
||
<p>Minor point: if the plugin reads files via
|
||
the kustomize-provided file <code>Loader</code> interface, it
|
||
will be constrained by kustomize file loading
|
||
restrictions. Of course, nothing but a code audit
|
||
prevents a Go plugin from importing the <code>io</code> package
|
||
and doing whatever it wants.</p>
|
||
<h3 id="debugging">Debugging</h3>
|
||
<p>A Go plugin developer can debug the plugin <em>in
|
||
situ</em>, setting breakpoints inside the plugin and
|
||
elsewhere while running a plugin in feature tests.</p>
|
||
<p>To get the best of both worlds (shareability and safety),
|
||
a developer can write an <code>.go</code> program that functions
|
||
as an <em>exec plugin</em>, but can be processed by <code>go generate</code>
|
||
to emit a <em>Go plugin</em> (or vice versa).</p>
|
||
<h3 id="unit-of-contribution">Unit of contribution</h3>
|
||
<p>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).</p>
|
||
<h3 id="ecosystems-grow-through-use">Ecosystems grow through use</h3>
|
||
<p>Tooling could ease Go plugin <em>sharing</em>, but this
|
||
requires some critical mass of Go plugin
|
||
<em>authoring</em>, which in turn is hampered by
|
||
confusion around sharing. <a href="https://github.com/golang/go/wiki/Modules">Go modules</a>, once they
|
||
are more widely adopted, will solve the
|
||
biggest plugin sharing difficulty: ambiguous
|
||
plugin vs host dependencies.</p>
|
||
|
||
</description>
|
||
</item>
|
||
|
||
<item>
|
||
<title>Guides: Go plugin example</title>
|
||
<link>https://kubernetes-sigs.github.io/kustomize/guides/plugins/gopluginguidedexample/</link>
|
||
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
|
||
|
||
<guid>https://kubernetes-sigs.github.io/kustomize/guides/plugins/gopluginguidedexample/</guid>
|
||
<description>
|
||
|
||
|
||
<h1 id="go-plugin-guided-example-for-linux">Go Plugin Guided Example for Linux</h1>
|
||
<p>This is a (no reading allowed!) 60 second copy/paste guided
|
||
example.</p>
|
||
<p>Full plugin docs <a href="README.md">here</a>.
|
||
Be sure to read the <a href="goPluginCaveats.md">Go plugin caveats</a>.</p>
|
||
<p>This demo uses a Go plugin, <code>SopsEncodedSecrets</code>,
|
||
that lives in the <a href="https://github.com/monopole/sopsencodedsecrets">sopsencodedsecrets repository</a>.
|
||
This is an inprocess <a href="https://golang.org/pkg/plugin">Go plugin</a>, not an
|
||
sub-process exec plugin that happens to be written
|
||
in Go (which is another option for Go authors).</p>
|
||
<p>This is a guide to try it without damaging your
|
||
current setup.</p>
|
||
<h4 id="requirements">requirements</h4>
|
||
<ul>
|
||
<li>linux, git, curl, Go 1.13</li>
|
||
</ul>
|
||
<p>For encryption</p>
|
||
<ul>
|
||
<li>gpg</li>
|
||
</ul>
|
||
<p>Or</p>
|
||
<ul>
|
||
<li>Google cloud (gcloud) install</li>
|
||
<li>a Google account with KMS permission</li>
|
||
</ul>
|
||
<h2 id="make-a-place-to-work">Make a place to work</h2>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#8f5902;font-style:italic"># Keeping these separate to avoid cluttering the DEMO dir.</span>
|
||
<span style="color:#000">DEMO</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#204a87;font-weight:bold">$(</span>mktemp -d<span style="color:#204a87;font-weight:bold">)</span>
|
||
<span style="color:#000">tmpGoPath</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#204a87;font-weight:bold">$(</span>mktemp -d<span style="color:#204a87;font-weight:bold">)</span>
|
||
</code></pre></div><h2 id="install-kustomize">Install kustomize</h2>
|
||
<p>Need v3.0.0 for what follows, and you must <em>compile</em>
|
||
it (not download the binary from the release page):</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">GOPATH</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$tmpGoPath</span> go install sigs.k8s.io/kustomize/kustomize
|
||
</code></pre></div><h2 id="make-a-home-for-plugins">Make a home for plugins</h2>
|
||
<p>A kustomize plugin is fully determined by
|
||
its configuration file and source code.</p>
|
||
<p>Kustomize plugin configuration files are formatted
|
||
as kubernetes resource objects, meaning
|
||
<code>apiVersion</code>, <code>kind</code> and <code>metadata</code> are <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields">required
|
||
fields</a> in these config files.</p>
|
||
<p>The kustomize program reads the config file
|
||
(because the config file name appears in the
|
||
<code>generators</code> or <code>transformers</code> field in the
|
||
kustomization file), then locates the Go plugin&rsquo;s
|
||
object code at the following location:</p>
|
||
<blockquote>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">$XDG_CONFIG_HOME</span>/kustomize/plugin/<span style="color:#000">$apiVersion</span>/<span style="color:#000">$lKind</span>/<span style="color:#000">$kind</span>.so
|
||
</code></pre></div></blockquote>
|
||
<p>where <code>lKind</code> holds the lowercased kind. The
|
||
plugin is then loaded and fed its config, and the
|
||
plugin&rsquo;s output becomes part of the overall
|
||
<code>kustomize build</code> process.</p>
|
||
<p>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&rsquo;s not
|
||
left to plugins to find their own config.</p>
|
||
<p>This demo will house the plugin it uses at the
|
||
ephemeral directory</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">PLUGIN_ROOT</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$DEMO</span>/kustomize/plugin
|
||
</code></pre></div><p>and ephemerally set <code>XDG_CONFIG_HOME</code> on a command
|
||
line below.</p>
|
||
<h3 id="what-apiversion-and-kind">What apiVersion and kind</h3>
|
||
<p>At this stage in the development of kustomize
|
||
plugins, plugin code doesn&rsquo;t know or care what
|
||
<code>apiVersion</code> or <code>kind</code> appears in the config file
|
||
sent to it.</p>
|
||
<p>The plugin could check these fields, but it&rsquo;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.</p>
|
||
<p>This demo uses a plugin called <em>SopsEncodedSecrets</em>,
|
||
and it lives in the <a href="https://github.com/monopole/sopsencodedsecrets">SopsEncodedSecrets repository</a>.</p>
|
||
<p>Somewhat arbitrarily, we&rsquo;ll chose to install
|
||
this plugin with</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">apiVersion</span><span style="color:#ce5c00;font-weight:bold">=</span>mygenerators
|
||
<span style="color:#000">kind</span><span style="color:#ce5c00;font-weight:bold">=</span>SopsEncodedSecrets
|
||
</code></pre></div><h3 id="define-the-plugins-home-dir">Define the plugin&rsquo;s home dir</h3>
|
||
<p>By convention, the ultimate home of the plugin
|
||
code and supplemental data, tests, documentation,
|
||
etc. is the lowercase form of its kind.</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">lKind</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#204a87;font-weight:bold">$(</span><span style="color:#204a87">echo</span> <span style="color:#000">$kind</span> <span style="color:#000;font-weight:bold">|</span> awk <span style="color:#4e9a06">&#39;{print tolower($0)}&#39;</span><span style="color:#204a87;font-weight:bold">)</span>
|
||
</code></pre></div><h3 id="download-the-sopsencodedsecrets-plugin">Download the SopsEncodedSecrets plugin</h3>
|
||
<p>In this case, the repo name matches the lowercase
|
||
kind already, so we just clone the repo and get
|
||
the proper directory name automatically:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">mkdir -p <span style="color:#000">$PLUGIN_ROOT</span>/<span style="color:#4e9a06">${</span><span style="color:#000">apiVersion</span><span style="color:#4e9a06">}</span>
|
||
<span style="color:#204a87">cd</span> <span style="color:#000">$PLUGIN_ROOT</span>/<span style="color:#4e9a06">${</span><span style="color:#000">apiVersion</span><span style="color:#4e9a06">}</span>
|
||
git clone git@github.com:monopole/sopsencodedsecrets.git
|
||
</code></pre></div><p>Remember this directory:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">MY_PLUGIN_DIR</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$PLUGIN_ROOT</span>/<span style="color:#4e9a06">${</span><span style="color:#000">apiVersion</span><span style="color:#4e9a06">}</span>/<span style="color:#4e9a06">${</span><span style="color:#000">lKind</span><span style="color:#4e9a06">}</span>
|
||
</code></pre></div><h3 id="try-the-plugins-own-test">Try the plugin&rsquo;s own test</h3>
|
||
<p>Plugins may come with their own tests.
|
||
This one does, and it hopefully passes:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#204a87">cd</span> <span style="color:#000">$MY_PLUGIN_DIR</span>
|
||
go <span style="color:#204a87">test</span> SopsEncodedSecrets_test.go
|
||
</code></pre></div><p>Build the object code for use by kustomize:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#204a87">cd</span> <span style="color:#000">$MY_PLUGIN_DIR</span>
|
||
<span style="color:#000">GOPATH</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$tmpGoPath</span> go build -buildmode plugin -o <span style="color:#4e9a06">${</span><span style="color:#000">kind</span><span style="color:#4e9a06">}</span>.so <span style="color:#4e9a06">${</span><span style="color:#000">kind</span><span style="color:#4e9a06">}</span>.go
|
||
</code></pre></div><p>This step may succeed, but kustomize might
|
||
ultimately fail to load the plugin because of
|
||
dependency <a href="https://kubernetes-sigs.github.io/kustomize/docs/plugins/README.md#caveats">skew</a>.</p>
|
||
<p>On load failure</p>
|
||
<ul>
|
||
<li>
|
||
<p>be sure to build the plugin with the same
|
||
version of Go (<em>go1.13</em>) on the same <code>$GOOS</code>
|
||
(<em>linux</em>) and <code>$GOARCH</code> (<em>amd64</em>) used to build
|
||
the kustomize being <a href="#install-kustomize">used in this demo</a>.</p>
|
||
</li>
|
||
<li>
|
||
<p>change the plugin&rsquo;s dependencies in its <code>go.mod</code>
|
||
to match the versions used by kustomize (check
|
||
kustomize&rsquo;s <code>go.mod</code> used in its tagged commit).</p>
|
||
</li>
|
||
</ul>
|
||
<p>Lacking tools and metadata to allow this to be
|
||
automated, there won&rsquo;t be a Go plugin ecosystem.</p>
|
||
<p>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.</p>
|
||
<h2 id="create-a-kustomization">Create a kustomization</h2>
|
||
<p>Make a kustomization directory to
|
||
hold all your config:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">MYAPP</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$DEMO</span>/myapp
|
||
mkdir -p <span style="color:#000">$MYAPP</span>
|
||
</code></pre></div><p>Make a config file for the SopsEncodedSecrets plugin.</p>
|
||
<p>Its <code>apiVersion</code> and <code>kind</code> allow the plugin to be
|
||
found:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">cat <span style="color:#4e9a06">&lt;&lt;EOF &gt;$MYAPP/secGenerator.yaml
|
||
</span><span style="color:#4e9a06">apiVersion: ${apiVersion}
|
||
</span><span style="color:#4e9a06">kind: ${kind}
|
||
</span><span style="color:#4e9a06">metadata:
|
||
</span><span style="color:#4e9a06"> name: mySecretGenerator
|
||
</span><span style="color:#4e9a06">name: forbiddenValues
|
||
</span><span style="color:#4e9a06">namespace: production
|
||
</span><span style="color:#4e9a06">file: myEncryptedData.yaml
|
||
</span><span style="color:#4e9a06">keys:
|
||
</span><span style="color:#4e9a06">- ROCKET
|
||
</span><span style="color:#4e9a06">- CAR
|
||
</span><span style="color:#4e9a06">EOF</span>
|
||
</code></pre></div><p>This plugin expects to find more data in
|
||
<code>myEncryptedData.yaml</code>; we&rsquo;ll get to that shortly.</p>
|
||
<p>Make a kustomization file referencing the plugin
|
||
config:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">cat <span style="color:#4e9a06">&lt;&lt;EOF &gt;$MYAPP/kustomization.yaml
|
||
</span><span style="color:#4e9a06">commonLabels:
|
||
</span><span style="color:#4e9a06"> app: hello
|
||
</span><span style="color:#4e9a06">generators:
|
||
</span><span style="color:#4e9a06">- secGenerator.yaml
|
||
</span><span style="color:#4e9a06">EOF</span>
|
||
</code></pre></div><p>Now generate the real encrypted data.</p>
|
||
<h3 id="assure-you-have-an-encryption-tool-installed">Assure you have an encryption tool installed</h3>
|
||
<p>We&rsquo;re going to use <a href="https://github.com/mozilla/sops">sops</a> to encode a file. Choose either GPG or Google Cloud KMS as the secret provider to continue.</p>
|
||
<h4 id="gpg">GPG</h4>
|
||
<p>Try this:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">gpg --list-keys
|
||
</code></pre></div><p>If it returns a list, presumably you&rsquo;ve already created keys. If not, try import test keys from sops for dev.</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">curl https://raw.githubusercontent.com/mozilla/sops/master/pgp/sops_functional_tests_key.asc <span style="color:#000;font-weight:bold">|</span> gpg --import
|
||
<span style="color:#000">SOPS_PGP_FP</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#34;1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A&#34;</span>
|
||
</code></pre></div><h4 id="google-cloude-kms">Google Cloude KMS</h4>
|
||
<p>Try this:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">gcloud kms keys list --location global --keyring sops
|
||
</code></pre></div><p>If it succeeds, presumably you&rsquo;ve already created keys and placed them in a keyring called sops. If not, do this:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">gcloud kms keyrings create sops --location global
|
||
gcloud kms keys create sops-key --location global <span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> --keyring sops --purpose encryption
|
||
</code></pre></div><p>Extract your keyLocation for use below:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">keyLocation</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#204a87;font-weight:bold">$(</span><span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> gcloud kms keys list --location global --keyring sops <span style="color:#000;font-weight:bold">|</span><span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> grep GOOGLE <span style="color:#000;font-weight:bold">|</span> cut -d <span style="color:#4e9a06">&#34; &#34;</span> -f1<span style="color:#204a87;font-weight:bold">)</span>
|
||
<span style="color:#204a87">echo</span> <span style="color:#000">$keyLocation</span>
|
||
</code></pre></div><h3 id="install-sops">Install <code>sops</code></h3>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">GOPATH</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$tmpGoPath</span> go install go.mozilla.org/sops/cmd/sops
|
||
</code></pre></div><h3 id="create-data-encrypted-with-your-private-key">Create data encrypted with your private key</h3>
|
||
<p>Create raw data to encrypt:</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">cat <span style="color:#4e9a06">&lt;&lt;EOF &gt;$MYAPP/myClearData.yaml
|
||
</span><span style="color:#4e9a06">VEGETABLE: carrot
|
||
</span><span style="color:#4e9a06">ROCKET: saturn-v
|
||
</span><span style="color:#4e9a06">FRUIT: apple
|
||
</span><span style="color:#4e9a06">CAR: dymaxion
|
||
</span><span style="color:#4e9a06">EOF</span>
|
||
</code></pre></div><p>Encrypt the data into file the plugin wants to read:</p>
|
||
<p>With PGP</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">$tmpGoPath</span>/bin/sops --encrypt <span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> --pgp <span style="color:#000">$SOPS_PGP_FP</span> <span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> <span style="color:#000">$MYAPP</span>/myClearData.yaml &gt;<span style="color:#000">$MYAPP</span>/myEncryptedData.yaml
|
||
</code></pre></div><p>Or GCP KMS</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">$tmpGoPath</span>/bin/sops --encrypt <span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> --gcp-kms <span style="color:#000">$keyLocation</span> <span style="color:#4e9a06">\
|
||
</span><span style="color:#4e9a06"></span> <span style="color:#000">$MYAPP</span>/myClearData.yaml &gt;<span style="color:#000">$MYAPP</span>/myEncryptedData.yaml
|
||
</code></pre></div><p>Review the files</p>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">tree <span style="color:#000">$DEMO</span>
|
||
</code></pre></div><p>This should look something like:</p>
|
||
<blockquote>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="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
|
||
</code></pre></div></blockquote>
|
||
<h2 id="build-your-app-using-the-plugin">Build your app, using the plugin</h2>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">XDG_CONFIG_HOME</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$DEMO</span> <span style="color:#000">$tmpGoPath</span>/bin/kustomize build --enable_alpha_plugins <span style="color:#000">$MYAPP</span>
|
||
</code></pre></div><p>This should emit a kubernetes secret, with
|
||
encrypted data for the names <code>ROCKET</code> and <code>CAR</code>.</p>
|
||
<p>Above, if you had set</p>
|
||
<blockquote>
|
||
<div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#000">PLUGIN_ROOT</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$HOME</span>/.config/kustomize/plugin
|
||
</code></pre></div></blockquote>
|
||
<p>there would be no need to use <code>XDG_CONFIG_HOME</code> in the
|
||
<em>kustomize</em> command above.</p>
|
||
|
||
</description>
|
||
</item>
|
||
|
||
</channel>
|
||
</rss>
|