Kubernetes (“K8s”) provides a flexible architecture for cloud-native applications at scale. We believe that Juju is the simplest way to manage multi-container workloads on K8s. This guide takes you through the registration steps necessary to connect the two systems.
What is Juju?: Juju is the simplest DevOps tool for managing digital services built with inter-related applications. If you are unfamiliar with Juju, then we recommend following our Getting Started with Juju tutorial.
Need a Kubernetes cluster for experimentation?: Install MicroK8s to create a local Kubernetes cluster with zero effort.
Running Kubernetes workloads
To run workloads on Kubernetes with Juju, a small number of registration steps are required:
- Obtain a Kubernetes cluster
- Register the cluster with Juju
- Create a Juju controller
- Register storage resources
You’re now ready to deploy cloud-native workloads with charms:
- Add a model
- Deploy workloads
Obtain a Kubernetes cluster
There are many ways to obtain a Kubernetes cluster. If you are unsure which option to choose, then you should install MicroK8s.
Use Case | Recommended Action(s) |
---|---|
Local development, testing and experimentation | Install MicroK8s |
Multi-node testing/production on a private cloud | Install Charmed Kubernetes |
Multi-node testing/production on the public cloud | Install Charmed Kubernetes with the relevant integrator charm |
Use a hosted Kubernetes distribution | Enable the service via the provider |
Alternative Kubernetes Options
Juju can work with other Kubernetes clusters in addition to those listed above, but there will likely be a little extra setup required to allow Juju to talk to services created in the cluster (such services include the Juju controller created at bootstrap). Ongoing investigation is taking place to automate these actions depending on the Kubernetes cluster used.
In the absence of anything else, service ingress can be achieved by configuring services as type “load balancer”. Juju does this automatically for supported clusters where load balancer services are known to be enabled. See Create a Juju controller below for available options.
Minikube
To use Juju with Minikube, you need to enable tunnelling to connect to the load balancer.
In a separate terminal:
minikube tunnel
and then follow the cluster registration steps below:
juju add-k8s minikube
juju bootstrap --config controller-service-type=loadbalancer minikube
Register the Kubernetes cluster with Juju
Registering the cluster with Juju is known as “adding a cloud” in Juju’s terminology. A cloud is a deployment target. The exact process to register the cluster depends on how your system is configured.
When running MicroK8s
The cluster is registered with Juju automatically, but we have to enable some addons.
microk8s enable storage dns
Then move on to Create a Juju controller.
When you’re already able to interact with your cluster via kubectl
The registration process is a single command:
juju add-k8s
When you have used Juju to deploy Charmed Kubernetes
We can use Juju to extract its configuration file to save it locally with these commands:
mkdir ~/.kube
juju scp kubernetes-master/0:/home/ubuntu/config ~/.kube/config
juju add-k8s
Otherwise
Copy the cluster’s configuration file from the master node to your local machine and save it as $HOME/.kube/config
, then run
juju add-k8s
Create a Juju controller
The Juju controller is a central software agent that oversees applications managed with Juju. It is created via the juju bootstrap
command.
juju bootstrap <cloud-name> <controller-name>
There are 3 important bootstrap config options that may be needed, depending on how the Kubernetes cluster has been configured to provision services requiring ingress. These options are shown when running the following:
juju help bootstrap
Usage: juju bootstrap [options] [<cloud name>[/region] [<controller name>]]
Summary:
Initializes a cloud environment.
...
controller-external-ips:
type: string
description: Specifies a comma separated list of external IPs for a k8s controller
of type external
controller-external-name:
type: string
description: Sets the external name for a k8s controller of type external
controller-service-type:
type: string
description: Controls the kubernetes service type for Juju controllers, see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#servicespec-v1-core
valid values are one of cluster, loadbalancer, external
...
In many cases, a Kubernetes cluster will have been configured by the cluster admin to provision load balancer services, so the only additional option needed for bootstrap is as follows:
juju bootstrap myk8s --config controller-service-type=loadbalancer
The out-of-the-box supported Kubernetes clusters mentioned at the start of this page do not require any additional configuration for most cases.
Register storage resources
When an application that you wish to deploy - a “workload” in Juju terms - makes uses of persistent storage, you may need to ensure that an appropriate storage pool has been added to your Kubernetes cluster.
Juju will initially have a storage pool called “kubernetes”.
Charmed Kubernetes users can use Juju to provide it with storage based on Ceph or NFS.
The create-storage-pool
command can be used to add new storage pools. For example:
juju create-storage-pool my-new-pool kubernetes storage-class=microk8s-hostpath
See Persistent storage and Kubernetes for more detail.
Add a model
Before deploying applications with charms, Juju users create a “model”. The model is a workspace for inter-related applications. It is an abstraction over applications, machines hosting them and other components such as persistent storage.
To add a model, use the juju add-model
command:
juju add-model <k8s-cloud-name>
Inside the cluster, adding a Juju model creates a Kubernetes namespace with the same name. The namespace hosts all of the pods and other resources, except global resources.
Deploy a Kubernetes charm
A Kubernetes-specific charm is deployed in standard fashion, with the deploy
command. If the charm has storage requirements you will need to specify them, as you do with a normal charm.
Configuration
The below table lists configuration keys supported by Kubernetes charms that are set at deploy time. The corresponding Kubernetes meaning can be obtained from the Kubernetes documentation for Services and Ingress.
Key | Type | Default |
---|---|---|
kubernetes-service-type |
string | ClusterIP |
kubernetes-service-external-ips |
string | [] |
kubernetes-service-target-port |
string | <container port> |
kubernetes-service-loadbalancer-ip |
string | "" |
kubernetes-service-loadbalancer-sourceranges |
string | "[]" |
kubernetes-service-externalname |
string | "" |
kubernetes-ingress-class |
string | nginx |
kubernetes-ingress-ssl-redirect |
boolean | false |
kubernetes-ingress-ssl-passthrough |
boolean | false |
kubernetes-ingress-allow-http |
boolean | false |
For example:
juju deploy cs:~charmed-osm/mariadb-k8s \
--config kubernetes-service-loadbalancer-ip=10.1.1.1 \
--storage database=100M,kubernetes
There are two other keys that are not Kubernetes-specific:
Key | Type | Default |
---|---|---|
juju-external-hostname |
string | "" |
juju-application-path |
string | "/" |
Keys ‘juju-external-hostname’ and ‘juju-application-path’ control how the application is exposed externally using a Kubernetes Ingress Resource in conjunction with the configured ingress controller (default: nginx).
Workload images
When the charm is deployed, Juju does not download the actual OCI image. It fetches the image metadata which is stored as a charm resource; this info is used to set up the Kubernetes pod spec image metadata; it’s Kubernetes which actually pulls the image from the specified registry path. Public images do not use a username or password.
For dev/test, you may want to use a different image to the one published with the charm. And for local charms, there is no published image so the follow applies in that case also. You deploy the charm and use the --resource
argument to specify the image path, eg
juju deploy cs:~charmed-osm/mariadb-k8s --resource mysql_image=mariadb:latest
juju deploy /path/to/mariadb-k8s --resource mysql_image=mariadb:latest
When upgrading a charm, --resource
can also be used to specify a different workload image, eg
juju upgrade-charm mariadb-k8s --resource mysql_image=mariadb:9.0
Tutorials and in-depth guides
The following practical guides are available:
- Tutorial Setting up static Kubernetes storage shows how to set up statically provisioned persistent volumes with Juju by way of the ‘kubernetes-core’ charm.
- Tutorial Multi-cloud controller with GKE and auto-configured storage provides steps on how to add an existing GKE-based Kubernetes cluster to an existing controller. It also covers storage auto-configuration.
- Tutorial Installing Kubernetes with CDK and using auto-configured storage shows how to install Kubernetes with the CDK bundle and illustrates storage class and storage pool auto-configuration.
- Tutorial Using Juju with MicroK8s provides steps for getting started with Juju and MicroK8s.
- Tutorial Using Juju on Charmed Kubernetes on VMWare provides the steps for getting started with Juju on a Kubernetes cluster on VMWare.
- Tutorial Using the aws-integrator charm demonstrates deploying Kubernetes with Juju on AWS with an integrator charm.