Happy Growth Engineer

成長と幸せな働き方の両立をするために役に立つ

【CTO of the year 2018:株式会社空】次回以降の CTO of the year 登壇者の方へ参考までに

昨年(2018年11月21日)に CTO of the year 登壇させていただいて、技術的な強み・CTO(CPO)としての価値を整理する良い機会でした。 受賞に至ることはありませんでしたが、登壇資料の作成で悩みポイントをあげつつ、実施したことを共有します。 また今後、CTO of the yearに登壇される方々へ参考にしてもらえればと思います。

CTO of the year 2018の登壇者が決定!TC Tokyo Startup Battle卒業生も参加 https://jp.techcrunch.com/2018/11/07/cto-of-the-year-2018-2/

CTO of the year 2018にはatama plus川原氏を選出 https://jp.techcrunch.com/2018/12/05/cto-of-the-year-2018-atama-plus/

個人的に写真で振り返る CTO of the year 2018 @ AWS Loft Tokyo https://shinodogg.com/?p=7898

プレゼン資料

SlideShareにアップしておきました。 ※一部写真は省きました

悩みポイント

  • 特許出願していること強みは明確にわかるけど、全体から見て技術的な強みは何なのか
  • 個人的な CTO(CPO)としての価値は何なのか

この2点が曖昧で、資料作成に躊躇していました。

社内全員にアンケート

悩みポイントを解消するため、

  • プロダクト開発の強みは?
  • プロダクトとして優れている技術は?
  • 開発チームとして良かったと思う施策は?
  • 田仲(私自身)の強み・弱みは?

を社内全員にアンケートに答えてもらうことから初めて、悩みポイントをクリアにする。

技術的な強みの明確化

どのような顧客価値を提供しているのかを考え、技術を組織能力も含めて、技術的な強みと定義しました。 その後、特許出願・具体的な数値改善・社内アンケートから顧客価値を発揮している技術的な強みを明確にしました。

技術的な強みは

  • シンプルな UI/UX
  • 統計学を用いたデータ分析手法
  • 問題解決に取り組む体制

の3点により、顧客価値を提供することが技術的な強みであるとしました。

具体的な数値改善の例

お客様の声から、売り上げが15%上がった・料金調整にかかる時間が2分の1になったなど

www.hotelbanzuke.com

技術的な強みにCTO(CPO)として貢献しているところ

主に、貢献しているところは、

  • 「問題解決に取り組む体制」
  • フロントエンド・バックエンドによるつなぎこみ:サービス提供する上では、「シンプルな UI/UX」と「統計学を用いたデータ分析手法」だけでは成り立たず、その間を担当

の2点でした。

問題解決に取り組む体制については、スクラムチームを組むことや、採用の一貫を担うことなど、随時取り組んでいましたが、 プレゼンで話すことは、組織よりもテクノロジーな話を選択するため、フロントエンド・バックエンドによるつなぎこみを多岐に渡って行っていることを話すことにしました。

テクノロジー周りは、実施して来た事例を掲載しました。

登壇で話したかったことを掲載

※ 登壇の途中でうまく話すことができなかったので、原稿に近い内容スライド単位で記しておきます。

プロダクトから顧客や様々な職種へ

エンジニアとしての私は、 学生時代は、パケットの解析をし、セキュリティを学んでいました。最初に入社したヤフーでは、Adtechの部署で、フロントエンド〜インフラまで経験しました。 その経験を活かし、プロダクトを通じて顧客や様々な職種へ貢献するCPOです。

Chief Production Officer

空では、Cheif Production Officerとして、プロダクトから顧客価値を作っています。 技術からの課題解決だけではなく、ビジネスチームとのコミュニケーションにより、プロダクト価値があるのかも判断しています。現在はCTOとしての責務も担いつつ、プロダクト全ての責任を持っています。

Price Tech Company

そのプロダクトのMissionは、PriceTechです。 売り手も買い手もWin-Winになれる価格決めに支援できる会社を目指しています。

ホテル業界の課題

まずはホテル業界の課題解決です。 料金設定には、調査や分析に多くの時間を使っていることや経験とカンによる属人化されていること。手間と精度に課題があります。

課題解決のためのサービス

課題解決のために2つのサービスを提供しています。 調査や分析にかかる時間を軽減するホテル番付。 経験とカンによる属人化をなくすMagicPrice。 2つを提供しています

MagicPrice / ホテル番付 システム構成図

システム構成図です。 ホテルのニーズによって、ホテル番付かMagicPriceか、手段を変更する可能性があるため、分析悔過のデータを共通基盤で持つようにしています。

MagicPrice / ホテル番付 システム構成図 2

分析の元データは、 市場に出ているデータ ホテルが持っている予約台帳 を元に分析しています。

技術的な強み

技術的な強みです。 統計学を用いたデータ分析手法から結果を出し、シンプルなユーザ体験を提供することで、顧客満足度90%を獲得しています。 また、顧客満足度を高めるために価値を継続的に届けることは大事です。 ビジネス・エンジニアが一体となって顧客への問題解決に取り組み、週1回リリースを行なっていることも要因にもなっています。

顧客価値への重要要素

技術的な強みからもわかるように、弊社は、デザインとデータサイエンスが重要要素になっています。

開発者として顧客価値への貢献

私は、開発者として、デザインやデータサイエンスではなく、フロントエンド・バックエンド・インフラから貢献し、橋渡しを行なっています。

2つの視点から貢献

経営・マネジメント・開発者の視点から、色々な職種に対して貢献していってます。

セールス・カスタマーサクセス

セールス・カスタマーサクセスへの貢献です。 顧客管理としてCRMを利用しています。顧客情報を自動で貯めることで、全ての顧客にいち早くサポートできるようにしました。

請求書についても極力自動化をし、お客様が選べるようにMF KESSAIとStripeとの連携をしました。

データサイエンス

次はデータサイエンスです。 システム構成図にもあったように、フロントエンドやバックエンドとデータサイエンスは共通基盤を利用して疎結合に繋がっているようにしています。データのアウトプットの使用を合わせるだけで、それぞれの職種の中でアップデートできるようにしています。データ受け取りは、オブジェクトストレージ間で基本的には行なっています。

デザイン

デザインです。 今までは、Invisionでスタイルガイドなどをフロントに提供し、フロントエンド側でファイルを分けることや、命名規則を作るなどで最適化を図ってきました。それだけでは、どこになんのコンポーネントがあるのかわからないことが多々ありました。 そこで現在は、React/styled-Component・AtomicDesignの概念を適応し、コンポーネント単位でのCSS適応を行なっています。

フロントエンド・バックエンド・インフラ

そして、私が得意としているフロントエンド〜インフラです。1つ2つとサービスを開発していく中で、インフラを考えることや構築するこことはすごく時間を費やすことがわかっています。 そこで、インフラの構成を型化・未来を描き、実践していってます。

できるだけ開発に注力するため、LambdaやCloudformationなどAWSサービスを駆使した構成になっています。

またその後のアプリケーションが増えることを想定し、共通化とマイクロサービス化を意識しています。

同じモデルの横展開

この構成は、私たちが今後取り組むその他の業界にも適応でき、スケールしやすくなると考えています。

Chief Production Officer

このようにプロダクトから、様々な職種へ貢献し、そのさきにある顧客に対しても価値を作っています。

【2018年を振り返る】組織と自分を深く理解した1年

株式会社空、この1年で自分の思い出せる範囲の出来事から振り返りをしてみました。 深掘りが必要なコンテンツがあれば、別記事で書いていきます。

f:id:hirontan:20190105033930j:plain

2018年できごと

  • CPO
  • ホテル番付への改善注力
  • シリーズA資金調達
  • カスタマーサクセスへの注力
  • コーチングを受け始める
  • Rubybiz 2018 エントリー
  • CTO of the year 2018登壇
  • MagicPriceリニューアル
  • 1on1始める
  • 開発でやりたいことが爆発的に増えた(特に React / Lambda / Docker)
  • ガチスクラムを始める
  • プロダクションチームの人数が6人から12人
  • 企画・デザイナー・エンジニア・データサイエンティストとバランスの取れた組織

できごとを振り返ってみる

CPOの肩書きがつく

今まで取締役兼エンジニアと肩書きがないまま株式会社空で1年半、歩んで来ていました。 シリーズAの資金調達を始めるときに、弊社社長である松村にCPO(Chief Production Officer)と肩書きをつけてくれたことが始まりでした。

肩書きがない1年半、働く上でフラットな関係性を保ちたいと強く望んでいたため、肩書きは不要と考えていました。 フラットな関係性であることで、お互いの意見を言い合える文化やプロフェッショナルな領域から貢献できる文化が根付くことを望んでいました。 肩書きができたからと言って、フラットな関係性であることは諦めてはいません。 空コアバリューの「Live Direct」にもあるように、遠慮や忖度を止めて、本質志向で話し、行動しよう。上司も社長も間違えるから、本音で指摘しよう。真実を直視して、過去にとらわれずに変化し続けよう。と上下ができたとしても、形を変えてフラットでいたい気持ちは残っています。

そうして、肩書きは素直に受け入れ、社外からプロダクトの責任者なんだとわかりやすく認識してもらえるようになりました。 エンジニアをしているとCTOじゃないの?「P」ってなに?とはよく聞かれますが、Production の「P」です。 プロダクトを通じて顧客や様々な職種へ貢献するため、技術からの課題解決だけではなくビジネスチームとのコミュニケーションにより、プロダクト価値があるのかを判断し、プロダクトの責任を持っています。 現在はエンジニア歴が多少あるためCTOとしての責務も担っています。

CPO/CTOの責務を担っていますが、個人的にCPOとCTOの住み分けをしています。(定義は決めの問題だと思っています) CTOは、技術で会社を引っ張っていける。技術で開発者をワクワクさせる。 CPOは、技術とビジネスの観点から課題解決のバランスを考える。 とざっくり考えています。

作ることだけでは、お客様の課題を感じ取り、価値を届けることは技術だけでは果たせないと強く思っているため、肩書きCPOはしっくりきています。

深掘りしたいコンテンツ
  • 価値を届けることは技術だけでは果たせないとなぜ強く思うのか?

バランスの取れた組織

この1年でプロダクションチームが6人から12人に2倍になりました。 プロダクションチームは企画・デザイナー・エンジニア・データサイエンティストから構成されています。

1番変化があったことはデザイナーの参画です。 今までは、企画が一緒にデザインをする・エンジニアがラフデザインから直接デザインをコーディングするなどして来ていました。 課題→情報設計→デザインの流れがデザイナー担当になって、デザインを企画・エンジニアで中途半端に作成しなくなりました。 恥ずかしながら、この時に情報設計という言葉を初めて知りました。

そして、人数が増えることで、どんなタスクをしているのかわからない・進捗状況がわからない・属人化しがちなど課題が上がって来ます。 タスクの見える化や属人化リスクの排除など、少ない人数の時だからこそガチでスクラムを始めています。

この時に1on1も徐々に始めました。経験したアンチパターンから学び、人となりを知ることから始め、何を大事にしているのかを知ることで成長支援のポイントを見つけられるようにしています。 また自分自身がコーチングを受けることで、1on1の質は高まりました。

深掘りしたいコンテンツ
  • 1on1について

登壇やエントリーは会社・組織・自分を知れる手助けになる

ホテル番付が少しずつお客様に使ってもらう機会が多くなり、Rubybiz 2018 エントリーを決意しました。 結果、ファイナリストに残ることはできませんでしたが、会社としてRubyをなぜ扱って技術的な強みになるのか深く考えられました。

個人的に最大コンテンツだったのが、CTO of the year 2018の登壇でした。 CTOとしての側面での成果や、会社としての技術的な強みを考える良い機会でした。

jp.techcrunch.com

深掘りしたいコンテンツ

MagicPrice リニューアル

実は2回目のリニューアルになります。1回目は、2017年4月に行なっています。 1回目と2回目のリニューアルの間はほぼホテル番付に注力し、得た経験からよりお客様に利用してもらいやすいようリニューアルを行いました。

リニューアルでは、React/Redux/Re-ducks/AtomicDesignと新しい挑戦もできました。

jp.techcrunch.com

振り返りまとめ

この1年はエンジニアリングだけでなく、組織と自分を見つめ直す機会が多かった1年でした。 深掘りしたいコンテンツも出て来たので、徐々に書いていこうと思います。

www.wantedly.com

資金調達を実施して、エンジニア組織をさらに拡大する #資金調達 #シリーズA #ホテル番付 #MagicPrice

本日(7/12)、株式会社空の約1.7億円の資金調達を発表しました

f:id:hirontan:20180712101951p:plain

まとまった内容は弊社代表の松村(まっつん)や記事で書いていただいている通りです。

medium.com

私からお伝えしたいことは「エンジニア組織拡大」についてです。

エンジニア組織拡大の前に・・・

弊社は、「世界中の価格を最適化し、売り手も買い手も嬉しい世界を作る」PriceTech Company〜になるために成長を続けています。 大きなことを言っていることは確かですが、プライシングを行なっている企業や個人の方がいらっしゃいます。

個人の方だと・・・

オークションやフリマで出品することが容易に想像できるのではないでしょうか。 出品するときに、売り手は最適な価格を考えて売ります。買い手は最適な価格か(上限価格は個人個人設けていると思います)を考えて買います。

プライシングは無数に存在する

プライシングとしてホテル事業に特化して成長していますが、今回の資金調達を機に新たな業界への展開へもチャレンジします。

f:id:hirontan:20180712101926p:plain

新たな業界への展開へもチャレンジするために

エンジニア組織拡大が必須になってきます。

現在のエンジニア組織

企画・デザイナー・開発エンジニア(フロントエンド、バックエンド)・機械学習エンジニア・データサイエンティストと各職種は揃っている組織ではあります。 企画アイデアは企画という立ち位置で案件を全て作るのではなく、エンジニア組織全体で案件を考えています。 つい先日も、「これからホテル番付・MagicPriceをさらによくするためには」の議論をし、優先順位も全員で考えました。 全員で考えることは生産性が生まれないと思うかもしれません。全員で認識を合わせることで、全員でプロダクトを作っているイメージがしやすく、プロダクトが前進しやすくなります。

これからのエンジニア組織

「企画を考えた人がリーダーとなる」「学習から行動に持っていく」を進めていきたいです。 まだ構想段階ではありますが、アウトプットさせてください。

企画を考えた人がリーダーとなる

プロダクト造りの企画は全員で実施していますが、とりまとめは基本的に企画が行なっています。 そのとりまとめは、企画を考えた人がリーダーとして進めていく方向にしたいです。 なぜなら、プロダクトとエンジニア組織の成長について2つ理由があります。 1つ目、プロダクトは企画を考えた人がリーダーとして実施することで企画に対する想いが入り、120点のプロダクト完成度ができる確率が高まります。 2つ目、エンジニア組織の成長はエンジニアがエンジニアリングだけを突き詰めることも良いことではあるが、リーダーシップを発揮できる機会をより多く作っていき、エンジニアリング以外も成長できる機会を作っていきたいです。企画のポジションが無くなるの?と思う方もいるかもしれませんが、いいえ無くなりません。現在直近でプロダクトをよくすることを考えていますが、中長期的な対策を練る方向にも時間が当てられるようになり、プロダクトとしてはさらに強化されていきます。

副次的ではありますが、職種が完全に別れていると会社内受託っぽくなりえる可能性が高く、全員で前進していきたいと考えています。

学習から行動に持っていく

プロダクトを開発する上での組織構造は現在のまま続けますが、実施していきたいことは、学習から行動に持っていくことをさらに加速していきます。 エンジニア主軸になってしまいますが、エンジニアは日頃から学習をしている方が多いかと思います。ただし、世にインパクトのある環境での学習したことをアウトプットすることは難しいのではないでしょうか。そのアウトプット(行動)をできる環境作りを全員で行なっていきたいです。現在は、新しいモジュールを入れてみて開発してみるなど短期的に効果があり生産性の生まれるものをやっています。これからは生産性の生まれそう?など疑問に思っているものでも、利用してみて問題なければそのまま導入。問題があれば破棄する。意思決定をライトに。また中長期で効果がありそうな技術への投資も実施していきたいです。

Happy Growth を掲げ、HappyとGrowthを両立させるためには、エンジニア組織としては重要になってくる要素です。

www.wantedly.com

最後に

エンジニア組織拡大は必須になってきます。まだまだ各領域の職種が足りていません。 ご応募お待ちしております。

f:id:hirontan:20180712102021j:plain

株式会社空 CPO 田仲紘典

sora.flights

採用募集

Wantedly

www.wantedly.com

www.wantedly.com

www.wantedly.com

Green

Railsエンジニア | 株式会社 空 | IT/Web業界の求人・採用情報に強い転職サイトGreen(グリーン) | 2018/07/19 14:50:28更新 | id:67213

データサイエンティスト | 株式会社 空 | IT/Web業界の求人・採用情報に強い転職サイトGreen(グリーン) | 2018/07/19 09:01:34更新 | id:67212

aliyuncli を使ってみた #Python #Image #サーバ作成

概要

イメージでサーバ作成するために aliyuncli を使ってみました。

やってみたまとめ

  • OpenAPI Explorerがあり、プログラムは相当簡単にかけます。
  • APIへリクエストが叩けない時があるので、リトライ処理入れる方が良い。(お決まり?)
  • OpenAPI Explorer に記されている do_action でリクエスト送るより、ServerException の処理があるdo_action_with_exception をリクエストを送る方が良い。
  • 自分でStatus拾って実行考えたい場合は、do_action_with_exception ではなく get_responseimplementation_of_do_action で実行する。

実行環境

  • CentOS 6.8
  • Python 2.7 → v3あることあとで気づきました

実行準備

$ pip install aliyun-python-sdk-core
$ pip install aliyun-python-sdk-ecs
→必要なライブラリをインストール
$ pip install logging
$ pip install retry
$ pip install argparse

実行

実行内容

事前に Image を作成して、インスタンスを作成する。 ミニマムのサーバリソースで同じセキュリティグループで同じサーバ名で作成していきたかったため、利用しました。 もちろん、UIでインスタンス数指定してもちろん複数構築は可能です。 ただ、また増設するときに必要になるので、書きました。 あと、オートスケーリングすれば。。。との話は置いておきます。

ソースコード

github.com

# -*- coding: utf8 -*-
#!/usr/bin/env python

import json
import argparse
from retry import retry
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526 import CreateInstanceRequest

def acs_client(api_key, api_access_key):
  return AcsClient(
    api_key,
    api_access_key,
    region_id
  );

@retry(tries=4, delay=5, backoff=2)
def request_cli(req):
  status, headers, body = clt.implementation_of_do_action(req)
  print('[ status: ' + str(status) + ' ] [ headers: ' + str(headers) + ' ] [ body: ' + str(body) + ' ]')
  if status != 200:
    raise('[ status: ' + str(status) + ' ] [ headers: ' + str(headers) + ' ] [ body: ' + str(body) + ' ]')
  json_body = json.loads(body)
  return status, json_body

def create_instance():
  req = CreateInstanceRequest.CreateInstanceRequest()
  req.set_accept_format('json')
  req.add_query_param('RegionId', region_id)
  req.add_query_param('ImageId', image_id)
  req.add_query_param('InstanceType', 'ecs.t5-lc2m1.nano')
  req.add_query_param('SecurityGroupId', '[security_group_id]')
  req.add_query_param('InstanceName', '[instance_name]')
  req.add_query_param('InternetMaxBandwidthIn', '50')
  req.add_query_param('InternetMaxBandwidthOut', '50')
  req.add_query_param('VSwitchId', '[vswitch_id]')
  req.add_query_param('SystemDisk.Size', '20')
  req.add_query_param('KeyPairName', '[key_pair_name]')
  status, body = request_cli(req)

def main():
  init_logger()
  create_instance()

def init_args():
  parser = argparse.ArgumentParser(
             prog='aliyun_sample',
             usage='python aliyun_sample.py --region [ap-northeast-1] --key [api key] --access [api access key] --image [image id],
             description='description',
             epilog='end',
             add_help=True
           )
  parser.add_argument("-r", "--region", help="please set region id", type=str, default='ap-northeast-1')
  parser.add_argument("-k", "--key", help="please set api key", type=str, required=True)
  parser.add_argument("-a", "--access", help="please set api access key", type=str, required=True)
  parser.add_argument("-i", "--image", help="please set image id", type=str, required=True)
  return parser.parse_args()

if __name__ == '__main__':
  args = init_args()
  region_id = args.region
  image_id = args.image
  clt = acs_client(args.key, args.access)
  main()
コマンド
$ python aliyun_sample.py --region [ap-northeast-1] --key [api key] --access [api access key] --image [image id]

採用

株式会社空のCPOが目指すテクノロジードリブンな組織 #株式会社空 #MagicPrice #ホテル番付 #SORA #エンジニア #採用 #インタビュー

社内インタビュー記事

www.wantedly.com

内容

以前、「ブラインドタッチもできなかった僕がヤフーと空で成長できた理由」と個人の話をさせていただきました。 個人だけではなく、株式会社空として組織はどうありたいのかを記事にしてもらいました。

サービス

www.hotelbanzuke.com

採用

ブラインドタッチもできなかった僕がヤフーと空で成長できた理由 #株式会社空 #MagicPrice #SORA #エンジニア #採用 #インタビュー #少し補足

社内インタビュー記事

www.wantedly.com

sora.flights

内容

学生、ヤフー、現在(空)としての活動内容などを中心に話しています。 前半部分の補足を若干しておきます。

補足

タイトル「ブラインドタッチもできなかった僕がヤフーと空で成長できた理由」

大学院まで卒業するまで、基本的にコピペエンジニアであったため、完全にブラインドタッチができないまま卒業しました。 その後、ヤフーに入社して、ブラインドタッチがみんなできていることに衝撃を受けました。 研修が終わって、家に帰ってブラインドタッチひたすらやっていました。 今はちゃんとブラインドタッチできています。

ーー立命館大学、大学院を卒業していますが何を学んでいたんですか?ーー

IDSを開発していた時は、研究室に構築しているサーバ群ネットワークのパケットを収集して、パケットをみることが好きでした。 パケットのキャプチャはライブラリ Jpcap を利用して、3ウェイ・ハンドシェイク などを実際に見て理解していました。

大学院の研究室でFreeBSDのOS

実際には FreeBSD だけでなく、CentOS も利用していました。 まだ仮想環境が流行り始めた時に、Windows機の上にVMwareをインストールし、サーバを構築していた経緯もあります。 この時に物理的なネットワーク構築も試みていました。

サーバ利用としては現在クラウド環境として、AWSGCP、Azureなど便利になってきていますね。 研究室時代ではなくヤフーではOpenStackも部の支援もあってJuno、Icehouseあたりの構築も経験しました。

ーーヤフーではどういった業務をやっていたんですか?ーー

基本的に毎年のようにチームが変わり、よく利用する技術・能力が違っていたことで、多様な学びがあった環境ではありました。 ブログには書かれていないですが、広告部門で利用されているツールの保守開発も行なっていました。 広告部門で利用されているツールはヤフーの外側に出ているツールではないため、Chef、Jenkinsなどアグレッシブに新しい技術・ツールを取り入れる機会がありました。

================================

若干ではありますが補足しました。 気がついたらまた補足します。

サービス

www.hotelbanzuke.com

採用

FTP サーバ構築(冗長化にも対応)[vsftp, goofys, s3fs, ec2, s3, elb]

概要

  • ファイルの受け取りをする時、FTP 通信でサーバ利用
  • サーバが潰れても良いよう、S3 にファイル保存する

構築方法

事前準備

  • EC2サーバ準備
  • ELB準備
  • セキュリティグループのポート開放(TCP:21, 60001-60010)
  • S3 のバケット
  • AWS ユーザ作成(SecretKey, SecretAccessKey を利用)

構築手順

$ sudo yum install -y vsftpd
$ sudo cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.orig
$ sudo vi /etc/vsftpd/vsftpd.conf
----- 下記に書き換える -----
anonymous_enable=NO
dirmessage_enable=NO
connect_from_port_20=NO
xferlog_std_format=NO
ascii_upload_enable=YES
ascii_download_enable=YES
chroot_local_user=YES
chroot_list_enable=YES
tcp_wrappers=NO

pasv_enable=YES
pasv_addr_resolve=YES
pasv_address=[ホスト名]
pasv_min_port=60001
pasv_max_port=60010
use_localtime=YES
force_dot_files=YES
user_config_dir=/etc/vsftpd/user_conf
--------------------------

$ sudo touch /etc/vsftpd/chroot_list
$ sudo adduser [ユーザ名]
$ sudo passwd [ユーザ名]
→ ここでパスワードを設定します

$ sudo chkconfig vsftpd on
$ sudo /sbin/service vsftpd start

$ sudo mkdir /home/[ユーザ名]/data
$ sudo chown [ユーザ名]:[ユーザグループ] /home/[ユーザ名]/data

$ sudo yum install -y golang fuse
$ sudo wget https://github.com/kahing/goofys/releases/download/v0.0.5/goofys -P /usr/local/bin/
$ sudo chmod 755 /usr/local/bin/goofys

$ aws configure
AWS Access Key ID [None]: [SecretKey]
AWS Secret Access Key [None]: [SecretAccessKey]
Default region name [None]: [region]
Default output format [None]: text

$ sudo /usr/local/bin/goofys -o allow_other --dir-mode 0700 --file-mode 0600 --region ap-northeast-1 --uid 502 --gid 502 [ユーザ名] /home/[ユーザ名]/data
$ sudo /usr/local/bin/goofys -o allow_other --dir-mode 0700 --file-mode 0600 --region ap-northeast-1 --uid 502 --gid 502 [ユーザ名] /home/[ユーザ名]/data
$ sudo mkdir /etc/vsftpd/user_conf
$ sudo vi /etc/vsftpd/user_conf/[ユーザ名]
-----
local_root=/home/[ユーザ名]/data

$ sudo vim /etc/vsftpd/user_list
----- 追記 -----
ec2-user

$ sudo /sbin/service vsftpd restart

$ sudo vim /etc/fstab
----- 追記 -----
# goofyn
/usr/local/bin/goofys#[ユーザ名] /home/[ユーザ名]/data fuse allow_other,--dir-mode=0700,--file-mode=0600,--uid=502,--gid=502    0       0
----------------

接続確認

$ ftp [ユーザ名]@ホスト名
ftp> put test
→ 「226 Transfer complete.」と出るようにする

Windows で接続できない場合の対処法

再構築

上書き保存ができない

  • vsftpgoofys の相性がどうも悪いようです
状態
ftp> put test
local: test remote: test
229 Entering Extended Passive Mode (|||60007|).
150 Ok to send data.
100% |*********************************************|     5        1.58 KiB/s    00:00 ETA
226 Transfer complete.
5 bytes sent in 00:00 (0.19 KiB/s)
ftp> put test
local: test remote: test
229 Entering Extended Passive Mode (|||60005|).
150 Ok to send data.
100% |*********************************************|     5       19.68 KiB/s    00:00 ETA
451 Failure writing to local file.
5 bytes sent in 00:00 (0.34 KiB/s)

goofys から s3fs に変更してみる

$ sudo su
$ yum -y install git automake gcc-c++ fuse fuse-devel libcurl-devel libxml2-devel openssl-devel
$ wget https://github.com/s3fs-fuse/s3fs-fuse/archive/v1.80.tar.gz
$ tar xzvf v1.80.tar.gz
$ rm -f v1.80.tar.gz
$ cd s3fs-fuse-1.80/
$ ./autogen.sh
$ ./configure prefix=/usr
$ make
$ make install
$ echo '[SecretKey]:[SecretAccessKey]' >> /etc/passwd-s3fs
$ chmod 640 /etc/passwd-s3fs
$ umount /home/[ユーザ名]/data/
$ s3fs [ユーザ名] /home/[ユーザ名]/data -o allow_other,use_cache=/tmp,uid=502,gid=502,passwd_file=/etc/passwd-s3fs
$ vim /etc/fstab
   # もし goofys の追記箇所があれば削除してください
----- 追記 -----
# s3fs
/usr/bin/s3fs#[ユーザ名] /home/[ユーザ名]/data fuse rw,allow_other,uid=502,gid=502    0       0
----------------