技術者として常に成長し続けたい
一技術者として、サービスで使われているありとあらゆる技術を学び続けていきたい。 計算機科学や数学の基礎知識、トレンドの技術、共に学習し続け、結果としてチームや会社に貢献できるようになりたい。
読む力: 公式ドキュメント、ソースコード、仕様を読み込んで得た情報から、検証を行い解答を導き出す力
(注) 本ドキュメントを採用目的で閲覧する場合、ミスマッチを防ぐために必ず目を通して頂けますようお願いします
以下の経験・スキルは現状持っていないため、キャッチアップに一定の時間を要します。
今までの経験が『少人数のチームで各自がアサインされたタスクをこなしていく』というスタイルに偏っていたため、その過程で技術選定を行った経験はあるものの、明確にテックリードとしての役割を遂行した経験はありません。 『新しい技術やサービスの導入可能性を探るためにPoCを実施、結果をチームで共有、議論の上で導入する』という経験は何回かありましたが、これもテックリードとしてふるまったというには弱いと考えています。
競技プログラミングはやっていたものの、AtCoderのランクは緑色にとどまっており、業務に生かせるレベルには達していません。
- 複数の事業部のアプリ、使った事がないAWSサービスなどを短期間でキャッチアップしてくれる
- CI/CDの整備など、Developer Experience(開発体験)の改善に関して動いてくれた
- ステークホルダーとの要件調整を行える
- ビジネス側との間で認識がずれないよう、語義を確認したり、システム関連の用語を噛み砕いて説明するなどの工夫をしていた
- ビジネス側の意思決定をサポートするように積極的に情報を提示していた
- 運用、保守、セキュリティなど、開発時に漏れがちな観点を意識している
- 責任やプロフェッショナリズムを大切にしている
- 任された仕事は、個人の好悪をはさまずに期待された成果をきちんと上げる
- 領域問わないチャレンジ精神を持っており、知らなければキャッチアップする
- 話が冗長になり、結論が簡潔に分からないことが往々にある
『詳細』をクリックすることで、各プロジェクトの詳細情報を閲覧できます
インフラを中心に、人手が足りない際にバックエンドサーバ(Golang)、BFF(Rails)の機能追加・改修等も行った。
Kubernetesクラスタ(GKE)上でのサービス構築と運用の整備を行った。
- 複数環境のマニフェストの整備
- CI/CDパイプラインによるデプロイの半自動化
- サービスから利用するGCPリソースのコード化
- 監視設計
- 構造化ログの導入
- アプリケーションのゴールデンシグナルの可視化
- アプリケーションへのトレースの導入
- 負荷試験と合わせたリソースサイジング
- エンジニア: 1人
CTOと相談しながら、技術選定、設計、実装、運用までをほぼ一人で実施した。
- Kustomize
- Terraform
- GCP
- GKE
- Cloud SQL(MySQL)
- Cloud Storage
- Cloud Logging
- Cloud Monitoring
- Cloud Trace
- Cloud Build
- OpenTelemetry
- Locust
作業者が自身のみという状況において、可能な限りGCPのマネージドサービスに寄せる判断を取った。 他方、コストを抑えつつトレースを導入するためにOpenTelemetryを採用する等、必要であるならば新しい技術も積極的に取り入れた。
- ほぼゼロからインフラの構築 及び 運用プロセスの確立 を行い、サービスの一般公開に貢献した。
- 負荷試験と合わせたリソースサイジングにより、要求されるパフォーマンスを維持しつつ、コストを削減した。
- アクセス急増によるサービスダウンがあり、応急対応としてリソース増強を行った。増強時のコストと比較すると、1/10までコストを削減できた。
それぞれの事業部で個別に管理していた顧客データを登録するデータパイプラインを作成した。 またデータパイプラインを通して集約されたデータを元に顧客のクロスユース分析に必要な情報を提供するAPIサーバを構築した。
- PM: 1〜2人
- エンジニア: 3〜4人
プロジェクトをリードする立場で、技術選定 及び 1つの事業部について実用レベルに至るまでの実装を一人で担当した。 その後は、チームメンバーへの説明を行い、他の事業部についての実装をチームメンバーと共に実施した。
- Golang
- AWS
- ECS
- Lambda
- SNS
- SQS
- RDS
- CDK
詳細
各事業部毎に顧客データを様々な場所に(ex. RDS、スプレッドシート)、様々なフォーマットで管理していた。 クロスユース分析を行う際には、これらのデータを手動でスプレッドシートにコピーした上で、ユーザ毎のデータを集計していた。
各事業部のデータソースを登録するためのデータパイプラインを実装した。 データパイプラインは、『ブリッジ』『イベントローダ』『APIサーバ』の3つのコンポーネントから成り立つ。
【ブリッジ】
ブリッジは、各サービスで登録された顧客データを、イベントローダが解釈可能なメッセージに変換した上で、イベントローダのインターフェースとなるSNSに送信する。
ブリッジは、データソース毎に異なる実装を持たせた。これはデータソース毎の違いを吸収するためである。 例えば、データソースがWebサービス化されている場合は、SQSとLambdaを用いてリアルタイムにデータ登録を行う。一方、データソースがスプレッドシートの場合は、LambdaとEventBridgeを用いて日時でデータ登録を行う。
【イベントローダ】
イベントローダは、ブリッジから受信したメッセージを元に登録APIを実行する。
イベントローダはブリッジからのメッセージを受信するSNS、SNSからメッセージを受け取りデータを処理するSQSとLambdaにより構成される。 SNSのメッセージフィルターを使って事業部毎に異なるLambdaが呼び出す事により、データソース毎に異なる処理を実行できるようにした。
【APIサーバ】
APIサーバは、イベントローダから呼び出される登録API、及び登録したデータを参照する参照APIを持つ。
クロスユース分析を実現するためには名寄せが必要だったため、Eメールを用いて名寄せした。 登録時に複数の事業部で同じEメールを用いた顧客が存在した場合、APIサーバ上では単一のユーザとみなされる。
また、Eメールをキーとして検索APIを実行することで、顧客が利用している事業部(=サービス)を取得できるようにレスポンスを設計した。 取得したデータには登録日時が含まれており、クロスユース分析をする際に必要な情報を提供する。
『Golang』で実装したAPIサーバを『ECS』でデプロイするという組み合わせは、既に社内で実績があったため、同じ構成であれば大きな問題にはならないだろうと判断して採用した。
一方、各種AWSリソースの作成には社内で実績がまだない『AWS CDK』を採用することとした。 私自身がまだAWSに不慣れであり、Terraform/CloudFormation など抽象度の低いIaCツールでは構築が難しいのではないかと考えた。 一方、CDKであれば抽象度の高いL2、L3コンストラクタを使う事で素早く構築できる、ドキュメントやCDK自体のコードを読む事でAWSに関する知識も得る事が期待できた。
顧客データが一箇所に集約されてAPIで取得できるようになったことにより、クロスユース分析の手順が省力化された。
リアルタイムにデータ登録を行うブリッジには、データの検証及び補正を行うバッチを日時で実行するようにした。 これにより、ブリッジからイベントローダへのメッセージ送信が何らかの理由で失敗しても、手動での修正が不要になった。
Well-Architectedに従ったマルチアカウントの管理、複数のセキュリティサービスが生成する検出情報の一元管理 など、 セキュアに複数のAWSアカウントを扱うための環境整備を行った。
- PM: 1〜2人
- エンジニア: 2〜3人
プロジェクトをリードする立場で、技術選定、技術調査、実施まで一貫して行った。 その後は、ドキュメントの作成を行い、チームメンバーに作業を引き継げる状態とした。
- AWS
- Control Tower
- Organizations
- Security Hub
- GuardDuty
詳細
セキュリティ観点から、1つのAWSアカウントに同居している本番環境と開発環境をアカウントレベルで分離したいという要求があった。
Well-Architectedに従ったマルチアカウント環境を作成するマネージドサービスであるControl Towerを導入した。 Control Tower導入後、本番環境を含むAWSアカウント、用意はされていたが使われていない開発用のAWSアカウントをそれぞれControl Tower配下に登録した。
マルチアカウント管理は今までに全くやっていなかったため、マネージドサービスである『Control Tower』を使用する決断は自然に行われた。 ただし、Control Towerから新規アカウントを作成するのではなく、既存アカウントをControl Towerに登録するため、 既存アカウントに与える影響に関しては、事前にAWSのソリューションアーキテクトに相談するなど慎重に調査した。
本番アカウント/開発アカウントをControl Towerに登録、開発者が利用できる環境を整備した。
その後、Security Hub/GuardDutyをOrganizationsと統合する事で、Control Tower配下の全メンバーアカウント/全リージョンの検出結果を、AuditアカウントのSecurity Hubの集約リージョンに集約した。 これにより、本番アカウント/開発アカウントで起こっている全ての問題を、一箇所で確認、通知できるようになった。
また、リージョン拒否コントロールを有効にする事で、本番アカウント/開発アカウントで利用できるリージョンを制限した。 これにより、Auditアカウントに集約した検出結果の総数が減り、状況を確認しやすくなった。
一通りメンバーアカウントのセキュリティ設定を行った後に、本番アカウントにある開発環境のリソースを開発アカウントに移行する計画を作成した。(計画を実施する前に、離職が決定したため実施には立ちあっていない。)
既存アカウントをControl Towerに登録する必要があったため、事前に作成したテストアカウントで、既存アカウントの登録手順を検証しドキュメント化した。 特にAWS Config回りでエラーが発生する事が多く、事前にそれらの問題の大部分を洗い出せたため良い判断だったと考える。
また、リージョン拒否コントロール等の比較的新しいサービスを、慎重に検証した上で導入する事ができた。 ただ新しいからという理由でなく、公式ドキュメントを中心に調査を行い、組織に取って有用だと判断した上で適用することができた。
Control Tower配下のメンバーアカウントに関してはセキュアに管理する態勢が整ったが、Control Tower管理アカウントに関してはもう少し検討の余地がある。 Control Tower管理アカウントは、リージョン拒否コントロールが効かないため、全リージョンでセキュリティサービスを有効にする必要があるなど。
また、OU毎に適用するコントロールの精査も今後の課題である。現状は必須コントロールしか適用していないため、統制が不十分である。
QAテストを実行するCI環境のコード化を行った。
- PM: 1人
- エンジニア: 2〜3人
プロジェクトをリードする立場で、技術選定 及び 実用レベルに至るまでの実装を担当した。 その後は、ドキュメント作成などを行い、チームでの運用態勢を確立した。
- Ansible
- Terraform
- Docker
- Packer
詳細
QAテストを実行するCI環境として、Jenkinsを使っていた。Jenkinsはmaster/slave構成を取り、masterノードは1台だが、slaveノードは複数台ある。 slaveノードを増やす事で一度に実行できるジョブを増やすことができるが、手動で環境を構築していたため作業コストが高かった。 テストの実行時間を短縮するためには、slaveノードを手軽に増やすことができる状態が望ましかった。
masterノード用とslaveノード用のコンテナイメージを作成することとした。 これにより、slaveノードを増やす場合はslaveノード用のイメージを使ってコンテナを追加するだけで良くなった。
コンテナの起動にDocker composeを使用していたため、数行追加するだけでslaveノードを増やせるようになった。
コンテナイメージの作成は『Ansible』『Packer』を使用した。 コンテナ環境だけでなく実マシンへのプロビジョニングもできるようにして欲しいとの要求を受けたため、Dockerfileによるプロビジョニングをメインの手段として採用しなかった。 また、Puppet/ChefなどAnsible以外の選択肢も検討したが、どちらもAnsibleよりもチームメンバの学習コストが高いと判断して採用しなかった。(Puppetは独自のDSLが、ChefはRuby自体がチームメンバーの学習障壁になると考えた)
コンテナオーケストレーションの選択肢が、当時は『Docker compose』ぐらいしか知りうる限りではなかったため、この判断は特に迷う事はなかった。
slaveノードを簡単に増やせるようになり、テストの実行時間を短縮しやすくなった。 また、各ノードの設定がコード化されたことにより、master/slave環境に変更を加える前にPRでレビューができるようになった。
Dockerfileではなく敢えてAnsibleによりコンテナをプロビジョニングすることで、コンテナのプロビジョニング と 実マシンへのプロビジョニングの両立を達成した。 コンテナイメージのレイヤが増えてしまうことは分かっていたが、要求を解決するために最適な手段を取る事ができたと考える。
当時は、コンテナの**(ex. なるべく小さなサイズで、1コンテナ-1サービス、など)を理解しておらず、仮想マシンの延長で考えてしまった。 そのため、 テストに必要なランタイムを全て1つのイメージに詰め込んでしまいサイズが肥大化しビルド時間が長くなった。 各テストで必要なランタイムは異なっていたため、ランタイム毎に別イメージを作成するなどすれば、この問題は解決できると思われる。
また、全てのコンテナを1台のマシン上で起動するため、slaveの数をある程度増やすためにはかなり性能の良いマシンが求められた。 ECS、EKS(Kubernetes)上で実行できるようにすれば、この問題は解決できると思われる。
社外からメールで送信されてくる課題管理簿と社内のissueトラッカーを連携するシステムを開発した。
- PM: 1人
- エンジニア: 2〜3人
要求ヒアリング、仕様策定、実装、テストまで全て一人で対応した。 その後は、チームメンバーからのレビューを受けての修正、追加要件への対応を行った。
- Python
詳細
Excelファイルで作成された課題管理簿を社外とメールでやり取りしていた。 一方、社内では課題管理にissueトラッカーを採用しており、以下の手順で内容を転記していた。
- 社外から課題管理簿を添付したメールが担当者に届く。
- 担当者は課題管理簿(パスワード付きzipで圧縮されている)を解凍し、内容を確認する。
- 内容を確認した後に、課題管理簿を更新し、社外へのメールに添付する。
- 社内のissueトラッカーに課題管理簿の内容を転記する。
上記の手順は相応の工数がかかっていたため、社内の担当者の工数を削減したいという要望があった。
課題で挙げた手順のうち、1、2、4は社内で閉じた手順であり自動化が可能だろうと考えた。 これらの手順を自動化するために、以下の処理を実行するプログラムを実装した。
- 課題管理簿の受信を検知する。
- 課題管理簿の内容を解析し、issueトラッカーに登録する。既にissueが作成してある課題管理簿に対して返信があった場合、該当するissueに対してコメントで追記する。
- 課題管理簿をやり取りするメールの内容により、該当するissueをクローズする。
実装したプログラムは、社内サーバのCronに登録して定期的に実行することとした。
『実行環境(Linux)、開発環境(OSX)ともにデフォルトでインストールされている』、『内容を考えると高い処理性能は不要である』、『インタプリタ言語故にトライアンドエラーがしやすい』という点により、『Python』を実装言語に採用した。
- 前述の手順1、2、4が自動化され、担当者の手間が大きく削減された。
- 担当者の裁量で転記していた内容が全てissueトラッカー上に集約されることになり、課題内容を把握・整理する必要があったQAチームのリーダに喜ばれた。
- Shift-JIS(課題管理簿)、euc-jp(動作環境のサーバ)、ISO-2022-JP(メール本文)、UTF-8(その他)、といった複数の文字符号化方式を扱う経験を得た。
- 当時のPython(2.x)はマルチバイト文字列の処理が今と比べてやや煩雑であり、その点は苦労した。後に文字列処理に関してブログにまとめた。
- 手順3を自動化する
- issueに対して返信すると、その内容を含んだ課題管理簿を生成、メールで送信する といった実装が考えられる
- issueのClose判定の偽陽性率/偽陰性率を下げる
- Close判定は正規表現によるテキストマッチングでの実装だったため、偽陽性率/偽陰性率がそれなりに高かった。Close判定に関する学習を実装する、といった解決策を検討する。
- 責任分割を行い、コードの可読性/メンテナンス性を向上させる
- 開発に慣れていなかったため、メイン関数にかなりの責任が含まれてしまった
社内ドキュメントをアクセス制限をかけて公開した。また、ドキュメント変更を自動で反映するデプロイパイプラインを整備した。
- PM: 1人
- エンジニア: 2〜3人
個人プロジェクトから始め、技術選定 及び 実用レベルに至るまでの実装を担当した。 その後は、ドキュメント作成などを行い、チームでの運用態勢を確立した。
- Terraform
- Kubernetes
- GCP
- Cloud Build
- Container Registry
- Cloud Armor
- Identity-Aware Proxy
詳細
社内サーバで社内限定のドキュメントを公開していたが、オフィス縮小に伴い社内サーバを撤去することになった。 前述のとおり社内限定公開だったため、パブリックネットワークで公開する場合はアクセス制限が必須であった。
https://cloud.google.com/kubernetes-engine/docs/tutorials/gitops-cloud-build を参考に、ドキュメント変更を自動でデプロイするパイプラインを整備した。
- Githubに『ドキュメントリポジトリ』と『デプロイリポジトリ』を用意する。
- ドキュメントリポジトリの変更をトリガとして Cloud Buildのビルドを実行する。
- Githubのコミットハッシュをタグに含めた上で、ドキュメントのコンテナイメージを作成する。作成したコンテナイメージはContainer RegistryにPushする。
- デプロイリポジトリをCloneする。Kubernetesマニフェストを上記タグを参照するよう変更した上で、Kubernetesマニフェストリポジトリにコミットする。
- デプロイリポジトリの変更をトリガとして、Cloud Buildのビルドを実行する。
- Terraformをapplyして、GCPのリソースを更新する。Cloud Armor(IPアドレス) と Identity-Aware Proxy(Google Workspaceドメイン)により、アクセス制限を達成する。
- Kubernetesマニフェストをapplyして、ドキュメントをKubernetes上に公開する。
ドキュメントを公開するプラットフォームとして『Kubernetes』を採用した。 ドキュメントの公開だけ見るとKubernetesであるべき技術要求はないが、テストの実行時間の短縮のための並列実行を行う事を検討しており、実行するプラットフォームとしてKubernetesを候補として考えていた。 そのため、Kubernetesに慣れるためのPoCとしての意味が強かった。
Kubernetesクラスタを独自に構築・運用する事はコスト的に許容しづらく、マネージメントサービスの採用はほぼ必須であった。 チームは以前GCPの経験があったため、『GKE』を採用することとした。連携の容易さを考慮して、他に必要なサービス(Cloud Build、Container Registry、Cloud Armor、 Identity-Aware Proxy)もGCPのものを採用した。
GCPのリソース作成には『Terraform』を使用した。こちらもチームの以前の経験を考慮して採用した。 KubernetesリソースとしてGCPリソースを管理するConfig Connectorも検討したが、 学習コストが高い、比較的新しいツール故に参考になる事例が少ない、といったことを考慮して採用しなかった。
要求どおり、パブリックネットワーク上に適切なアクセス制限をかけて社内限定ドキュメントを公開できた。 また、ドキュメントの更新を自動で反映する仕組みを整備して、小さなToil(手動でのマニフェスト更新->デプロイ)を削減する事ができた。
現状は Terraform/Kubernetesの設定に固有情報がベタ書きされている。 これを外部に切り出す事で、今回のユースケース以外にも汎用に使える仕組みにできるのではないかと考えている。
APIサーバのQAテストを実装するプログラミング言語を、JavaからGroovyに移行した。
- PM: 1人
- エンジニア: 2〜3人
移行するプログラミング言語の選定を行い、移行計画を作成した。 その後は、チーム全員で新しい言語への移行を実施した。
- Java
- Groovy
詳細
元々APIサーバのQAテストはJavaで実装していたが、 当時のJava(1.5、1.6)は現在のバージョンと比べてボイラープレートが多く、テストコードが冗長になりやすい傾向にあった。冗長なテストコードでは、何をテストしているのかがテストコード上から追いにくくなるため、同じ処理を簡潔に記述できる言語に移行したいと考えた。
また異常系を考えるとテストは様々な入力を扱う事になるため、(Javaが持つような)堅牢性よりも柔軟性を優先したい場面が多かった。
『Groovy』を移行先の言語として採用した。 『Javaとの相互呼び出しが簡単に行える』『ファイルの拡張子を変更するだけで、大部分のコードが移行できる』など、他のJVM言語と比較してもJavaとの親和性が高く、移行コストを抑えつつもスクリプト言語のような柔軟性をテスト実装に導入できると考えた。
前述の『ファイルの拡張子を変更するだけで、大部分のコードが移行できる』特性を生かして、既存のコードを書き直す前に拡張子のみ変更して、Groovyで動作する事を確認した。その後、特に冗長になっている部分を優先して変更し、変更する度にテストが再実行できるかを検証した。 これにより、段階的にJavaからGroovyに移行する事ができ、日々のQAに大きな影響を及ぼさずに移行を終えることができた。
大規模データの分散処理フレームワークである『Hadoop』の研究調査 及び 報告書作成を行うプロジェクトに参加した。
- PM: 2〜3人
- エンジニア: 5〜6人
Hadoop管理ノードの冗長化に関する調査を担当した。
- Java
- Hadoop
- DRBD: データを冗長化するミドルウェア
- Heartbeat(現Pacemaker): サーバプロセスを冗長化するミドルウェア
- オープンソースへのコントリビュート
- Neovimプラグイン
- Ansible
- 競技プログラミング
- 執筆
(*)一部トップページと重複した記述あり