On this page
关于GitHub Actions和Terraform
GitHub Actions 是 GitHub 提供的一个强大而灵活的自动化工具,能够帮助开发者实现持续集成(CI)和持续交付/部署(CD)流水线。它能够让开发者在代码库的不同阶段(如代码提交、拉取请求、发布等)自动触发构建、测试、部署等任务。借助 GitHub Actions,开发者可以通过自定义的 YAML 文件定义工作流,实现从代码提交到应用发布的全自动化过程。
Terraform是目前最热门的基础设施即代码工具,它能够以脚本的形式定义基础设施配置,这极大地增强了基础设施的可复用性,并且可以更好的同CI/CD流水线集成。
GitHub Actions的优势
深度集成:GitHub Actions 与 GitHub 仓库无缝集成,可以根据事件自动触发工作流,适用于各类开发项目。
灵活性高:支持高度自定义的工作流,开发者可以根据不同的项目需求,灵活地配置不同的任务、条件和依赖
生态系统丰富:GitHub Marketplace 提供了数千个现成的 Actions(如容器部署、测试工具、CI/CD 任务等),开发者可以方便地复用已有组件,减少重复工作。
并行化任务执行:GitHub Actions 可以让多个任务并行运行,提升 CI/CD 的效率,适应大型项目的复杂需求。
可扩展性强: GitHub actions可以与主流云计算平台相结合,实现无缝的云部署。
实践:通过GitHub Actions实现自动化构建docker镜像并部署到Azure Kubernetes上
项目链接:
使用Terraform创建Azure Kubernetes集群和Container Registry镜像存储库
Terraform脚本可以参照之前的这篇文章,需要将variables中设置的默认值清空
编写Shell脚本
GitHub Actions会使用Linux环境执行Workflow中的操作,因此将所有涉及到的命令拆分为多个Shell脚本效率更高,也更便于修改。
构建镜像脚本
set -u
: $CONTAINER_REGISTRY
: $VERSION
docker build -t $CONTAINER_REGISTRY/book-catalog:$VERSION --file ./book_catalog/Dockerfile .
docker build -t $CONTAINER_REGISTRY/inventory:$VERSION --file ./inventory_management/Dockerfile .
推送镜像脚本
set -u
: "$CONTAINER_REGISTRY"
: "$VERSION"
: "$REGISTRY_UN"
: "$REGISTRY_PW"
echo $REGISTRY_PW | docker login $CONTAINER_REGISTRY --username $REGISTRY_UN --password-stdin
docker push $CONTAINER_REGISTRY/book-catalog:$VERSION
docker push $CONTAINER_REGISTRY/inventory:$VERSION
部署脚本
set -u
: "$CONTAINER_REGISTRY"
: "$VERSION"
: "$DB_URL"
envsubst < ./scripts/kubernetes/configmap.yaml | kubectl apply -f -
envsubst < ./scripts/kubernetes/service.yaml | kubectl apply -f -
envsubst < ./scripts/kubernetes/deployment.yaml | kubectl apply -f -
其中envsubst
命令能将后面文件中的环境变量占位符替换为当前环境中的实际值。
删除脚本
set -u
: "$CONTAINER_REGISTRY"
: "$VERSION"
: "$DB_URL"
envsubst < ./scripts/kubernetes/deployment.yaml | kubectl delete -f -
envsubst < ./scripts/kubernetes/service.yaml | kubectl delete -f -
envsubst < ./scripts/kubernetes/configmap.yaml | kubectl delete -f -
编写GitHub workflow配置
Apply terraform yaml
在编写配置之前,需要做一些准备工作
- 创建Azure服务主体
Azure服务主体包含了一些数据,如CLIENT_ID,CLIENT_SECRET和TENANT_ID,这些数据可以用来免交互登录Azure。使用如下命令:
az ad sp create-for-rbac --name <服务主体名称> --role Owner --scopes /subscriptions/<你的subscriptions ID> --sdk-auth
该命令执行成功后会生成一个Json文件,保存好该文件
- 为GitHub账户创建Personal access tokens
该字符可以让GitHub Actions执行器访问GitHub仓库中的secrets并设置。
- 编写Workflow配置
name: Terraform Apply
# 仅限手动构建,如果使用branches关键字,可以指定当代码被推送到对应分支是触发自动构建
on:
workflow_dispatch:
jobs:
terraform:
name: Terraform apply
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Set up Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.6
# 使用之前生成的服务主体数据
- name: Azure Login
run: az login --service-principal -u ${{ secrets.CLIENT_ID }} -p ${{ secrets.CLIENT_SECRET }} --tenant ${{ secrets.TENANT_ID }}
- name: Terraform Init
working-directory: ./scripts/terraform
run: terraform init
# ${{ vars.AZURE_RESOURCE_NAME }}等变量保存在GitHub仓库中的Repository variables列表下,由于这些内容并非机密数据,因此不必设置为secrets
# 这些变量指定的Terraform资源所使用的资源组名,位置,K8s集群和容器注册表名称以及K8s版本
- name: Terraform Apply
working-directory: ./scripts/terraform
run: terraform apply -auto-approve -var "resource_group_name=${{ vars.AZURE_RESOURCE_NAME }}" -var "location=${{ vars.AZURE_RESOURCE_LOCATION }}" -var "app_name=${{ vars.APP_NAME }}" -var "kubernetes_version=${{ vars.AZURE_AKS_VERSION }}"
continue-on-error: true
# 安装后续操作所需的依赖,其中gh为GitHub-Cli,jq用来过滤Json数据
- name: Install dependencies
run: |
sudo apt install gh -y
sudo apt install jq -y
# 这里的Token是先前创建的Personal access tokens
- name: GitHub-Cli login
run: |
echo "${{ secrets.TOKEN }}" | gh auth login --with-token
# 刷新Terraform状态
- name: Refresh terraform state
run: terraform refresh
# 通过gh命令设置Secrets
- name: Set Secrets
run: |
acr_name=$(az acr list | jq -r '.[0].loginServer')
gh secret set CONTAINER_REGISTRY --body "$acr_name"
az acr credential show --name "$acr_name" --query "{username:username, passwords:passwords[0].value}" --output json > credentials.json
gh secret set REGISTRY_UN --body "$(cat credentials.json | jq -r '.username')"
gh secret set REGISTRY_PW --body "$(cat credentials.json | jq -r '.passwords')"
az aks get-credentials --resource-group ${{ vars.AZURE_RESOURCE_NAME }} --name ${{ vars.APP_NAME }}
gh secret set KUBE_CONFIG --body "$(cat ~/.kube/config | base64 -w 0)"
Deploy Microservice yaml
name: Deploy microservice
on:
workflow_dispatch:
# 将要运行的任务
jobs:
deploy:
runs-on: ubuntu-latest
# 环境变量,这些变量在仓库的secrets中声明和配置
env:
VERSION: ${{ github.sha }}
CONTAINER_REGISTRY: ${{ secrets.CONTAINER_REGISTRY }}
REGISTRY_UN: ${{ secrets.REGISTRY_UN }}
REGISTRY_PW: ${{ secrets.REGISTRY_PW }}
DB_URL: ${{ secrets.DB_URL }}
# 具体的任务步骤
steps:
# actions/checkout:GitHub 官方提供的一个标准 Action,用来将代码库的当前版本拉取到虚拟机或容器中。
- uses: actions/checkout@v3
- name: Build images
run: bash ./scripts/build-image.sh
- name: Push image
run: bash ./scripts/push-image.sh
# tale/kubectl-action:一个第三方 Action,用于在 GitHub Actions 工作流中执行 kubectl 命令,管理 Kubernetes 集群
- uses: tale/kubectl-action@v1
with:
# 经过 base64 编码的 Kubernetes 配置文件
base64-kube-config: ${{ secrets.KUBE_CONFIG }}
# 指定 kubectl 的版本号
kubectl-version: v1.30.3
- name: Deploy
run: bash ./scripts/deploy.sh
Delete Microservice yaml
和Deploy差不多,只不过在关键的地方使用delete.sh
脚本触发kubectl delete操作。
name: Delete microservice
on:
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
env:
VERSION: ${{ github.sha }}
CONTAINER_REGISTRY: ${{ secrets.CONTAINER_REGISTRY }}
REGISTRY_UN: ${{ secrets.REGISTRY_UN }}
REGISTRY_PW: ${{ secrets.REGISTRY_PW }}
DB_URL: ${{ secrets.DB_URL }}
steps:
- uses: actions/checkout@v3
- uses: tale/kubectl-action@v1
with:
base64-kube-config: ${{ secrets.KUBE_CONFIG }}
kubectl-version: v1.30.3
- name: delete
run: ./scripts/delete.sh
在仓库的secrets中声明和配置变量
需要将azure登录凭据和gh登录凭据存储到secrets中,其他的secrets会通过gh命令在执行Actions自动设置。
触发构建
在GitHub仓库中点击Actions
,在workflow中找到Deploy microservice
,然后点击Run workflow
就可以触发构建。
当右上角出现对号图标,意味着构建成功。
值得注意的是,GitHub Actions构建成功不一定代表部署成功,比如如果Kubernetes配置文件中存在错误,除非是会导致exit code 1
的语法错误,否则是不会提示错误的。
同理,要想删除部署,只需要点击Delete microservice
并运行构建。