1"use strict";(self.webpackChunkk_3_s_docs=self.webpackChunkk_3_s_docs||[]).push([[4765],{281:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"upgrades/roll-back","title":"Rolling Back K3s","description":"You can roll back the K3s Kubernetes version after an upgrade, using a combination of K3s binary downgrade and datastore restoration. Rollback can be performed on clusters of all types, including a single-node SQLite, an external datastore, or an embedded etcd. When rolling back to a previous Kubernetes minor version, you must have a datastore snapshot taken on the Kubernetes minor version you wish to roll back to.","source":"@site/docs/upgrades/roll-back.md","sourceDirName":"upgrades","slug":"/upgrades/roll-back","permalink":"/upgrades/roll-back","draft":false,"unlisted":false,"editUrl":"https://github.com/k3s-io/docs/edit/main/docs/upgrades/roll-back.md","tags":[],"version":"current","lastUpdatedAt":1790705508000,"frontMatter":{"title":"Rolling Back K3s"},"sidebar":"mySidebar","previous":{"title":"Automated Upgrades","permalink":"/upgrades/automated"},"next":{"title":"Security","permalink":"/security/"}}');var t=s(74848),l=s(28453);const i={title:"Rolling Back K3s"},a=void 0,o={},c=[{value:"Important Considerations",id:"important-considerations",level:2},{value:"Rolling Back a K3s Cluster",id:"rolling-back-a-k3s-cluster",level:2},{value:"Verification",id:"verification",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components},{TabItem:s,Tabs:r}=n;return s||u("TabItem",!0),r||u("Tabs",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"You can roll back the K3s Kubernetes version after an upgrade, using a combination of K3s binary downgrade and datastore restoration. Rollback can be performed on clusters of all types, including a single-node SQLite, an external datastore, or an embedded etcd. When rolling back to a previous Kubernetes minor version, you must have a datastore snapshot taken on the Kubernetes minor version you wish to roll back to."}),"\n",(0,t.jsx)(n.admonition,{type:"warning",children:(0,t.jsx)(n.p,{children:"If you cannot restore the database, you cannot roll back to a previous minor version."})}),"\n",(0,t.jsx)(n.h2,{id:"important-considerations",children:"Important Considerations"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Backups:"})," Before upgrading, ensure you have a valid database or etcd snapshot from your cluster running the older version of K3s. Without a backup, a rollback is impossible."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Potential Data Loss:"})," The ",(0,t.jsx)(n.code,{children:"k3s-killall.sh"})," script forcefully terminates K3s processes and may result in data loss if applications are not properly shut down."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Version Specifics:"})," Always verify K3s and component versions before and after the rollback."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"rolling-back-a-k3s-cluster",children:"Rolling Back a K3s Cluster"}),"\n",(0,t.jsxs)(r,{children:[(0,t.jsx)(s,{value:"SQLite",default:!0,children:(0,t.jsxs)(n.p,{children:["To roll back a K3s cluster when using a SQLite database, replace the ",(0,t.jsx)(n.code,{children:".db"})," file with the copy of the ",(0,t.jsx)(n.code,{children:".db"})," file you made while backing up your database."]})}),(0,t.jsxs)(s,{value:"Embedded etcd",children:[(0,t.jsx)(n.p,{children:"To roll back a K3s cluster when using an embedded etcd, follow these steps:"}),(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"If the cluster is running and the Kubernetes API is available, gracefully stop workloads by draining all nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"kubectl drain --ignore-daemonsets --delete-emptydir-data <NODE-ONE-NAME>
1 <NODE-TWO-NAME> <NODE-THREE-NAME> ...\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"On each node, stop the K3s service and all running pod processes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"k3s-killall.sh\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["On each node, roll back the K3s binary to the previous version, but ",(0,t.jsx)(n.em,{children:"do not"})," start K3s."]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Clusters with Internet Access:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Server nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=vX.Y.Zk3s1 INSTALL_K3S_EXEC="server" INSTALL_K3S_SKIP_START="true" sh -\n'})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Agent nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=vX.Y.Zk3s1 INSTALL_K3S_EXEC="agent" INSTALL_K3S_SKIP_START="true" sh -\n'})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Air-gapped Clusters:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Download the artifacts and run the ",(0,t.jsx)(n.a,{href:"/installation/airgap#2-install-k3s",children:"install script"})," locally. Add the environment variable ",(0,t.jsx)(n.code,{children:'INSTALL_K3S_SKIP_START="true"'})," when running the install script to prevent K3s from starting."]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["On the first server node or the node without a ",(0,t.jsx)(n.code,{children:"server:"})," entry in its ",(0,t.jsx)(n.a,{href:"/installation/configuration",children:"K3s config file"}),", initiate the cluster restore. Refer to the ",(0,t.jsx)(n.a,{href:"/cli/etcd-snapshot#snapshot-restore-steps",children:"Snapshot Restore Steps"})," for more information:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"k3s server --cluster-reset --cluster-reset-restore-path=<PATH-TO-SNAPSHOT>\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"warning",children:(0,t.jsx)(n.p,{children:"This overwrites all data in the etcd datastore. Verify the snapshot's integrity before restoring. Be aware that large snapshots can take a long time to restore."})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Start the K3s service on the first server node:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"systemctl start k3s\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"On the other server nodes, remove the K3s database directory:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"rm -rf /var/lib/rancher/k3s/server/db\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Start the K3s service on the other server nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"systemctl start k3s\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Start the K3s service on all agent nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"systemctl start k3s\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Verify the K3s service status with ",(0,t.jsx)(n.code,{children:"systemctl status k3s"}),"."]}),"\n"]}),"\n"]})]}),(0,t.jsxs)(s,{value:"External Database",children:[(0,t.jsx)(n.p,{children:"To roll back a K3s cluster when using an external database (e.g., PostgreSQL, MySQL), follow these steps:"}),(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"If the cluster is running and the Kubernetes API is available, gracefully stop workloads by draining all nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"kubectl drain --ignore-daemonsets --delete-emptydir-data <NODE-ONE-NAME>
1 <NODE-TWO-NAME> <NODE-THREE-NAME> ...\n"})}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsx)(n.p,{children:"This process may disrupt running applications."})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"On each node, stop the K3s service and all running pod processes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"k3s-killall.sh\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Restore a database snapshot taken before upgrading K3s and verify the integrity of the database. For example, if you're using PostgreSQL, run the following command:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"pg_restore -U <DB-USER> -d <DB-NAME> <BACKUP-FILE>\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"On each node, roll back the K3s binary to the previous version."}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Clusters with Internet Access:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Server nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=vX.Y.Zk3s1 INSTALL_K3S_EXEC="server" sh -\n'})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Agent nodes:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:'curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=vX.Y.Zk3s1 INSTALL_K3S_EXEC="agent" sh -\n'})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Air-gapped Clusters:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Download the artifacts and run the ",(0,t.jsx)(n.a,{href:"/installation/airgap#2-install-k3s",children:"install script"})," locally. Verify the K3s version after install with ",(0,t.jsx)(n.code,{children:"k3s --version"})," and reapply any custom configurations that were used before the upgrade."]}),"\n"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:"Start the K3s service on each node:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"systemctl start k3s\n"})}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsxs)(n.p,{children:["Verify the K3s service status with ",(0,t.jsx)(n.code,{children:"systemctl status k3s"}),"."]}),"\n"]}),"\n"]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"verification",children:"Verification"}),"\n",(0,t.jsx)(n.p,{children:"After the rollback, verify the following:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["K3s version: ",(0,t.jsx)(n.code,{children:"k3s --version"})]}),"\n",(0,t.jsxs)(n.li,{children:["Kubernetes cluster health: ",(0,t.jsx)(n.code,{children:"kubectl get nodes"})]}),"\n",(0,t.jsx)(n.li,{children:"Application functionality."}),"\n",(0,t.jsx)(n.li,{children:"Check the K3s logs for errors."}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}function u(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}},28453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>a});var r=s(96540);const t={},l=r.createContext(t);function i(e){const n=r.useContext(l);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),r.createElement(l.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.