Dogacel
Dogacel

Reputation: 123

GCP Can I Expose Kubernetes Cluster ExternalIP without LoadBalancer?

I would like to maintain a very low-cost Kubernetes cluster on GCP. I am using a single node pool of e1-small instances. The monthly cost of this instance is $4.91 which is fine. But the problem is the ingress I am using to expose my node ports to an external-IP. The ingress instance uses a Google load balancer which costs around $18. Therefore, I am mostly paying to a useless load balancer which I really don't need. Is there a way that I can expose the IP addresses of those instances without the load balancer?

Upvotes: 1

Views: 933

Answers (2)

Bicameral Mind
Bicameral Mind

Reputation: 789

Add the ingress-nginx repository

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Use Helm to deploy an NGINX ingress controller

helm install $NGINX ingress-nginx/ingress-nginx \
    --namespace $NAMESPACE \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set controller.admissionWebhooks.patch.nodeSelector."beta\.kubernetes\.io/os"=linux

That's your load balancer.

Now get yourself a certificate manager...

Label the namespace to disable resource validation

kubectl label -n $NAMESPACE cert-manager.io/disable-validation=true

Add the Jetstack Helm repository

helm repo add jetstack https://charts.jetstack.io

Install the cert-manager Helm chart

helm install cert-manager jetstack/cert-manager \
  --namespace $NAMESPACE \
  --set installCRDs=true \
  --set nodeSelector."kubernetes\.io/os"=linux \
  --set webhook.nodeSelector."kubernetes\.io/os"=linux \
  --set cainjector.nodeSelector."kubernetes\.io/os"=linux

Next you'll need to add a CA Cluster Issuer...

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: $EMAIL_ADDRESS
    privateKeySecretRef:
      name: letsencrypt
    solvers:
    - http01:
      ingress:
        class: nginx
          podTemplate:
            spec:
              nodeSelector:
                "kubernetes.io/os": linux

Apply CA Cluster Issuer

kubectl apply -f cluster-issuer.yaml

You'll also need an ingress and service yaml.

Ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: $INGRESS_NAME
  namespace: $NAMESPACE
  labels:
    app.kubernetes.io/part-of: $NAMESPACE
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/use-regex: "true"
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
    - hosts:
      - $YOUR_DOMAIN
      secretName: tls-secret
  rules:
  - host: $YOUR_DOMAIN
    http:
      paths:
      - backend:
          serviceName: $SERVICE_NAME
          servicePort: $SERVICE_PORT

Service

apiVersion: v1
kind: Service
metadata:
  name: $SERVICE_NAME
  namespace: $NAMESPACE
  labels:
    app.kubernetes.io/part-of: $NAMESPACE
    app.kubernetes.io/type: service
spec:
  type: ClusterIP
  ports:
  - name: fart
    port: $SERVICE_PORT
    targetPort: $SERVICE_PORT
  selector:
    app.kubernetes.io/name: $DEPLOYMENT_NAME
    app.kubernetes.io/part-of: $NAMESPACE

It shouldn't cost anything more to deploy these resources.

If you're so concerned about costs you can deploy a fully functioning and publicly reachable cluster locally with minikube or micro-k8s.

Upvotes: 0

guillaume blaquiere
guillaume blaquiere

Reputation: 75715

If you expose the nodePort externally, you will expose a port number 10k+. So not a port 80 or 443 for a website. You need to proxy the connection, with a loadbalancer by example.

A solution is to use Cloud Run as reverse proxy with NGINX for example. In this case, you can also use serverless VPC Connector and reach the service through the private IP in your VPC.

Upvotes: 2

Related Questions