えんじにあメモ

試してみた技術とか、たまに家電ネタ

VimでUMLを編集しDocker+ブラウザでプレビューする

VimでのUMLプレビューは検索すると様々な記事が見つかりますが、以下のような点から導入を躊躇ってました

  • 事前インストールが必要な依存関係が多い
  • 外部のUMLサーバへの接続が行われる
  • 可視化性が低い

そこでDockerでローカルに起動したPlantUML Serverを利用し、Vimで編集中のUMLをブラウザでプレビューできるようにした

事前準備

DockerでPlantUML Serverを起動する

$ docker run -d -p 8080:8080 plantuml/plantuml-server

vimrcに以下を追記

nmap <leader><Space><Space> :! curl -s -i http://localhost:8080/form -H "Content-Type: application/x-www-form-urlencoded" --data-urlencode text@% \| grep "^Location:" \| awk '{print $2}' \| sed -e "s/\/uml\//\/png\//" \| xargs open<CR><CR>

/png/PlantUMLの圧縮文字列のendpointでも生成できるが圧縮文字列を生成するのが面倒くさいのでformに投げつけてる)

プレビュー

例として以下のUMLVimで開く

@startuml
アリス -> ボブ: Authentication Request
ボブ --> アリス: Authentication Response

アリス -> ボブ: Another authentication Request
アリス <-- ボブ: another authentication Response
@enduml

開いた状態で <leader> -> space -> space でブラウザでプレビュー画像が開かれる

f:id:shosfs:20211228163122p:plain

ヨシ!

git add . を禁止する

git add . を手癖で打ってたけど、不要なファイルを追加してしまうことがあったので

commitの粒度を適切に分割するためにも git add . を行わないようにするのは良さげ

なにする?

以下をbashrc/zshrcに追加

git() {
  if [ $# -eq 2 -a "$1" = 'add' -a "$2" = '.' ]; then
      #echo '# prohibit to use "git add ."'
      echo '"git add ." ダメ💩'
      return
  fi
  command git "$@"
}

以上

f:id:shosfs:20211228144338p:plain

設定当初はよく怒られちゃってたけど今は慣れてほとんど出なくなった

ちなみに

↑を参考にgit configに以下のaliasを入れています

addf = ! git status --porcelain=v2 | awk '{print $NF}' | vim -

Github ActionsでDocker公式アクションを使って複数アーキテクチャ向けのDockerイメージを作る

ラズパイ上で動くarmイメージなど、複数アーキテクチャ向けのイメージをGithub Actionsで作成しDockerHubなどのコンテナレジストリにpushする方法をまとめます

以前同様の記事を以下に書きました

sminamot-dev.hatenablog.com

この記事ではbuildxのセットアップに crazy-max/ghaction-docker-buildx を使ってましたが、Docker公式のアクションでできるようになっているのでそちらを試してみます
crazy-max/ghaction-docker-buildx のREADMEにもDocker公式アクションを使うようアナウンスされています)

GitHub Actionsの設定

以下のGitHubリポジトリで試してます

github.com

rootにあるDockerfileをもとに、masterブランチにgit pushを行ったタイミングで linux/arm/v7linux/amd64 のイメージを作成しDockerHubに上げてみます

.github/workflows/docker.yml を作成

name: Publish Docker image
on:
  push:
    branches:
      - master
jobs:
  build:
    name: build and publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ github.repository_owner }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          platforms: linux/arm/v7,linux/amd64
          push: true
          tags: ${{ github.repository }}:latest

DockerHubのパスワードは事前にGitHubのsecretsに設定しておきましょう

Settings -> Secrets -> "New repository secret" からyamlに記載したsecrets(DOCKER_PASSWORD)を設定

f:id:shosfs:20210307190359p:plain

↑の例だとpushしたタイミングでgitと同じリポジトリ名(sminamot/docker-actions-multi-arch-image)でDockerHubに上がります

利用できるplatformは以下の通り(Set up Docker Buildxの結果に表示されている)

linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6

docker/build-push-action の platforms にカンマ区切りで追加すれば変更することができます

動作確認

masterブランチにpushすると作ったワークフローが動き出しDocker Hubにイメージがpushされました

https://hub.docker.com/r/sminamot/docker-actions-multi-arch-image/tags

f:id:shosfs:20210321114104p:plain

応用編

応用編としてgit tagを打ったときにそのタグでイメージ作成+Docker Hubへのpushをやってみます

git上のタグは v1.0.0のフォーマットで打ち、Docker Hubに 1.0.0 に上げるパターン

name: Publish Docker image
on:
  push:
    tags:
      - v*
jobs:
  build:
    name: build and publish
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ github.repository_owner }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      # use tag for image_tag, example:'v1.2.3' -> '1.2.3'
      - name: Set image tag
        run: |
          IMAGE_TAG=${GITHUB_REF##*/v}
          echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          platforms: linux/arm/v7,linux/amd64
          push: true
          tags: ${{ github.repository }}:latest,${{ github.repository }}:${{ env.IMAGE_TAG }}

変更点は以下の3つ

  • ワークフローのトリガーを v から始まるgit tagがpushされたときに変更
  • Set image tag のstepを追加
    • git tagから v を除いたタグを環境変数 IMAGE_TAG に設定している
  • Build and push stepのtagsに↑の IMAGE_TAG を追加

その他、各公式アクションで指定可能なパラメータは多くあるため、いろいろとお試しあれ 🙌

2020年買ったものまとめ

2020年はコロナやリモートワークなどがあった分、家にいる時間が増えて色々と買った気がするのでまとめておきます。

買ったサイトのリンクそのまま載っけてます

個人的な良かった度を5段階で評価(★〜★★★★★)

仕事関係編

HHKB Professional HYBRID Type-S 日本語配列/墨

★★★★★

store.shopping.yahoo.co.jp

リモートワークで自宅用にも購入
安定のHHKB
有線で使っているのでBluetoothでの接続の良さは分からないけど、Type-Sになってよりスコスコ感が上昇で良い

キングストンテクノロジー HX-WR [HyperX Wrist Rest]

★★★★★

https://www.yodobashi.com/product-detail/100000001004133582/

f:id:shosfs:20201231113039p:plain

リストレスト
HHKBに合わせて購入
自分はこれなしだと手首の出っ張っている部分?が痛くなるので必需品

エレコム リストレスト MOH-FTRBK

★★

Amazon | エレコム リストレスト 疲労軽減 ショート 日本製 FITTIO ブラック MOH-FTRBK | エレコム | マウスパッド 通販

f:id:shosfs:20201231114020p:plain

これもリストレスト
トラックパッド用に購入
製品自体は悪くなかったけど、↑のリストレストがキーボード/トラックパッド両方に使えるのでお蔵入り

グリーンハウス 液晶ディスプレイアーム 2軸 クランプ式 GH-AMC02

★★★★

Amazon | グリーンハウス 液晶ディスプレイアーム 2軸 クランプ式 GH-AMC02 | グリーンハウス(Green House) | パソコン・周辺機器 通販

f:id:shosfs:20201231141746p:plain

机の上をスッキリさせるためのディスプレイアーム
ディスプレイ2台あるので2つ購入
調整はそれほど効かないけどシンプルかつリーズナブルで良し

縦置き用PCスタンド

★★

Amazon | ノートパソコン スタンド 縦置き 収納 ホルダー幅調整可能 アルミ合金素材 OBENRI Vertical Laptop Stand Designed for MacBook Pro Air Mini Clamshell Mode & All Notepc | OBENRI | PCアクセサリ・サプライ 通販

f:id:shosfs:20201231120049p:plain

mac book proをクラムシェルで使っているのでスタンド購入
製品自体はしっかりしていて良い
ただ私用PCとの入れ替えが面倒だったり、左右両サイドのtype-Cポートを使っているので配置が難しくお蔵入り

UGREEN USB Type C ケーブル L字

★★★★

Amazon.co.jp: UGREEN USB Type C ケーブル L字ナイロン編み 3A急速充電 Quick Charge 3.0/2.0対応 56Kレジスタ実装 Xperia XZ XZ2、 S9 S8、Huawei P9 Mate 9、LG G5 G6 V20等対応 (0.5m): パソコン・周辺機器

f:id:shosfs:20201231115957p:plain

HHKB用に購入
やはりHHKBのケーブルはL字がいい

アリア クリーニングクロス CC-500

★★★

Amazon | ARIA アリア クリーニングクロス CC-500 NB | 楽器・音響機器 | 楽器

f:id:shosfs:20201231120509p:plain

HHKBのカバークロスとして購入
サイズ感としては半分に折るとHHKBよりちょっと大きいくらいで良い
たまにかぶせ忘れる

エレコム 電源タップ T-NSLK-2620BK

★★★★

Amazon | エレコム 電源タップ ACアダプタが5つ挿せる幅広コンセント 雷ガード付 6個口 2m ブラック T-NSLK-2620BK | エレコム | 電源タップ 通販

f:id:shosfs:20201231122618p:plain

電源タップ
差込口の感覚が広く、スッキリしたデザインがいい

ラズパイ編

Raspberry Pi4 ModelB 4GB

★★★★

Amazon.co.jp: 【国内正規代理店品】Raspberry Pi4 ModelB 4GB ラズベリーパイ4 技適対応品【RS・OKdo版】: パソコン・周辺機器

f:id:shosfs:20201231120954p:plain

おうちk8sクラスタ構築のために購入
最初はもともと持っていたいラズパイ3とコレ2台でやってたけど、後でもう一台追加で購入してラズパイ4を3台で構成中

構築したときの記事はこちら↓

sminamot-dev.hatenablog.com

TP-Link スイッチングハブ TL-SG105V6.0

★★★★

Amazon | TP-Link 5ポート スイッチングハブ 10/100/1000Mbps ギガビット 金属筺体 設定不要 ライフタイム保証 TL-SG105V6.0 | TP-LINK | スイッチングハブ 通販

f:id:shosfs:20201231121538p:plain

スイッチングハブ
ラズパイケースの台座にもなってる

GeeekPi Raspberry Piラックケース

★★★

Amazon | GeeekPi Raspberry Pi4クラスターケース冷却ファンとRaspberryPi4ヒートシンク付きRaspberryPi4ケースアクリルケースPiラックケースRaspberryPi 3B +に適した積み重ね可能なケースRaspberryPi3 / 2モデルB(トランスペアレント) | GeeekPi | ベアボーンPC 通販

f:id:shosfs:20201231121813p:plain

おうちk8sクラスタを全台ラズパイ4に変えるタイミングでケースも買い替え
簡易ファンがついていて一応効果アリ

ただずっと使っているとケースと干渉するせいか音がうるさくなった

趣味編

天気の子 Blu-ray

★★★★

Amazon | 「天気の子」Blu-rayスタンダード・エディション | アニメ

f:id:shosfs:20201231123127p:plain

映画館でも見に行った天気の子
上映日は晴れてました

藤子・F・不二雄 大全集 ドラえもん

★★★★

https://www.amazon.co.jp/gp/product/409143403

f:id:shosfs:20201231123526p:plain

てんとう虫コミックス版ではなく大全集版
10巻まで買ったけど本棚の空きがなくなったので一旦ストップ
1冊が辞書並の大きさ
大長編含めて全部揃えるのにまだあと20冊くらいある

鬼滅の刃 コミック

★★★★★

鬼滅の刃 23 (ジャンプコミックス) | 吾峠 呼世晴 |本 | 通販 | Amazon

f:id:shosfs:20201231123857p:plain

流行に見事に乗りアニメ→映画→コミックと完走
コミックはネットでは全然買えなかったので書店で取り寄せしてもらった
映画のblu-ray出たら買う

桃太郎電鉄 ~昭和 平成 令和も定番! ~

★★★★★

Amazon.co.jp: 桃太郎電鉄 ~昭和 平成 令和も定番! ~: ゲーム

f:id:shosfs:20201231124208p:plain

ゲームを買うのはリングフィットぶり
対COM戦でも楽しい
オンラインもやってみたい

ソーダストリーム スピリット スターターキット

★★★★★

paypaymall.yahoo.co.jp

炭酸水メーカー
普段レモンサワーや男梅の原液?を買って炭酸水で割って飲んでるので、自分で炭酸水が作れるのは良い
電動のやつもあるけど、ケーブルなしの手動式のほうが置き場所自由に変えれるので個人的にオススメ

COMPLY コンプライ Tx200M/3P

★★★

https://www.yodobashi.com/product-detail/100000001001164768/

f:id:shosfs:20201231124845p:plain

beatXのイヤホンにつけてるイヤーチップ
前にも買ってて、使い切ったと思って買ったらあと1ピース残ってたのでまた開けてない
耳へのフィット感は良いがちょっとお高め

その他編

KATOMOKU Muku Clock 7

★★★★★

Amazon.co.jp: KATOMOKU Muku Clock 7 ナチュラル 電波時計 連続秒針ムーブメント km-60NRC φ306mm (ナチュラル): ホーム&キッチン

f:id:shosfs:20201231125343p:plain

掛け時計
木の感じがオサレ

壁美人 時計用フック

★★★★

Amazon|壁美人 ホチキスで取付壁掛けフック 時計用フック 2個 痕が目立たない CH-2|フック オンライン通販

f:id:shosfs:20201231125516p:plain

↑の時計の壁掛け用に購入
壁美人はテレビの壁掛けにも使ってて安定感○

コクヨ 超強力 マグネットフック タフピタ

★★★

Amazon.co.jp: コクヨ 超強力 マグネットフック タフピタ 黒 最大10kgf フク-227D: 文房具・オフィス用品

f:id:shosfs:20201231125753p:plain

会社でデスクにカバンをかけるために購入
マグネットはけっこう強力

耐震突っ張り本棚 鉄芯

★★★★

item.rakuten.co.jp

床から天井まで突っ張りタイプの本棚
値段の割にしっかりしているのと収納スペース多めで良い
天井高によって真ん中の収納部分の高さが変わるので注意
あと組み立てがちょっと大変
45cm幅のを買ったけど60cm幅にしておけばよかったかもしれない

HYCHIKA 電動ドライバー

★★★★★

Amazon | HYCHIKA(ハイチカ) 電動ドライバー 充電式ドライバードリル トルク6Nm 3.6V 2000mAh大容量 USB充電(アダプタ含む) 正逆転切り替え | ドリルドライバー

f:id:shosfs:20201231131059p:plain

↑の本棚を組み立てるために購入
付属品多くてまだほとんど使ったことないけど、コレ1台あれば家具の組み立てとかは大丈夫そう

アルコール噴霧器 アルコールディスペンサー

★★★★

Amazon.co.jp: アルコール噴霧器 アルコールディスペンサー オートセンサー 自動誘導 オートディスペンサー 非接触 360ml 大容量 IPX4防水 吐出量2段階切替 透明ボトル 残量確認可 学校/キッチン/洗面所に適用 日本語取扱説明書付き: ホーム&キッチン

f:id:shosfs:20201231131333p:plain

コロナ対策で購入
デザインはスッキリしていて、ちょうどいい量出してくれるので良い

まとめ

以上、2020年に買ったものまとめでした

今年のベストバイはソーダストリーム(炭酸水メーカー)で!

今年は大型家電は買わなかったのでベストバイを決めるのは難しいけど、コロナで家飲みの機会が増えたのでコレで決まり

2021年もよろしくお願いします

GitHub Actionsを使ってラズパイk8sクラスタの自動デプロイ環境を作る

最近Netflixを登録し、ジョジョを一気観しました
6部のアニメ化も期待しています

はじめに

以前作成した ラズパイのk8sクラスタ 上にアプリケーションをデプロイする際に、今までは同じネットワークにあるローカルMacから直接kubectlやhelmコマンドでデプロイを行ってました

利用するDockerイメージのアップロードはGitHub Actionsを利用してgit push → DockerHubへのアップロードを自動化していましたが、今回はk8sへのデプロイ部分もGitOpsで自動化していきたいと思います 💪

GitHub Actionsを利用してラズパイ(複数アーキテクチャ)向けのイメージを作る方法は↓こちら

sminamot-dev.hatenablog.com

TL;DR

  • GitHub Actionsのセルフホストランナーを利用する
  • 構築パターンは以下の2つ
    • ラズパイ上に直接構築する
    • 専用のイメージを作成し、k8sのPodとして構築する
  • 作成した専用イメージ
  • 必要なツールをラズパイ上もしくはイメージに含め、GitHub Actionsのジョブ上で利用してデプロイを行う

GitHub Actionsのセルフホストランナー

セルフホストランナーとは独自の環境(VMなど)をGitHub Actionsのジョブ実行環境にすることができる機能です

docs.github.com

ポーリングによってGitHubとの通信を行うため、自分のラズパイのように外部に穴あけされていない環境でも利用することができます

セルフホストランナーを利用する上での注意点として、パブリックリポジトリで利用しないことが推奨されています

パブリックリポジトリのフォークでは、ワークフロー中のコードを実行するプルリクエストが作成されると、セルフホストランナー上で危険なコードが実行される可能性があります。

今回はセルフホストランナーを構築する環境として、k8sクラスタとして利用しているラズパイ上に直接設定を行うパターンと、k8s上に専用のPodを立てて利用するパターンの2パターンを試してみます

ラズパイ上に直接設定を行う

まずワークフローを設定するためのプライベートリポジトリを作成し、「Settings」→「Actions」を開きます f:id:shosfs:20200706192206p:plain

「Add Runner」を押し、OSとArchitectureを選びます(ラズパイの場合はOS:Linux、Architecture:ARMを選択) f:id:shosfs:20200706192510p:plain

セフルホストランナーとして利用するラズパイにログインして表示されているコマンドを実行します

# Download
$ mkdir actions-runner && cd actions-runner
$ curl -O -L https://github.com/actions/runner/releases/download/v2.267.1/actions-runner-linux-arm-2.267.1.tar.gz
$ tar xzf ./actions-runner-linux-arm-2.267.1.tar.gz

# Configure
$ ./config.sh --url https://github.com/sminamot/<作ったprivateリポジトリ> --token XXXX
$ ./run.sh

config.shの実行時にrunnerの名前、追加のlabel、workフォルダを聞かれますが、ひとまずすべてデフォルトのままEnter

run.shを実行し、Listening for Jobs と表示され、GitHubのActions画面でセルフホストランナーが追加されていればOKです f:id:shosfs:20200706193450p:plain

あとはいつものようにGitHub Actionsのワークフロー設定を追加すればOKですが、yaml中のruns-onにはself-hostedを指定するようにしてください

以下は作成したプライベートリポジトリへpushした際に、ラズパイk8sクラスタ上にbusyboxイメージでsleepするだけのpodを作るワークフロー例です

name: Deploy

on:
  push:

jobs:
  deploy:
    runs-on: self-hosted

    steps:
    - name: deploy
      run: kubectl run busybox --image busybox --restart Never -- /bin/sh -c "sleep 3600"

デプロイするための事前準備として、対象のラズパイ上でkubectlが実行できるようにしておく必要があります

上記yaml.github/workflows/k8s.ymlとして保存しgit pushを行うとデプロイが走りbusyboxのPodがデプロイされました

GitHub上のAction画面

f:id:shosfs:20200706200012p:plain

Pod確認

f:id:shosfs:20200706195945p:plain

run.shと同じディレクトリにあるsvc.shを使うことでランナーをサービス化することができます

# 事前にrun.shを動かしている場合は終了しておく

# インストール
$ ./svc.sh install

# 起動
$ ./svc.sh start

# ステータス確認
$ ./svc.sh status

# 停止
$ ./svc.sh stop

# アンインストール
$ ./svc.sh uninstall

実際のデプロイフローとしては以下のようになります

  • ラズパイ上にデプロイに必要なツールを事前にインストール(kustomizeやhelmなど)
  • 作成したプライベートリポジトリ上にデプロイしたいk8sのリソース用yamlを配置し、↑のツールを利用してgit push時にデプロイを行う

k8s上に専用のPodを立てる

上記のランナーをk8sのPod上に立てる方法です

セルフホストランナー用ベースイメージ

Podとして動かすために以下のようなDockerfileとentrypoint.sh/remove.shを作成します

github.com

作成したイメージ

Dockerfileはセルフホストランナーのためのベース用イメージであり、実際に使うイメージではこちらをベースにデプロイに必要なツール等を含めたイメージにします(後述)

また、amd64/armともにbuildできるよう環境別にARGを設定し、FROM base-$TARGETARCHの記述で各Archに対応できるようにしています

「はじめに」で紹介した複数アーキテクチャ向けのイメージ作成の方法ではbuildxを使っているため、$TARGETARCHにそれぞれのArchの値が入ることで処理の分岐が行われます

(再掲) sminamot-dev.hatenablog.com

entrypoint.shとremove.shを分けているのは、ジョブ実行後以外にPod終了時にもRunnerの解除を行いたいためです

entrypoint.shではrun.shの実行時に--onceオプションをつけてジョブを1つ実行後に終了するようにしています
これによりデプロイ時に生成したファイル等がPod内に残らないようにしています

k8s用イメージ

上記Dockerfileをベースにして実際にk8sクラスタ上に配置するイメージを作成します
自分はデプロイにkubectl、kustomize、sopsを利用しているため、これらのバイナリを追加したイメージにしています

github.com

作成したイメージ

kustomizeとsopsはarm向けのバイナリが公式に提供されていなかったため、docker build時にソースからビルドする手順としています

イメージが用意できたら実際にPod(Deployment)をラズパイk8sクラスタ上にデプロイします

Pod上でkubectlを実行するための、ServiceAccountClusterRoleBindingも一緒に作成します

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: github-actions-runner-k8s
  labels:
    app: github-actions-runner-k8s
spec:
  replicas: 2
  selector:
    matchLabels:
      app: github-actions-runner-k8s
  template:
    metadata:
      labels:
        app: github-actions-runner-k8s
    spec:
      serviceAccount: admin
      containers:
      - name: github-runner
        image: sminamot/github-actions-runner-k8s:1.0.0
        imagePullPolicy: IfNotPresent
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "./remove.sh"]
        envFrom:
        - configMapRef:
            name: github-actions-configmap
        - secretRef:
            name: github-actions-secret

↑で書いたとおりpreStopにランナーを外す処理を入れています

serviceaccount.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin

clusterrolebinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin
  namespace: default

deployment.yaml中のconfigMapとsecretには以下の環境変数を設定するための値を指定しておきます

key value configMap/secret
GITHUB_OWNER 対象リポジトリのOwner(ORG) configMap
GITHUB_REPOSITORY 対象のリポジトリ configMap
GITHUB_TOKEN GitHubアクセストークン(repoの権限を付与したもの) secret

以上のリソースをすべて作成し、ログを確認すると(sternで確認)、ラズパイ上で直接動かしたときと同様に Listening for Jobs と出力されランナーが起動しています f:id:shosfs:20200726133054p:plain

対象リポジトリのActionsの設定を見ると、自動的にランナーが追加されていることが分かります f:id:shosfs:20200726133632p:plain

先程のentrypoint.shでは終了時のremove処理も書かれているので、Podが終了した際に自動的にランナーから削除が行われます

あとは同様に対象のプライベートリポジトリ上にデプロイ用のワークフロー設定を追加すればOKです

終わりに

GitHub Actionsを利用したGitOpsでの自動デプロイ環境の構築方法について紹介しました

2つやり方を紹介しましたが、自分はPodを立てる方のやり方で利用しています

GitHub Actionsでは指定したパス以下のファイルが更新されたときだけ動く設定があるため、k8sデプロイ用のプライベートリポジトリにアプリケーションごとにyamlを配置するディレクトリを作成し、それぞれ更新時のみデプロイされるように設定しました

kustomizeを使った例だと↓のような感じです
ファイル構成

.
├── .github
│   └── workflows
│       ├── my-app1.yaml
│       └── my-app2.yaml
├── my-app1
│   ├── deployment.yaml
│   └── kustomization.yaml
└── my-app2
    ├── deployment.yaml
    └── kustomization.yaml

.github/workflows/my-app1.yaml

name: Deploy my-app1

on:
  push:
    paths:
      - 'my-app1/**'
      - '.github/workflows/my-app1.yaml'

jobs:
  deploy:
    runs-on: self-hosted

    steps:
    - uses: actions/checkout@v2

    - name: Run kubectl apply
      run: kustomize build my-app1 | kubectl apply -f -

Let's 自動デプロイライフ🚀

参考

k8sの設定管理ツール「kpt」を試してみる

はじめに

先日行われた Kubernetes Meetup Tokyo #31 の中で kpt というk8sの設定管理ツールの存在を知りました

googlecontainertools.github.io

github.com

まだ出来て日が浅いとのことで開発も進んでいるらしく、どのようなものか実際に使って試してみました

kptとは

公式ドキュメントのFAQ に他のツールとの違いなどが書かれています

  • 他のツールとどう違うか?
    • 設定パッケージをコードとしてではなく、Kubernetesリソースモデルに準拠したYAML/JSONオブジェクトとして表す
  • なぜテンプレートやDSLでないか?
    • kubectl、kustomizeなどのk8sプロジェクトで開発されたツールと同じ書き方ができる

インストール

実際に動かしてみます

こちら からバイナリをダウンロードします

MacだとHomebrewでも入れられますが、6/9時点ではHomebrewがv0.27.0に対して、上記のバイナリがv0.29.0だったため、今回は最新版が使える方で導入しました

$ kpt version
v0.29.0

pkgの作成

サンプルパッケージを作ってみます
kpt pkg init でパッケージを作ります

$ mkdir kpt-sample-pkg
$ kpt pkg init kpt-sample-pkg
writing kpt-sample-pkg/Kptfile
writing kpt-sample-pkg/README.md

kpt-sample-pkgディレクトリを見るとKptfileというものが出来ました

apiVersion: kpt.dev/v1alpha1
kind: Kptfile
metadata:
  name: kpt-sample-pkg
packageMetadata:
  shortDescription: sample description

kptで管理するリソース作成

今回のサンプルではnginxイメージのdeploymentとClusterIPのserviceをパッケージに含めます

(以下kpt-sample-pkgディレクトリで作業)

↓のdeployment.yamlservice.yamlを作成します

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.18.0
        name: nginx

service.yaml

apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx

setter/substitutionの作成

kptで値を書き換えるよう、setter/substitutionというものを作ります

setterの作成にはkpt cfg create-setterを利用します

$ kpt cfg create-setter . replicas 2 --field "spec.replicas" --set-by "package-default" --description "replicas" --type integer

spec.replicas の値についてsetterを作成しました
set-by/descriptionに加えて、値がintegerであることもオプションで指定しています

setterはOpenAPIに基づいて定義されるようです

Kptfileが書き換わったので差分を確認しておきます

--- Kptfile
+++ Kptfile
@@ -4,3 +4,13 @@ metadata:
   name: kpt-sample-pkg
 packageMetadata:
   shortDescription: sample description
+openAPI:
+  definitions:
+    io.k8s.cli.setters.replicas:
+      description: replicas
+      type: integer
+      x-k8s-cli:
+        setter:
+          name: replicas
+          value: "2"
+          setBy: package-default

--- deployment.yaml
+++ deployment.yaml
@@ -5,7 +5,7 @@ metadata:
     app: nginx
   name: nginx
 spec:
-  replicas: 2
+  replicas: 2 # {"$kpt-set":"replicas"}
   selector:
     matchLabels:
       app: nginx

Kptfileにsetterの情報が、deployment.yamlのsetter対象であるspec.replicasの部分に何やらコメントが追記されています

続いてimageを指定する部分もsetter化します
imageはnginx:1.18.0のようにイメージ名:イメージタグの形式になっているため、まずはそれぞれをsetterとして定義します

$ kpt cfg create-setter . image-setter nginx --field "none" --set-by "package-default" --description "image name"
$ kpt cfg create-setter . tag-setter 1.18.0 --field "none" --set-by "package-default" --description "image tag version"

作成したsetter(image-settertag-setter)を利用してspec.containers.imageを管理するために、substitutionを作成します

substitutionの作成にはkpt cfg create-substを利用します

$ kpt cfg create-subst . image-tag --field-value nginx:1.18.0 --pattern \${image-setter}:\${tag-setter}

ちなみに、最初のkpt cfg create-setterはやらなくても自動(推測して)で作ってくれますが、set-byやdescriptionは埋められないので明示的に作りました

再度差分を確認すると、

--- Kptfile
+++ Kptfile
@@ -14,3 +14,27 @@ openAPI:
           name: replicas
           value: "2"
           setBy: package-default
+    io.k8s.cli.setters.image-setter:
+      description: image name
+      x-k8s-cli:
+        setter:
+          name: image-setter
+          value: nginx
+          setBy: package-default
+    io.k8s.cli.setters.tag-setter:
+      description: image tag version
+      x-k8s-cli:
+        setter:
+          name: tag-setter
+          value: 1.18.0
+          setBy: package-default
+    io.k8s.cli.substitutions.image-tag:
+      x-k8s-cli:
+        substitution:
+          name: image-tag
+          pattern: ${image-setter}:${tag-setter}
+          values:
+          - marker: ${image-setter}
+            ref: '#/definitions/io.k8s.cli.setters.image-setter'
+          - marker: ${tag-setter}
+            ref: '#/definitions/io.k8s.cli.setters.tag-setter'

--- deployment.yaml
+++ deployment.yaml
@@ -15,5 +15,5 @@ spec:
         app: nginx
     spec:
       containers:
-      - image: nginx:1.18.0
+      - image: nginx:1.18.0 # {"$kpt-set":"image-tag"}
         name: nginx

replicasのときと同様にKptfiledeployment.yamlが更新されました

作成したpkgをgit push

kptのpkgはgitで管理を行うため、gitへ上げておきます

kptではブランチ名でも管理可能ですが、バージョン管理できるようv0.1.0のタグも打っておきます

この時点でのサンプルパッケージ
GitHub - sminamot/kpt-sample-pkg at v0.1.0

作成したpkgの利用

さきほど作ったkpt-sample-pkgパッケージを実際に使ってみます

pkgの取得
v0.1.0のバージョンを指定して取得します

$ kpt pkg get https://github.com/sminamot/kpt-sample-pkg.git@v0.1.0 ./
fetching package / from https://github.com/sminamot/kpt-sample-pkg to kpt-sample-pkg

取得したpkg情報を参照

$ kpt pkg desc
/Users/sminamot/Documents/kpt-sample-pkg/Kptfile
   PACKAGE NAME                      DIR                                        REMOTE                     REMOTE PATH   REMOTE REF   REMOTE COMMIT
  kpt-sample-pkg   /Users/sminamot/Documents/kpt-sample-pkg   https://github.com/sminamot/kpt-sample-pkg   /             v0.1.0       e94562c

setterの指定

setterの値を書き換えてみます

setterの一覧を確認

$ kpt cfg list-setters .
      NAME       VALUE        SET BY           DESCRIPTION      COUNT
  image-setter   nginx    package-default   image name          1
  replicas       2        package-default   replicas            1
  tag-setter     1.18.0   package-default   image tag version   1
  SUBSTITUTION              PATTERN                       SETTERS
  image-tag      ${image-setter}:${tag-setter}   [image-setter,tag-setter]

replicastag-setterを書き換える

$ kpt cfg set . replicas 3
$ kpt cfg set . tag-setter 1.19.0
$ kpt pkg diff
diff /var/folders/hf/s2x0n1yd7fgdptq9xp4dsf3c0000gn/T/kpt-089821092/deployment.yaml /var/folders/hf/s2x0n1yd7fgdptq9xp4dsf3c0000gn/T/kpt-029525683/deployment.yaml
8c8
<   replicas: 3 # {"$kpt-set":"replicas"}
---
>   replicas: 2 # {"$kpt-set":"replicas"}
18c18
<       - image: nginx:1.19.0 # {"$kpt-set":"image-tag"}
---
>       - image: nginx:1.18.0 # {"$kpt-set":"image-tag"}

書き換えたyamlはkubectlでそのままデプロイ可能です

$ kubectl apply -f .
deployment.apps/nginx created
service/nginx created

ちなみにreplicasのsetter定義時にintegerであることを指定したので、文字列などを設定しようとすると怒られます

$ kpt cfg set . replicas hoge
set 0 fields
Error: The input value doesn't validate against provided OpenAPI schema: validation failure list:
replicas in body must be of type integer: "string"

今回の例ではv0.1.0しか作成しませんでしたが、v0.2.0をリリースした場合に利用する側で更新するには、

$ kpt pkg update kpt-sample-pkg@v0.2.0

と実行すればOKです

その他の機能

live

kptのパッケージをデプロイするためのサブコマンド

パッケージが管理するリソースを追跡するために最初に kpt live init を実施してテンプレートリソースを作ります

$ kpt live init .
$ tree .
.
├── Kptfile
├── README.md
├── deployment.yaml
├── inventory-template.yaml
└── service.yaml

0 directories, 5 files

# inventory-template.yamlというのができてる

これによってstatusの制御やapply時の自動pruneが行われるようになります

kpt live preview で実際にデプロイされるリソースを確認

$ kpt live preview .
configmap/inventory-e00bb1dd created (preview)
service/nginx created (preview)
deployment.apps/nginx created (preview)
3 resource(s) applied. 3 created, 0 unchanged, 0 configured (preview)
0 resource(s) pruned, 0 skipped (preview)

kpt live applyでデプロイ

reconcile-timeoutオプションを指定することで作成されたpodが利用可能になるまで待機してくれます
公式Docでは--wait-for-reconcileオプションを指定するようになってますが、--wait-timeoutと合わせて--reconcile-timeoutオプションに統合されたようです→関連Issue

$ kpt live apply --reconcile-timeout=15m .
configmap/inventory-e00bb1dd created
service/nginx created
deployment.apps/nginx created
3 resource(s) applied. 3 created, 0 unchanged, 0 configured
configmap/inventory-e00bb1dd is NotFound: Resource not found
service/nginx is NotFound: Resource not found
deployment.apps/nginx is NotFound: Resource not found
configmap/inventory-e00bb1dd is Current: Resource is always ready
service/nginx is Current: Service is ready
deployment.apps/nginx is InProgress: Available: 0/3
deployment.apps/nginx is InProgress: Available: 1/3
deployment.apps/nginx is InProgress: Available: 2/3
deployment.apps/nginx is Current: Deployment is available. Replicas: 3
all resources has reached the Current status
0 resource(s) pruned, 0 skipped

また、--outputオプションにtableを指定するとより見やすい形式(色も付く)で表示されます

$ kpt live apply --reconcile-timeout=15m --output table .
NAMESPACE   RESOURCE                                  ACTION        STATUS      CONDITIONS                                AGE     MESSAGE
default     ConfigMap/inventory-e00bb1dd              Created       Current     <None>                                    4s      Resource is always ready
default     Service/nginx                             Created       Current     <None>                                    4s      Service is ready
default     Deployment/nginx                          Created       Current     Available,Progressing                     4s      Deployment is available. Replicas: 3
default     └─ ReplicaSet/nginx-6fd78f555b                          Current     <None>                                    4s      ReplicaSet is available. Replicas: 3
default        ├─ Pod/nginx-6fd78f555b-6rgfd                        Current     Initialized,Ready,ContainersReady,PodSch  4s      Pod is Ready
default        ├─ Pod/nginx-6fd78f555b-8lf46                        Current     Initialized,Ready,ContainersReady,PodSch  4s      Pod is Ready
default        └─ Pod/nginx-6fd78f555b-mlqr8                        Current     Initialized,Ready,ContainersReady,PodSch  4s      Pod is Ready

ただ、このreconcile機能ですが、v0.29.0時点ではタイムアウトで落ちてもexit statusが0のため、改善されないとCIなどでは使えなさそう

cfg fmt

kpt cfgのサブコマンドにfmtという、k8syamlファイルのフォーマット機能があります

これはkptで管理するリソースには限らず、既存のyamlに適用することができます

例えば以下のようなpod.yamlがあった場合(apiVersion/kindが下にあったり、インデントが統一されていない)に、

metadata:
  labels:
    run: nginx
  name: nginx
spec:
      containers:
      - image: nginx:1.19.0
        name: nginx
      dnsPolicy: ClusterFirst
      restartPolicy: Never
kind:       Pod
apiVersion: v1

kpt cfg fmtをかけると、

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    run: nginx
spec:
  restartPolicy: Never
  dnsPolicy: ClusterFirst
  containers:
  - name: nginx
    image: nginx:1.19.0

このように整形してくれます

kptへの移行はすぐに出来ないかもしれませんが、フォーマッタだけ導入するものアリかもしれません

まとめ

k8sの設定管理ツールであるkptを使ってみました

ドキュメントが最新バージョンのものに追いついていなかったり、機能的に物足りない点が多いですが、今後の改善に期待しましょう

今週末6/13(土)に開催される KubeFest Tokyo 2020 にも kptに関するLT があるようです

今回紹介出来なかった機能についても説明がありそうなので楽しみです😃

CKAD/CKA取った

Kubernetes認定試験であるCKADとCKAを取りました

CKADとCKAはそれぞれ、

CKAD:Certified Kubernetes Application Developer
CKA:Certified Kubernetes Administrator

を指しており、CKADがk8sでのアプリケーション開発者向け、CKAがk8sの管理者向けの認定資格のようです

自分が取得したのは厳密にはCKAD-JP/CKA-JPで、試験内容は同じですが、開始前後などに試験官とのやり取りで利用するチャットがJPの方だと日本語が利用できます
(とはいえ、英語のほうが多く日本語もあまりはっきりと伝わらない感じだったので正直どちらでもよかったと思う)
また試験中の問題文は英語/日本語(中国語もあったかな?)を適時切り替え可能です

CKAD-JP training.linuxfoundation.org

CKA-JP training.linuxfoundation.org

試験の申込みや概要などはいろんな方が体験記を書いてくれているので割愛して、ざっくりとした勉強法と試験で感じたことを書きたいと思います

勉強法

勉強法もほかの体験記などに書かれている内容とだいたいかぶっています

CKAD/CKA共通

book.impress.co.jp

Kubernetes完全ガイドを元々持っていて何度か読んでいたため今回のために0から読んだわけではないですが、後半のノード管理やスケジューリング周りを読み飛ばしていたためそこだけ新たに読みました

Kubernetes完全ガイドはほんとに良書でCKAD/CKA対策にももってこいです

CKAD

github.com

CKAD対策としてはCKAD-exercisesを2周しました

答えを見ずにスラスラ解けるようになればCKADの合格は大丈夫かな、という印象です

CKA

Certified Kubernetes Administrator (CKA) with Practice Tests

CKA対策としてはUdemyのCKA向けの講座を一通りやりました

途中簡単なテストや、講座の最後に1時間程度の疑似テストもありCKA対策としてはこれだけで良いかもしれません

講座は英語ですが字幕もあり理解はしやすいと思います、ただ英語あまりできない自分からすると結構集中しないと大変でした

Udemyあるあるの、だいたいいつもセールで安くなってるので、自分は1,380円になってたときに受講しました

試験を受けてみて

  • 上にも書いたけどJPだと試験官とのチャットが可能
    • ただし基本は英語でたまに日本語が交じる感じ
  • ブラウザ以外のアプリケーションは利用できない
  • 外部キーボードは使っても良い
    • ↑の通りブラウザ以外のアプリケーションが使えないため、RealForceをKarabinerでキーマッピング変えてたけどKarabiner閉じろと言われて詰んだ
    • 結局外部キーボードは使わないことにした(これが一番焦った)
  • CKAの試験の途中、コネクションエラー?が起きて画面上に「復旧中です」のような内容が出てオワタかと思った
    • チャットで助けを求めても反応なし
    • 3分くらい放置してたら急に治った
    • 治ったあとにチャットもつながるようになり、止まっていた時間は試験時間延長してくれたらしい

今なら

CKAD/CKAの受験には$300かかりますが、4/30 まで有効な30%オフのクーポンコードがあり、$210で受験可能です

2020年4月のプロモーション-Linux Foundation-トレーニング

クーポンコードの利用は受験資格を得る(支払いの)際に利用可能なもので、受験資格は1年間有効なので4/30までに試験を受ける必要はありません

まとめ

こういった資格は今まで全然取ろうと思ったことはなかったですが、CKAD/CKAは実技試験だったので興味を持って取り組めました

取得に向けた勉強で新たに知れた内容も多くあったので、よい経験になりました

k8sやっていき」がより強まりました 💪

f:id:shosfs:20200418172922j:plain

f:id:shosfs:20200418172937j:plain