How to send a GET/POST request from Lambda to a pod with ClusterIP service

5/8/2019

I'm trying to send a GET request from Lambda to a pod without exposing it externally. That pod got a ClusterIP service attached to it. I can access this pod directly via internet (via ingress) so I know it works properly.

Here is the part of the service attached to a pod:

spec:
  clusterIP: 10.xxx.xxx.xx
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: app_name
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}

I attached lambda to the vpc and subnets but if I use below code I get an error. I tried using pod IP address and cluster IP address but with the same error. It works for google/other sites and when the pod is exposed to the internet.

    const http = require('http');
    exports.handler = async (event, context) => {
    return new Promise((resolve, reject) => {
        const options = {
            host: 'www.google.com',
            path: '/api/',
            port: 80,
            method: 'GET'
        };
        const req = http.request(options, (res) => {
          let data = '';

          // A chunk of data has been recieved.
          res.on('data', (chunk) => {
            data += chunk;
          });

          // The whole response has been received. Print out the result.
          res.on('end', () => {
            console.log(JSON.parse(data));
            });

        });
        req.write('');
        req.end();
    });
};

Response:

{
  "errorMessage": "Task timed out after 3.00 seconds"
}

I understand all below and I'm happy to change the service type but I don't know how do I supposed to address the pod in my Lambda (replace www.google.com with something). Happy to try any other code or python script.

A ClusterIP service is the default Kubernetes service. It gives you a service inside your cluster that other apps inside your cluster can access. There is no external access.

A NodePort service is the most primitive way to get external traffic directly to your service. NodePort, as the name implies, opens a specific port on all the Nodes (the VMs), and any traffic that is sent to this port is forwarded to the service.

A LoadBalancer service is the standard way to expose a service to the internet. On GKE, this will spin up a Network Load Balancer that will give you a single IP address that will forward all traffic to your service.

Anyone tried something like that?

-- tr53
amazon-web-services
kubernetes
lambda

1 Answer

5/8/2019

One of the easiest way is to expose service behind internal Load Balancer. In this way your service will not be exposed to Internet but will still be available within VPC.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-internal: 0.0.0.0/0
spec:
  type: LoadBalancer
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

A little bit more advanced but more flexible solution is to use Nginx Ingress with the same internal Load Balancer.

-- Vasily Angapov
Source: StackOverflow