Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
設定預設的 Zone 並啟用 Compute Engine API。
gcloud config set compute/zone us-central1-f gcloud services enable compute.googleapis.com
內容目錄
用來存放程式碼與起始指令 (startup scripts)。其中 $DEVSHELL_PROJECT_ID
是 Cloud Shell 中的環境變數,用來確保有唯一的名稱。
gsutil mb gs://fancy-store-$DEVSHELL_PROJECT_ID
git clone https://github.com/googlecodelabs/monolith-to-microservices.git ## 安裝服務 cd ~/monolith-to-microservices ./setup.sh ## 開啟 npm 專案 cd microservices npm start
開啟完專案後,可以在 Cloud Shell 的面板點擊 Web Preview 進行預覽。
此時 Products 跟 Orders 都會顯示 An error has occurred, please try reloading the page. 的錯誤訊息,因為這兩項功能還沒公開。
點擊 Cloud Shell 的 Open Editor,如果瀏覽器不支援第三方 Cookies 的話,系統會請你開啟新的頁面,點擊 Open in a new window。
前往 monolith-to-microservices 路徑,點擊 [File] > [New File] 建立 startup-script.sh
檔案,貼上下列指令後,將 [DEVSHELL_PROJECT_ID] 改成你的 Devshell Project ID (可以用 echo $DEVSHELL_PROJECT_ID
查詢):
#!/bin/bash # Install logging monitor. The monitor will automatically pick up logs sent to # syslog. curl -s "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh" | bash service google-fluentd restart & # Install dependencies from apt apt-get update apt-get install -yq ca-certificates git build-essential supervisor psmisc # Install nodejs mkdir /opt/nodejs curl https://nodejs.org/dist/v8.12.0/node-v8.12.0-linux-x64.tar.gz | tar xvzf - -C /opt/nodejs --strip-components=1 ln -s /opt/nodejs/bin/node /usr/bin/node ln -s /opt/nodejs/bin/npm /usr/bin/npm # Get the application source code from the Google Cloud Storage bucket. mkdir /fancy-store gsutil -m cp -r gs://fancy-store-[DEVSHELL_PROJECT_ID]/monolith-to-microservices/microservices/* /fancy-store/ # Install app dependencies. cd /fancy-store/ npm install # Create a nodeapp user. The application will run as this user. useradd -m -d /home/nodeapp nodeapp chown -R nodeapp:nodeapp /opt/app # Configure supervisor to run the node app. cat >/etc/supervisor/conf.d/node-app.conf << EOF [program:nodeapp] directory=/fancy-store command=npm start autostart=true autorestart=true user=nodeapp environment=HOME="/home/nodeapp",USER="nodeapp",NODE_ENV="production" stdout_logfile=syslog stderr_logfile=syslog EOF supervisorctl reread supervisorctl update
儲存並關閉檔案。
上述指令碼執行的工作:
stdout
與 stderr
傳送至 syslog 中。利用 gsutil cp
將指令碼複製到貯體 (bucket) 中。
gsutil cp ~/monolith-to-microservices/startup-script.sh \ gs://fancy-store-$DEVSHELL_PROJECT_ID
將其他程式碼也複製到貯體中。這個步驟會先將 node_modules 中的內容刪除,確保上傳效率。
cd ~ rm -rf monolith-to-microservices/*/node_modules gsutil -m cp -r monolith-to-microservices gs://fancy-store-$DEVSHELL_PROJECT_ID/
在此案例中,後端實體的目的用來支援 Products 和 Orders。
實際運作中會建議將 Products 與 Orders 再分開成獨立的實體,但範例中先放一起。
建立 backend 實體,並執行貯體中的起始指令。
gcloud compute instances create backend \ --machine-type=n1-standard-1 \ --tags=backend \ --metadata=startup-script-url=https://storage.googleapis.com/fancy-store-$DEVSHELL_PROJECT_ID/startup-script.sh
檢查目前有的實體。
gcloud compute instances list ## 結果 NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS backend us-central1-f n1-standard-1 10.128.0.2 xxx.xxx.xxx.xx RUNNING
複製 EXTERNAL_IP,到 Cloud Shell Explorer (Open Editor 開啟的視窗) 中前往 monolith-to-microservices > react-app 路徑。點選選單中的 View > Toggle Hidden Files 檢視隱藏檔案。
編輯 .env
檔,用 EXTERNAL_IP 取代 localhost。
REACT_APP_ORDERS_URL=http://EXTERNAL_IP:8081/api/orders REACT_APP_PRODUCTS_URL=http://EXTERNAL_IP:8082/api/products
接著重新建立一次 NPM 專案。
cd ~/monolith-to-microservices/react-app npm install && npm run-script build
接著再將原始碼複製到 Cloud Storage 的貯體中。
cd ~ rm -rf monolith-to-microservices/*/node_modules gsutil -m cp -r monolith-to-microservices gs://fancy-store-$DEVSHELL_PROJECT_ID/
這裡建立 frontend
的標籤,主要目的是設定防火牆規則用。
gcloud compute instances create frontend \ --machine-type=n1-standard-1 \ --tags=frontend \ --metadata=startup-script-url=https://storage.googleapis.com/fancy-store-$DEVSHELL_PROJECT_ID/startup-script.sh
建立前端與後端的防火牆規則。
gcloud compute firewall-rules create fw-fe \ --allow tcp:8080 \ --target-tags=frontend gcloud compute firewall-rules create fw-be \ --allow tcp:8081-8082 \ --target-tags=backend
此時應該已經可以正常存取網站了。用 watch
指令來監看狀態。
watch -n 2 curl http://[FRONTEND_ADDRESS]:8080
此時再透過 frontend
的 EXTERNAL_IP 存取,就能夠看到功能完整的應用程式了。
接下來要透過前面建立的 frontend 與 backend 實體,建立實體範本。首先,先停止這兩個實體的服務。
gcloud compute instances stop frontend gcloud compute instances stop backend
利用 gcloud compute instance-templates
指令建立實體範本。藉由 --source-instance
選項指定作為範本的實體。
gcloud compute instance-templates create fancy-fe \ --source-instance=frontend gcloud compute instance-templates create fancy-be \ --source-instance=backend # 檢視範本清單 gcloud compute instance-templates list
刪除原本的 backend 實體,釋放一些資源。
gcloud compute instances delete backend
gcloud compute instance-groups managed create fancy-fe-mig \ --base-instance-name fancy-fe \ --size 2 \ --template fancy-fe gcloud compute instance-groups managed create fancy-be-mig \ --base-instance-name fancy-be \ --size 2 \ --template fancy-be
base-instance-name
的選項是在命名實體名稱時使用,實體名稱就會是 base-instance-name + 隨機字串。
設定存取服務的連接埠,前端是 8080,後端 Orders 是 8081 與 Products 的 8082。使用 --named-ports
的選項是為了後續做負載平衡用。
gcloud compute instance-groups set-named-ports fancy-fe-mig \ --named-ports frontend:8080 gcloud compute instance-groups set-named-ports fancy-be-mig \ --named-ports orders:8081,products:8082
如果連續遇到三次 Unhealthy 時,將啟動自動修復。
gcloud compute health-checks create http fancy-fe-hc \ --port 8080 \ --check-interval 30s \ --healthy-threshold 1 \ --timeout 10s \ --unhealthy-threshold 3 gcloud compute health-checks create http fancy-be-hc \ --port 8081 \ --request-path=/api/orders \ --check-interval 30s \ --healthy-threshold 1 \ --timeout 10s \ --unhealthy-threshold 3
接著要設定防火牆規則,允許 Health Check 進行檢查。
gcloud compute firewall-rules create allow-health-check \ --allow tcp:8080-8081 \ --source-ranges 130.211.0.0/22,35.191.0.0/16 \ --network default
將 Health Check 檢查套用到實體群組中。
gcloud compute instance-groups managed update fancy-fe-mig \ --health-check fancy-fe-hc \ --initial-delay 300 gcloud compute instance-groups managed update fancy-be-mig \ --health-check fancy-be-hc \ --initial-delay 300
gcloud compute http-health-checks create fancy-fe-frontend-hc \ --request-path / \ --port 8080 gcloud compute http-health-checks create fancy-be-orders-hc \ --request-path /api/orders \ --port 8081 gcloud compute http-health-checks create fancy-be-products-hc \ --request-path /api/products \ --port 8082
GCP 的後端服務是用來定義如何分配負載平衡流量。其組態包含要使用的連接埠、健康狀態檢查、以及逾時設定等。
gcloud compute backend-services create fancy-fe-frontend \ --http-health-checks fancy-fe-frontend-hc \ --port-name frontend \ --global gcloud compute backend-services create fancy-be-orders \ --http-health-checks fancy-be-orders-hc \ --port-name orders \ --global gcloud compute backend-services create fancy-be-products \ --http-health-checks fancy-be-products-hc \ --port-name products \ --global
gcloud compute backend-services add-backend fancy-fe-frontend \ --instance-group fancy-fe-mig \ --instance-group-zone us-central1-f \ --global gcloud compute backend-services add-backend fancy-be-orders \ --instance-group fancy-be-mig \ --instance-group-zone us-central1-f \ --global gcloud compute backend-services add-backend fancy-be-products \ --instance-group fancy-be-mig \ --instance-group-zone us-central1-f \ --global
gcloud compute url-maps create fancy-map \ --default-service fancy-fe-frontend
新增路徑的比對規則到 fancy-map
中。
gcloud compute url-maps add-path-matcher fancy-map \ --default-service fancy-fe-frontend \ --path-matcher-name orders \ --path-rules "/api/orders=fancy-be-orders,/api/products=fancy-be-products"
針對 fancy-map
建立 URL 對應的 Proxy
gcloud compute target-http-proxies create fancy-proxy \ --url-map fancy-map
設定轉址規則
gcloud compute forwarding-rules create fancy-http-rule \ --global \ --target-http-proxy fancy-proxy \ --ports 80
利用 gcloud compute forwarding-rules list --global
檢視負載平衡器的外部 IP。
重新編輯 .env
檔案,將 IP 改為外部 IP。
REACT_APP_ORDERS_URL=http://[LB_IP]/api/orders REACT_APP_PRODUCTS_URL=http://[LB_IP]/api/products
重新建立 NPM 專案,並更新到 Cloud Storage 上。
cd ~/monolith-to-microservices/react-app npm install && npm run-script build cd ~ rm -rf monolith-to-microservices/*/node_modules gsutil -m cp -r monolith-to-microservices gs://fancy-store-$DEVSHELL_PROJECT_ID/
利用 rolling-action
來更新前端的原始碼。
gcloud compute instance-groups managed rolling-action replace fancy-fe-mig \ --max-unavailable 100%
監控前端受控管實體群組 (fancy-fe-mig) 的狀況。
watch -n 2 gcloud compute instance-groups list-instances fancy-fe-mig
監管前端受控管實體群組 (fancy-fe-mig) 後端服務的健康狀況。
watch -n 2 gcloud compute backend-services get-health fancy-fe-frontend --global
等到都顯示 HEALTHY 即代表完成。
前面的步驟建置了靜態的架構,無法根據流量大小調整。因此要設定縮放政策 set-autoscaling
,根據動態情況來縮放實體。
gcloud compute instance-groups managed set-autoscaling \ fancy-fe-mig \ --max-num-replicas 2 \ --target-load-balancing-utilization 0.60 gcloud compute instance-groups managed set-autoscaling \ fancy-be-mig \ --max-num-replicas 2 \ --target-load-balancing-utilization 0.60
上述的指令中,當負載平衡達到 60% 的效能時,會再建立新的實體,當低於 60% 時,便會移除實體。
利用 gcloud compute backend-services update
的方式,更新後端服務的選項設定。加入 --enable-cdn
來啟用 CDN 功能。
gcloud compute backend-services update fancy-fe-frontend \ --enable-cdn --global
已經建立的實體範本 (Instance Template) 不能修改。
如果要修改範本內的設定,需要建立新的範本,並改用新的範本。
利用 set-machine-type
將主機的類型調整為客製化的 4 vCPU + 3840 Mb 的 RAM。
gcloud compute instances set-machine-type frontend --machine-type custom-4-3840
建立新的實體範本。
gcloud compute instance-templates create fancy-fe-new \ --source-instance=frontend \ --source-instance-zone=us-central1-f
利用 rolling-action start-update
將實體更新為新的範本 fancy-fe-new
。
gcloud compute instance-groups managed rolling-action start-update fancy-fe-mig \ --version template=fancy-fe-new
監看實體群組的狀態。
watch -n 2 gcloud compute instance-groups managed list-instances fancy-fe-mig ## 結果 NAME ZONE STATUS HEALTH_STATE ACTION INSTANCE_TEMPLATE VERSION_NAME LAST_ERROR fancy-fe-gzll us-central1-f RUNNING HEALTHY VERIFYING fancy-fe-new fancy-fe-x2xr us-central1-f RUNNING TIMEOUT VERIFYING fancy-fe-new
複製其中一個實體的名稱,並用 describe
來檢查實體的主機類型是否已經變更。
gcloud compute instances describe fancy-fe-x2xr | grep machineTyp # 結果 machineType: https://www.googleapis.com/compute/v1/projects/qwiklabs-gcp-02-d1a7a4979118/zones/us-central1-f/machineTypes/custom-4-3840
Lab 中已經準備 index.js.new
檔案,用這個檔案取代原本的 index.js
檔。
cd ~/monolith-to-microservices/react-app/src/pages/Home mv index.js.new index.js
重新建立 NPM 程式。
cd ~/monolith-to-microservices/react-app npm install && npm run-script build
整理檔案,並上傳至 Cloud Storage 的貯體中。
cd ~ rm -rf monolith-to-microservices/*/node_modules gsutil -m cp -r monolith-to-microservices gs://fancy-store-$DEVSHELL_PROJECT_ID/
利用 rolling-action replace
更新實體內容。
gcloud compute instance-groups managed rolling-action replace fancy-fe-mig \ --max-unavailable=100%
先列出群組中的實體名稱,並建立 SSH 連線。
gcloud compute instance-groups list-instances fancy-fe-mig gcloud compute ssh [INSTANCE_NAME]
關閉 nodeapp
的服務,並結束 SSH 連線。
sudo supervisorctl stop nodeapp; sudo killall node exit
監看 gcloud compute operation
執行修復。
watch -n 2 gcloud compute operations list \ --filter='operationType~compute.instances.repair.*'