<p>I have a k3s (light weighted k8s) cluster running on my Raspberry PI. So, I am not using any cloud hosted cluster but a bear metal one on my Raspberry PI.</p>
<p>I have deployed a application with this manifest:</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
  namespace: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
        - name: hello-world
          image: bashofmann/rancher-demo:1.0.0
          imagePullPolicy: Always
          resources:
            requests:
              cpu: 200m
          ports:
          - containerPort: 8080
            name: web
            protocol: TCP
</code></pre>
<p>I also created a service to forward traffic to the application pod. Its manifest is:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  name: demo-app-svc
  namespace: myapp
spec:
  selector:
    app: hello-world
  ports:
  - name: web
    protocol: TCP
    port: 31113
    targetPort: 8080
</code></pre>
<p>Then, I created a Ingress for the routing rules:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ing
  namespace: myapp
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx 
  rules:
  - host: myapp.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: demo-app-svc 
            port:
              number: 31113

</code></pre>
<p>I successfully deployed above application pod, service &amp; Ingress to my k3s cluster.  Like the manifests indicate, they are under namespace <code>myapp</code>.</p>
<p>The next thing I would like to do is to deploy the <strong>Kubernetes Nginx Ingress Controller</strong> in order to have the clients outside the cluster be able to access the deployed application.</p>
<p>So, I deployed it by :</p>
<pre><code>kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
</code></pre>
<p>The above command successfully deployed <strong>Ingress Controller</strong> under namespace <code>ingress-nginx</code> along with other objects as shown below with command <code>k get all -n ingress-nginx</code>:
<a href="https://i.stack.imgur.com/QZH7P.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QZH7P.png" alt="enter image description here" /></a></p>
<p>As you can see above, the <code>LoadBalancer</code> type <code>service</code> external IP is with value <code>&lt;pending&gt;</code>. So, client outside the cluster still can not access the application pod.</p>
<p>Why is that &amp; what do I miss deploying the Nginx Ingress Controller on a bear metal machine? The goal is to have an external IP that can be used to access the application pod from outside cluster, how can I achieve that?</p>
<p><strong>===== Update =====</strong></p>
<p>Based on the answer below from @Dawid Kruk , I decided to use the k3s default Traefik Ingress Controller.</p>
<p>So, I deleted all the deployed Nginx Ingress Controller resources by <code>k delete all --all -n ingress-nginx</code> .</p>
<p>Then, I checked the Traefik Ingress related <code>LoadBalancer</code> type service:
<a href="https://i.stack.imgur.com/gjrbN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gjrbN.png" alt="enter image description here" /></a></p>
<p>The <code>external IP</code> of that Traefik service is exactly my Raspberry PI's IP address!</p>
<p>So, added this IP to <code>/etc/hosts</code> to map it to the hostname defined in my Ingress object:</p>
<pre><code>192.168.10.203 myapp.com
</code></pre>
<p>I opened browser &amp; use address <a href="http://myapp.com" rel="nofollow noreferrer">http://myapp.com</a>, with the routing rules defined in my <code>Ingress</code> object (see the manifest for my ingress above), I hoped I could see my deployed web application now. But get <code>404 Page Not Found</code>.  What am I missing now to access my deployed application?</p>
<p><strong>Another side question:</strong> I noticed when I check the deployed <code>Ingress</code> object, its IP address is empty, I wonder am I supposed to see an IP address for this object or not when the Traefik Ingress Controller takes effect?
<a href="https://i.stack.imgur.com/3GDNq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3GDNq.png" alt="enter image description here" /></a></p>
<p><strong>Another issue:</strong> Now, when I re-deploy my ingress manifest by <code>k apply -f ingress.yaml</code>, I get error:</p>
<pre><code>Resource: &quot;networking.k8s.io/v1, Resource=ingresses&quot;, GroupVersionKind: &quot;networking.k8s.io/v1, Kind=Ingress&quot;
...
for: &quot;ingress.yaml&quot;: error when patching &quot;ingress.yaml&quot;: Internal error occurred: failed calling webhook &quot;validate.nginx.ingress.kubernetes.io&quot;: failed to call webhook: Post &quot;https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s&quot;: service &quot;ingress-nginx-controller-admission&quot; not found
</code></pre>
<p>It looks like even I decided to use Traefik Ingress Controller, I still need to instal Nginx Ingress Controller. I get confused now, anyone can explain it?</p>

<p>I'm not K3S expert but I think I found a piece of documentation that is addressing your issue.</p>
<p>Take a look:</p>
<blockquote>
<h3>Service Load Balancer</h3>
<p>Any service load balancer (LB) can be used in your K3s cluster. By default, K3s provides a load balancer known as <a href="https://github.com/k3s-io/klipper-lb" rel="nofollow noreferrer">ServiceLB</a> (formerly Klipper Load Balancer) that uses available host ports.</p>
<p>Upstream Kubernetes allows Services of type LoadBalancer to be created, but doesn't include a default load balancer implementation, so these services will remain <code>pending</code> until one is installed. Many hosted services require a cloud provider such as Amazon EC2 or Microsoft Azure to offer an external load balancer implementation. By contrast, the K3s ServiceLB makes it possible to use LoadBalancer Services without a cloud provider or any additional configuration.</p>
<h3>How the Service LB Works</h3>
<p>The ServiceLB controller watches Kubernetes <a href="https://kubernetes.io/docs/concepts/services-networking/service/" rel="nofollow noreferrer">Services</a> with the <code>spec.type</code> field set to <code>LoadBalancer</code>.</p>
<p>For each LoadBalancer Service, a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/" rel="nofollow noreferrer">DaemonSet</a> is created in the <code>kube-system</code> namespace. This DaemonSet in turn creates Pods with a <code>svc-</code> prefix, on each node. <strong>These Pods use iptables to forward traffic from the Pod's NodePort, to the Service's ClusterIP address and port.</strong></p>
<p>If the ServiceLB Pod runs on a node that has an external IP configured, the node's external IP is populated into the Service's <code>status.loadBalancer.ingress</code> address list. Otherwise, the node's internal IP is used.</p>
<p>If multiple LoadBalancer Services are created, a separate DaemonSet is created for each Service.</p>
<p>It is possible to expose multiple Services on the same node, as long as they use different ports.</p>
<p>If you try to create a LoadBalancer Service that listens on port 80, the ServiceLB will try to find a free host in the cluster for port 80. If no host with that port is available, the LB will remain Pending.</p>
<p>-- <em><a href="https://docs.k3s.io/networking#service-load-balancer" rel="nofollow noreferrer">Docs.k3s.io: Networking</a></em></p>
</blockquote>
<p>As a possible solution, I'd recommend to use <code>Traefik</code> as it's a default <code>Ingress</code> controller within <code>K3S</code>.</p>
<p>The <code>Pending</code> status on your <code>LoadBalancer</code> is most likely caused by another service used on that port (<code>Traefik</code>).</p>
<p>If you wish to still use <code>NGINX</code>, the same documentation page explains how you can disable <code>Traefik</code>.</p>
<hr />
<h3>UPDATE</h3>
<p>I'd be more careful to delete resources as you did. The following command:</p>
<ul>
<li><code>k delete all --all -n ingress-nginx</code></li>
</ul>
<p>Will not delete all of the resources created. The better way in my opinion would be to use the command that you've used to create and instead of:</p>
<ul>
<li><code>kubectl create -f ...</code></li>
</ul>
<p>Use:</p>
<ul>
<li><code>kubectl delete -f ...</code></li>
</ul>
<p>I assume that you did not modify your <code>Ingress</code> definition, hence you receive the error and the <code>kubectl get ingress</code> is showing incorrect results.</p>
<p>What you will need to do:</p>
<pre class="lang-yaml prettyprint-override"><code>spec:
  ingressClassName: nginx # &lt;-- DELETE IT OR CHANGE TO &quot;traefik&quot;
</code></pre>
<p>Either delete or change should work as <code>traefik</code> is set to be a default <code>IngressClass</code> for this setup.</p>
