The helm
provisioner is one of the provisioners of RukPak.
It is able to instantiate a given helm+v3
bundle with a specified helm chart onto a cluster where it then installs the content. It does so by reconciling Bundle
and BundleDeployment
types that have
the spec.provisionerClassName
field set to core-rukpak-io-helm
. This field must be set to the correct provisioner
name in order for the helm
provisioner to see and interact with the bundle.
Supported source types for a helm bundle currently include the following:
- A container image
- A directory in a git repository
- A http
Additional source types, such as a local volume are on the roadmap. These source types all present the same content, a directory containing a helm chart, in a different ways.
⚠️ Anyone with the ability to create or update BundleDeployment objects can become a cluster admin. It's important to limit access to this API via RBAC to only those that explicitly require access, as well as audit your bundles to ensure the content being installed on-cluster is as-expected and secure.
The helm
provisioner can install and make available a specific helm+v3
bundle in the cluster. To do this, the helm
provisioner will retrieve the configured helm chart, instantiate a Bundle onto the cluster, and eventually install the desired helm chart on the cluster.
apiVersion: core.rukpak.io/v1alpha1
kind: BundleDeployment
metadata:
name: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
config:
values: |
# Default values for hello-world.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
nameOverride: "formvalues"
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
service:
type: ClusterIP
port: 80
template:
metadata:
labels:
app: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
source:
http:
url: https://github.com/helm/examples/releases/download/hello-world-0.1.0/hello-world-0.1.0.tgz
type: http
For the helm chart, the values file embedded in the config
can be applied during the installation of the chart.
Note: the generated Bundle will contain the BundleDeployment's metadata.Name as a prefix, followed by the hash of the provided template.
As the bundle content is retrieved and stored onto the cluster via the defined storage mechanism, the bundle status will be updated to Unpacked, indicating that all its contents have been stored on-cluster.
$ kubectl get bundle -l app=my-ahoy
NAME TYPE PHASE AGE
my-ahoy-5764594dc8 http Unpacked 33s
Now that the bundle has been unpacked, the provisioner is able to create the resources in the bundle on the cluster. These resources will be owned by the corresponding BundleDeployment. Creating the BundleDeployment on-cluster results in an InstallationSucceeded Phase if the application of resources to the cluster was successful.
$ kubectl get bundledeployment my-ahoy
NAME ACTIVE BUNDLE INSTALL STATE AGE
my-ahoy my-ahoy-5764594dc8 InstallationSucceeded 48s
Note: Creation of more than one BundleDeployment from the same Bundle will likely result in an error.
Fork https://github.com/helm/examples
github repository into any origanization that you have write access.
Set a YOUR_ORG environment variable for convenience.
export YOUR_ORG="your goranization name"
Edit https://github.com/$YOUR_ORG/examples/blob/main/charts/hello-world/Chart.yaml
and update version: 0.1.0
to version: 0.1.1
and
commit the change into v0.1.1
branch.
To experiment with the helm
provisioner locally, take the following steps to
create a local kind cluster and deploy the provisioner onto it:
# Clone the repository
git clone https://github.com/operator-framework/rukpak
# Navigate to the repository
cd rukpak
# Start a local kind cluster then build and deploy the provisioner onto it
make run
From there, create some Bundles and BundleDeployment types to see the provisioner in action. For an example helm chart to use, the helm/examples is a good example.
Create the sample BundleDeployment referencing the desired sample helm chart in Bundle configuration:
kubectl apply -f -<<EOF
apiVersion: core.rukpak.io/v1alpha1
kind: BundleDeployment
metadata:
name: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
template:
metadata:
labels:
app: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
source:
http:
git:
ref:
branch: main
repository: https://github.com/akihikokuroda/examples
directory: ./charts
type: git
EOF
A message saying that the BundleDeployment is created should be returned:
$ kubectl apply -f -<<EOF
...
EOF
bundledeployment.core.rukpak.io/my-ahoy created
Next, check the Bundle status via:
kubectl get bundle -l app=my-ahoy
Eventually the Bundle should show up as Unpacked:
$ kubectl get bundle -l app=my-ahoy
NAME TYPE PHASE AGE
my-ahoy-5764594dc8 git Unpacked 33s
Check the BundleDeployment status to ensure that the installation was successful:
kubectl get bundledeployment my-ahoy
A successful installation will show InstallationSucceeded as the INSTALL STATE
:
$ kubectl get bundledeployment my-ahoy
NAME ACTIVE BUNDLE INSTALL STATE AGE
my-ahoy my-ahoy-5764594dc8 InstallationSucceeded 48s
From there, ensure that the helm chart is installed and the operator is present on the cluster:
# Check the installed helm chart
helm list
# Check the my-ahoy deployment
kubectl get deployments.apps my-ahoy-hello-world
# Check that the operator is present
kubectl get deployments.apps my-ahoy-hello-world -o yaml | grep 'image:' | xargs
The deployment should show ready and available:
$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-ahoy rukpak-system 1 2022-08-27 22:08:23.310271084 +0000 UTC deployed hello-world-0.1.0 1.16.0
$ kubectl get deployments.apps my-ahoy-hello-world
NAME READY UP-TO-DATE AVAILABLE AGE
my-ahoy-hello-world 1/1 1 1 102s
$ kubectl get deployments.apps my-ahoy-hello-world -o yaml | grep 'image:' | xargs
- image: nginx:1.16.0
This means the operator should be successfully installed.
Delete BundleDeployment for the next step
kubectl delete bundledeployment my-ahoy
bundledeployment.core.rukpak.io "my-ahoy" deleted
Add a values file into the BundleDeployment to override some default values:
kubectl apply -f -<<EOF
apiVersion: core.rukpak.io/v1alpha1
kind: BundleDeployment
metadata:
name: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
config:
values: |
# Default values for hello-world.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
nameOverride: "fromvalues"
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
service:
type: ClusterIP
port: 80
template:
metadata:
labels:
app: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
source:
git:
ref:
branch: main
repository: https://github.com/akihikokuroda/examples
directory: ./charts
type: git
EOF
This values file is updating the nameOverride
bundledeployment.core.rukpak.io/my-ahoy created
Check the name of the deployment:
kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
core 1/1 1 1 20h
helm-provisioner 1/1 1 1 20h
my-ahoy-fromvalues 1/1 1 1 36s
rukpak-webhooks 1/1 1 1 20h
The name of the deployment is my-ahoy-fromvalues
now
Change this a value in the values file. Update the nameOverride
to name1
kubectl apply -f -<<EOF
apiVersion: core.rukpak.io/v1alpha1
kind: BundleDeployment
metadata:
name: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
config:
values: |
# Default values for hello-world.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
nameOverride: "name1"
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
service:
type: ClusterIP
port: 80
template:
metadata:
labels:
app: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
source:
git:
ref:
branch: main
repository: https://github.com/akihikokuroda/examples
directory: ./charts
type: git
EOF
bundledeployment.core.rukpak.io/my-ahoy configured
Check the name of the deployment
kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
core 1/1 1 1 20h
helm-provisioner 1/1 1 1 20h
my-ahoy-name1 1/1 1 1 56s
rukpak-webhooks 1/1 1 1 20h
Now the name of the deployment is my-ahoy-name1
Check the helm chart version install now
# Check the installed helm chart
helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-ahoy rukpak-system 2 2022-08-27 22:14:50.56889877 +0000 UTC deployed hello-world-0.1.0 1.16.0
Now the helm chart version is hello-world-0.1.0
. Change the git branch to v0.1.1
from main
kubectl apply -f -<<EOF
apiVersion: core.rukpak.io/v1alpha1
kind: BundleDeployment
metadata:
name: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
config:
values: |
# Default values for hello-world.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
nameOverride: "name1"
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
service:
type: ClusterIP
port: 80
template:
metadata:
labels:
app: my-ahoy
spec:
provisionerClassName: core-rukpak-io-helm
source:
git:
ref:
branch: v0.1.1
repository: https://github.com/akihikokuroda/examples
directory: ./charts
type: git
EOF
bundledeployment.core.rukpak.io/my-ahoy configured
Check the helm chart version, again
# Check the installed helm chart
helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-ahoy rukpak-system 3 2022-08-27 22:12:51.056782394 +0000 UTC deployed hello-world-0.1.1 1.16.0
Now the helm chart version is hello-world-0.1.1
.
The helm
provisioner continually reconciles BundleDeployment resources. Next, let's try deleting the my-ahoy-name1 deployment:
kubectl delete deployments.apps my-ahoy-name1
A message saying the deployment was deleted should be returned:
deployment.apps "my-ahoy-name1" deleted
The provisioner ensures that all resources required for the BundleDeployment to run are accounted for on-cluster. So if we check for the deployment again, it will be back on the cluster:
NAME READY UP-TO-DATE AVAILABLE AGE
my-ahoy-name1 1/1 1 1 7s
To clean up from the installation, simply remove the BundleDeployment from the cluster. This will remove all references resources including the deployment, RBAC, and the operator namespace.
Note: There's no need to manually clean up the Bundles that were generated from a BundleDeployment resource. The plain provisioner places owner references on any Bundle that's generated from an individual BundleDeployment resource.
# Delete the combo BundleDeployment
kubectl delete bundledeployments.core.rukpak.io my-ahoy
A message should show that the BundleDeployment was deleted and now the cluster state is the same as it was prior to installing the operator.
$ kubectl delete bundledeployments.core.rukpak.io my-ahoy
bundledeployment.core.rukpak.io "my-ahoy" deleted
To stop and clean up the kind cluster, delete it:
# Clean up kind cluster
kind delete clusters rukpak