Search code examples
kubernetes-ingresstraefikk3straefik-ingressingress-controller

Configuring K3S and Traefik Ingress to Expose TCP Port for SSH


I have a GitLab service deployed with a pod listening on TCP port 22. Additionally, I've set up a service to link port 2222 to port 22, which is functioning correctly.

Now, I aim to utilize Traefik Ingress to route TCP traffic from port 2222 to the service's port 22.

Here's my current setup:

GitLab Deployment:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: gitlab
      namespace: gitlab
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gitlab
      template:
        metadata:
          labels:
            app: gitlab
        spec:
          containers:
            - name: gitlab
              image: gitlab/gitlab-ce:16.7.7-ce.0
              ports:
                - containerPort: 80
                - containerPort: 443
                - containerPort: 22

Service:

    apiVersion: v1
    kind: Service
    metadata:
      name: gitlab-service
      namespace: gitlab
    spec:
      selector:
        app: gitlab-shell
      ports:
        - protocol: TCP
          port: 2222
          targetPort: 22

Ingress for Traefik:

    apiVersion: traefik.containo.us/v1alpha1
    kind: IngressRouteTCP
    metadata:
      name: gitlab-shell
      namespace: gitlab
    spec:
      entryPoints:
        - gitlab-shell
      routes:
      - match: HostSNI(`*`)
        services:
        - name: gitlab-gitlab-shell
          namespace: gitlab
          port: 2222

I suppose that is is required to update Ingress controller itself to able to listen on port 2222, but can't find how to edit it.

I have tried:

    kubectl edit deployment traefik -n kube-system
        - args:                                          
          - --entrypoints.gitlab-shell.address=:2222/tcp 
        ports:                                                                                                                                              
           - containerPort: 2222                                                               
             name: gitlab-shell                                                                
             protocol: TCP

And there is still no result

Next I checked Traefik services:

    kubectl get service traefik -n kube-system
    spec:                                              
      allocateLoadBalancerNodePorts: true              
      clusterIP: 10.43.208.160                         
      clusterIPs:                              
      - 10.43.208.160                          
      externalTrafficPolicy: Cluster           
      internalTrafficPolicy: Cluster           
      ipFamilies:                              
      - IPv4                                   
      ipFamilyPolicy: PreferDualStack          
      ports:                             
      - name: web                        
        nodePort: 30552              
        port: 80                     
        protocol: TCP                
        targetPort: web              
      - name: websecure              
        nodePort: 30113              
        port: 443                    
        protocol: TCP                
        targetPort: websecure

And there is no TCP/2222 port.

If I add TCP/2222 manually, there is still no success

kubectl edit service traefik -n kube-system
ports:                                         
  - name: gitlab-shell           
    nodePort: 31250              
    port: 2222                   
    protocol: TCP                
    targetPort: 2222 

Now I can't find a proper way to expose TCP port.

Desired diagram:

IngressController (Traefic) <--?--> Ingress <--?--> Service:2222 <--OK--> Pod:22

Could somebody please help me out with this? I would be happy with any configuration example.


Solution

  • I suppose that is is required to update Ingress controller itself to able to listen on port 2222, but can't find how to edit it.

    That's exactly the issue: when you're using an ingress, the thing that actually binds to ports is the ingress controller. When using k3s, traefik is installed using a HelmChart resource:

    $ kubectl -n kube-system get helmchart
    NAME          JOB                        CHART                                                                      TARGETNAMESPACE   VERSION   REPO   HELMVERSION   BOOTSTRAP
    traefik       helm-install-traefik       https://%{KUBERNETES_API}%/static/charts/traefik-25.0.2+up25.0.0.tgz                                                        
    traefik-crd   helm-install-traefik-crd   https://%{KUBERNETES_API}%/static/charts/traefik-crd-25.0.2+up25.0.0.tgz                                                    
    

    We can configure that chart using a HelmChartConfig manifest, like this:

    apiVersion: helm.cattle.io/v1
    kind: HelmChartConfig
    metadata:
      name: traefik
      namespace: kube-system
    spec:
      valuesContent: |-
        ports:
          ssh: 
            port: 2200
            expose: true
            exposedPort: 2200
    

    When you deploy the HelmChartConfig resource into the kube-system namespace, it will trigger a re-install of Traefik with the following changes:

    • It will update the traefik Deployment to:

      • Add --entrypoints.ssh.address=:2200/tcp to the traefik server command line.

      • Add an entry to the ports section:

        - containerPort: 9100
          name: metrics
          protocol: TCP
        
    • It will add a new port to the traefik Service:

      - name: ssh
        nodePort: 32594
        port: 2200
        protocol: TCP
        targetPort: ssh
      

    The load balancer (ServiceLB by default) will expose the appropriate port on the host.