Kubernetes Notes - Ingress TLS

Posted by poe on Fri, 16 Aug 2019 04:44:48 +0200

ingress tls

Last lesson showed you how to install traefik and configure ingress. In this lesson, we will learn how to use ingress tls and path paths in ingress objects.

TLS authentication

In most scenarios now we will use https to access our services. In this lesson we will use a self-signed certificate. Of course, it is best that you have a CA certificate purchased by some formal organizations so that anyone who accesses your services will be trusted by the browser.Use the following openssl command to generate a CA certificate:

$ openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -out tls.crt

Now that we have a certificate, we can use kubectl to create a secret object to store the certificate above:

$ kubectl create secret generic traefik-cert --from-file=tls.crt --from-file=tls.key -n kube-system

Configure Traefik

Previously, we used the default configuration of Traefik, but now let's configure Traefik to support https:

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      CertFile = "/ssl/tls.crt"
      KeyFile = "/ssl/tls.key"

In the configuration file above, we configure both http and HTTPS entries, and configure to force http services to jump to HTTPS services, so all our services coming in through traefik are https. To access HTTPS services, of course, you have to configure the corresponding certificate. You can see that we have specified CertFile And KeyFile, since traefik pod does not have these two certificates, we want to find a way to mount the certificates generated above into Pod. Did we explain earlier that secret objects can be mounted into Pod as volume s?As for the traefik.toml file above, how do we make the traefik pod accessible?Remember the ConfigMap we talked about earlier?Can we mount the traefik.toml configuration file above into the traefik pod through a ConfigMap object?

$ kubectl create configmap traefik-conf --from-file=traefik.toml -n kube-system

Now you can change the yaml file of traefik pod from the next lesson:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
  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: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      volumes:
      - name: ssl
        secret:
          secretName: traefik-cert
      - name: config
        configMap:
          name: traefik-conf
      tolerations:
      - operator: "Exists"
      nodeSelector:
        kubernetes.io/hostname: master
      containers:
      - image: traefik
        name: traefik-ingress-lb
        volumeMounts:
        - mountPath: "/ssl"
          name: "ssl"
        - mountPath: "/config"
          name: "config"
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: https
          containerPort: 443
          hostPort: 443
        - name: admin
          containerPort: 8080
        args:
        - --configfile=/config/traefik.toml
        - --api
        - --kubernetes
        - --logLevel=INFO

In comparison with the previous one, we added port configuration of 443 and specified traefik.toml configuration file in the boot parameters through configfile, which was mounted through volume.Then update the traefik pod below:

$ kubectl apply -f traefik.yaml
$ kubectl logs -f traefik-ingress-controller-7dcfd9c6df-v58k7 -n kube-system
time="2018-08-26T11:26:44Z" level=info msg="Server configuration reloaded on :80"
time="2018-08-26T11:26:44Z" level=info msg="Server configuration reloaded on :443"
time="2018-08-26T11:26:44Z" level=info msg="Server configuration reloaded on :8080"

When the update is complete, we look at the traefik pod's log, and if some log information similar to the one above appears, it will prove that the update was successful.Now when we visit traefik's dashboard, we will jump to https address and prompt the certificate-related alert information. This is because our certificate is self-built and not trusted by browsers. If you buy a certificate from a regular institution and it doesn't change the alert information, you should see that we are familiar with itGreen flag for:
By clicking on Advanced below, we can force it to jump so that we can access traefik's dashboard normally.

Configure ingress

In fact, the above TLS authentication method has succeeded. Next, we illustrate the use of path in ingress through an example, where we deploy three simple web services to identify which service is currently running through an environment variable: (backend.yaml)

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: svc1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: svc1
    spec:
      containers:
      - name: svc1
        image: cnych/example-web-service
        env:
        - name: APP_SVC
          value: svc1
        ports:
        - containerPort: 8080
          protocol: TCP

---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: svc2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: svc2
    spec:
      containers:
      - name: svc2
        image: cnych/example-web-service
        env:
        - name: APP_SVC
          value: svc2
        ports:
        - containerPort: 8080
          protocol: TCP

---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: svc3
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: svc3
    spec:
      containers:
      - name: svc3
        image: cnych/example-web-service
        env:
        - name: APP_SVC
          value: svc3
        ports:
        - containerPort: 8080
          protocol: TCP

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: svc1
  name: svc1
spec:
  type: ClusterIP
  ports:
  - port: 8080
    name: http
  selector:
    app: svc1

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: svc2
  name: svc2
spec:
  type: ClusterIP
  ports:
  - port: 8080
    name: http
  selector:
    app: svc2

---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: svc3
  name: svc3
spec:
  type: ClusterIP
  ports:
  - port: 8080
    name: http
  selector:
    app: svc3

As you can see above, we have defined three Deployment s corresponding to three Service s:

$ kubectl create -f backend.yaml
deployment.extensions "svc1" created
deployment.extensions "svc2" created
deployment.extensions "svc3" created
service "svc1" created
service "svc2" created
service "svc3" created

Then we create an Ingres object to access the three services above: (example-ingress.yaml)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-web-app
  annotations:
    kubernetes.io/ingress.class: "traefik"
spec:
  rules:
  - host: example.haimaxy.com
    http:
      paths:
      - path: /s1
        backend:
          serviceName: svc1
          servicePort: 8080
      - path: /s2
        backend:
          serviceName: svc2
          servicePort: 8080
      - path: /
        backend:
          serviceName: svc3
          servicePort: 8080

Note that one of the differences between the ingress object we defined here and the previous one is that we added the definition of the path path path, which defaults to'/'if not specified, and created the ingress object:

$ kubectl create -f test-ingress.yaml
ingress.extensions "example-web-app" created
$ kubectl get ingress
NAME              HOSTS                 ADDRESS   PORTS     AGE
example-web-app   example.haimaxy.com             80        1m
$ kubectl describe ingress example-web-app
Name:             example-web-app
Namespace:        default
Address:
Default backend:  default-http-backend:80 (<none>)
Rules:
  Host                 Path  Backends
  ----                 ----  --------
  example.haimaxy.com
                       /s1   svc1:8080 (<none>)
                       /s2   svc2:8080 (<none>)
                       /     svc3:8080 (<none>)
Annotations:
  kubernetes.io/ingress.class:  traefik
Events:                         <none>

Now we can add a corresponding hosts resolution to the domain name example.haimaxy.com in the local hosts, and then we can access it in the browser. We can see that by default we will also jump to the https page:
We can see that the result of accessing the domain name above is svc3 service!This is because in ingress above we matched the path for the domain name with the service svc3. Similarly, when we visit http://example.haimaxy.com/s1, we should get the svc1
Visit http://example.haimaxy.com/s2 and you should get the service svc2:

What we need to note here is that the root path / must be declared at the end of the ingress object, or it will be blocked / matched. You can try putting / this path on the top, then visit the next s1 and s2 path s to see what happens?

Some students may have the need that different ingress objects are used by different domain names, and then different domain names have different certificates, so we want to use the unified https certificate provided by traefik above to everyone. At this time, we can make a separate offer for the current service.For a separate certificate, you can also create a secret object from the certificate file and then declare a tls object in the ingress object. For example, haimaxy.com above, we can specify a separate certificate file:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-web-app
  annotations:
    kubernetes.io/ingress.class: "traefik"
spec:
  tls:
    - secretName: traefik-cert
  rules:
  - host:
...

Topics: Kubernetes SSL OpenSSL