tech.guitarrapc.cóm

Technical updates

WSL2 環境でのローカル Kubernetes クラスタ構築を検討した話

私はローカル環境の Kubernetes にDocker Desktop for Windows を用いています。

Minikube や kubeadm、k3s、kind、microk8s など各種クラスタ構成がある中で、WSL2にローカルのクラスタ環境を他で組んだ場合の違いを改めてみておくことにしました。

今回は ローカル Kubernetes クラスタの構成にMinikubeを用いて構築してみて、最終的にどれがいいかの所感です。

目次

TL;DR

Windows/WSL で共通のコードベースを Windows にファイルを置きつつ、Windows と WSL でファイルマウントして、docker-compose も使って、Kubernetesも使いたい、という環境だとDocker Desktop (Hyper-V) + WSL1 が現時点ではおすすめ。 Docker Desktop での Kubernetes Cluster は、展開も極めて容易で local docker registry も共用され、Windows/WSLの両方からアクセスが容易なのでとてもいいです。Minikubeやkindと比べても何気に構成も奇をてらっていないのもいいです。今後のdockershimsに対する同行が気になります。

  • Docker Desktop (Hyper-V) + WSL1 がストレスなく快適。WSL1 Ubuntu での docker volume マウントだけ注意。
  • Docker Desktop (WSL2) + WSL2 は、Kubernetes は快適だが docker-compose でファイルマウント、dockerアプリのWebレスポンスが絶望なので無理筋。
  • Minikube を docker-driver でWSL2 に建てる場合、Windows からのアクセスは minikube tunnel で Load Balancerをトンネルする以外は手がない、悲しい。
  • Docker Desktop (Hyper-V) + WSL2 は ホスト docker イメージの共有ができず、大変に厳しいものがある。

半年余り WSL2 で組んでいましたが、Minikube の結果も受けたうえで、Hyper-V + WSL1 に戻ることにしました。 2020年は WSL2 で喜び、WSL2 に泣いた。 2021年がどうなるのか... WSL2 の 9P が劇的改善、vmmem/COM Surrogate の CPUあげあげも解消したら最高ですね、WSL2に戻ります。

なお、Linux 上でファイル操作が完結するなら WSL2 が圧倒的におすすめです。WSL と違って妙な制約一切ないので WSL2 最高。Windows と Linux でファイル操作をまたぐ頻度、ファイル量がほぼないなら WSL2 でいいでしょう。

はじめに

この記事の視点は利用用途に強く依存しています。 私と同じ使い方をしたい方でないとまったく違う検討結果になると予想されます。

環境と利用方法が合致するときにだけ参考になるかもしれませんし、あるいは参考にもならないかもしれません。

環境

  • Windows 10 Pro 20H2
  • Docker for Windows 3.0.0
  • Ubuntu 20.04 on WSL2

期待する利用方法

  • Windows から WSL にたてたKubernetes の Ingress/LoadBalancer へのアクセスを行う。
  • Kubernetes より簡便に動作確認を行う環境として docker-compose も同様の構成で動かす

NOTE: WSL内部からの Kubernetes アクセスのしやすさは評価対象ではない。

Kubernetes のローカルクラスター構成

ローカルのKubernetes Cluster構成には選択肢がいくつかあります。 この記事ではMinikube on WSL2 で見ていきますがちらっと見ておきましょう。

NOTE: おおむね今のローカルKubernetesクラスタの選択肢はなんとなくここをみていただくとして。

  • kind
  • microk8s
  • k3s
  • k3d

それぞれ WSL2 と組み合わせて動作させる方法があるので興味ある人はみるといいでしょう。

NOTE: kind は LoadBalancer に対応していないので、こういう用途では使いにくいのを付記しておきます。インストールは本当に簡単なのですが。

kind.sigs.k8s.io

wsl.dev

k3s on WSL2 · GitHub

wsl.dev

WSL2 ではなく、ホストOS に Kubernetes クラスターを組むのも十分に有用な方法です。 Windows/macOS で最も簡便、かつ構成の組みなおしも用意なのは Docker Desktop の Kubernetes クラスターでしょう。

docs.docker.com

VMに建てるという意味では、Minikube を Hyper-V/Virtual Box で入れるという手もあります。(よくやられているやつ) Minikube に限らず、WSL2 で建てるのとVMで建てるのはおおむね概念は同じなので、どれもそういった方法を提供しています。

kubernetes.io

Minikube on WSL2 のインストール

WSL2 で起動した Ubuntu 20.04 に Minikube を入れて、Minikubeの自動起動をsystemd にさせることろまで構築します。 おおむね Kubernetesブログ に沿ってみていきましょう。

kubernetes.io

記事では Docker Desktop の WSL2 Integration を有効にしていますが、docker のファイルマウントの遅さを排除するため Hyper-V のまま動作させます。

f:id:guitarrapc_tech:20210101032549p:plain

Hyper-Vバックエンドの場合、WSL2 Ubuntu には docker /docker-compose / kubectl は入らないので、Ubuntuには自分で入れましょう。

systemd の構成

Minikube は --vm-driver=none の場合 systemd が必要ですが、docker の場合不要です。

--vm-driver=docker でも、WSL2ログインごとに minikube 起動をやっていられない + SysV Init を用意するのもつらいという場合、WSL2でSystemdを動かして minikube.service を作って調整してもいいでしょう。

NOTE: もちろん、.bashrc で適当に開始させてもいいでしょう。

systemd を WSL2 に入れる方法は、Kubernetes のminikube ブログやいい記事が紹介しています。

qiita.com

これで systemd の起動が確認できます。

f:id:guitarrapc_tech:20210101033522p:plain

systemd で自動起動するためのminikube.service は適当にこんな感じで。

[Unit]
Description=Runs minikube on startup
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/minikube start --vm-driver=docker --addons ingress --kubernetes-version v1.18.0
ExecStop=/usr/local/bin/minikube stop
User={{ ansible_user_id }}
Group={{ ansible_user_id }}

[Install]
WantedBy=multi-user.target

systemd を構成する場合、genie ではなく enter-systemd-namespace スクリプトの方がカスタマイズしやすいのでおすすめです。 例えば、systemd にすると Windows からの WSL2 ログイン時に bash loginをするため /mnt/Windowsパス が維持されず ~/ になってしまいますが、enter-systemd-namespace で bash login 前に今のパスを保持しておいて、ログイン後に自動的に cd するなどの対処が取れます。

minikube の動作確認

minikube を docker driver で起動させてみます。

minikube start --vm-driver=docker

minikube の起動が確認できます。

$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
timeToStop: Nonexistent
$ kubectl get node
NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   21h   v1.18.0

$ k get pod -A
NAMESPACE     NAME                                        READY   STATUS      RESTARTS   AGE
kube-system   coredns-66bff467f8-tmqw6                    1/1     Running     1          21h
kube-system   etcd-minikube                               1/1     Running     1          21h
kube-system   ingress-nginx-admission-create-49j8v        0/1     Completed   0          21h
kube-system   ingress-nginx-admission-patch-cwrkz         0/1     Completed   0          21h
kube-system   ingress-nginx-controller-6f5f4f5cfc-9hw8f   1/1     Running     1          21h
kube-system   kube-apiserver-minikube                     1/1     Running     1          21h
kube-system   kube-controller-manager-minikube            1/1     Running     1          21h
kube-system   kube-proxy-72482                            1/1     Running     1          21h
kube-system   kube-scheduler-minikube                     1/1     Running     1          21h
kube-system   storage-provisioner                         1/1     Running     3          21h

minikube on WSL2 の面倒な点

minikube を --vm-driver=docker-driver で起動した場合に面倒なのは2点です。

  1. minikube の docker registry に push しないといけない
  2. ingress に Windows ホストからアクセスできない

minikube を docker driver で起動した場合、minikube の docker registry は Ubuntu とは別に構成されます。 そのため、bashログイン時に eval $(minikube docker-env) をする必要があるので注意です。

minikube を docker driver で起動した場合、ingress のAddress は docker ドライバーで起動した minikube ip のアドレスになります。 localhost ではないため、Windows から WSL2 への直接のアクセスはできません。 この場合、Service: LoadBalancer にしておくと minikube tunnel でlocalhost にトンネルされるので Windows からアクセス可能になります。

余談: なぜローカル Kubernetes 環境を必要とするのか

開発環境、開発ブランチ環境に対応するKubernetes があるとき、なぜローカルのKubernetes は必要なのかという話があります。

私はKubernetesの管理者であり、Devでもあるので、ローカル開発は何にもまして最速でプロダクトに期待する動作を確認する必須の場といえます。 ローカル開発は PoC であり、実際の運用環境とくらべて構成要素はミニマムだったりクラウド依存のなさなど差異もあるでしょう。 しかし、想定するアプリ動作を満たす場としては最適であり、常にメンテされていくべきと考えています。 また、自分のみに閉じているという意味でもローカル開発環境は整備する価値があります。 Kubernetes に各種 Operator/Controller を入れて動作させる場合は、ローカルKubernetes がない状況で、Devなどに展開するのは開発効率の面からみて避けたいものです。

ただしこれらの前提として、実際に動作する環境とかけ離れた構成になることは望ましくありません。 例えば、ローカルKubernetesではIngress に何かしらの制約がありLoad Balancer にする、といった状況は絶対的に避けたいものです。 運用環境とかけ離れ、期待する動作環境をローカルに作れず、メンテもできない場合、そのローカルKubernetes 環境はむしろ害悪になるので避けたいものがあります。

別の視点としてKubernetesの管理者という前提がない場合、ローカルKubernetes が必要である必然性が消えます。 例えば、通常のアプリコードを書いて動かすだけにおいては、Kubernetes だろうとどこででもいいからコードがデプロイされて動作すればいいです。 というか Kubernetes とか知りたくないし、ぐらいでもいいでしょう。

Kubernetes の管理をしつつDevもする身としては、ローカルKubernetes 環境はほしいものですが、メンテできるか、その構成は常に今のスタンダードからみてかけ離れていないかは常に気にする必要があります。Minikube はそういう意味ではスタンダードですが、悩ましい側面も多いですね。

kind on WSL2 はどうなのか

インストールはスムーズです。minikube より楽。 ただし、kind は Load Balancer に対応していないので使いにくさは否めません。

おまけ: WSL環境の選定

WSL には、WSL1 と WSL2 があり、この二つはホストOS のWindows との相互利用で結構な違いがあります。 Kubernetes を WSL に建てる場合、これは大きな違いになります。

docs.microsoft.com

f:id:guitarrapc_tech:20210101024249p:plain

WSL2 なのか WSL1 なのか

選択肢はおおむね2択であることが多いかと思います。

  • WSL2のみで利用し純粋にLinuxとほぼ同様に扱いたい、WSL2とWindows は速度面などで気にならない場合、WSL2 + Docker on WSL2 がいいでしょう。
  • Windows と WSL2 のファイルマウント1 の9Pに由来する遅さ、Docker on WSL2のパフォーマンス制約、ホストOSのCPU/メモリ負荷が気になり許容できない場合、WSL1 がいいでしょう。

別の構成として、Docker のみ Hyper-V で動かし、WSL2 でUbuntu を動かすことも考えられます。 この場合、docker 利用時のファイルマウントの遅さは生じず、WSL2 の Ubuntu はLinux 同様に扱えますが ホストWindows の Docker は共有できません。(tls:localhost:2375 がだめなんですよね)

WSL2 でないといけないのか WSL1 ではだめなのか

Windows/WSLの相互利用時のパフォーマンス、docker volume のマウントの取捨選択になります。 私の利用ケースはWindowsとWSLの相互利用がメインなので、WSL2 よりもWSL1 のほうが望ましいとなります。

ファイルマウント、ホストCPU負荷の両面でWSL1 は優れています。 一方で、純粋なLinux として使うには細かな差異とdocker 動作の制約が大きなハンデになります。(エラーもでないので罠に感じやすい)

WSL2

ほとんどのケースで問題ないことが多いでしょうが、パフォーマンス制約は軽く見るのは避けるほうがいいでしょう。

NOTE: Zen3 5900X + PCIE 4.0 NVMe でCPU負荷は無視できます。しかしWindowsホストファイルのマウントはどうしようもなく遅く回避策が現状ありません。

回避不可能な Windows ホストとのファイルボリュームマウント制約、そしてCPU負荷 (vmmem / COM Surrogate) があることに注意です。

NOTE: .wslconfing でメモリ、CPUの上昇をある程度止められますが十分に負荷が大きいので厄介です。

ただ、WSL2 Ubuntu と Docker WSL2 で Docker registry も共有され、docker/kubectl も入ってくるので非常に使いやすいです。

WSL1

WSLでdocker volume マウントができない制約があります。また、単純なWSL内部のファイルアクセスもWSL2 に比べて格段に遅いので注意がいります。

NOTE: docker実行はWindows でdocker run している限りは起こらないので回避策はあります。

WSL2 と違って、Windows ホストに対するパフォーマンスペナルティがなく、WSL での動作制約があるだけなのはバランスがいい選択になります。

WSL Ubuntu から docker を使うには、Docker Desktop で tls:localhost:2375 を開放して、WSLのDOCKER_HOST にする必要があります。 これで Windows の docker registry が WSL Ubuntu でも共有されるので、使い勝手の面で非常に楽になります。

おまけ: Kubernetes のインストール先の検討

ホストOSのWindowsでKubernetes クラスターを組んだ場合、Windows/WSLの両方からアクセスしても問題ありません。 WSL2 でKubernetes を組んだ場合、Windows からのアクセスには WSL2 の localhost でアクセスができる必要があります。

こういう意味では、Windows ホストにサクッとクラスターを組んで、いつでも爆破できる状況を作るのが最も使いやすいでしょう。

Docker Desktop for Windows なら、Settings 画面から Kubernetes Cluster のファクトリーリセット、再構成も用意なのでいいでしょう。


  1. それに伴うネットワーク速度の遅さも発生する

Unifi AP AC-Pro が永遠に消えたVLAN への接続を試みる件

Unifi のアクセスポイントである Uniti AP AC-Pro (UAP) を使っています。

www.ui.com

今買うなら Unifi nanoHD が本来筋なのですが、いろいろあってメッシュ先のLAN ポイントとして使いたかったのでシカタナイ。

unifi-nanohd.ui.com

今回は、UAPのアップグレード中にVLAN の構成を変更したらエラーが出続けてちょっと困ったことになったので対処をメモ。

目次

再現手順

  • UAP のファームアップデートがきた通知があったので、Unifi Deram Machine(UDM) のコンパネからUAPのファームを更新
  • 更新中に 不要になったVLAN2000の削除
  • UAP が起動後、UAP が消えたVLAN へのアクセスを試みて失敗するエラーが出続けます。
Message: AP[MAC ADDRESS] event: {"event_string":"EVT_AP_Notification","payload":"UAP-AC-Pro is unable to reach the DHCP server for VLAN 2000"}

f:id:guitarrapc_tech:20201229021444p:plain

どういうトラブルか

私の場合消したVLANはVLAN2000 だったのですが、インシデントに対してメール通知を仕掛けていたので1分に一度エラー通知メールが飛んでしまいました。

さて、ファームアップデート後に設定が同期していないと思われるので対処をやってみます。 上から順に解決すればそれでok でしょう。

  1. Provision のし直し
  2. Fatory Reset からのデバイス追加
  3. 適当な既存VLANネットワークの構成をし直.してVLAN設定の同期

結論からいうと、適当な既存VLANネットワークの構成をし直せば同期しました。

復旧の流れ

Provision をすると、設定が同期されるので解消を期待しましたがエラーは出続けました。 Provision あんまりうまくいくことないのでぐぬぬ。

仕方ないので、UAPのFactory Reset、 UDM上から UAP を Forget、iOS の Unifi App からUAPを追加し直しても復帰後に同じエラーが出続けました。 UAP の Factory Reset 後にUDM上からデバイスをForget 忘れてて追加できなくて??っとなったのでマニュアルは読みましょう。

help.ui.com

ここまでで、UAP自体というより同期されるべきVLANの構成が正常にUAP向けに生成されているない気配なので、VLAN を修正して強制的に同期させます。 既存の適当なVLAN を修正します、私の場合 VLAN ID を修正したかったところだったので直してSave、これでUAP が自動的に構成を受け取ってエラーが消えました。

ちなみに、エラーが出てる間は既存の Guest Portal な SSID が不正なアクセスポイントとして検出もされていました。コミュニティフォーラム見るとGuest Portal を有効にしていると起こる気配も。

まとめ

自動構成同期、いいのですがどういう構成を同期しているのか、そういえばあんまり気にしたことありませんでした。 Unifi の場合、Device > UAP > Settings > Download Device Info で動作状況がダウンロードできるので良いのですが、ちょっと困りますね。

余談

そういえばこういう古い記事はいい加減直してほしいものです。VHT20 以外も選べるようになってるのですよ。

internet.watch.impress.co.jp

f:id:guitarrapc_tech:20201229015843p:plain
UAPのVHTは選択可能になっている

scoop の bucket を自動更新する

Scoop Bucket を作るのは避けたいものです。 しかし、Main や Extras に追加するのもアレだし、既存のパッケージ更新はメンテされてないし、など様々な理由で自分のバケットを作ることはあるでしょう。

自分のバケットを持った時に面倒なのが、バケットの更新追従です。 幸いにも Scoop には Excavate という自動更新する仕組みがあります。今回はこれを仕込んでみましょう。

目次

TL;DR

  • Bucket の manifest を記述した json に checkverautoupdate セクションを設定する
  • Excavate と更新スクリプトをバケットに配置する。
    • バケットフォルダで、bukcet/ などフォルダを掘っている場合はスクリプトで対応が必要
  • Excavate は docker-compose で動くので、動かしっぱなしにするか適当などこかで定期実行

実際に使用しているリポジトリ

この記事で使っている自動更新のためのスクリプトや仕組みは .github フォルダに一式が入っています。

github.com

動作環境

バケットの自動更新は以下の環境で動作します。

  • Linux コンテナ
  • PowerShell 7
  • 定期実行環境 (ローカルマシン、GitHub Actions、Kubernetes など)

Linux コンテナで動作するので、事実上実行環境に困らないでしょう。Windows でも実行できますが、私はLinuxのみで行っています。

Scoop App Manifest 自動更新の仕組み

3つやることがあります。

  1. 自動更新するバケットjsonを自動更新に対応させる
  2. 自動更新スクリプトをバケットのリポジトリにおく
  3. 自動更新を定期実行する

順番に見ていきましょう。

1. 自動更新するバケットjsonを自動更新に対応させる

Scoop App Manifest は、checkverautoupdate に適切な内容を記述することで自動更新対象のマニフェストとして認識されます。この辺りは公式の Wiki に書いてあります。

App Manifest Autoupdate · lukesampson/scoop Wiki · GitHub

といってもWikiの内容は複雑でよくわからん.... ということで実際に使っているシンプルなパターンで説明します。

GitHub のリリースページを見る

今回のパターンは GitHub Releases のパッケージ更新を見てバケットを構成している場合に利用できます。ただし、プレリリースではない && バージョン1.0.0 や v1.0.0 といったパターンでタグ公開されているの2点が前提です。

実際に利用しているctop を定義したマニフェストを用意しました。

{
    "description": "Top-like interface for container metrics",
    "homepage": "https://github.com/bcicen/ctop",
    "version": "0.7.5",
    "license": "MIT",
    "url": "https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-windows-amd64#/ctop.exe",
    "hash": "sha256:bffb1499d62c46b70dd25d557b653f812ccdc8b4bfb08473c063a6265faf78b3",
    "bin": "ctop.exe",
    "checkver": "github",
    "autoupdate": {
        "url": "https://github.com/bcicen/ctop/releases/download/v$version/ctop-$version-windows-amd64#/ctop.exe"
    }
}

自動バージョン更新に必要なのは、checkver と autoupdate のセクションです。

  • checkver"github" で問題ありません。これでリリースぺージのTagが \/releases\/tag\/(?:v|V)?([\d.]+) パターンで公開されていれば抽出されます。
  • autoupdate のセクションは、$version を使って実際のリリースページのダウンロードurl を表現します。url が https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-windows-amd64 なので、0.7.5 というバージョンが $version に置き換えられていることがわかります。

これでバケットのjsonは準備が整いました。

2. 自動更新スクリプトをバケットのリポジトリにおく

リポジトリ直下にバケットのjsonを配置しているか、bucketフォルダを掘ってそこにまとめているかで微妙に異なります。

bucket フォルダを掘っている場合は、lukesampson/scoop-extras の bin フォルダの中身を、そのまま自分のリポジトリの/binに持ってくるといいでしょう。

f:id:guitarrapc_tech:20201123222946p:plain
lukesampson/scoop-extras の bin フォルダの中身

もしもリポジトリ直下にバケットjson を置いている場合は、以下のように $dir = "$psscriptroot/.." とします。各スクリプトにこの変更がいるので面倒です。

# auto-pr.ps1
param(
    # overwrite upstream param
    [String]$upstream = "<user>/<repo>:master"
)
if(!$env:SCOOP_HOME) { $env:SCOOP_HOME = resolve-path (split-path (split-path (scoop which scoop))) }
$autopr = "$env:SCOOP_HOME/bin/auto-pr.ps1"
# $dir = "$psscriptroot/../bucket" # checks the parent dir
$dir = "$psscriptroot/.." # checks the parent dir
iex -command "$autopr -dir $dir -upstream $upstream $($args |% { "$_ " })"

これでバケットのスクリプト配置も完了です。

NOTE: 調べるとこのスクリプト名がbucket-updater.ps1 だったり auto-pr.ps1 だったりしますが、後述のExcavatorを使う場合どちらでも対応されているので大丈夫です。auto-pr.ps1 が公式でも使ってて新しいかな?

3. 自動更新を定期実行する

自動更新方法はWikiにもいくつかのっています。

App Manifest Autoupdate · lukesampson/scoop Wiki · GitHub

個人的には、ScoopInstaller/Excavatorを用いて docker-compose で実行するのがおすすめです。Linux で実行できるのと、docker-compose が利用できるので実行環境を選びません。あとこの方法なら Kubernetes で実行も簡単です。

github.com

docker-compose を実行すると ssh キーが生成されるので、公開鍵 id_rsa.pub をGitHub に登録して push できるようにしましょう。sshキーを再利用する場合は、id_rsa も取得しておいて、docker-compose 実行時にマウントさせればok です。

$ docker-compose up --build
$ docker-compose exec bucket cat /root/.ssh/id_rsa.pub
$ docker-compose exec bucket cat /root/.ssh/id_rsa

このコンテナイメージは定期的に呼び出して実行するには注意があります。/sbin/my_init を実行した上でないと scoop コマンドがコンテナ内部で見つからずエラーが出ます。

走らせっぱなしで定期実行する前提なイメージになっているので、自分のように定期的に呼び出し実行する場合は docker-compose で次のようなラッパーコマンドを用意して呼び出すといいでしょう。

#!/bin/bash
/sbin/my_init &
chmod 600 /root/.ssh/id_rsa
pwsh ./root/scoop/lib/install.ps1
bash -x /root/excavate.sh

これで コンテナを使っていい感じに更新されるようになります。

実行環境について

このような定期実行環境は、Kubernetes の cron job、後今日使えるようになった Amazon ECS のdocker-compose対応などが楽でしょう。

www.docker.com

GitHub Actions での使用は、使用条件のここに該当するかによりそうです。

any other activity unrelated to the production, testing, deployment, or publication of the software project associated with the repository where GitHub Actions are used.

バケットのデプロイ作業なので実行は許されそうですが、自前のクラスタで実行で行えるならそれがいいでしょう。 仮にリポジトリで実行していますが、自前Kubernetes クラスタでの実行に変更を予定しています。

以下に GitHub Actions で実行する場合の Workflow を示します。

name: auto update bucket

on:
  schedule:
    - cron: "0 * * * *"
  workflow_dispatch:

jobs:
  update:
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: openssl aes-256-cbc --pbkdf2 -d -in .github/.ssh/id_rsa.cipher -k ${{ secrets.CIPHER_KEY }} >> .github/.ssh/id_rsa
      - run: docker-compose up
        working-directory: .github

パッケージの更新ログの例です。

main_1  | 
main_1  | ScriptBlock ID: f43b73d1-2181-437c-9d72-8b0797e62035
main_1  | Path: /root/scoop/lib/install.ps1
main_1  | py: 1.0.1.6
main_1  | DejaVuSansMono-Bront: couldn't match '\/releases\/tag\/(?:v|V)?([\d.]+)' in https://github.com/chrismwendt/bront/releases/latest
main_1  | bombardier: 1.2.5 (scoop version is 1.2.4) autoupdate available
main_1  | Autoupdating bombardier
main_1  | Downloading bombardier-windows-386.exe to compute hashes!
main_1  | Downloading https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-windows-386.exe#/bombardier.exe (9.7 MB)...
main_1  | Computed hash: d2bfd99019ca590610c89ccf829bf4c84ed6652821fe55e7f9bcf342106fe496
main_1  | Downloading bombardier-windows-amd64.exe to compute hashes!
main_1  | Downloading https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-windows-amd64.exe#/bombardier.exe (10.9 MB)...
main_1  | Computed hash: 52e0c22e3a10c06f7013bbb09d713ab52fae6fba5a86a5ffcfdd6546ed86b7cf
main_1  | Nov 22 12:17:39 3e2cb27a65fb powershell[86]: (7.0.2:9:80) [ScriptBlock_Compile_Detail:ExecuteCommand.Create.Warning] Creating Scriptblock text (1 of 1):
main_1  | {⏎⏎            $architecture = $_.Name⏎⏎            if ($json.architecture.$architecture.$prop -and $json.autoupdate.architecture.$architecture.$prop) {⏎⏎                $json.architecture.$architecture.$prop = substitute (arch_specific $prop $json.autoupdate $architecture) $substitutions⏎⏎            }⏎⏎        }
main_1  | 
main_1  | ScriptBlock ID: a1ca077d-4175-458e-9ad3-e0f9e4c68c86
main_1  | Path: /root/scoop/lib/autoupdate.ps1
main_1  | Writing updated bombardier manifest
main_1  | ctop: 0.7.5
main_1  | warning: LF will be replaced by CRLF in bucket/bombardier.json.
main_1  | The file will have its original line endings in your working directory.
main_1  | Creating update bombardier (1.2.5) ...
main_1  | hub add bucket/bombardier.json
main_1  | warning: LF will be replaced by CRLF in bucket/bombardier.json.
main_1  | The file will have its original line endings in your working directory.
main_1  | hub status --porcelain -uno
main_1  | hub commit -m 'bombardier: Update to version 1.2.5'
main_1  | [master 603a742] bombardier: Update to version 1.2.5
main_1  |  1 file changed, 5 insertions(+), 5 deletions(-)
main_1  | Pushing updates ...
main_1  | hub push origin master
main_1  | Warning: Permanently added the RSA host key for IP address '140.82.112.4' to the list of known hosts.
main_1  | To github.com:guitarrapc/scoop-bucket.git
main_1  |    c5e2c3f..603a742  master -> master
main_1  | hub reset --hard
main_1  | HEAD is now at 603a742 bombardier: Update to version 1.2.5
main_1  | + '[' -f /root/bucket/bin/bucket-updater.ps1 ']'
github_main_1 exited with code 0

まとめ

難しい記述をしなくても自動更新できるのはいいことです。 実行環境だけ面倒ですね。

参考

手の入れ方が好みじゃないので参考程度にしています。 こういう公式のやり方に乗っかる場合は、コンテナに手を入れないのがおすすめです。メンテしきれなくなるので。

Scoopを使ったWindows環境構築のススメ - Hyper!!! - Qiita

Unifi Dream Machine で MAP-E方式の IPv6 に対応する

IPv4 PPPoE からIPoE にしつつ、Unifi Dream Machine (UDM) で IPv4 over IPv6 環境でアクセスするまで組んだのでそのメモです。

Unifi Dream Machine はMAP-E に対応していないので、ちょっと小細工が必要だったのは学びでした。

私が欲しい内容の記事がなかったので自分で書いたいつものプレイ。

目次

TL;DR

特に複雑なことは行わず、必要なことを順にクリアするだけです。ポイントは3 つです。

  1. MAP-E 方式の IPoE (IPv4 over IPv6) で、DHCPv6 Prefix Delegate (DHCPv6-PD) を行うため「ひかり電話」の契約が必要 (HGWもこれで得られる)
  2. ホームゲートウェイ(HGW)によるIPoE接続 にすることで、UDMで DHCPv6-PD を受けられるようにする (ついでに速度も改善する)
  3. Unifi Dream Machine で、LAN/WAN ともに IPv6 対応を行う

構成は以下の通りです。

  • ぷらら光
  • 光配線方式
  • ひかり電話あり、HGW あり
  • Unifi Dream Machine

結果、UDM の出口速度でIPoE VDSL から IPoE光配線 で 約6-10倍に上がったのでいったんこれで。(満足できてない)

今後のメモ

  • HGW のLAN接続とUDMのWifi を比べたときに、アップロードは有線並みに出ている一方でダウンロードが遅い (要改善)
  • WIFI 6 対応した Unifi 製品はアメリカでアーリーアクセスで出ているので日本にも来てほしい (希望)
  • WAN回線を 2Gbps 程度にあげるか、10Gbps サービス試していきたいところ (まずはWifi速度の改善をしてから)

前説

いくつか事前情報を共有します。

記事の対象となる人

  • UDM (UDM Pro) を使いMAP-E 方式の IPoE を用いて、クライアントが IPv6 ネイティブアクセスを可能にしたい人
  • 海外ルーターなどMAP-E をサポートしてない自分の好みのルーターを使う場合、同様に該当するでしょう。

はたして国内に何人いるのでしょう、いない気がします。

記事の対象ではない人

  • UDM 配下のクライアントが IPv6 を持たなくていいなら不要です。IPoE を契約してUDM をつなぎ IPv4 のみにすればok です、この記事は IPv6 もクライアントに配布してつなぎたい場合に役立つでしょう。
  • 国内の IPoE 対応を謳うルータであれば不要です。多くの場合、MAP-E (あるいは DS-Lite) 方式のIPoE で契約して、プロバイダが提供する無線ルーターあたりでつなげばいいでしょう。自前のWifi にしても AP モードで適当につなげばok なはずです。
  • Nuro もIPv4/v6デュアル方式なので不要です。ほぼなにも考えずただつなぐだけでいいです。DHCP-PD で Prefix /56 が降ってきます。

LANネットワーク環境の前提

私の個人環境は8年前から完全にWifiで統一しています。 ケーブルが嫌いというのもあるのですが、配線や配置の自由さと、ネットワーク環境でやりたい放題やるを考えたときに、Wifiもまとめて制御することを自分に課しています。有線LANは好みではないし、Wifiの技術的進展が目覚ましいのでよい。

Wifi で統一するにあたり、当然メッシュ環境が欲しくなるので以前は Amplifi を使っていました。

tech.guitarrapc.com

しかし、メッシュを広げつつ、計測やIDS/IPSを展開しつつ、今後の変化にも追随することを考えるとUnifi にしたくなります。でも Cloud Keyはいや。ということで、Unifi Dream Machine は欲しかったマシンであり、日本Ubiquiti Store で販売されてすぐに切り替えました。

UniFi Dream Machinejp.store.ui.com

私の環境において「あらゆる機器は UDM配下からのアクセスになる」というのが構成上の大前提となります。

もしもUDMに興味がなくて、「さくっとIPoEでいい感じに組みたい」だけなら適当にIPoE 対応の国内ルーターでも使えばいいと思います、好きにするのが一番。Synology とかもMAP-E対応ありますしね。

www.synology.com

WAN ネットワーク環境の前提

私はISPに、ぷららを利用しています。

以前は住んでいたところが VDSL だったため、何をどうあがいても100Mbps が上限でした。

とはいえ、IPv4 PPPoE だと夜間の速度が不安定になることが多くなってきたので、回線速度を安定させるため IPoE にすることにします。

IPoE にするだけで、いったん回線速度は安定しますが、せっかくなので IPv6 への対応も考えたいものです。 しかし、ぷららが提供する MAP-E 方式の IPoE 環境とUDM は相性が悪いので「UDM配下のクライアントで IPv6 ネイティブでアクセスさせるためにどんな構成にするのか」、これがこの記事のポイントです。

ネットワーク環境

IPv4 で PPPoE でつないでいるときは次のような環境です。

ONU -- ルーター -- UDM -- 各Wifiクライアント

最終的に、MAP-E方式の IPv6 で次のような構成に持っていきます。

HGW -- UDM -- 各Wifiクライアント

PPPoE から IPoE までの変遷を見ていきます。

事前調査

IPoE と UDMをどう組めばいいのか考えます。

UDM は MAP-E にも DS-Lite にも対応していない。これは調べればすぐにわかります。

ではどうすれば組めそうでしょうか。

採用しなかった方法

まず採用しなかった方法を見てみます。

EdgeRouter の EdgeOS なら DS-Lite 構成組まれている方もいますが、UDM は UnifiOS でそういった構成は組めません。(そういえば MAP-E 組んでいる人はいませんね)

stop-the-world.hatenablog.com

こういう MAP-E に対応していない場合のよくある対処の一つは、IPv4 アクセスは IPv4 PPPoE 回線から、IPv6 アクセスは IPv6 プラスルーター経由でアクセスさせる方法です。PPPoE を残したくないですし、なんのための IPv4 over IPv6 なのかって話で好みではありません。(過渡期としてはやむを得ないですね。あと、ぷららの技術部門の人と話をしたときも、ぷららの人はこの構成で話していました、わかる。)

chitoku.jp

あるいは、ひかり電話なしでRAをLANにいきわたらせてしまうのも手でしょう。IPv6でクライアントがグローバルにさらされるのを避けるために、スマートスイッチでタグベースVLANを使ってIPv6を選択的に設定するのもありだと思います。(めんどくさすぎて好みじゃない)

yabe.jp

どれも単純ではない、自分が運用したくないと感じる構成です、こういうのは避けたい。

必要な条件が何かを考える

IPv4 over IPv6 でUDMを使ってどのように組めるか調査すると、「ひかり電話」の有無で前提が大きく変わるのがわかります。ひかり電話の有無で DHCPv6 が使えるかが決まり、同時にHGW を使えるかも決まります。

構成の単純さとDHCPv6 を考えるとひかり電話はいれるのが妥当だと思います。月500円で機器にお金をかけてもどうしようもない問題が解決するので。ひかり電話は使わないので、これだけのために入れるのは納得感はないですが!

もう一つが HGW です。UDM はMAP-Eをしゃべられないルーターなので、事前にMAP-E をしゃべらせておく必要があります。

  • HGWがない場合、MAP-E 認証をさせるため、HGWとUDMの間に対応ルータを置いた二重ルータが確定します。
    • HGWとUDM間にルーターを挟むため、DHCPv6-PD がスムーズにいかなくなります。
  • HGW がある場合、HGW でMAP-E認証が終わっているので、UDM を直接刺せます。
    • UDMで直接DHCPv6-PDを受け取ることができます。

HGWから直でなくても、MAP-E 対応ルーターが RA パススルーに対応していればワンチャンとふと思いましたが、私の借りた MAP-E対応ルーター WN-AX1167GR2 は RAパススルーがなかったです。

必要な条件

次の通りです。

  • ひかり電話を契約する
  • HGW を手に入れる

YAMAHA などでもよく組まれているほう方法ですね。

y2lab.org

NTT の方式でいうところの、光配線方式の接続パターンB が該当します。

4466.jp

では構成の変遷を見ていきましょう。

余談: UDM とMAP-E

UDM が MAP-E 対応すると、ひかり電話なしでもよくなるので対応されると嬉しいですね。対応されるかは期待はあまりできなさそうですが....

community.ui.com

1. PPPoE から IPoE への変更

ぷららの場合、ぷららv6エクスプレスで IPoEを提供しています。 プロフィールページから「ぷらら光」に契約を切り替えることでIPoE に変更できます。 なかなか手間がかかる作業で、事前にNTTから承諾番号を得る必要があり、ぷららの契約切り替え自体も概ね2週間見る必要があります。

www.plala.or.jp

この時点では、「HGW での IPoE 接続」はしません、まずは IPoE 接続を安定させます。ということで、IPoEへの切り替えを申し込むにあたり、MAP-E対応ルータとして「ぷららWi-Fiルーター」をレンタルします。

PPPoE から IPoE への切り替え時の申し込みは次の通りです、めんどくさい。

  • 切り替えに2週間程度は猶予時間を見る
  • 事前にNTT から承諾番号を得る
  • 「ぷらら光」への切り替え
  • 「ひかり電話」の契約
  • 「ぷららWi-Fiルーターレンタル」の申し込み

変更予定日前に、HGWとMAP-E 対応ルーターが届きます。変更予定前日夜にでもVDSLルータとUDM の間に入れましょう。AM8:00ぐらいに切り替えが走ったのが計測できました。

IPoEへの切り替えが無事に完了すると、ぷららv6エクスプレスが開通済み、IPoE対象接続先がIPv4+IPv6へと変わります。

f:id:guitarrapc_tech:20201017034334p:plain

接続状態はVDSL方式の接続パターンCになります。すごく面倒くさい。

VDSLルーター -- HGW -- MAP-E対応ルーター -- UDM -- 各Wifiクライアント

この時点では、UDM 配下には IPv6 が配布されず IPv4のみになります。MAP-E対応ルーターを抜いて IPv6 ネイティブ接続にすることはできますが、はっきり言ってどこも接続できないのでムリ。 (GitHub も Twitter もつながらないのは意外でしたが)

なので、IPoE + IPv6 もクライアントで使いたいなら、MAP-E 対応ルーターに直接接続すれば期待通り動きます。(私はUDM を使いたいのでやらない)

通信速度は、VDSL の上限によって 100Mbps できっちり止められます。PPPoE とは違い、IPoEでは速度はある程度安定し、100Mbps 程度ならずっと維持できるのでいいでしょう。

余談ですが、UDMの代わりに Amplifi HD をおいて Bridge 接続 + Router Steeling を仕掛けると、Wifi クライアントに IPv6 が配布されたりします。Amplifi をどうしても使いたい人はこれでもいいですね。

2. VDSL から 光ファイバー回線への切り替え

いろいろあって、住んでいるところがVDSL回線が光ファイバー回線に更新されることになりました。(下り/上り 1Gbps)

ということで、当然 VDSL ルーターは不要になり、光コンセントからHGWに直接回線がつながるようになります。 接続状態は光配線方式の接続パターンCに相当します、一般的な光回線が入っている場所ではこの構成が多いでしょう。

HGW -- MAP-E対応ルーター -- UDM -- 各Wifiクライアント

VDSL がなくなるだけですが、これで回線速度が 300Mbps に上がりました、遅いもののだいぶん改善しました。(LAN も Wifi も同じ速度がでている) 当然ですが、まだ UDM の配下には IPv6 は渡せず IPv4 のみです。

余談: MAP-E 対応ルータの下に UDM を置くと、なぜか速度が 60~70Mbps に落ちたのですが、どうやら LAN の DHCPv6 が残っているとゴミ設定で速度が落ちるバグがある気配があります。LAN の IPv6 対応を無効にして再起動すれば速度劣化なしに300Mbpsでます。(その後は同じ設定をいれても速度劣化がなくなりました)

3. ホームゲートウェイ(HGW)によるIPoE接続 への変更

これで、UDM で IPv6 を配布する準備が整います。IPoE の MAP-E 接続をHGW にゆだねましょう。

HGW にするには、HGW製品が型番が300番台以降でないとだめなのと、いくつか使えなくなるサービスがあるので注意です

faq.plala.or.jp

faq.plala.or.jp

まずは、ぷららのプロフィールから 「ホームゲートウェイ(HGW)によるIPoE接続」への切り替えを申し込みましょう。

www.plala.or.jp

次の日の夜ぐらいにいきなりスパッと切り替わります。HGW で PPPoE 接続を入れていない場合は回線が切れます、MAP-E対応ルーターは不要なので外します、やったー!

これで、光配線方式の接続パターンB に無事移行できました。

HGW -- UDM -- 各Wifiクライアント

余談: ちなみに、デフォルトのLANサブネットが HGW (192.168.1.1/24) と UDM (192.168.1.1/24) でかぶります。UDM のLANを 192.168.2.1/24 あたりにずらしておきましょう。(MAP-E 対応ルータが 192.168.0.1/24 なので放置していた)

HGWに特に設定は不要なので、HGW と UDM を再起動すればすべてが期待通りに動き出します。(PPPoE は不要ですし外しておきましょう)

4. UDM で IPv6 を受けてクライアントに配布する

さてようやく本題です。

ひかり電話を契約していれば、RA ではなくDHCPv6-PD (Prefix Delegate) 方式が利用できます。 早速UDM で IPv6 を HGW から受ける設定 (WAN) と、クライアントへのIPv6 配布の2点を行います。

WAN の設定

ひかり電話がある場合、IPv6は DHCPv6-PD 方式で60bitのPrefix再委任が行われます。(ひかり電話なしだと、RAが直でおりてきて 64bit しかこない)

ということで、IPv6の構成を行います。加えて、DNS の解決ができなくなるケースを防ぐため、DNSにGoogle DNS あたりを指定します。

  • IPv6 Connection Types: DHCPv6
  • Prefix Delegation Size: 60
  • DNS: 8.8.8.88.8.4.4

f:id:guitarrapc_tech:20201017042019p:plain

LAN の設定

LAN に IPv6 を配布する設定を行います。 IPv6 RA、IPv6 Priority、DHCP Range はデフォルトのままでok です。DHCPv6/RDNSS DNS は、Google DNS を指定します。

  • IPv6 Inteface type: Prefix Delegation
  • IPv6 RA: 有効
  • IPv6 Priority: High
  • DHCP Range: Start ::2、 Stop ::7d1
  • DHCPv6/RDNSS DNS Control: Manual
  • DNS Server1: 2001:4860:4860::8888
  • DNS Server2: 2001:4860:4860::8844

f:id:guitarrapc_tech:20201017042249p:plain

IPv6 の確認

ipv6 test を行います。 HGW - UDM 接続 + DHCPv6-PD の構成を組むことで、UDM のWifi クライアントもIPv6テストが通るようになります。長かった。

f:id:guitarrapc_tech:20201017042907p:plain

速度の確認

HGW と UDM を直接つなげたこと、ルーターが一つ減ります。ということで、速度も改善します。

UDM との LAN 接続で 610Mbps まで向上します。

UDM の 5GHz 160 VHT と 1.7 Gbpsのネットワークアダプタで接続すると、下りがLAN より劣化しているのが気になります。(調査中) アップロードは想定通り向上しているのだけれども...

まとめ

IPv6 IPoE で接続して、好きなルーターで良い感じに構成するなら、ひかり電話は契約しておくといいです。 DHCPv6-PD に持ち込めばどうとでもなれるので、ひかり電話なしで頑張るのは避けましょう。

なによりも、VDSLはところは絶対に避けて光配線の住居を選びましょう。自分で入れるのいろいろ面倒ですしね。