nginx、docker、skydns、skydockを使用してコードをオンザフライで更新します(ゼロダウンタイム展開)

使用するツール



Docker



Dockerは、相互に分離された軽量の仮想コンテナを作成するためのシンプルでエレガントなライブラリであり、任意のコードを実行できます。 絶対にリソースを必要とする、最小限のオーバーヘッド。



コンテナを一度収集すると、再利用できます。



簡単な例は、Redisデータベースです。 同じコンピューター上に複数のRedisサーバーが必要な場合、通常のアプローチでは、/ etc / redisの構成ファイルを変更し、/ etc / init.dのファイルを変更する必要があります。 bashスクリプトを作成できますが、これによりプロセスが簡単になるわけではありません。



Dockerの場合、次のコマンドを使用できます。



docker run -d --name test-redis-server dockerfile/redis
      
      





このコマンドは、メインリポジトリ( index.docker.io )からRedisコンテナーをダウンロードし、バックグラウンドで実行し、新しく作成されたコンテナーにtest-redis-serverという名前を付けます。



このコンテナは次のコマンドで起動できます:



 docker start test-redis-server
      
      





Skydns



最近では、Docker開発者は、コンテナを起動するときに--linkツールを導入して、ENV環境変数を使用して複数のコンテナをリンクできるようにしました。 たとえば、WebアプリケーションコンテナーをRedis、Postgresql、Elasticsearchなどのコンテナーに関連付けるには



これは便利ですが、コンテナの起動条件と--linkパラメータを変更する場合は、ENVの正確さを監視し、コードを変更する必要があります。



これはサービスディスカバリーと呼ばれ、多くのソリューションがあります(既存のソリューションの詳細については、 オープンソースのサービスディスカバリーの記事をご覧ください)。



そのようなソリューションの1つがSkyDNSです。 Goで書かれた小さなローカルDNSおよびDNSプロキシサーバー(Goはリソース消費の観点から非常に効率的であり、起動時に最大約6MBのメモリを消費することに注意することが重要です。約20MB)。



SkyDNSでは、単純なAPI(より詳細にはSkyDNS )を使用してDNSレコードを追加し、SRV、AまたはAAAAレコードを返す定期的なクエリを作成できます。



レコードが見つからない場合、SkyDNSはGoogleのパブリックDNSサーバー(8.8.8.8/8.8.4.4)にリクエストを送信します。



SkyDNSは、ドメインに対して独自の興味深いスキームを使用します。



 <uuid>.<host>.<region>.<version>.<service>.<environment>.skydns.local
      
      





環境=本番、サービス= redisの場合、redis.production.skydns.localにリクエストを送信すると 、1つ以上のレコードが返されます(デフォルトではAレコードが返されます)。



スカイドック



Skydockは、DockerとSkyDNSを統合する小さなプログラムです。



Skydockは次のようにSkyDNSドメインスキーマを使用します。



 <name>.<container-name>.<environment>.skydns.local
      
      





container-nameは、リポジトリのないDockerイメージの名前です(例:crosbymichael / redis => redisまたはtest / cool-api => cool-api)。 nameは、-nameパラメーターを使用して割り当てられたコンテナーの名前です。



Skydockは、実行中のコンテナーを自動的に検出し、SkyDNSに追加します。



Dockerは各コンテナに個別のIPアドレスを割り当てるため、次のようにコンテナを起動すると:



 docker run -d --name redis-test-app dockerfile/redis
      
      





要求を作成し(後で172.17.42.1を要求する理由を説明します)、応答でAレコード、つまりRedisが実行されているコンテナのIPアドレスを取得できます。



 dig @172.17.42.1 redis-test-app.redis.dev.skydns.local dev.skydns.local. 27 IN A 172.17.0.3
      
      





デフォルトのRedisポートは6379であるため、コードで次のようなことができます(疑似言語の例):



 redisConn = redis.Connect("redis-test-app.redis.dev.skydns.local:6379")
      
      





設置



Dockerのインストールは検討しません。非常に簡単で、ここで詳しく説明します: Dockerの使用を開始する



SkyDNSを使用するコンテナとSkydockを使用するコンテナの2つのコンテナを起動する必要があります。 Skydockの作成者とは異なり、追加パラメーター-p 172.17.42.1:8080:8080を使用してSkyDNSを開始することをお勧めします。これにより、コンテナーは自分のニーズに合わせてSkyDNS APIを直接使用できます。



 docker pull crosbymichael/skydns docker run -d -p 172.17.42.1:53:53/udp -p 172.17.42.1:8080:8080 --name skydns crosbymichael/skydns -nameserver 8.8.8.8:53 -domain skydns.local
      
      





IP 172.17.42.1は、Dockerが独自のネットワークを構成するために使用するdocker0ブリッジです。 skydns.localドメインを指定しましたが、たとえばdocker、super.localなど、任意の選択を行うことができます。 私の意見では、skydns.localはより便利で普遍的であり、SkyDNSでデフォルトでさらに使用されています。



次に、Skydockを起動します。



 docker pull crosbymichael/skydock docker run -d -v /var/run/docker.sock:/docker.sock --name skydock -link skydns:skydns crosbymichael/skydock -ttl 30 -environment dev -s /docker.sock -domain skydns.local
      
      







ここで、TTLを指定する必要があります(小さい場合-より動的な環境であれば、アーキテクチャをより速く変更できます。より-動的でない、よりキャッシュされた環境)および環境-これは絶対に任意の行(dev、development、production、stage、qa )



すべてがうまくいった場合、必要なすべてのコンポーネントが実行されています。



必要なことは、アプリケーションでコンテナを起動するときだけです。プライマリDNSサーバーを指定する必要があります。



 docker run -d --dns 172.17.42.1 test/cool-api
      
      





cool-apiのコンテナは、 cool-api.dev.skydns.localのローカルDNSで利用可能になります-これにより、cool-apiという名前のすべてのコンテナのIPアドレスが一覧表示されます。 このプロパティを使用して、nginxを構成します。



コンテナの起動時に--name api1を指定すると、 api1.cool-api.dev.skydns.localで使用可能になります-api1という名前のコンテナが1 だけです。



コンテナー内では、ローカルDNSを使用するため、ドメインを直接指定できるようになりました: redis.dev.skydns.local -Redisを実行しているすべてのコンテナーのAレコードを返します。 当然、Redisクライアントが接続するアドレスは1つだけ選択されます。



nginx



このローカルDNSの魔法を使用して、たとえば次のことができます。





次の構成ファイルをnginxに追加します。



 server { listen 80; server_name super-cool-domain.com; #  nginx  SkyDNS resolver 172.17.42.1 valid=5s; resolver_timeout 5s; #      ,  nginx   DNS. - nginx   set $dns cool-api.production.skydns.local; location /api { proxy_pass http://$dns:8080; } #    location / { try_files $uri /index.html; } }
      
      





nginxがローカルDNSサーバーを使用するように指定し、次にどこに行くか-$ dns変数を指定し、アプリケーションが使用するポートに古き良きproxy_passを実行します。



現在、新しいコンテナを開始すると、SkydockはそれをSkyDNSに追加し、nginxはこのコンテナにリクエストをプロキシします。 コンテナが停止すると、SkydockはそのアドレスをSkyDNSから削除します。



この方法で2〜3個のコンテナを起動することにより、コンテナ間の負荷を分散できます。



いくつかの追加のコンテナを開始しましょう。nginxは自動的にそれらへのリクエストのプロキシを開始します。 その後、古いものの作業を停止することができます-それにより、その場で更新を行います。



これは再構成を必要としません。 すべてがデフォルトで機能します。 基本的に、コードを変更するために必要なことは次のとおりです。



 #          docker pull test/cool-api #  ID   OLDPORTS=( `docker ps | grep cool-api | awk '{print $1}'` ) #    docker run -d test/cool-api #   for i in ${OLDPORTS[@]} do echo "removing old container $i" docker kill $i done
      
      





おわりに



Skydockの作成者は、このアイデアを開発し、データセンター内の複数のサーバーをサポートしたいと考えています。 現時点では、これは実装されていませんが、SkyDNS自体はすでに多くのサーバーの運用環境で使用されています。



この記事では、Dockerリポジトリーのトピックについても取り上げていません。 イメージのプライベートリポジトリを作成できるオープンソースソリューションがあります。



このソリューションはパフォーマンスにほとんど影響を与えません。DockerとSkyDNSは非常に適切に設計されており、効率的で高速なGo言語を使用しています。

一見、これはプロセスの複雑さのようですが、結果は非常に柔軟なソリューションであり、初期セットアップ後に追加で構成する必要はありません。



All Articles