serverless / serverless-kubeless

This plugin enables support for Kubeless within the Serverless Framework.
Apache License 2.0
303 stars 80 forks source link

examples/cert-manager-https is broken #166

Closed mpalumbo7 closed 5 years ago

mpalumbo7 commented 5 years ago

Summary

The tlsConfig and additionalAnnotations for Ingress objects is broken. Following the example cert-manager-https does not generate the spec.tls or metadata.annotations that is should:

$ kubectl get ingress cert-manager-https -o yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    undefined.ingress.kubernetes.io/rewrite-target: /
  name: cert-manager-https
  namespace: default
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: hello
          servicePort: 8080
        path: /hello
status:
  loadBalancer: {}

The annotation kubernetes.io/tls-acme: "true" is missing, the other annotation has undefined where it should be nginx, and there is no spec.tls at all.

Environment

Steps to Reproduce

Install kubeless via Release notes after applying the PodSecurityPolicy psp:privileged to the kubeless namespace:

kubectl create ns kubeless
kubectl create -f kubeless.psp-privileged.yaml
kubectl create -f https://github.com/kubeless/kubeless/releases/download/v1.0.1/kubeless-v1.0.1.yaml

Install serverless CLI locally:

npm install -g serverless

NOTE: I had to follow these instructions to work around the global install issue.

git clone https://github.com/serverless/serverless-kubeless.git
cd serverless-kubeless/examples/cert-manager-https
npm install

Now, after the install is successful, I can see the Ingress object was created, but it is missing the tlsConfig and additionalAnnotations which are defined in serverless.yaml.

$ serverless deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Deploying function hello...
Serverless: Pods status: {"waiting":{"reason":"PodInitializing"}}
Serverless: Function hello successfully deployed
Serverless: Deployed Ingress rule cert-manager-https

$ kubectl get ingress cert-manager-https -o yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    undefined.ingress.kubernetes.io/rewrite-target: /
  creationTimestamp: "2019-01-25T09:09:36Z"
  generation: 1
  name: cert-manager-https
  namespace: default
  resourceVersion: "24678002"
  selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/cert-manager-https
  uid: eff9f0d6-2080-11e9-b174-000d3a0ca0cb
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: hello
          servicePort: 8080
        path: /hello
status:
  loadBalancer: {}

The serverless.yaml:

provider:
  name: kubeless
  hostname: example.com
  runtime: nodejs8
  ingress:
    additionalAnnotations:
      kubernetes.io/tls-acme: "true"
    tlsConfig:
      - hosts:
          - "example.com"
        secretName: ingress-example-com-certs
mpalumbo7 commented 5 years ago

I found that the root cause is that the cert-manager-https example references serverless-kubeless version ^0.4.0 but per the release notes, the tlsConfig and additionaAnnotations were only added in v0.6.1.

I'll open a pull request for the fix.

christhomas commented 5 years ago

ok, I'm having this "undefined.ingress.kubernetes.io/rewrite-target" using serverless-kubeless 0.7.1.

Although I do see the tls annotation correctly applied. In my nodejs express app, I'm missing the pathinfo for the function, all it sees is "/" which means my app doesn't register the correct url even though with curl -v I can see the url is set correctly.

{
  "kind": "Ingress",
  "apiVersion": "extensions/v1beta1",
  "metadata": {
    "name": "country-service",
    "namespace": "__SNIP__",
    "selfLink": "/apis/extensions/v1beta1/namespaces/__SNIP__/ingresses/country-service",
    "uid": "85ec34cc-742a-11e9-b881-9600000d0565",
    "resourceVersion": "38842960",
    "generation": 2,
    "creationTimestamp": "2019-05-11T20:22:39Z",
    "annotations": {
      "kubernetes.io/tls-acme": "true",
      "undefined.ingress.kubernetes.io/rewrite-target": "/"
    }
  },
  "spec": {
    "tls": [
      {
        "hosts": [
          "__SNIP__"
        ],
        "secretName": "tls-__SNIP__"
      }
    ],
    "rules": [
      {
        "host": "__SNIP__",
        "http": {
          "paths": [
            {
              "path": "/country",
              "backend": {
                "serviceName": "country",
                "servicePort": 8080
              }
            }
          ]
        }
      }
    ]
  }, __SNIP__
}
andresmgot commented 5 years ago

Taking a quick look to the code, you need to set a class for your ingress definition. So if you are using a Nginx Ingress controller that will be nginx.

Apart from that, if the controller is behaving as expected, you should be able to reach your function using hostname/country. If that's not the case, the logs of the controller may give you more information about the cause of the error.

mpalumbo7 commented 5 years ago

Can you provide the serverless.yaml you used to generate the ingress? It must include the following field: provider.ingress.class

Here is an example:

# Update the service name below with your own service name
service: hello-world

provider:
  name: kubeless # where to deploy the function
  runtime: nodejs8 # the runtime to use
  namespace: kubeless # the k8s namespace to use

  # configuration for the Ingress object
  hostname: fn.example.com
  ingress:
    class: nginx # type of ingress-controller used
    additionalAnnotations:
      # auto generation of TLS certificates via cert-manager
      certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    tlsConfig:
      - hosts:
          - fn.example.com
        secretName: fn.example.com-cert

plugins:
  - serverless-kubeless # required

functions:
  hello: # the name of the function
    handler: handler.hello # the filename and exported function name
    events: # create an http trigger
      - http:
          method: GET # http trigger method
          path: hello # path rule created in Ingress object
  # another function
  capitalize:
    handler: handler.capitalize
    events:
      - http:
          path: captilize