<p>Hi all I just created a fresh Kubernetes cluster and created a namespace called 'routing'</p>
<p>In here I created the latest traefik via the helm chart (2.2)</p>
<p>I can see the pod running fine.</p>
<p>No logs from the traefik pod.</p>
<p>When I run:</p>
<pre><code>kubectl get svc --namespace routing
</code></pre>
<p>It shows the</p>
<pre><code>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
</code></pre>
<p>I tried on my browser going to https:external-ip-is-here but it just shows 404</p>
<p>I tried with just HTTP also.</p>
<p>When I run kubectl get pods -A I see cilium and coredns running (default with digital oceans kubernetes cluster)</p>
<p>Here is when I do <strong>kubectl get service -A</strong></p>
<pre class="lang-sh prettyprint-override"><code>NAMESPACE     NAME         TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)                      AGE
default       kubernetes   ClusterIP      10.245.0.1      &lt;none&gt;            443/TCP                      7d
kube-system   kube-dns     ClusterIP      10.245.0.10     &lt;none&gt;            53/UDP,53/TCP,9153/TCP       7d
routing       traefik      LoadBalancer   10.245.69.214   external-ip   80:32252/TCP,443:30252/TCP   2d
</code></pre>
<p>Here is the file and command I am using for the dashboard:</p>
<pre class="lang-sh prettyprint-override"><code>kubectl apply -f dashboard.yml --namespace routing
</code></pre>
<p>and file:</p>
<h1>dashboard.yml</h1>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: dashboard
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`traefik.localhost`) &amp;&amp; (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
      kind: Rule
      services:
        - name: api@internal
          kind: TraefikService
</code></pre>
<p>Here is the values file used:</p>
<h1>Default values for Traefik</h1>
<pre class="lang-yaml prettyprint-override"><code>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 &quot;volume-permissions&quot; 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: [&quot;sh&quot;, &quot;-c&quot;, &quot;chmod -Rv 600 /data/*&quot;]
    #   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: &quot;&quot;

#
# 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:
# - &quot;--providers.file.filename=/config/dynamic.toml&quot;
volumes: []
# - name: public-cert
#   mountPath: &quot;/certs&quot;
#   type: secret
# - name: configs
#   mountPath: &quot;/config&quot;
#   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: &quot;200,300-302&quot;
      # 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:
  - &quot;--global.checknewversion&quot;
  - &quot;--global.sendanonymoususage&quot;

#
# 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=&quot;additionalArguments={--providers.kubernetesingress.ingressclass=traefik-internal,--log.level=DEBUG}&quot;`
additionalArguments: []
#  - &quot;--providers.kubernetesingress.ingressclass=traefik-internal&quot;
#  - &quot;--log.level=DEBUG&quot;

# 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: &quot;1.2.3.4&quot;
    # clusterIP: &quot;2.3.4.5&quot;
  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:
# - &quot;--certificatesresolvers.le.acme.storage=/data/acme.json&quot;
# It will persist TLS certificates.
persistence:
  enabled: false
#  existingClaim: &quot;&quot;
  accessMode: ReadWriteOnce
  size: 128Mi
  # storageClass: &quot;&quot;
  path: /data
  annotations: {}
  # subPath: &quot;&quot; # 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&gt;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: &quot;&quot;

# Additional serviceAccount annotations (e.g. for oidc authentication)
serviceAccountAnnotations: {}

resources: {}
  # requests:
  #   cpu: &quot;100m&quot;
  #   memory: &quot;50Mi&quot;
  # limits:
  #   cpu: &quot;300m&quot;
  #   memory: &quot;150Mi&quot;
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 &quot;traefik.name&quot; . }}
#       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: &quot;&quot;

# 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

</code></pre>
<p>If I run:</p>
<pre class="lang-sh prettyprint-override"><code>kubectl port-forward $(kubectl get pods --selector &quot;app.kubernetes.io/name=traefik&quot; --output=name -n routing) 9000:9000 -n routing
</code></pre>
<p>and then visit</p>
<pre><code>http://localhost:9000/dashboard/#/
</code></pre>
<p>I can see the dashboard, but I want to see it online not on localhost</p>

Jacob
<p>Looks you need to expose port <code>9000</code> as the config comments say. Keep in mind the warning for production environments:</p>
<pre class="lang-yaml prettyprint-override"><code>  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. 👈 Keep in mind this
    # If you want to access it from outside of your cluster,
    # use `kubectl proxy` or create a secure ingress
    expose: true 👈 Change this
    # The exposed port for this service
    exposedPort: 9000
    # The port protocol (TCP/UDP)
    protocol: TCP
</code></pre>
<p>Then it should be available through <code>external-ip-is-here:9000</code>.</p>
<p>If you like to service it through port <code>80</code> or <code>443</code> you will have to modify the existing or create another <code>IngressRoute</code>/<code>TraefikService</code> pair.</p>
<p>✌️</p>
