Helm 3 Plugin

Helm is the first application package manager running on top of Kubernetes. It allows describing the application structure through convenient helm-charts and managing it with simple commands. Helm uses three main concepts:

A Chart is a Helm package. It contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. Think of it like the Kubernetes equivalent of a Homebrew formula, an Apt pkg, or a Yum RPM file.

A Repository is a place where charts can be collected and shared. It’s like Perl’s CPAN archive or the Fedora package Database, but for Kubernetes packages.

A Release is an instance of a chart running in a Kubernetes cluster. One chart can often be installed many times into the same cluster. And each time it is installed, a new release is created. Consider a MySQL chart. If you want two databases running in your cluster, you can install that chart twice. Each one will have it’s own release, which will in turn have it’s own release name.

With Cloudify Helm 3 plugin you can add repositories and create releases on Kubernetes cluster.

Plugin Requirements

In order to know which versions of Kubernetes Helm supports,see Helm version support policy.

Authentication

Authentication is required for Helm interaction with Kubernetes. There are two authentication methods which are:

Kube Config Authentication

To configure authentication with Kubernetes, use “client_config.configuration” section in “cloudify.nodes.helm.Release” node type. The config should be a Kube Config style object.

One of three methods options can be used to provide the configuration:

Moreover, api_options can be used in addition to one of the three above (under configuration).
api_options contains host (kubernetes endpoint), api_key (service account token for authentication with the cluster) and ssl_ca_cert(Cluster certificate authority). If provided, they will override kubeconfig configuration (will attach --kube-apiserver,--kube-token,--kube-ca-file flags to helm install/uninstall commands).

Example 1:

This is an example for authentication with kubeconfig file content:

 inputs:

  configuration_file_content:
    type: string

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          file_content: {get_input: configuration_file_content } # secret also can be used.

Example 2:

This is another example for authentication with kubeconfig file content,as a dict:

 node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          file_content:
            apiVersion: v1
            kind: Config
            preferences: {}
            current-context: kubernetes-admin@kubernetes
            clusters:
            - name: kubernetes
              cluster:
                certificate-authority-data: { get_input: kubernetes_certificate_authority_data }
                server: { concat: [ 'https://', { get_input: kubernetes_master_ip}, ':', { get_input: kubernetes_master_port } ] }
            contexts:
            - name: kubernetes-admin@kubernetes
              context:
                cluster: kubernetes
                user: kubernetes-admin
            users:
            - name: kubernetes-admin
              user:
                client-certificate-data: { get_input: kubernetes-admin_client_certificate_data }
                client-key-data:{ get_input: kubernetes-admin_client_key_data }

Example 3:

This is an example for authentication with kubeconfig file path (the file is in the blueprint archive):

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          blueprint_file_name: path/to/kubeconfig

Example 4:

This is an example for authentication with kubeconfig file path and token:

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          blueprint_file_name: path/to/kubeconfig
          api_options:
            api_key: 'put token here (secret is recommended)'

Cluster CA, Cluster Endpoint And Token Authentication

Example:

This example demonstrates cluster authentication with API endpoint, token and CA.

node_templates:

 release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          api_options:
            host: <kubernetes API endpoint>
            api_key: <token>
            ssl_ca_cert: <CA file path or content>

GKE OAuth2 Tokens Authentication

While using gcp, an OpenID Connect Token can be generated from gcp service account in order to authenticate with kubernetes(see kubernetes docs). In order to refresh the token that resides in kubeconfig (or create one) from gcp service account before invoking helm commands, add gcp service account to the blueprint under authentication:

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          file_content: {get_secret: kube_config }
        authentication:
          gcp_service_account: { get_secret: gcp_credentials }

While using GKE if Kubernetes service account token isn’t used it’s recommended to add authentication section.

EKS Authentication

When using EKS, create kubeconfig as explained in AWS docs using AWS cli (not aws-iam-authenticator). Specify aws_access_key_id, aws_secret_access_key, aws_default_region under client_config.authentication like:

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          file_content: {get_secret: kube_config }
        authentication:
          aws_access_key_id: {get_secret: aws_access_key_id }
          aws_secret_access_key: {get_secret: aws_secret_access_key }
          aws_default_region: {get_secret: aws_default_region }

Node Types

cloudify.nodes.helm.Binary

This node type responsible for installing helm (move the given binary to the default location).

Moreover, in order to allow different environment for every binary, this node will create 3 temporary folders for: cache, data and configuration files of Helm. It will save those paths in runtime properties.

Actually, those paths are going to override HELM_CACHE_HOME,HELM_CONFIG_HOME and HELM_DATA_HOME environment variables in each helm command we will execute.

Properties:

Helm plugin uses curl on installation_source and unzip it, then move it to executable_path or to default location (deployment directory) if executable_path is not provided.

Example:

node_templates:

  helm_install:
    type: cloudify.nodes.helm.Binary
    properties:
      use_existing_resource: false
      installation_source: <link to helm binary release zip> # e.g: 'https://get.helm.sh/helm-v3.6.0-linux-amd64.tar.gz'

cloudify.nodes.helm.Repo

This node type responsible for adding repositories to Helm client using helm repo add command.

Properties

Runtime Properties

All above runtime properties created by cloudify.relationships.helm.run_on_host relationship.

Notes:

Example:

node_templates:

  repo:
    type: cloudify.nodes.helm.Repo
    properties:
      resource_config:
        name: { get_input: repo_name }
        repo_url: { get_input: repo_url }
    relationships:
      - target: helm_install
        type: cloudify.helm.relationships.run_on_host

cloudify.nodes.helm.Release

This node type responsible for create release on Kubernetes cluster.

In this note type client_config.configuration is required in order to interact with Kubernetes Cluster.

Properties

required: False

Currently contains executable_path with default value of “.

It’s not recommended use this property, by default Helm plugin will extract the executable to the deployment directory which safe to use.

Contains:

      
- name: namespace
  value: my_namespace

Equals to --set namespace=my_namespace in helm command.

Runtime Properties

All above runtime properties created by cloudify.relationships.helm.run_on_host relationship.

Notes:

Way to pass more flags to start and delete is to add interface inputs, like :

    interfaces:
      cloudify.interfaces.lifecycle:
        start:
          implementation: helm.cloudify_helm.tasks.install_release
          inputs:
            flags:
              - name: debug

Example:

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          file_content: {get_secret: kube_config }
      resource_config:
        name: "myrelease"
        chart: { concat: [ { get_input: repo_name },'/', { get_input: chart_name } ] }
    relationships:
      - target: helm_install
        type: cloudify.helm.relationships.run_on_host
      - target: repo
        type: cloudify.relationships.depends_on

Relationships

cloudify.relationships.helm.run_on_host relationship:

This relationship job is to inject helm environment variables locations to runtime properties of release/repo nodes. Target node is cloudify.nodes.helm.Binary which creates temporary environment for each binary.

The relationship is derived from the cloudify.relationships.connected_to relationship type.

Every Release/Repo node in the blueprint need to use this relationship in order to interact with helm client!.

Example:

node_templates:

  helm_install:
    type: cloudify.nodes.helm.Binary
    properties:
      use_existing_resource: false
      installation_source: { get_input: helm_installation_source }

  repo:
    type: cloudify.nodes.helm.Repo
    properties:
      resource_config:
        name: { get_input: repo_name }
        repo_url: { get_input: repo_url }
    relationships:
      - target: helm_install
        type: cloudify.helm.relationships.run_on_host

Workflows

update_repositories workflow

This workflow provides the ability to update all the repositories for a Helm client.

Parameters:

Example of using update_repositories workflow

Assuming the repository node type is :

node_templates:

  bitnami_repo:
    type: cloudify.nodes.helm.Repo
    properties:
      resource_config:
        name: bitnami
        repo_url: https://charts.bitnami.com/bitnami
    relationships:
      - target: helm_install
        type: cloudify.helm.relationships.run_on_host

update_repositories can triggered this way:

cfy executions start update_repositories -d <deployment_name> -p node_instance_id=bitnami_repo_rnudof -p ./inputs.yaml

Where inputs.yaml contains flags parameter:

flags:
  - name: debug

upgrade_release workflow

This workflow provides the ability to upgrade Helm release created with Helm plugin.

Parameters:

required: true

required: true

      
    - name: x 
      value: y
    - name: a
      value: b

Equals adding --set x=y --set a=b to helm command.

Example of using upgrade_release workflow

Assuming the release node type is :

node_templates:

  release:
    type: cloudify.nodes.helm.Release
    properties:
      client_config:
        configuration:
          file_content: {get_secret: kube_config }
        authentication:
          gcp_service_account: { get_secret: gcp_credentials }
      resource_config:
        name: "myrelease"
        chart: bitnami/postgresql
    relationships:
      - target: helm_install
        type: cloudify.helm.relationships.run_on_host
      - target: repo
        type: cloudify.relationships.depends_on

upgrade_release can triggered this way:

cfy executions start upgrade_release -d release-upgrade-test -p node_instance_id=release_8uwvap -p ./inputs.yaml

Where inputs.yaml contains:

chart: /tmp/postgresql-10.2.0.tgz
set_values:
  - name: postgresqlPassword
    value: Passwordforpostgress
    

Where postgresql-10.2.0.tgz is a packaged chart.

Notes:

General Notes:

  1. By chart reference: helm install mymaria example/mariadb.

  2. By a path to a packaged chart: helm install mynginx ./nginx-1.2.3.tgz

  3. By path to an unpacked chart directory: helm install mynginx ./nginx

  4. By absolute URL: helm install mynginx https://example.com/charts/nginx-1.2.3.tgz

  5. By chart reference and repo URL: helm install – repo https://example.com/charts/ mynginx nginx

Currently, the plugin support only the first option.