OrangePi 5 Max で istio を動かす

Orange Pi オフィシャルディストリビューションのカーネルでは残念ながら istio が動きません。そこでカーネルを再ビルドする必要があります。
ここではカーネルを再ビルドして OrangePi 5 Max で istio を動かすための方法を紹介します。
この方法はたぶん RaspberryPi でも同様なので参考になれば良いですね。

# 問題

以下の二つの問題があり、istio は OrangePi や RaspberryPi で動きません。
これらをなんとかすれば動きます。がんばれ。

## Envoy が動かないのをどうにかする

### 結論

カーネル設定の以下を変更する
```
CONFIG_ARM64_VA_BITS_39=n
CONFIG_ARM64_VA_BITS_48=y
CONFIG_ARM64_VA_BITS=48
```

### 症状
以下の様なエラーが出て ingress gateway とかが起動しません。

```
external/com_github_google_tcmalloc/tcmalloc/system-alloc.cc:631] MmapAligned() failed - unable to allocate with tag (hint, size, alignment) - is something limiting address placement? 0x151880000000 1073741824 1073741824 @ 0x55941cfa88 0x55941cb6a0 0x55941caf48 0x55941b2f4c 0x55941c8010 0x55941c7e2c 0x55941a78a8 0x55940e6c00 0x55940e2298 0x559406f484 0x559419dbd0 0x7f834774ac
external/com_github_google_tcmalloc/tcmalloc/arena.cc:58] FATAL ERROR: Out of memory trying to allocate internal tcmalloc data (bytes, object-size); is something preventing mmap from succeeding (sandbox, VSS limitations)? 131072 600 @ 0x55941cfde4 0x55941b2fdc 0x55941c8010 0x55941c7e2c 0x55941a78a8 0x55940e6c00 0x55940e2298 0x559406f484 0x559419dbd0 0x7f834774ac
```

### 説明

Envoy では tcmalloc(Thread-Caching Malloc) というのを使用して高速なメモリアロケーションを行っている様です。 tcmalloc を使用するためにはカーネルのコンフィグで `CONFIG_PGTABLE_LEVELS=4` を設定する必要がある様です。

`CONFIG_ARM64_VA_BITS_48=y` オプションを有効にしてカーネルをコンパイルすることで、48ビットの仮想アドレス空間が有効になり、自動的に `CONFIG_PGTABLE_LEVELS=4` になります。

詳しくは以下の issue を見て下さいね
https://github.com/envoyproxy/envoy/issues/23339#issuecomment-2150966438

## istio-init が動かないのをどうにかする

### 結論

カーネル設定の以下を変更する
```
CONFIG_NF_CONNTRACK_ZONES=y
CONFIG_NETFILTER_XT_TARGET_CT=y
```

### 症状
以下の様なエラーが出て istio-init が起動しません。
```
(省略)
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_OUTPUT -p udp -m udp --dport 53 -m owner --wid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -p udp -m udp --dport 53 -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 10.152.183.10/32 -p udp -m udp --dport 53 -j REDIRECT --to-ports 15053
-A ISTIO_REDIRECT -p tcp -7 REDIRECT --to-ports 15001
COMMIT
# Completed on Fri Oct 11 19:04:20 2024
2024-10-1119:04:20.788475Z    error     exit status 1
```

### 説明

istio-init が `-A OUTPUT -p udp --dport 53 -m owner --uid-owner 1337 -j CT --zone 1` みたいな iptables 設定を投げてるため？ここはまだ調べてないので不明。
が、とにかくこれで治る。

詳しくは以下の issue を見て下さいね
https://github.com/istio/istio/issues/37885

# OrangePi 5 Max カーネルの再ビルド

### パッケージのビルド用ツールがあるので git で clone
```
cd /usr/src/
git clone https://github.com/orangepi-xunlong/orangepi-build.git linux
cd linux
```

### カーネル設定の修正

opi5max の設定 _(linux-rockchip-rk3588-legacy-opi5max.config)_ が存在しますが、opi5pro の設定を変更しないと反映されません。なんでだよｗ
```
vi ./external/config/kernel/linux-rockchip-rk3588-current-opi5pro.config
CONFIG_NF_CONNTRACK_ZONES=y

CONFIG_ARM64_VA_BITS_39=n
CONFIG_ARM64_VA_BITS_48=y
CONFIG_ARM64_VA_BITS=48
```

diff はこんな感じ
(以下の diff には CIFS を使えるようにする設定が混じっています)
```diff
diff --git a/external/config/kernel/linux-rockchip-rk3588-current-opi5pro.config b/external/config/kernel/linux-rockchip-rk3588-current-opi5pro.config
index 520191f..3661dc6 100644
--- a/external/config/kernel/linux-rockchip-rk3588-current-opi5pro.config
+++ b/external/config/kernel/linux-rockchip-rk3588-current-opi5pro.config
@@ -384,9 +384,9 @@ CONFIG_ARM64_ERRATUM_2441007=y
 CONFIG_ARM64_4K_PAGES=y
 # CONFIG_ARM64_16K_PAGES is not set
 # CONFIG_ARM64_64K_PAGES is not set
-CONFIG_ARM64_VA_BITS_39=y
-# CONFIG_ARM64_VA_BITS_48 is not set
-CONFIG_ARM64_VA_BITS=39
+CONFIG_ARM64_VA_BITS_39=n
+CONFIG_ARM64_VA_BITS_48=y
+CONFIG_ARM64_VA_BITS=48
 CONFIG_ARM64_PA_BITS_48=y
 CONFIG_ARM64_PA_BITS=48
 # CONFIG_CPU_BIG_ENDIAN is not set
@@ -1056,7 +1056,7 @@ CONFIG_NF_LOG_SYSLOG=m
 CONFIG_NETFILTER_CONNCOUNT=m
 CONFIG_NF_CONNTRACK_MARK=y
 # CONFIG_NF_CONNTRACK_SECMARK is not set
-# CONFIG_NF_CONNTRACK_ZONES is not set
+CONFIG_NF_CONNTRACK_ZONES=y
 CONFIG_NF_CONNTRACK_PROCFS=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 # CONFIG_NF_CONNTRACK_TIMEOUT is not set
@@ -7771,7 +7771,15 @@ CONFIG_SUNRPC_GSS=y
 CONFIG_SUNRPC_SWAP=y
 # CONFIG_SUNRPC_DEBUG is not set
 # CONFIG_CEPH_FS is not set
-# CONFIG_CIFS is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_CIFS_DFS_UPCALL=y
 # CONFIG_SMB_SERVER is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
```

### ビルド

```
export NO_HOST_RELEASE_CHECK=yes
./build.sh
```

`NO_HOST_RELEASE_CHECK=yes` は debian bookworm とかでビルドするために必要な設定。
厳密には ubuntu 21 しかサポートされてないけど、ubuntu 21 なんて化石は ESXi でも動かなかったし、たぶんみんな無理なのでチェックを無視させます。

Kernel package を選ぶ
![スクリーンショット 2024-10-13 15.35.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663893/54d35efd-f404-1e84-5546-0f7c60a6cc7c.png)

Do not change the kernel configuration を選ぶ
![スクリーンショット 2024-10-13 15.37.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663893/468d3afa-3f73-392f-ae06-855aacc5845e.png)

orangepi5max を選ぶ
![スクリーンショット 2024-10-13 15.38.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663893/803820c1-38e6-20db-0a07-38df90a402f0.png)

Current Recommended. Come with best support を選ぶ
![スクリーンショット 2024-10-13 15.39.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663893/75e28443-ba00-fb30-0866-425ba6f93155.png)

あとは1時間くらい待ちます

### カーネルのインストール

終わったら終わりなので、カーネルをインストールします。
このビルドスクリプトはかしこいので deb パッケージを作ってくれます。便利。

```
cd ./output/debs/
dpkg -i linux-dtb-current-rockchip-rk3588_1.0.0_arm64.deb
dpkg -i linux-headers-current-rockchip-rk3588_1.0.0_arm64.deb
dpkg -i linux-image-current-rockchip-rk3588_1.0.0_arm64.deb
```

### 再起動

```
reboot
```

# その後

再起動した後は適当に istio が動く環境を作ってあげれば OK です。
ウチではこんな感じ。

```sh
###############################################################################
# SNAP
###############################################################################

apt-get -y update
apt-get install -y snapd
snap install core

###############################################################################
# MICRO K8S
###############################################################################

snap info microk8s
snap install microk8s --classic --channel=1.30/stable

microk8s enable community
microk8s enable ingress
microk8s enable dns

###############################################################################
# KUBECTL
###############################################################################

if [ "$(arch)" = "x86_64" ]; then
  curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
else
  curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
fi
chmod +x kubectl
chown root:root kubectl
mv kubectl /usr/local/bin/

###############################################################################
# KUBE CONFIG
###############################################################################

mkdir -p ~/.kube
microk8s config > ~/.kube/config
cat << EOF > ~/.bash_aliases
alias k='microk8s kubectl'
alias m='microk8s'
alias ll='ls -l'
EOF
cat << EOF > ~/.bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi
EOF

###############################################################################
# ISTIO
###############################################################################

curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.22.3 sh -
cd ~/manifests
../istio-1.22.3/bin/istioctl install -y -f ./operator.yml

###############################################################################
# APPS
###############################################################################

# お好みのアプリをデプロイしてね
kubectl apply -k some-application/
```

k8s のバージョンを 1.31 に上げなければ…
とはいえ 2024/10/14 にはまだ 1.31 に対応する istio 1.24 は出てない😇
https://istio.io/latest/docs/releases/supported-releases/