株式会社クイックのWebサービス開発blog

HAPPYなサービスプランナー・エンジニア・デザイナーのブログです。

LocalStackでAWSサービスを試してみた

はじめまして。ソフトウェアエンジニアのやぎーです。

コロナが再燃してますね。 在宅勤務を継続している方も多いのではないでしょうか。

最近、在宅時にローカル開発環境をもっと充実させたいなー、と感じることが増えてきたので 今回はAWSのローカルモック環境をご紹介したいと思います。

LocalStackとは

開発環境においてAWSのサービスを擬似的に使用できるモックフレームワークです。

github.com

特徴

手軽に環境が作れる

Dockerイメージを利用するか、pipでローカルへ直接インストールすることができます。 今回はDockerイメージを利用します。

複数のAWSサービス(モック環境)が利用できる

LocalStackを使うと、下記サービスがまとめて利用できるようになります。

  • API Gateway
  • Kinesis
  • DynamoDB
  • DynamoDB Streams
  • S3
  • Firehose
  • Lambda
  • SNS
  • SQS
  • Redshift
  • Elasticsearch Service
  • SES
  • Route53
  • CloudFormation
  • CloudWatch
  • SSM
  • SecretsManager
  • StepFunctions
  • CloudWatch Logs
  • EventBridge (CloudWatch Events)
  • STS
  • IAM
  • EC2
  • KMS
  • ACM

料金など気にせずにテストや動作確認ができる

上記のサービスは基本的に無料で利用できます。 有料版でしか使えないサービスもあるのでGitHubを確認してみてください。

つくるもの

今回は簡素に。 サービス間でのやりとりができるのか検証をしたいと思ったので、 LambdaでS3にファイルを作成してみたいと思います。

設定

準備

基本モジュールは事前に導入しておいてください。

  • docker
  • docker-compose
  • git
  • aws-cli
  • zip

LocalStackインストール&起動

$ git clone https://github.com/localstack/localstack
$ cd localstack

指定がないとLambdaが別ネットワークで実行されるようなので、ネットワークを指定します。 docker-compose.yml->environmentに下記を追加

LAMBDA_DOCKER_NETWORK=host

起動

$ TMPDIR=/private$TMPDIR docker-compose up -d

起動確認

$ docker ps
CONTAINER ID  IMAGE COMMAND  CREATED STATUS  PORTS  NAMES

74c4493e092a  localstack/localstack "docker-entrypoint.sh" 2 minutes ago Up 2 minutes  0.0.0.0:4566-4599->4566-4599/tcp, 0.0.0.0:8080->8080/tcp localstack_main

起動できました。はやい。お手軽。

AWS CLI設定

ダミーの設定で大丈夫です。

$ aws configure --profile=localstack

AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: ap-northeast-1
Default output format [None]: json

S3バケット作成

## 作成
$ aws s3 mb s3://test-bucket --endpoint-url=http://localhost:4566 --profile=localstack

make_bucket: test-bucket

## 確認
$ aws s3 ls --endpoint-url=http://localhost:4566 --profile=localstack

2020-07-28 13:37:57 test-bucket

こんな感じで表示されればOKです。

Lambda設定

テスト用のpyファイルを作成 S3にtest_日時.txtというファイルを作成するだけの処理。

$ vi lambda.py

import boto3
from boto3.session import Session
from datetime import datetime


## 検証なので固定値で設定
session = Session(aws_access_key_id='dummy',
    aws_secret_access_key='dummy',
    region_name='us-east-1'
)

s3 = session.resource(
    service_name='s3', 
    endpoint_url='http://localhost:4566'
)

def lambda_handler(event, context):

    bucket = 'test-bucket'    # バケット名を指定
    key = 'test_' + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + '.txt'
    file_contents = 'Lambda Save File'

    s3.Bucket(bucket).put_object(Key=key, Body=file_contents)
    
    return 'create file'

zipファイルに圧縮

$ zip lambda.zip lambda.py

アップロード

$ aws lambda create-function --function-name="test-function" --runtime=python3.7 --role="arn:aws:iam::123456789012:role/service-role/lambda-test-role" --handler=lambda.lambda_handler --zip-file fileb://lambda.zip --endpoint-url=http://localhost:4566 --profile=localstack
{
    "FunctionName": "test-function",
    "FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:test-function",
    "Runtime": "python3.7",
    "Role": "arn:aws:iam::123456789012:role/service-role/lambda-test-role",
    "Handler": "lambda.lambda_handler",
    "CodeSize": 567,
    "Description": "",
    "Timeout": 3,
    "LastModified": "2020-07-28T13:37:23.672+0000",
    "CodeSha256": "GfPKv7jYspFribBiEInVUfLyR8W+K65LPOUID82vG3Y=",
    "Version": "$LATEST",
    "VpcConfig": {},
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "44540e0e-ce6a-45db-a5c1-da6ac0ba776b",
    "State": "Active",
    "LastUpdateStatus": "Successful"
}

動作確認

作成したLambda Functionを実行 AWS CLI バージョン2では、パラメータはbase64エンコードが前提のため、--cli-binary-formatを指定します。

Lambda起動

$ aws lambda invoke --cli-binary-format raw-in-base64-out --function-name test-function result.log --endpoint-url=http://localhost:4566 --profile=localstack 

{
"StatusCode": 200,
"LogResult": "",
"ExecutedVersion": "$LATEST"
}

FunctionErrorが出力されていないことを確認しましょう。

S3ファイルを確認

$ aws s3 ls s3://test-bucket --endpoint-url=http://localhost:4566 --profile=localstack
2020-07-27 13:38:08 16 test_2020-07-26-13-38-08.txt

期待通りにファイルが作成されました!

さわってみた感想

使いやすい点

  • Dockerイメージ簡単!
  • 好きなサービスだけ指定して起動できる
  • 完全に独立したAWS環境が使える

使いにくい点

  • CLI操作が前提となるため、慣れていないと結構大変
  • 前提環境がある場合、構築用のスクリプトなどを用意する必要がある
  • ユースケースによっては機能が対応してなかったりする

おわりに

ほんの一部になりますが、LocalStackの使い方を紹介させていただきました。

在宅勤務などでクラウドサービスの需要が増加している中、 AWSの機能をローカルでも利用・検証できるのはとても素晴らしいことです。

また、これからAWSを使いたい方・AWSの勉強をしたい方の練習環境としても手軽に利用できます。

ローカル環境を充実させることで、在宅勤務でも開発のパフォーマンスを高めていきましょう!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

AWS SAMを使ってバッチシステムを作ってみたぞ!

こんにちは、ソフトウェアエンジニアのiwateaです。

皆さん、AWS使ってますか?

AWSのおかげで複雑な知識がなくてもインフラ構築ができるので、とてもいい時代になりましたよね。

そんなクラウド時代になって、ちょくちょく耳にするキーワード「Serverless」。
今回はそんなServerlessフレームワークの1つであるAWS SAMの話です。

AWS SAMって何?

AWSでServerlessアプリケーションを構築するためのフレームワークです。

aws.amazon.com

ローカルでLambdaの実行環境ができるので開発・テストがしやすく、AWSへのデプロイも1コマンドでできる優れものです。

Serverlessでバッチシステムを作ると何が嬉しいの?

料金が安い

Serverlessでは必要な時に必要な時間だけ実行環境を起動するためコスト削減に繋がります。

小中規模システムのバッチは特定の時間に数分〜数十分だけ動かすケースが多く、逆に言うと何もしない時間が大半です。
そのため、EC2を常時起動してバッチサーバーとしてしまうと無駄な課金が発生してしまいます。

並列化で実行時間の短縮ができる

Lambdaは並列実行が容易にできるので、並列化による処理時間の短縮ができます。

バッチ処理が遅くなるケースの一つに、データ量に伴うループ回数の増加に起因するものがあります。
このケースではコードの最適化による速度改善には限界があり、中々難しいのが実情です。
この問題を解決するために並列化という手法を使うことがありますが、これをインフラレベルで簡単に実現することができます。

早速SAMを動かしてみよう!

今回はシンプルなProducer Consumerパターンを作ります。

f:id:aimstogeek:20200714154150p:plain

Step1. SAMプロジェクトの作成

sam init コマンドでSAMプロジェクトを生成しましょう。
今回はgolangを使いました。

 $ sam init --name blog --runtime go1.x
Which template source would you like to use?
    1 - AWS Quick Start Templates
    2 - Custom Template Location
Choice: 1

Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git

AWS quick start application templates:
    1 - Hello World Example
    2 - Step Functions Sample App (Stock Trader)
Template selection: 2

-----------------------
Generating application:
-----------------------
Name: blog
Runtime: go1.x
Dependency Manager: mod
Application Template: step-functions-sample-app
Output Directory: .

Next steps can be found in the README file at ./blog/README.md

Step2. 処理を作る

2つのLambdaファンクションを用意しました。

producer : SQSにメッセージをEnqueueするLambda
consumer : SQSからメッセージを受け取り、標準出力に表示するLambda

├── functions
│   ├── consumer
│   │   ├── go.mod
│   │   ├── go.sum
│   │   └── main.go
│   └── producer
│       ├── go.mod
│       ├── go.sum
│       ├── main.go
│       └── main_test.go
└── template.yaml

Step3. template.ymlを編集する

AWSリソースの定義をします。

AWSコンソールから作ろうとしたらCloudWatchEventやIAM Role等を作る必要がありますが、なんとSAMリソースを使うと必要なものをまとめて作ってくれます
AWS SAM リソースおよびプロパティのリファレンス - AWS サーバーレスアプリケーションモデル

なお、SAMリソースに定義されていないものはCloudFormationの定義をすればOKです。

※Resourcesのみ抜粋

Resources:
  TaskQueue:
    Type: AWS::SQS::Queue

  ProducerFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functions/producer/
      Handler: producer
      Runtime: go1.x
      Events:
        Timer:
          Type: Schedule
          Properties:
            Schedule: cron(0 9 ? * MON *)
      Environment:
        Variables:
          SQS_ENDPOINT: !Ref TaskQueue

  ConsumerFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: functions/consumer/
      Handler: consumer
      Runtime: go1.x
      ReservedConcurrentExecutions: 10
      Events:
        TaskQueueEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt TaskQueue.Arn
            BatchSize: 10

Step4. ローカルで実行してみる

SQSからメッセージを受け取るConsumerFunctionを実行してみます。

sam local invoke コマンドに -e オプションをつけてメッセージのパラメーターを渡しますが、パラメーターのフォーマットが分からない事件が度々。。
そんな時は sam local generate-event コマンドで生成できます。

$ sam local generate-event sqs receive-message
{
  "Records": [
    {
      "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
      "receiptHandle": "MessageReceiptHandle",
      "body": "Hello from SQS!",
      "attributes": {
        "ApproximateReceiveCount": "1",
        "SentTimestamp": "1523232000000",
        "SenderId": "123456789012",
        "ApproximateFirstReceiveTimestamp": "1523232000001"
      },
      "messageAttributes": {},
      "md5OfBody": "7b270e59b47ff90a553787216d55d91d",
      "eventSource": "aws:sqs",
      "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue",
      "awsRegion": "us-east-1"
    }
  ]
}

では、ConsumerFunctionを実行してみましょう。

$ sam build && sam local invoke -e functions/consumer/event.json ConsumerFunction
...

Fetching lambci/lambda:go1.x Docker container image......
Mounting /Users/iwata-yoshihiro/workspace/go/blog/.aws-sam/build/ConsumerFunction as /var/task:ro,delegated inside runtime container
START RequestId: ef5f5202-0cc8-19a1-0fcf-014c89d8f258 Version: $LATEST
Hello from SQS!
END RequestId: ef5f5202-0cc8-19a1-0fcf-014c89d8f258
REPORT RequestId: ef5f5202-0cc8-19a1-0fcf-014c89d8f258  Init Duration: 124.26 ms    Duration: 4.11 ms   Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 22 MB

"success"

やったぜ!!

Step5. AWSへデプロイしてみる

最後にAWSへデプロイしてみましょう。

事前にデプロイで使うbucketをS3に作っておきます。
そして sam deploy コマンドを実行すればデプロイ完了です!

楽ちん!

$ sam deploy --stack-name blog --s3-bucket blog-deploy-bucket --capabilities CAPABILITY_IAM

あのtemplate.ymlで、これだけのAWSリソースが生成されます。 f:id:aimstogeek:20200714162556p:plain

実際に運用してみて起きた問題点

Terraformとの共存がしにくい

インフラ構築の際にTerraformがよく使われますが、SAMはCloudFormationを使うことになります。
もしWeb + Batchの様なシステムを構築する場合にどちらで何のAWSリソースを管理するかが課題になります。

Lambdaの実行時間制限

Lambdaは1回あたり15分しか実行できない制限があります。
そのため、15分以上の実行時間が必要なものは運用できません。

こういったケースではECS TaskやAWS Batchを使いますが、SAMプロジェクトでDockerを使ったバッチを作ろうとするとアーキテクチャが違いすぎて複雑化してしまいます。
ある日データ量の増加で15分制限に引っかかり、処理の都合上Lambdaでは限界ということが判明した時は頭を抱えました。

全体像把握のハードルが高い

ServerlessではAWSマネージドサービスを復数組み合わせることになります。
また、イベント駆動で各種リソースを起動することが多いので、AWSに慣れていないと全体像把握のハードルが高くなります。
AWS大好きでコードをゴリゴリ書けるエンジニアを揃えるのは中々難しいところです。

おわりに

例えば「S3にファイルがアップロードされた時」にLambdaで処理をするなんてこともでき、これまで時間決め打ちやポーリングといった柔軟性が無かったり、無駄が多かった設計がイベント駆動のシンプルな設計に置き換えることができるようになりました。

しかし、便利さの裏で如何ともし難い問題点も含んでいますので、自分たちが作るシステムに合わせて技術選定をして頂ければ幸いです。

AWSのおかげでインフラストラクチャがより扱いやすくなり、マネージドサービスの活用で開発コストを削減することができて嬉しい反面、システム設計にアプリ・インフラ両軸の知識が必要になり大変な時代でもあります。

技術の移り変わりは激しいですが、取り残されずに良いエンジニアライフを送りましょう!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

在宅勤務はfish + tmux + vimでイケてるターミナル環境に引き篭もろう!

どうもはじめまして!
去年の11月に入社したSREチームのとっしーです!

最近はコロナの影響で在宅勤務となった方も多いと思いますが、
その影響で引き篭もりになってしまったという方も多いのではないでしょうか?

ぼくも完全に引き篭もりまくっています、そう、ターミナルの中にね。

ターミナルに引き篭もるということ

「引き篭もり」というとあまり良い印象はないですが、個人的にターミナルというとエンジニアの象徴的なイメージもあり、そんなターミナルを使いこなしてる(引き篭もってる)ってカッコいいし、なんかエンジニアっぽい、ということを思ったことがきっかけでぼくのターミナルライフは始まりました。

f:id:aimstogeek:20200708102512p:plain

ターミナルに引き篭もるということは理想のエンジニアに近づくという行為であり、それは修行を重ね、信仰している神に近づくことにも似たとても尊いことでもありますが、正直自己満なので沼にどっぷり浸かりすぎないよう注意が必要です。

ですが、きっとみなさんもうすでにターミナルに引き篭もりたくて仕方ないと思うので、これから一緒にターミナルに引き篭もる準備をしていきましょう。

ターミナルに引き篭もるための道具

さて、イケてるターミナル環境に引き篭もるためには以下のツール達が必要になります。

github.com

github.com

github.com

上記ツールについての詳細な説明は公式に委ねますが、簡単に説明すると以下のような感じです。

名前 説明
fish シェル。他のシェルと比べると新しく(2005年リリース)、強力なサジェスチョン/補完機能、親切なシンタックスハイライト、GUI(ブラウザ)での設定/ヘルプページなどが標準で備わっている。
tmux ターミナルの仮想化とかするやつ。似たものではscreenがある。
vim 言わずと知れたエディタ界の神。しばしば他のエディタ界の神々と喧嘩をする。

ちょっと前まではZshを使っていたんですが、Plugin管理に疲弊したため、標準で良い感じに動いてくれそうなfishに乗り換えました!

そしてそれぞれのツールをイケてる感じに使うためには結構色々な設定が必要だったり使い方に癖があったり何かと大変なんですが、興味があれば是非チャレンジしてみてください!

ターミナルに引き篭もってみよう!

というわけで、早速ですが、設定がめんどくてやる気が出ないみなさんのために、ぼくのdotfilesリポジトリを使ってイケてるターミナル環境を体験してみてもらおうと思います!!

github.com

Vagrantが動く環境であれば以下のようにリポジトリをクローンしてvagrant upすればイケてるターミナル環境が構築されるので、立ち上げたサーバーにvagrant sshで入ったあとsudo su -rootユーザーへスイッチ後のターミナルを見てみてください!

$ git clone https://github.com/Tocyuki/dotfiles.git
$ cd dotfiles
$ vagrant up
$ vagrant ssh
$ sudo su -

すると・・・

おおおおおおおおおおおおおイケてるううううう

tmuxで画面分割便利いいいい f:id:aimstogeek:20200708100754p:plain

Vimでfzfでのインクリメンタルサーチ便利いいいい f:id:aimstogeek:20200708100802p:plain

NerdTreeでファイルツリー見れて便利いいいい f:id:aimstogeek:20200708100810p:plain

LazyGitを使ったVim上でのGit操作便利いいいい f:id:aimstogeek:20200708100818p:plain

docuiを使ったVim上でのDocker操作便利いいいい f:id:aimstogeek:20200708100829p:plain

という感じでカスタマイズは結構必要ですが、ターミナルに良い感じに引き篭もれることがおわかりいただけたかと思います!

ほとんどVimの話になってしまいましたけど・・・\(^o^)/

おわりに

ターミナルの世界はどうだったでしょうか?

カスタマイズができる反面、設定や管理が面倒くさかったり、操作に癖があったりと中々手が出しづらい部分はあるかもしれませんが、たまごっち的な感覚で自分のターミナル環境を育てていくと愛着も湧いてくるのでオススメです!

実際の詳細な設定は是非ぼくのdotfilesリポジトリの設定ファイルを見てみてください!

ちなみに冒頭ではターミナルに引き篭もってるとか言ってましたけど、実は最近VS Codeに引き篭もっている今日このごろです\(^o^)/

それでは良きターミナルライフをお過ごし下さい!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

IPアドレス枯渇問題奮闘記

はじめまして!情シスのユキチです。

昨年の11月にクイックに中途入社しました!
前職では2年ほどネットワークエンジニアをしていました。

前職では同じネットワークエンジニアとしかコミュニケーションを取ることが無かったので、
最初はヘルプデスクでのコミュニケーションの量の多さに驚きました゚( •̀ㅁ•́;)
今では電話対応も異常な汗をかくこと無くこなしています!

なんやかんやでヘルプデスクの業務に慣れてきた頃、同じチームの福さんから
「ネットワークの作業があるんだけど、お願いしても良い??」
と案件をいただきました!

やったー!機器のリプレース?それともLANの拡張?と目を輝かせて、作業の詳細を聞いてみると…
東京拠点にある多くの端末に割り振られるIPアドレスが足りないので、対処してほしい

東京拠点のIPアドレス枯渇問題への対処でした

なんだ、IPアドレスレンジ拡張すれば良いのか、と思っていました。 IPアドレス表を見るまでは……

前置きが長くなりましたが、今回はその問題の原因及び現時点での対処そして今後行っていく理想の対処をお話します。

問題の背景

数年前、クイックではデスクトップPCを有線LANに接続し使用していました。
そのため、1人あたり1IPのみ保持していました。

しかし2019年頃から、
・全社員PCのノート化
Wifi設置
・社用携帯の社内ネットワークへの参加
を開始し、1人あたり3IPアドレス必要に!

さらに社員数は2倍以上になり……

f:id:aimstogeek:20200701160149p:plain

こうして東京拠点で必要なIPアドレスの数は、数年前と比べて約6倍になりました!
結果、IPアドレスが枯渇寸前になりました。

東京IPアドレス枯渇問題の全貌

そこで回線業者に、東京拠点のIPアドレスのレンジ拡張を依頼しようとしたのですが…

f:id:aimstogeek:20200629152748p:plain

きっちり両脇が固められていました。
東京拠点の前後のIPアドレスが、すでに他の拠点で使われているため
変更や調整に膨大な時間がかかります。

単純にレンジを広げてもらうことは不可能でした。

しかも今回規模が大きくなった東京拠点だけでなく、
同じく規模が大きくなる可能性がある大阪拠点のIPアドレスも前後に余裕無く設定されていました。

こうして、東京拠点のIPアドレス枯渇問題は
各拠点のIPアドレスレンジに拡張性が無い
という実に根が深い問題のほんの一部ということが明らかになりました。

東京拠点のみの現最善策

東京のみの問題では無いことが分かったとはいえ、新型コロナ感染拡大予防に伴うリモートワークのためにノートPC数百台を早急に追加する必要があったので、IPアドレス設計をやり直し回線業者に依頼しサーバのIPアドレスを変更し……は数カ月ほどの時間を要するため出来ません。

まずは今IPアドレスが枯渇しそうな東京拠点のみ早急に対処する必要があります。

そこで現時点での最善策として、東京拠点の1フロアのみ全く別のIPアドレスレンジを追加することを検討しています。

f:id:aimstogeek:20200629154000p:plain

そしてこの案には大きく3つの実現方法があります。
1.VLANを追加し、回線業者のルータでルーティングしてもらう
2.新しく回線を追加契約する
3.クイックでルータを追加し、ルーティング設定する

※今回は具体的な設定や構成の説明は省略します。

今まさに、上記3案の構成図や比較資料を作成し回線業者の方と調整を行っている最中です。

早ければ7月中にめでたく東京拠点のIPアドレス枯渇問題は解決する見込みです!

問題全体への理想的な対策

最終的に、以下を考慮して各拠点のIPアドレスレンジの見直しを行い、数ヶ月かけて一新する予定です。
・全社員ノート化に伴い有線LANを廃止し、1人2IPにする
・社員増減の傾向を考慮し、数年後の社員最大数を予想する

最後に

大きな環境の変化があったために起きた今回の問題ですが、
今後は1人1IPではなく、1人複数IP持つことを考慮して設計しないといけないと実感しました。

まだIPアドレス枯渇問題は解決途中ですが、大きな責任を伴う作業なので引き続き慎重に進めていきます!


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

振り返りの質を高めて変化に強いチームをつくる - 在宅勤務でも高いパフォーマンスを-

こんにちは!サービスプランナーのaiです。
緊急事態宣言が発令されクイックも基本在宅勤務になりました。在宅勤務というこれまでとは違う環境下でチームで仕事を進める中で、改めて振り返りの重要性を実感しましたので、本記事では私たちのチームで実施している振り返りと、実施する中で見えてきた振り返りのコツをご紹介させていただきます。

KPT

私たちのチームではここ1年以内にメンバーが急激に増えたこともあり、それぞれのメンバーが思っていることを自由にアウトプットしてチームの改善に繋げるため、 KPTを使用したチームの振り返りを始めました。
KPTは「Keep(よかったこと、このまま継続すること)」「Problem(困ったこと、問題点)」「Try(解決策)」の3つの項目について意見を出す、振り返りの手法のひとつです。
Keep、Problem、Tryの3項目を全員が付箋に書き出し、ホワイトボードに張り出してトークという一般的なスタイルではじめましたが、現在は以下のやり方で実施しています。

KPTのやり方

・週に1回、60分
・在宅勤務中はオンラインで実施
ファシリテーターは持ち回り制
・以下の5項目について、事前にメンバーがスプレッドシートを埋めておく
 ①誰かに相談したい・聞いてほしいこと(Problem)
 ②チームで変えたいこと・困っている問題/理由(Problem)
 ③チームで続けたいこと(Keep)
 ④自分が続けたい・ドヤりたいこと(Keep)
 ⑤誰かに感謝したいこと(Keep)
・会の最初に前週の振り返りを行う(①②のみ)
・前週の振り返りが終わったら①と②についてTryを出す
・残りの時間で③④⑤を読み上げてみんなで見ていく

やり方を変更する前は、前回の振り返りの後に、Keep→Problem→Tryの順で話をしていましたが、 以下のような問題がありました。

  • Problemに個人的に困っていることとチームの問題点が混在している
  • Tryを議論する時間が少なくなってしまうことが多い

やり方を変更してからはProblemについては議論が必要なものとそうでないものが明確になり、Tryについても十分に時間を割いて議論することが可能になりました。主語と対象がわかりやすくなり挙げやすくなったというメンバーからの声もありました。
また、最初は一人のメンバーが担当していたファシリテーターを持ち回り制にしたことにより、良い緊張感を保った状態でKPTを継続できています。

振り返りの重要性

日常的に振り返りを実施していることで、チームが置かれている状況や環境が大きく変化した場合(今回の在宅勤務がまさにそれ)に、早い段階で問題点を検知し、解決に向けて動くことができます。

例えば、在宅勤務が始まってからのKPTでは

  • 文字だけだとメンバーの反応がわかりづらい
  • コミュニケーション不足を感じる

といったようなコミュニケーションに関する問題点が多くあがってきました。
私たちが実施したTryとしては

  • 毎日のオンライン朝会の中で、メンバーのことを知れるようなコンテンツ(質問コーナー等)を追加する
  • ちょっとした相談や雑談用のビデオチャット部屋を作る
  • ビデオをONにして話す
  • 意識的にチャットでのコミュニケーションを多くする

等がありますが、早い段階で効果として現れたのが、ビデオチャットの活用頻度が増えたことです。
最初は相手の状況が見えないことによる遠慮が少なからずあったようでしたが、
「在宅勤務中のチームのパフォーマンスの維持・向上のためには、遠慮は捨ててビデオチャットを活用し、案件をどんどん進めていくことが必要!」という共通認識をKPTの場でみんなで持てたことも ビデオチャットへの心理的ハードルを下げることにつながりました。

問題点の可視化や改善以外にも、メンバーの状況把握や、チーム全員で共通認識をもつためにも振り返りを行うことはとても有用です。

問題点を継続して挙げ続けるためのコツ

振り返りを繰り返していくと、問題点が出づらくなったり、特定のメンバーからしか問題点が出なくなる場合があります。
私もKPTを繰り返すうちに問題点を出しづらいと感じたことがありますが、問題点を挙げることが得意なメンバーを見ていて、以下のようなコツがあると思いました。

  • 少しでも良いと感じたこと、良くないと感じたことを躊躇せずに挙げてみる
  • 振り返りのスパンを変えてみる(直近1週間、3ヶ月間、半年間、在宅勤務期間など)
  • 特定のテーマに絞ってチームに必要なことを挙げてみる(チームの目指す姿を満たす上で足りてないものは?生産性をあげるために必要なものは?など)

日々の業務で発生したことだけを振り返っていると、長期的な課題が出づらくなるため、振り返り対象や期間を変えてみたり、チームが目指す姿から逆算して考えてみたりすることで、気づけなかった問題点の発見に繋がります。

まとめ

振り返りをチームにとって意味のある状態で継続していくには、
振り返りのやり方を見直したり、問題点が出づらくなった場合にはそれを問題点として改善していきながら、 より良い振り返りの場をチームみんなで作り上げていくことが重要だと思います。

新型コロナウィルス影響下で日々状況が変化する毎日ですが、
振り返りの質を高めて、変化に強いチームを作っていきます!

参考記事 https://ihcomega.hatenadiary.com/entry/2020/04/28/055258


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

RaspberryPi 4+NatureRemo APIで暗くなったら自動で照明をつけさせてみた【自作】

こんにちは。 ソフトウェアエンジニアのスネ夫です。

弊社では緊急事態宣言後、在宅での勤務が基本となっており、私もほぼ自宅で仕事をしています。
私は太陽光が好きなので、窓の近くにデスクを置き部屋の照明はつけず、朝から太陽光を浴びて仕事をしています!
気持ちいいですね。

夕方ごろになると当然暗くなってくるのですが、気がつくと部屋が真っ暗なまま仕事をしていたりします。
暗くなったら勝手に照明がつけばいいのに・・・。
と考えていたら、目の前にはRespberryPiとNatureRemoが!

この2つを使って、「暗くなったら照明をつける」を実現してみたいと思います。

システム構成

ざっくりとこんな感じになります

f:id:aimstogeek:20200618173726p:plain
システム構成

  • RaspberryPi

ボード型のスモールコンピューターで、大きさは名刺サイズ!
簡単なサーバ用途として使ったり、電子工作をしてラジコンを作ったりなど楽しいおもちゃです。
今回はRaspberryPi Model4とカメラモジュールを使い、部屋が暗くなったことを感知して、NatureRemoのAPIから部屋の照明をつけます。

  • Nature Remo

家の中の家電をスマート家電化するためのスマートリモコンです。
赤外線リモコンで動く家電ならば、スマホスマートスピーカーから操作することが可能になります!
また、NatureRemoはREST型のAPIも公開しているため、プログラミングによって操作することが可能です。

NatureRemoのAPIで照明をON/OFFする

まず、RaspberryPiからNatrueRemoを通して照明をつけるところから始めます。

つけたい照明の情報をアプリから確認しておく

NatureRemoを使っている方はわかると思いますが、家の中の機器にはそれぞれ名前をつけているはずなので、アプリからつけたい照明の名前を確認しておきましょう。
私の場合は「リビングの電気」になります。

API仕様の確認

APIの仕様がきっちりまとまっており、非常に簡単です。
ざっと眺めておきましょう。
https://developer.nature.global/

アクセストークンの取得

まず、APIを使うためのアクセストークンを生成します

https://home.nature.global/

ここにブラウザでアクセスしてログインすると以下のページが表示され
「Generate Access Token」から、操作するためのアクセストークンが取得できます。
APIを使う時に必要なので、コピーしましょう。

f:id:aimstogeek:20200618174546p:plain
アクセストークン取得

機器情報(signal_idの確認)

「リビングの電気」をつけるためNatureRemo側で認識されている機器情報を確認します。
先ほどのアクセストークンと合わせて、以下のようなcurlコマンドをたたきます。

curl -X GET "https://api.nature.global/1/appliances" -H "accept: application/json" -k --header "Authorization: Bearer xxxAccessTokenxxx"

※xxxAccessTokenxxxの部分を、先ほど取得したアクセストークンに置き換えて実行します。

すると、以下のような情報が返ってきます。

[
-- 省略 --
    {
        "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "device": {
            "name": "Remo",
            "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "created_at": "20xx-xx-xxTxx:xx:xxZ",
            "updated_at": "20xx-xx-xxTxx:xx:xxZ",
            "mac_address": "xx:xx:xx:xx:xx:xx",
            "serial_number": "xxxxxxxxxxxxxxxx",
            "firmware_version": "Remo/x.x.xx-g808448c",
            "temperature_offset": 0,
            "humidity_offset": 0
        },
        "model": null,
        "type": "IR",
        "nickname": "リビングの電気",
        "image": "ico_light",
        "settings": null,
        "aircon": null,
        "signals": [
            {
                "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                "name": "オン",
                "image": "ico_on"
            },
            {
                "id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
                "name": "オフ",
                "image": "ico_off"
            }
        ]
    }
]

先ほどアプリから確認した、「リビングの電気」の情報のうち、ONとOFFのidをコピーしておきます。
上記のサンプルでいうと、

"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
"id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"

この部分になります。

ONにしてみる

先ほど取得したオンのシグナルIDを使って、「リビングの電気」をONにしてみます。

curl -H 'Authorization: Bearer xxxAccessTokenxxx' -H 'accept: application/json' -X POST "https://api.nature.global/1/signals/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded"

※AccessTokenの部分とsingalの部分は取得した情報に置き換えてください。

するとどうでしょう・・・。

照明がつきますヽ(´∀`)ノ

コマンドラインから照明がつく・・・。リモコン押せば照明はつきますが、コマンドラインから照明がつくって感動しますよね!

シェルから実行できるように以下のようにshファイルを作っておきます。
今回、OFFは使いませんが同様にOFFにもできます!

#!/bin/sh

curl -H 'Authorization: Bearer xxxAccessTokenxxx' -H 'accept: application/json' -X POST "https://api.nature.global/1/signals/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded"

RaspberryPiのカメラから暗くなったことを検知してNatureRemoにONを送信する

RaspberryPiのセットアップ

基本的なセットアップの方法はたくさん記事があると思いますので、そちらを参照してください。
今回は、GUIのデスクトップ版で確認を行なっています。

カメラモジュールの設定

今回は、オフィシャルなカメラモジュールである

raspberry pi camera module v2.1

こちら使用しています。
RaspberryPi に接続して、設定からカメラを使える状態にしておきましょう!

Pythonやモジュールの設定

画像やデータの解析などでOpenCV、matplotlib、numpy、pnadsを使うためインストールしておきます。

pyenv環境を整えてpipからインストールする方法もありますが、バージョンによってはすんなりいかないようなので、自分の場合はaptとpip3からインストールしました。

sudo apt-get install libhdf5-dev libhdf5-serial-dev libhdf5-103
sudo apt-get install libatlas-base-dev
sudo apt-get install libjasper-dev
sudo apt-get install python3-matplotlib python3-numpy python3-pandas
sudo pip3 install opencv-python

画像の解析

カメラから部屋の画像を撮影して、その画像情報から明るさの情報を抽出します。
この辺り画像解析の知識はほとんどないので、かなり自己流?な方法かもしれません笑

まず、1分ごとに部屋の特定の場所を撮影してRGBとHSVの値を取得します。
それをCSVに出力して、傾向を見ることにしました。

import csv
import pprint
import datetime
import cv2
import numpy as np
import os

# raspistillコマンドを使ってカメラで撮影して画像に保存する
os.system('raspistill -o /home/pi/nature/image.jpg')

# 画像をOpenCVで読み込んで、RGB情報とHSV情報をそれぞれ取得
img=cv2.imread(str('/home/pi/nature/image.jpg'))
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
b, g, r = cv2.split(img)

dt_now = datetime.datetime.now()
dt_str = dt_now.strftime('%Y/%m/%d %H:%M:%S')

# csvファイルに書き込む
with open('/home/pi/nature/data.csv', 'a') as f:
    writer = csv.writer(f)
    writer.writerow([dt_str, str(h.mean()), str(s.mean()), str(v.mean()), str(r.mean()), str(g.mean()), str(b.mean())])

上記の結果、HSV情報のうちV(明度)が使えそうなことがわかりました! 下のグラフが明度の平均値をプロットしたものですが、 18:30頃は120だったものが、暗くなってきた18:50には20になっています!

f:id:aimstogeek:20200618175808p:plain
明度

明度を判別して、基準値を下回っていたら照明をONにする

上記のグラフから、照明をつける必要がある明度の値を70として以下のようにプログラムを書き換えます。
直近の明度を3つ取得して、全てが70以下ならば照明をつけます。
(1回だけだと、猫とかが写り込んでしまうかもしれないので)

import csv
import pprint
import datetime
import cv2
import numpy as np
import os
import pandas as pd

# 明度の境界値
V_VALUE = 70

os.system('raspistill -o /home/pi/nature/image.jpg')

# raspistillコマンドを使ってカメラで撮影して画像に保存する
img=cv2.imread(str('/home/pi/nature/image.jpg'))

# 画像をOpenCVで読み込んで、RGB情報とHSV情報をそれぞれ取得
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
b, g, r = cv2.split(img)

dt_now = datetime.datetime.now()
dt_str = dt_now.strftime('%Y/%m/%d %H:%M:%S')
file_name = '/home/pi/nature/' + dt_now.strftime('%Y%m%d') + ".csv"

# csvファイルに書き込む
with open(file_name, 'a') as f:
    writer = csv.writer(f)
    writer.writerow([dt_str, str(h.mean()), str(s.mean()), str(v.mean()), str(r.mean()), str(g.mean()), str(b.mean())])

# csvファイルをpandasで読む
csv_input = pd.read_csv(filepath_or_buffer=file_name, encoding="ms932", sep=",")

# 直近の明度を3件取得して、全て基準値以下ならon.sh呼び出してリビングの電気をつける
is_dark = True;
for v in csv_input.tail(3).iloc[:, 3]:
    if float(v) > V_VALUE:
        is_dark = False
        break

if is_dark:
    os.system('/home/pi/nature/on.sh')

上記をコマンドラインから実行して、動作することを確認してみると・・・。

つきました!感動ですね!

コマンドラインから照明がつくなんt(略

cronに設定する

crontabで毎分、上記のpythonを動作させるようにします

*/1 8-21 * * * /usr/bin/python3 /home/pi/nature/on.py >> /tmp/on.log 2>&1

これで1分ごとにプログラムが実行されて、暗くなったら自動で照明がつきますヽ(´ω`)ノ

まとめ

実はNatureRemo、照度センサーがついているのでアプリだけでも
「暗くなったら照明をつける」
は実現できます!!
ただ、センサーの更新が1時間に1回なのでちょっと実用的ではないのです。
なので今回は、わざわざRaspberryPiとカメラを使って実現してみました。
NatureRemoのようなスマートホーム家電がいろいろと出てきていますが、RaspberryPiなどと組み合わせて使うと、いろんな可能性が広がって楽しいですね。


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp

駆け出しエンジニアが入社後半年間で経験したお仕事

はじめまして!
プログラミング歴1年4ヶ月
エンジニア歴7ヶ月
な駆け出しソフトウェアエンジニアのちーかまです。

去年の11月に中途採用でクイックに入社する前は、某素材メーカーの人事として働いていました。

エンジニアになるべく奮闘していた頃、思っていたことがあります。

  • エンジニアになる方法を載せたサイトはたくさんあるけれど、実際にエンジニアになった後の話ってあんまり載ってないよね...?
  • 最初からコード書いたりするんだろうか...キャッチアップできるかな...?
  • できれば入社した後の話を具体的に聞いてみたいよね...?

ということで、ひとつのサンプルとして私が入社してから今までどんな仕事をしてきたか紹介します!

11月頭〜中旬 画面構成書の修正と勉強

ソフトウェアエンジニアとしても、プロジェクトメンバーとしてもペーペーな私には足りないものが大きくわけて2つありました。

  1. 参画したプロジェクトが開発する社内システムに関する知識

  2. プログラミングに関する知識

前者を培うためにシステムを触りながら画面構成書を最新の状態に修正する作業をしつつ、 後者を補うために毎日自主学習の時間をいただき、実際にコードを読んだりわからない箇所を調べたりしていました。

11月中旬〜12下旬 テストと便利ツールの開発

次に、テストを任されるようになりました。
最初は画面上で確認することができるフロントサイドのテストが割り振られ、
徐々にデータ関連のテストや比較的簡単なサーバーサイドに関するテストも行うようになりました。

そんな中

「せっかくならコード書きたいよね?気が向いたらプロジェクトでほしいと思ってた便利ツール作ってみて」

というありがたい提案があったため、Backlogのタスクが完了したときとレビューが追加されたときにChatworkに通知するBotを作りました。

実装に使用したのはZapier。
あまりの簡単さに感動し、ChatworkでBotに問いかけることでBacklogの自担当タスクを教えてくれる機能を作成したところ、タスクが上限を超えてあっという間に使用できなくなってしまったのもいい思い出です...

(ちなみにその後 Python + Flask + Heroku でBot作り直しました。今でもきちんと動いています!)

f:id:aimstogeek:20200612102712j:plain

12月下旬〜1月頭 初リリース

機能追加を任せてもらい、設計書を書いてそれを基に実装する、という作業をはじめて行いました。

2ヶ月間も勉強期間があったにも関わらず結果は散々…
戒めのためにも、簡単に反省点を記載します。

  • 工数把握ができていなく、スケジュール通りに作業を遂行できなかった
  • 設計書の書き方が下手で、他の人にもわかりやすい書き方ができなかった
  • 対応漏れがあることにリリース直前に気付いた

不甲斐なさで心が折れそうでしたが、リリース後チャットで労いの言葉をいただき、もっと精進しようと前向きな気持ちになることができました。

f:id:aimstogeek:20200615073844j:plain

1月頭〜 バグ修正とレビュー

簡単なバグ修正のタスクやレビューが振られるようになりました。
テストのときと同様、最初は画面上で確認することができるフロントサイドの修正やレビューが割り振られ、
徐々にサーバーサイドに関するタスクも振られるようになりました。

入社した11月にコードをみたときはどこになにが書いてあるのかチンプンカンプンだったのに、修正を任されるまで知識がついてきたことが感慨深く、そして少し不思議な気持ちになったことを覚えています。

依然として差し戻しが多いので、差し戻しを減らすことが最近の目標です!
そのための個人的な課題は

  • 尻込みせずに、ばんばん質問すること(質問しやすい雰囲気はあるけど遠慮してしまう...)
  • 想像力を働かせ仕様把握を行うこと
  • 対応漏れがないように、何度もチェックする癖をつけること

です。宣言すると実現に近づくと聞くので、表明させてもらいます!!

5月中旬〜 プロジェクトの問い合わせ対応業務追加

バグ修正とレビューに加えて、参画プロジェクトで開発している社内システムの、問い合わせ対応の窓口を担当することになりました。
お問い合わせがきて不具合の原因がどこにあるのか調査するたびに、新たな発見をする毎日です...

いち早くユーザーの意見を聞くことができるのはとても貴重な体験なので、真のユーザーファーストを目指しどんどん吸収していきたいです!!

さいごに

思い返してみると、エンジニア未経験の私が潰れないようかなり目をかけてもらっていたなと思います。
「最初からコード書いたりするんだろうか...?」なんていう懸念は現実には起こらなく、徐々にステップアップできるよう仕事が振られました。

今回は紹介できませんでしたが、メンター制度があり仕事でもプライベートでもなんでも相談できる環境にあったのも本当にありがたかったです。
過去にメンター制度について記載してある記事があるので、興味ある方はぜひ一読を!

aimstogeek.hatenablog.com

この記事が、エンジニアに興味がある方、またはクイックに興味がある方のお役に少しでも立てば幸いです。


\\『真のユーザーファーストでマーケットを創造する』仲間を募集中です!! //

919.jp