Package: k8t
k8tPronounced katie [ˈkeɪti]Simple cluster and environment specific aware templating for kubernetes manifests.Table of Contentsgenerated withDocTocInstallationDockerCompletionConceptsClustersandEnvironmentsTemplatingTemplate helper functionsConfiguration inheritanceUsageScaffoldingConfig managementValidate templatesShortcomingsis definedGenerate manifestsOverriding templatesManaging secretsProvidersSSMrole assumptionRandomHashUsing as a pre-commit hookTODOInstallationrun this$pipinstall--user--upgradek8trun the following to installujsonas a dependency$pipinstall--user--upgradek8t[ujson]note: k8t is not Python 2 compatibleDockerYou can also run k8t via docker$dockerrunclarksource/k8t:latesthint: the docker image comes withaws-cli, andkubectl.CompletionRun the following and store the file in your distribution/OS specific spotbash:$_K8T_COMPLETE=sourcek8t>k8t-completion.shzsh:$_K8T_COMPLETE=source_zshk8t>k8t-completion.shConceptsBy combining those concepts you can quickly add completely new environments to your deployment pipeline just by
modifying specializing values and sharing the rest.Check out our exampleshere.ClustersandEnvironmentsk8t comes with a builtin framework forclustersandenvironments(e.g. production, staging). This came from the need to be able to deploy
the same application over multiple clusters and in different environments with completely different setups and values.
This idea is helped by the fact that k8t deep-merges values and configs, allowing easy variation through different
stages of your application deployment.Bothclustersandenvironmentsare intentionally working the same way and can be used to add another degree of freedom when
combined.Environmentshowever are also available globally, meaning clusters can share environment specific
configuration while specifying differences in those environments.TemplatingTemplating is supported viaJinja. k8t also comes with some additionalhelper functionsand avalidation functionwith verbose output to
quickly verify the written templates.Template helper functionsrandom_password(N: int)- generate a random string of length Nenvvar(key: str, [default])- get a value from any environment variable with optional defaultb64encode(value: str)- encodes a value in base64 (usually required for secrets)b64decode(value: str)- decodes a value from base64hash(value: str, [method: str])- hashes a given value (default usingsha256)get_secret(key: str)- provides a secret value from a given provider (seehere)bool(value: Any)- casts value to boolean ("true", "on", "yes", "1", 1 are considered asTrue)sanitize_label(value: str)- sanitizes label values according to kubernetes specsanitize_cpu(value: str | int)- sanitize cpu value to millicoressanitize_memory(value: str | int)- sanitize memory value to megabyte (note: values in scientific notation need to be converted to strings)standardize_cpu(value: str | int)- standardize cpu value to millicores (as int)standardize_memory(value: str | int)- standardize memory value to megabyte (as int; note: values in scientific notation need to be converted to strings)Configuration inheritanceConfiguration, values and templates are used according to the scope they are in. The following snippet shows an example project with low scores (1) and high scores (4) for evaluation order.So variables and templates will be overridden fromproject->environments->clusters->cluster-environmentsresulting in more specific configuration overriding lower values..(1)# k8t new project .├──clusters
│├──foo(3)# k8t new cluster foo││├──config.yaml
││├──values.yaml
││├──environments
│││├──production(4)# k8t new environment production -c foo││││├──config.yaml
││││└──values.yaml
│││└──staging(4)# k8t new environment staging -c foo│││├──config.yaml
│││├──values.yaml
│││└──templates
│││└──deployment.yaml.j2(4)# k8t new template deployment -c foo -e staging││└──templates
││└──deployment.yaml.j2(3)# k8t new template deployment -c foo│└──bar(3)# k8t new cluster bar│├──config.yaml
│└──values.yaml
├──environments
│├──production(2)# k8t new environment production││├──config.yaml
││└──values.yaml
│└──staging(2)# k8t new environment staging│├──config.yaml
│└──values.yaml
├──config.yaml(1)└──values.yaml(1)UsageScaffoldingCreate a new project folder with a cluster directory and an empty defaults file$k8tnewproject.Create a new cluster$k8tnewclusterMyClusterCreate a new global environment$k8tnewenvironmentstagingAnd a new cluster environmentk8tnewenvironmentstaging-cMyClusterGenerate a new deployment template for cluster MyCluster (for a list of available templates see thek8t new template --help)$k8tnewtemplatedeployment-cMyCluster-estagingConfig managementTo ease file access a little bit k8t can open config and value files in your$EDITORor fallback to a sensible
default.$k8teditvalues--environmentstaging$k8teditconfig--clusterMyClusterValidate templatesWhile validation is done before generating, templates can be validated for environment files easily.$k8tvalidateTo validate for clusters/environments the usual options can be used$k8tvalidate-cMyCluster-eproductionShortcomingsThe validation is currently not a 100% correct and can miss certain edge cases.  If you notice any other issues please let us know.is definedThe following will result in a false negative forfoobarbeing defined{{ foobar }}

{% if foobar is defined %}
{{ foobar }}
{% endif %}To avoid this make sure that theis definedtest is applied to all instances of the variable.The following may result in a false positive forbarbeing undefined{% if foobar is defined %}
{{ bar }}
{% endif %}Generate manifestsThe--clusterflag will load variables from a directory. By default the filedefault.yamlin that directory will be
loaded, however an environment can be specified with--environment.$k8tgen-cMyCluster-estagingAdditionally k8t will attempt to load a filedefaults.yamlin the root directory. This way a set of default
variables can be specified and selectively overriden via cluster and environment.Additional values can be given via flag--value-filein the form of a file or--value KEY VALUE, both can be
supplied multiple times.Variables will be merged via deep merging. Default merge strategy is left-to-right.Overriding templatesTemplates can be overriden on a cluster/environment level.If a fileapplication.yamlexists in the root templates folder, simply add a file with the same name to the
cluster/environment template folder.Managing secretsSecrets can be interpolated with the helper functionget_secret. It requires a key as first argument and providers
are configurable by environment/cluster.foobar:"{{get_secret('/my-key')}}"ProvidersSSMSetup secrets on SSMsecrets:provider:ssmregion:"eu-central-1"prefix:"/foobar"Keep in mind that SSM parameter names can be formed as a path and  they can only consist of sub-paths divided by slash symbol; each sub-path can be formed as a mix of letters, numbers and the following 3 symbols:.-_Be careful to follow this format when setting up the providerprefixandget_secret(key).Global secrets config can be overridden inget_secrethelper function call by specifyingconfig_overrideargument.foobar:"{{get_secret('/my-key',config_override={'prefix':'/dev'})}}"role assumptionYou can optionally assume an IAM role to retrieve secrets by specyfingrole_arnin the config:secrets:
  provider: ssm
  region: "eu-central-1"
  role_arn: "arn:aws:iam::account:role/role-name-with-path"RandomRandom secrets can be generated easily by using the random provider. This provider uses a global dictionary to store
results for the time of the run in python so keys should always produce the same result.secrets:provider:randomHashIn case consistent (fake) secrets are needed, thehashprovider can be used that hashes the secret key for the value.secrets:provider:hashUsing as a pre-commit hookYou can also use this repo as ahttps://github.com/pre-commit/pre-commithookAdd this to your.pre-commit-config.yaml:-repo:https://github.com/ClarkSource/k8trev:''# Use the sha / tag you want to point athooks:-id:k8t-validate# args: [ -e dev -c us-west-2 ]-id:k8t-generatename:k8t(dev)args:[-o dev.yaml -e dev]TODOtesting needs to be expandedthe ability to add additional template directories via the CLIvalidation functions for template values (e.g. memory/cpu values)