{"id":622,"date":"2023-04-24T00:30:37","date_gmt":"2023-04-23T21:30:37","guid":{"rendered":"https:\/\/grechka.family\/dmitry\/blog\/?p=622"},"modified":"2023-04-24T00:30:50","modified_gmt":"2023-04-23T21:30:50","slug":"ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt","status":"publish","type":"post","link":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/","title":{"rendered":"High Availability Traefik for K8s (IngressRoute + Cert Manager + LetsEncrypt)"},"content":{"rendered":"\n<p>Here I share the recipe for how to setup High Availability<a href=\"https:\/\/traefik.io\/traefik\/\" target=\"_blank\" rel=\"noreferrer noopener\"> Traefik Proxy<\/a> (multiple instances) for Kubernetes with TLS certificates obtained from <a href=\"https:\/\/letsencrypt.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">LetsEncrypt<\/a> with help of <a href=\"https:\/\/cert-manager.io\" target=\"_blank\" rel=\"noreferrer noopener\">Cert Manager<\/a>.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>To get high availability setup for Traefik we will host multiple instances of Traefik on different hosts (or even in different availability zones). All of the Traefik instances need to load the same TLS certificates and equally participate in ACME http challenge process during obtaining the certificates from LetsEncrypt. Both can be achieved by using <a href=\"https:\/\/cert-manager.io\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cert Manager<\/a>, which stores the TLS certificates in Kubernetes secrets (no need for PVC) and carries out LetEncrypt ACME http challenge through Kubernetes Ingress entities. We leave <a href=\"https:\/\/cert-manager.io\/docs\/installation\/\" target=\"_blank\" rel=\"noreferrer noopener\">deployment of Cert Manager <\/a>out of scope for this post. The following assumes that you have Cert Manager deployed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Configuring Cert Manager for LetsEncrypt<\/h3>\n\n\n\n<p>In order to get certificates from LetsEncrypt we can define the following Issuers (CRD used by Cert Manager):<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" style=\"font-size:.875rem;line-height:1.25rem\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">YAML<\/span><span role=\"button\" tabindex=\"0\" data-code=\"apiVersion: cert-manager.io\/v1\nkind: ClusterIssuer\nmetadata:\n  name: letsencrypt-staging\nspec:\n  acme:\n    server: https:\/\/acme-staging-v02.api.letsencrypt.org\/directory\n    email: hostmaster@your-domain.tld # Replace this with your mail address\n    privateKeySecretRef:\n      name: letsencrypt-staging\n    solvers:\n    - http01:\n        ingress:\n          class: traefik\n---\napiVersion: cert-manager.io\/v1\nkind: ClusterIssuer\nmetadata:\n  name: letsencrypt-prod\nspec:\n  acme:\n    server: https:\/\/acme-v02.api.letsencrypt.org\/directory\n    email: hostmaster@your-domain.tld # Replace this with your mail address\n    privateKeySecretRef:\n      name: letsencrypt-prod\n    solvers:\n    - http01:\n        ingress:\n          class: traefik\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\"><code><span class=\"line\"><span style=\"color: #8FBCBB\">apiVersion<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">cert-manager.io\/v1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">kind<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">ClusterIssuer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">metadata<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">letsencrypt-staging<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">spec<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">acme<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">server<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">https:\/\/acme-staging-v02.api.letsencrypt.org\/directory<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">email<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">hostmaster@your-domain.tld<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\"># Replace this with your mail address<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">privateKeySecretRef<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">letsencrypt-staging<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">solvers<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">http01<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">ingress<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">class<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">traefik<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">apiVersion<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">cert-manager.io\/v1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">kind<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">ClusterIssuer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">metadata<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">letsencrypt-prod<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">spec<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">acme<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">server<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">https:\/\/acme-v02.api.letsencrypt.org\/directory<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">email<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">hostmaster@your-domain.tld<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\"># Replace this with your mail address<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">privateKeySecretRef<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">letsencrypt-prod<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">solvers<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">http01<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">ingress<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">class<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">traefik<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Configuring Traefik for Cert Manager<\/h3>\n\n\n\n<p>Note that we specified the &#8220;traefik&#8221; ingress class among ACME solvers. That is how Cert Manager will get the TLS certificates for our domains. Cert Manager can&#8217;t use IngressRoute CRD defined for Traefik as they are too application specific. Instead, it can use standard Ingress or newly emerged Gateway API Kubernetes entities. Here we use Ingress. That means that we need to enable Traefik to serve Kubernetes Ingress entities. That can be done, for instance, through CLI args:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" style=\"font-size:.875rem;--cbp-line-highlight-color:rgba(201, 218, 248, 0.2);line-height:1.25rem\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">YAML<\/span><span role=\"button\" tabindex=\"0\" data-code=\"...\n      spec:\n        containers:\n        - name: traefik\n          image: traefik:v2.9\n          args:\n            - --entrypoints.web.Address=:80\n            - --entrypoints.websecure.Address=:443\n            - --providers.kubernetescrd # needed for IngressRoutes\n            - --providers.kubernetesingress # needed for cert-manger\n          ports:\n            - name: web\n              containerPort: 80\n            - name: websecure\n              containerPort: 443\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">      <\/span><span style=\"color: #8FBCBB\">spec<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #8FBCBB\">containers<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">traefik<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">image<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">traefik:v2.9<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">args<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">--entrypoints.web.Address=:80<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">--entrypoints.websecure.Address=:443<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">--providers.kubernetescrd<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\"># needed for IngressRoutes<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">--providers.kubernetesingress<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\"># needed for cert-manger<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">          <\/span><span style=\"color: #8FBCBB\">ports<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">web<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">              <\/span><span style=\"color: #8FBCBB\">containerPort<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">80<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">websecure<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">              <\/span><span style=\"color: #8FBCBB\">containerPort<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">443<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>If you use IngressRoutes then you will have to enable both <em>kubernetescrd <\/em>and <em>kubernetesingress <\/em>Traefik configuration providers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defining &#8220;certificate&#8221; for IngressRoute<\/h3>\n\n\n\n<p>Now the Cert Manager will be able to finish the ACME http challenge for our domains. At this point we can define a certificate to obtain from LetsEncrypt. The following example defines the certificate that is used at this blog (note that you can define multiple DNS names for single certificate).<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" style=\"font-size:.875rem;line-height:1.25rem\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">YAML<\/span><span role=\"button\" tabindex=\"0\" data-code=\"apiVersion: cert-manager.io\/v1\nkind: Certificate\nmetadata:\n  name: grechka.family-tls-cert\nspec:\n  secretName: grechka.family-tls-secret\n  issuerRef:\n    name: letsencrypt-prod\n    kind: ClusterIssuer\n  dnsNames:\n    - grechka.family\n    - www.grechka.family\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\"><code><span class=\"line\"><span style=\"color: #8FBCBB\">apiVersion<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">cert-manager.io\/v1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">kind<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">Certificate<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">metadata<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">grechka.family-tls-cert<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">spec<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">secretName<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">grechka.family-tls-secret<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">issuerRef<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">letsencrypt-prod<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">kind<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">ClusterIssuer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">dnsNames<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">grechka.family<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">-<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">www.grechka.family<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Right after we create this entity in Kubernetes, Cert Manager will acquire the certificate. Now we can use the certificate in Traefik IngressRoute, like in the following example:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" style=\"font-size:.875rem;--cbp-line-highlight-color:rgba(201, 218, 248, 0.2);line-height:1.25rem\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#39404f;color:#c8d0e0\">YAML<\/span><span role=\"button\" tabindex=\"0\" data-code=\"apiVersion: traefik.containo.us\/v1alpha1\nkind: IngressRoute\nmetadata:\n  name: tls-dmitry-web-blog\nspec:\n...\n  tls:\n    secretName: grechka.family-tls-secret\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\"><code><span class=\"line\"><span style=\"color: #8FBCBB\">apiVersion<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">traefik.containo.us\/v1alpha1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">kind<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">IngressRoute<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">metadata<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">name<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">tls-dmitry-web-blog<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8FBCBB\">spec<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #8FBCBB\">tls<\/span><span style=\"color: #ECEFF4\">:<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #8FBCBB\">secretName<\/span><span style=\"color: #ECEFF4\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">grechka.family-tls-secret<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>That&#8217;s it! We have high availability Traefik with LetsEncrypt certificates.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here I share the recipe for how to setup High Availability Traefik Proxy (multiple instances) for Kubernetes with TLS certificates obtained from LetsEncrypt with help of Cert Manager.<\/p>\n","protected":false},"author":1,"featured_media":627,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[65],"tags":[69,70,71,66,68,67],"class_list":["post-622","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-it-infrastructure","tag-cert-manager","tag-highavailablilty","tag-ingressroute","tag-kubernetes","tag-letsencrypt","tag-traefik"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>HA Traefik: IngressRoute + Cert Manager + LetsEncrypt<\/title>\n<meta name=\"description\" content=\"How to deploy multiple instances of Traefik which serves certificates from LetsEncrypt while using IngressRoute at the same time.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HA Traefik: IngressRoute + Cert Manager + LetsEncrypt\" \/>\n<meta property=\"og:description\" content=\"How to deploy multiple instances of Traefik which serves certificates from LetsEncrypt while using IngressRoute at the same time.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/\" \/>\n<meta property=\"og:site_name\" content=\"Dmitry A. Grechka\" \/>\n<meta property=\"article:published_time\" content=\"2023-04-23T21:30:37+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-04-23T21:30:50+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"525\" \/>\n\t<meta property=\"og:image:height\" content=\"233\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"dmitry\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"dmitry\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/\",\"url\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/\",\"name\":\"HA Traefik: IngressRoute + Cert Manager + LetsEncrypt\",\"isPartOf\":{\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp\",\"datePublished\":\"2023-04-23T21:30:37+00:00\",\"dateModified\":\"2023-04-23T21:30:50+00:00\",\"author\":{\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/#\/schema\/person\/63485104fdec6dbe258ea67c2e053a6f\"},\"description\":\"How to deploy multiple instances of Traefik which serves certificates from LetsEncrypt while using IngressRoute at the same time.\",\"breadcrumb\":{\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#primaryimage\",\"url\":\"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp\",\"contentUrl\":\"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp\",\"width\":525,\"height\":233,\"caption\":\"HA Traefik + CertManager + LetsEncrypt\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/grechka.family\/dmitry\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"High Availability Traefik for K8s (IngressRoute + Cert Manager + LetsEncrypt)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/#website\",\"url\":\"https:\/\/grechka.family\/dmitry\/blog\/\",\"name\":\"Dmitry A. Grechka\",\"description\":\"Personal blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/grechka.family\/dmitry\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/#\/schema\/person\/63485104fdec6dbe258ea67c2e053a6f\",\"name\":\"dmitry\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/grechka.family\/dmitry\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ce55dc1fed08e9a15667f56e3285826aa634c717d9c0e34809d717f699bb7b0b?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ce55dc1fed08e9a15667f56e3285826aa634c717d9c0e34809d717f699bb7b0b?s=96&d=identicon&r=g\",\"caption\":\"dmitry\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HA Traefik: IngressRoute + Cert Manager + LetsEncrypt","description":"How to deploy multiple instances of Traefik which serves certificates from LetsEncrypt while using IngressRoute at the same time.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/","og_locale":"en_GB","og_type":"article","og_title":"HA Traefik: IngressRoute + Cert Manager + LetsEncrypt","og_description":"How to deploy multiple instances of Traefik which serves certificates from LetsEncrypt while using IngressRoute at the same time.","og_url":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/","og_site_name":"Dmitry A. Grechka","article_published_time":"2023-04-23T21:30:37+00:00","article_modified_time":"2023-04-23T21:30:50+00:00","og_image":[{"width":525,"height":233,"url":"http:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp","type":"image\/webp"}],"author":"dmitry","twitter_misc":{"Written by":"dmitry","Estimated reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/","url":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/","name":"HA Traefik: IngressRoute + Cert Manager + LetsEncrypt","isPartOf":{"@id":"https:\/\/grechka.family\/dmitry\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#primaryimage"},"image":{"@id":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#primaryimage"},"thumbnailUrl":"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp","datePublished":"2023-04-23T21:30:37+00:00","dateModified":"2023-04-23T21:30:50+00:00","author":{"@id":"https:\/\/grechka.family\/dmitry\/blog\/#\/schema\/person\/63485104fdec6dbe258ea67c2e053a6f"},"description":"How to deploy multiple instances of Traefik which serves certificates from LetsEncrypt while using IngressRoute at the same time.","breadcrumb":{"@id":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#primaryimage","url":"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp","contentUrl":"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp","width":525,"height":233,"caption":"HA Traefik + CertManager + LetsEncrypt"},{"@type":"BreadcrumbList","@id":"https:\/\/grechka.family\/dmitry\/blog\/2023\/04\/ha-traefik-for-k8s-ingressroutes-cert-manager-letsencrypt\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/grechka.family\/dmitry\/blog\/"},{"@type":"ListItem","position":2,"name":"High Availability Traefik for K8s (IngressRoute + Cert Manager + LetsEncrypt)"}]},{"@type":"WebSite","@id":"https:\/\/grechka.family\/dmitry\/blog\/#website","url":"https:\/\/grechka.family\/dmitry\/blog\/","name":"Dmitry A. Grechka","description":"Personal blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/grechka.family\/dmitry\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/grechka.family\/dmitry\/blog\/#\/schema\/person\/63485104fdec6dbe258ea67c2e053a6f","name":"dmitry","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/grechka.family\/dmitry\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/ce55dc1fed08e9a15667f56e3285826aa634c717d9c0e34809d717f699bb7b0b?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ce55dc1fed08e9a15667f56e3285826aa634c717d9c0e34809d717f699bb7b0b?s=96&d=identicon&r=g","caption":"dmitry"}}]}},"jetpack_featured_media_url":"https:\/\/grechka.family\/dmitry\/blog\/wp-content\/uploads\/2023\/04\/ha_traefik.webp","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/posts\/622","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/comments?post=622"}],"version-history":[{"count":7,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/posts\/622\/revisions"}],"predecessor-version":[{"id":631,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/posts\/622\/revisions\/631"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/media\/627"}],"wp:attachment":[{"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/media?parent=622"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/categories?post=622"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/grechka.family\/dmitry\/blog\/wp-json\/wp\/v2\/tags?post=622"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}