nazolabo

フリーランスのWebエンジニアが近況や思ったことを発信しています。

Unity で gRPC を試す( HelloworldUnity )

概要

Unity で gRPC を試すには、以前はいろいろ準備する必要があったようですが、現在は https://github.com/grpc/grpc/tree/master/examples/csharp/HelloworldUnity にサンプルが丸ごと入っていますので、これを動かすところまで試します。

手順

上記を UnityEditor で開きます。

README.md に書いてある通り、別途 grpc_csharp_unity.zip が必要です。指定場所からダウンロードして展開して出てきた Plugins ディレクトリをプロジェクトに突っ込みます。

エラーが出る

Error: Could not load signature of Google.Protobuf.ByteString:get_Span due to: Could not load file or assembly 'System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. assembly:System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 type:<unknown type> member:(null) signature:<none>

こんな感じのエラーが出るのですが、grpc_unity_package.2.26.0-dev までは動作するが、それ以上のバージョンではエラーになるようです。いずれ解決する問題かどうかはよくわかりません。ちなみに grpc_unity_package.2.26.0-dev はここからダウンロードできます

動かす

f:id:nazone:20200505183848p:plain

動かすとこんな画面になります。

ちなみに Unity 側単体でサーバーとクライアントが両方起動しているので、通信はしているのですがよくわからないと思います。

ボタンを押すと表示が変わります。

f:id:nazone:20200505183906p:plain

サーバーを別で動かす

HelloWorldTest.cs に、Server server を new している一帯がありますので、そこを削除なりコメントアウトなりします。

同等のサーバーは https://github.com/grpc/grpc/tree/master/examples/csharp/Helloworld/GreeterServer にありますので、代わりにこちらをビルドして起動してから Unity 側を起動すると、いい感じで通信するようになります。

Webエンジニアとしてフリーランスしています

これまでのあらすじ(&お前誰よ)

UUUM株式会社を2019年10月に退職し、のんびりとした生活をしていましたが、本格的に働くことにしました。

能力や経歴などについてはポートフォリオを作りましたので、そちらをご覧頂ければと思います。

なぜフリーランス

働き方を自分で制御したいというのと、会社員という立場から一度離れていろいろな現場を見てみたい、そして私の力でそれを改善できるのか挑戦してみたい、という点から、しばらくフリーランスをすることを選びました。

特に最近は一人で全て解決することを求められることが多く、他の会社の視点ではどのようになっているのか、どのような他の良い方法があるのかというのをもっと知りたくなり、様々な現場を見てみたいという気持ちが強いです。

前にも少しやっていたのですが、当時の居住地や知名度では正直難しい(私の営業力不足も大きいですが…)状況で断念していました。

全く就職しないの?

そのうちすると思います。フリーランスという形態は自分には向いていないと思っておりますので、よほど軌道に乗って収入に困らない状態が続くとかでなければ就職するのではないかと思います。

その場合にしても、フリーランス中にお試しで仕事をしてマッチしたら入社という形態を取らせていただきたいと考えておりますので、興味がある会社様は先に声をかけていただいておくと良いと思います。

仕事募集してるの?

ありがたいことに今(2020年3月現在)は埋まっているので受けられないのですが、フリーランスなので状況はすぐ変わると思いますので、お仕事の相談をしたい方は先にご連絡頂ければと思います。本記事公開以降も状況が変わっているかもしれませんので、詳しくはお問い合わせ頂ければと思います。

原則としてリモートが可能な現場のみ受け付けております。たまには出社してほしいとかという場合でもお受けできますが、そのあたりは直接ご相談頂ければと思います。また最大でも週4まで、通常週2程度の稼働で受けております。

Terraform AWS modulesでざっくりAWSインフラを作る

https://github.com/terraform-aws-modules には、TerraformですぐにAWSリソースを立ち上げるためのModuleがいくつか存在します。

VPCの作成

terraform-aws-vpcでは、主に以下のリソースを作ってくれます。オプションでNATとかも用意してくれます。

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"

  name = "test"
  cidr = "10.0.0.0/16"

  azs             = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = false
  enable_vpn_gateway = false
}

ALBの作成

terraform-aws-albでは、主に以下のリソースを作ってくれます。

Security Group は作ってくれないので、自前で用意しましょう。

resource "aws_security_group" "alb" {
  name        = "alb"
  description = "alb"
  vpc_id      = module.vpc.vpc_id
}

module "alb" {
  source  = "terraform-aws-modules/alb/aws"
  version = "~> 5.0"

  name = "test"

  load_balancer_type = "application"

  vpc_id          = module.vpc.vpc_id
  subnets         = module.vpc.public_subnets
  security_groups = [aws_security_group.alb.id]

  target_groups = [
    {
      name             = "test"
      backend_protocol = "HTTP"
      backend_port     = 80
      target_type      = "ip"
      deregistration_delay = 10
    }
  ]

  http_tcp_listeners = [
    {
      port               = 80
      protocol           = "HTTP"
      target_group_index = 0
    }
  ]
}

ACM

terraform-aws-acmでは、ACM証明書を一発で作ってくれます。これは定型フォーマットなので、そのまま利用して問題ないでしょう。(手元にRoute53管理のドメインがなかったので試してはいません)

module "acm" {
  source  = "terraform-aws-modules/acm/aws"
  version = "~> v2.0"

  domain_name  = "my-domain.com"
  zone_id      = "Z2ES7B9AZ6SHAE"

  subject_alternative_names = [
    "*.my-domain.com",
    "app.sub.my-domain.com",
  ]

  tags = {
    Name = "my-domain.com"
  }
}

SNSのSlack通知

terraform-aws-notify-slackを使うと、SNSトピックをSlackに通知させるやつも簡単にTerraformで管理することが可能です。おそらくこれが一番使うのではないでしょうか。

使い方も簡単で、よくあるCloudWatch AlarmをSlackに通知するのは以下の書き方で実装できます。(手元に通知するものがなかったので試していません)

  
provider "aws" {
  region = "eu-west-1"
}

resource "aws_kms_key" "this" {
  description = "KMS key for notify-slack test"
}

# Encrypt the URL, storing encryption here will show it in logs and in tfstate
# https://www.terraform.io/docs/state/sensitive-data.html
resource "aws_kms_ciphertext" "slack_url" {
  plaintext = "https://hooks.slack.com/services/AAA/BBB/CCC"
  key_id    = aws_kms_key.this.arn
}

module "notify_slack" {
  source = "../../"

  sns_topic_name = "slack-topic"

  slack_webhook_url = aws_kms_ciphertext.slack_url.ciphertext_blob
  slack_channel     = "aws-notification"
  slack_username    = "reporter"

  kms_key_arn = aws_kms_key.this.arn

  lambda_description = "Lambda function which sends notifications to Slack"
  log_events         = true

  tags = {
    Name = "cloudwatch-alerts-to-slack"
  }
}

resource "aws_cloudwatch_metric_alarm" "LambdaDuration" {
  alarm_name          = "NotifySlackDuration"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = "1"
  metric_name         = "Duration"
  namespace           = "AWS/Lambda"
  period              = "60"
  statistic           = "Average"
  threshold           = "5000"
  alarm_description   = "Duration of notifying slack exceeds threshold"

  alarm_actions = [module.notify_slack.this_slack_topic_arn]

  dimensions = {
    FunctionName = module.notify_slack.notify_slack_lambda_function_name
  }
}

https://github.com/terraform-aws-modules/terraform-aws-notify-slack/blob/master/examples/cloudwatch-alerts-to-slack/main.tf

まとめ

公式とはいえ外部にあるmoduleだと、例えば最新の機能を入れたい場合にmoduleの反映を待たないといけないですし、そういう理由以外でもカスタマイズすることが難しく、また、moduleが勝手にアップデートされることが嬉しくないことも多いため、実際に使うのであればローカルにmoduleまるごどcloneして利用するのがいいのではないでしょうか。

SNSのSlack通知やACMに関してはほぼそのまま使っても問題ないと思います。

今はVPC一通りとALBがあればECS on Fargateでクラスタを作ればサービスを上げられるので(DBとかは別にして)、Terraformで管理したいけど書き方が難しいという場合は使ってみるのもありなのではないでしょうか(そんなに難しくないですが…)。

SSH先のdockerをローカルからシームレスに使用する(SSHでDOCKER_HOSTを指定する)

何がしたいの?

例えば「MacBook Air で開発しているけどスペックが低いので Docker で動かすものはデスクトップPCで動かしたい」というようなケースに使います。

docker をリモートで動かす

まずリモートの Docker を用意します。私は Windows なので Hyper-V で作りました。Docker のバージョンはリモートもローカルも最新が良いです。最低でも 18.09 以上が必要かと思われます。

対象の環境に SSH で入れるようにしておいて、SSH で入るユーザーが sudo なしで docker コマンドを叩ける必要があります。 sudo usermod -aG docker myuser のようにして SSH 対象ユーザーを docker グループに所属させましょう。

docker コマンド内で SSH 鍵のプロンプトは出せないので、事前に ssh-add しておきましょう。

ここまでで、設定が問題なければ以下の方法で起動すると思います。

docker -H ssh://user@remote-host run -d -P nginx

-H の部分は、環境変数 DOCKER_HOST で指定が可能です。

docker-compose 対応

Docker for Mac 標準の docker-compose ではうまく動かなかったので(多分 このあたりの都合 )、docker-compose は pip で入れました。pip で入れただけでも動かない場合は pip install cryptography==2.4.2 が必要かもしれません。

また、 docker-compose は .ssh/config を読んでくれないっぽいので(1.25.0 時点)、DOCKER_HOST はそれを考慮して書いてください。

ボリュームマウントは SSH 先のホストに対して行われます。マウント先は SSH 先のホストのディレクトリ構成に合わせて記述してください。ローカルと同期したい場合は別途自前で同期する必要があると思います。

※ 2020-06-04 追記 : docker-py 4.2.0 で .ssh/config を読むようになったようなので、それが取り込まれている docker-compose 1.26.0 では読み込むことができるのではないかと思います。(未検証)

ユースケース

ローカルとボリュームマウントが基本的にできないので、アプリケーションコードを Docker コンテナ内で実行するようなケースには向いていません。特殊な構成のアプリケーションで実行に Docker がどうしても必要という場合は、この方法は避けたほうが良いです。

ローカルで編集しないもの、DB やキャッシュサーバーのようなものだけ Docker で起動し、アプリケーションはローカルで起動する、といったケースにはすぐに使用できると思います。この場合も設定ファイルを送り込むことができないので、設定ファイルが必要なもの(Elasticsearch など)は設定ファイルを入れるための Dockerfile を書いて、それ経由で起動するのが良いかと思われます。

現代の一般的な構成の Web アプリケーションでは、Docker でアプリケーションそのものを実行するメリットはあまりないので、この構成は十分実用的かと思われます。

そもそもSSH先で開発すればいいのでは?VSCodeのRemote-SSHもあるし…

あっはい…

一応ローカルに開発中のファイルを置いておけるので、外出先で開発したくなった場合にそれをそのまま使えるというメリットはありますが、まあ適当に作業中ブランチをpush/pullすればいいだけですね…

2019年トップツイート振り返り

Twitter Analyticsから各月のトップツイートについて振り返ってみます。

1月

ありません

2月

今でもこういう感想だし、下手に並列化するより直列でそのまま流したほうが(個別のジョブの時間が長すぎる場合以外は)速いという認識なのですが、皆様どうしてるのでしょうか。

3月

EntityやらValueObjectとかってのはDDDの表現手法の一つであって、本質としてDDDが目指してるものってそこじゃないでしょ?みたいな話でした。

4月

自分もそれなりにTerraform書いている量では多い自信があるのですが、こうやって具体例がまとめられている書籍は今までなかったのでとても良い内容でした。

現在はさらに内容を充実させた 実践Terraform AWSにおけるシステム設計とベストプラクティス が出ているようなので、そちらを読むのが良いのではないかと思われます。(私はまだ買ってないです…)

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

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

5月

通信レイヤーを使ってサービスを分離するのは規模が大きくないと難しいですが、モノリシックなプロダクトでも内部構造は分離できる構造になっていると変更に強いしテストも書きやすいしという話です。マイクロサービスが目指したいものが何なのかを考えて導入しましょう。

6月

リモートワーク論についてはいろいろあるのですが、自然にリモートワークをするにはオフィスを提供しても提供しなくても何も変わらないというような環境がベストではないかと思います。そのためにはオンラインにリソースを集中させる必要がありますし、顔を合わせないとできないことを最小限にする必要もあります。

7月

Terraform人気ですね。ACMDNS検証周りは内部でオーダーが勝手に変わるらしく突然差分が発生するというやつです。最近は諦めてここだけ手動でやっています。管理するメリットないし…。

8月

2019後半は本当に何もしていないので、2019年のアウトプットのほとんどはここに凝縮されています。12月の登壇内容と併せてご覧いただければと思います。

9月

リモートワーク大好きマンです。身も蓋もない話なのですが、できる人はできるしできない人はできないみたいな結論に行き着きます。そして多くの人はどちらかといえば「できない」ほうです。主語が大きいですが根拠はあるのでどこかで書けたらと思います。

10月

大きめの企業で「誰々さんを新たな役員に任命!」みたいなのって、大きく会社の方向性を変えたいという意思でもあると思うので、当然決断するのは大変だし、失敗することも多いと思うし、それでも決断するのはすごいなーという話です。私には無縁の内容ですが…。

なお、このツイートの次はこんな内容です。

11月

元ネタがあります

12月

これについては年が明けたら詳しく書きます。それではよいお年を。

OKRでありがちな間違い2点

ドキュメント(OKRはGoogleのものではありませんが…)ちゃんと読もうシリーズ第二弾です。(第三弾は多分ないです)

Google re:Workに書いてある内容のうち、間違った運用をされてそうな2点をピックアップしてみました。

一部に独自の解釈が含まれていますので、詳細は上記リンクなどを参照してください。またre:Workに書いてある内容ベースなので、OKRの正しい解釈としてはもう少し違う可能性があります。

1. 「OKR は、従業員を評価するためのツールではありません。」

評価するためのツールではないということは、OKRで評価しちゃ駄目なの?

普通に解釈したらそうなるのではないでしょうか。

なんで駄目なの?

OKRは、達成率が60%~70%が理想的とされています。簡単には達成できないような目標を設定して大きな成果を上げるのが目的だからです。しかしそれを個人の評価にしてしまうと、達成できなかった場合にマイナスにしてしまう可能性があります。達成できるかできないか微妙な目標で達成できなくてマイナスというのは理不尽なのではないでしょうか。

また、OKRでは、目標を達成できなくてもその過程で個人は大きな進化をするだろうとしています。「大きな目標に対して努力をする」ということが既に成果になっていて、それは評価されるべき内容となっているので、OKRの達成と個人の評価は関係がないということがわかります。

2. 「OKR は、社内共有のタスク管理ツールではありません。」

タスク管理ツールじゃないの?

そもそもOもKRもタスクではないのでタスク管理ツールではありません。

OにもKRにもタスクを入れないなら、OとKRの違いって何なの?

Oには数値ではない(定性的な)大きな目標を入れ、KRにはOを達成するための具体的な(定量的な)数値指標を入れる、とされています。

Oには会社規模であれば「世界一の〇〇を作る」みたいな感じの、とにかくすごそうな内容を入れておくのが良いでしょう。チームであればもう少しフォーカスを絞って「UIを改善する」とか「利益率を上げる」とかでもいいでしょう。

KRは、Oを達成するための具体的な数値を指定します。OKRの達成はKRの数値を0.0~1.0の範囲で評価できる状態にするというのがありますので、数値で評価できないものはKRにはなりません。

そうはいってもKRに具体的な話を書きたいんだけど…

「なお、OKR はチェックリストではありません。」ともあります。詳細はそこを読んでいただきたいのですが、あくまで「チームをどうしたか」を決める指針であり、具体的な内容を並べる場所ではありません。

まとめ

  • OKRで評価するのはやめましょう。
  • Oには大きな到達点、KRにはタスクではなく結果から見える数値指標を採用しましょう。
  • OKRのフォーマットが合わない場合はそこから外れても別にいいとは思いますが、その場合はOKRとは名乗らず「我々の手法」として利用しましょう。組織に合わせた適切なフォーマットを使用するのが一番です。

TerraformのWorkspaceはstaging/productionの切り替えに使うべきではない

Workspaceって何だっけ?

簡単に言うと「同一のtfファイル群を別のtfstateとして扱う、それを切り替える」機能です。

なんでだめなの?

公式がそう言っているからです。

In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages (e.g. staging vs. production) or different internal teams. In this case, the backend used for each deployment often belongs to that deployment, with different credentials and access controls. Named workspaces are not a suitable isolation mechanism for this scenario. State: Workspaces - Terraform by HashiCorp

どういうこと?

公式の言い分としては、「全く同じ環境のコピーを作るならいいけど、そうじゃない場合(staging/productionのような)は資格情報とか認証情報とか合わないから使えないよ」ということです。これは例えばstagingとproductionで別のAWSアカウントを使用している場合に該当すると思います。この場合は向いていないのが直感的に理解できるかと思います。

また、公式では「その場合は再利用可能なモジュールを使うべき」としています。つまり、部分的にモジュール化したものを組み合わせて別の構成として取り扱うべきとしています。これであればどのような構成でも部分的にモジュールを組み合わせて使う形になるので、自由な構成を組むことが可能です。

現実では小さい環境であれば片方の環境からコピペして必要なところだけ書き換えて新しい環境を作る、という感じでも最初のうちは困らないことが多いと思いますが、環境が増えそうであれば早めにモジュール化していくのが良いでしょう。

公式が言ってたらダメなの?使えるから使っても良くない?

以下は私の独自見解になります。

大前提として「stagingとproductionのtfstateは分けるべき」と考えています。これはapply時の影響範囲を狭めることができるためです。

その上で、私としては「そんなにstagingとproductionって同一環境ではないのでは?」というような理由で、Workspaceをその用途に使うべきではないのではと思っております。

The Twelve-Factor Appでは、外部環境は本番環境と開発環境のギャップがないようにすべきとされています。これは「開発環境ではローカルメモリに保存するけど本番はMemcached」のような、プロトコルレベルで違うようなものを使うと、それによるアダプターの実装の差異による思わぬ事故が発生する可能性があるためです。

一方で、外部リソースはアタッチされたリソースとして扱うというのもあり、そこでは「リソースを簡単に切り替えることができるようにしておく」とされています。

つまり、「アプリケーションレベルでは常に同一の対象に対してアクセスしているように振る舞うが、その先の通信対象が何なのかはアプリケーションが関与しない」ということです。これは問題が発生したときに責任がどちらにあるのか明確になり、性能限界などでの差し替え時にも容易に差し替えることができるためスケールしやすいアプリケーションになります。

これを踏まえた上で、一般的によくあるケースとして「本番ではメールを送信したいがstagingではメールを送りたくない」といったケースがあります。この場合、本番では普通のメールサーバーを構築します(外部のサービスを使うかもしれません)が、stagingでは「送信したメールを全て吸収してWeb上で表示してくれるサービスに送る」というようなことをすることがあります。具体的にはMailHogMailtrap.ioといったようなものです。私は前者を使うことが多いので、前者用のインスタンスをstagingのみで組み込んでおくということをします。

同様に、AWSでは「stagingではシンプルなRDSを使うが、本番ではAuroraクラスタを組む」というようなケースもよくあります。これも大幅に設定が変わる内容になります。Auroraクラスタまでいかなくても、DBのパラメーターを細かく変えることはあると思いますので、それをWorkspaceでどうにかするのはなかなか大変ではないかと思います。

上記の観点から、そもそもWorkspaceでstaging/productionのような「似てるようで用途が違うもの」の切り替えには向いていないのではないかと思います。が、これらを理解した上で「それでもWorkspaceで切り替えるのがベストだ!」となるのであれば、それでもいいかもしれません。

それじゃWorkspaceって何のためにあるの?

公式では以下のようになっています。

A common use for multiple workspaces is to create a parallel, distinct copy of a set of infrastructure in order to test a set of changes before modifying the main production infrastructure. For example, a developer working on a complex set of infrastructure changes might create a new temporary workspace in order to freely experiment with changes without affecting the default workspace. State: Workspaces - Terraform by HashiCorp

簡単に言うと、「インフラの変更のテスト用にもう1つ作っておいてそこで試すため」とあります。Terraformは実際にapplyする時の挙動は当然apply先のクラウドサービスに依存していますので、applyするまでどうなるかわからないということは多々あります。そのような場合を試すのにはベストなケースだと思います。

同様に、「本番環境と全く同じものを作って、そこでないと発生しないようなバグのテストをする」というようなケースにも良いのではないかと思います。

どちらにしても、「Workspaceを切り替えて複数環境を作れるようにする(しておく)」というのは設計上欠かせない要素になります。必要な設定を切り出しておいて、いつでもWorkspaceで切り替えれる状態を作っておくようにしましょう。

まとめ

  • 公式がそう言っているのでなるべく従いましょう。
  • stagingとproductionってそこまで同一環境ではないので、公式が言ってなくても向いていないのではないかと思います。
  • Workspace機能自体は常に使える準備をしておきましょう。