code

2022年1月21日 星期五

Cloud Native - Designing Cloud Native Applications

 General Guides

每個服務商(e.g. Azure / AWS / GCP ...) 都有自己的cloud patterns guide,可以generalize成以下五點:

1. operational excellence - 在設計cloud native app的時候就要考慮維運與開發的因子,透過DevOps的practice來實踐:

a. 所有東西都要自動化 - 減少人為錯誤到最低程度,配合上Infrastructure as Code (IaC),整個環境設定都是程式控制。

b. 所有東西都要監控 - 對如何持續改善有幫助

c. 自動化文件化所有東西 - 透過Swagger這類tool

d. 所有動作都是reversible - 所以IaC是很重要的

e. 設計錯誤時的處理 - gracefully fail

2. 資安 - 目前普遍接受的說法是cloud application比地端要安全,但還是要特別著墨,採用defense-in-depth的approach,在設計架構時就把資安納入考量。以下是一個voting cloud app:


此app採用的defense-in-depth的方向如下(假設使用container + K8s):

 - 採用安全的code repository + CI整合靜態分析code安全性

 - container image: 永遠只加入與expose最低限度需要的東西

- container registry: 使用private registry來存放image,需要有權限控管,以及安全性掃描image例如使用Twistlock

- Pod: container images只能從被許可的registry pull後來,每個pod要有identity才能讓其中的程式存取其他的service,再來要考慮node-node間如何安全的通訊。

- Cluster and orchestrator: cluster要放在內網還是外網,以及要把Kubernetes RBAC enabled。

3. Reliability vs Availability

reliability - application能持續運作,即便存在某些錯誤。所以application要能被設計成即便發生錯誤持續使用之外,還要能恢復正常。

availability - application能被使用在一段持續的時間內,例如多個redundant instances or replicas。


4. Scalability and cost

1. 如果不自動決定何時該scale up,則需要在一開始就支付某個規模程度的cluster of nodes,則不是很cost-effective,因為多數時間可能都資源遠大於需求

2. 如果採取自動scale up當資源不足時,則會被啟動new node (VM)的速度遠慢於啟動container的速度所困擾,這需要考慮進去。可以考慮Container as a Service (CaaS)包含Azure Kubernetes Service virtual node,或是AWS Fargate。


Cloud Native vs 傳統架構

差異包括:

1. state處理 - state包含session / application configuration等,傳統架構通常是stateful的,通常暫存放於compute instance variables,所以需要load balancer透過sticky session的方式來確保同一個session都是連到同一個compute instance。


上圖中,LB發現VM0死掉的話,會將user 導向VM1,但是原本的session data將會遺失,造成問題。

而cloud native由於compute instances是動態增減的,所以在設計之初就會朝向stateless的方向去設計,通常session data是被外部化的存放於data store,不隨著compute instance的增減被影響。如下圖:


2. orchestration - 傳統架構通常使用service orchestration service來處理request,而且通常是synchronous等待的:


這樣synchronous waiting當然就有他的問題

cloud native通常採用event-driven pattern來溝通,把一個request分給多個低耦合的服務來執行稱為service choreography,每個service maintain自己的state:


上圖紅色方塊就是event-driven communication component,整個流程就是所謂的service choreography。


Functions vs Services

在設計一個application之初,就會面臨要選擇一個容器化的service,還是要走FaaS?

FaaS雖然比較適合短生命週期跟獨立的tasks,但目前許多FaaS已經成熟到能讓整個application都建立在FaaS上面(e.g. Azure Durable Functions or AWS Step Functions)。FaaS比較大的限制是執行時間timeout短(不能執行長時間運算的東西)

FaaS適合以下scenarios: 平行化獨立事件 / 排程 / map-reduce / message routing。

使用FaaS也有以下要考慮的問題:

1. 一個monolithic切分成小function的複雜度

2. 有限的執行生命週期

3. 目前尚無(人)法用特異化的硬體,例如GPU

4. 由於每個function沒有state,所以所有計算都要pass in data,並且pass out data,會有較多節點的溝通,形成網路上的延遲

5. local開發不一定能成立,因為FaaS不一定有local開發環境

6. FaaS不一定比較便宜,因為節省了compute instance cost,但是又加入了networking / storage / eventing等supporting services費用。


容器化的服務沒有以上的問題,所以可以混合使用services + FaaS來達成彈性。之前提到的voting application可以在某些component使用FaaS:



這個FaaS component只負責將event發生時的某些條件,變成data放入data store,非常方便去scale up。但是要注意FaaS scales up的時候,瓶頸會發生在與他對接的系統中,例如圖中的data store,所以好的practice是data store也採用managed services (e.g. AWS RDBMS)。

此外,你應該要知道自己的application scale的特性,例如container image大的話,根本就來不及在高峰期scale up,或是你的container雖然冷啟動很快,但是她依賴的相關的service要scale up的冷啟動時間很長,也會使得高峰期(busrt scenarios)的scale up失敗。


2022年1月20日 星期四

Cloud Native - Microservices

 Microservices Architecture

1. application被拆分成低耦合的多個小服務
2. 根據business / functionality 來區分服務範圍
3. 由不同的獨立team維運開發
4. services彼此間跑不同process,透過API溝通

monolithic arch 是微服務的對立面,有以下特徵:

1. single code base
2. shared data store / data structure

 


優點

1. 敏捷度 - 由於每個更動都侷限在某個小code base,部署/測試/開發 速度都變快
2. 持續創新 - ? 我覺得還好
3. evolutionary design - 由於影響範圍小,可以快速做技術更新
4. 小而美的team
5. 侷限性錯誤
6. 每個service可以有不同的scaling

挑戰

1. 複雜度提高 - 分散式系統的所有問題都會出現
2. data 完整度與consistency - 因為data store也是分散式的,所以也是會遇到分散式系統的問題
3. 效能 - API calls會增加networking overhead,需要使用某些design patterns
4. 服務版控 - 每個微服務都有自己的版本,在跟其他服務整合時,版本控管複雜度增加
5. logging/monitoring複雜度增加
6. service discovery - 所有component都是API溝通的微服務,需要好的方法來找到彼此


 



2022年1月12日 星期三

Cloud Native - Serverless Computing & Functions & Application Modernization

Serverless Computing 

Serverless computing意思就是讓programmer不用去理會底層所有的資源分配以及infrastructure,讓程式執行去啟動cloud provider自動做資源分配,把所有資源管理的工作都對programmer隱藏起來。

有提供serverless container包括:
1. Azure Container Instances
2. Azure SF Mesh
3. AWS Fargate
4. GCP Serverless Containers on Cloud Functions


Functions

Functions as a service (FaaS)包括:
1. AWS Lambda
2. Azure Functions
3. Google Cloud Functions

優點:快速啟動與快速執行(?),當然最大優點就是此服務的結構很簡單,通常是由其他event驅動,甚至執行結果也會驅動其他functions。當多個FaaS組成一個龐大的複雜服務時候,需要adopt某些design pattern來協作。

考量:
1. vendor lock-in,通常實作會跟FaaS平台綁定,變成不太portable
2. 當你想要跑在on-premise facility: 可以採用open source FaaS runtime,例如 Kubless / OpenFaaS, Serverless / Apache Open Whisk,甚至Azure Functions也已經open sourced。
安裝這些open source platform之後可以利用Kubernetes來資源管理。


From VMs to Cloud Native

怎麼從傳統VM走向Functions?
1. brownfield scenarios: lift-and-shift (負載平移) 透過application modernization以及optimization方法使之轉變
2. greenfield scenarios: 從頭開始創建一個cloud native application

透過lift-and-shift方式將現有的application搬移至IaaS,可立即享受cloud好處,但是管理的問題仍然很多(scaling / dependencies /.. )。如果搬遷到PaaS上,減少了底層管理事務,但受限於Paas架構於VM技術上,仍然會有之前提到的VM的(相對於Container) 一些問題。


Application Modernization

monolithic application透過container轉變成modern application,通常是採用微服務的架構,以及一些patterns (Strangler / Anticorruption Layer) 可以解決以下monolithic application的問題:
1. deployment is faster
2. 某些components會要更高的更新頻率,所以個別微服務的container可以節省很多啟動部署的時間
3. 某些components需要更大的scaling requirements,這跟2. 是類似優點
4. 某些components應該要用不同的技術發展,對monolithic application來說,單一的tech stack runtime較適合多人共同開發,但是如果可以切割成不同的小components,則各自可以有不同的tech stack,因為dependency不會是個麻煩
5. code base太大:monolithic的問題在於一個application share same code base,微服務則每個服務有自己的code base (12 app rules)

Orcehstration變成很重要,事實上Kubernetes 可以看作是cloud OS,所以目前主流的cloud vendors甚至提供了 Orchestrators as a Service,也就是將Kubernetes的管理部分變成一個managed service,不過開發者還是得懂Kubernetes如何維護運作,才能使用這類服務。

Application Optimization

application-level optimization也是必要的,找出適合function這種獨立回應的事件處理,例如CRUD operations (Create Read Update Delete),甚至可以整個application都建築在這些基本的function上面。




Cloud Native Fundamentals - Kubernetes

 Containers

containers算是application modernization的工具,是一種將OS資源slice成獨立的運算unit的工具 (OS virtualization)。好處:
1. 輕量化:可以快速部署啟動,因為採用copy-on-write來分享資源給多個containers,所以在磁碟空間和記憶體使用上非常輕量。
2. 確定性部署:因為所有的dependencies都被獨立打包了都被獨立打包了,所以部署時不會有什麼意外。

一個host可以跑多個VM,而每個VM上可以run多個container instances


比VM這種hardware virtualization來說,containers是比較佔優勢的,但是當考慮其他因素(例如資安),還是會使用VM方式來當作virtualization,不過也有類似Google Visor這種microVM,改善量體與啟動速度。

Container Orchestration

要掌管container的生命週期,需要一個orchestration管理工具,主要任務:
1. 開通與部署(provisioning / deployment)到cluster nodes上
2. 資源管管理
3. 監控
4. scaling
5. containers之間的load balancing

Kubernetes

代表性的工具就是Kubernetes(k8s),可以視為container平台 / 微服務平台 / 雲端portability layer。一個K8s cluster有以下components:
1. master components: 管理各個nodes的master nodes
2. worker node components: 負責維持部署的noe上的環境管理
3. addons: 其他支援性服務



Kubernetes提供CRI (container runtime interface) 讓支援K8s的container runtime實作。

Cloud Native - Introduction to Cloud Native

 Cloud native application 核心就是 distributed systems


有著以下特性:

1. 網路不可信任
2. 高延遲
3. 高頻寬需求
4. 網路不安全
5. 網路topology並非固定,隨時可能有新的node加入或移出,規格也可能改變
6. 無單一管理者,因為是分散式的資源
7. 資料傳輸需要費用,通常是外送資料(egress)會需要費用
8. 網路協定可能是非homogeneous
9. 通常只能在CAP (consistency / availability / tolerance)顧及其中兩項



12-factor app

cloud native application需要增加機器數目而非提高規格去達成scaling, 所以也要有不同的開發方式,有以下12因素:

1. 每個服務使用單一code base去佈建在不同用途的環境,例如production / testing
2. 利用containers (e.g. Docker) 或是dependency managers (e.g. Maven) 來管理dependency
3. configuration只存在於環境中,不可寫入source code
4. 第三方service也需要寫入configuration來達到降低耦合度
5. apply CI/CD practices
6. stateless processes,所以data會外存於service本身
7. data isolation,每個service自己管理data,外部程式只能透過API來存取
8. scale out
9. fast startup & gracefully crash
10. 讓各種環境 (dev / staging / production)盡量一致
11. log很重要,將之以data stream方式導向服務之外的儲存
12. admin tasks是short-lived processes (? 什麼意思)