We can think of Helm as apt-get/yum under Kubernetes. Helm is the package manager of kubernetes. There are only configuration list files in the Helm warehouse, but no mirror image. The mirror image is still provided by the mirror warehouse, such as hub.docker.com, Private warehouse.
You can go to the download address of Helm to download and install. The steps of Helm installation are as follows:
# 下载包
$ wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz
# 解压压缩包
$ tar -xf helm-v3.9.4-linux-amd64.tar.gz
# 制作软连接
$ ln -s /opt/helm/linux-amd64/helm /usr/local/bin/helm
# 验证
$ helm version
$ helm help
④ Helm components and related terms
Helm——Helm is a client tool under the command line, which is mainly used for the creation, packaging and publishing of the Kubernetes application Chart, as well as the creation and management of local and remote Chart warehouses;
Chart—Chart represents the Helm package, which contains all the resource definitions needed to run applications, tools or services inside the Kubernetes cluster, and can be regarded as the equivalent of Homebrew formula, Apt dpkg or Yum RPM in Kubernetes;
Release——Release is an instance of a chart running in a Kubernetes cluster. A chart can usually be installed multiple times in the same cluster, and each installation will create a new release;
Repoistory - A Repository is a place to store and share charts, like Perl's CPAN archive network or Fedora's package repository, except it's for Kubernetes packages.
2. Helm Chart
① Chart directory structure
You can create a new chart package with the helm create command:
From v3.3.2, extra fields are no longer allowed, the recommended way is to add custom metadata in annotations. Each chart must have a version number (version), and the version must follow the "Semantic Version 2" standard. Unlike classic Helm, Helm v2 and subsequent versions will use the version number as a release marker. Packages in the warehouse are added by name and version ID number. For example, the version field version: 1.2.3 of nginx chart is set to:
nginx-1.2.3.tgz
Note: The appVersion field is not related to the version field, which is a way of specifying the app version. For example, this drupal chart might have an appVersion: "8.2.1", indicating that the version of Drupal contained in the chart (by default) is 8.2.1.
③ Chart dependency management (dependencies)
Other charts that the current chart depends on will be defined as a list in the dependencies field:
Once the dependencies are defined, running helm dependency update will use the dependency files to download all specified charts to the charts/ directory:
helm dependency update ./wordpress
When helm dependency update pulls a chart, a chart package is formed in the charts/ directory, so for the above example, you would expect to see the following files in the chart directory:
Tag and condition fields in dependencies: In addition to the other fields above, each requirement item can contain optional fields tags and condition, and all charts will be loaded by default. If tags or condition fields are present, they will be evaluated and used to control the loading of the chart they apply to.
Condition: The condition field field contains one or more YAML paths (separated by commas). If this path already exists in the upper-level values and resolves to a Boolean value, the chart will enable or disable the chart based on the Boolean value, and only the ones found in the list will be used. The first valid path, if the path is not found then the condition is invalid;
Tags: The tag field is a list of tags in YAML format associated with the chart. In the top-level value, you can enable or disable all tagged charts by specifying tag and Boolean value.
In the above example, all charts with front-end tag will be disabled, but as long as the subchart1.enabled path in the value of the upper layer is set to 'true', the condition will override the front-end tag and subchart1 will be enabled.
Once subchart2 uses the back-end tag and is set to true, subchart2 will be enabled. Also note that although subchart2 specifies a condition field, the upper-level value does not have a corresponding path and value, so this condition will not take effect.
The --set parameter can be used to set labels and conditional values:
The condition (when set in value) will always override the label. If the conditional path of the first chart exists, the following path will be ignored;
The label is defined as 'If any of the chart labels is true, the chart can be enabled;
Labels and conditional values must be set in the top-level value;
The tags: key in value must be a top-level key.
④ Import child Value through dependency
In some cases it is worthwhile to allow child chart values to be passed as public defaults into the parent chart, with the added benefit of using the exports format so that future tools can introspect user-settable values.
The imported key containing values can be specified in the import-values field in the dependencies of the parent chart in the form of a YAML list, and each item in the list is a key imported from the exports field in the child chart.
Import values not contained in the exports key, using the child-parent format.
Use the export format: If the values.yaml file of the child chart contains the exports field in the root node, its content can be directly imported into the value of the parent chart by specifying, as follows:
As long as the key data is specified in the import list, Helm will look for the data key in the subchart's exports field and import its contents.
The final parent value will contain our exported fields. The parent key data is not included in the parent's final value. If you want to specify this parent key, use the 'child-parent' format:
# parent's values
myint:99
The import-values in the example shown below instructs Helm to take any values it can find in the child: path and copy them to the specified path in parent::
The Helm Chart template is written in the Go templating language, adding about 50 additional template functions from the Sprig library and some other specified functions.
All template files are stored in the chart's templates/ folder. When Helm renders a chart, it traverses each file in the directory through the template engine.
The Value of the template is provided in two ways:
Chart developers can provide a file named values.yaml in the chart, which contains default values;
Chart users can provide a YAML file containing value, and can specify the value file by -f when using the helm install command on the command line.
charts is a template for a Kubernetes replica controller, which can use the following four template values (generally defined in the values.yaml file):
imageRegistry: the source registry of the Docker image;
dockerTag: the tag of the Docker image;
pullPolicy: Pull policy of Kubernetes;
storage: background storage, default is "minio".
② Predefined Values
Values are provided through the values.yaml file accessible by the .Values object in the template (or via the --set parameter), but other predefined data fragments are accessible in the template. The following values are predefined, valid for each template, and can be overridden, and like all values, the names are case-sensitive:
Release.Name: version name (non-chart);
Release.Namespace: the namespace of the released chart version;
Release.Service: Organization version service;
Release.IsUpgrade: Set to true if the current operation is an upgrade or rollback;
Release.IsInstall: Set to true if the current operation is installation;
Chart: the content of Chart.yaml, so the version of chart can be obtained from Chart.Version, and the maintainer is in Chart.Maintainers;
Files: A diagram-like object in a chart that contains non-special files, this will not allow you to access templates, but will allow access to other existing files (unless excluded by .helmignore), use { { index .Files "
file.name ” }} You can access the file or use the {
{.Files.Get name }} function, or you can use {
{ .Files.GetBytes }} as []byte to access the file content;
Capabilities: A class diagram object containing Kubernetes version information. ({
{ .Capabilities.KubeVersion }}) and supported Kubernetes API versions ({
{ .Capabilities.APIVersions.Has “batch/v1” }});
Considering the template from the previous section, the necessary values provided by the values.yaml file are as follows:
The values file is defined in YAML format. The chart will contain a default values.yaml file. The Helm installation command allows the user to override this value with additional YAML values:
A Values file can declare values for the top-level chart, as well as any other charts contained in the charts/ directory. Or to put it another way, the values file can provide values for the chart and any of its dependencies. For example, the WordPress chart demonstrated above has both mysql and apache as dependencies, and the values file can provide dependencies for all of the following components:
title:"My WordPress Site" # Sent to the WordPress template
mysql:
max_connections:100 # Sent to MySQL
password:"secret"
apache:
port:8080 # Passed to Apache
Higher-level charts have access to all variables defined below, so WordPress charts can access MySQL passwords with Values.mysql.password. But lower-level charts cannot access parent charts, so MySQL cannot access the title attribute, nor can it access apache.port.
④ Global Values
Since 2.0.0-Alpha.2, Helm supports special global values, imagine a modified version of the previous example:
title:"My WordPress Site" # Sent to the WordPress template
global:
app:MyWordPress
mysql:
max_connections:100 # Sent to MySQL
password:"secret"
apache:
port:8080 # Passed to Apache
Added a global section and a value app: MyWordPress, which is available in all charts as .Values.global.app. For example, the mysql template can
access the app as { {.Values.global.app}}, and the apache chart can also access it. In fact the above values file will be regenerated like this:
title:"My WordPress Site" # Sent to the WordPress template
global:
app:MyWordPress
mysql:
global:
app:MyWordPress
max_connections:100 # Sent to MySQL
password:"secret"
apache:
global:
app:MyWordPress
port:8080 # Passed to Apache
4. Helm resource installation order
Namespace
NetworkPolicy
ResourceQuota
LimitRange
SubSecurityPolicy
PodDisruptionBudget
ServiceAccount
Secret
SecretList
ConfigMap
StorageClass
PersistentVolume
PersistentVolumeClaim
CustomResourceDefinition
ClusterRole
ClusterRoleList
ClusterRoleBinding
ClusterRoleBindingList
Role
RoleList
RoleBinding
RoleBindingList
Service
DaemonSet
Pod
ReplicationController
ReplicaSet
Deployment
HorizontalPodAutoscaler
StatefulSet
Job
CronJob
Ingress
APIService
5. Three ways for Helm to install the Chart package
Helm comes with a powerful search command that can be used to search from two sources:
helm search hub finds and lists helm charts from Artifact Hub https://artifacthub.io/, where a large number of different warehouses are stored;
helm search repo Searches from the repositories added (using helm repo add) to the local helm client. This command searches based on local data and does not require an Internet connection.
There are two ways to pass configuration data during installation:
–values (or -f): Use YAML files to override the configuration, you can specify multiple times, and use the rightmost file first;
–set: Overwrite the specified item through the command line.
If both methods are used at the same time, the value in --set will be merged into --values, but the value in --set has higher priority. The content overwritten in –set will be saved in ConfigMap. You can use helm get values to view the value set by --set in the specified release, or you can run helm upgrade and specify the --reset-values field to clear -- The value set in set. Examples are as follows:
Direct online installation does not need to download the package to the local first:
helm install mysql bitnami/mysql
helm list
Offline installation is installed directly through the installation package:
# 先删除
helm uninstall mysql
# 拉包到本地
helm pull bitnami/mysql
# 不解压直接安装
helm install mysql ./mysql-9.3.1.tgz
helm list
Offline installation Unzip the package and install again:
# 拉包到本地
helm pull bitnami/mysql
# 解压安装
tar -xf mysql-9.3.1.tgz
# 开始安装
helm install mysql ./mysql \
--namespace=mysql \
--create-namespace \
--set image.registry=myharbor.com \
--set image.repository=bigdata/mysql \
--set image.tag=8.0.30 \
--set primary.service.type=NodePort \
--set service.nodePorts.mysql=30306
# 查看在运行的Release
helm list
# 卸载
helm uninstall mysql -n mysql
6. Helm Basic Grammar
① variable
The variables in the template (templates/) are placed
in { {}}, for example: {
{ .Values.images }} means the images field under the Values object. Values come from the values.yaml file or the yaml file specified by -f, or the variables set by --set.
Use - to delete spaces and line breaks. To delete other spaces and line breaks in that line, you can use { {
- or -}}, one is to delete spaces and line breaks on the left, and the other is to delete spaces and line breaks on the right .
② Built-in objects
Release: The Release object describes the release itself, including the following objects:
Release.Name: release name;
Release.Namespace: the namespace included in the release (if not covered by the manifest);
Release.IsUpgrade: If the current operation is an upgrade or rollback, this value will be set to true
Release.IsInstall: If the current operation is to install, the value will be set to true
Release.Revision: The version number of this revision, which is 1 when installed, will increase automatically every time you upgrade or roll back;
Release.Service: This service is used to render the current template, and Helm is always in Helm.
Values: The Values object is passed into the template from the values.yaml file and the file provided by the user, and is empty by default;
Chart: the content of the Chart.yaml file, all data in Chart.yaml can be accessed here, for example {
{ .Chart.Name }}-{
{ .Chart.Version }} will print out mychart-0.1.0;
Template: Contains the current template information currently being executed:
Template.Name: namespace file path of the current template (eg mychart/templates/mytemplate.yaml);
Template.BasePath: The path of the current chart template directory (eg mychart/templates).
③ Commonly used built-in functions
quote and squote:
This function converts the value into a string enclosed in double quotes (quote) or **single quote (squote)**. Examples are as follows:
Helm has the following encode and decode functions:
-b64enc/b64dec: Encode or decode Base64
-b32enc/b32dec: Encode or decode Base32
⑦ Dictionaries and Dict Functions
Helm provides a key/value storage type called dict (short for "dictionary", also available in Python), dict is an unordered type, and the key of the dictionary must be a string. But the value can be of any type, even another dict or list.
Create a dictionary (dict) , as follows to create a dictionary of three key-value pairs:
Given a map and a key, get the value from the map, resulting in "value1":
get $myDict"name1"
Note that if not found, it will simply return "" and no error will be generated.
Add key-value pairs (set) :
Use set to add a key-value pair to the dictionary:
$_:= set $myDict"name4""value4"
Note that set returns a dictionary (a requirement of Go template functions), so it may be necessary to use $_ assignment as above to get the value.
delete (unset) :
Given a map and a key, remove the key from the map:
$_:= unset $myDict"name4"
Like set, a dictionary needs to be returned.
Judgment key (hasKey) :
The hasKey function will return true if the given key is contained in the given dictionary:
hasKey $myDict"name1"
If the key is not found, false will be returned.
pluck:
The pluck function is given a key and multiple mappings and gets a list of all matches:
pluck "name1"$myDict$myOtherDict
The above will return a list containing each found value ([value1 otherValue1]).
Merge dict(merge, mustMerge) : Merge two or more dictionaries into one, target dictionary first:
$newdict:= merge $dest$source1$source2
Get all keys :
The keys function will return a list of all keys in one or more dict types. Since dictionaries are unordered, the keys will not have a predictable order, and can be stored using sortAlpha:
keys $myDict| sortAlpha
When multiple dictionaries are provided, the keys are concatenated, using the uniq function and sortAlpha to obtain a uniquely ordered list of keys:
keys $myDict$myOtherDict| uniq | sortAlpha
Get all values :
The values function is similar to keys, returning a new list containing all the values in the source dictionary (only one dictionary is supported).
$vals:= values $myDict
The result of the above is: list["value1", "value2", "value 3"]. Note that values does not guarantee the order of the results; if order is desired, sortAlpha can be used.
⑧ Lists and List Functions
Helm provides a simple list type that holds lists in any order. Similar to arrays or slices, but lists are designed for immutable data types.
Create list :
$myList:= list 12345
The above would generate a list [1 2 3 4 5].
Get the first item of the list (first, mustFirst) :
To get the first item in the list, use first.
first $myList
# 返回 1
An error will occur if there is a problem with first, and an error will be returned to the template engine if there is a problem with mustFirst.
Get the tail content of the list (rest, mustRest) :
To get the tail content of the list (everything but the first item), use rest:
rest $myList
# 返回 [2345]
An error will occur when there is a problem with rest, and an error will be returned to the template engine when there is a problem with mustRest.
Get the last item of a list (last, mustLast) :
Use last to get the last item of a list:
last $myList
# 返回 5。这大致类似于反转列表然后调用first。
Get all contents of list (initial, mustInitial) :
By returning all elements except the last one:
initial $myList
# 返回 [1234]
An error will occur if there is a problem with initial, but an error will be returned to the template engine if there is a problem with mustInitial.
Add elements at the end (append, mustAppend) :
Append an item to an existing list, creating a new list:
$new= append $myList6
The above statement will be set to [123456], myList will remain unchanged,
There is an error when append fails, but mustAppend returns an error to the template engine when there is a problem.
Add elements in front (prepend, mustPrepend) :
Add elements to the front of a list, producing a new list:
prepend $myList0
The above statement will generate [0 1 2 3 4 5] and $myList will remain unchanged.
prepend will throw an error, but mustPrepend will return an error to the template engine if there is a problem.
Multiple list concatenation (concat) :
Concatenate any number of lists into one:
concat $myList( list 67)( list 8)
The above statement would generate [1 2 3 4 5 6 7 8] and $myList would remain unchanged.
reverse(reverse, mustReverse) :
Reverse the given list to generate a new list:
reverse $myList
The above statement produces a list: [5 4 3 2 1].
reverse will throw an error, but mustReverse will return an error to the template engine.
deduplication(uniq, mustUniq) :
Generate a list with duplicates removed:
list 1112| uniq
The above statement produces [1 2].
uniq will throw an error when there is a problem, but mustUniq will return an error to the template engine if there is a problem.
filter(without, mustWithout) :
The without function filters content from a list:
without $myList3
# 上述语句会生成 [1245]
A filter can filter multiple elements:
without $myList135
# 这样会得到: [24]
Without will throw an error, but mustWithout will return an error to the template engine.
Determine whether an element exists (has, mustHas) :
Verify that a list has a specific element:
has 4$myList
The above statement will return true, but has “hello” $myList will return false.
Has will throw an error, but mustHas will return an error to the template engine.
Remove empty items (compact, mustCompact) :
Take a list and remove null items:
$list:= list 1"a""foo"""$copy:= compact $list
compact returns a new list with null values (eg, "") removed.
compact will throw an error, but mustCompact will return an error to the template engine.
index:
Use index list[n] to get the nth element of a list, and index list[n][m] ... to get multibit list elements:
index $myList0 返回 1,同 myList[0]
index $myList01 同 myList[0][1]
Get some elements (slice, mustSlice) : Get some elements from the list, use slice list [n] [m], which is equivalent to list[n:m]:
The next control structure is the with operator, this is used to control variable scope. Recall that . is a reference to the current scope, so .Values is telling the template to look for the Values object in the current scope.
The syntax of with is similar to that of an if statement:
{
{
with PIPELINE}}
# restricted scope
{
{
end }}
The scope can be changed, with allows specific objects to set the current scope (.). For example, if .Values.favorite is already in use, modify the scope of . in the configuration map to point to .Values.favorite:
This will report an error because Release.Name is not within the scope of the . limit. But it's normal if you reverse the last two lines, because
the scope is reset after { { end }}:
Or you can access the Release.Name object from the parent scope, access the Release.Name object from the parent scope when the template starts executing, and when the template starts executingThe Re l e a se . Name object is accessed from the parent scope . When the template starts executing, it will be mapped to the root scope and will not change during execution . The following also works fine:
Variables can also be defined outside, following the format of the $name variable and specifying a special assignment operator: :=, which can be rewritten using a variable for Release.Name:
Note that before the with block begins, the assignment relname := .Release .Name , now in the with block, relname := .Release.Name , now in the with block,relname:=.R e l e a se .N ame , now in the with block , the relname variable still executes the version name .
⑫ rang loop statement
Many programming languages support the use of for loops, foreach loops, or similar method mechanisms. In Helm's templating language, the way to iterate over a collection is to use the range operator.
Sometimes it is useful to be able to quickly create a list in a template and then iterate over it, and Helm template tuples make this easy. In computer science, a tuple represents a list-like collection of fixed size, but can be of any data type, which roughly expresses the usage of tuple:
sizes:|-{
{
- range tuple "small""medium""large"}}-{
{
.}}{
{
- end }}
上述模板会生成以下内容:
sizes:|-- small
- medium
- large
⑬ Naming templates
At this point, you need to skip the template and start creating other content. This section can see how to define a named template in a file and use it elsewhere. A named template (sometimes called a "section" or a "subtemplate") is simply a template defined inside a file with a name.
Three methods of declaring and managing templates: define, template, and block. In this section, these three operations will be used and a special-purpose include method will be introduced, similar to the template operation.
An important detail to remember when naming templates: template names are global, if you want to declare two templates with the same name, whichever is loaded last will be used, because templates in subcharts are compiled together with top-level templates, pay attention when naming chart specific name.
A common naming convention is to prefix the template with the chart name: {
{ define “mychart.labels” }}, using a specific chart name as a prefix can avoid possible conflicts caused by two different charts using a template with the same name.
Before writing the template details, the naming convention of the file needs attention:
Most files in templates/ are considered to contain Kubernetes manifests;
NOTES.txt is an exception;
Files whose names begin with an underscore (_) are assumed to contain no manifest content. These files are not rendered as Kubernetes object definitions, but are available in other chart templates.
These files are used to store local and helper objects. In fact, when we first create mychart, we will see a file called _helpers.tpl, which is the default location for template locals.
Declare and use templates with define and template:
The define operation allows us to create a named template in the template file, the syntax is as follows:
{
{
- define "MY.NAME"}}
# body of template here
{
{
- end }}
A template can be defined to encapsulate Kubernetes tags:
{
{
- define "mychart.labels"}}
labels:
generator: helm
date:{
{
now | htmlDate }}{
{
- end }}
Now embed the template into the existing configuration map and include it using template:
When the template engine reads the file, it stores the reference to mychart.labels until template "mychart.labels" is called, and then renders the template line by line, so the result looks like this:
$ helm install --dry-run measly-whippet ./mychart
Error: unable to build kubernetes objects from release manifest: error validating "": error validating data:[ValidationError(ConfigMap): unknown field "app_name"in io.k8s.api.core.v1.ConfigMap,ValidationError(ConfigMap): unknown field "app_version"in io.k8s.api.core.v1.ConfigMap]
To see what is rendered, re-execute with the --disable-openapi-validation parameter: helm install --dry-run --disable-openapi-validation measly-whippet ./mychart. Input is not what you want:
Note that the indentation of app_version in both places is wrong, why is this? Because the text in the replaced template is left-aligned, and since template is a behavior, not a method, the output of the template call cannot be passed to other methods, and the data is simply inserted line by line. To deal with this problem, Helm provides an include, which can import the template content into the current pipeline, and then pass it to other methods in the pipeline. The mychart.app template is properly indented using indent as follows:
apiVersion: v1
kind:ConfigMap
metadata:
name:{
{
.Release.Name}}-configmap
labels:{
{
include "mychart.app".| indent 4}}
data:
myvalue:"Hello World"{
{
- range $key,$val:=.Values.favorite }}{
{
$key}}:{
{
$val| quote }}{
{
- end }}{
{
include "mychart.app".| indent 2}}
Every part of the generated YAML is now properly indented:
include Compared to using template, using include in helm is considered a better way just to better handle the output format of YAML documents.
⑭ NOTES.txt file
At the end of the helm install or helm upgrade command, Helm will print useful information to the user, which can be highly customized using templates. To add installation notes to a chart, simply create a templates/NOTES.txt file, which is plain text but is treated like a template, and all normal template functions and objects are available.
Create a simple NOTES.txt file:
Thank you for installing {
{
.Chart.Name}}.Your release is named {
{
.Release.Name}}.To learn more about the release,try:
$ helm status {
{
.Release.Name}}
$ helm get all {
{
.Release.Name}}
If you execute helm install rude-cardinal ./mychart you will see at the bottom:
RESOURCES:==> v1/SecretNAMETYPEDATAAGE
rude-cardinal-secret Opaque1 0s
==> v1/ConfigMapNAMEDATAAGE
rude-cardinal-configmap 3 0s
NOTES:Thank you for installing mychart.Your release is named rude-cardinal.To learn more about the release,try:
$ helm status rude-cardinal
$ helm get all rude-cardinal
Using NOTES.txt this way is a good way to provide users with detailed information on how to use a newly installed chart. Although not required, it is strongly recommended to create a NOTES.txt file.
⑮ Template debugging
Debugging templates can be tricky, as rendered templates are sent to the Kubernetes API server, which may reject the YAML file for reasons other than formatting. The following commands are helpful for debugging:
helm lint is the tool of choice for verifying that charts follow best practices;
helm install --dry-run --debug or helm template --debug: This is a great way to have the server render a template and return the resulting manifest file;
helm get manifest: This is a great way to view the templates installed on the server.
When parsing a YAML file fails, but you want to know what was generated, an easy way to retrieve the YAML is to comment out the offending part of the template, then re-run helm install --dry-run --debug: