隨著 IT 發展的腳步越來越快、雲端應用也不斷的推陳出新、使用者需求一日數變… 等浪潮開始襲向醫院時,傳統的醫療 IT 該如何因應?醫院又該如何跨出 DevOps 的第一步?
文/鄭重男
開發與維運的距離
把開發(Development)和維運(Operations)兩個字組合起來,我們就稱之為「DevOps」,意思是在醫院或企業中,將開發與維運團隊(人)藉由自動化整合、軟體持續發布與修正,縮短兩者之間的距離,以應付快速變動的內外在環境。隨著 IT 發展的腳步越來越快、雲端應用也不斷的推陳出新、使用者需求一日數變… 等浪潮開始襲向醫院時,傳統的醫療 IT 該如何因應?醫院又該如何跨出 DevOps 的第一步?這些都是值得思考的課題。
資料庫是醫院系統的心臟
開始之前,我想先從醫院的心臟談起,關聯式資料庫(RDBMS)是醫院普遍使用的資料庫,儲存患者就醫、電子病歷、各式臨床儀器交換及健康保險等重要資料,說資料庫是醫院賴以維生的心臟無庸置疑,而大部分醫院對核心資料庫的考量,無非以「安全、穩定且可容納醫療大量資料」為優先,因此,多數中大型醫院多半採用 Oracle 或 IBM DB2 等商業型關聯式資料庫作為核心,如圖1所示。
這類商業型資料庫雖有上述安全、穩定及儲存資料量大等優點,但因為體積較為龐大、移動性相對緩慢及需要高度專業人才維護之故,當在實作其他應用系統及談論物聯網(IoT)的時間序列資料(Metrics)、微服務(Micro Services)或邊緣運算(Edge Computing)時,都甚少提及或使用此類大型資料庫,不是因為不好,而是因為「殺雞不用牛刀」。話雖如此,實務上,無論何種應用系統所產出之最終資料,理應還是要儲存到大型資料庫以確保資料安全方為上策。
大致說來,關聯式資料庫仍是市場主流,商業邏輯及開發框架仍多半以此為主,後續筆者將提到的「物件關聯對映」(Object Relational Mapping,ORM)亦是使用關聯式資料庫的資料模型(Model)的開發架構。
如果醫療資訊系統是一個銀河系
如果把醫院的醫療資訊系統視為一個獨自運行的銀河系(Galaxy),如圖2 。就一個中大型的區域醫院來說,系統核心使用的資料庫可能是 Oracle 或是 DB2,銀河系中離核心資料庫最接近的第一個軌道上,運行的是三層式架構(3-tier architecture)開發的醫療資訊系統(醫學中心為自行開發,區域及地區醫院多半委外開發),其主要系統通常包含門診、急診、住院、檢查、檢驗、放射、藥局、臨床檢查及健保申報等系統,就是我們常說的單體式架構(Monolithic Architecture)的醫療資訊系統。
由於第一個軌道上運行的多為醫院的核心系統,在資訊安全及維持系統穩定的情況下,通常不會讓外部系統進入第一層軌道直接操作核心資料庫。因此,醫療資訊系統以外的周邊輔助系統(如:網路掛號系統)或特定儀器廠商既有的醫療應用系統(如:PACS、臨床檢查系統)等,都只會放在最外層軌道上運行。為了讓這些外部系統可以順利與核心系統及資料庫溝通,我們會在第一層軌道上,多放上一顆叫做 Gateway 或 API 的小行星(衛星),以便讓外部系統透過 Gateway 進行資料同步及整合的工作。
正常情況下,醫療資訊系統主要用戶(Client)為醫院之醫護及行政人員,因早期開發環境多半以微軟視窗作業系統為主,因此,用戶只能在微軟作業系統上執行其應用程式,其他作業系統如 Linux 或平板(iOS/Android)想執行醫療資訊系統實屬不易。不過在行動醫療及雲端服務需求與日俱增情況下,醫院也多會利用虛擬主機(VMware)作為跳板或重新開發 APP 及微型網頁服務系統因應。
如圖2右上所示,在原來的醫療系統銀河系之外,隱約可看到以容器技術(Docker)為核心的銀河系也在慢慢成形。當容器技術開始被企業接受、有越來越多人開始思考以此技術重構醫療應用系統時,什麼時候該讓敏捷開發(Agile)與 DevOps 文化在醫院內發酵,並引進容器技術銀河系進入醫院軌道運行,也是大家都想要知道的事。
帶醫院前往 DevOps 軌道的鯨魚(Docker)
假設說醫院或企業想進入 DevOps 需要一張門票,我想那應該非 Docker 莫屬了。我們不多談 Docker 的發展史,有興趣的讀者,不妨去維基百科瞧瞧,我們只需清楚 Docker 能帶給醫院或企業哪些實質的好處,以及為何它是 DevOps 的入門票?
大約四到五年前,當時 Docker 在企業還不盛行,筆者每每與人提起 Docker 時,都會被對方拿來跟虛擬主機做比較,最常聽到聲音都是:「已經有虛擬主機了,為什麼還要用 Docker?」,殊不知那是兩種完全不同性質的應用模式,虛擬主機是將主機硬體及資源虛擬化,映射出一台虛擬的主機,以達硬體利用最大化。而 Docker 做的只是單純將應用程式虛擬化,把各種不同程式語言撰寫的應用系統封裝成 Docker 影像檔(image),使其具備安裝容易、啟動快速(一鍵啟動,就是這麼來的)及高可攜性之特質。
對於某些需在特定作業系統才可執行的應用程式(如:Windows .exe),只能使用虛擬主機來解決其相容性問題,也是一般醫院及企業常見的應用方式。(初期,Docker 容器無法執行 Windows 的應用程式,慢慢的不只微軟,包含 IBM、Oracle、Google、Cisco 等軟體及 IT 巨擘等,也於 2016 年開始成為 Docker 最大的貢獻者(Contributors),同年 6 月,微軟便公開對外宣稱旗下 windows 10 可以原生支援 Docker ),雖說微軟已經宣稱正式支援,但也不是所有版本都可以順利支援,加上 Docker 本來就是 Unix-like 下的產物,所以,若沒有微軟情結,DevOps 的生產環境(Production)仍習慣在 Linux 作業系統上運行居多。
我們也可以把 Docker 當成一顆星球,如(圖3)所示,外圍軌道上可以同時運行不同程式框架開發出來的應用程式,如:筆者使用的 Ruby on Rails 或其他如 PHP、Go、Python、Node.js 及微軟的部分軟體等等。理論上,只要實體主機或虛擬主機的資源足夠,Docker 容器數量可說是沒有上限;但實務上,沒有人會在同一機器上啟動大量的容器,當容器數量大到一定的規模時,多半會改用 Kubernetes 管理。甚至在樹莓派(Raspberry Pi)之類的單板電腦上,也曾有人執行超過一千個容器,由此可見 Docker 之威力及影響力已銳不可擋了。
早期網頁系統開發及建置,通常要按部就班 Step by Step 從主機(虛擬主機)、網頁伺服器(Apache, IIS)、程式語言(PHP, ASP.net)再到資料庫的建立等,都要花上維運工程師不少時間,雖然目前大都可以用虛擬主機母板(Templates)調度降低部分時間,但仍是需要耗費一定的人力及時間來處理生產環境(Production),再加上開發(Development)及測試(Test)環境,就需要更多資源來應付軟體的開發。
面對這樣的環境,醫院使用 Docker 的好處,筆者認為至少有下列幾點:
- 取得成本 = 0,並有豐富的說明文件及社群資源,對資源相對不足的中小型醫院來說或有助益。
- 建置及管理成本較低,只佔用極少的硬體資源,無論複雜指令集(x86)架構或是精簡指令集(Arm)架構的單板電腦、桌機、筆電、虛擬主機、超融合到大型主機,甚至雲端服務主機等都可輕易運行,且支援大多數的作業系統,如:Windows、Linux、macOS 或 Unix-like 等。
- 一鍵啟動,扣掉第一次啟動需下載影像檔(images)的時間,服務啟動可說是以「秒級」計算,幾乎是瞬間就啟動完成的。
- 版本可控,發布及退版速度快,若新發布的版次存在無法修復的錯誤,可立刻退回前一個正常發布的版次,降低系統停止運作時間(Downtime)。
[ 推薦下載: 2022年度CIO大調查報告PDF ]
Docker 雖有上述優點,導入時仍有些問題需考量:
- 沒有對應的醫療資訊系統可以在 Docker 執行,一般來說都要重新開發。
- 系統安全問題。Docker 容器得以快速啟動,主要的原因是把可獨立執行的環境及應用程式封裝(build)在一個影像檔(image)中,如果你使用了來路不明或內含有惡意程式的影像檔,那就是上演「木馬屠城記」了。所以,一個有經驗的開發者,最終都會自行封裝(build)影像檔,以確保容器內的系統服務沒有問題。
- 沒有協作開發的習慣,開發與維運者分離。傳統醫院系統開發模式,通常是一個人包辦一個或多個子系統,雖然用相同的程式語言,一個醫療資訊系統中,門診系統跟住院系統的操作、邏輯、撰寫風格及資料庫欄位命名原則,都可能因人而異,千奇百怪,甚至令人驚訝不斷,一旦年代久遠,找不到原開發者,就只有又進入「打掉重練的無限輪迴」一途了。在以 Docker 為始的 DevOps 中,建立團隊協作文化及開發風格是非常重要的事。
工欲善其事,必先利其器
這是一句老掉牙的古諺,卻是亙古不變的智慧結晶。在我們的工作及生活中,隨時都在遭遇各式的問題,我們會依自己能力所及的知識與技能,用不同的方法來處理,有人愛用傳統的人工作業,有人喜歡創新及高效的解決方式。由於筆者傾向喜歡後者的解決方式,因此,找到合適組織或自己的框架及工具,便是一門重要的課題,唯有經由不斷學習新技能、嘗試錯誤、迭代修正,最終才得以融合成為自己的本能利器,而達「善其事」之效。
為何工具很重要?舉個簡單的例子來說:「有一個人需要獨自從高雄到台北,他有三種工具可以使用,一是萬能的雙腳、二是加滿足夠油料的汽車、三是有飛行許可的直昇機。」如果是你,你的選擇是什麼?
你可能想:「再笨的人都知道要選直昇機吧!」,但是,你會開直昇機嗎?
我們來看看這三個工具:
- 「走路」是最慢的,但是不用學習,人生落地後第一件事就是學會走路。
- 「開車」是比較快的,需要學會開車並持有汽車駕駛執照。
- 「開直昇機」想當然耳是最快的,但是並不是人人都可以有飛行技術及飛行執照。
三種不同的交通工具,學習曲線不同,達到目的的效率也截然不同。因此,當我們回頭來看「DevOps」時,要先有一個觀念,它絕對不是真的「三兩天」就可以達成的!當你聽到有人在三天內完成「住院核酸陽性病人即時動態看板」時,不要真的以為開發者只花了三天就做出來,而是先前不斷學習及重構所累積能量的自然釋放。
DevOps 工具
一個好的廚師身上一定有一組習慣的刀具,不在於刀具價格的多寡,而在於是否上手。 相同的,一個好的系統開發者一定也會有自己習慣的開發工具及框架,沒有好壞,就是用起來會讓自己快樂而已。
DevOps 不是新名詞,經常會與數位轉型(Digital Transformation)相提並論,熱度與人工智慧(AI)也不相上下,如前面所述,開發工作想要「事半功倍」就要找到高效的工具組合,筆者就自己使用及常見的工具組合稍作說明。
DevOps 用數學無限符號(Infinity Symbol)表示(圖5),意思是說,一旦開始了就停不下來了?
規劃工具(Plan)
● 最簡單的工具是「人 + 紙 + 便利貼 + 筆」,也是敏捷開發(Scrum)常見的手法之一。
● 使用者故事(User Stroy)的撰寫是一個非常重要的概念,透過簡短的「身為○○角色,我想要○○功能,就可得到○○好處」,讓需求者與開發者的想法在迭代(Iteration)及重構(Refactoring)的過程中保持一致。
● 其他輔助工具,如:雲端流程圖繪製工具(Drawio),可協助開發團隊聚焦開發流程及資料關聯模型的繪製。
開發工具(Code)
● Vscode 是由微軟公司提供可以免費使用的文字編輯軟體,在眾多編輯器中,使用者有越來越多的趨勢,加上可以自行安裝其他整合的應用套件,是一個值得學習的工具。
● Git 版本控制專家,除了知名的雲端服務 Github 外,若不想將開發好的程式碼存放在雲端儲存庫(Repository),就可以使用前述的 Docker 把 Gitlab 或 Gitea 之類的服務在醫院中落地。
● Ruby on Rails 是筆者近年來使用的開發框架,有著優雅著稱的 Ruby 語言,及不重複做自己(Don’t Repeat Yourself,DRY)和以程式設計師的快樂為優先之基本主義的 Rails,是一個敏捷開發(Agile)及全端(Fullstack)的網頁開發框架。
封裝工具(Build)
● Electron 用戶端應用程式的封裝工具,可將開發出來的網頁服務進行封裝,讓使用者可以在不同平台的電腦執行,而不需要使用任何瀏覽器。目前可以封裝的程式包含 Windows、Linux 及 macOS 的應用程式。
● Gitlab 跟 Github 相似,提供存放程式碼及版本控制的儲存庫,此外還提供 CI/CD 自動封裝 Docker image、自動測試及自動發布的工具,也是 DevOps 必備工具。
● Docker 在前面文章已經提過,主要提供 Docker 運作環境及封裝應用程式影像檔(image)。
測試工具(Test)
● Rails 有一套內建的測試機制,開發過程中除了會自動產出測試程式外,亦可隨時做單元或系統測試,並以 Capybara 、Selenium 及 webdrivers 這幾個 Gem(Ruby 語言撰寫的程式庫)來做前端擬真(模擬真人)測試,遇有錯誤時,會自動擷取錯誤畫面,以便於修正。當然,如果想用「測試驅動開發(Test-Driven Development,TDD)」的模式來進行系統開發,也是完全沒問題的。
釋出(Release)及發布(Deploy)工具
● Docker Registry 也是可以用 Docker 在醫院「本地端」運行的 Docker images 儲存庫,主要目的是在為 Gitlab Auto DevOps(CI/CD)所產生的影像檔提供一個本地安全的存放空間,如此一來,就可避免將已開發的應用程式(images)推到(push)雲端的 Dockerhub ,以減少一些非必要的風險。
維運工具(Operate)
● Kubernetes 可說是 DevOps 的終極目標,當醫院的 Docker 應用程式已經多到連 Docker-compose 都難以應付時,你就必須找到更有效率的工具來管理你的鯨魚群(Docker),一方面也可以讓你的自動化程序及系統穩定度達到一個最佳狀態,但如同前面所述,越高效工具越難學習,需要用到的時候非得會不可!
● 作業系統及資料庫 DevOps 中比較常用的主機還是以 Linux based(Ubuntu)為大宗,筆者目前用 Rails 開發的資料庫是以 Postgresql 為主,醫院的資料庫則是 Oracle。
● Redis 是從記憶體保留部分空間,做為鍵值(key: value)的暫存區,以增加系統的執行效率,目前幾乎已成為系統開發的標準模式了。在 Rails 中,也會使用 Redis 來處理工作排程(jobs)及佇列(queue),並依照優先等級自動安排執行的順序,以改善使用者的操作體驗。
監控工具(Monitor)
● Grafana 是一套開放原始碼的視覺化監控(Monitoring)軟體,可運用在非常多地方,在醫院中也可以將資料庫中的臨床、住院病人、門急診就醫資料,甚至健保總額等營運資料,轉換為時間序列型態的資料,藉由 Grafana 提供的介面,就可輕易拉出動態的數位看板(Dashboard)。 在 DevOps 裡,它則扮演蒐集系統主機資源耗用及使用量的動態顯示,一旦系統發生異常時,便可即時發出告警或透過機制自動調整系統資源以達系統穩定及服務不中斷的目標。
單體式(Monolith)醫療資訊系統的重構
每家醫院的醫療資訊系統,都有其發展的背景與歷史,有的因為自身需求改變,也有因為大環境的變遷,更有些是健保政策或法規的變動,不管什麼原因,長久下來,或多或少都累積了相當數目的技術債,如果沒有定期審視重構及更新最新狀態(Latest),到最後只有不斷更換更高檔的硬體資源或主機來還債了。我們常說醫療資訊系統是一個動不了的單體應用程式(Monolithic applications),或者說怪獸(Monster),因為幾乎沒有一個人完全了解該系統的全貌,因此,就有以微服務重新開發醫療資訊系統的聲音出現,其最終目的也是想解決此一問題。
[ 加入 CIO Taiwan 官方 LINE 與 Facebook ,與全球CIO同步獲取精華見解 ]
就筆者的看法,單體式的醫療資訊系統經過這麼多年的縫縫補補,要應付快速變動的需求,確實已顯得捉襟見肘及不堪負荷,但,若說要完全以微服務取而代之,也不是一般中小型醫院可輕易負擔的,如果 DevOps 可以在醫院端普及,降低進入門檻,藉由重構去除系統中的壞味道(Bad smell),並以使用者需求為導向,依需求抽出部分商業邏輯,以微服務或筆者所述衛星、城堡(Citadel)概念來實作,吸引更多醫院開發人員利用 Docker 封裝應用系統及共享,對未來醫療資訊發展或資源缺乏的中小型醫院,或可提供一劑良方也說不定。
本文專欄作者鄭重男,目前任職於國軍高雄總醫院資訊及健保總額管理部門,經歷地區、區域兩種不同層級醫院近 20 年,看到醫療 IT 的迭代及健保法規與總額管理的快速變動,深刻體會到醫療資訊人員和醫護人員一樣需要持續學習,也知道這些層級醫療院所相對於醫學中心,自行開發的能量及資訊人才都極為匱乏。約莫四年前,腦海一直出現一個念頭,心想:「如果可以快速寫出解決醫院痛點的自動化程式,哪怕是一個很簡單的服務,都一定是件快樂的事」。但開發從「零」開始談何容易?某天,無意間「一鍵啟動」了一個叫做「Redmine」的專案管理軟體,才發現,原來除了一般熟知的微軟(Windows, IIS, MS-SQL, ASP, .Net, C#...)及 LAMP(Linux, Apache, MySQL, PHP)開發架構外,還有一個叫 Ruby on Rails(一般通稱 Rails)的網頁開發框架(實際上,網頁發框架多到學不完),很訝異這個釋出超過 15 年的專案,仍然持續在更新維護且沒有任何落隊的跡象。更令人好奇的是,為什麼看似複雜的系統卻可以「一鍵啟動」?於是這便開啟了 Rails 學習及醫院系統轉型之路。
筆者自以為是:
● 開放原始碼的狂熱份子,喜歡分享及解決痛點。
● 想以程式設計師及醫護人員的快樂為優先。
● 想當醫院的 Ruby on Rails & DevOps 傳教士。
● 想找到第一位 Rails Doctor。
【Rails doctor 想法源自於 [Rails girls]其目標是為女性提供工具和社群,讓她們了解技術並構建她們的想法】
(本文授權非營利轉載,請註明出處:CIO Taiwan)