[WIP][1000% vibed] Add RestateKafkaIntegration CRD (restate.dev/v1alpha1) - #196
Draft
slinkydeveloper wants to merge 2 commits into
Draft
[WIP][1000% vibed] Add RestateKafkaIntegration CRD (restate.dev/v1alpha1)#196slinkydeveloper wants to merge 2 commits into
slinkydeveloper wants to merge 2 commits into
Conversation
Runs the Restate Kafka ingress integration (github.com/restatedev/ingress-integration-kafka) as an operator-managed Deployment: a container that consumes Kafka topics and turns each record into a Restate invocation. Previously this meant hand-writing a Deployment, knowing the cluster's in-cluster ingress URL, and keeping the image tag in sync. Only the Restate destination is modelled as CRD fields: - spec.restate.ingress is the same cluster/cloud/service/url union as RestateDeployment's spec.restate.register, resolved to the ingress port (8080) rather than the admin port. - spec.restate.authToken references a Secret key in the custom resource's own namespace, passed through as RESTATE_AUTH_TOKEN. Required with ingress.cloud, since the RestateCloudEnvironment's own credentials live in the operator's namespace and copying them across namespaces would mean granting the operator cluster-wide read access to Secrets. Everything Kafka-side -- connection, consumer settings, record mapper, metrics, retry policy -- is the container's own configuration surface and is passed through verbatim as a Java .properties file, inline via spec.config (held in a ConfigMap the operator owns, digested into the pod template so an edit rolls the pods) or from a Secret/ConfigMap via spec.configFrom. Mirroring those options as typed fields would mean a CRD change for every upstream addition, for no validation worth having. spec.template is a partial pod template strategic-merged over the generated one: objects merge key by key, and lists whose Kubernetes merge key we know merge entry by entry, so overriding a container's image does not drop its ports and adding an env var does not drop the operator's. The labels backing the Deployment's immutable selector are re-applied after the merge. The generated pod has no probes on purpose: the image exposes no health endpoint and exits non-zero on unrecoverable errors, so the restart policy is the real liveness mechanism, and a probe on the metrics port would break for anyone setting restate.metrics.enabled=false. Rollouts use maxSurge: 0 to avoid an extra Kafka rebalance. No finalizer: there is nothing to deregister, so owner references and garbage collection are enough. RBAC gains cluster-wide apps/deployments and delete on configmaps, since unlike the RestateCloudEnvironment tunnel these children land in the user's namespace. Note: reaching a RestateCluster's ingress requires spec.security.networkPeers.ingress on that cluster -- documented in the README and examples, since the failure otherwise presents as a hang. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PNVbxD7hyaHFyCQTowMdXi
Upstream now accepts a comma-separated CONFIG_FILE list, merged left to right (env still wins over files). Move the resolved ingress URL out of the RESTATE_INGRESS_URL env var into a restate.properties file mounted first (lowest precedence), so config can override it. Replace the mutually-exclusive config/configFrom with two fields that layer: spec.config (an inline .properties block) and spec.configRefs (a list of secretRef/configMapRef sources). CONFIG_FILE lists them in merge order: ingress URL, then config, then each ref. The auth token stays in its Secret, still injected as RESTATE_AUTH_TOKEN via secretKeyRef (operator never reads it) and never written into a plaintext config file. The owned ConfigMap now always exists (it carries the ingress URL plus inline config), so its digest always rolls the pods on a change, and the operator no longer deletes it -- dropping the configmaps delete RBAC grant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Runs the Restate Kafka ingress integration github.com/restatedev/ingress-integration-kafka as an operator-managed Deployment: a container that consumes Kafka topics and turns each record into a Restate invocation.
Usage example:
Another example with secrets:
--- Slop slop slop ---
Only the Restate destination is modelled as CRD fields:
Everything Kafka-side -- connection, consumer settings, record mapper, metrics, retry policy -- is the container's own configuration surface and is passed through verbatim as a Java .properties file, inline via spec.config (held in a ConfigMap the operator owns, digested into the pod template so an edit rolls the pods) or from a Secret/ConfigMap via spec.configFrom. Mirroring those options as typed fields would mean a CRD change for every upstream addition, for no validation worth having.
spec.template is a partial pod template strategic-merged over the generated one: objects merge key by key, and lists whose Kubernetes merge key we know merge entry by entry, so overriding a container's image does not drop its ports and adding an env var does not drop the operator's. The labels backing the Deployment's immutable selector are re-applied after the merge.
The generated pod has no probes on purpose: the image exposes no health endpoint and exits non-zero on unrecoverable errors, so the restart policy is the real liveness mechanism, and a probe on the metrics port would break for anyone setting restate.metrics.enabled=false. Rollouts use maxSurge: 0 to avoid an extra Kafka rebalance.
No finalizer: there is nothing to deregister, so owner references and garbage collection are enough.
RBAC gains cluster-wide apps/deployments and delete on configmaps, since unlike the RestateCloudEnvironment tunnel these children land in the user's namespace.
Note: reaching a RestateCluster's ingress requires spec.security.networkPeers.ingress on that cluster -- documented in the README and examples, since the failure otherwise presents as a hang.
Claude-Session: https://claude.ai/code/session_01PNVbxD7hyaHFyCQTowMdXi