From 0779c6a139d34a55d326a90b07ac5da0f006a952 Mon Sep 17 00:00:00 2001 From: mpl Date: Wed, 27 Mar 2019 15:16:04 +0100 Subject: [PATCH] Full ACME+CRD example Co-authored-by: Jean-Baptiste Doumenjou --- docs/content/providers/kubernetes-crd.md | 8 +- docs/content/user-guides/crd-acme/01-crd.yml | 91 ++++++++++++++++ .../user-guides/crd-acme/02-services.yml | 32 ++++++ .../user-guides/crd-acme/03-deployments.yml | 79 ++++++++++++++ .../user-guides/crd-acme/04-ingressroutes.yml | 30 ++++++ docs/content/user-guides/crd-acme/index.md | 100 ++++++++++++++++++ docs/content/user-guides/crd-acme/k3s.yml | 30 ++++++ docs/mkdocs.yml | 2 + integration/fixtures/k8s/03-ingressroute.yml | 1 - 9 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 docs/content/user-guides/crd-acme/01-crd.yml create mode 100644 docs/content/user-guides/crd-acme/02-services.yml create mode 100644 docs/content/user-guides/crd-acme/03-deployments.yml create mode 100644 docs/content/user-guides/crd-acme/04-ingressroutes.yml create mode 100644 docs/content/user-guides/crd-acme/index.md create mode 100644 docs/content/user-guides/crd-acme/k3s.yml diff --git a/docs/content/providers/kubernetes-crd.md b/docs/content/providers/kubernetes-crd.md index 44bb2fe79..6e4398027 100644 --- a/docs/content/providers/kubernetes-crd.md +++ b/docs/content/providers/kubernetes-crd.md @@ -3,7 +3,9 @@ The Kubernetes Ingress Controller, The Custom Resource Way. {: .subtitle } -[comment]: # (Link "Kubernetes Ingress controller" to ./kubernetes-ingress.md) + The Traefik Kubernetes provider used to be a Kubernetes Ingress controller in the strict sense of the term; that is to say, it would manage access to a cluster services by supporting the [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) specification. @@ -120,3 +122,7 @@ spec: ## Full reference example [Traefik IngressRoute Reference](../reference/providers/kubernetescrd.md). + +## Further + +Also see the [full example](../user-guides/crd-acme/index.md) with Let's Encrypt. diff --git a/docs/content/user-guides/crd-acme/01-crd.yml b/docs/content/user-guides/crd-acme/01-crd.yml new file mode 100644 index 000000000..45ace3f90 --- /dev/null +++ b/docs/content/user-guides/crd-acme/01-crd.yml @@ -0,0 +1,91 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: ingressroutes.traefik.containo.us + +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: IngressRoute + plural: ingressroutes + singular: ingressroute + scope: Namespaced + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: middlewares.traefik.containo.us + +spec: + group: traefik.containo.us + version: v1alpha1 + names: + kind: Middleware + plural: middlewares + singular: middleware + scope: Namespaced + +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: traefik-ingress-controller + +rules: + - apiGroups: + - "" + resources: + - services + - endpoints + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - extensions + resources: + - ingresses + verbs: + - get + - list + - watch + - apiGroups: + - extensions + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - traefik.containo.us + resources: + - middlewares + verbs: + - get + - list + - watch + - apiGroups: + - traefik.containo.us + resources: + - ingressroutes + verbs: + - get + - list + - watch + +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: traefik-ingress-controller + +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: traefik-ingress-controller +subjects: + - kind: ServiceAccount + name: traefik-ingress-controller + namespace: default diff --git a/docs/content/user-guides/crd-acme/02-services.yml b/docs/content/user-guides/crd-acme/02-services.yml new file mode 100644 index 000000000..753d9e65b --- /dev/null +++ b/docs/content/user-guides/crd-acme/02-services.yml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Service +metadata: + name: traefik + +spec: + ports: + - protocol: TCP + name: web + port: 8000 + - protocol: TCP + name: admin + port: 8080 + - protocol: TCP + name: websecure + port: 4443 + selector: + app: traefik + +--- +apiVersion: v1 +kind: Service +metadata: + name: whoami + +spec: + ports: + - protocol: TCP + name: web + port: 80 + selector: + app: whoami diff --git a/docs/content/user-guides/crd-acme/03-deployments.yml b/docs/content/user-guides/crd-acme/03-deployments.yml new file mode 100644 index 000000000..712503a53 --- /dev/null +++ b/docs/content/user-guides/crd-acme/03-deployments.yml @@ -0,0 +1,79 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: default + name: traefik-ingress-controller + +--- +kind: Deployment +apiVersion: extensions/v1beta1 +metadata: + namespace: default + name: traefik + labels: + app: traefik + +spec: + replicas: 1 + selector: + matchLabels: + app: traefik + template: + metadata: + labels: + app: traefik + spec: + serviceAccountName: traefik-ingress-controller + containers: + - name: traefik + image: traefik:v2.0 + args: + - --api + - --accesslog + - --entrypoints=Name:web Address::8000 + - --entrypoints=Name:websecure Address::4443 + - --providers.kubernetescrd + - --providers.kubernetescrd.trace + - --acme + - --acme.acmelogging + - --acme.tlschallenge + - --acme.onhostrule + - --acme.email=foo@you.com + - --acme.entrypoint=websecure + - --acme.storage=acme.json + # Please note that this is the staging Let's Encrypt server. + # Once you get things working, you should remove that whole line altogether. + - --acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory + ports: + - name: web + containerPort: 8000 + - name: websecure + containerPort: 4443 + - name: admin + containerPort: 8080 + +--- +kind: Deployment +apiVersion: extensions/v1beta1 +metadata: + namespace: default + name: whoami + labels: + app: whoami + +spec: + replicas: 2 + selector: + matchLabels: + app: whoami + template: + metadata: + labels: + app: whoami + spec: + containers: + - name: whoami + image: containous/whoami + ports: + - name: web + containerPort: 80 diff --git a/docs/content/user-guides/crd-acme/04-ingressroutes.yml b/docs/content/user-guides/crd-acme/04-ingressroutes.yml new file mode 100644 index 000000000..9e67cc83d --- /dev/null +++ b/docs/content/user-guides/crd-acme/04-ingressroutes.yml @@ -0,0 +1,30 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: simpleingressroute +spec: + entrypoints: + - web + routes: + - match: Host(`your.domain.com`) && PathPrefix(`/notls`) + kind: Rule + services: + - name: whoami + port: 80 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: ingressroutetls +spec: + entrypoints: + - websecure + routes: + - match: Host(`your.domain.com`) && PathPrefix(`/tls`) + kind: Rule + services: + - name: whoami + port: 80 + tls: + secretName: "" diff --git a/docs/content/user-guides/crd-acme/index.md b/docs/content/user-guides/crd-acme/index.md new file mode 100644 index 000000000..84c8db503 --- /dev/null +++ b/docs/content/user-guides/crd-acme/index.md @@ -0,0 +1,100 @@ +# Traefik & CRD & Let's Encrypt + +Traefik with an IngressRoute Custom Resource Definition for Kubernetes, and TLS Through Let's Encrypt. +{: .subtitle } + +This document is intended to be a fully working example demonstrating how to set up Traefik in [Kubernetes](https://kubernetes.io), +with the dynamic configuration coming from the [IngressRoute Custom Resource](../../providers/kubernetes-crd.md), +and TLS setup with [Let's Encrypt](https://letsencrypt.org). +However, for the sake of simplicity, we're using [k3s](https://github.com/rancher/k3s) docker image for the Kubernetes cluster setup. + +Please note that for this setup, given that we're going to use ACME's TLS-ALPN-01 challenge, the host you'll be running it on must be able to receive connections from the outside on port 443. +And of course its internet facing IP address must match the domain name you intend to use. + +In the following, the Kubernetes resources defined in YAML configuration files can be applied to the setup in two different ways: + +- the first, and usual way, is simply with the `kubectl apply` command. +- the second, which can be used for this tutorial, is to directly place the files in the directory used by the k3s docker image for such inputs (`/var/lib/rancher/k3s/server/manifests`). + +## k3s Docker-compose Configuration ## + +Our starting point is the docker-compose configuration file, to start the k3s cluster. +You can start it with: + +```bash +docker-compose -f k3s.yml up +``` + +```yaml +--8<-- "content/user-guides/crd-acme/k3s.yml" +``` + +## Cluster Resources ## + +Let's now have a look (in the order they should be applied, if using `kubectl apply`) at all the required resources for the full setup. + +### IngressRoute Definition ### + +First, the definition of the `IngressRoute` and the `Middleware` kinds. +Also note the RBAC authorization resources; they'll be referenced through the `serviceAccountName` of the deployment, later on. + +```yaml +--8<-- "content/user-guides/crd-acme/01-crd.yml" +``` + +### Services ### + +Then, the services. One for Traefik itself, and one for the app it routes for, i.e. in this case our demo HTTP server: [whoami](https://github.com/containous/whoami). + +```yaml +--8<-- "content/user-guides/crd-acme/02-services.yml" +``` + +### Deployments ### + +Next, the deployments, i.e. the actual pods behind the services. +Again, one pod for Traefik, and one for the whoami app. + +```yaml +--8<-- "content/user-guides/crd-acme/03-deployments.yml" +``` + +### Port Forwarding ### + +Now, as an exception to what we said above, please note that you should not let the ingressRoute resources below be applied automatically to your cluster. +The reason is, as soon as the ACME provider of Traefik detects we have TLS routers, it will try to generate the certificates for the corresponding domains. +And this will not work, because as it is, our Traefik pod is not reachable from the outside, which will make the ACME TLS challenge fail. +Therefore, for the whole thing to work, we must delay applying the ingressRoute resources until we have port-forwarding set up properly, which is the next step. + +```bash +kubectl port-forward --address 0.0.0.0 service/traefik 8000:8000 8080:8080 443:4443 -n default +``` + +Also, and this is out of the scope if this guide, please note that because of the privileged ports limitation on Linux, the above command might fail to listen on port 443. +In which case you can use tricks such as elevating caps of `kubectl` with `setcaps`, or using `authbind`, or setting up a NAT between your host and the WAN. +Look it up. + +### Traefik Routers ### + +We can now finally apply the actual ingressRoutes, with: + +```bash +kubectl apply -f 04-ingressroutes.yml +``` + +```yaml +--8<-- "content/user-guides/crd-acme/04-ingressroutes.yml" +``` + +Give it a few seconds for the ACME TLS challenge to complete, and you should then be able to access your whoami pod (routed through Traefik), from the outside. +Both with or (just for fun, do not do that in production) without TLS: + +```bash +curl [-k] https://your.domain.com/tls +``` + +```bash +curl [-k] http://your.domain.com:8000/notls +``` + +Note that you'll have to use `-k` as long as you're using the staging server of Let's Encrypt, since it is not in the root DNS servers. diff --git a/docs/content/user-guides/crd-acme/k3s.yml b/docs/content/user-guides/crd-acme/k3s.yml new file mode 100644 index 000000000..5fe32dfff --- /dev/null +++ b/docs/content/user-guides/crd-acme/k3s.yml @@ -0,0 +1,30 @@ +server: + image: rancher/k3s:v0.2.0 + command: server --disable-agent --no-deploy traefik + environment: + - K3S_CLUSTER_SECRET=somethingtotallyrandom + - K3S_KUBECONFIG_OUTPUT=/output/kubeconfig.yaml + - K3S_KUBECONFIG_MODE=666 + volumes: + # k3s will generate a kubeconfig.yaml in this directory. This volume is mounted + # on your host, so you can then 'export KUBECONFIG=/somewhere/on/your/host/out/kubeconfig.yaml', + # in order for your kubectl commands to work. + - /somewhere/on/your/host/out:/output + # This directory is where you put all the (yaml) configuration files of + # the Kubernetes resources. + - /somewhere/on/your/host/in:/var/lib/rancher/k3s/server/manifests + ports: + - 6443:6443 + +node: + image: rancher/k3s:v0.2.0 + privileged: true + links: + - server + environment: + - K3S_URL=https://server:6443 + - K3S_CLUSTER_SECRET=somethingtotallyrandom + volumes: + # this is where you would place a alternative traefik image (saved as a .tar file with + # 'docker save'), if you want to use it, instead of the traefik:v2.0 image. + - /sowewhere/on/your/host/custom-image:/var/lib/rancher/k3s/agent/images diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 6de0d6d04..34e069940 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -122,6 +122,8 @@ nav: - 'Logs': 'observability/logs.md' - 'Access Logs': 'observability/access-logs.md' - 'Tracing': 'observability/tracing.md' + - 'User Guides': + - 'Kubernetes and Let''s Encrypt': 'user-guides/crd-acme/index.md' - 'Contributing': - 'Thank You!': 'contributing/thank-you.md' - 'Submitting Issues': 'contributing/submitting-issues.md' diff --git a/integration/fixtures/k8s/03-ingressroute.yml b/integration/fixtures/k8s/03-ingressroute.yml index 608b52a42..303d8bdfa 100644 --- a/integration/fixtures/k8s/03-ingressroute.yml +++ b/integration/fixtures/k8s/03-ingressroute.yml @@ -15,4 +15,3 @@ spec: services: - name: whoami port: 80 -