金融データ分析基盤の構築 - Hadoop(1)

前回:


今回やること

  1. AnsibleでHadoopクラスタ構築

  2. Hadoopクラスタへの接続

使用するマシン

今回はHadoopクラスタの構築・検証を行うことを主な目的とするため、NameNodeの可用性やDataNodeによる処理性能についてはあまり考えないことにする。それらについては、一通り構築してみてからまた別の記事で取り扱う。

使用するマシンは以下の二つで、クラスタとしては最小構成となる。

  1. NameNode:格安シンクラ1台

  2. DataNode:格安シンクラ1台

格安シンクラはすべてCPUがX5-E8000、RAMが2GB、ストレージはHDD500GBとなり、全体的にスペックはかなり低めだ。OSはUbuntu server 24.04で、初期設定のみをしたマシンとなっている。

AnsibleでHadoopクラスタ構築

事前準備

事前準備として必要なのはJavaのインストールとHadoopのソースコードのダウンロード。JavaのバージョンはHadoopのバージョンに依存しているが、公式ドキュメントに貼ってあるリンクを見るとHadoop2.7から3.3(とそれ以上)はJava 8にすべて対応されているようだった。

  • Java 8のインストール

  • Hadoopの安定版ソースコード(Apache mirrorから)

Javaのインストール

Java(OpenJDK)のインストールは圧縮ファイルをそのまま解凍して配置するような形になるので、とりあえずJava8のOpenJDK(圧縮)をOpenLogicからダウンロードしてきた。

このファイルをfiles配下に置いて、以下のようにAnsibleのタスクを書いていく。

$ tree roles/java
roles/java
├── files
│   └── openlogic-openjdk-8u422-b05-linux-x64.tar.gz
├── tasks
│   └── main.yaml
└── vars
    └── main.yaml
# roles/java/tasks/main.yaml

- name: "Copy Java 8 to the server"
  copy:
    src: "{{ jdk_archive }}"
    dest: "/opt/{{ jdk_archive }}"

- name: "Unarchive the file"
  ansible.builtin.unarchive:
    src: "/opt/{{ jdk_archive }}"
    dest: "/opt/"
    remote_src: yes

- name: "Set Java 8 as the default"
  alternatives:
    name: java
    link: "/usr/bin/java"
    path: "/opt/{{ jdk_directory }}/bin/java"
    priority: 1000

- name: Set JAVA_HOME environment variable
  template:
    src: jdk.sh.j2
    dest: /etc/profile.d/jdk.sh
    mode: '0755'
# roles/java/vars/main.yaml

jdk_version: "8u422-b05"
jdk_archive: "openlogic-openjdk-{{ jdk_version }}-linux-x64.tar.gz"
jdk_directory: "openlogic-openjdk-{{ jdk_version }}-linux-x64"

Hadoopの安定版ソースコード

ApacheのミラーサイトでHadoopの安定版バージョンをダウンロードしてくる。下のページだと現状は3.4.0が最も新しいバージョンとなっている。これのBinaryをダウンロードしてくる。

ダウンロードして解答するとこんな感じの中身になっており、基本的にはetc配下に設定ファイルが入っており、それらを適宜設定して各ノードに置くような形になる。

ls -la
total 116
drwxr-xr-x 10 yuuki yuuki  4096 Mar  4  2024 .
drwxr-xr-x  6 yuuki yuuki  4096 Sep 15 20:34 ..
-rw-r--r--  1 yuuki yuuki 23756 Mar  4  2024 LICENSE-binary
-rw-r--r--  1 yuuki yuuki 15696 Mar  4  2024 LICENSE.txt
-rw-r--r--  1 yuuki yuuki 27165 Mar  4  2024 NOTICE-binary
-rw-r--r--  1 yuuki yuuki  1541 Mar  4  2024 NOTICE.txt
-rw-r--r--  1 yuuki yuuki   175 Mar  4  2024 README.txt
drwxr-xr-x  2 yuuki yuuki  4096 Mar  4  2024 bin
drwxr-xr-x  3 yuuki yuuki  4096 Mar  4  2024 etc
drwxr-xr-x  2 yuuki yuuki  4096 Mar  4  2024 include
drwxr-xr-x  3 yuuki yuuki  4096 Mar  4  2024 lib
drwxr-xr-x  4 yuuki yuuki  4096 Mar  4  2024 libexec
drwxr-xr-x  2 yuuki yuuki  4096 Mar  4  2024 licenses-binary
drwxr-xr-x  3 yuuki yuuki  4096 Mar  4  2024 sbin
drwxr-xr-x  4 yuuki yuuki  4096 Mar  4  2024 share

Hadoopのセットアップ(ユーザ作成・ファイル設置など)は以下のタスクで行う。

# roles/hadoop/tasks/main.yaml

- name: Create Group
  group:
    name: hadoop
    state: present

- name: Create HDFS user
  user:
    name: hdfs
    group: hadoop
    state: present
    shell: /bin/bash

- name: Install ACL
  apt:
    name: acl
    state: present

- name: Copy Hadoop archive file
  copy:
    src: "{{ hadoop_archive }}"
    dest: "/tmp/{{ hadoop_archive }}"
    force: no

- name: Unarchive the file
  ansible.builtin.unarchive:
    src: "/tmp/{{ hadoop_archive }}"
    dest: "/opt/"
    creates: "/opt/{{ hadoop_directory }}"
    remote_src: yes
    group: hadoop

- name: Create a log directory
  file:
    path: "/opt/{{ hadoop_directory }}/logs"
    group: hadoop
    mode: "0775"
    state: "directory"

- name: Create necessary directories
  file:
    path: "/opt/{{ hadoop_directory }}/{{ item }}"
    group: hadoop
    mode: "0775"
    state: "directory"
  loop:
    - logs
    - tmp

- name: Create a symbolic link
  file:
    src: "/opt/{{ hadoop_directory }}"
    dest: "/opt/hadoop"
    state: "link"

- name: Configure workers file to namenode
  template:
    src: workers.j2
    dest: /opt/hadoop/etc/hadoop/workers

- name: Copy setting files to hadoop dir
  copy:
    src: etc/hadoop/
    dest: /opt/hadoop/etc/hadoop/
    group: hadoop
    mode: "0644"
    directory_mode: "0755"

デフォルト設定のHadoopではHADOOP_HOME(今回は/opt/hadoop)の下にlogsというディレクトリが作られ、その中にデーモンのログなどが入る。しかし、HADOOP_HOMEの権限はグループに対して書き込みを入れてないので、グループのユーザが書き込む場所(logs, tmp)は権限をいじってある。

ちなみに、"Copy setting files to hadoop dir"でやっているように、特定の設定ファイルのみをroles/hadoop/files/配下に入れて各マシンにコピーさせることもできる。これを使ってデフォルトから設定をいじれる。

SSH設定とHadoopクラスタの起動

これでJavaのインストールとHadoopのファイル群の設置が出来たので、あとはSSH設定をしてNameNodeからDataNodeに接続できるようにして、NameNodeからshellスクリプト(sbin/start-dfs.sh)を呼び出すだけで行ける。

メインとなるPlaybookは以下のようになっている。

- name: Setup Hadoop Cluster
  hosts: all
  become: yes
  roles:
    - java
    - hadoop

- name: SSH key setting (namenode)
  hosts: namenode
  become: yes
  vars:
    hadoop_users:
      - hdfs
  tasks:
    - name: Generate SSH key for hadoop users
      user:
        name: "{{ item }}"
        generate_ssh_key: yes
        ssh_key_bits: 2048
        ssh_key_file: .ssh/id_rsa
      loop: "{{ hadoop_users }}"

    - name: Fetch SSH public key from namenode
      slurp:
        src: "/home/{{ item }}/.ssh/id_rsa.pub"
      register: slurped_keys
      loop: "{{ hadoop_users }}"

    - name: Set public keys fact
      set_fact:
        public_keys: "{{ public_keys | default({}) | combine({ item.item: (item.content | b64decode) }) }}"
      loop: "{{ slurped_keys.results }}"

- name: SSH key setting
  hosts: all
  become: yes
  vars:
    hadoop_users:
      - hdfs
  tasks:
    - name: Copy SSH public keys to datanode
      authorized_key:
        user: "{{ item }}"
        key: "{{ hostvars[groups['namenode'][0]].public_keys[item] }}"
      loop: "{{ hadoop_users }}"

- name: HDFS Format NameNode 
  hosts: namenode
  become: yes
  become_user: hdfs
  become_flags: "-i"
  tasks:
    - name: Format NameNode
      command: /opt/hadoop/bin/hdfs namenode -format -force

- name: HDFS Start
  hosts: namenode
  become: yes
  become_user: hdfs
  become_flags: "-i"
  tasks:
    - name: Start
      command: /opt/hadoop/sbin/start-dfs.sh

これとinventory(各ノードのipを設定)を合わせて実行するとHadoopクラスタの構築と起動をすることができる。起動後はNameNodeの9870ポート(Hadoop 2.x.xの場合は50070)にアクセスするとHadoopのWebUIを見ることができる。

とりあえず、Ansibleを使ったHadoopの構築はいったんこんな感じ。ただ、これはまだ「構築ができる」という検証をしたまでで、設定がほぼデフォルトなので実用性はないと思う。

次やること

ここから使えるデータ分析基盤にするまでに、今のところ思いつく必要そうなものは以下のような感じだと思う。

  1. Hadoopクラスタの認証(調べたらKerberosというのが出てきた)

  2. Hadoopクラスタの適切な設定(/etc/hadoop配下の設定ファイルをいじる)

  3. Hadoopエコシステムの整備(Hive、Sparkなど)

  4. データ収集部分の構築

  5. データカタログ

  6. 予算と並列処理性能を考慮したインフラ設計

まだ解像度低いので今後変わっていくかもしれないが、直近でやろうと思うのは1と2。Hadoopクラスタ(HDFS、YARN、MapReduce)の設定と認証を調べつつより良くしていこうと思う。

この記事が気に入ったらサポートをしてみませんか?