潮流特區

最新文章

排程執行任務 | Linux Schedule Job

科技新知
MacauYeah・2023-09-07

在Linux底下,crontab是一個最簡單建立Schedule Job的方法。大家用crontab -e 就可以進入設定。 # crontab -e */1 * * * * /opt/run.sh 其中每個星號,順序代表的是分、時、日、月、星期。上面的例子就是不論何月何日何時,只要每一分鐘就執行一次/opt/run.sh Singleton Job 問題是,實際情況下,你想執行程式的時間都不一定會少於1分鐘。所以你總是有機會上一個job未跑完,下一個job就開始了。為了保障自已,需要一些參考機制,去決定是否讓job開始跑。 有些情況,可能你會想用job server去做監管,但若只為單線執行的工作,起一個job server還是會增加管理上的複雜性。 最簡單的做法,就是根據不同的程式語言,使用file lock(鎖上)的機制,先上鎖,再做事。但要注意考慮有沒有出現異常情況,令你自己反鎖自己。即是你的process死了,但不懂自己解鎖,這樣以後你也不能再執行了。 在Linux Bash Shell下,就有一個很簡單的做法,就是使用flock指令。用它的最大好處,就是從OS層面下,去鎖上。只要process結束了,不論正常還是不正常結束,都會自動解鎖。 以下例子就是在執行/opt/run.sh前,先要取得/tmp/run.lockfile的鎖。如果沒法取鎖,就自動放棄執行後面的指令。 flock -n /tmp/run.lockfile /opt/run.sh # crontab -e */1 * * * * flock -n /tmp/run.lockfile /opt/run.sh Timeout 引入singleton的概念後,其實會引發另一個問題。因為異常的情況,還有機會是不生不死,process hang。所以我們還需要設定一個最大的執行時間,讓你的process在異常的情況下,被強行清走。 例如,ping指令在linux預設是永遠不會自動停止的,可以模擬process hang的情況。如果我們想定時從外部收走ping process,就可以使用timeout指令。以下指令就是2分鐘後殺指ping process。 # in file /opt/run.sh timeout 2m ping localhost # to check process id, you could use # > ps aux | grep ping # you will see two different id for ping and timeout 配合errorcode使用,你可能還會在想在timeout時送出一個email通知自已。 # in file /opt/run.sh timeout 2m ping localhost exitCode=$? if [[ $exitCode -eq 124 ]]; then echo "timeout" # enter email alert with timeout elif [[ $exitCode -gt 0 ]]; then echo "exit with error" # enter email alert with timeout else echo "exit normal" fi 配合docker使用,你可能需要考慮signal怎樣傳遞。 在筆者測試的環境中,似乎SIGTERM會被擋,也有可能是SIGTERM太強,它只把前景的docker container run收走,但其內的ping process還在docker daemon中行走。所以最後改用SIGINT,讓docker container run可以好好地把SIGINT傳入其內。 # It seems that docker captured the SIGTERM. Send SIGINT instead # in file /opt/run.sh timeout --signal=SIGINT 10s docker container run --rm pingtest -c 20 exitCode=$? if [[ $exitCode -eq 124 ]]; then echo "timeout" # enter email alert with timeout elif [[ $exitCode -gt 0 ]]; then echo "exit with error" # enter email alert with timeout else echo "exit normal" fi Full demo, github repo cronjobWithDocker

發佈Docker Swarm App的選擇 - CI/CD系統的參與

科技新知
MacauYeah・2023-08-25

一段時間前,筆者就討論了一些Docker打包的程式的文章,也討論了一些Docker Cluster環境下的選擇。現在也是時候,可以分享一些對於發佈環境的可選空間。 CI/CD系統 CI/CD 全稱是continuous integration (CI) 和 continuous delivery (CD),字面上代表的持續地集成和發佈,實體上就是某台伺服器自動發佈APP。因為使用到Docker Cluster,不論前述什麼選擇 (前文連結 請點這裏),都會有多個node(節點)的出現。要發佈App,總不能一個個node逐個登入設定。所以我們需要一些CI/CD工具,把這個過程都自動化。 在筆者的認知上,CI/CD系統,由兩個部份組成,一個是取得Source Code(程式原始碼)的過程,一個是編譯或發佈Source Code的過程。Gitlab,Github,BitBucket等大型的代碼庫供應商,它們天生為了保存Source Code而提供服務的。不少CI/CD系統都可以跟它們整合,它們提供了存取Source Code的部份,剩下你只要能提供編譯或發佈的伺服器就好。 如果作為小型開發團隊,很少會有意願去自己花錢養一個編譯或發佈的伺服器。(極端地,如果我就是一人團隊,我用自己電腦編譯和發佈就好,伺服器能做的,我自己也能做。)好消息的是,Github提供了一個叫Github Action的CI/CD系統,即使你沒有自己的編譯專用的伺服器,Github Action也可以用Docker Image,提供一個臨時的編譯程序,用完就刪掉。詳細功能還請各位先查看官方教學,筆者也暫時只能零星使用經驗,無法給出有意思的架構。 如果對智慧財產權有高度重視,Source Code不能存放在公開的伺服器,那麼Gitlab Enterprise Edtion則是一個好選擇。運用Gitlab ee,你可以用自己的機器,造一個純本地的庫存伺服器。更強的是,它內建也有CI/CD系統,只要你有間置的伺服器,就可以作為編譯使用。筆者也是從這個方向著手,架設了自己的Gitlab Runner(Gitlab CI/CD系統)。在這裏,就分享一下與Docker Swarm整理的概念。 對於前述兩種選擇,GitLab Runner都可以做得到 底層程式打包成Image並運行在Swarm mode上,每次發佈的是App Binary(執行檔或核心檔案)。 把App直接打包成Image,並運行在Swarm mode上,每次發佈的是App Image。 CI/CD - 打包底層程式成為Image 在這個選擇下,其實就跟傳統自動化發佈的做法類似,只是發佈時,要多個node報行更新指令。如果你使用的底層程式原本就有支援多版本並行,這樣更新時就不用太操心rollback(回滾?)等操作。若系統不支援多版本並行,為求簡化,若遇到要rollback的情況,重跑過去舊的CI/CD操作也是一個做法。當然,我們也可以經過一些備份的操作,來保存被代替的程式,若在發佈過程中出問題,也可以手動重來,不過整件事就越來越複雜。 筆者發佈的基本思路是 使用docker image,編譯和打包App Binary。 使docker image做編譯的好處是,你可以比較放心地假設每次編譯時,你的編譯環境都是乾淨的。 傳送上述的結果至生產環境可以取用的地方。 跳入生產環境執行更新指令 這裏有些隱藏的管理成本,如果你生產環境中有多個node,最後那幾行指令就要多抄幾次。 CI/CD - 打包App成為Image 在這個選擇下,對比傳統自動化發佈的做法,現在要多做一步,就是要包裝自己的Image。不過好處是docker swarm有提供監測工具,在發佈過程每個分身會逐個更新,前一個分身更新成功後才會到下一個分身更新。而且 rollback等的操作,你可以靠docker做到。即是要手動rollback,也可以透過更正docker tags來達到,所以整體上來說沒有比傳統的麻煩。 筆者發佈的基本思路是 編譯App Binary。 打包成docker image。 經docker上傳image。 跳入生產環境執行更新指令。 對比傳統自動化發佈的做法,最後的更新指令,只要執行一次就可以。當然,原本在Docker Swarm中要管理的事還是要好好管理。 CI/CD - 備註事項 雖然CI/CD可以幫忙簡化更新的過程,但實際操作會比上述的例子複雜一些。因為通常對非技術型的外界用戶來說,一個Web App會包含很多不同的功能。上述的例仔,在實際情況下可能需要拆解成很多微服務來進行。所以對管理上還是有相當的挑戰。

Docker Swarm mode 指令教學 | docker service

科技新知
MacauYeah・2023-08-22

之前一直都討論Image 的打包形式,現在聊聊部署上線時的一些指令。 Docker Service swarm mode 主要通過"docker service" 指令去產生一堆可以在不同節點上運行的container。為了更加形象地講,我把container稱為Image的分身。 docker service create跟docker container run的感覺很像,兩者都可以指定image # swarm mode $ docker swarm init $ docker service create --name nginx_s nginx # container mode $ docker container run -d --name nginx_c nginx 兩者的差別在於docker service 可以指定多少個分身,可以隨時加減數目,而且如果你有多過一台機器,分身就會在不同的機器上遊走。而docker container就是只對本機有操作,也不會散播到其他機器。 # swarm mode $ docker service create --replicas=2 --name nginx_s nginx $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS uro4rwy6nelh nginx_s replicated 2/2 nginx:latest $ docker service update --replicas=5 nginx_s $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS uro4rwy6nelh nginx_s replicated 5/5 nginx:latest # container mode $ docker container run -d --name nginx_c1 nginx $ docker container run -d --name nginx_c2 nginx $ docker container run -d --name nginx_c3 nginx $ docker container run -d --name nginx_c4 nginx $ docker container run -d --name nginx_c5 nginx $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c45771f06612 nginx "/docker-entrypoint.…" 7 seconds ago Up 6 seconds 80/tcp nginx_c5 a587a718da3a nginx "/docker-entrypoint.…" 9 seconds ago Up 9 seconds 80/tcp nginx_c4 079f206f8645 nginx "/docker-entrypoint.…" 9 seconds ago Up 9 seconds 80/tcp nginx_c3 e10dc525fd22 nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp nginx_c2 dcaa2b4bb3de nginx "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp nginx_c1 在建立網段時也差不多,service需要的是overlay network,而container用一般network就可以。 # swarm mode $ docker network create --driver overlay nginx_s_gateway $ docker service update --network-add name=nginx_s_gateway,alias=gateway nginx_s $ docker service ps nginx_s ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS fxqtheyvr914 nginx_s.1 nginx:latest dockertest Running Running 33 seconds ago u0pvj1leoizw \_ nginx_s.1 nginx:latest dockertest Shutdown Shutdown 33 seconds ago q7arumjlxduv nginx_s.2 nginx:latest dockertest Running Running 36 seconds ago kurlwqfmopbg \_ nginx_s.2 nginx:latest dockertest Shutdown Shutdown 37 seconds ago zd0zlkhxafv0 nginx_s.3 nginx:latest dockertest Running Running 40 seconds ago 3kapr00fs6pt \_ nginx_s.3 nginx:latest dockertest Shutdown Shutdown 40 seconds ago 5o4afd3whygo nginx_s.4 nginx:latest dockertest Running Running 35 seconds ago oxocropolbo8 \_ nginx_s.4 nginx:latest dockertest Shutdown Shutdown 35 seconds ago x5y94jf3ok51 nginx_s.5 nginx:latest dockertest Running Running 38 seconds ago cgld3au0w1i9 \_ nginx_s.5 nginx:latest dockertest Shutdown Shutdown 39 seconds ago # container mode $ docker network create nginx_c_gateway $ docker network connect --alias gateway nginx_c_gateway nginx_c1 $ docker network connect --alias gateway nginx_c_gateway nginx_c2 $ docker network connect --alias gateway nginx_c_gateway nginx_c3 $ docker network connect --alias gateway nginx_c_gateway nginx_c4 $ docker network connect --alias gateway nginx_c_gateway nginx_c5 不過比較大的差異是service會停了原有的分身,重開新的分身去加入網段。所以上面的docker service ps nginx_s執行結果,就有一半是停掉的。 類似地,docker service也不能單獨地停掉分身,頂多只能調整--replicas=NUMBER,來控制分身數量。而單機則可以經過docker container stop來暫停分身。

Docker打包 App還是打包底層程式作為Image ?

科技新知
MacauYeah・2023-07-28

雖然筆者對於Docker Swarm Mode的資歷尚淺,但由於後期更動的難點越來越多,筆者很想早一點討論其中不同操作的差異 Docker Swarm Docker Swarm Mode其實是Docker提供的一個Cluster(群集)環境。在其中運行的Image,都可以比較方便地隨時分身到不同的node(節點)上,對於提高負載或可用性,都是一個不錯的解決。 只要該Image跑起的Container是Stateless(前後兩次執行的結果互不相干涉),或者是把Stateful的部份(有干涉的部份)外包到第三方(例如儲存空間使用NFS,或記憶體暫存改為Key-Value Database),就可以方便地運作在Docker Swarm mode上。 部署Docker Swarm的選項 Docker Swarm可以把Image變成分身Container,但並不沒有硬性改變傳統App操作方式。大部份App在執行時,都需要另一個底層程式的支緩。例如 Php Web App,需要底層php fpm + nginx或apache Java Web App,就需要java + Tomcat 所以在發佈App時,可以選擇把 App直接打包成Image 只把底層程式打包在Image中(例如Tomcat),再在跑起Container時再動態接起App。 兩者有何差別? 就信心層面上,一定是把App直接打包成Image實際一點。因為這樣可以極大地減少測試環境和正式環境的差異而出現的問題。筆者一開始也不完全讚成,但也越來越傾向這種做法。 在解釋筆者為何有這個結論前,先條列式地對比一下兩種差別。 事項打包App成為Image打包底層程式成為Image 打包複雜度 需要把App用到的一些環境變數引入設定Image的entrypoint中,方便配合不同的環境可以改變App的行為。打包次數根據App數量有關。比較靈活,但比較需要學習和試錯。 底層程式統一設定環境變數,其中所有App都會使用類似或相同的設定,設定方式跟傳統方式無異。打包次數根據底層程式數量有關。比較死版,但要試錯的成本較低 發佈流程 打包App成Image。再靠Docker Swarm設定Image有多少分身,每個分身不需要特別再設定。 原來的底層程式已存在於Docker Swarm中,只需把新建或更新了的App放入不同分身的儲存空間,讓底層程式動態跑起App。 管理複雜度 每個App都是獨立的,代表有任何更新也是獨立更新。在微服務的協作環境中,需要管理員從Image層面為每個App設定網絡(network)或開放端口(Port)。但每個App可以設定不同的分身數量,靈活性一定比只打包底層程式要高。 使用同一個底層程式Image的App都會使用同一個網路和端口設定。在微服務的協作環境中,管理員要應付的設定數量一定比打包App要少。但由於是Conatiner分身是針對底層程式,所以若然某個App有不同需求,就要重新設定另一套底層程式。 上述幾個點,最後其實都是複雜度和靈活度的取捨。雖然打包App的工序更多,但提供的靈活性也更多。如果考慮要從傳統模式中過渡,方便與完成不懂Docker的同事協作,就首選打包底層程式。如果考慮可重複性和信心保證,還是打抱App比較直接,要複制一個環境到另一個環境,也比較易測試。

自己架設Docker的共享儲存空間

科技新知
MacauYeah・2023-07-21

Docker很好用,在單機環境下真的很好用。Docker原本的設計,是為了快速迭代而設計成Image的。在一般設定下,每次新建或重建container,都會根據Image重設一下各方面的環境,包括儲存空間。重設CPU,Memory,大家都很易理解,但重設儲存空間,真的不是每一個使用情況都可以這樣。 又或者說,未必所有使用情況都會有一個第三方的儲存空間可以用。所以良心的Docker在單機環境下也有提供bind mount或是docker named volume,作為可以長期保存,不受container生死的影響,以達到長期存在Data的存在。 單機-儲存空間 單機情況下很簡單,就用一個docker compose做例子 其中html就是一個bind mount,而nginxlogs就是一個docker named volume,兩者都可以長期保存data,除非各位自己手動刪除,否則不會因為container的興亡而不見了。 但有兩個很重要的分別 bind mount,直接跟host os連接,實際上是每次folder有更新,docker都要同步host和container之間的資料。 bind mount在linux下很暢順,因為大部份docker image/container原本就是linux engine,所以folder mount真的可以互通。 bind mount在windows / mac下,就會不斷抄資料。面對大量檔案,例如node_module,就會有速度上的問題 docker named volume,就是docker 分離一些獨立空間,然後再綁到container上 相對bind mount,即使在windows / mac下,都沒有那個速度上的問題。筆者猜測,即使是獨立空間,其實本身都已經限定在linux enginx下,所以沒有需要抄資料。 但在windows / mac下,因應docker 底層建立Linux VM的技術不同,你可能沒法在windows / mac預設環境下直接讀取docker named volume。 若要讀取docker named volume,最好的做法,還是連上docker container,然後用docker cp 來抄回資料。一但抄資料,其實都會有速度上問題,不過docker cp是手動決定何時做的,不做docker cp,其實container也是可以用。 Cluster-儲存空間 雖然良心的bind mount和named volume解決了單機上的儲存問題,但到了cluster環境,就沒有可以跨機同步儲存空間的做法,要做就自己建立。 筆者也稍為研究了一下同步的問題,不過對技術真的很有要求。所以退而求其次,筆者還是選擇簡單的第三方儲存空間。就是做一個可以分享存取的NAS。 建立nfs linux下要安裝nfs其實很簡單,不過要注意資料夾和防火牆權限,以下安裝教學以ubunut 22.04為例,記得把下面的YOUR_DOCKER_NODE_ADDRESS_RANGE轉為你的真實IP段落 修改docker compose 最後,你在原來的docker-compose的docker volume上加driver_opts就大功告成。 記得把下面的YOUR_NFS_IP轉為你的真實IP

Git Co-Work Flow

科技新知
MacauYeah・2023-06-23

Git Co-Work Flow 雖然git面世已很久,但相當一部份澳門朋友都是solo man,很少合作寫code,對git branch始終都有些恐懼。所以這次來解召一個基本原則,至少你不會爛了code救不回來。 若然大家未熟悉git,初次利用git合作寫program,請盡量減少使用共同分支(branch),可以極大地減少問題。 第一個大原則 - 建立一條自己分支 在一個repo中,為自己建立一條分支(branch),可以減少Remote repo中有人比你先commit,而令你push失敗的情況。 Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 除非你的隊友故意你用的分支名先commit,又或者你自己有幾台電腦,幾台一起做改動。不然push 應該不會有問題。 第二個大原則 - 用fetch取代pull 很多人在取用Remote Repo的更新時,都會使用pull。但pull其實是fetch及merge的混合,而且merge還要考慮source branch是那條分支的問題,若然大家都有一條獨立branch,那麼這個無腦pull並不存於每人只有一台電腦下的多人協作中。 fetch的過程中,還可以加入參數--prune,順便依照Remote Repo的指示,同步刪掉本機中一些不再存在的origin/branch。 Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 第三個大原則 - Merge前先Commit 經過前述fetch後,其實他人的改動並未加入自己的分支中,必需經過merge才會出現。但並不是沒有conflict就無腦merge。 假若自己有改動,未commit,應該老虎蟹都先commit。這是為了在merge後,還有機會可以無腦reset,回到之前那個commit。這就像是做任何更新前,先做backup。 Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 第四個大原則 - 由某個特定的人來管理master或main branch main branch(以前叫master branch),是他人下載時的預設分支,也是Github、Gitlab的預設顯示分支。所以該分支存放著的source code,應該在代表信心度比較高。 在協作的環境中,每人都有自己分支,那就代表要有一位人員做管理,他負責checkout main, 然後合併其他已驗證的分支。 Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 在某些比較嚴僅的環境中(例如Github、Gitlab),main分支可能會被系統機制鎖定,必需通過系統內鍵的Pull Request,才能通過審核,合併到main。另外,也有一些關於開發上的Git workflow,主要針對功能管理、版本發佈、錯誤修正等控制。有機會再為大家介紹。 希望以上的流程,可以有效且容易地讓大家協作。如果有任何command錯誤或更新,都可以經Github Pull Request通知筆者。

Vmware下建立Docker Cluster

科技新知
MacauYeah・2023-06-16

之前都使用Multipass作為Proof of Concept,自己做測試用。直正上Production,Network環境就多少有點差異。 假設大家為Application Admin,但無條件處理Vmware層面上的事項,只可以從VM內部install / setup application。 安裝Docker script 都來自Docker 官方網,筆者微調了一些auto accept選項。 Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 假設三台VM已經安裝docker,ip分別為 10.13.31.21, 10.13.31.22, 10.13.31.23。 在其中一台VM上,例如:ip 10.13.31.21上, Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 與前述Multipass不同的是,這裏的data-path-port要自定義,因為預設的port 4789在Vmware的有特殊同途。 之後部份就跟傳統做法一樣,先取得manager join token, 然後在其他VM上使用該token加入cluster Code block由於安全性問題,沒有獨立寫了LifeMag 網誌中,請移到github repo。 這樣,在swarm上的application,就會自動在10.13.31.21, 10.13.31.22, 10.13.31.23,上遊走。 即使你的app container目前是跑在10.13.31.23:8080上,但因為swarm mode routing mesh,你經過10.13.31.21:8080都可以連到該app。 如果你只是做stateless app load balance分流,這樣就足夠了,不用考慮ip fail over。但如果你要做到ip fail over,還要額外設定keepalive virtual ip,這個virtual ip會自動依付到某台活著的VM上,這樣外界才不會連到一個死ip上。又或者額外建一台load balancer,可以偵測到swarm node上那台機還活著,從而達到fail over效果。但這台load balancer也有一些穩定性要求,若然大家只是用一個普通的nginx做load balance,還是會有單點故障問題(single point of failure)。

使用 Multipass 建立Docker Cluster

科技新知
MacauYeah・2023-06-02

以下流程,假設各位已經 在Ubuntu Server中開設了virtual bridge 供Multipass設定Static IP,並且network interface定為 localbr 使用Packer template制成docker.img , 並存放於當前資料夾內 使用docker.img 起三個node,並使用network interface localbr,各有一個指定的mac address multipass launch file://$PWD/docker.img --name node21 --network name=localbr,mode=manual,mac="52:54:00:4b:ab:21" multipass launch file://$PWD/docker.img --name node22 --network name=localbr,mode=manual,mac="52:54:00:4b:ab:22" multipass launch file://$PWD/docker.img --name node23 --network name=localbr,mode=manual,mac="52:54:00:4b:ab:23" 對運行中的三個node,為它們設定static ip multipass exec -n node21 -- sudo bash -c 'cat /etc/netplan/10-custom.yaml network: version: 2 ethernets: extra0: dhcp4: no match: macaddress: "52:54:00:4b:ab:21" addresses: [10.13.31.21/24] EOF' multipass exec -n node22 -- sudo bash -c 'cat /etc/netplan/10-custom.yaml network: version: 2 ethernets: extra0: dhcp4: no match: macaddress: "52:54:00:4b:ab:22" addresses: [10.13.31.22/24] EOF' multipass exec -n node23 -- sudo bash -c 'cat /etc/netplan/10-custom.yaml network: version: 2 ethernets: extra0: dhcp4: no match: macaddress: "52:54:00:4b:ab:23" addresses: [10.13.31.23/24] EOF' multipass exec -n node21 -- sudo netplan apply multipass exec -n node22 -- sudo netplan apply multipass exec -n node23 -- sudo netplan apply 使用node21作為Leader (Manager),與其他兩個node一起組成Cluster multipass exec -n node21 -- sudo docker swarm init --advertise-addr 10.13.31.21 multipass exec -n node21 -- sudo docker swarm join-token manager managerToken=$(multipass exec -n node21 -- sudo docker swarm join-token manager -q) multipass exec -n node22 -- sudo docker swarm join --token $managerToken 10.13.31.21:2377 multipass exec -n node23 -- sudo docker swarm join --token $managerToken 10.13.31.21:2377 Cluster就建立完成。 若想刪掉重來 multipass delete node21 multipass delete node22 multipass delete node23 multipass purge 備註 在直正使用時,大部份時間還需要做port forwarding。multipass沒有自己的port forward,可以用ssh tunnel來模擬。 例如把Ubuntu Server的8080指向node21的8080,可以這樣 sudo ssh -i /var/snap/multipass/common/data/multipassd/ssh-keys/id_rsa -L 0.0.0.0:8080:10.13.31.21:8080 ubuntu@10.13.31.21 完整的script可以參考initDockerCluster.sh。 沒有Bare Metal Ubuntu或者沒有static ip也可以參考initDockerClusterWithoutStaticIp.sh。只是因為network brandwidth問題,我就不會在每次更新時都測試。

[教學] 平民雲端服務不是夢 | 5分鐘教你如何快速起VM

科技新知
MacauYeah・2023-05-11

前言 原本筆者只是想做docker cluster,但因為在實機中建VM極其麻煩,所以就研究了好一陣子如何快速起VM。 Hyper-V有預設的Ubuntu template,但只有ubuntu desktop版,沒有server版。而且desktop gui顯得浪費資源,要clone VM也很廢時,放棄。 Windows Subsystem Linux起VM很方便,但同一個Linux version只有一個instance,沒法起cluster,放棄。 Virtual box沒有Ubuntu template,若要clone的話就變得跟Hyper-V差不多,放棄。 經過一輪資料搜集,發現了一個Ubuntu multipass engine,聲稱可以跨平台快速起VM。裏面有一些很吸引的功能,可以自己建立images、使用固定IP。 那怕即使是沒有snapshot,在自定義images的配合下預裝docker,要隨時加減cluster node都是一件容易的事。 重大決策點 醜話說在前頭。經過一輪測試,multipass最大的問題,就是custom image、fix IP都只能在bare metal ubuntu 中才能使用。如果你沒有一台閒置實體機安裝Ubuntu,還是要再多考慮一下。 重點 詳細的流程,筆者記錄了在Packer template 和Multipass Static IP中,在這裏就只說一些重點。 packer是使用cloud-init和qemu的技術,行起template中指定的cloud image (在筆者的例子中就是ubuntu-22.04-server-cloudimg-amd64.img) 大家可以定義image行起後進行一些操作,而那些操作都是經過qemu vnc、ssh進去操作的。 操作完後就會直接儲存當時的image。所以在操作結束之前,盡可能地刪cache或刪去不要的user / group settings。 最後生成的image,還是一個cloud image。若要再運行它,必需要使用支援cloud-init的VM來讀取。 cloud-init是用來指定初次運行時要設定的事,例如:hdd size, user account password, ssh key import等。 使用工具cloud-localds可以生成一個seed.img,這樣qemu也可以cloud-init。 Hyper-V應該也可以經過類似方式,進行cloud-init,但筆者未有去實測。如有更簡便的方法請告知。 multipass預設就已經有cloud-init,在bare metal ubuntu就可以直接執行。 multipass也可以設定不同的cloud-init參數。 成品 最後筆者就選擇了用packer用來預裝docker,經mulitpass無腦起VM,再使用shell script對多個node設定docker,達到即時起docker node的功能。這樣就減省了VM的安裝時間,也省去了docker的安裝問題。 說到底,如果只想測試docker cluster,其實windows, macOS中的multipass也可以實現相同的功能。因為安裝docker那些都可以經過shell script自動化,只是每次重複操作,都變得相當慢。另外,因為multipass在windows, macOS不支援fix ip,對於指定docker cluster interface又會再多一重功夫。

文字創作者的辛酸 | 定制鍵盤改善不合理的按鍵佈局

科技新知
MacauYeah・2021-12-14

不知道經常做中文文字編輯的朋友,右手會不會特別疲勞? 筆者就會有這種經歷,主要是因為筆者右手要同時兼顧鍵盤與滑鼠;而且打字時,很多刪除,左右移動,也只能靠右手完成。久而久之,右手的操作量會特別大 筆者都嘗試過左手用滑鼠,但左手要熟習到像右手一樣靈活,可不是一時三刻可以做到事。 所以筆者就轉而試途在某寶上,尋找一些特制鍵盤,以調整左右手的操作頻率。 (原圖引用自知乎 https://zhuanlan.zhihu.com/p/56901961) 實際是有的,大家只要搜尋【全反】或【半反】鍵盤,就可以找到左右互換的鍵盤。大家也可以搜尋【方向鍵】或【九宮格】自定義鍵盤。 大家想省心,可以購【全反】鍵盤,不過選擇並不多,就只有一家可以選擇;【九宮格】自定義鍵盤比較多廠牌,也比較便宜,可以一試。 但對於想極度減輕手部移動的筆者來說,這樣並不足夠。因為換了左右,只代表可以減少右手的操作量,但並不會讓那些原有的操作變得更便利。 所以最後,筆者還是要掏出最後武器,AutoHotkey,自行開發軟件,重新定義組合鍵。 這樣做不但可以平衝左右手的操作量,也同時減少手部移動的距離。(也可以為大家省一點錢,想要更改功能也更為簡單一點) 筆者就在這裏分享自己的AutoHotkey小程序,做個例子,如何簡單把方向鍵重新定義到左手使用。 大家只要安裝AutoHotkey,官方網站 https://www.autohotkey.com/ 並下載筆者的小程序,Github連結 https://github.com/macauyeah/autohotkeyExample.git 就可以像筆者更改方向鍵啦,有需要大家可以自行用記事本更新小程度,重讀程式就可以馬上執行最新結果啦~ Support 如果大家覺得只有四個Key不夠用,進階一點的修改,歡迎訂閱我的Patreon,提出客制化支援需求。