Ansibleに関するGoogleの情報は、Habré
に関する記事に出会いました。 私は読んで、とても驚きました:あなたはそれをもっと美しくすることができます! 興味があるなら、キャットへようこそ!
これはすべて、実際のプロジェクトで機能するとすぐに言わなければなりません(ノードの数は80を超えますが、100未満です)。
以下に、少なくとも3分の1、または2番めのDevOpsが遭遇する未知の問題を扱うタスクを示します。
- 構成ファイルのパラメーターとして、以前は未知のホストアドレスを使用し、これらのノードは別のロールに属します( ソリューション )
- 不明なホストアドレスから動的にインベントリを生成する-AWSサービスにアクセスして( ソリューション )
- Nginx構成ファイルを作成します。このファイルには、バックエンドノードの不明なアドレスを事前に登録する必要があります( ソリューション )
最初は最も簡単です:
ノードアドレスの置換
例を見てみましょう。ノード「app_nodes」のグループがあり、次のようなタスクファイルを使用して特定のアプリケーションがインストールされます。
application.yml ---
-ホスト:app_nodes
gather_facts:はい
役割:
-役割:共通
-役割:アプリケーション
ZooKeeperサービスがあり、アプリケーション構成ファイルでこのサービスを使用するための設定を登録する必要があると想像してください。
zk.connect=127.0.0.1:2181,127.0.0.2:2181,127.0.0.3:2181,127.0.0.4:2181, 127.0.0.5:2181
ペンを使用して、たとえば、ZooKeeperがインストールされている5つのノードすべてのアドレスを、アプリケーションのあるノードに登録することは明らかです。 Ansibleがこれらのノードのすべてのアドレスを構成ファイルテンプレートに挿入するために何ができますか?
特別なことは何もありません。 AnsibleはYAMLの上でJinja2テンプレートエンジンを使用するため、テンプレートエンジンサイクルを使用します。
zk.connect={% for host in groups['zk_nodes'] %}{{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}:{{ zk_port }}, {% endfor %}
その結果、テンプレートエンジンが機能した後、目的の行を取得する必要がありますが、問題は次のとおりです。app_nodesノードを操作し、このテンプレートでzk_nodesノードに関する情報(「ファクト」)を使用します。 このジョブファイルでこれらのノードをまったく使用しない場合、zk_nodesノードのアドレスを取得する方法は? この特定のノードグループ(zk_nodes)に空のタスクリストを割り当てます。
application.yml ---
-ホスト:zk_nodes
gather_facts:はい
タスク:[]
-ホスト:app_nodes
gather_facts:はい
役割:
-役割:共通
-役割:アプリケーション
このジョブファイルを機能させるには、必要なノードグループをインベントリファイルで定義する必要があります。
環境/テスト/インベントリ[zk_nodes]
127.0.0.1
127.0.0.2
127.0.0.3
127.0.0.4
127.0.0.5
[app_nodes]
127.0.0.10
127.0.0.11
127.0.0.12
しかし、ホストアドレスが事前にわからない場合はどうでしょうか? たとえば、仮想マシンはEC2で使用されていますか? ここで、2番目の質問にスムーズに回答します。
ダイナミックインベントリを使用する
インターネット上のこのトピックに関する情報はあまり多くありません-Ansible Towerの存在を考慮して、私が理解しているように。
したがって、EC2には多数のノードがあり、それらを一元的かつ簡単に管理する必要があります。 可能な解決策の1つは、Ansible +動的インベントリスクリプトを使用することです。
対応するインベントリディレクトリの構造は次のとおりです。
ツリー./environments/dynamic 。
├──ec2.ini
├──ec2.py
├──グループ
└──group_vars
├──すべて
├──zk_nodes
├──プロキシ
└──app_nodes
ここ:
ec2.py-スクリプト自体。
ここで取得できます。リンクは直接です。
ec2.ini-スクリプト設定を含むファイル。
ここで取得できます。リンクは直接です。
groups-このインベントリで作業するノードのグループを記述するファイル、
group_vars-各特定グループの変数の値を含むディレクトリ、およびすべてに共通のディレクトリ。
次に、スポイラーの下で、リンクのiniファイルと異なる設定:
変更されたec2.iniオプション#ノードが配置されている地域
リージョン = us-east-5、us-west-2
#「ライブ」(実行中)ノードでのみ動作します
instance_states =実行中
#1つを除くすべてのgroup_by _....パラメーターはコメント化されています。
group_by_tag_keys = true
#インベントリに含めるノードを選択します。 この場合、指定された値を持つ「Name」タグを持つもの。
instance_filters =タグ:名前= zk_node、タグ:名前= app_node、タグ:名前=プロキシ
Ansibleがこれらのグループとノードを正しく認識するために、
グループファイルを作成します。
グループファイル [すべて:子供]
zk_nodes
代理人
app_nodes
[zk_nodes:子]
tag_Name_zk_node
[プロキシ:子供]
tag_Name_proxy
[app_nodes:子]
tag_Name_app_node
[tag_Name_zk_node]
[tag_Name_proxy]
[tag_Name_app_node]
ここでは、デフォルトで動作するノードのグループ
allにネストされたグループ
zk_nodes 、
proxies 、
app_nodesが含まれていることをAnsibleに通知します。 さらに、これらのグループには動的に形成されるネストされたグループがあるため、ノードの説明にはまったく示されていません。 このようなブラックマジック-動作中、動的インベントリスクリプトはtag_ <タグ名> _ <タグ値>という形式のグループを作成し、これらのグループにノードを入力します。その後、通常のAnsibleツールを使用してこれらのグループを操作できます。
はい、
group_varsディレクトリについてです。 インベントリを読み込むときにAnsibleによって自動的に読み取られ、このインベントリ内の各グループはファイル
group_vars / group_nameから変数を取得し
ます 。 使用例の1つは、特定のノードグループの個別のキーです。
group_vars / zk_nodesansible_ssh_private_key_file: "/tmp/key.pem"
動的インベントリを調べた後、3番目の問題をエレガントに解決できます。
Nginx構成ファイルの生成
Nginx構成テンプレートがHabréのユーザーを驚かせないことは明らかです。したがって、説明で
上流のブロックに限定します。
nginx.confアップストリームアップストリームapp_nodes {
{%in group in item ['app_nodes']%} server {{hostvars [item] ['ec2_private_ip_address']}}:{{app_port}};
{%endfor%}
キープアライブ600;
}
この構成ブロックは、異なるアドレスと共通のポート番号を持つ上流サーバーのグループを定義します。
テンプレートエンジンは、app_nodesグループのすべてのノードを介して実行され、各ノードの行を生成します。 このようになります
結果の例アップストリームapp_nodes {
127.0.0.1lla000;
127.0.0.2lla000;
127.0.0.3 {000;
127.0.0.4 {000;
キープアライブ600;
}
これは、タスクの空のリストでapp_nodesノードグループを追加で参照する必要がない場合の最初の
ソリューションの状況とは異なります。このグループは、動的インベントリスクリプトのおかげで、上記の
グループファイルに従って、とりわけ自動的に作成されます。 そして、もちろん、VPCの内部アドレスへのアピールが使用されます。
あとがき
環境、タスク、インベントリ、ノード、IPアドレスの名前は架空のものに置き換えられます。 一致するものはすべてランダムです。 ファイル名またはディレクトリ名が機能にとって重要である場合、それらがそのように呼ばれる理由の説明が与えられます。
マネージャー、顧客、そしてあなた自身の良心に対するプロジェクトの状態については、あなたとあなた自身だけが責任を負っていることを忘れないでください。 私は完全なふりをしません。 この記事が誰かの時間を節約し、誰かを正しい方向に押し進めることを願っています。 私の能力と理解の及ぶ限り、コメントで質問に答えます。