helm-guide

An opinionated guide for the Helm system
git clone git://archive.git.mtrnord.blog/MTRNord/helm-guide.git
Log | Files | Refs | LICENSE

commit 93ccef6ef4584d9c79b82bfd786a3b59ce613574
parent e921bdc1bc83e65e67af0f35e0fab9791af11814
Author: MTRNord <mtrnord1@gmail.com>
Date:   Mon,  9 Dec 2024 19:05:56 +0100

Apply various wording improvements to the document

Diffstat:
Mbibliography.bib | 18++++++++++++++++++
Mpages/chapter1.tex | 28++++++++++++++--------------
Mpages/chapter2.tex | 43++++++++++++++++++++++---------------------
Mroot.tex | 30+++++++++++++++++-------------
Mstyle.sty | 2+-
5 files changed, 72 insertions(+), 49 deletions(-)

diff --git a/bibliography.bib b/bibliography.bib @@ -38,3 +38,21 @@ language = {en}, organization = {Kubernetes}, } + +@online{helmauthorsAppVersionsField, + title = {The "{{appVersions}}" Field}, + author = {{Helm Authors} and {The Linux Foundation}}, + url = {https://helm.sh/docs/topics/charts/#the-appversion-field}, + urldate = {2024-12-09}, + abstract = {Explains the chart format, and provides basic guidance for building charts with Helm.}, + language = {en}, +} + +@online{Pods, + title = {Pods}, + url = {https://kubernetes.io/docs/concepts/workloads/pods/}, + urldate = {2024-12-09}, + abstract = {Pods are the smallest deployable units of computing that you can create and manage in Kubernetes. A Pod (as in a pod of whales or pea pod) is a group of one or more containers, with shared storage and network resources, and a specification for how to run the containers. A Pod's contents are always co-located and co-scheduled, and run in a shared context. A Pod models an application-specific "logical host": it contains one or more application containers which are relatively tightly coupled.}, + language = {en}, + organization = {Kubernetes}, +} diff --git a/pages/chapter1.tex b/pages/chapter1.tex @@ -3,7 +3,7 @@ Helm is a system for managing \Glspl{k8sResources} and being able to deliver a s It is one of the most used packaging systems in the \Gls{k8s} ecosystem and helps to provide a consistent \gls{ux} in the ecosystem. \section{Helm as a packaging system} -Helm itself describes itself as \enquote{The package manager for Kubernetes}\cite{helmauthorsHelm} +Helm refers to itself as \enquote{The package manager for Kubernetes}\cite{helmauthorsHelm}. This means it's main goal and design is centered around being able to package an application, deal with dependencies and versioning. As a result of this Helm is a generic way to define an application deployment. @@ -12,32 +12,32 @@ In the typical Docker illustration style the Helm deployment would be a delivery \section{Helm as a template engine} As part of being a package manager for Kubernetes it has to deal with definitions written in pure YAML. -Therefor it features a powerful template engine which works similar to how Ansible's template engine works. +Therefore it features a powerful template engine which works similar to how Ansible's template engine works. -Under the hood this is archived by using the Go template language\cite{helmauthorsTemplateFunctionsPipelines,thegoauthorsTemplatePackageText} as well as additional go functions provided to the users. +Under the hood this is achieved by using the Go template language\cite{helmauthorsTemplateFunctionsPipelines,thegoauthorsTemplatePackageText} as well as additional go functions provided to the users. On top of the template language itself it also provides the option to print messages at the end of the installation or upgrade as well as nesting charts, having libraries for charts and using a global value context. -These are needed to provide consistent helm charts across a company or set of related charts and to ensure a nice \gls{ux} for those deploying said chart. +These are needed to provide consistent Helm charts across a company or set of related charts and to ensure a nice \gls{ux} for those deploying said chart. \section{Features Helm gives us over pure \Glspl{k8sResources}} -Pure \Glspl{k8sResources} come with multiple downsides over helm or similar packaging systems for \Gls{k8s}. +Pure \Glspl{k8sResources} come with multiple downsides over Helm or similar packaging systems for \Gls{k8s}. \Gls{k8s} brings no update management or atomic deployment management itself. This means that an admin would need to ensure that they manually deploy each thing every time, possibly in the correct order and then has to ensure that it did not break. If despite all efforts it did break you now end up with no easy way to rollback. -Ideally one has a git to go from but this might not be a safe operation either and may lead to new issues. +Ideally one has a VCS to go from but this might not be a safe operation either and may lead to new issues. Helm on the other side brings two major things to the table. -It provides a way to manage the version independent of the product version. +It provides a way to manage the chart version independent of the product version. This is called the \emph{version} of the Helm package, while the version of the product is called \enquote{\emph{appVersion}} in Helm. Helm also provides you with a history of deployments. This list tracks if a deployment is in progress, successful, failed or rolled back. -Due to this list helm allows you to seamlessly \emph{rollback} to any prior deployment you made.\footnote{While a \emph{rollback} is possible it is not possible to jump forward afterwards} -Additionally to the manual rollback Helm has the feature of atomic updates, which automatically will rollback to the last successful deployment version in case of invalid templates, values\footnote{Only syntactic errors} or failures to rollout the deployment in the given timeout. +Due to this list Helm allows you to seamlessly \emph{rollback} to any prior deployment you made.\footnote{While a \emph{rollback} is possible it is not possible to jump forward afterwards} +Additionally to the manual rollback Helm has the feature of atomic updates, which automatically will roll back to the last successful deployment version in case of invalid templates, values\footnote{Only syntactic errors} or failures to roll out the deployment within the given timeout period. Beyond the managing of versions and updates Helm also provides a way to share and therefor depend on other charts. -To do this Helm has their own Chart Repo setup or can use regular \gls{oci} repositories. -Using these repositories it allows then to define dependencies on existing helm charts. +To do this Helm has it's own Chart-repository setup or can use regular \gls{oci} repositories. +Using these repositories it allows then to define dependencies on existing Helm charts. This is especially useful to fulfill the goal of having a single deployable bundle for an application. -For example an API server might want to bundle a PostgreSQL helm chart as a dependency. -Instead of then defining it themselves it can then depend on existing Charts and provide a consistent experience for consumers in the ecosystem. -\ No newline at end of file +For example an API server might want to bundle a PostgreSQL Helm chart as a dependency. +Instead of then defining it themselves it can depend on existing Charts and provide a consistent experience for consumers in the ecosystem. +\ No newline at end of file diff --git a/pages/chapter2.tex b/pages/chapter2.tex @@ -34,13 +34,13 @@ home: https://github.com/nordeck/matrix-neoboard \subsection{The \emph{appVersion} field} The appVersion field is referring to the version of the application. -It can be different from the version of the helm chart which is defined in the version field and is expected to contain the tag of the application's docker image. -Be aware that this is not semver or similar but instead is an opaque string as helm won't make assumptions about the version of an application. +It can be different from the version of the Helm chart which is defined in the version field and is expected to contain the tag of the application's docker image. +Be aware that this is not semver\cite{helmauthorsAppVersionsField} or similar but instead is an opaque string as Helm won't make assumptions about the version of an application. \subsection{The \emph{maintainers} field} Another section of the Chart.yaml is the \enquote{maintainers} field which allows you to set the maintainers of the application. -This is not mandatory but useful if you publish this helm chart to some places. +This is not mandatory but useful if you publish this Helm chart to some places. It is an array which contains a name, an email and a url field and is meant to contain each maintainer that works on the chart. -However, in a company setting it can also be used to just have the company instead. +However, in a company setting it can also be used to just refer to the company instead. \section{The \enquote{values.yaml}} @@ -74,7 +74,7 @@ Things to note here are the 3 fields it should contain: \item{ The \enquote{pullPolicy} which defines how often it is pulled By default this should be \enquote{IfNotPresent}. - For latest tags it automatically defaults however to \enquote{Always} which, as the name says, will always pull the image when a pod is started. + For latest tags it automatically defaults however to \enquote{Always} which, as the name says, will always pull the image when a \Gls{pod} is started. } \item{ The \enquote{tag} field defines the value after the colon in a docker image. @@ -83,14 +83,14 @@ Things to note here are the 3 fields it should contain: } \end{enumerate} -Additionally, there is the \enquote{imagePullSecrets} field which allows you to pull from private repositories. For more information on this take a look at \url{https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/} +Additionally, there is the \enquote{imagePullSecrets} field which allows you to pull from private repositories. For more information on this take a look at \url{https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/}. \subsection{Service Account} \begin{figure}[h] \begin{minted}[numbers=left, frame=lines,breaklines,breakanywhere,samepage=false]{yaml} -#This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ serviceAccount: # Specifies whether a service account should be created create: true @@ -141,19 +141,19 @@ ingress: \caption{The \enquote{service} section and the \enquote{ingress} section of the \gls{values}}\label{code:service_and_ingress_section} \end{figure} -A service consists of the service type and a port +A service consists of the service type and a port. The type of service generally will be \enquote{ClusterIP} for production clusters. However, there are users which might want to prefer \enquote{NodePort} as a type instead of using an Ingress. Therefor it should be left as an option for users. For the port on the other hand it depends on the application. -It is only useful to be kept as an option if the Dockerimage at runtime allows adjusting it. +It is only useful to be kept as an option if the container image at runtime allows adjusting it. This is incredibly useful for \enquote{NodePort} users and should be preferred. -It should default however to the application default to avoid confusion in case an enduser has to debug it. - +It should default however to the application default to avoid confusion in case an end-user has to debug it. You can find more information about the service resource in \gls{k8s} at \url{https://kubernetes.io/docs/concepts/services-networking/service}. + \bigskip -The ingress of a Helm chart is used to represent public access point of an application. +The ingress of a Helm chart is used to represent the public access point of an application. It is used to define one or multiple hosts or subpaths for the application. They should stay in the same pattern as above since ingresses do depend a lot on the user and their ingress software used. Additionally this is where the secrets and hosts for the tls certificate attached to the ingress are defined. @@ -161,10 +161,10 @@ It is safe to assume that a \gls{k8s} cluster has means to provide this certific \subsection{Volumes} -Volumes and volume mounts are a way to describe storage in \gls{k8s} . -In terms of a helm chart there are 2 things to differenciate here. +Volumes and volume mounts are a way to describe storage in \gls{k8s}. +In terms of a Helm chart there are 2 things to differenciate here. On the one side we have mandatory storage which an application requires. -Usually this is being named \enquote{persistence} in a helm chart and takes just the storage size and access modes definition. +Usually this is being named \enquote{persistence} in a Helm chart and takes just the storage size and access modes definition. For example: @@ -189,7 +189,7 @@ persistence: This example defines that the persistence is enabled, does not use an existing \Gls{pvc}. It also says that we use the \enquote{ReadWriteOnce} access mode meaning only one pod at a time can use it\cite{KubernetesPersistentVolume}. -Last but not least it also defines that the size must be 10Gigabit for this storage. +Last but not least it also defines that the size must be \qty{10}{\giga\byte} for this storage. The storage class is not set which means the cluster default is used. As there can be multiple storage providers it is desirable to have this as an option to allow a user to change this based on their cluster. @@ -197,9 +197,9 @@ Additionally, one could also not set \enquote{size} and \enquote{accessMode} and That way the underlying \gls{pvc} will not be managed by the chart. \bigskip -Additionally, to required storage there is the option to provide means to add optional user defined storage. +In addition to required storage, there is the option to provide means to add optional user defined storage. The use for this depends on the application type. -It allows defining the same volumes and volumeMounts definitions as explained in the \gls{k8s} Pod resource. +It allows defining the same volumes and volumeMounts definitions as explained\cite{Pods} in the \gls{pod} resource. As we do not know if in the end the user keeps using our image or forks it, it is a good idea to allow this flexiblity. Usually it looks something like this example: @@ -247,6 +247,7 @@ Notable things you might want by default but need Docker adjustments are: \item{ \enquote{readOnlyRootFilesystem} should be enabled. This ensures that the system never writes to the temporary filesystem of the pod. + As a result of this an attacker has a harder time to inject changes into a Pod which would affect the end-user in case a container has been compromised. For \enquote{/tmp} you should prefer an \enquote{emptyDir} volume instead. } \item{ @@ -256,7 +257,7 @@ Notable things you might want by default but need Docker adjustments are: } \item{ \enquote{capabilities} should default to dropping all. - Ideally these should be tight scoped. + Ideally these should be tightly scoped. Depending on the application common ones are network related and chroot related capabilities with webservers. } \end{enumerate} @@ -290,7 +291,7 @@ The \enquote{startup} probe is only used when an application is slow to start an Generally you want to have a health endpoint for this on your application which can be pinged. Alternatively this also can be a command within the pod. -Usually this also is a command that can be fixed for the helm chart, but when you do that you should have the timeouts exposed in the \gls{values}. +Usually this also is a command that can be fixed for the Helm chart, but when you do that you should have the timeouts exposed in the \gls{values}. \subsection{Auto scaling} Auto scaling is the automation of replication. @@ -336,7 +337,7 @@ The nodeSelector value can be used to for example deploy it on a specific node w The tolerations are helping with nodes which have taints. Taints prevent scheduling unless tolerated. -A common example of a taint for example is the control plane of the cluster. +A common example of a taint is the control plane taint for the control plane nodes of the cluster. It is usually used to restrict a node for important core tasks of the cluster. \enquote{Affinity} is another more flexible way for the application to define where it can get scheduled. diff --git a/root.tex b/root.tex @@ -19,11 +19,15 @@ name={Kubernetes Resource}, description={A Kubernetes Resource is a YAML document defining a thing inside of a Kubernetes Cluster. This for example can be a Pod} } +\newglossaryentry{pod}{ + name={Kubernetes Pod}, + description={A kubernetes Pod is the smallest deployable unit of computing which can be created and managed in Kubernetes. It is defining a group of one or more containers (see Docker/Podman containers) with shared storage and network resources. See \url{https://kubernetes.io/docs/concepts/workloads/pods/} for more details.} +} \newacronym{k8s}{k8s}{Kubernetes} \newacronym{oci}{OCI}{Open Container Initiative} \newacronym{ux}{UX}{User Experience} \newacronym{values}{values file}{values.yaml} -\newacronym[description={A resource which describes how a volume should be allocated and how it is usable by pods or other resources}]{pvc}{pvc}{Private Volume Claim} +\newacronym[description={A resource which describes how a volume should be allocated and how it is usable by pods or other resources}]{pvc}{pvc}{Persistent Volume Claim} \newglossaryentry{deployment resource}{ name={Deployment resource}, description={A resource which allows replication of pods and rolling updates.} @@ -44,38 +48,38 @@ \chapter{Usage of a Helm Package} \section{Atomic mode} -One of the less mentioned things helm can do is that it can atomically deploy things to a cluster. +One of the less mentioned things Helm can do is that it can atomically deploy things to a cluster. What does atomically mean here? -Specifically it means that an application will (if the helm chart was configured correctly) will never let the application get stuck in a broken state on upgrades. +Specifically it means that an application will (if the Helm chart was configured correctly) never let the application get stuck in a broken state on upgrades. -To do that it provides the \enquote{--atomic} flag usable on \enquote{helm upgrade}. -When the flag is provided helm will wait until the application entered a successful state where all pods report being ready in \Gls{k8s}. -If this is not archived helm will automatically roll back to the last successful deployment version. +To do that it provides the \mintinline[breaklines]{bash}{--atomic} flag usable on \mintinline[breaklines]{bash}{helm upgrade}. +When the flag is provided Helm will wait until the application entered a successful state where all pods report being ready in \Gls{k8s}. +If this is not achieved Helm will automatically roll back to the last successful deployment version. It also ensures that the old application still is running while trying this by utilizing the way Deployments in \Gls{k8s} work. -A deployment with rolling update will spawn a new pod, wait for it to get successful and only then stop the old pod. +A deployment with rolling update will spawn a new pod, wait for it to get into the \enquote{Ready} state on the cluster and only then stop the old pod. The default timeout for Helm's atomic deployment is at 5m. It is generally a good idea to use this however tools like argocd generally do not expose this mode to the users. \section{Listing deployments and rollback of deployments} -Helm automatically records a list of deployments done to each helm chart. +Helm automatically records a list of deployments done to each Helm chart. This allows for 2 great things: \begin{enumerate} \item Your application is deployed in a way which can be audited \item Your application can be rolled back easily to a previous state even if you do not know the values anymore \end{enumerate} -To view the history of a specific helm chart deployment you can use \enquote{helm history <release\_name> -n <namespace>}. +To view the history of a specific Helm chart deployment you can use \mintinline[breaklines]{bash}{helm history <release_name> -n <namespace>}. Note however that unless you add the `--max` flag only the last 256 revisions will be displayed. -When you end up in a broken deployment or need to downgrade the application version this information can be coupled with \enquote{helm rollback}. -You can either use \enquote{helm rollback <release\_name>} to roll back to the previous revision or \enquote{helm rollback <release\_name> <revision>} to rollback to a specific revision. +When you end up in a broken deployment or need to downgrade the application version this information can be coupled with \mintinline[breaklines]{bash}{helm rollback}. +You can either use \mintinline[breaklines]{bash}{helm rollback <release_name>} to roll back to the previous revision or \mintinline[breaklines]{bash}{helm rollback <release_name> <revision>} to rollback to a specific revision. Important to note is that this does not handle database migrations. \section{Linting} -Apart from operational commands helm also allows you to lint a package. -To do that there is the \enquote{helm lint <PATH>} subcommand available which provides a relatively small linter for the helm chart. +Apart from operational commands Helm also allows you to lint a package. +To do that there is the \mintinline[breaklines]{bash}{helm lint <PATH>} subcommand available which provides a relatively small linter for the Helm chart. It is generally a good idea to use this. You can find more information on this at \url{https://helm.sh/docs/helm/helm_lint/}. diff --git a/style.sty b/style.sty @@ -15,7 +15,7 @@ \usepackage{amsmath,amssymb,amsthm} \usepackage{booktabs} \usepackage{array} -\usepackage{siunitx} +\usepackage[binary-units]{siunitx} \usepackage{graphicx} \usepackage{lmodern} \usepackage{dirtree}