关于GitHub Actions和Terraform {#%E5%85%B3%E4%BA%8Egithub-actions%E5%92%8Cterraform}
GitHub Actions 是 GitHub 提供的一个强大而灵活的自动化工具,能够帮助开发者实现持续集成(CI)和持续交付/部署(CD)流水线。它能够让开发者在代码库的不同阶段(如代码提交、拉取请求、发布等)自动触发构建、测试、部署等任务。借助 GitHub Actions,开发者可以通过自定义的 YAML 文件定义工作流,实现从代码提交到应用发布的全自动化过程。
Terraform是目前最热门的基础设施即代码工具,它能够以脚本的形式定义基础设施配置,这极大地增强了基础设施的可复用性,并且可以更好的同CI/CD流水线集成。
GitHub Actions的优势 {#github-actions%E7%9A%84%E4%BC%98%E5%8A%BF}
深度集成:GitHub Actions 与 GitHub 仓库无缝集成,可以根据事件自动触发工作流,适用于各类开发项目。
灵活性高:支持高度自定义的工作流,开发者可以根据不同的项目需求,灵活地配置不同的任务、条件和依赖
生态系统丰富:GitHub Marketplace 提供了数千个现成的 Actions(如容器部署、测试工具、CI/CD 任务等),开发者可以方便地复用已有组件,减少重复工作。
并行化任务执行:GitHub Actions 可以让多个任务并行运行,提升 CI/CD 的效率,适应大型项目的复杂需求。
可扩展性强: GitHub actions可以与主流云计算平台相结合,实现无缝的云部署。
实践:通过GitHub Actions实现自动化构建docker镜像并部署到Azure Kubernetes上
使用Terraform创建Azure Kubernetes集群和Container Registry镜像存储库 {#%E4%BD%BF%E7%94%A8terraform%E5%88%9B%E5%BB%BAazure-kubernetes%E9%9B%86%E7%BE%A4%E5%92%8Ccontainer-registry%E9%95%9C%E5%83%8F%E5%AD%98%E5%82%A8%E5%BA%93}
编写Shell脚本 {#%E7%BC%96%E5%86%99shell%E8%84%9A%E6%9C%AC}
GitHub Actions会使用Linux环境执行Workflow中的操作,因此将所有涉及到的命令拆分为多个Shell脚本效率更高,也更便于修改。
构建镜像脚本 {#%E6%9E%84%E5%BB%BA%E9%95%9C%E5%83%8F%E8%84%9A%E6%9C%AC}
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 .
</code> </pre>
推送镜像脚本 {#%E6%8E%A8%E9%80%81%E9%95%9C%E5%83%8F%E8%84%9A%E6%9C%AC}
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 </code> </pre> #### 部署脚本 {#%E9%83%A8%E7%BD%B2%E8%84%9A%E6%9C%AC} ````````bash 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 - </code> </pre> 其中 ` envsubst ` 命令能将后面文件中的环境变量占位符替换为当前环境中的实际值。 #### 删除脚本 {#%E5%88%A0%E9%99%A4%E8%84%9A%E6%9C%AC} ```````bash 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 - </code> </pre> ### 编写GitHub workflow配置 {#%E7%BC%96%E5%86%99github-workflow%E9%85%8D%E7%BD%AE} #### Apply terraform yaml {#apply-terraform-yaml} 在编写配置之前,需要做一些准备工作 * 创建Azure服务主体 Azure服务主体包含了一些数据,如CLIENT_ID,CLIENT_SECRET和TENANT_ID,这些数据可以用来免交互登录Azure。使用如下命令: ``````bash az ad sp create-for-rbac --name <服务主体名称> --role Owner --scopes /subscriptions/<你的subscriptions ID> --sdk-auth </code> </pre> 该命令执行成功后会生成一个Json文件,保存好该文件 * 为GitHub账户创建Personal access tokens 该字符可以让GitHub Actions执行器访问GitHub仓库中的secrets并设置。 https://github.com/settings/tokens?ref=blog.freelytomorrow.com * 编写Workflow配置 `````yaml 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 &gt; 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)" </code> </pre> #### Deploy Microservice yaml {#deploy-microservice-yaml} ````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 </code> </pre> #### Delete Microservice yaml {#delete-microservice-yaml} 和Deploy差不多,只不过在关键的地方使用 ` delete.sh ` 脚本触发kubectl delete操作。 ```yaml 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 </code> </pre> ### 在仓库的secrets中声明和配置变量 {#%E5%9C%A8%E4%BB%93%E5%BA%93%E7%9A%84secrets%E4%B8%AD%E5%A3%B0%E6%98%8E%E5%92%8C%E9%85%8D%E7%BD%AE%E5%8F%98%E9%87%8F} 需要将azure登录凭据和gh登录凭据存储到secrets中,其他的secrets会通过gh命令在执行Actions自动设置。 ### 触发构建 {#%E8%A7%A6%E5%8F%91%E6%9E%84%E5%BB%BA} 在GitHub仓库中点击 ` Actions ` ,在workflow中找到 ` Deploy microservice ` ,然后点击 ` Run workflow ` 就可以触发构建。 当右上角出现对号图标,意味着构建成功。 值得注意的是,GitHub Actions构建成功不一定代表部署成功,比如如果Kubernetes配置文件中存在错误,除非是会导致 ` exit code 1 ` 的语法错误,否则是不会提示错误的。 同理,要想删除部署,只需要点击 ` Delete microservice ` 并运行构建。 ``` ```` ````` `````` ``````` ````````