Dans ce tutoriel nous allons avoir comment installer Nginx-Ingress sur un Kubernetes « self managed ». L’objectif est d’obtenir des fonctionnalités qui sont normalement réservées au Cloud mais sur une machine virtuelle ou un serveur dédié. Rien ne vous empêche de l’installer sur une Instance Cloud. Nous utiliserons Ubuntu comme base, les adaptations pour d’autres systèmes devraient être mineures.
Objectifs :
- Nginx Ingress
- Génération de certificats avec Let’s Encrypt
- Obtenir l’IP de nos visiteurs
Prérequis :
- Un système Ubuntu à jour
- Kubernetes, sur l’interface privée
- Une interface privée
- Helm3 installé
L’interface privée n’est pas forcément nécessaire, vous pouvez aussi ajouter une IP privée à votre interface principale. Ce réseau nous permettra de communiquer avec le Load Balancer.
Nous utiliserons 172.16.1.0/24 pour notre réseau privé et 172.16.1.250 pour le Load Balancer.
Le Reverse Proxy
Nous allons commencer par installer et configure Nginx en mode reverse Proxy. Il écoutera sur notre interface publique et redirigera le trafic sur le Load Balancer.
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
echo "deb http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install nginx
Configurons Nginx pour rediriger les requêtes, modifiez /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
gzip on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/json application/xml;
gzip_disable msie6;
server_tokens off;
}
stream {
server {
listen 80;
proxy_protocol on;
proxy_pass 172.16.1.250:80;
}
server {
listen 443;
proxy_protocol on;
proxy_pass 172.16.1.250:443;
}
}
N’oubliez pas de redémarrer Nginx.
service nginx restart
Configurer le Load Balancer
Metal-lb va faire tout le travail et nous permettra de communiquer avec l’Ingress. Creez le fichier metallb-config.yml, la partie default n’est pas nécessaire mais nous permettra d’avoir une autre IP de disponible pour le futur.
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 172.16.1.251/32
- name: nginx-ingress
protocol: layer2
addresses:
- 172.16.1.250/32
On crée tous les éléments
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.9.3/manifests/metallb.yaml
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
kubectl apply -f metallb-config.yml
Installer Nginx Ingress
Le controller recevra les connections depuis notre Reverse Proxy et les redirigera vers le service voulu. Créez le fichier nginx-config.yml.
apiVersion: v1
kind: Namespace
metadata:
name: nginx-ingress
labels:
name: nginx-ingress
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-ingress-controller
namespace: nginx-ingress
labels:
app.kubernetes.io/name: nginx-ingress
app.kubernetes.io/part-of: nginx-ingress
data:
proxy-protocol: "True"
use-proxy-protocol: "True"
real-ip-header: "proxy_protocol"
On installe Ingress controller
kubectl apply -f nginx-config.yml
helm repo add stable https://kubernetes-charts.storage.googleapis.com
helm install nginx-ingress stable/nginx-ingress --namespace nginx-ingress --set controller.service.externalTrafficPolicy=Local --set controller.service.annotations."metallb\.universe\.tf/address-pool"=nginx-ingress
Gestion des certificats
Nous utiliserons cert-manager. Créez le fichier cert-manager.yml.
---
global:
rbac:
create: true
leaderElection:
namespace: cert-manager
installCRDs: true
ingressShim:
defaultIssuerName: letsencrypt-prod
defaultIssuerKind: ClusterIssuer
Puis cluster-issuer.yml
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-stage
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: youremail@domain.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-stage
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
---
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: youremail@domain.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
On installe cert-manager, dans son propre namespace.
kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager --namespace cert-manager --values cert-manager.yml
kubectl apply -f cluster-issuer.yml
Conclusion
Nous avons maintenant un le support des Ingress et des objets de type LoadBalancer dans notre Kubernetes ainsi que la gestion automatique des certificats. Vous pouvez désormais créer vos objets de type Ingress et configurer vos services.
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
app.kubernetes.io/name: nginx-ingress
app.kubernetes.io/part-of: nginx-ingress
ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- yourhost.com
secretName: tls-secret
rules:
- host: "yourhost.com"
http:
paths:
- path: /
backend:
serviceName: yourservice
servicePort: 80