<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Infrastructure on omegaatt</title>
    <link>https://www.omegaatt.com/tags/infrastructure/</link>
    <description>Recent content in Infrastructure on omegaatt</description>
    <generator>Hugo -- 0.164.0</generator>
    <language>zh-TW</language>
    <managingEditor>raiven.kao@gmail.com (Raiven Kao)</managingEditor>
    <webMaster>raiven.kao@gmail.com (Raiven Kao)</webMaster>
    <copyright>Raiven Kao 2020 - 2026</copyright>
    <lastBuildDate>Sun, 24 May 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.omegaatt.com/tags/infrastructure/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>把 k3s 從 Ubuntu 搬到 OpenSUSE MicroOS，順便換上 FluxCD GitOps</title>
      <link>https://www.omegaatt.com/blogs/develop/2026/migrate_k3s_lab_from_ubuntu_to_opensuse_micro_os/</link>
      <pubDate>Sun, 24 May 2026 00:00:00 +0000</pubDate><author>raiven.kao@gmail.com (Raiven Kao)</author>
      <guid>https://www.omegaatt.com/blogs/develop/2026/migrate_k3s_lab_from_ubuntu_to_opensuse_micro_os/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;我的 Homelab 跑著一台 Proxmox VE，底下有一個 Ubuntu Server 24.04 的 VM 負責跑 k3s cluster，這個 cluster 接管了家裡所有的自架服務：從 &lt;a href=&#34;https://www.omegaatt.com/blogs/develop/2023/bitwarden_with_self_hosted_password_backend/&#34;&gt;Vaultwarden 密碼管理&lt;/a&gt;、&lt;a href=&#34;https://karakeep.app/&#34;&gt;Karakeep&lt;/a&gt; 書籤、&lt;a href=&#34;https://github.com/filebrowser/filebrowser&#34;&gt;Filebrowser&lt;/a&gt; 文件管理，到 &lt;a href=&#34;https://www.wakapi.dev/&#34;&gt;Wakapi&lt;/a&gt; 開發時間追蹤，大大小小跑了十幾個服務。&lt;/p&gt;
&lt;p&gt;這個架構一直跑得很穩。直到 Linux kernel 7.0 發布，我才開始動搖。&lt;/p&gt;
&lt;p&gt;kernel 7.0 的各種新特性讓我心癢，Ubuntu 26.04 LTS 剛好以 kernel 7.0 作為預設核心，理論上從 24.04 升上去就能一步到位。但在一個跑著十幾個服務的生產 VM 上執行 &lt;code&gt;do-release-upgrade&lt;/code&gt;，那種心臟發抖的感覺，即便有做好備份，還是讓我遲遲下不了手。&lt;/p&gt;
&lt;p&gt;就在猶豫要不要升級的當下，我問了自己一個問題：「我要繼續用 Ubuntu 嗎？」&lt;/p&gt;
&lt;p&gt;這個問題打開了一扇門。我的 Linux desktop 是 openSUSE Tumbleweed + KDE Plasma，用了三年、換過兩台裝置（筆電和桌電），沒有遇到太多問題。Tumbleweed 的滾動更新讓我一直跑著最新的 kernel，升級這件事從來不是一個需要另外排行程的壓力事件。&lt;/p&gt;
&lt;p&gt;既然 desktop 側已經對 openSUSE 生態有信心，server 側為什麼不試試看？&lt;/p&gt;
&lt;p&gt;這讓我開始認真考慮：有沒有一種 OS，讓 server 的升級這件事也變成「預設安全」而不是「需要勇氣」？&lt;/p&gt;
&lt;h2 id=&#34;為什麼選-opensuse-microos&#34;&gt;為什麼選 OpenSUSE MicroOS&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://microos.opensuse.org/&#34;&gt;OpenSUSE MicroOS&lt;/a&gt; 是一個 Immutable OS（不可變作業系統），核心特性有幾個：&lt;/p&gt;</description>
    </item>
    <item>
      <title>k3s Ingress Controller 從 Nginx 遷移到 Traefik 同時整合 CrowdSec</title>
      <link>https://www.omegaatt.com/blogs/develop/2026/migrate_ingress_controller_from_nginx_to_traefik/</link>
      <pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate><author>raiven.kao@gmail.com (Raiven Kao)</author>
      <guid>https://www.omegaatt.com/blogs/develop/2026/migrate_ingress_controller_from_nginx_to_traefik/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TL;DR 馬上就看到有小王八蛋想壞壞&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://www.omegaatt.com/blogs/develop/2026/migrate_ingress_controller_from_nginx_to_traefik/images/SCR-20260411-nmjr.webp&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;2025 年 11 月，Kubernetes SIG Network 發布了一篇公告：&lt;a href=&#34;https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/&#34;&gt;ingress-nginx 將正式退役&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;這個消息讓不少人震驚，但嚴格來說有個細節需要釐清。目前市場上有兩個長得很像的 nginx ingress controller：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/kubernetes/ingress-NGINX&#34;&gt;kubernetes/ingress-nginx&lt;/a&gt;：由 Kubernetes SIG Network 維護，這次宣布 EOL 的就是它。&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/nginx/kubernetes-ingress&#34;&gt;nginx/kubernetes-ingress&lt;/a&gt;（又稱 NKS）：由 F5 / NGINX Inc. 維護，目前仍持續開發中。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我的 homelab k3s cluster 一直以來用的是 F5 維護的版本，嚴格來說不在這次 EOL 的範圍內。但這個公告還是給了我一個動力，與其繼續追蹤兩個版本之間的差異、擔心哪天又有什麼變化，不如趁這個機會把遷移一次做完。&lt;/p&gt;
&lt;p&gt;遷移目標選定 Traefik v3，原因有兩個：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;k3s 內建 Traefik 作為預設 Ingress Controller，&lt;a href=&#34;https://docs.k3s.io/networking/networking-services&#34;&gt;1.32 版本後升級為 Traefik v3&lt;/a&gt;，搭配 &lt;code&gt;HelmChartConfig&lt;/code&gt; 管理，和 cluster 的整合度最高。&lt;/li&gt;
&lt;li&gt;順手引入 CrowdSec 主動防護——長期以來我的服務靠著 Cloudflare proxy 當唯一守門人，但我一直想要在 Ingress 層就能即時判斷並封鎖攻擊者 IP，而不只是依賴前端的 CDN 過濾。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;為什麼不選-cilium-gateway-api&#34;&gt;為什麼不選 Cilium Gateway API&lt;/h2&gt;
&lt;p&gt;在決定遷移到 Traefik 之前，我也閱讀了 Gene 的&lt;a href=&#34;https://igene.tw/cilium-gateway-api-migration&#34;&gt;告別 ingress-nginx：Cilium Gateway API 遷移筆記&lt;/a&gt;，評估過 Cilium Gateway API 方案。Cilium 在 CNI 層整合了 Gateway API，理論上能提供更底層、效能更好的流量控制，且完全符合 Kubernetes Gateway API 的標準規範。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Helm Smart Resource：讓你的 Chart 學會與既有資源和平共處</title>
      <link>https://www.omegaatt.com/blogs/develop/2025/helm_smart_resource/</link>
      <pubDate>Sat, 22 Nov 2025 00:00:00 +0000</pubDate><author>raiven.kao@gmail.com (Raiven Kao)</author>
      <guid>https://www.omegaatt.com/blogs/develop/2025/helm_smart_resource/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;在 Kubernetes 的世界裡，Helm 無疑是管理應用程式部署的霸主。它標準化了資源的定義，讓我們可以用宣告式的方式管理整套系統。然而，在真實世界的維運場景中，事情往往沒那麼單純。&lt;/p&gt;
&lt;p&gt;我們常遇到一種尷尬的情況：某些資源（例如 Database 的 Secret、外部系統的 ConfigMap）可能在 Helm Chart 安裝之前就已經由維運人員手動建立，或是由另一個流程（如 Terraform）預先準備好了。&lt;/p&gt;
&lt;p&gt;這時候，如果直接執行 &lt;code&gt;helm install&lt;/code&gt;，往往會收到 &amp;ldquo;resource already exists&amp;rdquo; 的錯誤；如果使用 &lt;code&gt;helm upgrade --install&lt;/code&gt;，又擔心 Helm 會覆蓋掉這些既有設定。&lt;/p&gt;
&lt;p&gt;這篇文章將分享一種「Smart Resource」的設計模式，透過 Helm 的 &lt;code&gt;lookup&lt;/code&gt; 函數與樣板邏輯，讓你的 Chart 能夠聰明地判斷：「這東西是我管的嗎？如果是，我才動它；如果不是，我就尊重現狀。」&lt;/p&gt;
&lt;h2 id=&#34;核心難題ownership&#34;&gt;核心難題：Ownership&lt;/h2&gt;
&lt;p&gt;在 Kubernetes 中，資源的「所有權」觀念至關重要。Helm 預設認為它 release 中的所有資源都應該由它全權管理。但當我們需要與外部資源協作時，我們需要更細緻的控制。&lt;/p&gt;
&lt;p&gt;我們的目標很明確：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;若資源不存在：建立它，並標記為 Helm 管理。&lt;/li&gt;
&lt;li&gt;若資源已存在且由 Helm 管理：更新它（Patch/Merge）。&lt;/li&gt;
&lt;li&gt;若資源已存在但由外部管理：保持原狀，不進行覆蓋或刪除。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;為了達成這個目標，我們需要一個輔助函數來判斷資源的歸屬權。&lt;/p&gt;
&lt;h2 id=&#34;實作細節&#34;&gt;實作細節&lt;/h2&gt;
&lt;h3 id=&#34;1-定義所有權檢查&#34;&gt;1. 定義所有權檢查&lt;/h3&gt;
&lt;p&gt;首先，我們在 &lt;code&gt;_helpers.tpl&lt;/code&gt; 中定義一個檢查函數。Helm 會在它建立的資源上打上特定的 Annotations（&lt;code&gt;meta.helm.sh/release-name&lt;/code&gt; 和 &lt;code&gt;meta.helm.sh/release-namespace&lt;/code&gt;）。我們可以利用這一點來判斷資源是否屬於當前的 Release。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#ae81ff&#34;&gt;/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;Check if a resource is owned by this Helm release&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;Returns &amp;#34;true&amp;#34; or &amp;#34;false&amp;#34; as string for stable piping&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;*/}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- &lt;span style=&#34;color:#ae81ff&#34;&gt;define &amp;#34;visionone-filesecurity.isOwnedByRelease&amp;#34; -}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- &lt;span style=&#34;color:#ae81ff&#34;&gt;$resource := .resource -}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- &lt;span style=&#34;color:#ae81ff&#34;&gt;$releaseName := .releaseName -}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- &lt;span style=&#34;color:#ae81ff&#34;&gt;$releaseNamespace := .releaseNamespace -}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- &lt;span style=&#34;color:#ae81ff&#34;&gt;$owned := and $resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;(hasKey $resource.metadata &amp;#34;annotations&amp;#34;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;(eq (get $resource.metadata.annotations &amp;#34;meta.helm.sh/release-name&amp;#34;) $releaseName)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;(eq (get $resource.metadata.annotations &amp;#34;meta.helm.sh/release-namespace&amp;#34;) $releaseNamespace)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ &lt;span style=&#34;color:#ae81ff&#34;&gt;printf &amp;#34;%t&amp;#34; $owned }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- &lt;span style=&#34;color:#ae81ff&#34;&gt;end -}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;這段程式碼邏輯很簡單：只有當資源存在，且其 Annotations 中的 Release Name 與 Namespace 都與當前 Release 相符時，才視為「Owned」。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
