Un atelier de migration vers Kubernetes et Traefik
Browse the slides: Use the arrows
Change chapter: Left/Right arrows
Next or previous slide: Top and bottom arrows
Overview of the slides: keyboard’s shortcut "o"
Speaker mode (and notes): keyboard’s shortcut "s"
Nicolas Mengin
DevOps & Code Craftsman @ Containous
Blacksmith on Traefik
Damien DUPORTAL
Traefik's Developer π₯ Advocate @ Containous
We Believe in Open Source
We Deliver Traefik
Commercial Support for Traefik
20 people, 90% tech
Docker as a standard
Orchestrators: Docker Swarm, Rancher Caddle, Mesos Marathon, Kubernetes…
The war lasted a couple of years…
Kubernetes
Used by the competition
Standard in the industry
Powerful but not easy to master
The Hobbit House: Introduction to Traefik with Docker
Break
Saruman Tower: Migrate Traefik to Kubernetes
Break
The Castle: Migrate the infrastructure to Kubernetes
We want to host:
Our web site
Our own SCM Server,
Our own Continous Integration,
and a "web" command line.
Step 1: Access the spreadsheet at https://bit.ly/2Pdfe41
Step 2: Select a line and put your name to allocate the VM
Step 3: no Step 3!
An online shell to reach the lab infrastructure via SSH
A public domain name lab-XX.ddu-workshops-Y.com
for your stack
A VM in the cloud, to run your "legacy" Dockerized applications
Connect to it from the WebCLI with ssh 10.0.x.y
Docker and docker-compose installed on the "Docker" VM
Create a directory named ~/01-docker
as working directory
Connect to the "Blue-Green Jenkins":
Link: Blue-Green Jenkins
Login with username devoxx
and password gandalf
Run the Job "change-dns"
Link: Job "change-dns"
Specify the EXTERNAL_HOSTNAME
of your lab (labXX.ddu-workshops-Y.com
)
Specify the BACKEND_IP
of your Docker VM (10.0.x.y
)
The external loadbalancer cannot reach our VM.
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
SSL for everyone
Why, Mr Anderson?
That You Don’t Have to Write This Configuration File…?
MIT License
Written in Go
21,000+ β
600M+ β¬οΈ
350+ π·
Step 1: Compose file in /home/devoxx/01-docker/docker-compose.yml
:
version: '2.4'
services:
edge:
image: traefik:1.7.10
command:
- "--docker.domain=lab-XX.ddu-workshops-Y.com"
ports:
- "80:80"
- "443:443"
volumes:
# To communicate with the Docker Engine
- /var/run/docker.sock:/var/run/docker.sock
Step 2: Start the stack:
docker-compose up -d
It’s good: we have an HTTP answer!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
SSL for everyone
We want to host a static webserver behind Traefik.
How to tell Traefik to route requests to the web server?
http://lab-XX.ddu-workshops-Y.com/index.html
-> Traefik
-> http://<Webserver Private IP>/index.html
Step 1: web server in Compose. Check the labels
:
web:
image: nmengin/web:devoxx-v1
labels:
- "traefik.frontend.rule=PathPrefix:/"
Step 2: Start the Web Server:
docker-compose up -d web
It’s good: we have a web page!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
SSL for everyone
We want to host our own automation system for Continuous Integration
Let’s use Jenkins
Problem: Jenkins exposes 2 ports: 8080
and 50000
. How to let Traefik know to only use 8080
?
Solution: Select the port with the label traefik.port
.
- "traefik.port=8080"
Problem: How to let Traefik know when to send requests to the Jenkins backend instead of the webserver?
http://lab-XX.ddu-workshops-Y.com/jenkins/configuration
-> Traefik
-> http://<Jenkins Private IP>:8080/jenkins/configuration
Solution: Change the frontend rule to use PathPrefix
.
- "traefik.frontend.rule=PathPrefix:/jenkins"
Problem: How to tell Jenkins to accept requests under /jenkins
?
Solution: Use the Jenkins flag --prefix=/jenkins
with the variable JENKINS_OPTS
.
environment:
- JENKINS_OPTS=--prefix=/jenkins
Step 1: Edit Compose file:
jenkins:
image: jenkins/jenkins:2.164.2-alpine
expose:
- 8080
- 50000
environment:
- JENKINS_OPTS=--prefix=/jenkins
labels:
- "traefik.port=8080"
- "traefik.frontend.rule=PathPrefix:/jenkins"
Step 2: start the service:
docker-compose up -d jenkins
It’s good: we can setup Jenkins!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
SSL for everyone
We want to host our own git server
Problem:
Gitea only serves requests under /
:
How to remove the prefix /gitserver
?
http://lab-XX.ddu-workshops-Y.com/gitserver/index.html
-> Traefik
-> http://<Gitea private IP>:3000/index.html
Solution: Use the Traefik Frontend Rule PathPrefixStrip
.
- "traefik.frontend.rule=PathPrefixStrip:/gitserver"
Step 1: Edit Compose file:
gitserver:
image: gitea/gitea:latest
expose:
- "3000"
- "22"
environment:
- ROOT_URL=/gitserver
labels:
- "traefik.port=3000"
- "traefik.frontend.rule=PathPrefixStrip:/gitserver"
Step 2: Create the service:
docker-compose up -d gitserver
It’s good: we can setup Gitea!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
SSL for everyone
We want to host our own Web Command Line.
Let’s use TTYD, Share your terminal over the web.
Problem: TTYD requires Websockets.
Solution: It’s not even a problem with Traefik!
Step 1: Edit Compose file:
ttyd:
image: tsl0922/ttyd:1.4.2-alpine
labels:
- "traefik.frontend.rule=PathPrefixStrip:/ttyd"
Step 2: Create the service:
docker-compose up -d ttyd
It’s good: we have our own "web CLI" in a web browser!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
SSL for everyone
Use HTTPS instead of HTTP
Do NOT care about certificates and renewal
Use a TOML configuration file
Letβs Encrypt is a free, automated, and open Certificate Authority.
It uses the "ACME" protocol to verify that you control a given domain name and to issue a certificate.
Problem: How to tell Traefik to listen on port 443
for HTTPS requests?
Solution:
Create a new entrypoint
Add it to the default entrypoints list
# TOML sample
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
Problem: How to tell Traefik to use Let’s Encrypt for HTTPS?
Solution:
Configure the ACME/Let’s Encrypt provider:
# TOML sample
[acme]
email = "noreply@lab.org"
storage = "/acme/acme.json"
entryPoint = "https"
# caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
[acme.tlsChallenge]
[[acme.domains]]
main = "lab-XX.ddu-workshops-Y.com"
Problem:
Traefik detects itself as a docker container with a port
It tries to request a 2nd certificate for edge.lab-XX.ddu-workshops-Y.com
.
Solution: Exclude Traefik’s container with the label traefik.enable=false
.
Step 1: Create the configuration file traefik.toml
:
defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[entryPoints.http]
address = ":80"
[acme]
email = "noreply@lab.org"
storage = "/acme/acme.json"
entryPoint = "https"
# caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
[acme.tlsChallenge]
[[acme.domains]]
main = "lab-XX.ddu-workshops-Y.com"
[docker]
domain = "lab-XX.ddu-workshops-Y.com"
watch = true
Step 2: Adapt the Compose file:
edge:
image: traefik:1.7.10
labels: # Replace "command" by labels
- "traefik.enable=false"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# Add the TOML configuration file in the root directory
- ./traefik.toml:/traefik.toml
# We declare the folder "/acme" as a data volume
- /acme
Step 3: Update the edge
service:
docker-compose up -d edge
Wait a few seconds (time to get the certificate from Let’s Encrypt) and reload the main page:
We want to begin the migration of our services from the our VM to a Kubernetes cluster:
keep the Docker services
migrate Traefik to Kubernetes
migrate the Let’s Encrypt certificates
access to the Docker services through Traefik in Kubernetes
A Kubernetes cluster (k3s) on a 2nd VM
Get the IP on the spreadsheet (column "Kube IP (10.0.n.p)")
Connect to the VM with the webshell: ssh 10.0.n.p
kubectl
and helm
installed on the client machines
Create a directory named ~/02-k8s-traefik
as working directory
Kubernetes Official Documentation:
kubectl
cheat sheet:
Get status of an object:
# Use the -o yaml for full readable description
kubectl get --namespace=devoxx <object type> <object name> (-o yaml)
An error after a kubectl apply
? Do a proper kubectl delete
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
Internet
|
[ Ingress ]
--|-----|--
[ Services ]
--|-----|--
[ Pods ]
Let’s start by migrating the Let’s Encrypt Certificates
Then, we install Traefik as Ingress Controller
We want to use our generated Let’s Encrypt certificates.
We do not want to exceed the ACME Rate Limits..
Step 1: From the "Legacy" (Docker) VM:
# Get Traefik Container ID
TRAEFIK_CONTAINER_ID="$(docker ps | grep traefik | grep edge | awk '{print $1}')"
# Generate a file "certs.b64" in the user home
docker run --rm --volumes-from="${TRAEFIK_CONTAINER_ID}" -t \
alpine cat /acme/acme.json | base64 > ~/certs.b64
Step 2: From the "bastion", copy the certificates to the new VM
ssh 10.0.x.y cat certs.b64 | ssh 10.0.n.p "cat > certs.b64"
On the "Kube" VM, we’ll create a pod with a PVC ("Persistent Volume Claim").
Then, using this pod, we’ll populate the persistent volume with the acme.json
data.
After that, we’ll be able to install the Traefik Ingress configured to use this PVC.
Step 1: Create the PVC ("Persistent Volume Claim") manifest file acme-pvc.yml
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: acme-data-pvc
namespace: devoxx
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 200Mi
Step 2: create namespace and PVC:
kubectl create namespace devoxx
kubectl apply -f acme-pvc.yml
Step 1: Create the manifest file acme-deploy.yml
:
apiVersion: v1
kind: Pod
metadata:
name: acme-loader
namespace: devoxx
spec:
containers:
- name: acme-loader
image: traefik:alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- name: acme
mountPath: /acme
volumes:
- name: acme
persistentVolumeClaim:
claimName: acme-data-pvc
Step 2: create the deployment:
kubectl apply -f acme-deploy.yml
Step 1: Wait for the pod and pvc to be created:
# Expecting the pod "acme-loader" to be in state "Running"
watch kubectl get pod,pv,pvc --namespace=devoxx
# Then hit CTRL-C
Step 2: Decode ACME data and copy it:
base64 --decode certs.b64 > ~/acme.json
chmod 0600 ~/acme.json
kubectl --namespace=devoxx cp ~/acme.json acme-loader:/acme/
kubectl exec --namespace=devoxx acme-loader -- ls -l /acme
# the file "acme.json" MUST be in 600 (-rw-------)
Step 3: Remove the "acme-loader" deployment:
kubectl delete -f acme-deploy.yml
values.yml
fileStep 1: Add rights on namespace:
# Allow creating the needed Role and Service Account
rbac:
enabled: true
Step 2: Set SSL EntryPoint with redirection:
ssl:
enabled: true
enforced: true
Step 3: Add Let’s Encrypt:
acme:
enabled: true
email: noreply@lab.org
onHostRule: true
#staging: true
challengeType: tls-alpn-01
persistence:
enabled: true
existingClaim: acme-data-pvc
helm install stable/traefik \
--name traefik-devoxx \
--namespace devoxx \
--set imageTag=1.7.10 \
--values values.yml
Step 1: Run the command:
kubectl --namespace=devoxx get services
Step 2: Once the column EXTERNAL-IP
show an IP in 172…
,
then the LoadBalancer can be reached at your VM’s IP address:
# Launch a curl command from the Kube VM
curl -v 10.0.n.p
# 302 Found -> https://10.0.n.p
It’s good: we have an anwser: HTTP/302 redirect to https!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
We want access to the webserver hosted in Docker through Traefik in Kubernetes.
Problem: How to tell to Traefik to route requests to the web server which is not deployed in Kubernetes?
https://lab-XX.ddu-workshops-Y.com/index.html
-> Traefik Kubernetes
-> Traefik Docker
-> https://<Webserver Private IP>/index.html
Solution: Define a service linked to an external address in ~/02-k8s-traefik/web.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: web-service
namespace: devoxx
labels:
guilde: web
spec:
ports:
# Define the port to contact on the external Host
# Here contact Traefik defined in lab1
- port: 80
name: traefik-http
# Indicate to Kubernetes that the service will redirect
# to a backend which is not managed in the Kubernets network
type: ExternalName
# IP of the VM in the lab1
externalName: 10.0.x.y
Problem: How to detect the HTTPS requests to catch?
Solution: Define a rule to catch all the incoming resquests for the PathPrefix:/
in ~/02-k8s-traefik/web.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-ingress
namespace: devoxx
labels:
guilde: web
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.passHostHeader: "false"
traefik.frontend.rule.type: PathPrefix
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /
backend:
serviceName: web-service
servicePort: traefik-http
Step 1: Apply the Kubernetes manifest:
kubectl apply -f ~/02-k8s-traefik/web.yml
Step 2: Verify locally:
curl -v -sSL 10.0.n.p -H "Host: lab-XX.ddu-workshops-Y.com" > /dev/null
# ...
# HTTP/2 200
# ...
Step 3: Use the Blue-Green Jenkins job to switch:
Your domain name (labXX.ddu-workshops-Y.com
)
To this VM_IP
(10.0.n.p
)
It’s good: we have a web page!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
We want access to the CI hosted in Docker through Traefik in Kubernetes
Problem: How to tell to Traefik to route requests to the CI which is not deployed in Kubernetes?
https://lab-XX.ddu-workshops-Y.com/jenkins
-> Traefik Kubernetes
-> Traefik Docker
-> https://<Jenkins Private IP>/jenkins
Solution: Use (once again) a service linked to an external address in ~/02-k8s-traefik/ci.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-service
namespace: devoxx
labels:
guilde: ci
spec:
ports:
- port: 80
name: traefik-http
type: ExternalName
externalName: 10.0.x.y
Problem: How to detect the HTTPS requests to catch?
Solution: Define a rule to catch all the incoming resquests for the PathPrefix:/jenkins
in ~/02-k8s-traefik/ci.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: devoxx
labels:
guilde: ci
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.passHostHeader: "false"
traefik.frontend.rule.type: PathPrefix
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /jenkins
backend:
serviceName: jenkins-service
servicePort: traefik-http
kubectl apply -f ~/02-k8s-traefik/ci.yml
It’s good: we still can setup Jenkins!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
We want access to the Git server hosted in Docker through Traefik in Kubernetes.
Problem:
Gitea only serves requests under /
Traefik in Docker already removes the prefix /gitserver
http://lab-XX.ddu-workshops-Y.com/gitserver/index.html
-> Traefik Kubernetes
-> Traefik Docker
-> http://<Gitea private IP>:3000/index.html
Solution: Do not remove the prefix (Thanks Captain Obvious!) in the ingress rule in ~/02-k8s-traefik/gitea.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gitea-ingress
namespace: devoxx
labels:
guilde: git
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.passHostHeader: "false"
# Only Path Prefix to let the other Traefik Strip it
traefik.frontend.rule.type: PathPrefix
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /gitserver
backend:
serviceName: gitea-server
servicePort: traefik-http
Problem: How to tell to Traefik to route requests to the SCM which is not deployed in Kubernetes?
Solution: Use (once again again) a service linked to an external address in ~/02-k8s-traefik/gitea.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: gitea-server
namespace: devoxx
labels:
guilde: git
spec:
ports:
- port: 80
name: traefik-http
type: ExternalName
externalName: 10.0.x.y
kubectl apply -f ~/02-k8s-traefik/gitea.yml
It’s good: Gitea is still available!
Traefik
Web Server
CI Server
SCM: A Gitea Git Server
Web CLI
We want to access to TTYD deployed in Docker through Traefik in Kubernetes.
Problem 1: How to tell to Traefik to route requests to TTYD which is not deployed in Kubernetes?
https://lab-XX.ddu-workshops-Y.com/ttyd
-> Traefik Kubernetes
-> Traefik Docker
-> https://<WebCLI Private IP>/
Problem 2: How to detect the HTTPS requests to catch ?
Use a Headless Service in ~/02-k8s-traefik/ttyd.yml
:
---
apiVersion: v1
kind: Service
metadata:
name: ttyd-service
namespace: devoxx
labels:
guilde: console
spec:
ports:
- port: 80
name: traefik-http
type: ExternalName
externalName: 10.0.x.y
Ingress Rule with PathPrefix:/ttyd
in ~/02-k8s-traefik/ttyd.yml
:
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ttyd-ingress
namespace: devoxx
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.passHostHeader: "false"
traefik.frontend.rule.type: PathPrefix
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /ttyd
backend:
serviceName: ttyd-service
servicePort: traefik-http
kubectl apply -f ~/02-k8s-traefik/ttyd.yml
It’s good: we can continue to develop in a web browser!
We want to terminate the migration of our services to the Kubernetes cluster.
Same VM as the Lab 2 (ssh 10.0.n.p
from the webshell)
kubectl
and helm
installed on the client machines
Create a directory named ~/03-k8s-apps
as working directory
CI Server
SCM: A Gitea Git Server
Web CLI
Web Server
We want to host the CI in Kubernetes and access it through Traefik
Problem: How to host the CI in Kubernetes?
Solution: Declare it as a Deployment
object in ~/03-k8s-apps/ci.yml
.
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: jenkins-full-deployment
namespace: devoxx
spec:
replicas: 1
template:
metadata:
labels:
guilde: ci
faction: jenkins
spec:
containers:
- name: jenkins-full-container
image: jenkins/jenkins:2.164.2-alpine
imagePullPolicy: IfNotPresent
env:
- name: JENKINS_OPTS
value: "--prefix=/jenkins"
Problem: How to access to the CI?
https://lab-XX.ddu-workshops-Y.com/jenkins
-> Traefik
-> https://<Jenkins Private IP>/jenkins
Solution: Adding a service in ~/03-k8s-apps/ci.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-full-service
namespace: devoxx
labels:
guilde: ci
spec:
type: ClusterIP
ports:
- port: 8080
name: jenkins-http
- port: 50000
name: jenkins-agent
selector:
guilde: ci
faction: jenkins
Solution: Adding an Ingress Rule in ~/03-k8s-apps/ci.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins-full-ingress
namespace: devoxx
labels:
guilde: ci
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.rule.type: PathPrefix
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /jenkins
backend:
serviceName: jenkins-full-service
servicePort: jenkins-http
# Add the new objects
kubectl apply -f ~/03-k8s-apps/ci.yml
# Delete the headless service and its ingress rule (blue-green)
kubectl delete -f ~/02-k8s-traefik/ci.yml
It’s good: we can setup Jenkins in Kubernetes!
CI Server
SCM: A Gitea Git Server
Web CLI
Web Server
We want to host the Git server in Kubernetes and access it through Traefik.
Problem 1:
How to host the Git server in Kubernetes?
Problem 2:
Gitea only serves requests under /
Traefik in Docker already removes the prefix /gitserver
http://lab-XX.ddu-workshops-Y.com/gitserver/index.html
-> Traefik
-> http://<Gitea private IP>:3000/index.html
Solution: Declare it as a Deployment
object in ~/03-k8s-apps/gitea.yml
.
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: gitea-full-deployment
namespace: devoxx
spec:
replicas: 1
template:
metadata:
labels:
guilde: git
faction: server
spec:
containers:
- name: gitea-full-container
image: gitea/gitea:latest
imagePullPolicy: IfNotPresent
env:
- name: ROOT_URL
value: "/gitserver"
Solution: Adding a service in ~/03-k8s-apps/gitea.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: gitea-full-server
namespace: devoxx
labels:
guilde: git
spec:
type: ClusterIP
ports:
- port: 3000
name: gitea-http
- port: 22
name: gitea-ssh
selector:
guilde: git
faction: server
Solution: Adding an Ingress Rule in ~/03-k8s-apps/gitea.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gitea-full-ingress
namespace: devoxx
labels:
guilde: git
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.rule.type: PathPrefixStrip
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /gitserver
backend:
serviceName: gitea-full-server
servicePort: gitea-http
# Add the new objects
kubectl apply -f ~/03-k8s-apps/gitea.yml
# Delete the headless service and its ingress rule (blue-green)
kubectl delete -f ~/02-k8s-traefik/gitea.yml
It’s good: we can setup Gitea in Kubernetes!
CI Server
SCM: A Gitea Git Server
Web CLI
Web Server
We want to host TTYD in Kubernetes and access it through Traefik.
Solution: Declare it as a Deployment
object in ~/03-k8s-apps/ttyd.yml
.
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: ttyd-full-deployment
namespace: devoxx
spec:
replicas: 1
template:
metadata:
labels:
guilde: console
faction: tty
spec:
containers:
- name: ttyd-full-container
image: tsl0922/ttyd:1.4.2-alpine
imagePullPolicy: IfNotPresent
Solution: Adding a service in ~/03-k8s-apps/ttyd.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: ttyd-full-service
namespace: devoxx
labels:
guilde: console
spec:
type: ClusterIP
ports:
- port: 7681
name: ttyd-ws
selector:
guilde: console
faction: tty
Solution: Adding an Ingress Rule in ~/03-k8s-apps/ttyd.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ttyd-full-ingress
namespace: devoxx
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.rule.type: PathPrefixStrip
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /ttyd
backend:
serviceName: ttyd-full-service
servicePort: ttyd-ws
# Add the new objects
kubectl apply -f ~/03-k8s-apps/ttyd.yml
# Delete the headless service and its ingress rule (blue-green)
kubectl delete -f ~/02-k8s-traefik/ttyd.yml
It’s good: we have our own "Dev Box" in a web browser hosted in Kubernetes!
CI Server
SCM: A Gitea Git Server
Web CLI
Web Server
We want to host the webserver in Kubernetes and access it through Traefik.
Problem 1: How to host the web server in Kubernetes?
Problem 2: How to access to the web server?
http://lab-XX.ddu-workshops-Y.com/index.html
-> Traefik
-> http://<Webserver Private IP>/index.html
Solution: Declare it as a Deployment
object in ~/03-k8s-apps/web.yml
.
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: web-full-deployment
namespace: devoxx
spec:
replicas: 1
template:
metadata:
labels:
guilde: web
faction: server
spec:
containers:
- name: web-full-container
image: nmengin/web:devoxx-v1
imagePullPolicy: IfNotPresent
Solution: Adding a service in ~/03-k8s-apps/web.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: web-full-service
namespace: devoxx
labels:
guilde: web
spec:
type: ClusterIP
ports:
- port: 80
name: web-http
selector:
guilde: web
faction: server
Solution: Adding an Ingress Rule in ~/03-k8s-apps/web.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-full-ingress
namespace: devoxx
labels:
guilde: web
annotations:
kubernetes.io/ingress.class: 'traefik'
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /
backend:
serviceName: web-full-service
servicePort: web-http
# Add the new objects
kubectl apply -f ~/03-k8s-apps/web.yml
# Delete the headless service and its ingress rule (blue-green)
kubectl delete -f ~/02-k8s-traefik/web.yml
It’s good: we have a web page in Kubernetes!
We want to deploy a new version of the webserver:
hosted in Kubernetes and accessed through Traefik
continue to access to the old version for the main part of the traffic
Problem: How to host the new version of the webserver in Kubernetes?
Solution: Declare it as a Deployment
object in ~/03-k8s-apps/web-v2.yml
.
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: web-full-v2-deployment
namespace: devoxx
spec:
replicas: 1
template:
metadata:
labels:
guilde: web
faction: server-v2
spec:
containers:
- name: web-full-v2-container
image: nmengin/web:devoxx-v2
imagePullPolicy: IfNotPresent
Problem: How to access to both the old and new version at the same time with a traffic repartition?
https://lab-XX.ddu-workshops-Y.com/
-> Traefik Kubernetes
-> 80% of traffic V1:
-> https://<Webserver Docker Private IP>/
-> 20% of traffic V2:
-> https://<Webserver kubernetes Private IP>/
Solution: Use the Traffic splitting feature in Traefik.
traefik.ingress.kubernetes.io/service-weights: |
web-full-service: 80%
web-full-v2-service: 20%
Solution: In ~/03-k8s-apps/web-v2.yml
.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-full-v2-ingress
namespace: devoxx
labels:
guilde: web
annotations:
kubernetes.io/ingress.class: 'traefik'
traefik.frontend.passHostHeader: "false"
traefik.frontend.rule.type: PathPrefix
traefik.ingress.kubernetes.io/service-weights: |
web-full-service: 80%
web-full-v2-service: 20%
spec:
rules:
- host: lab-XX.ddu-workshops-Y.com
http:
paths:
- path: /
backend:
serviceName: web-full-v2-service
servicePort: web-http
- path: /
backend:
serviceName: web-full-service
servicePort: web-http
Solution: In ~/03-k8s-apps/web-v2.yml
.
---
apiVersion: v1
kind: Service
metadata:
name: web-full-v2-service
namespace: devoxx
labels:
guilde: web
spec:
type: ClusterIP
ports:
- port: 80
name: web-http
selector:
guilde: web
faction: server-v2
# Add the new objects
kubectl apply -f ~/03-k8s-apps/web-v2.yml
# Delete only the old ingress rule: the service will be reachable from the new one
kubectl --namespace devoxx delete ingress web-full-ingress
It’s good: when reloading, the 2 versions of the web page are shown!
# Edit the ingress
kubectl --namespace devoxx edit ingress web-full-v2-ingress
####
# Delete the following lines
traefik.frontend.passHostHeader: "false"
traefik.frontend.rule.type: PathPrefix
traefik.ingress.kubernetes.io/service-weights: |
web-full-service: 80%
web-full-v2-service: 20%
...
- path: /
backend:
serviceName: web-full-service
servicePort: web-http
# Exit and save
###
It’s good: we only have the new version of the web page!
Used during all the workshop π§
Alpha version since March
Main features:
Revamped Documentation && Clarified Concepts
Expressive Routing Rule Syntax
Middlewares
TCP Support! π
Kubernetes "CRD"
Highly Available Traefik πͺ
Split responsabilities π
Control Plane
Data Plane
Let’s Encrypt Distributed Support π
Smooth Operations with the traefikeectl
CLI
1.0.0 GA since… Today! π₯³
stickers!
docker run -it containous/jobs