{"id":23902665,"url":"https://github.com/mtumilowicz/helm-workshop","last_synced_at":"2025-06-30T03:06:52.363Z","repository":{"id":110876323,"uuid":"411438213","full_name":"mtumilowicz/helm-workshop","owner":"mtumilowicz","description":"Simple introduction to Helm basics.","archived":false,"fork":false,"pushed_at":"2024-08-01T22:35:55.000Z","size":217,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-11T00:13:20.335Z","etag":null,"topics":["helm","helm-chart","helm-charts","kubernetes-helm","kubernetes-helm-chart","kubernetes-helm-charts","workshop","workshop-materials","workshops"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtumilowicz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-09-28T21:05:14.000Z","updated_at":"2024-08-01T22:35:57.000Z","dependencies_parsed_at":"2024-08-01T23:35:02.387Z","dependency_job_id":null,"html_url":"https://github.com/mtumilowicz/helm-workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mtumilowicz/helm-workshop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fhelm-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fhelm-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fhelm-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fhelm-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtumilowicz","download_url":"https://codeload.github.com/mtumilowicz/helm-workshop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtumilowicz%2Fhelm-workshop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262702324,"owners_count":23350641,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["helm","helm-chart","helm-charts","kubernetes-helm","kubernetes-helm-chart","kubernetes-helm-charts","workshop","workshop-materials","workshops"],"created_at":"2025-01-04T22:49:42.576Z","updated_at":"2025-06-30T03:06:52.317Z","avatar_url":"https://github.com/mtumilowicz.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)\n# helm-workshop\n\n* references\n    * [Helm Masterclass](https://www.udemy.com/course/helm-masterclass)\n    * https://jfrog.com/blog/is-your-helm-2-secure-and-scalable/\n    * https://helm.sh/docs/\n    * https://insights.project-a.com/whats-the-best-way-to-manage-helm-charts-1cbf2614ec40\n    * https://blog.risingstack.com/packing-a-kubernetes-microservices-with-helm/\n    * https://github.com/addamstj/helm-course\n    * [What is Helm in Kubernetes? Helm and Helm Charts explained | Kubernetes Tutorial 23](https://www.youtube.com/watch?v=-ykwb1d0DXU)\n    * [Introduction to Helm | Kubernetes Tutorial | Beginners Guide](https://www.youtube.com/watch?v=5_J7RWLLVeQ)\n    * https://helm.sh/docs/howto/charts_tips_and_tricks/\n    * [An Introduction to Helm - Matt Farina, Samsung SDS \u0026 Josh Dolitsky, Blood Orange](https://www.youtube.com/watch?v=Zzwq9FmZdsU)\n    * [Delve into Helm: Advanced DevOps [I] - Lachlan Evenson \u0026 Adam Reese, Deis](https://www.youtube.com/watch?v=cZ1S2Gp47ng)\n    * https://helm.sh/docs/\n    * https://jacky-jiang.medium.com/use-named-templates-like-functions-in-helm-charts-641fbcec38da\n    * https://stackoverflow.com/questions/62472224/what-is-and-what-use-cases-have-the-dot-in-helm-charts\n\n## preface\n* goals of this workshop\n    * understanding the purpose of helm\n    * understanding how it facilitates k8s deployments\n    * introducing structure of helm\n        * charts\n        * templates\n        * values\n    * familiarize with basic commands for releasing app\n\n## introduction\n* suppose we are deploying elastic stack for logging\n    * needs: stateful set, config map, k8s user with permissions, secret, services\n        * and you want to rollback them as a whole\n    * maybe someone could create the yaml files once, package them and make available somewhere\n        * that package is known as helm charts\n    * public repositories: https://artifacthub.io/\n    * private repositories: share in organisation\n* suppose we have many microservices in the cluster and across different environments (dev, stage, prod)\n    * with very similar deployments (ex. apart from name and image)\n    * a lot of copy-paste and duplication\n    * maybe someone could create a template and make available somewhere\n        * then we fill that template with values\n        * that template engine is know as helm\n\n## helm\n* package manager - software tool that automates the process of installing, upgrading, configuring, and removing\nsoftware in a consistent manner\n* is a package manager for k8s\n    * package yaml files and distribute them in public / private repositories\n    * manage your k8s deployments\n    * teardown and create deployments with one command\n* is a templating engine\n* tasks\n    * create new charts from scratch\n    * package charts into chart archive (tgz) files\n    * interact with chart repositories where charts are stored\n    * install and uninstall charts into an existing Kubernetes cluster\n    * manage the release cycle of charts that have been installed with Helm\n* components\n    * Helm Client\n        * a command-line client for end user\n        * responsible for:\n            * local chart development\n            * managing repositories\n            * managing releases\n            * interfacing with the Helm library\n            * sending charts to be installed\n            * requesting upgrading or uninstalling of existing releases\n    * Helm Library\n        * provides the logic for executing all Helm operations\n        * interfaces with the Kubernetes API server\n        * provides the following capability:\n            * combining a chart and configuration to build a release\n            * installing charts into Kubernetes, and providing the subsequent release object\n            * upgrading and uninstalling charts by interacting with Kubernetes\n* helm2 vs helm3\n    * most apparent change is the removal of Tiller\n        * Tiller was the server-side component which is used to maintain the state of helm release\n        * Tiller = in-cluster server that interacts with the Helm client, and interfaces with the Kubernetes API server\n\n## project structure\n* `Chart.yaml`\n    * meta info about chart\n    * description of the package (most important fields below)\n        * apiVersion: chart API version (required)\n            * should be v2 for Helm charts that require at least Helm 3\n        * appVersion: version of the app that this chart contains (optional)\n            * informational, has no impact on chart version calculations\n        * version: A SemVer 2 version (required)\n        * kubeVersion: range of compatible Kubernetes versions (optional)\n        * name: The name of the chart (required)\n        * description: A single-sentence description of this project (optional)\n        * type: type of the chart (optional)\n            * application (default) and library\n            * library chart defines chart primitives or definitions which can be shared in other charts\n        * dependencies: list of the chart requirements (optional)\n            * one chart may depend on any number of other charts\n            * will download all the specified charts into your `charts/` directory for you\n                * example\n                    ```\n                    dependencies:\n                      - name: apache\n                        version: 1.2.3\n                        repository: https://example.com/charts\n                      - name: mysql\n                        version: 3.2.1\n                        repository: https://another.example.com/charts\n                    ```\n                    will be downloaded into `charts`\n                    ```\n                    charts/\n                      apache-1.2.3.tgz\n                      mysql-3.2.1.tgz\n                    ```\n            * if more control required: dependencies can be explicitly copied into the `charts/` directory\n* `values.yaml`\n    * contains default values for the template files\n    * could be overridden\n        * `helm install --values=my-values.yaml \u003cchartname\u003e`\n        * example: `dev.yaml`, `prod.yaml`, `stage.yaml`\n* `charts` -\u003e chart dependencies\n* `templates`\n    * templates that, when combined with values, will generate valid Kubernetes manifest files\n    * most files are treated as if they contain Kubernetes manifests\n    * files whose name begins with an underscore `_` are assumed to not have a manifest inside\n        * used to store partials and helpers\n        * example: `_helpers.tpl`\n\n## helm charts\n* is\n    * unit of deployment\n    * set of yaml files\n    * a collection of files that describe a related set of Kubernetes resources\n* hooks\n    * to intervene at certain points in a release's life cycle\n    * purpose\n        * load a ConfigMap or Secret during install before any other charts are loaded\n        * run a Job before deleting a release to gracefully take a service out of rotation before removing it\n    * example\n        * pre-install: executes after templates are rendered, but before any resources are created in Kubernetes\n        * post-install: executes after all resources are loaded into Kubernetes\n    * remark: if you create resources in a hook, you cannot rely upon `helm uninstall` to remove it\n        * either add a `custom helm.sh/hook-delete-policy` annotation to the hook template file\n        * or set the time to live (TTL) field of a Job resource\n* tests\n    * lives under the `templates/`\n    * specifies a container with a given command to run\n        * container should exit successfully (exit 0) for a test to be considered a success\n    * purpose\n        * validate that `values.yaml` was properly injected\n        * username and password work correctly\n        * incorrect username and password does not work\n    * example\n        ```\n        kind: Pod\n        metadata:\n          annotations:\n            \"helm.sh/hook\": test\n        ...\n        ```\n* where do you put your Helm charts?\n    1. chart repository to store one big shared chart\n        * one big shared chart\n            * can save a lot of hassle if services are similar\n            * example: maintaining charts for 15 different microservices in a central chart repository\n                * it is easier update them all in one place rather than submitting pull requests to 15\n                different repositories\n        * many service-specific charts\n            * you can make a change to one service without worrying about breaking something for another service\n            * if the charts are service-specific - no argument for storing them together\n    1. same repository as the service itself\n       * good choice for microservice-based applications where the services have significant differences\n       * it’s easier to continuously deploy the service independently from other projects\n       * it’s much easier to test if the chart and the code are in the same repo and can be tested in the same branch\n* when Helm installs/upgrades charts\n    1. Kubernetes objects from the charts and all its dependencies are aggregated into a single set\n    1. then sorted by type followed by name\n    1. then created/updated in that order\n* when it comes to sharing charts, the preferred mechanism is a chart repository\n    * chart museum ~ docker repository for charts\n\n## template\n* resides in `template/`\n* k8s manifest = template + values\n* recommended labels\n    * app.kubernetes.io/name\n        * app name\n        * `{{ template \"name\" . }}`\n    * helm.sh/chart\n    \t* chart name and version\n    \t* `{{ .Chart.Name }}-{{ .Chart.Version | replace \"+\" \"_\" }}`\n    * app.kubernetes.io/managed-by\n        * for finding all things managed by Helm\n        * `{{ .Release.Service }}`\n    * app.kubernetes.io/instance\n        * aids in differentiating between different instances of the same application\n        * `{{ .Release.Name }}`\n    * app.kubernetes.io/version\n    \t* version of the app\n    \t* `{{ .Chart.AppVersion }}`\n    * app.kubernetes.io/component\n        * role of the pieces in an application\n        * example: frontend, backed\n* named template\n    * used to share and reuse template snippets and deployment logic\n    * example\n        ```\n        {{- define \"mychart.labels\" -}}\n          labels:\n            myLabel: {{ .Values.myLabel }}\n        {{- end -}}\n        ```\n        then in template\n        {{- include \"mychart.labels\" . }}\n    * two templates with the same name - whichever one is loaded last will be the one used\n        * naming convention: prefix each template with the name of the chart\n    * passing scope\n        * when a named template (created with define) is rendered, it will receive the scope passed in by the\n        template call\n        * example\n            * `{{- template \"mychart.labels\" }}`\n                * no scope was passed in, so within the template we cannot access anything in `.`\n            * `{{- template \"mychart.labels\" . }}`\n                * note that we pass `.` at the end of the template call\n                * we could just as easily pass `.Values`, but we want a top-level scope\n    * `include` vs `template`\n        * `include` (preferable)\n            * bring the template, and then pass the results to other template functions\n            * example\n                * `{{ include \"mytpl\" . | lower | quote }}`\n                * includes a template called mytpl, then lowercases the result, then wraps that in double quotes\n        * `template`\n            * no option to pipe the results\n\n## commands\n* `helm create helm-chart-name`\n    * create a new chart with the given name\n* `helm install helm-chart-name .`\n    * performs a release\n        * a Release is an instance of a chart running in a Kubernetes cluster\n    * deploy an app on your Kubernetes cluster\n    * `helm install prodmyfirstchart . -f production.yaml`\n* `helm template .`\n    * render chart templates locally and display the output\n    * any values that would normally be looked up or retrieved in-cluster will be faked locally\n* `helm uninstall helm-chart-name`\n    * removes all of the resources associated with the last release of the chart as well as the release history,\n    freeing it up for future use\n* `helm upgrade helm-chart-name`\n    * upgrades a release to a new version of a chart\n* `helm upgrade --install \u003crelease name\u003e --values \u003cvalues file\u003e \u003cchart directory\u003e`\n    * install or upgrade a release with one command\n* `helm get manifest helm-chart-name`\n    * fetches the generated manifest for a given release\n* `helm list`\n    * list releases\n* `helm lint`\n    * runs a series of tests to verify that the chart is well-formed\n* `helm template .`\n    * locally render templates\n    * `helm template . \u003e templated.yaml`\n\n## functions\n* required\n    * declare a particular values entry as required for template rendering\n    * example: `{{ required \"A valid .Values.who entry required!\" .Values.who }}`\n* if statement\n    ```\n    {{- if eq .Values.proxy.enabled true -}}\n    {{- include \"proxy\" . | nindent 8 -}}\n    {{- end -}}\n    ```\n* set scope\n    ```\n    {{- with .Values.favorite }} // with statement sets . to point to .Values.favorite\n    drink: {{ .drink | default \"tea\" | quote }}\n    food: {{ .food | upper | quote }}\n    {{- end }} // . is reset to its previous scope after {{ end }}\n    ```\n    vs\n    ```\n    drink: {{ .Values.favorite.drink | default \"tea\" | quote }}\n    food: {{ .Values.favorite.food | upper | quote }}\n    ```\n* from UNIX: pipelines are a tool for chaining together a series of template commands\n    * `{{ .Values.favorite.food | upper | quote }}`\n    * pizza -\u003e PIZZA -\u003e \"PIZZA\"\n* default\n    * specify a default value inside of the template, in case the value is omitted\n    * `{{ .Values.favorite.drink | default \"tea\" | quote }}`\n    * remark: all static default values should live in the `values.yaml`\n        * perfect for computed values, which can not be declared inside `values.yaml`\n\n## best practices\n* chart names: lower case, numbers, words may be separated with dashes (-)\n* template file names: dashed notation (my-example-configmap.yaml)\n* template file names: reflect the resource kind (foo-pod.yaml, bar-svc.yaml)\n* templates should be indented using two spaces (never tabs)\n* all named template names should be namespaced (they are globally accessible)\n* variable names: camelcase\n* type conversion errors\n    * `foo: false` is not the same as `foo: \"false\"`\n    * rule: quote all strings\n* each resource definition should be in its own template file\n* item of metadata: `label` or `annotation`\n    * label if\n        * is used by Kubernetes to identify this resource\n        * is useful to expose to operators for the purpose of querying the system\n    * annotation\n        * item not used for querying\n        * example\n            * Automatically Roll Deployments\n                ```\n                spec:\n                  template:\n                    metadata:\n                      annotations:\n                        checksum/config: {{ include (print $.Template.BasePath \"/configmap.yaml\") . | sha256sum }}\n                ```\n\n## workshops\n1. inspect `helm/` directory\n1. create image: `gradle bootBuildImage`\n1. run image: `docker run -p 8000:8080 -d helm-workshop:1.0-SNAPSHOT`\n1. verify that is working: `http://localhost:8000/app/greeting`\n1. remove container\n    * `docker ps` - list all containers\n    * `docker stop containerId`\n    * `docker rm containerId`\n1. go to helm chart directory: `cd helm`\n1. release app: `helm install greeting-app .`\n    * to uninstall: `helm uninstall greeting-app-chart`\n1. verify release: `helm list`\n1. verify service: `kubectl get services`\n1. verify pods: `kubectl get pods`\n1. verify app is working: `http://localhost:31234/app/greeting`\n1. verify labels: `kubectl get pods --show-labels`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtumilowicz%2Fhelm-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtumilowicz%2Fhelm-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtumilowicz%2Fhelm-workshop/lists"}