Install locally on kind

Self-managed Materialize requires: a Kubernetes (v1.29+) cluster; PostgreSQL as a metadata database; and blob storage.

The following tutorial uses a local kind cluster and deploys the following components:

  • Materialize Operator using Helm into your local kind cluster.
  • MinIO object storage as the blob storage for your Materialize.
  • PostgreSQL database as the metadata database for your Materialize.
  • Materialize as a containerized application into your local kind cluster.
! Important:

This tutorial is for local evaluation/testing purposes only.

  • The tutorial uses sample configuration files that are for evaluation/testing purposes only.
  • The tutorial uses a Kubernetes metrics server with TLS disabled. In practice, refer to your organization’s official security practices.

Prerequisites

kind

Install kind.

Docker

Install Docker.

Docker resource requirements

For this local deployment, you will need the following Docker resource requirements:

  • 3 CPUs
  • 10GB memory

Helm 3.2.0+

If you don’t have Helm version 3.2.0+ installed, install. For details, see the Helm documentation.

kubectl

This tutorial uses kubectl. To install, refer to the kubectl documentationq.

For help with kubectl commands, see kubectl Quick reference.

Installation

  1. Start Docker if it is not already running.

    For this local deployment, you will need the following Docker resource requirements:

    • 3 CPUs
    • 10GB memory
  2. Open a Terminal window.

  3. Create a working directory and go to the directory.

    mkdir my-local-mz
    cd my-local-mz
    
  4. Create a kind cluster.

    kind create cluster
    
  5. Add labels materialize.cloud/disk=true and workload=materialize-instance to the kind node (in this example, the kind-control-plane node).

    kubectl label node kind-control-plane materialize.cloud/disk=true
    kubectl label node kind-control-plane workload=materialize-instance
    

    Verify that the labels were successfully applied by running the following command:

    kubectl get nodes --show-labels
    
  6. To help you get started for local evaluation/testing, Materialize provides some sample configuration files. Download the sample configuration files from the Materialize repo:

    mz_version=v0.130.4
    
    curl -o sample-values.yaml https://raw.githubusercontent.com/MaterializeInc/materialize/refs/tags/$mz_version/misc/helm-charts/operator/values.yaml
    curl -o sample-postgres.yaml https://raw.githubusercontent.com/MaterializeInc/materialize/refs/tags/$mz_version/misc/helm-charts/testing/postgres.yaml
    curl -o sample-minio.yaml https://raw.githubusercontent.com/MaterializeInc/materialize/refs/tags/$mz_version/misc/helm-charts/testing/minio.yaml
    curl -o sample-materialize.yaml https://raw.githubusercontent.com/MaterializeInc/materialize/refs/tags/$mz_version/misc/helm-charts/testing/materialize.yaml
    
    • sample-values.yaml: Used to configure the Materialize Operator.
    • sample-postgres.yaml: Used to configure PostgreSQL as the metadata database.
    • sample-minio.yaml: Used to configure minIO as the blob storage.
    • sample-materialize.yaml: Used to configure Materialize instance.

    These configuration files are for local evaluation/testing purposes only and not intended for production use.

  7. Install the Materialize Helm chart.

    1. Add the Materialize Helm chart repository.

      helm repo add materialize https://materializeinc.github.io/materialize
      
    2. Update the repository.

      helm repo update materialize
      
    3. Install the Materialize Operator. The operator will be installed in the materialize namespace.

      helm install my-materialize-operator materialize/materialize-operator \
          --namespace=materialize --create-namespace \
          --version v25.1.2 \
          --set observability.podMetrics.enabled=true \
          -f sample-values.yaml
      
    4. Verify the installation and check the status:

      kubectl get all -n materialize
      

      Wait for the components to be ready and in the Running state:

      NAME                                           READY   STATUS    RESTARTS   AGE
      pod/my-materialize-operator-6c4c7d6fc9-hbzvr   1/1     Running   0          16s
      
      NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
      deployment.apps/my-materialize-operator   1/1     1            1           16s
      
      NAME                                                 DESIRED   CURRENT         READY   AGE
      replicaset.apps/my-materialize-operator-6c4c7d6fc9   1         1               1       16s
      

      If you run into an error during deployment, refer to the Troubleshooting guide.

  8. Install PostgreSQL and minIO.

    1. Use the sample-postgres.yaml file to install PostgreSQL as the metadata database:

      kubectl apply -f sample-postgres.yaml
      
    2. Use the sample-minio.yaml file to install minIO as the blob storage:

      kubectl apply -f sample-minio.yaml
      
    3. Verify the installation and check the status:

      kubectl get all -n materialize
      

      Wait for the components to be ready and in the Running state:

      NAME                                           READY   STATUS     RESTARTS   AGE
      pod/minio-777db75dd4-zcl89                     1/1     Running    0          84s
      pod/my-materialize-operator-6c4c7d6fc9-hbzvr   1/1     Running    0          107s
      pod/postgres-55fbcd88bf-b4kdv                  1/1     Running    0          86s
      
      NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
      service/minio      ClusterIP   10.96.51.9     <none>        9000/TCP   84s
      service/postgres   ClusterIP   10.96.19.166   <none>        5432/TCP   86s
      
      NAME                                      READY   UP-TO-DATE    AVAILABLE   AGE
      deployment.apps/minio                     1/1     1             1           84s
      deployment.apps/my-materialize-operator   1/1     1             1           107s
      deployment.apps/postgres                  1/1     1             1           86s
      
      NAME                                                 DESIRED    CURRENT         READY   AGE
      replicaset.apps/minio-777db75dd4                     1          1               1       84s
      replicaset.apps/my-materialize-operator-6c4c7d6fc9   1          1               1       107s
      replicaset.apps/postgres-55fbcd88bf                  1          1               1       86s
      
  9. Install the metrics service to the kube-system namespace.

    1. Add the metrics server Helm repository.

      helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
      
    2. Update the repository.

      helm repo update metrics-server
      
    3. Install the metrics server to the kube-system namespace.

      ! Important: This tutorial is for local evaluation/testing purposes only. For simplicity, the tutorial uses a Kubernetes metrics server with TLS disabled. In practice, refer to your organization’s official security practices.
      helm install metrics-server metrics-server/metrics-server \
         --namespace kube-system \
         --set args="{--kubelet-insecure-tls,--kubelet-preferred-address-types=InternalIP\,Hostname\,ExternalIP}"
      

      You can verify the installation by running the following command:

      kubectl get pods -n kube-system -l app.kubernetes.io/instance=metrics-server
      

      Wait for the metrics-server pod to be ready and in the Running state:

      NAME                             READY   STATUS    RESTARTS   AGE
      metrics-server-89dfdc559-bq59m   1/1     Running   0          2m6s
      
  10. Install Materialize into a new materialize-environment namespace:

    1. Use the sample-materialize.yaml file to create the materialize-environment namespace and install Materialize:

      kubectl apply -f sample-materialize.yaml
      
    2. Verify the installation and check the status:

      kubectl get all -n materialize-environment
      

      Wait for the components to be ready and in the Running state.

      NAME                                             READY   STATUS    RESTARTS   AGE
      pod/mz32bsnzerqo-balancerd-756b65959c-6q9db      1/1     Running   0                 12s
      pod/mz32bsnzerqo-cluster-s2-replica-s1-gen-1-0   1/1     Running   0                 14s
      pod/mz32bsnzerqo-cluster-u1-replica-u1-gen-1-0   1/1     Running   0                 14s
      pod/mz32bsnzerqo-console-6b7c975fb9-jkm8l        1/1     Running   0          5s
      pod/mz32bsnzerqo-console-6b7c975fb9-z8g8f        1/1     Running   0          5s
      pod/mz32bsnzerqo-environmentd-1-0                1/1     Running   0                 19s
      
      NAME                                               TYPE        CLUSTER-IP          EXTERNAL-IP   PORT(S)                                        AGE
      service/mz32bsnzerqo-balancerd                     ClusterIP   None                <none>        6876/TCP,6875/TCP                              12s
      service/mz32bsnzerqo-cluster-s2-replica-s1-gen-1   ClusterIP   None                <none>        2100/TCP,2103/TCP,2101/TCP,2102/TCP,6878/TCP   14s
      service/mz32bsnzerqo-cluster-u1-replica-u1-gen-1   ClusterIP   None                <none>        2100/TCP,2103/TCP,2101/TCP,2102/TCP,6878/TCP   14s
      service/mz32bsnzerqo-console                       ClusterIP   None                <none>        8080/TCP                                       5s
      service/mz32bsnzerqo-environmentd                  ClusterIP   None                <none>        6875/TCP,6876/TCP,6877/TCP,6878/TCP            12s
      service/mz32bsnzerqo-environmentd-1                ClusterIP   None                <none>        6875/TCP,6876/TCP,6877/TCP,6878/TCP            19s
      service/mz32bsnzerqo-persist-pubsub-1              ClusterIP   None                <none>        6879/TCP                                       19s
      
      NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
      deployment.apps/mz32bsnzerqo-balancerd   1/1     1            1           12s
      deployment.apps/mz32bsnzerqo-console     2/2     2            2           5s
      
      NAME                                                DESIRED   CURRENT   READY          AGE
      replicaset.apps/mz32bsnzerqo-balancerd-756b65959c   1         1         1              12s
      replicaset.apps/mz32bsnzerqo-console-6b7c975fb9     2         2         2              5s
      
      NAME                                                        READY   AGE
      statefulset.apps/mz32bsnzerqo-cluster-s2-replica-s1-gen-1   1/1     14s
      statefulset.apps/mz32bsnzerqo-cluster-u1-replica-u1-gen-1   1/1     14s
      statefulset.apps/mz32bsnzerqo-environmentd-1                1/1     19s
      

      If you run into an error during deployment, refer to the Troubleshooting guide.

  11. Open the Materialize Console in your browser:

    1. Find your console service name.

      MZ_SVC_CONSOLE=$(kubectl -n materialize-environment get svc \
        -o custom-columns="NAME:.metadata.name" --no-headers | grep console)
      echo $MZ_SVC_CONSOLE
      
    2. Port forward the Materialize Console service to your local machine:1

      (
        while true; do
           kubectl port-forward svc/$MZ_SVC_CONSOLE 8080:8080 -n materialize-environment 2>&1 | tee /dev/stderr |
           grep -q "portforward.go" && echo "Restarting port forwarding due to an error." || break;
        done;
      ) &
      

      The command is run in background.
      - To list the background jobs, use jobs.
      - To bring back to foreground, use fg %<job-number>.
      - To kill the background job, use kill %<job-number>.

    3. Open a browser and navigate to http://localhost:8080.

    💡 Tip: If you experience long loading screens or unresponsiveness in the Materialize Console, we recommend increasing the size of the mz_catalog_server cluster. Refer to the Troubleshooting Console Unresponsiveness guide.

Next steps

  • From the Console, you can get started with the Quickstart.

  • To start ingesting your own data from an external system like Kafka, MySQL or PostgreSQL, check the documentation for sources.

Clean up

To delete the whole local deployment (including Materialize instances and data):

kind delete cluster

See also


  1. The port forwarding command uses a while loop to handle a known Kubernetes issue 78446, where interrupted long-running requests through a standard port-forward cause the port forward to hang. The command automatically restarts the port forwarding if an error occurs, ensuring a more stable connection. It detects failures by monitoring for “portforward.go” error messages. ↩︎

Back to top ↑