* refactor: migrate error packages from pkg/errors to stdlib
Replace github.com/pkg/errors with Go standard library error handling
in foundation error packages:
- internal/datastore/errors: errors.Wrap -> fmt.Errorf with %w
- internal/errors: errors.As -> stdlib errors.As
- controllers/soot/controllers/errors: errors.New -> stdlib errors.New
Part 1 of 4 in the pkg/errors migration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate datastore package from pkg/errors to stdlib
Replace github.com/pkg/errors with Go standard library error handling
in the datastore layer:
- connection.go: errors.Wrap -> fmt.Errorf with %w
- datastore.go: errors.Wrap -> fmt.Errorf with %w
- etcd.go: goerrors alias removed, use stdlib errors.As
- nats.go: errors.Wrap/Is/New -> stdlib equivalents
- postgresql.go: goerrors.Wrap -> fmt.Errorf with %w
Part 2 of 4 in the pkg/errors migration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate internal packages from pkg/errors to stdlib (partial)
Replace github.com/pkg/errors with Go standard library error handling
in internal packages:
- internal/builders/controlplane: errors.Wrap -> fmt.Errorf
- internal/crypto: errors.Wrap -> fmt.Errorf
- internal/kubeadm: errors.Wrap/Wrapf -> fmt.Errorf
- internal/upgrade: errors.Wrap -> fmt.Errorf
- internal/webhook: errors.Wrap -> fmt.Errorf
Part 3 of 4 in the pkg/errors migration.
Remaining files: internal/resources/*.go (8 files, 42 occurrences)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(resources): migrate from pkg/errors to stdlib
Replace github.com/pkg/errors with Go standard library:
- errors.Wrap(err, msg) → fmt.Errorf("msg: %w", err)
- errors.New(msg) → errors.New(msg)
Files migrated:
- internal/resources/kubeadm_phases.go
- internal/resources/kubeadm_upgrade.go
- internal/resources/kubeadm_utils.go
- internal/resources/datastore/datastore_multitenancy.go
- internal/resources/datastore/datastore_setup.go
- internal/resources/datastore/datastore_storage_config.go
- internal/resources/addons/coredns.go
- internal/resources/addons/kube_proxy.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(controllers): migrate from pkg/errors to stdlib
Replace github.com/pkg/errors with Go standard library:
- errors.Wrap(err, msg) → fmt.Errorf("msg: %w", err)
- errors.New(msg) → errors.New(msg) (stdlib)
- errors.Is/As → errors.Is/As (stdlib)
Files migrated:
- controllers/datastore_controller.go
- controllers/kubeconfiggenerator_controller.go
- controllers/tenantcontrolplane_controller.go
- controllers/telemetry_controller.go
- controllers/certificate_lifecycle_controller.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(soot): migrate from pkg/errors to stdlib
Replace github.com/pkg/errors with Go standard library:
- errors.Is() now uses stdlib errors.Is()
Files migrated:
- controllers/soot/controllers/kubeproxy.go
- controllers/soot/controllers/migrate.go
- controllers/soot/controllers/coredns.go
- controllers/soot/controllers/konnectivity.go
- controllers/soot/controllers/kubeadm_phase.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(api,cmd): migrate from pkg/errors to stdlib
Replace github.com/pkg/errors with Go standard library:
- errors.Wrap(err, msg) → fmt.Errorf("msg: %w", err)
Files migrated:
- api/v1alpha1/tenantcontrolplane_funcs.go
- cmd/utils/k8s_version.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: run go mod tidy after pkg/errors migration
The github.com/pkg/errors package moved from direct to indirect
dependency. It remains as an indirect dependency because other
packages in the dependency tree still use it.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(datastore): use errors.Is for sentinel error comparison
The stdlib errors.As expects a pointer to a concrete error type, not
a pointer to an error value. For comparing against sentinel errors
like rpctypes.ErrGRPCUserNotFound, errors.Is should be used instead.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve golangci-lint errors
- Fix GCI import formatting (remove extra blank lines between groups)
- Use errors.Is instead of errors.As for mutex sentinel errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(errors): use proper variable declarations for errors.As
The errors.As function requires a pointer to an assignable variable,
not a pointer to a composite literal. The previous pattern
`errors.As(err, &SomeError{})` creates a pointer to a temporary value
which errors.As cannot reliably use for assignment.
This fix declares proper variables for each error type and passes
their addresses to errors.As, ensuring correct error chain matching.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(datastore/etcd): use rpctypes.Error() for gRPC error comparison
The etcd gRPC status errors (ErrGRPCUserNotFound, ErrGRPCRoleNotFound)
cannot be compared directly using errors.Is() because they are wrapped
in gRPC status errors during transmission.
The etcd rpctypes package provides:
- ErrGRPC* constants: server-side gRPC status errors
- Err* constants (without GRPC prefix): client-side comparable errors
- Error() function: converts gRPC errors to comparable EtcdError values
The correct pattern is to use rpctypes.Error(err) to normalize the
received error, then compare against client-side error constants
like rpctypes.ErrUserNotFound.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add ObservedGeneration to all status types
Add ObservedGeneration field to DataStoreStatus, KubeconfigGeneratorStatus,
and TenantControlPlaneStatus to track which generation the controller has
processed. This enables clients and tools like kstatus to determine if the
controller has reconciled the latest spec changes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: follow Cluster API pattern for ObservedGeneration
Move ObservedGeneration setting for TenantControlPlane from intermediate
status updates to the final successful reconciliation completion. This
follows Cluster API conventions where ObservedGeneration indicates the
controller has fully processed the given generation.
Previously, ObservedGeneration was set on every status update during
resource processing, which could mislead clients into thinking the spec
was fully reconciled when the controller was still mid-reconciliation
or had hit a transient error.
Now:
- DataStore: Sets ObservedGeneration before single status update (simple controller)
- KubeconfigGenerator: Sets ObservedGeneration before single status update (simple controller)
- TenantControlPlane: Sets ObservedGeneration only after ALL resources processed successfully
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: verify ObservedGeneration equals Generation after reconciliation
Add assertion to e2e test to verify that status.observedGeneration
equals metadata.generation after a TenantControlPlane is successfully
reconciled.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: regenerate CRDs with ObservedGeneration field
Run make crds to regenerate CRDs with the new ObservedGeneration
field in status types.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Run make manifests
* Run make apidoc
* Remove rbac role
* Remove webhook manifest
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* docs: Modified bitnami cert-manager reference because images do not exist anymore
* docs: update MetalLB version
* docs: added podman specific command for retrieving GW_IP
This change extends Gateway API support to Konnectivity addons.
When `spec.controlPlane.gateway` is configured and Konnectivity addon is
enabled, Kamaji automatically creates two TLSRoutes:
1. A Control plane TLSRoute (port 6443, sectionName "kube-apiserver")
2. A Konnectivity TLSRoute (port 8132, sectionName "konnectivity-server")
Both routes use the hostname specified in `gateway.hostname` and reference
the same Gateway resource via `parentRefs`, with `port` and `sectionName`
set automatically by Kamaji.
This patch also adds CEL validation to prevent users from specifying
`port` or `sectionName` in Gateway `parentRefs`, as these fields are now
managed automatically by Kamaji.
Signed-off-by: Parth Yadav <parth@coredge.io>
* feat: add support for multiple Datastores
* docs: add guide for datastore overrides
* feat(datastore): add e2e test for dataStoreOverrides
* ci: reclaim disk space from runner to fix flaky tests
* Feat: Gateway Routes Specs, plus resource and status init progress
* Generated content, RBAC and start of e2e
* latest code POC Working but e2e fails
* Use Gateway API v1.2.0
* Remove draft comment
* Use TCPRoute
* Revert the charts folder to reduce noise
* Use the correct controller-gen version
* Rename fields and fix tcp/tls typos
* Rename TLSRouteSpec to GatewayRouteSpec
* Remove last instance of tcproute
* Renaming more fields to match the gateway api naming
* Remove ownership of the gateway
* Revert Ko to 0.14.1 and makefile comments
* service discovery, webhooks, and deadcode removal.
* add conditional check for gateway api resources and mark is as owned!
* removing duplicated code and note for maybe a refactor later
* E2E now works!
* e2e suite modifications to support Gateway API v1alpha2 TLSRoute
* Suggestions commit, naming and other related.
* First pass at the status update
* Rename route to gateway
* Only allow one hostname in gateway
* Update status types
* WIP: testing conditions
* Update status API
* Add tests
* Detect endpoint
* Update manifests
* Remove old code and use proper condition check
* Fix compilation error
* Watch the Gateway resources
* Rename fields
* Add missing port
* Add ingress endpoint to the kubeadm
* Error if access points are empty
* Check the spec and status to delay the creation of the kubeadm
* Use the spec for the hostname
* Update api/v1alpha1/tenantcontrolplane_types.go
Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
* PR fixes, CEL k8s validations, proper status updates checks
* more context and separation of functions
* resolve all pr comments, with indexer
* merge master - go {sum,mod} updates dependabot
* Feat: Gateway Routes Specs, plus resource and status init progress
* Use Gateway API v1.2.0
* merge master - go {sum,mod} updates dependabot
* sum go mod tidy
* leftover comments
* clean go.sum
* fix: missing generated crds spec
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* docs: gateway api support
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* golint comments
* linting and test fix.
* Gateway API resource watching was made conditional to prevent crashes when CRDs are absent, and TLSRoute creation now returns an error when the service isn't ready instead of creating invalid resources with empty rules.
* unit test was incorrect after all the fixes we did, gracefull errors are not expected due to conditional adds
* fix(conditional-indexer): Gateway Indexer should also be conditional
* fix(conditional-indexer): Gateway Indexer should also be conditional
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
Co-authored-by: Hadrien Kohl <hadrien.kohl@gmail.com>
Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
* feat: loose control over k8s patch version
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(ci): fixing no space left on device
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(docs): document how to install helm kamaji-crds
* fix(docs): document how to install helm kamaji-crds
---------
Co-authored-by: bsctl <bsctl@clastix.io>
* fix(coredns): using patch for deployment and service reconciliation
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(kubeproxy): using patch for daemonset reconciliation
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
This commit extends CRD API: Added hostNetwork field to KonnectivityAgentSpec struct.
It's false by default so it's backwards compatible.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat: pausing reconciliation of controlled objects
Objects such as TenantControlPlane and Secret can be annotated with
kamaji.clastix.io/paused to prevent controllers from processing them.
This will stop reconciling objects for debugging or other purposes.
Annotation value is irrelevant, just the key presence is evaluated.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* docs: pausing reconciliation of controlled objects
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(logs): typo for deleted resources
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
This patch switches default kubelet-preferred-address-types to
"InternalIP,ExternalIP,Hostname" to avoid failures in kube-apiserver
connection to kubelet when node hostnames are not resolvable by the
external DNS server. This improves out-of-the-box reliability across
most environments by choosing node `InternalIP` as the preferred mode
to reach Kubelet.
Signed-off-by: Parth Yadav <parthyadav3105@gmail.com>
* feat(migration): customising timeout via tcp annotation
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* docs: customising migration timeout via tcp annotation
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* fix(migrate): delete job in case of timeout change
This will delete the failed job due to an incorrect timeout and performs
the creation of a new object rather than updating it, since its
immutability in the API specification.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(migration): cleanup prior migration
When using the annotation `kamaji.clastix.io/cleanup-prior-migration`
with a true boolean value, Kamaji will perform a clean-up on the target
DataStore to avoid stale resources when back and forth migrations occur.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* docs: cleanup prior migration
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat: buffered channels for generic events
Channels used for GenericEvent feeding for cross controllers triggers
are now buffered according to the --max-concurrent-tcp-reconciles: this
is required to avoid channel full errors when dealing with large
management clusters serving a sizeable amount of Tenant Control Planes.
Increasing this value will put more pressure on memory (mostly for GC)
and CPU (provisioning multiple certificates at the same time).
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* refactor: retrying datastore status update
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(performance): reducing memory consumption for channel triggers
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(datastore): reconcile events only for root object changes
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat: waiting soot manager exit before termination
This change introduces a grace period of 10 seconds before abruptly
terminating the Tenant Control Plane deployment, allowing the soot
manager to complete its exit procedure and avoid false positive errors
due to API Server being unresponsive due to user deletion.
Aim of this change is reducing the amount of false positive errors upon
mass deletion of Tenant COntrol Plane objects.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* refactor: unbuffered channel with timeout
WatchesRawSource is non blocking, no need to check if channel is full.
To prevent deadlocks a WithTimeout check has been introduced.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
This change is required for the enterprise offering where the Kamaji
stable image is hosted in a container registry with authentication and
can't be pulled with no credentials: when a migrate job is spun up it
resuses the same Kamaji controller ServiceAccount which will offer its
image pull credentials.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* test: add scale to zero e2e test
Signed-off-by: Mario Valderrama <mario.valderrama@ionos.com>
* fix: retry create token command
* fix: use correct assertion
---------
Signed-off-by: Mario Valderrama <mario.valderrama@ionos.com>
* feat(api): introducing sleeping status
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(helm)!: introducing sleeping status
Marking this commit as breaking since a CustomResourceDefinition update
is required for users dealing with scale to zero since the introduction
of the new enum for the status field.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* docs: introducing sleeping status
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat: Validate DataStores with CEL using the following rules
- certificateAuthority privateKey must have secretReference or content when driver is etcd
- clientCertificate must have secretReference or content when driver is etcd
- clientCertificate privateKey must have secretReference or content when driver is etcd
- When driver is not etcd and tlsConfig exists, certificateAuthority must be null or contain valid content
- When driver is not etcd and tlsConfig exists, clientCertificate must be null or contain valid content
- When driver is not etcd and basicAuth exists, username must have secretReference or content
- When driver is not etcd and basicAuth exists, password must have secretReference or content
- When driver is not etcd, either tlsConfig or basicAuth must be provided
Signed-off-by: aerosouund <aerosound161@gmail.com>
* fix: Add extra rule
Signed-off-by: aerosouund <aerosound161@gmail.com>
* fix: ginkgo flag ordering
Signed-off-by: aerosouund <aerosound161@gmail.com>
* fix: Fix syntax of tls or basic auth rule and remove the certificate authority rule
Signed-off-by: aerosouund <aerosound161@gmail.com>
* test: Add ginkgo tests for validations
Signed-off-by: aerosouund <aerosound161@gmail.com>
* fix(test): missing default values
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(ci): running integration tests as gh job
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: aerosouund <aerosound161@gmail.com>
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
Addresses #688, this commit removes the deprecated `spec.loadBalancerIP`.
With the property being set in the service, the AWS cloud controller complained and caused issues.
This commit introduces a breaking change such as the removal of
the default bootstrap token created by kubeadm on an idempotent basis.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
- Fixes a deployment issue with CD tools like ArgoCD.
- apiVersion and kind not set in source, causing drift.
- Ensures consistent state across deployments.
Signed-off-by: kahirokunn <okinakahiro@gmail.com>
* feat(webhook): validating api server cert sans
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(controller): validating api server cert sans
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* Update README.md
Minor changes to helm deployment instructions
* further changes to improve helm deployment instructions
* ran make -C charts/kamaji docs
* fixed helm deployment instructions
* chore(kubeadm): bumping up support to v1.31.3
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(deps): bumping up support to v1.31.3
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* fix: cel for load balancer class
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* fix(helm): cel for load balancer class
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat: automatically set dns service address
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(helm): automatically set dns service address
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* docs: automatically set dns service address
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* feat(crd): add LoadBalancerSourceRanges field and integrate with service resource
* test(crd): add tests for CEL validation logic
* feat(webhook): implement LoadBalancerSourceRanges validation logic for CIDRs
* test(webhook): add tests for webhook validation logic
* test: modify Makefile for envtest setup
* docs: add LoadBalancerSourceRanges field to API reference
* fix(adopters): order alphabetically according to the header
Signed-off-by: Jan Schoone <jan@jass.es>
* feat(adopters): add Sovereign Cloud Stack
Signed-off-by: Jan Schoone <jan@jass.es>
---------
Signed-off-by: Jan Schoone <jan@jass.es>
* feat: Add DataStoreSchema field to TCP spec
* feat: Read DB_SCHEMA from TCP spec field
* feat: Default DataStoreSchema in webhook
* fix: Catch unsetting the dataStore via CEL
* fix: Apply all patches, not only the first
This also includes converting OnUpdate() to a no-op, as the
existence and immutability of the fields are already checked
by the API server, thanks to kubebuilder markers.
The webhook ensures that fields like dataStore, dataStoreSchema
are defaulted during creation (if unset), and the CEL expressions
prohibit unsetting them during update.
* test: Add tests for defaulting webhook
* fix: typo
* fix: Linter issues
* fix: make apidoc
* Update TCP CRD in charts folder
* fix: Don't run E2E tests during `make test`
* fix: Use proper `metav1` import name
* feat: Handle updates of TCPs without dataStoreSchema (+ tests)
* fix: Prioritize Status over Spec
Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
* Update goDoc on DataStore field
* make apidoc
---------
Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
A bug has been introduced with #527 which doesn't handle properly all the required business logic, such as the application of customised labels, as well as the handling of the controller Resource.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(makefile): installing cert-manager via helm
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore: removing need of kustomize in favor of yq
By removing kustomize generation files we can simply release, despite
the bundles must be removed since based on kustomize despite never being
used.
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore(ci): aligning to latest manifest generation strategy
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
---------
Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
* chore: improve error handling and logging for certificate operations
- Enhance error reporting in GenerateCertificatePrivateKeyPair function
- Add detailed error checks for CA certificate and private key parsing
- Implement check for expected number of certificate files
- Improve error logging in APIServerCertificate resource
This commit preserves more details about certificate-related issues,
aiding in debugging and troubleshooting.
* feat: support loadbalancer hostname resolution
Add functionality to resolve loadbalancer hostname to IP address in DeclaredControlPlaneAddress method.
This enhances the existing IP address handling by allowing the use of hostnames for loadbalancers.
- Add hostname check in addition to IP check
- Implement hostname resolution using net.LookupIP
- Return the first resolved IP address if available
* fix: Remove hostname support for LoadBalancer ingress
- Extract LoadBalancer address logic to separate function
- Remove hostname resolution for LoadBalancer ingress
- Add explanatory comments on reasons for not supporting hostnames
* fix: replace fmt and vet with golint
- Remove fmt and vet targets
- Update build target to use golint instead of fmt and vet
- Remove fmt and vet dependencies from run target
* fix: lint errors
@@ -7,11 +7,32 @@ Feel free to open a Pull-Request to get yours listed.
| Type | Name | Since | Website | Use-Case |
|:-|:-|:-|:-|:-|
| End-user | KINX | 2024 | [link](https://kinx.net/?lang=en) | KINX is an Internet infrastructure service provider and will use kamaji for its new [Managed Kubernetes Service](https://kinx.net/service/cloud/kubernetes/intro/?lang=en). |
| End-user | sevensphere | 2023 | [link](https://www.sevensphere.io) | Sevensphere provides consulting services for end-user companies / cloud providers and uses Kamaji for designing cloud/on-premises Kubernetes-as-a-Service platform. |
| Vendor | Ænix | 2023 | [link](https://aenix.io/) | Ænix provides consulting services for cloud providers and uses Kamaji for running Kubernetes-as-a-Service in free PaaS platform [Cozystack](https://cozystack.io). |
| Vendor | Netsons | 2023 | [link](https://www.netsons.com) | Netsons is an Italian hosting and cloud provider and uses Kamaji in its [Managed Kubernetes](https://www.netsons.com/kubernetes) offering. |
| Vendor | Aknostic | 2023 | [link](https://aknostic.com) | Aknostic is a cloud-native consultancy company using Kamaji to build a Kubernetes based PaaS. |
| Vendor | Aruba | 2025 | [link](https://www.arubacloud.com/) | Aruba Cloud is an Italian Cloud Service Provider using Kamaji to build and offer [Managed Kubernetes Service](https://my.arubacloud.com). |
| Vendor | CBWS | 2025 | [link](https://cbws.nl) | CBWS is an European Cloud Provider using Kamaji to build and offer their [Managed Kubernetes Service](https://cbws.nl/cloud/kubernetes/). |
| Vendor | Coredge | 2025 | [link](https://coredge.io/) | Coredge uses Kamaji in its K8saaS offering to save infrastructure costs in its Sovereign Cloud & AI Infrastructure Platform for end-user organisations. |
| Vendor | DCloud | 2024 | [link](https://dcloud.co.id) | DCloud is an Indonesian Cloud Provider using Kamaji to build and offer [Managed Kubernetes Service](https://dcloud.co.id/dkubes.html). |
| Vendor | Dinova | 2025 | [link](https://dinova.one/) | Dinova is an Italian cloud services provider that integrates Kamaji in its datacenters to offer fully managed Kubernetes clusters. |
| Vendor | Hikube | 2024 | [link](https://hikube.cloud/) | Hikube.cloud is a Swiss sovereign cloud platform with triple replication across three Swiss datacenters, offering enterprise-grade infrastructure with full data sovereignty. |
| End-user | KINX | 2024 | [link](https://kinx.net/?lang=en) | KINX is an Internet infrastructure service provider and will use kamaji for its new [Managed Kubernetes Service](https://kinx.net/service/cloud/kubernetes/intro/?lang=en). |
| End-user | Namecheap | 2025 | [link](https://www.namecheap.com/) | Namecheap is an ICANN-accredited domain registrar and web hosting company that provides a wide range of internet-related services and uses Kamaji for both internal and external services. |
| Vendor | Netalia | 2025 | [link](https://www.netalia.it) | Netalia uses Kamaji for the Italian cloud
| Vendor | Netsons | 2023 | [link](https://www.netsons.com) | Netsons is an Italian hosting and cloud provider and uses Kamaji in its [Managed Kubernetes](https://www.netsons.com/kubernetes) offering. |
| Vendor | NVIDIA | 2024 | [link](https://github.com/NVIDIA/doca-platform) | DOCA Platform Framework manages provisioning and service orchestration for NVIDIA Bluefield DPUs. |
| R&D | Orange | 2024 | [link](https://gitlab.com/Orange-OpenSource/kanod) | Orange is a French telecommunications company using Kamaji for experimental research purpose, with Kanod research solution. |
| Vendor | Platform9 | 2024 | [link](https://elasticmachinepool.com) | Platform9 uses Kamaji in its offering - Elastic Machine Pool, which is a tool for optimizing the cost of running kubernetes clusters in EKS. |
| Vendor | Qumulus | 2024 | [link](https://www.qumulus.io) | Qumulus is a cloud provider and plans to use Kamaji for it's hosted Kubernetes service |
| End-user | sevensphere | 2023 | [link](https://www.sevensphere.io) | Sevensphere provides consulting services for end-user companies / cloud providers and uses Kamaji for designing cloud/on-premises Kubernetes-as-a-Service platform. |
| End-user | Sicuro Tech Lab | 2024 | [link](https://sicurotechlab.it/) | Sicuro Tech Lab offers cloud infrastructure for Web Agencies and uses kamaji to provide managed k8s services. |
| Vendor | Sovereign Cloud Stack | 2024 | [link](https://sovereigncloudstack.org) | Sovereign Cloud Stack develops a standardized cloud platform and uses Kamaji in there Kubernetes-as-a-Service reference implementation |
| R&D | TIM | 2024 | [link](https://www.gruppotim.it) | TIM is an Italian telecommunications company using Kamaji for experimental research and development purposes. |
| End-user | Tinext Cloud | 2025 | [link](https://cloud.tinext.com) | Tinex Cloud is a Swiss cloud service provider using Kamaji to build their Managed Kubernetes Services. |
| Vendor | Ænix | 2023 | [link](https://aenix.io/) | Ænix provides consulting services for cloud providers and uses Kamaji for running Kubernetes-as-a-Service in free PaaS platform [Cozystack](https://cozystack.io). |
| End-user | Rackspace | 2024 | [link](https://spot.rackspace.com/) | Rackspace Spot uses Kamaji to manage our instances, offering fully-managed kubernetes infrastructure, auctioned in an open market. |
| R&D | IONOS Cloud | 2024 | [link](https://cloud.ionos.com/) | IONOS Cloud is a German Cloud Provider evaluating Kamaji for its [Managed Kubernetes platform](https://cloud.ionos.com/managed/kubernetes). |
| Vendor | OVHCloud | 2025 | [link](https://www.ovhcloud.com/) | OVHCloud is a European Cloud Provider that will use Kamaji for its Managed Kubernetes Service offer. |
| Vendor | WOBCOM GmbH | 2024 | [link](https://www.wobcom.de/) | WOBCOM provides an [**Open Digital Platform**](https://www.wobcom.de/geschaeftskunden/odp/) solution for Smart Cities, which is provided for customers in a Managed Kubernetes provided by Kamaji. |
| Vendor | Mistral AI | 2025 | [link](https://mistral.ai/products/mistral-compute) | Mistral provides a baremetal kubernetes service that uses Kamaji for control plane management. |
### Adopter Types
@@ -20,3 +41,5 @@ Feel free to open a Pull-Request to get yours listed.
**Integration**: The organization has a product that integrates with Kamaji, but does not contain Kamaji.
**Vendor**: The organization packages Kamaji in their product and sells it as part of their product.
**R&D**: Company that exploring innovative technologies and solutions for research and development purposes.
controller-gen:$(CONTROLLER_GEN)## Download controller-gen locally if necessary.
$(CONTROLLER_GEN):$(LOCALBIN)
test -s $(LOCALBIN)/controller-gen ||GOBIN=$(LOCALBIN)CGO_ENABLED=0 go install -ldflags="-s -w" sigs.k8s.io/controller-tools/cmd/controller-gen@v0.20.0
GOLANGCI_LINT=$(shell pwd)/bin/golangci-lint
golangci-lint:## Download golangci-lint locally if necessary.
golangci-lint:$(GOLANGCI_LINT)## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT):$(LOCALBIN)
test -s $(LOCALBIN)/golangci-lint ||GOBIN=$(LOCALBIN)CGO_ENABLED=0 go install -ldflags="-s -w" github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.2
KUSTOMIZE=$(shell pwd)/bin/kustomize
kustomize:## Download kustomize locally if necessary.
$(call install-kustomize,$(KUSTOMIZE),3.8.7)
.PHONY:apidocs-gen
apidocs-gen:$(APIDOCS_GEN)## Download crdoc locally if necessary.
$(APIDOCS_GEN):$(LOCALBIN)
test -s $(LOCALBIN)/crdoc ||GOBIN=$(LOCALBIN)CGO_ENABLED=0 go install -ldflags="-s -w" fybrik.io/crdoc@latest
APIDOCS_GEN=$(shell pwd)/bin/crdoc
apidocs-gen:## Download crdoc locally if necessary.
envtest:$(ENVTEST)## Download envtest-setup locally if necessary.
$(ENVTEST):$(LOCALBIN)
test -s $(LOCALBIN)/setup-envtest ||GOBIN=$(LOCALBIN)CGO_ENABLED=0 go install -ldflags="-s -w" sigs.k8s.io/controller-runtime/tools/setup-envtest@$(ENVTEST_VERSION)
##@ Development
manifests:controller-gen## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
**Kamaji** is a**Kubernetes Control Plane Manager** leveraging on the concept of [**Hosted Control Plane**](https://clastix.io/post/the-raise-of-hosted-control-plane-in-kubernetes/).
**Kamaji** is the**Kubernetes Control Plane Manager** leveraging on the concept of [**Hosted Control Plane**](https://clastix.io/post/the-raise-of-hosted-control-plane-in-kubernetes/).
Kamaji's approach is based on running the Kubernetes Control Plane components in Pods instead of dedicated machines.
This allows operating Kubernetes clusters at scale, with a fraction of the operational burden.
@@ -53,7 +53,7 @@ The state is managed by the `Datastore` API, a cluster-scoped resource which can
- **Managing core addons**: Kamaji allows configuring automatically `kube-proxy`, `CoreDNS`, and `konnectivity`, with automatic remediation in case of user errors (e.g.: deleting the `CoreDNS` deployment).
- **Auto Healing**: the `TenantControlPlane` objects in the management cluster are tracked by Kamaji, in case of deletion of those, everything is created in an idempotent way.
- **Datastore multi-tenancy**: optionally, Kamaji allows running multiple Control Planes on the same _Datastore_ instance leveraging on the multi-tenancy of each driver, decreasing operations and optimizing costs.
- **Overcoming `etcd` limitations**: optionally, Kamaji allows using a different _Datastore_ thanks to [`kine`](https://github.com/k3s-io/kine) by supporting `MySQL` or`PostgreSQL` as an alternative.
- **Overcoming `etcd` limitations**: optionally, Kamaji allows using a different _Datastore_ thanks to [`kine`](https://github.com/k3s-io/kine) by supporting `MySQL`,`PostgreSQL`, or `NATS` as an alternative.
- **Simplifying mixed-networks setup**: thanks to [`Konnectivity`](https://kubernetes.io/docs/tasks/extend-kubernetes/setup-konnectivity/),
the Tenant Control Plane is connected to the worker nodes hosted in a different network, overcoming the no-NAT availability when dealing with nodes with a non routable IP address
(e.g.: worker nodes in a different infrastructure).
@@ -104,7 +104,7 @@ Since Kamaji is just focusing on the Control Plane a [Kamaji's Cluster API Contr
- [x] Dynamic address on Load Balancer
- [x] Zero Downtime Tenant Control Plane upgrade
- [x] [Join worker nodes from anywhere thanks to Konnectivity](https://kamaji.clastix.io/concepts/#konnectivity)
- [x] [Alternative datastore MySQL and PostgreSQL](https://kamaji.clastix.io/guides/alternative-datastore/)
- [x] [Pool of multiple datastores](https://kamaji.clastix.io/concepts/#datastores)
- [x] [Seamless migration between datastores](https://kamaji.clastix.io/guides/datastore-migration/)
- [ ] Automatic assignment to a datastore
@@ -122,6 +122,9 @@ Since Kamaji is just focusing on the Control Plane a [Kamaji's Cluster API Contr
- YouTube ▶️ [Equinix, Kamaji, and Cluster API](https://www.youtube.com/watch?v=TLBTqROj_wA)
- YouTube ▶️ [Rancher & Kamaji: solving multitenancy challenges in the Kubernetes world](https://www.youtube.com/watch?v=VXHNrMmlF8U)
- YouTube ▶️ [Enabling Self-Service Kubernetes clusters with Kamaji and Paralus](https://www.youtube.com/watch?v=JWA2LwZazM0)
- YouTube ▶️ [Hosted Control Plane on Kubernetes (HPC) with Kamaji and K0mostron by Hervé Leclerc, ALTER WAY](https://www.youtube.com/watch?v=vmRdE2ngn78)
- Medium 📖 [Set up Virtual Control Planes with Kamaji on Minikube, by Ben Soer](https://medium.com/@bensoer/set-up-virtual-control-planes-with-kamaji-on-minikube-a540be0275aa)
- Hands-On tutorial 📖 [How to build your own managed Kubernetes service on Hetzner Cloud, by Hans Jörg Wieland](https://wieland.tech/blog/kamaji-cluster-api-and-etcd)
### 🏷️ Versioning
@@ -147,7 +150,7 @@ In case of **✨ Feature Requests** please use the [Discussion's Feature Request
### 📝 License
The Kamaji Cluster API Control Plane provider is licensed under Apache 2.0.
Kamaji is licensed under Apache 2.0.
The code is provided as-is with no warranties.
### 🛟 Commercial Support
@@ -157,4 +160,4 @@ The code is provided as-is with no warranties.
If you're looking to run Kamaji in production and would like to learn more, **CLASTIX** can help by offering [Open Source support plans](https://clastix.io/support),
as well as providing a comprehensive Enterprise Platform named [CLASTIX Enterprise Platform](https://clastix.cloud/), built on top of the Kamaji and [Capsule](https://capsule.clastix.io/) project (now donated to CNCF as a Sandbox project).
Feel free to get in touch with the provided [Contact form](https://clastix.io/contact).
Feel free to get in touch with the provided [Contact form](https://clastix.io/contact).
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Datastore driver is immutable"
typeDriverstring
@@ -16,13 +17,21 @@ var (
EtcdDriverDriver="etcd"
KineMySQLDriverDriver="MySQL"
KinePostgreSQLDriverDriver="PostgreSQL"
KineNatsDriverDriver="NATS"
)
//+kubebuilder:validation:MinItems=1
//+kubebuilder:validation:MinItems=1
typeEndpoints[]string
// DataStoreSpec defines the desired state of DataStore.
// +kubebuilder:validation:XValidation:rule="(self.driver == \"etcd\") ? (self.tlsConfig != null && (has(self.tlsConfig.certificateAuthority.privateKey.secretReference) || has(self.tlsConfig.certificateAuthority.privateKey.content))) : true", message="certificateAuthority privateKey must have secretReference or content when driver is etcd"
// +kubebuilder:validation:XValidation:rule="(self.driver == \"etcd\") ? (self.tlsConfig != null && (has(self.tlsConfig.clientCertificate.certificate.secretReference) || has(self.tlsConfig.clientCertificate.certificate.content))) : true", message="clientCertificate must have secretReference or content when driver is etcd"
// +kubebuilder:validation:XValidation:rule="(self.driver == \"etcd\") ? (self.tlsConfig != null && (has(self.tlsConfig.clientCertificate.privateKey.secretReference) || has(self.tlsConfig.clientCertificate.privateKey.content))) : true", message="clientCertificate privateKey must have secretReference or content when driver is etcd"
// +kubebuilder:validation:XValidation:rule="(self.driver != \"etcd\" && has(self.tlsConfig) && has(self.tlsConfig.clientCertificate)) ? (((has(self.tlsConfig.clientCertificate.certificate.secretReference) || has(self.tlsConfig.clientCertificate.certificate.content)))) : true", message="When driver is not etcd and tlsConfig exists, clientCertificate must be null or contain valid content"
// +kubebuilder:validation:XValidation:rule="(self.driver != \"etcd\" && has(self.basicAuth)) ? ((has(self.basicAuth.username.secretReference) || has(self.basicAuth.username.content))) : true", message="When driver is not etcd and basicAuth exists, username must have secretReference or content"
// +kubebuilder:validation:XValidation:rule="(self.driver != \"etcd\" && has(self.basicAuth)) ? ((has(self.basicAuth.password.secretReference) || has(self.basicAuth.password.content))) : true", message="When driver is not etcd and basicAuth exists, password must have secretReference or content"
// +kubebuilder:validation:XValidation:rule="(self.driver != \"etcd\") ? (has(self.tlsConfig) || has(self.basicAuth)) : true", message="When driver is not etcd, either tlsConfig or basicAuth must be provided"
typeDataStoreSpecstruct{
// The driver to use to connect to the shared datastore.
DriverDriver`json:"driver"`
@@ -33,7 +42,8 @@ type DataStoreSpec struct {
// This value is optional.
BasicAuth*BasicAuth`json:"basicAuth,omitempty"`
// Defines the TLS/SSL configuration required to connect to the data store in a secure way.
TLSConfigTLSConfig`json:"tlsConfig"`
// This value is optional.
TLSConfig*TLSConfig`json:"tlsConfig,omitempty"`
}
// TLSConfig contains the information used to connect to the data store using a secured connection.
@@ -42,7 +52,7 @@ type TLSConfig struct {
// The key reference is required since etcd authentication is based on certificates, and Kamaji is responsible in creating this.
// CompoundValue allows defining a static, or a dynamic value.
// Options are mutually exclusive, just one should be picked up.
// +kubebuilder:validation:XValidation:rule="(has(self.stringValue) || has(self.fromDefinition)) && !(has(self.stringValue) && has(self.fromDefinition))",message="Either stringValue or fromDefinition must be set, but not both."
typeCompoundValuestruct{
// StringValue is a static string value.
StringValuestring`json:"stringValue,omitempty"`
// FromDefinition is used to generate a dynamic value,
// it uses the dot notation to access fields from the referenced TenantControlPlane object:
// Defining the options for an Optional Ingress which will expose API Server of the Tenant Control Plane
Ingress*IngressSpec`json:"ingress,omitempty"`
// Defining the options for an Optional Gateway which will expose API Server of the Tenant Control Plane
Gateway*GatewaySpec`json:"gateway,omitempty"`
}
// IngressSpec defines the options for the ingress which will expose API Server of the Tenant Control Plane.
@@ -93,6 +154,17 @@ type IngressSpec struct {
Hostnamestring`json:"hostname,omitempty"`
}
// GatewaySpec defines the options for the Gateway which will expose API Server of the Tenant Control Plane.
// +kubebuilder:validation:XValidation:rule="!has(self.parentRefs) || size(self.parentRefs) == 0 || self.parentRefs.all(ref, !has(ref.port) && !has(ref.sectionName))",message="parentRefs must not specify port or sectionName, these are set automatically by Kamaji"
typeGatewaySpecstruct{
// AdditionalMetadata to add Labels and Annotations support.
//+kubebuilder:validation:XValidation:rule="!(self.mode == 'DaemonSet' && has(self.replicas) && self.replicas != 0) && !(self.mode == 'Deployment' && has(self.replicas) && self.replicas == 0)",message="replicas must be 0 (or unset) when mode is DaemonSet, and greater than 0 (or unset) when mode is Deployment"
typeKonnectivityAgentSpecstruct{
// AgentImage defines the container image for Konnectivity's agent.
// DataStoreOverride defines which kubernetes resource will be stored in a dedicated datastore.
typeDataStoreOverridestruct{
// Resource specifies which kubernetes resource to target.
Resourcestring`json:"resource,omitempty"`
// DataStore specifies the DataStore that should be used to store the Kubernetes data for the given Resource.
DataStorestring`json:"dataStore,omitempty"`
}
// TenantControlPlaneSpec defines the desired state of TenantControlPlane.
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.dataStore) || has(self.dataStore)", message="unsetting the dataStore is not supported"
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.dataStoreSchema) || has(self.dataStoreSchema)", message="unsetting the dataStoreSchema is not supported"
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.dataStoreUsername) || has(self.dataStoreUsername)", message="unsetting the dataStoreUsername is not supported"
// +kubebuilder:validation:XValidation:rule="!has(self.networkProfile.loadBalancerSourceRanges) || (size(self.networkProfile.loadBalancerSourceRanges) == 0 || self.controlPlane.service.serviceType == 'LoadBalancer')", message="LoadBalancer source ranges are supported only with LoadBalancer service type"
// +kubebuilder:validation:XValidation:rule="!has(self.networkProfile.loadBalancerClass) || self.controlPlane.service.serviceType == 'LoadBalancer'", message="LoadBalancerClass is supported only with LoadBalancer service type"
// +kubebuilder:validation:XValidation:rule="self.controlPlane.service.serviceType != 'LoadBalancer' || (oldSelf.controlPlane.service.serviceType != 'LoadBalancer' && self.controlPlane.service.serviceType == 'LoadBalancer') || has(self.networkProfile.loadBalancerClass) == has(oldSelf.networkProfile.loadBalancerClass)",message="LoadBalancerClass cannot be set or unset at runtime"
typeTenantControlPlaneSpecstruct{
// DataStore allows to specify a DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
// This parameter is optional and acts as an override over the default one which is used by the Kamaji Operator.
// Migration from a different DataStore to another one is not yet supported and the reconciliation will be blocked.
DataStorestring`json:"dataStore,omitempty"`
ControlPlaneControlPlane`json:"controlPlane"`
// WritePermissions allows to select which operations (create, delete, update) must be blocked:
// by default, all actions are allowed, and API Server can write to its Datastore.
//
// By blocking all actions, the Tenant Control Plane can enter in a Read Only mode:
// this phase can be used to prevent Datastore quota exhaustion or for your own business logic
// (e.g.: blocking creation and update, but allowing deletion to "clean up" space).
// DataStore specifies the DataStore that should be used to store the Kubernetes data for the given Tenant Control Plane.
// When Kamaji runs with the default DataStore flag, all empty values will inherit the default value.
// By leaving it empty and running Kamaji with no default DataStore flag, it is possible to achieve automatic assignment to a specific DataStore object.
//
// Migration from one DataStore to another backed by the same Driver is possible. See: https://kamaji.clastix.io/guides/datastore-migration/
// Migration from one DataStore to another backed by a different Driver is not supported.
DataStorestring`json:"dataStore,omitempty"`
// DataStoreSchema allows to specify the name of the database (for relational DataStores) or the key prefix (for etcd). This
// value is optional and immutable. Note that Kamaji currently doesn't ensure that DataStoreSchema values are unique. It's up
// to the user to avoid clashes between different TenantControlPlanes. If not set upon creation, Kamaji will default the
// DataStoreSchema by concatenating the namespace and name of the TenantControlPlane.
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="changing the dataStoreSchema is not supported"
//+kubebuilder:printcolumn:name="Control-Plane endpoint",type="string",JSONPath=".status.controlPlaneEndpoint",description="Tenant Control Plane Endpoint (API server)"
//+kubebuilder:printcolumn:name="Kubeconfig",type="string",JSONPath=".status.kubeconfig.admin.secretName",description="Secret which contains admin kubeconfig"
//+kubebuilder:printcolumn:name="Installed Version",type="string",JSONPath=".status.kubernetesResources.version.version",description="The actual installed Kubernetes version from status"
//+kubebuilder:printcolumn:name="Control-Plane endpoint",type="string",JSONPath=".status.controlPlaneEndpoint",description="Tenant Control Plane Endpoint (API server)"
//+kubebuilder:printcolumn:name="Kubeconfig",type="string",JSONPath=".status.kubeconfig.admin.secretName",description="Secret which contains admin kubeconfig"
There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`.
The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it.
Specify your overrides file when you install the Chart:
The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. Any values in `values.yaml` that weren’t overridden will keep their defaults.
If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example:
| fullnameOverride | string | `""` | Overrides the full name of the resources created by the chart. |
| kamajiCertificateName | string | `"kamaji-serving-cert"` | The cert-manager Certificate resource name, holding the Certificate Authority for webhooks. |
| kamajiNamespace | string | `"kamaji-system"` | The namespace where Kamaji has been installed: required to inject the Certificate Authority for cert-manager. |
| kamajiService | string | `"kamaji-webhook-service"` | The Kamaji webhook Service name. |
| nameOverride | string | `""` | Overrides the name of the chart for resource naming purposes. |
There are two methods for specifying overrides of values during Chart installation: `--values` and `--set`.
The `--values` option is the preferred method because it allows you to keep your overrides in a YAML file, rather than specifying them all on the command line. Create a copy of the YAML file `values.yaml` and add your overrides to it.
Specify your overrides file when you install the Chart:
The values in your overrides file `myvalues.yaml` will override their counterparts in the Chart's values.yaml file. Any values in `values.yaml` that weren’t overridden will keep their defaults.
If you only need to make minor customizations, you can specify them on the command line by using the `--set` option. For example:
{{-printf"%s/%s"(required"A valid .Values.kamajiNamespace is required".Values.kamajiNamespace)(required"A valid .Values.kamajiCertificateName is required".Values.kamajiCertificateName)}}
[Kamaji](https://github.com/clastix/kamaji) requires a [multi-tenant `etcd`](https://github.com/clastix/kamaji-internal/blob/master/deploy/getting-started-with-kamaji.md#setup-internal-multi-tenant-etcd) cluster.
This Helm Chart starting from v0.1.1 provides the installation of an internal `etcd` in order to streamline the local test. If you'd like to use an externally managed etcd instance, you can specify the overrides and by setting the value `etcd.deploy=false`.
@@ -27,9 +31,13 @@ This Helm Chart starting from v0.1.1 provides the installation of an internal `e
| datastore.basicAuth.passwordSecret.keyPath | string | `nil` | The Secret key where the data is stored. |
| datastore.basicAuth.passwordSecret.name | string | `nil` | The name of the Secret containing the password used to connect to the relational database. |
| datastore.basicAuth.passwordSecret.namespace | string | `nil` | The namespace of the Secret containing the password used to connect to the relational database. |
| datastore.basicAuth.usernameSecret.keyPath | string | `nil` | The Secret key where the data is stored. |
| datastore.basicAuth.usernameSecret.name | string | `nil` | The name of the Secret containing the username used to connect to the relational database. |
| datastore.basicAuth.usernameSecret.namespace | string | `nil` | The namespace of the Secret containing the username used to connect to the relational database. |
| datastore.endpoints | list | `[]` | (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically. |
| datastore.nameOverride | string | `nil` | The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to. |
| datastore.tlsConfig.certificateAuthority.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. |
| datastore.tlsConfig.certificateAuthority.certificate.name | string | `nil` | Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.certificateAuthority.certificate.namespace | string | `nil` | Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.certificateAuthority.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. |
| datastore.tlsConfig.certificateAuthority.privateKey.name | string | `nil` | Name of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.certificateAuthority.privateKey.namespace | string | `nil` | Namespace of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.certificate.keyPath | string | `nil` | Key of the Secret which contains the content of the certificate. |
| datastore.tlsConfig.clientCertificate.certificate.name | string | `nil` | Name of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.certificate.namespace | string | `nil` | Namespace of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.privateKey.keyPath | string | `nil` | Key of the Secret which contains the content of the private key. |
| datastore.tlsConfig.clientCertificate.privateKey.name | string | `nil` | Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. |
| datastore.tlsConfig.clientCertificate.privateKey.namespace | string | `nil` | Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore. |
| etcd.livenessProbe | object | `{"failureThreshold":8,"httpGet":{"path":"/health?serializable=true","port":2381,"scheme":"HTTP"},"initialDelaySeconds":10,"periodSeconds":10,"timeoutSeconds":15}` | The livenessProbe for the etcd container |
| etcd.overrides.caSecret.name | string | `"etcd-certs"` | Name of the secret which contains CA's certificate and private key. (default: "etcd-certs") |
| etcd.overrides.caSecret.namespace | string | `"kamaji-system"` | Namespace of the secret which contains CA's certificate and private key. (default: "kamaji-system") |
| etcd.overrides.clientSecret.name | string | `"root-client-certs"` | Name of the secret which contains ETCD client certificates. (default: "root-client-certs") |
| etcd.overrides.clientSecret.namespace | string | `"kamaji-system"` | Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji-system") |
| etcd.overrides.endpoints | object | `{"etcd-0":"etcd-0.etcd.kamaji-system.svc.cluster.local","etcd-1":"etcd-1.etcd.kamaji-system.svc.cluster.local","etcd-2":"etcd-2.etcd.kamaji-system.svc.cluster.local"}` | (map) Dictionary of the endpoints for the etcd cluster's members, key is the name of the etcd server. Don't define the protocol (TLS is automatically inflected), or any port, inflected from .etcd.peerApiPort value. |
| etcd.peerApiPort | int | `2380` | The peer API port which servers are listening to. |
| etcd.port | int | `2379` | The client request port. |
| etcd.serviceAccount.create | bool | `true` | Create a ServiceAccount, required to install and provision the etcd backing storage (default: true) |
| etcd.serviceAccount.name | string | `""` | Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "") |
| etcd.tolerations | list | `[]` | (array) Kubernetes affinity rules to apply to Kamaji etcd pods |
| defaultDatastoreName | string | `"default"` | If specified, all the Kamaji instances with an unassigned DataStore will inherit this default value. |
| extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones |
| fullnameOverride | string | `""` | |
| healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") |
@@ -115,9 +82,28 @@ Here the values you can override:
| image.repository | string | `"clastix/kamaji"` | The container image of the Kamaji controller. |
| image.tag | string | `nil` | Overrides the image tag whose default is the chart appVersion. |
| kubeconfigGenerator.podAnnotations | object | `{}` | The annotations to apply to the Kubeconfig Generator controller pods. |
| kubeconfigGenerator.podSecurityContext | object | `{"runAsNonRoot":true}` | The securityContext to apply to the Kubeconfig Generator controller pods. |
| kubeconfigGenerator.replicaCount | int | `2` | The number of the pod replicas for the Kubeconfig Generator controller. |
| kubeconfigGenerator.securityContext | object | `{"allowPrivilegeEscalation":false}` | The securityContext to apply to the Kubeconfig Generator controller container only. |
| kubeconfigGenerator.serviceAccountOverride | string | `""` | The name of the service account to use. If not set, the root Kamaji one will be used. |
| kubeconfigGenerator.tolerations | list | `[]` | Kubernetes node taints that the Kubeconfig Generator controller pods would tolerate |
| livenessProbe | object | `{"httpGet":{"path":"/healthz","port":"healthcheck"},"initialDelaySeconds":15,"periodSeconds":20}` | The livenessProbe for the controller container |
| loggingDevel.enable | bool | `false` | (string) Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false) |
| metricsBindAddress | string | `":8080"` | (string) The address the metric endpoint binds to. (default ":8080") |
| loggingDevel.enable | bool | `false` | Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false) |
| metricsBindAddress | string | `":8080"` | The address the metric endpoint binds to. (default ":8080") |
# -- A list of extra arguments to add to the kamaji controller default ones
extraArgs:[]
serviceMonitor:
# -- Toggle the ServiceMonitor true if you have Prometheus Operator installed and configured
enabled:false
etcd:
# -- Install an etcd with enabled multi-tenancy along with Kamaji
deploy:true
# -- The peer API port which servers are listening to.
peerApiPort:2380
# -- The client request port.
port:2379
# -- Install specific etcd image
image:
repository:quay.io/coreos/etcd
tag:"v3.5.6"
pullPolicy:IfNotPresent
# -- The livenessProbe for the etcd container
livenessProbe:
failureThreshold:8
httpGet:
path:/health?serializable=true
port:2381
scheme:HTTP
initialDelaySeconds:10
periodSeconds:10
timeoutSeconds:15
serviceAccount:
# -- Create a ServiceAccount, required to install and provision the etcd backing storage (default: true)
create:true
# -- Define the ServiceAccount name to use during the setup and provision of the etcd backing storage (default: "")
name:""
persistence:
size:10Gi
storageClassName:""
accessModes:
- ReadWriteOnce
# -- The custom annotations to add to the PVC
customAnnotations:{}
# volumeType: local
# -- (array) Kubernetes affinity rules to apply to Kamaji etcd pods
tolerations:[]
overrides:
caSecret:
# -- Name of the secret which contains CA's certificate and private key. (default: "etcd-certs")
name:etcd-certs
# -- Namespace of the secret which contains CA's certificate and private key. (default: "kamaji-system")
namespace:kamaji-system
clientSecret:
# -- Name of the secret which contains ETCD client certificates. (default: "root-client-certs")
name:root-client-certs
# -- Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji-system")
namespace:kamaji-system
# -- (map) Dictionary of the endpoints for the etcd cluster's members, key is the name of the etcd server. Don't define the protocol (TLS is automatically inflected), or any port, inflected from .etcd.peerApiPort value.
# -- The address the probe endpoint binds to. (default ":8081")
healthProbeBindAddress:":8081"
@@ -102,7 +38,7 @@ readinessProbe:
initialDelaySeconds:5
periodSeconds:10
# -- (string) The address the metric endpoint binds to. (default ":8080")
# -- The address the metric endpoint binds to. (default ":8080")
metricsBindAddress:":8080"
imagePullSecrets:[]
@@ -156,66 +92,67 @@ affinity: {}
temporaryDirectoryPath:"/tmp/kamaji"
loggingDevel:
# -- (string) Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false)
# -- Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error) (default false)
enable:false
datastore:
# -- (bool) Enable the Kamaji Datastore creation (default=true)
enabled:true
# -- (string) The Datastore name override, if empty and enabled=true defaults to `default`, if enabled=false, this is the name of the Datastore to connect to.
# -- (array) List of endpoints of the selected Datastore. When letting the Chart install the etcd datastore, this field is populated automatically.
endpoints:[]
basicAuth:
usernameSecret:
# -- The name of the Secret containing the username used to connect to the relational database.
name:
# -- The namespace of the Secret containing the username used to connect to the relational database.
namespace:
# -- The Secret key where the data is stored.
keyPath:
passwordSecret:
# -- The name of the Secret containing the password used to connect to the relational database.
name:
# -- The namespace of the Secret containing the password used to connect to the relational database.
namespace:
# -- The Secret key where the data is stored.
keyPath:
tlsConfig:
certificateAuthority:
certificate:
# -- Name of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the CA required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the certificate.
keyPath:
privateKey:
# -- Name of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the CA private key required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the private key.
keyPath:
clientCertificate:
certificate:
# -- Name of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the client certificate required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the certificate.
keyPath:
privateKey:
# -- Name of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore.
name:
# -- Namespace of the Secret containing the client certificate private key required to establish the mandatory SSL/TLS connection to the datastore.
namespace:
# -- Key of the Secret which contains the content of the private key.
keyPath:
# -- If specified, all the Kamaji instances with an unassigned DataStore will inherit this default value.
defaultDatastoreName:default
cfssl:
image:
repository:cfssl/cfssl
tag:latest
# -- Subchart: See https://github.com/clastix/kamaji-etcd/blob/master/charts/kamaji-etcd/values.yaml
kamaji-etcd:
deploy:true
fullnameOverride:kamaji-etcd
## -- Important, this must match your management cluster's clusterDomain, otherwise the init jobs will fail
clusterDomain:"cluster.local"
datastore:
enabled:true
name:default
# -- Disable the analytics traces collection
telemetry:
disabled:false
kubeconfigGenerator:
# -- Toggle to deploy the Kubeconfig Generator Deployment.
enabled:false
fullnameOverride:""
# -- The number of the pod replicas for the Kubeconfig Generator controller.
replicaCount:2
# -- The annotations to apply to the Kubeconfig Generator controller pods.
podAnnotations:{}
# -- The securityContext to apply to the Kubeconfig Generator controller pods.
podSecurityContext:
runAsNonRoot:true
# -- The name of the service account to use. If not set, the root Kamaji one will be used.
serviceAccountOverride:""
# -- The address the probe endpoint binds to.
healthProbeBindAddress:":8081"
# -- Enables the leader election.
enableLeaderElect:true
loggingDevel:
# -- Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error)
enable:false
# -- A list of extra arguments to add to the Kubeconfig Generator controller default ones.
extraArgs:[]
resources:
limits:
cpu:200m
memory:512Mi
requests:
cpu:200m
memory:512Mi
# -- The securityContext to apply to the Kubeconfig Generator controller container only.
cmd.Flags().StringVar(&metricsBindAddress,"metrics-bind-address",":8090","The address the metric endpoint binds to.")
cmd.Flags().StringVar(&healthProbeBindAddress,"health-probe-bind-address",":8091","The address the probe endpoint binds to.")
cmd.Flags().BoolVar(&leaderElect,"leader-elect",true,"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
cmd.Flags().DurationVar(&controllerReconcileTimeout,"controller-reconcile-timeout",30*time.Second,"The reconciliation request timeout before the controller withdraw the external resource calls, such as dealing with the Datastore, or the Tenant Control Plane API endpoint.")
cmd.Flags().StringVar(&managerNamespace,"pod-namespace",os.Getenv("POD_NAMESPACE"),"The Kubernetes Namespace on which the Operator is running in, required for the TenantControlPlane migration jobs.")
cmd.Flags().DurationVar(&certificateExpirationDeadline,"certificate-expiration-deadline",24*time.Hour,"Define the deadline upon certificate expiration to start the renewal process, cannot be less than a 24 hours.")
cmd.Flags().StringVar(&healthProbeBindAddress,"health-probe-bind-address",":8081","The address the probe endpoint binds to.")
cmd.Flags().BoolVar(&leaderElect,"leader-elect",true,"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
cmd.Flags().StringVar(&tmpDirectory,"tmp-directory","/tmp/kamaji","Directory which will be used to work with temporary files.")
cmd.Flags().StringVar(&kineImage,"kine-image","rancher/kine:v0.9.2-amd64","Container image along with tag to use for the Kine sidecar container (used only if etcd-storage-type is set to one of kine strategies).")
cmd.Flags().StringVar(&datastore,"datastore","etcd","The default DataStore that should be used by Kamaji to setup the required storage.")
cmd.Flags().StringVar(&migrateJobImage,"migrate-image",fmt.Sprintf("clastix/kamaji:%s",internal.GitTag),"Specify the container image to launch when a TenantControlPlane is migrated to a new datastore.")
cmd.Flags().StringVar(&kineImage,"kine-image","rancher/kine:v0.11.10-amd64","Container image along with tag to use for the Kine sidecar container (used only if etcd-storage-type is set to one of kine strategies).")
cmd.Flags().StringVar(&datastore,"datastore","","Optional, the default DataStore that should be used by Kamaji to setup the required storage of Tenant Control Planes with undeclared DataStore.")
cmd.Flags().StringVar(&migrateJobImage,"migrate-image",fmt.Sprintf("%s/clastix/kamaji:%s",internal.ContainerRepository,internal.GitTag),"Specify the container image to launch when a TenantControlPlane is migrated to a new datastore.")
cmd.Flags().IntVar(&maxConcurrentReconciles,"max-concurrent-tcp-reconciles",1,"Specify the number of workers for the Tenant Control Plane controller (beware of CPU consumption)")
cmd.Flags().StringVar(&managerNamespace,"pod-namespace",os.Getenv("POD_NAMESPACE"),"The Kubernetes Namespace on which the Operator is running in, required for the TenantControlPlane migration jobs.")
cmd.Flags().StringVar(&managerServiceName,"webhook-service-name","kamaji-webhook-service","The Kamaji webhook server Service name which is used to get validation webhooks, required for the TenantControlPlane migration jobs.")
cmd.Flags().StringVar(&webhookCAPath,"webhook-ca-path","/tmp/k8s-webhook-server/serving-certs/ca.crt","Path to the Manager webhook server CA, required for the TenantControlPlane migration jobs.")
cmd.Flags().DurationVar(&controllerReconcileTimeout,"controller-reconcile-timeout",30*time.Second,"The reconciliation request timeout before the controller withdraw the external resource calls, such as dealing with the Datastore, or the Tenant Control Plane API endpoint.")
cmd.Flags().BoolVar(&disableTelemetry,"disable-telemetry",false,"Disable the analytics traces collection.")
cmd.Flags().DurationVar(&certificateExpirationDeadline,"certificate-expiration-deadline",24*time.Hour,"Define the deadline upon certificate expiration to start the renewal process, cannot be less than a 24 hours.")
cmd.Flags().StringVar(&tenantControlPlane,"tenant-control-plane","","Namespaced-name of the TenantControlPlane that must be migrated (e.g.: default/test)")
cmd.Flags().StringVar(&targetDataStore,"target-datastore","","Name of the Datastore to which the TenantControlPlane will be migrated")
cmd.Flags().BoolVar(&cleanupPriorMigration,"cleanup-prior-migration",false,"When set to true, migration job will drop existing data in the target DataStore: useful to avoid stale data when migrating back and forth between DataStores.")
cmd.Flags().DurationVar(&timeout,"timeout",5*time.Minute,"Amount of time for the context timeout")
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.