K3s deploys Traefik as the default Ingress with the Helm chart. Traefik configuration can be managed with the HelmChartConfig CRD that allows you to define any values you would otherwise supply directly with helm --set or helm --values.
Example:
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
      - "--entrypoints.websecure.http.tls.certresolver=letsencrypt"
      - "--entrypoints.websecure.http.tls.domains[0].main=ravianand.me"
      - "--certificatesresolvers.letsencrypt.acme.tlsChallenge"
      - "--certificatesresolvers.letsencrypt.acme.email=moravrav@gmail.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json"
      # - "--certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--experimental.plugins.htransformation.modulename=github.com/tomMoulard/htransformation"
      - "--experimental.plugins.htransformation.version=v0.2.7"
    ports:
      web:
        redirectTo: websecure
    persistence:
      enabled: true
      storageClass: local-path
      path: /data
    logs:
      access:
        enabled: true
    experimental:
      plugins:
        enabled: true
Simply apply this to your cluster with kubectl apply -f traefik-config.yml and wait for the Traefik pod to restart. This will setup Let's Encrypt and the htransformation plugin for Traefik, as well as enable persistence for certificates.
Traefik supports both Kubernetes Ingress, and a CRD to services under your domain. The Kubernetes Ingress supports most of Traefik's features, so you can use that which makes it easier to switch to a different reverse proxy if needed.
Example Ingress with Let's Encrypt:
resource "kubernetes_ingress_v1" "my_ingress" {
  metadata {
    name      = "my_ingress"
    namespace = kubernetes_namespace.my_namespace.metadata.0.name
    annotations = {
      "traefik.ingress.kubernetes.io/router.entrypoints"      = "websecure"
      "traefik.ingress.kubernetes.io/router.tls.certresolver" = "letsencrypt"
    }
  }
  spec {
    rule {
      host = var.host
      http {
        path {
          path      = "/"
          path_type = "Prefix"
          backend {
            service {
              name = kubernetes_service.my_service.metadata.0.name
              port {
                name = kubernetes_service.my_service.spec.port.0.name
              }
            }
          }
        }
      }
    }
  }
}
With Terraform you can use references to other resources, such as the Kubernetes service, to make sure that the Ingress is only deployed once the service is ready. This will also map the port name and service name correctly to avoid errors.
It's important to make sure that the entrypoints is the same as what you configured in Traefik and you use a certresolver that you configured.