kubernetesnginxnginx-ingressmicrok8s

How to apply nginx ingress in kubernetes with different namespaces?


I am new to k8s and nginx. I am currently implementing an nginx ingress on my microk8s kubernetes via yaml since it's an nginx plus. Here is the result:

myubuntu$ kubectl get all -n nginx-ingress
NAME                                READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-8dd4c95f5-b5qzs   1/1     Running   0          3d23h
pod/nginx-ingress-8dd4c95f5-vbvc6   1/1     Running   0          3d23h

NAME                    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/nginx-ingress   NodePort   10.152.183.119   <none>        80:31656/TCP,443:30406/TCP   4d3h

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress   2/2     2            2           4d3h

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-8dd4c95f5   2         2         2       3d23h
replicaset.apps/nginx-ingress-c4d985f57   0         0         0       4d3h

I have also deploy a testing app with the following yaml values:

apiVersion: v1
kind: Namespace
metadata:
  name: web
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
  namespace: web
  labels:
    app: web
  annotations:
    deployment.kubernetes.io/revision: '1'
    sensor.crowdstrike.com/imageanalyzer: "enable"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: test
        image: my docker image
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-server-service
  namespace: web
spec:
  selector:
    app: web
  type: ClusterIP
  ports:
    - port: 3000
      targetPort: http
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-server-ingress
  namespace: web
  annotations:
      kubernetes.io/ingress.class: nginx-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-server-service
            port:
              number: 3000

I have check and confirm that both services work good independently, but when I tried to configure the port in the web ingress file, the nginx plus ingress always return 404? Is it a problem with my config file or namespace? Thanks in advance.

Deploy an app on microk8s with custom nginx plus ingress.


Solution

  • You can set up your services on another namespace and have your ingress controllers in another namespace.

    For nginx, most times, when there is a 404 error, the hostname is either invalid or not correctly represented. Or the path is wrong.

    I set up a local nginx ingress and applied your configuration using nginx pod and 80 as my container port. I changed the hostname of the web-server-ingress to localhost. below is a sample of what I ran:

    # install nginx
    kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.1/deploy/static/provider/cloud/deploy.yaml
    
    # setup the application
    k apply -f <<EOF
    apiVersion: v1
    kind: Namespace
    metadata:
      name: web
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-server
      namespace: web
      labels:
        app: web
      annotations:
        deployment.kubernetes.io/revision: '1'
        sensor.crowdstrike.com/imageanalyzer: "enable"
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - name: test
            image: nginx:alpine
            imagePullPolicy: IfNotPresent
            ports:
            - name: http
              containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: web-server-service
      namespace: web
    spec:
      selector:
        app: web
      type: ClusterIP
      ports:
        - port: 80
          targetPort: http
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: web-server-ingress
      namespace: web
    spec:
      ingressClassName: nginx
      rules:
      - host: localhost
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-server-service
                port:
                  number: 80
    EOF
    
    # expose the ingress controller
    kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 8000:80
    
    # access the application
    curl -X GET http://localhost:8000/
    

    In your case, I would advise you to grab the name of the ingress-controller pod:

    enter image description here

    The name for me is ingress-nginx-controller-77cfd766fc-2h4k8

    Then try to view the logs: enter image description here

    You will notice no request log if the hostname does not match.

    If there are logs, you will get information about the request made to the upstream service:

    Below is a sample 200 response:

    127.0.0.1 - - [05/Aug/2024:11:10:01 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" 1758 0.004 [web-web-server-service-80] [] 172.17.0.4:80 615 0.003 200 f12389c9f84a7855e38758a2004a021e
    

    Notice the part after [web-web-server-service-80] records the pod that was reached and the port, the request length, time and response, and an ID for the request.

    Here is a log for a 503 response:

    127.0.0.1 - - [05/Aug/2024:11:08:12 +0000] "GET / HTTP/1.1" 503 592 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" 1758 0.000 [web-web-server-service-80] [] - - - - c1e3a81377b6483e8e2fb8293ff181a7
    

    Notice there is no log for the upstream service request/response

    When the hostname does not match, the controller records no log and returns a 404 to the client.