# Migrate with the Diagrid Kubernetes Operator

The Diagrid Kubernetes Operator is a Kubernetes-native way to migrate your workloads from Dapr OSS. It can read your existing Dapr resources directly from Kubernetes and only requires you to migrate from the `dapr.io` annotations to the `catalyst.diagrid.io` annotations. It will manage configuring Diagrid for you and integrating your workloads without manual intervention.

**Diagram: What the Diagrid operator does.** The operator reads the catalyst.diagrid.io annotations and configures your Diagrid project. A remote Dapr server reaches your app over a secure tunnel; with a local Dapr server, the sidecar reaches it over localhost instead.

- **Your Kubernetes cluster**: Workload (catalyst.diagrid.io annotations), Dapr resources (catalyst.diagrid.io/project), Diagrid operator (reads the annotations)
- **Diagrid project**: Remote Dapr server, App IDs & components (created for you)

- Workload (catalyst.diagrid.io annotations) → Diagrid operator (reads the annotations)
- Dapr resources (catalyst.diagrid.io/project) → Diagrid operator (reads the annotations)
- Diagrid operator (reads the annotations) → App IDs & components (created for you) (creates, configures)
- Remote Dapr server → Workload (catalyst.diagrid.io annotations) (secure tunnel, async)

## 1. Deploy the operator

:::warning Install cert-manager first
The operator's mutating webhook needs a serving certificate, and by default the chart has [cert-manager](https://cert-manager.io/) issue it. Install cert-manager before the operator:

```bash
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
kubectl wait --for=condition=Available -n cert-manager deploy --all --timeout=120s
```

The CLI checks for cert-manager before it installs anything and stops with these commands if it is missing. Plain Helm does not check, so on the **Helm** tab below the install fails part-way with a resource mapping error for `Certificate` in `cert-manager.io/v1` instead of telling you what to install.

Already managing the webhook certificate yourself? Pass `--set webhook.certManager.enabled=false` and the chart renders no cert-manager resources.
:::

**CLI**

You can use the Diagrid CLI to install the Diagrid Kubernetes Operator Helm chart into your cluster.

```bash
diagrid k8s-operator install
```

You can also override the Helm values using the `--set` flag:

```bash
diagrid k8s-operator install --set some.helm.value=foo
```

The chart also installs the Dapr CRDs, which on this migration path your Dapr open source installation already owns. The CLI checks the cluster before it installs and turns them off for you when it finds them, so `diagrid k8s-operator install` works whether or not Dapr is present. To decide yourself instead, set the value explicitly — `--set dapr.installCRDs=false` never installs them, `--set dapr.installCRDs=true` always does, and either choice is left untouched:

```bash
diagrid k8s-operator install --set dapr.installCRDs=false
```

To uninstall the Diagrid Kubernetes Operator, run:

```bash
diagrid k8s-operator uninstall
```

**Helm**

You can directly use Helm to install the Diagrid Kubernetes Operator into your cluster. On a cluster that already runs Dapr open source, add `--set dapr.installCRDs=false`:

```bash
helm install catalyst-operator oci://public.ecr.aws/diagrid/catalyst-operator \
  --namespace catalyst-system --create-namespace \
  --set dapr.installCRDs=false
```

:::note
Helm does not check the cluster the way the CLI does. Without that flag the install fails before it creates anything, because the Dapr CRDs already exist and belong to your Dapr installation rather than to this Helm release:

```
Unable to continue with install: CustomResourceDefinition "components.dapr.io" in
namespace "" exists and cannot be imported into the current release: invalid
ownership metadata; label validation error: missing key
"app.kubernetes.io/managed-by": must be set to "Helm"
```

Leave the flag out only on a cluster that has never had Dapr installed, where nothing else registers the `dapr.io` types.
:::

You can uninstall the Diagrid Kubernetes Operator with:

```bash
helm uninstall catalyst-operator --namespace catalyst-system
```

See the [Helm chart reference](https://docs.diagrid.io/operate/hosting/enterprise-self-hosted/reference) for the full list of values you can set on the chart.

## 2. Migrate resources

You can use the Diagrid CLI to automatically migrate an existing namespace or you can manually annotation your workloads and Dapr resources within a namespace.

### Add the annotations with the CLI

You can migrate a namespace in-place, which will update the annotations and sidecar on your existing workloads and CRDs to use Diagrid instead of Dapr OSS.

```bash
diagrid k8s-operator migrate my-namespace --project my-project
```

Or you can copy your existing namespace to a new one and only update the copy, leaving the original namespace untouched.

```bash
diagrid k8s-operator migrate my-namespace --project my-project \
  --new-namespace my-namespace-copy
```

We recommend using `--new-namespace` on any real use cases to ensure you can validate the migrated workloads before removing the existing workloads.

:::info Your workloads restart
`migrate` writes the annotations onto the pod template, which Kubernetes treats as a change to the Deployment. Your pods are replaced by a rolling update as soon as the command finishes — that is when the Dapr OSS sidecar goes and the Diagrid one arrives. You do not need to restart anything yourself.

Migrating in place therefore restarts the running workload. With `--new-namespace` the restart happens in the copy, and the original is left alone, which is the other reason to prefer it.
:::

If you want to use `local` Dapr Servers, you must add the `--host local` flag to the migrate command:

```bash
diagrid k8s-operator migrate my-namespace --project my-project \
  --host local
```

In a public region, a local Dapr server cannot run workflows or use the managed KV store and pub/sub. See [Dapr Server location](https://docs.diagrid.io/dapr-open-source/migrate-to-diagrid#dapr-server-location-remote-or-local) before you choose it.

### Add the annotations manually

You can also manually apply the necessary `catalyst.diagrid.io` annotations to your workloads and Dapr resources.

#### Workloads

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders
spec:
  template:
    metadata:
      annotations:
        catalyst.diagrid.io/enabled: "true"
        catalyst.diagrid.io/app-id: "orders"
        catalyst.diagrid.io/provider: "catalyst"          # tells the Diagrid operator to claim this pod
        catalyst.diagrid.io/project: "my-project"         # which Diagrid project to register against
        catalyst.diagrid.io/host: "remote"                # or "local" to inject the sidecar
        catalyst.diagrid.io/app-port: "8080"              # optional
        catalyst.diagrid.io/app-protocol: "grpc"          # optional
```

`catalyst.diagrid.io/host` is the switch between [remote and local location](https://docs.diagrid.io/dapr-open-source/migrate-to-diagrid#dapr-server-location-remote-or-local). The operator reads only the annotations listed above — any `dapr.io/*` annotations on the pod are ignored. To prevent the Dapr OSS operator from also acting on the pod, the Diagrid operator disables the `dapr.io/enabled` annotation whenever `catalyst.diagrid.io/enabled` is present, so you don't get conflicting sidecars.

#### Dapr resources

```yaml
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: orderstate
  annotations:
    catalyst.diagrid.io/project: "my-project"
spec:
  type: state.redis
  version: v1
  metadata:
    - name: redisHost
      value: redis:6379
```

CRDs without `catalyst.diagrid.io/project` are left alone, which is useful for keeping in-cluster Dapr OSS resources side-by-side with Diagrid-managed ones during a phased migration.

## Connecting Diagrid to your app endpoints

Some Dapr APIs require the Dapr server to be able to call endpoints on your application, such as service invocation, input bindings or programmatic pub/sub subscriptions.
When using the Diagrid Kubernetes Operator, all you need to do is ensure you have the following annotation:

```yaml
catalyst.diagrid.io/app-port: "8080" # or whatever port your app listens on
```

For **remote** Dapr servers, the operator will establish a secure tunnel between Diagrid and your app so that traffic can flow without you having to expose the app directly to the Diagrid network.

For **local** Dapr servers (external apps), the operator will set the app's `appEndpoint` to `https://localhost:<app-port>` and the sidecar will route traffic from Diagrid to your app over localhost.

## Next steps

- To see every step on a local cluster first, follow the [migration quickstart](https://docs.diagrid.io/dapr-open-source/migrate-to-diagrid/quickstart).
- Once your workloads are running on Diagrid, [cut over your traffic and decommission Dapr OSS](https://docs.diagrid.io/dapr-open-source/migrate-to-diagrid/cut-over).
