解せぬ日記

雑な話をする

Arch Linuxでffmpegの依存解決に失敗する

今日、ArchLinuxのパッケージをいつものようにアップデートしようとしてハマった。解決策がネット上に見当たらなかったので書いておく。

遭遇したエラーは以下のような感じだった。

$ yaourt -Syua                                                                  
[sudo] password for terut:                                                      
:: Synchronizing package databases...                                           
 core is up to date                                                             
 extra is up to date                                                            
 community is up to date                                                        
 multilib is up to date                                                         
 archlinuxfr is up to date                                                      
error: failed to prepare transaction (could not satisfy dependencies)           
:: Starting full system upgrade...                                              
resolving dependencies...                                                       
looking for conflicting packages...                                             
error: failed to prepare transaction (could not satisfy dependencies)           
:: unable to satisfy dependency 'libx265.so=160-64' required by ffmpeg          
No database errors have been found!

どうやら依存が上手く解決できないように見える。 ffmpegのバージョンは 4.0.2-3 が入っていて、ffmpegのパッケージのバグページを見てみると 4.0.2-6 で直るらしいことが分かった。

bugs.archlinux.org

データベースのアップデートをしてもffmpeg4.0.2-4 しかなかったので、仕方なくffmpegのパッケージサイトからミラー経由でダウンロードして直接入れた。

Arch Linux - ffmpeg 1:4.0.2-6 (x86_64)

右上の [Download From Mirror] からダウンロードできる。 ダウンロードしたら直接インストールしてしまう。

$ yaourt -U ~/Downloads/ffmpeg-1_4.0.2-6-x86_64.pkg.tar.xz                      
resolving dependencies...                                                       
looking for conflicting packages...                                             
error: failed to prepare transaction (could not satisfy dependencies)           
:: installing x265 (2.9-1) breaks dependency 'libx265.so=160-64' required by ffm
peg                                                                             
loading packages...                                                             
resolving dependencies...                                                       
looking for conflicting packages...                                             
                                                                                
Packages (2) x265-2.9-1  ffmpeg-1:4.0.2-6 
...

エラーが出ているが、これは現在のffmpegのバージョンによるエラーっぽい。ffmpeg4.0.2-6libx265.so=165-64 に依存しており、x265-2.9.1libx265.so=165-64 として提供している。依存関係からすると同時にインストールしてしまえば問題なさそうだったのでインストールした。 結果として、ffmpeglibx265.so=165-64 版の共有ライブラリに依存するようにインストールされていたので良さそうに見える。 ひとまずこれで全体のアップデートができるようになった。 すでに ffmpeg4.0.2-6 がデータベース側にも反映されてるので、同じように依存でアップデートできないぞという人は参考にしてほしい。

GCPの検証・本番環境をTerraformで上手く管理する方法

Goodpatch Advent Calendar 2017 - Qiita の24日目は @terut がお送りします。

さてさて12月24日ですが、みなさんリア充してますか? 24日は若者に書かせるわけにいかないので、24日のアドベントカレンダーはおっさんの仕事というのが相場のようです。

最近GCPの管理のためにTerraformに入門しました。入門しながら思ったのが、検証の目的に合わせて複数の環境を作るのが面倒くさいということです。Terraformで管理する場合、Terraform用のサービスアカウントを用意したりするのですが、普通にやってしまうとプロジェクト毎にTerraform用のサービスアカウントを準備しなくてはならず、さらにビリングアカウントへの紐付けをある特定の人へお願いしたりという作業が発生します。もうちょっといい方法がないものかと思って色々と調査をしたところ、GCPのリソースは階層構造を持っておりIAMポリシーは継承されるので、それを上手く使うのがよさそうな雰囲気を感じて、試してみました。

TL;DR

前提条件

組織で管理する中でどのように階層と権限を設計するかという話だったので、一応環境を揃えるために組織で管理する環境を作りました。自分のドメインがあれば、Cloud Identityを使って申請できます。ドメインを自分のものであると証明するために、DNSへTXTレコードかCNAMEを登録する必要がありますが、15分程度あれば登録して、組織で管理された環境を作れます。なおドメインに関連したアカウントを作る必要があり、そのアカウントにも$300が有効にできるので、今回のこの方法でお金がかかることはないですが、ロボットでないことを証明するためにクレジットカードは入れなければなりません。

support.google.com

環境の構築方法

基本的は上に紹介した Managing GCP Projects with Terraform  |  Google Cloud Platform Community  |  Google Cloud Platform の流れに沿って環境を作っていくことになります。IAMのポリシーの継承を上手く使うため、Adminプロジェクトを作り、その中でTerraformで管理するためのサービスアカウントを発行し、他のプロジェクトを管理する権限を与え、すべてのプロジェクトをそのサービスアカウントで管理するというイメージになります。

https://storage.googleapis.com/gcp-community/tutorials/managing-gcp-projects-with-terraform/diagram.png

一通りリンクの手順を試してみると分かりますが、このままではAdminプロジェクトで管理された一つのtfstateファイルに変更が反映されていきます。そこでTerraformのworkspaceの出番です。

$ terraform workspace new staging

これを実行するとAdminプロジェクトのCloud Storage上には staging.tfstate が出来ているのが分かると思います。workspaceの値はtfファイル内で参照できるので、ディレクトリでtfstateファイルの置き場所を分けたりといったことも出来そうです。Terraformのworkspaceを上手く使いながら、一つのTerraform用のサービスアカウントを用意することで、すべてのプロジェクトが管理できるような感じがしますね。

まとめ

GCPのリソース階層へのIAMポリシーの継承などを使い、管理用のサービスアカウントを用意することで、すべてのプロジェクトで同じような手作業をするということが避けられ、ほぼすべてをTerraformに任せられそうです。入門したてなので、もっといい方法や普通はこうやるんやでなど、色々なアドバイスをお待ちしてます。

そういえばまったく関係ないんですが、12月25日は僕の誕生日でした。いつものやつ貼っておきますね!

http://amzn.asia/8zIyv8F

「ですます」であまり書かないので不思議な気持ちやな〜。

画像ビューアを作ってみている話

macOS用の見開き画像ビューアがほしいなぁと思い、車輪の再発明をすべく画像ビューアを作り始めた。最初Electronで作っていて、最小の機能の付いたそれっぽいものを作った段階でいかんともしがたい問題にぶつかり、一旦、他の技術も見てみようと、QtのGoバインディングで作り直してみてる。

成果

何はともあれ成果です。

vimeo.com

vimeo.com

Electronの問題

Electronで一通り作り終えた時に、サムネイル画像のキャッシュなどを作らずにオリジナルで表示してたので、メモリの使用量がどんなものになるのか気になって調べた。いろいろ調べているうちに、macOSで画像を切り替えまくると爆速でメモリが1.5GBぐらいまで増加していくことが分かった。画像自体は全体で110MBほどなのでいくら何でもひどい。待っていても開放される気配は一切なく、Chromeのプロファイラを見た限りではJS Heapなどはたいしてメモリを食っていなかったのとGCは走ってるように見えたので、DOMリークなのかなと思っている。とにかく何をしても解消しなかった。Chromiumの複数バージョンを試して、それっぽいバグは再現できたけど、既にバグ報告はしてあり最新版では再現しない。加えてWindowsLinuxでは特に問題なくてメモリも開放されてるので、内部のChromiumのバージョンが上がったら直りそう。ちなみに次のバージョンでは直ってなかった。

QtのGoバインディング

github.com

上記のやつを使っている。ただデバッグがやりにくくて萎えそう。独特の文法みたいなものが必要にはなるものの、サンプルも結構用意してあるので、それを読めば割とイケる。

https://github.com/therecipe/qt/tree/master/internal/examples

Qt自体はQMLというインターフェースのためのマークアップ言語を用意していて、Javascriptが利用可能でJavascriptにロジックを追いやったりできるので、そこはとっつきやすい。ちなみにQtの最新版である1.9.1を使っていたら、QMLのImageでメモリリークが起こっていて、笑うしかなかった。バージョンを下げて対応した。

今後

QtのGoバインディングのデバックについて、もうちょっといいやり方がないか調べたりして、知見ためたい。もう少し試してみて、ElectronかQtのGoバインディングにするか決めようと思っている。

雰囲気でマイクロサービス入門をやってみた

ごんげお兄さんのエントリーを見て、興味あったのでやってみた。

gong023.hatenablog.com

TL;DR

  • お兄さんのエントリー通りやると、雰囲気が分かるので超お勧め
  • 動かしてからドキュメント眺めたらいいと思う
  • GCP初めての人は$300のクレジットが貰えるぞ!

ありがたいなぁ。

補足

僕の環境はArch Linuxでかつ、GCPを触るのが初めてだったこともあって、いくつか追加の作業が必要だったのでそれだけ書いておく。最初にGCPのアカウントを開設して$300のクレジットを貰っておくように。

コマンドラインツールのインストール

AURにある。

$ yaourt -S google-cloud-sdk
$ gcloud auth login

# /opt以下に入るのでsudoで実行
$ sudo gcloud components install kubectl

初めてのコマンド前に認証が必要。ターミナルのコマンドからブラウザが起動してターミナルに処理が戻るの初めて見たかも知れない。

結構頑張ってついて行ってるのに、out-of-dateフラグ立てられてるのがかわいそう。僕もheroku-cliパッケージでたまに立てられるので気持ちは分かる。

コマンドラインツールの設定

リージョンやらプロジェクトやら色々設定しておいたほうが毎回オプションを渡さなくて済む。configの設定については https://cloud.google.com/sdk/gcloud/reference/config/set を眺める。

$ gcloud config set project micro-sample-XXXXX

Container Registry 有効化

dockerのimageをpushする際、Container Registryというサービスにpushするのだけど、これは有効化されてないとpushできない。ブラウザのコンソールから有効化するとよい。

環境変数の設定

対象のコードではBACKEND_SERVICE_NAMEという環境変数を使ってるので、その設定がいる。暗号化の仕組みも用意されてそうだった。バックエンドのIPを見たら設定しておく。たぶんドキュメントとかにコマンドラインとかから渡す方法が書いてあるんじゃないのって思ってるんだけど、どうなんすかね?

2017/10/06 追記

お兄さんにDNSあるよって教えてもらったので、そっちを使うほうが良さそう。IP変わるのでおっしゃる通りすぎる。コメントを参照のこと。ハマりどころがあって勉強になったぞ!!!!!!!1

ドキュメントによればKubernetes 1.3からDNSがビルトインされたようで、Serviceの名前がfooでKubernetesのネームスペースがbarの場合、foo.barで対象のServiceのクラスタIPが解決できる模様。ネームスペースやDNSの様子は以下のコマンドで眺められた。

$ kubectl get namespaces                                                                                         
NAME          STATUS    AGE                                                                                    
default       Active    19m                                                                                      
kube-public   Active    19m                                                                                      
kube-system   Active    19m 

$ kubectl get svc --namespace=kube-system                                                                        
NAME                   CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE                       
default-http-backend   10.31.249.157   <nodes>       80:31925/TCP    21m
heapster               10.31.247.113   <none>        80/TCP          21m
kube-dns               10.31.240.10    <none>        53/UDP,53/TCP   21m
kubernetes-dashboard   10.31.245.255   <none>        80/TCP          21m

$ kubectl get svc --namespace=default                                                                            
NAME                            CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE                                 
kubernetes                      10.31.240.1    <none>         443/TCP        22m                                 
micro-sample-service-backend    10.31.244.62   <none>         8000/TCP       17m                                 
micro-sample-service-frontend   10.31.249.64   XX.XX.XX.XXX   80:32186/TCP   21m

ということで、バックエンドはmicro-sample-service-backend.defaultで引けることになる。 ちなみにPodの中にはresolv.confが用意してあって、ドキュメントに書いてあるように以下のような定義になっている。

$ kubectl get pods
NAME                                               READY     STATUS    RESTARTS   AGE
micro-sample-backend-deployment-3300239719-22qdm   1/1       Running   0          38m
micro-sample-backend-deployment-3300239719-mpjh9   1/1       Running   0          38m
micro-sample-frontend-deployment-836517767-3vgzv   1/1       Running   0          10m
micro-sample-frontend-deployment-836517767-vbbrp   1/1       Running   0          10m

$ kubectl exec -ti micro-sample-frontend-deployment-836517767-3vgzv -- cat /etc/resolv.conf
nameserver 10.31.240.10
search default.svc.cluster.local svc.cluster.local cluster.local c.micro-sample-XXXXX.internal google.internal
options ndots:5

なのでネームスペースがdefaultの場合は、micro-sample-service-backendだけでも引けるわけだけど、ネームスペースがいつもdefaultとは限らないので、ネームスペースと組み合わせた名前で指定しておくのがいいと思う。

追記終わり。

...
     containers:
      - name: micro-sample-frontend
        image: gcr.io/micro-sample-XXXXX/micro-sample-frontend:v0.1
        env:
          - name: BACKEND_SERVICE_NAME
            #value: 10.31.XXX.XXX
            value: micro-sample-service-backend.default
        ports:
...

Podの削除

せっかくなので、Podを消してみると不死鳥のように蘇る様子を見ることが出来る。

$ kubectl get pods
NAME                                               READY     STATUS    RESTARTS   AGE                            
micro-sample-backend-deployment-3300239719-ghw8q   1/1       Running   0          5m                             
micro-sample-backend-deployment-3300239719-h8nwp   1/1       Running   0          5m                             
micro-sample-frontend-deployment-602895698-qrwfk   1/1       Running   0          4m                             
micro-sample-frontend-deployment-602895698-ts2kr   1/1       Running   0          4m

$ kubectl delete pod micro-sample-backend-deployment-3300239719-ghw8q 
pod "micro-sample-backend-deployment-3300239719-ghw8q" deleted

$ kubectl get pods
NAME                                               READY     STATUS    RESTARTS   AGE                            
micro-sample-backend-deployment-3300239719-h8nwp   1/1       Running   0          6m                             
micro-sample-backend-deployment-3300239719-ppzf9   1/1       Running   0          9s                             
micro-sample-frontend-deployment-602895698-qrwfk   1/1       Running   0          5m                             
micro-sample-frontend-deployment-602895698-ts2kr   1/1       Running   0          5m

ありがたいなぁ。

電源が入ってないiPhoneやAndroid端末を見つける技術

本日、Android端末を落とした。多分タクシーに乗っているときだと思うけど、ちょうど領収書をもらってなくて、タクシー会社名も分からなければ車両番号も分からないという状態で困っていた。幸いにも世の中は便利になっていて、iPhoneAndroid端末の位置を調べたりできるのだけど、僕の場合は気づいた時間の1時間前ぐらいから場所が拾えなくなっていた。つまり電波が入ってないか、電源が切られている状況で、普通に端末を探す方法は使えなかった。なので、ロックしてメッセージを出したり、着信音を強制的に鳴らしたり、リモートでデータを消したりとかそんなことはできない。そんな時にどうして見つけ出したかという話を書いておく。

TL;DR

  • タクシーの領収書は必ずもらいましょう。
  • Google Mapのタイムラインを使いましょう。

f:id:terut:20170913203009p:plain

探し出した流れ

Google端末を探すで表示される位置は結構ラグがあるみたいで、1時間前にある場所はよく分からないマンションの前を指し示していた。あーこれは後の乗客にパクられたかなと思っていたのだけど、タイムラインから表示してるような旨のメッセージが出ていたので、Google Mapのタイムラインから今日の移動経路を見てみると隣町の警察署で止まってる感じだった。え、位置情報違うじゃんって思いながらも、3時間ぐらい警察署の位置で止まってるような表記だったので、警察署に電話して落とし物係に繋いでもらい、この時間帯にこういう端末が届けられてないかという確認をしたら、それっぽいものがあるとのことだった。どうも照会するのにSIMの製品番号が必要だったので、携帯ショップに行って事情を説明すると、電話番号の入力で警察署にあることが分かり、拾得物番号、受理番号、SIMの製品番号などをメモしてもらって、警察署に電話を折り返して照会したら端末があるとのことだった。あとは受け取りに向かい、身分証明とメモを渡して、サインを書けばOKだった。イースタンモータース東京とかいうタクシー会社の運転手さんが届けてくれたとのことで、有り難しだった。まあなんでタイムラインで表示されている位置が変な場所なら、諦めて紛失届を警察に出して枕を濡らしながら待つとよい。

追記

疑問

そういえば電源はどの時点で切られたのか?警察署?タクシーの運転手さん??警察署に行った段階で必ず電源切られるとなるとなかなか厳しいのかもしれない。

近況報告

f:id:terut:20170908152513p:plain

僕の知り合いへ向けての報告です。7月中旬に海外から住所不定無職として日本に帰ってきました。7月中は実家に帰省していて、8月に関東へ戻ってきて日本の住所を得た結果、現在のステータスは無事に住所一定無職です。正確には7月末日付の退職でした。

元々自分の好きなことでもやりながらしばらくはフラフラするかーと思っていたんですが、8月はプライベートな問題で色々ゴタゴタしていたこともあり、あっという間に9月になった感じでした。自分が使う用の画像ビューアが欲しくて、絶賛車輪の再発明中ということで、暇があればコードを書いたりしてましたが、太陽フレアの影響もあり、そろそろ職探しでもするかーという気持ちになってきたので、職探しします。ずっと新規サービスばっかり開発してきたのですが、今後は開発者やデザイナーを後押しするようなツールやサービスを開発してご飯を食べていきたいなと何となく思っています。

恥ずかしながら転職するのは初めてなのだけど、職歴って前にLinkedInにまとめたやつがあって、こんなんでいいのかな?

https://www.linkedin.com/in/terunori-togo-03ab4511b/

とりあえず無職になって思ったことは健康保険の任意継続の便利さは異常

相談

ところで画像ビューアをElectronで作ってんですが、img.src切り替えるとメモリ積まれていってて、色んなリークを疑って最小構成にしても起こったんですが、Chrominumが抱えてるバグが直ってないだけなんですかね?そんなこんなでQtのgolangのbindingを見つけたんで、そちらで作り直してる感じですが、最新版の5.9.1でもImageのソースを切り替えるとメモリリークするバグにぶち当たり最高なので、Qtやりましょう。

例のヤツ

http://amzn.asia/1X52w1M

Arch LinuxのHeroku CLIパッケージのメンテナになるまでにやったこと

メンテナになったと言えば聞こえは非常にいいのだけど、つまるところArch Linux用のHeroku CLIパッケージがなかったので作って公開して使えるようになったということだったりする。まあサイトにはメンテナとして名前が載ってるし、メンテナなんだろうと思う。何らかのOS用のパッケージ配布自体は初めてで、作る上で色々と人々に教えを乞うたら、Arch Wikiには書いてなかった気がすることも教えてもらえたのでまとめておくことにした。

f:id:terut:20170611171250p:plain

成果

何はともあれ、成果になります。

aur.archlinux.org

モチベーション

パッケージを作っていた時点のGo/NodeベースのHeroku CLIのドキュメントには、Apt以外で管理する場合、スタンドアロンバージョンを使うように書いてあり、自分でファイル管理をしないといけなかった。とにかくパッケージとしてシュッとインストールしたり、アンインストールしたかった。作っていた時点と言ってるのは今はドキュメントが変わっているからで、それについてはあとの方で触れようと思う。

パッケージの作り方

Arch LinuxではPKGBUILDというファイルを使ってパッケージのビルドの手順をシェルスクリプトで書いていく感じになるのだけど、まず最初はArch Wikiをよく読むとよい。パッケージに関してもArch Packaging Standardsとして基本的な作成方針がまとめられている。他にも基本的な作り方であれば、ググれば見つかるのでそういう類の情報は書かない。勢い良くブラウザバックして別のページを探すとよいと思う。

Arch packaging standards - ArchWiki

最初作ろうとしたもの

僕が作り始めた当初はGolang/Nodeで書かれたHeroku CLI v5がGithubのmasterで開発されていた。プラグイン機構がNodeで実現されてるからだと思う。Nodeベースのv6系もリリースはされてはいたが、v6ブランチ上で開発されていたのとGolangのコードがまだあったため、masterで開発されているGolang/NodeのHeroku CLIをパッケージ化しようと試みた。ただHeroku CLIはそれ自身に自動アップデートの機構をもっているため、バージョン指定でバイナリを取得できず、ステーブルという形でのダウンロードになってしまって、どのバージョンなのか分からない状態だった。VCSなどから直接コードを持ってきてビルドするタイプのパッケージは、gitコマンドなどからバージョンを取得してパッケージのバージョンを動的に決めていたので、それを真似してダウンロードしてきたバイナリの実行結果からバージョン情報を解析してバージョンをつける方式をとった。

最初のレビュー

基本的なことは既に述べたようにPackaging Standardsを読めば分かるわけだけど、不安がある人はBBSとかでレビューしてもらいましょうと書いてあったので、作ったPKGBUILDのレビューをお願いしてみた。そうするとWikiに書いてなかったようなアドバイスを色々ともらえた。

  • ダウンロードしたものの検証にはsha512を使ったほうが良いこと
  • 検証をSKIPする指定は、VCSなどからのソースビルドをするようなパッケージに使うこと
  • pkgver()はVCSを使うパッケージ用なので使うのはやめたほうがよいこと
  • バージョンを固定できないため、VCSで使うような方法をワークアラウンドとして採用してるみたいだけどセキュリティホールになるので、バージョンが固定されたアーカイブを探したほうが良いこと
  • ライセンスファイルのコピーの正しい方法
  • installコマンドを使ったほうが良いこと
  • メッセージを出すためにはprintじゃなくてechoやcatとヒアドキュメントを使うこと
  • ~/.local/shareなどのHOMEをいじるようなメッセージは出さないこと
  • HOMEをいじるような場合はスクリプトを用意し、かつ"${XDG_DATA_HOME:-~/.local/share}“のようにXDG_DATA_HOMEを使うこと
  • ソースとバイナリはライセンスが違う場合があること

それでバージョンを固定するには自分でビルドするしかないなと思ったのだけど、Golang/Nodeで書かれているため、普通のgo buildとかではなく、Makefileと格闘するハメになった。

Herokuへの問い合わせ

Makefileでやるのはビルドできなすぎて辛すぎたので、Heroku Supportで問い合わせしてバージョン固定でバイナリをダウンロードできないのか聞いてみた。そうするとNodeバージョンを使うと良いよというアドバイスと共に、Heroku CLIのドキュメントを見てと言われたので眺めてたら、全体的にアップデートされ、ArchやBSDは自動アップデートなしのNodeバージョンを使ってくれという感じになっていた。GithubのmasterもNodeベースに切り替わっていてGolangの実装は全てなくなっていた。CLIのコア部分はcli-engineというFrameworkに依存してたので、Golangの実装はv6で使ってなかったのかも知れないし、以前から切り替える計画があったのかもしれないけど、問い合わせてから2-3日でやるのはさすがに強い。これが世界のやっていきですかという気持ちになった。結果としてNodeのライブラリとしてバージョンを指定してインストールするパッケージを書けば良くなった。

2回目のレビュー

1回目のレビューの時と違い、Nodeのライブラリをパッケージとして提供してるものは既にあったので、探してマネをした。ただAURで公開されてるライブラリは正しいやり方をしてないものも多いし、PKGBUILDのオートジェネレータがおかしなビルド方法を提供していたりるので、気をつけたほうが良さそうだった。既にコミュニティパッケージになっているものを参照してリリースにこぎつけた。正直Nodeとnpmがあれば普通にインストールできるのだけど、Node使う環境にいない人にとっては、依存を解決して全部入れてくれるし多少は便利かなと思ってリリースすることにした。レビューのスレッドを一応貼っておく。

[SOLVED] PKGBUILD review request: heroku / Creating & Modifying Packages / Arch Linux Forums

最終的なPKGBULDの様子。

github.com

今の悩み

めちゃめちゃHeroku CLIのリリーススピードが早くて、一日に2回リリースされたりとかザラだったりする。そんな感じなので最新バージョンに違いが出やすくて、マイナーバージョンの違いでもOut-of-dateフラグ、つまり古いぞフラグをパッケージにつけるマンがいる気配を感じている。僕はどうしたらいいんだろうか。

まとめ

とにかくHeroku強い。世界のやっていきを見た。