Commit 61f8b441 authored by Nicolas Pernoud's avatar Nicolas Pernoud
Browse files

Initial commit

parents
# Création et utilisation d'un cluster Kubernetes "Kapsule" sur Scaleway
L'objet de ce document est de présenter la création et l'utilisation d'un cluster kubernetes managé fonctionnel chez Scaleway, en donnant un exemple adaptable et reproductible de déploiement d'application avec stockage (stateful) et accès externe via un certificat TLS automatiquement et dynamiquement généré par Let's Encrypt.
## Pré requis
Cloner ce dépôt pour avoir les fichiers yaml nécessaires à son utilisation.
## Création du cluster
Aller sur https://console.scaleway.com/kapsule/clusters, créer un cluster avec 2 noeuds "Development" (DEV1-M).
Ne pas installer de contrôleur "ingress".
## Connexion et manipulation du cluster
Installer kubectl sur votre poste de travail : https://kubernetes.io/fr/docs/tasks/tools/install-kubectl .
Il faut également installer sur votre poste l'outil helm pour déployer les helm charts : https://helm.sh/docs/intro/install .
Enregistrer le fichier "Kubeconfig" propre à votre cluster avec le chemin `$HOME/.kube/config` (config est le nom du fichier, pas un dossier), ainsi les commandes kubectl et helm permettront de manipuler votre cluster directement.
## Installation de traefik
Traefik doit être installé à part, à partir de sa "helm chart" afin de garantir la stabilité de la configuration dans le temps.
Installer traefik avec la configuration permettant d'utiliser Let's Encrypt :
```bash
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm install --namespace kube-system --set="additionalArguments={--providers.kubernetesIngress.ingressClass=traefik-cert-manager, --serverstransport.insecureskipverify}" traefik traefik/traefik
```
## Exposition du cluster via une ressource de type "load balancer" et le gestionnaire de certificat Let's Encrypt
Pour rendre accessible le cluster via des noms d'hôtes classique, il faut déployer une ressource Scaleway de type load balancer devant.
Le load balancer n'est pas déployé dans le cluster, c'est une ressource externe, mais il est piloté par le cluster comme une ressource kubernetes particulière.
```bash
kubectl apply -f setup/traefik-loadbalancer.yml
```
Obtenir l'adresse IP publique du load balancer (EXTERNAL-IP sur la ligne de type LoadBalancer) :
```bash
kubectl get svc -n kube-system
```
Enregistrer cette IP dans le DNS Scaleway :
| Name | Type | Data | TTL | Priority |
| ---------------------------- | ---- | ---------------------- | ---- | -------- |
| <sous_domaine_du_cluster> | A | IP publique du cluster | 3600 | 0 |
| \*.<sous_domaine_du_cluster> | A | IP publique du cluster | 3600 | 0 |
Créer le gestionnaire de certificats Let's Encrypt :
```bash
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml
kubectl apply -f setup/cluster-issuer.yaml
```
## Exposition de l'interface graphique kubernetes dashboard
Il est pratique de pouvoir voir les resources kubernetes depuis un dashboard graphique.
Pour ce faire, utiliser la documentation disponible sur https://www.scaleway.com/en/docs/get-started-with-scaleway-kubernetes-kapsule/#-Connecting-to-a-Kubernetes-Cluster-via-kubectl .
En deux mots :
```bash
kubectl proxy
```
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login
## Déploiement complet d'une application de test
L'application proposée est un simple serveur nginx de test, il comporte deux pods répliqués, partageant le même espace de stockage.
Il est possible de se connecter à un pod, créer une page index.html, et vérifier que celle ci est servie par nginx et accessible depuis l'autre pod.
Modifier le nom d'hôte "myapp.air.alpha.grandlyon.com" dans le fichier "demo/kapsule-deployment-example.yml".
```bash
kubectl apply -f demo/kapsule-deployment-example.yml
```
Vérifier que l'application est bien joignable sur le nom d'hôte spécifié.
L'application doit afficher "403 Forbidden" puisque qu'il n'y a pas d'index.html créé.
Pour le créer, se connecter au dashboard en passant le fichier "config" de kubectl en méthode de connexion, trouver le pod dans son namespace "myapp", se connecter et créer un fichier d'index :
```bash
echo "fichier créé depuis le pod 1" >
```
## Déploiement d'autres applications de test
D'autres exemples complets de déploiement sont fournis dans le dossier "apps".
---
# Ingress
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: k8sdashboard-https
namespace: kubernetes-dashboard
spec:
entryPoints:
- websecure
routes:
- match: Host(`k8sdashboard.air.alpha.grandlyon.com`)
kind: Rule
middlewares:
- name: svc-k8sdashboard-headers
services:
- name: kubernetes-dashboard
port: 443
tls:
secretName: k8sdashboard-cert
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: k8sdashboard-http
namespace: kubernetes-dashboard
spec:
entryPoints:
- web
routes:
- match: Host(`k8sdashboard.air.alpha.grandlyon.com`)
kind: Rule
middlewares:
- name: svc-redirectscheme-to-https
services:
- name: kubernetes-dashboard
port: 443
---
# Middlewares
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: svc-k8sdashboard-headers
namespace: kubernetes-dashboard
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: svc-redirectscheme-to-https
namespace: kubernetes-dashboard
spec:
redirectScheme:
scheme: https
permanent: true
---
# Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: k8sdashboard-cert
namespace: kubernetes-dashboard
spec:
commonName: k8sdashboard.air.alpha.grandlyon.com
secretName: k8sdashboard-cert
dnsNames:
- k8sdashboard.air.alpha.grandlyon.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
# Namespace
apiVersion: v1
kind: Namespace
metadata:
name: onlyoffice
---
# Application
apiVersion: apps/v1
kind: Deployment
metadata:
name: onlyoffice
namespace: onlyoffice
spec:
selector:
matchLabels:
app: onlyoffice
replicas: 1
template:
metadata:
labels:
app: onlyoffice
spec:
containers:
- name: onlyoffice
image: alehoho/oo-ce-docker-license
imagePullPolicy: Always
ports:
- containerPort: 80
readinessProbe:
failureThreshold: 5
httpGet:
path: /healthcheck
port: 80
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 2
livenessProbe:
failureThreshold: 5
tcpSocket:
port: 80
initialDelaySeconds: 200
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 2
volumeMounts:
- name: tz-config
mountPath: /etc/localtime
volumes:
- name: tz-config
hostPath:
path: /usr/share/zoneinfo/Europe/Paris
---
# Service
apiVersion: v1
kind: Service
metadata:
name: onlyoffice-svc
namespace: onlyoffice
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: onlyoffice
---
# Ingress
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: onlyoffice-https
namespace: onlyoffice
spec:
entryPoints:
- websecure
routes:
- match: Host(`onlyoffice.air.alpha.grandlyon.com`)
kind: Rule
middlewares:
- name: svc-onlyoffice-headers
services:
- name: onlyoffice-svc
port: 80
tls:
secretName: onlyoffice-cert
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: onlyoffice-http
namespace: onlyoffice
spec:
entryPoints:
- web
routes:
- match: Host(`onlyoffice.air.alpha.grandlyon.com`)
kind: Rule
middlewares:
- name: svc-redirectscheme-to-https
services:
- name: onlyoffice-svc
port: 80
---
# Middlewares
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: svc-onlyoffice-headers
namespace: onlyoffice
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: svc-redirectscheme-to-https
namespace: onlyoffice
spec:
redirectScheme:
scheme: https
permanent: true
---
# Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: onlyoffice-cert
namespace: onlyoffice
spec:
commonName: onlyoffice.air.alpha.grandlyon.com
secretName: onlyoffice-cert
dnsNames:
- onlyoffice.air.alpha.grandlyon.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
# Namespace
apiVersion: v1
kind: Namespace
metadata:
name: myapp
---
# Storage
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myapp-pvclaim
namespace: myapp
spec:
# storageClassName: scw-bssd-retain # need further tests to see if the default scw-bssd is enough for our use cases
accessModes:
- ReadWriteOnce # it's ok to read write from the pods for the same app
resources:
requests:
storage: 1Gi
---
# Application
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-webserver
namespace: myapp
spec:
selector:
matchLabels:
app: myapp-webserver
replicas: 2
template:
metadata:
labels:
app: myapp-webserver
spec:
volumes:
- name: myapp-webserver-volume
persistentVolumeClaim:
claimName: myapp-pvclaim
containers:
- name: myapp-webserver
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: myapp-webserver-volume
---
# Service
apiVersion: v1
kind: Service
metadata:
name: myapp-webserver-svc
namespace: myapp
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: myapp-webserver
---
# Ingress
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp-https
namespace: myapp
spec:
entryPoints:
- websecure
routes:
- match: Host(`myapp.air.alpha.grandlyon.com`)
kind: Rule
services:
- name: myapp-webserver-svc
port: 80
tls:
secretName: myapp-cert
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp-http
namespace: myapp
spec:
entryPoints:
- web
routes:
- match: Host(`myapp.air.alpha.grandlyon.com`)
kind: Rule
middlewares:
- name: svc-redirectscheme-to-https
services:
- name: myapp-webserver-svc
port: 80
---
# Middlewares
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: svc-redirectscheme-to-https
namespace: myapp
spec:
redirectScheme:
scheme: https
permanent: true
---
# Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: myapp-cert
namespace: myapp
spec:
commonName: myapp.air.alpha.grandlyon.com
secretName: myapp-cert
dnsNames:
- myapp.air.alpha.grandlyon.com
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: nicolas@alpha.grandlyon.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource used to store the account's private key.
name: issuer-account-key
# Add a single challenge solver, HTTP01
solvers:
- http01:
ingress:
class: traefik-cert-manager
apiVersion: v1
kind: Service
metadata:
name: traefik-ingress
namespace: kube-system
labels:
k8s.scw.cloud/ingress: traefik2
spec:
type: LoadBalancer
ports:
- port: 80
name: http
targetPort: 8000
- port: 443
name: https
targetPort: 8443
selector:
app.kubernetes.io/name: traefik
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment