hekiblo

hekki blog

AWS Systems Manager Session Manager を使って、手元のマシンから楽してEC2へ接続する

概要

AWS Systems Manager Session Manager(以下Session Manager)を使用している環境でEC2 に接続する場合、色々と面倒なことがわかりました。

面倒事

Session Manager はマネジメントコンソールから利用する場合「マネジメントコンソールにログイン -> 接続先のEC2 インスタンスを探す -> Session Manager を使用して接続」という流れになります。
毎回この手順を踏むのは面倒ですし、SSH のように手元のマシンから接続できないのは不便なので、AWS CLI を使いたくなります。

ただし、AWS CLI + Session Manager の場合でも、接続先のEC2 インスタンスインスタンスID を調べるためにマネジメントコンソールから確認する必要がありました。
これは非常に面倒なので、この手順をスキップして接続できるように工夫してみます。

本題

前提

手元のマシンMac を想定しています。ただし、Windows/Linux など他のOS でも適宜読み替えれば同じことができるはずです。 また、予め以下のようなツールがインストールされている必要があります。

また、aws ssm start-sessionaws ec2 describe-instances が実行できる権限が付与されたAWS アクセスキーが手元のマシンに登録されている必要があります。
ここでは hoge-profile という名前付きプロファイルとして、アクセスキーが登録されていることとします。

ツールの用意

下記のシェルスクリプトをパスが通っているディレクトリに作成します。ここではスクリプトのファイル名を awssh とします。
gist.github.com

使ってみる

このようにしてAWS のプロファイルを指定しつつコマンドを実行します。

$ awssh --profile hoge-profile

コマンドを実行すると起動中のEC2 インスタンスの一覧が表示されるので、接続したいインスタンスを選択すると、そのインスタンスのコンソールにログインすることができます。

これで接続先のEC2 インスタンスインスタンスID をマネジメントコンソールから確認しなくてもSession Manager を使ってインスタンスのコンソールにログインすることができるようになりました。やったね!

2020年 振り返り

2020年も終わりが近づいてきたので1年の振り返りをする。

今年も去年と同じく、SREというロールで仕事をしていた。 今年の自分のテーマは「ソフトウェア開発スキルの向上」で、とくにかくこれを念頭に置きながら1年過ごした。

2018年の夏に今の部署に異動して、SREというロールで 家族アルバム みてね というスマートフォンアプリのバックエンドの開発や運用をやるようになった。 それまで物理インフラ畑にずっといたからか、最初の1, 2年は特にコーディングの苦手意識がすごくて(苦手意識というか実際にできなかったんだけど…)、重めの開発タスクがあると嫌だなあーと思って避ける事が多かった。
とはいえそのまま避け続けるわけにはいかないし、せっかくなら自分で開発したものをユーザーに使ってほしいのでなんとかしようといろいろやった1年だった。

具体的には次のようなことをやった。

デザインパターンを身につける

トンチンカンな設計をしたままコーディングに進んでしまって、あとあと大きな手戻りが発生する…みたいな経験を何度かしたので、その問題を克服するためにいくつか本を読んだ。

どちらもまずはパラパラと一周読み、実際に業務で設計しながら使えそうなところを後で何度もじっくり読むようにして、辞書的に使っている。
はじめからじっくり読んでもイメージが湧きにくいし、読み終えるまでにダレるし、一度だけじっくり読んだってすぐに忘れるので。

フレームワークに馴染む

業務でRails を使っていることもあり、とにかくRails way に乗って素早く・(Rails のお作法的に)正しく・美しく実装ができるようにしたくて、Rails に慣れ親しむのを意識した。

初めの方はRails チュートリアルをじっくりこなしたり、今年の夏にパーフェクト Ruby on Rails の改訂版が出たのでそれを読み進めたりした。
初めてRails を学んだ対象が、それなりに歴史のある大きなRails プロジェクトだったこともあり「よく分からんけどなんか動いてる」といった知識の穴が結構多く、その穴を埋めるのにはとても良かったと思う。とはいえ、未だにRails 知らない機能多いけど。

gem のコードをたくさん読む

これは特になにか意識付けがあったわけではないし、どちらかというとバグ調査などで必要があったから読むことが大半ではあったものの、面倒くさがらずにちゃんと読んで理解するのは結構自分のためにはいい経験だった。

また、danger-rubocop というgem のバグに遭遇し、該当の箇所を読んでみたところ直せそうな雰囲気を感じたのでPR を送ってみたところなんとマージしてもらうこともできた。(OSS 初コントリビュート!) 内容的には些細なバグ修正ではあるものの、自分のスキルの向上を感じれたのでこの経験はかなり嬉しかったし、自信にも繋がった。 github.com


来年は引き続きソフトウェア開発のスキルは伸ばして行きたいなーと思いつつ、kubernetes を本格的に触り始めたのでその辺りの開発・運用もガッチリやっていきたい。 また、サービスの性質上膨大な量の画像・動画を取り扱うので、メディアの基礎的な知識も更に蓄えていかねばという感じ。

来年も引き続き頑張っていきましょう!

宣伝

自分が所属する「家族アルバム みてね」ではエンジニアを大募集中です! medium.com

WebP を試す

iOS14 でWebP に対応との情報を見かけたのでこれを機にとりあえずエンコードして試してみることにした。

エンコード環境の作成

docker コンテナ内にImageMagick をインストールして、使うことにする。

Dockerfile を作成する。 簡易的なテストのためのものなので、とりあえずapt でインストールしてみた。

FROM ubuntu:20.04

RUN apt-get -y update && \
    apt-get -y install imagemagick && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

続いてdocker image をビルドして、convert コマンドを実行してみる。

# docker image をビルド
$ docker build -t imagemagick .

# 動作確認
$ docker run -it imagemagick convert --version
Version: ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
Copyright: © 1999-2019 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP
Delegates (built-in): bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff webp wmf x xml zlib

ここまでで準備は完了。

エンコード

エンコード対象の画像を /path/to/images/1.jpg とする。

特にパラメータを指定せずエンコードしてみる。

$ docker run -v /path/to/images:/images --rm -it imagemagick convert /images/1.jpg /images/1.webp

これでエンコードできた。 画像を並べて比較してみたところ、色味や粗さなど自分の肉眼では判別できないほど違いが分からなかった。

エンコード結果の確認

ファイルサイズはかなり違いがある。 とはいえ、これはパラメータ次第だと思われるので、大した参考にはならなさそう。

$ docker run -v /path/to/images:/images --rm -it imagemagick ls -l /images
total 6184
-rwx------ 1 root root 4101341 Oct 22  2019 1.jpg
-rw-r--r-- 1 root root 1908796 Sep 24 14:43 1.webp

ImageMagick に同梱されているidentify コマンドで画像の詳細をチェックできる。

$ docker run -v /path/to/images:/images --rm -it imagemagick identify -verbose /images/1.jpg
$ docker run -v /path/to/images:/images --rm -it imagemagick identify -verbose /images/1.webp

パラメータに関してはImageMagick と WebP がよくまとまっていた。 こちらの記事で概要を掴んで、Google の仕様書を読み込んでいくと詳細まで把握することができそう。

Linuxで作るVLAN変換サーバー

2015年12月17日に公開した記事を移動してきました。


L2 ネットワーク内で、ある VLAN タグが付いたフレームを、別の VLAN タグに付け替える Linux サーバーを作ってみます。 万人に使い道があるとは思えませんが、誰かの参考になると嬉しいですね。

概要

全体像

まずは VLAN 変換サーバーを含めた今回のお題とするネットワークを紹介します。

ネットワークには通常の Linux サーバーが二台 (Node1, Node2) と、VLAN 変換サーバー (VLAN-brige) を1台用意します。 VLAN 変換サーバーには Ubnutu14.04 を利用していますが、ディストリビューションはお好きなものを利用して構わないです。

f:id:ni_hi:20190927172910j:plain
図1: 検証NWの全体像

しくみ

VLAN 変換サーバーの仕組みについて説明します。

VLAN 変換サーバーは、内部に VLAN インターフェースと、bridge インターフェースを持っています。 変換対象となる VLAN インターフェースのペアを brdige インターフェースを使って論理的に接続します。

まず、VLAN 変換サーバーに到達した VLAN フレームは、VLAN インターフェースによって VLAN タグが外されます。 次にタグが外されたフレームは bridge インターフェースに到達します。 bridge インターフェースから、もう片側の VLAN インターフェースにフレームは転送され、元々付いていた VLAN タグとは異なる VLAN タグが付けられます。 この仕組を利用することによって、任意の VLAN タグが付いたフレームを別の VLAN タグに付け替えることができます。

f:id:ni_hi:20190927173008j:plain
図2: VLAN 変換サーバーの内部 NW

つくってみよう

それでは VLAN 変換サーバーを作ってみましょう。 サーバーは2台でも試験できますが、今回は分かりやすくするために3台用意します。

VLAN <-> VLAN 変換編

まずは終端となる2台のサーバーに異なる VLAN インターフェースを作成します。 Node1 に VLAN 番号 100 のインターフェース、Node2 に VLAN 番号 200 のインターフェースを作成します。 ここでは、eth1 のサブインタフェースとして作成してみます。

Node1

# サブインタフェースの追加をする
$ vconfig add eth1 100

# 作った eth1.100 に IP address を割り振って
$ ip addr add 192.168.0.100/24 dev eth1.100

# eth1 インターフェースを起こして
$ ip link set eth1 up

# eth1.100 インタフェースを起こす
$ ip link set eth1.100 up

Node2

Node2 も同様に 200 番の VLAN インターフェースを作成して、IP address を付けておきます。

$ vconfig add eth1 200

$ ip addr add 192.168.0.200/24 dev eth1.200
$ ip link set eth1 up
$ ip link set eth1.200 up

VLAN 変換サーバー

VLAN 変換サーバーは、前述した通り、VLAN インターフェースの他に brige インターフェースを作成するので、brctl コマンドを利用します。

# eth1.100 インターフェースを作っておいて
$ vconfig add eth1 100
$ ip link set eth1 up
$ ip link set eth1.100 up

# eth1.200 インターフェースも作っておいて
$ vconfig add eth1 200
$ ip link set eth1 up
$ ip link set eth1.200 up

# br1 という名前で bridge インターフェースを作って
$ brctl addbr br1

# br1 に eth1.100 を論理的に接続
$ brctl addif br1 eth1.100

# br1 に eth1.200 も論理的に接続
$ brctl addif br1 eth1.200

# br1 インターフェースを起こす
$ ip link set br1 up

これで準備は整いました。 Node1 と Node2 でお互いの IP address に ping を送信してみましょう! ping が到達するのが確認できましたか?

到達が確認できたら、VLAN 変換サーバーで各インターフェースを tcpdump で眺めてみると面白いかもしれないですね!

VLAN <-> Nested VLAN 変換編

おまけです。 ほとんど変わらないですが、任意の VLAN フレームと Nested VLAN フレームも同じように変換できます。

Node1

# サブインタフェースの追加をする
$ vconfig add eth1 100

# 作った eth1.100 に IP address を割り振って
$ ip addr add 192.168.0.100/24 dev eth1.100

# eth1 インターフェースを起こして
$ ip link set eth1 up

# eth1.100 インタフェースを起こす
$ ip link set eth1.100 up

Node2

Node2 は Nested VLAN インターフェースを作っておきます。

$ vconfig add eth1 200
$ vconfig add eth1.200 300

$ ip addr add 192.168.0.200/24 dev eth1.200.300
$ ip link set eth1 up
$ ip link set eth1.200 up
$ ip link set eth1.200.300 up

VLAN 変換サーバー

# eth1.100 インターフェースを作っておいて
$ vconfig add eth1 100
$ ip link set eth1 up
$ ip link set eth1.100 up

# eth1.200.300 インターフェースも作っておいて
$ vconfig add eth1 200
$ vconfig add eth1.200 300

$ ip link set eth1 up
$ ip link set eth1.200 up
$ ip link set eth1.200.300 up

# br1 という名前で bridge インターフェースを作って
$ brctl addbr br1

# br1 に eth1.100 を論理的に接続
$ brctl addif br1 eth1.100

# br1 に eth1.200.300 も論理的に接続
$ brctl addif br1 eth1.200.300

# br1 インターフェースを起こす
$ ip link set br1 up

これで準備は整いました。 Node1 と Node2 でお互いの IP address に ping を送信してみましょう!

感想

仕組みさえ分かってしまえば意外と簡単でした。 ただ、変換サーバーの冗長化はめちゃくちゃ苦労したので、興味のある方はぜひ挑戦してみてくださいね!

ネットワークの勉強をするときには、どの地点でパケットやフレームにどういったヘッダーが付いていて、それらが着信したインターフェースによってどう処理されるかをひとつひとつしっかり考えることが一番の近道だと思います。 繋がったときに楽しさ倍増なので、tcpdump をバンバンしましょう!