レジュメの Static site を Jekyll(Azure CDN) から Hugo(Static Web Apps) に乗り換えた話

タイトルで8割書いてるので、あとは補足だけ書く。

サイトはこちら。

cv.kheiakiyama.com

背景

理由1: ビルド遅い問題

GitHub Actions を使ってビルドしているが、ビルドからデプロイまで、約8分前後の時間がかかっていた。

内容を精査すると、主に Jekyll でビルドするための bundle install に時間が大半を占めていた。
また、 Gemfile が Dependabot に検知される要因になっていて、地味に嫌な感じだった。

移行先を検討していたところ、Hugo は使ったことがあり、 2021年時点でベストな静的サイトジェネレータの一つらしいのでそれにした。

Best static site generators of 2021 | TechRadar

理由2: Static Web Apps 使いたい

Azure Static Web Apps – App Service | Microsoft Azure

単に使いたかった。
静的コンテンツだけなら Azure CDN と大して変わらないが、 PullRequest でレビューできるのは便利。

Azure Static Web Apps における実稼働前環境での pull request の確認 | Microsoft Docs

そのうち Function 機能もちゃんと使ってあげたい。

移行方法

Jekyll から Hugo

頑張って載せ替えるだけ。

Jekyll to Hugo by kheiakiyama · Pull Request #2 · kheiakiyama/kheiakiyama.github.com · GitHub

個人のレジュメサイトなので、移行前に使っていたデザインテーマはあきらめて別のテーマに移行した。

Azure CDN から Static Web App

Static Web App への載せ替えは淡々とやるとして、移行は TXT レコードを使ったダウンタイムなしの移行を試したが動かなかったのであきらめて CNAME を切り替えてしまった。

Set up a custom domain in Azure Static Web Apps | Microsoft Docs

TXT record validation 、現在は Zone Apex しか対応してないのでは?というのが予測。

移行後

約8分かかっていたビルド&デプロイが1分10秒前後で終わるようになった。

速いのは正義。

GitHub Actions と Azure Pipeline を両方使っていて思うことを書く

この記事は Azure DevOps Advent Calendar, GitHub Actions Advent Calendar 11日目の記事で、表題のとおり両方を実用していて思うところを書く。

はじめに断っておくと、この記事ではマルバツの比較表は出てこない。
特徴を理解して使い分けが必要というのが結論。

はじめに

サービスができた歴史上、GitHub Actions のほうが後発なので、足りないところを感じる場面が多々ある。
たとえば Yaml の書き方で不便さを感じたり、欲しい job が用意されてなかったり、細かい制御ができなかったりという具合だ。

Yaml の書き方

前提として git-flow に近い形で CI/CD を組むことが多いため、それに沿った書き方をしている。
develop に対して開発環境、 master に対して本番環境があるイメージ。

このときのリリースパイプラインは、トリガーやリソースは環境ごとに異なるが、処理の流れは同じパイプラインを組む、としている。
これを Azure Pipeline で組むと、 Template を作ってそこに環境毎の変数を渡す、という形が実装しやすい。

- stage: xxxx
  variables:
  - group: 'dev-env-variable-group' # ここが prod だと変わる
  jobs:
  - template: deployment-template.yml
    parameters:
      azureConnectionName: '$(AzureConnectionName)'
      resourceGroupName: '$(ResourceGroupName)'
      environment: 'DEV' # ここが prod だと変わる

これと同じことを GitHub Actions でやろうとすると、やりづらい。
そもそも GitHub Actions には Template がない
そのため、ブランチによって処理を変えるなどの対応をするか、Yaml を複製することになる。

ここに対するいいアイデアがあったら知りたい。

GitHub Actions で使いたい Job がない

ないのはどうしようもない。
なかったら作ればいいじゃない、ということで GitHub Actions Advent Calendar を見ると結構多くの人が作っているのがわかる。

GitHub Actions では 6000 以上の Job が Marketplace に公開されているとのこと。
私も1つ作った。
kheiakiyama.hateblo.jp

個人的にはイチから OSS を作る機会は初めてだったので、いい経験になっている。

GitHub Actions で細かい制御ができない

Azure Pipeline ユーザにはおなじみの Approvals and check 機能GitHub Actions にはない。
と書くつもりが、 GitHub Universe で今月末にベータ版が公開されるという発表があった。

Environment Protect rulesでは、例えばデプロイ前に人間(required reviewers)の承認を求めるようにしたり、時間を置いたりできる(今月末にベータとして利用可能予定)
GitHub Universe 2020の基調講演で発表された新機能を紹介、GitHub ActionsのアップデートやDependency reviewなど - クラウド Watch

GitHub Actions の agent は Azure Pipeline の fork ということなので、今後も Azure Pipeline にある機能は適宜取り込まれると期待してよさそう。

The GitHub-hosted runner application is a fork of the Azure Pipelines Agent
Specifications for GitHub-hosted runners - GitHub Docs

ところで GitHub Actions のほうが軽量で実行が速い気がするのは fork だからなのだろうか。

導入するまでの敷居

どのクラスタに対して存在するツールか、という問題だと思っている。
自分がたまたま Azure を利用する立ち位置なので敷居は高くないが、たとえば AWS ユーザに Azure Pipeline 勧めるのは現実的ではない。
とはいえ AWS ユーザにも GitHub(Microsoft 傘下!) はかなり使われているため、GitHub Actions に抵抗はそう感じないはずだ。

また、Azure Pipeline ひいては Azure DevOps を使うとなると、エンタープライズ向けのもろもろの機能がついてきてしまうため、そこに目がいってしまい、まずは CI/CD だけ手軽に導入して試す、となりづらい印象がある。
(それもあってか Azure ではいくつかの機能は内部的に Azure Pipeline を作成する、という挙動がある。個人的にはあまり好きではない)

この点、GitHub Actions は GitHub ユーザにスムーズに利用してもらえる位置づけである。
実際のところ、サービス公開以降 Travis CI や Circle CI ユーザが移行しているのを SNS 上で見かけることは多い。

おわりに

ということで、どちらも甲乙つけがたいので今後も両方使い続けていきたい。

Terraform で Market Place の Azure VM をデプロイするときにやること

Terraform 使い始めてしばらくになるのに知らなかったのでメモを残しておきます。

Terraform 定義

plan block がマストです。

resource "azurerm_virtual_machine" "main" {
  ...

  plan {
    name      = "{Name}"
    publisher = "{publisher}"
    product   = "{product}"
  }
}

storage_image_reference で記載する値と同じようなものを入れることになります。
詳細は Azure Provider のドキュメントを参照ください。

Azure Resource Manager: azurerm_virtual_machine - Terraform by HashiCorp

デプロイ前に実行すること

利用許諾に承諾する必要があります。
Azure ポータルでデプロイするときに画面に表示されるアレですね。

それぞれ以下のコマンドで実行します。

Azure CLI: az vm image | Microsoft Docs

PowerShell: AzureRM.MarketplaceOrdering Module | Microsoft Docs

もちろん該当のサブスクリプションに対して行う必要があるので、そこは注意ですね。

Cognitive Service を使った Jekyll 製の翻訳サイトを話題の Static Web Apps に載せ替えた

昨日書いた Azure CDN + Blob Static website のサイト、載せ替えたい欲求が高まったので載せ替えた。

今回の変更は Build 前だったのだが、今やるなら話題の Static Web Apps で実装するのがよさそう。というかもう載せ替えたい。

kheiakiyama.hateblo.jp

ホスティング

f:id:khei-fuji:20200525124958p:plain
hosting

これまで Azure CDN + Blob static website だったのが Static Web Apps に変わったので非常にシンプルになった。

デプロイ

f:id:khei-fuji:20200525125018p:plain
deployment

デプロイも構成要素が減った分シンプルになった。
Static Web Apps ではリソース作成時、GitHub Action が作成され、 GitHub の Secret にデプロイ用のキーが登録される仕様なので、それを使ってデプロイされる。

パイプラインは こちら

f:id:khei-fuji:20200525125855p:plain
GitHub - Secret

現在は Preview で課金されないことになっているが、個人サイトで使うには金額次第で元の構成に戻す可能性があるため、前の GitHub Action はファイルを残してある。
Disable にできない仕様のようなので、意味がない Trigger 設定にしておく。
参考: How can I disable a github action? - GitHub Community Forum

つまづいた点

Jekyll でデプロイできない

このサイトでは Jekyll を使っていて、Hugo のチュートリアル を見てデプロイ設定を推察して書いていたが、デプロイできずに Issue 投げて質問して解決した。

How do we use for jekyll? · Issue #27 · Azure/static-web-apps · GitHub

これだと NG(Hugo はこのパターン なのに・・)

        app_location: '/'
        app_artifact_location: '_site'

これで OK

        app_location: '_site'
        app_artifact_location: ''

一応回答の通りに対応したが、それだと app_artifact_location がなんのためにあるのかって気もしていて、たぶんそのうち解決するのだと思う。

感想

Static Site 部分、API 部分どちらも Consumption Plan になりますように。(個人でも払える範囲だといいなあ)

Effective DevOps ―4本柱による持続可能な組織文化の育て方

Effective DevOps ―4本柱による持続可能な組織文化の育て方

GitHub Actions を使って Azure CDN + Blob Static website を使った Cognitive Service の翻訳サイトをデプロイ

昔作った Cognitive Service による翻訳サイトのホスティングを普通の方法にアップデートした。

github.com

以前の課題

kheiakiyama.hateblo.jp

  • Azure Function Proxy で静的ホスティングは現代的ではないのと、Function のコストが微妙にかかるのでやめたい
  • Travis CI やめたい
  • 昔の記事まで保持するとコストかかる

ホスティング

f:id:khei-fuji:20200523230047p:plain
hosting

以前は Function Proxy + Blob Storage で配信していた。
当時は Blob Static website や Front Door がなく、CDN の設定もやりづらかった印象だったが、今はよくなっているので Azure CDN に置き換えた。
今回の変更は Build 前だったのだが、今やるなら話題の Static Web Apps で実装するのがよさそう。というかもう載せ替えたい。

デプロイ

f:id:khei-fuji:20200523230104p:plain
deployment

これまで Travis CI で処理していた部分を GitHub Actions で書き直した。
GitHub Actions での Blob へのデプロイは install-azcopy-action でインストールした azcopy が行う。
自分の cv サイトがほぼほぼ同じデプロイ方法 なので簡単に載せ替えできた。

翻訳記事の生成

f:id:khei-fuji:20200523230021p:plain
translate

このサイトは RSS フィードを更新することが目的にあるため、コンテンツが追加されるごとにサイトが再度 Generate されないといけない。
以前は Travis CI のジョブを API で呼び出していたが、今回は GitHub Actions を呼び出す。
公式にあるように repository_dispatch を呼び出す必要がある。

参考:

ほか

ついでに Blob Storage のライフサイクル管理をいじって、90日前より前のコンテンツはすべて削除することにした。
RSS フィードを1週間読まないことはあっても 90日はさすがに不要なので。
経費削減。

Azure Storage のライフサイクルの管理 | Microsoft Docs

{
    "rules": [
        {
            "enabled": true,
            "name": "SaveCosts",
            "type": "Lifecycle",
            "definition": {
                "actions": {
                    "baseBlob": {
                        "tierToCool": {
                            "daysAfterModificationGreaterThan": 30
                        },
                        "delete": {
                            "daysAfterModificationGreaterThan": 90
                        }
                    }
                },
                "filters": {
                    "blobTypes": [
                        "blockBlob"
                    ],
                    "prefixMatch": [
                        "translated"
                    ]
                }
            }
        }
    ]
}

感想

GitHub Actions じわじわ詳しくなってきた。

Effective DevOps ―4本柱による持続可能な組織文化の育て方

Effective DevOps ―4本柱による持続可能な組織文化の育て方

Azure Resource Magement テンプレートを書くときにやっていること

大まかに以下の流れで行っている。

  1. 完成品を Azure Portal 上で実装
  2. Azure Portal 上でテンプレートを Export
  3. Visual Studio Code 上で編集
  4. Azure Portal 上でデプロイテスト、問題があれば一つ前に戻る

完成品を Azure Portal 上で実装

動作を確認する意味でも完成品がなければ何も進まない。
ありものをベースに書く。

Azure Portal 上でテンプレートを Export

以下のドキュメントの手順の通りにテンプレートを Export する。

docs.microsoft.com

自分で一から書くのは手間なので動いているものをそのまま落としてくるのが手っ取り早い。

Subscription Id や Resource Group Name などのパラメータがハードコードされているのがちょっと惜しい。
これについて Twitter に書いたところ PM っぽい人が反応してたので、返信したがその後返信がない。。。

Visual Studio Code 上で編集

以下のようにエディタの拡張機能もあるので、Visual Studio Code の生産性が高い。

marketplace.visualstudio.com

先に書いたパラメータの件などはここで書き換える。
テンプレートで使える関数は以下。concatresourceId あたりはほぼ必須だろう。

docs.microsoft.com

他にもリソースの種類によっては「こういうときにどうするのがいいんだろう?」という場面に出くわすことがある。
そういうときは以下の公式テンプレート集から同じシチューエーションを探して参考にする。
たとえばダウンロードしたテンプレートでは書かれている内容でもテンプレートとしては不要な記述が結構あるので、それをどこまで削るべきかといった判断に役立つ。

github.com

Azure Portal 上でデプロイテスト、問題があれば一つ前に戻る

完成したテンプレートを使ってデプロイし、思ったとおりデプロイされたリソースが動くか確認する。

テンプレートを使ったデプロイは以下のドキュメントの通り。

docs.microsoft.com

Azure で Nomad(Consul)のクラスターを作成する

Web サーバーとスケジュールジョブなら App Service と Logic App + Azure Container Instance が最初の選択肢だと考えていたが、他の選択肢を調べてみようと検証した。

Nomad 事情

Nomad は Hashicorp のプロダクト。
Nomad by HashiCorp

日本に馴染みがあるところでは Circle CI や trivago が使っている。
Who Uses Nomad - Nomad by HashiCorp

trivago の記事で KubernetesNomad の違いについて触れている。
"(意訳)Kubernetes は自動車だとしたら Nomad はスクーターで、場合に応じて使い分けます"
Maybe You Don't Need Kubernetes | Matthias Endler

公式でも Kubernetes との違いについて触れている。
"(意訳)Kubernetes は Docker にフォーカスしてますが Nomad は一般的な利用を想定しています"
Nomad vs. Kubernetes - Nomad by HashiCorp

Nomad が Docker 特化ではないとはいえ k8s を使うべきシーンはそこまで多くないと考えていて、Nomad がそのときの代替案になるのではないかと考えている。

知るかぎり Nomad の as a Service はないため、下回りは自分で整える必要がある。

事前知識

  • Nomad 公式の Getting Started を完了している
  • Azure Virtual Machine やその周辺の知識を保持している
  • Terraform は利用している
  • Consul と Packer は触ったことがない

チュートリアル

Hashicorp が手順を用意してくれているので、それに沿って行う。

github.com

Nomad と Consul を同じクラスターにデプロイすることにし、"Deploy Nomad and Consul in the same cluster" の手順を追う。
手順の中で terraform-azurerm-nomad を見ていたと思ったらリンク先が terraform-azurerm-consul でいつの間にか違うリポジトリ、ということがあるのでそこは注意すること。

Consul と Nomad 入りの VM イメージ作成

Use the install-consul module from the Consul Azure Module and the install-nomad module from this Module in a Packer template to create an Azure Image with Consul and Nomad.

Packer 使って VM Image を作成してねということなので、リポジトリ内の以下を参考に作成する。
https://github.com/hashicorp/terraform-azurerm-nomad/tree/master/examples/nomad-consul-image

Packer 初めてだったのでよくわからずにそのまま packer build nomad-consul.json したが、できていた。
環境変数として与える Service Principal のスコープを制限しようとしたところ、packer-XXX というリソースグループを作成できる必要があり、そこだけハマった。

Consul と Nomad のサーバークラスター作成

Deploy a small number of server nodes (typically, 3) using the consul-cluster module. Execute the run-consul script and the run-nomad script on each node during boot, setting the --server flag in both scripts.

Terraform を使ってクラスターを作成する。
クラスターは Virtual Machine Scale Set で構成されている。
ドキュメントを読んで必要なパラメータを入れれば構成できる、はずなのだが Consul と Nomad が動いておらず、デプロイ後にミドルウェアのインストールを SSH で接続して行った。
ここは仮想マシンの起動スクリプトで完結できないと不便なので、実用するときはもう少し掘り下げる予定。

Consul と Nomad のクライアントクラスター作成

Deploy as many client nodes as you need using the nomad-cluster module. Execute the run-consul script and the run-nomad script on each node during boot, setting the --client flag in both scripts.

基本的にサーバークラスターと同じ要領で作業を進めるのみ。
自分の場合はサーバークラスターを作成した時点でコア数上限に引っかかり、別リージョンに作成した。
Consul と Nomaddatacenterregion の値は terraform テンプレートにリージョンとして書いてある値に準じるため接続できないエラーが出ていた。
デプロイ後に config を書き直すことで対応。

感想

Consul サーバークラスターのマネージドサービスが現在プライベートベータになっている。
Announcing HashiCorp Consul Service on Azure

Kubernetes も踏まえてこれを提供しているようだが、Nomad のマネージドサービスが欲しいなという印象。
そうはいっても現状はないので、Virtual Machine Scale Set をうまく使って仮想マシンを操作する必要がないように起動スクリプトを整備するのと、Consul と Nomad のアップデートなどの運用フローを整備できれば実用に耐えられるかなという印象。

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス