出力を入力へ

プログラミングに関する自分が考えた事を中心にまとめます

Ubuntu on WSL2 でsnapを利用する

Ubuntu20.04 LTS と WSL2を試してみたところ snapコマンドが上手く利用できなかったのでそのまとめ

WSL2

もともとWSL2もInsider Previewを利用して試していたけど, とうとうGA版がリリースされたということで改めて試してみた.

WSL2の利用方法は Insider Previewの頃と変わらず. Insider Previewを利用せずともWSL2が利用できるようになった.

WSL2におけるsnapdとsystemd

Ubuntuの新しいパッケージ管理システムであるsnap. ところが WSL2上のUbuntuではsnapコマンドが実行できない.

$snap install hello-world
error: cannot communicate with server: Post http://localhost/v2/snaps/hello-world: dial unix /run/snapd.socket: connect: no such file or directory

原因は snapコマンドが systemdに依存しており,WSL2ではsystemdが起動していないこと. snapコマンドはsnapdと通信して動作するが,snapdはsystemdサービスとして動作するので systemdが動作していないとsnapdも動作せず,snapコマンドは正常に実行できない.

$ cat /etc/systemd/system/multi-user.target.wants/snapd.service
[Unit]
Description=Snap Daemon
Requires=snapd.socket
OnFailure=snapd.failure.service
# This is handled by snapd
# X-Snapd-Snap: do-not-start

[Service]
# Disabled because it breaks lxd
# (https://bugs.launchpad.net/snapd/+bug/1709536)
#Nice=-5
OOMScoreAdjust=-900
ExecStart=/usr/lib/snapd/snapd
EnvironmentFile=-/etc/environment
Restart=always
WatchdogSec=5m
Type=notify
SuccessExitStatus=42
RestartPreventExitStatus=42
KillMode=process

[Install]
WantedBy=multi-user.target

WSL2ではsystemdはinitシステムとして動作していない. WSL2ではWindowsとのを実現するために独自のセットアップを実行しており, Ubuntuなどで採用されているsystemdは利用されていない. このため,systemctlコマンドなどは動作しない.

$ systemctl status snapd
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

WSL2上でsystemdを実行する

無理矢理systemdを起動してあげることで対処する. この記事に従いsystemdを起動すると systemctlが利用できるようになるし,snapdも動作するようになる.

$ systemctl status snapd
● snapd.service - Snap Daemon
     Loaded: loaded (/lib/systemd/system/snapd.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2020-05-24 13:46:21 JST; 5min ago
TriggeredBy: ● snapd.socket
   Main PID: 444
      Tasks: 27 (limit: 30645)
     Memory: 170.6M
     CGroup: /user.slice/user-1000.slice/session-c2.scope/system.slice/snapd.service
             └─444 /usr/lib/snapd/snapd

 5月 24 13:50:47 DESKTOP-JCB3AFB snapd[801]: rip    0x5580ad845031
 5月 24 13:50:47 DESKTOP-JCB3AFB snapd[801]: rflags 0x286
 5月 24 13:50:47 DESKTOP-JCB3AFB snapd[801]: cs     0x33
 5月 24 13:50:47 DESKTOP-JCB3AFB snapd[801]: fs     0x0
 5月 24 13:50:47 DESKTOP-JCB3AFB snapd[801]: gs     0x0
 5月 24 13:50:47 DESKTOP-JCB3AFB systemd[1]: snapd.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
 5月 24 13:50:47 DESKTOP-JCB3AFB systemd[1]: snapd.service: Failed with result 'watchdog'.
 5月 24 13:50:48 DESKTOP-JCB3AFB systemd[1]: snapd.service: Scheduled restart job, restart counter is at 2.
 5月 24 13:50:48 DESKTOP-JCB3AFB systemd[1]: Stopped Snap Daemon.
 5月 24 13:50:48 DESKTOP-JCB3AFB systemd[1]: Starting Snap Daemon...

あとは 通常通りsnapコマンドを実行すればいいだけ. ただし,当然ながらsystemdはあまり正常な状態ではないようで, systemctl restartなどでsnapdを含む適当サービスを再起動するとエラーになる.

$ sudo systemctl restart snapd
[sudo] thaim のパスワード:
Warning! D-Bus connection terminated.
Failed to restart snapd.service: 接続が相手からリセットされました
See system logs and 'systemctl status snapd.service' for details.

一応snapコマンドでhello-worldをインストール・実行できたのである程度は動作する,はず. ただし,現状では可能な限りsnapコマンドは利用しない方がよさそう.

参考

書評: 新 企業の研究者を目指す皆さんへ

もともと自分が学生だった頃に読んだ本の新版. 当時はまだ企業における研究とは何か理解しておらず,その後の自分の企業研究者人生に大きな影響を与えてくれた. その新版が出たということで読んでみた.

企業の研究者を目指す人という書き方ではあるが, 企業の研究者ではなくなった今の自分でも読んでよかったと思えた.

概要

企業の研究者や,研究者を目指す学生に向けて著者のキャリアの中で感じた 企業において必要なこと,研究者において必要なことなどを記載している. 著者はソフトウェアに関する研究者ではあるが,分野に依存しない 一般的な研究者へのメッセージ・考え方を示している.

新版での追加内容として,旧版が出版されてからの著者のキャリアとして 数理研やPFNなどの経験を踏まえた内容となっている. 旧版のIBMにおける研究に対する考え方を知る本という立ち位置から, 企業という枠を超えて研究者とは何かについて知ることができる.

よかったところ

新版で追加された内容では,2章におけるソリューションを設計するが深く刺さった. 設計型の研究を上手く成果に結び付けることが難しいことは,自分も多く経験しており, 論文にすることの難しさや,成果としての評価の難しさを今でこそ理解している. さらっと書かれており,学生が読むとしたらスルーされるだろうけれど, もっと早く出会えていたら自分の悩みにもっと向き合えていたかもと思う.

旧版からあった内容で,改めて深く考えたのが6章のインテグリティについてである. もちろん,研究成果の捏造といった重大な事件はやっていないし,実際に見たことはなかったけど, 進捗のごまかしという点では大なり小なり見てきたし手を出してしまったこともある. あとはやるだけだからとか,ここのバグを直せば完了だからと,成果をごまかして報告したり, 逆に毎週良い成果を報告したいから,まだ今週は上手くいっていないことにして次週に報告しよう, といって報告しなかったりという場面に多々出会ってきた. これはコミュニケーションの問題でもあるが,社内だからこそ包み隠さず報告することが大切だし, 過剰にアピールせず等身大に伝える,ということの大切さと難しさを再度考えてしまった.

よくなかったところ

特に疑問に思ったところはなく,基本的に非常に満足できる内容だった.

あえて言うのであれば企業という視点が軽くなったように感じた. タイトルの「企業の」ということが本質ではなく,アカデミックの研究者を目指す人にも読んで欲しい内容だと思った. 「企業の研究者」と述べているからにはもっと企業特有の話を記載して欲しいとも感じた. 例えば2章の研究の出口はまさに企業とアカデミックで大きく異なるところだと思っているので, もう少し掘り下げて欲しかった(技術移転はそれだけで1冊本になりそうなほど難しいトピックだと思う).

まとめ

企業で研究するならぜひとも一度は読んで欲しい本だと思うし, 研究でなく開発よりでも非常に参考になる. 自分も読んでいてまた研究したいなと思ってしまった.

新 企業の研究者をめざす皆さんへ

新 企業の研究者をめざす皆さんへ

MySQL 5.7.30 でvalidate_password プラグインを回避する

いつも Docker での動作検証しかしていなかったので, Docker以外の環境とかMySQLの初期化処理とか知らなかった.

事の始まり

AWS EC2 / Amazon Linux2 に MySQL をインストールして利用したい. このとき,開発・検証環境だから弱いパスワードを許可したかった(もちろん本当はよくないけれど).

ところが,弱いパスワードを設定しようとするとエラーになる. 軽く検索すると設定ファイルにパスワードポリシーの変更を追記するといいよという記事がたくさんヒットする. ただし,設定項目が記事によって異なる,タイポ?バージョンで違う? しかも設定を反映するとMySQLがエラーで起動しなくなる. とりあえず非公式情報は参考にならなそう.

ということで,なぜパスワードが変更できないのか,なぜ設定変更するとMySQLが起動しなくなるのか, その設定を変更する正しい手順はどうすればいいのか について調査した.

したいこと

  • Amazon Linux2 に MySQL 5.7.30 をインストールする
  • validate_passwordプラグインの制限を緩和する
  • この設定のセットアップ手順を確立する

なぜ上手くいかなかったのか

validate_passwordプラグインによるパスワードポリシー設定

弱いパスワードが設定できなかったのはデフォルトで validate_passwordプラグインが有効になっているため. このプラグインにより,弱いパスワードを設定することができなくなっている.

dev.mysql.com

このプラグインがデフォルトで有効になるのはyumリポジトリからMySQLをインストールした場合などで, 今回のAmazon Linux2ではYumリポジトリからインストールしていたのでこのプラグインが有効化されていた.

dev.mysql.com

Note

If you installed MySQL 5.7 using the MySQL Yum repository, MySQL SLES Repository, or RPM packages provided by Oracle, validate_password is enabled by default after you start your MySQL Server for the first time.

実際に Dockerの公式イメージ(mysql:5.7.30)で確認するとプラグインは有効になっておらず, validate_passwod プラグインのみ差異があることがわかる. 公式DockerイメージはDebianベースなので確かに公式ドキュメントの通りvalidate_passwordプラグインは有効にならない.

Yumリポジトリからインストールした場合

mysql> show plugins;
+----------------------------+----------+--------------------+----------------------+---------+
| Name                       | Status   | Type               | Library              | License |
+----------------------------+----------+--------------------+----------------------+---------+
| binlog                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| mysql_native_password      | ACTIVE   | AUTHENTICATION     | NULL                 | GPL     |
| sha256_password            | ACTIVE   | AUTHENTICATION     | NULL                 | GPL     |
| CSV                        | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| MEMORY                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| InnoDB                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| INNODB_TRX                 | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_LOCKS               | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_LOCK_WAITS          | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP                 | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP_RESET           | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMPMEM              | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMPMEM_RESET        | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP_PER_INDEX       | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_CMP_PER_INDEX_RESET | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_BUFFER_PAGE         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_BUFFER_PAGE_LRU     | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_BUFFER_POOL_STATS   | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_TEMP_TABLE_INFO     | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_METRICS             | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_DELETED          | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_BEING_DELETED    | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_CONFIG           | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_INDEX_CACHE      | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_FT_INDEX_TABLE      | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_TABLES          | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_TABLESTATS      | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_INDEXES         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_COLUMNS         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_FIELDS          | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_FOREIGN         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_FOREIGN_COLS    | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_TABLESPACES     | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_DATAFILES       | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| INNODB_SYS_VIRTUAL         | ACTIVE   | INFORMATION SCHEMA | NULL                 | GPL     |
| MyISAM                     | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| MRG_MYISAM                 | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| PERFORMANCE_SCHEMA         | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| ARCHIVE                    | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| BLACKHOLE                  | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| FEDERATED                  | DISABLED | STORAGE ENGINE     | NULL                 | GPL     |
| partition                  | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| ngram                      | ACTIVE   | FTPARSER           | NULL                 | GPL     |
| validate_password          | ACTIVE   | VALIDATE PASSWORD  | validate_password.so | GPL     |
+----------------------------+----------+--------------------+----------------------+---------+
45 rows in set (0.00 sec)

Dockerで起動した場合

mysql> show plugins;
+----------------------------+----------+--------------------+---------+---------+
| Name                       | Status   | Type               | Library | License |
+----------------------------+----------+--------------------+---------+---------+
| binlog                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| mysql_native_password      | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| sha256_password            | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| CSV                        | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MEMORY                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| InnoDB                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| INNODB_TRX                 | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_LOCKS               | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_LOCK_WAITS          | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMP                 | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMP_RESET           | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMPMEM              | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMPMEM_RESET        | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMP_PER_INDEX       | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_CMP_PER_INDEX_RESET | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_BUFFER_PAGE         | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_BUFFER_PAGE_LRU     | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_BUFFER_POOL_STATS   | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_TEMP_TABLE_INFO     | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_METRICS             | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_FT_DEFAULT_STOPWORD | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_FT_DELETED          | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_FT_BEING_DELETED    | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_FT_CONFIG           | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_FT_INDEX_CACHE      | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_FT_INDEX_TABLE      | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_TABLES          | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_TABLESTATS      | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_INDEXES         | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_COLUMNS         | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_FIELDS          | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_FOREIGN         | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_FOREIGN_COLS    | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_TABLESPACES     | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_DATAFILES       | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| INNODB_SYS_VIRTUAL         | ACTIVE   | INFORMATION SCHEMA | NULL    | GPL     |
| MyISAM                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MRG_MYISAM                 | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| PERFORMANCE_SCHEMA         | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| ARCHIVE                    | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| BLACKHOLE                  | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| FEDERATED                  | DISABLED | STORAGE ENGINE     | NULL    | GPL     |
| partition                  | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| ngram                      | ACTIVE   | FTPARSER           | NULL    | GPL     |
+----------------------------+----------+--------------------+---------+---------+
44 rows in set (0.01 sec)

対策としては,セキュアなパスワードを利用するか,ポリシーを変更するか,プラグインをアンインストールするか.

プラグインの反映タイミング

パスワードの制限を緩和するためには,ポリシーとして validate_password_policy = OFF を設定すればよい. これにより利用できるパスワードの制限を変更できる. もう少しパスワードポリシーをカスタマイズしたい場合は, 以下のプラグインオプションが参考になる.

dev.mysql.com

一方で初回起動前にこの設定を my.cnf に記載すると,validate_password プラグインがインストールされる前に反映しようとして, 無効な設定としてエラーになってしまう.

2020-05-04T10:31:49.970600Z 0 [ERROR] unknown variable 'validate_password_policy=LOW'

これは公式ドキュメントにも記載されている.

This option is available only if the validate_password plugin has been previously registered with INSTALL PLUGIN or is loaded with --plugin-load-add. See Section 6.4.3.1, “Password Validation Plugin Installation”.

ではこのプラグイン自体を最初から無効化すればいいかというとそれは難しい. プラグインの設定反映はMySQLをインストールしたときの systemdの設定ファイルによるもので, /usr/lib/systemd/system/mysqld.service には

# Needed to create system tables
ExecStartPre=/usr/bin/mysqld_pre_systemd

の記載があり, この /usr/bin/mysqld_pre_systemd で validate_passwordプラグインのインストールを含む 証明書の作成やシステムテーブルの作成などの処理(mysqld --initialize)を実行している.

validate_passwordプラグインを有効にしないオプションなどは存在せず, このpreスクリプトを実行しないと自分で初期化処理が必要になるので このスクリプトを実行しない選択肢は基本的にない. このスクリプトを自前でカスタマイズするのもリスクが高いので, Yumリポジトリからインストールした場合は基本的にvalidate_passwordプラグインは有効になっている想定がよさそう.

初回起動直後にプラグインをアンインストールしようとしても, 初期パスワードの変更前にパスワード変更以外の操作は受け付けないので, 初回起動→複雑なパスワード設定→プラグインアンインストール→簡易なパスワードの設定 といった無意味な手順が生じてしまう.

以上から,一度MySQLを起動してプラグインを反映した上でパスワードポリシーを変更して再起動, という手順がよさそう.

validate_passwordプラグインを回避するセットアップ手順

MySQLのインストール

Amazon Linux2ではMariaDBが有効になっている. MySQL5.7を利用したい場合はMySQLリポジトリを追加し, MySQL8を無効化して 明示的に5.7を有効化・インストールする必要がある.

dev.classmethod.jp

このタイミングでパスワードポリシーも変更したいが,それは実行しない. 自動起動の設定は反映されていないので sudo systemctl enable mysqld自動起動を有効にだけしておく.

MySQLのセットアップ

MySQLの初回起動後に /etc/my.cnf にパスワードポリシーの変更設定を記載する. 設定ファイルの末尾に validate_password_policy = OFF を追記だけしてあげればよい.

その後MySQLを再起動すればパスワードポリシーが変更される. あとは初期パスワードを弱いパスワードでも自由に設定できる.

初期パスワードはログ(/var/log/mysql.log)に出力されているので, これを利用してパスワードを変更する.

パスワード変更時にpassword関数を利用する方法はDeprecatedなのでpassword関数は利用しない. またSET PASSWORD FOR root@localhost = 'password' よりはALTER USERの方が推奨のようで, ALTER USER root@localhost IDENTIFIED BY 'password' でよい.

dev.mysql.com

Note

SET PASSWORD ... = PASSWORD('auth_string') syntax is deprecated as of MySQL 5.7.6 and will be removed in a future MySQL release.

SET PASSWORD ... = 'auth_string' syntax is not deprecated, but ALTER USER is the preferred statement for account alterations, including assigning passwords. For example:

参考

dev.mysql.com

hub.docker.com

hirose31.hatenablog.jp

qiita.com

SRE NEXT 2020 に参加しました

2020-01-25 に開催された SRE NEXT 2020 に参加しました.

sre-next.dev

現在自分はインフラエンジニアとして働いており, 運用も合わせて行っているので勝手に自分もSREを名乗れるかな?と考えて 自分が今後目指すべきキャリアを見極めようと考えて参加しました.

以下自分が聴講したセッションとその感想です.

[A0]基調講演: 分散アプリケーションの信頼性観測技術に関する研究

さくらインターネットにおける(というより発表者の?)SREを研究に昇華させた取組み.

speakerdeck.com

単なるアプリケーションの信頼性に限らず,クラウドを構築・提供する事業者としてのサービスの信頼性を どのように取組むかといった将来のSREに向けた取組みであると,まさにSRE NEXT だった.

一方で,これは今自分が取組む内容とはかけ離れていて,同じSREでもここまで違うんだな,と他人事に思えた. 最後のパネルディスカッションの中で,将来のSREはアプリ開発の中に原則は残りつつも, 究極的にはクラウド事業者だけが気を付ければいい職掌になる,といった内容の話があり, この基調講演の他人事のように思えた感じはクラウド事業者とクラウド利用者の差なのだなと感じた. だとすると,この発表のようなクラウド事業者としてのSRE NEXT ではなく, サービス開発者側のSRE NEXT を探さないといけない.

[C1] 絶え間なく変化するメルカリ・メルペイにおけるSREの組織と成長

メルカリおよびメルペイにおけるSREを組織化するに向けて取り組んできた成果.

speakerdeck.com

メルカリとメルペイで (マイクロサービス化できているかという視点から)組織構成や取組みが異なることは初めて知ったし, これだけ技術的に優れているメルペイであってもSREがチームとして動くようになるまでには大きな苦労を伴うことは, どこでも簡単ではないんだなと現実を知った感じ.

ただ,どちらの発表もなぜそうなったのか,どうやってそうしたのかというプラクティスがあまり共有されなかったのが残念だった. メルカリのマイクロサービス移行の過去の取組みとしてchocon開発移行の状況は紹介されていても, SREがボトルネックになりそうという問題があまり理解できなかったし,組織編成でどうして解決できるのかも伝わらなかった. 時間があれば聞いてみたかったところ. メルペイもToilを受け入れて戦う必要があるし採用は辛い,チーム化も辛いと,課題はよくわかるのだけれど, サービスがリリースされたら採用できました,人が増えたら解決できました,と聞こえてしまい, どのようにToilを対処したのか,どのように頑張ったのかがわからなかった.

[C2] 成長を続ける広告配信プラットフォームのモニタリングを改善してきた話

Voyage におけるアラートや監視の取組み.

speakerdeck.com

ユーザ視点でサービスが正常であるかを判断し,サービスの外側から重点的に監視するというのは, あたりまえではあるけどその通りだと思った.実際,自分のところではできていないから対処しないといけない. アラートも目的に応じて通知先をふりわけるというのも必要なこと. それでSREが楽になるだけでなく開発者も気にしてくれるようになるのであればこれ以上はない. アラートの見直しは障害が起きたとき,監視システムを置き換えたとき,人が増えたとき,というのはなるほどと思った. 障害が起きたときの見直しは当然だけど,人が増えたときにそれを切っ掛けにするというのは 大変だけど効果がありそうなので取組みたい.

ツール選択には複数の指標をもとに,ツールと仲良くなって判断するというのも, なかなかできていないので耳が痛い話.もっと普段からいろいろ挑戦してみないと.

[D3] Practices for Making Alerts Actionable

グリーにおける静観対応となるアラートの問題と, アラートの計測とふりかえりによるアラートの見直し,自動復旧の検討の取組み紹介.

speakerdeck.com

最近自分のところでもアラートの対応に課題があることは認識しており, どのように対応すべきか考えていたのでとても参考になった.

アラートに問題があるならアラートを計測してふりかえるという, あたりまえのことにきちんと取組めているのはすばらしいと思うしぜひ真似していきたい. 自動復旧も,既に障害で動いていない場合などこれ以上悪くならない場合には 導入しやすいというプラクティスもその通りなのでぜひ取組みたい.

[D4] 100万回線のIoT通信を支えるソラコムにおけるOpsDevの実践

ソラコムにおけるOpsDev (=SRE)の取組み.

www.slideshare.net

開発者も運用をするし,開発者もSREもサポートをするし,インシデント通知はエンジニア以外の全社員に通知するのは,すごい取組みだと思った. これがきちんと実践できているのであれば,サービスの信頼性や顧客満足度を全員が意識するようになるので, カルチャーとしてはすばらしいと思う.

ただ,カスタマーサポートも非常に難しい職掌だし,エンジニアと兼務して取組める気がしない. エンジニアのスキルだけでもキャッチアップするのが大変な,さまざまな技術が求められる時代なのに, 加えてカスタマーサポートもは自分だったら対応できない. どのようにエンジニアがサポートを実践しているのか, どのようにバックオフィス系の社員が障害アラートを認識して対応しているのかは気になるところ.

[C5] スクラムを1年回してSREと開発組織がどう変わったのか

HAMOS(ビズリーチ)におけるSREとしてのスクラムの取組み. 特定のタスクに取組めず,割り込みの多いSREがどのようにスクラムを実践してきたか紹介があった.

speakerdeck.com

どれに取組めばいいのかわからないので,タスクの優先度を定量的に評価することで全員が合意の元で判断できるようにする,というのはすばらしい取組み. 一方で,タスクの優先度を定量化するのはそう簡単ではなく, 下手をすれば設定したい優先度に向けて定量化の式を毎回見直したくなる気がする.

開発チームとの共依存について, ペアプロ等で相互に技術移管して割り込みで他者に仕事を依頼するのではなく, 自分ごととして対処できるようにするというのは理想的な状態. 現状,自分たちではまだまだ1人がやることが多くて技術移管までできそうにないのが辛いところ. このあたりは属人化の問題と関連しているのだろうけれど, どうしてもスピードが優先されるスタートアップにおいてなかなか 長期的な運用を見据えてスピードを犠牲にする判断はできない. 自分たちの取組みが必要なところかも.

[C6] Designing fault-tolerant microservices with SRE and circuit breaker centric architecture

クックパッドにおける既存のアプリの信頼性を担保しつつも機械学習サービスなど新しい技術領域を取り入れていく取組み.

このあたりは自分たちも近い将来同じ課題にぶつかることが想定されるので非常に参考になった. とはいえ,機械学習エンジニア側で開発リソースや自分たちで運用することができる前提なので なかなか同じようにはいかなそう. それでも信頼性の異なるサービスをサーキットブレイカーで分けるとか, デザインドキュメントで期待値をすりあわせるとか,できれば自分たちも取り入れたい.

若干ながら機械学習チームをつき離しているようにも聞こえたが, 何が大切なのかを共有できており,相互に信頼・尊重しているからこそできる無駄のない取組みだろう. そのようなチームができるように自分たちも頑張りたい.

[B7] SRE Practices in Mercari Microservices

メルカリにおけるマイクロサービスを実践していく中での,SLI/SLOを更新し続けるための取組み,オンコールへの対応,Toil(リアクティブなタスク)への取組み.

speakerdeck.com

これまでの発表内容が随所に出てくる,まさにロングセションに相応わしくSREの個々のプラクティスが一本にまとまるようで聞いていて非常に面白かった.

SLI/SLOを始めから完璧を目指さず更新していく体制を整えること,それを実現するためのポストポーテムの実践と SLO Decision Matrixを参考にしつつも 内容に応じて自分たちで判断することこは理想的なチームであるように見える.

アラートをアクション可能として,REDでアラートしてUSEで調査するという, 障害対応とはこのように実践するんだといわんばかりの体制だった.

Toilを減らしリアクティブなタスクに対処するため, デザインドキュメントで期待値を調整し,Production Readiness Checkでチェックするというのは 開発者とサービスリリース後にもめないためのリスクを減らす仕組みとしてよさそう. 一方でこれを実践しても形骸化せずサービスの品質に落とし込めるのは メルカリの優秀なエンジニアがいてこそだろうか.

[A8]基調講演: Webサービスを1日10回デプロイするための取り組み

Lobi(面白法人カヤック)における 10 deploy per dayを実現するために, デプロイを構成するあらゆる要素の高速化と誰でも安全にデプロイできる仕組みを実現する取組み.

speakerdeck.com

デプロイを高速化するためにエラー検知やロールバックを含めて高速化するところはなるほどと気付きを得た. 安全に誰でもデプロイできるようにするために,自動化するのはもちろん,計測して管理するのも王道だしよいプラクティスだと思った.

自分のところでは,デプロイが大変だと認識していてもまだデプロイも自動化できていない. デプロイ作業を計測して,デプロイの大変さを再共有し,自動化に向けた対応を強化するのはいいかもしれない. ChangeLogの生成自動化もやりたいところなので,早めに完了させたい.

全体をふりかえって

自分にもすぐに取組めそうなプラクティスから,すぐには取組めないけど将来の目標に見据えられるようなすばらしい取組みまで, さまざまな知見を共有できたすばらしい1日だった.

今までは先進技術として面白く感じていても他人事であったのが, やっと自分もインフラエンジニア・SREエンジニアとなって自分ごととなり, 自分事という新しい視点で話を聞けて非常に刺激になった.

取り入れられるプラクティスは積極的に取り入れて 今度は自分が発表する側に立てるようになりたい.

TerraformでAWS管理ポリシー/カスタム管理ポリシー混合のロールを作成する

なんで悩んでいたのかわからない.

ロールにアタッチするポリシーのうち, AWS管理ポリシーをアタッチする場合は data.aws_iam_policy で対象のarnを指定する, カスタム管理ポシリーをアタッチする場合は resource.aws_iam_policyでポシリーを作成してarnを指定する. アタッチはどちらも resource.aws_iam_policy_attachment を利用すればよい.

dataとresourceをきちんと理解していなかった.反省.

resource "aws_iam_role" "terraform_sts_role" {
  name = "terraform-sts-role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

resource "aws_iam_policy" "custom_s3_list_bucket" {
  name = "CustomS3ListBucket"
  path = "/"

  policy = <<POLICY
{
  "Statement": [
    {
      "Action": [
        "s3:ListAllMyBuckets",
        "s3:ListBucket",
        "s3:HeadBucket"
      ],
      "Effect": "Allow",
      "Resource": "*",
      "Sid": "VisualEditor0"
    }
  ],
  "Version": "2012-10-17"
}
POLICY
}

resource "aws_iam_policy_attachment" "attach_custom_policy_to_sts_role" {
  name       = "CustomS3ListBucket"
  policy_arn = aws_iam_policy.custom_s3_list_bucket.arn
  roles      = [ aws_iam_role.terraform_sts_role.name ]
}


data "aws_iam_policy" "ec2_read_only_access" {
  arn = "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"
}


resource "aws_iam_policy_attachment" "attach_ec2_read_only_access_to_sts_role" {
  name       = "EC2ReadOnlyAccessAttachment"
  policy_arn = data.aws_iam_policy.ec2_read_only_access.arn
  roles      = [ aws_iam_role.terraform_sts_role.name ]
}

実践Terraform AWSにおけるシステム設計とベストプラクティス (技術の泉シリーズ(NextPublishing))

実践Terraform AWSにおけるシステム設計とベストプラクティス (技術の泉シリーズ(NextPublishing))

書評:DNSがよくわかる教科書

DNSはなんとなくはわかるけど詳しいことは理解できていない, という状況の中で発売され評判もよかった本. やっとのことで読む時間を確保できたので読んだけど, 実際すごくよかった.

概要

DNSの仕組みから運用ノウハウまでを解説した本. 大きく3部構成で,DNSとは何かから学べる基礎編, 実際にネットワークを構築しDNS設定を行う設定やDNSを運用するときに必要な知見を記載した実践編, 運用のノウハウやセキュリティまわりの動向を扱ったアドバンス編で構成されている.

よかったところ

正確な表現を利用しつつも,わかりやすい解説があったことが良かった. インターネット上で調べると用語や説明がわかりにくいか,場合のよっては間違えているものが多く 理解の妨げになっていたけど, 世の中における誤りを指摘しつつ正しい用語で説明してくれたので理解が進んだ. その中でもわかりやすさを重視して解説してくれたおかげで, 途中で理解が迷子にならず読み進めることができた.

また,教科書というだけあって,一通りのトピックを扱っているので 知識の抜けがなく全体を俯瞰できたのはよかった. 加えてよくある誤りや設定ミスも記載されており, どういった点に注意すればよいかも理解しやすい.

8章のDNSの動作確認では実際にコマンドを使ってDNSの動きを理解できたこと, 9章のDNSに関するサイバー攻撃の分類と解説, 11章のDNS設定でよくある誤り, は特に参考になった.

よくなかったところ

全体をコンパクトにまとめることを重視したせいかもしれないけれど, もう少し説明が欲しい章はいくつもあった. 個人的には特にリソースレコードやDNSSECはもう少し詳しく扱って欲しかった. DNSの動作検証用のサイトとして取り上げた3つのDNSチェックサイトも どう見ればいいのか理解できていないでいる.

まとめ

DNSに対する苦手意識は払拭できたし, 今後どこの技術領域を調べればいいのかわかるようになった という点で非常によかった. インフラ/ネットワークを扱う人なら誰でも1度はDNSで つまずいた経験はあると思うので, そういう人には間違いなくお勧めできる. 基礎編はインフラを扱う人でなくても1度読んでおいて欲しいくらい.

GitHub Actionsのsteps.withディレクティブでは環境変数ではなく出力パラメータを利用する

タイトルがすべて.

steps.with ディレクティブにおける制御

GitHub ワークフローにてActionsを呼び出すとき, Actionsのパラメータ設定としてsteps.withディレクティブを利用する.

例えば,GitHubのリリースページにビルド成果物をアップロードする Upload Release Asset Actions では以下のように指定する.

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Upload Release Asset
        id: upload-release-asset 
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./my-artifact.zip
          asset_name: my-artifact.zip
          asset_content_type: application/zip

ここで, steps.withディレクティブ以下の upload_url, asset_path, asset_name, asset_content の4つが upload-release-asset Actionsの入力パラメータである.

入力パラメータの動的制御

Releaseページにアップロードするファイルを指定する asset_path において, ビルドソフトウェアのバージョンが含まれたファイルを指定したい. ソフトウェアバージョンを環境変数に設定したとして, 以下のような利用方法を想定する.

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Set software version
        run: |
          VERSION=$(cat VERSION)
          echo ${ VERSION }
      - name: Upload Release Asset
        id: upload-release-asset 
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./my-artifact-${ VERSION }.zip
          asset_name: my-artifact-${ VERSION }.zip
          asset_content_type: application/zip

このように,VERSIONファイルに格納されているソフトウェアバージョンをVERSION変数に格納し, ビルド成果物の制御にこの値を利用したい. しかし,この方法には以下の2つ問題がある

このため,Set software versionのステップにおける echo ${ VERSION }では期待した通りの値が出力されるが, Upload Release Assetのステップではそんなファイル存在しない (##[error]ENOENT: no such file or directory )と怒られてしまう. これは,VERSION 変数が設定されていない問題と,仮に設定されていたとしてもその変数を利用できない問題の両方を解決する必要がある.

出力パラメータによる制御

ではどうするかと言うと環境変数ではなく 出力パラメータ(output parameter)を利用しましょう,というのが解決策である. 出力パラメータは別のステップから出力結果を参照するための仕組みであり, steps.withディレクティブでも利用できる.

jobs:
  build:
    name: Upload Release Asset
    runs-on: ubuntu-latest
    steps:
      ...
      - name: Set software version
        id: software_version
        run: |
          VERSION=$(cat VERSION)
          echo ::set-output name=version::${ VERSION }
          echo ${ VERSION }
      - name: Check output parameter value
        run: |
          echo ${{ steps.software_version.outputs.version }}
      - name: Upload Release Asset
        id: upload-release-asset 
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./my-artifact-${{ steps.software_version.outputs.version }}.zip
          asset_name: my-artifact-${{ steps.software_version.outputs.version }}.zip
          asset_content_type: application/zip

このように, Set software version ステップにて VERSION変数の値を出力パラメータに設定しているので, 後段の Check output parameter value では最初に設定した VERSION 変数と同じ出力を確認することができ, Upload Release Assetステップの asset_pathasset_name でも利用することができる.