kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Next.js 9.3 で使えるようになった getStaticProps と getServerSideProps

2020年3月にリリースされた Next.js 9.3 から,アプリケーションをビルドする戦略として以下3種類の API が使えるようになった.Next.js Blog では「Next-gen Static Site Generation (SSG) Support」と紹介されていた.

  • getStaticProps
    • 「ビルド時」にデータを取得する
  • getStaticPaths
    • 「ビルド時」にデータを取得する(Dynamic Routing を作る)
  • getServerSideProps
    • 「リクエスト時」にデータを取得する

nextjs.org

今までの getInitialProps は?

レンダリング時に API からデータを取得するなど,今まで使ってきた getInitialProps はどうなるの?と気になると思う.ドキュメントに書いてある通り,Next.js 9.3 以降は getInitialProps ではなく getStaticPropsgetServerSideProps を使うことが推奨 (Recommended) になっている.とは言え,今までの getInitialProps も非推奨とまでは書いてなく,引き続き使える.今後実装するなら,getStaticPropsgetServerSideProps を使っていくと良さそう.

nextjs.org

なお,getStaticPropsgetServerSideProps は Node.js コンテキスト(サーバサイド)で実行される.よって,今まではフロントエンドにも対応した fetch API として,例えば isomorphic-unfetch などを使っていたけど,サーバサイドだけなら node-fetch を使える.Next.js 9.3 に対応したサンプルコードも node-fetch を使うように更新されていたりする.

data-fetch テンプレート

実際に getStaticPropsgetServerSideProps を試しながら理解を深めるため,create-next-app で使える data-fetch テンプレートの実装を参考に試した.既に getStaticProps を使った実装に更新されている.さらに今回は TypeScript を使うために with-typescript テンプレートをベースにした.create-next-app に関しては先週の記事にまとめた.

kakakakakku.hatenablog.com

検証環境

今回は Next.js 9.3.5 を使う.

$ npm view next version
9.3.5

また,動作確認をするサンプルコードを pages 直下に実装した.

$ tree pages
pages
├── get-server-side-props.tsx
└── get-static-props.tsx

サンプルコード : get-static-props.tsx

まず,getStaticProps を使ったサンプルコード get-static-props.tsx を載せる.ビルド時に GitHub API から Next.js の Star⭐️ 件数を取得する.また Link コンポーネントを使って遷移できるように /get-server-side-props へのリンクも実装した.

import React from 'react'
import Link from 'next/link'
import fetch from 'node-fetch'

type Props = {
  stars: number
}

function Index({ stars }: Props) {
  return (
    <div>
      <p>Next.js has {stars} ⭐️</p>
      <Link href="/get-server-side-props">
      <a>Go to getServerSideProps</a>
      </Link>
    </div>
  )
}

export async function getStaticProps() {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return {
    props: {
      stars: json.stargazers_count,
    },
  }
}

export default Index

サンプルコード : get-server-side-props.tsx

次に,getServerSideProps を使ったサンプルコード get-server-side-props.tsx を載せる.リクエスト時に GitHub API から Next.js の Star⭐️ 件数を取得する.また Link コンポーネントを使って遷移できるように /get-static-props へのリンクも実装した.

import React from 'react'
import Link from 'next/link'
import fetch from 'node-fetch'

type Props = {
  stars: number
}

function Index({ stars }: Props) {
  return (
    <div>
      <p>Next.js has {stars} ⭐️</p>
      <Link href="/get-static-props">
        <a>Go to getStaticProps</a>
      </Link>
    </div>
  )
}

export async function getServerSideProps() {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return {
    props: {
      stars: json.stargazers_count,
    },
  }
}

export default Index

ビルド

yarn build を実行すると,実装された getStaticPropsgetServerSideProps を参考に判定される./get-static-props「● (SSG)」となり /get-server-side-props「λ (Server)」となる.

$ yarn build

(中略)

Page                            Size     First Load JS
┌ ○ /                           1.8 kB         59.9 kB
├ ○ /404                        2.61 kB        60.7 kB
├ λ /get-server-side-props      1.84 kB        59.9 kB
└ ● /get-static-props           1.85 kB        59.9 kB

(中略)

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)(Static)  automatically rendered as static HTML (uses no initial props)(SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

✨  Done in 5.0s.

動作確認

実際に画面にアクセスして確認した.ビルド時の Star⭐️ 件数は 46914 だった(動作確認中にどんどん増えてて驚いた!).ビルド時と変化させるために Star⭐️ を付けたり消したりした.以下にイメージ画像を載せておく.

f:id:kakku22:20200420102656p:plain

1. /get-static-props

getStaticProps の場合はビルド時にデータを取得しているため,素早く表示された.5ms ~ 10ms 程度.直接 http://localhost:3000/get-server-side-props にアクセスすると Content-Typetext/html で返ってきた.Link コンポーネントをクリックしてフロントエンド側で画面遷移をすると Content-Typeapplication/json で以下のように返ってきた.

{
  "pageProps": {
    "stars": 46914
  },
  "__N_SSG": true
}

2. /get-server-side-props

getServerSideProps の場合はリクエスト時にデータを取得しているため,少し時間がかかる.getStaticProps と同じく,直接 http://localhost:3000/get-server-side-props にアクセスすると Content-Typetext/html で返ってきた.Link コンポーネントをクリックしてフロントエンド側で画面遷移をすると Content-Typeapplication/json で以下のように返ってきた.

{
  "pageProps": {
    "stars": 46918
  },
  "__N_SSP": true
}

まとめ

Next.js 9.3 で使えるようになった getStaticPropsgetServerSideProps の理解を整理するためにサンプルコードを実装しながら試した.getStaticProps はビルド時にデータを取得し,getServerSideProps はリクエスト時にデータを取得する.詳しくは Data fetching のドキュメントにも載っている.Static Site Generation (SSG) を使っていくぞー!

nextjs.org

Next.js に入門するのに便利な create-next-app の with-typescript テンプレート

最近 Next.js Learn を使って Next.js に入門した.今度は Next.js でプロトタイプを実装しながら学ぶため,プロジェクトの初期構築として create-next-app を使うことにした.少し調べたところ,create-next-app はもともと Segment 社で実装されて,現在は Next.js を管理する ZEIT 社に譲渡されている.さらに2019年10月に再実装された create-next-app もリリースされている.

nextjs.org

with-typescript テンプレート

create-next-app にテンプレートを指定するオプションがある.試しに Next.js と TypeScript 組み合わせた with-typescript テンプレートを指定したところ,Next.js を学ぶのに便利な構成になっていた.Next.js 9.3 にも対応している.今回は create-next-appwith-typescript テンプレートを使って学べる「計6点」を紹介する.コードを書きながら試行錯誤するなら Next.js Learn よりも使える.

  1. ディレクトリ構造
  2. Link コンポーネント
  3. Layout コンポーネント
  4. getStaticProps 関数
  5. getStaticPaths 関数と Dynamic Routes 機能
  6. API Routes 機能

なお with-typescript 以外のテンプレートは以下にある.

準備

まず npx create-next-app--example オプションを使ってプロジェクトを構築する.構築後に yarn dev を実行すると,すぐに http://localhost:3000 にアクセスできるようになる.

$ npx create-next-app --example with-typescript sandbox-create-next-app-ts
$ cd sandbox-create-next-app-ts
$ yarn dev

f:id:kakku22:20200413214932p:plain

1. ディレクトリ構成

create-next-app を実行した直後は以下のようなディレクトリ構成になっている.node_modules 以外を載せた.議論の余地はあるかもしれないけど,pages/ 以外にコンポーネントを管理する components/ や,型定義を管理する interfaces/ など,最低限このあたりは分割しておこう!という指針になる.

$ tree -I node_modules
.
├── README.md
├── components
│   ├── Layout.tsx
│   ├── List.tsx
│   ├── ListDetail.tsx
│   └── ListItem.tsx
├── interfaces
│   └── index.ts
├── next-env.d.ts
├── package.json
├── pages
│   ├── about.tsx
│   ├── api
│   │   └── users
│   │       └── index.ts
│   ├── index.tsx
│   └── users
│       ├── [id].tsx
│       └── index.tsx
├── tsconfig.json
├── utils
│   └── sample-data.ts
└── yarn.lock

7 directories, 16 files

2. Link コンポーネント

まず,トップページの実装を確認するため pages/index.tsx を読む.すると Link コンポーネントを使って /about へのリンクが実装されている.React Router などを使わずに簡単に実装できる.

import Link from 'next/link'
import Layout from '../components/Layout'

const IndexPage = () => (
  <Layout title="Home | Next.js + TypeScript Example">
    <h1>Hello Next.js 👋</h1>
    <p>
      <Link href="/about">
        <a>About</a>
      </Link>
    </p>
  </Layout>
)

export default IndexPage

3. Layout コンポーネント

画面の1番上には Users ListUsers API など,他にもリンクが実装されている.既に載せた pages/index.tsx を読むと,独自実装の Layout コンポーネントがあり,title 属性が指定されている.コンポーネントの実装を確認するため components/Layout.tsx を読むと,画面共通のレイアウトが実装されている.ここにまた Link コンポーネントがあったり,{children} を使ってコンテンツを受け渡していたり,ベーステンプレートの実装として参考になる.

import * as React from 'react'
import Link from 'next/link'
import Head from 'next/head'

type Props = {
  title?: string
}

const Layout: React.FunctionComponent<Props> = ({
  children,
  title = 'This is the default title',
}) => (
  <div>
    <Head>
      <title>{title}</title>
      <meta charSet="utf-8" />
      <meta name="viewport" content="initial-scale=1.0, width=device-width" />
    </Head>
    <header>
      <nav>
        <Link href="/">
          <a>Home</a>
        </Link>{' '}
        |{' '}
        <Link href="/about">
          <a>About</a>
        </Link>{' '}
        |{' '}
        <Link href="/users">
          <a>Users List</a>
        </Link>{' '}
        | <a href="/api/users">Users API</a>
      </nav>
    </header>
    {children}
    <footer>
      <hr />
      <span>I'm here to stay (Footer)</span>
    </footer>
  </div>
)

export default Layout

4. getStaticProps 関数

次にトップページから Users List をクリックすると,一覧画面に遷移する.

f:id:kakku22:20200413215057p:plain

一覧画面を実装した pages/users/index.tsx を読むと,Next.js 9.3 でリリースされた新機能 getStaticProps 関数を使って実装されている.getStaticProps 関数を使うと,Next.js のビルド時に静的ファイルを生成できるため,不要な SSR (Server-Side Rendering) を減らせる.今回は API ではなく,ファイルデータ utils/sample-data.ts を読み込む実装になっている.当然ながら,全ての一覧画面を静的ファイルにするべきという意味ではなく,あくまでサンプルとして.

なお,AliceBob など,一覧部分は,独自実装の List コンポーネント (components/List.tsx) と ListItem コンポーネント (components/ListItem.tsx) に実装されている.

export const getStaticProps: GetStaticProps = async () => {
  // Example for including static props in a Next.js function component page.
  // Don't forget to include the respective types for any props passed into
  // the component.
  const items: User[] = sampleUserData
  return { props: { items } }
}

5. getStaticPaths 関数と Dynamic Routes 機能

一覧画面で Alice など,特定のユーザーをクリックすると,詳細画面に遷移する.

f:id:kakku22:20200413215135p:plain

詳細画面は pages/users/[id].tsx に実装されている.詳細画面はユーザーごとに異なるため,Next.js の「Dynamic Routes 機能」を使って,任意の id に対応する.そのために Next.js 9.3 でリリースされた新機能 getStaticPaths 関数を使って実装されている.まず getStaticProps 関数で,URL から取得した id を使ってファイルデータを検索し,ビルド時に静的ファイルを生成する.さらに getStaticPaths 関数で,Dynamic Routes 機能に必要なパスのリストを生成する.簡単な実装ではあるけど,参考になる.

import React from 'react'
import { GetStaticProps, GetStaticPaths } from 'next'

import { User } from '../../interfaces'
import { sampleUserData } from '../../utils/sample-data'
import Layout from '../../components/Layout'
import ListDetail from '../../components/ListDetail'

type Props = {
  item?: User
  errors?: string
}

export default class StaticPropsDetail extends React.Component<Props> {
  render() {
    const { item, errors } = this.props

    if (errors) {
      return (
        <Layout title={`Error | Next.js + TypeScript Example`}>
          <p>
            <span style={{ color: 'red' }}>Error:</span> {errors}
          </p>
        </Layout>
      )
    }

    return (
      <Layout
        title={`${
          item ? item.name : 'User Detail'
        } | Next.js + TypeScript Example`}
      >
        {item && <ListDetail item={item} />}
      </Layout>
    )
  }
}

export const getStaticPaths: GetStaticPaths = async () => {
  // Get the paths we want to pre-render based on users
  const paths = sampleUserData.map(user => ({
    params: { id: user.id.toString() },
  }))

  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}

// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export const getStaticProps: GetStaticProps = async ({ params }) => {
  try {
    const id = params?.id
    const item = sampleUserData.find(data => data.id === Number(id))
    // By returning { props: item }, the StaticPropsDetail component
    // will receive `item` as a prop at build time
    return { props: { item } }
  } catch (err) {
    return { props: { errors: err.message } }
  }
}

6. API Routes 機能

最後は Next.js で API を実装する「API Routes 機能」で,pages/api/users/index.ts のように pages/api 配下にファイルを置く.すると http://localhost:3000/api/users で API にアクセスできるようになる.

$ curl -s http://localhost:3000/api/users | jq .
[
  {
    "id": 101,
    "name": "Alice"
  },
  {
    "id": 102,
    "name": "Bob"
  },
  {
    "id": 103,
    "name": "Caroline"
  },
  {
    "id": 104,
    "name": "Dave"
  }
]

今回はファイルデータ utils/sample-data.ts をそのまま JSON で返すだけになっているけど,例えば NextApiRequest で HTTP メソッドを判定したり,API Middlewares を使って拡張もできる.最低限の API 実装という観点で参考になる.

import { NextApiRequest, NextApiResponse } from 'next'
import { sampleUserData } from '../../../utils/sample-data'

export default (_: NextApiRequest, res: NextApiResponse) => {
  try {
    if (!Array.isArray(sampleUserData)) {
      throw new Error('Cannot find user data')
    }

    res.status(200).json(sampleUserData)
  } catch (err) {
    res.status(500).json({ statusCode: 500, message: err.message })
  }
}

まとめ

create-next-appwith-typescript テンプレートから Next.js プロジェクトを初期構成すると,Next.js の主要な機能を学べる.一通りの機能を試せる点や Next.js 9.3 をサポートしている点など,Next.js Learn よりも便利だなと感じた.機能ごとに学びたかったら Next.js Learn を使って,コードを書きながら試行錯誤したかったら create-next-app で新規プロジェクトを作ってしまうと良さそう.Next.js Learn の紹介記事も載せておく!

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Chrome DevTools で「オフライン環境」をエミュレートする

例えば「オフライン対応」のアプリケーションを実装して動作確認をするときなど「オフライン環境」が必要になる場合もある.単純に WiFi をオフにすれば良いこともあるけど,WiFi をオフにせず,部分的にオフライン環境をエミュレートできると便利.具体的には,先週とあるライブコーディングを自宅から配信したときに,WiFi をオフにせず「オフライン環境のテスト」をする必要があった.

Chrome DevTools を使う

developers.google.com

Chrome DevTools を使えば,簡単にオフライン環境をエミュレートできる.Network タブを開き Disable cache の右側にあるプルダウンから「Offline」を選ぶ.すると,設定したタブはオフライン環境になる.

f:id:kakku22:20200410235002p:plain

ネットワーク設定は「計4種類」から選べる.さらに Add... から自由に Network Throttling Profiles を作れる.Download (kb/s)Upload (kb/s)Latency (ms) を自由に設定できるため,低速ネットワーク環境におけるフロントエンドのレンダリング確認などに使える.

  • Online(デフォルト)
  • Fast 3G
  • Slow 3G
  • Offline

f:id:kakku22:20200410235217p:plain

おまけ : Chrome Dino Game も遊べる

オフライン環境をエミュレートすれば Chrome Dino Game も遊べる!とは言え,実はオフライン環境をエミュレートしなくても,直接 chrome://dino/ にアクセスすれば遊べる.気分転換に便利!

f:id:kakku22:20200411000247p:plain

まとめ

今回は Chrome DevTools の小ネタを書いた.Chrome でオフライン環境をエミュレートする場合は Network タブを開き「Offline」を選ぼう!

git checkout の代替としてリリースされた git switch と git restore

2019年8月にリリースされた Git 2.23 から,Experimental(実験的機能)として新コマンド git switchgit restore が使える.今までずっと使ってきた git checkout は機能が多すぎたため,機能を分割し git checkout の代替としてリリースされた.個人的にリリースされてから,できる限り git switchgit restore を使うようにしてるけど,まだ無意識に git checkout を使ってしまうこともある.最近 git switch を教える機会があったため,ブログにまとめておく.

github.blog

なお,以下の検証は Git 2.26.0 を使った.

$ git --version
git version 2.26.0

1. git switch を使う

git switch を使って「ブランチ操作」を行なう.ドキュメントを網羅的に紹介するのではなく,よく使う操作を中心に git checkout などと比較しながら紹介する.詳細はドキュメントを参照してもらればと.

git-scm.com

ブランチを作る

git switch -c でブランチを作れる.今までは git checkout -b を使っていた.

$ git checkout -b my-git-checkout

$ git switch -c my-git-switch

ブランチを切り替える

git switch という名前の通り,ブランチ名を指定すると切り替えられる.

$ git checkout master

$ git switch master

1個前のブランチに切り替える

Linux の cd - と同じく,- を使って git switch - とすると,1個前のブランチに切り替えられる.

$ git checkout -

$ git switch -

リモートブランチを取得する

「ブランチを作る」と同じく git switch -c を使って,origin/xxx など,リモートブランチを指定する.

$ git fetch
$ git checkout -b my-github-branch origin/my-github-branch

$ git fetch
$ git switch -c my-github-branch origin/my-github-branch

"強制的に" ブランチを作る

個人的にあまり使う機会はなさそうだし,誤って使うと危険な気もするけど,git switch-C オプション(大文字)もしくは --force-create オプションを使うと,もし同じ名前のブランチが存在していても強制的に作り直す.-c-C は区別しにくそう...!

$ git switch -C my-git-switch

2. git restore を使う

git restore を使って「変更を戻す操作」を行なう.ドキュメントを網羅的に紹介するのではなく,よく使う操作を中心に git checkout などと比較しながら紹介する.詳細はドキュメントを参照してもらればと.

git-scm.com

Unstaging な変更を戻す(git add をする前)

今まで git checkout を使って変更を戻していたけど,git restore で戻せる.とは言え,個人的に1番無意識に使ってしまうのが git checkout . で,今もまだ git restore . には慣れていない.

$ git checkout README.md
$ git checkout .

$ git restore README.md
$ git restore .

実際に git status を使うと,git restore を使うリファレンスも出る.

$ git status

(中略)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

Staging な変更を戻す(git add をした後)

git add で Staging にした変更を戻す場合,今までは git reset を使っていたけど,git restore --staged を使う.

$ git reset README.md

$ git restore --staged README.md

実際に git add をした後に git status を使うと,git restore --staged を使うリファレンスも出る.

$ git status

(中略)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

指定した Commit に戻す

指定した Commit に戻す場合は git restore -s を使う.ただし,git checkoutStaging な状態に戻り,git restore -sUnstaging な状態に戻るため,単純比較ではなく,注意すること.

$ git checkout ${HASH} .
$ git checkout master~2 .

$ git restore -s ${HASH} .
$ git restore -s master~2 .

まとめ

Git 2.23 から,Experimental(実験的機能)として使えるようになった新コマンド git switchgit restore の中でよく使う操作を中心に紹介した.プログラミング講師の仕事をしていたときに git checkout の説明に苦労した経験もあり,今後は Git 初学者は git switchgit restore から学べば良さそう.

Kubernetes の CronJob に設定できる concurrencyPolicy と suspend を試した

Kubernetes の CronJob を使って Job を定期的に実行するときに,マニフェストに設定できるフィールド concurrencyPolicysuspend を試す機会があった.振り返りながら整理しておく.

kubernetes.io

Concurrency Policy とは?

CronJob では,例えば「ジョブの実行時間が長時間化した(突き抜けた)場合」のために「同時実行ポリシー (Concurrency Policy)」を設定できる.具体的なフィールドは concurrencyPolicy となり,以下の3種類から選べる.デフォルトは Allow となり,同時実行を許容する.

  • Allow : 同時実行を許容する
  • Forbid : 同時実行を許容せず,実行中のジョブがあれば,新規ジョブをスキップする
  • Replace : 同時実行を許容せず,実行中のジョブがあれば,新規ジョブに置き換える

concurrencyPolicy のイメージを図解してみた.青は Running で,赤は Terminating などを意味する.

f:id:kakku22:20200406113227p:plain

concurrencyPolicy 検証 : Allow

Kubernetes のドキュメントを参考に簡単なマニフェストを作成した.Cron 表記は「1分間隔」とし,単純に「300秒スリープする」 Job にした.そして,今回検証する concurrencyPolicyAllow にした(デフォルト設定).

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: kakakakakku
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Allow
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: sleep
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; sleep "300"; date
          restartPolicy: OnFailure

マニフェストを適用し,少し待ってから Pod を確認すると,同時実行になっていた.

$ kubectl apply -f cronjob.yaml
cronjob.batch/kakakakakku created

$ kubectl get pods
NAME                           READY   STATUS              RESTARTS   AGE
kakakakakku-1585740960-kvq28   0/1     Completed           0          6m6s
kakakakakku-1585741020-fmjl7   0/1     Completed           0          5m6s
kakakakakku-1585741080-x88r2   1/1     Running             0          4m6s
kakakakakku-1585741140-f7sbh   1/1     Running             0          3m6s
kakakakakku-1585741200-jpxnj   1/1     Running             0          2m5s
kakakakakku-1585741260-6lbc7   1/1     Running             0          65s
kakakakakku-1585741320-s54b2   0/1     ContainerCreating   0          5s

concurrencyPolicy 検証 : Forbid

次は concurrencyPolicyForbid にしてマニフェストを適用する.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: kakakakakku
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Forbid

(中略)

Forbid は同時実行を許容せず,実行中のジョブがあれば,新規ジョブをスキップする.Running になっている kakakakakku-1585741620-spbnkCompleted になってから,新しく kakakakakku-1585741920-phjzsRunning になっている.

$ kubectl get pods
NAME                           READY   STATUS    RESTARTS   AGE
kakakakakku-1585741620-spbnk   1/1     Running   0          4m50s

$ kubectl get pods
NAME                           READY   STATUS      RESTARTS   AGE
kakakakakku-1585741620-spbnk   0/1     Completed   0          5m20s
kakakakakku-1585741920-phjzs   1/1     Running     0          10s

concurrencyPolicy 検証 : Replace

最後は concurrencyPolicyReplace にしてマニフェストを適用する.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: kakakakakku
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Replace

(中略)

Replace は同時実行を許容せず,実行中のジョブがあれば,新規ジョブに置き換える.実行中だった kakakakakku-1585743600-ftmb8Terminating になり,新しく kakakakakku-1585743660-4gb5vRunning になっている.

$ kubectl get pods
NAME                           READY   STATUS        RESTARTS   AGE
kakakakakku-1585743600-ftmb8   1/1     Terminating   0          70s
kakakakakku-1585743660-4gb5v   1/1     Running       0          10s

Suspend とは?

CronJob では,例えば「メンテナンス時に実行を止める」など,「一時停止 (Suspend)」を設定できる.具体的なフィールドは suspend となり,truefalse を設定できる(デフォルトは false).

suspend 検証

同じマニフェスト(concurrencyPolicyForbid にしておく)に suspend: false を設定し,マニフェストを適用する.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: kakakakakku
spec:
  schedule: "*/1 * * * *"
  concurrencyPolicy: Forbid
  suspend: false

(中略)

一時停止を有効化する場合,マニフェストを suspend: true に更新することもできるけど,今回は kubectl patch コマンドを使って一時的に suspend: true に変更する.その後に CronJobPod を確認すると,SUSPEND: True になり,新しく Pod はスケジューリングされなくなった.

$ kubectl patch cronjob kakakakakku -p '{ "spec": { "suspend": true } }'
cronjob.batch/kakakakakku patched

$ kubectl get cronjob,pods
NAME                        SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/kakakakakku   */1 * * * *   True      0        7m14s           13m

NAME                               READY   STATUS      RESTARTS   AGE
pod/kakakakakku-1585746240-296mt   0/1     Completed   0          12m
pod/kakakakakku-1585746540-8spgm   0/1     Completed   0          7m

一時停止を無効化する(戻す)ために,同じく kubectl patch コマンドを使う.

$ kubectl patch cronjob kakakakakku -p '{ "spec": { "suspend": false } }'
cronjob.batch/kakakakakku patched

なお,kubectl patch コマンドを使った方法は「Kubernetes 完全ガイド」の第5章にも載っている.

Kubernetes完全ガイド (impress top gear)

Kubernetes完全ガイド (impress top gear)

  • 作者:青山 真也
  • 発売日: 2018/09/21
  • メディア: 単行本(ソフトカバー)

まとめ

Kubernetes の CronJob に設定できるフィールド concurrencyPolicysuspend を試す機会があり,検証結果を整理した.Kubernetes 関連の記事は今まであまり書いてなく,今後はどんどん書いていく.