Question Docker - mise à l'échelle de nginx et php-fpm séparément


J'ai joué avec docker et docker-compos et j'ai une question.

Actuellement, mon fichier docker-compose.yml ressemble à ceci:

app:
    image: myname/php-app
    volumes:
        - /var/www
    environment:
        <SYMFONY_ENVIRONMENT>: dev

web:
    image: myname/nginx
    ports:
        - 80
    links:
        - app
    volumes_from:
        - app

L'application contient php-fpm sur le port 9000 et mon code d'application. Web est nginx avec quelques éléments de configuration.

Cela fonctionne comme je l’attendais cependant pour connecter nginx à php-fpm, j’ai cette ligne:

fastcgi_pass    app:9000;

Comment puis-je réduire cela efficacement? Si je voulais, par exemple, avoir un conteneur nginx en cours d'exécution mais trois conteneurs d'applications en cours d'exécution, je vais sûrement avoir trois instances php-fpm essayant toutes d'écouter sur le port 9000.

Comment puis-je avoir chaque instance de php-fpm sur un port différent, tout en sachant où elles se trouvent dans ma configuration nginx à un moment donné?

Est-ce que je prends la mauvaise approche?

Merci!


9
2018-05-21 08:26


origine




Réponses:


Une solution consiste à ajouter des instances php-fpm supplémentaires à votre fichier docker-compose, puis à utiliser un nginx en amont, comme indiqué dans les autres réponses, pour équilibrer la charge entre elles. Ceci est fait dans cet exemple de rapport docker-compose: https://github.com/iamyojimbo/docker-nginx-php-fpm/blob/master/nginx/nginx.conf#L137

upstream php {
    #If there's no directive here, then use round_robin.
    #least_conn;
    server dockernginxphpfpm_php1_1:9000;
    server dockernginxphpfpm_php2_1:9000;
    server dockernginxphpfpm_php3_1:9000;
}

Ce n'est pas vraiment idéal car cela nécessitera de changer les configurations nginx config et docker-compose.yml lorsque vous souhaitez augmenter ou réduire la taille.

Notez que le port 9000 est interne au conteneur et non à votre hôte réel; il n’importe donc pas que vous ayez plusieurs conteneurs php-fpm sur le port 9000.

Docker a acquis Tutum cet automne. Ils ont une solution qui combine un conteneur HAProxy avec leur API pour ajuster automatiquement la configuration de l’équilibreur de charge aux conteneurs en cours d’équilibrage de charge. C'est une bonne solution. Ensuite, nginx pointe vers le nom d’hôte attribué à l’équilibreur de charge. Docker intégrera peut-être davantage ce type de solution dans leurs outils après l’acquisition de Tutum. Il y a un article à ce sujet ici: https://web.archive.org/web/20160628133445/https://support.tutum.co/support/solutions/articles/5000050235-load-balancing-a-web-service

Tutum est actuellement un service payant. Rancher est un projet open source qui fournit une fonctionnalité d’équilibrage de charge similaire. Ils ont également un "rancher-compose.yml" qui peut définir l’équilibrage de la charge et la mise à l’échelle de la configuration des services dans le fichier docker-compose.yml. http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer 

UPDATE 2017/03/06: J'ai utilisé un projet appelé emboîtement cela fonctionne avec Docker pour mettre à jour automatiquement la configuration de nginx et le redémarrer. Voir aussi @ iwaseatenbyagrue's réponse qui a des approches supplémentaires.


5
2017-12-02 21:09





Vous pouvez utiliser un amont pour définir plusieurs moteurs, comme décrit ici:

https://stackoverflow.com/questions/5467921/how-to-use-fastcgi-next-upstream-in-nginx

Vous voudriez également que la configuration soit mise à jour chaque fois que de nouveaux serveurs meurent / entrent en service avec quelque chose comme:

https://github.com/kelseyhightower/confd


1
2018-05-21 08:41





Dans le cas où vos conteneurs Nginx et php-fpm sont sur le même hôte, vous pouvez configurer un petit Dnsmasq instance sur l’hôte à utiliser par le conteneur Nginx et exécutez un script pour mettre à jour automatiquement l’enregistrement DNS lorsque l’adresse IP du conteneur a été modifiée.

j'ai écris un petit script faire ceci (collé ci-dessous), qui met automatiquement à jour l'enregistrement DNS qui porte le même nom que le nom du conteneur et le dirige vers les adresses IP des conteneurs:

#!/bin/bash

# 10 seconds interval time by default
INTERVAL=${INTERVAL:-10}

# dnsmasq config directory
DNSMASQ_CONFIG=${DNSMASQ_CONFIG:-.}

# commands used in this script
DOCKER=${DOCKER:-docker}
SLEEP=${SLEEP:-sleep}
TAIL=${TAIL:-tail}

declare -A service_map

while true
do
    changed=false
    while read line
    do
        name=${line##* }
        ip=$(${DOCKER} inspect --format '{{.NetworkSettings.IPAddress}}' $name)
        if [ -z ${service_map[$name]} ] || [ ${service_map[$name]} != $ip ] # IP addr changed
        then
            service_map[$name]=$ip
            # write to file
            echo $name has a new IP Address $ip >&2
            echo "host-record=$name,$ip"  > "${DNSMASQ_CONFIG}/docker-$name"
            changed=true
        fi
    done < <(${DOCKER} ps | ${TAIL} -n +2)

    # a change of IP address occured, restart dnsmasq
    if [ $changed = true ]
    then
        systemctl restart dnsmasq
    fi

    ${SLEEP} $INTERVAL
done

Ensuite, démarrez votre conteneur nginx avec --dns host-ip-address, où host-ip-address est l'adresse IP de l'hôte sur l'interface docker0.

Votre Configuration de Nginx devrait résoudre les noms dynamiquement:

server {
  resolver host-ip-address;
  listen 80;
  server_name @server_name@;
  root /var/www/@root@;
  index index.html index.htm index.php;

  location ~ ^(.+?\.php)(/.*)?$ {
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$1;
    set $backend "@fastcgi_server@";
    fastcgi_pass $backend;
  }
}

Références:

Si votre nginx et php-fpm sont sur des hôtes différents, vous pouvez essayer la réponse de @ smaj.


0
2018-05-21 21:00





Une autre approche pourrait consister à examiner quelque chose comme consul-template.

Et bien sûr, à un moment donné, Kubernetes peut avoir besoin d'être mentionné.

Cependant, vous pouvez envisager une approche légèrement plus «ficelle et ruban adhésif» en examinant ce que les événements liés au menu fixe pourraient faire pour vous (exécuter docker events --since 0 pour un échantillon rapide).

Il serait relativement simple de disposer d’un script examinant ces événements (en gardant à l’esprit plusieurs packages clients disponibles, notamment pour python, go, etc.), modifier un fichier de configuration et recharger nginx (en utilisant l’approche consul-template, mais sans la nécessité d'un consul).

Pour revenir à votre prémisse d'origine, cependant: tant que vos conteneurs php-fpm sont démarrés avec leur propre réseau (c'est-à-dire ne partageant pas celui d'un autre conteneur, tel que celui de nginx), vous pouvez avoir autant de conteneurs à l'écoute sur le port. 9000 comme vous voulez - comme ils ont des IPs par conteneur, il n'y a pas de problème avec les ports 'en conflit'.

Votre mise à l'échelle dépendra probablement de votre objectif ultime / cas d'utilisation, mais envisagez de placer HAproxy entre nginx et vos nœuds php-fpm. Une chose que cela pourrait vous permettre est simplement de nommer une plage (et éventuellement de créer une docker network) pour vos serveurs php-fpm (c’est-à-dire 172.18.0.0/24) et que HAproxy soit configuré pour essayer d’utiliser toute adresse IP comprise dans cette plage en tant que serveur principal. Puisque HAproxy a des contrôles de santé, il peut rapidement identifier les adresses actives et les utiliser.

Voir https://stackoverflow.com/questions/1358198/nginx-removing-upstream-servers-from-pool pour une discussion sur la façon dont nginx vs haproxy traite les amonts.

Sauf si vous utilisiez un réseau de dockers dédié à cet effet, vous pourrait besoin de faire de la gestion IP manuelle pour vos nœuds php-fpm.


0
2018-03-03 08:35