Kubernetes templates made easy.
#keep-it-simple #no-server-component
Features:
- Template flavor of your choice
- $ (
$VAR/${VAR}); - go-template (go-template enriched with sprig);
- template-kind (
kind: Template).
- $ (
- Support for *.env (
<VAR>=<VAL>) and YAML / JSON config files. - Fail-fast defaults (all variables must be given a value (unless explicitly marked optional)).
- ConfigMap/Secret freezing for easier and less error-prone ConfigMap/Secret rollouts
(something to considerifwhen you hit kubernetes/kubernetes#22368). - ConfigMap/Secret "data-from-file" injection when
kubectl create configmap ... --from-file=... --from-file=... --from-file=... ...feels like too much typing. image:tag->image@digestpinning with the help of dockry
(e.g.kubetpl render -s IMAGE=$(dockry digest --fq user/image:master) ...to force redeployment of the new build published under the same tag).
curl -sSL https://github.com/shyiko/kubetpl/releases/download/0.9.0/kubetpl-0.9.0-$(
bash -c '[[ $OSTYPE == darwin* ]] && echo darwin || echo linux'
)-amd64 -o kubetpl && chmod a+x kubetpl && sudo mv kubetpl /usr/local/bin/Verify PGP signature (optional but recommended):
curl -sSL https://github.com/shyiko/kubetpl/releases/download/0.9.0/kubetpl-0.9.0-$(
bash -c '[[ $OSTYPE == darwin* ]] && echo darwin || echo linux'
)-amd64.asc -o kubetpl.asc
curl -sS https://keybase.io/shyiko/pgp_keys.asc | gpg --import
gpg --verify kubetpl.asc /usr/local/bin/kubetplmacOS:
gpgcan be installed withbrew install gnupg
Download executable from the Releases page.
# create template
echo $'
# kubetpl:syntax:$
apiVersion: v1
kind: Pod
metadata:
name: $NAME-pod
spec:
containers:
- name: $NAME-container
image: $IMAGE
env:
- name: ENV_KEY
value: $ENV_KEY
' > template.yml
# create config file (.env, .yml/.yaml or .json) (optional)
# (you'll probably have a different config file for each cluster/namespace/etc)
echo $'
NAME=sample-app
ENV_KEY=value
' > staging.env
# you might not need a config file if there are only a handful of variables (like in this case)
# -s/--set key=value might be enough
# render template
kubetpl render template.yml -i staging.env -s IMAGE=nginx
# to apply, pipe "render"ed output through kubectl
kubetpl render template.yml -i staging.env -s IMAGE=nginx |
kubectl apply -f -
# you can also apply remote template(s)
kubetpl render https://rawgit.com/shyiko/kubetpl/master/example/nginx.sh.yml \
-s NAME=kubetpl-example-nginx -s MESSAGE="hello $(whoami)" |
kubectl apply -f -(for more examples see Template flavors)
# bash
source <(kubetpl completion bash)
# zsh
source <(kubetpl completion zsh)When kubetpl render --freeze ... is used, kubetpl rewrites ConfigMap/Secret's name to include hash of the content
and then updates all the references (in Pods / DaemonSets / Deployments / Jobs / ReplicaSets / ReplicationControllers / StatefulSets / CronJobs) with a new value.
For example, executing kubetpl render --freeze example/nginx-with-data-from-file.yml -s NAME=app -s MESSAGE=msg
should produce example/nginx-with-data-from-file.rendered+frozen.yml.
NOTE: this feature can be used regardless of the Template flavor choice (or lack thereof (i.e. on its own)).
[email protected]+ also supports
kubetpl/data-from-env-file.
Optionally, ConfigMap/Secret|s can be extended with kubetpl/data-from-file to load "data" from a list of files (relative to a template unless a different -c/--chroot is specified), e.g.
kind: ConfigMap
kubetpl/data-from-file:
- file
- path/to/another-file
- custom-key=yet-another-file
data:
key: value
...Upon kubetpl render the content of file, another-file and yet-another-file (using custom-key as a key)
will be added to the object's "data" (kubetpl/data-from-file is automatically striped away).
For example, executing kubetpl render --allow-fs-access example/nginx-with-data-from-file.yml -s NAME=app
should produce example/nginx-with-data-from-file.rendered.yml.
NOTE #1: for security reasons, kubetpl/data-form-file is not allowed to read files unless --allow-fs-access or -c/--chroot=<root dir> is specified (see kubetpl render --help for more).
NOTE #2: this feature can be used regardless of the Template flavor choice (or lack thereof (i.e. on its own)).
Template syntax is determined by first checking template for # kubetpl:syntax:<$|go-template|template-kind> comment
and then, if not found, --syntax=<$|go-template|template-kind> command line option. In the absence of both,
kubetpl assumes that template is a regular resource definition file.
A type of template where all instances of
Use
$$when you need a literal dollar sign ($$vis interpreted as$vstring and not'$' + <value_of_v>).
Let's say we have the following (click to expand):
<project_dir>/k8s/staging.env
NAME=sample-app
REPLICAS=1<project_dir>/k8s/template.yml
# kubetpl:syntax:$
apiVersion: v1
kind: Service
metadata:
name: $NAME-service
spec:
selector:
app: $NAME
ports:
- protocol: TCP
port: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: $NAME-deployment
spec:
replicas: $REPLICAS
template:
metadata:
labels:
app: $NAME
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kubetpl render k8s/template.yml -i k8s/staging.env -s REPLICAS=3 should then yield
(click to expand)
apiVersion: v1
kind: Service
metadata:
name: sample-app-service
spec:
selector:
app: sample-app
ports:
- protocol: TCP
port: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: sample-app-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
[email protected]+ default values can be specified via # kubetpl:set:KEY=VALUE directive(s), e.g.
# kubetpl:syntax:$
# kubetpl:set:NAME=nginx
# kubetpl:set:REPLICAS=1
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: $NAME
annotations:
version: $VERSION
spec:
replicas: $REPLICAS
... All functions provided by sprig are available
(with the exception ofenvandexpandenv).
A good overview of go-template|s can be found here. You might also want to check official documentation.
Some of the most commonly used expressions:
{{ .VAR }}- get the value ofVAR;{{ if isset "VAR" }} ... {{ end }}- render content between}}and{{only if .VAR is set;{{ get "VAR" "default" }}- get the value ofVAR, return"default"if not set (e.g.{{ get "REPLICAS" 1 }});{{ .VAR | quote }}- quote the value of VAR;{{ .VAR | indent 4 }}- indent value of VAR with 4 spaces;{{ .VAR | b64enc }}- base64-encode value of VAR.
Let's say we have the following (click to expand):
<project_dir>/k8s/staging.env
NAME=sample-app
REPLICAS=1<project_dir>/k8s/template.yml
# kubetpl:syntax:go-template
apiVersion: v1
kind: Service
metadata:
name: {{ .NAME }}-service
spec:
selector:
app: {{ .NAME }}
ports:
- protocol: TCP
port: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: {{ .NAME }}-deployment
spec:
replicas: {{ .REPLICAS }}
template:
metadata:
labels:
app: {{ .NAME }}
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
kubetpl render k8s/template.yml -i k8s/staging.env -s REPLICAS=3 should then yield
(click to expand)
apiVersion: v1
kind: Service
metadata:
name: sample-app-service
spec:
selector:
app: sample-app
ports:
- protocol: TCP
port: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: sample-app-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
aka
kind: Template.
As described in Templates + Parameterization proposal.
Let's say we have the following (click to expand):
<project_dir>/k8s/staging.env
NAME=sample-app<project_dir>/k8s/template.yml
# kubetpl:syntax:template-kind
kind: Template
apiVersion: v1
metadata:
name: nginx-template
annotations:
description: nginx template
objects:
- apiVersion: v1
kind: Service
metadata:
name: $(NAME)-service
spec:
selector:
app: $(NAME)
ports:
- protocol: TCP
port: 80
- apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: $(NAME)-deployment
spec:
replicas: $((REPLICAS))
template:
metadata:
labels:
app: $(NAME)
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
parameters:
- name: NAME
description: Application name
required: true
parameterType: string
- name: REPLICAS
description: Number of replicas
value: 1
required: true
parameterType: int
kubetpl render k8s/template.yml -i k8s/staging.env -s REPLICAS=3 should then yield
(click to expand)
apiVersion: v1
kind: Service
metadata:
name: sample-app-service
spec:
selector:
app: sample-app
ports:
- protocol: TCP
port: 80
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: sample-app-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80PREREQUISITE: go1.9+.
git clone https://github.com/shyiko/kubetpl $GOPATH/src/github.com/shyiko/kubetpl
cd $GOPATH/src/github.com/shyiko/kubetpl
make fetch
go run kubetpl.goAll code, unless specified otherwise, is licensed under the MIT license.
Copyright (c) 2018 Stanley Shyiko.