退職しました4
TwitterやFacebookでフォローされてる方は知っているかと思いますが、3月末で前職を退職していました。短い間ですがお世話になった皆さんありがとうございました。1年弱という社会人生活で一番短い在職期間になりました。
これまで
Hosted Embulk for TDである、DataConnector/ResultOutputという2つのサービスをメンテナンスするチームに所属していました。そこで新規/既存のEmbulkプラグインの開発、Embulk本体のメンテナンス、サービスを提供するためのアプリケーション開発、実行環境や開発環境の改善など主にバックエンド周りのことをやっていました。また、夏ごろにアメリカ出張に行ったことは人生初のアメリカということもあって、とても良い経験になりました。
現在
SEQSENSEという警備ロボットを開発しているベンチャー企業に4月から所属しています。コアとなる強みは自律移動ロボットの開発能力でロボット界隈では結構有名な会社のようです。自分が担当しているのはバックエンド周り全般で、具体的には以下のようなものがあります。メインとなる言語はGoなので勉強中です。
恥ずかしながらインタビューもしてもらったので、会社についてや転職の理由など詳しいところはこちらを見て頂ければと思います。
興味を持たれた方はぜひDMなりでご連絡いただくか、Wantedlyで応募してください、お待ちしております m(_ _)m
Goで複数バージョンを管理する
(2021.10 更新)
まあここに書いてることそのままなのですが、日本語のメモとして。
go install
でダウンロード用のバイナリを取ってきて、downloadコマンドを打つ
$ go install golang.org/dl/go1.17.1@latest $ go1.17.1 download Downloaded 0.0% ( 16384 / 135929081 bytes) ... Downloaded 0.3% ( 360448 / 135929081 bytes) ... Downloaded 4.2% ( 5685248 / 135929081 bytes) ... Downloaded 9.0% ( 12287984 / 135929081 bytes) ... Downloaded 15.5% ( 21020576 / 135929081 bytes) ... Downloaded 21.0% ( 28524528 / 135929081 bytes) ... Downloaded 28.4% ( 38616896 / 135929081 bytes) ... Downloaded 34.9% ( 47415296 / 135929081 bytes) ... Downloaded 40.7% ( 55312032 / 135929081 bytes) ... Downloaded 47.6% ( 64700416 / 135929081 bytes) ... Downloaded 53.9% ( 73203232 / 135929081 bytes) ... Downloaded 58.9% ( 80035296 / 135929081 bytes) ... Downloaded 65.6% ( 89194304 / 135929081 bytes) ... Downloaded 72.8% ( 98942576 / 135929081 bytes) ... Downloaded 79.3% (107757552 / 135929081 bytes) ... Downloaded 85.9% (116735376 / 135929081 bytes) ... Downloaded 92.8% (126205120 / 135929081 bytes) ... Downloaded 100.0% (135929081 / 135929081 bytes) Unpacking /Users/kamatama41/sdk/go1.17.1/go1.17.1.darwin-amd64.tar.gz ... Success. You may now run 'go1.17.1'
GOROOT
はgo env GOROOT
で分かるので、GoLandとかIntelliJとかで使いたい場合はそこをSDKとして指定する。アンインストールする場合はGOROOT
のディレクトリを消す。
$ go1.17.1 env GOROOT /Users/kamatama41/sdk/go1.17.1
embulk-executor-remoteserver 0.4.0 リリース
このバージョンより、Embulk clientとserver間でTLSでの接続ができるようになりました。
設定方法 (クライアント)
まず、use_tls
オプションをtrueに設定してください。サーバ側が(クライアントにとって)既知のCA証明書でサインされた証明書を使っていれば、これだけでOKです*1。
exec: type: remoteserver hosts: ... use_tls: true
そうでない場合は、CA証明書をca_cert_path
に追加してください
exec: type: remoteserver hosts: ... use_tls: true ca_cert_path: path/to/ca.cert.pem
クライアント認証が必要な場合、クライアント証明書と秘密鍵がセットになったPKCS12ファイルのパスとパスワードをcert_p12_file
で指定してください。
exec: type: remoteserver hosts: ... use_tls: true cert_p12_file: path: path/to/cert/client.p12 password: xxxxx
設定方法 (サーバ)
EmbulkサーバをTLSの終端にする場合*2、以下の環境変数を設定してサーバを起動してください
USE_TLS=true
: TLS接続を有効にするREQUIRE_TLS_CLIENT_AUTH=true
: クライアント認証を有効にするCERT_P12_PATH
,CERT_P12_PASSWORD
: サーバ証明書と秘密鍵のペアのPKCS12ファイルパスとパスワードCA_CERT_PATH
: CA証明書のパス。クライアント証明書が(サーバにとって)未知のCA証明書でサインされてる場合に必要
例えばdocker-composeで設定する場合以下のようになるかと思います
version: '3' services: server: image: kamatama41/embulk-executor-remoteserver ports: - "30001:30001" volumes: - ./certs:/root/certs environment: USE_TLS: "true" REQUIRE_TLS_CLIENT_AUTH: "true" CERT_P12_PATH: /root/certs/embulk-server.local.p12 CERT_P12_PASSWORD: xxxxx CA_CERT_PATH: /root/certs/ca.cert.pem
Gradleで動的にプラグインを適用する
モチベーション
とあるプロジェクトでgradle-release pluginを使っているのですが、DockerでJarをビルドするときにこのプラグインを設定していると .git
ディレクトリをコピーしないと(プロジェクトがGitリポジトリじゃないと)最初のbuild.gradle
の検証で失敗してしまうのですが、無駄なレイヤーが増えるのでDockerコンテナ上に.git
はあまりコピーしたくない。なので、releaseタスクを実行するときのみ上記のプラグインを有効にしたい。
方法
こちらの記事 を参考にさせてもらいました。プラグインを指定するときにapply false
をつけてallprojects
ブロックの中で指定したプロパティがあるかをを使って遅延applyします。
before
plugins { id "net.researchgate.release" version "2.8.0" } release { git { requireBranch = 'master' } }
after
plugins { id "net.researchgate.release" version "2.8.0" apply false } allprojects { if (properties.get("enableReleasePlugin") == "true") { apply plugin: "net.researchgate.release" release { git { requireBranch = 'master' } } } }
これで、実行時に -PenableReleasePlugin=true
をつけたときのみプラグインが適用されます。
$ ./gradlew release -PenableReleasePlugin=true
CicleCIでDockerイメージを再利用する in 2019
CicleCIでDockerイメージを再利用する - かまたま日記3
こちらの記事の最新版です。 現在CircleCIはバージョン2で、Docker Layer Cachingという機能がありますが、残念ながら追加のフィーが必要です。というわけで、会社とかで使っててフィーを払える方はそちらを使うとして、個人のOSS活動などで払うのが厳しい方用に普通にCircleCI 2.0のファイルのキャッシュ機能を使った方法を解説します*1
前回に比べて以下の点が変わっています
- GoのようにMulti stage buildを使って多段ビルドを行う前提 (最初のビルドのステージは
as buider
でbuilderという名前がついてます) - Docker image を完全に再利用はしないで中間イメージを再利用する (
docker build
は毎回やる) docker save
後のtarファイルを更にgzに圧縮してリストアの時間短縮を図る
注意として、自分の環境では、数百メガのキャッシュをload cacheとsave cacheするので2~3分かかるのでキャッシュを使うことによって、それ以上短縮出来なければ、総時間は変わらないか悪くなる可能性もあります。
1. キャッシュ用のディレクトリとキャッシュキーを決める
ここではディレクトリは /home/circleci/docker-cache
、キャッシュキーは毎回変えたいので {{ .Branch }}-{{ .Revision }}
を使います
- restore_cache: keys: - v1-docker-{{ .Branch }}-{{ .Revision }} - v1-docker-{{ .Branch }}- - v1-docker- - save_cache: paths: - "/home/circleci/docker-cache" key: v1-docker-{{ .Branch }}-{{ .Revision }}
2. イメージをビルドする
今回は builder
のイメージを取っておきたいので、builderの部分は別にビルドしてbuilerタグを付けています。
IMAGE_NAME=my_app CACHE_FROM="--cache-from ${IMAGE_NAME}:builder --cache-from ${IMAGE_NAME}" docker build --pull ${CACHE_FROM} --target builder -t ${IMAGE_NAME}:builder . docker build --pull ${CACHE_FROM} -t ${IMAGE_NAME} .
3. イメージを保存する
docker save
で保存するイメージを docker history
コマンドで取得します。 builder
を取ってるのがミソです。
mkdir -p /home/circleci/docker-cache image_ids=$(docker history -q my_app:builder | grep -v '<missing>') docker save ${image_ids} | gzip > ${DOCKER_CACHE_FILE}
4. イメージを展開する
Gzip化しているのでgunzipコマンドで解答して docker load
に渡します
if [ -f /home/circleci/docker-cache/image.tar.gz ]; then gunzip -c /home/circleci/docker-cache/image.tar.gz | docker load fi
全体
キャッシュファイルのパスを変数に入れて、以下のような感じになります。関係ない部分*2は略してます。
version: 2 jobs: build: environment: DOCKER_CACHE_FILE: /home/circleci/docker-cache/image.tar.gz steps: - checkout - restore_cache: keys: - v1-docker-{{ .Branch }}-{{ .Revision }} - v1-docker-{{ .Branch }}- - v1-docker- - run: | name: Load Docker cache command: | if [ -f ${DOCKER_CACHE_FILE} ]; then gunzip -c ${DOCKER_CACHE_FILE} | docker load fi - run: | name: Docker build command: | IMAGE_NAME=my_app CACHE_FROM="--cache-from ${IMAGE_NAME}:builder --cache-from ${IMAGE_NAME}" docker build --pull ${CACHE_FROM} --target builder -t ${IMAGE_NAME}:builder . docker build --pull ${CACHE_FROM} -t ${IMAGE_NAME} . - run: name: Save Docker cache command: | mkdir -p $(dirname ${DOCKER_CACHE_FILE}) image_ids=$(docker history -q my_app:${t} | grep -v '<missing>') docker save ${image_ids} | gzip > ${DOCKER_CACHE_FILE} - save_cache: paths: - ${DOCKER_CACHE_FILE} key: v1-docker-{{ .Branch }}-{{ .Revision }}
embulk-executor-remoteserverを作った #Embulk
Embulkのexecutor pluginの仕組みとネットワークプログラミングを学びたかったので、勉強がてらこのようなプラグインを作ってみました。
できること
- Embulkのタスクの実行を別に立てた専用のサーバ(以下
Embulkサーバ
と呼びます)上で実行できる - 複数サーバにタスクの処理を分散させる
- サーバとの接続が切れたときに再接続する
できないこと (TODOs)
- Maven style pluginを実行する (実行できるのはGemのプラグインのみ) *1
- LocalExecutorのscatter modeのように1つのInputを複数のアウトプットに分ける (inとoutが1:1に紐付く)
- 複数バージョンのEmbulkを使う(サーバに組み込まれているEmbulk0.9.16を固定で使用)
- セキュアな仕組み
使い方
2019/04/06時点の最新は 0.2.1
です
Embulkサーバを起動する
基本的にはDockerコンテナ上で動かすことを想定していて、DockerHubにイメージをホストしているので、それをrunすれば起動できます。クライアント(plugin)と同じバージョンのイメージを使うことをおすすめしますが、多少違ってもたぶん動きます。コンテナ側は 30001
番のポートを開くので*2それを公開します。
$ docker run -p 30001:30001 -it --rm kamatama41/embulk-executor-remoteserver 14:55:48.805 [main] INFO c.g.kamatama41.nsocket.SocketServer - Starting server..
Embulkを起動する
exec
に type: remoteserver
を指定して hosts
に起動中のEmbulkサーバのホストを登録します。
exec: type: remoteserver hosts: - localhost:30001
この状態でEmbulk runをすると、サーバに接続に行き、タスクの実行を依頼します。 もっと詳しいチュートリアルは、こちらのexample を参照してください。
中身の話
このプラグインは、指定されたEmbulkサーバとTCPコネクションを張り、そのコネクションを通じてクライアントとサーバが相互にデータのやり取りを行います。例えばクライアントからはEmbulkEmbedを構築するのに必要なタスクの情報やシステムコンフィグ、OSSのプラグインを実行に必要なgemをZIPファイルにまとめて送ったりしています。逆にサーバからはクライアントに各タスクの進捗状況を送っており、クライアント側は終了の通知が来るまで待受をします。
いわゆるWebSocket的な双方向通信をしているのですが、この仕組みを自作しました。
まあnettyとか使ってWebSocketにしても良かったのですが、あんまり依存ライブラリを増やしたくなかったのとネットワークプログラミングの勉強も兼ねてスクラッチで作ってみたかったという次第です。nsocket
は NIOで作ったノンブロッキングsocketサーバとクライアント
の略です。大変だったけど結構いい勉強になりました。
実用性があるかは微妙なところですが、よかったら使ってみて感想をいただけると喜びます。
gradle-embulk-plugin v0.5.0 リリース
Release 0.5.0 · kamatama41/gradle-embulk-plugin · GitHub
embulk_*
のタスクを実行時の config.yml
output.yml
のオーバーライドを build.gradle
内ではなくプロパティを渡すようにしました。
以前
embulk { configYaml = "myconfig.yml" outputYaml = "myoutput.yml" }
今回以降
$ ./gradlew embulk_guess -PconfigYaml=myconfig.yml -PoutputYaml=myoutput.yml
プラグインの詳しい使い方は以下の記事を参照ください。