👍

Kubernetesにおけるリリースフローの改善

2022/12/13に公開

はじめに

今回はKubernetesにおけるリリースフローを改善したのでどのように行なったか紹介します。

最終的なアーキテクチャ

以前のリリースフロー

  1. applicationリポジトリのmainブランチにMerge
  2. Dokcer ImageのBuild
  3. manifestリポジトリのimageTagをKustomizeで変更
  4. manifestリポジトリのmainブランチに対して変更内容をPush
  5. Argo CDがimageTagの変更を検知してPodのローリングアップデート

2,3,4はGitHub Actions上で行なっています。

リリースフローの課題

上記のようなリリースには以下の課題がありました。

  • manifestリポジトリに対して直接Pushするため、素早くロールバックできない
 - name: Update New Image Tag by Kustomization
   uses: stefanprodan/kube-tools@v1
   with:
     kustomize: 4.5.7
     command: |
       cd /github/workspace/manifest/api/overlays/prd/
       kustomize edit set image $ECR_REGISTRY/$ECR_REPOSITORY=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
   env:
     ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
     IMAGE_TAG: ${{ github.sha  }}

- name: Deploy via Git Commit
  run: |
    git config --global user.email ${{ secrets.email }}
    git config --global user.name ${{ secrets.name }}
    git add .
    git commit -m "Update imageTag ${{ env.ECR_REPOSITORY }}"
    git push origin main
  env:
    GITHUB_TOKEN: ${{ secrets.token }}

検討

課題を解決するためにArgo CDを導入しているのでArgo CD Image Updaterを検討しました。

https://techblog.zozo.com/entry/measure-argocd-image-updater

https://techblog.zozo.com/entry/measure-argocd-introduction

しかし、リリースフローには書いていませんでしたが、リリース前にMigrationを行う必要があるAPIがあり、Migrationが失敗した際でもImageを検知してPRを作成してしまって混乱を招く可能性があるので今回は採用しませんでした。

解決策

GitHub ActionsでPushしていた箇所をPRを作成するように変更しました。以下のように変更することで、manifestリポジトリにimageTag更新のPRを作成し、Mergeすることでリリースでき、問題があった際はGitHubのWeb上でリバートすることでロールバックができるので、安全にリリースできるようになりました。

また、Argo CD Image Updaterより導入のスピードが圧倒的に速いです。

- name: Create pull request
  uses: actions/github-script@v6
  env:
    BRANCH: image-update-prd-${{ github.sha }}
  with:
    github-token: ${{ secrets.token }}
    script: |
      github.rest.pulls.create({
        owner: context.repo.owner,
        repo: "manifest",
        title: `prdのimageTagを更新`,
        body: `imageTagを「${{ github.sha }}」に変更します。`,
        head: process.env.BRANCH,
        base: "release"
      })

imageTag更新PRの課題

安全にリリースできるようになったと思いきや、imageTag更新PRにすることで以下の2つの課題が出てきました。

  • PRのMergeが大変
  • PRからリリースの内容を追いにくい

1点目に関しては、staggingへのリリースは頻繁に行われるのでPRが大量に作成され、Merge作業に時間を取られていました。また、applicationとmanifestのリポジトリを分けているので、Mergeのし忘れなども起こっていました。

2点目に関しては、PRは変更されるimageTagのhash値しか分からないため、applicationのリリース内容を追いにくくなっていました。

課題への対応

1点目に関しては、staggingは従来のmanifestリポジトリへ直接Pushに変更しました。staggingでは安全性より、作業効率を優先したためです。

2点目に関しては、リリースの内容を追いやすくするためにimageTag更新PRのbodyにapplication側のPRを紐づけることにしました。

on.pull_requestにすることでgithub.event.numberでPRの番号を取得することができるのでyamlファイルを以下のように編集しました。

on: 
  pull_request:
    branches:
      - release
    types: [closed]

jobs:
  build-and-push:
    name: Build and push to ECR
    if: github.event.pull_request.merged == true

bodyを以下のように変更しました。

imageTagを「${{ github.sha }}」に変更します。\nPR: https://github.com/st-tech/application/pull/${{ github.event.number }}

bodyにリリースの元となったapplicationリポジトリのPRのURLを貼り付けることでimageTag更新PRから変更内容が追いやすくなりました。

さいごに

これらの改善でリリースがより快適かつ安全に行えるようになりました。Kubernetesに関する課題はまだまだ山積みなのでこれからも頑張っていこうと思います。

株式会社ZOZO

Discussion