{"id":571,"date":"2018-10-17T15:07:49","date_gmt":"2018-10-17T15:07:49","guid":{"rendered":"https:\/\/www.appservgrid.com\/paw93\/?p=571"},"modified":"2018-10-17T15:35:42","modified_gmt":"2018-10-17T15:35:42","slug":"introducing-kustomize-template-free-configuration-customization-for-kubernetes","status":"publish","type":"post","link":"https:\/\/www.appservgrid.com\/paw93\/index.php\/2018\/10\/17\/introducing-kustomize-template-free-configuration-customization-for-kubernetes\/","title":{"rendered":"Introducing kustomize; Template-free Configuration Customization for Kubernetes"},"content":{"rendered":"<h3><a href=\"https:\/\/kubernetes.io\/blog\/2018\/05\/29\/introducing-kustomize-template-free-configuration-customization-for-kubernetes\/\">Introducing kustomize; Template-free Configuration Customization for Kubernetes<\/a><\/h3>\n<p>Authors: Jeff Regan (Google), Phil Wittrock (Google)<\/p>\n<p>If you run a Kubernetes environment, chances are you\u2019ve<br \/>\ncustomized a Kubernetes configuration \u2014 you\u2019ve copied<br \/>\nsome API object YAML files and editted them to suit<br \/>\nyour needs.<\/p>\n<p>But there are drawbacks to this approach \u2014 it can be<br \/>\nhard to go back to the source material and incorporate<br \/>\nany improvements that were made to it. Today Google is<br \/>\nannouncing <a href=\"https:\/\/github.com\/kubernetes-sigs\/kustomize\" target=\"_blank\" rel=\"noopener\">kustomize<\/a>, a command-line tool<br \/>\ncontributed as a <a href=\"https:\/\/github.com\/kubernetes\/community\/blob\/master\/keps\/sig-cli\/0008-kustomize.md\" target=\"_blank\" rel=\"noopener\">subproject<\/a> of <a href=\"https:\/\/github.com\/kubernetes\/community\/tree\/master\/sig-cli\" target=\"_blank\" rel=\"noopener\">SIG-CLI<\/a>. The tool<br \/>\nprovides a new, purely <em>declarative<\/em> approach to<br \/>\nconfiguration customization that adheres to and<br \/>\nleverages the familiar and carefully designed<br \/>\nKubernetes API.<\/p>\n<p>Here\u2019s a common scenario. Somewhere on the internet you<br \/>\nfind someone\u2019s Kubernetes configuration for a content<br \/>\nmanagement system. It\u2019s a set of files containing YAML<br \/>\nspecifications of Kubernetes API objects. Then, in some<br \/>\ncorner of your own company you find a configuration for<br \/>\na database to back that CMS \u2014 a database you prefer<br \/>\nbecause you know it well.<\/p>\n<p>You want to use these together, somehow. Further, you<br \/>\nwant to customize the files so that your resource<br \/>\ninstances appear in the cluster with a label that<br \/>\ndistinguishes them from a colleague\u2019s resources who\u2019s<br \/>\ndoing the same thing in the same cluster.<br \/>\nYou also want to set appropriate values for CPU, memory<br \/>\nand replica count.<\/p>\n<p>Additionally, you\u2019ll want <em>multiple variants<\/em> of the<br \/>\nentire configuration: a small variant (in terms of<br \/>\ncomputing resources used) devoted to testing and<br \/>\nexperimentation, and a much larger variant devoted to<br \/>\nserving outside users in production. Likewise, other<br \/>\nteams will want their own variants.<\/p>\n<p>This raises all sorts of questions. Do you copy your<br \/>\nconfiguration to multiple locations and edit them<br \/>\nindependently? What if you have dozens of development<br \/>\nteams who need slightly different variations of the<br \/>\nstack? How do you maintain and upgrade the aspects of<br \/>\nconfiguration that they share in common? Workflows<br \/>\nusing kustomize provide answers to these questions.<\/p>\n<h2>Customization is reuse<\/h2>\n<p>Kubernetes configurations aren\u2019t code (being YAML<br \/>\nspecifications of API objects, they are more strictly<br \/>\nviewed as data), but configuration lifecycle has many<br \/>\nsimilarities to code lifecycle.<\/p>\n<p>You should keep configurations in version<br \/>\ncontrol. Configuration owners aren\u2019t necessarily the<br \/>\nsame set of people as configuration<br \/>\nusers. Configurations may be used as parts of a larger<br \/>\nwhole. Users will want to <em>reuse<\/em> configurations for<br \/>\ndifferent purposes.<\/p>\n<p>One approach to configuration reuse, as with code<br \/>\nreuse, is to simply copy it all and customize the<br \/>\ncopy. As with code, severing the connection to the<br \/>\nsource material makes it difficult to benefit from<br \/>\nongoing improvements to the source material. Taking<br \/>\nthis approach with many teams or environments, each<br \/>\nwith their own variants of a configuration, makes a<br \/>\nsimple upgrade intractable.<\/p>\n<p>Another approach to reuse is to express the source<br \/>\nmaterial as a parameterized template. A tool processes<br \/>\nthe template\u2014executing any embedded scripting and<br \/>\nreplacing parameters with desired values\u2014to generate<br \/>\nthe configuration. Reuse comes from using different<br \/>\nsets of values with the same template. The challenge<br \/>\nhere is that the templates and value files are not<br \/>\nspecifications of Kubernetes API resources. They are,<br \/>\nnecessarily, a new thing, a new language, that wraps<br \/>\nthe Kubernetes API. And yes, they can be powerful, but<br \/>\nbring with them learning and tooling costs. Different<br \/>\nteams want different changes\u2014so almost every<br \/>\nspecification that you can include in a YAML file<br \/>\nbecomes a parameter that needs a value. As a result,<br \/>\nthe value sets get large, since all parameters (that<br \/>\ndon\u2019t have trusted defaults) must be specified for<br \/>\nreplacement. This defeats one of the goals of<br \/>\nreuse\u2014keeping the differences between the variants<br \/>\nsmall in size and easy to understand in the absence of<br \/>\na full resource declaration.<\/p>\n<h2>A new option for configuration customization<\/h2>\n<p>Compare that to kustomize, where the tool\u2019s<br \/>\nbehavior is determined by declarative specifications<br \/>\nexpressed in a file called kustomization.yaml.<\/p>\n<p>The kustomize program reads the file and the<br \/>\nKubernetes API resource files it references, then emits<br \/>\ncomplete resources to standard output. This text output<br \/>\ncan be further processed by other tools, or streamed<br \/>\ndirectly to kubectl for application to a cluster.<\/p>\n<p>For example, if a file called kustomization.yaml<br \/>\ncontaining<\/p>\n<p>commonLabels:<br \/>\napp: hello<br \/>\nresources:<br \/>\n&#8211; deployment.yaml<br \/>\n&#8211; configMap.yaml<br \/>\n&#8211; service.yaml<\/p>\n<p>is in the current working directory, along with<br \/>\nthe three resource files it mentions, then running<\/p>\n<p>kustomize build<\/p>\n<p>emits a YAML stream that includes the three given<br \/>\nresources, and adds a common label app: hello to<br \/>\neach resource.<\/p>\n<p>Similarly, you can use a <em>commonAnnotations<\/em> field to<br \/>\nadd an annotation to all resources, and a <em>namePrefix<\/em><br \/>\nfield to add a common prefix to all resource<br \/>\nnames. This trivial yet common customization is just<br \/>\nthe beginning.<\/p>\n<p>A more common use case is that you\u2019ll need multiple<br \/>\nvariants of a common set of resources, e.g., a<br \/>\n<em>development<\/em>, <em>staging<\/em> and <em>production<\/em> variant.<\/p>\n<p>For this purpose, kustomize supports the idea of an<br \/>\n<em>overlay<\/em> and a <em>base<\/em>. Both are represented by a<br \/>\nkustomization file. The base declares things that the<br \/>\nvariants share in common (both resources and a common<br \/>\ncustomization of those resources), and the overlays<br \/>\ndeclare the differences.<\/p>\n<p>Here\u2019s a file system layout to manage a <em>staging<\/em> and<br \/>\n<em>production<\/em> variant of a given cluster app:<\/p>\n<p>someapp\/<br \/>\n\u251c\u2500\u2500 base\/<br \/>\n\u2502 \u251c\u2500\u2500 kustomization.yaml<br \/>\n\u2502 \u251c\u2500\u2500 deployment.yaml<br \/>\n\u2502 \u251c\u2500\u2500 configMap.yaml<br \/>\n\u2502 \u2514\u2500\u2500 service.yaml<br \/>\n\u2514\u2500\u2500 overlays\/<br \/>\n\u251c\u2500\u2500 production\/<br \/>\n\u2502 \u2514\u2500\u2500 kustomization.yaml<br \/>\n\u2502 \u251c\u2500\u2500 replica_count.yaml<br \/>\n\u2514\u2500\u2500 staging\/<br \/>\n\u251c\u2500\u2500 kustomization.yaml<br \/>\n\u2514\u2500\u2500 cpu_count.yaml<\/p>\n<p>The file someapp\/base\/kustomization.yaml specifies the<br \/>\ncommon resources and common customizations to those<br \/>\nresources (e.g., they all get some label, name prefix<br \/>\nand annotation).<\/p>\n<p>The contents of<br \/>\nsomeapp\/overlays\/production\/kustomization.yaml could<br \/>\nbe<\/p>\n<p>commonLabels:<br \/>\nenv: production<br \/>\nbases:<br \/>\n&#8211; ..\/..\/base<br \/>\npatches:<br \/>\n&#8211; replica_count.yaml<\/p>\n<p>This kustomization specifies a <em>patch<\/em> file<br \/>\nreplica_count.yaml, which could be:<\/p>\n<p>apiVersion: apps\/v1<br \/>\nkind: Deployment<br \/>\nmetadata:<br \/>\nname: the-deployment<br \/>\nspec:<br \/>\nreplicas: 100<\/p>\n<p>A patch is a partial resource declaration, in this case<br \/>\na patch of the deployment in<br \/>\nsomeapp\/base\/deployment.yaml, modifying only the<br \/>\n<em>replicas<\/em> count to handle production traffic.<\/p>\n<p>The patch, being a partial deployment spec, has a clear<br \/>\ncontext and purpose and can be validated even if it\u2019s<br \/>\nread in isolation from the remaining<br \/>\nconfiguration. It\u2019s not just a context free tuple.<\/p>\n<p>To create the resources for the production variant, run<\/p>\n<p>kustomize build someapp\/overlays\/production<\/p>\n<p>The result is printed to stdout as a set of complete<br \/>\nresources, ready to be applied to a cluster. A<br \/>\nsimilar command defines the staging environment.<\/p>\n<h2>In summary<\/h2>\n<p>With kustomize, you can manage an arbitrary number<br \/>\nof distinctly customized Kubernetes configurations<br \/>\nusing only Kubernetes API resource files. Every<br \/>\nartifact that kustomize uses is plain YAML and can<br \/>\nbe validated and processed as such. kustomize encourages<br \/>\na fork\/modify\/rebase <a href=\"https:\/\/github.com\/kubernetes-sigs\/kustomize\/blob\/master\/docs\/workflows.md\" target=\"_blank\" rel=\"noopener\">workflow<\/a>.<\/p>\n<p>To get started, try the <a href=\"https:\/\/github.com\/kubernetes-sigs\/kustomize\/blob\/master\/examples\/helloWorld\" target=\"_blank\" rel=\"noopener\">hello world<\/a> example.<br \/>\nFor discussion and feedback, join the <a href=\"https:\/\/groups.google.com\/forum\/#!forum\/kustomize\" target=\"_blank\" rel=\"noopener\">mailing list<\/a> or<br \/>\n<a href=\"https:\/\/github.com\/kubernetes-sigs\/kustomize\/issues\/new\" target=\"_blank\" rel=\"noopener\">open an issue<\/a>. Pull requests are welcome.<\/p>\n<p><a href=\"https:\/\/kubernetes.io\/blog\/2018\/05\/29\/introducing-kustomize-template-free-configuration-customization-for-kubernetes\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introducing kustomize; Template-free Configuration Customization for Kubernetes Authors: Jeff Regan (Google), Phil Wittrock (Google) If you run a Kubernetes environment, chances are you\u2019ve customized a Kubernetes configuration \u2014 you\u2019ve copied some API object YAML files and editted them to suit your needs. But there are drawbacks to this approach \u2014 it can be hard to &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.appservgrid.com\/paw93\/index.php\/2018\/10\/17\/introducing-kustomize-template-free-configuration-customization-for-kubernetes\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Introducing kustomize; Template-free Configuration Customization for Kubernetes&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-571","post","type-post","status-publish","format-standard","hentry","category-kubernetes"],"_links":{"self":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/571","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/comments?post=571"}],"version-history":[{"count":1,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/571\/revisions"}],"predecessor-version":[{"id":573,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/posts\/571\/revisions\/573"}],"wp:attachment":[{"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/media?parent=571"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/categories?post=571"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw93\/index.php\/wp-json\/wp\/v2\/tags?post=571"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}