文章列表

Steam OS 內建 podman DNS 問題解決方法

科技新知
MacauYeah・2024-12-20

前幾天筆者在介紹SteamDeck 內建的podman時,沒有測試得很清楚。在長期使用下,的確有些問題需要進一步處理,這裏就補充一下解決方法。 我們前一篇介紹的 Steam Deck 內建 podman ,配上再自行安裝 podman-compose 有時會出現warning :`WARN[0002] aardvark-dns binary not found, container dns will not be enabled`。這不單影響到沒有在 service 之間自動産生 DNS 記錄,還會令互聯網功能失效,因為它會是整個 DNS 解釋功能丢失了,只是在 service 中定義 DNS 的地址並不會解決問題。筆者亦測試過,照著原本的 docker 思路,使用最傳統的做法,自己起 network ,自己起 container ,然後再串連在一起,依然會出現問題:`Error: "slirp4netns" is not supported: invalid network mode`。所以根源問題應該不在 podman-compose 上,而是在內建的 podman 依賴上。 緊急的解決方案,我們需要用到 "network_mode: host" 的方式去解決。例如以下例子 "network_mode: host" 的主要作用,就是讓 container 直接在主機的網段上執行。上面的例子中的 postgres 資料庫,它預設使用5432端口,我們並不需要再獨立宣告,即使在 container 內外,都可以直接使用 localhost:5432 溝通。而使用了主機的網段後,DNS 也可以正常運作。但這個做法的缺點就是 container 內的所有 port 都自動佔用了 host 上的使用,有時候那怕我們並不需要,它也會被暴露在外。更可能的是增加了不同 container 之間的 port 衝突。不過筆者要用於開發環境,所以這並不會是很太大的問題。

Docker 來源掃瞄 - Docker Image Scan

科技新知
MacauYeah・2024-12-19

當網安要求越來越高時,我們也要留心 docker image 的來源是不是有漏洞問題。 docker hub 本身就已經有一些安全掃瞄報告,以 nginx 的 1.27.3 版本為例, docker hub nginx 1.27.3 , docker hub 已經列出相當多的CVE漏洞。 不過對於不公開的 docker image ,安全描瞄可是要收費的。作為小團隊,可能想先尋求一些簡單的免費方案。如果你想同樣的需求,可能Trivy會幫到你。 Trivy Trivy 是一個用於描瞄軟件版本依賴或設定檔是否引用到一些有漏洞問題的軟件,它也能檢測 docker image 是否有漏洞或錯誤設定的問題。而且更好的是, Trivy 本身亦有 Docker Image 版本,我們就不用煩惱怎樣弄一個 Trivy 的執行環境,只要可以運行 docker ,有網路就可以了。但使用 Docker Image 版的 Trivy 有一個額外要求,就是它要有主機上的 docker.sock 權限。 描瞄的指令如下,其中 docker.sock 就是為了讓 containers 內部的程式可以存取主機的 docker daemon , .cache 則是為了方便暫在下載資源。 上面故意用 nginx 的兩個同版本號不同平台的 docker image,其實就是為了引出一些潛在問題。nginx 預設是使用的debain OS的,在筆者寫文章的當下,已經更新到最近的 image ,但始終有一大部份可能的漏洞。反觀 alpine OS 版本,就找不到這麼多問題。 這是因為 alpine 預設安裝的依賴較少,所以找到的漏洞也少。正所謂,做多錯多,唔做唔錯(大誤)。這其實有好有不好,因為在發生問題時,在 alpine 下可能連基本的除錯工具都沒有。除非大家有完整測試,或者對 alpine 有相當的認識,你才會選擇一個非官方預設的版本。但就以事論事,引用較少的依賴,長久之下的確是不會有那麼多隱患。大家如果有條件,也可以試試 alpine 或其他版本。 前一節我們可以看到,Trivy需要經過 socket 的方式才能存取主機上的 container daemon 操作權。但 podman 作為一個不主張 daemon (daemon less),亦主張不需要 root (rootless),那麼它該怎樣執行? 其實podman也有user層面上的 socket,而且 trivy 也有對應的方式去轉用第三方 socket (有點像使用遠端主機 socket,但官方並未宣佈正式支援遠端的方式。) 具體使用方式,筆者亦已在 steam deck 上測試,使用方式如下。不過因為 steam deck 預設沒有 root,筆者就省略 cache 指令,免得之後要有權限問題要手動清理。 Ref Podman socket activation Trivy: Support for rootless podman

steam deck 辦公用途工具資訊 2024/12更新

科技新知
MacauYeah・2024-12-17

購入steam deck 已經有一年多的時間,之前亦發過一些安裝教學。適逢筆者系統重裝,又有機會重新檢視工具的可用性。 Podman / Distrobox 一項很重要的更新,Steam OS已經有預安裝podman,不需要經home brew安裝。但預裝的podman 沒有內置DNS,可能會對K8S等進階應用有影響,不過筆者只作為單機測試用,普通的podman compose沒有問題。 另一項很重要的更新,就是 distrobox,它可以經 podman 讓大家方便地執行不同的 linux 版本,想在Steam OS上使用Ubuntu?沒問題,開箱即用;想用VScode官方維護版本,沒問題,安裝指定Linux再按裝VScode就好。 詳見上一期的介紹。Steam OS 3.5更新,內建 podman, distrobox 中文輸入法 我們不需要再安裝Fcitx5 + Rime,如果大家在遊戲模式下,已經設定好中文輸入法,那麼在輸到桌面模式下,照樣以Steam Button + X Button的方式,打開內鍵輸入法。你會見到有虛擬鍵盤彈出,它會覆寫桌面模式的。此時,即使你關掉虛擬鍵盤,並用實體鍵盤,中文輸入法都會保留。不過大家要確認,彈出當下必需要是【中文】。 若然你彈出的虛擬鍵盤是英文,請按【地球】轉換到【中文】後,關掉虛擬鍵盤,再重來一次(重按Steam Button + X Button),確保彈出的時候是經【中文】覆寫。 Discovery Discovery 是 Steam OS 預設用來安裝第三方程式的地方,它經 flathub / flatpak 存取程式。但筆者一定要先強調,它提供的第三方程式,並不一定會得到原開發者的支援,它屬於打包移植之類。 例如 flathub 中可以找到 Google Chrome (https://flathub.org/apps/com.google.Chrome) ,但它實際是經過一個github 專案移植過去的 (https://github.com/flathub/com.google.Chrome)。它有提供持續更新,但筆者不保證當中有沒有任何被植入過任何不正當軟件。 相反,flathub中有一些程式是經過原開發者支援的,例如 Firefox (https://support.mozilla.org/en-US/kb/install-firefox-linux), Gnome Boxes (https://gitlab.gnome.org/GNOME/gnome-boxes), Gimp (https://www.gimp.org/downloads/) ,這類可以比較放心使用。 筆者過去使用 Discovery ,的確有遇到一些權限問題,但最後估計應該是筆者安裝 Homebrew 所影響。筆者在重裝 Steam OS 後,直接使用 Discovery,就沒有問題。過去需要經 Homebrew 安裝的東西,現在經 podman , distrobox 或 Gnome boxes 就可以了,不再需要經Homebrew去折騰一輪。而且Homebrew也不是萬能的,因為Steam OS有限制一些套件的事用,即使安裝Homebrew也解決不了。若想要完全開放套件限制或解決依賴問題,還不如直接開啟Steam OS覆寫權限,轉用Arch Linux的安裝包。

Steam OS 3.5更新,內建 podman, distrobox

科技新知
MacauYeah・2024-12-10

之前筆者有介紹過如何在Steam OS上安裝podman,但都必需要自行折騰一番,特別是遇到一些依賴缺失時,還要逐個除錯。在Steam OS 3.5更新之後,官方已經有預安裝的 podman,筆者建議,如果有機重刷OS,就直接使用預安裝版本就好。更重要的是,不但有預設podman,連另一個神器distrobx,也在Steam OS 3.5之後引入。 podman-compose Steam OS 3.5,雖然已經有預安裝 podman ,但在實際環境下,多安裝一個 podman-compose 可以更方便地一體化操作。 我們可以經 python 安裝。 剛安裝 podman-compose ,會出現在自己的 home 目標的隱藏目錄。最後一步就是要加到自己的 PATH 環境變數裏面。 修改保存後,就重啟。之後 podman-compose 的指令就可以任意存取了。 要補充一點,就是官方預安裝的 podman 還是缺少了一些 DNS 的元件,大家會看到 warning 提示。不過在筆者單個 container 的使用情境下,並不受影響。之後要在其上二次引用的 distrobox 也可以順利執行。 神器 distrobox 在 Steam OS 3.5 中,除了 podman 外,還有預裝 distrobox 。 distrobox 其實是基於 container 技術的擴展應用,它目標是讓用經過 container 就可以輕鬆使用到不同 linux 的發佈版本。例如我想在 Steam OS 中使用 Ubuntu ,經過 distrobox 就可以用到。道理上, distrobox 基於 container (podman) 操作的,所以它能做到的,其實自己手動經 podman 也是可以做到。但若果大家想使用跨 Linux 版本的 GUI 程式,筆者還是建議優先使用 distrobox 。因為 distrobox 預設已為不同版本的 Linux 的 Image (來源影像檔) 加入部份調整,在運行時亦有x11等互通,指令也較為簡單。 以下做來例子,示範在 Steam OS 中就執行 Ubuntu 版本的 vscode。 註: Distrobox 也不是萬能的,例如它的 Ubuntu 版本內沒有 snap ,所以不能執行 Ubuntu 版本的 Firefox。 snap will not works (firefox not works)

國模內卷作-摩動核-威遠式劍鬥型

手機‧電玩
MacauYeah・2024-12-04

隨著模型愛好者的增多,中國的拼裝模型市場逐漸崛起,尤其是原創拼裝模型,不少廠商都在研發自己的機甲拼裝模型,價錢宜人,份量十足,所以吸引了越來越多的目光。 今日,筆者亦來分享一下自己首款的原創國模拼裝體驗-摩動核-威遠式劍鬥型 一般來講,國模機甲有以下特色 分件量多,但也因此可能太過細碎 好多隱藏水口。有好有唔好,精修隱水口一定比傳統水口易處理,但處理不好,會導致不完全咬合。 摩動核的特色 內卷的大廠,分件量多之餘,還有金屬骨架。亦因為有成品骨架,所以少了骨架的拼裝體驗,換來的就是更強的關節。 外型尖刺多,吉手(扎手),要小心。 有送支架 摩動核-威遠式特色 原本的角色分類為小兵機,尖刺量已經大大減少,但腳部還是有一些,把玩時要小心。 隱水口設計不太合理,導致剪鉗不好下刀。若強行用薄刃剪修水口,長久會因為位置不當,令薄刃剪變型。筆者薄刃剪就中招了,應該需要用筆刀做精修清理。 隱水口量多,所以不需要做任何打磨。 除手掌部份有個別掌型難以組裝,其他都易於組裝,不需要擴孔或削柱,精密度讓筆者很感動。雖然比不上日本Bandai,但都算流暢。 單手、單腳的可動性高,手型多,裙甲亦有三款,有潛力地擺出各種(奇怪的)姿態。 胸部、腹、胯部裙甲有相連,站屍很好看,但攞動就變得很有干涉。需要拆了裙甲,才能同時平轉腰部及抬腿。 站立沒有煩惱。因為沒有背包負擔,站立沒有配重不良的問題。再加上有合金骨架,初期不會有腳軟、腰軟問題,但緊合度有待時間的驗證。 如果一定要評個分,那就分幾個方面逐評分,以下各項以5分為滿分。 拼裝流暢度及體驗:組合度OK,但剪零件、修隱水口很花時間。組合體驗就很一般,以貼皮為主。3.5分。 造型:分件多,而且成型色好,亦有預塗裝件,成品一流。美中不足就是扎手,4.5分。 性價比:官方售價99RMB,性價比高。5分 因為性價比高,如果各位對那個小兵造型不太討厭,都可以入手一款,試下手感,支持原創。 但若果各位對機械感很有要求,就不要入手了,因為拼裝部份就是貼皮,沒有很驚艷的體驗,簡說講就是沒有結構感覺。但要補充,在99RMB這個價錢,有金屬骨架+預塗裝的貼皮,已經是成本上的極限。

重入膠坑3 |如何在有限的空間內收納Gunpla高達模型:斷捨離的是必要之技巧

手機‧電玩
MacauYeah・2024-11-26

高達模型(Gunpla)是許多模型愛好者的最愛,隨著收藏數量的增加,如何有效地在有限的空間內進行收納成為一個重要課題。這時,斷捨離的概念顯得尤為重要。這篇文章將探討如何在有限的空間內收納高達模型,還有如何處理不再需要的模型。 1. 理解有限空間的重要性 在收納高達模型時,我們首先要認識到,空間是有限的。我們不可能無限制地擴展收藏,因此在購買前,就需要對模型進行認真的思考和評估。問問自己:這個模型是否真的令我感到滿足?它是否在我的收藏中有特別的意義?這些問題能幫助我們展示、收藏、出讓的決定。 2. 選擇合適的收納容器 一個足夠大的立體空間,絕對是展示高達模型最好的方式。高模模型主要想呈現的,是機械感及戰爭感。而現在很多型號的模型,都以大翅膀為主,需要夠大的地方,才能好好地展現它們原本的設計。但土地資源短缺,是大部份澳門居民的常見的情況,所以通常的結果就是在一個空間中放入多台模型,每台模型所分得的空間相對不夠充足。筆者一直以來也有這個問題,經過幾次搬遷,再加上空間越來越少,令筆者不得不調整展示策略。 方法一:分開兩個空間,一個空間以自然站立為主,另一個空間即以支架作獨立展示。 第一個空間,自然站立,即通俗講的「站屍」,以方便收藏及次要觀賞為主。即使緊密地站著,也有列陣的感覺,只要不要模型之間不要相互壓到就好。 第二個空間,獨立展示。但這裏只會展示一或兩台模型,不要多。盡力去擺姿勢,利用各種支架或配件,展現最有魄力的感覺。大家可以想像成這就是一個攝影棚,在這裏放著的就是主角。把自己的焦點,集中在單一的模型上,好好地欣賞自己的大作。 方法二:分開兩個空間,一個空間完全看不見,另一個空間即以支架作獨立展示。 如果空間很不夠,就完全取消自然站立的空間,只保留獨立展示空間。前者就是等於要入盒收納,除了使用原裝的模型盒外,其實飯盒(透明膠盒)也是一個好的收納方式。放在飯盒中,方方正正,易於疊起,它比原裝的模型盒要堅硬一點,也易於查看內部內容。 3. 定期清理和整理 定期檢查和整理您的收藏,就是斷捨離的具體體現。經過歲月的消禮,模型可能會發黃,經常把玩的話,關節亦會有鬆脫或折斷的情況出現。有能力自己修件重鑄的話,一定要好好修理。打椿,重新上色補色是必要的保養技巧。若然無修件再修復,可以考慮設立一個零件區,把作品分解(即俗稱殺肉),供日後其他改造之用。清理損壞的模型,讓空間更加整潔,可以讓您更專注於珍藏的模型。 另一點,也是最難的一點,就是重新檢視您的收藏,將那些不再合心意的模型進行取捨,這樣不僅能騰出空間,還能讓收藏更具意義。 4. 處理被淘汰的模型 前述因為不再合心意,或是損壞而變成被淘汰的模型,有幾種處理方式: 贈送或交流:將不再需要的模型送給朋友或其他模型愛好者,這樣能讓它們得到更好的利用。 二手出售:澳門常見的社交平台,都有模友互相出售二手作品,這不僅可以收回一部分資金,還能讓其他人享受這些模型的樂趣。 二次改造:如果模型已經損壞,可以考慮拆件,進行再利用或改造。例如常見的步槍,可以二次改裝為手槍,巨劍、造型手可以用藍丁膠固定,讓其他作品更易手持。 練習用途:確定不要的模型,可以進行各種上色或改造實驗。不同的塗裝、改造、滲線刻線,都需要大量的練習去熟練。如果大家有意進一步提升制作技巧,需要練手的素材就相當多。 總結 在有限的空間內收納高達模型需要一些創意和計劃,特別是斷捨離的智慧。希望這些建議能幫助您在小空間中也能享受高達模型的樂趣!

重入膠坑2

手機‧電玩
MacauYeah・2024-11-21

水性漆上色 雖然筆者已經砌模型很久了,但很少試著自行上色。但多得模型開模技術的進步,以及水性漆、補色筆的出現,模型預設的分色再加上少量自行補色,就已經效果不錯了。以下是筆者完全使用水性漆+補色筆重塗的作品。打灰底後全部重新上色,白色為水性漆海棉干掃,紅色、藍色、黃色則為Marker筆。 海棉干掃要注意幾點,因為是白色,遮蓋力弱,一定要多層掃。而家每層一定要足夠輕透。筆者太貪,想半小時內就掃第二層,效果不是特別好。有條件的話,放個半天會好一點。感覺上白色遮蓋力弱,掃完第三層後,第四、五層的差別就不太大。大家可以自行取捨。 關於刮漆 大家留意自己的補色筆是不是水性,若果為水性,就跟水油的刮漆情況差不多。再加上小制作的情況下,使用補色筆都是為了方便,九成都不會預先打灰底,所以附著力會更弱。把玩時要更小心。(感謝賢者模型工作室關於水性油的選擇及指導。) 拍照把玩 作為經驗尚淺的筆者來看,老實講,在「上色」與「把玩」之間,還找不到共存的地方。前面已經提到,刮漆是會發生的問題,那怕大家用的是油性漆。更什的是,即使大家只打磨、素組、滲線,把玩多了也是會斷關節的。當花了一百小時精心制作,然後玩壞了,可痛心阿。若換成金錢來衡量,100元的高達模型,找代工精修上色,最後埋單可能要400以上,跟買一隻入門的成品模型差不多。所以大家在把玩之前,一定要做心理準備,斷了,就讓他去吧。塑膠,始㚵是不耐操。 雖然模型易壞,但放著不玩,就跟鹹魚沒有分別。所以筆者就拼著一去無回頭的決心,把高達模型扭下去(但也的確扭壞了兩三隻高達)。在這裏分享一些拍照的姿勢。 支架 拍照環境光不可控的情況下,不要拘泥於背景及支架。有條件搭個攝照棚,打光充足,誰不想。但條件不允許就要要拘泥那些了,找個有燈光的地板,手持拍照就好。選擇手持的原因是,拿得比較穩,重力干涉的因素較少,可以容易地調整模型的面向,使光源看來起比較充足。 構圖 如果是戰鬥模型,例如是高達,盡量選一些對角線構圖,會讓模型看來起更猛。另一個重點就是手機不要貼太近拍照,因為會變型。至少距離一個成人的手位,最後再把圖栽成合適的大小。或者在一個遠的位置,再使用1.5倍或2倍放大,拍出來的效果就跟肉眼感覺得差不多了。手機太近,一定是筆者卡關的問題,好不容易筆者才發現這一點。

概有雲供應商的K8S,為何要自己弄Docker Swarm / 本地K8S ?

科技新知
MacauYeah・2024-11-19

其實筆者寫了這麼多篇docker 的文章,可能有朋友會問,為何要自己從零建立Container環境,使用供應商直接提供的K8S服務不是很好嗎? 按照市場發展,各大雲供應商都越來多,競爭越嚟越激烈,作為用戶方,理應可以得到更合理的價格。不過作為使用VPS多年的筆者,真的沒有覺得雲服務的價格可以便宜到一個不用煩惱的水平,大家還是需要很㥀重地考量自己的業務是不是值得雲端化。 正常來講,在有足夠使用量的前提下,雲端化也是合適的,也真的有產到錢。但問題是大部份情況下公司內部自主開發的應用,都沒有去到這個程度。每個應用去租用一個VPS,即使使用最低配置,用起來的時候覺得不夠快,閒起來的時侯也是浪費錢。 這時,使用 Container 技術,就是讓多個不同的應用,共享同一個或多個VPS的好方法。因為 Container 可以簡易地做到應用之間的隔離,即使不同應用之間有依賴衝突,只要 Contianer 層面沒有衝突就可以共存。 Docker swarm 與 K8S 同為 container 技術,文章最前面,就提到了這個問題,為何不選現有的K8S,反而要自己弄Docker Swarm?其實關鍵亦是價錢的問題。使用K8S固然方便,但就每個節點都得使貴一級的雲端供應商服務,當我們的應用總是流量不足,就更易變得食之無味,棄之可惜。老實講,貴一級的雲端服務,有它存在的價值,很多東西可以做自動化擴展,例如概據流量自動擴容。另外,因為底層 Container 技術有供應商支援,也不用再另外購買支援服務。但這些都是業務有一定流量,才能展現出優勢。 反觀Docker Swarm,就是簡單可入手,初時一個VPS也可以。什至乎不上雲,找幾台舊電腦,實機做也可以。當然K8S也可以實機,不過就簡易程度來講,Docker Swarm 無得輸。待業務真正成長到一個有足夠流量的服務時,才進一步遷移到供應商的原生雲。在初期使用自建的Docker Swarm或小型K8S,可以先加入一些資源統計,以確定是否即裝滿負荷。

Swarm mode 上線 5 - load balancer | 還有那些事該考量?

科技新知
MacauYeah・2024-11-18

前面介紹了 ingress network ,亦介紹了 proxy gateway 。能做到的基本都做到了,再來就是考量安全性的問題。因為加了 proxy gateway ,前述的例子是所有 service ,都放在同一個 yaml 檔中。好處是,所有相關的東西存放在同一個檔中, gateway ,背後的 service 都一眼看到。但壞處就是有其中一個 service 更新,都要改那個 yaml 檔。更大的問題是, stack deploy 的指令,不單只更新其中一個 service ,就連其他 service 都會自動取得最新 image 而 redeploy 。 對於一個緊密的系統來講,同步更新可能不是大問題。但對於一些預定排程發佈的系統可不能這樣因為副作用而更新了。如果你也有這樣的分開管理需求,可以參考下面做法,把 gateway service 及 upstream service 放在不同的檔案中,然後經過 external network把所有 service 串連起來。 # nginx-stack.yaml, docker stack deploy -c nginx-stack.yaml nginx services: http-gateway: image: http-gateway ports: - 8080:8080 deploy: replicas: 1 update_config: delay: 10s restart_policy: condition: on-failure # manager-stack.yaml services: managerhttp: image: bretfisher/httpenv networks: - nginx_default - default deploy: replicas: 3 update_config: delay: 10s restart_policy: condition: on-failure placement: constraints: - node.labels.zone==manager networks: nginx_default: external: true # dmz-stack.yaml services: dmzhttp: image: bretfisher/httpenv networks: - nginx_default - default deploy: replicas: 2 update_config: delay: 10s restart_policy: condition: on-failure placement: constraints: - node.labels.zone==dmz networks: nginx_default: external: true 這樣,不同 service 的維護人員,就可以獨自控制自己的檔案。在第一次發佈時,確認 nginx-stack.yaml 先行發佈就可以了。對應的發佈指令是docker stack deploy -c nginx-stack.yaml nginx,它會自動産生一個 nginx_default (即 stack名字_default )的網絡。之後其他service,就可以經networks的設定找到它了。 services: YOUR_SERVICE: networks: - nginx_default - default networks: nginx_default: external: true 上述即使分離檔案,在安全性考量時還是有一個問題,就是 ingress network 的問題。試想一下,dmzhttp (Demilitarized Zone)原本被設定的原因,就是想限制某些訪問只能一些可以公開的服務。但因為經過 ingress network 之後,它們會在所有機器上開放這些 port。那就是,以下面的例子來講,若 dmzhttp 是公開的服務, intrahttp 是內部服務,即使用 intrahttp 使用不同的port 8889。但一經 swarm mode 預設的 ingress network ,在node.labels.zone==dmz的那些節點,還是可以訪問到 intrahttp 。 services: dmzhttp: image: bretfisher/httpenv ports: - 8888:8888 deploy: replicas: 2 update_config: delay: 10s restart_policy: condition: on-failure placement: constraints: - node.labels.zone==dmz intrahttp: image: bretfisher/httpenv ports: - 8889:8888 deploy: replicas: 3 update_config: delay: 10s restart_policy: condition: on-failure placement: constraints: - node.labels.zone==intra 我們前述介紹的 proxy gateway ,其實已經有一定程度可以解決這個問題。因為 proxy gateway 是根據 http 協定中的 host header 去做分流。在邊界網絡進來的「合法」訪問,道理上會好好地經引導到我們的 dmzhttp 。不過網路的邪惡可容小看, proxy gateway 也會有被騙的一日。有特定能力的攻擊者,只需找到目標域名,還是可以接觸到 intrahttp 。 若要做進一步隔離,在這種情況下,我們可以在 dmz , intra 機器中各設定一套 swarm ,完全獨立,這是最安全的做法。但這樣做的管理成本就會變高,因為兩個網段都會有自己的 manager 節點,而且在 dmz 網段的 manager 節點也有被攻擊的可能。 若我們回到單一 swarm 的方向,可以修改各個 service 中的 port 和 deploy 。利用 post mode 中的「host」,配合 deploy mode 中的「global」,完全跳開 ingress network。 services: dmzhttp: image: nginx ports: - target: 80 published: 8888 mode: host deploy: mode: global update_config: delay: 1s restart_policy: condition: any placement: constraints: - node.labels.zone==dmz intrahttp: image: bretfisher/httpenv ports: - target: 8888 published: 8888 mode: host deploy: mode: global update_config: delay: 10s restart_policy: condition: on-failure placement: constraints: - node.labels.zone==intra 上面的例子中, dmzhttp 會在所有 dmz 的機器中,每個節點只運行一份服務,而且直接使用該機的 8888 port ,外面不會再有 ingress network 的 存在。同樣地,intrahttp 會在 intra 的所有節點,運行一份服務,佔用它們的8888 。這兩個服務,即使使用一個 port ,swarm 也不會說有任何問題。因為它們不會經 ingress network 搶佔其他人的 8888。 可能會有讀者問,如果 host mode 這麼安全,為什麼預設會是 ingress network,那我們就要先了理清 ingress network 與 host mode 有有什麼分別?假設我們只運行一個service,它佔用8888。 功能ingress modehost mode replicas 數 同一個 service replicas 為任意數量,什至比節點的數目多 因為有 port 限制,每個節點最多只能運行一份 Virtual IP Virtual IP 任意在節點中跳轉也可以,因為 ingress 會自動找到對應的 service 所在的節點 Virtual IP必需要與 service 所在節點綁定,其他節點訪問不到 load balance 有 沒有 host mode 就像我們傳統在各自的節點上自行佈署自己的程序,各個節點只有一份。所以不會有自動 load balance 的效果,如果客戶端訪問固定的IP,就會得到是固定的接器接受請求。我們有需要,就要在前面加一個 Proxy Gateway (或 HA proxy )。 Virtual IP 也一樣, host mode 下需要好好地自動跟著 service 的生命期,不過幸運的是, Docker 預設己經有自動重啟 service 功能,即前文中的 restart_policy ,它在 host mode 下也適用。如果大家有配合 deploy 中的 global mode , Virtual IP 的並沒有實際變動。但如果沒有 global mode ,就要再想想辦法了。 最後考慮 load balance 的問題,如果進入點的 service 的真的不太消耗資源,沒有 load balance 也是可以的 ,但若超負荷,就必需要自建 proxy gateway 。經過進入點後,若我有背後的 service 就沒有所謂的 ingress 和 host mode 選擇。

Swarm mode 上線 5 - load balancer | proxy gateway 代理伺服器

科技新知
MacauYeah・2024-11-11

前面的例子,我們已經成功設定 ingress Network,也加了 virtual ip 。如果大家的目標是單一 web 應用,應該就已經很足夠。但作為一個足夠節儉的老闆,怎會讓一個 Swarm 只跑一個 Web 應用?但問題來了,一個 docker swarm service 就已經佔用一個公開端口 (例如上述的8888,或是更常見的443)。怎麼可以做到多個 service 分享同一個端口?答案就是回到傳統的 Web Server 當中,使用它們的 virtual host 及 proxy 功能,以達到這一效果。我們就以 Nginx 為例,去建立一個守門口的網關 (gateway) 。 以下就是一個最簡單的例子,最前端的 http-gateway (nginx) 對外公開端口 8080 ,它根據 virtual host,去分派對應的請求去 dmzhttp (bretfisher/httpenv) 及 managerhttp (bretfisher/httpenv) 。構架圖就是以下這樣。 ┌───────────┐ ┌──────────────►│ dmzhttp │ │ └───────────┘ │ ┌───────────────┐ │ http-gateway │ ────────►│ (nginx:8080) │ └──┬────────────┘ │ │ ┌─────────────┐ └─────────────►│ managerhttp │ └─────────────┘ 換成 docker stack ,就大概如下 services: http-gateway: image: http-gateway ports: - 8080:8080 deploy: replicas: 1 update_config: delay: 10s restart_policy: condition: on-failure dmzhttp: image: bretfisher/httpenv deploy: replicas: 2 update_config: delay: 10s restart_policy: condition: on-failure managerhttp: image: bretfisher/httpenv deploy: replicas: 3 update_config: delay: 10s restart_policy: condition: on-failure docker stack有一個很好的功能,就是 service 名會自動成為同一段網絡中的 hostname 。即是http-gateway中,它可以經DNS,找到 dmzhttp 、 managerhttp,也就是它的 nginx 可以設定成如下的樣子。 # default.conf server { listen 8080; listen [::]:8080; server_name managerhttp; resolver 127.0.0.11 valid=30s; location ^~ / { set $upstream_manager managerhttp; proxy_cache off; proxy_pass http://$upstream_manager:8888$request_uri; } } server { listen 8080; listen [::]:8080; server_name dmzhttp; resolver 127.0.0.11 valid=30s; location ^~ / { set $upstream_dmz dmzhttp; proxy_cache off; proxy_pass http://$upstream_dmz:8888$request_uri; } } 上面的例子中,就是一般的 virtual host + nginx proxy 設定。特別要說明的是 resolver 那一行,它指向 docker DNS (127.0.0.11), 而且還可以讓nginx在找不到上游時,不要馬上死亡。這樣 docker swarm 中各個 service 隨時加加減減,有保命的作用。 最後我們的 http-gateway 就是 nginx image + default.conf 上述的 docker 就可以用以下方式打包。 # Dockerfile # docker image build -t http-gateway ./ FROM nginx:latest COPY default.conf /etc/nginx/conf.d/default.conf 上面的 docker stack 和 nginx config,只要同步增加 service 及對應的 proxy pass,就可以o讓同一個端口,根據不同hostname做分流。當然,如果大家可以共用端口及 hostname 也可以,分流就改用 nginx location 來設定,不過這是更加偏向 nginx 的內容,日後有機會再介紹。本篇就先集中於 docker 相關的議題。 在安全性的角度, docker 還有一些配置可以做,就是讓 dmzhttp 和 managerhttp 在不同的機器上發佈。假設我們的網絡分開兩段,一段是 manager 專用,一段是 dmz 專用。在建立 docker swarm 後,我們可以為不同的節點加入對應的標簽。 docker node update --label-add zone=manager YOUR_MANAGER_NODE docker node update --label-add zone=dmz YOUR_DMZ_NODE 然後我們通過修改 docker stakc 中的 placement -> constraints ,限制不同的 service 在不同的節點上運行。 services: http-gateway: image: http-gateway ports: - 8080:8080 deploy: replicas: 1 update_config: delay: 10s restart_policy: condition: on-failure dmzhttp: image: bretfisher/httpenv deploy: replicas: 2 update_config: delay: 10s restart_policy: condition: on-failure + placement: + constraints: + - node.labels.zone==dmz managerhttp: image: bretfisher/httpenv deploy: replicas: 3 update_config: delay: 10s restart_policy: condition: on-failure + placement: + constraints: + - node.labels.zone==manager 使用上面的例子,我們就可以達到簡單分離的效果。但大家緊記,這個分離效果始終是一個規則式功能,它與防火牆的隔離還是有本質上的區別。除了利用傳統的防火牆技術外,我們的docker swarm network,其實也可以做更多隔離,我們日後再慢慢加強這個例子。

Git 歴史修正

科技新知
MacauYeah・2024-10-29

有時候,我們修正一系統檔案,例如某個commit中,多了一個不該放的檔案,又或者想修改該commit的作者,我們就要追搜到某個commit,然後用rebase隨個改。 例如本次repo,有一個githubAction.md,因為錯誤原因,被加到了main中,也藏了很久。如果我們想連根拔起,我們需要加出它第一次出現的commit。 $ git log githubAction.md commit 60ccd70f6b768138cbe23c93ffcfa32574ce895c 那我們就以它前一個commit作為rebase的根據,進行逐個commit修正。 $ git rebase -i 60ccd70f6b768138cbe23c93ffcfa32574ce895c^ pick 60ccd70 draft some content pick e2ee9a3 add some senario. pick b91afc1 refine submodule; pick 98cd366 add notes about submodule specific checkout; pick 064b06f test directly commit in submodule main pick 7b648d2 update git submodules notes pick 556f25e add notes about merge timing pick 5244804 Create git-continuous-integration-strategy.md pick 107e486 add more pratical nodes about ci; pick d93cbee add mono repo challenge pick 1c471b6 add worktree notes pick 9063ccb notes about different of git flow and github flow; pick b72e89e Update github-flow.md, add ref more link pick 0b8f2a9 draft github flow release problem pick 8b333fc finalize github flow release strategy 在rabase選項中,把需要改的commit由pick改為edit。(rebase會以舊到新顯示)。然後儲存。例如 edit 60ccd70 draft some content edit e2ee9a3 add some senario. edit b91afc1 refine submodule; pick 98cd366 add notes about submodule specific checkout; pick 064b06f test directly commit in submodule main pick 7b648d2 update git submodules notes pick 556f25e add notes about merge timing pick 5244804 Create git-continuous-integration-strategy.md pick 107e486 add more pratical nodes about ci; pick d93cbee add mono repo challenge pick 1c471b6 add worktree notes pick 9063ccb notes about different of git flow and github flow; pick b72e89e Update github-flow.md, add ref more link pick 0b8f2a9 draft github flow release problem pick 8b333fc finalize github flow release strategy 我們第一次會在60ccd70,我們作出想要的改動,然後經amend去改掉60ccd70 $ rm githubAction.md $ git add -u $ git commit --amend --author="newuser " 確定無誤的話,就可以去下一步,即是到了e2ee9a3 $ git rebase --continue 因為已經rebase過,你此時看到的不會再是hash不再是e2ee9a3,而是自動rebase完的e2ee9a3。若大家有東西要改,就使用commit --amend。如果沒有東西要改,也沒有conflict,可以繼續rebase --continue下去。

Swarm mode 上線 5 - load balancer | 負載平衡器

科技新知
MacauYeah・2024-10-28

前面我們一直談 swarm 的設定,但對於真實的服務,我們還要考慮客戶端是如何連接我們的伺服器群集。通常網路服務,客戶端都會經過域名轉換成IP,然而通過IP連線服務。 Ingress Network 假設我們 swarm 內有5個節點,那到底域名應該指向我們哪一個節點的 IP 呢? 如果我們不考慮節點死機的話,其實5個節點的IP都可以。因為 swarm 會自動把同一個公開的 port ,在每一個節點上都可以訪問到。 以下例子,即使只有一個 container 運行,佔用 port 8888,它還是會在5個節點上全開。 swarm 通過自己的 ingress network,它所有節點的 8888 串連起來。 services: http: image: bretfisher/httpenv ports: - 8888:8888 deploy: replicas: 1 update_config: delay: 10s restart_policy: condition: on-failure 我們可以在每個節點上,都會找到這個 ingress network,而且那個Network ID,應該是一樣的 > docker network ls | grep ingress t7rmk6g9zybm ingress overlay swarm 如果上述的 service 的 replicas 調成大於1的數量, ingress network 還會方便地自動 round robin (輪替) 地分派流量,達到最簡單的負載平衡。 Virtual IP 前述的設定,我們有一最大的假設,就是節點不會死機。但實際情況下,各種原因,例如安全性更新、重啟中,都會讓節點暫時無法使用。即使所有 service 都是會自動 failover (故障轉移),但客戶端還是用舊機 IP ,它還是無法訪問。因為該機 IP 已無法使用,除非我們連 IP 也懂 failover。這時, Virtual IP 就是我們的救命靈藥。 在 ubuntu 上,我們可以經過 keepalived 去設定 Virtual IP apt-get update && apt-get install keepalived -y 然後設定 keepalived , 假設 172.22.1.5 是我們的 Virtual IP 。 然後每個節點都要加入conf # vim /etc/keepalived/keepalived.conf # assume failover ip is 172.22.1.5 vrrp_instance VI_1 { # change interface according to machine status interface eth1 state MASTER # 101 for node1, 102 for node2 # you can start seq from other value, remind unqiue for each node is ok; virtual_router_id 101 # lower value will become master # ex, node1 priority 100, node2 priority 200, node3 priority 150. # if node 1, 2, 3 alive, node2 will become master. # if node 2 gone, node 3 will become master. priority 100 advert_int 1 authentication { auth_type PASS auth_pass YOUR_RANDOM_PASSWORD } virtual_ipaddress { 172.22.1.5 } } 上述需要特別注意的是 virtual_router_id : 每個節點應該都要不一樣,以作唯一標識。 priority : 每個節點應該都要不一樣,最大的那個節點,就會優先使用 Virtual IP 。 auth_pass : 每個節點都相同,但大家在抄時,記得更改。 還有的是開通 iptables ,讓各個節點可以經網絡廣播的方式互相看到對方。 iptables -I INPUT -d 224.0.0.0/8 -j ACCEPT iptables -I INPUT -p vrrp -j ACCEPT systemctl restart keepalived

Docker Tag 命名

科技新知
MacauYeah・2024-10-24

一般來講,同一個docker image會提供多個不同的版本,每個版本會附予不同的tag,以作標識。但以docker image的維護者來講,它的tag通常代表的是自己程式的版本號。不過這個版本號卻存在很多變數,就讓筆者好好地逐一說明。 程式的版本號 在沒有Docker的年代,其實所有軟件在發佈時,都會標示版本號,方便使用方明確追蹤問題,自行選擇升級、降級以解決相容性問題。大家要重現問題,也能清清楚地重現。所以docker image的tag,在某程度,都是代表發佈自己的程式版本號。但以前的年代,軟件底層的依賴,例如OS層面的共享程式庫,則不在發佈的管控中,所以過去的程式,在跨電腦安裝時,都會出現缺少某些共享庫的問題。而使用了Docker後,image以內的共享庫的都會在打包的那一刻固定和發佈,就不會有漏的問題。 庫更新,怎麼辦 上面說到image可以打包共享庫,但問題是共享庫也會有安全性更新問題,那麼對docker image的維護者來講,它自己的tag又該如何命名? 因為庫的量可大可少,所以一般來說,都不可能完全把各個庫的版本號寫在自己的tag上。退而求其次,就是用"版本號+日期",庫的細版本號,就存在原始碼當中。Ubuntu 就是這樣的例子。 不過"版本號+日期"的命名方式真的方便嗎?每次下遊用戶想更新去最近版本,都要自己找一次最近的日期。這樣對很多用戶來講都不夠方便。所以docker又提供了一個重tag的功能。例如ubuntu:noble,在早些時候指著noble-20240904.1,然後過幾天,又指向更新的noble-20241009。更常見的是latest,每次image都預設會存在,docker也希望大家會定期更新這個tag,讓大家可以更易地找到最新版本。 註: 這跟git tag有所不同,git tag並不預期會變的。當協作者收到tag後,那怕上遊刻意更新tag指針,協作者沒有刪除原tag之前,都不會知道tag更新去了哪裏。 我們該如何選 在發佈方和引用方來講,引用時可以明確使用唯一的"版本號+日期",對穩定性來講是有意義的。不過多多少少,會產生額外的時間成本。發佈方來說,就是多用了一些儲存空間,方便引用方可以隨時找到舊(庫)版本。而引用方,就要手動修改引用號,作為驗收依據,自動更新的難度比較大。 但對於自動更新要求比較大的情況下,可能就是使用latest或者會隨時更新的share tag(共用tag)比較實際。但我們也依然要定一些方式去版本更新記錄,例如:同時使用 beta latest archive 每日自動更新beta,只有所有測試都通過時,才把archive指向現在的latest,再把latest指向現在的beta。這樣做的好處是,核心的docker stack檔案改變的機會較少,也可以免除docker swarm做太細緻的權限管理。

重入膠坑

手機‧電玩
MacauYeah・2024-10-21

上期講到,筆者因為機緣之下,認識到賢者模型工作室,也很感謝他們幫忙修復了筆者那斷椿的模型(斷樁是膠老永遠都要面對的難題) 不知道大家看了筆者的爛尾舊模之後,有沒有也心動想把自己的舊模拿出來再繼前緣?概然有這個麼好的地方,有人指路,何不帶著大家的模型或問題,去賢者問一問。筆者就在最近一個月,就乾脆一口氣做一隻新模,翻新一隻舊模。 筆者也來分享一下最近的素組+補色的制作心得 剪鉗 - 新模 如果大家有機會做新模,看大家有沒有打磨的需求。打磨是很花時間的,但成品通過打磨後,即使不上色,只噴保護漆,已經超級美觀的。但時間成本也真的很高。 為什麼明明標題講剪鉗,但開篇卻在講打磨。因為第一步把模型從流道剪下來的那一刻,就間接地影響了日後能不能打磨。也根據大家要求的打磨完美度,去決定剪鉗要買多貴。 不論大家想不想打磨,但買一把實用的剪鉗,不要在剪下來取件的一刻令水口位花了,是很重要的。雖然有時留了位置打磨,但若水口花了,有時還是會傷到零件本身,不論表面怎樣打磨,都救不了。那時不是使用補土,就是要打磨到缺肉。家裏環境不方便上色的話,補土的做法就不適合了,還是好好地選剪鉗吧。 完全不打磨,可以買薄刃單刃剪。薄刃單刃剪可以極大地讓水口切割平整,又讓水口細小,之後不想打磨,也不會大刺刺地看到。筆者有試過這個方案,筆者還有一些更奇妙的想法:一開始開心剪,先素組/假組再說,後期有機會再打磨。但這個不是賢者老闆的推薦方案,而筆者慢慢地也發現了一些問題,果然不聽老人言,吃虧在眼前。我們有機會實際操作再詳述。 進行打磨,可以買田宮的雙刃剪,雙刃剪也有薄刃的,但鋒利程度不單刃。賢者老闆比較推這款,因為價格宜人,也耐用。不過筆者都有聽一些其他朋友的建議,一把粗剪,一把薄刃,這樣薄刃剪比較耐用。因為薄刃剪不論多便宜,也要 MOP 200起跳。但壞處就是時間成本越來越多,所以到頭來,可能賢者老闆推薦的田宮的雙刃剪 + 自行打磨,才是長久的做法。 打磨 - 新舊模 若果大家選擇打磨的話,就需要不同號數的砂紙。筆者就直接買了老闆推薦的海棉砂紙套裝:400, 600, 1000, 1500, 3000。省心,好用。 不過對於有需求的朋友,可能要另外再散買800和1200號。另外400,600號,也要加構砂紙+打磨板的版本。因為400,600號切削力強,不分情況全用海棉的話,很易磨到出現曲面。800和1200則作為600、1000、1500之間的過渡。有時太粗心,部份地方沒有足夠用1000打磨,噴保護漆後,還是會有明顯的傷痕。 手塗補色 - 新舊模 不論大家有多痛恨Bandai的貼色,筆者都不建議大面積手塗補色。因為市面上手塗的marker筆,多為水性塗,附著力本來就低,沒有底色補土的情況下,水性塗很易刮塗。筆者之前不知道,刮了又塗,塗了又刮,惡夢。經向賢者請教之後,才放棄這一方向。 而中、細型面積的補色,軟頭的Marker補色筆,實在太好用。除了白色這類遮蓋力不強的顏色,其他遮蓋力強的顏色,例如藍色、紅色,在補土加成之下,筆者塗得很滿意,不過刮漆還是會有。

Tmux - 繼 Screen以後的Linux多工神器

科技新知
MacauYeah・2024-10-08

因為各硬件/軟件的發難,筆者又不得不回到那個只有純純linux tty console的世界。很多時候,那怕使用tty,我們在Desktop mode,也有現代terminal 可以用,需要多分頁,滑鼠選取文字、複制、貼上,都可以輕易做到。 但在mobile / tablet device 上,手指操作真的很不方便。又或者你像筆者一樣,即使有電腦,但要操作一些Linux VM,它們連ssh都沒有,只能直接登入它們的tty,那麼懂得使用Tmux進行分頁及複制、貼上,就變得很重要。 Tmux 是什麼? Tmux 就是可以在Linux Terminal 同一個窗口中,實現多工處理的小程式。就像我們利用多分頁一樣,不同分頁做不同的事。不過最大的差異就是,生成分頁,排列分頁,我們都要使用鍵盤來完成。有時筆者也會用它來作為背景程式,以免不小心關了Terminal就會把所有運行中的指令都停掉。 我們就馬上來看實際例子吧 前置事項: 安裝Tmux及運行Tmux Debain & Ubuntu 安裝: sudo apt-get update && sudo apt-get install tmux 運行:tmux 進入tmux後,你就會至少有一個分頁,而且不會因為Terminal關閘而中斷 用法一: 建立兩個分頁,並切換 增加分頁: 先按 “Ctrl + b” (前置鍵),再按”c” (create) 切換分頁: 在多於一個分頁的情況下,先按 “Ctrl + b” (前置鍵),再按”n” (next) 用法二: 同一個分頁中,建立左右並排的窗口 增加水平窗口: 先按 “Ctrl + b” (前置鍵),再按 “ (雙引號) 切換窗口: 在多於一個窗口的情況下,先按 “Ctrl + b” (前置鍵),再按方向鍵左或右 用法三: 回到前一個tmux session中 因為不小必關閉了terminal,又或是remote ssh中,ssh斷線後,需要回到之前的工作狀態 未進入tmux 的狀態下:tmux attach 要留意tmux 可以有很多個session,要去到指定的session,就要為session命名。但這個不是筆者常用的情境,原本多個分頁已經很夠用,還要多個session,會很混亂。但不排除它在某些情況下有特別用途,有興趣的朋友可以自行挖挖看。 進階: 回頭看過去的terminal screen output 在現代的Terminal中,原本按滑鼠滑輪向上滾,就可以看到過去的資訊,但tmux下反而不行,所以我們需要進入特殊模式 進入Copy Mode: 先按 “Ctrl + b” (前置鍵),再按 [ (開括號中括號) 向上翻頁: 上方向鍵或PageUp 離開Copy Mode: Copy Mode中任何時候按”q” 進階: 複制貼上 進入Copy Mode: 先按 “Ctrl + b” (前置鍵),再按 [ (開括號中括號) 選擇範圍: 移到需要複制的文字起點,“Ctrl + Space” ,然後再移動到結束點,再按”Ctrl + w” 複制 貼上: 離開Copy Mode後,再按”Ctrl + b” ,然後 ] (關括號中括號) 進行貼上 進階: 複制貼上2 某些情況下,我們不允許使用“Ctrl + Space” 或 ”Ctrl + w”,因為它們可能跟系統的組合鍵有衝突,所以需要改為單鍵。 讓tmux使用類似vim的操作模式: echo “set-window-option -g mode-keys vi” >> ~/.tmux.conf 關掉所有使用中的tmux,重開tmux 進入Copy Mode: 先按 “Ctrl + b” (前置鍵),再按 [ (開括號中括號) 選擇範圍: 移到需要複制的文字起點,按單鍵“Space” ,然後再移動到結束點,再按”Enter” 複制 貼上: 離開Copy Mode後,再按”Ctrl + b” ,然後 ] (關括號中括號) 進行貼上 筆者常用的功能就這些,有興趣的朋友可以再深挖一下。 Reference https://tmuxcheatsheet.com/