
したがって、Ansibleは、あらゆる複雑な自動化スクリプトを作成するための非常に柔軟で簡単なツールです。 シンプルな開発者環境として説明できるので、複数の環境(dev / stage / prod)を持つ大規模プロジェクトの複雑な構造です。
Ansibleで見たように、次の問題を解決できます。
- ソフトウェアのインストール/アンインストール。
- ソフトウェア構成;
- ユーザーの作成/削除。
- ユーザーのパスワード/キー制御。
- コンテナ/仮想マシンの作成/削除。
- ソフトウェアコードを展開します。
- さまざまなスクリプト/テストの実行。
Ansibleに慣れていない人へのコメント:
-プレイブック/ロールの作成を開始する前に、 Ansible-playbook 、 Ansible-roleのドキュメントを読み、 YAML構文の理解を学ぶ必要があります (これは非常に簡単です)。
-gitリポジトリで開発する方が良いこともすぐに言及する価値があります。そのため、githubでアカウントを取得したり、ローカルgit-repo(mercurial、svnなど)を開始したりしないでください。 gitの使用方法をまだ習得していないのであれば、今がその時です。
私の意見では、Ansibleは人形やシェフ(以前は両方を使用していました)よりもはるかにシンプルで「学習」しやすいですが、これらはわずかに異なる製品です。 イントロダクションに精通し、 モジュールインデックスを確認した後、あなたの人生をずっと楽にするプレイブックの作成をすでに始めることができます。
ssh pub-keyをサーバーに配布するためのプレイブックの例:
# file: keys.yml --- - hosts: app-servers tasks: - name: Set up authorized_keys for the backup user # , . authorized_key: user=backup key="{{ item }}" with_file: - keys/backup.pub ...
ansible-playbook playbooks/keys.yml
これはすべて明らかですが、次は何ですか?
拡張プロジェクト構造
n層アーキテクチャの多かれ少なかれ複雑なプロジェクトの構造を記述したい場合は、ロールごとにホストグループのリストをすぐに決定し、この図に基づいて、すべてのホストに共通のタスク(リポジトリの接続、ユーザーの作成など)を決定する必要がありますそして、どれがプライベートであるか(nginx、mysqlの設定、python venvの作成など)、これに基づいて、基本的な共通ロールから始めてロールを書き始め、徐々にプライベートロールに移行します。
拡張されたプロジェクト構造には次のものが含まれます。
- 変数(一般およびプライベート);
- プレイブック(スクリプト);
- ロール(構造化されたプレイブック);
- ホストグループのリスト(インベントリ)。
ホストグループのリスト(インベントリ)
複数の環境が必要な場合は、いくつかのインベントリファイルを作成する必要があります。デフォルトでは(debパッケージで)hostsファイル(/ etc / ansible / hosts)がansible.cfg構成で使用されます。 構成でインベントリへのパスを指定する必要はありません; -iスイッチで異なるファイルを指定できます。
役割またはプレイブックで説明されているロジックが異なる環境で同じように機能するように、すべての環境で同じ名前のグループを開始します。次に例を示します。
生産在庫
# file: production [app-servers:children] app-php-servers app-python-servers [app-php-servers] appserv-01.example.com appserv-03.example.com [app-python-servers] appserv-02.example.com appserv-04.example.com [db-servers] dbserv-[01:02].example.com [cdn] cdn-[01:03].example.com [app-servers:vars] env=PROD ansible_ssh_user=admin
在庫を開発する
# file: develop [app-servers:children] app-php-servers app-python-servers [app-php-servers] appserv-01.dev.example.com appserv-03.dev.example.com [app-python-servers] appserv-02.dev.example.com appserv-04.dev.example.com [db-servers] dbserv-[01:02].dev.example.com [cdn] cdn-[01:02].dev.example.com [app-servers:vars] env=DEV ansible_ssh_user=admin
この例からわかるように、グループには他のグループを含めることができます。また、インベントリで共通変数を直接宣言することもできます。
変数
ディレクトリ構造は次のようになります。
ansible/ # () - group_vars/ - all/ - common - secret - dev/ - common - secret - stage/ - common - secret - prod/ - common - secret # () - host_vars/ - appserv-01.example.com/ - common - secret - dbserv-01.example.com/ - common - secret - cdn-01.example.com/ - common - secret
各グループと各ホストは、異なるファイル(たとえば、共通、シークレット)に一連の変数を持つことができます。ディレクトリ内のファイルの名前はここでは基本的ではありません。主なことは、ディレクトリの名前が対応するインベントリ内の(グループまたはホストの)名前と一致することです。 グループまたは単一のホスト用のディレクトリを作成する必要はありません;ファイルを作成し、必要な変数をすべて書き込むことができます。 ただし、パスワードを暗号化された形式(ハッシュではなくパスワード)で、一般的な変数とは別に保存する場合は、上記の構造を取得する価値があります。これについては以下で説明します。
Ansible-vaultを使用した変数暗号化
グループ変数またはホスト変数のファイル(デフォルトAES256)と、原則として、秘密変数(パスワード、キーなど)を保存するファイルを暗号化するためのAnsible-vaultユーティリティ。 したがって、リポジトリにデータを保存することはできますが(パブリックでも、これは望ましくありませんが)、データの安全性について心配する必要はありません。
グループの名前でグループファイル(group_vars)にユーザーパスワードを保存するか、すべての環境に同じユーザーがいる場合はすべてを保存することは理にかなっています。
上記の構造では、暗号化された変数が保存されることになっている秘密ファイルを示しました。
ファイルを暗号化する:
ansible-vault encrypt host_vars/cdn-01.example.com/secret
暗号化されたファイルを編集します。
ansible-vault edit host_vars/cdn-01.example.com/secret
暗号化されたファイルを表示:
ansible-vault view host_vars/cdn-01.example.com/secret
もちろん、ファイルを暗号化および復号化するには、十分な長さのキーが必要であり、安全な場所(KeePassなど)に保存する必要があります。 プレイブックの実行中にファイルを自動的に復号化するには、 --vault-password-fileキーを指定するか、 ansible.cfg configを介してファイルへのパスを指定する必要があります。この場合、キーのセキュリティを管理し、それに必要な権限を設定する必要があります(0400 ) そしてもちろん、暗号化されたファイルと一緒にリポジトリに保存するべきではありません。
プレイブック
実行したいすべてのアクション(タスク)をプレイブックに記録することができます(10を超えないと言って、ファイルとテンプレートを使用しない場合)、ロールを使用する価値があります。
プレイブックでは、少なくとも以下を示す必要があります。
-ここでホストのターゲットグループ( hosts )は、マスク例外を設定できます(-hosts:app-servers :! App-04。*)、またはコロンを介したいくつかのグループ(-hosts:db-servers:cdn);
-アクション( タスク )またはロール( ロール )。
さらに、次を指定できます。
-ssh -connectのユーザー( remote_user );
-ユーザーsudo( become_user );
-特権エスカレーションを使用(true / falseになります);
-変数( vars )
-変数ファイル( vars_files )
-同時接続の数( serial )、1に設定されている場合、プレイブックは一度に1ホストずつ順番に実行されます。
役割
ロールは、タスク(タスク)のセット(少なくとも)と、さらにイベントハンドラー(ハンドラー)、変数(デフォルト)、ファイル(ファイル)、テンプレート(テンプレート)、および説明と依存関係(メタ)を含む構造化されたプレイブックです。
ロール構造を展開する
- deploy/ - defaults/ - main.yml - files/ - maintenance.html - handlers/ - main.yml - meta/ - main.yml - tasks/ - deploy.yml - main.yml - migrations.yml - tests.yml - templates/ - app_config.j2
デフォルト変数を持つファイル:
# file: deploy/defaults/main.yml --- branch_name: master mysql_host: localhost ...
ここでいくつかの一般的な設定を行うと非常に便利です。たとえば、localhostデータベースのデフォルトホストや、それぞれの環境に必要なホストを設定できるgroup_vars / host_varsです。
イベントハンドラファイル
# file: deploy/handlers/main.yml --- - name: reload uwsgi service: name=uwsgi state=reloaded - name: flush cache shell: redis-cli flushall ...
ハンドラーでは、特定のタスクの後に実行する必要のあるアクションを、絶対に指定できます(新しいコードのレイアウトまたは構成の変更)。
タスク記述ファイル
# file: deploy/tasks/main.yml --- - include: deploy.yml tags: - common - deploy - include: migrations.yml tags: - common - migrations - include: pytasks.yml when: "'app-python-servers' in group_names" tags: - common - pytasks - include: tests.yml tags: - tests ...
一部のタスクの実行に厳しい条件を設定できます。 上記の例では、条件を設定しました:
when: "'app-python-servers' in group_names"
つまり、タスクはapp_python-serversグループに属するホストに対してのみ実行されます。
ほとんどの場合、タグを使用して大きな役割を分解します。 上記のロールの例では、最初の2つのタスクに共通タグを設定し、最後のタスクのテストに別のタグを設定します。 最初の2つのタスクのみを実行する必要がある場合(つまり、コードをロールアウトする場合)、キー--tags common(または--skip-tagsテスト)でプレイブックを実行します。
ansible-playbook -i develop playbooks/deploy.yml --tags common
次に、テストを個別に実行できます(通常、完了するまでに長い時間がかかります)。--tagsテストを設定します。
ansible-playbook -i develop playbooks/deploy.yml --tags tests
パターン
テンプレートエンジンとして、Ansibleはすべての魅力を備えたjinja2を使用します。 変数を含むiniファイルとしての単純なuwsgi構成の例:
# {{ ansible_managed }} [uwsgi] chdir = {{ app_dir }}/{{ app_name }} home = {{ app_dir }}/{{ app_name }}/env master = True module = {{ app_name }}.wsgi:application chmod-socket = 660 uid = {{ web_user }} gid = {{ web_user }} processes = 8 listen = 256 max-requests = 100 buffer-size = 16384 vacuum = true env DJANGO_SETTINGS_MODULE = {{ env }}.settings {% if env is defined and env == DEV %} # Enable logging req-logger = file:/{{ logs_dir }}/{{ app_name }}/reqlog logger = file:/{{ logs_dir }}/{{ app_name }}/errlog {% endif %}
Ansible変数と組み合わせて、任意のjinja2トリックを使用できます。 例:
-ホストのみが特定のグループに属する行を設定(または特定のホストのみに行を設定)し、 loopを使用します 。
# file: iptables.j2 ... {% if (groups['cdn'] is defined and inventory_hostname in groups['cdn']) %} # Allows HTTP and HTTPS connections from anywhere {% for port in webs_ports %} -A INPUT -p tcp -m tcp --dport {{ port }} -j ACCEPT {% endfor %} {% endif %} ...
依存関係
ここでの依存関係とは、最終的な役割を果たす前に満たさなければならない他の役割を意味します-{role:role_name、var_name:value}の形式で、たとえば:
# file: deploy/meta/main.yml --- dependencies: - { role: base, apt_repo: us }
最終的な役割(たとえば、app-servers)に必要な依存関係をすべて指定したら、ターゲットホストグループと役割を指定するだけで十分なプレイブックを1つだけ作成できます。 そして、これはシステムを一貫した状態に維持するのに十分であり、例えば王冠でプレイブックを実行します。 特定の構成を適切に更新する必要がある場合は、タグが役立ちます。
定期的なビルドを行い、その実行を制御するか、単に開発者に「ボタン」を与える場合は、プレイブック、インベントリ、およびJenkinsタスクバーのタグとエクストラ変数にパスを設定できるJenkinsのAnsibleプラグインを接続することをお勧めします。
次は?
この記事で説明されている構造は、参照や普遍的なふりをするものではありませんが、ほとんどの場合に適しています。 出発点として使用できます。 独自のロールを作成するプロセスでは、構築しているインフラストラクチャを記述するためのより適切で便利な方法を見つけるでしょう。 主なことは、物事を複雑にしようとすることではなく、書くのが簡単で、他の人にとってあなたのプレイブックがより理解しやすいものであるほど良いことです。
Ansibleの公式ドキュメントでタブを開いたままにしてください。プロジェクトの進行に合わせて常に更新されます。 私はまだ自分にとって新しくて面白いものを見つけています。
この記事では、私が望んでいたすべてを語ったわけではありません。1つまたは2つ以上のメモについての考えやアイデアがあります。 特定の質問に興味がある場合は、コメントに書き込んでください。または、私にメールを送ってください。次の記事を書くときに、あなたの願いを考慮に入れて答えることを試みます。
UPD:
ここでの環境の分離の有用な例(プロダクション/ステージング)。 リンクをありがとう。