Updating server components of YTsaurus
Important
This describes how to perform an update using the operator version 0.32.0 or later. For differences with older versions, see the section Migrating from enableFullUpdate to updatePlan.
This article describes the process of fully updating the server components of a YTsaurus cluster via the Kubernetes operator: how to prepare for the update, update the operator, modify the Ytsaurus specification, monitor the update progress, and verify the result.
What you need to know before updating
- Update only to the next major version.
- Update the cluster sequentially by major versions, without skipping intermediate ones: first
25.1 → 25.2, then25.2 → 25.3. Skipping a version may disrupt cluster operation. Within the target major version, you can select the latest minor version to get the most recent updates — for example,25.2.0 → 25.3.2. See available versions in the release list. - The update cannot be undone.
- Once the master servers exit
read-onlymode and apply irreversible changes, rolling back to the previous version is not supported. - Update the operator first, then the cluster.
- Before updating the cluster, update the operator. Its version must be compatible with the target cluster version. Check compatibility in the compatibility table.
- The cluster may be unavailable during the update.
- By default, the cluster is fully unavailable during the update — all operations and requests are interrupted. Schedule the update during a period of minimal load. If the cluster must remain available, choose a different strategy — see Update strategies.
Updating the cluster without downtime
If you need to update the cluster without downtime, configure the RollingUpdate strategy via the updatePlan field. See an example in the section Updating the cluster without downtime via RollingUpdate.
Cluster update
The update process consists of four steps:
1. Prepare the cluster for the update
Before changing the Ytsaurus specification, check the current state of the cluster and make sure the operator is ready to start a new update cycle.
-
Find out the current cluster version:
$ kubectl get YTsaurus <cluster_name> -n <namespace> -o jsonpath='{.spec.coreImage}' ghcr.io/ytsaurus/ytsaurus:stable-25.1.0-relwithdebinfo -
Check the cluster state:
$ kubectl get YTsaurus <cluster_name> -n <namespace> NAME CLUSTERSTATE UPDATESTATE UPDATINGCOMPONENTS BLOCKEDCOMPONENTS YTsaurus RunningBefore the update, the cluster must be in the
Runningstate. If the cluster is in another state, fix the issues first — see the Troubleshooting section. -
Make sure the operator is ready for the update. To do this, check its logs:
kubectl logs -n <namespace> deployment/ytsaurus-ytop-chart-controller-manager --tail=100 # If the deployment name is different, get the list kubectl get deployments -n <namespace>This is an important step: the operator must not be busy with pending actions. Proceed to the next step only when the logs contain the message
INFO YTsaurus is running and happy. This means the operator considers the cluster consistent and is not performing any pending actions.Important
If the operator does not report
running and happy, do not start the update. This may lead to unpredictable cluster behavior. -
Save a backup copy of the specification:
The file is required to enable rollback before passing the point of no return:
kubectl get YTsaurus <cluster_name> -n <namespace> -o yaml > ytsaurus-spec-backup.yamlAfter the master servers exit the
read‑onlymode and apply irreversible changes, rollback to the previous version is not supported.
If all checks are passed, you can proceed with updating the operator.
2. Update the operator
Update the operator first. New versions of server components may not work correctly with an older version of the operator.
Warning
The new version of the operator may trigger a cluster update immediately — without you changing coreImage. This happens if the new operator version generates static configs differently from the old one: the operator detects a discrepancy and starts reconciliation. For more details on the reasons and how to stop an unwanted update, see the section Automatic update after operator update.
Check the current operator version:
helm list -n <namespace>
See the list of releases and compatible versions on the releases page and in the compatibility table.
Update the operator:
helm upgrade YTsaurus --install oci://ghcr.io/ytsaurus/ytop-chart --version <new_version>
Verify that the operator has been updated:
kubectl get pods -n <namespace>
Right after the update, you may see both the old and new pods at the same time:
NAME READY STATUS RESTARTS AGE
ytsaurus-ytop-chart-controller-manager-6f67fd5d5c-6bbws 2/2 Running 0 21s
ytsaurus-ytop-chart-controller-manager-7478f9b6cb-qr8wd 2/2 Terminating 0 23h
After some time, the old pod will be removed:
NAME READY STATUS RESTARTS AGE
ytsaurus-ytop-chart-controller-manager-6f67fd5d5c-6bbws 2/2 Running 0 25s
3. Start the update
When you change the coreImage field in the Ytsaurus specification, the operator recreates pods for all server components from this specification, even if the image of a specific component hasn’t changed. This ensures version compatibility across all server components.
Components with their own release cycle — Query Tracker, YQL agent, and others — are not updated in this process. To learn how to update them, see the section Updating individual components. Before updating, check the compatibility of these components with the target cluster version in the compatibility table.
Save the current specification to a file for editing:
kubectl get YTsaurus <cluster_name> -n <namespace> -o yaml > ytsaurus-spec-new.yaml
Warning
Only save the specification from your running cluster using the kubectl get ytsaurus command. Do not use a specification from GitHub or another template: it won’t include your current settings — such as marked disks, encryption parameters, and custom settings. Applying a clean specification may break the cluster.
Make the following changes to the ytsaurus-spec-new.yaml file:
-
Set the
updatePlanfield with a list of components to update. For a full update, specify theEverythingclass — all server components will be updated. -
Change
coreImageto the next version. -
Select the target version on the releases page. Open the required release and copy the image tag
ghcr.io/ytsaurus/ytsaurus.
spec:
coreImage: ghcr.io/ytsaurus/ytsaurus:stable-25.2.0-relwithdebinfo # Next version
updatePlan:
- class: Everything # Full update of all server components
Important
Only update to the stable version following your current one. Do not use dev images from the main branch. After a successful update, rolling back to the previous version is not supported.
By default, the operator uses the BulkUpdate strategy — the cluster will be completely unavailable during the update. If the cluster must stay available, configure the RollingUpdate strategy via the updatePlan field in the ytsaurus-spec-new.yaml file before applying the changes. See an example in the section Updating without cluster downtime using RollingUpdate.
Apply the modified specification:
kubectl apply -f ytsaurus-spec-new.yaml
Expected output:
ytsaurus.cluster.ytsaurus.tech/<cluster_name> configured
Monitor the status in the UPDATESTATE field of the Ytsaurus resource:
kubectl get YTsaurus <cluster_name> -n <namespace>
During the update, the output may look like this:
NAME CLUSTERSTATE UPDATESTATE UPDATINGCOMPONENTS
ytsaurus Updating WaitingForPodsCreation {ms hp ds dnd rp end tnd sch ca}
For a description of update stages and pod states, see the status reference below.
Check the pod statuses:
kubectl get pods -n <namespace>
Note
The update may take some time, as the operator first downloads the new Docker image and then starts the updated components. To have images ready in advance and speed up the update, configure image pre‑loading.
If the update takes too long, check the events for the problematic pod:
kubectl describe pod <pod_name> -n <namespace> | grep -A 10 "Events:"
If the events show an image pull error ImagePullBackOff, verify that the image tag is correct and that this version exists in the registry. If the pod is in the Pending state, the issue is related to resources — check their availability in the cluster.
4. Verify the result
The update is complete when the following conditions are met:
- The cluster is in the
Runningstate. - All main pods are in the
Runningstate. - There are no pods in the cluster in the
Init,Pending,ImagePullBackOff, andCrashLoopBackOffstates.
Check the final cluster state:
kubectl get YTsaurus <cluster_name> -n <namespace>
Expected output:
NAME CLUSTERSTATE UPDATESTATE UPDATINGCOMPONENTS BLOCKEDCOMPONENTS
ytsaurus Running
Check pod statuses:
kubectl get pods -n <namespace>
Example of expected output:
NAME READY STATUS RESTARTS AGE
ca-0 1/1 Running 0 5m
dnd-0 1/1 Running 0 5m
dnd-1 1/1 Running 0 5m
dnd-2 1/1 Running 0 5m
ds-0 1/1 Running 0 10m
end-0 2/2 Running 0 5m
hp-0 1/1 Running 0 5m
ms-0 1/1 Running 0 10m
qt-0 1/1 Running 15 75d
rp-0 1/1 Running 0 5m
sch-0 1/1 Running 0 5m
tnd-0 1/1 Running 0 10m
Verify that the new version is specified in the specification:
kubectl get YTsaurus <cluster_name> -n <namespace> -o jsonpath='{.spec.coreImage}'
Expected output:
ghcr.io/ytsaurus/ytsaurus:stable-25.2.0-relwithdebinfo
Make sure the operator is again logging Ytsaurus is running and happy:
kubectl logs -n <namespace> deployment/ytsaurus-ytop-chart-controller-manager --tail=100
After a successful update, clear the updatePlan field in the ytsaurus-spec-new.yaml file — leave it empty:
spec:
updatePlan: []
You can achieve the same result with an explicit rule using the Nothing class — the operator won’t update any component:
spec:
updatePlan:
- class: Nothing
Apply the change:
kubectl apply -f ytsaurus-spec-new.yaml
The operator doesn’t clear updatePlan automatically — reset it yourself. An empty updatePlan means “don’t update anything” and protects against accidental component restarts during further specification changes. If you leave - class: Everything, the next change to coreImage will trigger a full update of all components again.
Updating to the next version: if you need to update to another version, repeat all steps starting from the Preparing for update section. Each time, save the specification anew via kubectl get ytsaurus — the operator might have changed it during the update, and the local file from last time is no longer up to date.
Troubleshooting updates
Use this section if the update doesn’t start, takes too long, fails, or behaves unpredictably.
Version conflict when applying the specification
You get a version conflict error when trying to apply the specification:
Error from server (Conflict): error when applying patch: the object has been modified; please apply your changes to the latest version and try again
This means another process has modified the specification. Save the current version of the specification and retry the change:
kubectl get YTsaurus <cluster_name> -n <namespace> -o yaml > ytsaurus-spec-new.yaml
Image not found
Image pull error:
Failed to pull image "ghcr.io/ytsaurus/ytsaurus:stable-X.X.X-relwithdebinfo": not found
Check that:
- The image tag is specified correctly.
- This version exists in the registry.
Pod stuck in Init state for a long time
This behavior is possible when Kubernetes is still downloading the new image.
kubectl describe pod <pod_name> -n <namespace> | grep -A 10 "Events:"
Example of normal process:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m10s default-scheduler Successfully assigned ytsaurus/ms-0 to docker-desktop
Normal Pulling 3m9s kubelet Pulling image "ghcr.io/ytsaurus/ytsaurus:stable-25.2.0-relwithdebinfo"
If the pod remains in the Init state longer than expected, check the pod logs and events to identify the issue.
Job is in CrashLoopBackOff state
For example, you might see yt-scheduler-init-job-op-archive in the CrashLoopBackOff state.
During an update, this may be a temporary state. The job might start before the cluster fully prepares tablet cells. Because of this, the job enters a restart loop but usually converges later — this is normal.
First, check the overall cluster status:
kubectl get YTsaurus <cluster_name> -n <namespace>
If the cluster is still updating, wait for the process to complete and check the job status again. If the cluster isn’t updating or the job doesn’t converge after a long time, check the job logs to identify the cause of the problem.
Operator doesn’t start the update
Check that:
- The
updatePlanfield lists the components to update — for example,- class: Everything. IfupdatePlanis empty and you changedcoreImage, the cluster will enter theUpdateBlockedstate and the update won’t start. - The operator has completed previous actions and the logs show
running and happy. - The cluster was in the
Runningstate before the update started. - Check the operator logs:
kubectl logs -n <namespace> deployment/ytsaurus-ytop-chart-controller-manager --tail=100
Update entered the ImpossibleToStart state
The Kubernetes operator may stop the update if it considers it unsafe. For example, if some tablet cell bundles are in poor condition — tablet cells aren’t working or have errors. In this case, the update won’t start until you fix the issue.
Check the resource status:
kubectl get YTsaurus -n <namespace>
Example output:
NAME CLUSTERSTATE UPDATESTATE UPDATINGCOMPONENTS
minisaurus Updating ImpossibleToStart
To find the reason, run the command:
kubectl describe YTsaurus -n <namespace>
And check the Conditions block in UpdateStatus.
Example of why an update can’t start
kubectl describe YTsaurus -n <namespace>
...
Update Status:
Conditions:
Last Transition Time: 2023-09-26T09:18:11Z
Message: Tablet cell bundles ([sys default]) aren't in 'good' health
Reason: Update
Status: True
Type: NoPossibility
State: ImpossibleToStart
If you can’t start the update, revert the specification to its previous value. After that, the operator will cancel the update and return the cluster to the Running state.
Unrecognized master options after update
After updating the cluster, master server configs may still contain unrecognized options that are no longer used in the new version of YTsaurus. This often happens during major updates. In this case, you’ll see a warning:
Found unrecognized options in dynamic cluster config
You can remove unrecognized master options in two ways:
- Using the CLI command — yt admin remove-master-unrecognized-options. This method supports the
--dryflag for previewing changes. - Using a standalone script — remove_master_unrecognized_options from the GitHub repository.
Advanced scenarios
Updating individual components
Warning
Use partial updates only in rare cases, such as fixing an error. We recommend discussing this decision with the YTsaurus team first.
A newer version of one component may require a specific version of master servers. If dependencies aren’t met, the cluster may fail to start. To update the cluster, we recommend using the update via the coreImage field. This guarantees version compatibility across all server components.
In the Ytsaurus specification, you can manage component images individually. How the operator handles such changes depends on the component type:
-
Components with their own release cycle — Query Tracker, YQL agent, Strawberry, and others. For more information, see the section Components with their own release cycle.
To update these components, change the
imagefield in theYtsaurusspecification. This is the only way to update these components. When you change their image, the operator updates only their pods without stopping cluster operation.When fully updating the cluster via the
coreImagefield, these components’ pods will restart, but their image will remain the same — the one set in theimagefield.Example: updating Query Tracker to version
0.0.7:spec: queryTrackers: image: ghcr.io/ytsaurus/query-tracker:0.0.7kubectl apply -f ytsaurus-spec-new.yamlThe operator will update only the
qtpods, without affecting other components. -
Targeted update of server components
You can override the image for a specific server component — for example, only for
tabletNodes— by specifying a separateimagefor it instead of the commoncoreImage.Specify the
imagefield for the required component in theytsaurus-spec-new.yamlfile and apply the change:kubectl apply -f ytsaurus-spec-new.yaml
Updating static configs
The operator automatically generates configuration files for each component — master servers, proxies, nodes — based on the Ytsaurus specification. Sometimes you need to modify parameters that go into these files — for example, add a new storage location locations or configure component-specific parameters via configOverrides.
In such cases, do not set the updatePlan field. It is sufficient to modify the specification and apply it — the operator will detect that the configuration has changed and restart only the pods of the affected components.
Make the necessary changes in ytsaurus-spec-new.yaml and apply them:
kubectl apply -f ytsaurus-spec-new.yaml
During the pod restart, the cluster will transition to the Reconfiguration state:
kubectl get ytsaurus <cluster_name> -n <namespace>
NAME CLUSTERSTATE UPDATESTATE
ytsaurus Reconfiguration
Once the pods restart and become ready, the cluster will return to the Running state.
Automatic update after operator upgrade
When the operator is upgraded, its new version may automatically trigger a cluster update — without you changing the coreImage. This happens because different operator versions may generate different configuration files for the same components — for example, a new field may be added in the newer version. The operator detects the discrepancy between the current cluster state and the desired state and initiates reconciliation.
If the update turns out to be impossible, the cluster will remain in the Updating state, and UPDATESTATE will transition to ImpossibleToStart. In this case, there are two options:
-
Roll back the operator to the previous version:
helm rollback ytsaurus -n <namespace> -
Leave the
updatePlanfield empty in theYtsaurusspecification — the operator will cancel the update and will not run it automatically:spec: updatePlan: []kubectl apply -f ytsaurus-spec-new.yamlAfter that, bring the cluster to a working state and retry when you are ready, specifying the required components in
updatePlan— for example,- class: Everything.
Updating the cluster without downtime via RollingUpdate
To keep the cluster available during the update, configure the RollingUpdate strategy via the updatePlan field in the Ytsaurus specification. The operator will update the pods one by one, maintaining the minimum number of available instances.
Requirements
For RollingUpdate to work correctly, each component being updated must have at least 2 instances. If there is only one instance, it will be unavailable during the update, just as with BulkUpdate. RollingUpdate is not yet implemented for master servers — they are updated via BulkUpdate or OnDelete.
For more details on the strategy, component availability, and the recommended number of instances, see the section RollingUpdate Strategy.
Minimal example: RollingUpdate for all components
apiVersion: cluster.ytsaurus.tech/v1
kind: Ytsaurus
metadata:
name: ytsaurus
spec:
coreImage: ghcr.io/ytsaurus/ytsaurus:stable-25.2.0-relwithdebinfo
updatePlan:
- class: Everything
strategy:
rollingUpdate: {}
Custom strategy per component for production
updatePlan:
# HTTP Proxies — Rolling Update
- component:
type: HttpProxy
strategy:
rollingUpdate: {}
runPreChecks: true
# RPC Proxies — Rolling Update
- component:
type: RpcProxy
strategy:
rollingUpdate: {}
runPreChecks: true
# Data Nodes — Rolling Update
- component:
type: DataNode
strategy:
rollingUpdate: {}
runPreChecks: true
# Exec Nodes — Rolling Update with drain
- component:
type: ExecNode
strategy:
rollingUpdate: {}
runPreChecks: true
# Other components — BulkUpdate
- class: Everything
concurrency: 2 # no more than 2 instance groups simultaneously
RollingUpdate with image preloading
The enableImageHeater flag downloads new images to the nodes before the update starts. Combined with RollingUpdate, this reduces the pod switchover time:
apiVersion: cluster.ytsaurus.tech/v1
kind: Ytsaurus
metadata:
name: ytsaurus
spec:
coreImage: ghcr.io/ytsaurus/ytsaurus:stable-25.2.0-relwithdebinfo
clusterFeatures:
enableImageHeater: true
updatePlan:
- class: Everything
strategy:
rollingUpdate: {}
For more details on preloading, see the section Image Preloading.
For a description of all updatePlan fields, see the section Configuring the updatePlan field.
Manual intervention
Attention
Before performing manual intervention, it is recommended to consult the YTsaurus team.
If the automatic update cannot complete and manual actions are required, temporarily disable the operator’s management of the cluster. To do this, set the isManaged: false flag in the Ytsaurus specification.
After this, the operator will stop making changes to the cluster, and you will be able to perform manual actions.
This scenario can be useful if the operator is stuck on a problematic component. It can also help if you need to manually check or restore the state of a part of the cluster. Or if you are troubleshooting an unusual error that cannot be resolved by simply reapplying the specification.
Status reference
How to check the cluster status
You can monitor the update via the Ytsaurus resource status:
kubectl get ytsaurus -n <namespace>
During the update, the cluster transitions to the Updating state, and the detailed stage is displayed in the UPDATESTATE field. After the update completes, the cluster returns to the Running state:
NAME CLUSTERSTATE UPDATESTATE UPDATINGCOMPONENTS
minisaurus Running None
UPDATESTATE
Not all statuses appear during every update — the set depends on which components are affected. For example, the WaitingForTabletCells statuses appear only when updating tablet nodes, and WaitingForOpArchiveUpdate appears only when updating the scheduler.
Table of UPDATESTATE field statuses
|
Status |
Condition |
Description |
|
|
— |
No update is in progress |
|
|
If image preloading is enabled |
The operator is waiting for the new image to be preloaded onto the cluster nodes |
|
|
If master servers or tablet nodes are being updated |
The operator is checking whether it is safe to start the update |
|
|
— |
The operator cannot start the update. For example, tablet cells of bundles are in a bad state. The update will not start until you resolve the issue |
|
|
If master servers are being updated |
The operator enables safe mode — it prohibits writes to the cluster during the master server update |
|
|
If tablet nodes are being updated |
The operator saves the current topology of the tablet cell before deleting them |
|
|
If tablet nodes are being updated |
The operator initiates the deletion of the tablet cell |
|
|
If tablet nodes are being updated |
The operator waits for the tablet cell to be fully deleted |
|
|
If data nodes or master servers are being updated |
The operator waits for “imaginary” chunks — temporary metadata created during data rebalancing — to disappear |
|
|
If master servers are being updated |
The operator waits for the master servers to save snapshots of their state |
|
|
Always |
The operator deletes the old pods of the components being updated |
|
|
Always |
The operator waits for the new pods with the updated image to start |
|
|
If master servers are being updated |
The operator waits for the master servers to exit read-only mode after restart |
|
|
If master servers are being updated |
The operator prepares to initialize sidecar containers |
|
|
If master servers are being updated |
The operator initializes sidecar containers |
|
|
Always |
The operator applies changes to the Cypress metadata tree after updating components |
|
|
If tablet nodes are being updated |
The operator restores tablet cells on the updated nodes |
|
|
If the scheduler is being updated |
The operator prepares to update the operational archive |
|
|
If the scheduler is being updated |
The operator updates the operational archive — the internal storage of operation metadata |
|
|
If the query tracker is being updated |
The operator prepares to update the query tracker state |
|
|
If the query tracker is being updated |
The operator updates the query tracker state |
|
|
If the YQL agent is being updated |
The operator prepares to update the YQL agent state |
|
|
If the YQL agent is being updated |
The operator updates the YQL agent state |
|
|
If the queue agent is being updated |
The operator prepares to update the queue agent state |
|
|
If the queue agent is being updated |
The operator updates the queue agent state |
|
|
If master servers are being updated |
The operator disables safe mode after successfully updating the master servers |
|
|
Always |
The operator waits for Timbertruck — the component for collecting structured logs — to be ready |
CLUSTERSTATE
Table of CLUSTERSTATE field statuses
|
Status |
Description |
|
|
The cluster has been created but not yet initialized |
|
|
The cluster is being initialized for the first time |
|
|
The cluster is operating normally |
|
|
The operator is applying configuration changes without fully updating the components |
|
|
The cluster is being updated |
|
|
The image has been changed, but |
|
|
The update is finishing — the operator is applying final changes |
|
|
The operator cancels the update and returns the cluster to the |
Pod states
Table of pod state statuses
|
Status |
Description |
|
|
Pod initialization |
|
|
Waiting for resources |
|
|
Container creation |
|
|
Pod is running |
|
|
Image pull error |
|
|
Pod is crashing and restarting |
Component reference
Components updated together with the cluster
The operator updates these components simultaneously with the cluster when the coreImage field in the Ytsaurus specification is changed. For each component, you can override the image separately via the image field.
Table of components updated together with the cluster
|
Component |
Specification field |
|
Master primary, secondary |
|
|
Master caches |
|
|
HTTP proxies |
|
|
RPC proxies |
|
|
TCP proxies |
|
|
Kafka proxies |
|
|
Cypress proxies |
|
|
Data nodes |
|
|
Exec nodes |
|
|
Tablet nodes |
|
|
Discovery |
|
|
Scheduler |
|
|
Controller agents |
|
|
Queue agents |
|
|
Tablet balancer |
|
|
Bundle controller |
|
Components with their own release cycle
These components have their own release cycles; the operator updates them independently via the image field of the specific component in the Ytsaurus specification.
Table of components with their own release cycle
|
Component |
Specification field |
|
Query trackers |
|
|
YQL agents |
|
|
Strawberry controller |
|