
これまで、多くの企業で展開すると大きな問題が発生し、数日、数週間、特に無視された場合は数か月かかることがあります。 しかし、状況は絶望的ではありません。 この困難な作業に役立つツールと実践が数多くあります。 しかし、これらのツールはほとんどの場合1〜2日で習得されず、締め切りが迫っています。
あなたは通常何が欲しいですか:
- 開発者のマシンでプロジェクトをローカルで解除する機会。 すべてまたは少なくとも一部。 そして、最小限のパラメーターでDev構成をProdと異なるようにしたいのです。 これにより、「私のマシンで作業する」バグを回避できます。 とにかく、ある開発者がOS Xで、別の開発者がWindowsで、Debianで本番環境で作業し、トラブルを待つ場合、これは誰もが環境を設定する作業を行っているという事実をカウントしません。
- コンソールのいくつかのコマンドで、任意のマシンとOSにDev構成をデプロイしたい。 これにより、バグの「マイマシンでの作業」要因が減少します。 また、最短時間で他の開発者をプロジェクトに引き付けることもできます(浮浪者になりましょう)。
- 構成は、プログラマーと管理者の両方にとって明確でなければなりません。
これはすべて、Djangoプロジェクトの例について、Salt + Vagrantの束で実現します。 しかし、Pythonだけでなく他の言語でも、ほとんどの手法は開発者に役立ちます。
ソースへのリンクをすぐに提供します: bitbucket.org/awnion/salt-django-deploy
ソルトとは?
Saltに精通している場合は、このセクションをスキップできます。
Saltはクラスター管理(クラスターオーケストレーション)のための非常に強力なツールですが、私の個人的な意見では、1台のマシンで使用しても十分に正当化され、過剰になりません(大まかに言うと、チームに1人の開発者しかいなければ、これは使用すべきではありませんバージョン管理システム)。
ソルト状態は、マシンがどの状態にあるべきかを記述するsls拡張子を持つYAMLファイルです。 たとえば、このファイルはここにある必要があり、このサービスは起動されている必要があり、このユーザーはそのような権限を持っている必要があります。 Saltでは、システムユーティリティ(apt、rpm、cron、initスクリプト、さまざまな構成)の状態を維持できるだけでなく、たとえば、そのようなユーザーがRabbitMQに存在するかどうか、最新バージョンのgitリポジトリ、すべてのパッケージが存在するかどうかを確認できますvirtualenvなど。 条件の完全なリストは、ここdocs.saltstack.com/ref/states/allにあり、私の意見では非常に印象的です。
塩に関するいくつかの事実
- Saltは、設定ファイルおよび状態ファイルのテンプレート言語としてJinjaを使用します。 それは信じられないほど便利で、設定でもDRYをフォローできます。
- ソルトは、すでにApple、NASA、LinkedInなどの企業で使用されています。
- SaltはPythonで書かれていますが、使用するためにPythonを知っている必要はありません。
- SaltのPDFドキュメントは約1000ページで、非常にしっかりと書かれています。 ここには、APIの説明だけでなく、使用方法と例もあります。
開発設定
私の意見では、優れた便利な開発環境の重要性を過大評価することは困難です。 ただし、「すべてを自分用に」設定するには、数日または1週間かかる場合があります。 これらの日を将来同僚に保存し、1つのコマンドでプロジェクトの現在のバージョンを上げることができる構成を作成しましょう。
git clone <repo_url> && cd <repo_name> && vagrant up
さて、これは実際には3つのチームですが、もっと簡単にできるなら-私はあなたの手を振る。
したがって、 Vagrantで dev構成を構築します(Vagrantに精通していない人のために、お会いすることを強くお勧めします)。
mkdir my_app && cd my_app git init vagrant init
Vagrantのgitリポジトリと設定がmy_appフォルダーに表示されました。
次に、 Vagrantfileの内容を次のものに置き換えます。
Vagrant.configure("2") do |config| config.vm.box = "precise64" config.vm.hostname = "dev-my-app" config.vm.network :private_network, ip: '3.3.3.3' config.vm.synced_folder "salt/roots/salt", "/srv/salt/" config.vm.synced_folder "salt/roots/pillar", "/srv/pillar/" config.vm.provision :salt do |salt| salt.minion_config = "salt/minion" salt.run_highstate = true end end
この構成では、Ubuntuでゲストマシンを作成できます。ホスト名とIPを設定する構成で、どのフォルダーを同期するかを決定し、saltを使用してマシンを目的の状態にすることを示しました(ところで、プロジェクトのルートはデフォルトになりますゲストマシンの/ vagrantフォルダーと同期されます)。
ここで何が起こっているかについて詳しく知ることができます。
これで、状態を説明する準備が整いました。 次の内容のソルト/ミニオンファイルを作成します。
file_client: local
実際、このマシンはその状態自体を保存すると言います。 デフォルトでは、saltはマスターサーバーから状態ファイルを取得するように構成され、ローカルでは/ var / cache / saltのどこかにのみキャッシュします。 したがって、カスタムが必要ない場合は、prodマシン上のこのファイルはほとんど必要ありません。
次に、2つのフォルダーを作成します。
mkdir -p salt/roots/pillar mkdir -p salt/roots/salt
最初の変数はさまざまな変数を格納し、2番目の変数はゲストマシンの状態フォルダーです。
ファイルsalt / roots / salt / top.slsを作成します
base: 'dev-my-app': - nginx - python - supervisor
ご想像のとおり、slsはyamlに非常に似ています。 しかし、ここでの主な違いは、slsはすべての結果を伴うjinjaテンプレートでもあることです(後で実際にメリットがあることがわかります)。
baseは、仮想クラスターの状態構成の名前です。 dev-my-appは、ゲストマシンのホスト名です。 ここでは、パターンマッチングが使用されます。つまり、「dev- *」を指定できます。以下のすべての状態は、dev-alpha、dev-foobarなどのすべてのマシンに適用されます。 以下は、説明する必要がある州のリストです。
python、nginx、supervisorの宣言された状態を作成します。
salt / roots / salt / python.sls
# , python python-virtualenv # , -- python: pkg: - installed - names: - python - python-virtualenv
salt / roots / salt / nginx.sls
# nginx , require # , service pkg nginx: pkg: - installed service: - running - reload: True # reload - require: - pkg: nginx
salt / roots / salt / Supervisor.sls
supervisor: pkg: - installed service: - running - require: - pkg: supervisor
そのため、「 vagrant up 」をすでに実行できます。 この手順では、Ubuntuイメージをダウンロードし(イメージキャッシュにまだない場合)、そこにsaltをインストールし、状態の同期を開始します。
これで、ゲストマシンにpython、supervisor、nginxができました。
vagrant sshを介してマシンにアクセスするか、 3.3.3.3にアクセスして確認できます。
これまでのところ、すべてがシンプルに思えます。 続ける:
柱変数を作成します。
塩/根/柱/top.sls
base: 'dev-my-app': - my-app
塩/根/柱/ my-app.sls
my_app: gunicorn_bind: 127.0.0.1:8000 dns_name: dev.my-app.com venv_dir: /home/vagrant/my_app_env work_dir: /vagrant
最初のファイルは、dev-my-appホストにmy-app configから変数が割り当てられていることを示しています。 2番目のファイルは、実際の変数そのものです。
次に、Djangoアプリケーションの構成状態用のフォルダーを作成します。
mkdir -p salt/roots/salt/my_app
salt / roots / salt / my_app / init.sls
{% set my_app = pillar['my_app'] %} my_app.venv: virtualenv.managed: - name: {{ my_app['venv_dir'] }} - system_site_packages: False - require: - pkg: python my_app.pip: pip.installed: - bin_env: {{ my_app['venv_dir'] }} - names: - Django==1.6 - gunicorn==18.0 - require: - virtualenv: my_app.venv my_app.nginx.conf: file.managed: - name: /etc/nginx/sites-enabled/my_app.conf - source: salt://my_app/nginx.my_app.conf - context: # pillar, bind: {{ my_app['gunicorn_bind'] }} dns_name: {{ my_app['dns_name'] }} - template: jinja - makedirs: True - watch_in: - service: nginx my_app.supervisor.conf: file.managed: - name: /etc/supervisor/conf.d/my_app.conf - source: salt://my_app/supervisor.my_app.conf - context: app_name: my_app bind: {{ my_app['gunicorn_bind'] }} gunicorn: {{ my_app['venv_dir'] }}/bin/gunicorn directory: {{ my_app['work_dir'] }} workers: {{ grains['num_cpus'] * 2 + 1 }} # - template: jinja - makedirs: True my_app.supervisor: supervisord.running: - name: my_app - watch: - file: my_app.supervisor.conf - require: - pip: my_app.pip - pkg: supervisor
ヒント :依存関係、require、watchなどを構築する場合、状態はランダムな順序でチェックされることに注意してください。 この記事を作成するとき、私はこの種の間違いを犯しました。djangoおよびgunicornパッケージは、まだ作成されていないvirtualenvにインストールしようとしました。
salt / roots / salt / my_app / nginx.my_app.conf
server { listen 80; server_name {{ dns_name }} _; location / { proxy_pass http://{{ bind }}; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
salt / roots / salt / my_app / supervisor.my_app.conf
[program:{{ app_name }}] command={{ gunicorn }} {{ app_name }}.wsgi:application -b {{ bind }} -w {{ workers }} directory={{ directory }} user=nobody autostart=true autorestart=true redirect_stderr=true
新しく作成された状態をsalt / roots / salt / top.slsに追加します
base: 'dev-my-app': - nginx - python - supervisor - my_app # <----
ほぼ完了です。 しかし、最も重要なことはありません-架空のDjangoアプリケーションのコードです。 次のように空のテストDjangoプロジェクトを作成しましょう。
vagrant provision
このプロセスには数分かかります(ほとんどの場合、djangoとgunicornはvirtualenvにインストールされます)。
プロビジョニングが機能したら、ゲストマシンに移動します。
vagrant ssh
内部では次のことを行います。
/home/vagrant/my_app_env/bin/django-admin.py startproject my_app /vagrant exit
また、ホストマシンでvagrant provisionを実行し、hostsファイルですべてが機能することを確認するために、一時的にメモします。
dev.my-app.com 3.3.3.3
ブラウザーでdev.my-app.comにアクセスすると、すべてがうまくいけば、うまくいきました!
開発構成が構築されます。 コミットできます。
友人にプロジェクトで遊びを与えたい場合、彼はgit cloneとvagrant upを行うだけです。 さらに、この架空の友人は、プロジェクト自体のソースコードを受け取るだけでなく、それがどのように展開されるかについてのアイデアも持っています。
とりわけ、デフォルトでは、プロジェクトはgunicorn +スーパーバイザーの制御下で独立してスピンします。 しかし、リモートでリモートにしたい場合や、お気に入りのオートリロードコードの変更を返したい場合はどうでしょうか? 質問なし:
vagrant ssh supervisorctl stop my_app /home/vagrant/my_app_env/bin/python /vagrant/manage.py runserver
これでコードを安全に編集でき、すべての変更がdjangoサーバーに自動的に反映されます。
また、ホストが一時的に調整されている場合、同じdjangoサーバーがdev.my-app.comからのリクエストに応答します。
製品構成
それで、最も重要なことに到達しました。 prod-my-appにデプロイすることを想定しています。
次に、salt-master(以下、単にマスター)用に別のサーバーがある状況での展開オプションを検討します。
マスター構成にコピーし、 / srv / salt / top.slsに追加します
'prod-my-app': - nginx - python - supervisor - my_app
または、私たちの場合、これを行うことができます:
base: '*-my-app': - nginx - python - supervisor - my_app
次に、 / srv / pillar / top.slsファイルで同じことを行います
base: '*-my-app': - my-app
/srv/pillar/my_app.slsでは 、レイアウトマップに従って変数を変更します。
prod-my-appでsalt-minionを設定します。 ソルトミニオンをソルトマスターに接続します (実行方法はこちらをご覧ください)。
ウィザードで、構成のアプリケーションを開始できます。
sudo salt prod-my-app state.highstate
残っているもの:
マスターへの構成の配信
rsyncからgitへの方法はたくさんあります。 それはすべてあなたの国内政策に依存します。
prod-my-appへのプロジェクトソースの配信
ここでも、多くのオプションがあります。 個人的には、私はこれを行います:saltをprod-my-appでサポートし、ハッシュがピラーに保存されている特定のコミットでgitリポジトリをサポートします。変更された場合、saltは作業の最後にデプロイメントスクリプトを実行します。
正直なところ、これは最良の方法ではありませんが、最も簡単な方法です。 理想的には、たとえばネイティブパッケージを作成するか、プライベートpypiを作成します。
参照資料
www.saltstack.com
www.vagrantup.com
hynek.me/talks/python-deploymentsは、Pythonプロジェクトのデプロイメントに関する要約のセットを含む非常に役立つ記事です。
PS
残念なことに、多くのことを逃さなければなりませんでした。さもないと、記事が途方もなく大きなサイズに膨らんでしまいます。 明らかなもの、またはドキュメントで見つけやすいものを見逃そうとしました。 ただし、コメントで質問してください。