kubernetes-ingress: HTTP to HTTPS not working

Describe the bug we have been having lots of issues trying to implement this helm chart on to our production environment. The documentation is not as straightforward as we need it to be in order to implement correctly. at the moment we have a couple of issues which we would like to get some guidance if possible or a solution.

  1. HTTP to HTTPS not working - in a perfect scenario we would like to control which endpoints esposes http or https. at this moment it’s been so frustrating that i’m ok with everything on HTTPS. we would like to know how to expose all endpoints on HTTPS. if users tries to use http it redirects them to https.

  2. we are also getting this message from the logs with in the nginx pod. - W1120 21:27:50.592441 1 controller.go:2667] Using the DEPRECATED annotation ‘kubernetes.io/ingress.class’. The ‘ingressClassName’ field will be ignored.

To Reproduce Steps to reproduce the behavior:

  1. helm upgrade --install internal -f nginx/internal.yml nginx/nginx-ingress --version 0.7.0 --namespace nginx-ingress
  2. kubectl logs internal-nginx-ingress-76cd6c89c5-6bzsk -n nginx-ingress
  3. apps run but when accessing the endpoints it allows me to use HTTP, and HTTPS should only be HTTPS

Expected behavior we want to deploy 2 nginx controllers in the same environment one for internal use and the other for external use. both will have 4 replicas for each node we have in the prod env. and all apps should ONLY work on HTTPS.

Your environment

  • Version of the Ingress Controller --version 0.7.0

  • Version of Kubernetes Client Version: version.Info{Major:“1”, Minor:“19”, GitVersion:“v1.19.3”, GitCommit:“1e11e4a2108024935ecfcb2912226cedeafd99df”, GitTreeState:“clean”, BuildDate:“2020-10-14T18:49:28Z”, GoVersion:“go1.15.2”, Compiler:“gc”, Platform:“darwin/amd64”} Server Version: version.Info{Major:“1”, Minor:“18”, GitVersion:“v1.18.9”, GitCommit:“94f372e501c973a7fa9eb40ec9ebd2fe7ca69848”, GitTreeState:“clean”, BuildDate:“2020-09-16T13:47:43Z”, GoVersion:“go1.13.15”, Compiler:“gc”, Platform:“linux/amd64”}

  • Kubernetes platform (e.g. Mini-kube or GCP) we run KOPS on AWS. we currently have 3 master nodes, and 4 worker nodes

  • Using NGINX or NGINX Plus we are currently using NGINX

Additional context Add any other context about the problem here. Any log files you want to share.

my current configuration file

controller:
  ## The name of the Ingress controller daemonset or deployment.
  ## Autogenerated if not set or set to "".
  # name: nginx-ingress

  ## The kind of the Ingress controller installation - deployment or daemonset.
  kind: deployment

  ## Deploys the Ingress controller for NGINX Plus.
  nginxplus: false

  # Timeout in milliseconds which the Ingress Controller will wait for a successful NGINX reload after a change or at the initial start.
  # Default is 4000 (default is 20000 instead if enable-app-protect is true)
  # If set to 0, default values will be used.
  nginxReloadTimeout: 0

  ## Support for App Protect
  appprotect:
    ## Enable the App Protect module in the Ingress Controller.
    enable: false

  ## Enables the Ingress controller pods to use the host's network namespace.
  hostNetwork: false

  ## Enables debugging for NGINX. Uses the nginx-debug binary. Requires error-log-level: debug in the ConfigMap via `controller.config.entries`.
  nginxDebug: true

  ## The log level of the Ingress Controller.
  logLevel: 1

  ## A list of custom ports to expose on the NGINX ingress controller pod. Follows the conventional Kubernetes yaml syntax for container ports.
  customPorts: []

  image:
    ## The image repository of the Ingress controller.
    repository: nginx/nginx-ingress

    ## The tag of the Ingress controller image.
    tag: "1.9.0"

    ## The pull policy for the Ingress controller image.
    pullPolicy: IfNotPresent

  config:
    ## The name of the ConfigMap used by the Ingress controller.
    ## Autogenerated if not set or set to "".
    # name: nginx-config

    ## The annotations of the Ingress Controller configmap.
    annotations: {}

    ## The entries of the ConfigMap for customizing NGINX configuration.
    entries: {}

  ## It is recommended to use your own TLS certificates and keys
  defaultTLS:
    ## The base64-encoded TLS certificate for the default HTTPS server. If not specified, a pre-generated self-signed certificate is used.
    ## Note: It is recommended that you specify your own certificate.
    cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN2akNDQWFZQ0NRREFPRjl0THNhWFhEQU5CZ2txaGtpRzl3MEJBUXNGQURBaE1SOHdIUVlEVlFRRERCWk8KUjBsT1dFbHVaM0psYzNORGIyNTBjbTlzYkdWeU1CNFhEVEU0TURreE1qRTRNRE16TlZvWERUSXpNRGt4TVRFNApNRE16TlZvd0lURWZNQjBHQTFVRUF3d1dUa2RKVGxoSmJtZHlaWE56UTI5dWRISnZiR3hsY2pDQ0FTSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUwvN2hIUEtFWGRMdjNyaUM3QlBrMTNpWkt5eTlyQ08KR2xZUXYyK2EzUDF0azIrS3YwVGF5aGRCbDRrcnNUcTZzZm8vWUk1Y2Vhbkw4WGM3U1pyQkVRYm9EN2REbWs1Qgo4eDZLS2xHWU5IWlg0Rm5UZ0VPaStlM2ptTFFxRlBSY1kzVnNPazFFeUZBL0JnWlJVbkNHZUtGeERSN0tQdGhyCmtqSXVuektURXUyaDU4Tlp0S21ScUJHdDEwcTNRYzhZT3ExM2FnbmovUWRjc0ZYYTJnMjB1K1lYZDdoZ3krZksKWk4vVUkxQUQ0YzZyM1lma1ZWUmVHd1lxQVp1WXN2V0RKbW1GNWRwdEMzN011cDBPRUxVTExSakZJOTZXNXIwSAo1TmdPc25NWFJNV1hYVlpiNWRxT3R0SmRtS3FhZ25TZ1JQQVpQN2MwQjFQU2FqYzZjNGZRVXpNQ0F3RUFBVEFOCkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWpLb2tRdGRPcEsrTzhibWVPc3lySmdJSXJycVFVY2ZOUitjb0hZVUoKdGhrYnhITFMzR3VBTWI5dm15VExPY2xxeC9aYzJPblEwMEJCLzlTb0swcitFZ1U2UlVrRWtWcitTTFA3NTdUWgozZWI4dmdPdEduMS9ienM3bzNBaS9kclkrcUI5Q2k1S3lPc3FHTG1US2xFaUtOYkcyR1ZyTWxjS0ZYQU80YTY3Cklnc1hzYktNbTQwV1U3cG9mcGltU1ZmaXFSdkV5YmN3N0NYODF6cFErUyt1eHRYK2VBZ3V0NHh3VlI5d2IyVXYKelhuZk9HbWhWNThDd1dIQnNKa0kxNXhaa2VUWXdSN0diaEFMSkZUUkk3dkhvQXprTWIzbjAxQjQyWjNrN3RXNQpJUDFmTlpIOFUvOWxiUHNoT21FRFZkdjF5ZytVRVJxbStGSis2R0oxeFJGcGZnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=

    ## The base64-encoded TLS key for the default HTTPS server. Note: If not specified, a pre-generated key is used.
    ## Note: It is recommended that you specify your own key.
    key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdi91RWM4b1JkMHUvZXVJTHNFK1RYZUprckxMMnNJNGFWaEMvYjVyYy9XMlRiNHEvClJOcktGMEdYaVN1eE9ycXgrajlnamx4NXFjdnhkenRKbXNFUkJ1Z1B0ME9hVGtIekhvb3FVWmcwZGxmZ1dkT0EKUTZMNTdlT1l0Q29VOUZ4amRXdzZUVVRJVUQ4R0JsRlNjSVo0b1hFTkhzbysyR3VTTWk2Zk1wTVM3YUhudzFtMApxWkdvRWEzWFNyZEJ6eGc2clhkcUNlUDlCMXl3VmRyYURiUzc1aGQzdUdETDU4cGszOVFqVUFQaHpxdmRoK1JWClZGNGJCaW9CbTVpeTlZTW1hWVhsMm0wTGZzeTZuUTRRdFFzdEdNVWozcGJtdlFmazJBNnljeGRFeFpkZFZsdmwKMm82MjBsMllxcHFDZEtCRThCay90elFIVTlKcU56cHpoOUJUTXdJREFRQUJBb0lCQVFDZklHbXowOHhRVmorNwpLZnZJUXQwQ0YzR2MxNld6eDhVNml4MHg4Mm15d1kxUUNlL3BzWE9LZlRxT1h1SENyUlp5TnUvZ2IvUUQ4bUFOCmxOMjRZTWl0TWRJODg5TEZoTkp3QU5OODJDeTczckM5bzVvUDlkazAvYzRIbjAzSkVYNzZ5QjgzQm9rR1FvYksKMjhMNk0rdHUzUmFqNjd6Vmc2d2szaEhrU0pXSzBwV1YrSjdrUkRWYmhDYUZhNk5nMUZNRWxhTlozVDhhUUtyQgpDUDNDeEFTdjYxWTk5TEI4KzNXWVFIK3NYaTVGM01pYVNBZ1BkQUk3WEh1dXFET1lvMU5PL0JoSGt1aVg2QnRtCnorNTZud2pZMy8yUytSRmNBc3JMTnIwMDJZZi9oY0IraVlDNzVWYmcydVd6WTY3TWdOTGQ5VW9RU3BDRkYrVm4KM0cyUnhybnhBb0dCQU40U3M0ZVlPU2huMVpQQjdhTUZsY0k2RHR2S2ErTGZTTXFyY2pOZjJlSEpZNnhubmxKdgpGenpGL2RiVWVTbWxSekR0WkdlcXZXaHFISy9iTjIyeWJhOU1WMDlRQ0JFTk5jNmtWajJTVHpUWkJVbEx4QzYrCk93Z0wyZHhKendWelU0VC84ajdHalRUN05BZVpFS2FvRHFyRG5BYWkyaW5oZU1JVWZHRXFGKzJyQW9HQkFOMVAKK0tZL0lsS3RWRzRKSklQNzBjUis3RmpyeXJpY05iWCtQVzUvOXFHaWxnY2grZ3l4b25BWlBpd2NpeDN3QVpGdwpaZC96ZFB2aTBkWEppc1BSZjRMazg5b2pCUmpiRmRmc2l5UmJYbyt3TFU4NUhRU2NGMnN5aUFPaTVBRHdVU0FkCm45YWFweUNweEFkREtERHdObit3ZFhtaTZ0OHRpSFRkK3RoVDhkaVpBb0dCQUt6Wis1bG9OOTBtYlF4VVh5YUwKMjFSUm9tMGJjcndsTmVCaWNFSmlzaEhYa2xpSVVxZ3hSZklNM2hhUVRUcklKZENFaHFsV01aV0xPb2I2NTNyZgo3aFlMSXM1ZUtka3o0aFRVdnpldm9TMHVXcm9CV2xOVHlGanIrSWhKZnZUc0hpOGdsU3FkbXgySkJhZUFVWUNXCndNdlQ4NmNLclNyNkQrZG8wS05FZzFsL0FvR0FlMkFVdHVFbFNqLzBmRzgrV3hHc1RFV1JqclRNUzRSUjhRWXQKeXdjdFA4aDZxTGxKUTRCWGxQU05rMXZLTmtOUkxIb2pZT2pCQTViYjhibXNVU1BlV09NNENoaFJ4QnlHbmR2eAphYkJDRkFwY0IvbEg4d1R0alVZYlN5T294ZGt5OEp0ek90ajJhS0FiZHd6NlArWDZDODhjZmxYVFo5MWpYL3RMCjF3TmRKS2tDZ1lCbyt0UzB5TzJ2SWFmK2UwSkN5TGhzVDQ5cTN3Zis2QWVqWGx2WDJ1VnRYejN5QTZnbXo5aCsKcDNlK2JMRUxwb3B0WFhNdUFRR0xhUkcrYlNNcjR5dERYbE5ZSndUeThXczNKY3dlSTdqZVp2b0ZpbmNvVlVIMwphdmxoTUVCRGYxSjltSDB5cDBwWUNaS2ROdHNvZEZtQktzVEtQMjJhTmtsVVhCS3gyZzR6cFE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=

    ## The secret with a TLS certificate and key for the default HTTPS server.
    ## The value must follow the following format: `<namespace>/<name>`.
    ## Used as an alternative to specifying a certificate and key using `controller.defaultTLS.cert` and `controller.defaultTLS.key` parameters.
    secret: #<namespace>/<secret_name>

  wildcardTLS:
    ## The base64-encoded TLS certificate for every Ingress host that has TLS enabled but no secret specified.
    ## If the parameter is not set, for such Ingress hosts NGINX will break any attempt to establish a TLS connection.
    cert: ""

    ## The base64-encoded TLS key for every Ingress host that has TLS enabled but no secret specified.
    ## If the parameter is not set, for such Ingress hosts NGINX will break any attempt to establish a TLS connection.
    key: ""

    ## The secret with a TLS certificate and key for every Ingress host that has TLS enabled but no secret specified.
    ## The value must follow the following format: `<namespace>/<name>`.
    ## Used as an alternative to specifying a certificate and key using `controller.wildcardTLS.cert` and `controller.wildcardTLS.key` parameters.
    secret: #<namespace>/<secret_name>

  ## The node selector for pod assignment for the Ingress controller pods.
  nodeSelector: {}

  ## The termination grace period of the Ingress controller pod.
  terminationGracePeriodSeconds: 30

  ## The resources of the Ingress controller pods.
  resources: {}
    # limits:
    #   cpu: 100m
    #   memory: 64Mi
    # requests:
  #   cpu: 100m
  #   memory: 64Mi

  ## The tolerations of the Ingress controller pods.
  tolerations: []

  ## The affinity of the Ingress controller pods.
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - company-internal-nginx-ingress
          topologyKey: "kubernetes.io/hostname"

  ## The volumes of the Ingress controller pods.
  volumes: []
  # - name: extra-conf
  #   configMap:
  #     name: extra-conf

  ## The volumeMounts of the Ingress controller pods.
  volumeMounts: []
  # - name: extra-conf
  #   mountPath: /etc/nginx/conf.d/extra.conf
  #   subPath: extra.conf

  ## The number of replicas of the Ingress controller deployment.
  replicaCount: 4

  ## A class of the Ingress controller.

  ## For Kubernetes >= 1.18, a corresponding IngressClass resource with the name equal to the class must be deployed. Otherwise,
  ## the Ingress Controller will fail to start.
  ## The Ingress controller only processes resources that belong to its class - i.e. have the "ingressClassName" field resource equal to the class.

  ## For Kubernetes < 1.18, the Ingress Controller only processes resources that belong to its class
  ## - i.e have the annotation "kubernetes.io/ingress.class" equal to the class.
  ## Additionally, the Ingress Controller processes resources that do not have the class set, which can be disabled by setting the "-use-ingress-class-only" flag

  ## The Ingress Controller processes all the VirtualServer/VirtualServerRoute resources that do not have the "ingressClassName" field for all versions of kubernetes.
  ingressClass: internal.company.com

  ## Ignore Ingress resources without the "kubernetes.io/ingress.class" annotation or the "ingressClassName" field in VirtualServer/VirtualServerRoute.
  useIngressClassOnly: false

  ## Only for Kubernetes >= 1.18
  ## New Ingresses without an ingressClassName field specified will be assigned the class specified in `controller.ingressClass`.
  setAsDefaultIngress: true

  ## Namespace to watch for Ingress resources. By default the Ingress controller watches all namespaces.
  watchNamespace: ""

  ## Enable the custom resources.
  enableCustomResources: true

  ## Enable TLS Passthrough on port 443. Requires controller.enableCustomResources.
  enableTLSPassthrough: false

  globalConfiguration:
    ## Creates the GlobalConfiguration custom resource. Requires controller.enableCustomResources.
    create: false

    ## The spec of the GlobalConfiguration for defining the global configuration parameters of the Ingress Controller.
    spec: {}
      # listeners:
      # - name: dns-udp
      #   port: 5353
      #   protocol: UDP
      # - name: dns-tcp
    #   port: 5353
    #   protocol: TCP

  ## Enable custom NGINX configuration snippets in VirtualServer and VirtualServerRoute resources.
  enableSnippets: false

  ## Add a location based on the value of health-status-uri to the default server. The location responds with the 200 status code for any request.
  ## Useful for external health-checking of the Ingress controller.
  healthStatus: false

  ## Sets the URI of health status location in the default server. Requires contoller.healthStatus.
  healthStatusURI: "/nginx-health"

  nginxStatus:
    ## Enable the NGINX stub_status, or the NGINX Plus API.
    enable: false

    ## Set the port where the NGINX stub_status or the NGINX Plus API is exposed.
    port: 8080

    ## Whitelist IPv4 IP/CIDR blocks to allow access to NGINX stub_status or the NGINX Plus API. Separate multiple IP/CIDR by commas.
    allowCidrs: "127.0.0.1"

  service:
    ## Creates a service to expose the Ingress controller pods.
    create: true

    ## The type of service to create for the Ingress controller.
    type: LoadBalancer

    ## The externalTrafficPolicy of the service. The value Local preserves the client source IP.
    externalTrafficPolicy: Local

    ## The annotations of the Ingress controller service.
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
      service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "https"
      service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
      service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
      service.beta.kubernetes.io/aws-load-balancer-internal: "true"
      service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
      service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "AWS_CERT"
      service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: "type=internal"
      external-dns.alpha.kubernetes.io/hostname: "www.company.com"

    ## The static IP address for the load balancer. Requires controller.service.type set to LoadBalancer. The cloud provider must support this feature.
    loadBalancerIP: ""

    ## The list of external IPs for the Ingress controller service.
    externalIPs: []

    ## The IP ranges (CIDR) that are allowed to access the load balancer. Requires controller.service.type set to LoadBalancer. The cloud provider must support this feature.
    loadBalancerSourceRanges: []

    ## The name of the service
    ## Autogenerated if not set or set to "".
    # name: nginx-ingress

    httpPort:
      ## Enables the HTTP port for the Ingress controller service.
      enable: true

      ## The HTTP port of the Ingress controller service.
      port: 80

      ## The custom NodePort for the HTTP port. Requires controller.service.type set to NodePort.
      nodePort: ""

      ## The HTTP port on the POD where the Ingress controller service is running.
      targetPort: 80

    httpsPort:
      ## Enables the HTTPS port for the Ingress controller service.
      enable: true

      ## The HTTPS port of the Ingress controller service.
      port: 443

      ## The custom NodePort for the HTTPS port. Requires controller.service.type set to NodePort.
      nodePort: ""

      ## The HTTPS port on the POD where the Ingress controller service is running.
      targetPort: 80

    ## A list of custom ports to expose through the Ingress controller service. Follows the conventional Kubernetes yaml syntax for service ports.
    customPorts: []

  serviceAccount:
    ## The name of the service account of the Ingress controller pods. Used for RBAC.
    ## Autogenerated if not set or set to "".
    # name: nginx-ingress

    ## The names of the secrets containing docker registry credentials.
    imagePullSecrets: []
    # - name: secret_name

  reportIngressStatus:
    ## Update the address field in the status of Ingresses resources with an external address of the Ingress controller.
    ## You must also specify the source of the external address either through an external service via controller.reportIngressStatus.externalService or the external-status-address entry in the ConfigMap via controller.config.entries.
    ## Note: controller.config.entries.external-status-address takes precedence if both are set.
    enable: true

    ## Specifies the name of the service with the type LoadBalancer through which the Ingress controller is exposed externally.
    ## The external address of the service is used when reporting the status of Ingress resources. controller.reportIngressStatus.enable must be set to true.
    ## The default is autogenerated and matches the created service (see controller.service.create).
    # externalService: nginx-ingress

    ## Enable Leader election to avoid multiple replicas of the controller reporting the status of Ingress resources. controller.reportIngressStatus.enable must be set to true.
    enableLeaderElection: true

    ## Specifies the name of the ConfigMap, within the same namespace as the controller, used as the lock for leader election. controller.reportIngressStatus.enableLeaderElection must be set to true.
    ## Autogenerated if not set or set to "".
    # leaderElectionLockName: "nginx-ingress-leader-election"

    ## The annotations of the leader election configmap.
    annotations: {}

  pod:
    ## The annotations of the Ingress Controller pod.
    annotations: {}

  ## The PriorityClass of the ingress controller pods.
  priorityClassName:

  readyStatus:
    ## Enables readiness endpoint "/nginx-ready". The endpoint returns a success code when NGINX has loaded all the config after startup.
    enable: false

    ## Set the port where the readiness endpoint is exposed.
    port: 8081

  ## Enable collection of latency metrics for upstreams. Requires prometheus.create.
  enableLatencyMetrics: false

rbac:
  ## Configures RBAC.
  create: true

prometheus:
  ## Expose NGINX or NGINX Plus metrics in the Prometheus format.
  create: true

  ## Configures the port to scrape the metrics.
  port: 9113

Example of one of my ingress

ingress:
  enabled: true
  # Values can be templated
  annotations:
    kubernetes.io/ingress.class: "internal.company.com"
    nginx.org/redirect-to-https: "True"
    external-dns.alpha.kubernetes.io/hostname: "grafana.company.com"
  labels: {}
  path: /
  hosts:
    - grafana.company.com
  ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services.
  extraPaths: []
  # - path: /*

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 15 (3 by maintainers)

Most upvoted comments

Success! The below worked on nginx/1.19.4:

  • On the configmap, set use-proxy-protocol: "true" (this has apparently changed recently and using proxy-protocol: "True" as recommended elsewhere just fails silently)
  • On AWS, go to NLB target groups, got to attributes, and check the box for Proxy Protocol V2.
  • For each ingress defintion add this attribute: nginx.ingress.kubernetes.io/force-ssl-redirect: "true" (previously setting this had caused an infinite redirect, but that was because the headers were missing because Proxy Protocol wasn’t configured properly)

The biggest thing that helped troubleshooting: kubectl exec --stdin --tty -n ingress-nginx ingress-nginx-controller-57fdfb77bf-8b2jb -- cat nginx.conf <- run before and after each kubectl apply of the configmap or update to an ingress. Diff the results. You may find that your changes had no impact at all…try something else.