Vue3のSuspenseを使ってみた

Vue3のSuspenseについて興味があったので、試しに触ってみた内容をまとめます

Suspenseって?

非同期処理が解決されるまで、コンポーネントの代わりにフォールバックコンテンツをレンダリングする特別なコンポーネントです。 今まで、computedで変数を定義して、v-ifで表示制御していたのを簡単に書けるようにしたもののようです。

実際に書いてみた

親コンポネ

親コンポネでは以下のように書きます。

<template>
  <Suspense>
    <template #default>
      <ArticleList/>
    </template>
    <template #fallback>
      Loading...
    </template>
  </Suspense>
</template>

<script lang="ts">
import {defineComponent} from 'vue'
import ArticleList from "./components/ArticleList.vue"

export default defineComponent({
  components: {
    ArticleList
  },
})
</script>

Suspenseは、2つのスロットを持っています。

default

最終的にレンダリングするコンテンツ

fallback

defaultに定義したコンテンツの非同期処理が完了するまでのコンテンツ


今回作ったサンプルだと、子コンポネの非同期処理が終わるまではLoadingと表示されます。

子コンポネ

非同期処理を行う子コンポネでは、以下のようにかきます。

<template>
  <div class="card-wrapper">
    <div class="card" v-for="(article, key) in articles" :key="key">
      <h1>{{ article.title }}</h1>
      <div>{{ article.content }}</div>
    </div>
  </div>
</template>

<script lang="ts">
import {defineComponent} from "vue";

export default defineComponent({
  async setup() {
    const sampleArticles = [
      {title: '記事A', content: '記事Aの内容'},
      {title: '記事B', content: '記事Bの内容'},
      {title: '記事C', content: '記事Cの内容'},
    ]

    const fetchArticles = () => {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve(sampleArticles)
        }, 3000)
      })
    };
    const articles = await fetchArticles();

    return {
      articles
    }
  }
});
</script>

通常ではAPIから何らかのデータを取得して、取得したデータを表示すると思いますが 今回は、簡潔にするためにsetTimeoutで擬似的に非同期処理にしています。 ブログの記事一覧を引っ張ってくるAPIを叩いているイメージで書いています。


このように書くことで非同期処理が終わるまではLoadingと表示され、終わったら記事が表示されるようになります。 f:id:ryonnsui1201:20210329004426g:plain

エラーが発生した際のハンドリング

非同期処理が失敗することもあると思います。
その場合は、onErrorCapturedでエラーを補足し、エラーを表示します。
onErrorCapturedは子孫コンポーネントからエラーが捕捉されるときに呼び出されるライフサイクルフックです。

<template>
  <div class="card-list">
    <div v-if="error">
      {{ error }}
    </div>
    <Suspense v-else>
      <template #default>
        <ArticleList/>
      </template>
      <template #fallback>
        Loading...
      </template>
    </Suspense>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, onErrorCaptured } from 'vue'
import ArticleList from "./components/ArticleList.vue"

export default defineComponent({
  components: {
    ArticleList
  },
  setup(){
    const error = ref(null);

    onErrorCaptured((e) => {
      error.value = e
      return true;
    });

    return {
      error
    }
  }
})
</script>


f:id:ryonnsui1201:20210329011320g:plain

まとめ

以上、Suspenseの使い方でした。 とてもシンプルに非同期処理の際の表示処理を書けるので便利ですね。

参考

Suspense - new feature in Vue 3 - Vue.js Tutorials

ふりかえりの設計からファシリを最近2回したのでふりかえる(熱気球とStory of Storyやった)

f:id:skmtko:20210318185506p:plain

この記事は個人ブログと同じ内容です

sakamotoko.hatenablog.jp


agent bank開発チームのさかもとです。タイトルの通り、最近やったふりかえりに関して書きます!

話したいこと

先週と先々週にそれぞれ毛色の違ったチームふりかえりを行った。
さらにその2つのふりかえりに対してふりかえりの設計と、ファシリテーションを担当したので、そのことについて個人的に整理をする。

やったこと、わかったことを整理してみる。

本題

やったこと(大まかに)

まず、「毛色の違ったチームふりかえりって何やねん」ですが、

  • ① 3名で約1ヶ月分くらいのふりかえり
  • ② 8名で1スプリント(1週間)のふりかえり

を実施しました。

各ふりかえりの前には、「ふりかえりの後にどうなれていたらよいか」を上げるなどして、ふりかえりの手法の選定と、ふりかえりを実施する場所を準備するなどした。
ふりかえりの当日には、ファシリテーター役として、ふりかえりの進行を行った。

① 3名で約1ヶ月分くらいのふりかえり

自分を含めた開発チームのメンバーx2, 副業メンバーx1 の3名で行った。
どういう集まりかとういうと、約1ヶ月ほど前から、副業メンバーにジョインいただき、プロダクトのe2eテスト導入を進めてもらっているので、それに関わっているメンバーの集まりだった。

以下のような属性を含むので、さすがにふりかえりちゃんとしたほうがいいでしょうと思い、ふりかえりを計画 - 新しい試み - 新しくジョインしたメンバー - 副業メンバー - なかなか複雑なプロダクト

ふりかえりは、「熱気球」という手法をメインに取り入れて行った。

② 8名で1スプリント(1週間)のふりかえり

自分のいるagent bank開発チームではスクラム開発を採用しているので、スプリント(うちでは1スプリント=1週間でやってる)の節目に、次のスプリントをより良くするためにという目的で、ふりかえりを行っている。

最近は、「KPTA」という手法を用いてふりかえりを行っているが、この前の回のときに「他の手法でもやりたい!」と自分が発言したのがきっかけで、この回ではいつもとはいつもとは違う手法でやってみることになった。
結果的に「Story of Story」をやってみた。

やったことと、わかったこと(詳細に)

2回のふりかえりでやったことをそれぞれ説明する

① 3名で約1ヶ月分くらいのふりかえり

上に書いていたものを再度整理する。こんな感じのチームでのふりかえり。

  • 自分を含めた開発チームのメンバーx2, 副業メンバーx1 の3名
  • プロジェクトとして
    • 新しい試み
    • 新しくジョインしたメンバー
    • 副業メンバー
    • なかなか複雑なプロダクト
  • メンバージョインから1ヶ月たった

やったこと

このふりかえりの後にどうなっていたいか?を出す(ふりかえりの目的)

スクラムマスター(以降SM)の協力を得て、自分を含めた開発チームのメンバーx2 + SMの3人でふりかえりの設計を行った。
まず、手法を選定するために、ふりかえる期間にどんな事があって、ふりかえりをした結果、我々がどういい状態になっていたいかを出しあった。

f:id:skmtko:20210318114017p:plain

割と、コミュニケーションや、お互いの状況把握の点に関して少し改善の余地がありそうな印象だったので、上のようなアイデアが出た。

これをベースに、どんな手法を採用するかを考えていった。

ふりかえり手法の選定

ふりかえりチートシートや、https://www.funretrospectives.com/ を参考に、ふりかえり手法を選定していった。 結果的には、「何度かやったことがある」「楽しい」を理由に熱気球を採用することになった。あとで書くが、結果楽しかった。

参考: ふりかえりチートシート qiita.com

参考: 熱気球 blog.engineer.adways.net

ふりかえりの構成を考える

手法の選定も、ふりかえりの構成にはいるだろうなあとは思うけど、細かいことは気にしない。

大きな構成としては、以下のようになる

  • 場の設定 
  • データ収集(熱気球に決定)
  • イデア出し(熱気球に決定)
  • 次やることの決定
  • ふりかえりのふりかえり

それぞれどのようにすすめるかを決めていった。

ふりかえりの目的として、「現状の進捗把握」も上がっていたので、熱気球の前に現状把握のステップを追加した。

結果として、 以下のような構成になった

  • 場の設定 → ハピネスレーダー(顔文字でこの1ヶ月を表現)
  • データ収集① → 現状把握
  • データ収集②、アイデア出し → 熱気球
  • 次やることの決定 → 熱気球で出たアイデアから、投票などして決める(その場の状況次第)
  • ふりかえりのふりかえり → 雑談形式

MTGを設定していた時間が1時間だったので、それに収まりきれうように、書くステップに必要な時間を割り振ることまでした

事前にデータ収集

各ステップの時間を設定したところ、「現状把握の時間」そんなに時間取れないな、というのが判明した & おそらく0からやると半端なく時間がかかるのが予想された。
解決策としては、「前もって聞けば分かるっしょ」ということで、slackで事前に質問して回答をもらっておいた。

結果聞いててよかった、ふりかえりの時間では読み合わせて認識合わせる&わからんこと質問する に集中することができて時間を効率よく進めれた。

ふりかえりに必要な物理的な場を作る

以下のツールを使用してふりかえりを行うことを決定した

Miroには、ふりかえり用のボードを用意しその中に、各ステップでやること、必要な時間、熱気球のイラストを事前に設置して、スムーズに始めれるように準備した。

ここまでしてやっとふりかえりの準備 DONE

実際にふりかえりを実施

SMにファシリテーターをお願いしたかったがきれいに予定がかぶっていたので、自分がファシリテーターをしつつ、ちょこちょこふりかえりにも参加するのをやった。

ちなみに、熱気球やった形跡はこんな感じになりましたf:id:skmtko:20210318124420p:plain

次やることの決定で、ほぼすべてのアイデアを次やることにした

出たアイデアの実施難易度が低いものが割と多かったので、結果的に出たアイデア全てに対して、具体的にどういうアクションが取れるかを決めて、次やることとして整理できた。 アイデア整理などして、5個の次やるアクションが出せた。

10分オーバー

1時間のMTGであったが、すべて完了するまでに10分オーバーしてしまった。今回は、幸い副業メンバーの方の後の予定が空いていたため、最後まで全員参加で、ふりかえりのふりかえりまで実施できた。

わかったこと

少人数だとスムーズに進む

いつもやっているチームのスプリントふりかえりだと、だいたい5-8名ほどで実施してるが、今回は3名だけだったので、凄くスムーズに進んだ気がする。

というのも、話す人少ないので、必然的に参加者が自発的に発言しやすい状態になっていたのかもしれない。
また、大人数だと、全員分話し聞こうとして物量てきに時間食っちゃうみたいなことになる。

ハピネスレーダー面白い

場の設定に使ったハピネスレーダーが意外と面白かった。
ネガティブそうな顔文字を貼っている人がいて不安になりながら話を聞いてみると、「なるほど、そんなことあったんか〜」みたいな予想外の展開あった。

貼られたのはこれで、「ヤバイドウシヨウ」ってなった。 f:id:skmtko:20210318123443p:plain
聞いてみたら深刻な内容ではなかったので一安心した

ふりかえり始めての体験の人だったが、楽しく質の高い場にできた

副業メンバーが、今回やったようなふりかえりをやるのが、初めてとのことだったが、とても楽しかったとの感想を貰えることができた。

次回1.5ヶ月くらい立ってから再度やりたいねとなったので、ほんとにちゃんと準備かいがありました。
よかったーーーーー


8名で1スプリント(1週間)のふりかえり

上の熱気球の文でだいぶ、力尽きた感あるので、こっちはシンプルな文章になりそう...

やったこと

いつもと違うふりかえり試したい発言

この回の前の回のふりかえりのふりかえり最後のSMの「なんにかやってみたいことあります?」問に対して「いつも違う(KPTAじゃない)ふりかえり手法でやってみたい」と発言したことにより、今回設計からファシリまでを務めることになりました。

SMの支援を受けながら進めた。

ふりかえり手法の選定

まず、ここでもふりかえりチートなどを参考に、どんな手法を取るかというのを考えていきました。

毎日の終了時に夕会としてその日あったことや次何やるかを、YWTを使って簡単に振り返ってます。

こんな感じ f:id:skmtko:20210318151935p:plain

縦長の四角が一日ごとのフレームでその中で上から「Yやったこと」「Wわかったこと」「Tつぎやること」をためています 付箋の色は、赤→ポジティブ、黄→ニュートラル、青→ネガティブ を表現してもらってます

このスプリントでは、新しくジョインしたメンバーが開発に本格的に参加し始めた & メンターと一緒に進めている様子がなかなかうまくいっているようだったので、良い学びが多かったのでは、YWTの結果もポジティブな付箋多めかな?という肌感だった。

良い学びを伸ばす系のふりかえりにしてみようというのと、毎日のYWTの内容を生かしてできないかなということで、Story of Storyを採用してみることにした

ちなみにふりかえりチートシートには、こんなふうに書いてた

f:id:skmtko:20210318170112p:plain 「良いところを伸ばす◎」なるほど良さそう。

Story of Story の参考webでみっけたの英語のページしかなかった...

www.funretrospectives.com

ふりかえりの構成を考える

結果的に以下のような構成に落ち着いた

  • 場の設定 → ハピネスレーダー(①でやったときに楽しかったので、味をしめたため)
  • データ収集① → 毎日ためてたYWTのYだけさらっと眺める
  • データ収集② → Story of Story
  • イデア出し → Story of Storyで集めた
  • 次やることの決定 → 出たアイデアから、Effort x Value という手法を使って、絞り込み、やることの具体案を決める話をする
  • ふりかえりのふりかえり → 3人くらいに話してもらう

次やることの決定に関しては、いつもは投票によって、アクションを決める対象を絞り込んでいるが、ここもチャレンジしようということで、Effort x Value という手法を取り入れてみた。 簡単に説明すると、Effort(必要な努力)と Value(得られる価値)の2軸のマトリックスに対して、アイデアマッピングする。より少ない努力で得られる価値の大きいアイデアに対してアクションを考えるというもの。
マッピングする中で、どうやったら少ない努力にできるかとか、アイデアの共通認識を合わせる的なやつです

www.funretrospectives.com

ふりかえりに必要な物理的な場を作る

Miroにこんな感じのボードをつくった、 f:id:skmtko:20210318173310p:plain

会話はDiscordで音声チャットをしながらおこなう。 また、①のときと同様にスッテプで何をするのかと、各ステップでどのくらい時間を使うかを見積もって記した。

実際にふりかえりを実施

実際にStory of Storyやった形跡はこんな感じになった

f:id:skmtko:20210318173938p:plain

わかったこと

ふりかえり慣れている人達がやっても、ハピネスレーダー楽しい

前回味をしめて、今回もやってみたがやっぱり楽しかった。 これからも困ったらこれやりそう

Story of Story 結構時間かかる

ステップとして、以下があるが、なかなかステップが多かったのと、すべてのステップで少しづつ予定の時間をオーバーしてた。ざっくり2倍づつくらい。

  • 期間の間に起きたことを書き出すステップ(以下を書き出す)
    • 事実
    • コミュニケーション・コラボレーション
    • 続けること
    • 避けること・やめること
  • 書き出したものを皆で共有する
  • 上で書き出したものから以下と書き出す
    • 個人の学び・成長
    • チームの学び・変化

事実の付箋がとても大量に書き出された事により、各ステップで、全部を見ながら次の付箋を貼るのがかなり負担だったみたい。 起きた出来事が多かったり、参加者が多いふりかえりに使う場合は、注意が必要かなあとおもった。 もしくは、テーマを絞るとかしても良かったのかな?

プロブレムに焦点が当たりづらかった

毎回やっているKPTAに比べると、プロブレム(課題)に対して焦点が当たりづらかあったという感想があった。
確かに、割と良いコミュニケーションや、良い学びに対して焦点が行きがちで、「このモヤモヤに対して話そうぜ」てきな雰囲気に行きづらかった感がある。

また、データの量が多すぎてアイデア出すのが大変みたいな感想もあった。

Effort x Value の使い方工夫必要そう

イデアの絞り込みにEffort x Value を使ってみたが、これもプロブレムに焦点が行きづらい要因だったかも。 プロブレムの解決って、大体すごいパワー必要そうなことが多い気がするので...

なので、ここぞというときに使えるように使い所を探ってみようと思う。

大人数疲れる!

6人+ファシリ(俺)+SM(俺の支援)みたいな感じだったんですが、みんなの出したアイデアを全部みたり、話を深ぼったりすると単純に時間がかかるし、超パワーがいりますね。

まとめ

2つの毛色のちがうふりかえりの設計から、ファシリまでやってみたんですが、 人数や、期間、目的によって適したやり方全く違うんだなと、実感した。

手法によって、得意不得意があるっぽいので、どんな手法がどんなときに効果的かみたいなことを実践で覚えていきたいなとおもった。
また、既存の手法も目的によってカスタマイズしながら進めれるようになりたい。

オンライン、オフライン関係なく少人数のほうが進めやすいんだろうなとは思うが、オフラインだと、途中で少人数に分離して合流的なことするにも、ツールとかの準備必要でめんどいなあ。ガッツリやるときは、zoomとかGoogleMeetのブレイクアウトセッション準備したりなんしたりするのだろうなあ...

最後に定期的に行っているスプリントのふりかえりで、実験的な事ができたのは、チームとしてとても良かったなと思う。
引き続きチャレンジしていきたい!

AWS Aurora Backtrack(バックトラック)で DB データを特定日時の時点に巻き戻す

この記事は個人ブログと同じ内容です

www.ritolab.com


AWS が提供しているリレーショナルデータベース Amazon Aurora には Backtrack(バックトラック)という機能があり、これを用いると現在のインスタンス上で特定の時点へのデータの巻き戻しを行なう事ができます。

今回はこの Backtrack を使って Aurora のデータを特定時点へ戻したり進めたりしてみたいと思います。

Aurora Backtrack

Aurora のデータをコンソール上から復元する際に、スナップショットからのリカバリやポイントインタイムリカバリは新しい DB インスタンスを作成するためアプリケーション等、参照している側にもエンドポイントの変更が必要になる一方で、バックトラックは現在の DB クラスタをそのまま特定の時刻まで巻き戻すため、比較的容易に行えるのが利点。

docs.aws.amazon.com

データベースへ変更を加えるたびに新しいログレコードが作成され、ログシーケンス番号 (LSN) が生成されます。巻き戻し機能を有効にすることで、LSN のストレージ用クラスターに FIFO バッファーがプロビジョニングされます。これにより、素早いアクセスと秒単位で測定されたリカバリ時間が利用できるようになります。

引用元:Amazon Aurora Backtrack – 時間を巻き戻す

Aurora DB クラスタの作成

まずは AWS コンソール画面から、Aurora インスンタンスを作成します。

f:id:ro9rito:20210312170436p:plain

バックトラックの設定項目は以下になっています。

f:id:ro9rito:20210312170453p:plain

ターゲットバックトラックウインドウ
何時間バックトラックを行えるようにするか。最大 72 時間で、どの時点まで巻き戻せるようにするかの設定です。

キャプチャの通り、ここでは 5 時間としました。

その他、基本的な設定項目はすべて最小構成で行っています。

Auroraクラスタを作成しました。

f:id:ro9rito:20210312170538p:plain

検証データについて

バックトラックを行うにあたり、1 分おきに insert したデータを作成しました。

f:id:ro9rito:20210312170605p:plain

表示されているのが全レコードです。このデータに対して Backtrack を行っていきたいと思います。

Backtrack を行う(データを巻き戻す)

AWS コンソール画面から実行します。対象のクラスタを選択して アクション → バックトラックを押下します。

f:id:ro9rito:20210312170731p:plain

DB クラスターのバックトラック画面に遷移するので、まずは 11:30:00 時点のデータまで巻き戻してみます。

f:id:ro9rito:20210312170753p:plain

復元可能な最新時刻っていうのは、巻き戻せる最も過去の時刻(=それ以上過去は指定できない)です。

実行後はクラスタの詳細画面に遷移しますが、上部にバックトラックを実行している旨のメッセージが表示されています。

f:id:ro9rito:20210312170812p:plain

バックトラックが完了すると、以下にように「正常にバックトラックしました。」と表示されます。

f:id:ro9rito:20210312170829p:plain

データを確認してみます。

f:id:ro9rito:20210312170849p:plain

最新レコードが 11:29 のものになっています。しっかり 11:30:00 時点のデータに戻っていました。

redo 的なこともやってみる(巻き戻した時点から未来時間へデータを進める)

戻した時刻よりも未来の時刻を指定して、データを未来へ戻してみます。(未来へ戻すとかちょっとややこしい)

現在の 11:30:00 時点から 12:00:00 時点のデータへ進める事ができるか確認してみます。

f:id:ro9rito:20210312170934p:plain

バックトラック完了後、データを確認してみます。

f:id:ro9rito:20210312170953p:plain

12:00:00 時点のデータへ進められる事も確認できました。

最後に、用意したデータの最終レコードである 12:03:01 時点のデータに戻します。(12:00:00 -> 12:03:01)

f:id:ro9rito:20210312171011p:plain

こちらも問題なく、データを戻す事ができました。

f:id:ro9rito:20210312171030p:plain

ちなみに当然ながらバックトラック日時の設定の際は、現在日時よりも未来日時を指定するとしっかり怒られます。

f:id:ro9rito:20210312171043p:plain

まとめ

バックトラックを 3 回行いましたが、開始してから完了までの時間は、いずれも 1 分 10 秒ほどでした。(変更レコード量によってここの時間は変動するのかは気になるところ)

料金については、変更レコードの保存量 × 保持時間で掛かるようです。東京リージョンでは時間あたりの料金が 0.014USD/変更レコード100万件 となっていました。(2021/03/06現在)

aws.amazon.com

操作を誤りあるレコードを削除してしまったとか、バッチが失敗してデータが中途半端な状態になってしまった等の時には役立つなと感じました。

Backtrack 普段は出番のない機能ですが、いざという時に役に立つとても良い機能でした。

Kubernetesを学習するにあたって出てきた用語をまとめてみる

はじめに

agent bank開発を行っている北原です。

目的

  • 個人でKubernetes(以下k8s)を学習したときに関連用語がたくさん出てきて今現在ほとんど頭から抜けているため復習がてら用語をブログにまとめてみる

概要

  • ここでは、k8sについての概要説明等は、いたしません。以下をご参考ください。

kubernetes.io

k8sを構成する要素の概要と言葉

kubectl

  • K8s クラスタを操作するためのコマンド
  • Macならbrew install kubectlで入ります

コントロールプレーンコンポーネント

kube-apiserver

  • API サーバーは kubectl などの API クライアントからの REST リクエストを検証して API オブジェクトを構成、または、状態を報告する

kube-scheduler

  • ワークロード専用のスケジュール機能である

Kubernetesのスケジューラー | Kubernetes

kube-controller-manager

  • 制御ループを使ってシステム状態を調整する。モニタリングした現在状態から希望状態への遷移を実行する

cloud-controller-manager

Kubernetesのコンポーネント | Kubernetes

etcd

  • K8s クラスタのすべての管理データは etcd で保存される。

kubelet

  • 各ノードで動作する。
  • ボッッドとコンテナの実行
  • ポッドとノードの状態を API サーバーへ報告する
  • コンテナを検査するブローブを実行
  • 内臓する cAdvisor がメトリックスを集約して公開する
  • k8sが作成したものではないコンテナは管理しません。

kube-proxy

  • 各ノードで動作し、高可用性かつ低オーバーヘッドのロードバランシングを提供
  • サービスとポッドの変更を API サーバーで監視し、構成を最新状態に保ち、ポッド間とノード間の通信を確実にする
  • サービスの生成時に ClusterIP へのパケットをトラップして、対応するポッドへリダイレクトするように、iptables のルールを操作する
  • サービス名と ClusterIP をアドオンの DNS へ登録する

coredns

  • ポッドがサービス名から IP アドレスを得るために利用されている

kube-flannel

  • すべてのノードで実行され、複数のノードの間で IPv4 ネットワークを提供する。これによりコンテナ(ノード)は K8s 内部の IP アドレスでノードを超えて、疎通できるようになる
  • ネットワークポリシーを必要とする場合には、calico を使用しなければならない

calico-kube-controllers

  • calico のためのコントローラ。データストアとしての etcd を利用するために使われる

calico-node

  • 全てのノードで実行され、ノード間のコンテナ(ポッド)の疎通、アクセスコントロール、ルーティングを提供

kubernetes-dashboard

  • WebUI

metrics-server

  • heapster に代わり API の aggregation layer を通じて、K8s クラスタ全体のメトリクスを収集する

k8sを触る際によく出る言葉や概要

コンテナ

  • 必ずポッド内で実行する
  • 軌道に設定できる項目がある

ポッド

  • コンテナを実行するためのオブジェクトで、複数のコンテナを内包している

コントローラ

  • ポッドの実行を制御するオブジェクト

コンフィグレーション

  • コンテナ内のアプリケーションの設定やパスワードなどの情報は、デプロイされた「名前空間」から取得することが推奨されている。
  • 設定を保存する:ConfigMap(コンフィグマップ)
  • 秘匿情報を保存する:Secret(シークレット)
  • 名前空間下に保存された情報は、コンテナ内のファイルや環境変数として、アプリケーションのコードから参照できるようになる

k8sの状態を示す言葉と概要

ContainerCreating

  • イメージをダウンロード中、またはコンテナ起動進行中を表す。
  • ConfigMap や Secret をマウントできず、コンテナ生成が保留された時もこの値が表示される

CrashLoopBackOff

  • ボッド内のコンテナが終了し、次の起動まで待機状態になる。
  • コンテナ内のプロセスを見直す必要がある

Pending

  • ポッド生成の要求を受け取るが、1 つ以上のコンテナが作成されていない状態
  • リソース不足、ポリシー制約によってスケジュールできていないケースがあるため見直す

Running

  • ノードに対応づけられ、少なくとも 1 つのコンテナが実行中、開始中、または再起動中である

Terminating

  • コンテナへの終了要求シグナルが送られ、コンテナが終了するまで待機中
  • 猶予時間をすぎ、コンテナが終了できていない場合、強制終了する

Succeeded

  • 正常

Completed

  • ポッド内のコンテナが正常終了し存在している。削除されるまで存在し続ける。ポッド名を指定することでログやステータスを取得できる
  • ポッド内に複数のコンテナがある場合、第 1 コンテナが正常終了するとポッドは、正常終了として扱われる

Error

  • コンテナが異常終了した。
  • Completed の対義

Failed

  • ポッドないの少なくとも 1 つのコンテナが異常終了した

Unknown

  • 何らかの理由により、ポッドの状態を取得できない状態
  • また、ノード障害、マスターからノードの状態を取得できなくなったときにもこの表示になる

参考資料

kubernetes.io

Amazon ECS でタスクをスケジューリングして定期的に実行する

この記事は個人ブログと同じ内容です

www.ritolab.com


Amazon ECS には タスクをスケジューリングして動作させることのできる機能があり、これを用いることで毎日走らせたい処理など定期的に行いたい処理を実行する事ができます。

今回は AWS ECS の「タスクのスケジューリング」を使って、タスクを定期的に実行してみます。

ECS タスクのスケジューリング

ECS の画面から設定が可能ですが、内部的には CloudWatch Events Rule を作成してスケジュールを構成しているようですね。

Amazon ECS タスクのスケジューリング

docs.aws.amazon.com

ECS の構築

まずはベースとなるタスク定義やクラスタを作成しておきます。

  • Terraform (v0.14.3) で行います。
  • 起動タイプは FARGATE です。
  • コンテナのイメージは ECR に登録済みの前提です。

IAM の作成

ECS でタスクを実行する IAM Role 作成します。

main.tf

# IAM Role - ECS Task Execution for Scheduler
resource "aws_iam_role" "ecs_scheduler_task_execution" {
  name               = "EcsTaskExecutionRole-sample"
  assume_role_policy = file("policies/iam_role/ecs_task_execution.json")
}
# IAM Role Policy - ECS Task Execution for Scheduler
resource "aws_iam_policy" "ecs_scheduler_task_execution" {
  name        = "EcsTaskExecutionPolicy-sample"
  description = "Ecs Task Execution"
  policy      = file("policies/iam_policy/ecs_task_execution.json")
}
# Attach Policy to Role / Scheduler
resource "aws_iam_role_policy_attachment" "ecs_scheduler_task_execution" {
  role       = aws_iam_role.ecs_scheduler_task_execution.name
  policy_arn = aws_iam_policy.ecs_scheduler_task_execution.arn
}

読み込んでいる各ファイルの内容は以下です

policies/iam_role/ecs_task_execution.json

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

policies/iam_policy/ecs_task_execution.json

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

タスク定義・クラスタ作成

ECS のタスク定義・クラスタを作成します。

main.tf

# CloudWatch Logs - log group
resource "aws_cloudwatch_log_group" "ecs_scheduler" {
  name = "/ecs-scheduler"
}

# Task Definition
resource "aws_ecs_task_definition" "task_scheduler" {
  family                   = "scheduler"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = "256"
  memory                   = "512"
  container_definitions    = templatefile("task-definitions/scheduler.json", {
    log_group_name      = aws_cloudwatch_log_group.ecs_scheduler.name
  })
  execution_role_arn       = aws_iam_role.ecs_scheduler_task_execution.arn
}

# ECS Cluster
resource "aws_ecs_cluster" "task_scheduler" {
  name = "scheduler-cluster"
}

読み込んでいる各ファイルの内容は以下です

[
    {
        "name": "<< CONTAINER-NAME >>",
        "image": "<< AWS-ID >>.dkr.ecr.<< REGION >>.amazonaws.com/<< CONTAINER-IMAGE-NAME >>:<< CONTAINER-IMAGE-TAG >>",
        "cpu": 128,
        "memory": null,
        "memoryReservation": 128,
        "logConfiguration": {
            "logDriver": "awslogs",
            "options": {
                "awslogs-group": "${log_group_name}",
                "awslogs-region": "<< REGION >>",
                "awslogs-stream-prefix": "scheduler",
                "awslogs-datetime-format": "%Y-%m-%d %H:%M:%S"
            }
        }
    }
]

<< ... >> としている部分は各々で必要な値が入ります。

これでベースとなる ECS 環境が構築できました。

タスクのスケジューリング設定

ここから ECS のタスクスケジューリングを設定していきます。

Cloudwatch Events を設定することでタスクスケジューリングを実現します。

IAM Role の作成

CloudWatch Events の IAM Role を作成します。

main.tf

# IAM Role - ECS Events
resource "aws_iam_role" "ecs_events" {
  name               = "EcsEventsRole-sample"
  assume_role_policy = file("policies/iam_role/ecs_events.json")
}
# IAM Role Policy
resource "aws_iam_policy" "ecs_events" {
  name   = "EcsEventsPolicy-sample"
  policy = templatefile("policies/iam_policy/ecs_events.json", {
    // リビジョンは固定しない
    task_definition_arn = replace(aws_ecs_task_definition.task_scheduler.arn, "/:\\d+$/", "")
  })
}
# Attach Policy to Role
resource "aws_iam_role_policy_attachment" "ecs_events" {
  policy_arn = aws_iam_policy.ecs_events.arn
  role       = aws_iam_role.ecs_events.name
}

1 点だけ注意するポイントがあります。IAM Policy 作成時のポリシー定義で、ECS タスク定義の ARN を指定しますが、この値はリビジョンを除いたものを渡します。

リビジョンが指定されたままの ARN で ポリシーを作成してしまうと当然ながらそのリビジョンでのみ実行可能なポリシーになってしまうため、例えばアプリケーションの新たなリリースを行ってイメージを更新した(イメージのタグを更新した、など)際にはタスク定義のリビジョンが一つ上がるので、作成したポリシーではスケジューリング実行ができなくなってしまいます。

他、読み込んでいる各ファイルの内容は以下です。

policies/iam_role/ecs_events.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "events.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

policies/iam_policy/ecs_events.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ecs:RunTask",
            "Resource": "${task_definition_arn}"
        }
    ]
}

タスクスケジューリング

スケジュールを設定します。

main.tf

# CloudWatch Event Rule
resource "aws_cloudwatch_event_rule" "ecs_scheduled_task" {
  name                = "ecs-scheduled-task"
  schedule_expression = "cron(20 2 * * ? *)"
}

# CloudWatch Event Target
resource "aws_cloudwatch_event_target" "ecs_scheduled_task" {
  arn       = aws_ecs_cluster.task_scheduler.arn
  rule      = aws_cloudwatch_event_rule.ecs_scheduled_task.name
  role_arn  = aws_iam_role.ecs_events.arn
  target_id = "scheduler-target"
  input     = file("container-overrides/ecs_scheduled_task.json")

  ecs_target {
    // リビジョンなしで渡すことで常に最新のバージョンを使用するようにする
    task_definition_arn = replace(aws_ecs_task_definition.task_scheduler.arn, "/:\\d+$/", "")
    task_count          = 1
    launch_type         = "FARGATE"
    platform_version    = "1.4.0"

    network_configuration {
      subnets          = [aws_subnet.private_1.id,aws_subnet.private_2.id]
      assign_public_ip = false
    }
  }
}

以下、いくつかポイントがあります。

スケジュールの設定

CloudWatch Event Rule の設定において schedule_expression を指定していますが、ここでどういったスケジュールで動作させるのかを指定します。

上記のような cron 式、または rate 式で記述できます。

ルールのスケジュール式

docs.aws.amazon.com

1 つ注意なのが、 cron 式を使う場合 AWS 上では UTC で実行されるため、日本のタイムゾーンで考えると時刻指定は -9h で行う必要があります。

今回は、毎日 11:20 に実行されるように設定しました。

サブネットの指定

network_configuration の値について、ここではマルチ AZ かつプライベートサブネットに ECS を展開しているため subnets および assign_public_ip は上記のような指定になっています。

サブネットの指定などは自身の環境に合わせて設定を行ってください。

Resource: aws_cloudwatch_event_target
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target

ContainerOverride

読み込んでいる各ファイルの内容は以下です

container-overrides/ecs_scheduled_task.json

{
    "containerOverrides": [
        {
            "name": "<< CONTAINER-NAME >>",
            "command": ["php", "artisan", "sample:logger"]
        }
    ]
}

ここでは ContainerOverride の値を設定しています。コンテナ起動時のデフォルトコマンドがここで指定したもので上書きされます。

タスク起動時にここで指定したコマンドが実行されるイメージです。

ContainerOverride

docs.aws.amazon.com

今回はサンプルとして、PHP フレームワークである Laravel のコマンドを動かす想定として、artisan コマンドを記述しています。

コンテナ起動時のデフォルトコマンドを上書きしたことによって動作は以下のようになります。

  1. スケジューリングによって指定した時間にコンテナが起動する
  2. コマンド php artisan sample:logger を実行する
  3. 処理が終了したらタスクが終了する

動作確認

ECS でのタスクスケジューリングの設定が完了したので、AWS コンソール画面から確認してみます。

ECS クラスタの画面からタスクのスケジューリングタブを選択すると、スケジュールが設定されている事が確認できます。

f:id:ro9rito:20210215084907p:plain

また、CloudWatch Events の Rule を確認すると、指定の通りに毎日 11:20 にトリガーが設定されている事が確認できます。

f:id:ro9rito:20210215084926p:plain

時間になったらタスクが起動しました

f:id:ro9rito:20210215084948p:plain

タスクを実行した際にログを出力するようにしておいたのでそちらも確認してみます。

f:id:ro9rito:20210215085012p:plain

スケジューリングでのタスク実行が動作している事を確認できました。

まとめ

ECS のタスクスケジューリングを使う事で、タスク実行をスケジュール化できました。

定期的に実行するような処理は ECS のタスクのスケジューリングでいい感じに行えそうでした。

Apple-Silicon(M1チップ)のMBPにk8s環境を作る方法

こちらは個人ブログ記事の転載です。

kotamat.com

Intel チップのときは Docker for Mac で Enable Kubernetes を on にするだけで k8s 環境が手に入っていました。 ただ、M1 チップ用の環境である Docker Desktop for Apple M1 で環境を構築すると執筆時点の段階では k8s をそのままでインストールすることができません。

https://docs.docker.com/docker-for-mac/apple-m1/

Kubernetes does not initialize because of a missing DNS name.

設定画面を見るとチェックボックスは押せるみたいだけど、 Kubernetes is starting... のままスタートしない…

f:id:kotamat:20210210070557p:plain

対応方法

kind

kindは Docker コンテナのノードを利用してローカルに k8s 環境を作るツールです。 Docker Desktop for Apple M1 を入れて Docker 環境を作っておけば、Docker コンテナ自体は立ち上がるようになっているので、kind を使うのが一番簡単かと思います。

GO111MODULE="on" go get sigs.k8s.io/kind@v0.10.0
kind create cluster --image rossgeorgiev/kind-node-arm64:v1.20.0

kind create cluster をする際に、arm64 の image を指定しないとエラーになる点だけ注意します。

Minikube

Minikubeも同様にローカルに k8s 環境を作るツールです。

すでに darwin-arm64 用の minikube がリリースされているので、そちらを使います。

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-arm64
sudo install minikube-darwin-arm64 /usr/local/bin/minikube

brew でのインストールもできるようですが、こちらは未確認です。

まとめ

意外とあっさり k8s の環境を構築できました。 今後開発していく中で環境依存の不具合に遭遇するかもしれないですが、その際はまた何か記事にしようかなと思います。

デイリースクラムで一日の計画を立てよう

私が所属しているROXXのagenbank事業部の開発チームでは、スクラムを取り入れています。 前回、スクラムのふりかえりについての記事をかきました 今回は開発チームで行っているデイリースクラムについて書いていきます。

今やってること

今、私達は朝昼夕と1日に3回、決まった時間にデイリースクラムを行っています。 一見、「そんなにやって意味あるの?」「時間の無駄じゃない?」などの声があがりそうですが 私は、ちゃんと目的意識を持って取り組めばとても意味があり効果的なものだと考えています。 ただし、スクラムメンバーがデイリースクラムを行う目的、価値を理解して行わないと効果は発揮しません。

朝会

一日のゴールを達成できるよう、効率よく作業を進められるようその日一日の計画を立てる場です。 前日からの状況、次のタスクの状況、さらには人員リソースの状況を鑑みて、効率の良い進め方を模索します。 また、不確実性が高いタスクをウォッチしてできるだけ計画に影響をきたさないようにします。

やってること

  1. 追加タスクの確認
  2. 一日の進め方を決める
  3. ウォッチする不確実タスクの確認

1. 追加タスクの確認

プランニングでは計画していなかった割り込みタスクや、スプリントのゴールに達する上で足りていなかった追加タスクを確認します。 このようなタスクはプランニングの時点では発生していなく、メンバー全員できちんと話せていない可能性が高いのでここで確認します。

2. 一日の進め方を決める

予めプランニングで一日の進め方は決めていますが、日々状況は変わります。 現在の状況を踏まえて、その時点での最適な一日の進め方を決定します。

3. ウォッチする不確実タスクの確認

ここでいう不確実性が高いとは - 開発チーム外の人が絡んでいる - 調査してからでないとタスクが進められない - 仕様がきちんと定まってない

などのことです。

不確実性が高いタスクが存在していると、進捗が遅れる可能性も高いです。 不確実なタスクをウォッチし、一日の進め方に対してどれくらいの影響をきたしているかを見極め、アクションを取ります。

昼会

午前中のタスクの進捗状況を全員で確認し、朝会で確認した一日の計画を達成するために午後の作業の進め方を調整する場です。 タスクの進捗状況によっては、タスクのアサインの変更やヘルプ依頼などあらゆる手段を用いて一日の計画を達成できるよう模索します。

当初、昼会は行っておらず昼の時点で進捗確認はしていませんでした。 「チームでプランニングしたインクリメントをスプリント内で作りきれない」というProblemが発生し、その改善策として行うことになりました。 1つのタスクに取り掛かるとそれを終わらせることに集中してしまい、全体の進捗がどうなっているかまで意識が回らないです。 全員で進捗を確認し、その進捗に対してアクションを考える場をつくることでタスクの進捗、午後の動きについてチーム全員で共通認識を得ることができます。

やってること

  1. 遅延タスクについての遅延要素の確認
  2. 午後の進め方を決める

1. 遅延タスクについての遅延要素の確認

現在各タスクがどのような状況なのかを、全員で確認し、進捗状況の認識を合わせます。 一日のゴール(一日に完了すべきタスク郡)に対して未完了のタスクや先取りしているタスクを確認し、現在の進捗を客観的に判別します。

ここで一番重要なのは、遅延しているタスクについてです。 遅延しているタスクは何らかの遅延要素が発生しているはずです。一日のゴール設定にも影響が出るため、この時点でしっかり検知をし、一日の予定に影響が出ないよう対策を立てます。

「現在自分が着手しているタスクで想定外に時間がかかっている箇所はないか?」 「仕様が不透明なまま進めてしまっている箇所はないか?」 などを考えこの場で共有する必要があります。

遅延理由を言いやすい雰囲気をつくる

弊社の開発チームではそんな人はいませんが、遅延していること自体を責める発言は良くないです。 重要なのは遅延要素を特定し、それに対してアクションを取ることです。 しかし、自ら遅延している理由をスラスラ話すことができないメンバーもいると思います(僕自身、どっちかというとそういうタイプです) そういう場合は、「不安なことはありませんか?」「困っていることはありませんか?」などの問いかけで出てくることもあります。

自分ごととして考える

タスクの遅延要素は自分で気がつけないこともあります。 他の人がやっているタスクでも「何故遅延しているのか?」、「こうした方がいいんじゃないか?」などを考えることで 遅延要素に気がつく為の目が増え、一日のゴールに向かいやすくなります。

2. 午後の進め方を決める

遅延タスクが発生している場合は、そのタスクの対応を踏まえた計画を作り、午後の進め方の共通認識を得ます。 遅延タスクの対応というのは例えば、 - 仕様が不透明なものがあったら、全員で話す場を設定する - 実装上詰まっているところがあれば、ヘルプ依頼をする

などです。

共通認識を得て、全員が同じ方向を向いていることが重要です。 共通認識を得ていないと、後でまた進め方の話になり昼会の時間が無駄になったり、効率的に進められず一日のゴールに到達しない可能性が高くなるからです。

夕会

書こうと思いましたが時間切れです。 弊社の開発メンバーのniisanが書いた記事を読みましょう。 一日のふりかえりにYWTやってみた

まとめ

一日に3回もデイリースクラムをしているスクラムチームは少ないのではないでしょうか。 重要なのは回数ではなく、スプリントのゴールを達成するために計画を立てることなので、チームの状況に合わせて行えば良いと思います。

おまけ

ROXXでは開発チームのメンバー(エンジニア/デザイナー)を募集しています。 少しでも興味がある方は、私のtwitterにご連絡お願いします。

twitter:@r_sato1201