How to debug Kubernetes Ingress? (TLS - Cert-Manager - HTTP-01 & DNS-01 Challenges)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Most of the time when we expose  our application to the internet,   we want it to be secure. One way we can  protect it is by encrypting all traffic   between the client and the application itself.  This would help prevent man-in-the-middle attacks,   where an unauthorized entity can intercept every  single packet that you send to the server. For   example, if it's an ecommerce website, a hacker  can steal your credit card number if you enter it   in the online form to pay for goods. Also, if you  enter the username and password for social media,   this information can also be stolen. Now, when  we encrypt the traffic, even if a hacker can   still listen to all the communications between  us and the application, they won’t be able   to decrypt that data such as credit card  information or a username and a password. To encrypt the traffic, we need to get a  certificate from a well-known trusted certificate   authority. And the best part is it’s free if  you use Let's Encrypt. The key part here is   "well-known," because you can generate your  own certificate authority and issue yourself   a certificate, but no one in the world would trust  it. The trust is established by installing a root   certificate from the CA, such as Let's Encrypt.  Since most of the computers and mobile devices are   shipped with pre-installed root certificates,  you don’t need to worry about that part. When a client first visits a website  protected by TLS, the client and the   server perform a TLS handshake. During the  TLS handshake, they generate session keys,   and those keys are used to encrypt and  decrypt all communications after that. Now, to issue a certificate, first you need  to generate a private key and a certificate   request. Then you would send the certificate  request to a certificate authority such as   Let's Encrypt to have it signed. And of course,  you would put a domain name or multiple ones in   the certificate request that you want to  use, such as devopsbyexample.com. Next,   the certificate authority would ask you to prove  that you actually own that domain. You usually   have three options. You can choose to verify it  using email, which is very hard to automate and   isn’t used in Kubernetes. Another more common  options are the HTTP-01 and DNS-01 challenges. First, let's talk about the HTTP-01 challenge.  This is a generic challenge that is not unique to   Let's Encrypt. When you request a certificate,  Let's Encrypt will give you a token which you   need to expose on your website by following  a specific pattern. Let's Encrypt would try   to retrieve that token back from you multiple  times, and if it succeeds, it will sign your   certificate request and issue a certificate. Keep  in mind the certificate is public and everyone   can have a copy of it, but you must keep your  private key secure and not give it to anyone. Second, a common challenge is DNS-01. Let's  Encrypt will give you the same token, but you   will need to create a TXT DNS record to prove that  you control your domain. When Let's Encrypt is   able to query DNS and retrieve that token, they  will issue a certificate. Later in the video,   we’ll discuss which challenge you should use in  production and why. It’s not only my preference   but it’s based on real-world experience. And in  the second part, we’ll run two demos, and I’ll   show you how to use both challenges, which are  applicable in all clouds: AWS, GCP, and Azure. To automate this process, there are a few clients  that can help you depending on your use case. If   you want to get certificates for Kubernetes,  most of the time you would use cert-manager. No matter which challenge you use, HTTP-01  or DNS-01, cert-manager internally follows   the same process. When you create an ingress  and specify the TLS section, cert-manager will   create a Certificate custom resource and  generate a private key that will be stored   in the Kubernetes secret. Then, cert-manager  will create a CertificateRequest custom resource,   and in this case, the certificate request will  be stored in the custom resource itself since   it’s public. The CertificateRequest will create  an order, and finally, the order will create a   challenge. The challenge can be either HTTP-01  or DNS-01 type. When the challenge is resolved,   cert-manager will receive a public certificate  and store it in the same Kubernetes secret with   the private key. That certificate will be valid  for 90 days, and approximately every 60 days,   cert-manager will automatically renew  it by following the same process. When you register with Let's  Encrypt, you use your email address,   and if for some reason cert-manager fails  to renew it, you’ll get an email warning.   You can also use Prometheus and create  an alert based on the expiration date. Now when you get the certificate, the  encryption and decryption are performed   at the ingress controller level, and all  traffic inside your Kubernetes cluster will   stay unencrypted. There are options to encrypt  absolutely all traffic, but in most cases,   it’s not necessary, and since encryption is  a CPU-intensive task, it will require you to   allocate more resources to your applications,  and you may see an increase in latency as well. Alright, let’s go ahead and run the demo. The  first http-01 challenge is much easier to set up,   and you’ll see why soon. First of all, we  need to create an issuer or cluster issuer.   I prefer clusterIssuer because you can create  it once and use it in all namespaces. Then,   you MUST specify your email address. If, for some  reason, cert-manager fails to renew your cert,   you’ll get an email message. Then we  can use the production environment,   or if you have never used it, you can  try the staging environment. By the way,   I have a detailed tutorial on how to set  everything up. Then it’s very important for   this issuer to properly set up ingressClassName.  It must match the same ingress class name that you   used when you deployed the nginx ingress  controller. Previously, we had to use   additional ingress annotations to resolve this  challenge, but newer versions of cert-managers   support the ingressClassName property. Then we have a simple deployment object.   Take note of the HTTP variable that  we will reference in the service. Next, we have a service and use that HTTP  variable as the targetPort. It’s optional,   but I still prefer this approach; you  can just drop the targetPort altogether. And for the ingress, we must specify the cluster  issuer that we created earlier, the host that you   want to use, and you must match the service  name and the port number to make it work.  And of course, we need to define TLS section  if we want to secure it with a TLS certificate.  So, I have Terraform code that you can  use to create an EKS cluster in AWS,   but the Terraform code for cert-manager and  ingress controller is generic and can be used   in other clouds. You just need to use proper  annotations to create layer 4 load balancers.   In most clouds, it’s the default, but in AWS,  to get it instead of a classic load balancer,   you have to explicitly define it. You  can find the source code in my public   GitHub repo; the link is in the description. Alright, let’s go ahead and apply this first   example. As soon as you create ingress with TLS  section, cert-manager will immediately create   a certificate custom resource placeholder. As  you can see, initially, it won’t be ready. Now,   cert-manager at the same time generates a private  key, and it will be stored in a native Kubernetes   secret. That Certificate custom resource  will simply have a reference to that secret. Every Kubernetes secret is encoded in base64,  so if you want to get the private key for some   reason, maybe to test something, you can get the  value using the YAML output option. Then you can   just use the base64 Linux utility and decode  it. Keep in mind, base64 is not encryption;   it’s just a common encoding technique. And  this is actually the private key itself.  Now, let me show you how to debug if the  certificate remains in the 'Non-ready' state.   Well, as with any other custom resource, you  can describe it and get related events. This is   the best place to start. If you have multiple  certificates, you would add the name of the   certificate, such as app-devopsbyexample-com,  at the end of this command. Now you can see that the CertificateRequest custom  resource was created. And you can also notice the   reference to the private key Kubernetes secret. Well, let’s go ahead and describe that   CertificateRequest. In this case, you can  actually find the certificate request itself as   a part of the custom resource. Well, because it’s  public, and you can safely share it with anyone. We can use the same approach if you want, and  decode that request to the regular string from   base64. Alright, this is the certificate request. Now let me describe that request one more time.   And you can see the event  that an Order was created. Alright, let’s go ahead and describe it  as well. And finally, you can find that   the challenge was created. Let’s describe  that challenge. Here you can actually find   the reason why the certificate remains  in the pending state. Well, obviously,   we need to create a DNS record and point  it to the load balancer. You don’t need   to specifically create something to resolve  that challenge; this DNS is needed in either   case just to route traffic to your application in  Kubernetes. You can install an additional addon,   external-dns, which can automatically create  DNS, but it’s out of scope for this tutorial. Alright, let’s go ahead and  create a DNS record. In AWS,   you need to create a CNAME or an  alias if it’s managed by Route53. Before that, let me show you that cert-manager  actually created an additional ingress in   Kubernetes to resolve the challenge. Also,  it has a pod and a service. This pod simply   returns the token that LetsEncrypt  gave it to prove that you control   your domain. When the challenge is resolved,  all those additional objects—ingress, pod,   and service—will be deleted and only recreated  in about 60 days to renew your certificate. Let’s go ahead and create the CNAME DNS  record to make our ingress work. In AWS,   you would use the load balancer  hostname as a value; in GCP and Azure,   you’ll get an IP address and you would  need to create an A record instead. Now   let’s wait until the challenge is resolved.  In my case, it took a couple of minutes,   but it’s possible to take even a few hours; just  try to resolve your domain yourself to verify. If   the certificate remains in a non-ready state, just  describe the challenge again, and you’ll see why. You can see that the temporary ingress was  removed, as well as the service and the pod.  Finally, let’s check in the browser if we can  access your application using HTTPS. Alright,   it works, and you can get a certificate  to check the issuer and expiration date.   And the challenge will be removed as well. Let’s clean up and delete the first  example. To automate the DNS-01 challenge,   you need to integrate your cert-manager with  a cloud DNS provider. It works with AWS, GCP,   Azure, and many others; you just need  to provide credentials. In my case,   I used an OpenID Connect provider and  created a dedicated IAM role to be used   by the cert-manager Kubernetes service  account. It’s all in the Terraform code. I already have a public hosted  zone with a few records. For this issuer, you need to provide the resolver;   in this case, it’s Route 53. You also need  to specify the region, hosted zone ID,   as well as the hosted zone domain. Other than  that, the remaining components stay the same. In Terraform, you can find how to configure  it to resolve the DNS-01 challenge. You need   to provide the service account name and  the IAM role ARN. If you make a mistake,   cert-manager will complain that it does not  have permissions to create DNS TXT records.  And this is the role itself with the  necessary permissions to create Route   53 DNS records. You can improve it a little  by limiting access to only a specific hosted   zone. And also keep in mind that cert-manager  must be deployed in the cert-manager namespace.  Alright, let’s go ahead and apply it.  Now we see the same certificate. And   if we describe the challenge, you’ll see the  DNS-01 type instead of HTTP-01. In Route 53,   you can find the TXT record that was created by  cert-manager to prove ownership. In a few minutes,   you should get a certificate. Also,  let's create a CNAME record for our   ingress. You can automate this  with the external-dns component. Let’s make sure that DNS is  ready. And from the browser,   you can verify that the certificate is valid. Now this approach to resolve the DNS-01  challenge requires more configurations   but is preferred in production. For example, in  the case of disaster recovery or if you simply   migrate your applications from one Kubernetes  cluster to another, with the HTTP-01 challenge,   it would take a few minutes to obtain a  certificate, which means your clients won’t   be able to connect to your application,  and it will cause downtime. With DNS-01,   you can obtain a certificate before you start  shifting traffic to the new location. You can   start with HTTP-01; it’s not a big deal,  and when you need to migrate your app,   just configure the DNS resolver. Thank you for  watching, and I’ll see you in the next video.
Info
Channel: Anton Putra
Views: 4,880
Rating: undefined out of 5
Keywords: kubernetes, k8s, cloud, kubernetes tutorial, k8s tutorial, k8s ingress, k8s networking, k8s explained, kubernetes tutorial for beginners, kubernetes explained, kubernetes interview questions, kubernetes crash course, kubernetes networking, kubernetes ingress, kubernetes for beginners, kubernetes cluster, cert-manager, cert-manager helm, cert manager nginx ingress, terraform, devops, anton putra, aws, eks, gcp-azure, letsencrypt
Id: DJ2sa49iEKo
Channel Id: undefined
Length: 15min 18sec (918 seconds)
Published: Mon Apr 29 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.