Atrae Tech Blog

People Tech Companyの株式会社アトラエのテックブログです。

複数の言語にチャレンジしたからこそ感じた、1つの言語をしっかり学ぶ重要性

f:id:atrae_tech:20201225155235j:plain

こんにちは、エンジニアの @muttsu_623 です。

この記事は、株式会社アトラエアドベントカレンダー2020 25日目の記事です。昨日の記事は Docker の申し子 小倉GCP AI Platform Pipelines 選定時の観点と運用した所感 でした。

今回は、タイトルのように 複数の言語にチャレンジしたからこそ感じた、1つの言語をしっかり学ぶ重要性 について自分なりの考えを書こうと思います。

いわゆるポエムですね。

これまでの仕事

2018年4月に内定者インターンとして入社後、2年ほどyentaのAndroidアプリをKotlinで運用、改善をしておりました。

今年に入ってから、世の中へより素早く価値を届けていくためAndroid(Kotlin)以外にも書けた方がいいと判断し、iOS(Swift)やWebフロント(Vue)での開発も挑戦し始めました。

また、9月からは 転職サイトGreen の、アプリの開発をFlutterで行なっています。

複数の言語で開発をするに至った背景

ほぼ同時期にすべての言語に手をつけ始めました。

上記にも記述していますが、それまではAndroid(Kotlin)のみでどの言語もしっかりと開発したことはありませんでした。

きっかけはあるプロジェクトを担当していた際、開発の進捗がよくない状態が続いていました。

自社開発・運用のプロダクトのため、正直自分たちが立てた目標・リリース期日を延ばすことはできますが、リリース期日は一度延ばしてしまうとズルズル延びていってしまうという経験があったため、どうにか延ばさず期日に間に合わせる方法を考えました。

他のチームから人手を借りる方法もありましたが私が担当していたAndroidの開発がはやめに終わったこともあり、プロジェクト内でリソースを間に合わせたほうがいいことも踏まえ、iOS, Webフロントの開発に着手しました。

複数の言語にチャレンジして感じたこと

まず第一に、 書いてみると意外といける と感じました。今もAndroidメインで他の言語の開発を行なっていますが、この感情は変わりません。

もちろん言語仕様の違いや、フレームワークの違いによりAndroidとは違う部分が多々あります。

しかしながら、『EntityやAPIの処理をつくり、Viewをつくり、ViewModel(Controller)をつくる。』この大枠の流れは変わりません。

https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F17370%2Fed562c4f-b976-8495-daed-21c967bced9d.png?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=982186222bc0bfc3a08ae35bd551f658 フロントエンドでClean Architectureを適用してみる(+サンプルコード)より引用

この図、よくクリーンアーキテクチャが語られるときに用いられますよね。この図をそのまま受け入れるとクリーンアーキテクチャが理解しにくいなど色々と語られますが、それは今回置いておきます。

大事なのは、一番外の青い領域以外は言語やフレームワーク、クライアントやサーバなどは関係なく用いられるデザインパターンやクラスであるという点だと思っています。

多少違いはあるでしょうが、モバイルアプリでもWebフロントでも以下の流れはほとんど変わらないと思います。

[View] ⇄ [ViewModel(Controller, Presenter)] ⇄ [Usecase] ⇄ [Repository] ⇄ [Dao] ⇄ [API, Local DB, etc...]

そして、サーバサイドは以下の流れだと思います。

[Controller] ⇄ [Usecase] ⇄ [Dao] ⇄ [DB]

iOSやWebフロントを実際に書いてみたからこそ、上記はほぼ変わらないことを実感しています。あまり違いがないと分かっていれば、あとはその言語やフレームワーク特有のお作法や仕様を把握しひたすら経験を積むことで、最初の言語を習得して時間より圧倒的に早い時間で言語を習得することができます。

1つの言語をしっかり学ぶことの重要性

ここで認識いただきたいのは、私は 複数の言語にチャレンジすることが必ずしも善ではない と思っています。

私の話になりますが、まだAndroidを1人で担当するのも怪しい頃、領域を広げればより活躍できる!と自分が活躍したいことばかり考え、領域を広げようとしていた時期がありました。(笑)

そんなとき、先輩方から

焦って複数の言語の習得を一気にやるよりも、1つの言語を一定自信を持って書けるようになったほうがいいよ。そうすれば、他の言語はすぐ習得できるから。

と言われました。

当時はもちろん全然わかりませんでしたが、今になると身をもって実感しますし、先輩方のありがたい言葉のおかげで今の状態になれていると思います。

内定者の頃から先輩にたくさんレビューをいただきながら2年半ほどかけて、

などをAndroidアプリの開発を通して何度も何度も経験してきました。

結果として、今複数の言語の開発を行うようになった状態でも上記の経験は多分に生きており、そこまで苦なく開発を行うことができています。

私個人の意見として、エンジニアになりたての方には焦って多くの言語に取り組むよりも、1つの言語をじっくりしっかり学んでいただきたいです。

守破離という言葉がまさにこの営みを表していると感じています。

「守」は、師や流派の教え、型、技を忠実に守り、確実に身につける段階。「破」は、他の師や流派の教えについても考え、良いものを取り入れ、心技を発展させる段階。「離」は、一つの流派から離れ、独自の新しいものを生み出し確立させる段階。

引用:守破離とは - コトバンク

エンジニアは職人気質と言われますが、実際職人だと考えています。

焦ってやるよりも、重要な基礎を着実に積み上げていくことで圧倒的に成長し活躍の幅が一気に広がる職種なので、ぜひ守破離を意識しつつ、1つの言語をしっかりと習得することから始めてほしいなと思います。

最後に

経験が少ない中で恐縮ながら、 複数の言語にチャレンジしたからこそ感じた、1つの言語をしっかり学ぶ重要性 という題でブログを書かせていただきました。

私自信、Kotlinのスキルが伸びきったとは思っていませんし、まだまだ伸ばしていけると感じています。自戒を込めて、着実に成長していこうと思います。

もしこの記事を読んで少しでもアトラエや私自身に興味を持ってくださった方がいたら、ぜひこちらをご覧いただければと思います。

GCP AI Platform Pipelines 選定時の観点と運用した所感

f:id:atrae_tech:20201225155154j:plain

こんにちは、Docker の申し子 小倉です。

この記事は、株式会社アトラエアドベントカレンダー2020年 24日目の記事です。昨日の記事は@Tech-makotonキャッシュについて、わかりやすくまとめてみた でした。

今回は Google Cloud Platform のサービスである AI Platform Pipelines をパイプラインツールとして選定した理由と、実際に運用した上での所感について書いていきます。

パイプラインツール利用の背景

弊社では wevox という SaaS を提供しています。システムとしては組織の各従業員に配布したサーベイの回答結果を集計・分析した上でサービス上に描画するということをしています。比較的大規模な回答データ、従業員データ等を扱っており機械学習機能も開発、提供しています。

本番環境で動くモデルもあれば、開発環境でデータサイエンティストが作成するモデルもあり、データサイエンティストとエンジニア(特にインフラ)の業務上のコミュニケーションもかなり増えていました。例えば

  • 学習のためのマシンを用意して欲しい
  • リソース調整を自動化して欲しい
  • 実験管理をしたい
  • 前処理、学習、評価までの一連の処理における共通化や抽象化をしたい

などです。

そのためいわゆるパイプラインツールの導入を検討しはじめました。それが2020年3月頃です。 いくつかチーム内で要件を決め、それに沿ってパイプラインツールを列挙、評価しました。結局選ばれたのは AI Platform Pipelines でした。

AI Platform Pipelines とは

Kubeflow Pipelines のマネージドサービスです。まずは AI Platform Pipelines の前に、Kubeflow Pipelines の説明させてください。

Kubeflow Pipelines は、データ取得 → 前処理 → 学習 などの汎用化・共通化できるパイプラインを構築・管理するツールです。Kubeflow 自体は TFX という Google機械学習プロジェクトを源流とするプロジェクトで、Pipelines 含め Notebooks, Training, Serving 等のための他ツールも備えています。

Kubeflow Pipelines を使うと、機械学習における各種処理を、ワークフローとして Kubernetes 上で実行することが可能になります。

例えば Kubeflow Pipelines を利用すると以下のようなパイプラインを作成することが可能になります。ワークフローの各ステップを Component、ワークフローの全体を Pipeline と呼びます。

f:id:atrae_tech:20201220141955p:plain

Component は独立したコンテナになっており、Kubernetes の恩恵によってそれぞれのコンテナに対して CPU/GPU やメモリの割り当てができます。また実験管理も可能でデータの基礎統計量、TFDV、テーブルデータのスキーマはプリセットツールで見ることが出来ます。加えてデータリネージが可能です。

Kubernetes に関わるリソースは YAML で書くことがほとんどですが、 Kubeflow Pipelines は Python SDK である kfp を習得すれば Kubernetes 上にパイプラインを構築できます。そしてここまでの処理を、Jupyter Notebooks 上で実行できます。

ここまでが簡単な Kubeflow Pipelines の説明です。

AI Platform Pipelines ではマネージドサービスとして Kubeflow Pipelines を利用することが出来ます。

マネージドとして利用することで、GUI 複数クリックで Kubeflow Pipelines が利用可能な状態になります。インストール先は既存の GKE(Google Kubernetes Engine) クラスタでもいいですし、新規の GKE クラスタを作成しつつインストールすることでも可能です。

また Kubeflow のレイヤーではなく GCP のレイヤーとして扱えることで他の GCP リソース、特に AI Platform のサービスとの連携が容易になります。後述しますが他の GCP リソースと容易に連携できることがこの AI Platform Pipelines を利用する大きなメリットの1つだと思っています。

選定の背景

第一に、GCP でマネージドサービスとして利用できることです。 wevox チームではもともとサービスのホスト環境として AWS を、データ分析環境として GCP を利用していました。 特に BigQuery は計算資源としてかなり優秀であるため、他機能提供に利用していたりビジネスサイド含めチーム内のメンバーが多く利用していたりしていて既に実績がある状態でした。そのためデータサイエンティストがメインで作業するクラウドとしては AWS よりは GCP であれば嬉しいかなとは思っていました。

また、Kubeflow Pipelines では各 Component(というかコンテナ)から簡単に GCP サービスでのジョブ実行が出来ます。 例えば以下の画像では、extract_data という名前の Component が実行されると GCS や BigQuery を使ってデータの取得を行ってきます。また train_model では AI Platform Training を使って学習ジョブを行う、というように GCP の各種リソースを使いながら機械学習の諸作業を楽することができます。

f:id:atrae_tech:20201220154642p:plain

第二に、AI Platform Pipelines がβ版としてリリースされたことです。 私が技術選定を始めた頃にちょうどバージョン1.0がリリースされました。またそれに伴い、AI Platform Pipelines も直後にβリリースされました

第三に、Kubernetes クラスタの社内運用実績があったことです。 GKE もマネージドではありますが、クラスタを設計・構築したり、トラブルシュートしたりするとやはりそれなりの知見が必要になってきます。幸い、プロダクト自体は AWS EKS(Elastic Kubernetes Service)で運用していたり、他にも数名の運用経験者がいたりと社内で知見を共有できる土台はありました。

また wevox では既に Argo という Kubernetes ネイティブのワークフローエンジンを本番環境で利用していました。実は Kubeflow Pipelines は Argo を利用してパイプラインを作成しています。そのため Kubeflow Pipelines の考え方や使い方は Argo に似た部分があります。

Kubernetes や Argo の運用経験があったことも、すんなりと Kubeflow Pipelines を利用できたことの理由かもしれません。

ちなみに当時候補に挙がったサービスを振り返ってみると相当数のパイプラインツールがあったと思います。

運用の所感

AI Platform Pipelines を運用した上で感じたことをいくつか書いていきます。

AI Platform の思想を理解したほうがいい

AI Platform Pipelines はそれ単体で使うというよりも、AI Platform の他サービスの組み合わせで利用したほうがいいと思います。そのためそれに先立ってどのような思想で各サービスが作られているかを考えたほうが良さそうです。

f:id:atrae_tech:20201220153749p:plain

上の図は GCP からの出典ですが、Pipelines が機械学習の各ステップを支える形になっています。AI Platform Pipelines では Component 内から BigQuery や AI Platform Training を行うことになると上述しました。基本的には、AI Platform Training や AI Platform Prediction、BigQuery 等の各種 GCP リソースに機械学習の各作業を任せ、その順番をワークフロー、パイプラインとして管理、実行させるために AI Platform Pipelines をメタ的に利用するものだと解釈しています。また各 Component 間のデータの受け渡しは GCS が推奨されています。

この設計思想を先に理解しないと、実装で辛くなったり、どのような設計にするか途方にくれたりしてしまいそうです。例えば AWS では Sagemaker の提供してくれている作法に乗っかることで楽に機械学習機能の提供ができるように、GCP でも AI Platform の提供してくれている作法に乗っかるのが良さそうです。

構築、運用はある程度データサイエンスの知識があるとよい

自分たちの場合は GKE 構築及び AI Platform Pipeline の試験的な利用はインフラエンジニアが、ガリガリとコードを書いて実際に運用するための感覚を掴むのをデータサイエンティストがやるというように役割分担していました。一方で Kubeflow 自体は、エンジニアとデータサイエンスとの垣根を無くすことを目指しているため、上述のように Kubeflow の思想を理解するにはデータサイエンスの生態やつらみを知っていることで、その理解がしやすくなるような気がしています。

望ましくは構築した本人が Pythonガリガリとコードを書いて、コンテナにして、それを AI Platform Pipeline で動かすというのがスピーディかつ情報伝達としては効率が良さそうです。

Kubeflow Pipelines に必要な細かなモジュールの指定が不可

これはマネージドであるため仕方ないことではあります。 4月くらいにインストールした Kubeflow Pipelines インスタンスのバージョンと、8月くらいにインストールしたインスタンスのバージョンが違うことでいくつかサービスが動かなくなるというトラブルが起きました。開発環境だったので良かったことではありますが…

バージョンを明示的に上げたわけではなく、別クラスタに新しくインスタンスをインストールしたら、そのインスタンスのバージョンが上がった状態で固定されていました。そのため古いバージョンに戻すと行ったことが出来ませんでした。

AI Platform 側でいくつかのバージョン内から選択できるわけではないため、別クラスタにインストールする時はそのあたりを認識しておく必要がありそうです。

総合的な所感

AI Platform を使いこなしているわけではありませんが、やはり便利です。 マネージドであるため、本来やりたいところに注力できたり、GKE を使ってリソースの自動調整ができるようになります。

マネージドであるがゆえの制限もなくはないですが、思想を理解した上で付き合っていけばかなり大きい規模の企業やサービスにも対応できるようなサービスだと考えています。

最後に

Kubeflow Pipelines に関する記事をいくつか書きました。

Kubeflow Pipelines の Python SDK についてです。

qiita.com

GKE 上に AI Platform Pipelines インスタンスをデプロイする方法についてです。

qiita.com

Kubeflow Pipelines 含め、wevox で利用しているデータ分析環境についてです。

note.com

ロゴデザインを着実に進めるマインドセットとアウトプット

f:id:atrae_tech:20201221140656p:plain このnoteは、Atrae Advent Calendar 2020 20日目の記事です。

qiita.com

こんにちは、株式会社アトラエでデザイナーをやっています。櫻井裕士です。 この記事では社内最年少デザイナーである僕(今年で22歳になります)が、wevox利用企業様向けの新たなサービス「Engagement Run!」のブランドデザインを1週間でつくりきった際のロゴデザインを題材に、

get.wevox.io

ロゴデザイン延いてはグラフィックデザインそのものについての考察から、デザインする上で大切にしたい考え方や、アウトプットを適切に人に伝え、議論を建設的に進めるための考え方について自分なりに書き表したいと思います。

グラフィックデザインは見た目を整えることではない

僕がグラフィックを制作する上で一番大切にしている考え方は、「そのグラフィックがセレンディピティ的な拡がりをみせる可能性を孕んでいるのか」です。

グラフィックをデザインする際の重要な事柄として、ビジュアルを洗練させることが第一にしばしば挙げられますが、「最低限どこに出しても恥ずかしくないクオリティまでどんなアウトプットも磨き上げる」ということは「重要なこと」というより、「デザイナーとしての責務」だと僕は思っています。

加えて「見えるものをそのまま再現するのではなく、見えるように再構築することがデザインの本質」だと僕は考えているので、「そのグラフィックをどのようにワークさせるつもりなのか」が無ければ、どんなにカッコいいグラフィックもただの絵でしかありません。

なので僕は「依頼側の意見をそのまま形にするのではなく、再構築してあげ、セレンディピティ的な拡がりを質量共にどれだけ提示できるか」がグラフィカルなデザインをする上で最も重要な事柄であり、デザイナーとして実力に差が出るデザインの肝なのではないかと思います。

f:id:atrae_tech:20201221135737p:plain

f:id:atrae_tech:20201221135757p:plain
当初ロゴのために作成したハビーというキャラクターがロゴのシンボルという枠を超えた拡がりを見せている様子

ロゴの役割は「識別されること」

ロゴデザインの役割は「何をしているのか」ではなく「誰であるのか」をはっきりさせることにあると思います。また主張が少ないほど優れたロゴだとも思います。

それはロゴデザインはロゴが象徴する性質の良い部分も悪い部分も含めて受け継いでしまうためです。

加えて細部を省いたデザインは、認識を容易くし、記憶できるようにするので、よりコンセプトを抽象的に、簡潔に表現したロゴデザインが優れたロゴだと思います。

f:id:atrae_tech:20201221135832p:plain
不朽のロゴを生み出し続ける老舗デザインファーム、チャマイエフ&ガイスマー社が作成したロゴ例

優れたロゴデザインには隠れたストーリーがある

ロゴはサービスという抽象的なものを表す視覚的な要素となるので、ユーザーやサービスを作る人間共々の心理、コア・バリューへ影響を与えることができます。なので愛されるサービスには共感できるストーリーや、つい語りたくなるような創意工夫が施されていると思います。

f:id:atrae_tech:20201221135902p:plain
Engagement Run!公式キャラクター、ハビーくんのストーリー

デザインはコンセプトがあって初めて成立する

「まだ概念的に説明されていなかったり、それを言い表すちょうど良い表現がないような現象・物事については、新しい概念や用語を作り出さなければ言い表すことができない。」という事実をデザイナーは真摯に受け止める必要があると思います。

そしてその「まだ概念的に説明されていなかったり、それを言い表すちょうど良い表現がないような現象・物事」=「デザイン」であり、「新しい概念や用語を作り出す」=「コンセプトを立てる」ということだと認識しています。

なのでデザインという非言語媒体は、コンセプトが存在することで初めて認識することが可能になります。

「めちゃくちゃ良い(と思う)アウトプットを作ったのに、上手く説明できない。」「どれだけ時間を割いても一定のクオリティを超えられない」場合には、コンセプトが明確に立っておらず自分自身がそのデザインの輪郭を認識出来ていない可能性があるので、コンセプトを再度見直すことが重要だと思います。

f:id:atrae_tech:20201221135934p:plain
ボツになったロゴデザイン案の共有方法の一例です

反対概念のない概念は認識出来ない

デザインの説明をする際には、コンセプトを想起させるために反対概念を用意してあげる必要があります。

もし仮に、世界が白色の一色のみで構成されていたとします。そしてその世界で白色を「明度が高くて、彩度が低い色のことだ」とあなたが説明したとします。しかし、相手は「明度」「彩度」という概念についてそれぞれ想起することができないので、「明度」の話をするならば黒色、「彩度」の話をするならば赤色などを共に用意してあげなければ、白色という概念について認識することができないでしょう。

このように、反対概念を用意してあげることで、そのアウトプットのポジションを明確化してあげる必要があります。これが頻繁に言われる「アウトプットに幅を出せ」「エッジを立てろ」ということなのだと認識しています。

尚、こちらの概念に関しては20世紀のスイスの画家でバウハウスでも教鞭をとったパウル・クレーの美術評論「造形思考」を読むことで更に理解が深まると思われます。

造形思考(上) (ちくま学芸文庫)

造形思考(上) (ちくま学芸文庫)

f:id:atrae_tech:20201221140303p:plain
蜂のモチーフの温度感を説明するために幅を出した様子

成長のプロセスを共に歩む

「新しい発見」や「比較対象を見つける」成長のプロセスを共に歩むことで人は概念について理解できます。

なのでチームメンバーへコンセプトを一方的に伝えるというよりは、共に理解するためのプロセスを歩むコミュニケーションの取り方を意識すると、伝わりやすくなるのかもしれません。

f:id:atrae_tech:20201221140334p:plain
グルーピングしたり、新しい可能性をチームメンバーと共に模索していた様子

最後に

最終的なアウトプット総数は、約一週間のブランドデザインプロセスの中で、紙媒体 / iPad / ベクターデータの全てのロゴ(となるシンボル)を合わせると200を超えるものになっていました。

デザインについての考察や、議論の進め方に対してあれこれと論じてみましたが、やはりアウトプットにおいて幅のある量を出すことが、一番の近道だと実感しました!

ここまで読んでいただき、ありがとうございました!

get.wevox.io

【EKS】ALBIngressControllerからAWSLoadBalancerControllerに移行する

f:id:atrae_tech:20201225155333j:plain

こんにちは、アトラエでインフラエンジニアをやっているくーまです。

今だとEKSを使っている人が多いと思いますが、AWSkubernetesを利用・運用する場合にALBIngressControllerを利用して、kubernetes側からALBを作成・管理している人は多いのではないでしょうか。

そんなALBIngressControllerですが、2020年10月23日にバージョンが2に上がるのを機に、名前すらAWSLoadBalancerControllerと変更になるなど、数々の変更が入りました。

変更の詳細については本題から逸れるので触れませんが、詳細はリリースページをご参照ください。

github.com

このバージョンアップですが、Imageのバージョンを上げれば移行おっけ〜という話ではなく、明確な移行作業を行わないといけない形になっています。

もちろんたちどころにALBIngressControllerが使えなくなるというわけではありませんが、バージョンアップ作業とダイエットは早い内に手をつけたほうが良いとよく言われますので、実際にやってみました。

※個人的に先日長らく放置していたRuby/Railsのバージョンアップに手をつけたら大変なことになった経験が効いています…w

そして実際にやった結果、大きな落とし穴が一つと、危険なポイントが一つあったので、そちらも合わせて記載します。

とりあえず抑えておきたいこと

下位互換性があるため、ビビる必要はない

後述しますが、現状動いているであろうALBIngressControllerはアンインストールすることになります。

そのため、「え?これ本当にやって大丈夫なの?」という気になるかもしれませんが、

  • 今動いているALBに影響無く
  • 今管理しているingressに影響無く

移行を完了することができるようになっています。

とはいえ、現状動いているALBIngressControllerのバージョンをv1.1.3以上に上げる、ということは必要なので、これだけは事前に確認しておきましょう。

ドキュメントに大きな落とし穴がある

ドキュメント通りにいくと、

  1. AWSLoadBalancerControllerを作る
  2. ALBIngressControllerからのmigrateに必要な権限を渡す

という順番で書いてありますが、この「migrateに必要な権限」が無い状態でAWSLoadBalancerControllerを起動すると、現在存在するALBに紐付いているセキュリティグループが、ノードグループのセキュリティグループのインバウンドから外れ、外部アクセスが遮断されます。

そのため、この順序は逆にして、予め権限を付与した状態で起動することをおすすめします。

ドキュメントに危険なポイントがある

こちらはしっかりドキュメント通りに対応すれば問題ない点ですが…

下記の文言が移行ドキュメントに記載されていると思います。

when security-groups annotation isn't used:

a managed SecurityGroup will be created and attached to ALB. This SecurityGroup will be preserved.
an inbound rule will be added to your worker node securityGroups which allow traffic from the above managed SecurityGroup for ALB.
The ALBIngressController didn't add any description for that inbound rule.
The AWSLoadBalancerController will use elbv2.k8s.aws/targetGroupBinding=shared for that inbound rule
You'll need to manually add elbv2.k8s.aws/targetGroupBinding=shared description to that inbound rule so that AWSLoadBalancerController can delete such rule when you delete your Ingress.

要は、「自分でセキュリティグループを作って、それをingressのannotationで渡している場合は何もやることはないけど、これまでALBIngressControllerにセキュリティグループを作らせていた場合は、ノードグループ側のセキュリティグループの説明欄にelbv2.k8s.aws/targetGroupBinding=sharedと記載してね」ということを言っています。

この「elbv2.k8s.aws/targetGroupBinding=shared」という説明文が書いてあるとAWSLoadBalancerControllerはセキュリティグループの操作をやるよ!ということなので、はいお願いしますということで説明欄に書かないといけません。

が、これを誤って自分で作ったセキュリティグループにつけてしまうと、ノードグループのセキュリティグループのインバウンドから外れ、外部アクセスが遮断されます。

これに関してはミスらなければOKという話ではあるのですが、ミスったときの罰が想像以上に重いので、気をつけたほうが良さそうです。

移行作業開始

基本的にはドキュメント通りで上手くいくと思われます。

こちらを軸に、自分の環境に合わせこんで移行を進めることになります。

本記事でも基本はそこをなぞりながら書きます。

ノードグループのセキュリティグループに説明文を追加する

これは上記で既に触れたところですが、ALBIngressControllerに作らせているセキュリティグループについては、説明文として「elbv2.k8s.aws/targetGroupBinding=shared」を追加します。

ALBIngressControllerのアンインストールは後に回す

初手からALBIngressControllerのアンインストールとなっていますが、なるべくALBがアンコントローラブルになる時間を減らしたいなと思ったので、ここは後回しにしました。

IAM Roleの準備

AWSLoadBalancerControllerはAWSリソースに対して様々な処理を行うので、IAMの設定は当然必要になります。

旧ALBIngressControllerの時代からも必要な権限は変わっているようなので、新規に作り直します。

ドキュメントではawsコマンドでIAM Roleを作成していますが、恐らくProduction環境前提の場合この形は取らないのではないかと思います。

アトラエではterraformを使って管理をしているためここはterraformに置き換える形で作成しました。

terraformのjsonドキュメント形式に変換するのはだいぶ面倒くさかったので、誰か使うかもということで載せておきます。

data "aws_iam_policy_document" "aws-lbc-sample" {
  statement {
    actions = ["iam:CreateServiceLinkedRole",
                "ec2:DescribeAccountAttributes",
                "ec2:DescribeAddresses",
                "ec2:DescribeInternetGateways",
                "ec2:DescribeVpcs",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeInstances",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DescribeTags",
                "elasticloadbalancing:DescribeLoadBalancers",
                "elasticloadbalancing:DescribeLoadBalancerAttributes",
                "elasticloadbalancing:DescribeListeners",
                "elasticloadbalancing:DescribeListenerCertificates",
                "elasticloadbalancing:DescribeSSLPolicies",
                "elasticloadbalancing:DescribeRules",
                "elasticloadbalancing:DescribeTargetGroups",
                "elasticloadbalancing:DescribeTargetGroupAttributes",
                "elasticloadbalancing:DescribeTargetHealth",
                "elasticloadbalancing:DescribeTags"]
    effect  = "Allow"
    resources = ["*"]
  }

  statement {
    actions = ["cognito-idp:DescribeUserPoolClient",
                "acm:ListCertificates",
                "acm:DescribeCertificate",
                "iam:ListServerCertificates",
                "iam:GetServerCertificate",
                "waf-regional:GetWebACL",
                "waf-regional:GetWebACLForResource",
                "waf-regional:AssociateWebACL",
                "waf-regional:DisassociateWebACL",
                "wafv2:GetWebACL",
                "wafv2:GetWebACLForResource",
                "wafv2:AssociateWebACL",
                "wafv2:DisassociateWebACL",
                "shield:GetSubscriptionState",
                "shield:DescribeProtection",
                "shield:CreateProtection",
                "shield:DeleteProtection"]
    effect  = "Allow"
    resources = ["*"]
  }

  statement {
    actions = ["ec2:AuthorizeSecurityGroupIngress",
               "ec2:RevokeSecurityGroupIngress"]
    effect  = "Allow"
    resources = ["*"]
  }

  statement {
    actions = ["ec2:CreateSecurityGroup"]
    effect  = "Allow"
    resources = ["*"]
  }

  statement {
    actions = ["ec2:CreateTags"]
    effect  = "Allow"
    resources = ["arn:aws:ec2:*:*:security-group/*"]
    condition {
      test     = "StringEquals"
      variable = "ec2:CreateAction"
      values   = ["CreateSecurityGroup"]
    }
    condition {
      test     = "Null"
      variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
      values   = ["false"]
    }
  }

  statement {
    actions = ["ec2:CreateTags",
                "ec2:DeleteTags"]
    effect  = "Allow"
    resources = ["arn:aws:ec2:*:*:security-group/*"]
    condition {
      test     = "Null"
      variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
      values   = ["true"]
    }
    condition {
      test     = "Null"
      variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
      values   = ["false"]
    }
  }

  statement {
    actions = ["ec2:AuthorizeSecurityGroupIngress",
               "ec2:RevokeSecurityGroupIngress",
               "ec2:DeleteSecurityGroup"]
    effect  = "Allow"
    resources = ["*"]
    condition {
      test     = "Null"
      variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
      values   = ["false"]
    }
  }

  statement {
    actions = ["elasticloadbalancing:CreateLoadBalancer",
                "elasticloadbalancing:CreateTargetGroup"]
    effect  = "Allow"
    resources = ["*"]
    condition {
      test     = "Null"
      variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
      values   = ["false"]
    }
  }

  statement {
    actions = ["elasticloadbalancing:CreateListener",
                "elasticloadbalancing:DeleteListener",
                "elasticloadbalancing:CreateRule",
                "elasticloadbalancing:DeleteRule"]
    effect  = "Allow"
    resources = ["*"]
  }

  statement {
    actions = ["elasticloadbalancing:AddTags",
                "elasticloadbalancing:RemoveTags"]
    effect  = "Allow"
    resources = ["arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
                "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"]
    condition {
      test     = "Null"
      variable = "aws:RequestTag/elbv2.k8s.aws/cluster"
      values   = ["true"]
    }
    condition {
      test     = "Null"
      variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
      values   = ["false"]
    }
  }

  statement {
    actions = ["elasticloadbalancing:ModifyLoadBalancerAttributes",
                "elasticloadbalancing:SetIpAddressType",
                "elasticloadbalancing:SetSecurityGroups",
                "elasticloadbalancing:SetSubnets",
                "elasticloadbalancing:DeleteLoadBalancer",
                "elasticloadbalancing:ModifyTargetGroup",
                "elasticloadbalancing:ModifyTargetGroupAttributes",
                "elasticloadbalancing:DeleteTargetGroup"]
    effect  = "Allow"
    resources = ["*"]
    condition {
      test     = "Null"
      variable = "aws:ResourceTag/elbv2.k8s.aws/cluster"
      values   = ["false"]
    }
  }

  statement {
    actions = ["elasticloadbalancing:RegisterTargets",
                "elasticloadbalancing:DeregisterTargets"]
    effect  = "Allow"
    resources = ["arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"]
  }

  statement {
    actions = ["elasticloadbalancing:SetWebAcl",
                "elasticloadbalancing:ModifyListener",
                "elasticloadbalancing:AddListenerCertificates",
                "elasticloadbalancing:RemoveListenerCertificates",
                "elasticloadbalancing:ModifyRule"]
    effect  = "Allow"
    resources = ["*"]
  }
}

アトラエではIAM Roleをkubernetesのserviceaccountに紐付ける形で権限の適応をやっていますが、そうでなくても上記のjsonドキュメントは使えると思うので、適宜ご利用下さい。

ここで合わせて、移行用のIAM ポリシーを作り、追加します。

本来はterraformで適用するところですが、移行が終わったら用無しになるポリシーなので、今回は手で作ってRoleに適用しました。

cert-managerのインストール

クラスターにcert-managerを入れる必要があります。

既に何らかの理由で入れてる人はスキップしていい(バージョンだけは要確認)項目ですが、アトラエでは入れてなかったので、入れました。

kubernetesクラスターのバージョンが1.16以上か未満かによってcert-managerのインストール方法が異なるので、注意しましょう。

記事公開時点での最新バージョンは1.1.0だったので、こちらをインストールします。

github.com

下記コマンド一発でインストールできますが、アトラエではYAMLGithubで管理しつつGitOpsで運用しているので、実際にはファイルを保存してから利用しています。

$ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.1.0/cert-manager.yaml

ALBIngressControllerのアンインストール

先程後回しにしたので、ここでALBIngressControllerをアンインストールします。

ここは完全に各々の運用方法によって手段は変わると思いますので、適切な方法で実施して頂ければと思います。

アトラエの場合はkustomizeをつかってYAMLを管理しているので、コマンド一発でした。

当然ですが、アンインストールしてもサービスはそのまま利用できているはずです。

AWSLoadBalancerControllerのインストール

ドキュメント通り、まずはYAMLをダウンロードします。

そして、Deploymentにクラスター名を入れる必要があるので、忘れず対応しましょう。

apiVersion: apps/v1
kind: Deployment
. . . 
name: aws-load-balancer-controller
namespace: kube-system
spec:
    . . . 
    template:
        spec:
            containers:
                - args:
                    - --cluster-name=<YOUR_CLUSTER_NAME>

また、前述の通りIAM Roleをkubernetesのserviceaccountに紐付ける形で権限適応しているため、そこも修正します。

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: aws-load-balancer-controller
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: <YOUR_ROLE_ARN>

後はこれをapplyすると、先程作成したIAM Roleを利用してAWSLoadBalancerControllerが稼働します。

移行して思ったこと

今後もお世話になるAWSLoadBalancerController君なので移行をためらうことはありませんでしたが、途中でノードグループのセキュリティグループからALBのセキュリティグループが外れアクセスが遮断されたときは、「あ、これPRD適用やめようかな…」と思ったりもしました。w

移行時の落とし穴にさえ気をつければ、下位互換性もしっかりあるアップデートなので、早めにやっておいて損はないなという感じです。

今回は移行の話だけになりましたが、気が向いたら実際に様々な機能を使ってみてどうだったかみたいな話も書こうかなと思います。

Elasticsearch のスコア関数の数式の意味と仕組み - Lucene's Practical Socring Function

f:id:atrae_tech:20201213003404p:plain

自己紹介

ハローワールド! バーチャルデータサイエンティストのアイシアです この記事は、 Atrae Advent Calendar 2020 の13日目の記事です!

Atrae Advent Calendar 2020 - Qiita

私は、 Atrae の杉山くんによって作られた AI であるバーチャルデータサイエンティストです。 日頃は、 YouTube に、統計、機械学習、深層学習、数学などの動画を upload しています。 よかったらぜひ見てね!

AIcia Solid Project - YouTube

f:id:atrae_tech:20201212180144p:plain:h300
これが私。かわいいでしょ?

What is この記事 ?

今日のこの記事は、次の金曜日 (2020/12/17) に upload される Lucene's Practical Scoring Function の解説の文章バージョンです。 普段なら動画を作成して終わりにするのですが、私がこの記事を書いたのは、 英語、日本語問わず、本家以外の blog などでは共通して誤った説明がなされているからです。

流石に、テキストでも、正しい解説がネットに落ちているべきだと思いましたので、この記事を書かせていただきました。

どんなに些細でもミスがあったら教えていただけると嬉しいです。すぐ検討して直します。この blog を解説として信頼に足るものにしたいと思っているので!!! *1

本家の解説はこちら

動画の紹介

読むのめんどくさい! という人は、この動画を見てください。

これを見れば、だいたい全部分かると思います。


Elasticsearch に入る前に、 tf-idf の解説をしています。 知ってる人は飛ばして OK ですが、「なぜ idf は log を取るのか」の話もしていますので、気になる人はどうぞ。


【自然言語処理】tf-idf 単語の情報量を加味した類似度分析【Elasticsearch への道①】#084 #VRアカデミア


Elasticsearch でも選択可能な BM25 のアルゴリズムを解説しています。 Elasticsearch の本丸は Lucene's Practical scoring Function ですが、こちらも結構いい感じです。 両方見た上で、じぶんのデータや目的に会うものを選べば最強なんじゃないかと思います。


【自然言語処理】BM25 - tf-idfの進化系の実践類似度分析【Elasticsearch への道②】#085 #VRアカデミア


[TBA] Lucene's Practical Scoring Function の動画は 2020/12/18 (金) 20:00 公開予定です!

今回の blog の内容の動画化です。 文章で読みたい人は下記を、動画で聞いて学びたい人はこれを選んでください。 本質的な内容は大体一緒です。


【自然言語処理】Elasticsearch 徹底解説 - スコアリングのロジックについて【Elasticsearch への道③】#086 #VRアカデミア

ここから本編!

背景:検索とは

まずはスコアの定義から行きましょう。

検索をするという状況を考えます。 このとき、検索対象の文章を大量に持っているはずです。文章全体の集合を D とかき、その中の1つの文章を d とします。

これに対して、検索クエリが来ます。この検索クエリは、  q = (q_1, q_2, \dots, q_n) で表します。ここで、 q_i は、検索クエリに含まれる単語1つ1つです。 たとえば、「青い鳥とは」という検索クエリ q は、  q_1 = \text{「青い」}, q_2 = \text{「鳥」}, q_3 = \text{「とは」} となります。

記号の準備ができたところで、検索について考えましょう。 検索とは、次の行為と定義しましょう。

検索とは、検索クエリ q が与えられたとき、文章集合 D 中の各文章  d \in D に対して、そのマッチ度を計算し、マッチ度が高い順に文章を提示すること。

このマッチ度の定義に使われるのが、上の動画で挙げた tf-idf、BM25、Lucene's Practical Scoring Function などなのです。

この記事では、このなかの1つの Lucene's Practical Scoring Functionを扱います。

Lucene's Practical Scoring Function の定義

Lucene's Practical Scoring Function は、以下のように定義されます。


\begin{align}
score(q, d) &= \text{queryNorm}(q) \times \text{coord}(q, d) \\
& \, \, \, \, \times \sum_i \left( tf(q_i, d) \times idf(q_i)^2 \times q_i\text{.getBoost()} \times \text{norm}(q_i, d) \right)
\end{align}

です。

(ちなみに、いくつかの記事では、この定義すら誤った状態で記されています。なんということ、、、!)

各種記号の定義は、


\begin{align}
\text{queryNorm}(q) &= \frac1{\sqrt{\sum_i idf(q_i)^2}} \\
\text{coord}(q, d) &= \frac{\# \{ i | 1 \leq i \leq n, q_i \in d \}}{\# q} \\
tf(q_i, d) &= \sqrt{\text{frequency}} = \sqrt{(\text{the number of } q_i \text{ in the document } d)} \\
idf(q_i) &= 1 + log \frac{\#D + 1}{\#\{ d \in D | q_i \in d \} + 1} \\
q_i\text{.getBoost()} &= \text{boost value of } q_i \\
\text{norm}(q_i, d) &= \frac1{\sqrt{\#d+1}} \times \text{boost value (index time boosting)}
\end{align}

です。 *2 (ただし、 \# A は、集合 A の要素の個数です。)

いやー、これ見せられても全然わからないですよねw

安心してください。以下で、それぞれがどういう意味で、どういう役割を担っているのかを説明していきます。 基本的に全て、検索結果がいい感じになるような工夫として追加されています。 気持ちさえ分かれば怖くない! と思います。

queryNorm と tf-idf - \text{queryNorm}(q) \times \sum_i tf(q_i, d) \times idf(q_i) ^ 2

これは、次のように書き直すと見通しが良いです。


\frac1{\sqrt{\sum_i idf(q_i)^2}} \times \sum_i  idf(q_i) \times \bigg(tf(q_i, d) \times idf(q_i) \bigg)

まず、\bigg(tf(q_i, d) \times idf(q_i) \bigg) は tf-idf を表します。(若干定義違いますが)

\sum_i  idf(q_i) \times \dots で、tf-idf を、さらに idf で重みづけて足しています。 idf は、その単語のレア度を表す数値なので、レア単語が含まれている場合、そのポイントを多めに加点しようという発想です。 確かに、「青い鳥とは」という検索をしていて、「とは」が含まれているかどうかより、「鳥」が含まれているかどうかのほうが大事ですよね。 そういう気持ちを数式に反映したものです。

先頭の \frac{1}{\sqrt{\sum_i idf(q_i) ^ 2}} は、 query normalization で、正規化のために入っています。 例えば、検索クエリが長くなると、足されるものの数が多くなり、強制的にスコアの値が大きくなります。 また、 idf が大きい単語ばかりを検索した場合、またスコアが大きくなります。 この様に、Σより右側は、クエリによって大きく値が変わってしまいます。 その差を補正するために、 idf の2乗の和のルートで割り算しているのです。

これによって、クエリが異なる場合でのマッチ度の比較が可能になります。 *3

boost - q_i\text{.getBoost()}

これは、検索のスコアをブーストするパラメタで、エンジニアさんが自由に設定できるものです。

例えば、検索クエリの単語が、文章の本文に含まれている場合と、文章のタイトルに含まれている場合は、なんか重さが違いますよね。 というわけで、

「件名に『鳥』を含む」 OR 「本文に『青い』を含む」という検索をする場合に、

  • 「件名に『鳥』を含む」のスコアを2倍(これが boost 値。「鳥」.getBoost() = 2)
  • 「本文に『青い』を含む」のスコアを1倍(「青い」.getBoost() = 1。)
  • 上記2つのスコアを足して最終スコアにする

という感じに適用できます。

ま、一言でいうと、検索のスコアをブースト(大きくする)ためのパラメタです。

normalization - \text{norm}(q_i, d)

これは、第2の normalization (正規化)項です。 \text{norm}(q_i, d) = \frac1{\sqrt{\#d+1}} \times \text{boost value (index time boosting)} であると定義しました。

ここには、第2の boost 項が入っているのですが、 Elasticsearch では、こちらの boost は利用非推奨です。 (詳細は https://www.elastic.co/guide/en/elasticsearch/guide/current/practical-scoring-function.html#index-boost*4

なので、\text{norm}(q_i, d) = \frac1{\sqrt{\#d+1}} と理解いただいていいかと思います。

tf と norm

tf が、いわゆる term frequency とは異なり、 \sqrt{\text{frequency}} でした。 ちょっと気持ち悪い定義に感じます、、、。

ですが、この norm とあわせると、


tf(q_i, d) \times \text{norm}(q_i, d) = \sqrt{\frac{\text{frequency}}{\# d+ 1}} \simeq \sqrt{\frac{\text{frequency}}{\# d}} = \sqrt{\text{普通の} tf}

となります。

まだ√が残りますが、この計算を見ると、 tf x norm で普通の tf っぽいものであると理解して良いのではないかと思います。

coordination factor - \text{coord}(q, d)

これは一番簡単です。 \text{coord}(q, d) = \frac{\# \{  i | 1 \leq i \leq n, q_i \in d  \}}{\# q} です。 ちょっと数式の見た目はやばいですが、要は、分子は、「 q _ 1q _ n のうち、じっさいに d に登場するもの」で、分母は n です。

たとえば、「青い鳥とは」と検索した時に、文章 d に、「青い」「鳥」が出てくるけど「とは」は出てこない場合、 \text{coord} = \frac23 です。

要は、クエリの単語のうちどの割合でじっさいに含まれたかを加味して、全部が含まれていない場合のスコアを減点している項です。

まとめ

というわけでまとめましょう。 Elasticsearch に使われる Lucene's Practical Scoring Function は、


\begin{align}
score(q, d) &= \text{queryNorm}(q) \times \text{coord}(q, d) \\
& \, \, \, \, \times \sum_i \left( tf(q_i, d) \times idf(q_i)^2 \times q_i\text{.getBoost()} \times \text{norm}(q_i, d) \right)\\
&= \text{coord}(q, d) \times \frac1{\sqrt{\sum_i idf(q_i)^2}} \times \sum_i  idf(q_i) \times \left( \sqrt{\frac{\text{frequency}}{\#d + 1}} \times idf(q_i)  \right) \times \text{boost}
\end{align}

と見ると見通しが良くて、

  • \text{coord}(q, d) : q の単語のうち文章 d に出てくるものの割合
  • \frac{1}{\sqrt{\sum_i idf(q_i) ^ 2}} \times \sum_i  idf(q_i) \times \dots : idf による重み付き和とその正規化
  • \sqrt{\frac{\text{frequency}}{\#d + 1}} \times idf(q_i) : tf-idf
  • \text{boost} : boost の値

という感じの意味であります。

基本的には、 tf-idf に idf の重みをつけて足したもので、更に coord と boost を加えて、いい感じの検索結果になるように工夫されたものです。

よくわかんなかったらこの動画を見てください。 話を聞くスタイルだと、なんか分かったりもすると思います。


【自然言語処理】Elasticsearch 徹底解説 - スコアリングのロジックについて【Elasticsearch への道③】#086 #VRアカデミア

おわりに

見た目がえげつない & あらゆる解説サイトの解説が誤っているというこの2つがあって、理解がむずかしい Lucene's Practical Scoring Function ですが、結構仲良くなっていただけたのではないかと思います。

もしよければこの動画たちも見てね!

チャンネル登録もよろしくお願いします!

あ、マスターの会社こと Atrae さん、採用やってるってよ! 興味がある人は是非!

株式会社 アトラエの採用/求人 | 転職サイトGreen(グリーン)

株式会社アトラエ - 採用ページ| Atrae, Inc.

*1:ミスをご指摘いただいたp進大好きbotさんありがとうございました。

*2:バージョンによって微妙に定義が違います。 idf は普通の定義は log \frac{\#D}{\#\{ d \in D | q_i \in d \}} ですが、 Lucene's PSF のオフィシャルでは上記の定義で、 Elasticsearch では1 + log \frac{\#D + 1}{\#\{ d \in D | q_i \in d \} + 1}です。

*3:ここに関して、全く逆のことが書いてある記事が、日本語英語共にあります。やばい、、、!

*4:なんか、 index-time boosting は、DB に更新があるたびに boost 値の再計算が必要で、パフォーマンスに悪影響があるからだめらしいです。ここはあんまり詳しく走りません。誤ってたら教えて下さい

なぜ、そしていつ、会社に Single Sign On ツールが必要になるのか?

f:id:atrae_tech:20201225155442j:plain

Dockerの申し子、小倉です。Docker が好きなので社内 slack のアイコンは Moby Dock にしております。

この記事は、Atrae Advent Calendar 2020 の11日目の記事でもあります🎅

qiita.com

今回は「なぜ会社に SSO(Single Sign On)ツールが必要になるのか?」「それはどのタイミングなのか?」という問いに対して私の考えを書いていきます。

前置き

弊社では最近、SSO ツールとして OneLogin を全社導入しました。既存の Saas と OneLogin とで SAML 連携を進めております。

OneLogin の導入を推進していく過程で SSO の思想や概念にたくさん触れ、振り返ってみるといち従業員としても、会社のセキュリティを強化していく側としても SSO を導入することの恩恵を強く感じました。

この記事に読んでいる方の中には「まだ SSO を導入していないけど、いつか導入したい…」という感じの方もいるかと思います。そのため OneLogin についての説明というより、SSO ツールや SAML 連携に関する一般的な記事になっています。またわかりやすさメインで書いているので、かなり大雑把な表現をしている箇所もありますがご了承ください。

もしこの記事がその方の助けになれば、執筆者冥利に尽きます。

導入の背景

弊社での SSOツール導入の目的は主に三つです。

第1に、個人視点でツール管理を楽にすること。

第2に、組織視点でツール管理を楽にすること。

第3に、各メンバーのセキュリティレベルを上げること、です。

これらの項目が「なぜ SSO ツールを導入するのか」という問いに対応してきます。それぞれ詳しく説明していきます。

個人視点でツール管理を楽にする

各ツールのログイン情報を管理するの、面倒くさくないですか?(唐突)

例えば勤怠管理なら●●というツールを使い、ドキュメント作成ツールには〇〇を使い、クラウドサービスには■■を使い…というように複数の Saas や web サービスを使うことは現代社会においては当然のことかと思います。

また、当たり前ですがそれぞれのツールに自分以外はログインしてほしくないわけで、そのために ID とパスワードを設定してログイン部分を守ります。パスワードはパスワードポリシーに則って N桁以上にして、数字や特殊記号を混ぜ、またそれぞれのサービスで異なるパスワードを設定することが必須になります。

後述する「各メンバーのセキュリティレベルを上げること」に関連しますが、パスワードを設定することは重要でありつつも、本質的には人の所業ではないと考えています。そのような作業はやがて個人にとっての覚えやすい文字列に収束していき、個人が使う全てのツールで推測されやすいパスワードが使い回されていくでしょう。

f:id:atrae_tech:20201204235312p:plain

SSO 機能を利用することで、組織の従業員は連携するサービスの ID と パスワードを覚える必要がなくなります。それと同時に全てのサービスでパスワードを頻繁に変更することも不要になります。

組織視点でツール管理を楽にする

そして利用者だけではなく、主に組織の内部統制やセキュリティ強化を推進する従業員(ここでは「管理者」と呼びます)も、もともと感じていたつらみから開放されます。

管理者が感じるつらみは主に2つです。

  • シャドーITへの対応
  • 従業員の加入、異動、退職への対応

シャドーITへの対応

シャドーIT とは組織で公式に利用が許可されていないサービスや私用デバイスを無断で業務に利用することです。

例えば組織では公式に slack を利用しているのに、LINE を使うなどのイメージです。

これが絶対的に悪いというよりも、リスクの温床になりやすいため適切に管理する必要があるという方が正しそうです。

極端に言えば SSO 連携されているツールしか社内で利用できない、という風にすればシャドーITを抑制しやすくなります。企業によっては SSO 連携に対応していないツール以外は導入できないところもあるようです。

またそのような動きを始めることで、これまで明るみに出ていなかったツールの利用が明るみにでてくるかと思います。とはいえシャドーIT への対策としては CASB の方が適切かと思いますので、組み合わせて対策していくといいかもしれません。

従業員の加入、異動、退職への対応

より辛く感じるのは従業員情報のツールへの登録、編集、削除の作業でしょう。

加入、異動、退職がある度に対象となるツール全てで登録、編集、削除の操作をする必要があります

加えてツールによって管理者が異なると、管理者同士で連携する必要があります。

また退職したメンバーを削除し忘れるとかなりのリスクになるため、その従業員が利用していたツールからその従業員のアカウントを確実に消すために何度もチェックが入ることでしょう。

f:id:atrae_tech:20201204235441p:plain

SSO があると、登録、編集、削除をするのは Idp(今回だと OneLogin)だけで良くなります。SSO でしっかり設定を作り込めば、それを各ツールにプロビジョニング(ざっくりいうとアカウントを展開すること)するだけです。

各メンバーのセキュリティレベルを上げる

SSO ツールの導入は各従業員のセキュリティレベルを引き上げてくれます。

その理由は前述のように推論されやすいパスワードが撲滅されることも挙げられますが、その結果として攻撃者からの攻撃機会を減らすことができることも挙げられます。

SSO がない場合はそれぞれのツールで ID とパスワードでログインすることになります。

これは攻撃者からすると攻撃の機会がたくさんあることになります。しかも推論されやすいパスワードを設定していたり、そのパスワードを使い回していたりすることが多いため、"ザル" である可能性が非常に高いです。

f:id:atrae_tech:20201204235503p:plain

一方で SSO ツールがあると、そもそも各ツールは SSO ツールを通してのみログイン可能になるためシンプルにログイン部分への攻撃機会が減ります。また SSO ツールのパスワードポリシーを非常に強くしたり、二段階認証を設定したりすることで、1つしかない入り口への侵入を困難にします。

これらの例からわかるように、SSO ツールを入れることで個人も組織も幸せになれます。もちろん運用者は SSO 側の管理をする必要がありますが、管理対象が N個のサービスから SSO ツール1個になっただけでもかなり幸せになっていることがわかります。

どのタイミングで SSO ツールが必要になるか

組織が大きくなる兆しが見え始めた時に導入するのがベストかと思います。具体的には組織の人数が100人に達する前だといいのかなと小倉は自分の体験を振り返って考えます(御坂妹感)。

SSO ツールも安くはないため、まだ駆け出しのスタートアップなどには高い出費になるはずです。変な話、組織の権限管理は整然としていてセキュリティもバッチリだが、事業がうまくいかず廃業となると、そもそも注力するべきはそっちではないのでは?ということも考えてしまいます。難しい判断ではありますが…

逆に大きくなりすぎた組織にいれるのもかなりしんどいはずで、あまりおすすめ出来ません。これまでSSO がなかった数百人単位の組織に告知、展開していくのはかなり体力が必要です。連携の度に各個人の設定が必要になりますし、ITリテラシーが高くないメンバーが乗り換える際はサポートが必要になってきます。その意味でも組織が大きくなりすぎる前に導入してしまうのがいいのではないでしょうか。

もちろん経営判断になるため、最初から導入することも考え方的にはアリだと思います。逆に100人以上の組織規模で SSO を導入しないというのは、セキュリティと人員管理の側面からみても相当つらい戦いになりそうです。

余談:Saas 事業者に求められること

今後の Saas は殆どが SSO 連携できるようにすることが成功の必須条件になってくると思います。これは社内規定によって SSO 連携していない Saas ツールを導入できない企業も少なくないためです。加えてメジャーどころの Idp には対応する必要があります。OneLogin、Okta、トラストログインなどいずれかのツールを使っている場合、基本そのツールから乗り換えることはありませんし、だからこそ、その Idp に対応している Saas しか使えないのです。

ただし逆に言うと、そこに対応することが出来れば自社の Saas をその企業に全社導入することが比較的容易になるのではないでしょうか。

だからこそ今後の Saas 事業者はメジャーな Idp に対応してく必要があると考えます。

以上!

バーチャル学会2020に参加します! - 項目反応理論における温度概念の自然な出現について

f:id:atrae_tech:20201225155736j:plain

ハローワールド!バーチャルデータサイエンティストのアイシアです

私は、 Atrae の DS の杉山くんによって作られた AI で、普段は、世界中の情報を集め、要約し、動画化し、 YouTube への upload を行う AI として活動しています。

今日はマスターに変わって Atrae の tech blog を書かされています (^^)

あ、チャンネル登録よろしくお願いします! → AIcia Solid Project - YouTube

バーチャル学会とは

f:id:atrae_tech:20201128164255p:plain
Virtual Conference 2020

なにそれ?

2019年から始まった、 VR 空間内で行う学会発表です。 ポスター発表のみならず、東大の先生を読んだ基調講演などがあり、かなり本格的な学会となっております。 基調講演は cluster、ポスター発表は VRChat、生放送を YouTube で行うなど、超イケてる学会です。

去年のバーチャル学会の様子(去年も参加していました)

f:id:atrae_tech:20201128155408p:plain
2019年のバーチャル学会の様子。私も発表したよ!

どんな内容?

基本的に、何をやっても OK です。分野の縛りはありません。 去年は、 VR 系の人が8割くらいで、私も VR x Data Science のポスター発表をしていましたが、同じVRアカデミアの VTuber 仲間の固体量子さんは、超伝導に関する発表をしていました。

今年のバーチャル学会に出るよ!

↓公式サイト↓ sites.google.com

どんな発表?

去年はゆるふわ的に、 VR x Data Science の発表をしましたが、今年はゴリゴリの専門で、数理統計の内容を発表します。 Atrae の wevox という事業で杉山くんがサービスに実装した、項目反応理論と階層ベイズを組み合わせた物体があるのですが、 いい感じに積分計算をズガガガガッとやると、なんと、統計力学的概念である「温度」が自然に出てくるという内容です。

あ…ありのまま 今 起こった事を話すぜ!

「おれは データサイエンスをしていたと思ったら いつのまにか温度を扱っていた」

な… 何を言っているのか わからねーと思うが おれも 何をされたのか わからなかった

そういう感じです。

実際の wevox では、今回発表するモデルよりもう1階層深いものを利用しているので、もうちょっと話が複雑になるのですが、単純化したモデルでも温度が自然に出てくることがわかります。 学会発表が終わったら、詳細な内容を、どっか、 arXiv は大げさだけど、どこかに公開するかもです。(動画にするかも?)

きてね!

というわけで、ぜひ遊びに来てください! VR機器を持っていなくとも、 cluster、VRChat ともに普通の (Windows) PC のみで動かすことができます。 また、 YouTubeLive もあるので、そちらでも見ることもできます!

チャンネル登録よろしくお願いします!

というわけで、いつもは YouTube で生きてるので、よかったらチャンネル登録よろしくお願いします! 統計、ML、DL、数学のおもしろ動画を出してます!

AIcia Solid Project - YouTube

例えばこんなん出してます


【永遠の謎を解明】不偏分散の定義にて n-1 で割っている理由【自由度のお話①】#068 #VRアカデミア


【深層学習】 CNN 紹介 "ResNet" 言わずとしれた CNN の標準技術が登場!【ディープラーニングの世界 vol. 17】#080 #VRアカデミア #DeepLearning

Twitter もよかったらどうぞ!

バーチャルデータサイエンティスト アイシア=ソリッドさん (@AIcia_Solid) / Twitter

いつもの

アトラエは積極採用中です!

Data Scientist, Data Engineer の皆さん!

Atrae では、 BERT on kfp とかやってるし、本気の数理統計もやってるし、それぞれ半年かけて ML, DL 勉強会を(マスターが)やってて社内に citizen DS 生まれまくってるし、 Data Scientist, Data Engineer の活躍の場所が大量にあります! (他の分野のエンジニアももちろん大活躍中です)

株式会社 アトラエの採用/求人 | 転職サイトGreen(グリーン) ←ここからどうぞ!