さくらのVPSの障害でいろいろ泣かされた話

さくらインターネットのVPS(仮想専用サーバー)の連日の障害発生により、私が契約していた東京や大阪のサーバでも意図せぬ停止と再起動が行われました。

その結果、自作のサービスにアクセスできない旨のお叱りを受けて、早朝からサーバの再設定という生産性もなく、責任重大な業務に負われる事態に陥り、考えうる限り最悪の気分で一日の始まりを迎えました。

これがあるから、モバイルPCを手放せないんですよ。

消えた Nginx の設定ファイル

さて、ウェブブラウザを用いて問題のドメイン名にアクセスしてみると、ページを表示できませんというエラーメッセージが出てくるばかりです(pingが通っていたかどうかは確認しましたが、結果をメモするのを忘れました)。

This site can’t be hogefuga.piyo refused to connect.
Try:

Checking the connection
Checking the proxy and the firewall
ERR_CONNECTION_REFUSED

私はさくらの VPS 上でリバースプロキシ兼ロードバランサとして Nginx を設置していますので、エラーが表示される場合には(1)ドメインのエラー、(2) サーバのエラー、(3) Nginx のエラー、(4) アプリケーションのエラー、(5)データベースのエラーの5つの可能性を検討しなければなりません。

今回の障害が発生したサーバとは無関係なアプリケーションとデータベースは除外して、ドメインとサーバと Nginx の状態を一つづつ確認していきます。




NsLookup でドメインを確認するとドメインは正常。そもそも更新時期とも違うので念の為の確認です。サーバも SSH で正常にログインできる時点で問題なし。

システム管理デーモン (systemd) で Nginx の状態を確認すると、ここが起動できていません。OSの再起動時に自動的に立ち上がる設定になっているはずなのですが、動いていないものは仕方がないので、コマンドを実行して稼働させます。

ところが Nginx が正常に起動しません。確認してみると、設定ファイルが見当たりません。

仕方がないので新規に設定ファイルを作成して Nginx を起動させます。

ポートが開いていない問題

Nginx を起動させたら全ての問題が解決… と簡単にはいきません。

ドメイン名でアクセスしても、IPアドレスでアクセスしても依然としてウェブブラウザでウェブサイトを表示できない状態に変化はありません。

Nginx の設定で 80 番ポートのアクセスを 443 番ポートにリダイレクトしているので、開いてるポート番号を確認すると、なんと Linux ファイアウォール (iptables) 側の設定でポートが閉じられているという事態が発覚しました。

自動再起動がほとんど機能していないですね。

画面が真っ白(ブランクページ)になるやつ

ポートを開放してファイアウォールデーモンをリロードすると、ようやくドメイン名でアクセスすることが可能になりました。

ログイン認証にも無事に成功しましたので、データベース接続にも異常はありません。アプリケーションやデータベースには問題は無さそうです。

と思っていたところ、一部のページがブランクになって何も表示されません。

ブラウザの Developer Tools でソースコードを参照すると、どうやらヘッダだけは読み込んでいる様子。さらに調べていると、次のようなエラーメッセージを表示させることができました。

ERR_CONTENT_LENGTH_MISMATCH 200 (OK)

こういうのは基本的には Nginx のエラーメッセージなので、設定ファイルに以下の1行を追加して Nginx をリロードします。

server {
	proxy_buffering	off;
}

ここまで来て、ようやく正常にウェブサイトにアクセスできるようになりました。

さいわいにもアプリケーションとデータベースには障害が出ていなかったので、今回はこれだけで済みましたけれども、Nginx そのものを冗長化することも真剣に考えなければならない気がしてきました。


[24時間365日] サーバ/インフラを支える技術 ‾スケーラビリティ、ハイパフォーマンス、省力運用 (WEB+DB PRESS plusシリーズ)

ツーリング用モバイル PC の最適解か – 約 500g の 7インチ ノート PC

日常的に出張を繰り返す私にとって、モバイルPCは無くてはならない存在です。

今までにも Chromebook を Linux マシンとして利用したときの使用感や、仮想環境上にて実行できる高性能なラップトップ PC の購入について述べてきました。

通常の出張においてであれば、こうした既存の PC を持ち運ぶことに何ら不満はないのですけれども、「自転車旅でも PC を持ち運びたい」と考えたとき、さらに小型で軽量な PC への欲求が湧いてきます。

Tabキーで入力補完のできるキーボードが付属していて、ローカルで Shell scripts と Python さえ動く端末があれば、移動中の時間も無駄にすることなくデータの処理が行なえますし、VPN と SSH と Git まで用意できれば、それこそサーバ経由であらゆることが実行できます。

自転車で遠くまで遊びに行ったときの隙間時間(フェリーや飛行機で移動する場合では数時間から数日間)を活用することで、もっと自由に遊べる時間を増やせるわけです。

そんな都合が良いものが無いかと年単位で探し続けていたら、先日、ついに見つけてしまいました。


ONE-NETBOOK Technology OneMix2s(専用デジタルスタイラスペン/WPS Office スタンダード版付属)シルバー[Core m3-8100Y /メモリ 8GB/ PCIe SSD 256GB] ONEMIX2SJ-S2

キーボードと一体型の筐体に、振動で故障しにくい SSD ストレージ、本体質量 515g の重さに 6,500mAh のバッテリー容量という素晴らしいスペックながら、182 x 110 x 17 mm という手のひらサイズの体積の「ノートパソコン」です。

この大きさでタブレット端末ではなくて PC というのが最高に素晴らしいです。

軽量なタブレット端末に Bluetooth キーボードを接続する方法も、もちろん試したことはあるのですが、ファイルアクセスが面倒であったり、レスポンスが悪かったりと、ストレス無くスクリプトを書いて走らせることは困難です。




そうは言っても、普通のノート PC は薄型であっても自転車で持ち運ぶには大き過ぎますし、専用の充電器も荷物になります。また軽量モデルほど高価になる傾向がありますので、廉価モデルには持ち運びに適したものが少ないです。

Chromebook は USB 充電できることと低価格が魅力ですが、本体はあまり小型ではありません。作業用マシンとしての使い勝手もそれなりです。

タブレットは使えなくはありませんけれども、ローカルで実行できることが限定されますので、長時間の作業を続ける環境としては、いろいろと辛いと思います。

作業性 USB充電 質量 価格
ノートPC 700g – 9万円 –
Chromebook 900g – 2.5万円 –
タブレット 230g – 2万円 –
7インチPC 500g – 6万円 –

ところが、7インチPCは携帯性と作業性を兼ね備えていて、PCとしてのスペック的にも全く妥協していません。

その分、本体価格も高価なので、ツーリングに向いていない点があるとしたら(雨に濡らしたり、道路に落下させたりする可能性が高い場面で用いるPCとしては)価格が高過ぎることでしょうか。

ストレージ容量を考えるとパーティションを分割して、デュアルブートにしても良さそうだなと考えると、ますます欲しくなってきます。

仮想マシンを動かすには RAM が心許ないですが、256GB のストレージ容量は2分割しても数年前のノート PC よりも余裕がありますので、確認作業やファイル閲覧用に Windows を残しておけるのも理想的です。

購入すべきかどうかを迷っているのは、ただ一点、遊びに出かけていないときにどれだけ使用機会があるかどうかということに尽きます。

小型化のためにポインティング・スティックと特殊なキーボード配列を搭載した筐体は、通常の用途では使いにくいかもしれません。

キーボードしか使わない私のような原理主義者は OS ごと Debian で上書きすれば良いと考え始めるので、あまり問題にならないと思われるのですが、トラックパッドの方が何かと使いやすいのも違いありません。

現状ではおよそ 1kg の旧いノートパソコンに SD カードから Linux をブートして使用しています。

旧いノートパソコンとは言え、数年前のフラッグシップモデルだった PC だけに、キーボードも使いやすく、スクリーンも広くて、動作速度も快適です。

SSDストレージ容量は時代なりですし、メーカーの補修部品の在庫もそろそろ怪しいところですが、単体での作業性で見たらこちらの方が使いやすいことは明白です(ストレージ容量と稼働時間は、さすがに厳しいですけど)。

使わなくなった時点で郵送してしまえば、携帯性は考えなくても良いですし、ある意味では既に役目を終えた PC の再利用なので、事故による故障や紛失も大きな問題にはなりません。

遊びに出かけている間に使用することはないので、長い移動時間の最中にだけ手元にあれば良いことを考えると、これでも良いかなという気になってきます。

郵送が頼りにできないような場面が出てきたら、その時こそ小型モバイルPCの買い時なのかも知れません。

何れにせよ、このスペックと携行性があれば利用用途はいくらでもありますし、モニターとキーボードを外付けすれば操作性も格段に向上しますので、メイン機として考えても良いななどと思っていると夢が無限に膨らみます。

PostgreSQL 導入後 サーバに接続できないときの対処法

PostgreSQL をインストールしたばかりのとき、以下のようなエラーを目にすることがあります。

最新の PostgreSQL 11 を Ubuntu 18.04 にインストールした際にも発生することがあります。

$ psql
psql: could not connect to server: No such file or directory
    Is the server running locally and accepting
psql: サーバに接続できませんでした: No such file or directory
      ローカルにサーバが稼動していますか?
      Unixドメインソケット"/var/run/postgresql/.s.PGSQL.5432"で通信を受け付けていますか?

このときの解決策として、PostgreSQLをアンインストールして環境を再構築するという記述が、しばしば見受けられます。

それで問題が解決すれば良いのですけれども、同じ問題が再発することがあります。

私の経験上、再インストールによって解決する問題は version を指定せずにパッケージマネージャから RDBMS をインストールして、正しいファイルや設定を読み込めていないことが多いので、そうでない場合にはあまり効果が期待できないです。

では、どうするかと言うと、経験上の判断から locale settings や cluster を見に行くことが多いです。




本題に入る前に、再現性を高めるために、いつものバージョン情報とインストール時の設定を掲載しておきます。

europa@Jupiter:~$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.2 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

$ psql -V
psql (PostgreSQL) 11.4 (Ubuntu 11.4-1.pgdg18.04+1)

導入時に行ったこと
参照: PostgreSQL: Linux downloads (Ubuntu)

$ sudo apt update && sudo apt -y upgrade
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)"-pgdg main | sudo tee /etc/apt/sources.list.d/pgdg.list
$ sudo apt update
$ sudo apt install postgresql-11  -y 
$ sudo passwd postgres && su - postgres

ここまででインストールに成功すると、冒頭 Connection refused error に遭遇することがあるかもしれません。

$ psql -p 5432 -h localhost
could not connect to server: Connection refused Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? could not connect to server: Connection refused Is the server running on host "localhost" (127.0.0.1) and accepting TCP/IP connections on port 5432?

psql: サーバに接続できませんでした: Connection refused
	サーバはホスト "localhost" (::1) で稼動しており、
	また、ポート 5432 で TCP/IP 接続を受け付けていますか?
サーバに接続できませんでした: Connection refused
	サーバはホスト "localhost" (127.0.0.1) で稼動しており、
	また、ポート 5432 で TCP/IP 接続を受け付けていますか?

まずはプログラムが動いているかどうか確認します。動作していないと、そもそも繋がりません。

$ service postgresql status
● postgresql.service - PostgreSQL RDBMS
   Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor prese
   Active: active (exited) since Fri 2019-07-20 08:46:24 CST; 31min ago
 Main PID: 2178 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 1130)
   CGroup: /system.slice/postgresql.service

$ ps -ef|grep postgres
postgres 3950  2503  0 09:20 pts/0    00:00:00 grep postgres

プログラムが動作していることを確認できましたら、ソケット(プログラムとネットワークの接続口)の状態を見に行きます。

$ ss -tunelp|grep 5432

PostgreSQL に接続するために必要なところなので、きちんと動いていれば状態を確認できます。

ここの反応が今はありませんので、うまく行っていませんね。

ということで、現在のクライアント認証はどうなっているのかを見に行きます。

認証設定ファイルは "pg_hba.conf" という名前で保存されていることが伝統なので、探し出して現在の設定を把握します。

$ sudo find / -name pg_hba.conf
$

ところが、なぜか該当ファイルが見当たらないので、決め打ちで探しにいきます。

$ ls /etc/postgresql/
$ ls -a /etc/postgresql
.  ..  

そうすると、そこにあるはずのディレクトリが存在しません。

設定の問題以前に、設定ファイルそのものがありません。

ようやく、ここからが本題なのですけれども、必要なファイルが無いときは初期化したり、ツールで作成させると問題の解決につながることもあります。

$ sudo pg_createcluster 11 main --start
Creating new PostgreSQL cluster 11/main ...
/usr/lib/postgresql/11/bin/initdb -D /var/lib/postgresql/11/main --auth-local peer --auth-host md5
データベースシステム内のファイルの所有者は"postgres"となります。
このユーザがサーバプロセスも所有する必要があります。

データベースクラスタは以下のロケールで初期化されます。
  COLLATE:  C.UTF-8
  CTYPE:    C.UTF-8
  MESSAGES: C.UTF-8
  MONETARY: en_US.UTF-8
  NUMERIC:  en_US.UTF-8
  TIME:     en_US.UTF-8
そのためデフォルトのデータベース符号化方式はUTF8に設定されました。
デフォルトのテキスト検索設定はenglishに設定されました。

データベージのチェックサムは無効です。

既存のディレクトリ/var/lib/postgresql/11/mainの権限を修正します ... 完了
サブディレクトリを作成します ... 完了
max_connectionsのデフォルト値を選択します ... 100
shared_buffersのデフォルト値を選択します ... 128MB
selecting default timezone ... America/Chicago
動的共有メモリの実装を選択します ... posix
設定ファイルを作成します ... 完了
ブートストラップスクリプトを実行します ... 完了
ブートストラップ後の初期化を行っています ... 完了
データをディスクに同期します...完了

成功しました。以下のようにしてデータベースサーバを起動できます。

    pg_ctlcluster 11 main start

Ver Cluster Port Status Owner    Data directory              Log file
11  main    5432 online postgres /var/lib/postgresql/11/main /var/log/postgresql/postgresql-11-main.log

必要なファイルが揃いますと、設定ファイルも検索で見つかるようになりますし、RDBMS にも接続できるようになります。

$ sudo find / -name pg_hba.conf
/etc/postgresql/11/main/pg_hba.conf

$ su - postgres -c psql
Password: 

これでも、まだ接続できなかったらサーバ側の設定でポートが開放されているか、認証設定はどうなっているかを疑ってください。

まとめますと、インストールされた RDBMS の version と、プログラムの起動状態、クライアント認証、初期化の有無、そして IP アドレスやポートのサーバ設定などを順を追って確認していくと問題の原因に行き当たる確率が高いです。


[改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)