建置與維運GCP資料處理的Infrastructure
這一篇我們會介紹GCP託管的資料處理(運算資料)的服務,例如App engine, Cloud Functions, Dataflow. 如何使用GCP的監控機制Stackdriver(metrics/logging/trace)來監控整個資料處理的infrastructure效能。
啟用與調整 Processing Resources
GCP有多種的processing resource. 這一篇我們將它們分成兩個種類,分別是server-based and serverless resource. Server-based resource 基本上就是你需要指定要使用的VM或是cluster; serverless resources則是不用管這些底層的資源管理,但還是需要設定configuration.
GCP的Server-based有以下服務
- Compute engine(VM)
- Kubernetes engine
- Cloud Bigtable
- Cloud Dataproc
- Cloud Dataflow
Compute engine可以是單獨的VM或是instance group. 其他的服務基本上就是用VM來組成一個cluster, 每個VM在cluster擔任著不同的role.
GCP的serverless 的服務如下
- App engine
- Cloud Function
雖然在serverless這邊在一開始設定時我們還是需要指定machine type或是cluster configuration, 但我們可以設定一些參數來調整這些服務所需要的資源來因應不同的使用狀況。
啟用與調整 Compute engine
Compute engine可以使用單一instance 或是一群instance(instance groups).Instance groups可以是託管式或非託管的。 Managed instance groups(MIGs)是包含著一群完全相同設定的VM; 非託管式的insatcne groups怎允許有著不同設定的VM, 但除非有特殊需求我們應該盡量的使用託管式VM。因為這一些在託管式方式產生出來的VM都是透過一個instance template所產生的。
提供單一的 VM instances
compute engine的基本單位就是Virtual machine. 我們可以使用console/command-line SDK/REST API來產生,但不論用哪種方式我們都要只指定機器一些參數,這些參數包含以下
- Machine type, 像要多少的vCPU / memory
- VM要跑在哪一個region哪一個zone
- Boot disk 參數
- 網路設定
- Disk image
- VM的service account
- Metadata and tags
此外我們還可以加上一些額外功能,像是Shielded VMs(security 功能)或是加GPU or TPU(tensor processing units).當VM關機時你可以對其做硬體規格的調整。
啟用Managed instance Groups
這邊我們所需要管理的是單一個logical resource, MIGs有著以下好用的properties:
- 根據特定的application的health check來執行autoscaling來更換無反應instance
- 可跨多個zone, 以免有zone-level failure危及服務的availability
- Load balancing 工作負載到這個group中所有的instance
- Autoscaling功能會根據現行的工作負載量來增加或減少instance的數量
- group裡的instance 會自動的用incremental update的方式來減少服務的中斷
在MIGs裡定義這些VM instance的參數稱為instance template(檔案型式)。這個template可以用gcloud的方式產生出來,例如我們要用gcloud產生一個machine type是 n1-standard-4, OS是Debian 9,250G boot disk
gcloud compute instance-template create jason-template \
— machine-type n1-standard-4 \
— image-family debain-9 \
— image-project jason \
— boot-disk-size 250GB
而當我們要用這個template來產生VM時的command 如下
gcloud compute instances create jason-vm — source-instance-template=jason-template
當然以上的作業也都可以在GCP的console中完成。
當我們在create instance group時要明定是要綁定哪一個 instance template,同時指定當CPU的使用率達到了某個程度後就會自動的加instance進去。然後也可定義instance 的數量最多能有幾個,當然也可以定義最小數量。為了避免insatnce 的數量的變化頻率太高我們也可以調整cooldown 的週期時間,cooldown period是讓GCP有時間去收集效能資料。這是因為從機器開機到完全ready能開始服務是需要時間的,在開始服務之後再來計算工作負載後效能資料才比較準確。
調整compute engine resource達到剛好的需求
該用sigle VM還是instance group則取決於需求,像是開發或測試環境啟用單一的VM就不會有浪費資源的狀況。而若是production環境則必須考慮到HA還有工作負載,這時選instance group是比較合理的做法。
instance group其中一個好處是當工作負載變大時它可以有autoscaling的功能。而instance group的autoscaling是屬於scale out(horizontal scaling)的方式。當然也有另一種的scaling方式: scale up(vertical scaling),不過這通常需要機器停機。而就要將Application or Services移動到其他VM上。
啟用與調整 Kubernetes engine(GKE)
GEK是一個託管式服務。GKE工作負載越大container的數量就越多,與VM不一樣的是它的overhead是小於VM的並且它對resource控制的精細度是優於VM的。
Kubernetes(K8s) 架構概觀
k8s cluster有兩種的instance type: cluster masters and nodes. Cluster master運行的控制整個k8s cluster的核心服務: controller manager, API server, scheduler, 與etcd。 Controller manager運作的是管理k8s abstract components的服務,像是deployments and replica sets. Application運行在k8s時是使用API server來呼叫master。 Scheduler是負責決定Pod要跑在哪裡。etcd則是分散式key-value的資料庫,是儲存cluster內的所有狀態資訊。Nodes則是實際處理工作負載;它是用 compute engine 的MIGs來架構底層。
K8s是一種abstractions, 這種方式可以管理到cluster裡的 containers, Applications, storages services, 一些重要的運作components如下
- Pods
- Services
- ReplicaSets
- Deployments
- PersistentVolumes
- StatefulSets
- Ingress
Pods是K8s的最小單位,它可以包含一個或一個以上的container。通常是一個Pod一個Container.但如果有一個以上的container,哪麼這個Pods裡的container關係就是tightly coupled。例如,一個Pods裡的一個container負責資料的extraction, transformation, and load process而另一個container負責資料的解壓縮與資料格式變更。會將多個container放在一個Pods裡的原因只有一個,它們各自的功能是高度相關的而且會有相似的scaling與lifecycle的特徵。
Pods被部屬到nodes是靠scheduler來完成的。它們通常被部署在groups 或replicas中。這可以讓我們的Application/service具有HA,因為Pods的特性是臨時性(ephemeral)的。可能會因為運作不正常或底層機器有問題而會消失,k8s則會監控這些狀況。因為Pods會有多個replica,所以即使其中一兩個Pods有問題後就被消除掉也不會中斷服務。因為k8s會根據定義好的Pods的數量再長出新的Pods.也因為replica的特性,當工作負載變大時Pods的數量就可以自動增加以應付工作量。
既然Pods的特性是臨時性(ephemeral)的,所以當有新的Pod或有舊的Pod被移除我們就需要一種機制來知道要去探索那些消失那些長出來了。K8s使用 service abstraction來達到這個目的。 Service是一種abstraction伴隨著穩定API endpoint與固定的IP. Application 使用service來跟API endpoint溝通。Services會持續追蹤與它關連到的Pods, 所以當有外部呼叫到Service時,它就可以將這個呼叫轉到有正常運作的Pods.
ReplicaSet是一種controllers,它可以控制pod 的replica數量。通常都是附屬在deployment中。而deployment是一種higher-level概念,它通常有管理到ReplicaSets與提供宣告式updates. 每一個Pod在deployment被create是使用相同的template,這個template定義了如何來運行Pods. 這個定義稱為pod specification.
k8s的deployments可以設定你想要多少數量的pod運作。假若實際運作的數量跟你規定的有落差 — 例如因為底層的機器壞了所以上面的Pod也消失了,ReplicaSet就會自動補上或刪除到你規定的數量。
Pods有時需要使用到persistent storage來儲存運算過後的資料,不過由於Pod的特質是臨時性的(ephemeral),所以比較好的作法還是將Pods與persistent storage分離。在K8s中 PersistentVolumes是提供給Pods做永久性資料儲存的地方。但PersistentVolumes比較像是一個硬碟還沒分割磁區狀態,但Pods真的要用到儲存資料時我們必須再從PersistentVolumes分隔一個邏輯磁碟區PersistentVolimeClaim出來。
Pods的特性從上面的描述來看就是一個stateless的applications, 不過當狀態是被Apppication所管理的話哪麼stateless的特性可能就會讓Application 的功能有問題。所以K8s提供了StatefulSets abstraction使Pods的狀態是stateful並且這個具有statefule的pods會有unique identifier. k8s 使用這些來跟踪哪些client端正在使用哪些 pod 並保持它們配對.
Ingress可以控制external access to service到k8s cluster內部的object。Ingress controller必須是運作在cluster中才能使Ingress 功能是正常運作的。
啟用一個 K8s engine Cluster(GKE)
你可以用GCP的console/ command line / REST API來啟用一個 k8s engine cluster.下圖為一個用console的範例來create 一個GKE cluster
當我們create一個cluster時我們需要只指定 cluster name, 然後這個cluster是要運行在單獨一個zone或是多個zone, 然後GKE的version是多少跟設定node pools. 如果是用command line的方式範例可參考如下
gcloud container clusters create “jason-kao-1” \
— zone “asia-east-1a” — cluster-version “1.13.11-gke.14” \
— machine-type “n1-syandard-1” \
— image-type “COS” \
— disk-type “pd-standard” \
— disk-size “100” \
— num-nodes “5” — enable-autoupgrade — enable-autorepair
用coomand line的方式create cluster使已 gcloud container cluster create的命令列開頭. 上面的command line我們指定了 zone, cluster versions, machine type, disk configuration 與在這個cluster有多少的nodes. 最後的autoupgrade與autorepair則是option.
Node pools是一個VM的集合,這個集合是由MIGs(managed instance group)來管控的。既然是由MIGs來管控的,哪麼裡面所有的VM的規格設定都會是一樣的。如果你沒有指定或命名其他pool,哪default pool就會被使用。create不同pool的好處在於你可以用不同的machine type來運行你要的application, 例如web service可以run在machine type比較小的而Redis cache可以run在比較大台的machine(所以可以create另一個pool).
當有job被submit到 K8s時, scheduler會決定哪一個或哪一些node是有資源可以run這些Pods的。當然你也可以指定那些Pod要run在哪一個node上(若你確定該node資源是足夠的),這在K8s abstraction稱為taints. 通過將tainrs分配給node pool並將taints的tolerance分配給 Pod,我們可以控制 Pod 何時運行。
調整Kubernetes engine resource達到剛好的需求
在K8s中有兩種方式來達成資源調整,一種是scaling application另一個是scaling cluster本身。
Autoscaling Applications
你的Application可以靠著指定有多少個replicas運作,replicas可以根據你workload的需求來增加或減少replicas. 這個可以自動也可以手動,手動調整可以使kubectl這一個command 來調整。這裡樣說明一下,kubectl是用來控制k8s 的component,而我們剛才create k8s cluster的command gcloud container是用來控制 kubernetes engine的。
假設我們要用kubectl來調整replicas,以下為一個示範的範例
kubect scale deployment jason-kao-1 — replicas 8
另外你也可以永久性的調整這個參數。可以到deployment的YAML檔修改並再次部署這一個deployment.
另外我們也可以根據CPU的負載自動稱加Pod, 例如我們定義Pod的數量最少是兩個最大是10個,只要這些Pod的平均使用率高於70就會自動增加直到加到10個Pod為止。
kubectl autoscale deployment jason-kao-1 — min 2 — max 10 — cpu-percent 70
Autoscaling cluster
剛剛我們的autoscaling是在cluster裡面的Application.萬一要是底層的資源不夠呢?也就是底層的VM資源不夠需要加VM呢?
Cluster Autoscaling的設定會是在node pool level中。當你create pool時,你可以指定在這個pool中最小與最大的VM數量。之後autoscaler會根據resource request(注意:不是根據真實使用量)來調整VM的數量。假若是在node pool裡的node數量導致Pod被pending,哪麼node的數量就會自動的增加上去直到達到你規定的數量。若是之後Pod減少了需求沒哪麼多,node的數量也會自動在減低下來。
在GKE的預設中,GKE會假定所有的Pod都可以被restart在其他的node上。架設你的Application沒有辦法應付這一種短暫的中斷,哪麼你這一類的Application就會建議不要使用autoscaling這一種功能。另外若cluster是運行在跨多個zone並且有多個MIGs,autoscaler會嘗試在scaling up時做平衡資源的工作。
底下為一個當我們create 一個cluster時指定autoscaling的參數範例
gcloud conatiner clusters jason-kao-1 \
— zone asia-east1-a \
— node-location asia-east1–a, asia-east1–b, asia-east1–c \
— num-node 2 — enable-autoscaling — min-nodes 1 — max-nodes 6
Kubernetes YAML 設定檔
當然GKE也支援一般Kubernetes會使用到的YAML檔案來部署你的Application,以下為一個使用YAML檔來部署有三個replicas的Nginx server範例
啟用與調整 Cloud Bigtable
Cloud Bigtable 是一種託管式的wide-column NoSQL DB,用於需要high-volume、low-latency random write的Application(例如 IoT Application)和analytic use case(例如存儲用於訓練機器學習的大量資料)models。 Bigtable 有一個 HBase interface,因此它也是在 Hadoop cluster上使用 Hadoop HBase 的一個很好的替代方案。
啟用Bigtable instances
你可以用GCP的console/ command-line SDK/ REST API來啟用 bigtable instance。當啟用bigtable insatnce時我們需要指定instance name(instance ID)/ instance type/ storage type / cluster specification.
這個instance type可以指定為Production or development. Production instance最少需要三個node;而development只要一個node即可但也因為這樣就沒有HA的功能。
Storage type 有兩種, SSD or HDD. 如果需要low-latency I/O就需要選SSD。會選HDD就是你有費用上的考量,但HDD效能就會不太好。
使用command-line來create bigtable的範例可參考如下,這個範例我們會create一個名為 jason-kao-1的 production instance並且底層會有8個node, cluster使用SSD這個cluster位置會在台灣region.
gcloud bigtable instance create jason-kao-1 \
— cluster= jason-kao-1 \
— cluster-zone=asia-east1-a \
— display-name=jason-kao-1 \
— cluster-num-nodes=8 \
— cluster-storage-type=SSD \
— instance-type=PRODUCTION
Bigtable本身有一個command-line工具稱作cbt. 可以用來create 多個bigtable instance, 範例如下
cbt createinstance jason-kao-instance1 jason-kao-instance2 jason-kao-instance3 asia-east1-a 8 SSD
在我們完成create insatnce之後有些參數我們可以事後調整如下的參數
- 每一個cluster的node數量
- Application profiles, 像是replication設定
- Labels, 使用在metadata attributes
- The display name
Replication in Bigtable
當我們使用多個bigtable cluster時,我們可以使用replication(primary-primary configuration with eventual consistency)功能來將資料同時寫到多個clutser中. BigtableZ可以support到4個replicated cluster,所有的cluster可以在不同的zone甚至是不同的region中。但是如果是在不同的region時,你就必需考量到這樣會增加資料的replication latency; 不過這樣卻也能增加當某一個region failure時的HA功能。
雖然會有write latency不過卻同時增加了read 的效能。因為當有大量的資料要寫入某一個cluster時,我們可以read另一個cluster的資料以免所有的loading都在一組cluster上。
Bigtable允許關於data consistency的設定調整。預設上bigtabl的提供的是eventual consistency,意思是資料需要一段時間才能在整個cluster的node中完成同步。但假如你的Application需要讀取到最新的一筆資料,你就需要設定為read-your-writes consistency. 若所有使用這個cluster的user都需要讀取到一致性的資料時,我們就需要設定成為 strong consistency. 這個設定將會把所有的read 導到同一個cluster(這個設定要與read-your-writes consistency一起設定)。但其他的cluster只會被使用在當read的cluster failure時使用到(failover only)。
啟用與調整 Cloud Dataproc
你可以用GCP的console/ command-line SDK/ REST API來啟用 bigtable instance。當啟用 Cloud dataproc resource時,我們需要指定 name/region/zone/cluster mode/machine type/ autoscaling policy.
Cluster mode 會決定 msater node的數量與可能的worker node數量。如果是Standard mode, 哪master node就會只有一個而其他的就會是worker node. Single mode則是只有一個master node而沒有worker node. 而HA mode則會有三個master nodes與一定數量的worker nodes. Master nodes與worker nodes的設定是分開的。這兩種的node都需要指定machine typr/ disk size/ disk type.
以下為一個用command line 來create dataproc cluster的範例
gcloud dataproc create jason-kao-1 \
— region asia-east1 \
— zone asia-east1-b \
— master-machine-type n1-standard-1 \
— master-boot-disk-size 500 \
— num-workers 6 \
— worker-machine-type n1-standard-1
— worker-boot-disk-size 500\
完成create cluster後worker node可以被事後調整(但maste node設定無法再更動了),像是preemptible node的數量。我們也可以用autoscaling policy來自動調整worker nodes的最大數量與scale-up/scale-down rate.
Cloud Dataflow的設定
Cloud dataflow執行的是streaming and batch Application(像是Apache Beam runner). 我們可以指定是pipeline options. 可以設定的參數如下
- Job ID
- Project ID
- Runner, 這是指在執行job的DataflowRunner
- Staging location, code pakche的Cloud storage 路徑
- temporary job file的暫時位置
我們還可以指定在執行pipeline時的使用的workers數量(設定成預設值),架設我們在設定時有多餘的worker可使用,哪workload的實行效能將會好非常多。另外我們如果要run的batch job需儲存大量的資料在workers(VM)裡時,我們可以定義disk size(boot disk)。
Cloud Dataflow是一個全託管的服務,通常我們不需要對它指定machine type這一類的資訊,但如果我們需要再客製化這一類的環境我們是可以指定machine type and worker 的disk type.
配置全託管式 Serverless Processing Services
GCP提拱了好幾種的Serverless服務,基本上你都不需要去做底層機器的配置。然而GCP還是提供了一些彈性可以讓你對這些serverless的底層機器最一些參數調整,底下我們就來介紹一般常用的兩種:
- App Engine
- Cloud Functions
App Engine配置
這是一個PaaS服務。你的Application會運作在這個App engine環境中。你會用到以下三種的configuration來設定你的環境分別是
- app.yaml
- cron.yaml
- dispatch.yaml
有一個與service的每個版本相關聯的 app.yaml 檔案。 通常,我們為service的每個版本創建一個目錄,並將 app.yaml 檔案和其他配置文件保存在那裡。
app.yaml檔案有三個必須的參數: runtime/ handlers / threadsafe. runtime就使指定runtime environment, 例如環境需要是 Python 3。handlers 是一組 URL patterns,用於指定回應調用 URL 時運行的code。
cron.yaml 用於為Appkication配置scheduled tasks。 paramaters包括run task的schedule和run task時要調用的 URL。
dispatch.yaml 用於指定routing rules是根據 URL 將傳入 incoming requests到特定service。
Cloud Function配置
這一個服務只需要將code放上去就可以運作了。基本這是一個event-based的服務。為了要讓你的code可以正常的運作你需要指定以下參數
- memory
- timeout
- region
- max-instance
每一個cloud function task的memory指定範圍可以從128MB到2GB. timeout是指code一旦開始執行運作要在多少時間內完成否則就算逾時,如果逾時哪cloud function就會自動終止掉這個task,預設是一分鐘但最多可以設定到9分鐘。
region是指定要在哪個地理區域執行。max-instances則指任何時間點會存在的cloud function instances數量。
監控Processing Resource
一旦你的Application跟其GCP相關的processing resource開始正常運作,下一步就應該監控這一些resource and application的效能。GCP的監控服務稱為stackdriver. stackdriver是一組監控方案,監控的層面可以從infrastructure到Application. 工具組合有monitoring, logging, and distributed tracing.
Stackdriver Monitoring
這是收集效能測量的指標,包含infrastructure跟Application. stackdriver Monitoring可以收集超過一千個效能指標,例如:
- App Engine 這是關於為Application提供服務的所有 VM 的使用率、current active connections數量和保留cpu core總數的指標。
- Compute Engine Autoscalers 具有與capacity和當前使用率相關的指標。
- BigQuery有關的query counts, execution times, scanned bytes, table count等。
- Cloud bigtable有關的 CPU load, disk load, node count, bytes 使用量, storage capacity
- Cloud function會收集相關的 active instance, execution count, and executiom time.
上面的list可以看到 metrics是關於所有重要特徵的擷取資訊。
stackdriver收集到的資料可以從stackdriver Monitoring dashboard上看到,同時也可以發出alerting.
Stackdriver Logging
這是用來儲存與搜尋log的服務,從infrastructure 到Application layer都可以。Logging預設可以收集150種一般常用的Application log.
stackdriver Monitor收集的是mertics,而Logging收集的是log entries。 log entries是指關於一個event的record. 這些record可能來自於 application, OS, middleware, 或其他的service. 一個log是一群log entries的集合。
Logs在 Stackdriver 中保留一段特定的時間,稱為保留期。 如果要保留更長時間,則需要在保留期結束前export logs。 保留期限因log類型而異。 管理Admin activity logs、system event audit logs和access transparency log會保留 400 天。data access audit logs和其他與audit無關的log保留 30 天。
我們可以使用支援pattern mach和Boolean expressions的查詢語言來搜索logs。 我們可以使用query在 Stackdriver Logging interface create filter,如下圖所示。
你可以把這些log經過你filetr的export出stackdriver . export的目的地(目標/接收器)可以是 Cloud storage, Bigquery, Cloud Pub/Sub做更進一步的分析。將新的log entry寫入log時,會將其與export 的filter進行比較,如果匹配,則將log entry的副本寫入接收器。請注意,由於只有新的log entry會寫入接收器,因此此過程無法export已存在的log entry。
Stackdriver Trace
Stackdriver Trace 是一個分散式追踪系統,主要在收集有關處理request to services所需時間的資料。 當我們使用Microservice架構時,這尤其有用。 Stackdriver Trace 在 Compute Engine、Kubernetes Engine 和 App Engine 中可用。
Stackdriver Trace 有兩個主要component:tracing client和tracing user interface。 tracing client收集資料並將其發送到 GCP。 tracing interface用於查看和分析該追蹤資料。 這個interface提供好幾種資料,包括
- performance insights
- Recent traces and times
- Most of frequent URIs
- Daily analysis report
Trace同時也提供了能讓你看位於trace list interface中所有trace detail的資料。