Blogaomu

WEBアプリケーション開発とその周辺のメモをゆるふわに書いていきます。

Kanazawa.rb meetup #92 に参加しました #kzrb

今回もオンライン開催のmeetupでした。

meetup.kzrb.org

kzrb.doorkeeper.jp

もくもく会

今回は、CloudFormation用JSON SchemaをVSCodeで利用しているのですがエラーが出ているので調査していました。現象については以下にまとめました。そこまで致命的なエラーというわけではないです。

github.com

JSON Schemaでは $ref というキーワードを使い特定のスキーマを参照できます。今回の問題ではこの参照先がファイル内に存在しないことでエラーが出ている模様でした。$ref に関しては以下を参照。

json-schema.org

具体的には AWS::ResourceGroups::Group の Tags という定義で、もくもく会のときに見たときは List of JSON というタイプだった記憶があるのですがこの記事書いている時点では List of Tag というより具体的なタイプになっています。もしかするとJSON Schema側を更新すれば解決するかもしれないですね。

docs.aws.amazon.com

作業環境とお題について

話は変わってもくもく会時の手元の作業環境ですが左半分にブラウザを、右半分の上部にSlack、下部にZoomをそれぞれ配置していました。本当はZoomを全画面にしてというのが理想的ですが作業しながら他の人の顔も見たかったのでこんな感じにしていました。別モニターにZoomを常時表示するのもいいかもしれませんね。

この画面をキャプチャしたのはもう一つ意図があります。作業中に「もくもく会でやることを毎回悩むのだけどみなさんどうやって見つけてますか?」という質問があり、私はまさにこのキャプチャ内のやりたいことリストというのを用意しています。調べてみたいことや作りたいことを思いついたときにメモしておいて、もくもく会当日にリストから選ぶという運用をしています。選ぶ基準はその時の気分ですw

f:id:TAKAyuki_atkwsk:20200426110102p:plain

他の人の話を聞いた感想など

  • Rubyの右代入演算子について(http://secret-garden.hatenablog.com/entry/2020/04/10/195207)
    • イデアはとても興味深い
    • プログラム書く側の考え方として、メソッドチェーンして最後に値を変数に入れるというのが新鮮だった
      • もしかすると日本語的な世界観???
    • irbなどのreplではざっと書いたものを逐次実行するので有用なのではと思う
      • 要するにコードスタイルはともかく実行結果がほしいので
      • ファイルに書くときは可読性の問題で左に変数があるスタイルで統一されている方がよいと思った
  • Rust
    • 学習コンテンツ(https://doc.rust-lang.org/book/index.html)
      • 本のようなフォーマットできれいだなと思っていたらmdBookというツールで作られているとのこと
    • 変数は基本的にイミュータブルという話が出てきて、驚いている参加者が多い印象があって逆に驚いた
      • たぶん慣れの問題で、私はScala関数型言語を触る機会が多いので一般的な感覚だった
      • 最近出ているプログラミング言語はイミュータブルな変数を採用しているものが多い気がする
      • こういうのは極論になりがちだけど、適材適所だと思う(私は基本的にはイミュータブルにしておいてループ内とか局所的にミュータブルな変数を使うというのはあり派)
      • 少しだけこの話(ミュータブルの方がいい例)に触れている発表がScalaMatsuri 2019で行われたので興味ある方はどうぞ
  • Cuprite - Headless Chrome driver for Capybara
    • 気になる

懇親会

懇親会は引き続きZoom上で行われました。途中退出したりまた戻ってきたりできて自由度が高くて良いですね。

f:id:TAKAyuki_atkwsk:20200426094132p:plain

作業用EC2インスタンスを cloud-init で準備する

AWS環境で単発の作業用サーバー(例: 負荷テストツールの実行用)を楽に準備したくて cloud-init を利用する方法を調べました。EC2インスタンスの起動時にユーザーが定義した設定を行ってくれる仕組み(= cloud-init)があり、この設定をユーザーデータという形でEC2インスタンスに渡すことができます。

cloudinit.readthedocs.io

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html

要件

  • プライベートサブネットに配置
  • デフォルトの ec2-user ではなくて、特定のユーザーでSSHログインしたい(公開鍵認証)
  • OpenJDK8 と sbt がインストール済み
    • Gatling という負荷テストツールを利用する想定
    • amazon-corretto のインストールで良い方法が見つからなかったので OpenJDK にしています

ユーザー作成

まず、SSHログインするためのユーザーアカウントを作成します。ログインするために公開鍵を登録するというのがポイントになります。cloud-init の users 設定で行います。

#cloud-config
cloud_final_modules:
    - [users-groups, always]
users:
    - name: takagi
      groups: [wheel]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
      ssh-authorized-keys:
          - ssh-rsa publickey # 公開鍵をセットする

この設定は以下資料を参考にしました。

aws.amazon.com

EC2インスタンス作成時に上記の設定内容をユーザーデータに渡しインスタンスが起動するとSSHログインできるようになります。踏み台サーバー経由でログインするために以下のような設定を行います。鍵は簡易的に踏み台サーバーと同じものを利用しています。諸々の設定が上手くいけば ssh working-server でログイン可能です。

# ~/.ssh/config
Host bastion # 踏み台サーバー
    HostName x.x.x.x # public IPアドレス
    User takagi
    IdentityFile /Users/takayuki_atkwsk/.ssh/id_rsa
Host working-server # 作業用サーバー
    HostName 192.168.2.73 # private IPアドレス
    User takagi
    IdentityFile /Users/takayuki_atkwsk/.ssh/id_rsa
    ProxyCommand ssh -W %h:%p bastion

パッケージのインストール

次に必要なパッケージをインストール済みの状態にします。上記でSSHログインできるようになった段階で yum install コマンドを打っても良いのですが、時間が空いて別の作業用インスタンスを起動したときに再度打つのも面倒くさいので cloud-init に任せてしまいます。今回は OpenJDK と sbt をインストールします。注意点としては、パッケージのインストールはインスタンスのライフサイクルで一度しか行われないため、上記の設定でインスタンスを起動した場合は一度終了(stop ではなく terminate)してパッケージの設定を追加した新しいインスタンスを作り直しましょう。

sbt に関しては以下のインストール方法に記されている方法の内、RPMレポジトリをパッケージマネージャに追加する方法で行います。

curl https://bintray.com/sbt/rpm/rpm | sudo tee /etc/yum.repos.d/bintray-sbt-rpm.repo
sudo yum install sbt

www.scala-sbt.org

cloud-init で対応するには yum_repos という設定を利用します。各設定値には上記の sbt RPM URLから得られるデータに含まれる値を使います。こちらがダウンロードしたデータです。

#bintray--sbt-rpm - packages by  from Bintray
[bintray--sbt-rpm]
name=bintray--sbt-rpm
baseurl=https://sbt.bintray.com/rpm
gpgcheck=0
repo_gpgcheck=0
enabled=1

それぞれの値を yum_repos に当てはめると以下の cloud-init 設定になります。これでパッケージマネージャにレポジトリを追加できます。後は yum install でインストールしたいパッケージ名を packages の値に書き込みます。

yum_repos:
    bintray--sbt-rpm:
        baseurl: https://sbt.bintray.com/rpm
        name: bintray--sbt-rpm
        enabled: true
        gpgcheck: false
packages:
    - java-1.8.0-openjdk-devel
    - sbt

yum_repos: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#yum-add-repo

packages: https://cloudinit.readthedocs.io/en/latest/topics/modules.html#package-update-upgrade-install

この設定をユーザーデータに含めてインスタンスを起動すると、OpenJDK および sbt がインストールされた状態になっています。これで Gatling シミュレーションを含んだソースコードをローカルから scp すれば実行できるようになります。

[takagi@ip-192-168-2-73 ~]$ which java
/usr/bin/java
[takagi@ip-192-168-2-73 ~]$ which sbt
/usr/bin/sbt
[takagi@ip-192-168-2-73 ~]$ java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

まとめ

用意した cloud-init 設定全体を以下に示します。今回は単発でEC2インスタンスを利用する(=定常的に稼働しないまたは他の人が利用しない)用途だったのでこのくらいの簡潔さが丁度良いなと感じました。組織でEC2インスタンスの構成管理を行いたい場合になると Chef や Ansible などのツールを使う方が上手く運用できるのかもしれません。

#cloud-config
cloud_final_modules:
    - [users-groups, always]
users:
    - name: takagi
      groups: [wheel]
      sudo: ["ALL=(ALL) NOPASSWD:ALL"]
      shell: /bin/bash
      ssh-authorized-keys:
          - ssh-rsa publickey # 公開鍵をセットする
yum_repos:
    bintray--sbt-rpm:
        baseurl: https://sbt.bintray.com/rpm
        name: bintray--sbt-rpm
        enabled: true
        gpgcheck: false
packages:
    - java-1.8.0-openjdk-devel
    - sbt

Kanazawa.rb meetup #91 に参加しました #kzrb

1月以来のKanazawa.rb meetupに参加しました。今回は昨今のCOVID-19の影響によりオンライン開催となりました。

kzrb.doorkeeper.jp

初のオンライン開催

Kanazawa.rb では史上初のオンライン開催となりました。Zoomを使って参加者はそれぞれの場所からログインして常時接続、発表以外のときはマイクも常時ONという状態でやっていました。上の写真は自分の環境(ITBP武蔵のサロンスペース)で、下の写真(by @kiyohara)はZoomの参加者集合写真です。ノートPCなので2画面無いと作業しながらかつ相手の様子を見ながら喋るのが大変そうだなと思いiPadをサブディスプレイにしていました。

f:id:TAKAyuki_atkwsk:20200324213354p:plain

雑に感想を並べていきます

  • 雑談する時間帯もあったし黙々と集中して作業する時間帯もあってよかった
  • オンライン開催ということで県外在住の人(確か東京から?)が参加していた
    • 遠方でもパッと参加できるのは良いね
  • 全員常時接続なので、peer to peer やグループ間の会話ができない構造になっている
    • 専用部屋みたいのを用意すればできなくはないけど準備が煩わしい
    • パッとこういう会話ができるのが現実のmeetupの良さかもしれない
  • 発表資料を手元で見れるのがよい(前の人と被って見えないとかが無い)
  • 画面共有は慣れが必要
  • 意図的にZoomの音を切ってもよいものか?
    • 音楽聞いて作業したいときどうするか?
  • 常時接続なのでネットワーク帯域が持ってかれる
    • 用事があったついでで外から参加していたので個人用のPocket WiFiを使ってたけど、次は家からやりたい...w
  • 他の人がはまりポイントを共有していて、それを聞いた他の人からアドバイスを貰って見事に解決していた
    • Slackでいろいろリンクを共有できててよかった
  • VTuber参加よさそう
  • 懇親会無いのは寂しい

もくもく内容

EC2のユーザーデータ(cloud-init)について調べていました。Gatlingという負荷テストツールがあってそれを単発でEC2上で動かすときに自分の公開鍵とか依存パッケージをいちいち持ってくるのが大変だな、という体験があってユーザーデータを使って楽にできないか、というのを調べていました。最後まで調査できなかったので詳細は別の記事で書く予定ですが、パッケージのインストールはある程度できるようになりました。この辺見ながら試していました。

cloudinit.readthedocs.io

来月もオンラインでのもくもく会となります。

Akka Streamsを利用するTCPクライアントのメモ

Akka Streamsを利用してTCP通信ができる簡易なコードが書けることを知ったのでメモ。

詳しくは以下のページを参照。

doc.akka.io

TCPクライアントのソースコード

package io.github.takayukiatkwsk.tcpclient

import akka.actor.ActorSystem
import akka.stream.scaladsl.{Flow, Keep, Sink, Source, Tcp}
import akka.util.ByteString

import scala.concurrent.Future

class TcpClient(implicit val system: ActorSystem) {
  private val connection = Tcp().outgoingConnection("127.0.0.1", 8080) // 接続先のホストとポート

  private val mapFlow = Flow.fromFunction[ByteString, String](b => b.utf8String)
  private val sink = Sink.headOption[String]

  def send(body: String): Future[Option[String]] = {
    Source
      .single(ByteString(body)) // TCPサーバーに送るデータ(StringからByteStringに変換)
      .via(connection)
      .via(mapFlow) // サーバーから返却されたデータをStringに変換
      .toMat(sink)(Keep.right) // 文字列を取り出す
      .run()
  }
}

object TcpClient extends App {
  implicit val actorSystem = ActorSystem("tcp-client")
  implicit val ec = actorSystem.dispatcher

  val tcpClient = new TcpClient()
  for {
    result <- tcpClient.send("Hello from TcpClient")
  } yield {
    println(result.getOrElse("Empty response"))
  }
}

今回TCPサーバーはnc(netcat)コマンドを利用してちゃちゃっと確認できるようにしました。

### 8080ポートでListenして、hello, worldを返す
$ echo -n 'hello world' | nc -l 8080

クライアントを実行してみます。

### ncコマンドとは別のターミナルで実行
$ sbt 'runMain io.github.takayukiatkwsk.tcpclient.TcpClient'

TCPサーバーに Hello from TcpClient というデータが送られてきて標準出力に出力されます。

$ echo -n 'hello world' | nc -l 8080
Hello from TcpClient

その後、TCPクライアントはTCPサーバーからの返信を受けて、ターミナルに hello world というデータが出力されます。

$ sbt 'runMain io.github.takayukiatkwsk.tcpclient.TcpClient'
...
hello world

感想としては、Akka Streamsのみで比較的シンプルにソースコードを書くことができ、レスポンスの扱いもFuture値を使うことができるのでハンドリングしやすいなと思いました。リソースのオープン・クローズも隠蔽されていて使う側としては非常に楽だなあと感じます。選択肢の一つとして覚えておくと良さげですね。

Kanazawa.rb meetup #89 に参加しました #kzrb

2020年になって最初の Kanazawa.rb です。今年もやっていきましょう。

kzrb.doorkeeper.jp

meetup.kzrb.org

もくもく進捗

久しぶりにWebアプリ作ってみようかなーとネタが浮んだのでユーザーストーリーの作成と必要になりそうな技術の調査を行いました。どういうお題かというとブログの最新記事を音声化して購読できるものです。アイデアとしてはよくあるものだとは思いますが自分が欲しいなあと少しでも思ったので作ってみることにしました。

ユーザーストーリーの作成は見様見まねでやってみました。最初はファイルに箇条書きで思いつくままに書いていたのですが、それぞれのユーザーストーリーの関連性や依存を洗い出したかったので付箋に書いてペタペタ貼って考えてみました。結果以下の画像のように並び替えました。

机のスペースが限られているので自分のみ分かる配置になっていますが左から右にストーリーが進んで目的が達成されるという並びにしています。縦方向は派生するパスを表しています。並べてみると最初はこの部分の一連のストーリーが実装できていればいいか、というようなことが決めやすいなという気付きがありました。

残りの時間は技術的な課題を洗い出して一つずつ調査実装していきました(全ては終わっていない)。今回はサーバレスな基盤でRubyを使って実装してみようと考えてます。趣味アプリなので自分の使いたい技術(Rubyは最近触れてなかったので...)を使うというところと、音声変換や非同期処理などクラウド基盤やサーバレスアーキテクチャに乗せた方がもろもろ楽できるのかなというのが技術選定の背景です。調査実装してみて構成を変える可能性はありますが。

ギャラリー

こう見るとタイトル重要だなというのを再認識させられます。

懇親会

www.hotpepper.jp

最近オープンしたという「十三」にて一次会!炭火で鶏肉を焼きながらあれこれ喋ってました。レガシーリソースと新規開発、リモートワークとテクノロジー、ラジオで聴いた分身ロボットのカフェとセルフ介護の話、にいがた酒の陣、社内ルール、ガリベンガーVなどについて話しました。お腹いっぱいでチキン南蛮食べられなかった...。

二次会は安心の「だんまや水産」にて。細巻き美味しかった。トークはあんまり覚えてませんw

次回

決済プラットフォームのStripeミートアップやりますよ。もう使ってるよって方はぜひ事例を共有して、興味あるよって方は気になりポイントを聞いてみる絶好の機会です!

eventregist.com

2019年個人的振り返り

今年もこの季節です。

www.blogaomu.com

仕事

引き続きZOZOのお仕事を手伝っておりますが、去年(=2018年)から運用に入っていたサービスが終了し、次のプロダクトのリリースに向けてあれこれやっているという状況です。役割としては技術調査を行ったり開発効率を高めるためのツールを作ったりということがメインでした。初期実装は自分の方でざっくりやって続きは若者に委譲していくというパターンのやり方が多かったです。やっていく上では思想も含めて引き継いでいくというのが大事だと感じたし、同時に難しさも感じました。一年を通しては上手くいったなーということより上手くいかなかったなーということの方が多かった気がします。

そういうことを感じてかまたは無意識にかは分かりませんが、自身の方向性について考えようとする機会が増えて模索をしていた年でもありました。

  • スキルの棚卸し
    • いまできること、将来やっていたいことを明らかにするためマインドマップでまとめていた。それから先は進められていない。
  • AWS認定
    • どの程度やれているのかを把握するのに受験した。新しく知れたこともあったし、得意不得意について言語化しやすくなった。
  • 人に会って話を聞く
    • meetupやライトな会社訪問などで外の世界の話を聞く機会を作った。特にチームとして何か解決するみたいな部分。

コミュニティ活動

定常的なもの

  • Kanazawa.rb 9回
  • JAWS-UG金沢 7回
  • Code for Kanazawa Civic Hack Night 1回

Kanazawa.rbでは今期も運営メンバーに入ったり飛び込みLTしたりで参加してる感出せたなーと思います。JAWS-UG金沢ではあまり発表できなかったので来年は2回以上発表できるようにしたいです。Code for Kanazawaは初めて参加してみたものの、コミュニティとしての関わり方が他の2つと異なって少し難しさを感じました。一応 ha4go にはほんのり貢献できたのでよかったです。

大規模イベントや単発もの

  • JAWS DAYS 2019
  • HashiCorp Terraform & Vault Enterprise 勉強会 in 金沢
  • 突撃!!隣のアーキテクチャ
  • ScalaMatsuri 2019
  • Algolia 勉強会 in 金沢
  • Google Cloud Next '19 in Tokyo
  • AWS Community Day Kanazawa
  • 松本CTOが語るテックカンパニーとDMMの目指す先 DMM Meetup in 金沢

特にAWS Community Day Kanazawaは結果的に100名超が参加するイベントになりましたが、運営スタッフの一員として関われたのは経験として大きかったなと思います。詳しくは個別に記事を書く予定ですが、ゴールから必要なことを割り出してこれらを一つ一つ実行していく力が問われました。個人的には会の直前までふわふわしていましたが無事に開催できてよかったです。

個人開発

今年はプロダクトは作りませんでした。PCにsandboxというディレクトリがあるのですがその中で写経したりサンプルアプリを作ったりするぐらいでしたね。引き出しは少しずつ増えているはずなのでアイデアを形にするのを来年はできたらよいなと思います。

来年も上手い酒を飲めるように精進。

Kanazawa.rb meetup #88 に参加しました #kzrb

あっという間に2019年も12月を迎えていますね。金沢は冬らしくない気候が続いておりあまり年末という感じがしません。それでも12月のKanazawa.rbは年末LT大会。毎年の恒例行事です。

kzrb.doorkeeper.jp

meetup.kzrb.org

LT

発表に使用したスライドはこちらです。

speakerdeck.com

今年の後半において2つのAWS認定を取得したので動機や勉強方法、ふりかえりなどをさらっと発表しました。AWSイベントにおける認定ラウンジは人権、というパワーワードも出つつ折角なので来年のAWS Summit(もし参加できたら)ではラウンジ入ってみたいですね。発表に含めなかったところでは、先にデベロッパーアソシエイトに合格してそこそこの出来ですっかり油断し、次に受けたSysOpsアドミニストレーターアソシエイトでは合格ラインギリギリで通過してしまいもう少し勉強したかったなというのと運用に比較的関われてないというのが改めて分かったという印象でした。来年はソリューションアーキテクトアソシエイトと上級の認定を取れるように精進していきたいです。

LT大会全体としては、18名もの参加者が各々取り組んでいることや興味を持っていることを発表していて、改めてKanazawa.rbの懐の広さを感じました。

懇親会

meat-meet.owst.jp

最近武蔵にできた肉料理のお店で懇親会。食べるのと話すのに夢中で全然写真撮れませんでしたw 話題としては、機械学習のおすすめ入門本の紹介、Python初心者がJupyter Nootbookを最初から使うべきか問題、リモートワークのつらみ、オープンオフィスの生産性、チームをリードする立場になった話、勉強会と領域初心者の問題などなど個人的には盛り上がりました。残念ながら私は1次会で撤収。

来年もKanazawa.rb盛り上げていきます。