シングルボードコンピューターにOpenStreetMapのタイルサーバーを立ててみる


タイルサーバーとはなんぞや?早い話、地図配信用のサーバーってことですね。

本家(tile.openstreetmap.org)の地図データを自由に使いまくってると利用規約に触れて怒られてしまうかアクセス禁止になることもあります。で、そうならないように自前でサーバーを用意しましょうということです。

たいそうに言うなら「Globe in My Pocket」プロジェクトです。

使ってみたシングルボードコンピューターはJetson Nanoとラズパイ4 Model B 4GB 、ラズパイ3 Model B/B+です。

JetsonやRaspberry Piはon-the-flyでタイルデータを提供するには、ちと非力です。

(でも、現状on-the-flyで運用されているサーバーは最小でCPU:2.40GHz / 12コア、Memory:8GB、HDD:2TBというスペックらしいので、シングルボードコンピューターでon-the-fly運用もそんなに遠い将来じゃないと思います。)

シングルボードコンピューターは2つの用途で使います。
1:タイルを事前にレンダリングしておく(プレレンダリング・キャッシュ)
PCが使えればそれに越したことはないですが、HDDが40GB以上消費される…ちともったいない。

2:プレレンダリングした地図をWebで配信する
シングルボードコンピューター程度でも可能ということ。
ただし一般公開ではなくプライベートネット内での使用と考えます。

具体的にはこんな感じです(Windowsアプリケーションから地図を使いたい場合です)。

(A)タイルデータ保存用ストレージ

(B)地図配信用Webサーバー

(C)地図を使ったWebサービス配信用サーバー(Apacheを使った本格派もいいですが、PHPのビルトインサーバーでも十分です)

 

日本だけなら以下の構成でいけると思います。

インターネットが無い環境でのアドホックな使い方もできます。Wi-Fi APにします。

タブレットのような端末で使います。ブラウザとGPSとWi-Fiを持ったシンクライアント端末ですね。GPSがラズパイ側にあれば、ブラウザとWi-Fiだけでいいです。

シングルボードコンピューターがJetson Nanoならもっといろいろなことができるでしょう。

 

以下はのプレレンダリングを実行する構成です。

タイルデータの保存先はNASやUSBストレージとします。

のWeb配信用サーバーの構成はもっとシンプルです。コチラのページ参照

 

OSにはUbuntu 18.04を使います。


Jestson Nanoを使う場合のMicroSD設定

MicroSDは128GBを使用(64GBでもいけるかも)

OSはJetpackです。

コチラのページ参照

稼働確認したのは最新のJetpackではなく4.2.1版です。

アカウントの設定はtileserverとしておきます。


Raspberry Pi 4 Model Bを使う場合のMicroSD設定

MicroSDは64GBを使用

OSはUbuntu 18.04.4 LTS Server、Desktop環境は不要です。以下の設定もすべてSSHで接続したCUIでまかなえます。

tileserverという新規ユーザーを作成してログインしておいてください。

コチラのページ参照


タイルサーバーの構成

Ubuntu 18.04がベースになるので、Jetsonもラズパイも同じ手順です。

Ubuntu 20.04でタイルサーバーを構成する場合はコチラのページをご参照ください。

元ネタはこちら – Switch2OSM

すこしアレンジしています。

Manually building a tile server (18.04 LTS)
マニュアルでタイルサーバー(Ubuntu 18.04 LTS)をビルドする

2020年5月にテストされました。

1:Softwareインストール

メインのOpenStreetMap.orgタイルサーバーで使用されているものと同様の最も標準的なバージョンについて説明します。
タイルサーバーはmod_tile、rendered、mapnik、osm2pgsql、postgresql / postgisデータベースという5つの主要コンポーネントで構成されています。

Mod_tileは、キャッシュされたタイルを提供し、どのタイルがまだキャッシュされていないか、または古くなっているため、再レンダリングが必要なタイルを決定するApacheモジュールです。

Renderedは、さまざまな種類のリクエストに優先キューイングシステムを提供し、レンダリングリクエストからの負荷を管理および平滑化します。

Mapnikは、実際のレンダリングを行うソフトウェアライブラリで、renderedによって使用されます。

osm2pgsql、postgresql / postgisはタイリング用のOpenStreetMapデータをデータベース化するためのコンポーネントです。

そしてApacheウェブサーバーが要求に従ってタイルデータを配信します。

これらのコンポーネントをビルドするために、さまざまな依存関係を最初にインストールしておきます。

 

 

2:postgresql / postgisインストール

「postgresql」は地図データを保存するデータベースであり、「postgis」はグラフィカルサポートを追加します。

postgisデータベースを作成します。

「postgres」ユーザーとして作業しながら、PostgreSQLデータベースでPostGISを設定します。

 

 

 3:データベースのチューニング

デフォルトのPostgreSQL設定は、OSMデータベースなどの非常に大規模なデータベースには適していません。 適切なチューニングにより、パフォーマンスが約2倍になります。

sudo nano /etc/postgresql/10/main/postgresql.conf

推奨される最小設定

保存して再起動
sudo /etc/init.d/postgresql restart

 

 

4:osm2pgsqlインストール

OpenStreetMapデータをデータベースにインポートおよび管理するためのツールosm2pgsqlを使用します。

前提条件をいくつかインストールしておきます。

ビルドします。

 

 

5:Mapnikをインストール

Ubuntu 18.04ではデフォルトバージョンを使用します。

Python2を使ってインストールされたか確認します。

python
>>> import mapnik

エラーが起きなければOKです。
Pythonコンソールから抜けます。

>>>quit()

 

 

6:mod_tile と renderdインストール

レンダリング用のmod_tileをインストールします。 「mod_tile」は、タイルのリクエストを処理するApacheモジュールです。 「renderd」は、「mod_tile」がタイルを要求したときに実際にタイルをレンダリングするデーモンです。

mod_tileのソースをコンパイル

 

 

7:スタイルシート構成

スタイルシートをダウンロードして構成します。

cartoのインストール

Switch2OSMでは最新のcartoをインストールするようになっていますが、これだと構成に失敗します。

cartoはバージョン0のものを使います。

mapnik-referenceで表示された中ならmapnikのバージョンに一番近いものをつかいます。
インストールされたmapnikのバージョンは3.0(正確には3.0.19)なので3.0.20を使います。

cartoプロジェクトをMapnikが理解できるものに変換します。

 

8:データのロード

各国のデータはOpenStreetMap Data Extractsで提供されています。

文字表示用にロケールが適切に設定できれば、お好きな国のタイルサーバーが構成できると思います。

日本のデータをロードします。元のosm.pbfファイル自体は1.5GB程度のサイズですがロードして展開すると40GBくらい消費します。

ロードに続いてデータがソートされ、インデックスが作成されます。

全体で7~8時間くらいかかります。

寝る前に実行して起きたら終わってる感じです。

なお、日本リージョンは、さらに8つのサブリージョンに分けられています。
(中部地方、中国地方、北海道、関西、関東、九州、四国、東北)

より小さな領域でよければ、どれかをロードすれば時間は短縮されます。四国でよければ10分もかかりません。関西で30分弱、中部地方で60分強といったところです。

ただosm2pgsqlの解説をみると、appendで他のサブリージョンを追加する際、隣接領域の場合は不具合が出るかも….と書かれているので注意が必要かもしれません(どう注意すればいいのかはこの辺の投稿を見てくれってことのようですが)。

まぁ、最終的に必要なのはレンダリングされたタイルデータだと割り切れば、最初から日本全体のデータベースを作る必要はないです。都度、必要な領域を含む最新のosm.pbfをロードすればテーブルが削除され、新しいテーブルが作成され、データが更新されます。

で、後は必要な範囲のタイルのみを新規作成したり、更新の場合は-fオプションで再作成すればいいと思います。

「データは常に日本全体で最新でなければならん!」というのは、商用利用以外ではレアケースだと思うんですが….。

 

他の国を追加したい場合

このページでやったように、ロケールを調べて、無ければ追加し、osm.pbfファイルをダウンロードしてosm2pgsqlでデータベースにロードします。

 

osm2pgsqlのオプションパラメータや使い方についてはこのページ参照

 

9:シェープファイルのダウンロード

ズーム率の低い、国の国境線などのためのシェープファイルがまだ必要です。
これらをダウンロードしてインデックスに登録します。
このプロセスにはかなりのダウンロードが含まれ、時間がかかる場合があります。実行中は画面にほとんど表示されません。 「openstreetmap-carto」の下の「data」ディレクトリに実際にデータが入力されます。

INFO:root:Checking table simplified_water_polygons
INFO:root:Checking table water_polygons
INFO:root:Checking table icesheet_polygons
INFO:root:Checking table icesheet_outlines
INFO:root:Checking table ne_110m_admin_0_boundary_land

だいたい12分くらいで終了。

 

たまにConnectionErrorで失敗することがあります。

ちょっと時間をおいて再実行してみましょう。

 

10:Fontsのインストール

世界中の場所で使用されている名前は、常にラテン文字で書かれているとは限りません(使い慣れた西洋のアルファベットa〜z)。
必要なフォントをインストールするには、次の手順を実行します。

 

 

11:webサーバーのセットアップ

renderdの構成

「renderd」の設定ファイルは「/usr/local/etc/renderd.conf」です。

[renderd]のセクション
num_threads=4

[ajt]セクションは、「ajt」と呼ばれる「名前付きマップスタイル」に対応しています。 XML=/home/tileserver/src/openstreetmap-carto/mapnik.xml
URI=/hot/

Apacheの構成

Apacheに「mod_tile」について通知する必要があります。

mod_tile.confを新規に作成します。

以下を追記

mod_tileを起動

次に、Apacheに「レンダリング」について通知する必要があります。
000-default.confをnanoなどのテキストエディターで編集します。

「ServerAdmin」行と「DocumentRoot」行の間に次を追加します。

Apacheを2回リロードします。
(Apacheは、実行時に再構成すると「混乱」するため、2回実行する必要があります)

 

 

12:renderdをバックグラウンドで実行

renderd.initを編集

以下のように変更
RUNASUSER=tileserver

パーミッションを変更してシステムディレクトリにコピーします。

 

 

13:タイル表示用のWebページ作成

Leafletライブラリを使ったサンプルが用意されています。

タイルを表示するために、mod_tileの「extras」フォルダーにある「sample_leaflet.html」というHTMLファイルを使ってみます。

Webのドキュメントルートは/var/www/htmlですので、ここにコピーします。
sample_leaflet.htmlはLeafletライブラリを使った地図表示用のWebアプリです。
lf.htmlという名前にしてみます。

編集してIPアドレスなどを変更します。

2か所変更

後でここにアクセスしてタイルを表示してみます。

 

 

14:レンダリング済のタイルデータをダウンロードして表示してみる

on-the-flyで実行してもストレスの元です。レンダリング済のデータを使ってみましょう。

事前にディレクトリを作っておきます。

ここに以下のサンプルデータを置きます(ズームレベル0から18までのデータ)。

データ(700MBくらいのZIP)は4sharedにアップしています。

東京23区近辺のデータです。だいたいこのへん。

ダウンロードしてSAMBAでコピーします。

sambaのpath書き換えます。
sudo nano /etc/samba/smb.conf

path = /var/lib/mod_tile/ajt

閉じて再起動
sudo service smbd restart
sudo service nmbd restart

 

Windowsの場合はネットワークから入れば「UBUNTU」という名前のアイコンが見えると思います。無ければ、ネットワークのフィールドに「¥¥IPアドレス」で入れます。

コピー後のディレクトリ構成はこんな感じです。

/var/lib/mod_tile/ajt/0 1 2 ….. 18

 

以下にアクセス

http://<IPアドレス>/lf.html

上記の東京23区付近のエリアにアクセスしてレベル18まで表示されればOK。

ズームボタンは表示されるものの、グレイの画面のままの場合

sudo chmod -R a+x /var/lib/mod_tile

で、リロードしてみてください。

 

 


レンダリングしたタイルをキャッシュする先を確保

実際にタイルを作る前に保存先を決めます。

キャッシュ先は外部ストレージにしてみます。

基本はどちらも、/var/lib/mod_tile/ajtをマウントポイントにしてストレージのディレクトリをマウントしてタイルデータをここにキャッシュします。

将来的にデータの増大などを顧慮するならNASやUSB接続のHDDを使い、地域を限定して使うならUSBメモリで十分でしょう。

 

ストレージをマウントしておきます。

NASの場合

試してみた実機はバッファローのLS210D021G(2TB)

cifsを使います。

マウントポイントを読み書き可能にしておきます。

NASのIPアドレスを調べておきます、例えば192.168.0.33だったとします。

NASのデータ保存先ディレクトリは共用フォルダー内のTileフォルダーだとします。

idコマンドでuidとgidを調べておきます。

NASのユーザー名(XXXXX)とパスワード(YYYYY)も確認しておいてください。

ラズパイの場合、例えばこんな感じになります。

Jetsonの場合エラーになりました。

マウントエラーのログを確認

無効な引数があったので削除しました。

 

USBストレージの場合

NASより簡単です。

Disk情報を確認

多分外部ストレージは
/dev/sda とか /dev/sdb と表示されると思います。

次にNASと同様にidコマンドでuidとgidを調べておきます。

例えばこんな感じでマウントします。

 

mount: unknown filesystem type ‘exfat’  というエラーが出た場合

Ubuntuはデフォルトでは「exfat」のフォーマットに対応していない….。

以下を実行して、再度マウント

 

*起動時にマウントする場合、/etc/fstabに記述

UUID=[UUID] [マウント先のディレクトリ] [フォーマット(vfat、ext4等)] defaults,nobootwait 0 0

nobootwaitでポートにストレージが無い場合に途中で起動がストップするのを回避します。

ただし、起動時マウントに失敗する場合もあります。なぜかvfatを認識してくれない。その場合はマニュアルでマウントしてください。

 


レンダリング

実行用のPerlスクリプトが用意されています。使い勝手がいいとは言えません(エラー処理や例外処理無し)が、ちゃんと動きます(^^)。

render_list_geo.plという名前でalx77によって開発されたコマンドラインPerlスクリプトを使用すると、地理座標を使用して特定の領域のタイルを自動的にプレレンダリングできます。
関連するGithub READMEには、使用方法とサンプルが記載されています。

render_list_geo.plコマンドの主なオプション
-n スレッド数、Jetsonやラズパイの場合は1CPU 4Core 、1thread/1core なので4
-m タイルの保存場所、デフォルトは’default’ですが、現設定では’ajt’になっているので、明示的に指定
参考ファイルー>/usr/local/etc/renderd.conf
-z ズームレベルの最小値
-Z ズームレベルの最大値
-x 指定範囲の経度の最小値
-X 指定範囲の経度の最大値
-y 指定範囲の緯度の最小値
-Y 指定範囲の緯度の最大値

その他のオプション(通常使わない)
-a 標準入力から読み取る代わりに、指定されたズームレベル範囲内のすべてのタイルをレンダリングする
-t タイルディレクトリ、デフォルトは/var/lib/mod_tile
-f タイルが最新なように見えても強制的にレンダリングを実行
-l 負荷がこの値より高い場合はスリープ(デフォルトは16)
-s レンダリングに接続するためのUNIXドメインソケット名

render_listのマニュアル

レンダリングしてみましょう。

念のためApache再起動

念のためrenderdを再起動

例えば淡路島、それでも十分な広さの領域です、短時間でレンダリングできるわけでもないですが、

どこにあるかはっきりしています。

こんなコマンドになります。

ズーム値が10~18なのはこのレベルが特有な領域であり、0~9は共通だからです。

0から9のデータは上記東京23区近辺データと共用できますからここからコピーして使います。

 

矩形範囲を確認するにはOpenstreeMapのExportサイトが便利です。

赤字が緯度・経度パラメータの値。例えば、ここは高知の室戸岬ですが、この範囲のレンダリングならz 10 ~18で3分くらいで終わります。

 


レンダリングしたタイルのファイル容量

ズームレベル17までと18では演算容量や時間は桁違いに異なります。でも、17と18は見た目そんなに違いがあるわけでもないです。

計算時間やストレージ容量が気になる場合は、思い切って18をやめる手もありです。

その場合は、上記13の「タイル表示用のWebページ」のhtml内でズームの上限を指定しておく必要があります。でないと、そのままズームアップすると18まで表示しようとして最後にグレイ画面になってしまいます。

leafletのL.tileLayerの指定オプションにmaxZoom:18,maxNativeZoom:17を追加することで、実際使うタイルは17までで18は17の画像を疑似拡大したものになります。

 

参考までに、ズームレベル10~18までを都道府県別の領域でタイルデータを作ると合計で190GB近くになりますが、重複するタイルがあるので結合すれば120GBくらいに収まります。

レベル0~17なら75GBくらい。

(2020/06時点でのサイズです)

ちなみに、都道府県別の矩形領域を知りたい場合は以下を参照

日本の東西南北端点の経度緯度

注意が必要なのは、例えば東京都などは最南端の沖ノ鳥島までも含む広大な領域を1矩形にしているので、これでレンダリングすると不要な海上面も計算してしまうようで膨大な時間がかかってしまいます。島嶼部は別個に矩形領域にして計算するようにした方がいいです。日本は海洋国家だということがよく分かります。

 


レンダリングに失敗した場合

頻度は多くはありませんが、それでも時々失敗して、あるレベルのデータがグレイで表示されることがあります。

レンダリングに失敗しているのですが、データファイルは作成されている状態です。

めったにない現象なので、理由は分かりません。

このままズームレベルを指定して再度コマンドを走らせてもファイルは存在するのでスルーされてしまいます。強制的に上書きする場合は-fオプションを使うか、そのレベルのフォルダーごと削除して再実行してください。


MicroSDのサイズ(数字はシステム込み)

ここではレンダリングするためのデータベースをフルセットで持つことも考慮してMicroSDは64GBにしています。

またタイルデータも持つとしたらズームレベル0~17で128GB、レベル18も持つなら200~256GB必要です。

でも、レンダリングせずにタイル配信のみでデータを外部ストレージに持たせるとしたら、MicroSDは16GBあれば十分です。

そういう構成の場合は以下のページ参照

ラズパイにOpenStreetMapの最小構成タイル配信サーバをセットアップ

 

インターネット環境が無い(使えない/使わない)場合のアドホックな構成

OSMタイルサーバーにしたラズパイをWi-Fiのアクセスポイントにしてみる

 

自分(達)だけの地図を作ってプライベートネットで使ってみましょう(準備中)

OpenStreetMapのデータを編集する

 


Appendix

 

osmconvertのインストール

適当なフォルダーへ移動

sudo apt install osmctools

wget -O – http://m.m.i24.cc/osmconvert.c | sudo cc -x c – -lz -O3 -o osmconvert

 

osmosisのインストール

sudo apt install osmosis

 

osm2pgrouting

 

JOSM

 


Be the first to comment

Leave a Reply

Your email address will not be published.


*