kubernetessslload-balancing

Using HTTPS and providing certificate for kubernetes LoadBalancer


I'm a bit new to kubernetes and am trying to set up a LoadBalancer which uses HTTPS. Checking online it appears the recommended way is to use and Ingress Controller. I'm trying to avoid doing that as I am already using a reverse proxy and do not want to add another layer on top (the ingress controller being the second reverse proxy).

Is there a way to set up my LoadBalancer service to use the certificates I have deployed and stored in my cert-manager? For example, using ingress it would be something like:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myApp
  namespace: myApp
spec:
  ingressClassName: internal
  tls:
    - hosts:
        - myApp.com
      secretName: myApp.com
  rules:
    - host: myApp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myApp
                port:
                  number: 443

Doing it like this handles getting the certificate by using secretName. But I can't find a way to do something similar using only a LoadBalancer service.

Currently my set up is like below, please let me know what I am missing here.

Added cert file to the cert manager:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: myApp
  namespace: myApp
spec:
  secretName: myApp.com
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt
  commonName: myApp.com
  dnsNames:
    - myApp.com

Service:

apiVersion: v1
kind: Service
metadata:
  name: myApp
  namespace: myApp
spec:
  selector:
    app: myApp
  type: LoadBalancer
  ports:
    - name: http
      port: 80
      targetPort: 5173
      protocol: TCP
    - name: https
      port: 443
      targetPort: 5173
      protocol: TCP

Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myApp
  namespace: myApp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myApp
  template:
    metadata:
      labels:
        app: myApp
    spec:
      containers:
        - name: myApp
          image: someImageHere
          resources:
            requests:
              cpu: 100m
              memory: 2000Mi
            limits:
              cpu: 500m
              memory: 2000Mi
          ports:
            - name: myApp
              containerPort: 5173
          envFrom:
            - configMapRef:
                name: myApp-config

Solution

  • From my experience, what you’re trying to achieve(using HTTPS directly with a Kubernetes LoadBalancer service without setting up an Ingress controller) would require you to configure your application to handle SSL/TLS termination within the pod itself. This means your application will directly use the certificates stored in Kubernetes secrets managed by cert-manager, and it will be responsible for terminating the HTTPS connections.

    From your description, I see you already have a Certificate resource configured with cert-manager. This should automatically create a Kubernetes secret (myApp.com) containing the TLS certificate and key.

    You need to configure your application to load the TLS certificate and key from files by mounting them into your pod from the Kubernetes secret.

    You can update your Deployment configuration to mount the secret as a volume:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myApp
      namespace: myApp
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: myApp
      template:
        metadata:
          labels:
            app: myApp
        spec:
          containers:
            - name: myApp
              image: someImageHere
              ports:
                - name: https
                  containerPort: 443
              volumeMounts:
                - name: cert-volume
                  mountPath: "/etc/ssl/certs"
                  readOnly: true
              envFrom:
                - configMapRef:
                    name: myApp-config
          volumes:
            - name: cert-volume
              secret:
                secretName: myApp.com
    

    The change I’ve made here configured your application to load the SSL certificate and key from /etc/ssl/certs. This directory will contain the files from the secret myApp.com, typically tls.crt for the certificate and tls.key for the private key.

    Your Service configuration appears to be correct. But it should only need to route traffic for port 443 to your application, which will now be configured to handle HTTPS traffic:

    apiVersion: v1
    kind: Service
    metadata:
      name: myApp
      namespace: myApp
    spec:
      selector:
        app: myApp
      type: LoadBalancer
      ports:
        - name: https
          port: 443
          targetPort: https
          protocol: TCP
    

    Deploy these changes to your cluster. If done correctly, the LoadBalancer service will expose your application on HTTPS port 443, routing traffic directly to your pod which now handles SSL/TLS termination.

    You also want to make sure that your DNS records (e.g., for myApp.com) point to the external IP address provided by the LoadBalancer service. You can find this IP address in the EXTERNAL-IP field when you run kubectl get svc.

    Hope this helps or at least points you in the right direction.