Self managed Kubernetes avec Nginx Ingress

Posted by

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

Leave a Reply

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *