From bf01897dd3b669bd608d0f8bcca824e80954c062 Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 21 Jan 2022 19:49:17 +0000 Subject: [PATCH 1/9] effective customizations chapter --- site/book/06-deploying-packages/00.md | 2 +- site/book/07-effective-customizations/00.md | 17 ++++++++++++ .../01-single-value-replacement.md | 26 +++++++++++++++++++ .../02-limiting-package-changes.md | 15 +++++++++++ .../03-generation.md | 15 +++++++++++ site/book/README.md | 2 ++ site/sidebar.md | 4 +++ 7 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 site/book/07-effective-customizations/00.md create mode 100644 site/book/07-effective-customizations/01-single-value-replacement.md create mode 100644 site/book/07-effective-customizations/02-limiting-package-changes.md create mode 100644 site/book/07-effective-customizations/03-generation.md diff --git a/site/book/06-deploying-packages/00.md b/site/book/06-deploying-packages/00.md index 81a6ad94f2..2727abf73f 100644 --- a/site/book/06-deploying-packages/00.md +++ b/site/book/06-deploying-packages/00.md @@ -1,4 +1,4 @@ -In the last chapter of this book, we are going to cover how you deploy a kpt +In this chapter of this book, we are going to cover how you deploy a kpt package to a Kubernetes cluster and how the cluster state is managed as the package evolves over time. diff --git a/site/book/07-effective-customizations/00.md b/site/book/07-effective-customizations/00.md new file mode 100644 index 0000000000..420bb53b32 --- /dev/null +++ b/site/book/07-effective-customizations/00.md @@ -0,0 +1,17 @@ +Kubernetes configuration packages and customizations go hand in hand, all the +packaging tools enable package customization. In this chapter we cover effective +customizations techniques the kpt hydration and packaging enables. We show how +providing customization through parameters has some pitfalls and recommend +alternatives where the contents of the package are no hidden behind a facade. +Some of these alternatives are only possible because kpt has made an investment +into bulk editing with KRM functions and upstream merging. + +### Prerequisites + +Before reading this chapter you should familiarize yourself with [chapter 4] +which talks about using functions as well as updating a package page in +[chapter 3]. + +[chapter 4]: /book/04-using-functions/ +[chapter 3]: /book/03-packages/ + diff --git a/site/book/07-effective-customizations/01-single-value-replacement.md b/site/book/07-effective-customizations/01-single-value-replacement.md new file mode 100644 index 0000000000..342d2fd5ce --- /dev/null +++ b/site/book/07-effective-customizations/01-single-value-replacement.md @@ -0,0 +1,26 @@ +## Scenario + +I have a single value replacement in my package, I don’t want package consumers to look through all the yaml files to find the value I want them to set, it seems easier to just create a parameter for this value and have the user look at Kptfile for inputs. + +## Problems + +1. With popularity the single values inevitably expand to provide a facade to a large portion of the data defeating the purpose of minimizing the cognitive load. +1. Some values like resource names are used as references so setting them in one place needs to trigger updates in all the places where they are referenced. +1. If additional resources that have similar values are added to the package new string replacements need to be added. +1. If a package is used as a sub-package the string replacement parameters need to be surfaced to the parent package and if the parent package already expects some values to be set and the parameters do not exist, the sub-package needs to be updated. + +## Suggestions + +1. kpt allows the user to edit a particular value directly in the configuration data and will handle upstream merge. When [editing the yaml] directly the consumers are not confined to the parameters that the package author has +provided. kpt has made an investment into upstream merge that allows +[updating a package] that has been changed with a text editor. ) +1. Attributes like resource names which are often updated by consumers to add prefix or suffix (e.g. *-dev, *-stage, *-prod, na1-*, eu1-*) are best handled by the [ensure-name-substring] function that will handle dependency updates as well as capture all the resources in the package. +1. Instead of setting a particular value on a resource a bulk operation can be applied to all the resources that fit a particular interface. This can be done by a custom function or by [search-and-replace] , [set-labels] and [set-annotations] functions. + + +[editing the yaml]: /book/03-packages/03-editing-a-package +[updating a package]: /book/03-packages/05-updating-a-package +[ensure-name-substring]: https://catalog.kpt.dev/ensure-name-substring/v0.1/ +[search-and-replace]: https://catalog.kpt.dev/search-replace/v0.2/ +[set-labels]: https://catalog.kpt.dev/set-labels/v0.1/ +[set-annotations]: https://catalog.kpt.dev/set-annotations/v0.1/ \ No newline at end of file diff --git a/site/book/07-effective-customizations/02-limiting-package-changes.md b/site/book/07-effective-customizations/02-limiting-package-changes.md new file mode 100644 index 0000000000..9014e06bc1 --- /dev/null +++ b/site/book/07-effective-customizations/02-limiting-package-changes.md @@ -0,0 +1,15 @@ +## Scenario: + +I’d like to limit what my package consumers can do with my package and it feels safer to just provide a string replacement in one place so they know not to alter the configuration outside of the few places that I designated as OK places to change. + +## Problems: + +1. The limitation by parameters does not guarantee that consumers are in fact going to limit their changes to the parameters. A popular pattern is using kustomize to change Helm packages beyond what the package author has allowed by parameters. +1. String replacements rarely describe the intent of the package author. +When additional resources are added I need additional places where parameters need to be applied. + +## Solutions: + +1. General ways to describe policy already exist. kpt has a [gatekeeper] function that allows the author to describe intended limitations for a class of resources or the entire package giving the consumer the freedom to customize and get an error or a warning when the policy is violated. + +[gatekeeper]: https://catalog.kpt.dev/gatekeeper/v0.2/ diff --git a/site/book/07-effective-customizations/03-generation.md b/site/book/07-effective-customizations/03-generation.md new file mode 100644 index 0000000000..a398568b08 --- /dev/null +++ b/site/book/07-effective-customizations/03-generation.md @@ -0,0 +1,15 @@ +## Scenario: + +When using template solutions like Helm I am able to provide conditional statements based on parameter values. This allows me to ask the user for a little bit of information and generate a lot of boilerplate configuration. + +## Problems: + +1. Over time the templating logic becomes its own language that becomes very complex. Debugging the template generation becomes a task of its own. +1. The interplay between different conditionals and loops is interleaved in the template making it hard to understand what exactly is configuration and what is the logic that alters the configuration. +1. Templates are generally monolithic, when a change is introduced the package consumers need to either pay the cost of updating or the new consumers pay the cost of having to decipher more optional parameters. + +## Solutions: + +1. When a complex configuration needs to be generated the package author can create a generator function using turing complete languages and debugging tools. Example of such a function is [folder generation]. The output of the function is plain old KRM. + +[folder generation]: https://catalog.kpt.dev/generate-folders/v0.1/ \ No newline at end of file diff --git a/site/book/README.md b/site/book/README.md index a77e3880d3..6001b70b5e 100644 --- a/site/book/README.md +++ b/site/book/README.md @@ -13,6 +13,7 @@ This book is organized as follows: - [Chapter 4] covers how to use kpt functions to automate configuration changes. - [Chapter 5] guides you through developing custom functions. - [Chapter 6] covers how to deploy a package to a Kubernetes cluster. +- [Chapter 7] covers effective customizations techniques. Let's get started! @@ -22,3 +23,4 @@ Let's get started! [chapter 4]: /book/04-using-functions/ [chapter 5]: /book/05-developing-functions/ [chapter 6]: /book/06-deploying-packages/ +[chapter 7]: /book/06-effective-customizations/ diff --git a/site/sidebar.md b/site/sidebar.md index 6aa992824e..8200754c7a 100644 --- a/site/sidebar.md +++ b/site/sidebar.md @@ -30,6 +30,10 @@ - [6.1 Initializing a Package for Apply](book/06-deploying-packages/01-initializing-a-package-for-apply.md) - [6.2 Applying a Package](book/06-deploying-packages/02-applying-a-package.md) - [6.3 Handling Dependencies](book/06-deploying-packages/03-handling-dependencies.md) + - [7 Effective Customizations](book/07-effective-customizations/) + - [7.1 Single Value Replacement](book/07-effective-customizations/01-single-value-replacement.md) + - [7.2 Limiting Package Changes](book/07-effective-customizations/02-limiting-package-changes.md) + - [7.3 Generation](book/07-effective-customizations/03-generation.md) - [Reference](reference/) - [CLI](reference/cli/) - [pkg](reference/cli/pkg/) From fd96715fba39ad283ee1b30d7c949dbcf38a3679 Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 21 Jan 2022 20:25:03 +0000 Subject: [PATCH 2/9] fixed broken link --- site/book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/book/README.md b/site/book/README.md index 6001b70b5e..005dd90c80 100644 --- a/site/book/README.md +++ b/site/book/README.md @@ -23,4 +23,4 @@ Let's get started! [chapter 4]: /book/04-using-functions/ [chapter 5]: /book/05-developing-functions/ [chapter 6]: /book/06-deploying-packages/ -[chapter 7]: /book/06-effective-customizations/ +[chapter 7]: /book/07-effective-customizations/ From db85266984463943f4401d790818158141b0a4f3 Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 28 Jan 2022 18:32:59 +0000 Subject: [PATCH 3/9] fixed based on Brian's feedback. --- site/book/07-effective-customizations/00.md | 16 +++++++++------- .../01-single-value-replacement.md | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/site/book/07-effective-customizations/00.md b/site/book/07-effective-customizations/00.md index 420bb53b32..8db3768614 100644 --- a/site/book/07-effective-customizations/00.md +++ b/site/book/07-effective-customizations/00.md @@ -1,17 +1,19 @@ Kubernetes configuration packages and customizations go hand in hand, all the -packaging tools enable package customization. In this chapter we cover effective -customizations techniques the kpt hydration and packaging enables. We show how -providing customization through parameters has some pitfalls and recommend -alternatives where the contents of the package are no hidden behind a facade. +packaging tools enable package customization, since every package needs to be adapted to each specific use. In this chapter we cover effective +customizations techniques that kpt hydration and packaging enables. We show how +providing customization through parameters has some [pitfalls] and recommend +alternatives where the contents of the package are not hidden behind a facade. Some of these alternatives are only possible because kpt has made an investment -into bulk editing with KRM functions and upstream merging. +into bulk editing with [KRM functions] and upstream merging. ### Prerequisites Before reading this chapter you should familiarize yourself with [chapter 4] -which talks about using functions as well as updating a package page in +which talks about using functions as well as [updating a package page] in [chapter 3]. [chapter 4]: /book/04-using-functions/ [chapter 3]: /book/03-packages/ - +[pitfalls]: https://github.com/kubernetes/design-proposals-archive/blob/main/architecture/declarative-application-management.md#parameterization-pitfalls +[KRM functions]: https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md +[updating a package page]: /book/03-packages/05-updating-a-package.md \ No newline at end of file diff --git a/site/book/07-effective-customizations/01-single-value-replacement.md b/site/book/07-effective-customizations/01-single-value-replacement.md index 342d2fd5ce..b167131644 100644 --- a/site/book/07-effective-customizations/01-single-value-replacement.md +++ b/site/book/07-effective-customizations/01-single-value-replacement.md @@ -1,6 +1,6 @@ ## Scenario -I have a single value replacement in my package, I don’t want package consumers to look through all the yaml files to find the value I want them to set, it seems easier to just create a parameter for this value and have the user look at Kptfile for inputs. +I have a single value replacement in my package. I don’t want package consumers to look through all the yaml files to find the value I want them to set. It seems easier to just create a parameter for this value and have the user look at Kptfile for inputs. ## Problems From a6c45748081586aed595b885aa895c102967980e Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Tue, 1 Feb 2022 07:11:28 +0000 Subject: [PATCH 4/9] rule 2 described with real code examples. --- .../02-limiting-package-changes.md | 108 +++++++++++++++++- 1 file changed, 103 insertions(+), 5 deletions(-) diff --git a/site/book/07-effective-customizations/02-limiting-package-changes.md b/site/book/07-effective-customizations/02-limiting-package-changes.md index 9014e06bc1..c7aa4bb0e3 100644 --- a/site/book/07-effective-customizations/02-limiting-package-changes.md +++ b/site/book/07-effective-customizations/02-limiting-package-changes.md @@ -1,15 +1,113 @@ ## Scenario: -I’d like to limit what my package consumers can do with my package and it feels safer to just provide a string replacement in one place so they know not to alter the configuration outside of the few places that I designated as OK places to change. +I’d like to limit what my package consumers can do with my package and it feels +safer to just provide a string replacement in one place so they know not to +alter the configuration outside of the few places that I designated as OK +places to change. + +Example deployment: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: # kpt-merge: /nginx-deploy + name: nginx-deploy +spec: + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: backend + image: nginx:1.16.1 # kpt-set: nginx:${tag} +``` + +kpt configuration that uses a setter: +```yaml +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: dont-change-much +pipeline: + mutators: + - image: gcr.io/kpt-fn/apply-setters:v0.2.0 + configMap: + tag: 1.21 +``` ## Problems: -1. The limitation by parameters does not guarantee that consumers are in fact going to limit their changes to the parameters. A popular pattern is using kustomize to change Helm packages beyond what the package author has allowed by parameters. -1. String replacements rarely describe the intent of the package author. -When additional resources are added I need additional places where parameters need to be applied. +1. The limitation by parameters does not guarantee that consumers are in fact +going to limit their changes to the parameters. A popular pattern is using +kustomize to change output of other tools no matter what parameters had. In +this particular case I am able to fork or patch this package and add: + +```yaml +securityContext: + runAsNonRoot: false +``` + +2. String replacements rarely describe the intent of the package author. +When additional resources are added I need additional places where parameters +need to be applied. I can easily add other containers to this deployment and +the package author's rules are not clear and not easily validated. ## Solutions: -1. General ways to describe policy already exist. kpt has a [gatekeeper] function that allows the author to describe intended limitations for a class of resources or the entire package giving the consumer the freedom to customize and get an error or a warning when the policy is violated. +1. General ways to describe policy already exist. kpt has a [gatekeeper] +function that allows the author to describe intended limitations for a class +of resources or the entire package giving the consumer the freedom to customize +and get an error or a warning when the policy is violated. + +In the sample provided by the function we see how to provide a policy that will +clearly describe the intent using rego: + +```yaml +apiVersion: templates.gatekeeper.sh/v1 +kind: ConstraintTemplate +metadata: # kpt-merge: /disallowroot + name: disallowroot +spec: + crd: + spec: + names: + kind: DisallowRoot + targets: + - target: admission.k8s.gatekeeper.sh + rego: |- + package disallowroot + violation[{"msg": msg}] { + not input.review.object.spec.template.spec.securityContext.runAsNonRoot + msg := "Containers must not run as root" + } +--- +apiVersion: constraints.gatekeeper.sh/v1beta1 +kind: DisallowRoot +metadata: # kpt-merge: /disallowroot + name: disallowroot +spec: + match: + kinds: + - apiGroups: + - 'apps' + kinds: + - Deployment +``` + +The Kptfile can enforce that resources comply with this policy every time +`kpt fn render` is used: + +```yaml +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: gatekeeper-disallow-root-user +pipeline: + validators: + - image: gcr.io/kpt-fn/gatekeeper:v0.2 +``` [gatekeeper]: https://catalog.kpt.dev/gatekeeper/v0.2/ From ebf4c6df80520d0a75b415668ffb34a9a772474c Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Tue, 1 Feb 2022 16:29:33 +0000 Subject: [PATCH 5/9] line formatting --- .../01-single-value-replacement.md | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/site/book/07-effective-customizations/01-single-value-replacement.md b/site/book/07-effective-customizations/01-single-value-replacement.md index b167131644..cf7813fa72 100644 --- a/site/book/07-effective-customizations/01-single-value-replacement.md +++ b/site/book/07-effective-customizations/01-single-value-replacement.md @@ -1,21 +1,39 @@ ## Scenario -I have a single value replacement in my package. I don’t want package consumers to look through all the yaml files to find the value I want them to set. It seems easier to just create a parameter for this value and have the user look at Kptfile for inputs. +I have a single value replacement in my package. I don’t want package consumers +to look through all the yaml files to find the value I want them to set. It +seems easier to just create a parameter for this value and have the user look +at Kptfile for inputs. ## Problems -1. With popularity the single values inevitably expand to provide a facade to a large portion of the data defeating the purpose of minimizing the cognitive load. -1. Some values like resource names are used as references so setting them in one place needs to trigger updates in all the places where they are referenced. -1. If additional resources that have similar values are added to the package new string replacements need to be added. -1. If a package is used as a sub-package the string replacement parameters need to be surfaced to the parent package and if the parent package already expects some values to be set and the parameters do not exist, the sub-package needs to be updated. +1. With popularity the single values inevitably expand to provide a facade to +a large portion of the data defeating the purpose of minimizing the cognitive +load. +1. Some values like resource names are used as references so setting them in +one place needs to trigger updates in all the places where they are referenced. +1. If additional resources that have similar values are added to the package +new string replacements need to be added. +1. If a package is used as a sub-package the string replacement parameters need +to be surfaced to the parent package and if the parent package already expects +some values to be set and the parameters do not exist, the sub-package needs to +be updated. ## Suggestions -1. kpt allows the user to edit a particular value directly in the configuration data and will handle upstream merge. When [editing the yaml] directly the consumers are not confined to the parameters that the package author has +1. kpt allows the user to edit a particular value directly in the configuration +data and will handle upstream merge. When [editing the yaml] directly the +consumers are not confined to the parameters that the package author has provided. kpt has made an investment into upstream merge that allows [updating a package] that has been changed with a text editor. ) -1. Attributes like resource names which are often updated by consumers to add prefix or suffix (e.g. *-dev, *-stage, *-prod, na1-*, eu1-*) are best handled by the [ensure-name-substring] function that will handle dependency updates as well as capture all the resources in the package. -1. Instead of setting a particular value on a resource a bulk operation can be applied to all the resources that fit a particular interface. This can be done by a custom function or by [search-and-replace] , [set-labels] and [set-annotations] functions. +1. Attributes like resource names which are often updated by consumers to add +prefix or suffix (e.g. *-dev, *-stage, *-prod, na1-*, eu1-*) are best handled +by the [ensure-name-substring] function that will handle dependency updates as +well as capture all the resources in the package. +1. Instead of setting a particular value on a resource a bulk operation can be +applied to all the resources that fit a particular interface. This can be done +by a custom function or by [search-and-replace] , [set-labels] and +[set-annotations] functions. [editing the yaml]: /book/03-packages/03-editing-a-package From 7f362f8ba8721a78f6a2e2fa2b30f987e0382762 Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 4 Feb 2022 04:55:51 +0000 Subject: [PATCH 6/9] update to the single value replacement --- .../01-single-value-replacement.md | 108 ++++++++++++++++-- 1 file changed, 101 insertions(+), 7 deletions(-) diff --git a/site/book/07-effective-customizations/01-single-value-replacement.md b/site/book/07-effective-customizations/01-single-value-replacement.md index cf7813fa72..9baf2261bd 100644 --- a/site/book/07-effective-customizations/01-single-value-replacement.md +++ b/site/book/07-effective-customizations/01-single-value-replacement.md @@ -5,40 +5,134 @@ to look through all the yaml files to find the value I want them to set. It seems easier to just create a parameter for this value and have the user look at Kptfile for inputs. +Example storage bucket: + +```yaml +apiVersion: storage.cnrm.cloud.google.com/v1beta1 +kind: StorageBucket +metadata: + name: my-bucket # kpt-set: ${project-id}-${name} + namespace: ns-test # kpt-set: ${namespace} + annotations: + cnrm.cloud.google.com/force-destroy: "false" + cnrm.cloud.google.com/project-id: my-project # kpt-set: ${project-id} +spec: + storageClass: standard # kpt-set: ${storage-class} + uniformBucketLevelAccess: true + versioning: + enabled: false +``` + +The corresponding Kptfile: + +```yaml +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: bucket +info: + description: A Google Cloud Storage bucket +pipeline: + mutators: + - image: gcr.io/kpt-fn/apply-setters:v0.2 + configMap: + name: todo-bucket-name + namespace: todo-namespace + project-id: todo-project-id + storage-class: standard +``` + + ## Problems 1. With popularity the single values inevitably expand to provide a facade to a large portion of the data defeating the purpose of minimizing the cognitive -load. +load. With this small example almost half of the StorageBucket configuration +is now covered with parameters. 1. Some values like resource names are used as references so setting them in one place needs to trigger updates in all the places where they are referenced. 1. If additional resources that have similar values are added to the package -new string replacements need to be added. +new string replacements need to be added. In this case everything will need +to also be marked up with project ID and namespace. 1. If a package is used as a sub-package the string replacement parameters need to be surfaced to the parent package and if the parent package already expects some values to be set and the parameters do not exist, the sub-package needs to be updated. -## Suggestions +## Solutions: 1. kpt allows the user to edit a particular value directly in the configuration data and will handle upstream merge. When [editing the yaml] directly the consumers are not confined to the parameters that the package author has provided. kpt has made an investment into upstream merge that allows -[updating a package] that has been changed with a text editor. ) +[updating a package] that has been changed with a text editor. In this case +storageClass can be set directly by the user. 1. Attributes like resource names which are often updated by consumers to add prefix or suffix (e.g. *-dev, *-stage, *-prod, na1-*, eu1-*) are best handled by the [ensure-name-substring] function that will handle dependency updates as well as capture all the resources in the package. 1. Instead of setting a particular value on a resource a bulk operation can be applied to all the resources that fit a particular interface. This can be done -by a custom function or by [search-and-replace] , [set-labels] and -[set-annotations] functions. +by a custom function or by [set-namespace], [search-and-replace] , [set-labels] +and [set-annotations] functions. + +New bucket configuration: + +```yaml +apiVersion: storage.cnrm.cloud.google.com/v1beta1 +kind: StorageBucket +metadata: + name: bucket + annotations: + cnrm.cloud.google.com/force-destroy: "false" +spec: + storageClass: standard + uniformBucketLevelAccess: true + versioning: + enabled: false +``` + +The suggested customizations are now in the Kptfile: + +```yaml +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: bucket +info: + description: A Google Cloud Storage bucket +pipeline: + mutators: + - image: gcr.io/kpt-fn/set-namespace:v0.2.0 + configMap: + namespace: example-ns + - image: gcr.io/kpt-fn/ensure-name-substring:v0.1.1 + configMap: + prepend: project111- + - image: gcr.io/kpt-fn/set-annotations:v0.1.4 + configMap: + cnrm.cloud.google.com/project-id: project111 +``` + +The resource configuration YAML doesn't need to be marked up with where the +namespace value needs to go. The [set-namespace] function is smart enough to +find all the appropriate resources that need the namespace. + +We have put in the starter name `bucket` and have an [ensure-name-substring] +that shows the package consumer that the project ID prefix is what we suggest. +However if they have a different naming convention they can alter the name +prefix or suffix on all the resources in the pacakge. +Since we are trying to set the annotation to the project ID we can use the +[set-annotations] function one time and the annotation are going to be set on +all the resources in the package. If we add additional resources or whole +sub packages we will get the consistent annotations across all resources +without having to find all the places where annotations can go. [editing the yaml]: /book/03-packages/03-editing-a-package [updating a package]: /book/03-packages/05-updating-a-package [ensure-name-substring]: https://catalog.kpt.dev/ensure-name-substring/v0.1/ [search-and-replace]: https://catalog.kpt.dev/search-replace/v0.2/ [set-labels]: https://catalog.kpt.dev/set-labels/v0.1/ -[set-annotations]: https://catalog.kpt.dev/set-annotations/v0.1/ \ No newline at end of file +[set-annotations]: https://catalog.kpt.dev/set-annotations/v0.1/ +[set-namespace]: https://catalog.kpt.dev/set-namespace/v0.2/ \ No newline at end of file From 4f002cbc0663e97fd9aaa2a7ed3edb28631a60bb Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 4 Feb 2022 04:58:10 +0000 Subject: [PATCH 7/9] minor changes --- .../01-single-value-replacement.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/site/book/07-effective-customizations/01-single-value-replacement.md b/site/book/07-effective-customizations/01-single-value-replacement.md index 9baf2261bd..708f5e1db5 100644 --- a/site/book/07-effective-customizations/01-single-value-replacement.md +++ b/site/book/07-effective-customizations/01-single-value-replacement.md @@ -45,10 +45,9 @@ pipeline: ## Problems -1. With popularity the single values inevitably expand to provide a facade to -a large portion of the data defeating the purpose of minimizing the cognitive -load. With this small example almost half of the StorageBucket configuration -is now covered with parameters. +1. With package popularity the single values inevitably expand to provide a +facade to a large portion of the data. That defeats the purpose of minimizing +the cognitive load. With this small example almost half of the StorageBucket configuration is now covered with parameters. 1. Some values like resource names are used as references so setting them in one place needs to trigger updates in all the places where they are referenced. 1. If additional resources that have similar values are added to the package From 124a777e817244a7e01ccf2e85f1cde1ac6c6f2b Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 4 Feb 2022 18:45:38 +0000 Subject: [PATCH 8/9] Sunil's feedback on the language --- site/book/07-effective-customizations/00.md | 2 +- .../01-single-value-replacement.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/book/07-effective-customizations/00.md b/site/book/07-effective-customizations/00.md index 8db3768614..3c699224db 100644 --- a/site/book/07-effective-customizations/00.md +++ b/site/book/07-effective-customizations/00.md @@ -1,6 +1,6 @@ Kubernetes configuration packages and customizations go hand in hand, all the packaging tools enable package customization, since every package needs to be adapted to each specific use. In this chapter we cover effective -customizations techniques that kpt hydration and packaging enables. We show how +customizations techniques that kpt rendering and packaging enables. We show how providing customization through parameters has some [pitfalls] and recommend alternatives where the contents of the package are not hidden behind a facade. Some of these alternatives are only possible because kpt has made an investment diff --git a/site/book/07-effective-customizations/01-single-value-replacement.md b/site/book/07-effective-customizations/01-single-value-replacement.md index 708f5e1db5..1239d5697a 100644 --- a/site/book/07-effective-customizations/01-single-value-replacement.md +++ b/site/book/07-effective-customizations/01-single-value-replacement.md @@ -63,9 +63,9 @@ be updated. 1. kpt allows the user to edit a particular value directly in the configuration data and will handle upstream merge. When [editing the yaml] directly the consumers are not confined to the parameters that the package author has -provided. kpt has made an investment into upstream merge that allows -[updating a package] that has been changed with a text editor. In this case -storageClass can be set directly by the user. +provided. [kpt pkg update] merges the local edits made by consumer with the +changes in the upstream package made by publisher. In this case `storageClass` +can be set directly by the user. 1. Attributes like resource names which are often updated by consumers to add prefix or suffix (e.g. *-dev, *-stage, *-prod, na1-*, eu1-*) are best handled by the [ensure-name-substring] function that will handle dependency updates as @@ -129,7 +129,7 @@ sub packages we will get the consistent annotations across all resources without having to find all the places where annotations can go. [editing the yaml]: /book/03-packages/03-editing-a-package -[updating a package]: /book/03-packages/05-updating-a-package +[kpt pkg update]: /book/03-packages/05-updating-a-package [ensure-name-substring]: https://catalog.kpt.dev/ensure-name-substring/v0.1/ [search-and-replace]: https://catalog.kpt.dev/search-replace/v0.2/ [set-labels]: https://catalog.kpt.dev/set-labels/v0.1/ From a2f9988aca8791e9aa059083075cddda50bb5f3d Mon Sep 17 00:00:00 2001 From: Mike Borozdin Date: Fri, 4 Feb 2022 19:18:30 +0000 Subject: [PATCH 9/9] updated language for the generation recipe --- .../03-generation.md | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/site/book/07-effective-customizations/03-generation.md b/site/book/07-effective-customizations/03-generation.md index a398568b08..2e56329942 100644 --- a/site/book/07-effective-customizations/03-generation.md +++ b/site/book/07-effective-customizations/03-generation.md @@ -1,15 +1,29 @@ ## Scenario: -When using template solutions like Helm I am able to provide conditional statements based on parameter values. This allows me to ask the user for a little bit of information and generate a lot of boilerplate configuration. +When using template languages I am able to provide conditional statements based +on parameter values. This allows me to ask the user for a little bit of +information and generate a lot of boilerplate configuration. Some template +languages like [Jinja] are very robust and feature rich. ## Problems: -1. Over time the templating logic becomes its own language that becomes very complex. Debugging the template generation becomes a task of its own. -1. The interplay between different conditionals and loops is interleaved in the template making it hard to understand what exactly is configuration and what is the logic that alters the configuration. -1. Templates are generally monolithic, when a change is introduced the package consumers need to either pay the cost of updating or the new consumers pay the cost of having to decipher more optional parameters. +1. Increased usage and additional edge cases make a template a piece of code +that required tets and debugging. +1. The interplay between different conditionals and loops is interleaved in the template making it hard to understand what exactly is configuration and what is +the logic that alters the configuration. The consumer is left with one choice +supply different parameter values, execute the template rendering code and see +what happens. +1. Templates are generally monolithic, when a change is introduced the package consumers need to either pay the cost of updating or the new consumers pay the +cost of having to decipher more optional parameters. ## Solutions: -1. When a complex configuration needs to be generated the package author can create a generator function using turing complete languages and debugging tools. Example of such a function is [folder generation]. The output of the function is plain old KRM. +1. When the generated configuration is simple consider just using a sub-package +and running customizations using [single value replacement] techniques. +1. When a complex configuration needs to be generated the package author can +create a generator function using turing complete languages and debugging tools. Example of such a function is [folder generation]. The output of the function +is plain old KRM. -[folder generation]: https://catalog.kpt.dev/generate-folders/v0.1/ \ No newline at end of file +[folder generation]: https://catalog.kpt.dev/generate-folders/v0.1/ +[Jinja]: https://palletsprojects.com/p/jinja/ +[single value replacement]: /book/07-effective-customizations/01-single-value-replacement.md \ No newline at end of file