もう前日なのですが、コミックマーケット89に初参加します。
こんな感じの本だします。
- Hardening 10 ValueChain体験記
- クラウド四方山話「サーバレスアーキテクチャ」
- 2015年振り返りと2016年予想
東4のメ-34bに居ますので、お近くまでお越しの際はよろしくお願いいたします。
なお、これから印刷はじめつつ表紙作る感じです。
技評さんがまとめてくださっている技術系Advent Calendarを見たら目玉飛び出るぐらい多すぎたので、自分の視野を広げることも兼ねて、適当に拾った中から紹介していくAdvent Calendarをやってみようと思います。それぞれの日の記事を紹介していくので、日付変わってからの更新です(という1日付けの記事を書いているのが3日という時点でお察しください)。
というわけで12/01付けの記事を上から順にだいたい全部見ていったら二日かかりました。
Windows & Microsoft技術 基礎 Advent Calendar 2015
なんだかんだでまだまだ使う事が多いWindowsのcmd.exeです。
Windows10でもかなりUI面が向上したのが話題になっていましたが、細かく機能が追加されていたりするのをあらためて発見しました。また、コードページをUTF-8に変更する方法も載っています。
Visual Studio / Visual Studio Code Advent Calendar 2015
最近サーバサイドでコード書くことが多いのでまだ触っていないのですが、VSCode、かなり気になっています。
Julia Advent Calendar 2015
科学技術計算が得意なJulia言語の入門書がPDFでまるっと配布されています。
今年中に新しい言語を覚えたい人におすすめ。
Bootstrap Advent Calendar
ホノカチャン!!
「企業サイトのベースにも使われるようにもなるなど」、広く普及していっているようです。個人的には宗教上の理由でNicoが気になっています。
仮想DOM/Flux Advent Calendar 2015
フロントエンド開発での仮想DOMの現状まとめです。話題になって一年経ちましたね。
R Advent Calendar 2015
ビッグデータやらオープンデータやらで、データ処理の機会が増えています。
環境省が公開するデータを使いながら、「tidyデータ」というデータ形式とそれを扱うRパッケージでモダンなデータ操作を試す記事です。
PHP Advent Calendar 2015
記事を書いている時点で既にタグが打たれたようですが、PHP 7のリリース内容のおさらいです。
人工知能 Advent Calendar 2015
昨今の機械学習アルゴリズムの普及などによってふたたびバズっている人工知能ですが、汎用人工知能についてその技術を紹介していくアドベントカレンダーのようです。
今年きっちり追いかけていきたいアドベントカレンダーの一つです。
WordPress Advent Calendar 2015
Transifexというウェブ翻訳プラットフォームがあるのを初めて知りましたが、そのなかのTransifex Liveというサービスを使ってWordpressを多言語化する記事です。
コンテンツ管理(CMS)と翻訳を機能として分けるのは新しい視点でした。
Office UI Fabric Advent Calendar 2015
MITライセンスで公開されているCSSフレームワークOffice UI Fabricの紹介です。みんなだいすきBootstrapよりも「少しカッキリした(まさにオフィスアプリ的な)印象」というもののようです。
UX Tokyo Advent Calendar 2015
UXという単語が氾濫し始めてだいぶたちますが、"「UI設計」と「UX調査」"というのは分かりやすかったです。
Live2D Advent Calendar 2015
思いのほか簡単に作れるように見える……!
ドワンゴ Advent Calendar 2015
昨今はやっているAWSネイティブのアーキテクチャで作ったメディアストレージ基盤の、詳細な解説です。
はてなエンジニアアドベントカレンダー2015
実際のアプリケーション運用を踏まえた上での、丁度良い落としどころとしてchrootを利用していくという議論です。
Qiita 数学 Advent Calendar 2015
最後に求められるのが数学の知識だったりしますが、復習するきっかけに!
Payment Advent Calendar 2015
PayPalの技術スライドてんこもり。[あとで読む]。
カノジョできないエンジニア Advent Calendar 2015
初日にして完璧に落ちている……。
友利奈緒 Advent Calendar
友利奈緒が友利奈緒になった話です。
論点書き出してみたけど多すぎて超絶カオス。
7/1 午前9時(JST)にうるう秒が挿入されますが、注意すべきポイントのおさらいです。
NICTの資料の先頭7ページ目まで読んでください。
ざっくり言うと、現在の時計というのは「原子時計」が基準になっています。太陽の周りを回る公転周期に合わせて微調整するのがうるう年で、地球自体が回転する自転時間に合わせて微調整するのがうるう秒です。
現象としては、「月末」の日付が変わる直前に1秒追加されます。ただし、これはUTC(協定世界時)での話なので、日本標準時では9時間の時差があるので朝9時(の直前)になるわけです。
時間の進みを表にするとこんな感じです。
UTC(協定世界時) | JST(日本標準時) | うるう秒を知らない時計 |
---|---|---|
2015年 6月30日 23時59分57秒 | 2015年 7月 1日 8時59分57秒 | 2015年 7月 1日 8時59分57秒 |
2015年 6月30日 23時59分58秒 | 2015年 7月 1日 8時59分58秒 | 2015年 7月 1日 8時59分58秒 |
2015年 6月30日 23時59分59秒 | 2015年 7月 1日 8時59分59秒 | 2015年 7月 1日 8時59分59秒 |
2015年 6月30日 23時59分60秒 うるう秒発生! |
2015年 7月 1日 8時59分60秒 | 2015年 7月 1日 9時 0分 0秒 |
2015年 7月 1日 0時 0分 0秒 | 2015年 7月 1日 9時 0分 0秒 | 2015年 7月 1日 9時 0分 1秒 ここで1秒進んでしまう! |
2015年 7月 1日 0時 0分 1秒 | 2015年 7月 1日 9時 0分 1秒 | 2015年 7月 1日 9時 0分 2秒 |
2015年 7月 1日 0時 0分 2秒 | 2015年 7月 1日 9時 0分 2秒 | 2015年 7月 1日 9時 0分 3秒 |
2015年 7月 1日 0時 0分 3秒 | 2015年 7月 1日 9時 0分 3秒 | 2015年 7月 1日 9時 0分 4秒 |
おわかり頂けただろうか。
前回のうるう秒は2012年7月1日(JST)に挿入されましたが、このときにLinuxカーネルでいくつかの不具合が判明しました。
一番影響が大きかったものが「CPU利用率が100%に張り付く」というもので、以下のブログ記事が詳しいです。
これは「不具合」による想定外の問題でしたが、そもそも「想定内」の範囲でも以下のような問題があります。
このように、きちんと考えると闇奥が深いのがうるう秒の処理です。
比較的新しいサービスのみ面倒を見ているのであれば、おそらくうるう秒に起因する不具合もないでしょうから、全力でうるう秒を受け入れてあげるのが良いと思います。2012年以上前のディストリビューションでは上記不具合が修正されていない可能性がありますが、それ以外は特に何の問題も無く動くと期待されています。
「60秒」を保存できることを確認できているなら、right/Asia/Tokyo などのタイムゾーンに変更するとより良いです。
例えば、インターネットマルチフィードのNTPサーバから時刻を受信し、データセンター内の自前NTPサーバを立てているようなケースを想定すると、全体像は以下のようになります。
うるう秒の情報は、最終的には3つの方法で各サーバのLinuxカーネルに届きます。
うるう秒の情報は、NTPのLeap Indicator(LI)というフラグを経由して各サーバに配布されます。最新のRFC上は一ヶ月前からフラグを立てても良いことになっていますが、NICTでは以前のRFC等も考慮してうるう秒の24時間前からフラグを立てる運用となっています。
Leap Indicatorを受け取ったNTPクライアントは、adjtimex(2)というシステムコールを呼んでLinuxカーネルにうるう秒の情報を伝えます。Linuxカーネルはtime_stateという変数にそれを保存しておき、月末(UTC)になったらその変数を見て必要ならばうるう秒を挿入します。
カーネル内部のシステムクロックは正しくうるう秒を扱いますが、プロセスから現在時刻を聞かれたときには、right/Asia/Tokyo などうるう秒対応のタイムゾーンが設定されていれば、59分60秒という正しいうるう秒時刻を返し、そうでなければ59分59秒を2周するような時刻を返すようになります。2周する場合も、カーネルにより厳密にループが行われるので午前9時0分0秒(JST)になることなく繰り返されます。
標準ntpdのデフォルト設定(STEPモード)ではこの動作となります。また、ChronyではSLEWモードで設定をしていてもLinuxカーネル側でうるう秒を挿入するようです。
万が一、カーネルがうるう秒情報を受け取ってしまった後になって回避策を実施したい場合は、ntptimeコマンドでカーネル内のtime_stateを変更することができます。外部NTPサーバを参照するntpdが起動しっぱだとまた受け取ってしまうのでそちらの対応もお忘れ無きよう。
% sudo ntptime
ntp_gettime() returns code 1 (INS)
time d93c801b.a8d4dc28 Tue, Jun 30 2015 11:40:27.659, (.659498716),
maximum error 207343 us, estimated error 490 us, TAI offset 0
ntp_adjtime() returns code 1 (INS)
modes 0x0 (),
offset -30.648 us, frequency -0.114 ppm, interval 1 s,
maximum error 207343 us, estimated error 490 us,
status 0x2011 (PLL,INS,NANO),
time constant 8, precision 0.001 us, tolerance 500 ppm,
% sudo ntptime -s0
(省略)
% sudo ntptime
ntp_gettime() returns code 0 (OK)
time d93c8023.30a87000 Tue, Jun 30 2015 11:40:35.190, (.190070),
maximum error 211343 us, estimated error 490 us, TAI offset 0
ntp_adjtime() returns code 0 (OK)
modes 0x0 (),
offset -30.000 us, frequency -0.114 ppm, interval 1 s,
maximum error 211343 us, estimated error 490 us,
status 0x0 (),
time constant 8, precision 1.000 us, tolerance 500 ppm,
何らかの設定により、NTPクライアントがうるう秒の処理をする場合があります。
具体的には、ntp-4.2.6p5-1.el6、ntp-4.2.6p5-2.el6_6、および ntp-4.2.6p5-18.el7 以下を実行しているRHEL系ディストリビューションでSLEWモード(後述)を設定した場合などが挙げられます。これらの環境では、Leap IndicatorによりNTPクライアントはうるう秒を把握しますが、その情報をLinuxカーネルには渡しません。その代わり、うるう秒になったらstetimeofday(2)やclock_settime(2)などのシステムコールを用いて1秒間時刻を戻します。
カーネルの処理では無いため、一瞬だけ9時0分0秒(JST)を過ぎてから8時59分0秒(JST)に戻されます(検証例あり)。
これは、安定した結果を保障できないため、オススメできません。
このように、うるう秒を上手い具合に処理するためにいくつかの方法が用意されているわけですが、古いカーネルで動けど止めづらいサーバがあったり、サーバ数が多すぎて漏れの無い対応がし切れないなどの理由で回避が必要であれば、全力を挙げて見逃す必要があります。その為には、以下の2つをどうするかを考えなくてはいけません。
回避すると決めたら、大事なのは「うるう秒をもたず、つくらず、もちこませず」の非うるう秒三原則をどう厳守するかを考えます。
ntpdにパッチを当てることで、強制的にLeap Indicatorをクリアする方法があります。
私は未検証なので紹介に留まりますが、IBMの記事では01や10に強制セットするパッチが下部「図3」として記載されているので、00に強制クリアすることも可能でしょう。
ntpdが落ちている場合でもうるう秒が不用意に挿入されないよう、意図しないサーバでtzdataが最新にならないようにします。
なお、最新のtzdataが入っているようなケースは他のパッケージでもうるう秒の影響を受けづらいとは思います。
Leap Indicatorを除去するためには、仮想化環境でない物理サーバがあるのであれば、ハードウェアクロック(RTC)もそれなりに正確ですので、一時的に外部のNTPサーバへの参照を辞めてしまうのが一番手っ取り早いです。
前述したとおり、NICT系のNTPサーバではうるう秒の24時間前からLeap Indicatorが設定されるので、それより前からうるう秒の後まで、24時間以上を外部への参照を止める必要があります。当然ながら、RTCの品質があまりにも悪い場合や仮想サーバなどでは秒単位で時刻がずれてしまう可能性もあります。
今後Leap Indicatorが一ヶ月前から設定されるようになると現実的では無くなるでしょう。それまでにはうるう秒を誰もが受け入れられる優しい世界か、なんらかの代替策が用意されていると嬉しいです。
うるう秒を無視するためには、その1秒を何らかの形で「より影響が少ない方法」で反映する必要があります。これは、時計をゆっくり動かして1秒を生み出すのが一般的です。実際に、パブリッククラウドのAWSやGCP、携帯キャリア、東京証券取引所などではこのやり方を採用しています。
一般的には、ntpdのSLEWモードを使う事になります。特に自前でNTPサーバを立てず、NTPクライアント側で設定を入れるのであれば、「-x」オプションを付ければ良いです。ただし、前述したとおりNTPのバージョンによってはSLEWモードにしていても、うるう秒だけは1秒ガツンと戻されるような不具合がすぐ最近まで残っていたので、注意が必要です。
その一方で、前述の図のように自前NTPサーバを立ててそこを参照しているような場合は、NTPクライアントの設定によりNTPサーバに時刻を聞きに来る頻度がデフォルト設定でも1024秒(約17分強)だったりするので、NTPサーバに「-x」オプションを付けるだけではダメです。また、自前NTPサーバも冗長化している場合にはそのサーバ間での時刻同期も重要となってきます。
このように、結構厄介な地獄が待っていますが、詳しくはそのうちどっかで記事に載るのでは無いでしょうか(他人事)。
(2016-07-04追記) 掲載済みです⇒ CyberAgentでの「うるう秒」対策
今年は、2015/07/01 08:59:60 JST としてうるう秒が挿入されます!(うるう秒実施日一覧)
「うるう秒なんてきちんと処理したくない」という人向けのまとめ。
前後10時間ずつ、計20時間かけて調整
うるう秒直後時点で1秒時計が先に進むが、そのあと少しずつ修正される。
Leap Indicatorフラグを元に、うるう秒直後に1秒巻戻る。
23:59:59.000000(→ 23:59:59.999999)→ 23:59:59.000000 → 00:00:00.000000
【ドメイン コントローラーの場合】
(略)
つまり、NTP Server との時刻差が 5.25 秒未満、もしくは 3.5 秒未満の場合は、Slew モードで時刻同期が行われる結果となります。【ドメイン メンバー サーバーの場合】
(略)
つまり、NTP Server との時刻差が 225 秒未満、もしくは 150 秒未満の場合は、Slew モードで時刻同期が行われる結果となります。【ワークグループの場合】
(略)
つまり、NTP Server との時刻差が 1 秒未満の場合は、Slew モードで時刻同期が行われる結果となります。
この中だと「0.5秒ずらしておく」で丁度良い人が多そうだけどAWSとGCPでも実装が異なるし、基盤をまたいで時刻を統一するのは諦めた方が良さそう。0分0秒の方をきっちり合わせたい人が多そうだから、あらかじめ最大1秒進めておくのもアリなのではと思うけど、そういう実装はないようだ。
エンタープライズ用途とか、0分0秒の厳密さが求められる場合には、マルチフィードみたいな正しくLeap Indicatorを実装したNTPサーバと同期する必要したうえで、その場合もミドルウェアやアプリケーションが正しくうるう秒(59分60秒999999)を扱えることを確認する必要がある。
This issue affects all x86 and x86-64 based HVM Xen and QEMU/KVM guests, regardless of their machine type, because both PIIX and ICH9 based QEMU machine types create ISA bridge (ICH9 via LPC) and make FDC accessible to the guest. It is also exposed regardless of presence of any floppy related QEMU command line options so even guests without floppy disk explicitly enabled in the libvirt or Xen configuration files are affected.