跳到主要內容

發表文章

目前顯示的是 5月, 2020的文章

GCP Cloud Build 跨專案部署 | Use Cloud Build to deploy service to different project

前言 開發者可以將測試以及部署的腳本定義在 cloudbuild.yaml 的設定檔中, 讓 Cloud Build 照著腳本去執行指令 # Build the module. steps: - name: 'gcr.io/cloud-builders/gcloud' args: [ 'run', 'deploy', 'myapp', '--set-env-vars', 'SERVICE_ENV=stage', '--image', 'gcr.io/build-prj/myapp', '--platform', 'managed', '--region', 'us-central1' ] 但預設 Cloud Build 的服務帳號只擁有當下專案的權限, 若想要做到跨專案部署應用程式的話, 就需要授予 Cloud Build 的服務帳號在另一個專案下的部署權限 本篇文章將會簡單的介紹如何跨專案部署服務 假設我們有兩個 Project, 一個是 Build Project 用來放 Source Code 以及跑 Cloud Build, 另一個是 App Project 用來部署服務 (如下示意圖) 要實作這個機制, 首先 授予部署權限 需要授予在 Build Project (8750547431)下的 Cloud Build 的服務帳號能在 App Project (2498738606)下部署的相關權限 (如下) Service Account User Cloud Run Admin APP_PRJ=app-prj BUILD_PRJ_NUM=8750547431 # Cloud Run Admin: can deploy Cloud Run Service gcloud projects add-iam-policy-binding $APP_PRJ \ --member serviceAccount

如何使用 Cloud Build 來達到自動化測試與佈署| Create a CI/CD Pipeline On Cloud Build

前言 GCP 的 Cloud Build 是個非常好用的 DevOps 工具, 對於使用 Cloud Source Repository 的開發者來說,  不需要繁複的設定,  就能快速的建立 CI/CD Pipeline, 使推送到 Cloud Source Repository 的交付能自動觸發 Cloud Build 的事件執行測試與部署  除此之外無伺服器的平台, 不需要額外管理 CI/CD 的伺服器, 也不避擔心 Scale 的問題,  這也是許多開發者選擇 Cloud Build 的原因之一 以下就簡單的帶各位了解如何在 Cloud Build 上建立 Pipeline 跑 CI/CD 的流程 首先, 建立 Pipeline 腳本 由於 Cloud Build 是基於容器的服務, 腳本上的指令都必須跑在容器的環境內, 所以在建立腳本的時候, 需要特別地指定執行環境的容器映像( 即 Builder 的映像), 如下 - name: 'gcr.io/cloud-builders/docker'   args: ['build', '-t', 'gcr.io/myproject/myapp', '.'] 目前 GCP 上已經內建了幾個常用的容器映像讓開發者使用, 所以想要實作 CI/CD 的 Pipeline 並不一定需要自己建立 Builder 的映像檔 預設所有要被執行的腳本都需要被定義在 cloudbuild.yaml 的檔案裡 內容如下 steps: - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/myproject/myapp', '.'] - name: 'gcr.io/cloud-builders/docker'   args: ['push', 'gcr.io/myproject/myapp'] - name: 'gcr.io/cloud-buil

淺談 Docker Network, None, Bridge, Host

前言 Docker 目前提供以下網路模式, None, Bridge, Host None 除了  loopback interface (127.0.0.1) 之外無其他網路介面, 所以無法存取外部網路 andy_lai@cloudshell:~$ docker run -it --network=none ubuntu:14.04 /bin/bash Digest: sha256:ffc76f71dd8be8c9e222d420dc96901a07b61616689a44c7b3ef6a10b7213de4 root@71aa5f112c7e:/# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) Host 使用和宿主機 (Host) 一樣的網路設定, 效能會比較好, 但仍不建議使用, 需要考慮網路安全性的問題, 除此之外也會使失去容器隔離的好處  Bridge Docker 預設會在宿主機 (Host) 上建立一個 docker0 的網路介面, 容器可以透過這網路介面跟外界溝通, 也可以透過這介面作容器間的溝通, 事實上 docker0 扮演著一個虛擬的網路橋接器,  當以 Bridge 的網路模式建立新的容器的時候 andy_lai@cloudshell:~$ docker run -it -p 8080:8080 my-docker docker0 會被接上虛擬網卡 veth3cc413e andy_lai@cloudshell:~$

如何在 Google App Engine 上除錯, 使用 Cloud Trace, Log Viewer

前言 Google App Engine (GAE) 提供了非常方便的環境讓開發者可以輕鬆地部署服務, 除此之外還有許多有用的功能族繁不及備載... 但若如果部署在 GAE 上的服務發生異常時, 我們該如何去追蹤問題呢? 以下簡單介紹一下幾個 GCP 上好用的服務幫助我們可以快速的縮小問題的範圍 Cloud Trace Cloud Logging Cloud Trace 這個服務可以讓我們快速的找到效能上的瓶頸是來源自哪隻 API 可以看出問題可能出在 /v1/interest/ads_pref 這隻API 上, 並且發生時間可能在  17:40 分左右 Cloud Logging 知道效能的瓶頸是源自於某隻 API 之後, 接下來可以用 Log Viewer 來看程式是否有拋出任何異常的訊息 在 Query Builder 下查詢語法來找出可能的線索 resource.type="gae_app" resource.labels.module_id="My-Service" textPayload:"exec bulk" timestamp >= "2020-05-15T17:40:00+08:00" AND timestamp <= "2020-05-15T17:43:00+08:00" 這個語法會找出 My-Service 這隻服務在 2020-05-15 這天17:40~17:43 產生含有 exec bulk 這段訊息的 log  以下是其他查詢可以用的運算子 =           # equal !=          # not equal > < >= <=   # numeric ordering :           # "has" matches any substring in the log entry field =~          # regular expression search for a pattern !~         

錯誤訊息 does not have storage.objects.get access to the Google Cloud Storage object

當我們想要建立 Cloud Run 的容器映像時, 可以使用 gcloud builds submit gcloud builds submit --tag gcr.io/andy-prj/my-service --project $PROJECT 若執行的過程中若出現以下的錯誤訊息時 Creating temporary tarball archive of 124 file(s) totalling 570.2 KiB before compression. Uploading tarball of [.] to [gs://andy-prj_cloudbuild/source/3422.582116-0fd81c021c243d892201dfd08ce1550.tgz] Created [https://cloudbuild.googleapis.com/v1/projects/andy-prj/builds/46712e03-3a15-403f-8be1-b1f1a238d02e]. Logs are available at [https://console.cloud.google.com/cloud-build/builds/ 46712e03-3a15-403f-8be1-b1f1a238d02e ?project=182871]. ERROR: (gcloud.builds.submit) HTTPError 403: <?xml version='1.0' encoding='UTF-8'?><Error><Code> AccessDenied </Code><Message> Access denied .</Message><Details>deploy-cloud@andy-prj.iam.gserviceaccount.com does not have storage.objects.get access to the Google Cloud Storage object .</Details></Error> 表示需要我們缺少存取 GCS 裡物件的權限 要解決這個問題

錯誤訊息 Permission iam.serviceaccounts.actAs denied

當我們想要在 Cloud Run 部署新的服務的時候, 可以使用 gcloud run deploy  gcloud run deploy bi-cronjob \ --image gcr.io/$PROJECT/bi-cronjob \ --platform managed \ --no-allow-unauthenticated \ --region us-central1 \ --project $PROJECT \ --set-env-vars SERVICE_ENV=$RUNMODE \ --memory 1G 若部署的過程中出現以下的錯誤訊息時 Deploying container to Cloud Run service [my-service] in project [andy-prj] region [us-central1] X Deploying...   . Creating Revision...   . Routing traffic... Deployment failed ERROR: (gcloud.run.deploy) PERMISSION_DENIED: Permission   'iam.serviceaccounts.actAs' denied on service account  compute@developer.gserviceaccount.com (or it may not exist). 表示需要 Service Account User 的權限才能完成部署的動作 要解決這個問題, 可以到 IAM 的頁面下加入此權限 或是使用 gcloud 的指令來提昇權限 gcloud projects add-iam-policy-binding <PROJECT_ID> \ --member=serviceAccount:<SERVICE_ACCOUNT_ID>@<PROJECT_ID>.iam.gserviceaccount.com \ --role=roles/iam.serviceAccountUser

修改資料表的欄位資訊 Change Column In BigQuery

前言 與傳統的關聯式資料庫不同, BigQuery 並不支援使用 ALTER 來修改資料表內的欄位, 如果很不幸的真的需要改欄位, 我們只能重新建立新的資料表 CREATE OR REPLACE TABLE ` dataset.usr_new ` AS SELECT * EXCEPT (usrType), CAST(usrType AS INT64) AS usrType, FROM `dataset.usr`; 分區表 (Partitioned Table) 以上的方法只適合用在普通的資料表, 若想要修改分區表內的欄位資訊, 建議使用 bq query 的指令來做 bq query 支援將查詢的結果寫入到指定的資料表中, 除此之外還可以用查詢結果來建立分區表(如下) bq --location=location query \ --destination_table project_id:dataset.table \ --time_partitioning_field column \ --use_legacy_sql=false \ 'query' 分區表都會有兩個虛擬的欄位 _PARTITIONDATA, _PARTITIONTIME 用來記錄資料的時間,  這邊需要注意的是 bq query 沒辦法將舊資料表內的虛擬欄位的資訊直接寫到新的資料表中,  若想將這些資訊保留下來, 必須額外建立新的欄位來放這些資訊 SELECT * EXCEPT (usrType), CAST(usrType AS INT64) AS usrType, _PARTITIONTIME AS createdAt FROM ` dataset.usr `; 完整的指令 bq query \ --destination_table 'dataset.usr_new' \ --time_partitioning_field createdAt \ --use_legacy_sql=false --append_table \ ' SELECT * EXCEPT (usrType), CAST(usrType AS INT64)

ElasticSearch rename field name in index

前言 傳統的關連式資料庫 (Relational Database, RDB), 若想要變更資料表內的欄位名稱可以用一行指令簡單地做到 MS SQL sp_rename 'table_name.old_column_name', 'new_column_name', 'COLUMN'; PostgreSQL ALTER TABLE Test1 RENAME COLUMN foo TO baz; 但如果想要在ElasticSearch上修改欄位的話就沒有這麼簡單了 假設現在有個 Index "user" PUT /user HTTP/1.1 Content-Type: application/json { "settings": { "number_of_shards": 1 }, "mappings": { "_doc": { "properties": { "devOs": { "type": "keyword" }, "devOsVer": { "type": "keyword" }, "appVer": { "type": "keyword" } } } } 如果想要將欄位 appVer 改成 ver, 基本上需要以下的步驟 Step 1. 用更新後的 Mapping 建立一個暫時的 Index, user_tmp PUT /User_tmp HTTP/1.1 Content-Type: application/json { "settings": { "number_of_shar

Git取消合并 Undo a merge by pull request

前言 實務上在多人開發的情況下, 很常在上 Code 的時候被 Git 要求先做 PULL 但若是 PULL 下來的內容有問題,  特別是當同仁交付了一段會造成系統崩潰的內容至版本庫 (Repository) 時, PULL 下來的 Commit 就會使正在開發的功能受到影響, 若無法在短時間內修正, 嚴重的話甚至會影響到整個軟體專案的開發, 造成其他新功能都無法進行部屬 使用 Revert git pull 做的事情就是 Fetch + merge, 所以事實上可以使用 git revert 把剛剛的 Merge Commit 打掉 找出要打掉的 Merge Commit Id 執行 Revert 指令 $ git revert -m 1 結果如下 使用 Reset $ git reset --hard <MERGE 之前的 COMMIT_ID> 不建議用這個方法, 因為執行完上面的指令之後, 雖然 HEAD 會往前移動, 工作目錄會被還原到合併之前的 Commit, 但是在重新上 Code 時 Git 還是會要求做 PULL, 因為遠端分支的 HEAD 還是指在比較新的 Commit 上(有問題的  Commit) 除非強行覆蓋遠端版本庫中的內容, 如下 $ git push --force 但實務上並不是每個開發團隊都接受使用--force 的指令作強制覆蓋, 所以要取消 Merge Commit, 建議還是使用 Revert 指令