PageSourceSearch

https://www.rabbitmq.com/assets/js/101a32ac.2360d632.js

js rabbitmq.com collected 2026-09-24 06:04:51 UTC 10,931 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkrabbitmq_website=self.webpackChunkrabbitmq_website||[]).push([["11798"],{7982(e,t,n){n.r(t),n.d(t,{metadata:()=>s,default:()=>h,frontMatter:()=>r,contentTitle:()=>a,toc:()=>d,assets:()=>l});var s=JSON.parse('{"id":"install-kubernetes-diy","title":"Deploying to Kubernetes (Do It Yourself)","description":"\x3c!--","source":"@site/docs/install-kubernetes-diy.md","sourceDirName":".","slug":"/install-kubernetes-diy","permalink":"/docs/next/install-kubernetes-diy","draft":false,"unlisted":false,"editUrl":"https://github.com/rabbitmq/rabbitmq-website/tree/main/docs/install-kubernetes-diy.md","tags":[],"version":"current","frontMatter":{"title":"Deploying to Kubernetes (Do It Yourself)","displayed_sidebar":"docsSidebar"},"sidebar":"docsSidebar","previous":{"title":"MacOs using Homebrew","permalink":"/docs/next/install-homebrew"},"next":{"title":"Upgrading RabbitMQ","permalink":"/docs/next/upgrade"}}'),o=n(74848),i=n(28453);let r={title:"Deploying to Kubernetes (Do It Yourself)",displayed_sidebar:"docsSidebar"},a,l={},d=[{value:"Overview",id:"overview",level:2},{value:"Deployment Guidelines",id:"deployment-guidelines",level:3},{value:"Use a Stateful Set",id:"use-a-stateful-set",level:4},{value:"Use Persistent Volumes",id:"use-persistent-volumes",level:4},{value:"Use Parallel podManagementPolicy",id:"use-parallel-podmanagementpolicy",level:4},{value:"ReadinessProbe",id:"readinessprobe",level:4},{value:"Configuration",id:"configuration",level:3},{value:"Make Sure <code>/etc/rabbitmq</code> is Mounted as Writeable",id:"make-sure-etcrabbitmq-is-mounted-as-writeable",level:4}];function c(e){let t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,o.jsxs)(t.p,{children:["This guide provides guidelines for deploying RabbitMQ to Kubernetes\nwithout using the ",(0,o.jsx)(t.a,{href:"https://www.rabbitmq.com/kubernetes/operator/operator-overview",children:"Operator"}),"\nnor any of the popular Helm charts. Such ",(0,o.jsx)(t.strong,{children:"a do-it-yourself deployment is\nhighly discouraged"}),"!"]}),"\n",(0,o.jsx)(t.admonition,{type:"danger",children:(0,o.jsxs)(t.p,{children:["You should almost certainly use the ",(0,o.jsx)(t.a,{href:"https://www.rabbitmq.com/kubernetes/operator/operator-overview",children:"Cluster Operator"}),"\n(highly recommended) or one of the popular Helm charts to deploy RabbitMQ to Kubernetes.\nIf you do that, you can ignore this guide altogether."]})}),"\n",(0,o.jsxs)(t.p,{children:["If you really don't want to use either the ",(0,o.jsx)(t.a,{href:"https://www.rabbitmq.com/kubernetes/operator/operator-overview",children:"Cluster Operator"}),'\nnor a Helm chart, it is nevertheless highly recommend to follow what they do when deploying RabbitMQ.\nYou can deploy a cluster using the Operator and "look around" to see how the deployment is structured, how the ',(0,o.jsx)(t.code,{children:"StatefulSet"}),"\nis configured, what the init container does and so on."]}),"\n",(0,o.jsxs)(t.p,{children:["Moreover, keep in mind that the ",(0,o.jsx)(t.a,{href:"https://www.rabbitmq.com/kubernetes/operator/operator-overview",children:"Cluster Operator"})," supports\n",(0,o.jsx)(t.a,{href:"https://www.rabbitmq.com/kubernetes/operator/using-operator#override",children:"StatefulSet and Service overrides"}),". You can therefore\ncustomize an Operator-based deployment the way you need, without reinventing everything."]}),"\n",(0,o.jsx)(t.h3,{id:"deployment-guidelines",children:"Deployment Guidelines"}),"\n",(0,o.jsx)(t.h4,{id:"use-a-stateful-set",children:"Use a Stateful Set"}),"\n",(0,o.jsxs)(t.p,{children:["RabbitMQ is a stateful application and is sensitive to hostname changes. Therefore, you have to use\na ",(0,o.jsx)(t.a,{href:"https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/",children:"StatefulSet"})," to run it."]}),"\n",(0,o.jsxs)(t.p,{children:["In addition, since RabbitMQ nodes ",(0,o.jsx)(t.a,{href:"./clustering#hostname-resolution-requirement",children:"resolve their own and peer hostnames during boot"}),",\nCoreDNS ",(0,o.jsx)(t.a,{href:"https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id",children:"caching timeout may need to be decreased"})," from default 30 seconds\nto a value in the 5-10 second range. Alternatively, an init container should delay the startup by 30 seconds."]}),"\n",(0,o.jsx)(t.admonition,{type:"important",children:(0,o.jsxs)(t.p,{children:["CoreDNS ",(0,o.jsx)(t.a,{href:"https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-network-id",children:"caching timeout may need to be decreased"}),"\nfrom default 30 seconds to a value in the 5-10 second range"]})}),"\n",(0,o.jsx)(t.h4,{id:"use-persistent-volumes",children:"Use Persistent Volumes"}),"\n",(0,o.jsxs)(t.p,{children:["Since RabbitMQ is a stateful application, a persistent volume should be used for its data folder.\nThe only exception is if your deployment is really ephemeral, which is often the case in test pipelines.\nIf you just need to have a temporary RabbitMQ instance during application tests, you can deploy it\nwithout a persistent volume. ",(0,o.jsx)(t.strong,{children:"Data (such as messages in the queues) can easily be lost if you do this!"})]}),"\n",(0,o.jsx)(t.h4,{id:"use-parallel-podmanagementpolicy",children:"Use Parallel podManagementPolicy"}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.code,{children:'podManagementPolicy: "Parallel"'})," is the recommended option for RabbitMQ clusters."]}),"\n",(0,o.jsxs)(t.p,{children:["Because of ",(0,o.jsx)(t.a,{href:"./clustering#restarting",children:"how nodes rejoin their cluster"}),", ",(0,o.jsx)(t.code,{children:"podManagementPolicy"})," set to ",(0,o.jsx)(t.code,{children:"OrderedReady"}),"\ncan lead to a deployment deadlock with certain readiness probes:"]}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsx)(t.li,{children:"Kubernetes will expect the first node to pass a readiness probe"}),"\n",(0,o.jsx)(t.li,{children:"The readiness probe may require a fully booted node"}),"\n",(0,o.jsx)(t.li,{children:"The node will fully boot after it detects that its peers have come online"}),"\n",(0,o.jsx)(t.li,{children:"Kubernetes will not start any other pods until the first one boots"}),"\n",(0,o.jsx)(t.li,{children:"The deployment therefore is deadlocked"}),"\n"]}),"\n",(0,o.jsxs)(t.p,{children:[(0,o.jsx)(t.code,{children:'podManagementPolicy: "Parallel"'})," avoids this problem, and the Kubernetes peer discovery plugin\nthen deals with the ",(0,o.jsx)(t.a,{href:"./cluster-formation#initial-formation-race-condition",children:"natural race condition present during parallel cluster formation"}),"."]}),"\n",(0,o.jsx)(t.h4,{id:"readinessprobe",children:"ReadinessProbe"}),"\n",(0,o.jsxs)(t.p,{children:["A TCP check on port 5672 (AMQP) or 5671 (AMQP with TLS) is a good ",(0,o.jsx)(t.code,{children:"readinessProbe"})," for most cases.\nThe AMQP listener is always enabled as one of the last steps in a node boot process. If the port is available,\nRabbitMQ pretty much completed the startup process and can indeed accept connections."]}),"\n",(0,o.jsxs)(t.p,{children:["A TCP check works well in combination with ",(0,o.jsx)(t.code,{children:'podManagementPolicy: "Parallel"'}),". If you want to use ",(0,o.jsx)(t.code,{children:"OrderedReady"}),",\nyou should use a readinessProbe which doesn't require the node to be fully booted (which goes against the idea\nof a readinessProbe). One health check that does not expect a node to be fully booted and have schema tables synced is:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-yaml",children:'readinessProbe:\n  exec:\n    # This is NOT the recommended readinessProbe!\n    command: ["rabbitmq-diagnostics", "ping"]\n'})}),"\n",(0,o.jsxs)(t.p,{children:["This basic check would allow the deployment to proceed and the nodes to eventually rejoin each other,\nassuming they are ",(0,o.jsx)(t.a,{href:"./upgrade",children:"compatible"}),". It is recommended to use a ",(0,o.jsx)(t.code,{children:"Parallel"})," startup strategy\ncombined with a TCP-based ",(0,o.jsx)(t.code,{children:"readinessProbe"}),"."]}),"\n",(0,o.jsx)(t.h3,{id:"configuration",children:"Configuration"}),"\n",(0,o.jsxs)(t.p,{children:["To use Kubernetes for peer discovery, set the ",(0,o.jsx)(t.code,{children:"cluster_formation.peer_discovery_backend"}),"\nto ",(0,o.jsx)(t.code,{children:"k8s"})," or ",(0,o.jsx)(t.code,{children:"kubernetes"})," or its module name, ",(0,o.jsx)(t.code,{children:"rabbit_peer_discovery_k8s"}),"\n(note: the name of the module is slightly different from plugin name):"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-ini",children:"cluster_formation.peer_discovery_backend = k8s\n\n# the backend can also be specified using its module name\n# cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s\n"})}),"\n",(0,o.jsxs)(t.p,{children:["The default settings of the peer discovery plugin should work in a vast majority of cases,\nbut there are some ",(0,o.jsx)(t.a,{href:"https://github.com/rabbitmq/rabbitmq-server/tree/main/deps/rabbitmq_peer_discovery_k8s#configuration",children:"settings available if the defaults don't work for you"}),"."]}),"\n",(0,o.jsxs)(t.h4,{id:"make-sure-etcrabbitmq-is-mounted-as-writeable",children:["Make Sure ",(0,o.jsx)(t.code,{children:"/etc/rabbitmq"})," is Mounted as Writeable"]}),"\n",(0,o.jsxs)(t.p,{children:["RabbitMQ nodes may need to update a file under ",(0,o.jsx)(t.code,{children:"/etc/rabbitmq"}),", the default ",(0,o.jsx)(t.a,{href:"./configure#config-location",children:"configuration file location"})," on Linux.\nThis may involve configuration file generation performed by the image used, ",(0,o.jsx)(t.a,{href:"./plugins#enabled-plugins-file",children:"enabled plugins file"})," updates,\nand so on."]}),"\n",(0,o.jsxs)(t.p,{children:["It is therefore highly recommended that ",(0,o.jsx)(t.code,{children:"/etc/rabbitmq"})," is mounted as writeable and owned by\nRabbitMQ's effective user (typically ",(0,o.jsx)(t.code,{children:"rabbitmq"}),"). Alternatively you can copy ",(0,o.jsx)(t.code,{children:"ConfigMap"})," volumes\nto ",(0,o.jsx)(t.code,{children:"/etc"})," in an init container."]}
1)]})}function h(e={}){let{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},28453(e,t,n){n.d(t,{R:()=>r,x:()=>a});var s=n(96540);let o={},i=s.createContext(o);function r(e){let t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},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.