【初心者向けハンズオン】インフラ構築自動化 ~Step4:Tomcatのインストール・Postgres連携~

本シリーズではAnsibleを適用してWeb3層システム(Apache/Tomcat/Postgres)を自動構築する方法をご紹介しています。
今回はStep4としてTomcatのインストールおよび基本設定の方法をご紹介しますので、ぜひ参考になさって下さい。


    まだAnsibleインストール、OS基本設定、Postgresインストールが済んでいない方は下記のStep1、Step2、Step3の記事を参考にしてみて下さい。
    【Ansible/インフラ構築自動化】Step1:Ansibleのインストール方法(AWS EC2/CentOS7)
    【Ansible/インフラ構築自動化】Step2:AWS EC2に構築したCentOSの基本設定

    【Ansible/インフラ構築自動化】Step3:Postgresインストール/データベース作成

    1. ymlファイル作成

    1.1 ディレクトリ作成

    まずはAnsibleユーザでmkdirコマンドを実行し、下記の通りディレクトリを作成して下さい。

    [ansible@ip-172-31-81-212 ~]$ tree
    .
    └── websystem
        └── roles
            ├── tomcat
            │   ├── files
            │   ├── tasks
            │   ├── tests
            │   └── vars
    
    1.2 プレイブック作成(main.yml)

    次はtasksディレクトリにmain.ymlを作成していきます。各タスクの内容は下記の通りです。
    ・check_install.yml:インストール前の事前準備
    ・install.yml:インストール作業
    ・configure.yml:設定作業

    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/tasks/main.yml
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/tasks/main.yml
    ---
    # tasks file for ./roles/
    
    - include_tasks: roles/tomcat/tasks/check_install.yml
    - include_tasks: roles/tomcat/tasks/install.yml
    - include_tasks: roles/tomcat/tasks/configure.yml
    
    [ansible@ip-172-31-81-212 ~]$
    1.3 インストール事前設定用yml作成(check_install.yml)

    インストールする前の設定確認・変更を行います。下記の通りtasksディレクトリにcheck_install.ymlを作成して下さい。ここではTomcatが使うポートの許可設定を入れています。実際に使用するポート番号(8080)の情報は後ほど/varsディレクトリのファイルに記載しますので、ここでは一旦、下記の通り作成してみて下さい。

    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/tasks/check_install.yml
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/tasks/check_install.yml 
    ---
    # tasks file for ./roles/tomcat
    
    - name: check_install / Allow ports for firewalld
      firewalld:
        port: "{{ item }}"
        permanent: yes
        immediate: yes
        state: enabled
      loop: "{{ tomcat_firewalld_port }}"
    
    [ansible@ip-172-31-81-212 ~]$
    
    1.4 インストール用yml作成(install.yml)

    続いてTomcatのインストールです。tasksディレクトリに配下にinstall.ymlを作成して下さい。各処理の詳細は下記の通りです。

    1. OpenJDKインストール
      Tomcatを動作させるためにはOpenJDKをインストールする必要がありますのでyumコマンドでインストールします。今回はOpenJDKのバージョン11をインストールしています。
    2. openjdk-develインストール
      javaの開発環境ツールも合わせてインストールしておきます。後続の動作確認にてjavacコマンドを使用してclassファイルを作成する際に使用します。
    3. ユーザ作成
      tomcatユーザを作成します。
    4. Tomcatインストーラのダウンロード
      yumコマンドだとサポート切れの古いバージョンしかインストールできないので、公式インストーラをダウンロードしてインストールしていきます。今回はTomcatバージョン9をインストールします。
    5. Tomcatインストール
      ダウンロードしたインストーラを/etcディレクトリに展開します。
    6. ディレクトリ存在確認
      /etc/tomcatディレクトリの存在確認をしています。/etc/tomcatディレクトリが存在していた場合に7.のmvコマンドを実行すると、期待している結果と異なる結果となってしまいますのでご注意ください。
    7. ディレクトリのリネーム
      好みの問題ですが、5.で展開したままののディレクトリのままだと扱いづらいので、/etc/tomcatディレクトリに名称を変更しています。
    8. 権限変更
      /etc/tomcat配下のディレクトリの権限を変更して、tomcatユーザで参照、実行できるように変更します。
    9. インストーラ削除
      最後に後片付けとして、ダウンロードしたインストーラを削除しておきます。
    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/tasks/install.yml
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/tasks/install.yml
    ---
    # tasks file for ./roles/tomcat
    
    #1.OpenJDKインストール
    - name: install / Install openjdk packages
      yum:
        name: "{{ openjdk_packages }}"
        state: present
    
    #2.openjdk-develインストール
    - name: install / Install openjdk-devel packages
      yum:
        name: "{{ openjdkdevel_packages }}"
        state: present
    
    #3.ユーザ作成
    - name: install / Add tomcat user
      user:
        name: tomcat
        group: tomcat
        system: yes
    
    #4.Tomcatインストーラのダウンロード
    - name: install / Download tomcat installer
      get_url:
        url: http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-9/v9.0.85/bin/apache-tomcat-9.0.85.tar.gz
        dest: /tmp
        timeout: 60
    
    #5.Tomcatインストール
    - name: install / Install tomcat
      unarchive:
        src: /tmp/apache-tomcat-9.0.85.tar.gz
        dest:  /etc
        remote_src: yes
    
    #6.ディレクトリ存在確認
    - file:
        path: /etc/tomcat
        state: absent
    
    #7.ディレクトリのリネーム
    - name: install / Rename directory
      command:
        cmd: 'mv -f /etc/apache-tomcat-9.0.85 /etc/tomcat'
    
    #8.権限変更
    - name: configure / directory permission change
      file:
       path: /etc/tomcat
       state: directory
       owner: tomcat
       group: tomcat
       recurse: yes
    
    #9.インストーラ削除
    - name: install / Delete installer
      file:
        state: absent
        path: /tmp/apache-tomcat-9.0.85.tar.gz
    
    1.5 設定変更用yml作成(configure.yml)

    続いてTomcatの設定作業です。tasksディレクトリに配下にconfigure.ymlを作成して下さい。各処理の詳細は下記の通りです。

    1. server.xmlの配置
      Tomcatの設定ファイルであるserver.xmlファイルを置き換える処理を記載しています。インストール先フォルダのconfディレクトリにrootオーナ、tomcatグループ権限でコピーします。server.xmlファイルは事前に編集してfilesディレクトリに格納しておく必要があるので後述します。
    2. JDBCドライバのダウンロード
      curlコマンドでpostgresql用のJDBCドライバをダウンロードします。Ansibleのhomeディレクト直下にファイルが置かれます。
    3. JDBCドライバ権限変更
      アプリ実行時に読み込みできるように適切な権限に変更します。
    4. テストアプリ配置用のディレクトリ作成
      テスト用アプリを配置するディレクトリを作成します。今回は/etc/tomcat/webapps配下にtestjspというディレクトリを作成しています。
    5. テストアプリ配置
      テスト用に作成したjspファイルを配置します。
    6. context.xml配置
      Postgresqlに接続するための設定を記載したcontext.xmlを配置します。
    7. ユニットファイルの配置
      Tomcatをsystemdコマンドで起動・停止するためのユニットファイルを配置します。
    8. ユニットファイルの読み込み
      8.で配置したユニットファイルをsystemctl daemon-reloadコマンドで認識させます。
    9. Tomcat自動起動設定
      systemctl enable tomcat.serviceコマンドを実行して自動起動設定を有効にします。
    10. Tomcat起動
      systemdコマンドでTomcatを起動しています。
    11. Tomcat起動確認
      Tomcat起動後のステータスを確認する処理を記載しています。起動に少し時間がかかるので適当なdelay、timoutの時間を指定します。
    #1.server.xmlの配置
    - name: configure / Setup global configuration file
      copy:
        src: server.xml
        dest: /etc/tomcat/conf/server.xml
        owner: root
        group: tomcat
        mode: 0644
    
    #2.JDBCドライバのダウンロード
    - name: configure / download jdbc driver
      get_url:
       dest: /etc/tomcat/lib/
       url: https://jdbc.postgresql.org/download/postgresql-42.3.4.jar
    
    #3.JDBCドライバ権限変更
    - name: change permission
      file:
       path: /etc/tomcat/lib/postgresql-42.3.4.jar
       state: file
       owner: tomcat
       group: tomcat
       mode: 0640
    
    #4. テストアプリ配置用のディレクトリ作成
    - name: configure / directory creation
      file:
       path: "/etc/tomcat/webapps/testjsp"
       state: directory
       owner: tomcat
       group: tomcat
       mode: 0750
    
    #5. テストアプリ配置
    - name: configure / deploy jsp file
      copy:
       src: test.jsp
       dest: /etc/tomcat/webapps/testjsp
       owner: tomcat
       group: tomcat
       mode: 0750
    
    #6. context.xml配置
    - name: configure / deploy context.xml
      copy:
       src: context.xml
       dest: /etc/tomcat/conf/context.xml
       owner: tomcat
       group: tomcat
       mode: 0600
    
    #7.ユニットファイルの配置
    - name: configure / deploy systemd setting file
      copy:
        src: tomcat.service
        dest: /etc/systemd/system/tomcat.service
        owner: root
        group: root
        mode: 0755
    
    #8.ユニットファイルの読み込み
    - name: configure / systemd daemon-reload
      command: /usr/bin/systemctl daemon-reload
      become: yes
    
    #9.Tomcat自動起動設定
    - name: configure / systemd enable
      command: /usr/bin/systemctl enable tomcat.service
      become: yes
    
    #10.Tomcat起動
    - name: configure / Start tomcat service
      systemd:
        name: tomcat
        state: restarted
        enabled: yes
    
    #11.Tomcat起動確認
    - name: configure / Wait for tomcat restart
      wait_for:
        host: "{{ ansible_default_ipv4.address }}"
        port: "{{ tomcat_service_port }}"
        delay: 3
        timeout: 60
    
    
    
    
    1.6 設定ファイル作成

    1.5で反映するための設定ファイルおよびユニットを事前に作成します。まずは要件に応じて修正したserver.xmlをfilesディレクトリ配下に格納しておいてください。今回はApahce連動させるためにAJPコネクタを有効にしています。

    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/files/server.xml
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/files/server.xml
    ~抜粋~
    
        <!-- Define an AJP 1.3 Connector on port 8009 -->
    
        <Connector protocol="AJP/1.3"
                   address="0.0.0.0"
                   port="8009"
                   redirectPort="8443"
                   secretRequired="false" />
    

    続いて環境変数を設定するため設定ファイル、/etc/profileを配置してください。

    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/files/profile
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/files/profile
    # /etc/profile
    
    ~省略~
    
    JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.22.0.7-1.el7_9.x86_64
    CATALINA_HOME=/etc/tomcat
    CLASSPATH=$CATALINA_HOME/lib/postgresql-42.3.4.jar
    export JAVA_HOME CATALINA_HOME CLASSPATH

    続いてテスト用アプリを格納します。Postgresに接続してテーブルの情報を参照するアプリとなります。

    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/files/test.jsp
    <!DOCTYPE html>
    <html>
        <head>
            <title>test.jsp</title>
        </head>
        <body>
         <p><font size="7" color="#00ff00">JDBC Connection Test</font></p>
        </body>
    </html>
    
    <%@page import="javax.sql.DataSource"%>
    <%@page import="java.sql.Connection"%>
    <%@page import="java.sql.*" %>
    <%@page import="javax.naming.InitialContext"%>
    <%@page contentType="text/html" pageEncoding="UTF-8" session="false" %>
    <%
            //jndi
            String jndi = "java:comp/env/jdbc/PostgreSQL";
            InitialContext context = null;
            Connection connection = null;
            Statement stmt = null;
    
            //
            try {
                    context = new InitialContext();
                    DataSource ds = (DataSource) context.lookup(jndi);
                    connection = ds.getConnection();
                    String sql = "SELECT * FROM customerlist order by id limit 3000;";
                    PreparedStatement pstmt = connection.prepareStatement(sql);
                    ResultSet result = pstmt.executeQuery();
                    while ( result.next() ) {
                        //
                        int id = result.getInt("id");
                        String name =result.getString("name");
                        String email =result.getString("email");
                        out.println("<p>");
                        out.println("id:" + id + ",name:" + name + ",email:"+ email );
                        out.println("</p>");
                     }
            }
            finally {
                    if (context != null) {
                            try {
                                    context.close();
                            }
                            catch (Exception e) {
                            }
                    }
                    if (connection != null) {
                            try {
                                    connection.close();
                            }
                            catch (Exception e) {
                            }
                    }
            }
    %>

    続いてPostgresに接続するための設定を記載したcontext.xmlを格納します。

    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/files/context.xml
    <?xml version="1.0" encoding="UTF-8"?>
    ~省略~
    
    #下記を追記
        <!-- PostgreSQL -->
        <Resource name="jdbc/PostgreSQL"
          auth="Container"
          type="javax.sql.DataSource"
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
          initialSize="2" maxActive="4" minIdle="1" maxIdle="2"
          username="websystem" password="websystem"
          driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/websystem"
          validationQuery="SELECT 1" />
    
    </Context>

    作成したファイルのパーミッションが下記の通りになっているか確認しておいてください。

    [root@ip-172-31-81-212 ~]# ll /home/ansible/websystem/roles/tomcat/files/
    total 24
    -rw-r--r--. 1 ansible ansible 1834 Mar  2 16:21 context.xml
    -rw-rw-r--. 1 ansible ansible 6743 Feb 17 19:21 server.xml
    -rw-rw-r--. 1 ansible ansible 1931 Mar  2 16:24 test.jsp
    -rw-rw-r--. 1 ansible ansible  336 Feb 18 08:08 tomcat.service
    
    
    1.7 変数定義

    続いて変数を定義しましょう。varsディレクトリ配下にmain.ymlを作成して変数に具体的な値を入れます。

    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/vars/main.yml
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/vars/main.yml
    ---
    # vars file for ./roles/tomcat
    
    tomcat_service_port: 8080
    tomcat_firewalld_port:
      - "{{ tomcat_service_port }}/tcp"
    openjdk_packages:
      - java-11-openjdk.x86_64
    openjdkdevel_packages:
      - java-11-openjdk-devel.x86_64
    1.8 実行対象有効化

    最後にTomcatのplaybookが実行されるように、前のStepで作成したwebsystem_install.ymlのrole:postgresに関する記載のコメントアウトを外しておきましょう。

    [ansible@ip-172-31-81-212 ~]$ vi /home/ansible/websystem/websystem_install.yml
    [ansible@ip-172-31-81-212 ~]$ cat /home/ansible/websystem/websystem_install.yml
    ---
    - name: Install for web system
      hosts: websystem
      become: true
      roles:
        - { role: common, tags: common }        ##OS setting
        - { role: postgres, tags: postgres }    ##Postgres Install/setting
        - { role: tomcat, tags: tomcat }        ##Tomcat Install/setting
    #    - { role: apache, tags: apache }        ##Apache Install/setting
    [ansible@ip-172-31-81-212 ~]$
    
    

    2. プレイブック実行

    2.1 プレイブック実行

    続いてansible-playbookコマンドを実行していきましょう。NGだった場合には-vvvvオプションをつけてエラー内容を確認して修正してみて下さい。

    [ansible@ip-172-31-81-212 ~]$ ansible-playbook -i ~/websystem/inventory/inventory.ini  ~/websystem//websystem_install.yml -t tomcat
    
    PLAY [Install for web system] ***********************************************************************************************************************************************
    
    TASK [Gathering Facts] ******************************************************************************************************************************************************
    ok: [web1i]
    
    TASK [tomcat : include_tasks] ***********************************************************************************************************************************************
    included: /home/ansible/websystem/roles/tomcat/tasks/check_install.yml for web1i
    
    TASK [tomcat : check_install / Allow ports for firewalld] *******************************************************************************************************************
    ok: [web1i] => (item=8080/tcp)
    
    TASK [tomcat : include_tasks] ***********************************************************************************************************************************************
    included: /home/ansible/websystem/roles/tomcat/tasks/install.yml for web1i
    
    TASK [tomcat : install / Install openjdk packages] **************************************************************************************************************************
    ok: [web1i]
    
    TASK [tomcat : install / Install openjdk-devel packages] ********************************************************************************************************************
    ok: [web1i]
    
    TASK [install / Add tomcat user] ********************************************************************************************************************************************
    ok: [web1i]
    
    TASK [install / Download tomcat installer] **********************************************************************************************************************************
    changed: [web1i]
    
    TASK [install / Install tomcat] *********************************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : file] ********************************************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : install / Rename directory] **********************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / directory creation] ******************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : install / Delete installer] **********************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : include_tasks] ***********************************************************************************************************************************************
    included: /home/ansible/websystem/roles/tomcat/tasks/configure.yml for web1i
    
    TASK [configure / Setup tomcat configuration file] **************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / download jdbc driver] ****************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : change permission] *******************************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / directory creation] ******************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / deploy jsp file] *********************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / deploy context.xml] ******************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / deploy systemd setting file] *********************************************************************************************************************
    ok: [web1i]
    
    TASK [tomcat : configure / systemd daemon-reload] ***************************************************************************************************************************
    changed: [web1i]
    
    TASK [tomcat : configure / systemd enable] **********************************************************************************************************************************
    changed: [web1i]
    
    TASK [configure / Start tomcat service] *************************************************************************************************************************************
    changed: [web1i]
    
    TASK [configure / Wait for tomcat restart] **********************************************************************************************************************************
    ok: [web1i]
    
    PLAY RECAP ******************************************************************************************************************************************************************
    web1i                      : ok=25   changed=15   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    
    
    
    
    
    

    ok, changedになっていたら成功です。

    2.1 プレイブック実行結果確認

    プレイブック実行によってTomcatが適切にインストールおよび設定されているか確認しましょう。

    1. Tomcatの起動確認
    systemdコマンドで状態確認しましょう。Activeの項目がactive (running)になっていれば正常に起動できています。

    [ansible@ip-172-31-81-212 ~]$ sudo systemctl status tomcat
    ● tomcat.service - Apache Tomcat 9
       Loaded: loaded (/etc/systemd/system/tomcat.service; enabled; vendor preset: disabled)
       Active: active (exited) since Sun 2024-03-03 06:04:48 JST; 8min ago
      Process: 9077 ExecStart=/etc/tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
     Main PID: 9077 (code=exited, status=0/SUCCESS)
       CGroup: /system.slice/tomcat.service
               └─9091 /usr/bin/java -Djava.util.logging.config.file=/etc/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djd...
    
    Mar 03 06:04:48 ip-172-31-81-212.ec2.internal systemd[1]: Starting Apache Tomcat 9...
    Mar 03 06:04:48 ip-172-31-81-212.ec2.internal systemd[1]: Started Apache Tomcat 9.
    
    
    

    2. Tomcatが使用しているポート確認
    lsof コマンドでTomcatが使用しているポートが5432であることを確認しましょう。

    [ansible@ip-172-31-81-212 ~]$ sudo lsof -i:8080
    COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    java    9091 tomcat   44u  IPv4  59214      0t0  TCP *:webcache (LISTEN)
    
    
    

    3. Tomcatの設定ファイル確認
    catコマンドでTomcatの設定ファイルが想定通り編集されているか確認しましょう。

    [ansible@ip-172-31-81-212 ~]$ vi ./websystem/roles/tomcat/files/server.xml
    [ansible@ip-172-31-81-212 ~]$ cat ./websystem/roles/tomcat/files/server.xml
    ~抜粋~
    
        <!-- Define an AJP 1.3 Connector on port 8009 -->
    
        <Connector protocol="AJP/1.3"
                   address="0.0.0.0"
                   port="8009"
                   redirectPort="8443"
                   secretRequired="false" />

    4. Tomcat管理コンソール接続
    Tomcatの管理コンソール画面にアクセスできるか確認します。EC2インスタンスのInboundルールにポート8080を追加して、ブラウザからアクセスできたら成功です。
    アクセス先:http://{サーバホスト名}:8080


    Inboundルール追加の詳細については下記サイトを参照ください。
    ※セキュリティの観点から、ひととおり構築が終わったら本管理コンソールは外部から接続できないようしておくことを推奨します。

    5. テストアプリ動作確認
    では最後にテストアプリが動作するか確認しましょう。ポート指定8080番ポートを指定してTomcat上のテストアプリにアクセスします。
    下記の通りテストデータが表示できたら成功です!
    アクセス先:http://{サーバホスト名}/testjsp/test.jsp

    まとめ

    Step4ではTomcatのインストール、各種設定、Tomcat/Postgres連携まですべてAnsibleで自動構築する方法をご紹介しまいした。次のStep5ではApacheインストールおよびApache/Tomcat連携の方法をご紹介します。いよいよ次が最後のStepとなりますので、最後まで見てもらえると嬉しいです!!
    【Ansible/インフラ構築自動化】Step5:Apacheのインストール・Tomcat連携

    参考文献

    Ansible実践ガイド

    Quiita:Tomcat・PostgreSQL連携

    コメント