How do I expose my Web API to the public net?

Hello Folks,

I am trying to host a WebApi on K8s using deployments and service. I want my API to be publicly accessible from the public net using the Public IP of the node. I have this cluster on a Cloud provider’s VM. Like bare metal but on cloud VMs. I have used Kubeadm to bootstrap this cluster.

I am able to access the API from inside the vnet (virtual network) using node port type. My API listens on 80.

Here are the YAML snippets:

Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <api>-deployment
  labels:
    app: <api>
spec:
  replicas: 1
  selector:
    matchLabels:
      app: <api>
  template:
    metadata:
      labels:
        app: <api>
    spec:
      containers:
      - name: <api>
        image: <api_image>
        ports:
        - containerPort: 80

Service:

apiVersion: v1
kind: Service
metadata:
  name: <api>
  labels:
    app: <api>
spec:
  type: NodePort
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30000
  selector:
    app: <api>

The issue is that I can only access my API from my local vnet i.e. using the private IP address from other VMs inside the vnet. (I have already whitelisted port 30000 from my network security group so that it allows)

I hosted the same solution on IIS and opened up ports in my VM, configured security group rules on my cloud provider and and then pinged the public IP (public IP mentioned on the cloud provider’s portal) of that VM and it worked without a problem. I am trying to do the same here.

Should I be using NodePort ? Is there any other way that is quick and simple ? I just want my API to publicly accessible from public net i.e. accessible with one singular IP address (logically the node’s public IP address that is displayed on my cloud provider’s portal of the VM).

I know Ingres exists but how does this solve my problem here ? My API is already accessible, just not outside the vnet. What exactly is going wrong here ?

(Even though I want expose the API to public, it’ll mainly be used by other systems not humans)
(Also I wasn’t able to figure out weave net’s version so sorry about that)
(I am new to k8s)

Thanks

Cluster information:

Kubernetes version: v1.26.1
Cloud being used: bare-metal (VMs on cloud)
Installation method: Kubeadm
Host OS: CentOS 7
CNI and version: weave-net
CRI and version: containerd://1.6.16

Simple, your cluster was build with the private IP of the nodes (the right way), check with kubectl get nodes -o wide. So, when you use NodePort you are exposing the specified port in all of your nodes with the nodes IP (private IPs). If you want to expose your service to internet in a cloud provider use a service type LoadBalancer (at the end this service type will create a NodePort service for the LB service and will attach this info as backend of the created LB.). Or you can try using externalIP, but Im pretty sure that will not work, check this.