Github Workflow 介紹
前言
為了利用 Github Workflow 完成 CI/CD,分成幾個部分來寫,分別是
- Github Workflow 的基本設定
- Github Workflow 中進行 CI
- 登入登出 AWS ECR 與 github container registry
- build & upload image
- 更新 helm value 中的 image tag,後續讓 argocd 得以偵測到 helm values 的變化後,進行自動化部屬
基本設定
- action 為
push的時候,所有 branch都會進行 github workflow - action 為
pull_request的時候,只有main branch會進行 github workflow - types
- paths
on:
push:
branches: ["*"]
pull_request:
branches: ["main"]
types:
- opened
paths:
- "**.js"
env 設定
- 設定方式如下,可以依照自身需求進行設定
env:
AWS_DEFAULT_REGION: ap-southeast-1
GIT_USER_NAME: jennyc
permissions 設定
- 設定方式如下,可以依照自身需求進行設定
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
自動化測試 CI
checkout repository
-
使用
actions/checkout@v3進行- name: Checkout repository uses: actions/checkout@v3
執行 npm install
- name: Install dependencies
run: npm install
執行 npm test
- name: Run tests
run: npm run test
Build multi-platform images 並上傳至 AWS ECR
前言
這部分需要先設定 AWS Credential 才能使用 AWS ECR,
接著 build multi-platform image 並且上傳至 AWS ECR。
1. 設定 AWS Credential
-
設定 AWS Credential
-
使用 GitHub’s OIDC provider 方式取得 short-lived credentials
-
workflow 要怎麼寫?
env.AWS_DEFAULT_REGION需要特別設定,與 AWS ECR 相同的 regionrole-to-assume填入 AWS rolerole-session-name預設是 GitHubActions,可以自行調整名稱
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: arn:aws:iam::1234567890:role/example-role role-session-name: GitHubActionsWithAwsEcrUsingOIDCSession aws-region: ${{env.AWS_DEFAULT_REGION}}
-
2. 登入 AWS private ECR
- 有兩種方式
-
Using
access key idandsecret access keyto login- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-southeast-1 -
Using
OpenID Connect (OIDC)to login- 官方推薦使用此方式
- name: Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1
-
3. 登入 AWS public ECR
- 可參考官方說明
4. 登出 AWS ECR
- name: Logout of Amazon ECR
if: always()
run: docker logout ${{ steps.login-ecr.outputs.registry }}
5. 設定 short sha 為 image tag
- 設定以 7 digits 長度的 short sha 作為 image tag,原因可以參考:
- 7 digits are the Git default for a short SHA
- 附上其他參考文件 Chapter 7 of the Pro Git book
- 將 output 出去的參數命名為
sha_short
- name: Set short sha outputs
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
6. Build multi-platform images 並上傳 images 到 AWS ECR
- 建立多平台 docker images 的官方文件
IMAGE_TAG會從步驟 5 取得 output 的變數sha_short--platform可接上需要的 platform 參考,例如 linux/amd64, linux/arm64
- name: Build, tag, and push docker image to Amazon ECR
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: pet-app
IMAGE_TAG: ${{ steps.vars.outputs.sha_short }}
run: |
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
( 官方建議: docker run --privileged --rm tonistiigi/binfmt --install all )
docker buildx create --name mybuilder --driver docker-container --bootstrap
docker buildx use mybuilder
docker buildx inspect
docker buildx build --platform linux/amd64,linux/arm64 -t $REGISTRY/$REPOSITORY:$IMAGE_TAG --push .
-
為什麼需要
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes?- 因為遇到
Error: while loading /usr/local/sbin/node: No such file or directory問題- 先使用方式一 : 連接方式,結果還是有相同問題
ln -s /usr/bin/node /usr/local/sbin/node - 後來使用方式二
-
使用 docker buildx 指令前先執行以下命令
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -
詳細原因的 Stack Overflow 原始文章在這邊,以下是節錄部分
` When you ask the Linux kernel to run some executable file, it needs to know, how to load this specific file, and whether this file is compatible with current machine, or not. By default, the ELF binary compiled for, say, arm64v8 is rejected by the kernel, running on amd64 hardware.
However, the binfmt_misc feature of the kernel allows you to tell it, how to handle the executables it cannot usually handle on its own - this includes the cases when the kernel does not know the binary format or considers it incompatible with current machine.
`
-
- 先使用方式一 : 連接方式,結果還是有相同問題
- 因為遇到
-
官方建議使用以下命令解決 QEMU binaries 問題,官方文件
docker run --privileged --rm tonistiigi/binfmt --install all
更新 helm value 的 image tag
前言
應用是以 terraform 方式部屬,並搭配使用 helm charts。而 docker image 的 tag 是寫在 helm values 內。
目標是更新 helm values 的 docker image tag 值,後續讓 argocd 得以偵測到 helm values 的變化後,進行自動化部屬。
需做到兩件事情:
- checkout 私有 repository
- 設定與更新 image tag
1. 先 checkout 私有存放 helm value 的 repository
需要先設定 credential 才能 fetch private repository,有兩種設定的方式
-
設定 deploy key
-
步驟如下,可參考這篇
- Create a new SSH key pair for your repository. Do not set a passphrase.
- Copy the contents of the public key (.pub file) to a new repository deploy key and check the box to “Allow write access.”
- Add a secret to the repository containing the entire contents of the private key.
- As shown in the example below, configure
actions/checkoutto use the deploy key you have created.
-
workflow 要怎麼寫?
- ssh-key 填入 private key 的 secrets 名稱
- path 設定 checkout 的 repo 會存在哪一個資料夾內
- name: Checkout ${{env.TERRAFORM_REPOSITORY_NAME}} repo and push file to ${{env.TERRAFORM_REPOSITORY_NAME}} uses: actions/checkout@v3 with: repository: ${{env.TERRAFORM_REPOSITORY_OWNER_NAME}}/${{env.TERRAFORM_REPOSITORY_NAME}} ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} path: ${{env.TERRAFORM_REPOSITORY_NAME}}
-
-
設定 Personal access token (PAT)
-
建立 PAT 的方式,官方文件
-
將建立完成的 PAT 設定到 repository 的 secrets 中,設定的 secrets 名稱為 GH_PAT,官方文件
-
workflow 要怎麼寫?
- repository 設定為
owner/repository_name - token 填入 PAT 的 secrets 名稱,這邊是將 secrets 名稱為 GH_PAT 的內容設定為 PAT
- name: Checkout ${{env.TERRAFORM_REPOSITORY_NAME}} repo and push file to ${{env.TERRAFORM_REPOSITORY_NAME}} uses: actions/checkout@v3 with: repository: ${{env.TERRAFORM_REPOSITORY_OWNER_NAME}}/${{env.TERRAFORM_REPOSITORY_NAME}} token: ${{ secrets.GH_PAT }} - repository 設定為
-
2. 設定 image tag
- 設定以 7 digits 長度的 short sha 作為 image tag
- 7 digits are the Git default for a short SHA
- 附上其他參考文件 Chapter 7 of the Pro Git book
- name: Set short sha outputs
id: vars
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
3. 更新 image tag
- 以 yq 的 github action 工具修改 yaml 檔內的 image tag 值
- 進行 git 操作,設定 user name, user email、commit 以及 push
- tag 取上一個步驟 output 的參數
sha_short
- name: Update image tag
uses: mikefarah/yq@master
with:
cmd: yq -i '.pet_app_dashboard_site.image.tag = "${{ steps.vars.outputs.sha_short }}"' ./${{env.TERRAFORM_REPOSITORY_NAME}}/${{env.HELM_FILE_NAME}}
- run: |
cd ${{env.TERRAFORM_REPOSITORY_NAME}}
git config user.name ${{env.GIT_USER_NAME}}
git config user.email ${{env.GIT_USER_EMAIL}}
git add ${{env.HELM_FILE_NAME}}
git commit -m "update image tag to ${{ steps.vars.outputs.sha_short }}"
git push origin main
若要將 docker image 上傳至 github container registry 該怎麼做?
1. 登入與登出 github container registry
-
需要設定 env.REGISTRY 為 ghcr.io
-
不需要另外設定 github.actor 與 GITHUB_TOKEN
- name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }}
2. Extract metadata
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
3. Build and push docker image
- labels 的值可以從步驟二取出 outputs labels 來使用
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.REPO }}:${{ steps.vars.outputs.sha_short }}
labels: ${{ steps.meta.outputs.labels }}
參考資料
- actions/checkout
- amazon-ecr-login
- docker/login-action
- docker-build-fails-for-arm-images
- yq 的官方文件
- yq 的 github
- Chapter 7 of the Pro Git book
- creating-a-personal-access-token
- creating-and-using-encrypted-secrets
最後,若喜歡我的分享,可以免費幫我按讚,是對我最大的鼓勵!