Skip to content

Managed Kubernetes

Frostmoln Managed Kubernetes runs clusters on Frostmoln compute. You manage your workloads; the platform provisions and manages the control plane, the worker nodes, the API load balancer, and your kubeconfig.

Pilot — access is granted per tenant

Managed Kubernetes is rolled out as a pilot. It appears in the portal only for tenants that have been granted the kubernetes entitlement — if you don't see Kubernetes in the navigation, it isn't enabled for your tenant yet. Contact support to request access (there is no self-service enablement during the pilot).

Create a cluster

In the portal, go to Kubernetes → Clusters → Create and choose:

  • Name.
  • Kubernetes version — currently 1.34 or 1.35 (the recommended version is marked); the dropdown is the source of truth.
  • Control-plane tier:
    • Standard (development) — one dedicated control-plane node.
    • Production (production) — three dedicated control-plane nodes (HA quorum), production SLA.
  • VPC + subnet the cluster runs in (the region is inherited from the VPC).
  • An initial node pool — a name, a node flavor (k8s.gp1.small / k8s.gp1.medium / k8s.gp1.large), and a node count.

There is no ingress option at create time. How your own traffic reaches your workloads is decided inside the cluster, afterwards — see Reaching your workloads.

CLI & Terraform

Managed Kubernetes is managed from the portal, with the fm CLI, or with Terraform. The CLI has a full fm kubernetes command group — clusters, node pools, and the flavor / tier / version / addon catalogs; see the fm kubernetes reference. In Terraform, use frostmoln_kubernetes_cluster (with its initial node pool and cluster addons), frostmoln_kubernetes_node_pool for additional pools, and the frostmoln_kubernetes_versions / _tiers / _flavors / _addons catalog data sources — see the Terraform reference. Once you have a kubeconfig you use kubectl, Helm, and your normal Kubernetes tooling against the cluster as usual.

Get your kubeconfig

When the cluster is running, use Download Kubeconfig on the cluster detail page. Point kubectl at it and you're in:

bash
export KUBECONFIG=~/Downloads/my-cluster-kubeconfig.yaml
kubectl get nodes

The Kubernetes API server is reached through a dedicated load-balanced endpoint (port 6443). The cluster's credentials are generated and held securely by the platform — node bootstrapping never transmits secrets back.

The cluster endpoint is not for your traffic. It is for kubectl, Helm and your CI. Your own traffic goes to the address of a load balancer you ask for from inside the cluster — see Reaching your workloads. Pointing an application's DNS record at the cluster endpoint is the mistake this distinction exists to prevent.

Reaching your workloads

A cluster comes with no load balancer for your own traffic. You get one the standard Kubernetes way: create a Service of type: LoadBalancer, and the platform provisions a load balancer for that Service, keeps your Pods wired in as its members, and writes the address back into the Service.

yaml
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
    - name: https
      port: 443
      targetPort: 8443
bash
kubectl get service web --watch
# NAME   TYPE           EXTERNAL-IP   PORT(S)
# web    LoadBalancer   10.20.4.17    443:31274/TCP

The address that appears as EXTERNAL-IP is the one to point your DNS at.

An ingress controller works the same way. Install the one you prefer (Traefik, ingress-nginx, …) and expose it with a type: LoadBalancer Service rather than a NodePort one. There are no reserved node ports to pin any more: Kubernetes picks the node ports itself and you never need to know them. TLS terminates in your cluster, with your own certificates — the platform never holds your keys.

A few properties worth knowing:

  • Each such Service gets its own load balancer. It shows up in your normal load-balancer list and is billed as a load balancer, like any other.
  • Manage it from Kubernetes, not from the load-balancer API. The Service is what the load balancer is reconciled against: change its ports or selector and the load balancer follows.
  • Delete the Service and its load balancer goes with it. Remove your Services before you delete the cluster, so nothing is left behind.
  • The Kubernetes API endpoint is separate and is not one of these — it is provisioned by the platform, not by a Service of yours.

Internal addresses only today — no public entrypoint yet

A load balancer provisioned for a Service gets an internal address, from the cluster's own subnet: reachable from inside the VPC, not from the internet. A public address for such a Service is not built yet, so a cluster workload has no supported public entrypoint at the moment. If your workload has to be reachable from the internet, that is not something this cluster can do today.

The automatic worker ingress load balancer has been removed

Clusters used to be given an ingress load balancer at create time, forwarding TCP 80 and 443 to fixed node ports on every worker node, chosen with an ingressScheme option (ingress_scheme in Terraform) and an optional bring-your-own address. All of that is gone: there is no ingress setting when you create a cluster, and no fixed node ports to publish. Use a Service of type: LoadBalancer, as above.

The API endpoint's exposure is not a setting

There is no scheme option on a cluster. How the Kubernetes API endpoint is exposed is decided by the platform, not per cluster — sending scheme is rejected.

Node pools

A cluster has one or more node pools — groups of worker nodes of a given flavor. From the cluster detail page you can:

  • Add a node pool (name, flavor, node count), optionally with labels and taints for scheduling (labels and taints are portal-only for now — the Terraform resource does not support them yet).
  • Scale a pool by setting a new node count.
  • Delete a pool.

Scale manually for now

Cluster autoscaling is not yet available — set the node count explicitly and scale pools manually as your workload changes.

Persistent storage

Clusters ship with a Frostmoln CSI storage class, frostmoln-block (the default StorageClass), backed by Frostmoln block storage. Create a PersistentVolumeClaim and a volume is provisioned and attached automatically; volumes support online expansion.

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes: ['ReadWriteOnce']
  storageClassName: frostmoln-block
  resources:
    requests:
      storage: 20Gi

Networking

The cluster CNI is Cilium. Cluster nodes reach the internet only if the cluster's VPC has a Gateway — without one the nodes have no outbound access, no DNS resolution and no managed-service connectivity, so add a Gateway to the VPC yourself if they need any of that. Creating a cluster never adds one for you. The nodes are isolated from Frostmoln's internal networks either way — your workloads run in their own tenant network. Reach the API server through the cluster endpoint above, and expose your own services with a Service of type: LoadBalancer (see Reaching your workloads).

Limits

  • One zone per cluster — nodes are placed in the cluster's region/subnet; no multi-AZ spread today.
  • Cilium is the only CNI — it isn't customer-selectable.
  • No in-place version upgrades yet — choose your version at create time.
  • Autoscaling is not yet available (scale node pools manually).
  • No public address for a workload load balancer yet — a load balancer provisioned for a Service of type: LoadBalancer is internal to the VPC.
  • Deleting a cluster removes its nodes, its API load balancer and its stored credentials.