CIをGitHub Actionsでやってみた
gitlabCIでやってたことをGitHub Actionsのドキュメント見て置き換えるだけ。
とはいえ最初workflow
とaction
がごっちゃになっててうまく検索できなかった。
gitlabCIのgitlab-ci.yml
に当たるのはworkflow
です。
action
は汎用するために処理単位で切り出した共通モジュールなので超便利っぽいけど一旦スルーすると理解しやすいと思う。
作ったもの
# ./.github/workflows/00.yml
name: "deploy"
# トリガをmasterへのpushに設定
on:
push:
branches:
- "master"
jobs:
# 別に名前は何でもよさそう
build:
# ジョブの実行環境を指定
runs-on: ubuntu-latest
# 環境変数定義
env:
GITHUB_SHA_S: $(echo ${GITHUB_SHA} | cut -c1-8)
# ジョブのタスクを定義していく
steps:
# リポジトリチェックアウトするアクションを最初に実行
- uses: actions/checkout@v2
# DockerHubにログイン
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Build&Push
- run: docker build --build-arg baseurl=${{secrets.APP_IP}} -t ${{ secrets.DOCKERHUB_USERNAME }}/52steps:${{env.GITHUB_SHA_S}} .
- run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/52steps:${{env.GITHUB_SHA_S}}
deploy:
runs-on: ubuntu-latest
env:
GITHUB_SHA_S: $(echo ${GITHUB_SHA} | cut -c1-8)
steps:
- uses: actions/checkout@v2
# namespaceの作成
- name: create ns
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: apply -f ./deploy/ns.yml
# k8sにdockerhubへのアクセス権限を作成
- name: create secret
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: |
-n 52steps create secret docker-registry regcred \
--docker-server=https://index.docker.io/v2/ \
--docker-username=${{ secrets.DOCKERHUB_USERNAME }} \
--docker-password=${{ secrets.DOCKERHUB_TOKEN }} \
--docker-email=${{ secrets.DOCKERHUB_MAIL }} \
-o yaml --dry-run | kubectl apply -f -
# dockerHubのプライベートイメージにアクセスできるようにアクセス権限をnamespaceのdefaultアカウントに付与
- name: add regcred namespace account
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: |
patch serviceaccount default \
-p '{\"imagePullSecrets\": [{\"name\": \"regcred\"}]}' \
-n 52steps
# DBイメージをデプロイ
- name: create db
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: apply -f ./deploy/db.yml
# アプリをデプロイ
- name: Update deployment file
run: TAG=${{ secrets.DOCKERHUB_USERNAME }}/52steps:${{env.GITHUB_SHA_S}} && sed -i "s|<IMAGE>|$TAG|" ./deploy/app.yml
- name: create app
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: apply -f ./deploy/app.yml
# アプリのサービスをIngressで公開
- name: create ingress
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: apply -f ./deploy/ingress.yml
DockerHubへのログイン
自分のprivateレジストリにアクセスしたいのでdocker/login-action
アクションを利用してdockerLoginを行う。
DOCKERHUB_USERNAME
とDOCKERHUB_TOKEN
はgithub actionsの設定画面から設定しておく。
# DockerHubにログイン
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
Dockerfileのビルドとプッシュ
githubのリポジトリに登録したDockerfileをbuildしてpushする。
${{env.GITHUB_SHA_S}}
はジョブの先頭で定義したGITHUB_SHA_S: $(echo ${GITHUB_SHA} | cut -c1-8)
を参照しているだけ。
GITHUB_SHA
はトリガとなったgitのcommitのハッシュ値でDockerImageのタグに使いたいけど長すぎるので短く切り取った。
# Build&Push
- run: docker build --build-arg baseurl=${{secrets.APP_IP}} -t ${{ secrets.DOCKERHUB_USERNAME }}/52steps:${{env.GITHUB_SHA_S}} .
- run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/52steps:${{env.GITHUB_SHA_S}}
k8sの操作
deployジョブではk8sの操作を行ってDockerImageのデプロイを行う。
steebchen/kubectl
アクションを使ってkubectlを実行していく。
KUBE_CONFIG_DATA
にはローカルの.kube/config
をbase64化した文字列を設定する。
# namespaceの作成
- name: create ns
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: apply -f ./deploy/ns.yml
k8sにDockerHubへのアクセス権を付与する
DockerHubのprivateレジストリを利用しているのでk8sにもアクセス権を与える必要がある。
k8sにはsecretの種別にdocker-registryへの権限が存在するのでそれを生成する。
secret作るときにapply
が使えないのでCIの2回目実行時に「既にあるけど」的なエラーが発生する。
そのためdry-run
でymlファイルを生成してパイプでapply
に渡すといい感じになる。
# k8sにdockerhubへのアクセス権限を作成
- name: create secret
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: |
-n 52steps create secret docker-registry regcred \
--docker-server=https://index.docker.io/v2/ \
--docker-username=${{ secrets.DOCKERHUB_USERNAME }} \
--docker-password=${{ secrets.DOCKERHUB_TOKEN }} \
--docker-email=${{ secrets.DOCKERHUB_MAIL }} \
-o yaml --dry-run | kubectl apply -f -
namespaceのdefaultアカウントに権限を付与
上記で作成したregcred
をdeploymentファイルのimagePullSecrets
に指定してもいいんだけどめんどくさいのでnamespaceのデフォルトアカウントにつけておく。
こうするとそのnamespace内で常に有効になる。
# dockerHubのプライベートイメージにアクセスできるようにアクセス権限をnamespaceのdefaultアカウントに付与
- name: add regcred namespace account
uses: steebchen/kubectl@master
env:
KUBE_CONFIG_DATA: ${{ secrets.K8S_CONFIG }}
with:
args: |
patch serviceaccount default \
-p '{\"imagePullSecrets\": [{\"name\": \"regcred\"}]}' \
-n 52steps
おじさんの感想
社内CI環境との違いはざっと以下の通り。
もの | 社内 | 今回 |
---|---|---|
CI | gitlabCI | github actions |
k8s | beremetalなk8s | digitaloceanのk3s |
docker registry | gitlab registory | dockerhub |
CI環境は書き方の違いがあるくらいで、使っている範囲では出来る事に違いはなさそう。
k3sは今回の範囲ではk8sと同じ操作が可能で特にk3sを意識することはなかった。
dockerregistoryはdockerhub使う事にしたおかげでinsecure-registries
の設定は要らなかった。