Amazon Ec2

EC2でAnsibleサーバー構築~ミドルウェア導入までやってみた

おはよう世界。どうも若林です。

もうすっかり11月ですね。私が入社した4月からもうそんなに経ったのかと思います。

9月のはじめくらいに秋に備えて洋服をいくつか買ったのですが、なんだかすぐ寒くなりましたよね。私が買った服では防ぎきれないくらい寒いです・・・。

さて、本日はEC2でAnsibleサーバーを構築してみようと思います。
今回はテストとして構築していきますので、LAMP環境の導入、初期設定を完了までをゴールに設定します。
結構長くなりましたので覚悟してください。

Ansibleってなに?

構築前にAnsibleについて軽く解説しようと思います。

AnsibleとはRedHat社が提供しているオープンソースのツールです。
SSH接続を使って単一・複数の機器に対してエージェントレスでソフトウェアのインストールや設定・パッチ適用を自動的に導入してくれる凄い構成管理ツールです。
構成管理といっても、私はITインフラを構築する際に手動で設定するものを自動で設定してくれる自動化ソフトとして扱っております。

私は業務でAnsibleを使う際は、ミドルウェアのインストール・初期設定、バーチャルホストの設定やドキュメントルートなど、Webサーバー構築の際にお世話になっております。

前準備

今回構築するのにあたって以下のものが必要になります。

  • AWSアカウント
  • 作成済みのEC2・RDS
  • EC2にアタッチするVPCやサブネット、セキュリティグループ諸々
  • Semaphoreのインストールリンク

今回はEC2が2台、RDSが2台(1台でも可)必要になります。
EC2が2台必要な理由は片方がAnsible用のサーバー、もう片方がターゲットサーバー(ミドルウェアを導入するサーバー)となっております。
RDSはAnsibleサーバー用に一台作成してください。
本当はターゲットサーバーにもRDSは欲しいですが、今回のメインはAnsibleサーバーの構築ですので、無くても大丈夫です。
Semaphoreのリンクは後程記述します。

AWSアカウント・EC2作成方法は私の先輩が以前に超絶初心者向けに作ってたのでそちらをご覧ください(チラッと見た感じ今と大体同じ手順ですのでこれを読んだら問題ないかと)
【超絶初心者向け】これだけでEC2を無料で建てられるブログ。前編

ただし一つ注意なのが、こちらの技術ブログでは「Amazon Linux」で作成されていますが、今回はAlma Linuxで作成してください。
理由はAmazon Linuxだと後で色々めんどくさくなりそうだからです。
EC2は後程スペックを書きますのでそちらを参考にしつつ構築していただければと思います。

RDSの作成からEC2に接続するやり方はこちらの記事をご覧ください。
AWS 上でRDS を作成して、 EC2 から接続する方法

次の章にスペックを書きましたので、それを見ながら構築していただければと思います。

EC2・RDSのスペック

では今回使用するEC2・RDSのスペックを確認していきましょう。
Ansible実行する際はそこまで大きな負荷はないため、ほとんど無料枠で収まると思います。

ではまずAnsibleサーバーのスペックです。
OSは「AlmaLinux OS 9系(x86_64)」インスタンスタイプは「t3.small」を使用してください。
その他はデフォルト設定、作成したVPCやサブネット、キーペアでサーバーを立ててください。

次にセキュリティグループですが、インバウンドルールに以下のポートを許可してください。

※SSHの許可するソースを一時的に0.0.0.0/0にしておりますが、セキュリティ的に普段は自分のIPアドレスにすることを推奨します。

アウトバウンドルールは全て許可して大丈夫です。
こちらは必要に応じて各自で設定してください。

では次にターゲットサーバーの構築を進めていきましょう。
といってもAnsibleサーバーと全く同じスペックでも問題ございませんので同じものを作って頂いて大丈夫です。
Amazon LimuxかAlmaLinuxにしていただいた方が同じ操作感ですのでわかりやすいと思います。

次はRDSの構築です。
RDSは現時点ではそこまで使う予定はないので、先程紹介した記事の通りに作成してください。

Ansibleサーバー内に必要なものをインストール

次はいよいよサーバー内に接続してAnsible環境を整えていきます。
こちらのAnsibleサーバーには手動で何個か必要なパッケージがありますのでインストールしていきましょう。

まず、AWS上かコマンドプロンプトやターミナル、またはサーバーに接続できるソフトウェアからSSH接続をしてください(今回私はTera Termから接続しました)

インストール前の準備

まず、root権限に切り替えておきましょう。

作業するうえで色々便利です。今回検証環境なので何かしらの制限とかが無ければrootで作業していただいて問題ございません。

それではroot権限に切り替えるために以下のコマンドを入力してください。

sudo su -

こちらでroot権限に切り替わったかと思います。

では次にアップデートをしておきましょう。これは依存関係でエラーが発生したり安定性向上のためにサーバーを立てたら毎回やっています。作りたてのサーバーですのであまりないとは思いますが、すぐ終わりますので念のため。

dnf update -y

そうしたら次はルートディレクトリを整えていきます。
今回はテンプレートをいくつか作っていくやり方にします。こうすると使いたい時にディレクトリをコピーするだけで済みますし、同じ構築を何回もすることがあれば後々楽になるからです。
ただ、その代わり作成するディレクトリやフォルダの量が多くなるので注意です。

それでは必要なディレクトリとフォルダを作っていきます。
今回のディレクトリ構成は以下になります。

ちょっと雑ですけどこんな感じになります。(青がディレクトリ、黄色がファイル)

今回はテストでLAMP導入と初期設定のみ行うだけですが、今後ほかのロールも増やす場合、一つのディレクトリにまとめた方が管理が楽なためロールディレクトリを作っておきます。
複数ロール増えるかもしれないけど、またいちいち設定し直したりするのが手間なのでおすすめです。

話を戻しまして、これらの構成図通りの環境を作成していきましょう。
まずはansibleディレクトリを作成していきます。今回は/root配下に作成していきます。

大変だと思いますので、以下のコマンドをコピペしていただければこちらのディレクトリ構成はクリアです。Ansibleを使って自動的に作る方法もありますが、また別の機会にします。

#ベースディレクトリ作成
mkdir -p /root/ansible

#ロール構成ディレクトリ作成
mkdir -p /root/ansible/roles/lamp/{tasks,vars,templates}

#各ファイルを作成
touch /root/ansible/{ansible.cfg,inventory,playbook.yml}
touch /root/ansible/roles/lamp/{tasks/main.yml,vars/main.yml,templates/index.php.j2}

完了したら念のため作成できているか確認してください。

MySQLをインストール

次は必要なパッケージのインストールをします。

まずはMySQLをインストールしましょう。

こちらのコマンドからMySQLをインストール(コマンド内のURLはなくなっている可能性がありますのでリンク元を辿って最新バージョンを入れることをお勧めします)

dnf -y install https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm

dnf -y install mysql mysql-community-client

dnf -y install mysql-community-server

これでMySQLのインストールが完了しました。
ちゃんと入っているか確認してみましょう。

mysql --version

MySQLのバージョンが確認出来たら完了です。
そしたらMySQLを起動しましょう。
その後ステータス確認も行います。

systemctl start mysqld

systemctl status mysqld

以下の文字が見えたら完了です。

● mysqld.service - MySQL Server

#          ↓これが見えたらOK
Active: active (running)

これでOKです。あとは必要に応じてenableとかも設定しておきましょう。
今回ではあまり直接MySQLは使いませんが、今後Ansibleサーバーを利用するとなると後々必要になってくるので今のうちに入れておきます。

wgetをインストール

あとで使いますので今のうちにインストールしちゃいましょう。

dnf install wget -y

こちらからインストールしちゃいます。
wgetは一旦これで以上です(短っ!)

EPEL・Ansibleをインストール

次はいよいよメインのAnsibleをインストールします。

まずEPELをインストールします。

dnf install epel-release -y

これで完了です。
余談ですが、私は以前コレに苦しめられて今回AlmaLinuxを選びました。
詳細は省きますが、AmazonLinuxだとEPELはリポジトリとして正式にサポートされてない為、AmazonLinuxだと手動で追加する必要があります。
AlmaLinuxは上記のコマンドで一瞬でインストールできるのに・・・。
それ以来このリポジトリを発見したら絶対にAlmaLinuxにしています。

話が脱線しましたが、次はAnsibleをインストールしていきます。

dnf install ansible git -y

こちらのインストールが完了したらMySQLの時と同様にちゃんと入っているか確認しましょう。

ansible --version

バージョンが出たら完了です。
これでAnsibleが使えるようになっていますが、まだミドルウェア導入までは手順がありますので次に進みましょう。

オプション:vimをインストール

これはやらなくてもいいのですが、便利ですのでvimもインストールしちゃいます(私はサーバーを立てたら毎回インストールしてます)

結構最近知ったんですけど、RHELやCentOSだとデフォルトで入ってないんですねこれ・・・。

dnf install vim -y

これで完了です。
他にもvim関連やその他入れられるパッケージがありますので自分の使いやすいようにしていただければと思います。

日本語に変えたり文字の色変えたりすると分かりやすくなって便利です。

Semaphoreのインストール・セットアップ

ここからはSemaphore編です。
私がサーバー構築してる中で一番ややこしかったので頑張って解説していきます。

まずSemaphoreのインストールリンクを取得します。
https://github.com/semaphoreui/semaphore/releases/
GitHubの中から最新バージョンをクリックします。
プレリリース版最新版があると思いますが、何かあったら怖いので最新版の方をインストールします。
全体表示するとsemaphore_〇.〇〇.〇〇_linux_amd64.tar.gzっていう欄があると思います。
※〇の部分はバージョンです。
後ろの方に「_linux_amd64.tar.gz」って書いてある本体を見つけてください。
発見したら、そのリンクに入らず、右クリックを押してリンクアドレスをコピーしてください。

コピーしたら一応メモとかに残しておいてください。
次にこちらのリンクを使ってサーバーにインストールします。
以下のコマンドを叩いてください。

#Semaphoreをインストール(今回はバージョン2.16.37を使います)
wget https://github.com/semaphoreui/semaphore/releases/download/v2.16.37/semaphore_2.16.37_linux_arm64.tar.gz

#解凍します。解凍後にllコマンドでちゃんと出来てるか確認すると〇
tar xzf semaphore_2.16.37_linux_amd64.tar.gz

#Semaphoreを移動(自分の環境に合わせておく場所を決めてください)
mv semaphore /usr/local/bin/semaphore

#権限を変更
chmod +x /usr/local/bin/semaphore

ここまででインストールや権限周りまでの手順が終わりました。

MySQL内にデータベースを作成する

今度はSemaphore用のデータベースを作成していきます。
まずはMySQL内にログインするために以下のコマンドを叩きます。

mysql -h [RDSのエンドポイント] -u [RDSのユーザー名] -p

RDSのエンドポイントをAWS RDSコンソールから確認してください。
ユーザー名は作成時に指定してなければadminがデフォルトですので、こちらを入力してください。

その後パスワードを求められますので、入力が完了したらMySQL内にログインできるはずです。

mysql -h [RDSのエンドポイント] -u [RDSのユーザー名] -p
Enter password:[パスワードを入力] ←セキュリティ上入力しても何も見えません

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.43 Source distribution

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

こんな感じの表示が出たらOKです。

その後にデータベースを作成してください。
名前は何でもいいですが、今回は「semaphore」という名前で行きます。

#データベースを作成
CREATE DATABASE semaphore;

#その後作成できたか確認 こんな感じで表示されるはず
mysql> SHOW DATABASES;;
+--------------------+
| Database           |
+--------------------+
| ****************** |
| *****              |
| ****************** |
| semaphore          | ←作成が出来ている
| ***                |
+--------------------+
5 rows in set (0.01 sec)

無事作成が完了したらexitと入力したらログアウトして、セットアップへ進んでいきます。

セットアップ方法

ここは英語過ぎて日本人の私にはかなり厳しかったです。
翻訳しつつで進めていきますので手順通りに進めたらきっと大丈夫だと思います。

まず以下のコマンドを叩きます。

semaphore setup

これを叩くとこんな結果が出ると思います。
ここから大体の翻訳内容も書いていきますので長くなります。覚悟してください。

Hello! You will now be guided through a setup to:

1. Set up configuration for a MySQL/MariaDB database
2. Set up a path for your playbooks (auto-created)
3. Run database Migrations
4. Set up initial semaphore user & password

What database to use:
   1 - MySQL
   2 - BoltDB (DEPRECATED!!!)
   3 - PostgreSQL
   4 - SQLite
 (default 1):

訳:「こんにちわ!今からセットアップのガイドするね」

  1. MySQL/MariaDB データベースの設定
  2. プレイブック用のパス設定(自動作成)
  3. データベースマイグレーションの実行
  4. 初期セマフォアユーザーとパスワードの設定
    使用するデータベースはどれ?
    1 - MySQL
    2 - BoltDB(非推奨!!!)
    3 - PostgreSQL
    4 - SQLite
    (デフォルト 1)

今回はRDS MySQLを使ってますので1と入力しましょう。

db Hostname (default 127.0.0.1:3306):

#こんな感じに入力
************************.ap-northeast-1.rds.amazonaws.com:3306

訳:データベースのホスト名はなんていうの?(デフォルト 127.0.0.1:3306)
RDSのエンドポイントと3306(MySQLのポート)を入力します

db User (default root):

訳:データベースのユーザーはなんていうの?(デフォルト root)
RDSのユーザー名を入力してください。デフォルトでは「admin」ですので何も設定してなければadminって入力してください。

db Password:

訳:データベースパスワードはなに?
直球でパスワードを聞いてきます(それはそう)
RDS作成した際のパスワードを入力してください。

db Name (default semaphore):

訳:データベースの名前はなんていうの?(デフォルト semaphore)
これはDBの名前を聞かれています。
ここで注意なのが「RDS名ではなくRDSの中に作ったDB名を入力」をしてください。
先程作ったsemaphoreがありますので、今回はこちらを入力します。

Playbook path (default /tmp/semaphore):

訳:プレイブックパス(Ansibleの自動化スクリプト)はどこがいい?
こちらはPlaybooksのでディレクトリパスを聞かれています。
先程作った/root/ansibleの中に入れましょう。

Public URL (optional, example: https://example.com/semaphore):

訳:パブリックURLは何がいい?(オプション、例: https://example.com/semaphore
これはパブリックURLを設定する項目です。
必須ではないので空白で大丈夫です。

Enable email alerts? (yes/no) (default no):

訳:メールアラートを有効にする?(yes/no)(デフォルト no)
Playbooksを実行した際に成功/失敗をメールで通知してくれます。
特に必要なければNOで大丈夫です。
※YESを選択したらSMTPサーバー設定や受信者設定など入力してください。

Enable telegram alerts? (yes/no) (default no):

訳:Telegramアラートを有効にする?(yes/no)(デフォルト no)
アラート設定だと思います(試してないため不明)
特に必要なければNOで大丈夫です。

Enable slack alerts? (yes/no) (default no):

訳:Slackアラートを有効にする?(yes/no) (デフォルト: no)
Slackにアラートの通知を送るかを聞いています。
特に必要なければNOで大丈夫です。

Enable Rocket.Chat alerts? (yes/no) (default no):

訳:Rocket.Chatアラートを有効にする?(yes/no) (デフォルト: no)
Rocket.Chatというチャットプラットフォームへの通知を送るかを聞いています。
特に必要なければNOで大丈夫です。

Enable Microsoft Team Channel alerts? (yes/no) (default no):

訳:Microsoft Teamsチャンネルアラートを有効にする?(yes/no) (デフォルト: no)
Microsoft Teamsのチャンネルへの通知を送るかを聞いています。
特に必要なければNOで大丈夫です。

Enable LDAP authentication? (yes/no) (default no):

訳:LDAP認証を有効にする?(yes/no) (デフォルト: no)
LDAPによる認証を有効にするかを聞いています。
特に必要なければNOで大丈夫です。

Config output directory (default /root):

訳:設定出力ディレクトリのパスはどこにする?(default /root)
これはどのパスが設定ファイルや出力ファイルを保存するディレクトリパスかを聞いています。
今回の場合は「/root/ansible」と入力します。
ここまで設定が終わったら以下の内容が出力されると思います。

Migrations Finished

 > Username:

訳:データベースの初期化が完了したよ。管理者アカウントを作ろう。何がいい?
初期セットアップが終わったのであとはSemaphore内で使う管理者アカウントを作成します。
このように進めればOKです。

> Username: admin #ログインID 覚えやすいものでOK
> Email: root@localhost #通知用のメールアドレス 要らなければ何でもOK
> Your name: wakabayashi.dayo #管理者アカウントの表示名 なんでもOK
> Password: password@1234 #ログイン用パスワード 必ず覚えるかメモするべし

※一応言いますとこちらは適当に入力したダミーです。

これらを入力するとこんな感じの文字が出力されます。

> Username: admin 
> Email: root@localhost 
WARN[0221] no rows in result set 
fields.level=Warn 
> Your name: wakabayashi.dayo 
> Password: password@1234

You are all setup wakabayashi.dayo! 
Re-launch this program pointing to the configuration file 
./semaphore server --config /root/ansible/config.json 

To run as daemon: 

nohup ./semaphore server --config /root/ansible/config.json & 

You can login with root@localhost or admin.

ここまで来たらデータベースの初期化・管理者ユーザーの作成・設定ファイルの作成・起動コマンドが作成されました。

それでは実際にSemaphoreのWebサーバーを起動してみましょう。

./semaphore server --config /root/ansible/config.json

#以下は実行結果
[root@********: ~]# ./semaphore server --config /root/ansible/config.json
Loading config
Validating config
MySQL admin@*********************.ap-northeast-1.rds.amazonaws.com:3306 semaphore #私のRDSエンドポイント
Tmp Path (projects home) /root/ansible
Semaphore 2.16.37-******-**********
Interface
Port :3000
Server is running

こちらを叩くと、ターミナル内にログが流れます。
ちなみに注意ですが、こちら先程インストールしたtar.gzファイルを展開しないとエラーが起こりますので、必ず展開してから実行するようにしましょう。※権限周りも忘れずに!
(私は何故かインストールした後展開せず放置してた為、原因不明のエラーだと思って20分程苦しんでました・・・)

展開後に実行が完了したら、以下のブラウザにアクセスしてみましょう。

http://[EC2のパブリックIP]:3000

ログイン画面が表示出来てればOKです。
あとは先程設定したログインIDとパスワードを入力すれば管理画面へ入れます。

ログイン後はこんな感じの画面になります。
これでSemaphoreのセットアップが終わりました!

この画面を動かしている間はSemaphoreをサーバー内でずっと実行する必要があります。
ですが、Ansibleを使う間は起動してなくても動くので今回は初期設定の間のみ実行しております。
なので、Apacheみたいにenable等で自動起動設定にしなくても問題ございません。

※しかし今後運用していくならSemaphore内の設定をすることもあると思うので自動起動設定しておくと良いかも

Semaphore内の初期設定方法

次はログインできたSemaphore内の初期設定を行います。
この辺りはちゃんと出来てるか自信はないのですが、頑張っていきます。

プロジェクトの作成

まず左上の矢印を教えてプロジェクトを作成します。
名前と最大並列タスク数とTelegramチャットIDを入力する画面になると思います。

名前は何でも大丈夫です。今回は「ansible-project」にします。
次に最大並列タスク数ですが、これはこのプロジェクト一つで何個Ansibleを同時に実行できるようにするかを決めます。
こちらは自分たちの環境規模とリソースの使用量と相談ですが、小規模でよかったら3台とかでいいと思ます。
TelegramチャットIDは先程サーバー内でセットアップした際に「Telegramアラートを有効にする?」みたいなことを聞かれたと思います。
オフにしてればここは無視で大丈夫です。
アラートを許可も必要に応じてオンにしてください。

キーストアの作成

次はキーストアを作成していきます。
と言っても今回キーストアの活躍は無いのですが、この後色々作成する際に「キーストア使えー!」って言われるので仕方なく作ります。
一応キーストアの方がセキュリティ的には安全にはなるのでおすすめです。
まずはキーストアを開いたら右上の新しいキーって項目をクリック

作成画面へ進みます。

名前は何でも大丈夫です。今回は「root-ssh」にします。
タイプはSSHキーを選択してください。
ユーザー名はEC2にログインするユーザー名(ec2-user等)を入力してください。
パスフレーズはSSH接続する際のパスワード(キーペアとは別)を設定している場合は入力してください。
秘密鍵はキーぺアを作成した時、.pemファイルをダウンロードしたと思います。その中身をコピペしてください。

その後は作成を押して次へ進みましょう。

インベントリの作成

次はインベントリを作成していきます。
こちらはAnsibleサーバー内の「inventory」ファイルの場所を記載します。
まずはインベントリを開いたら、右上の新しいインベントリって項目をクリック。

こちらも作成画面へ行きます。

名前は何でも大丈夫です。今回は「lamptest-invenory」にします。
ユーザー資格情報は先程作ったキーストア(今回の場合root-ssh)を選択します。
Sudo資格情報は、Ansibleが管理者権限でコマンドを実行する際に、sudoでログインできるようにするためのパスワードを入力するところです。
特に必要ないので今回はスルーします。使用したい場合はキーストアでsudoパスワードを設定する必要があります。
タイプはFileを選択してください。そしたらインベントリファイルへのパスを入力する項目が表れます。
そうしたらAnsibleサーバーに先程作った「inventory」ファイルへのパスを入力します。
今回の場合は/root/ansible/inventoryですね。

すべて入力したら作成してください。

リポジトリの作成

次はリポジトリの作成に進みます。
こちらはAnsibleで使う「Playbooks」の場所を記載します。
まずはリポジトリを開いたら、右上の新しいリポジトリって項目をクリック。

ここでリポジトリを作成していきます。

名前は何でも大丈夫です。今回は「lamptest-repository」にします。
URLまたはパスは「Playbooks」が置いてあるパスを指定します。今回の場合はfile:///root/ansibleとなります。
ブランチは今回ローカルファイルですので、空白で大丈夫です。GitHubとか使っていると入力する必要があるみたいです。
※もし必須って出たらmainって入力してください。

アクセスキーは先程作ったキーストア(今回の場合root-ssh)を選択します。

終わったら作成してください。

変数グループの作成

次は変数グループの作成です。
お使いのバージョンによっては「環境変数」だったり「Environment」だったりするみたいです。
今回は変数グループっていう前提でお話しします。
まずは変数グループを開いたら、右上の新しいグループって項目をクリック。

名前は何でも大丈夫です。今回は「lamptest-group」にします。
変数はJSON形式で入力をします。以下を変数内に入力してください。

{
  "ANSIBLE_HOST_KEY_CHECKING": "False",
  "ANSIBLE_STDOUT_CALLBACK": "yaml",
  "ANSIBLE_FORCE_COLOR": "True",
  "ANSIBLE_SSH_PIPELINING": "True",
  "ANSIBLE_TIMEOUT": "30"
}

こちらザックリ解説します。

HOST_KEY_CHECKING

  • ホスト認証を自動化。本番環境にはTrueがおすすめかも(セキュリティ的に)

STDOUT_CALLBACK

  • Ansible実行結果の出力形式を指定。これは各々好みでOK

FORCE_COLOR

  • ログを出力した際に、結果を色分けしてくれる。見やすくなるためおすすめ。無くても大丈夫

SSH_PIPELINING

  • SSH接続をパイプライン形式にする。実行速度が高速になる(らしい)

TIMEOUT

  • SSHとタスク実行時のタイムアウト時間。本番環境はもう少し長めに設定していいかも

以上となります。
これで後は作成してください。

タスクテンプレートの作成

最後はタスクテンプレートの作成です。
これが終わればSemaphoreでの作業は終了です。
まずはタスクテンプレートを開いたら、右上の新しいテンプレートって項目をクリック。

名前は何でも大丈夫です。今回は「lamptest-template」にします。
次にプレイブックへのパスはPlaybooksファイルの相対パスを選択してください。今回の場合は「playbook.yml」と入力します。
インベントリは先程作ったものを選択。今回の場合は「lamptest-inventory」を選びます。
リポジトリも先程作ったものを選択。今回の場合は「lamptest-repository」を選びます。
変数グループも先程作ったものを選択。今回の場合は「lamptest-repository」を選びます。
ビューは今回は使いませんが、Ansibleの実行を管理・監視設定をしたい場合は推奨です。

その他は特に設定しなくても大丈夫です。必要に応じて各自設定してください。
これら全て終わったら作成を押してください。

以上でSemaphoreでの設定は終わりです。お疲れ様でした。
あとはAnsibleサーバー内の構築だけです。

一応ここまでやればAnsibleサーバー自体は構築完了です。
あとはおまけですが、LAMP環境の導入までやりたいと思います。

Ansibleサーバー側の設定

いよいよラストです。もう少しで完成します。
構築側も書き手である私も疲れていますが、あともう少し頑張っていきましょう!

その前に、ターゲットサーバーにAnsibleを実行するためのローカルSSHの設定をし忘れていました・・・。
一応キーストアがあればなくても行けますが、上手くいかなかった時用に作成しておきます。
ですのでこのタイミングで行います。(先程のディレクトリ構成図から少し変わります。すみません)

まず/root/ansible内に秘密鍵用のディレクトリを作成します。

mkdir -p ssh-keys

touch ssh-keys/master_key

中を開いたら、ターゲットサーバーの秘密鍵を貼り付けます。
そしたら権限も設定しておきましょう。

chmod 600 ssh-keys/master_key

権限の設定が終わったら公開鍵を作成・確認をします。
以下のコマンドを叩いてください。

#秘密鍵から公開鍵を生成
ssh-keygen -y -f ssh-keys/master_key > ssh-keys/master_key.pub

#公開鍵の権限設定
chmod 644 ssh-keys/master_key.pub

#最後に確認
ls -la ssh-keys/
cat ssh-keys/master_key.pub

そうしたら、ターゲットサーバー内に入って公開鍵を追加していきます。

#生成した公開鍵を追加
vi ~/.ssh/authorized_keys

#権限を設定
chmod 600 ~/.ssh/authorized_keys

#最後に確認
tail -1 ~/.ssh/authorized_keys

これで完了です。
それでは最後にAnsible内の設定を行っていきます。

といっても私がファイル内の設定を記載しますのでコピペしていけばOKです。ただものによっては自分の環境に合わせるものもあります。
まずは全内容コピペでOKなファイルから記載します。
(この辺は分からなかったためAI出力です)
playbook.yml

---
- name: LAMP Stack Installation using Role
  hosts: all

  roles:
    - lamp

inventory
※アスタリスクの部分はターゲットサーバーのパブリックIPアドレスを入力してください。

[lampservers]
lamp1 ansible_host=**.**.***.***

[all:vars]
ansible_user=ec2-user
ansible_ssh_private_key_file=ssh-keys/master_key
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
ansible_become=yes

ansible.cfg

[defaults]
inventory = inventory
host_key_checking = False
remote_user = ec2-user
private_key_file = ssh-keys/master_key
timeout = 30
gathering = smart
roles_path = roles
forks = 5
stdout_callback = yaml
display_skipped_hosts = False

[ssh_connection]
ssh_args = -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
pipelining = True
ssh_retries = 3

[privilege_escalation]
become = True
become_method = sudo
become_user = root

tasks/main.yml

---
# Apache のインストール
- name: Install Apache (RHEL/CentOS)
  dnf:
    name: httpd
    state: present
  when: ansible_os_family == "RedHat"

# MySQL のインストール
- name: Install MySQL (RHEL/CentOS)
  dnf:
    name:
      - mysql
      - mysql-server
    state: present
  when: ansible_os_family == "RedHat"

# PHP のインストール
- name: Install PHP (RHEL/CentOS)
  dnf:
    name: "{{ php_packages }}"
    state: present
  when: ansible_os_family == "RedHat"

# Firewall パッケージのインストール
- name: Install firewalld (RHEL/CentOS)
  dnf:
    name: 
      - firewalld
      - python3-firewall
    state: present
  when: ansible_os_family == "RedHat"

# Firewalld サービスの開始
- name: Start and enable firewalld
  systemd:
    name: firewalld
    state: started
    enabled: yes
  when: ansible_os_family == "RedHat"

# サービスの開始と有効化
- name: Start and enable Apache
  systemd:
    name: "{{ apache_service_name }}"
    state: started
    enabled: yes

- name: Start and enable MySQL
  systemd:
    name: "{{ mysql_service_name }}"
    state: started
    enabled: yes

# テンプレートを使用してindex.phpを作成
- name: Create index.php from template
  template:
    src: index.php.j2
    dest: /var/www/html/index.php
    mode: '0644'

# PHP情報ページ作成
- name: Create phpinfo page
  copy:
    content: |
      <?php
      phpinfo();
      ?>
    dest: /var/www/html/phpinfo.php
    mode: '0644'

# ファイアウォール設定(RHEL/CentOS)
- name: Open HTTP port (RHEL/CentOS)
  firewalld:
    service: http
    permanent: true
    state: enabled
    immediate: yes
  when: ansible_os_family == "RedHat"

- name: Open HTTPS port (RHEL/CentOS)
  firewalld:
    service: https
    permanent: true
    state: enabled
    immediate: yes
  when: ansible_os_family == "RedHat"

# ファイアウォール設定(Ubuntu/Debian)
- name: Open HTTP port (Ubuntu/Debian)
  ufw:
    rule: allow
    port: '80'
  when: ansible_os_family == "Debian"

- name: Open HTTPS port (Ubuntu/Debian)
  ufw:
    rule: allow
    port: '443'
  when: ansible_os_family == "Debian"

# 完了メッセージ
- name: Display completion message
  debug:
    msg: |
      🎉 LAMP Role Installation Complete!
      Access: http://{{ ansible_default_ipv4.address }}/
      MySQL root password: {{ mysql_root_password }}
      Services: Apache, MySQL, PHP-FPM
      Firewall: HTTP/HTTPS ports opened

vars/main.yml

---
# LAMP設定用変数
mysql_root_password: "SecurePassword123!"
apache_port: 80
php_version: "default"
server_admin: "admin@localhost"
document_root: "/var/www/html"

# Apache設定用変数
apache_service_name: "{{ 'httpd' if ansible_os_family == 'RedHat' else 'apache2' }}"

# MySQL設定用変数
mysql_service_name: "{{ 'mysqld' if (ansible_os_family == 'RedHat' and ansible_distribution_major_version|int >= 8) else 'mariadb' if (ansible_os_family == 'RedHat' and ansible_distribution_major_version == '7') else 'mysql' }}"

# PHP設定用変数
php_packages:
  - php
  - php-mysqlnd
  - php-fpm
  - php-opcache
  - php-gd
  - php-xml
  - php-mbstring
  - php-json
  - php-curl
  - php-zip

# サービス設定
services_to_start:
  - "{{ apache_service_name }}"
  - "{{ mysql_service_name }}"

# ファイアウォール設定
firewall_services:
  - http
  - https

templates/index.php.j2

<html>
<head>
    <title>LAMP Server - {{ ansible_hostname }}</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
        .container { background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .success { background: #d4edda; padding: 15px; border-radius: 5px; margin: 15px 0; border-left: 4px solid #28a745; }
        .info { background: #e7f3ff; padding: 15px; border-radius: 5px; margin: 15px 0; border-left: 4px solid #007bff; }
        h1 { color: #333; }
        h2 { color: #666; }
        .links a { display: inline-block; margin: 10px 15px 10px 0; padding: 8px 15px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; }
        .links a:hover { background: #0056b3; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🚀 LAMP Server Deployed with Ansible Role!</h1>

        <div class="success">
            <h2>✅ Server Information</h2>
            <p><strong>Hostname:</strong> {{ ansible_hostname }}</p>
            <p><strong>Server IP:</strong> {{ ansible_default_ipv4.address }}</p>
            <p><strong>Current Time:</strong> <?php echo date('Y-m-d H:i:s T'); ?></p>
            <p><strong>Deployed using:</strong> Ansible LAMP Role</p>
        </div>

        <div class="info">
            <h2>📊 LAMP Components</h2>
            <p><strong>🐧 Operating System:</strong> {{ ansible_distribution }} {{ ansible_distribution_version }}</p>
            <p><strong>🌐 Web Server:</strong> Apache ({{ apache_service_name }})</p>
            <p><strong>🗄️ Database:</strong> MySQL/MariaDB ({{ mysql_service_name }})</p>
            <p><strong>🐘 PHP Version:</strong> <?php echo PHP_VERSION; ?></p>
        </div>

        <div class="info">
            <h2>⚙️ Configuration</h2>
            <p><strong>Document Root:</strong> {{ document_root }}</p>
            <p><strong>Apache Port:</strong> {{ apache_port }}</p>
            <p><strong>Server Admin:</strong> {{ server_admin }}</p>
            <p><strong>PHP Extensions:</strong>
            <?php
            $extensions = get_loaded_extensions();
            echo count($extensions) . " loaded";
            ?>
            </p>
        </div>

        <div class="info">
            <h2>🔗 Test Pages</h2>
            <div class="links">
                <a href="phpinfo.php">📋 PHP Information</a>
            </div>
        </div>

        <div class="info">
            <h2>🛠️ Role Details</h2>
            <p>This LAMP stack was deployed using Ansible role structure:</p>
            <ul>
                <li><code>roles/lamp/tasks/main.yml</code> - Installation tasks</li>
                <li><code>roles/lamp/vars/main.yml</code> - Configuration variables</li>
                <li><code>roles/lamp/templates/index.php.j2</code> - This template file</li>
            </ul>
        </div>
    </div>
</body>
</html>

これで設定ファイル内は完了です。
後は正常に接続できるか試してみましょう。

Anisible実行してみた

まずはこちらのコマンドを叩きます。すると以下のような結果が出ます。
必ずcdコマンドで/root/ansibleに移動してから実行してください。

ansible all -m ping

#実行結果
lamp1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

この表記が出ればOKです。
最初の行に[WARNING]って出るとどこか間違えています。
次は構文チェックです。

ansible-playbook playbook.yml --syntax-check

実行結果

playbook: playbook.yml

何も出ないでplaybookって出たらOKです。
エラーだと何かしら怖いメッセージがいろんな色で表示されます。

全て確認終えたら、いよいよLAMPを導入していきます。

ansible-playbook playbook.yml

こちらを叩けば実行され、ログが表示されます。
大体10分程はかかると思います。

先程ログの色を変えたのでメッセージの区別が分かりやすくなっていると思います。緑の文字が出てれば正常に動いています!
ログの最後の方を確認して、以下のようになっていればOKです。

PLAY RECAP *********************************************************************
lamp1                      : ok=13   changed=0    unreachable=0    failed=0    
                             skipped=2    rescued=0    ignored=0

「skipped=2」って表示があるのはおそらくtasks/main.ymlでUbuntu/Debian用のファイアーウォール設定用のスクリプトがあったからだと思います。
特に影響はないのでスルーで大丈夫です。

後は各々構築した箇所を確認していただければと思います。
MySQLだけ最初にターゲットサーバー分のRDSを作成してなければ見れないと思います。
今回LAMPはおまけだから無くてもいいかって思って省きました。

最後に

いかがだったでしょうか。

気付いたらとんでもなく長文になってました。
私は一度自分で構築してから技術ブログ用に再度構築をしているのですが、複雑すぎて二回目でも苦戦しました。

今回メインはAnsibleサーバーの構築で、LAMP環境はおまけみたいなものですので、みなさんの好きな環境にしていただければと思います。
ずっとタイピングした指が痛い・・・トホホ

ちゃんと勉強したわけではなかったので、これが最適な方法ではないと思いますが、動いたから良しとします。
数年後に今より技術力を身に着けてこのサーバーも最適化していきたいですね。

それではまたどこかでお会いしましょう。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA