【KMC新歓】Go言語で LINE Botをつくろう!

これは、4月15日にKMC春プロジェクト(新歓講座)として開催したイベントで用いたスライドです。

speakerdeck.com

※スライド中でCodeboxというものが出てきますが、これはcoder/code-server をカスタムし、KMC サーバー上にデプロイしたものです。 Codespace等でも代替可能だと思われます。Webhookの公開方法だけ、ngrokなどを使用した方法に切り替えてください。

GitHub github.com

FluxCDのHelmReleaseでinstall後のリソースの差分を出す

目的

自宅 k8s の manifest を管理するリポジトリであるwalnuts1018/infraでは、renovate を用いて、HelmRelease の自動更新を行っています。 FluxCD の HelmRelease リソースには、Chart の Version を指定する項目があるのでそこが更新されていきます。

しかし、リポジトリに Commit されているのはあくまでも HelmRelease の Manifest であり、helm install をするのは Server-Side の helm-controller です。 そのため、Helm Chart 更新の Pull Request を出されても、結局何が変わるのか一目ではわかりません。

そこで、PR の base と head でhelm installした後に生成されるリソースの差分を出力し、PR にコメントされるような GitHub Action を作成しました。

完成形

さっそく完成形を置いてしまいます。

https://github.com/walnuts1018/infra/pull/307#issuecomment-2039935834

このように、PR にコメントが投稿され、Helm によって生成されるリソースの差分が表示されています。

方針

  • base と head、それぞれで kustomize build を行い、一つの Manifest にまとめる
  • その Manifest から、HelmRepository と HelmRelease リソースを抽出する
  • HelmRepository リソースを yq でごにょごにょして、helm repo addを行う
  • HelmRelease リソースも yq でごにょごにょして、helm templateを行う
  • 一番最初の Manifest ファイルに追記する
  • 最後に diff を生成し、API 経由でコメントを投稿する

kustomize build

actions/checkout を使って、PR の base と head のリポジトリをチェックアウトし、azure/k8s-bake を使って kustomize build を行います。

- uses: actions/checkout@v4
  with:
    ref: ${{ github.event.pull_request.base.ref }}

- uses: azure/k8s-bake@v3
  with:
    renderEngine: "kustomize"
    kustomizationPath: "./k8s/clusters/kmc/"
    kubectl-version: "latest"
  id: base_bake

- run: "mv ${{ steps.base_bake.outputs.manifestsBundle }} /tmp/manifests-base.yaml"

- uses: actions/checkout@v4

- uses: azure/k8s-bake@v3
  id: base_changed
  with:
    renderEngine: "kustomize"
    kustomizationPath: "./k8s/clusters/kmc/"
    kubectl-version: "latest"

- run: "mv ${{ steps.base_changed.outputs.manifestsBundle }} /tmp/manifests-head.yaml"

この部分はもともと存在していたのでそのまま使うだけです

Dependency のインストール

yq と jq と helm をいれます

- name: install dependencies
  run: |
    # Install jq
    sudo wget https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64 -O /usr/bin/jq
    sudo chmod +x /usr/bin/jq

    # Install yq
    sudo wget https://github.com/mikefarah/yq/releases/download/v4.43.1/yq_linux_amd64 -O /usr/bin/yq
    sudo chmod +x /usr/bin/yq

    # install helm
    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | sudo bash
    ```

HelmRepository と HelmRelease の抽出

/tmp/manifests-base.yaml/tmp/manifests-head.yaml から、HelmRepository と HelmRelease のリソースを抽出します。

- name: HelmReleaseとHelmRepoを抽出
  run: |
    cat /tmp/manifests-head.yaml |yq -j '. | select(.kind == "HelmRelease") | sort_keys(.metadata.name .metadata.namespace)' > /tmp/helmreleases-head.json
    cat /tmp/manifests-head.yaml |yq '. | select(.kind == "HelmRepository") | sort_keys(.metadata.name .metadata.namespace)' > /tmp/helmrepository-head.yaml

    cat /tmp/manifests-base.yaml |yq -j '. | select(.kind == "HelmRelease") | sort_keys(.metadata.name .metadata.namespace)' > /tmp/helmreleases-base.json
    cat /tmp/manifests-base.yaml |yq '. | select(.kind == "HelmRepository") | sort_keys(.metadata.name .metadata.namespace)' > /tmp/helmrepository-base.yaml

helm repo の追加

/tmp/helmrepository-[head|base].yaml から、helm の repository 情報を取得し、helm repo addを行います。

- name: helm repo add
  run: |
    # helm repo add head-<.metadata.name-.metadata.namespace> <.spec.url>
    cat /tmp/helmrepository-head.yaml | yq -r '"head-" + .metadata.name + "-" + .metadata.namespace + " " + .spec.url' | while read line; do
      helm repo add $line
    done

    # helm repo add base-<.metadata.name-.metadata.namespace> <.spec.url>
    cat /tmp/helmrepository-base.yaml | yq -r '"base-" + .metadata.name + "-" + .metadata.namespace + " " + .spec.url' | while read line; do
      helm repo add $line
    done
    ```

[head|base]-<.metadata.name-.metadata.namespace> という名前で helm repository が追加されました。 yq の中で実行コマンド文字列を生成しているので、Parse 処理が一回で済みます。

helm template

/tmp/helmreleases-[head|base].json/tmp/helmrepository-[head|base].yaml をもとに、helm templateコマンドを使って、リソースを生成します。

helm install --dry-run は、k8s cluster にアクセスできる必要がありますが、helm template は helm 単体で実行できるので、こちらを使います。

- name: helm template
  run: |
    length=$(cat /tmp/helmreleases-head.json | jq -s length)
    for i in $( seq 0 $(($length - 1)) ); do
      cat /tmp/helmreleases-head.json | jq -rs ".[$i] | .spec.values" | tee values.json >> /dev/null
      command=$(cat /tmp/helmreleases-head.json | jq -rs "\"helm template \" + .[$i].metadata.name + \" --namespace \" + .[$i].metadata.namespace + \" head-\" + .[$i].spec.chart.spec.sourceRef.name + \"-\" + .[$i].metadata.namespace + \"/\" + .[$i].spec.chart.spec.chart + \" --version \" + .[$i].spec.chart.spec.version + \" -f values.json\"")
      eval $command | yq  "sort_keys(..)" >> /tmp/manifests-head.yaml
    done

    length=$(cat /tmp/helmreleases-base.json | jq -s length)
    for i in $( seq 0 $(($length - 1)) ); do
      cat /tmp/helmreleases-base.json | jq -rs ".[$i] | .spec.values" | tee values.json >> /dev/null
      command=$(cat /tmp/helmreleases-base.json | jq -rs "\"helm template \" + .[$i].metadata.name + \" --namespace \" + .[$i].metadata.namespace + \" base-\" + .[$i].spec.chart.spec.sourceRef.name + \"-\" + .[$i].metadata.namespace + \"/\" + .[$i].spec.chart.spec.chart + \" --version \" + .[$i].spec.chart.spec.version + \" -f values.json\"")
      eval $command | yq  "sort_keys(..)" >> /tmp/manifests-base.yaml
    done

helmreleases-[head|base].json に、それぞれの HelmRelease のリソースが jsonl として入っているので、jq -sで配列に変換、lengthで長さを取得し、for ループで一つずつ処理していきます。

対象の HelmRelease のspec.valuesを取得し、values.json として出しておきます。

次に、helm template コマンドを組み立てていきます。これも jq の中で文字列を生成しているので、一回で済みます。 helm template <HelmReleaseのname> --namespace <HelmReleaseのnamespace> <[head|base]-HelmRelease中で指定されているHelmReporisitoryの名前>-<HelmReleaseのnamespace(=HelmRepositoryのnamespace)>/<HelmRelease中で指定されているChartの名前> --version <HelmRelease中で指定されているChartのバージョン> -f values.json という文字列が最終的に出来上がります。

そして最後にこれを実行し、出力されたリソースを/tmp/manifests-[head|base].yamlに追記していきます。デフォルトで1行目に---が入るので、そのまま追記できます。 ただしここで、sort_keys(..)を使って、リソースの順番を揃えています。完全ではありませんが、ほとんどの項目が head と base で同じ順番になるので余計な差分が出にくくなります。

diff の生成

ただ diff コマンドを実行するだけです

- name: Build markdown comment with manifest diff
  run: |
    echo "## Manifest diff
    <details>
    <summary>Click to expand</summary>

    \`\`\`diff
    $(diff -u manifests-base.yaml manifests-head.yaml)
    \`\`\`

    </details>" | tee /tmp/comment.md
    ```

PR にコメントを投稿

これが少し難しいですが、「Pull request レビュー コメント用 REST API」を使うのではなく、「issue コメント用の REST API」を使います。 「Pull request レビュー コメント用 REST API」は、PR のコミットに対するコメントが付くので、少し探しにくくなってしまいます。

「issue コメント用の REST API」は、issue だけでなく PR にも使うことができ、これが一番皆さんの使う「PR のコメント」となります。

- name: Comment manifest diff to GitHub PR
  run: |
    cat /tmp/comment.md | jq -Rs '{ "body": . }' | curl --fail \
      -X POST -H 'Accept: application/vnd.github.v3+json' \
      --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
      https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/comments \
      -d @-

まとめ

もっと複雑になるかと思ったのですが、意外と単純に行けました。 あと、実行時間ももっとかかるかと思ったのですが、1 分ちょいで終わります。

これで少しは PR の中身をちゃんと確認する気が起きそうです。(今までは脳死で Merge していました) renovate の PR だけではなく自分で更新する際にも意図しない変更がないかどうか確認出来てよさそうです。

とりあえず自宅 infra のリポジトリと、KMC のリポジトリに導入してみました。しばらく様子をみて改善していきたいと思います。

また、今後は「kustomize の resources に include していない」「Chart の values.yaml に存在しない項目を指定している」などについてもテストを用意していきたいな~と考えています。

PowerShellでAliasを設定するときの便利関数

function SetAlias {
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Alias,
        [Parameter(Mandatory = $true, Position = 1)]
        [string[]]$Command
    )

    foreach ($cmd in $Command) {
        # 空白を含んでいたら関数として定義
        if ($Command -match "\s") {
            $func = "function global:$Alias { $Command }"
            Invoke-Expression $func
            return
        }
        # それ以外はAlias
        else {
            # コマンドが存在するかどうかチェック
            if (Get-Command $cmd -ea SilentlyContinue) {
                Set-Alias -Name: $Alias -Value: $cmd -Scope: Global
                break
            }
        }
    }
}

PowerShellでは、空白を含むAliasを登録できないので、オプションまで含めてAliasにしたいときは、functionとして登録する必要があります。

また、Alias登録時に対象のコマンドが存在しないと困るので、そのチェックも入れています。

それだけでした。

FluxCDのImageUpdateAutomationをPull Requestベースにする & Auto Mergeを設定する

目的

FluxCD には、Manifest 中の Image フィールドを自動的に更新してくれる機能があります。

とても便利な機能なのですが、公式ドキュメントの通りに ImageUpdateAutomationを設定すると、mainブランチに直接コミットされていきます。 そうではなくて、Renovate のように更新ごとに別のブランチを作成し、Pull Request を作成する挙動にしたい!というのが今回の目的です。

また、自動的に Test を実行し、テストに成功したら Merge するという挙動を実現する際に、思ったよりも手間がかかったので、その手順も記録しておきます。

ImageUpdateAutomation のドキュメント通りの設定

あまり詳しくは説明しないので、興味のある方は公式ドキュメントや、id:kakku22 さんの 「Flux v2 で Image Ops を実現する「自動イメージ更新機能」を試した - kakakakakku blog 」などを参照してください。

今回は、アプリごとに以下のような Manifest を適用しました。

apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
  name: hedgedoc
spec:
  git:
    checkout:
      ref:
        branch: main
    commit:
      author:
        email: fluxcdbot@users.noreply.github.com
        name: fluxcdbot
      messageTemplate: "{{range .Updated.Images}}{{println .}}{{end}}"
    push:
      branch: main
  interval: 1m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
    namespace: flux-system
  update:
    path: ./k8s/apps/hedgedoc
    strategy: Setters
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: hedgedoc
spec:
  image: quay.io/hedgedoc/hedgedoc
  interval: 2m0s
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: hedgedoc
spec:
  imageRepositoryRef:
    name: hedgedoc
  policy:
    semver:
      range: "^1.x.x"

ImageUpdateAutomationには、更新方法についての設定、つまり参照する GitRepository や、ブランチ、コミットの Author、更新を監視するパスなどの設定などを記述します。

ImageRepositoryでは image が公開されている repository や取得頻度を設定します。

最後にImagePolicyでは、どのような条件で更新を行うかを設定します。

そして、Deployment などの image の項目に

image: quay.io/hedgedoc/hedgedoc:1.9.9 # {"$imagepolicy": "default:hedgedoc"}

のようにコメントすることで Image の更新が自動的に Push されるようになります。

push 先を別ブランチにする

このままでは、mainブランチに直接コミットされてしまうので、アプリケーション事に別のブランチにコミットされるようにします。

ImageUpdateAutomationpushフィールドを以下のように変更します。

push:
  branch: fluxcd/hedgedoc

こうすると、main から pull し、タグを更新後、fluxcd/hedgedocブランチにコミットされるという挙動になります。

Pull Request を作成する

FluxCD 単体では、自動的に Pull Request を作成する機能は存在しないようでした。そこで、GitHub Actions を利用して、自動的に Pull Request を作成するようにします。

以下のような GitHub Actions を作成しました。

name: flux-auto-PR
on:
  workflow_dispatch:
  push:
    branches:
      - "fluxcd/*"

jobs:
  create-pull-request:
    name: Open PR to main
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        name: checkout
      - name: create pull-request
        run: |
          gh pr create --body ":crown: *An automated PR*" --base main --title "Update image tag"
        env:
          GITHUB_TOKEN: ${{ github.token }}

pushイベントをトリガーに、fluxcd/から始まるブランチに変更があった場合に、自動的に Pull Request を作成します。GitHub CLI を利用しているので、オプションを変更することで、Reviewer の設定や、Label の設定なども行うことができます。

cli.github.com

これで、FluxCD によって作られたブランチに対して、自動的に Pull Request が作成されるようになります。

Auto Merge する

テストが通ったら自動的に Merge するようにしたいですよね。Renovate などでは簡単に実現できますが、Actions 経由だと少し手間がかかります。

まず、Actions の create pull-request ステップに automerge の設定を追加します。

run: |
  gh pr create --body ":crown: *An automated PR*" --base main --title "Update image tag"
  gh pr merge --auto --squash
  gh pr merge --merge --auto

リポジトリの設定でAllow auto-mergeが有効化されており、Branch protection rules でRequire status checks to pass before mergingが適切に設定されていれば、Status Check が通った後に自動的に Merge されるようになります。

しかし、この設定では、Pull Request の作成までは動くのですが、Status Check のための Actions がいつまでたっても実行されないという問題が発生しました。

原因を調べてみると、どうやら Actions で用いられる${{secrets.GITHUB_TOKEN}}の権限では GitHub Actions 内から別の Action の Workflow をトリガーすることができないようです。*1

ということで、記事にある通り、GitHub App を作り、その App に Pull Request を作らせることで、Test の Workflow をトリガーすることにしました。

https://github.com/settings/apps/newに飛び、新しい App を作成します。名前とHomepage URLは適当に、Webhook のActiveを無効化し、Permissionsは、Repository permissions内のContentsPull requestsRead & writeに設定します。

作成した App に対して、Install Appをクリックし、インストールします。その後、App 設定内のApp IDPrivate keysをメモしておきます。

次に、リポジトリの設定に戻り、SecretsAPP_IDPRIVATE_KEYを追加します。

最後に Workflow を以下のように書き換えます。

name: flux-auto-PR
on:
  workflow_dispatch:
  push:
    branches:
      - "fluxcd/*"

jobs:
  create-pull-request:
    name: Open PR to main
    runs-on: ubuntu-latest
    steps:
      - uses: actions/create-github-app-token@v1
        id: generate_token
        with:
          app-id: ${{ secrets.APP_ID }}
          private-key: ${{ secrets.PRIVATE_KEY }}

      - name: Set env
        run: |
          echo "GH_TOKEN=${{ steps.generate_token.outputs.token }}" >> $GITHUB_ENV

      - uses: actions/checkout@v4
        name: checkout

      - name: create pull-request
        run: |
          gh pr create --body ":crown: *An automated PR*" --base main --title "Update image tag"
          gh pr merge --merge --auto

create-github-app-tokenアクションを利用して、GitHub App に対してトークンを発行し、$GH_TOKEN に格納することで、GitHub CLI から新しい Token が自動的に利用されます。

これでようやく、Pull Request が作成され、Test が実行され、Auto Merge されるようになりました!

リポジトリの設定でAutomatically delete head branchesを有効化しておくとmerge後にブランチを消してくれるので便利です。

まとめ

Actions で作成された Pull Request にそのような制約があったことは知りませんでした。

そもそも Actions で頑張るのは面倒すぎるので、FluxCD 側で早く実装してほしいですね~

参考文献

fluxcd.io

kubectl applyでしかインストールできないアプリをFluxCD×Renovateで管理する

目的

walnuts.devのk8sクラスタは、FluxCDを使って管理されています。

github.com

多くのアプリケーションはFluxCD特有のHelm用設定ファイルやdeployment.yamlなどのManifestをコミットすることで本番環境に自動適用される、という運用になっています。

しかし、Helmに対応しておらず、kubectl apply -f https://github.com/<org>/<repo>/releases/download/<version>/<hoge>.yamlを実行してインストールしなさい、的なアプリケーションも意外とあります。(flannel、kubevirtなど)

そこで今回は、そのようなアプリケーションにおいて、手動による操作を省きFluxCDの管理下に置く、さらにRenovateで更新まで自動化することを目標にします。

Kustomize

FluxCDではkind: KustomizationのManifestを置くことで、kustomize buildをflux上で行うことができます。

Kustomizeでは、resourcesに適用するファイルの相対パスを書いていきますが、ここに直接URLを書くことができます。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - https://github.com/flannel-io/flannel/releases/download/v0.24.2/kube-flannel.yml

こうすることで、リモートのファイルをわざわざwgetして、コミットして...といった手間が生じなくなります。楽~

Renovate

このままでは一生更新されないので、Renovateを用いて先ほどのresources内のタグを自動更新します。Renovateというとnpmなどパッケージマネージャーの依存関係を更新する、というイメージがありますが、調べてみるといろいろなDataSourceを用いることができることがわかります。

docs.renovatebot.com

この中にgithub-tagsというものがありました。今回の用途にマッチしそうですね。

customManagers

customManagersのcustomType: "regex"を用いることで、自前で対象ファイルをパースし、パッケージ名(今回は<user|org>/)やバージョンを取得することができます。

{
  ...
  customManagers: [
    {
      customType: "regex",
      fileMatch: "^k8s/apps/.*/kustomization.yaml$",
      matchStringsStrategy: "any",
      matchStrings: [
        "https:\\/\\/github\\.com\\/(?<depName>.*?)\\/releases\\/download\\/(?<currentValue>\\S+)\\/.*\\s*",
      ],
      datasourceTemplate: "github-tags",
    },
  ],
  ...
}

この設定を入れると、リポジトリ内の、/k8s/apps/<hoge>/kustomization.yamlファイルにおいてhttps://github.com/<depName>/releases/download/<currentValue>/<hoge>という文字列を探し出し、github-tagsという名前のdatasourceTemplateにおけるdepNamecurrentValueに対応付けてくれます。

このrenovate設定をリポジトリに入れることで、自動的にPullRequestを作ってくれます。便利ですね~~~~

https://github.com/walnuts1018/infra/pull/96

packageRules

packageRulesを定義することで、特定の条件下での振る舞いを変えることができます。 これを用いることでパッチバージョンについてはAutoMergeを有効化する、といった設定が行えます。

{
  ...
  packageRules: [
    {
      matchUpdateTypes: ["patch"],
      matchDatasources: ["github-tags"],
      automerge: true,
    },
  ],
...
}

この辺りはご自宅のテスト環境とお好み次第、といった感じですね~

renovate.jsonの完全版はこちら

最後に

flannelとkubevirtくらいしか影響がないので正直そこまで困っていなかったですが、世界がちょっとだけ平和になった気がします。

HelmReleaseの自動更新はid:nonyleneさんの Renovate で Flux 配下の Helm Chart をアップデートする - Unyablog. が大変役に立ったのでみなさんも是非。

昇降デスクのケーブルを整理した

昇降デスクのケーブルって最大限上げてもつっかえないようにケーブルを眺めにとっているので、下げて使っている時ブラーんとなって邪魔ですよね。

ということでケーブルチューブを買ってきれいにしました。

Amazonで800円くらいで売ってました。

意外とこれつけるの大変で、既存の配線にぐるぐる巻きつけていくのでチューブがどんどんねじれていっちゃいます。気合で直しました。

充電器系は長さに余裕がなかったので、昇降しない側のデスクに移して充電ステーションスペースを用意しました。


マグネットでケーブルまとめるやつ結構便利でした。

さて、綺麗なデスクは何週間持つのでしょうか。

Walnuts.dev を支える技術 (物理環境/ネットワーク編)

これは KMC Advent Calendar 2023 6日目の記事です。

こんにちは。KMC 46代会長のWalnutsです。最近はKMCのインフラを破壊する仕事をしています。この前はJenkinsや内部DNSなどが動くマシンを破壊しました。次はKubernetesクラスターを壊す予定ですのでお楽しみに。

Memtestでとんでもない数のErrorを出したelizabeth


そして昨日のアドベントカレンダー記事は進捗ゼミさんの「仏像をぶつぞう!!!!というゲームを作りました」でした。
 私もイラストの背景透過などについてお手伝いしました、面白いゲームでしたよね~


さて、今回の記事ではWalnuts家の自宅インフラについて解説していきます。

とりあえず今の所は以下のように少しずつ記事を分けで紹介していきたいと思います。

  • 物理環境/ネットワーク編(この記事)
  • サービス一覧編
  • Kubernetes構成編
  • 自動化編
  • モニタリング編
  • ユーザー認証システム編
  • 今後編

第一回では物理的なサーバー構成やOS、ネットワークなどについて紹介していきたいと思います。

物理マシン一覧

HostName Model CPU Memory Disk OS 役割
cake ProDesk 400 G4 DM Intel i5-8500T (6 cores) 64GB KIOXIA-EXCERIA G2 SSD 1TB Ubuntu 22.04 k8s Node
snow Raspberry Pi 4B BCM2835 (4 cores) 4GB CSSD-S6O240NCG1Q 240GB Debian GNU/Linux 11 k8s Node
donut Raspberry Pi 4B BCM2835 (4 cores) 2GB Apacer AS340 120GB Debian GNU/Linux 11 k8s Node
alice 自作PC Intel i5-12400f (6 cores) 48GB Crucial P5 Plus 1TB / Western Digital 1TB WD Blue Proxmox8 VM基盤&メインマシン
inazuma OptiPlex 790 Core i5-2500 (4 cores) 8GB SSD 240GB / HDD 500GB / HDD 500GB Ubuntu 22.04 バックアップ?

現在Walnuts家には5台のマシンがいます。そのうちMini PCのcake、ラズパイのsnow・donutはk8s専用サーバーとして使っています。自作PCのaliceはProxmoxを入れてVM基盤を作り、その上にWindows、Manjaroのクライアントマシン、k8s Nodeのマシン、検証環境などを立てています。

特に、Windows仮想マシンはホストマシンのGPUやUSBデバイスをアタッチすることによって普通のデスクトップPCのように使えるようにしています。モニターに直接映像出せて便利~

alice外観 / VMの映像をモニターに出した様子

walnuts.devの全サービスをk8sに移行したので、VMを常駐サーバーとしては使わなくなりました。常駐マシンはcake、snow、donutだけですね。数カ月前まではcakeがなかったので、たった6GBでk8sを運用していました。よく動いていたな...という感じです、、、

常駐させたときの消費電力は大体30Wくらいです。めちゃめちゃエコ~~~

ネットワーク

物理ネットワークは特になにも面白いところはないです...

図を見ると分かる通り、自宅内のルーターの上に共用ルーターがあります。そのせいで自宅ではポート開放などができません。

そこで、Cloudflare Tunnelを使うことで各サイトを公開しています。
Cloudflare Tunnelはその名の通り、Cloudflareと自宅間でトンネルを構成し、特定のドメインに来たリクエストをプロキシし、自宅側に転送してくれるサービスです。
アウトバウンド接続のみで外部アクセスができるようになるのでポート開放は不要です。

自宅ではCloudflaredをsnow上で動かし、*.walnuts.devをプロキシしています。本当はk8s Podとして動かしたいのですが謎のエラーによりまだ動かせていません。
Kubernetes構成編などでまた説明しますが、ExternalDNSにパッチを当て、Ingressリソースから自動でCloudflare Tunnelの設定を行うようにしています。Ingressをつくるだけで外部公開サイトを追加できるのでめちゃめちゃ便利です。

HTTP/HTTPS以外はTailscaleを用いて外部からのアクセスを実現しています。SSHやRDPなどは自分しか使わないので、ClientAppが必要なTailscaleでも今の所問題は起きていません。

k8s内のネットワークはMetalLB と Flannel を用いていい感じにしています。そしてkube-api-serverへのアクセスはkeepalivedを用いて冗長構成としています。

おわりに

うーん、物理環境とネットワークについてはあんまりおもしろい内容はありませんでしたね......。
次回以降のKubernetes関連記事ではもっといろいろ面白い話があると思うので期待していてください!

明日の記事はヘルファイアいしだ さんの記事です!お楽しみに!