techno-tim / launchpad

A collection of quick starters for ansible, kubernetes, docker, linux, windows, and more. Great for HomeLabs!
https://technotim.live
1.42k stars 475 forks source link

Managing external resources through traefik #18

Closed RovoMe closed 1 year ago

RovoMe commented 2 years ago

I spent the last few days trying to figure out how I can use the kubernetes hosted traefik, which does know of the let's encrypt wildcard certificate, to handle also external services not located in kubernetes directly.

I.e. I have a couple of portainer installations which I "grouped up" in the past already via the environment section of portainer on my main server. That portainer was so far reachable via an internal host name I set for my server but it didn't use a valid certificate.

With the configuration below I am now finally able to address external services through traefik which itself is running in kubernetes (k3s to be precise). This allows to utilize the wildcard certificate obtained from let's encrypt on external service which are not yet part of kubernetes.

---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: default-headers
  namespace: portainer
spec:
  headers:
    browserXssFilter: true
    contentTypeNosniff: true
    forceSTSHeader: true
    stsIncludeSubdomains: true
    stsPreload: true
    stsSeconds: 15552000
    customFrameOptionsValue: SAMEORIGIN
    customRequestHeaders:
      X-Forwarded-Proto: https
---
apiVersion: v1
kind: Service
metadata:
  name: portainer
  namespace: portainer
spec:
  type: ClusterIP
  ports:
    - name: https
      port: 443
      targetPort: 9443
      protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
  name: portainer
  namespace: portainer
subsets:
  - addresses:
    - ip: {ip-of-external-server}
    ports:
      - name: https
        port: 9443
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: portainer
  namespace: portainer
  annotations:
    kubernetes.io/ingress.class: traefik-external
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`portainer.local.example.com`)
      kind: Rule
      services:
        - name: portainer
          port: 443
      middlewares:
        - name: default-headers
  tls:
    secretName: local-example-com-tls

The ingress configuration is rather straight forward, though the service definition differs here. I tried a lot with ExternalName or ExternalIPs in the service config, though the primer one doesn't use ports while the latter one didn't show up in traefik dashboard no matter what I tried.

The final clue came while watching this Google Cloud Tech video where Sandeep mentioned all of the hurdles I faced and that on defining an Endpoints resource and defining the IP and port there directly one can still make use of traefik for external resources.

Hope this helps others :) If there is a simpler approach to get the job done, please feel free to post it here as I'm always keen on learning new tech-tings I can try in my homelab .

SuperSweatyYeti commented 1 year ago

@RovoMe

Hello my friend,

I have suffered through the same issue trying to setup external services through traefik in the k3s cluster.

Turns out... traefik does not allow external services by default and any ingresses referring to services you setup that point to external stuff will never show up in the traefik dashboard...

UNLESS...

You toggle these flags here in the values.yaml file when installing traefik with helm.

providers:
  kubernetesCRD:
    allowExternalNameServices: true # added this line
  kubernetesIngress:
    enabled: true
    allowExternalNameServices: true # added this line

You can reinstall with the updated values.yaml file using helm upgrade --namespace=traefik traefik traefik/traefik --values=values.yaml

Now you can just use a service.yaml and ingress.yaml file like the respective examples below and they will show up properly in traefik. service.yaml ingress.yaml

I made a pull request for this issue: #25