garbagetown

個人の日記です

在宅勤務メモ

こんなご時世のため三月から基本的に在宅勤務しているので買い物メモ。

関連ツイートはこの辺り。

職場から持ち帰った備品が写り込むので画像は自粛。外国のえらい人たちが余裕でいろいろな写真を SNS に投稿しているので問題なさそうだけど。

面倒でアフィリエイトは貼っていないのでお気軽におポチりください。

買ったもの

DMM.make 卓上昇降デスク デュアル720ブラック DKS-LDD720B

  • 腰痛持ちのため自宅にあるダイニングチェアやソファで長時間働くと腰が死ぬ。
  • 段ボール箱を重ねてスタンディングデスクにしたところヒザが死にかけたため購入。
  • 高さ 72cm のキャビネットに乗せて使用。キズ防止のため緩衝材として同梱されていた厚さ 2cm ほどの発泡スチロールを噛ませて設置。
  • 本体重量 14.2kg で成人男性なら一人で設置可能。
  • ディスプレイ一枚とラップトップをぎりぎり横に並べられる。
  • ガス式で無段階調整可能。右手側のレバーを握り込んで上げ下げする。
  • ガス圧は強めで天板に何も乗せていないとレバーを握っただけで力強く上がる。ディスプレイやラップトップなど一式を乗せるとレバーを握っただけでは上がらず、自分で軽く押し上げてやる必要がある。
  • 上限 505mm まで上げると立ったときにキーボードトレーの位置がいい感じ (身長 184cm の場合)
  • 下限 120mm まで下げると座ったときにキーボードトレーの位置がいい感じ。キーボードトレーが前に迫り出してくれるのでイスに座ってもヒザが少しキャビネットに当たる程度。
  • 本体、キーボードトレーともに剛性は必要十分という印象。平穏な気持ちでタイプするぶんには問題なく、感情が高ぶってくると多少揺れる。
  • 一週間程度使った感想としてはとてもいい。基本的に立って使っていて、気分や疲労に応じて小まめに上げ下げして使っている。
  • 参考価格 ¥18,700 が ¥14,236 にディスカウントされている。費用対効果を考えるといい買い物だったと思う。

エレコム 電源タップ 3ピン マグネット付 4個口 2.5m ホワイト T-T1B-3425WH

  • USB Type-C ハブのコンセントが 3 ピンで自宅にあった電源タップが使用できなかったため購入。
  • 下記ラップトップスタンドと併せて購入し総額 ¥2,000 超としたところラッシュ便を指定することができた。06:00 頃に注文して当日 15:00 頃に配達された。

NEXSTANDノートPCスタンド ノートパソコン PCホルダー 折り畳み式 放熱 軽量 携帯便利 高さ 角度 8段階調整可能 肩こり腰痛対策 Macbook ノートPCスタンド 正規品

  • ラップトップを直接デスクに置くと視線が下がって首が死ぬ。
  • 在宅勤務とは直接的に無関係だが、いい機会なので購入。
  • Roost が先駆けらしいが値段の桁が違うので断念
  • 本体はかなり軽い。
  • ラップトップを乗せると乗せるとしっかり安定する。基本的に外付けキーボードを使っているが、たまにラップトップのキーボードをタイプしてもまったく問題ない。
  • ¥2,980 で購入。こちらも費用対効果を考えるといい買い物だったと思う。

日経コンピュータ 2019 年 9 月 5 日号を読んだ

以下の内容だけ読んだけど多分すぐに忘れるので思ったことをメモ。

特集 みずほ3度目の正直
・みずほ3度目の正直 ついに崖越え、勘定系再構築の全貌(026p)
スカイツリー7本分 30年ぶりの全面刷新(028p)
バッチ処理を解体 みずほSOAの全貌(032p)
・最大8000人が連携 品質確保に悪戦苦闘(038p)
・緊張と重圧の1年間 20年の悲願ようやく(046p)
みずほフィナンシャルグループ 社長 坂井 辰史 氏(052p)
緊急版 動かないコンピュータ
・米アマゾン ・ ウェブ ・ サービス
AWSが6時間停止、30社超に影響 バグで空調が止まりオーバーヒート招く(006p)

きっかけはツイッター

緊急版 動かないコンピュータ

米アマゾン ・ ウェブ ・ サービス

  • AWSが6時間停止、30社超に影響 バグで空調が止まりオーバーヒート招く(006p)

ネットで入手できる以上の情報はなく、冊子としてまとまっていることに価値があるという印象。

以下に引用した通り RDS が PaaS と表記されており、ちょっと違うかなと思った。

PaaS (プラットフォーム・アズ・ア・サービス) であるリレーショナルデータベース (RDB) サービスの「Amazon RDS」

自分が調べた限りネットの情報ではこのあたりが詳しい。

特集 みずほ3度目の正直

以下のサイトでも会員登録していれば同じ内容を見られるようだけど、自分は会員ではないので分からない。

30年ぶりの全面刷新

  • Q01 結局いくらかかった?
  • Q02 そもそも何をやっていた?
  • Q03 完成まで何年かかった?

景気が良かった頃は 10 年程度でシステム刷新をくり返してきたが 1990 年頃にぱたりと止まり、また合併の際にシステムを片寄せし続けたためにブラックボックスとなっていた。

このままシステムを使い続けることはできず、2025 年までになんとかしなければならないとする "2025 年の崖" という課題があった。構想 20 年、東日本大震災義援金振り込み障害など二度の大規模障害を経て三度目の正直。

総コストは 35 万人月、4000 億円台半ばとのこと。

振り返ってみればコストを削減できたところは多々あるだろうけど、もし仮に半分で済んだとしても、前職では高々数億円規模の案件にしか関わっていない自分には想像もできない規模。

みずほSOAの全貌

  • Q04 「老朽化」問題は解決した?
  • Q05 二重引き落としは再発しない?
  • Q06 メインフレームはなくなった?

ハブ & スポーク型の SOA を採用。

取引メイン、流動性預金、内国為替取引はメインフレーム、SAIL なるミドルウェアCOBOL で構築しており、その他は LinuxJava で構築。メインフレームは 19 台から 4 台に集約とのこと。

メインフレームCOBOL と聞くと真っ先にレガシーという言葉を思い浮かべてしまい、脊髄反射的に関わりたくないと思ってしまうが実際のところはどうなんだろう。

ざっと調べた限りではメインフレームCOBOL には二進化十進法による誤差のない計算と、高速/高並列処理に利点があるらしい。

海外の金融システムがどのような事情になっているのか気になって調べてみたけど、日本語で検索したためか有用な情報は得られなかった。

最大8000人が連携

  • Q07 参加ベンダーは何社?
  • Q08 本当に新規開発した?
  • Q09 プロジェクトはどう管理した?
  • Q10 稼働を 2 度延期、本当の理由は?
  • Q11 開発拠点はいくつあった?

主要 4 ベンダーは富士通日立製作所、日本 IBM および NTT データで、トップマネジメント定例メンバー 16 社のうちアプリケーション開発ベンダー 5 社として前職の社名が掲載されていた。

1 次委託先 70~80 社、2/3 次委託先として 900 社強とのこと。

いわゆる多重下請け構造であり、幸か不幸か金融案件に関わったことがないものの前職に身を置いていたものとして、どのように工程管理されていたか想像がつく。

As-is, いわゆる現行踏襲の要件定義を禁止し、Xupper なるツールで業務フローを描き起こしたという点は興味深かった。自分たちが使うシステムをベンダ任せにせず取り組む良い前例になってほしい。

超高速開発ツールを全面活用して手動コーディングを禁止したという点も興味深かった。当然のことながら不満も出たものの品質確保に貢献し、パフォーマンスにも問題はなかったとのこと。私情を挟むと揺れるところもあるが超大規模開発であれば妥当な判断なのかもしれない。

緊張と重圧の1年間

  • Q12 なぜ 9 回も ATM を止めた?
  • Q13 移行失敗をなぜ回避できた?
  • Q14 1 万 7000 人の操作訓練はどうした?
  • Q15 目に見える成果はあった?
  • Q16 投資回収の見込みは?
  • Q17 経費率はどこまで下がる?
  • Q18 開発力は上がった?

入念に計画した段階リリースと運用訓練によりトラブルなくシステムを移行。

5 年間で 720 億円の費用削減を見込んでおり、SOA 化などにより実際に新規開発コストを削減。

また、社内で益荒男 (ますらお) が育ち、海外の大規模開発などで一騎当千の活躍をしているとのこと。

プロジェクトマネジメントなど抽象度の高いタスクに取り組んでいたエンジニアには得難い経験になったことと思う。ぜひ超大規模案件における知見を活用して活躍してほしい。

設計や実装など具体的なタスクに取り組んでいたエンジニアも、もし赤や緑の類似案件があった際には引っ張りだこになるといいなと思う。

進退かけて指揮した

  • Q19 インタビュー「経営責任」果たせたか?
  • Q20 「3 度目」は起こらない?

2018-01-15 にみずほ証券社長からみずほフィナンシャルグループ社長に抜擢された坂井辰史氏のインタビュー。

社長になるのは自分の首を洗っておくこと、という言葉が印象深かった。

IT 人材のビジネスリテラシーが高くないとも仰っており気になったが、インタビュー記事では深掘りされておらず具体的にどのような課題なのか分からなかった。

感想

大変な規模の案件を、従来の多重下請け構造と一部にレガシーなメインフレームCOBOL を残した SOA で実現したと理解した。

他に類を見ない事例であることは間違いなく、関わったエンジニアのみなさんにはお疲れさまでしたという気持ちと共に、貴重な経験を活かして今後も活躍してほしいと思う一方、この事例がエンジニアにとって未来の希望や発奮材料になり得るかと言うと、ちょっと厳しいかなーという印象。

とにかくレガシーというイメージがよくない。

古くからあるものが再評価されて名前を変えてエンジニアに受け入れられた事例は多いし、マイクロサービスも SOA の再発見と言えないこともないと思うので、メインフレームCOBOL も少しいじって名前を変えるだけでずいぶん状況が変わるのではないだろうか。

メインフレームはなんかすごい速いすごいマシンということにすればよいし、そもそも開発終盤まで意識することは少ないと思うので影響は小さいはず。

COBOL の採用理由が二進化十進法による誤差のない計算にあるのであれば、その機能を持つモダンなプログラミング言語を開発してしまえばいいのではないかと思った。

きちんとコンピュータサイエンスを履修していない素人の妄想に過ぎないけど、Go や Swift などを思い返すと自分たちのシステムを支えるプログラミング言語そのものを開発するという発想は特にクレイジーではないし、4000 億円の 1% でも投入すれば意外となんとかなったりしないだろうか。

モダンなプログラミング言語で最高のパフォーマンスとセキュリティを求められる超大規模開発と聞けば、腕が鳴るというエンジニアは少なくないように思うし、そこに名乗りを上げるエンジニアにはそれなりに期待して良いように思った。

Amazon Linux 2 で X-Ray デーモンを build する

基本的な手順は README に書いてあるけど Go 弱者で何度やっても GOPATH 辺りの内容を忘れるので手順をメモ。

当時の関連するツイート。 ghq と相性が悪いので go 関連のリポジトリは自前で git clone すると良さそう。

手順

Amazon Linux 2 に SSH ログインしたら go 1.11 をインストールして GOPATH を設定。 今回は ~/repo/go を GOPATH にしてみた。

[ec2-user@ip-172-31-17-41 ~]$ sudo amazon-linux-extras install -y golang1.11
...
[ec2-user@ip-172-31-17-41 ~]$ go version
go version go1.11.13 linux/amd64

[ec2-user@ip-172-31-17-41 ~]$ mkdir -p ~/repo/go/src ~/repo/go/bin
[ec2-user@ip-172-31-17-41 ~]$ echo 'export GOPATH=~/repo/go' >> ~/.bash_profile 
[ec2-user@ip-172-31-17-41 ~]$ echo 'export PATH=$GOPATH/bin:$PATH' >> ~/.bash_profile 
[ec2-user@ip-172-31-17-41 ~]$ source ~/.bash_profile

X-Ray デーモンは依存性の解決に Glide を使っているのでインストールする。

[ec2-user@ip-172-31-17-41 ~]$ curl https://glide.sh/get | sh
...
glide version v0.13.3 installed successfully

GOPATH 配下に github.com/aws ディレクトリを作って x-ray-daemon を clone する。

[ec2-user@ip-172-31-17-41 ~]$ mkdir -p ~/repo/go/src/github.com/aws
[ec2-user@ip-172-31-17-41 ~]$ cd ~/repo/go/src/github.com/aws/
[ec2-user@ip-172-31-17-41 aws]$ git clone https://github.com/aws/aws-xray-daemon.git
...

glide install して make build-linux する。

[ec2-user@ip-172-31-17-41 aws]$ cd aws-xray-daemon/
[ec2-user@ip-172-31-17-41 aws-xray-daemon]$ glide install
...
[INFO]  Replacing existing vendor dependencies
[ec2-user@ip-172-31-17-41 aws-xray-daemon]$ make build-linux
Build for Linux amd64
GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o /home/ec2-user/repo/go/src/github.com/aws/aws-xray-daemon/build/xray/xray ./daemon/daemon.go ./daemon/tracing.go

build/xray/ にバイナリがビルドされるのでリージョンを指定して起動する。 オプションの詳細はドキュメントを参照。

[ec2-user@ip-172-31-17-41 aws-xray-daemon]$ ls -la build/xray/
...
-rwxrwxr-x 1 ec2-user ec2-user 9493024 Sep 28 22:11 xray
[ec2-user@ip-172-31-17-41 aws-xray-daemon]$ ./build/xray/xray -n ap-northeast-1
2019-09-28T22:12:28Z [Info] Initializing AWS X-Ray daemon 3.1.0
2019-09-28T22:12:28Z [Info] Using buffer memory limit of 9 MB
2019-09-28T22:12:28Z [Info] 144 segment buffers allocated
2019-09-28T22:12:28Z [Info] Using region: ap-northeast-1
2019-09-28T22:12:28Z [Info] HTTP Proxy server using X-Ray Endpoint : https://xray.ap-northeast-1.amazonaws.com
2019-09-28T22:12:28Z [Info] Starting proxy http server on 127.0.0.1:2000

なにか間違っていたら教えてください。

App Mesh と ECS のサンプルを試したら CloudFormation とシェルスクリプトや jq の知見が詰まっていて X-Ray も付いてきた話

Medium 記事にもなっている AWS App Mesh のサンプルを試してみたらいい内容だったので、備忘も兼ねて一年半ぶりにブログを書いてみます。

TL; DR

  • App Mesh のサンプルに多い EKS ではなく ECS
  • App Mesh だけでなく CloudFormation やシェルスクリプト、jq の使い方も学べる
  • X-Ray も学べる

以下、サンプルの内容に沿って紹介します。

Prerequisites

サンプルを試す前提条件は以下の通りです。

  • AWS CLI 1.16.124 以上をインストールしている
  • AWS CLI を default または名前付きのプロファイルで適切に設定している
  • EC2 インスタンスにログインする SSH キーペアを作っている
  • github.com/aws/aws-app-mesh-examples リポジトリをクローンしている
  • jq をインストールしている

Create the VPC and other core Infrastructure

まず以下の環境変数を指定してシェルスクリプトを実行し CloudFormation で VPC とサブネットを作るところから始めます。

  • AWS_PROFILE: AWS CLI のプロファイル
  • AWS_DEFAULT_REGION: リージョン
  • ENVIRONMENT_NAME: デモに使う環境の名前

このシェルスクリプトは基本的に aws cloudformation deploy を実行しているだけで難しいことはしていません。

#!/bin/bash

set -ex

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-vpc" \
    --capabilities CAPABILITY_IAM \
    --template-file "${DIR}/vpc.yaml" \
    --parameter-overrides \
    EnvironmentName="${ENVIRONMENT_NAME}"

ここで使っている CloudFormation テンプレートには、知っている人には当たり前でも知らない人やどう書いたらいいか迷っている人の参考になる知見が詰まっています。

例えば !Select!GetAZsアベイラビリティゾーンを指定したり、!Join ではなく !Sub と変数で文字列を組み上げたり

  PublicSubnet1: 
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      CidrBlock: !Ref PublicSubnet1CIDR
      MapPublicIpOnLaunch: true
      Tags: 
        - Key: Name 
          Value: !Sub ${EnvironmentName} Public Subnet (AZ1)

!DependsOn で依存するリソースの作成順序を制御したり

  NatGateway1EIP:
    Type: AWS::EC2::EIP
    DependsOn: InternetGatewayAttachment
    Properties: 
      Domain: vpc

!GetAtt で作成したリソースの属性を参照する方法も、通常はトライアンドエラーで覚えるものなので、このようなサンプルでショートカットして学べるのはとてもいいと思います。

  NatGateway1: 
    Type: AWS::EC2::NatGateway
    Properties: 
      AllocationId: !GetAtt NatGateway1EIP.AllocationId
      SubnetId: !Ref PublicSubnet1

クロススタック参照する Outputs の名前の付け方も地味に悩むので参考になります。

Outputs: 

  VPC: 
    Description: A reference to the created VPC
    Value: !Ref VPC
    Export: 
      Name: !Sub "${EnvironmentName}:VPC"

Create an App Mesh

先ほどと同様に環境変数に App Mesh の名前を指定してシェルスクリプトを実行します。

  • MESH_NAME: App Mesh の名前

ここでは AWS::AppMesh::Mesh リソースを作っているだけです。

Create compute resources

続いて ECS クラスターを作ります。

サービスディスカバリで使う Route 53 プライベートホストゾーンもここで作るので環境変数に指定します。

コンテナインスタンスは AutoScaling グループでプライベートサブネットに作成されますが、パブリックサブネットに踏み台インスタンスも作成されるので SSH キーペアも指定します。

  • SERVICES_DOMAIN: プライベートホストゾーン名
  • KEY_PAIR_NAME: SSH キーペア名

シェルスクリプトはこれまでと同じで CloudFormation スタックを作るだけです。

ここで使う CloudFormation テンプレートも参考になります。

コンテナインスタンスと踏み台インスタンスに使う AMI ID はパラメータストアから取得することができます。

  ECSAmi:
    Description: ECS AMI ID
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ecs/optimized-ami/amazon-linux/recommended/image_id"

  EC2Ami:
    Description: EC2 AMI ID
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"

Fn::ImportValue!Sub でクロススタック参照したり

  ECSInstancesSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties: 
      GroupDescription: "Security group for the instances"
      VpcId:
        'Fn::ImportValue': !Sub "${EnvironmentName}:VPC"
...

AutoScalingGroup の UpdatePolicy 属性 もちゃんと指定しています。

  ECSAutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
...
    UpdatePolicy:
      AutoScalingRollingUpdate:
        MinInstancesInService: 1
        MaxBatchSize: 1
        PauseTime: PT15M
        SuspendProcesses:
          - HealthCheck
          - ReplaceUnhealthy
          - AZRebalance
          - AlarmNotification
          - ScheduledActions
      WaitOnResourceSignals: true

UserData で SSM エージェントをインストールしているので、コンテナインスタンスにセッションマネージャで接続することもできます。

  ECSLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
...
      UserData:
        "Fn::Base64": !Sub |
          #!/bin/bash
          yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
          yum install -y aws-cfn-bootstrap hibagent
          /opt/aws/bin/cfn-init -v --region ${AWS::Region} --stack ${AWS::StackName} --resource ECSLaunchConfiguration
          /opt/aws/bin/cfn-signal -e $? --region ${AWS::Region} --stack ${AWS::StackName} --resource ECSAutoScalingGroup
          /usr/bin/enable-ec2-spot-hibernation

UserData で指定するには複雑過ぎる設定は AWS::CloudFormation::Init リソースを使って指定します。

    Metadata:
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              awslogs: []

          commands:
            01_add_instance_to_cluster:
              command: !Sub echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config
          files:
            "/etc/cfn/cfn-hup.conf":
              mode: 000400
              owner: root
              group: root
...

Configure App Mesh resources

いよいよ本命の App Mesh を作ります。

シェルスクリプトはこれまでと同様で、

CloudFormation テンプレートで VirtualNode, VirtualRouter, Route, VirtualService を作ります。

バーチャルバーチャル言ってて何のこっちゃ分からんという感情が先行しますが、雰囲気が掴めてくるとたしかに仮想的なノードと、それに対するルートを提供するサービスだなあという気もしてきます。

自分はブログ記事 "Learning AWS App Mesh" の "DJ App revisited" の辺りを読んで腑に落ちた感じがしたので、もし未読の方は一読されるといいかもしれません。

Deploy services to ECS

ここまででネットワークインフラを作って ECS クラスタを作って App Mesh を作ったので、最後に実際に ECS サービスをデプロイします。

Deploy images to ECR for your account

まず AWS CLI で ECR を作ってコンテナイメージを push します。

これまでのシェルスクリプトとは毛色が違いますが、基本的に docker build して作った ECR に push しているだけです。

#!/usr/bin/env bash
# vim:syn=sh:ts=4:sw=4:et:ai

set -ex

if [ -z $COLOR_GATEWAY_IMAGE ]; then
    echo "COLOR_GATEWAY_IMAGE environment variable is not set"
    exit 1
fi

# build
docker build -t $COLOR_GATEWAY_IMAGE .

# push
if [ -z $AWS_PROFILE  ]; then
    $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
else
    $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION --profile $AWS_PROFILE)
fi
docker push $COLOR_GATEWAY_IMAGE

Dockerfile では真面目にマルチステージビルドしています。

FROM golang:1.10 AS builder

# Download and install the latest release of dep
ADD https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 /usr/bin/dep
RUN chmod +x /usr/bin/dep

# Copy the code from the host and compile it
WORKDIR $GOPATH/src/github.com/username/repo
COPY Gopkg.toml Gopkg.lock ./
RUN dep ensure --vendor-only
COPY . ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /app .

FROM scratch
COPY --from=builder /app ./
ENTRYPOINT ["./app"]

バックエンドサービスを build して push するシェルスクリプト、Dockerfile も同じ内容です。

Deploy gateway and colorteller services

環境変数に最新の Envoy コンテナイメージと先ほど ECR に push したコンテナイメージを指定したら、シェルスクリプトを実行して ECS サービスをデプロイします。

  • ENVOY_IMAGE: 最新の Envoy コンテナイメージ。現時点では v1.9.1.0-prod が最新
  • COLOR_GATEWAY_IMAGE: ゲートウェイサービスのコンテナイメージ
  • COLOR_TELLER_IMAGE: バックエンドサービスのコンテナイメージ

シェルスクリプトは今まで変わり映えしないように見えますが、create-task-defs.sh を呼び出している点が異なります。

#!/bin/bash
...
# Creating Task Definitions
source ${DIR}/create-task-defs.sh

aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation deploy \
    --stack-name "${ENVIRONMENT_NAME}-ecs-colorapp" \
...

このシェルスクリプトでは AWS CLI と jq をうまく使ってタスク定義を登録していました。

describe-stacks の結果を jq でパースして必要な値を取得したら

stack_output=$(aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    cloudformation describe-stacks --stack-name "${ENVIRONMENT_NAME}-ecs-cluster" \
    | jq '.Stacks[].Outputs[]')

task_role_arn=($(echo $stack_output \
    | jq -r 'select(.OutputKey == "TaskIamRoleArn") | .OutputValue'))

execution_role_arn=($(echo $stack_output \
    | jq -r 'select(.OutputKey == "TaskExecutionIamRoleArn") | .OutputValue'))
...

やはり jq の -f オプションで読み込んだテンプレートファイルに --arg--argjson オプションで変数の値を渡してタスク定義の入力となる JSON 文字列を組み上げ、AWS CLI でタスク定義を登録しています。

generate_color_teller_task_def() {
    color=$1
    task_def_json=$(jq -n \
    --arg NAME "$ENVIRONMENT_NAME-ColorTeller-${color}" \
    --arg STAGE "$APPMESH_STAGE" \
    --arg COLOR "${color}" \
    --arg APP_IMAGE $COLOR_TELLER_IMAGE \
    --arg AWS_REGION $AWS_DEFAULT_REGION \
    --arg ECS_SERVICE_LOG_GROUP $ecs_service_log_group \
    --arg AWS_LOG_STREAM_PREFIX_APP "colorteller-${color}-app" \
    --arg TASK_ROLE_ARN $task_role_arn \
    --arg EXECUTION_ROLE_ARN $execution_role_arn \
    --argjson ENVOY_CONTAINER_JSON "${envoy_container_json}" \
    --argjson XRAY_CONTAINER_JSON "${xray_container_json}" \
    -f "${DIR}/colorteller-base-task-def.json")
    task_def=$(aws --profile "${AWS_PROFILE}" --region "${AWS_DEFAULT_REGION}" \
    ecs register-task-definition \
    --cli-input-json "$task_def_json")
}

CloudFormation テンプレートでは登録したタスク定義を使用するサービスおよびサービスディスカバリレコード、そしてゲートウェイサービスにリクエストをフォワードする ALB を作ります。

その他にテスト用と思われるサービスやサービスディスカバリレコードも作っていますが本質ではないので割愛。

作成した ALB のエンドポイントに curl でリクエストを送ると App Mesh によってルーティングされたいずれかの ECS サービスから応答が得られます。

$ colorapp=$(aws cloudformation describe-stacks --stack-name=$ENVIRONMENT_NAME-ecs-colorapp --query="Stacks[0
].Outputs[?OutputKey=='ColorAppEndpoint'].OutputValue" --output=text); echo $colorapp
http://DEMO-Publi-M7WJ5RU13M0T-553915040.us-west-2.elb.amazonaws.com

$ curl $colorapp/color
{"color":"red", "stats": {"red":1}}

Shape traffic

Apply traffic rules

作成した CloudFormation スタックに含まれる AWS::AppMesh::Route リソースの WeightedTargets を変更して CloudFormation スタックを更新することで、App Mesh のルーティング情報を変更できます。

また、App Mesh コンソールで対象の Virtual routes を Edit して Virtual nodes の Weight を変更することでもルーティング情報を変更できます。

Monitor with AWS X-Ray

Envoy コンテナで X-Ray 統合が有効に設定されていて、かつ各サービス内で稼働する Go アプリケーションにも X-Ray SDK が設定されているので、X-Ray サービスマップからVirtualNode を経由して各アプリケーションにアクセスしている様子を確認できます。

各トレースをドリルダウンすることで詳細な内訳を確認できます。

まとめ

ちょっと App Mesh やってみようかなと軽い気持ちで手を出したサンプルから予想を大きく上回る収穫が得られて満足です。気になった方は是非お試しください。

15 年勤めた SIer を辞めて外資系企業に転職した話

この記事は 退職者その2 Advent Calendar 2017 の二日目です。

adventar.org

おことわり

現職に就いて間もない試用期間中の身であるため、現職に関しては表面的な内容しか書けません。

そのため、「なぜ現職に就いたのか」というポジティブな側面よりも「なぜ前職を辞めたのか」というネガティブな側面を強く感じられる方がいらっしゃるかもしれませんが、いわゆる一身上の都合であり、前職や SIer というビジネスを否定するものではありません。

予めご了承ください。

前職について

大手と言って差し支えない規模の SIer に新卒として入社して 15 年と 1 ヶ月間、システムエンジニアとして勤めました。

Java 言語を使った Web アプリケショーン開発を多く担当し、直近の数年間は Hadoop, Azure, AWS なども経験できました。中国やタイへの出張、社内勉強会の開催など、システム開発以外にも多くの経験を積ませて頂きました。

大規模企業としての安定感は抜群で、業界平均以上の待遇に加えて技術職への理解と手当てもある良い企業でした。

お世話になった方々にこの場を借りて改めて御礼を申し上げます。本当にありがとうございました。

転職の動機

瑣末な理由も当然いくつかあったものの、次の二点が大きな理由でした。

  • 家族が増えた
  • 組織に広く貢献したくなった

それぞれ微妙に関連しますが、以下、個別に詳述します。

家族が増えた

今年で五歳になる娘が家族に加わってから、生活が一変しました。

個人という観点では見るもの聞くものすべてが新鮮で、目まぐるしくも充実した日々ですが、会社員という観点では単純に労働時間が減りました。

前職では準委任契約という形態でお客様先に常駐してお仕事させて頂く機会が多くありましたが、この契約は大雑把に言うと労働時間に対して対価を頂く内容であり、労働時間の減少は売上に影響します。

個人の事情を相互にフォローするのが組織ですし、お客様も含め現場の方々は理解を示してくださいましたが、ビジネスモデルとライフスタイルのミスマッチが根本的に解消されるわけではありませんでした。

組織に広く貢献したくなった

会社員として経験を積むにつれて、関心の対象が個人からチーム、組織へと移っていきました。

最初の五年間は個人として技術を身に付けることに夢中で、チームや組織のことは考えもしませんでした。

次の五年間はチームリーダーとして案件を成功させるために躍起になっていましたが、リーダー以前に個人としてあまりにも未熟で、メンバーに迷惑をかけてばかりでした。

そして、チームリーダーとして少しずつ上手く立ち回れるようになった最後の五年間は、自分が身に付けたことを他のチームや部署にも展開したい、自分の価値をスケールしたいと考えるようになりました。

そこで R&D 等を担当する部署への異動を希望しましたが、(ありがたいことに) 自分を必要としてくれる現場もあってなかなか認められず、仕方なく社内 SNS に技術情報を展開したり、社内勉強会を開催したりなど試みるものの、組織に広く貢献できているという実感を強く得ることはできませんでした。

転職の契機

今年の三月に念願が叶って R&D 等を担当する部署へ異動した数ヶ月後、現職よりスカウトのメールを頂きました。

登壇資料やブログを見てお声掛け頂いたとのことで、拙いながらも情報発信を続けていてよかったと思います。また LinkedIn もご覧になったとのことで、外資系企業らしいとも思いました。

当初は異動したばかりということもあり転職するつもりはありませんでしたが、他の企業がどのようにビジネスをしているのか、エンジニアがその中でどのように活躍しているのかなど、お話を聞きたいと思って面接を受けることにしました。

その面接で、現職には以下のような特徴があることを理解しました。

  • エンジニアが能力を発揮して短時間で問題を解決することが組織への貢献となること
  • 常に新しい技術を学び続けることが求められること

本質的ではありませんが、日常的に英語に触れる機会があることにも魅力を感じ、この企業で働きたいと思うようになりました。

転職した感想

前述の通り試用期間中であるため表面的ではありますが、実際に転職した感想を以下に列挙します。

エンジニアの質が高い

技術力が高いのはもちろんですが、強い言葉やネガティブな言葉を使うエンジニアがいません。みなさんコミュニケーション能力が高く、ポジティブで親切です。

企業文化がきちんと浸透していて、人間的にとても洗練されています。

オフィスが快適

広いデスクにラップトップとサブディスプレイを二枚貸与して頂いています。ラップトップは Win/Mac, JIS/US キーボードから選べて、自分は JIS キーボードの MacBook Pro を使っています。

服装規定は一切ありません。コーヒーなどの簡易な飲み物は無料です。人によって好みがあるかと思いますが、オフィスがとても静かなのも個人的には快適です。

なお、自宅で働いている人も多いです。

トレーニングが充実

入社してから一ヶ月経ちますが、ひたすらトレーニングしています。e ラーニングとエキスパートによるラボトレーニングの予定がびっしりで、トレーニングにここまでコストをかけてくれるのかと驚きました。

トレーニングした内容よりも更に深く知りたい場合は、社内 Wiki に大量の情報が蓄積されています。

英語が身近

会話は日本語ですが、上記トレーニング教材や Wiki はほとんど英語です。

今はまだ読むだけですが、トレーニングを終えて実務に移ると海外のエンジニアとメールでやり取りする機会もあるそうですし、エキスパートは海外出張の機会も多いようです。海外へ転籍していく方も多いです。

最後に

転職して本当によかったと思います。

単純に環境や待遇が改善されたこともありますが、仕事のこと、家族のこと、自分のことを改めて考え直して行動したこと、また実際にまったく違う世界を目の当たりにしたことで、視野が広がり、人間的に幅が出たように感じます。

今はまだ組織にぶら下がっているだけの新人ですが、一日でも早く成長して組織に貢献していきたいと思います。

JJUG CCC 2017 Fall に登壇しました #jjug_ccc #ccc_a1

JJUG CCC でお話ししてきました!

www.java-users.jp

2017 Spring に続いて二回目。前回よりはリラックスできたかなー。

発表資料はこちら。

p キーを押すとスピーカーノートが表示されます。当日はピンマイクでうろうろしながらスピーカーノートを見ずにお話ししたので、お伝えし忘れたことがぽろぽろありました。反省。

資料中で紹介している gradle プロジェクトも以下にアップロードしました。

github.com

登壇の経緯

業務ドキュメントの作成について、以下のような課題を感じていました。

  • バイナリフォーマットとバージョン管理ツールの相性が悪い
  • いつ、なにを、どのように書けばよいのか、いまいちよく分からない
  • レビューがうまく機能していない気がする

いつ、なにを書くべきなのかについては、システムエンジニア Advent Calendar 2016 に書きました。

この頃は Markdown でドキュメントを書けないかと考えていたのですが、その後に参画した案件で採用した AsciiDoc と PlantUML に手応えを感じたので、この成果を共有したいと考え、関係各位の了承を得た上で CfP に応募しました。

KPT

以下、振り返り。

Ask the Speaker

以下、登壇後に頂いたご質問など。

日本語でセクションタイトルを書いても自動生成される id は問題ないか

実際の案件でも日本語でセクションタイトルを書きましたが、特にハマったことはないです。自動生成 id でハマったのは以下の二件。

  • 予期しない記号がアンダースコアに置き換えられた
  • セクションタイトルが重複して連番が付与された

いずれもビルド後の HTML ソースから自動生成された id を確認して解決しました。事前にカスタム id の付与ルールを検討するのもよいと思います。

Table セルを改行して記述した場合、列数はどのように判定されるのか

|A |B |C |D と書けば 1 行 4 列であることは明白ですが、B や C の後に改行すると列数が分からなくなるのでは?という鋭いご質問ですね。

[cols="xx,yy,zz"] のように明示しない場合、一行目の列数で判定されるようです。

実際の案件では以下のルールで記述しました。

  • [cols="xx,yy,zz", options="header"] の指定必須
  • 列ごとに改行
  • 行ごとに空行を挿入

GitLab CI を使えば Jenkins は不要では?

GitLab CI が登場するより前から利用している docker-compose を再利用したため、GitLab と Jenkins を組み合わせて利用しています。

新規に構築する場合は GitLab CI でもよいと思います。

まとめ

今回も登壇駆動勉強が捗りました...

また、資料を書き進めていくにつれて「あのときこういう言い方をしたからみんな受け入れてくれたんだなー」という気付きを得られたのが個人的に大きな収穫でした。

拝聴した各セッションや全体の感想は別途投稿します。

朝一番のセッションにも関わらずお越しいただいた方々、スタッフの方々、某案件でお世話になった方々、お忙しい中レビューしてくださったくらもとパイセン、本当にありがとうございました!

babun に awscli をインストールする

お仕事で AWS を使い始めたので、コマンドラインから AWS のサービスを操作する AWS Command Line Interface (AWS CLI) をインストールしてみた。

OS ネイティブなターミナルを使っている場合は AWS Command Line Interface のインストール やネットに手順が載っているので、それらを参照すればよいですが、自分は大人の事情で Windows7 上で Babun を使っており、ここに AWS CLI をインストールしたので手順をメモっておきます。

pip のインストー

AWS CLIPython 製のようで、Pyhon のパッケージ管理システムである pip を使ってインストールできるとのこと。

Babun にはデフォルトで Python は入っているものの、pip は入っていないので、まず pip をインストールする必要がある。

$ which pip
pip not found

で、pip は python-setuptools に含まれる easy_install でインストールするらしく、この python-setuptools は Babun のパッケージ管理システムである pact でインストールできる。

$ pact find python-setuptools
(snip)
Searching for installed packages matching python-setuptools:

Searching for installable packages matching python-setuptools:
python-setuptools

$ pact install python-setuptools
(snip)
Package python-setuptools installed

自分の環境では末尾に Python のバージョン番号が付与された状態で easy_install がインストールされた。

$ which easy_install-2.7
/usr/bin/easy_install-2.7

このままでは扱いづらいのでエイリアスを設定する。

$ echo "alias easy_install='easy_install-2.7'" >> ~/.zshrc

$ tail -5 ~/.zshrc
#
# Example aliases
# alias zshconfig="mate ~/.zshrc"
# alias ohmyzsh="mate ~/.oh-my-zsh"
alias easy_install='easy_install-2.7'

$ source ~/.zshrc

$ which easy_install
easy_install: aliased to easy_install-2.7

$ easy_install --version
setuptools 34.3.2 from /usr/lib/python2.7/site-packages (Python 2.7)

easy_install で pip をインストールする。

$ easy_install pip
(snip)
Installed /usr/lib/python2.7/site-packages/pip-9.0.1-py2.7.egg
Processing dependencies for pip
Finished processing dependencies for pip

$ pip --version
pip 9.0.1 from /usr/lib/python2.7/site-packages/pip-9.0.1-py2.7.egg (python 2.7)

awscli のインストー

これでようやくお目当ての AWS CLI をインストールできる。

$ pip install awscli
(snip)
Successfully installed PyYAML-3.12 awscli-1.11.123 botocore-1.5.86 colorama-0.3.7 docutils-0.13.1 futures-3.1.1 jmespath-0.9.3 pyasn1-0.2.3 python-dateutil-2.6.1 rsa-3.4.2 s3transfer-0.1.10

$ aws --version
aws-cli/1.11.123 Python/2.7.13 CYGWIN_NT-6.1-WOW/2.8.0(0.309/5/3) botocore/1.5.86

AWS クレデンシャルの設定

AWS に接続するためのクレデンシャル情報を以下のように設定する。

$ cat ~/.aws/credentials
[default]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXX

AWS CLI を使う

とりあえず S3 の中を見てみる。

$ aws s3 ls
2017-02-10 19:22:15 XXXXXXXXXXXXXXXXXXXX
2017-01-25 13:40:08 XXXXXXXXXXXXXXXXXXXX
2016-11-30 14:46:51 XXXXXXXXXXXXXXXXXXXX

hadoop fs ls のように結果が返ってくるまで突っかかる感じはあるものの、無事に S3 の中身が見られた。