diff --git a/cmd/kinflate/README.md b/cmd/kinflate/README.md index ac99bf6b7..0b130a4d4 100644 --- a/cmd/kinflate/README.md +++ b/cmd/kinflate/README.md @@ -1,77 +1,44 @@ -# Overview +# kinflate + +[_kubectl apply_]: https://goo.gl/UbCRuf +[Declarative Application Management]: https://goo.gl/T66ZcD + + +`kinflate` is a command line tool supporting +template-free customization of declarative +configuration targetted to kubernetes. + +It's an implementation of ideas described in Brian +Grant's [Declarative Application Management] proposal. + + +## Design tenets + + * __composable__: do one thing, use plain text, work + with pipes, usable in other tools (e.g. helm, + kubernetes-deploy, etc.). + + * __simple__: no templating, no logic, no inheritance, + no new API obscuring the k8s API. + + * __accountable__: gitops friendly, diff against + declaration in version control, diff against + cluster. + + * __k8s style__: recognizable k8s resources, + extensible (openAPI, CRDs), + patching, intended for [_kubectl apply_]. -`kinflate` is a command line interface to manage Kubernetes Application configuration. ## Installation -`kinflate` is written in Go and can be installed using `go get`: - -```shell +``` go get k8s.io/kubectl/cmd/kinflate ``` -After running the above command, `kinflate` should get installed in your `GOPATH/bin` directory. +## Demos -## Usage - -This section explains sub-commands of `kinflate` using examples. - -### init -`kinflate init` initializes a directory by creating an application manifest file named `Kube-manifest.yaml`. This command should be run in the same directory where application config resides. - -```shell -kinflate init -``` - -### set nameprefix - -`kinflate set nameprefix` updates the nameprefix field in the [manifest]. -`kinflate inflate` uses the prefix to generate prefixed names for Kubernetes resources. - -Examples -```shell -# set nameprefix to 'staging' -kinflate set nameprefix staging - -# set nameprefix to 'john` -kinflate set nameprefix john -``` - -### add -`kinflate add` adds a resource, configmap or secret to the [manifest]. - -#### examples -```shell -# adds a resource to the manifest -kinflate add resource - -# adds a configmap from a literal or file-source to the manifest -kinflate add configmap my-configmap --from-file=my-key=file/path --from-literal=my-literal=12345 - -# Adds a generic secret to the Manifest (with a specified key) -kinflate add secret generic my-secret --from-file=my-key=file/path --from-literal=my-literal=12345 - -# Adds a TLS secret to the Manifest (with a specified key) -kinflate add secret tls my-tls-secret --cert=cert/path.cert --key=key/path.key -``` - -### inflate -`kinflate inflate` generates application configuration by applying -transformations (e.g. name-prefix, label, annotations) specified in the [manifest]. - -#### examples -```shell -# generate application configuration and output to stdout -kinflate inflate -f - -# generate application configuration and apply it to a Kubernetes cluster -kinflate inflate -f | kubectl apply -f - -``` - - -## Demos and tutorial - - * [Getting Started](getting_started.md) - * [Short demo](shortDemo.md) - * [Longer demo / tutorial](longerDemo/README.md) + * [hello world one-pager](shortDemo.md) + * [hello world detailed, with instances](longerDemo/README.md) + * [mysql](getting_started.md) diff --git a/cmd/kinflate/getting_started.md b/cmd/kinflate/getting_started.md index e32a0bf64..8fffd5ec6 100644 --- a/cmd/kinflate/getting_started.md +++ b/cmd/kinflate/getting_started.md @@ -1,122 +1,118 @@ -# Kinflate: Getting Started +# MySql Example + +This example takes some off-the-shelf k8s resources +designed for MySQL, and customizes them to suit a +production scenario. + +In the production environment we want: -In this `getting started` guide, we will take an off-the-shelf MySQL configuration for Kubernetes and customize it to suit our production scenario. -In production environment, we want: - MySQL resource names to be prefixed by 'prod-' to make them distinguishable. -- MySQL resources to have 'env: prod' labels so that we can use label selector to query these. +- MySQL resources to have 'env: prod' labels so that we can use label selector to query these. - MySQL to use persistent disk for storing data. -## Installation +### Download resources -If you have `kinflate` installed already, then you can skip this step. `kinflate` can be installed using `go get`: - - -```shell -go get k8s.io/kubectl/cmd/kinflate -``` -This fetches kinflate and install `kinflate` executable under `GOPATH/bin` - you will want that on your $PATH. - - -### Get off-the-shelf MySQL configs for Kubernetes -Download a sample MySQL YAML manifest files: +Download `deployment.yaml`, `service.yaml` and +`secret.yaml`. These are plain k8s resources files one +could add to a k8s cluster to run MySql. -```shell -MYSQL_DIR=$HOME/kinflate_demo/mysql -rm -rf $MYSQL_DIR && mkdir -p $MYSQL_DIR -cd $MYSQL_DIR +``` +DEMO_HOME=$HOME/kinflate_demo/mysql +rm -rf $DEMO_HOME && mkdir -p $DEMO_HOME +cd $DEMO_HOME # Get MySQL configs for f in service secret deployment ; do \ - wget https://raw.githubusercontent.com/kinflate/mysql/master/emptyDir/$f.yaml ; \ + wget https://raw.githubusercontent.com/kinflate/mysql/master/emptyDir/$f.yaml ; \ done - ``` -This downloads YAML files `deployment.yaml`, `service.yaml` and `secret.yaml` which are needed to run MySQL in a Kubernetes cluster. -### Initialization -Now that we have base configuration for MySQL in place, we can begin with customization for production environment. Follow the step below: +### Initialize a manifest + +A manifest is needed to group these resources together. + +Create one: -```shell -mkdir -p $MYSQL_DIR/prod -cd $MYSQL_DIR/prod - -#initialize the customization +``` +mkdir -p $DEMO_HOME/prod +cd $DEMO_HOME/prod kinflate init - -cat Kube-manifest.yaml ``` -`Kube-manifest.yaml` should contain: +You should now have a file called `Kube-manifest.yaml`: + ``` -apiVersion: manifest.k8s.io/v1alpha1 -kind: Manifest -metadata: - name: helloworld -description: helloworld does useful stuff. -namePrefix: some-prefix -# Labels to add to all objects and selectors. -# These labels would also be used to form the selector for apply --prune -# Named differently than “labels” to avoid confusion with metadata for this object -objectLabels: - app: helloworld -objectAnnotations: - note: This is a example annotation -resources: -- deployment.yaml -- service.yaml -# There could also be configmaps in Base, which would make these overlays -configmaps: [] -# There could be secrets in Base, if just using a fork/rebase workflow -secrets: [] -recursive: true - +cat $DEMO_HOME/prod/Kube-manifest.yaml ``` -Lets break this down: -- First step create a directory called `prod` and switches to that dir. We will keep all the resources related to production customization in this directory. -- `kinflate init` generates a kinflate manifest file called `Kube-manifest.yaml` that contains metadata about the customizations. You can think of this file as containing instructions which inflate will use to apply to generate the required configuration. +containing something like: + + +> ``` +> apiVersion: manifest.k8s.io/v1alpha1 +> kind: Manifest +> metadata: +> name: helloworld +> description: helloworld does useful stuff. +> namePrefix: some-prefix +> # Labels to add to all objects and selectors. +> # These labels would also be used to form the selector for apply --prune +> # Named differently than “labels” to avoid confusion with metadata for this object +> objectLabels: +> app: helloworld +> objectAnnotations: +> note: This is a example annotation +> resources: +> - deployment.yaml +> - service.yaml +> # There could also be configmaps in Base, which would make these overlays +> configmaps: [] +> # There could be secrets in Base, if just using a fork/rebase workflow +> secrets: [] +> recursive: true +> ``` + ### Add resources -Lets add resource files that we want to `kinflate` to act on. Steps below add the three resources for MySQL. +Add the resources to the manifest -```shell +``` +cd $DEMO_HOME/prod -cd $MYSQL_DIR/prod - -# add the MySQL resources kinflate add resource ../secret.yaml kinflate add resource ../service.yaml kinflate add resource ../deployment.yaml -cat Kube-manifest.yaml +cat Kube-manifest.yaml ``` `Kube-manifest.yaml`'s resources section should contain: -``` -apiVersion: manifest.k8s.io/v1alpha1 -.... -.... -resources: -- ../secret.yaml -- ../service.yaml -- ../deployment.yaml -``` +> ``` +> apiVersion: manifest.k8s.io/v1alpha1 +> .... +> resources: +> - ../secret.yaml +> - ../service.yaml +> - ../deployment.yaml +> ``` Now we are ready to apply our first customization. ### NamePrefix Customization -We want MySQL resources to begin with prefix 'prod' in production environment. Follow the steps below: + +Arrange for the MySQL resources to begin with prefix +_prod-_ (since they are meant for the _production_ +environment): -```shell - -cd $MYSQL_DIR/prod +``` +cd $DEMO_HOME/prod kinflate set nameprefix 'prod-' @@ -125,95 +121,87 @@ cat Kube-manifest.yaml `Kube-manifest.yaml` should have updated value of namePrefix field: -``` -apiVersion: manifest.k8s.io/v1alpha1 -..... -..... -namePrefix: prod- -objectAnnotations: - note: This is a example annotation -..... +> ``` +> apiVersion: manifest.k8s.io/v1alpha1 +> .... +> namePrefix: prod- +> objectAnnotations: +> note: This is a example annotation +This `namePrefix` directive adds _prod-_ to all +resource names. -``` - -Lets break this down: -- `kinflate set nameprex ` updates the `namePrefix` directive to `prod` in the manifest file. -- Now if you view the `Kube-manifest.yaml`, you will see `namePrefix` directive updated. Editing the `namePrefix` directive in the file will also achieve the same thing. - -At this point you can run `kinflate inflate` to generate name-prefixed configuration as shown below. +Run kinflate: -```shell -cd $MYSQL_DIR/prod - -# lets generate name-prefixed resources +``` +cd $DEMO_HOME/prod kinflate inflate -f . ``` -Output should contain: -``` -apiVersion: v1 -data: - password: YWRtaW4= -kind: Secret -metadata: - .... - .... - name: prod-mysql-pass-d2gtcm2t2k ---- -apiVersion: v1 -kind: Service -metadata: - .... - .... - name: prod-mysql -spec: - .... ---- -apiVersion: apps/v1beta2 -kind: Deployment -metadata: - .... - .... - name: prod-mysql -spec: - selector: - .... - .... - -``` - +The output should contain: +> ``` +> apiVersion: v1 +> data: +> password: YWRtaW4= +> kind: Secret +> metadata: +> .... +> name: prod-mysql-pass-d2gtcm2t2k +> --- +> apiVersion: v1 +> kind: Service +> metadata: +> .... +> name: prod-mysql +> spec: +> .... +> --- +> apiVersion: apps/v1beta2 +> kind: Deployment +> metadata: +> .... +> name: prod-mysql +> spec: +> selector: +> .... +> ``` ### Label Customization -We want resources in production environment to have certain labels so that we can query them by label selector. `kinflate` does not have `set label` command to add label, but we can edit `Kube-manifest.yaml` file under `prod` directory and add the production labels under `objectLabels` fields as highlighted below. +We want resources in production environment to have +certain labels so that we can query them by label +selector. +`kinflate` does not have `set label` command to add +label, but we can edit `Kube-manifest.yaml` file under +`prod` directory and add the production labels under +`objectLabels` fields as highlighted below. + + ``` -cd $MYSQL_DIR/prod - -edit Kube-manifest.yaml - -# Edit the objectLabels -.... -objectLabels: - app: prod -.... - +cd $DEMO_HOME/prod +sed -i 's/app: helloworld/app: prod/' Kube-manifest.yaml ``` -At this point, running `kinflate inflate -f .` will generate MySQL configs with name-prefix 'prod-' and labels `env:prod`. +At this point, running `kinflate inflate -f .` will +generate MySQL configs with name-prefix 'prod-' and +labels `env:prod`. ### Storage customization -Off the shelf MySQL uses `emptyDir` type volume, which gets wiped away if the MySQL Pod is recreated, and that is certainly not desirable for production environment. So -we want to use Persistent Disk in production. Kinflate lets you apply `patches` to the resources. +Off the shelf MySQL uses `emptyDir` type volume, which +gets wiped away if the MySQL Pod is recreated, and that +is certainly not desirable for production +environment. So we want to use Persistent Disk in +production. Kinflate lets you apply `patches` to the +resources. -```shell -cd $MYSQL_DIR/prod +``` +cd $DEMO_HOME/prod -# create a patch for persistent-disk.yaml +# Create a patch for persistent-disk.yaml cat <<'EOF' > persistent-disk.yaml apiVersion: apps/v1beta2 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment @@ -229,15 +217,30 @@ spec: pdName: mysql-persistent-storage EOF -# edit the manifest file to add the above patch or run following command -cat <<'EOF' >> $MYSQL_DIR/prod/Kube-manifest.yaml +# Edit the manifest file to add the above patch: +cat <<'EOF' >> $DEMO_HOME/prod/Kube-manifest.yaml patches: - persistent-disk.yaml EOF ``` Lets break this down: -- In the first step, we created a YAML file named `persistent-disk.yaml` to patch the resource defined in deployment.yaml -- Then we added `persistent-disk.yaml` to list of `patches` in `Kube-manifest.yaml`. `kinflate inflate` will apply this patch to the deployment resource with the name `mysql` as defined in the patch. -At this point, if you run `kinflate inflate -f .`, it will generate the Kubernetes config for production environement. +- In the first step, we created a YAML file named + `persistent-disk.yaml` to patch the resource defined + in deployment.yaml + +- Then we added `persistent-disk.yaml` to list of + `patches` in `Kube-manifest.yaml`. `kinflate inflate` + will apply this patch to the deployment resource with + the name `mysql` as defined in the patch. + + +The output of the following command can now be applied +to the cluster (i.e. piped to `kubectl apply`) to +create the production environment. + + +``` +kinflate inflate -f $DEMO_HOME/prod # | kubectl apply -f - +``` diff --git a/cmd/kinflate/longerDemo/README.md b/cmd/kinflate/longerDemo/README.md index 1a4cf3c57..278752dc5 100644 --- a/cmd/kinflate/longerDemo/README.md +++ b/cmd/kinflate/longerDemo/README.md @@ -1,4 +1,4 @@ -# Kinflate Demo +# Demo: hello world with instances Goal: @@ -25,4 +25,4 @@ Alternatively, use -__Next:__ [Clone an Example](clone) +__Next:__ [Clone an Example](clone.md) diff --git a/cmd/kinflate/longerDemo/clone.md b/cmd/kinflate/longerDemo/clone.md index 408e428bc..bf71e7a34 100644 --- a/cmd/kinflate/longerDemo/clone.md +++ b/cmd/kinflate/longerDemo/clone.md @@ -30,4 +30,4 @@ cluster: to instantiate the _hello_ service in off-the-shelf form. -__Next:__ [The Base Manifest](manifest) +__Next:__ [The Base Manifest](manifest.md) diff --git a/cmd/kinflate/longerDemo/manifest.md b/cmd/kinflate/longerDemo/manifest.md index 5e75ef4b3..15a69640f 100644 --- a/cmd/kinflate/longerDemo/manifest.md +++ b/cmd/kinflate/longerDemo/manifest.md @@ -16,4 +16,4 @@ to `stdout`: kinflate inflate -f $BASE ``` -__Next:__ [Customize it](customize) +__Next:__ [Customize it](customize.md) diff --git a/cmd/kinflate/longerDemo/overlays/README.md b/cmd/kinflate/longerDemo/overlays/README.md index 777b1ec3e..4c772b93d 100644 --- a/cmd/kinflate/longerDemo/overlays/README.md +++ b/cmd/kinflate/longerDemo/overlays/README.md @@ -13,4 +13,4 @@ mkdir -p $OVERLAYS/staging mkdir -p $OVERLAYS/production ``` -__Next:__ [Staging](staging) +__Next:__ [Staging](staging/manifest.md) diff --git a/cmd/kinflate/longerDemo/overlays/compare.md b/cmd/kinflate/longerDemo/overlays/compare.md index 1aca4add9..686215f32 100644 --- a/cmd/kinflate/longerDemo/overlays/compare.md +++ b/cmd/kinflate/longerDemo/overlays/compare.md @@ -1,14 +1,16 @@ -# Compare them +# Compare overlays [original]: https://github.com/kinflate/example-hello -`DEMO_HOME` now contains a _base_ directory - your -slightly customized clone of the [original] -configuration, and an _overlays_ directory, that -contains all one needs to create a _staging_ and -_production_ instance in a cluster. +`DEMO_HOME` now contains: -Review the directory structure: + - a _base_ directory - your slightly customized clone of the [original] + configuration, and + + - an _overlays_ directory, containing the manifests and patches required to + create distinct _staging_ and _production_ instance in a cluster. + +Review the directory structure and differences: ``` @@ -23,4 +25,4 @@ diff \ more ``` -__Next:__ [Deploy](deploy) +__Next:__ [Deploy](deploy.md) diff --git a/cmd/kinflate/longerDemo/overlays/deploy.md b/cmd/kinflate/longerDemo/overlays/deploy.md index 71f905567..35a6d40fa 100644 --- a/cmd/kinflate/longerDemo/overlays/deploy.md +++ b/cmd/kinflate/longerDemo/overlays/deploy.md @@ -23,3 +23,5 @@ To deploy, pipe the above commands to kubectl apply: > kinflate inflate -f $OVERLAYS/production |\ > kubectl apply -f - > ``` + +__Next:__ [Editting](../editor.md) diff --git a/cmd/kinflate/longerDemo/overlays/production/manifest.md b/cmd/kinflate/longerDemo/overlays/production/manifest.md index 7c4126fa3..dec532aae 100644 --- a/cmd/kinflate/longerDemo/overlays/production/manifest.md +++ b/cmd/kinflate/longerDemo/overlays/production/manifest.md @@ -24,4 +24,4 @@ patches: EOF ``` -__Next:__ [Production Patch](patch) +__Next:__ [Production Patch](patch.md) diff --git a/cmd/kinflate/longerDemo/overlays/production/patch.md b/cmd/kinflate/longerDemo/overlays/production/patch.md index 548bf1342..b2ab433cb 100644 --- a/cmd/kinflate/longerDemo/overlays/production/patch.md +++ b/cmd/kinflate/longerDemo/overlays/production/patch.md @@ -15,4 +15,4 @@ spec: EOF ``` -__Next:__ [Compare](../compare) +__Next:__ [Compare](../compare.md) diff --git a/cmd/kinflate/longerDemo/overlays/staging/manifest.md b/cmd/kinflate/longerDemo/overlays/staging/manifest.md index d7c3867fc..e8f69c01f 100644 --- a/cmd/kinflate/longerDemo/overlays/staging/manifest.md +++ b/cmd/kinflate/longerDemo/overlays/staging/manifest.md @@ -23,4 +23,4 @@ patches: - map.yaml EOF ``` -__Next:__ [Staging Patch](patch) +__Next:__ [Staging Patch](patch.md) diff --git a/cmd/kinflate/longerDemo/overlays/staging/patch.md b/cmd/kinflate/longerDemo/overlays/staging/patch.md index 872383a90..97209c040 100644 --- a/cmd/kinflate/longerDemo/overlays/staging/patch.md +++ b/cmd/kinflate/longerDemo/overlays/staging/patch.md @@ -18,4 +18,4 @@ data: EOF ``` -__Next:__ [Production Manifest](../production) +__Next:__ [Production Manifest](../production/manifest.md) diff --git a/cmd/kinflate/shortDemo.md b/cmd/kinflate/shortDemo.md index 9a055176c..846a12341 100644 --- a/cmd/kinflate/shortDemo.md +++ b/cmd/kinflate/shortDemo.md @@ -1,4 +1,4 @@ -# Short Demo +# Demo: hello world Prerequisites: [Go](https://golang.org/), [git](https://git-scm.com), a `PATH` containing `$GOPATH/bin`, [kubectl] set up @@ -6,28 +6,31 @@ to talk to a cluster. [kubectl]: https://kubernetes.io/docs/user-guide/kubectl-overview/ -The following clones an app, customizes the resources in -the app with a name prefix, then pipes the resulting -YAML directly to a cluster via [kubectl]. +Steps: - + 1. Clone an off-the-shelf example configuration. + 1. Customizes the resources in it with a name prefix. + 1. Apply the result to a cluster via [kubectl]. + +First make a place to work: + + ``` -TUT_DIR=$HOME/kinflate_demo -/bin/rm -rf $TUT_DIR -mkdir -p $TUT_DIR +DEMO_HOME=$(mktemp -d) ``` -Download the app: +[example-hello]: https://github.com/kinflate/example-hello +Clone an example configuration ([example-hello]): - + ``` -cd $TUT_DIR -git clone https://github.com/kinflate/tuthello -cd tuthello +cd $DEMO_HOME +git clone https://github.com/kinflate/example-hello +cd example-hello ``` -Customize the base application by specifying a prefix that will be applied to -all resource names: +Customize the base application by specifying a prefix +that will be applied to all resource names: ``` @@ -48,16 +51,16 @@ Confirm that the prefix appears in the output: kinflate inflate -f . | grep --context=3 acme- ``` -Optionally apply to a cluster: +Optionally apply the modified configuration to a cluster: ``` kinflate inflate -f . | kubectl apply -f - ``` -This fork of the app repository could be committed to a private repo. Rebase as -desired. +This fork of [example-hello] could be commited to a +private repo, and evolve independently of its upstream. -## Longer demo / tutorial +One could rebase from upstream as desired. -See [longerDemo](longerDemo/README.md). +__Next:__ [hello world (with instances)](longerDemo/README.md).