Issue

The Universal Control Plane 3.0 documentation details how to configure an Nginx ingress controller, to provide Layer 7 ingress routing to deployments within Kubernetes. This article details how to deploy Traefik within UCP 3.0 as alternative Kubernetes ingress controller.

Prerequisites

Before performing these steps, you must meet the following requirements:

Universal Control Plane 3.0

Resolution

To configure a Traefik Kubernetes ingress controller within UCP 3.0 follow the steps below:

Authorization

First, create a Kubernetes namespace for the Traefik ingress controller and a permissions grant for the default Service Account within this namespace:

Create a namespace for the Traefik ingress controller: Navigate to the Namespaces page, under the Kubernetes section of the UCP UI, and click Create. In the Object YAML editor, copy and paste this Namespace definition: apiVersion: v1 kind: Namespace metadata: name: ingress-traefik Click Create. Create Kubernetes role to manage Traefik ingress controller access: Navigate to Access Control -> Roles page in UCP UI and click Create. In the Object YAML editor, copy and paste this ClusterRole definition: kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: traefik-ingress-controller rules: - apiGroups: - "" resources: - services - endpoints - secrets - configmaps verbs: - get - list - watch - apiGroups: - extensions resources: - ingresses verbs: - get - list - watch For more RBAC information see Traefik documentation. Create a grant for the default service account within the ingress-traefik namespace: Navigate to Access Control -> Grants page in the UCP UI and click Create Role Binding. Within the Subject pane, select Service Account . For the Namespace select ingress-traefik , and select default for the Service Account, and click Next. Within the Resource Set pane, select the Apply Role Binding to all namespaces toggle. Within the Role pane, select traefik-ingress-controller role. Click Create. Alternatively, one can create ClusterRoleBinding object by deployting this YAML code: kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: ingress-traefik-default:traefik-ingress-controller labels: subjectName: ingress-traefik-default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: traefik-ingress-controller subjects: - kind: ServiceAccount name: default namespace: ingress-traefik

Deploy the traefik ingress controller

The following Traefik ingress controller deployment closely follows the Traefik documentation, with some modifications to function correctly within UCP 3.0.

Navigate to the + Create Kubernetes Object page, under the Kubernetes section of the UCP UI, and in the Object YAML editor, paste the following YAML and click Create:

--- kind: Deployment apiVersion: extensions/v1beta1 metadata: name: traefik-ingress-controller namespace: ingress-traefik labels: k8s-app: traefik-ingress-lb spec: replicas: 1 selector: matchLabels: k8s-app: traefik-ingress-lb template: metadata: labels: k8s-app: traefik-ingress-lb name: traefik-ingress-lb spec: serviceAccountName: default terminationGracePeriodSeconds: 60 containers: - image: traefik name: traefik-ingress-lb ports: - name: http containerPort: 80 - name: admin containerPort: 8080 args: - --api - --kubernetes - --logLevel=INFO # enable access log - --accesslog # write logs into container STDOUT - --accesslog.filepath=/dev/stdout - --accesslog.format=json --- kind: Service apiVersion: v1 metadata: name: traefik-ingress-service namespace: ingress-traefik spec: selector: k8s-app: traefik-ingress-lb ports: - protocol: TCP nodePort: 35080 port: 80 name: web - protocol: TCP nodePort: 33167 port: 8080 name: admin type: NodePort

Navigate to the Namespaces page under the Kubernetes section of the UCP UI. Hover mouse over ingress-traefik namespace and click Set Context on the far-right. Navigate to the Load Balancers page under the Kubernetes section of the UCP UI, under which traefik-ingress-service should be listed. Click on this traefik-ingress-service , and details similar to the following screenshot should be displayed: The first Node Port with Target Port: 80 is the port to access the ingress controller, applications exposed via the Traefik ingress controller can be access via the IP of any node in the UCP cluster using this Node Port (i.e. 35080 ) and the host header configured for the application in the Ingress object rules section. The second Node Port with TargetPort: 8080 is to access the Traefik admininistration page, which can be useful for inspecting the Traefik configuration. The Traefik administration page can be accessed via the IP of any node in the UCP cluster using this Node Port (i.e. 33167 ). Note: You should secure access to the Traefik admin page, and add authentication to this within the Traefik configuration to prevent unauthorized access to this page as it can expose private information. You need to secure it and add authentication within the Traefik configuration.

Deploy Grafana application to test the ingress

With the traefik-ingress controller deployed, you may now deploy an application exposed via this ingress controller. Be sure to use the annotation kubernetes.io/ingress.class: traefik inside the Ingress object for the deployment.

To deploy a grafana pod into the default Kubernetes namespace and expose this via the Traefik ingress, navigate to the + Create Kubernetes Object page, under the Kubernetes section of the UCP UI. In the Object YAML editor paste the following YAML and click Create:

apiVersion: apps/v1beta2 kind: Deployment metadata: namespace: default name: grafana-deployment labels: app: grafana spec: replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: containers: - name: grafana image: grafana/grafana:latest ports: - containerPort: 3000 --- kind: Service apiVersion: v1 metadata: name: grafana-service namespace: default spec: selector: app: grafana ports: - name: http protocol: TCP port: 80 targetPort: 3000 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress namespace: default annotations: kubernetes.io/ingress.class: traefik spec: rules: - host: grafana.traefik http: paths: - path: / backend: serviceName: grafana-service servicePort: 80

This deployment exposes the grafana pod via the hostname grafana.traefik . Update your hosts file to direct the hostname grafana.traefik to the IP of a node within the Docker Enterprise cluster. You should then be able to access this grafana deployment within a browser at http://grafana.traefik:Traefik ingress Node Port , where the ingress Node Port configured in the traefik-ingress-service above was 35080 .

Deploy traefik ingress controller scoped to a specific namespace

While Traefik ingress controller deployment described above can provide ingress access to Kubernetes services cluster wide, it is considered to be a better practice to limit Traefik ingress controller to handle requests for services within a specific namespace. These steps show how one can deploy another Traefik ingress controller that is restricted to the specified namespace in addition to already deployed Traefik ingress controller.

In UCP UI use Kubernetes -> + Create page to create objects from YAML definitions below.

Create the namespace apiVersion: v1 kind: Namespace metadata: name: ingress-traefik-scopedns Create a grant for default service account scoped to ingress-traefik-scopedns namespace (a.k.a. RoleBinding ) Note that in the first example of the ingress controller described above the ClusterRoleBinding was used that allows you to configure ingress for any service deployed into any namespace. In this example RoleBinding is used that is limited to ingress-traefik-scopedns namespace only. The object uses role traefik-ingress-controller that was previously created. kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: ingress-traefik-scopedns-default:traefik-ingress-controller namespace: ingress-traefik-scopedns labels: subjectName: ingress-traefik-scopedns-default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: traefik-ingress-controller subjects: - kind: ServiceAccount name: default namespace: ingress-traefik-scopedns Create Traefik configuration object Traefik service can be configured via args section in container template definition on Kubernetes deployment of via traefik.toml configuration file that can be supplied as a ConfigMap object. This example uses traefik.toml configuration file. For more details on Traefik configuration see Traefik documentation. apiVersion: v1 kind: ConfigMap metadata: namespace: ingress-traefik-scopedns name: traefik-conf data: traefik.toml: | # traefik.toml logLevel = "DEBUG" defaultEntryPoints = ["http"] [entryPoints] [entryPoints.http] # port for http entrypoint that traefik listens on address = ":80" # section to define kubernetes provider configuration [kubernetes] # namespace that Traefik controller should be scoped to # if scoped to specific namespace(s), it must have service account configured to access resources in the specified namespace(s) namespaces = ["ingress-traefik-scopedns"] # Value of `kubernetes.io/ingress.class` annotation that identifies Ingress objects to be processed. # # this setting makes Traefik to only watch ingress that has "kubernetes.io/ingress.class: traefik-scopedns" annotation ingressClass = "traefik-scopedns" [ping] entryPoint = "http" # defines where accessLog output should be directed [accessLog] # The /dev/stdout directs output to container logs filePath = "/dev/stdout" format = "json" # api section is tied to expose access to dashboard entry point [api] # Name of the related entry point entryPoint = "traefik" # Enable Dashboard dashboard = true Deploy ingress controller kind: Deployment apiVersion: apps/v1 metadata: name: traefik-ingress-controller namespace: ingress-traefik-scopedns labels: k8s-app: traefik-ingress-lb spec: replicas: 1 selector: matchLabels: k8s-app: traefik-ingress-lb strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 template: metadata: labels: k8s-app: traefik-ingress-lb name: traefik-ingress-lb spec: serviceAccountName: default terminationGracePeriodSeconds: 60 volumes: - name: traefik-configmap configMap: name: traefik-conf containers: - image: traefik name: traefik-ingress-lb ports: - name: http containerPort: 80 - name: admin containerPort: 8080 volumeMounts: - mountPath: "/config" name: "traefik-configmap" args: - --configfile=/config/traefik.toml --- kind: Service apiVersion: v1 metadata: name: traefik-ingress-service namespace: ingress-traefik-scopedns spec: selector: k8s-app: traefik-ingress-lb ports: - protocol: TCP nodePort: 35090 port: 80 name: web - protocol: TCP nodePort: 34200 port: 8080 name: admin type: NodePort Deploy Whoami application to test ingress apiVersion: apps/v1 kind: Deployment metadata: namespace: ingress-traefik-scopedns name: whoami-deployment labels: app: whoami spec: replicas: 1 selector: matchLabels: app: whoami template: metadata: labels: app: whoami spec: containers: - name: whoami image: containous/whoami:latest ports: - containerPort: 80 --- kind: Service apiVersion: v1 metadata: name: whoami-service namespace: ingress-traefik-scopedns spec: selector: app: whoami ports: - name: http protocol: TCP port: 80 targetPort: 80 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: whoami-ingress namespace: ingress-traefik-scopedns annotations: # this annotation must match ingressClass value in config file kubernetes.io/ingress.class: traefik-scopedns traefik.ingress.kubernetes.io/frontend-entry-points: http spec: rules: - host: whoami.traefik http: paths: - path: /whoami backend: serviceName: whoami-service servicePort: 80

This deployment exposes the whoami pod via the hostname whoami.traefik . Update your hosts file to direct the hostname whoami.traefik to the IP of a node within the Docker Enterprise cluster. You should then be able to access the whoami deployment within a browser at http://whoami.traefik:Traefik ingress Node Port , where the ingress Node Port configured in the traefik-ingress-service above was 35090 .

References