Docker-nginxとphp-fpmを別々にスケーリングする


11

私はdockerとdocker-composeをいじくり回してきましたが、質問があります。

現在、私のdocker-compose.ymlは次のようになっています。

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

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

アプリには、ポート9000のphp-fpmとアプリケーションコードが含まれています。Webはnginxであり、設定は数ビットです。

これは、nginxをphp-fpmに接続するために私がそれを期待する方法を機能します:私はこの行を持っています:

fastcgi_pass    app:9000;

これを効果的にスケーリングするにはどうすればよいですか?たとえば、1つのnginxコンテナを実行し、3つのアプリコンテナを実行したい場合、3つのphp-fpmインスタンスがすべてポート9000でリッスンしようとします。

php-fpmの各インスタンスを異なるポートに配置し、どの時点でもnginx構成のどこにあるのかを知るにはどうすればよいですか?

私は間違ったアプローチを取っていますか?

ありがとう!

回答:


5

1つの解決策は、追加のphp-fpmインスタンスをdocker-composeファイルに追加し、他の回答で説明したようにnginxアップストリームを使用してそれらの間の負荷分散を行うことです。これは、この例の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;
}

スケールアップまたはスケールダウンしたい場合、nginx configとdocker-compose.ymlを変更する必要があるため、これはあまり理想的ではありません。

9000ポートは実際のホストではなくコンテナの内部にあるため、ポート9000に複数のphp-fpmコンテナがあることは重要ではありません。

Dockerはこの秋にTutumを買収しました。HAProxyコンテナとAPIを組み合わせて、ロードバランサの構成を、ロードバランシングを実行している実行中のコンテナに自動的に調整するソリューションがあります。それは素晴らしい解決策です。次に、nginxはロードバランサーに割り当てられたホスト名を指します。おそらく、DockerはTutumの買収に続いて、このタイプのソリューションを自社のツールにさらに統合するでしょう。それについての記事がここにあります:https : //web.archive.org/web/20160628133445/https : //support.tutum.co/support/solutions/articles/5000050235-load-balancing-a-web-service

Tutumは現在、有料サービスです。Rancherは、同様の負荷分散機能を提供するオープンソースプロジェクトです。また、docker-compose.ymlで設定されたサービスの負荷分散とスケーリングを定義できる「rancher-compose.yml」もあります。 http://rancher.com/the-magical-moment-when-container-load-balancing-meets-service-discovery/ http://docs.rancher.com/rancher/concepts/#load-balancer

更新2017/03/06:Docker と連動するインターロックと呼ばれるプロジェクトを使用して、nginx構成を自動的に更新し、再起動しました。@iwaseatenbyagrueの回答も参照してください。追加のアプローチがあります。



0

Nginxコンテナーとphp-fpmコンテナーが同じホスト上にある場合、Nginxコンテナーが使用するホスト上に小さなdnsmasqインスタンスを構成し、コンテナーのIPアドレスがあるときに自動的にDNSレコードを更新するスクリプトを実行できますかわった。

私が書いた小さなスクリプト自動的にコンテナの名前やコンテナへのポイントにそれらのIPアドレスと同じ名前を持つDNSレコードを更新し、これを(下の貼り付け)を行うには、:

#!/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

次に、でnginxコンテナを起動します--dns host-ip-address。ここhost-ip-addressで、はインターフェイス上のホストのIPアドレスですdocker0

あなたのnginxの構成が動的に名前を解決する必要があります。

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;
  }
}

参照:

nginxとphp-fpmが異なるホストにある場合は、@ smajの答えを試すことができます。


0

別のアプローチは、consul-templateのようなものを調べることです。

そしてもちろん、ある時点でKubernetesに言及する必要があるかもしれません。

ただし、消費するdockerイベントがあなたに何をすることができるかを調べることで、もう少し「ストリングとダクトテープのビット」アプローチを検討することができます(docker events --since 0クイックサンプルを実行します)。

これらのイベントを調べるスクリプト(Python、goなどを含むいくつかのクライアントパッケージがあることを念頭に置いて)、構成ファイルの修正、nginxの再読み込み(consul-templateアプローチの使用など)しかし、領事の必要はありません)。

ただし、元の前提に戻るには:php-fpmコンテナーが独自のネットワークで開始されている限り(つまり、nginxコンテナーなどの別のコンテナーのコンテナーを共有していない場合)、ポートでリッスンしているコンテナーをいくつでも持つことができます必要に応じて9000-コンテナごとのIPがあるため、ポートが「クラッシュ」しても問題はありません。

これをどのようにスケーリングするかは、最終的な目標/ユースケースに依存する可能性がありますが、考慮することができるのは、nginxとphp-fpmノードの間にHAproxyを配置することです。これでできることの1つdocker networkは、php-fpmサーバー(172.18.0.0/24など)の範囲を指定し(場合によってはを作成し)、その範囲内のIPをバックエンドとして使用するようにHAproxyを構成することです。 。HAproxyにはヘルスチェックがあるため、どのアドレスがライブであるかを迅速に識別し、それらを利用できます。

nginxとhaproxyがアップストリームを処理する方法については、https: //stackoverflow.com/questions/1358198/nginx-removing-upstream-servers-from-poolを参照してください

このために専用のdockerネットワークを使用していない限り、php-fpmノードのIP管理を手動で行う必要ある場合あります。


0

この投稿は2015年のものであり、私は壊していると感じています(申し訳ありませんがコミュニティ)、この時点で追加することは価値があると感じています:

最近(およびKubernetesが言及されたため)Dockerを使用している場合、KubernetesまたはDocker Swarmを非常に簡単に使用してこの問題を解決できます。両方のオーケストレーターは、ドッカーノード(1ノード= Dockerを搭載した1台のサーバー)を取り込み、それらにサービスを展開でき、オーバーレイネットワークを使用してポートの課題を管理します。

私はDocker Swarmに精通しているので、この問題に取り組むためにこれを行う方法は次のとおりです(単一のDockerノードがある場合)。

swarmを初期化します:

docker swarm init

プロジェクトルートにcd

cd some/project/root

(docker-composeを使用する代わりに)docker-compose.ymlからswarmスタックを作成します:

docker stack deploy -c docker-compose.yml myApp

これにより、「myApp」という名前のdocker swarmサービススタックが作成され、ポートが管理されます。つまり、1つの「port:9000:9000」定義をdocker-composeファイルのphp-fpmサービスに追加するだけで、その後、swarmが3つのインスタンスに対してphp-fpmサービスをスケールアップできます。これ以上の作業を必要とせずに、3つのインスタンス間でリクエストを自動的にロードバランシングします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.