<p>I'm using standard procedure for enabling HTTPS termination for my application that is running on Kubernetes using:
- Ingress nginx
- AWS ELB classic
- Cert Manager for Let's encrypt</p>

<p>I've used procedure described here: <a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes" rel="nofollow noreferrer">https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes</a></p>

<p>I've been <strong>able to make Ingress work with HTTP</strong> before but I'm having problem with HTTPS where I'm getting following error when I try to cURL app URL:</p>

<pre><code>$ curl -iv https://&lt;SERVER&gt;
* Rebuilt URL to: &lt;SERVER&gt;
*   Trying &lt;IP_ADDR&gt;...
* Connected to &lt;SERVER&gt; (&lt;IP_ADDR&gt;) port 443 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* found 592 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* gnutls_handshake() failed: An unexpected TLS packet was received.
* Closing connection 0
curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received.
</code></pre>

<p>This is what I currently have:</p>

<p><strong>Cert manager running in kube-system namespace:</strong></p>

<pre><code>$ kubectl get pods -n kube-system
    NAME                                     READY   STATUS      RESTARTS   AGE
    cert-manager-5f8db6f6c4-c4t4k            1/1     Running     0          2d1h
    cert-manager-webhook-85dd96d87-rxc7p     1/1     Running     0          2d1h
    cert-manager-webhook-ca-sync-pgq6b       0/1     Completed   2          2d1h
</code></pre>

<p><strong>Ingress setup in ingress-nginx namespace:</strong></p>

<pre><code>$ kubectl get all -n ingress-nginx
NAME                                            READY   STATUS    RESTARTS   AGE
pod/default-http-backend-587b7d64b5-ftws2       1/1     Running   0          2d1h
pod/nginx-ingress-controller-68bb4bfd98-zsz8d   1/1     Running   0          12h

NAME                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/default-http-backend   ClusterIP   &lt;IP_ADDR_1&gt;   &lt;none&gt;        80/TCP                       2d1h
service/ingress-nginx          NodePort    &lt;IP_ADDR_2&gt;   &lt;none&gt;        80:32327/TCP,443:30313/TCP   2d1h

NAME                                       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/default-http-backend       1         1         1            1           2d1h
deployment.apps/nginx-ingress-controller   1         1         1            1           12h
</code></pre>

<p><strong>Application and ingress in app namespace:</strong></p>

<pre><code>$ kubectl get all -n app
NAME              READY   STATUS    RESTARTS   AGE
pod/appserver-0   1/1     Running   0          2d1h

NAME                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)         AGE
service/appserver   ClusterIP   &lt;IP_ADDR&gt;   &lt;none&gt;        22/TCP,80/TCP   2d1h

NAME                         DESIRED   CURRENT   AGE
statefulset.apps/appserver   1         1         2d1h

$ kubectl describe ingress -n app
Name:             appserver
Namespace:        app
Address:
Default backend:  default-http-backend:80 (&lt;none&gt;)
TLS:
  letsencrypt-prod terminates &lt;SERVER&gt;
Rules:
  Host                      Path  Backends
  ----                      ----  --------
  &lt;SERVER&gt;
                            /   appserver:80 (&lt;none&gt;)
Annotations:
  certmanager.k8s.io/cluster-issuer:  letsencrypt-prod
  kubernetes.io/ingress.class:        nginx
Events:                               &lt;none&gt;
</code></pre>

<p>This is how ingress resource looks like:</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
  name: appserver
  namespace: app
spec:
  tls:
  - hosts:
    - &lt;SERVER&gt;
    secretName: letsencrypt-prod
  rules:
  - host: &lt;SERVER&gt;
    http:
      paths:
      - backend:
          serviceName: appserver
          servicePort: 80
        path: /
</code></pre>

<p><strong>Additional checks that I've done:</strong></p>

<p>Checked that certificates have been generated correctly:</p>

<pre><code>$ kubectl describe cert -n app
Name:         letsencrypt-prod
...
Status:
  Conditions:
    Last Transition Time:  2019-03-20T14:23:07Z
    Message:               Certificate is up to date and has not expired
    Reason:                Ready
    Status:                True
    Type:                  Ready
</code></pre>

<p>Checked logs from cert-manager:</p>

<pre><code>$ kubectl logs -f cert-manager-5f8db6f6c4-c4t4k -n kube-system
...
I0320 14:23:08.368872       1 sync.go:177] Certificate "letsencrypt-prod" for ingress "appserver" already exists
I0320 14:23:08.368889       1 sync.go:180] Certificate "letsencrypt-prod" for ingress "appserver" is up to date
I0320 14:23:08.368894       1 controller.go:179] ingress-shim controller: Finished processing work item "app/appserver"
I0320 14:23:12.548963       1 controller.go:183] orders controller: syncing item 'app/letsencrypt-prod-1237734172'
I0320 14:23:12.549608       1 controller.go:189] orders controller: Finished processing work item "app/letsencrypt-prod-1237734172"
</code></pre>

<p>Not really sure at this point what else might be worth of checking? </p>

<p>It appears that you are using legacy versions of the nginx-ingress with cert-manager, which could be the culprit to your error.</p>

<p>I suggest you try to deploy the nginx-ingress with Helm using the latest version (ensure that the image tag is v0.23.0 for the nginx-ingress-controller). Also make sure you are deploying your cert-manager with the latest version (--version v0.7.0) during your helm deployment. You should see three pods by default: cert-manager, cert-manager-cainjector, and cert-manager-webhook. </p>

<p>I had to disable the webhook because it was preventing the certificate from being issued despite providing it with the correct parameters, so you may have to do the same. </p>

<p>Hope this helps!</p>
