freeeの新しく公開されたAPIを使って、非エンジニアが音声で勤怠打刻をしてみました!

こんにちは、freee株式会社のgokiです。

私は2017年の新卒としてビジネス職で入社し、現在はProduct Value Boosterという、営業チームや導入支援チームに自社プロダクトの価値を咀嚼してお伝えするお仕事をしています。

非エンジニアではあるのですが、いろんな業務改善ツールを作ることが好きで、趣味でいろいろ作ったりしています。

IFTTTを使って音声で勤怠打刻をしたかった理由

皆さんは、勤められている会社で勤怠って付けていますか?

ほとんどの人が”YES”だと思うのですが、あれってなかなか面倒だったりしますよね。

freeeでは、会計や人事労務管理はすべて自社のサービスを使用しているのですが、クラウドとはいえ、勤怠のためにPCをつけて、ログインして打刻、という作業時間がもったいないなぁ、と感じていました。

人事労務freeeがタイムレコーダー(打刻)のAPIを公開!

そんな勤怠打刻の悩みを悶々と抱えていた矢先、なんと人事労務freeeがタイムレコーダー(打刻)のAPIを公開しました)!

人事労務freeeのタイムレコーダー(打刻)APIのリファレンスの画像

嬉しーーーーー!!!

タイムレコーダー(打刻)APIについて

指定した従業員のタイムレコーダー(打刻)情報を 登録 / 取得する ことができます。 登録の場合は、webの画面やアプリと同じく出勤 / 退勤 / 休憩開始 / 休憩終了 の登録ができます。 このAPIを用いて、自社のツール・ICカードや生体認証に対応した打刻機からAPIを呼び出すことで出退勤の管理を自動化することができます。

※タイムレコーダー(打刻)機能は、ビジネスプランのみ有効です。 https://developer.freee.co.jp/docs/hr 人事労務API 概要 | freee Developers Community

これで色んな方法で打刻ができます!

やっぱりやるなら音声入力

実は前回、Google HomeとIFTTTを使って、音声で経費の仕訳を作成するという記事を書かせていただきました。

developers.freee.co.jp

大変ご好評もいただいたこともあり、今回の打刻APIの活用アイデアを考えたときに、私は真っ先に音声入力が思い浮かびました。

前回のノウハウもありますし、何より音声入力ってやっぱり楽ですしね。

というわけで、前振りが長くなってしまいましたが、

「OK Google!出勤したよ!」と言ったら、自動的に人事労務freeeで出勤を記録する仕組みを作りたいと思います。

基本的な仕組み

仕組みとしては、前回の音声仕訳と同じく「①Google Assistant →②Google スプレッドシート→③freee」という順番でデータを飛ばそうと思います。

①と②の間をIFTTTで、②と③の間はGoogleのスクリプト“Google Apps Script(略称GAS)”を使用して、freeeが公開したAPIを叩くという方法です。

下準備で必要なもの

  • Googleアカウント
  • Google Assistantアプリのスマホへのインストール
  • IFTTTアカウント
  • 人事労務freeeのビジネスプランのアカウント

IFTTTの設定

準備が終わったら、あとはIFTTTの設定です。IFTTTにログインしたら「New Applet」よりAppletの新規作成を行います。

IFTTTのNew Applet画面のスクリーンショット

Appletのトリガーであるthisの部分は次のように設定します。

service
Google Assistant
trigger
Say a simple phrase

最後のtrigger fieldsについてですが、今回は、「出勤したよ」と喋りかけたら自動で打刻の処理をしたいので、次のように設定しました

What do you want to say?
出勤したよ
What's another way to say it? (optional)
出勤しました
And another way? (optional)
出勤するよ
What do you want the Assistant to say in response?
今日も一日頑張ってください

IFTTTの設定クリーンショット

これで、「出勤したよ」と話しかけたことをトリガーにアクションを実施できるようになりました。

ちなみに、このトリガー後のGoogle Assistantからのレスポンスは「今日も一日頑張ってください」とし、朝からテンションが上がるように設定しました。

続いて、thatにあたるアクション部分を作成します。

service
Google Sheet
action
Update cell in spreadsheet

を選択します。

action fieldsは、「音声打刻」というスプレッドシートを指定し、そのシートのA1セルを出力先に指定しました。

Spreadsheet name
音声打刻
Which cell?
A1
Value
clock_in

IFTTTの設定のスクリーンショット

また、出力先への値としては「clock_in」を指定しています。

これは、freeeの打刻APIでリクエストを送るときのtype(出勤・休憩開始・休憩終了・退勤)を指定する必要があるので、今回は出勤を指定する「clock_in」を入れています。

APIにて操作可能な打刻種別は以下のとおりです

clock_in
出勤
break_begin
休憩開始
break_end
休憩開始
clock_out
退勤

あとは同じ要領で休憩や退勤も作成

ここまでで、Google Assistantに話しかければ、Googleスプレッドシートに出勤情報を飛ばすことができました。

同じ要領で休憩開始、休憩終了、退勤なども作成すれば、IFTTT側の準備は終了です。

「①Google Home →②Google スプレッドシート→③freee」のうち、①→②が完成しましたので、

次からは②スプレッドシートから③freeeへの入力について説明します。

Google スプレッドシートとfreeeの連携の仕方

前回の記事でも書きましたが、Google スプレッドシートとfreeeの連携は意外と簡単です。

実はfreeeのヘルプページにはスプレッドシートからAPIを送信する用のサンプルシートがあります。

support.freee.co.jp

ただし、上記のサンプルシートについては、人事労務freeeではなく、会計freeeの取引登録APIなので、そのまま使うことはできません。

しかし、これを使えば、OAuth2認証で必要なアクセストークンなどを簡単に取得することができるうえ、POSTリクエスト(APIの叩く操作)もコードを数行書き換えるだけですぐ終わるので、めちゃくちゃ楽です。

Googleスプレッドシートの変更点

まず、サンプルシートをIFTTTの値出力先にするため、名前を「音声打刻」に変更します。

IFTTTからを値を受け取るシートを作成し、連携認証をマニュアルに従って行えば準備完了です。

Google Assistantから休憩開始を喋りかけてみて、A1セルにbreak_beginが入力されれば成功です。

Googleスプレッドシートのスクリーンショット

あとは、スプレッドシートの「ツール」→「スクリプトエディタ」から少しコードを書き換えるだけで完成です。

コードを変更した箇所

今回は、会計freeeの明細POSTのコードをコピーして、下記の部分だけ変更を加えました。

変数のrequestUrl を "https://api.freee.co.jp/hr/api/v1/employees/従業員ID/time_clocks"に変更

POSTする内容の記述を下記のように変更

  var d = new Date();
  var postdate = Utilities.formatDate( d , "JST" , "yyyy-MM-dd" ); 
  var gSheet = ss.getSheetByName( "IFTTT" );
  var posttype = gSheet.getRange( 1 , 1 ).getValue();

  var requestBody = 
        {
          "company_id" : 事業所ID,
          "type" : posttype,
          "base_date" : postdate,         
        };

打刻の場合はリクエストに必要な情報が少ないので、とってもシンプルかと思います。 説明するまでもないかもしれませんが、リクエストのtypeの値をIFTTTから出力されるA1セルの値にしています。

事業所IDと従業員IDの取得について

事業所IDと従業員IDについては、もともとサンプルファイルには事業所IDの取得リクエストができるようになっています。

さらに従業員IDについても、「ログインユーザーの取得」という人事労務freeeのAPIを叩けば分かるのですが、

そのコードを書くのがめんどくさいので、人事労務freeeにログインして「従業員情報」のリンクのURLが

https://p.secure.freee.co.jp/employees#従業員ID/年/月となっているので、そこで調べてコードに直打ちしています。

準備完了!!

これで準備が整いました、最後にスクリプトエディタのトリガー設定にて、シートが更新されると打刻のスクリプトが動くように設定しておけば完了です!

トリガー設定のスクリーンショット

音声打刻の使用感

作成してからは、これで打刻を行うようにしていますが、とても快適です!

「OK Google!出勤したよ!」で終わるので、とっても時間短縮。

あとは、Google Assistantが「いってらっしゃい、今日も頑張って」と返してくれるのも心がほっこりします。

Googleアシスタント(アプリ)のスクリーンショット
自分が設定したのだけど、応援してくれるのがうれしい...

もっとイメージがわくように、動画もいつか撮影して載せたいと思いますが、今回は写真ですみません。

人事労務freeeのビジネスプランを使っている方は、ぜひぜひ試してみてくださいね!

打刻APIを使えばいろんな連携ができそう。

私は技術にめちゃくちゃ詳しいわけではないのですが、今回のAPI公開で

GitHubやSlackから勤怠打刻したり、生体認証で勤怠を打刻したりといったことができるようになりそうですね!

個人的に音声については目が不自由だったりする方には最高の勤怠ソリューションかな?とか思いました。

もし、このようなテクノロジーを使って、いろんなビジネスの課題を解決することに興味がある方は、ぜひぜひfreeeという会社のこともチェックしてみてください~

jobs.freee.co.jp

iOSDC2018にスポンサーとして参加してきました!

こんにちは。freeeでモバイルエンジニアとして働いている kohirose です。 私の所属しているモバイルチームのiOSメンバーで iOSDC2018 に参加してきました。私自身は主にAndroid界隈で生きているエンジニアですが、iOSにも興味があるため今回のiOSDCに潜入してきました。

また、弊社は try!SwiftDroidKaigi といった技術カンファレンスでもスポンサーとして参加をしてきており、今回のiOSDCでもスポンサーブースを会場で出展しておりました。

developers.freee.co.jp

developers.freee.co.jp

iOSDCとは

受付の写真

2018年8月30日(木)〜9月2日(日)に3日+前夜祭の計3.5日間で開催されたiOS関連技術をコアのテーマとした技術者のためのカンファレンスです。 昨年の開催では計2.5日だったため、1日増えたことになります。

私は国内国外問わずモバイル関連のカンファレンスには頻繁に参加するのですが、iOSDCはその中でもセッション&LT数もとても多かったと思います。

8/30(木) 8/31(金) 9/1(土) 9/2(日)
12 35 49 38

また、毎年お酒が振舞われ、LTでは参加者が飲みながらワイワイと参加する形となっているのがiOSDCの特徴かと思います。

開場で振舞われる缶ビール

ブース出展

freeeブースの様子;

先述の通り、今回は弊社ではブーススポンサーとして参加したため、4日間会場でブースを出展しておりました。

昨今、働き方改革という流れもあって「副業やってみたいのですが・・・」「個人事業主として働こうと思ってます。」といった声が多くあった印象でした。また、今回弊社のブースでは確定申告についてお話しさせて頂きながら、私たちが開発しているiOSアプリを体験して頂きました。なお、こちらのアプリは開発中のものとなります。

youtu.be

上の動画と同じ、領収書の撮影から取引の登録までを体験して頂いていたのですが、その中でも私たちのiOSアプリでは、撮影時に OpenCV を利用して領収書矩形を切り抜いたり、取引登録時に OCR を実現していたりと、確定申告準備をより楽にしようとして開発をしております。

www.freee.co.jp

「どうやって実現しているのか?」「OCRはクライアントでやっているのか?サーバー側でやっているのか?」といった技術的なお話も多くすることができ私たちのiOSアプリに興味を持って頂いてとても嬉しく思いました。また、実際に体験して頂くことにより、UI/UX面での気づきもあり、今後より使いやすくなるようにより改善を続けていく必要があるなと改めて感じました。

freeeロゴのキーキャップと装着されたキーボード

また、今回もキートップノベルティは健在で人気を集めていました。弊社のブースで展示していた自作キーボードはブーススタッフの作成物であったため、自作キーボードの作り方や、種類、部品の発注方法まで多くのことを語られていました。私自身は作成したことなかったため、こんなに多くのキーボード自作ファンがいるのかと驚かされました。またノベルティを配布することがあればキートップも配布するかと思いますのでご興味ある方は是非スタッフに話しかけてみてください。弊社にはキーボード部があるくらいなのできっと喜ぶかと思います。

セッションについて

セッション開場の様子

iOSDC2018のセッションは先述の通りとても多く、内容もコアな部分から現場でのテクニックまでとても幅広く扱っていました。今年のWWDCで注目を浴びた ARKit の話であったり、差分更新アルゴリズムの話であったり、圏論 の話であったり、本当に多種多様なセッションが揃っていました。参加させて頂いたものの中からいくつか紹介させて頂きます。

ARKitと3D数学

speakerdeck.com

前夜祭である初日の1発目のセッションはARKitでした。ARKitを利用するにあたって必要となった3D数学を説明してくれるという、数学好きな私としては楽しみなものでした。

定義されたあらゆる体系の座標系があり、その座標系の中での座標を最終的にスクリーンに落とし込むことにより、スクリーンの任意の場所へ3Dオブジェクトを配置できるとのことです。この座標系の知識があれば、あとはARKitが用意しているAPIでiOS上でのARが実現できます。物体を30cm奥に表示するという簡単なところから説明してくださっていたのでARって難しそうで敷居が高いと思っている方におすすめです。今回のスライドでは行列の話がなかったので残念でしたが、Qiitaに追加として書かれていたのでそれも見るとより理解が深まるかと思います。

qiita.com

MicroViewControllerで無限にスケールするiOS開発

www.icloud.com

複数人開発を行っていると避けては通れないコンフリクトやオーバーヘッドを無くして多くの人数でプロダクトを効率的に開発していこうという目的に向けて、1画面のViewControllerの中の各々の部品をViewControllerとして実装していこうというお話でした。各々の開発者が触る領域が決まりやすいため、確かに人数が多ければ多いほどこの開発手法は生きてくるなと感じました。ただし、大量のViewControllerを作成していくことになるので負担をより軽減させるためにテンプレートが多くあると良いとのことです。一つ一つのViewControllerの責務が分かりやすく分割されるのでテストも書きやすくて良いなという印象を受けました。

iOSと(深層)強化学習

speakerdeck.com

本セッションでは、そもそも強化学習とはどういったものなのかから始まり、ニューラルネットワークをSwiftで実装しCartPole問題を題材にiOS上でデモを行うというものでした。

ニューラルネットワークを自作するには行列演算が必要で、そこにはBLAS(Basic Linear Algebra Subprograms)を利用するとのことでした。私自身このBLASを存じていなかったのでこのセッションが終わった後一番試してみたかったものでした。その場のデモでロボットが学習していき最終的にロボットが解決していく姿を見ていて会場も盛り上がっていました。

Depth in Depth

speakerdeck.com

iOSでは深度は AVDepthData というクラスで表さられ iOS11から利用できます。このAVDepthDataの取得には

  • 撮影済みの写真から取得
  • カメラからリアルタイムに取得
  • ARKitから取得

のパターンがあり、各々は用途によって使い分けると良いとのことです。

実際に本セッションではカメラからリアルタイムに取得して切り取られた自分自身の顔と任意の画像を合成するデモがあり、徐々に改善していくという実践的な発表となっていて惹きつけられました。また、今月リリースされるであろうiOS12からは Portrait Matte という、静止画かつ人物に限定されるがより従来の深度マップより人物と背景の深度差が的確に表現できるフォーマットが利用できるとのことで、ますます実用的なものになっていくなという印象を受けました。今回は被写体が静止画なのかリアルタイムなのかや、フロントカメラなのかリアカメラなのか、はたまたOSのVersionは幾つなのかなどといった多くのパターンがあるため、対象のアプリにおいて何が実現できるのかを整理することで自分自身の開発するアプリにも何かしらの機能として盛り込めるかなと思います。

まとめ

私自身iOSDCへは2回目の参加でしたがブーススタッフとしては初めての参加となりました。個人事業主の方で「freee使ってます!」といったとても嬉しい声や、同じくブーススポンサーとして参加された企業との情報共有などあり、セッションだけでなく他のところにも楽しみがあった良い機会だったと思います。今回実際にお話しさせて頂いた多くのエンジニアの方々や運営スタッフの方々に大変感謝しております。また、アプリを体験して頂いたことで得られたフィードバックについては改善として今後の開発とさせて頂きます!

iOSDCの開場で、freeeメンバーの集合写真

最後に

freee ではモバイルエンジニアを募集中です。 今回に限らず、弊社ではエンジニア向けカンファレンスに精力的にスポンサーとして参加しており、内容にもよりますが、大抵のエンジニア向けイベントには業務の一環として、業務時間にチケット会社負担で参加することができます。 今回は土日開催であったため代休を2日もらいました。私はその代休(と有給休暇)で沖縄にダイビングをしに今月行ってきます!ご興味がある方は是非一度弊社に遊びにいらしてください!

jobs.freee.co.jp

WWDC 2018に参加しました

こんにちは。freeeでモバイルエンジニアをしている高野です。
6/4(月)から6/8(金)にかけてサンノゼで開催された、AppleのWWDCに参加してきました。

このブログはiOSエンジニア以外の読者もいらっしゃるので、WWDCについて簡単に説明します。WWDCはAppleが毎年開催している大規模な開発者向けのカンファレンスです。国籍・性別・年齢問わず大勢の参加者が訪れます。5日間かけて、最新OSの発表やそれに含まれる新しい機能などについて説明する多くのセッションが開かれます。デザインに関するセッションも多く、エンジニアだけでなくデザイナーの参加者も居ます。

目次

今回の旅程

私は今回がWWDC初参加のため、張り切りから前のめり気味の6/1(金)に仕事を早めに切り上げ、夜の便で羽田〜サンフランシスコへ向かいました。

サンフランシスコを経由せず直接サンノゼに行っても良かったのですが、羽田からのサンノゼに行く便がなく、成田まで1時間以上かけて移動するよりは、サンフランシスコ〜サンノゼと移動した方が景色も楽しめるし良いかな、ということでサンフランシスコ行きの便にしました。

WWDC会期前後の数日でGoogleplex、Computer History Museum、Apple Park Visitor Centerなどを回ったり、サンフランシスコ市内の観光をしました。
観光に関しては後回しにするとして、まずはWWDCについてのレポートです。
少し長くなってしまいましたが、初めて行く方向けの有益そうな情報も散りばめているので、よければお読みください。

WWDC前日チェックインがオススメ

6/1(金)の昼過ぎにサンフランシスコに着き、2日かけて何箇所か観光した後、6/3(日)に会場であるSan Jose McEnery Convention Centerに行き、事前チェックインしました。チェックインは会期中もできるのですが、Keynoteの列に並んでなるべくいい席で見るためには、前日にチェックインしておく必要があります。

チェックイン時に入場カードや参加者へのお土産を受け取ります。

参加者へのお土産のLevi'sのジャケット

今年のお土産は去年と同じくLevi'sのジャケットとピンバッジでした。

WWDC会場入り口。大きくWWDC18の看板が掲げられている 会場正面の入り口です。着いた時はテンション上がりました。

事前チェックインの時、Tim Cookが会場に訪れていて写真を撮ったりできたようですが、残念ながら私は会えませんでした。

チェックインの後、Yahooのエンジニアの方が開いてくださった日本人グループの懇親会に参加しました(事前に参加していたWWDC2018日本人参加者のFacebookグループで知りました)。日本からのWWDC参加者と食事しつつ色々と交流することができ、同じホテルに滞在する方とも知り合えて良かったです(有意義な場をありがとうございました 🙏)。

WWDC初日・Keynote待ちの朝は早くて寒い

初日はKeynote、Platforms State of the Union、Apple Design Awardsがあります。
KeynoteはTim Cookも登壇し、新型のハードが発表されることもあるためメディアから最も注目される発表です。

ライブ配信もあるのでリアルタイムで見たり、翌朝メディアでキャッチアップされる方も多いのではないでしょうか。残念ながら今年はハードの発表はありませんでしたね。

まだ暗い時間帯のWWDC会場の屋外

初日ですが、私は午前3時半くらいにホテルから会場に移動し、並び始めました。
この時点ですでに100人位並んでいました。ちなみに先頭の人は夜の9時台から並んでいたらしいです。早くから並ぶ場合、特に朝方はダウンジャケットを着てもいいくらい寒くなるので注意が必要です。

ここから何時間も並びます。イベントへの期待感もあり、近くにいる他の参加者と話したりして時間を過ごしていると、そこまで辛い時間ではありませんでした。私は今回1人で参加したのですが、列の前後の人と話して仲良くなっておいたりすると、お手洗いなどでその場を離れたい時などに場所をキープしてもらいやすくなったりもします。

入場直後の様子。前に多くの参加者が溜まっている

朝の7時頃に会場の中に入れましたが、入場時に一時的に列が崩れるところがあり、油断していたら若干後ろに下がってしまいましたがまだまだ前寄りです。

ホール開場前、通路で待っている様子。多くの人で混みあっている

今度はKeynoteが行われるホールの開場を待ちます(写真左手奥が入り口)。ここで2~3時間待つのですが、整理された列という形の物がないので、結構人口密度が高くて、外にいる間よりここがしんどかったです。

ホール前で提供された朝食のビュッフェ

朝食も提供されるのですが、隙間の少ない列の中にいると取りに行くのもなかなか苦労します。長時間並ぶなら自分でパンや飲み物を持って行っておくのもアリですね。

そして・・・

ホールの中に入れた様子。奥に見えるスクリーンには数多くのアプリアイコンが表示されている

9時過ぎになり遂にホールに入りました。早くから並んだ甲斐あって、Tim Cookも立つ中央スクリーン近くの前寄りの席に座れました。ステージ正面・中央あたりの一番良い列はメディアなど向けて確保されているようで、一般参加者はどうしてもちょっと斜めの角度からになってしまうみたいですね。

ようやく落ち着いて座れたので、スクリーンに映るアイコンの中から日本のアプリを探してみると、UNIQLO、Suica、NAVITIMEを見つけました。

壇上に上がったTim Cook

そしてTim Cookの登場。近くてテンション上がります。 iOS 12、macOS Mojave、watchOS 5など新しいOSバージョンや、それらの主要な変更点が発表されます。発表内容について詳しくはGigazineさんなどを参照ください。

WWDC会場内の高速有線LANが使えるスペース。大きな机にたくさんの人が向かい、それぞれラップトップ(もちろんほとんどがMacBook)を開いている

会場にはWi-Fiも飛んでいますが、開発者がすぐに新しい物を試せるよう高速の有線LANを使えるスペースがあり、ご覧の通りかなり混雑していました。すぐ試せるようにメインのものとは別に検証用のiPhoneなどを持っていくといいですね。

2日目以降・エンジニア的にはここからが本番

屋外のビュッフェで朝食が提供され、参加者で賑わっている

朝9時から始まるセッションの開始前から、毎日朝食が提供されます。パンやフルーツ、コーヒーやオレンジジュースなど。

他にも、早朝からワークアウト系の催しがあり、参加すると特典(Beatsイヤフォンなど結構豪華なものも)がもらえたりします。会期中、こういう催しに参加すると何かにつけてピンバッジ等の特典が貰えたりするようですね。

9:00からはセッションが始まります。初日に発表された新しいOSの新機能について扱う具体的なセッションや、技術やデザインについてのセッションが4トラック程並行して行われるので、参加者は各々興味のあるセッションを選んで参加します。どのホールも大きなスクリーンや音響設備が整っており、どの席に座っても満足度は高そうでした。

前列の椅子の間から電源タップがぶら下がっている plain
席によっては、椅子の足に電源タップがついていて便利です。

セッションは夕方6時頃には終わって会場も閉館しますが、日没が夜8時半と遅いので、その後でも近場なら観光できますね。

会場までの移動方法・VTAが安い

会場までの移動手段として

  • Lyft/Uber
  • VTA(バス・ライトレール)
  • シェアサイクル
  • 近ければ徒歩

等があります。
勤務先の経費でLyftやUberを利用できる場合はそれがベストですが、個人の費用で行く場合や観光のため等、私用のため自費で移動する場合等の交通費はなるべく安く済ませたいところです。
Lyft等だと近距離移動でもチップを入れると$10前後はしてしまうので、1日に複数回利用しているとそこそこの額になりますが、VTAだと一定時間内の乗り継ぎ等含めてどこまで行っても約$2(後述するClipper Cardを使うとさらに少し安くなる)で済むので無駄な出費をかなり抑えられます。

VTAはバス以外にもライトレールという路面電車を運行しており、会場までの移動手段は充実しています。現地の人が利用するバスに乗るのも楽しいものですし、利用してみても良いかと思います。

他、Limebike等のシェアサイクルを利用するのも手ですが、自転車で歩道は走れなかったり車線の向きが日本と逆だったり少し勝手が違うのでやや注意が必要です。

道端に停められた4台のLime-s電動スクーター

免許を持っている方はこのような電動スクーター(写真はLime-s)という選択肢もありますが、最高時速20km近く出るので、特にヘルメットなしで使うのは少し危険な感じがしました。

なお、シェアサイクルもスクーターも値段的にはVTAとあまり変わらないです。

ランチは海外のエンジニアと話すチャンス

会期中は毎日ランチが配られます。日本人の知り合いを探して一緒に食べたり、セッションの内容を振り返りながら食べるのも良いですが、せっかく「Appleに関連する何らかのクリエイターである」こと位しか共通点のない人が大勢集まる場でもあるので、同じくボッチの外国人の隣に座ってカジュアルに話しかけたりしました。

某ドイツ自動車メーカーでiOSアプリを作っているエンジニアや、韓国の某盛れるカメラアプリを作っているエンジニアとも知り合い、中の話を聞くことができて面白かったです。

WWDCでは会場待ちで並んでいる時間・セッションの開始を待っている時間・ランチの時間など、別の国のエンジニアと話すチャンスが沢山あるのも魅力の一つだと思いました。

Company Storeは初日がベスト

2日目以降、Company Storeと呼ばれる、いわゆる物販がありました。私は初日最初のセッションが始まる前に行ったので十分在庫がある状態でしたが、2日目の夕方頃に再度行ったところ、売り切れている物もかなりありました。

Company Storeの様子。バックパックなどが販売されている

Bashも有り

木曜日には会場付近の広場でBashがあり、音楽ライブなども催されていました。しかも単体の野外ライブと同じくらい本格的。

Bashの様子

食事やドリンクも提供されます。ランチよりBashの食事の方が美味しかったです。

セッションについて

ARやML、Siri等目立つ発表以外にも、ユーザー目線でも嬉しいNotification周り・パスワード管理関連の変更など、セッションを聞いていくごとにとてもいい変更だなと感じることが多く、新しいハードこそ発表されませんでしたが、エンジニア的には充実した内容を聞くことができたかなと思います。

セッションの動画は翌日にはWWDCのサイトにアップロードされます。以下のページにほとんどのセッションが上がっているので、気になるものは見てみると良いと思います。

WWDC 2018 - Videos - Apple Developer

Appleはこの辺り年々オープンになっていて、今ではDevelper Accountを持っていなくてもセッション動画が視聴できますし、今年に至ってはSafari以外のブラウザでも動画を視聴することができるようになっていて素晴らしいですね。

最も印象に残ったセッション

印象に残ったものは沢山あるのですが、ここでは紹介しきれないので、見た中で最も印象に残った、Designing Fluid Interfacesのセッションについて紹介します。

developer.apple.com

iOS・iPhoneを、思考を拡張するデバイスにすべくAppleのデザイナーが考え、実践する手法やその背景にある論理を、Fluid Interfacesという言葉を用いて解きほどいていく感じの内容です。

スピーカーのプレゼンスキルの高さも相まって、私たちがなぜ普段気持ちよくAppleのデバイス(特にiPhone)を使うことができるのか、その根底にあるAppleのデザイナーの情熱のようなものに触れてグッと来るものがありました。私も自分の関わるプロダクトにあれだけの情熱を注いでいるだろうかと振り返るきっかけになるような、繰り返し見たくなるセッションでした。
自分のプロダクトをより良くするのに繋がりそうな具体的なテクニックも含まれるので、まだ観ていない方は是非観ることをオススメします。

セッション飛ばしてもLabには行くべき

Labの様子

WWDC会期中はAppleのエンジニアやデザイナーに直接質問することができるLabが多く開かれます。技術に関すること、デザインに関すること、マーケティングに関すること大体なんでも聞けます。セッションは後からでも見られますが、Labはこの場限りなので積極的に利用しました。
私は参加できなかったのですが、Appleのデザイナーに、自分のアプリのUIデザインに対してアドバイスをもらえるLabなんかもありました。

Labで貰えたXcodeのアイコンのステッカー plain
Labではこんなステッカーを貰えたりします。

最終日はあっさり

最終日は少し早く、夕方の4時くらいにはセッションが終わります。 最後は特別な催しなどはなく、スタッフに見送られながら案外素っ気なく解散となる感じでした。
私は最終日もサンノゼのホテルに宿泊しましたが、すぐにサンフランシスコに向かって観光しても良かったかなと思いました。

WWDC前後で観光

WWDCの話はここまでで、ここから少しWWDC会期前後の観光についての内容になります。会期前の3日間と、会期後の2日間で

などに行きました。 大体の位置関係はこんな感じです

WWDC2018関連観光マップ - Google マイマップ

サンフランシスコ周辺に本社があるIT企業などにも行ってみたかったですが、土日だと休み&平日でも基本的に知り合い社員のツテが無いと社屋には入れないみたいなので諦めました。定期的にオフィスツアーを開いている企業もあるそうなので、タイミングがよければ行けるかもしれませんね。

Googleplex

Googleplexの社員用自転車。各部のパーツがGoogleのロゴの配色になっている Google本社ですね。金曜日、サンフランシスコに着いてすぐに訪れました。広大な敷地の中にいくつも建物があります。建物の中はツテが無いと入れませんが、敷地内は入っても大丈夫そうでした。敷地が広いので、社員用の自転車がいたるところにあります。敷地内のコートで社員の方がビーチバレーをしていたり。

Google Mechandise Store内部の様子 次にGoogle Merchandise Storeです。Googleの敷地内にあります。Googleのデバイスやプリントボトル・Tシャツ、他にボールペンやステッカーなどお土産にしやすいものも売っています。平日は開いていないので注意が必要です。実はここでお土産を買っておきたくて金曜日に来たのでした。

Computer History Museum

Googleのすぐ近くにあるComputer History Museumでは、100年以上前の計算機から始まり、現代のコンピューターに繋がるまでの歴史を、当時の機材そのものの展示含めて見学でき、かなり感動します。

Computer History Museumに展示されるApple II Apple Ⅱや

Computer History Museumに展示されるENIGMA ENIGMAも

チケットを購入して中に入り、気づいたら4時間経っていました。まだの方は是非。

Apple Park Visitor Center

Apple Park Visitor Centerの外観。ガラスの外壁の上に屋根が載った構造 こちらはApple Park Visitor Center。

Apple本社の模型の説明をiPadで見ている様子 中にはApple本社の大きな模型が置いてあり、貸し出されるiPadをかざすとARで社屋の設計や機能が見られて楽しいです。

販売されているTシャツが展示された棚 限定Tシャツなども売られています。

残念ながら一般客は普段Apple本社の社屋には入れませんが、WWDCのスカラーシップ参加者は入る機会があったらしく、羨ましいです。

Apple本社を囲む歩道の写真。両側には木が植えられている

Googleのあるマウンテンビューもそうでしたが、Appleのあるクパチーノは高い建物が少なく、緑も多くて観光していて気持ちよかったです。(上の写真はApple本社を囲む歩道)治安もかなり良いようです。
サンノゼまでは車で20分(バスだと40分)位でしょうか。WWDCの会期中は会場付近にあるホテルの宿泊料金は高騰するので、この辺りのホテルから通っても良かったかもしれません。

サンフランシスコ周辺

WWDC会期後の土日はCaltrainでサンフランシスコに戻り、ケーブルカーに乗ってフィッシャーマンズワーフに行ってクラムチャウダーを食べたり、ゴールデンゲートブリッジに行ったりと普通の観光を楽しみました。

b8taというショップで、面白いガジェットが色々と売っているので、ここにも行きました。
サンフランシスコ以外にもいくつか店舗があるようなので、近くにあったら寄ってみると楽しいと思います。

b8ta内部の写真

現地での必携アイテムClipper Card

Clipper Card実物の写真 plain

Clipper Cardという交通系のICカードで、Caltrain・BART・VTA・Muniなどサンフランシスコやサンノゼなどで移動に使える複数の交通機関に乗ることができます。さらに、都度チケットを買うより少し安くなりますので、着いたら初日に入手しておくと便利です。大きめの駅や、Walgreenというドラッグストアチェーンで入手・チャージできます。

バスや電車の時刻表は一応事前に公式サイトなどから入手していましたが、実際現地ではほとんどiOSのMapアプリの経路案内に従って行動しましたが何も困りませんでした。

まとめ

というわけで、非常に充実した10日間でした。チケット代・渡航費・宿泊費等合わせるとかなりの額になりますが、ありがたいことに前後の観光日程以外は全て経費で行かせてもらうことができました。来年も自分や他のメンバーが参加できるように頑張るぞという気持ちです。

おなじみの採用情報

freee ではモバイルエンジニアを募集中です。 ご興味がある方は是非一度弊社に遊びにいらしてください!

スモールビジネスの未来をアプリで切り拓くモバイルエンジニア募集! - freee 株式会社のモバイルエンジニア中途の求人 - Wantedly

jobs.freee.co.jp

KubernetesでのService公開方法に関する検証 - Ingress Controllerの活用

freeeでSREをしている河村(at-k)です。

freeeでは、既存・新規サービスのマイクロサービス化を推進しており、効率的なマイクロサービスの運用を実現するためにKubernetesを積極活用しています。Kubernetesはコンテナのオーケストレーションツールであり、コンテナ化されたマイクロサービスを管理・運用していく上で大きな効果が期待されます。

Kubernetesでは、複数のノード(例えばAWS EC2 Instance)を組み合わせてクラスタを構成し、そのクラスタ上にコンテナが指定された構成(manifest)で配置されます。Kubernetesはコンテナ構成を自律的に維持する機能を持ち、運用コストや耐障害率を改善します。また、クラスタに配置されたサービスに対しては、具体的などのノードにコンテナをスケールするか、といった詳細にとらわれることなく、宣言的にサービスを定義し、細かな運用はKubernetesにまかせるといったことができます。本稿では後者の、Kubernetes内サービスを外部に公開する手法について行った検証を解説します。

Kubernetesクラスタ内のサービスを公開する方法はいくつかありますが、最近社内で検証を行ったIngress Controller、特にNGINX Ingress Controllerについて紹介し、導入方法及び、カスタマイズ方法としてgRPC通信を有効にする手順を解説します。他の方法としては、例えばIstioや、envoyを利用する、ということも考えられましたが、freeeではNGINXの本番運用経験が豊富なことと、Ingress以外でもKubernetes上でNGINXを利用するあてがあったこと、envoyでないとできないというクリティカルな要件が「まだ」なかったこと、Ingressの実装としてはNGINX Ingress Controllerが一番こなれている(機能の豊富さとメンテナのアクティブさ、本番事例)といった点を考慮しました。

Kubernetesについてある程度の基本的知識を想定していますが、公式が提供しているTutorials - Kubernetesがよくまとまっており、1時間程度でキャッチアップ出来ますので、興味があればこの機会にいかがでしょうか。

Minikubeを使ったサービスの公開

まず例として、Minikubeを使った公式チュートリアル(Hello Minikube - Kubernetes)をベースに、サービスの外部公開まで実施します。MinikubeのインストールとImageの作成までは省略しますが、以下のコマンドで指定しているhello-nodeは、上記の公式チュートリアルで作成した、”Hello World!” を返すWeb ServerのImageです。

> kubectl run hello-node --image=hello-node:v1 --port=8080

> kubectl expose deployment hello-node --type=LoadBalancer

> kubectl get svc
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node     LoadBalancer       10.96.19.86     <none>        8080:32623/TCP   1m

> minikube service hello-node --url
http://192.168.99.100:32623

> curl http://192.168.99.100:32623
Hello World!

LoadBalancer Type(NodePort Typeでも可)のServiceを作成し、Service毎に割り当てられたポート(例では32623)を通してアクセスします。この様な方法は、サービスがどこで動いているのか一見してわかりやすく感じます。しかし、サービスを追加するたびに、未使用portを払い出したり、portへのネットワーク疎通を確保するなどのKubernetesの外側のインフラを別途整備する必要があります。公開するサービスが少なければ良いですが、数が増えてくると煩雑になります。

参考

Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?

Services - Kubernetes Ingress - Kubernetes

Nginx Ingress Controllerを用いたサービス公開

そこで、次に紹介するIngressとIngress Controllerを用いて、それらの課題の解決を図ります。Serviceの前段にIngressを配置する構成で、それらのIngressに対し、ルーティングを行うIngress Controllerがクラスタ内に最低1つ置かれます。Ingress ControllerはInboundトラフィックに対し、要求ホスト名とIngressで公開されるホスト名を突き合わせてルーティングを行います。先程の例と比較すると以下の図の様になります。

Ingress Controllerを使った構成とそうでない構成との違いの図。Ingressを使わない場合はサービスごとにポートを別々にしているが、Ingressを使用した場合は同じポートで2つのサービスを公開している

詳しくは実際の動作を見ていただくほうがわかりやすいかと思うので、ここからIngress Controllerの導入と動作例を見ていきます。Ingress Controllerとして利用できるものはいくつかあるようですが、ここではNGINX Ingress Controllerを試しました。Kubernetesが公式に開発していること、NGINXベースで高いスケーラビリティが期待できること、また、gRPCに対応していること、が採用理由です。

標準設定でのインストール

helm chartが用意されているので、標準的設定であればクラスタへのインストールは比較的容易です。helmはKubernetesにおけるパッケージ管理ツールで、パッケージの検索、インストール、標準設定からのカスタマイズ、設定のrevision管理、などの便利な機能が提供されています。ここでは詳細は省略します。

まずはinstall。

> helm search nginx-ingress
NAME                    CHART VERSION   APP VERSION     DESCRIPTION
stable/nginx-ingress    0.20.1          0.14.0          An nginx Ingress controller that uses ConfigMap...

> helm upgrade --install nginx-ingress stable/nginx-ingress

> helm list
NAME            REVISION        UPDATED                         STATUS          CHART                   NAMESPACE
nginx-ingress   1               Sun Jun 17 22:44:48 2018        DEPLOYED        nginx-ingress-0.20.1    default

helm installで何が行われるかは、以下のコマンドを実行することで、具体的にどういったmanifestが生成・適用されるかを確認することが出来ます。

> helm upgrade --install nginx-ingress stable/nginx-ingress --dry-run --debug | grep Source
...
# Source: nginx-ingress/templates/controller-service.yaml
# Source: nginx-ingress/templates/default-backend-service.yaml
# Source: nginx-ingress/templates/controller-deployment.yaml
# Source: nginx-ingress/templates/default-backend-deployment.yaml
...

Service/Deploymentがそれぞれ2つ宣言されていることがわかります。1つはIngress Controller本体、もう一つのdefault backendは、定義されていないhost nameでアクセスされた場合に用いられるServiceです。kubectlで配置されたServiceを見てみます。

> kubectl get svc
NAME                            TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress-controller        LoadBalancer   10.103.136.223   <pending>     80:30774/TCP,443:31153/TCP   35m
nginx-ingress-default-backend   ClusterIP      10.106.62.223    <none>        80/TCP                       35m

動作検証

続いて、ingressの設定を行います。

> kubectl expose deployment hello-node --type=ClusterIP --name hello-node-svc --port 8080
service "hello-node-svc" exposed

> cat << EOF | kubectl create -f -
pipe heredoc> apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-world
spec:
  rules:
  - host: hello-world
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-node-svc
          servicePort: 8080
EOF

> kubectl get ingress
NAME            HOSTS              ADDRESS   PORTS     AGE
hello-world   hello-world                80        1m

このとき、ingress controllerのlogを見ていると以下のようにingressの追加が自動で検出され、設定が反映されたことがわかります。

> kubectl logs nginx-ingress-controller-786dc4f648-zlcqz -f

I0617 14:14:29.430140       6 event.go:218] Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"hello-world", UID:"bfa92545-7238-11e8-b043-080027992c84", APIVersion:"extensions", ResourceVersion:"995305", FieldPath:""}): type: 'Normal' reason: 'CREATE' Ingress default/hello-world
I0617 14:14:29.546514       6 controller.go:177] ingress backend successfully reloaded...

それではpodにアクセスします。

> minikube service nginx-ingress-controller --url
http://192.168.99.100:30774
http://192.168.99.100:31153

> sudo sh -c 'echo 192.168.99.100 hello-world >> /etc/hosts'

> curl http://hello-world:30774
Hello World!

Ingressに設定したhost nameを使うことで、hello world podにアクセス出来ました。

同じ要領で、"Hello World!"の代わりに"Hello Ingress!"と返すServiceを作ります。ImageとDeploymentの作成は省略、hello-ingress-nodeというDeploymentを作成したとします。

> kubectl expose deployment hello-ingress-node --type=ClusterIP --name hello-ing-node-svc --port 8080
service "hello-ing-node-svc" exposed

> cat << EOF | kubectl create -f -
pipe heredoc> apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hello-ingress
spec:
  rules:
  - host: hello-ingress
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-ing-node-svc
          servicePort: 8080
EOF

> sudo sh -c 'echo 192.168.99.100 hello-ingress >> /etc/hosts'

> curl http://hello-ingress:30774
Hello Ingress!

hello-worldとhello-ingressは、host nameは異なりますが、どちらも同じIPを指しており、portも同じなので、ネットワーク的には同一のものを参照しています。host nameを元にIngress Controllerが振り分けを行っています。

この様に、Ingress Controllerを配置しておけば、新しいサービスが追加される際に、公開ホスト名を定義したIngressを設定することで自動でサービスまでの動線を整備してくれます。これらの作業はKubernetes内で完結しているため、クラスタ内・外での責任範囲が明確化され、運用の簡易化・権限委譲を効率的に進めることが出来ます。 なお、ホスト名をDNSに登録する必要がありますが(例では/etc/hostsに登録)、こちらについてもexternal-dnsを使うことで、例えばAWSではIngressの追加時にRoute 53に自動設定することが出来ます(今回はMinikubeでの検証なので省略します)。

参考

Kubernetesのexternal-dnsでRoute53 RecordSetを自動作成する - Qiita

external-dns/aws.md at master · kubernetes-incubator/external-dns

カスタマイズ - gRPC用追加設定

デフォルトの設定でもおおよその目的は達せられましたが、実際の運用では設定をカスタマイズしたくなることもあると思います。ここでは、NGINX Ingress ControllerのBackendにgRPCアプリケーションを配置するための手順を説明します。 先にも書いたとおり、NGINX Ingress ControllerはgRPCに対応していますが、いくつか追加設定が必要になります。対象は、Ingress、Ingress Controller、場合によってはapplicationにも手を入れる必要があります。

検証環境として、grpc/grpc-goで配布されているgreeter_serverを配置した以下のDockerfileのコンテナを用いました。同様にgreeter_clientを使って疎通検証を行います。

FROM grpc/go:1.0
EXPOSE 50051
RUN go get -u google.golang.org/grpc/examples/helloworld/greeter_server
RUN go get -u google.golang.org/grpc/examples/helloworld/greeter_client
CMD greeter_server

Ingressの設定

gRPCサービスであることをAnnotationに記載する必要があります。metadataにannotationsとして、grpc-backendであることを明示します。

cat << EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/grpc-backend: "true"
  name: hello-grpc
spec:
  rules:
  - host: hello-grpc
    http:
      paths:
      - path: /
        backend:
          serviceName: hello-grpc-svc
          servicePort: 8080
EOF

Ingress Controllerの設定

NGINX Ingress ControllerのHTTPポートのデフォルトの設定では、HTTP2が有効になっていません。gRPCをHTTPで公開する場合は、追加の設定が必要です(HTTPSの場合は不要)。デフォルト設定で、HTTP2でIngress ControllerのHTTPポートにアクセスすると、次のようなログが出力されます。

172.17.0.1 - [172.17.0.1] - - [17/Jun/2018:16:26:34 +0000] "PRI * HTTP/2.0" 400 174 "-" "-" 0 0.001 [] - - - -

修正が必要な設定箇所は以下のあたりです。listen 443はhttp2が設定されていますが、listen 80にはされていません。

minikube > k exec nginx-ingress-controller-786dc4f648-2k4hh cat /etc/nginx/nginx.conf | grep listen
                listen 80 default_server  backlog=511;
                listen [::]:80 default_server  backlog=511;
                listen 443  default_server  backlog=511 ssl http2;
                listen [::]:443  default_server  backlog=511 ssl http2;

そこで、修正を入れた設定ファイルをロードするように、helm chartsを補正します。NGINX Ingress Controllerは、カスタムテンプレートからnginx.confを生成する仕組みになっているため、このテンプレートを自前のものに差し替えます。

まず、オリジナルのテンプレートを取ってきます。

> kubectl exec nginx-ingress-controller-786dc4f648-2k4hh cat /etc/nginx/template/nginx.tmpl > nginx.tmpl.org

これに対し、以下のように変更を加えます。わかりにくいですが、listen 80 にhttp2を追加しています。

> diff nginx.tmpl.org nginx.tmpl
702c696
<         listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}};
---
>         listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }} http2{{end}};
704c698
<         listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{end}};
---
>         listen {{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }} http2{{end}};
708c702
<         listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{ end }};
---
>         listen {{ $address }}:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }} http2{{ end }};
710c704
<         listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}{{ end }};
---
>         listen [::]:{{ $all.ListenPorts.HTTP }}{{ if $all.Cfg.UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $server.Hostname "_"}} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }} http2{{ end }};

これを元にconfigmapを作成します。

> kubectl create configmap nginx-custom-tmpl --from-file=nginx.tmpl
configmap "nginx-custom-tmpl" created

configmapをマウントするようにvalues.yamlを書き換え、helm upgradeします。

> cat <<EOF > values.yaml
controller:
  name: controller
  ## Override NGINX template
  customTemplate:
    configMapName: nginx-custom-tmpl
    configMapKey: nginx.tmpl
EOF

> helm upgrade --install nginx-ingress stable/nginx-ingress -f values.yaml
参考

ingress-nginx version 0.13 for grpc not work · Issue #2444 · Kubernetes/ingress-nginx

動作確認

アクセス先を、Nginx Ingress Controllerに変更したgreeter_clientを実行します。

> go run greeter_client/main.go
2018/06/18 02:01:40 Greeting: Hello world

うまく疎通したようです。

アプリケーション側対応(必要であれば)

ここまででIngress ControllerのgRPC対応は完了ですが、アプリケーション側に修正が必要なケースもあります。gRPC通信が時々うまくいかず(全部失敗するわけではない)、NGINX Ingress Controllerのログに

upstream sent invalid http2 table index: 64 while reading response header from upstream

といったエラーが出ている場合は、go-grpcの既知のバグが原因である可能性があり、その場合は、修正PRが取り込まれたバージョンが必要です。詳しくは下記のIssueを参考にしてください。

gRPC servers cannot use dynamic HPACK · Issue #2405 · kubernetes/ingress-nginx

終わりに

Kubernetesのサービス公開方法として、Nginx Ingress Controllerを使った方法を紹介しました。個別にNodePort設定をするよりも、シンプルかつ容易にサービスの外部公開が可能になります。

Kubernetesはコンテナ管理のための新しい基盤であり、日々多くの機能が提案・追加されています。そのため、情報が不足していたり、まだデファクトが定まっていなかったりする部分が多く、学習・導入コストが高くつく可能性があります。一方で、Kubernetesの提供するフレームワークは非常に強力であり、複雑化しがちなマイクロサービス構成を、集約・統合的にまとめることで、サービスの運用を大幅に効率化できる可能性を持っています。本稿が、読者の皆様の何かしらのご助力になれば幸いです。