<a id="cloud-kubernetes-microk8s"></a>

# MicroK8s

In Juju, [MicroK8s](https://canonical.com/microk8s) is a [Kubernetes cloud](https://documentation.ubuntu.com/juju/3.6/reference/cloud.md#kubernetes-cloud) and works as described below.

#### NOTE
This reference assumes basic familiarity with Juju. If you are new to Juju, start with the [Tutorial](https://documentation.ubuntu.com/juju/3.6/tutorial.md#tutorial), then use this page together with the generic materials it links to.

<a id="microk8s-requirements"></a>

## Requirements

**Services that must be enabled:**

- `dns`
- `hostpath-storage`

## Concepts

If you are familiar with Kubernetes, the following maps Kubernetes concepts to their Juju equivalents:

| Kubernetes                                                                                 | Juju                                                                                                       |
|--------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|
| [namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) | [model](https://documentation.ubuntu.com/juju/3.6/reference/model.md#model)                                                 |
| [node](https://kubernetes.io/docs/concepts/architecture/nodes/)                            | [machine](https://documentation.ubuntu.com/juju/3.6/reference/machine.md#machine) (on Kubernetes clouds, not managed by Juju) |
| [pod](https://kubernetes.io/docs/concepts/workloads/pods/)                                 | [unit](https://documentation.ubuntu.com/juju/3.6/reference/unit.md#unit)                                                   |
| container                                                                                  | process in a unit                                                                                          |
| [service](https://kubernetes.io/docs/concepts/services-networking/service/)                | [application](https://documentation.ubuntu.com/juju/3.6/reference/application.md#application)                                     |

## The cloud

See also: [Cloud](https://documentation.ubuntu.com/juju/3.6/reference/cloud.md#cloud), [Juju | Manage clouds](https://documentation.ubuntu.com/juju/3.6/howto/manage-clouds.md#manage-clouds), [Juju | Add a Kubernetes cloud](https://documentation.ubuntu.com/juju/3.6/howto/manage-clouds.md#add-a-kubernetes-cloud), [Terraform Provider for Juju | Manage clouds](https://canonical.com/juju/docs/terraform-provider-juju/latest/howto/manage-clouds/#manage-clouds)

As for all Kubernetes clouds, the cloud is registered in Juju via a cloud definition, stored in `clouds.yaml` on the client and following this schema.

#### TIP
If using the Juju CLI, you can skip writing this file manually – `juju add-k8s` can read `kubeconfig` and create the cloud definition for you.

```yaml
clouds:
  <cloud-name>:                    # User-defined name for the cluster
    type: kubernetes               # Always 'kubernetes' for Kubernetes clouds
    auth-types:                    # Authentication types
      - clientcertificate          # or: oauth2, userpass (legacy compatibility only: certificate, oauth2withcert)
    endpoint: <endpoint>           # Kubernetes API server URL
    host-cloud-region: <cloud>/<region>  # Optional: host cloud for the cluster (e.g., ec2/us-west-2)
    regions:                       # Optional: define regions
      <region-name>:
        endpoint: <endpoint>       # Region-specific endpoint (if different)
    config:                        # Optional: model config defaults
      operator-storage: <class>    # Storage class for operator storage
      workload-storage: <class>    # Storage class for workload storage
    ca-certificates:               # Optional: cluster CA certificates
      - <base64-cert>              # Base64-encoded x.509 certificates
```

<a id="microk8s-cloud-adding"></a>

### Adding the cloud

For a localhost MicroK8s cloud, if you would like to be able to skip `juju add-k8s`, install MicroK8s from the strictly confined snap.

See more: [MicroK8s | Strict MicroK8s](https://microk8s.io/docs/install-strict)

## Credentials

See also: [Credential](https://documentation.ubuntu.com/juju/3.6/reference/credential.md#credential), [Juju | Manage credentials](https://documentation.ubuntu.com/juju/3.6/howto/manage-credentials.md#manage-credentials), [Terraform Provider for Juju | Manage credentials](https://canonical.com/juju/docs/terraform-provider-juju/latest/howto/manage-credentials/#manage-credentials)

As for all Kubernetes clouds, credentials are stored in `credentials.yaml` on the client and follow this schema.

#### TIP
If using the Juju CLI, you can skip writing this file manually – `juju add-k8s` can read `kubeconfig` and create the matching credential entry for the selected context.

```yaml
credentials:
  <cloud-name>:
    <credential-name>:
      auth-type: <auth-type>          # clientcertificate | oauth2 | userpass
      <auth-attributes>               # fill using one of the mappings below
```

### Authentication types

As for all Kubernetes clouds, the supported authentication types are:

#### `clientcertificate`

Kubernetes client certificate and key.

- `ClientCertificateData`: The Kubernetes certificate data (required).
- `ClientKeyData`: The Kubernetes certificate key (required).
- `rbac-id`: The unique ID key name of the RBAC resources (optional).

#### `oauth2`

OAuth2 token authentication.

- `Token`: The Kubernetes token (required).
- `rbac-id`: The unique ID key name of the RBAC resources (optional).

#### `userpass`

Username and password authentication.

- `username`: The username to authenticate with (required).
- `password`: The password for the specified username (required).

#### `certificate` (legacy)

Kubernetes service account token with certificate.

- `ClientCertificateData`: The Kubernetes certificate data (required).
- `Token`: The Kubernetes service account bearer token (required).
- `rbac-id`: The unique ID key name of the RBAC resources (optional).

#### `oauth2withcert` (legacy)

OAuth2 token with certificate.

- `ClientCertificateData`: The Kubernetes certificate data (required).
- `ClientKeyData`: The Kubernetes private key data (required).
- `Token`: The Kubernetes token (required).

## Controllers

See also: [Controller](https://documentation.ubuntu.com/juju/3.6/reference/controller.md#controller), [Juju | Manage controllers](https://documentation.ubuntu.com/juju/3.6/howto/manage-controllers.md#manage-controllers), [Terraform Provider for Juju | Manage controllers](https://canonical.com/juju/docs/terraform-provider-juju/latest/howto/manage-controllers/#manage-controllers)

As for all Kubernetes clouds, bootstrapping a controller creates the following resources in the cluster.

<a id="kubernetes-bootstrap-behavior"></a>

When bootstrapping a controller on a Kubernetes cloud, Juju creates a namespace for the controller and deploys the controller as a `StatefulSet` with associated resources. The controller manages the Juju state database (MongoDB) and API server within Kubernetes pods.

<a id="kubernetes-resources-created-at-bootstrap"></a>

Resources created at bootstrap:

- **`Namespace`**: A dedicated namespace for the controller (named `controller-<controller-name>`).
- **`Service`**: A Kubernetes `Service` to expose the controller API (type depends on the cloud: `LoadBalancer` for public clouds, `ClusterIP` for localhost clouds).
- **`ServiceAccount`**: A service account for the controller with cluster-admin privileges.
- **`ClusterRoleBinding`**: Binds the controller service account to the cluster-admin `ClusterRole`.
- **`StatefulSet`**: A `StatefulSet` with the controller pod containing two containers: `mongodb` (Juju’s state database) and `api-server` (Juju API server).
- **`Secret`s**: Multiple secrets for TLS certificates (`server.pem`), shared secrets, and optionally docker registry credentials for private image registries.
- **`ConfigMap`s**: Configuration maps for bootstrap parameters and agent configuration.
- **`PersistentVolume`** and **`PersistentVolumeClaim`**: Storage for the controller’s operator-storage (MongoDB data and API server state).
- **Proxy resources** (if using `ClusterIP` `Service`): Additional `ConfigMap`, `Role`, `RoleBinding`, and `ServiceAccount` for cluster IP proxy access.

As for all Kubernetes clouds, the controller service type depends on the host platform.

When bootstrapping a controller, Juju creates a Kubernetes `Service` to expose the controller API. The `Service` type depends on the host cloud platform where the Kubernetes cluster is running:

- **`LoadBalancer`**: For managed Kubernetes on public clouds.
  - Amazon EKS (on EC2)
  - Google GKE (on GCE)
  - Microsoft AKS (on Azure)
  - Charmed Kubernetes on OpenStack
  - Charmed Kubernetes on MAAS (experimental)
- **`ClusterIP`**: For localhost and development environments.
  - MicroK8s
  - Kubernetes on LXD
  - Other/unrecognized host clouds (default)

#### NOTE
`LoadBalancer` creates a cloud load balancer with a public IP, while `ClusterIP` uses internal cluster networking with optional proxy access.

## Models

As for all Kubernetes clouds, the following [cloud-specific model configuration keys](https://documentation.ubuntu.com/juju/3.6/reference/configuration/list-of-model-configuration-keys.md#model-config-cloud-specific-key) are supported:

**Storage**

<a id="kubernetes-model-config-operator-storage"></a>
- **`operator-storage`**: The storage class used to provision operator storage. Type: `string`. Default: `""` (uses cluster default storage class). Immutable.

<a id="kubernetes-model-config-workload-storage"></a>
- **`workload-storage`**: The preferred storage class used to provision workload storage. Type: `string`. Default: `""` (uses cluster default storage class).

See more: [<cloud-specific key>](https://documentation.ubuntu.com/juju/3.6/reference/configuration/list-of-model-configuration-keys.md#model-config-cloud-specific-key)

## Pods

See also: [Unit](https://documentation.ubuntu.com/juju/3.6/reference/unit.md#unit), [Juju | Manage units](https://documentation.ubuntu.com/juju/3.6/howto/manage-units.md#manage-units)

As for all Kubernetes clouds, the following constraints apply to pod resources and placement.

<a id="kubernetes-constraints"></a>

The following [constraints](https://documentation.ubuntu.com/juju/3.6/reference/constraint.md#constraint) apply to pod resources and placement behavior:

- [cpu-power](https://documentation.ubuntu.com/juju/3.6/reference/constraint.md#constraint-cpu-power). CPU resource request/limit for pods.
- [mem](https://documentation.ubuntu.com/juju/3.6/reference/constraint.md#constraint-mem). Memory resource request/limit for pods.
- [tags](https://documentation.ubuntu.com/juju/3.6/reference/constraint.md#constraint-tags). Used for pod affinity, anti-affinity, and node affinity rules.

Constraints like `arch`, `cores`, `instance-type`, `root-disk`, `zones`, and others are not supported on Kubernetes clouds. Kubernetes manages node resources and pod scheduling.

<a id="kubernetes-placement-directives"></a>

Placement directives are not supported on Kubernetes clouds. Pod placement is controlled by Kubernetes scheduling, node selectors, and affinity rules (configured via constraints).

As for all Kubernetes clouds, application pods follow these deployment patterns.

See also: [Unit](https://documentation.ubuntu.com/juju/3.6/reference/unit.md#unit), [Juju | Manage units](https://documentation.ubuntu.com/juju/3.6/howto/manage-units.md#manage-units)

<a id="kubernetes-resources-per-application"></a>

When deploying an application to a Kubernetes model, Juju creates:

- **`Deployment`, `StatefulSet`, or `DaemonSet`**: Depending on the charm specification and application type. `StatefulSet`s are used for applications requiring stable network identities and persistent storage. `Deployment`s are used for stateless applications. `DaemonSet`s run one pod per node.
- **Pod**: One or more pods containing the application’s charm containers. Each pod typically includes an init container (`juju-init`) and a main container (`juju-operator`).
- **`Service`**: A Kubernetes `Service` to expose the application within the cluster or externally.
- **`ConfigMap`**: Configuration data for the application.
- **`Secret`**: Sensitive data like credentials.
- **`PersistentVolume`** and **`PersistentVolumeClaim`**: If the charm requires storage, one PV/PVC per unit is created based on the configured storage class.

<a id="kubernetes-pod-deployment-patterns"></a>

Kubernetes application pods in Juju follow these patterns:

**Sidecar charms** (current pattern):

- **Init container** (`charm-init`): Prepares the pod environment before the main container starts.
- **Charm container** (`charm`): Runs the charm logic alongside the workload.
- **Workload containers**: Defined by the charm (e.g., database, web server).

**Operator charms** (older pattern):

- **Init container** (`juju-init`): Prepares the pod environment before the main container starts.
- **Operator container** (`juju-operator`): Runs the charm logic and manages the application lifecycle.
- **Workload containers**: Defined by the charm.

## Storage

See also: [Storage](https://documentation.ubuntu.com/juju/3.6/reference/storage.md#storage), [Juju | Manage storage](https://documentation.ubuntu.com/juju/3.6/howto/manage-storage.md#manage-storage); [Storage provider](https://documentation.ubuntu.com/juju/3.6/reference/storage.md#storage-provider)

### Storage providers

As for all Kubernetes clouds, in addition to the generic storage providers, this cloud also has access to the following [cloud-specific storage provider](https://documentation.ubuntu.com/juju/3.6/reference/storage.md#storage-provider-cloud-specific):

#### `kubernetes`

See also: [Persistent storage and Kubernetes](https://discourse.charmhub.io/t/topic/1078)

The `kubernetes` storage provider provisions storage using Kubernetes PersistentVolumeClaims (PVCs). The underlying storage is provided by the cluster’s configured storage classes.

Configuration options:

- **`storage-class`**: The storage class for the Kubernetes cluster to use. It can be any storage class defined in your cluster, for example: `microk8s-hostpath`, `gp2`, `standard`, etc.
- **`storage-provisioner`**: The Kubernetes storage provisioner. For example: `kubernetes.io/no-provisioner`, `kubernetes.io/aws-ebs`, `kubernetes.io/gce-pd`, `microk8s.io/hostpath`, etc.
- **`parameters.type`**: Extra parameters passed to the storage provisioner. For example: `gp2`, `pd-standard`, etc.
