How-to Guides
Goal-oriented recipes for getting specific tasks done with Jikkou.
These guides answer “how do I…?” — practical, step-by-step recipes for getting specific tasks done with Jikkou. If you are learning Jikkou for the first time, start with the Tutorials. For exhaustive option-by-option detail, see the Reference.
Install & operate
Manage resources
Govern & operate safely
1 - Install Jikkou
This guide shows how to install the Jikkou CLI.
This guide covers installing the Jikkou CLI, either from source or from releases. To install the REST server, see Install API Server.
From SDKMan! (recommended)
The latest stable release of jikkou (x86) for Linux, and macOS can be retrieved via SDKMan!:
From The Jikkou Project
Releases
Every release released versions of Jikkou is available:
These are the official ways to get Jikkou releases that you manually downloaded and installed.
Install From Release distribution
- Download your desired version
- Unpack it (
unzip jikkou-<version>-linux-x86_64.zip) - Move the unpacked directory to the desired destination (
mv jikkou-<version>-linux-x86_64 /opt/jikkou) - Add the executable to your PATH (
export PATH=$PATH:/opt/jikkou/bin)
From there, you should be able to run the client: jikkou help.
It is recommended to install the bash/zsh completion script jikkou_completion:
wget https://raw.githubusercontent.com/streamthoughts/jikkou/main/jikkou_completion -O jikkou_completion
or alternatively, run the following command for generation the completion script.
$ source <(jikkou generate-completion)
Using Docker Image
# Create a Jikkou configfile (i.e., jikkouconfig)
cat << EOF >jikkouconfig
{
"currentContext" : "localhost",
"localhost" : {
"configFile" : null,
"configProps" : {
"provider.kafka.config.client.bootstrap.servers" : "localhost:9092"
}
}
}
EOF
# Run Docker
docker run -it \
--net host \
--mount type=bind,source="$(pwd)"/jikkouconfig,target=/etc/jikkou/config \
streamthoughts/jikkou:latest -V
Development Builds
In addition to releases you can download or install development snapshots of Jikkou.
From Docker Hub
Docker images are built and push to Docker Hub from the latest main
branch.
They are not official releases, and may not be stable.
However, they offer the opportunity to test the cutting edge features.
$ docker run -it streamthoughts/jikkou:main
From Source (Linux, macOS)
Building Jikkou from source is slightly more work, but is the best way to go if you want to test the latest (
pre-release) Jikkou version.
Prerequisites
To build the project you will need:
- Java 25 (i.e.
$JAVA_HOME environment variable is configured). - GraalVM 25.0.2 or newer to create native executable
- TestContainer to run integration tests
Create Native Executable
# Build and run all tests
./mvnw clean verify -Pnative
You can then execute the native executable with: ./jikkou-cli/target/jikkou-$PROJECT_VERSION-runner
Build Debian Package (.deb)
# Build and run all tests
./mvnw clean package -Pnative
./mvnw package -Pdeb
You can then install the package with: sudo dpkg -i ./dist/jikkou-$PROJECT_VERSION-linux-x86_64.deb
NOTE: Jikkou will install itself in the directory : /opt/jikkou
Build RPM Package
# Build and run all tests
./mvnw clean package -Pnative
./mvnw package -Prpm
The RPM package will available in the ./target/rpm/jikkou/RPMS/noarch/ directory.
1.1 - Install Jikkou API Server
This guide shows how to install the Jikkou API Server.
Releases
The latest stable release of Jikkou API Server is available:
Standalone Installation
Follow these few steps to download the latest stable versions and get started.
Prerequisites
To be able to run Jikkou API Server, the only requirement is to have a working Java 25 installation.
You can check the correct installation of Java by issuing the following command:
Step 1: Download
Download the latest Java binary distribution from the GitHub Releases (e.g. jikkou-api-server-$LATEST_VERSION.zip)
Unpack the download distribution and move the unpacked directory to a desired destination
unzip jikkou-api-server-$LATEST_VERSION.zip
mv jikkou-api-server-$LATEST_VERSION /opt/jikkou
Step 2: Start the API Server
Launch the application with:
./bin/jikkou-api-server.sh
Step 3: Test the API Server
$ curl -sX GET http://localhost:28082 -H "Accept: application/json" | jq
{
"version": "0.37.0",
"build_time": "2025-08-26T00:00:00+0000",
"commit_id": "dae1be11c092256f36c18c8f1d90f16b0c951716",
"_links": {
"self": {
"href": "/",
"templated": false
},
"get-apis": {
"href": "/apis",
"templated": false
}
}
}
Step 4: Stop the API Server
PID=`ps -ef | grep -v grep | grep JikkouApiServer | awk '{print $2}'`
kill $PID
Docker
# Run Docker
docker run -it \
--net host \
streamthoughts/jikkou-api-server:latest
Development Builds
In addition to releases you can download or install development snapshots of Jikkou API Server.
From Docker Hub
Docker images are built and push to Docker Hub from the latest main
branch.
They are not official releases, and may not be stable.
However, they offer the opportunity to test the cutting edge features.
$ docker run -it streamthoughts/jikkou-api-server:main
Next Steps
2 - Automating
Integrate Jikkou into CI/CD pipelines.
2.1 - Automate Jikkou with GitHub Actions
Learn Jikkou Setup Github Action in your CI/CD Workflows
Setup Jikkou
The streamthoughts/setup-jikkou action is a JavaScript action that
sets up Jikkou in your GitHub Actions workflow by:
- Downloading a specific version of Jikkou CLI and adding it to the
PATH. - Configuring JIKKOU CLI with a custom configuration file.
After you’ve used the action, subsequent steps in the same job can run arbitrary Jikkou commands using the GitHub
Actions run syntax. This allows most Jikkou commands to work exactly like they do on your local command line.
Usage
steps:
- uses: streamthoughts/setup-jikkou@v1
A specific version of Jikkou CLI can be installed:
steps:
- uses: streamthoughts/setup-jikkou@v0.1.0
with:
jikkou_version: 0.37.0
A custom configuration file can be specified:
steps:
- uses: streamthoughts/setup-jikkou@v0.1.0
with:
jikkou_config: ./config/jikkouconfig.json
This Action additionally supports the following inputs :
| Property | Default | Description |
|---|
jikkou_version | latest | The version of Jikkou CLI to install. A value of latest will install the latest version of Jikkou CLI. |
jikkou_config | | The path to the Jikkou CLI config file. If set, Jikkou CLI will be configured through the JIKKOUCONFIG environment variable. |
See also
2.2 - Detect Configuration Drift
Run jikkou diff on a schedule to detect when your clusters no longer match what is in Git.
Configuration drift happens to every Kafka platform: someone bumps retention.ms during an
incident with a vendor UI, a topic gets created by hand, an ACL is “temporarily” widened.
Because Jikkou is stateless and always compares your Git-versioned definitions against the
actual cluster state, detecting drift is a single command:
jikkou diff --files ./resources --fail-on-changes
Exit codes
With --fail-on-changes, jikkou diff uses distinct exit codes so CI can react precisely:
| Code | Meaning |
|---|
0 | No changes: cluster matches Git |
1 | Validation or execution error |
2 | Usage error (invalid flags or arguments) |
3 | Drift detected: at least one pending change |
A one-line summary is printed to stderr (for example, 3 changes detected: 1 CREATE, 2 UPDATE),
while stdout carries the full machine-readable diff (YAML by default, -o JSON available).
Scoping the check
The drift check is evaluated on the filtered result. For example,
--fail-on-changes --filter-change-op UPDATE only counts updates as drift and ignores
creations and deletions. Without filters, every operation other than NONE counts.Scheduled drift check with GitHub Actions
The workflow below runs every hour using the
streamthoughts/setup-jikkou action, uploads
the diff as an artifact, and opens an issue when drift is detected:
name: Kafka Drift Detection
on:
schedule:
- cron: '0 * * * *' # every hour
workflow_dispatch: {}
jobs:
drift:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/checkout@v4
- uses: streamthoughts/setup-jikkou@v1
with:
jikkou_config: ${{ github.workspace }}/.jikkou/config
- name: Check for drift
id: diff
run: |
set +e
jikkou diff --files ./resources --fail-on-changes -o YAML > drift.yaml
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
- name: Upload diff
if: steps.diff.outputs.exit_code == '3'
uses: actions/upload-artifact@v4
with:
name: drift-report
path: drift.yaml
- name: Open an issue on drift
if: steps.diff.outputs.exit_code == '3'
run: |
gh issue create \
--title "Kafka configuration drift detected ($(date -u +%F))" \
--body "jikkou diff found pending changes. Download the drift-report artifact from run ${{ github.run_id }}."
env:
GH_TOKEN: ${{ github.token }}
- name: Fail on error
if: steps.diff.outputs.exit_code == '1' || steps.diff.outputs.exit_code == '2'
run: exit 1
Instead of opening an issue, the same gate (exit_code == '3') can post to Slack, page an
on-call rotation, or even trigger a jikkou apply job to revert the drift automatically.
Running without cluster credentials
CI runners do not need direct access to your Kafka clusters. Run the
Jikkou API server inside your platform, and point
the CLI at it with proxy mode:
jikkou {
proxy {
enabled = true
url = "https://jikkou.my-platform.internal"
security {
access-token = ${?JIKKOU_API_TOKEN}
}
}
}
With this configuration, the workflow above only needs an API token: cluster credentials stay
on the server side.
3 - Manage Kafka ACLs
Declare and apply Access Control Lists (ACLs) for principals on your Apache Kafka cluster.
This guide shows how to manage Kafka Access Control Lists (ACLs) as code with Jikkou. For the full
resource specification, see the Kafka Authorizations reference.
Before you begin
- A running Apache Kafka cluster with an authorizer enabled (e.g.
StandardAuthorizer or AclAuthorizer). - A configured Jikkou context pointing at your cluster — see Getting Started.
- A principal with permission to manage ACLs.
1. Describe the ACLs you want
Create a file describing the desired authorizations for each principal.
file: kafka-acls.yaml
---
apiVersion: "kafka.jikkou.io/v1beta2"
kind: "KafkaPrincipalAuthorization"
metadata:
name: "User:Alice"
spec:
acls:
- resource:
type: 'topic'
pattern: 'orders-'
patternType: 'PREFIXED'
type: "ALLOW"
operations: [ 'READ', 'WRITE' ]
host: "*"
2. Preview the changes
Always run in --dry-run first to review what Jikkou will do:
jikkou apply --files ./kafka-acls.yaml --dry-run
3. Apply the ACLs
jikkou apply --files ./kafka-acls.yaml
Reuse permissions with roles
To avoid repeating the same ACLs for many principals, define a KafkaPrincipalRole once and reference
it from several principals:
---
apiVersion: "kafka.jikkou.io/v1beta2"
kind: "KafkaPrincipalRole"
metadata:
name: "OrdersReadWrite"
spec:
acls:
- type: "ALLOW"
operations: [ 'READ', 'WRITE' ]
resource:
type: 'topic'
pattern: 'orders-'
patternType: 'PREFIXED'
host: "*"
---
apiVersion: "kafka.jikkou.io/v1beta2"
kind: "KafkaPrincipalAuthorization"
metadata:
name: "User:Alice"
spec:
roles:
- "OrdersReadWrite"
Delete ACLs
Jikkou reconciles to the declared state. With apply, any ACL that exists on the cluster but is not
present in your resource files will be deleted for the principals you describe. To delete all ACLs for a
principal, add the delete annotation:
apiVersion: "kafka.jikkou.io/v1beta2"
kind: "KafkaPrincipalAuthorization"
metadata:
name: "User:Alice"
annotations:
jikkou.io/delete: true
spec:
acls: []
Recommendation
In production, scope changes with --selector and always review them with --dry-run before applying.4 - Manage Schema Registry Subjects
Register and evolve Avro, Protobuf, and JSON schemas in your Schema Registry as code.
This guide shows how to manage Schema Registry subjects with Jikkou. For the full resource
specification, see the Schema Registry Subjects reference.
Before you begin
1. Describe a subject
Keep your schema in its own file and reference it from the resource with $ref.
file: subject-user.yaml
---
apiVersion: "schemaregistry.jikkou.io/v1beta2"
kind: "SchemaRegistrySubject"
metadata:
name: "User"
annotations:
schemaregistry.jikkou.io/normalize-schema: true
spec:
compatibilityLevel: "FULL_TRANSITIVE"
schemaType: "AVRO"
schema:
$ref: ./user-schema.avsc
file: user-schema.avsc
{
"namespace": "example.avro",
"type": "record",
"name": "User",
"fields": [
{ "name": "name", "type": ["null", "string"], "default": null },
{ "name": "favorite_number", "type": ["null", "int"], "default": null }
]
}
2. Preview and apply
jikkou apply --files ./subject-user.yaml --dry-run # review
jikkou apply --files ./subject-user.yaml # apply
3. Evolve the schema safely
To evolve a schema, edit the .avsc file and re-apply. Jikkou registers a new version only when the
schema actually changes, and the registry rejects changes that violate the subject’s
compatibilityLevel. Run with --dry-run first to confirm the diff is what you expect.
Manage many subjects at once
Use a SchemaRegistrySubjectList (handy with templating) to manage
multiple subjects in a single file:
apiVersion: "schemaregistry.jikkou.io/v1beta2"
kind: "SchemaRegistrySubjectList"
items: [] # an array of SchemaRegistrySubject
5 - Manage Kafka Connect Connectors
Deploy, configure, and control the lifecycle of Kafka Connect connectors as code.
This guide shows how to manage Kafka Connect connectors with Jikkou. For the full resource
specification, see the KafkaConnector reference.
Before you begin
- One or more reachable Kafka Connect clusters.
- Each cluster declared under the
kafkaConnect.clusters[] setting in your Jikkou configuration —
see the Kafka Connect provider configuration.
1. Describe a connector
The kafka.jikkou.io/connect-cluster label selects which configured cluster the connector is created in.
file: kafka-connector-filestream-sink.yaml
---
apiVersion: "kafka.jikkou.io/v1beta1"
kind: "KafkaConnector"
metadata:
name: "local-file-sink"
labels:
kafka.jikkou.io/connect-cluster: "my-connect-cluster"
spec:
connectorClass: "FileStreamSink"
tasksMax: 1
config:
file: "/tmp/test.sink.txt"
topics: "connect-test"
state: "running"
2. Preview and apply
jikkou apply --files ./kafka-connector-filestream-sink.yaml --dry-run # review
jikkou apply --files ./kafka-connector-filestream-sink.yaml # apply
3. Control the connector lifecycle
Set spec.state and re-apply to change the runtime state of a connector:
running — connector and tasks are active (default).paused — message processing is paused until resumed.stopped — connector and tasks are shut down; the config is kept.
4. Inspect connector status
jikkou get kafkaconnectors --expand-status
The status.connectorStatus block reports the live state of the connector and its tasks as returned
by the Kafka Connect REST API.
6 - Manage Apache Iceberg Tables
Create Iceberg namespaces and tables, and evolve table schemas safely, as code.
This guide shows how to manage Apache Iceberg namespaces and tables with Jikkou, including safe schema
evolution. For the full resource specification, see the
Iceberg Table reference.
Before you begin
1. Create a namespace
file: iceberg-namespace.yaml
---
apiVersion: "iceberg.jikkou.io/v1beta1"
kind: "IcebergNamespace"
metadata:
name: "analytics.events"
jikkou apply --files ./iceberg-namespace.yaml --dry-run # review
jikkou apply --files ./iceberg-namespace.yaml # apply
2. Create a table
file: iceberg-page-views.yaml
---
apiVersion: "iceberg.jikkou.io/v1beta1"
kind: "IcebergTable"
metadata:
name: "analytics.events.page_views"
spec:
schema:
columns:
- name: "event_id"
type: "uuid"
required: true
- name: "user_id"
type: "long"
required: true
- name: "page_url"
type: "string"
required: true
- name: "event_time"
type: "timestamptz"
required: true
partitionFields:
- sourceColumn: "event_time"
transform: "day"
sortFields:
- column: "event_time"
direction: "asc"
properties:
write.format.default: "parquet"
write.parquet.compression-codec: "zstd"
jikkou apply --files ./iceberg-page-views.yaml
3. Evolve the schema safely
To add, update, or drop columns, edit the resource and re-apply. Jikkou performs safe schema evolution
and preserves Iceberg field IDs.
To rename a column without breaking existing readers, set previousName to the old name instead of
dropping and re-adding it:
columns:
- name: "user_identifier" # new name
previousName: "user_id" # triggers a rename, not drop+add
type: "long"
required: true
By default Jikkou rejects unsafe type changes (e.g. string → int). Safe promotions such as
int → long are allowed. To force an incompatible change on a single resource, set the annotation
iceberg.jikkou.io/allow-incompatible-changes: "true".
Warning
Incompatible schema changes may break existing data readers. Use the override annotation only when you
are certain all consumers can handle the new schema.Manage many tables at once
Use an IcebergTableList (handy with templating) to define multiple
tables in a single file.
7 - Back Up and Restore Configuration
Export the current state of a cluster to YAML for backup or replication, then restore it elsewhere.
Because Jikkou is stateless and uses your platform as the source of truth, you can export the live state
of any managed resource to YAML. Those files can be version-controlled, used as a backup, or applied to
another cluster to replicate its configuration.
Before you begin
1. Export resources to a file
Use jikkou get <kind> with YAML output and redirect it to a file:
jikkou get kafkatopics -o yaml > topics-backup.yaml
The same pattern works for any managed resource kind. List the kinds available in your context — and
the exact names accepted by get — with:
Then export each kind to build a full snapshot, for example:
jikkou get kafkatopics -o yaml > topics-backup.yaml
jikkou get kafkaprincipalauthorizations -o yaml > acls-backup.yaml
Tip
Add --default-configs to jikkou get kafkatopics to include built-in default config values in the
export. Use --selector to back up only a subset of resources.2. Restore or replicate
Point Jikkou at the target cluster (e.g. switch context with jikkou config use-context <name>), then
preview and apply the exported files:
jikkou apply --files ./topics-backup.yaml --dry-run # review
jikkou apply --files ./topics-backup.yaml # apply
This same flow lets you replicate configuration from one cluster to another: export from the source,
switch context, and apply to the target.
Recommendation
When restoring with apply, Jikkou reconciles the target to the declared state — resources present on
the target but absent from your files may be altered or deleted. Always run with --dry-run first and
scope changes with --selector.Automate periodic backups
Run the export commands on a schedule (e.g. a cron job or a CI pipeline) and commit the output to a Git
repository to keep a versioned history of your cluster configuration. See
Automating for running Jikkou in CI/CD.
8 - Enforce Governance Policies
Use ValidatingResourcePolicy to enforce organizational rules on resources and changes with CEL.
A ValidatingResourcePolicy is a declarative, reusable way to enforce governance rules across any
resource using Google CEL expressions. Use it to block destructive operations,
enforce limits (partitions, replication factor), or require naming and metadata conventions.
For the full specification, see the
ValidatingResourcePolicy reference.
For the broader picture, see Validations.
Before you begin
1. Write a policy
A policy selects the resources it applies to and defines rules. Each rule’s expression is a CEL
assertion that must hold for the resource to be valid: the rule fails when the expression evaluates
to false (the same convention as Kubernetes ValidatingAdmissionPolicy). The failurePolicy decides
what happens on failure:
FAIL: abort the operation with an error.FILTER: silently drop the invalid resource(s) and continue.CONTINUE: report the violation but let the resource proceed. Useful to introduce a new rule in
“warning mode” before making it blocking.
file: policy-topics.yaml
---
apiVersion: core.jikkou.io/v1
kind: ValidatingResourcePolicy
metadata:
name: KafkaTopicPolicy
spec:
failurePolicy: FAIL
selector:
matchResources:
- kind: KafkaTopic
rules:
- name: MaxTopicPartitions
expression: "resource.spec.partitions <= 50"
messageExpression: "'Topic partitions MUST be <= 50, but was: ' + string(resource.spec.partitions)"
- name: MinTopicPartitions
expression: "resource.spec.partitions >= 3"
message: "Topic must have at least 3 partitions"
2. Apply resources with the policy
Policies are transient resources: pass the policy file alongside the resources being validated. Jikkou
evaluates the policy during reconciliation.
jikkou apply --files ./kafka-topics.yaml --files ./policy-topics.yaml --dry-run
If a topic violates a rule, a FAIL policy stops the run and prints the rule’s message.
Block destructive operations
Policies can match change resources (e.g. KafkaTopicChange) to control operations. This example
filters out delete operations on topics so they are never executed:
---
apiVersion: core.jikkou.io/v1
kind: ValidatingResourcePolicy
metadata:
name: BlockTopicDeletes
spec:
failurePolicy: FILTER
selector:
matchResources:
- kind: KafkaTopicChange
rules:
- name: FilterDeleteOperation
expression: "resource.spec.op != 'DELETE'"
messageExpression: "'Operation ' + resource.spec.op + ' on topics is not authorized'"
Target a subset of resources
Combine matchResources, matchLabels, and matchExpressions (with matchingStrategy: ALL or ANY)
to scope a policy. For example, apply it only to topics in the prod environment:
selector:
matchingStrategy: ALL
matchResources:
- kind: KafkaTopic
matchLabels:
- key: environment
operator: In
values: ["prod"]
Policy library
Ready-made policies you can copy and adapt live in
examples/policies/:
| Policy | What it enforces |
|---|
topic-naming-convention.yaml | Topic names follow a convention (kebab-case by default; adapt the regex) |
topic-min-insync-replicas.yaml | min.insync.replicas is set explicitly and is at least 2 |
topic-min-replication-factor.yaml | Replication factor is declared and at least 3 |
topic-partition-limits.yaml | Partition count stays within platform bounds (3 to 50 by default) |
require-owner-label.yaml | Every topic carries an owner label |
block-topic-deletes.yaml | Reconciliation may never delete a topic (matches change resources) |
Centrally enforce policies for all teams
Passing policy files on every command works for one team, but a platform team usually wants policies
applied to every run, no matter which files an application team passes. Configure a
resource repository in the shared Jikkou context:
repository resources are injected automatically into each execution.
jikkou {
repositories = [
{
name = "platform-policies"
type = io.jikkou.core.repository.GitHubResourceRepository
config {
repository = "my-org/kafka-platform-policies"
branch = "main"
paths = [ "policies/" ]
# Access token for private repositories
token = ${?GITHUB_TOKEN}
}
}
]
}
With this configuration in the context used by CI (or by the Jikkou API server), an application
team running jikkou apply -f ./my-topics.yaml gets the platform policies evaluated on every
resource and every change, without ever seeing the policy files. Updating a rule is a pull
request on the central policies repository, immediately effective for all teams.
9 - Manage a Fleet of Kafka Clusters
Apply the same resource definitions across multiple Kafka clusters and providers in one command, with per-cluster results.
Most Kafka estates are fleets: a production cluster per region, staging, and often a mix of
on-premises and managed services. Jikkou applies one declarative model across all of them:
define each cluster as a named provider instance, group them, and target the group in one
command.
Before you begin
1. Declare one provider instance per cluster
Each cluster is a named entry under provider, all sharing the same provider type:
jikkou {
provider.kafka-prod-eu {
type = io.jikkou.kafka.KafkaExtensionProvider
config {
client {
bootstrap.servers = "kafka-eu.internal:9092"
}
}
}
provider.kafka-prod-us {
type = io.jikkou.kafka.KafkaExtensionProvider
config {
client {
bootstrap.servers = "kafka-us.internal:9092"
}
}
}
provider.kafka-staging {
type = io.jikkou.kafka.KafkaExtensionProvider
config {
client {
bootstrap.servers = "kafka-staging.internal:9092"
}
}
}
# Named groups for batch operations
provider-groups {
prod = ["kafka-prod-eu", "kafka-prod-us"]
}
}
2. Target the fleet
The three selection flags are mutually exclusive:
# One cluster
jikkou apply -f ./resources --provider kafka-prod-eu
# A named group
jikkou apply -f ./resources --provider-group prod
# Every registered instance
jikkou apply -f ./resources --provider-all
Multi-provider runs are fail-fast by default: the first failing cluster aborts the run.
Add --continue-on-error to keep going and get results for the remaining clusters.
3. Read per-cluster results
Results are reported per provider. In TEXT output, tasks are grouped under a provider header:
PROVIDER [kafka-prod-eu] *******************************************************
TASK [CREATE] Create a new topic orders-events (partitions=6, replicas=3) - CHANGED
PROVIDER [kafka-prod-us] *******************************************************
TASK [CREATE] Create a new topic orders-events (partitions=6, replicas=3) - CHANGED
EXECUTION in 3s 421ms
ok : 0, created : 2, altered : 0, deleted : 0 failed : 0
In JSON or YAML output, every change carries the jikkou.io/provider annotation, so results
stay attributable when piped into other tools:
{
"change": {
"metadata": {
"annotations": {
"jikkou.io/provider": "kafka-prod-eu"
}
}
}
}
Fleet-wide drift detection
jikkou diff accepts the same provider flags, so a scheduled CI job can check the whole
fleet at once and tell you which cluster drifted:
jikkou diff -f ./resources --provider-group prod --fail-on-changes
See Detect configuration drift
for the full CI setup.
10 - Migration
Step-by-step upgrade guides between Jikkou versions.
This section collects upgrade guides for major and breaking releases. If you’re moving between minor versions, the release notes usually contain everything you need.
10.1 - Migrating to Jikkou 1.0
Step-by-step upgrade guide from Jikkou 0.37.x to 1.0.0.
Jikkou 1.0.0 is a major release. The good news: the project’s first real breaking change — the move from io.streamthoughts.jikkou.* to io.jikkou.* — ships with a runtime deprecation shim, so most existing setups will run unchanged with warnings while you migrate at your own pace.
This guide walks through the upgrade end to end.
Before You Upgrade
A short checklist before you start:
- Pin your current version. Make sure your CI and any automation reference
0.37.3 (or whichever 0.37.x you run today) explicitly, not latest, so you can roll back fast. - Back up your configurations. Commit any uncommitted Jikkou configuration and resource files. The migration is mechanical, but a clean baseline makes review easier.
- Plan a window. The shim means you don’t need downtime, but if you operate Jikkou as a service (
jikkou-api-server), the upgrade is a normal rolling deploy. - Read the v1.0.0 release notes. This guide is focused on change recipes; the release notes explain the why.
1. Update Maven / Gradle Coordinates
The Maven group changed from io.streamthoughts to io.jikkou. Artifact names are unchanged.
Maven
<!-- Before -->
<dependency>
<groupId>io.streamthoughts</groupId>
<artifactId>jikkou-core</artifactId>
<version>0.37.3</version>
</dependency>
<!-- After -->
<dependency>
<groupId>io.jikkou</groupId>
<artifactId>jikkou-core</artifactId>
<version>1.0.0</version>
</dependency>
Gradle
// Before
implementation("io.streamthoughts:jikkou-core:0.37.3")
// After
implementation("io.jikkou:jikkou-core:1.0.0")
If you depend on multiple Jikkou modules (jikkou-extension-rest-client, individual providers, etc.), update them all in one pass — they all moved together.
2. Rename Java Imports
If you maintain custom extensions, providers, or any Java code that imports Jikkou classes, replace the package prefix:
io.streamthoughts.jikkou. → io.jikkou.
With your IDE. Use the project-wide find-and-replace, scoped to *.java files. IntelliJ’s “Refactor → Rename” on the package root handles imports and pom.xml references in one step.
With sed (POSIX-friendly):
# From the repo root
git ls-files '*.java' '*.kt' '*.scala' \
| xargs sed -i 's|io\.streamthoughts\.jikkou|io.jikkou|g'
Don’t rename your own packages. Only the prefix io.streamthoughts.jikkou.* belonging to Jikkou itself moved.
You don’t have to do this immediately. The runtime keeps resolving old class names through a deprecation shim and logs a warning. This means a staged rollout is safe: upgrade the dependency first, observe warnings in your logs, then schedule the import rename. The shim is scheduled for removal in 1.1.0.
3. Migrate Off Deprecated JikkouApi Overloads
Four JikkouApi overloads that take a raw Configuration have been deprecated since 0.37.0 (@Deprecated(forRemoval = true)) and will be removed in a future release. If you have custom Java code calling them, switch to the GetContext / ListContext builders:
| Deprecated | Replacement |
|---|
getResource(Class<?>, String, Configuration) | getResource(ResourceType, String, GetContext) |
getResource(ResourceType, String, Configuration) | getResource(ResourceType, String, GetContext) |
listResources(Class<?>, Selector, Configuration) | listResources(ResourceType, ListContext) |
listResources(ResourceType, Selector, Configuration) | listResources(ResourceType, ListContext) |
Recipe:
// Before
KafkaTopic topic = api.getResource(KafkaTopic.class, "events", configuration);
ResourceList<KafkaTopic> topics = api.listResources(
KafkaTopic.class, selector, configuration);
// After
KafkaTopic topic = api.getResource(
ResourceType.of(KafkaTopic.class),
"events",
GetContext.builder().configuration(configuration).build()
);
ResourceList<KafkaTopic> topics = api.listResources(
ResourceType.of(KafkaTopic.class),
ListContext.builder().selector(selector).configuration(configuration).build()
);
The new context objects also accept a provider (string) — that’s how you target a specific provider instance when you have several configured.
4. CLI Changes
get is now grouped by provider
jikkou get subcommands are organised under their provider. The canonical form is now:
jikkou get kafka topics
jikkou get kafka acls
jikkou get schema-registry subjects
Existing scripts that call the old flat form (jikkou get topics, jikkou get kafkatopics, jikkou get kt, …) still work — the old names are registered as hidden, deprecated subcommands that print a deprecation notice on each invocation. Plan to switch your scripts to the provider-grouped form before 1.1.0.
New flags on reconciliation commands
apply, create, update, patch, replace, delete, and diff accept three new options for multi-provider setups:
| Flag | Purpose |
|---|
--provider-all | Apply to every registered provider of the matching type. |
--provider-group <name> | Apply to a named provider group (configured under jikkou.provider-groups). |
--continue-on-error | Continue the batch when one provider fails (default: fail-fast). |
--provider, --provider-all, and --provider-group are mutually exclusive. None of them are required: if you have a single provider of each type, your existing commands keep working unchanged.
For a complete walkthrough (configuration, per-cluster results, fleet-wide drift checks), see
Manage a fleet of Kafka clusters.
-o/--output now accepts JSON, YAML, or TABLE on list and get commands.
5. REST API Additions
ResourceReconcileRequest accepts two new optional fields:
{
"resources": [ ... ],
"providers": ["kafka-prod-eu", "kafka-prod-us"],
"continueOnError": true
}
Both fields are additive. Existing clients that omit them are unaffected.
6. Verify the Upgrade
After updating coordinates and (optionally) imports:
# Confirm the version
jikkou --version
# Check that resources still parse and providers still load
jikkou api-providers list
jikkou api-resources
# Validate your manifests against the running providers
jikkou validate --files <your-manifests>
If you’re running custom extensions, watch the logs on first start for Class name 'io.streamthoughts.jikkou.…' is deprecated warnings — those are your remaining import-rename targets.
7. Rolling Back
If something goes wrong, revert the coordinate change to fall back to 0.37.3. Pin to the previous version via the original group:
<groupId>io.streamthoughts</groupId>
<artifactId>jikkou-core</artifactId>
<version>0.37.3</version>
Or download the binary from the v0.37.3 GitHub release.
Need Help?