{"id":386,"date":"2026-01-16T01:25:00","date_gmt":"2026-01-16T01:25:00","guid":{"rendered":"https:\/\/blog.ngocha.biz\/?p=386"},"modified":"2026-01-16T01:25:00","modified_gmt":"2026-01-16T01:25:00","slug":"backup-etcd-restore-kubernetes","status":"publish","type":"post","link":"https:\/\/blog.ngocha.biz\/?p=386","title":{"rendered":"Etcd Backup and Restore on Kubernetes Cluster [Tutorial]"},"content":{"rendered":"<p>In this kubernetes tutorial, you will learn the etcd backup and restore on Kubernetes cluster with an etcd snapshot.<\/p>\n<p>In Kubernetes architecture, etcd is an integral part of the cluster. All the cluster objects and their state is stored in etcd. Few things you should know about etcd from a Kubernetes perspective.<\/p>\n<ol>\n<li>It is a consistent, distributed, and secure key-value store.<\/li>\n<li>It uses <a href=\"https:\/\/raft.github.io\/?ref=devopscube.com\" rel=\"noreferrer noopener\">raft protocol.<\/a><\/li>\n<li>Supports highly available architecture with stacked etcd.<\/li>\n<li>It stores kubernetes cluster configurations, all API objects, object states, and <a href=\"https:\/\/devopscube.com\/open-source-service-discovery\/\">service discovery<\/a> details.<\/li>\n<\/ol>\n<p>If you want to understand more about etcd and how kubernetes uses it, I recommend reading the comprehensive <a href=\"https:\/\/devopscube.com\/kubernetes-architecture-explained\/\">Kubernetes Architecture<\/a> post.<\/p>\n<p>Also, if you consider <a href=\"https:\/\/devopscube.com\/key-considerations-kubernetes-cluster-design-setup\/\">Kubernetes design best practices<\/a>, Kubernetes etcd backup and restore is one of the important aspects under the backup strategy.<\/p>\n<h2 id=\"kubernetes-etcd-backup-using-etcdctl\">Kubernetes etcd Backup Using etcdctl<\/h2>\n<p>Here is what you should know about etcd backup.<\/p>\n<ol>\n<li>etcd has a built-in snapshot mechanism.<\/li>\n<li><code>etcdctl<\/code> is the command line utility that interacts with etcd for snapshots.<\/li>\n<\/ol>\n<figure class=\"kg-card kg-image-card kg-card-hascaption\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-5-25.png\" class=\"kg-image\" alt=\"etcd backup workflow using etcdctl\" loading=\"lazy\" width=\"1662\" height=\"1225\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2025\/03\/image-5-25.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2025\/03\/image-5-25.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2025\/03\/image-5-25.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2025\/03\/image-5-25.png 1662w\" sizes=\"auto, (min-width: 720px) 720px\"><figcaption><span style=\"white-space: pre-wrap;\">Click to view in HD<\/span><\/figcaption><\/figure>\n<p>Follow the steps given below to take an etcd snapshot.<\/p>\n<h3 id=\"step-1-log-in-to-the-control-plane\">Step 1: Log in to the control plane.<\/h3>\n<p>SSH into your control plane to backup ETCD.<\/p>\n<h3 id=\"step-2-install-required-tools\"><strong>Step 2:<\/strong> Install Required Tools<\/h3>\n<p>We need two tools called etcdctl and etcdutl to backup and restore ETCD.<\/p>\n<p>If you don&#8217;t have etcdctl and etcdutl installed in your cluster, install it using the following script.<\/p>\n<pre><code class=\"language-bash\">ARCH=$(uname -m)\nif [ \"$ARCH\" = \"x86_64\" ]; then\n    ARCH_TYPE=\"amd64\"\nelif [ \"$ARCH\" = \"aarch64\" ]; then\n    ARCH_TYPE=\"arm64\"\nelse\n    echo \"Unsupported architecture: $ARCH\"\n    exit 1\nfi\n\nETCD_VER=v3.6.7\nDOWNLOAD_URL=https:\/\/storage.googleapis.com\/etcd\nDOWNLOAD_FILE=etcd-${ETCD_VER}-linux-${ARCH_TYPE}.tar.gz\n\nmkdir -p \/tmp\/etcd-download\ncurl -L ${DOWNLOAD_URL}\/${ETCD_VER}\/${DOWNLOAD_FILE} -o \/tmp\/${DOWNLOAD_FILE}\n\ntar xzvf \/tmp\/${DOWNLOAD_FILE} -C \/tmp\/etcd-download --strip-components=1\n\nsudo mv \/tmp\/etcd-download\/etcd \/tmp\/etcd-download\/etcdctl \/tmp\/etcd-download\/etcdutl \/usr\/local\/bin\/\nrm -f \/tmp\/${DOWNLOAD_FILE}\nrm -rf \/tmp\/etcd-download<\/code><\/pre>\n<h3 id=\"step-3-verify-the-installation\">Step 3: Verify the Installation<\/h3>\n<p>Run the following commands to verify the installation.<\/p>\n<pre><code class=\"language-bash\">etcdctl version\n\netcdutl version<\/code><\/pre>\n<h3 id=\"step-4-get-required-information-for-backup\">Step 4: Get Required Information for Backup<\/h3>\n<p>We need to get the following four pieces of information to <code>etcdctl<\/code> to take an etcd snapshot.<\/p>\n<ol>\n<li>etcd endpoint (&#8211;endpoints)<\/li>\n<li>ca certificate (&#8211;cacert)<\/li>\n<li>server certificate (&#8211;cert)<\/li>\n<li>server key (&#8211;key)<\/li>\n<\/ol>\n<p>You can get the above details in two ways.<\/p>\n<p>From the etcd static pod manifest file located at <code>\/etc\/kubernetes\/manifests\/etcd.yaml<\/code> the location.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2026\/01\/image-21.png\" class=\"kg-image\" alt=\"getting cert files from etcd static pod manifest\" loading=\"lazy\" width=\"839\" height=\"758\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2026\/01\/image-21.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2026\/01\/image-21.png 839w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>You can also get the above details by <strong>describing the etcd pod running<\/strong> in the <code>kube-system<\/code> namespace.<\/p>\n<p>While describing the pod, replace <strong><code>etcd-master-node<\/code><\/strong> with your etcd pod name.<\/p>\n<pre><code class=\"language-bash\">kubectl get po -n kube-system\nkubectl describe pod etcd-master-node -n kube-system<\/code><\/pre>\n<p>Another way to view the etcd-server parameters faster is using the following command.<\/p>\n<pre><code class=\"language-bash\">ps -aux | grep etcd<\/code><\/pre>\n<p>Choose a method that you are comfortable with the get the cert details.<\/p>\n<h3 id=\"step-4-backup-using-etcdctl\">Step 4: Backup using etcdctl<\/h3>\n<p>To backup, take an etcd snapshot backup using the following command.<\/p>\n<pre><code class=\"language-bash\">sudo etcdctl \\\n  --endpoints=&lt;etcd endpoint&gt; \\\n  --cacert=&lt;ca-file&gt; \\\n  --cert=&lt;cert-file&gt; \\\n  --key=&lt;key-file&gt; \\\n  snapshot save &lt;backup-file-location&gt;<\/code><\/pre>\n<p>Before running the backup command, create a backup directory where we will be saving the snapshot.<\/p>\n<pre><code class=\"language-bash\">sudo mkdir -p \/opt\/backup\/<\/code><\/pre>\n<p>The command looks like the following when you add the actual location and parameters. Execute the command to perform a backup. <\/p>\n<p>You can replace<code> \/opt\/backup\/etcd.db<\/code> with the location and name of your choice.<\/p>\n<pre><code class=\"language-bash\">sudo etcdctl \\\n  --endpoints=https:\/\/127.0.0.1:2379 \\\n  --cacert=\/etc\/kubernetes\/pki\/etcd\/ca.crt \\\n  --cert=\/etc\/kubernetes\/pki\/etcd\/server.crt \\\n  --key=\/etc\/kubernetes\/pki\/etcd\/server.key \\\n  snapshot save \/opt\/backup\/etcd.db<\/code><\/pre>\n<p>On a successful execution you will get a <code>Snapshot saved at \/opt\/backup\/etcd.db<\/code> message as shown below.<\/p>\n<pre><code class=\"language-bash\">root@master-node:\/opt\/backup# sudo etcdctl \\\n  --endpoints=https:\/\/192.168.201.10:2379 \\\n  --cacert=\/etc\/kubernetes\/pki\/etcd\/ca.crt \\\n  --cert=\/etc\/kubernetes\/pki\/etcd\/server.crt \\\n  --key=\/etc\/kubernetes\/pki\/etcd\/server.key \\\n  snapshot save \/opt\/backup\/etcd.db\n2022-09-29 08:23:43.027261 I | clientv3: opened snapshot stream; downloading\n2022-09-29 08:23:43.088264 I | clientv3: completed snapshot read; closing\nSnapshot saved at \/opt\/backup\/etcd.db<\/code><\/pre>\n<p>Also, you verify the snapshot snapshot status using the etcdutl command.<\/p>\n<pre><code class=\"language-bash\">etcdutl --write-out=table snapshot status \/opt\/backup\/etcd.db<\/code><\/pre>\n<p>Here is an example output.<\/p>\n<pre><code class=\"language-bash\">+----------+----------+------------+------------+\n|   HASH   | REVISION | TOTAL KEYS | TOTAL SIZE |\n+----------+----------+------------+------------+\n| b7147656 |    51465 |       1099 |     5.1 MB |\n+----------+----------+------------+------------+<\/code><\/pre>\n<h2 id=\"kubernetes-etcd-restore-using-snapshot-backup\">Kubernetes etcd Restore Using Snapshot Backup<\/h2>\n<p>Now we have the backup in the <code>\/opt\/backup\/etcd.db<\/code> location. We will use the snapshot backup to restore etcd with the help of etcdutl.<\/p>\n<blockquote><p>Before restoring, you should stop the&nbsp;<code>kube-apiserver<\/code>&nbsp;and&nbsp;<code>etcd<\/code>&nbsp;pods. Because, the API server continously reads or writes to etcd, if API server is running during restore, it can cause data corruption.<\/p><\/blockquote>\n<h3 id=\"step-1-move-statis-pod-manifests\">Step 1: Move Statis Pod Manifests<\/h3>\n<p>First, we need to move the manifest files of the API server and ETCD.<\/p>\n<p>Since they are static, their pods will be recreated, even if you delete them.<\/p>\n<p>Use the following commands to move the files to <code>\/tmp<\/code> location.<\/p>\n<pre><code class=\"language-bash\">sudo mv \/etc\/kubernetes\/manifests\/kube-apiserver.yaml \/tmp\/\n\nsudo mv \/etc\/kubernetes\/manifests\/etcd.yaml \/tmp\/<\/code><\/pre>\n<p>Once the manifests are moved, the&nbsp;<strong>kube-apiserver<\/strong>&nbsp;and&nbsp;<strong>ETCD<\/strong>&nbsp;pods will be terminated within a few seconds.<\/p>\n<p>You can verify this by running the&nbsp;<strong>crictl<\/strong>&nbsp;command. Make sure the API server and ETCD containers are no longer running. Wait until the containers are fully removed before proceeding.<\/p>\n<pre><code class=\"language-bash\">crictl ps\n<\/code><\/pre>\n<h3 id=\"step-2-restore-etcd-using-etcdutl\">Step 2: Restore ETCD using etcdutl<\/h3>\n<p>Now we have the backup in the&nbsp;<code>\/opt\/backup\/etcd.db<\/code>&nbsp;location, let&#8217;s restore it.<\/p>\n<p>Given below is the etcdutl command to restore etcd<strong>.<\/strong><\/p>\n<pre><code class=\"language-bash\">sudo etcdctl snapshot restore &lt;snapshot-location&gt;<\/code><\/pre>\n<p>Let&#8217;s execute the etcd restore command. In my case <code>\/opt\/backup\/etcd.db<\/code> is the backup file.<\/p>\n<pre><code class=\"language-bash\">sudo etcdctl snapshot restore \/opt\/backup\/etcd.db<\/code><\/pre>\n<p>If you want to use a specific data directory for the restore, you can add the location using the <code>--data-dir<\/code> flag as shown below.<\/p>\n<pre><code class=\"language-bash\">sudo etcdutl --data-dir \/var\/lib\/etcd-from-backup \\\n  snapshot restore \/opt\/backup\/etcd.db<\/code><\/pre>\n<p>If the restoration is successful, you will get the output logs with restored snapshot message as shown below.<\/p>\n<figure class=\"kg-card kg-image-card\"><img decoding=\"async\" src=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2026\/01\/image-22.png\" class=\"kg-image\" alt=\"etcd snapshot backuped message\" loading=\"lazy\" width=\"1868\" height=\"1698\" srcset=\"https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w600\/2026\/01\/image-22.png 600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1000\/2026\/01\/image-22.png 1000w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/size\/w1600\/2026\/01\/image-22.png 1600w, https:\/\/storage.ghost.io\/c\/5f\/2f\/5f2f4d20-2abf-4534-8d40-7aa233aedd43\/content\/images\/2026\/01\/image-22.png 1868w\" sizes=\"auto, (min-width: 720px) 720px\"><\/figure>\n<p>After restoring the etcd snapshot to a new directory, we need to update&nbsp;<code>etcd.yaml<\/code>&nbsp;because it still references the old data path.<\/p>\n<p>\ufeffGenerally, you should change only the&nbsp;<code>hostPath<\/code>. This keeps the internal container structure exactly as kubeadm expects it, while pointing it to your new data folder.<\/p>\n<p>Edit the&nbsp;<code>\/tmp\/etcd.yaml<\/code>&nbsp;file modify the following sections and change the new directory in the volume section, as given below.<\/p>\n<pre><code class=\"language-bash\">volumes:\n  - name: etcd-data\n    hostPath:\n      path: \/var\/lib\/etcd-from-backup\n      type: DirectoryOrCreate<\/code><\/pre>\n<p>Then, move the manifest files back to the original static pod directory. This will redeploy the&nbsp;<strong>kube-apiserver<\/strong>&nbsp;and&nbsp;<strong>ETCD<\/strong>&nbsp;pods.<\/p>\n<pre><code class=\"language-bash\">sudo mv \/tmp\/kube-apiserver.yaml \/etc\/kubernetes\/manifests\/\n\nsudo mv \/tmp\/etcd.yaml \/etc\/kubernetes\/manifests\/<\/code><\/pre>\n<p>It will take around&nbsp;<strong>10-15 seconds<em>&nbsp;<\/em><\/strong>for the API server and ETCD to start running.<\/p>\n<p>Once the Pods are back up, verify the cluster status. It is the ultimate test is whether&nbsp;<code>kubectl<\/code>&nbsp;can see the objects that were in the backup<\/p>\n<pre><code class=\"language-bash\">$ kubectl get no\n\nNAME           STATUS   ROLES           AGE     VERSION\ncontrolplane   Ready    control-plane   3h13m   v1.34.0\nnode01         Ready    worker          3h11m   v1.34.0\nnode02         Ready    worker          3h11m   v1.34.0<\/code><\/pre>\n<p>You can also check the ETCD status using the following command. Replace the endpoint IP with your ETCD endpoint IP.<\/p>\n<pre><code class=\"language-bash\">$ sudo etcdctl \\\n  --endpoints=https:\/\/192.168.201.10:2379 \\\n  --cacert=\/etc\/kubernetes\/pki\/etcd\/ca.crt \\\n  --cert=\/etc\/kubernetes\/pki\/etcd\/server.crt \\\n  --key=\/etc\/kubernetes\/pki\/etcd\/server.key \\\n  endpoint health\n\nhttps:\/\/192.168.201. 10:2379 is healthy: successfully committed proposal: took = 13.107842ms<\/code><\/pre>\n<h2 id=\"etcd-backup-faqs\">etcd Backup FAQs<\/h2>\n<h3 id=\"how-to-take-etcd-backup-in-kubernetes\">How to take etcd backup in Kubernetes?<\/h3>\n<p>To take the etcd backup, you need to the etcdctl command line utility. You need to use the etcdctl snapshot command with the etcd certificates to perform a backup operation.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>In this blog, we learned <strong>Kubernetes etcd backup and restore<\/strong> using <code>etcdctl<\/code> and <code>etcdutl<\/code> command line utility.<\/p>\n<p><strong>etcd backup, and restore<\/strong> are essential tasks in Kubernetes cluster administration. Also, it is an important topic in the CKA certification exam.<\/p>\n<p>If you are preparing for the CKA exam, do check out the <a href=\"https:\/\/devopscube.com\/cka-exam-study-guide\/\">CKA exam study guide<\/a> and for the exam discount voucher, check the <a href=\"https:\/\/devopscube.com\/kubernetes-certification-coupon\/\">Kubernetes certification coupon<\/a>.<\/p>\n<hr>\n<p><strong>Ngu\u1ed3n:<\/strong> <a href=\"https:\/\/devopscube.com\/backup-etcd-restore-kubernetes\/\" target=\"_blank\" rel=\"noopener noreferrer\">Etcd Backup and Restore on Kubernetes Cluster [Tutorial] \u2014 DevOpsCube<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Source: https:\/\/devopscube.com\/backup-etcd-restore-kubernetes\/<\/p>\n","protected":false},"author":1,"featured_media":387,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-386","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"_links":{"self":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/386","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=386"}],"version-history":[{"count":0,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/posts\/386\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=\/wp\/v2\/media\/387"}],"wp:attachment":[{"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=386"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=386"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.ngocha.biz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=386"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}