serverless / serverless-kubeless

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

Q: Serverless HTTP Trigger - serverless info crashes #141

Open nea opened 6 years ago

nea commented 6 years ago

Hi

I created a trigger as explained via serverless.yml. A simple http trigger:

  weather:
    handler: handler.weather
    events:
      - http:
          path: /weather

When I call kubectl get ing I see it being created. Now, I wanted to call serverless info as mentioned here: https://serverless.com/framework/docs/providers/kubeless/guide/functions/#custom-hostname-and-path

The following error is displayed:

const path = _.find(rule.http.paths, p => p.backend.serviceName === f).path;
                                         ^
TypeError: Cannot read property 'http' of undefined

It is triggered by node_modules\serverless-kubeless\lib\get-info.js:119:42

Am I missing something? Any help is much appreciated.

Thanks a lot in advance

andresmgot commented 6 years ago

Hi,

It seems that the ingress object is somehow malformed. What is the output of kubectl get <ingres_name> -o yaml?

In any case that should not crash, it should just skip that info. I will send a PR to patch that.

nea commented 6 years ago

Hi @andresmgot

Is this helpful?

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
  creationTimestamp: 2018-07-30T14:21:48Z
  generation: 4
  name: exampleName
  namespace: default
  resourceVersion: "40881"
  selfLink: /apis/extensions/v1beta1/namespaces/default/ingresses/gs999
  uid: e4f48827-9403-11e8-b0f4-00155d8675ae
spec:
  rules:
  - host: localhost.xip.io
    http:
      paths:
      - backend:
          serviceName: weather
          servicePort: 8080
        path: /weather
status:
  loadBalancer:
    ingress:
    - hostname: localhost

Thanks

andresmgot commented 6 years ago

mm, that's weird. That ingress rule is properly formed. To debug the issue: Can you open the file that is crashing (node_modules\serverless-kubeless\lib\get-info.js) and in the line 118 (the line before the crash) add the following? (and put here the output of the command).

console.log(fIngress);
console.log(rule);

Somehow it's not parsing the ingress rule properly but there is not any obvious cause.

nea commented 6 years ago

Hey

Sure thing:

{
    kind: 'Ingress',
    apiVersion: 'extensions/v1beta1',
    metadata: {
        name: 'exampleName',
        namespace: 'default',
        selfLink: '/apis/extensions/v1beta1/namespaces/default/ingresses/gs999',
        uid: 'e4f48827-9403-11e8-b0f4-00155d8675ae',
        resourceVersion: '40881',
        generation: 4,
        creationTimestamp: '2018-07-30T14: 21: 48Z',
        annotations: {
            'kubernetes.io/ingress.class': 'nginx',
            'nginx.ingress.kubernetes.io/rewrite-target': '/'
        }
    },
    spec: {
        rules: [[Object]]
    },
    status: {
        loadBalancer: {
            ingress: [Array]
        }
    }
}{
    host: 'localhost.xip.io',
    http: {
        paths: [[Object]]
    }
}{
    kind: 'Ingress',
    apiVersion: 'extensions/v1beta1',
    metadata: {
        name: 'exampleName',
        namespace: 'default',
        selfLink: '/apis/extensions/v1beta1/namespaces/default/ingresses/gs999',
        uid: 'e4f48827-9403-11e8-b0f4-00155d8675ae',
        resourceVersion: '40881',
        generation: 4,
        creationTimestamp: '2018-07-30T14: 21: 48Z',
        annotations: {
            'kubernetes.io/ingress.class': 'nginx',
            'nginx.ingress.kubernetes.io/rewrite-target': '/'
        }
    },
    spec: {
        rules: [[Object]]
    },
    status: {
        loadBalancer: {
            ingress: [Array]
        }
    }
}

rule is empty.

Cheers

andresmgot commented 6 years ago

that's a weird output, are there two different ingress objects? One gs999 and a different one exampleName? That could be causing the issue. Can you try to delete the function, make sure that there are no ingress objects and then redeploy the function?

nea commented 6 years ago

Hi @andresmgot

They are both called gs999. I just wanted to replace them with exampleName to make clear its a local example project. Nothing of that sort. Its just the one.

Sorry

andresmgot commented 6 years ago

So that's probably the problem. Only one ingress rule should be generated. Does it work if you clean up the resources?

nea commented 6 years ago

Hi @andresmgot

You were right, it does not crash anymore if I clean up everything.

But what can I derive from that information to e.g. call a local ingress rule? I got

Service Information "feeder"
Cluster IP:  10.110.175.130
Type:  ClusterIP
Ports:
  Name:  http-function-port
  Protocol:  TCP
  Port:  8080
  Target Port:  8080
Function Info
URL:  localhost.xip.io/feed

How would I test this now?

I have nginx-ingress running at:

NAME                           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/default-http-backend   ClusterIP      10.100.34.150   <none>        80/TCP                       10d
service/ingress-nginx          LoadBalancer   10.110.200.29   localhost     80:31289/TCP,443:31397/TCP   10d

I tried localhost, localhost.xip.io, 10.110.175.130, 10.110.200.29, with ports and without, nothing was able to read it.

And here is the ingress output again:

apiVersion: v1
items:
- apiVersion: extensions/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
      nginx.ingress.kubernetes.io/rewrite-target: /
    creationTimestamp: 2018-08-09T13:40:29Z
    generation: 1
    name: conduit
    namespace: conduit
    resourceVersion: "522830"
    selfLink: /apis/extensions/v1beta1/namespaces/conduit/ingresses/conduit
    uid: c79c627c-9bd9-11e8-af33-00155d8675c0
  spec:
    rules:
    - host: localhost.xip.io
      http:
        paths:
        - backend:
            serviceName: feeder
            servicePort: 8080
          path: /feed
  status:
    loadBalancer:
      ingress:
      - hostname: localhost
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

And this is the output if I describe the service:

Name:              feeder
Namespace:         conduit
Labels:            created-by=kubeless
                   function=feeder
Annotations:       <none>
Selector:          function=feeder
Type:              ClusterIP
IP:                10.110.175.130
Port:              http-function-port  8080/TCP
TargetPort:        8080/TCP
Endpoints:         10.1.2.103:8080
Session Affinity:  None
Events:            <none>

Thanks a lot in advance

nea commented 6 years ago

I removed the namespace now, to head into defaultbut still the same effect . . .

Damn, missing something important here . . . blindness surrounds me ^^'

andresmgot commented 6 years ago

@nea the xip.io service allows you to use an IP as a domain so what it does is routing 1.1.1.1.xip.io to the IP 1.1.1.1. You will not reach localhost setting the domain to localhost.xip.io. Anyway, if your ingress controller is reachable using localhost you should be able to call your function executing:

curl -H "Host: localhost.xip.io" localhost:31289/feed

As a general rule you should use as Host header the configured host and the IP and port of the Nginx that is running the Ingress.

nea commented 6 years ago

Hey @andresmgot

Thanks for that.

This has rather little todo with serverless but I am definitely missing something when it comes to the nginx-ingress controller. I just followed the instructions at https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md to install it as load balancer as posted above but it does not seem to be reachable by any means locally. No localhost, no local IP, no nothing. I described the service

Name:                     ingress-nginx
Namespace:                ingress-nginx
Labels:                   app=ingress-nginx
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"ingress-nginx"},"name":"ingress-nginx","namespace":"ingress-nginx"},"...
Selector:                 app=ingress-nginx
Type:                     LoadBalancer
IP:                       10.110.200.29
LoadBalancer Ingress:     localhost
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  31289/TCP
Endpoints:                10.1.2.109:80
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  31397/TCP
Endpoints:                10.1.2.109:443
Session Affinity:         None
External Traffic Policy:  Local
HealthCheck NodePort:     32019
Events:                   <none>

Everything looks correct but no matter what Could not get any response.

Do you have any idea? Or know something you can point me to to read up on? I just installed everything based on the documentation and deployed a simple http-trigger but am not able to ping it no matter what. All curls, Postman requests etc. just cannot connect.

Thanks a lot and sorry about the many questions ^^

andresmgot commented 6 years ago

Where are you running Kubernetes? It seems that doesn't have a proper LoadBalancer setup. That is only available for cloud providers like AWS or GKE. Is your cluster a local one run with Minikube or Docker for Mac? If that's the case you need to follow the specific steps that you can find in the URL you mention (and use probably a NodePort instead)

nea commented 6 years ago

Hi

I have a local Kubernetes with Docker for Win.

laurencechan commented 6 years ago

Hi~ @andresmgot I tried the serverless-kubeless doc but there is no "Node port " in the serverless info as the doc showed. what's wrong with it ?

[root@localhost get-python]# serverless info

Service Information "hello"
Cluster IP:  10.104.127.134
Type:  ClusterIP
Ports:
  Name:  http-function-port
  Protocol:  TCP
  Port:  8080
  Target Port:  8080
Function Info
Description: Hello function
Labels:
  created-by: kubeless
  function: hello
Handler:  handler.hello
Runtime:  python2.7
Dependencies:

[root@localhost get-python]# pwd
/root/serverless-kubeless/examples/get-python
andresmgot commented 6 years ago

Hi @laurencechan, that's indeed the default behavior. By default it will use a ClusterIP as your info show. I will update the docs to reflect that.