LoginSignup
17
9

More than 5 years have passed since last update.

GitHub Appを使ってGitOpsする

Last updated at Posted at 2018-12-15

Kubernetes3 Advent Calendar 2018 - Qiita の16日目です。

概要

既存のKubernetes環境向けCDツールがチームの要件に満たなかったのでGitHub AppでGitOpsをしていくことにしました。ここではその内容を共有しています。

GitOpsについての詳細はこちら: GitOps

小さな仕組みでGitOpsをする

  • 一般的にあらゆるプロジェクトの持つ予算と残された時間はそれほど多くありません。kubernetesの持つメリットを享受しつつ素早くデプロイフローを作る必要があります。
  • 環境は大きく変化していくため、変化に強くありたいと願います。端的に言えば今しばらくはワークフローをシンプルでつまらないものに保つべきと考えています。

既存ツールなんかもさわってみたんですよ

  • ローカルで kubectlapply する

    • 2-3人の規模であれば問題は起こらないと思えます。ただし今は開発人数が増えてきていて、破綻が見えているか破綻します。
  • Spinnaker, Jenkins X, argo CDも触った

私が少し機能追加しようとすると面倒に思えました。
経験上もうしばらく時間を置けばデファクトが決まり技術も枯れて安定するはずで、それまでは待ちたいと思います。
正味、複数RepositoryとDockerRepositoryとGitHubと、Slack等の通知先とやり取りすれば良いので、さっとやってみることにしました。

GitHub Appを使ったワークフロー

以下のようなデプロイフローを想定します。

deploy_flow.png

  1. 開発者はPull RequestをApp repo のstagingブランチに出す
  2. 1.のPull Request がmergeされる
  3. Github Appは2のイベントを検知すると、App repoのstagngブランチを docker buildして docker pushする。
  4. Github Appはstagngブランチを Staging用のManifestを自動生成してManifest RepoへPull Requestを出す
  5. 4のPull Requestがmergeされる。
  6. Github Appは5のイベントを検知すると、mergeされた内容をstagingクラスタへkubectl applyする

使用する技術について

probotを使ったGitHub Appが仲介業をする

probotはNode.jsでeasyに作れるGitHub App FrameWorkです。
Probot | GitHub Apps to automate and improve your workflow

GitHub Webhookを受け取って特定の動作をさせることができ、独自でHTTPエントリポイントを作って任意の動作をさせることが可能です。
このporobotを利用したGitHub Appのサーバを立ててRepositoryへのdeploy keysやGKEの場合はGCPサービスアカウントへの認証を持たせると仲介者の役割を果たせます。

ex: stagingにmergeされたら処理する

    app.on('push', async context => {
      const branch = context.payload.ref.split('/')[2] // format is "refs/heads/$BRANCH"
      const repo = context.payload.repository.name
      if (branch === 'staging' && repo === 'AppRepo') {
        const result = someOps(branch, repo)
        app.log(result)
      }
    })

ex: GitHubAppにkubectl applyさせるHTTPエンドポイント

  // kubectl apply action
  const router = app.route('/github-app')
  router.post('/apply', (req, res) => {
    if (req.header('token') !== token) {
      res.send('Recieved invalid token.') // check valid token
      return
    }
    const result = someApplyExec()
    app.log(result)
    res.send(`k8s Applied.`)
  })

KustomizeとシェルスクリプトでManifestを自動生成する

例えばDeploymentを以下のようなシェルスクリプトで作り、kustomize buildすればテンプレート的に作れそうです。

cat << EOS > $FILE_NAME
apiVersion: "extensions/v1beta1"
kind: "Deployment"
metadata:
  name: $DEPLOYMENT
spec:
  replicas: $REPLICA
  selector:
    matchLabels:
      app: $APP
  template:
    metadata:
     labels:
       app: $APP
    spec:
      containers:
      - name: $NAME
        image: $IMAGE
        ports:
          - containerPort: 80
EOS

その他: 本番環境や他サービス連携

productionの場合は図1.のPullRequestのheadをstagingに、baseをproductionにします。
Slackにイベントの通知を流したい場合はGitHubAppの処理に記述を入れます。

終わりに:

今回のフロー自体には手間を感じ得ますが、それぞれの仕組みはシンプルでくだらない、分かりやすいものになります。
シェルスクリプトかJavaScriptの知識とそれからGitHubやKubernetesのAPIを眺めればその日のうちに修正を入れることができます。
私はこの仕組に全くこだわりがありません。デファクトが出たら/dev/nullにアーカイブするでしょう。
引き続きプロダクトとその先にいる顧客に集中したいと思っています。

17
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
9