Helm chart getting 404 on kubernetes - namespace issue perhaps?

Hi all I just created a fresh kubernetes cluster and created a namespace called 'routing'

In here I created the latest traefik via the helm chart (2.2)

helm upgrade --install traefik traefik/traefik --version 9.1.0 --namespace routing -f values.yml

I can see the pod running fine.

No logs from the traefik pod. but I also enabled the access logs so the only log I get is when I try to access external-ip/dashboard

external-ip - - [30/Aug/2020:15:25:44 +0000] "GET /dashboard/ HTTP/1.1" 404 19 "-" "-" 75 "-" "-" 0ms

When I run:

kubectl get svc --namespace routing

It shows the

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    
    traefik LoadBalancer cluster-ip-is-here external-ip-is-here 80:32252/TCP,443:30252/TCP 33m

I tried on my browser going to https:external-ip-is-here but it just shows 404

I tried with just http also.

When I run kubectl get pods -A I see cilium and coredns running (default with digitial oceans kubernetes cluster)

Here is when I do kubectl get service -A

 NAMESPACE     NAME         TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)                      AGE
    default       kubernetes   ClusterIP      10.245.0.1      <none>            443/TCP                      7d
    kube-system   kube-dns     ClusterIP      10.245.0.10     <none>            53/UDP,53/TCP,9153/TCP       7d
    routing       traefik      LoadBalancer   10.245.69.214   external-ip   80:32252/TCP,443:30252/TCP   2d

Here is the file and command I am using for the dashboard:

`kubectl apply -f dashboard.yml --namespace routing`

and file:


    # dashboard.yml
    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRoute
    metadata:
      name: dashboard
    spec:
      entryPoints:
        - web
      routes:
        - match: Host(`traefik.localhost`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
          kind: Rule
          services:
            - name: api@internal
              kind: TraefikService

Here is the values file used:


    # Default values for Traefik
    image:
      name: traefik
      tag: 2.2.8
      pullPolicy: IfNotPresent
    
    #
    # Configure the deployment
    #
    deployment:
      enabled: true
      # Number of pods of the deployment
      replicas: 1
      # Additional deployment annotations (e.g. for jaeger-operator sidecar injection)
      annotations: {}
      # Additional pod annotations (e.g. for mesh injection or prometheus scraping)
      podAnnotations: {}
      # Additional containers (e.g. for metric offloading sidecars)
      additionalContainers: []
      # Additional initContainers (e.g. for setting file permission as shown below)
      initContainers: []
        # The "volume-permissions" init container is required if you run into permission issues.
        # Related issue: https://github.com/containous/traefik/issues/6972
        # - name: volume-permissions
        #   image: busybox:1.31.1
        #   command: ["sh", "-c", "chmod -Rv 600 /data/*"]
        #   volumeMounts:
        #     - name: data
        #       mountPath: /data
      # Custom pod DNS policy. Apply if `hostNetwork: true`
      # dnsPolicy: ClusterFirstWithHostNet
    
    # Pod disruption budget
    podDisruptionBudget:
      enabled: false
      # maxUnavailable: 1
      # minAvailable: 0
    
    # Create an IngressRoute for the dashboard
    ingressRoute:
      dashboard:
        enabled: true
        # Additional ingressRoute annotations (e.g. for kubernetes.io/ingress.class)
        annotations: {}
        # Additional ingressRoute labels (e.g. for filtering IngressRoute by custom labels)
        labels: {}
    
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
    
    
    #
    # Configure providers
    #
    providers:
      kubernetesCRD:
        enabled: true
      kubernetesIngress:
        enabled: true
        # IP used for Kubernetes Ingress endpoints
        publishedService:
          enabled: false
          # Published Kubernetes Service to copy status from. Format: namespace/servicename
          # By default this Traefik service
          # pathOverride: ""
    
    #
    # Add volumes to the traefik pod.
    # This can be used to mount a cert pair or a configmap that holds a config.toml file.
    # After the volume has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg:
    # additionalArguments:
    # - "--providers.file.filename=/config/dynamic.toml"
    volumes: []
    # - name: public-cert
    #   mountPath: "/certs"
    #   type: secret
    # - name: configs
    #   mountPath: "/config"
    #   type: configMap
    
    # Logs
    # https://docs.traefik.io/observability/logs/
    logs:
      # Traefik logs concern everything that happens to Traefik itself (startup, configuration, events, shutdown, and so on).
      general:
        # By default, the logs use a text format (common), but you can
        # also ask for the json format in the format option
        # format: json
        # By default, the level is set to ERROR. Alternative logging levels are DEBUG, PANIC, FATAL, ERROR, WARN, and INFO.
        level: ERROR
      access:
        # To enable access logs
        enabled: false
        # By default, logs are written using the Common Log Format (CLF).
        # To write logs in JSON, use json in the format option.
        # If the given format is unsupported, the default (CLF) is used instead.
        # format: json
        # To write the logs in an asynchronous fashion, specify a bufferingSize option.
        # This option represents the number of log lines Traefik will keep in memory before writing
        # them to the selected output. In some cases, this option can greatly help performances.
        # bufferingSize: 100
        # Filtering https://docs.traefik.io/observability/access-logs/#filtering
        filters: {}
          # statuscodes: "200,300-302"
          # retryattempts: true
          # minduration: 10ms
        # Fields
        # https://docs.traefik.io/observability/access-logs/#limiting-the-fieldsincluding-headers
        fields:
          general:
            defaultmode: keep
            names: {}
              # Examples:
              # ClientUsername: drop
          headers:
            defaultmode: drop
            names: {}
              # Examples:
              # User-Agent: redact
              # Authorization: drop
              # Content-Type: keep
    
    globalArguments:
      - "--global.checknewversion"
      - "--global.sendanonymoususage"
    
    #
    # Configure Traefik static configuration
    # Additional arguments to be passed at Traefik's binary
    # All available options available on https://docs.traefik.io/reference/static-configuration/cli/
    ## Use curly braces to pass values: `helm install --set="additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}"`
    additionalArguments: []
    #  - "--providers.kubernetesingress.ingressclass=traefik-internal"
    #  - "--log.level=DEBUG"
    
    # Environment variables to be passed to Traefik's binary
    env: []
    # - name: SOME_VAR
    #   value: some-var-value
    # - name: SOME_VAR_FROM_CONFIG_MAP
    #   valueFrom:
    #     configMapRef:
    #       name: configmap-name
    #       key: config-key
    # - name: SOME_SECRET
    #   valueFrom:
    #     secretKeyRef:
    #       name: secret-name
    #       key: secret-key
    
    envFrom: []
    # - configMapRef:
    #     name: config-map-name
    # - secretRef:
    #     name: secret-name
    
    # Configure ports
    ports:
      # The name of this one can't be changed as it is used for the readiness and
      # liveness probes, but you can adjust its config to your liking
      traefik:
        port: 9000
        # Use hostPort if set.
        # hostPort: 9000
        #
        # Use hostIP if set. If not set, Kubernetes will default to 0.0.0.0, which
        # means it's listening on all your interfaces and all your IPs. You may want
        # to set this value if you need traefik to listen on specific interface
        # only.
        # hostIP: 192.168.100.10
    
        # Defines whether the port is exposed if service.type is LoadBalancer or
        # NodePort.
        #
        # You SHOULD NOT expose the traefik port on production deployments.
        # If you want to access it from outside of your cluster,
        # use `kubectl proxy` or create a secure ingress
        expose: false
        # The exposed port for this service
        exposedPort: 9000
        # The port protocol (TCP/UDP)
        protocol: TCP
      web:
        port: 8000
        # hostPort: 8000
        expose: true
        exposedPort: 80
        # The port protocol (TCP/UDP)
        protocol: TCP
        # Use nodeport if set. This is useful if you have configured Traefik in a
        # LoadBalancer
        # nodePort: 32080
        # Port Redirections
        # Added in 2.2, you can make permanent redirects via entrypoints.
        # https://docs.traefik.io/routing/entrypoints/#redirection
        # redirectTo: websecure
      websecure:
        port: 8443
        # hostPort: 8443
        expose: true
        exposedPort: 443
        # The port protocol (TCP/UDP)
        protocol: TCP
        # nodePort: 32443
    
    # Options for the main traefik service, where the entrypoints traffic comes
    # from.
    service:
      enabled: true
      type: LoadBalancer
      # Additional annotations (e.g. for cloud provider specific config)
      annotations: {}
      # Additional entries here will be added to the service spec. Cannot contains
      # type, selector or ports entries.
      spec: {}
        # externalTrafficPolicy: Cluster
        # loadBalancerIP: "1.2.3.4"
        # clusterIP: "2.3.4.5"
      loadBalancerSourceRanges: []
        # - 192.168.0.1/32
        # - 172.16.0.0/16
      externalIPs: []
        # - 1.2.3.4
    
    ## Create HorizontalPodAutoscaler object.
    ##
    autoscaling:
      enabled: false
    #   minReplicas: 1
    #   maxReplicas: 10
    #   metrics:
    #   - type: Resource
    #     resource:
    #       name: cpu
    #       targetAverageUtilization: 60
    #   - type: Resource
    #     resource:
    #       name: memory
    #       targetAverageUtilization: 60
    
    # Enable persistence using Persistent Volume Claims
    # ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
    # After the pvc has been mounted, add the configs into traefik by using the `additionalArguments` list below, eg:
    # additionalArguments:
    # - "--certificatesresolvers.le.acme.storage=/data/acme.json"
    # It will persist TLS certificates.
    persistence:
      enabled: false
    #  existingClaim: ""
      accessMode: ReadWriteOnce
      size: 128Mi
      # storageClass: ""
      path: /data
      annotations: {}
      # subPath: "" # only mount a subpath of the Volume into the pod
    
    # If hostNetwork is true, runs traefik in the host network namespace
    # To prevent unschedulabel pods due to port collisions, if hostNetwork=true
    # and replicas>1, a pod anti-affinity is recommended and will be set if the
    # affinity is left as default.
    hostNetwork: false
    
    # Whether Role Based Access Control objects like roles and rolebindings should be created
    rbac:
      enabled: true
    
      # If set to false, installs ClusterRole and ClusterRoleBinding so Traefik can be used across namespaces.
      # If set to true, installs namespace-specific Role and RoleBinding and requires provider configuration be set to that same namespace
      namespaced: false
    
    # The service account the pods will use to interact with the Kubernetes API
    serviceAccount:
      # If set, an existing service account is used
      # If not set, a service account is created automatically using the fullname template
      name: ""
    
    # Additional serviceAccount annotations (e.g. for oidc authentication)
    serviceAccountAnnotations: {}
    
    resources: {}
      # requests:
      #   cpu: "100m"
      #   memory: "50Mi"
      # limits:
      #   cpu: "300m"
      #   memory: "150Mi"
    affinity: {}
    # # This example pod anti-affinity forces the scheduler to put traefik pods
    # # on nodes where no other traefik pods are scheduled.
    # # It should be used when hostNetwork: true to prevent port conflicts
    #   podAntiAffinity:
    #     requiredDuringSchedulingIgnoredDuringExecution:
    #     - labelSelector:
    #         matchExpressions:
    #         - key: app
    #           operator: In
    #           values:
    #           - {{ template "traefik.name" . }}
    #       topologyKey: failure-domain.beta.kubernetes.io/zone
    nodeSelector: {}
    tolerations: []
    
    # Pods can have priority.
    # Priority indicates the importance of a Pod relative to other Pods.
    priorityClassName: ""
    
    # Set the container security context
    # To run the container with ports below 1024 this will need to be adjust to run as root
    securityContext:
      capabilities:
        drop: [ALL]
      readOnlyRootFilesystem: true
      runAsGroup: 65532
      runAsNonRoot: true
      runAsUser: 65532
    
    podSecurityContext:
      fsGroup: 65532

If I run:

kubectl port-forward $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name -n routing) 9000:9000 -n routing

and then visit

http://localhost:9000/dashboard/#/

I can see the dashboard, but I want to see it online not on localhost

1 Like

Host(`traefik.localhost`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))

The router matches requests to dashboard on traefik.localhost host header, and 404 means that there is not matching rule. Perhaps you are not using traefik.localhost host header in your request.

I just used your configuration as posted, and I added the loadbalancer external ip to the local hosts file:

external-ip traefik.localhost

Then I ran curl: curl http://traefik.localhost/dashboard/

I've got the html content as expected.

If I change traefik.local to traefik in both the hosts file and the dashboard.yml and re-apply dashboard.yml I also can see the dashboard in the browser at http://traefik/dashboard/

1 Like