実現したいこと
argo workflowを使ってCIパイプラインを構築する
今回はリポジトリのクローンまで
対象はGithubプライベートリポジトリ(内容は前回と同じ)
環境
- Golang 1.13.5
- Docker 18
- AWS 東京リージョン
argoはAWS EKSクラスターに配置
やったこと
Argoの導入
基本的には Argo公式ドキュメントに沿って進める
前提としてEKSにCI用クラスタ ci-cluster
を作成しておく
# namespaceの作成
kubectl create ns argo
# install.yamlをダウンロードしてargo namespaceにapply
kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo/v2.2.1/manifests/install.yaml
# default namespaceのサービスアカウントにadmin権限を付与
kubectl create rolebinding default-admin --clusterrole=admin --serviceaccount=default:default
とりあえずexampleを動かす
Argoはyamlでパイプラインを記述する
例として公式exampleのconflip.yamlを実行する
coinflip.yaml
# The coinflip example combines the use of a script result,
# along with conditionals, to take a dynamic path in the
# workflow. In this example, depending on the result of the
# first step, 'flip-coin', the template will either run the
# 'heads' step or the 'tails' step.
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: coinflip-
spec:
# entorypointで指定されたtemplates.nameが起動時に実行される
entrypoint: cinflip
templates:
# ここからパイプラインの構成
- name: coinflip
steps:
# name: タスクの名前
- - name: flip-coin
# 実際のタスクの処理への参照
template: flip-coin
# - - name: stage-name で直列のタスクになる
- - name: heads
template: heads
when: "{{steps.flip-coin.outputs.result}} == heads"
# - name: stage-name で直前のタスクと並列のタスクになる
- name: tails
template: tails
when: "{{steps.flip-coin.outputs.result}} == tails"
# パイプラインの構成ここまで
# タスクの中身の定義
- name: flip-coin
# タスク毎にPodが立ち上がるのでそれぞれのタスクで起動するイメージを指定する
script:
image: python:alpine3.6
# タスク内で実行するコマンドの言語指定 今回はpython
command: [python]
# 実際に実行させる処理
source: |
import random
result = "heads" if random.randint(0,1) == 0 else "tails"
print(result)
- name: heads
container:
image: alpine:3.6
# タスク内で実行するコマンドの言語指定 今回はshell
command: [sh, -c]
args: ["echo \"it was heads\""]
- name: tails
container:
image: alpine:3.6
command: [sh, -c]
args: ["echo \"it was tails\""]
パイプラインの実行はargo submit
で行う
argo submit coinflip.yaml
Name: coinflip-pwk7p
Namespace: argo
ServiceAccount: default
Status: Pending
Created: Thu Jan 23 09:52:11 +0900 (1 second from now)
これで argo namespace上にタスク毎のPodが立ち上がりそれぞれ順に実行される
今回であれば作成されるPodは3つ
作成されるPod名は以下の通り
${metadata.generateName}{パイプライン毎のプレフィクス}-{タスク毎のプレフィクス}
今回であれば例えばcoinflip-pwk7p-4162510633
UIツールでパイプラインを監視する
argoにはUIツールが備わっているので,パイプラインの構成が複雑になる場合などに有用である.
前段でinstall.yamlを使ってargoの起動をした場合は,既にargo-ui-{プレフィクス}
という名前のPodが立てられているはず.
以下のコマンドでUIツールをlocalhost:8001
にポートフォワードする
kubectl -n argo port-forward deployment/argo-ui 8001:8001
これでブラウザでパイプラインの実行を確認できるようになった.
UIツールをインターネットから確認する
localhostから確認しているUIツールをインターネット経由で確認できるようにする
これで,確認のために毎回ポートフォワードする必要がなくなる
argo-ui serviceのTypeを ClusterIPからLoadBalancerに変更する
argoを導入した際のinstall.yamlを編集する
.
.
.
apiVersion: v1
kind: Service
metadata:
name: argo-ui
namespace: argo
# TypeをLoadBalancerに変更
spec:
type: LoadBalancer
# アクセス元IPアドレスを制限したい場合は記述
loadBalancerSourceRanges:
- "ALLOWED ACCESS IP"
ports:
- port: 80
targetPort: 8001
selector:
app: argo-ui
.
.
.
これを再度 applyすればLoadBalancerのエンドポイントからargo-uiにアクセスできる
Githubから
大筋は公式exampleのinput-artifact-git.yaml
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: input-artifact-git-
spec:
entrypoint: git-clone
templates:
- name: git-clone
inputs:
artifacts:
- name: argo-source
path: /src
git:
repo: https://github.com/argoproj/argo.git
revision: "v2.1.1"
container:
image: golang:1.10
command: [sh, -c]
args: ["git status && ls && cat VERSION"]
workingDir: /src
このパイプラインはgit-clone
タスク1つのみの単純なもので
git-clone
も実行しているコマンドは git status && ls && cat VERSION"
のみ
ただ,このタスクの実行前にgitリポジトリのリソースを入力Artifactとして/src
配下に配置している
今回は myOrg/myRepo
リポジトリのmasterブランチをクローンしたいので以下のようになる
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: input-artifact-git-
spec:
entrypoint: git-clone
templates:
- name: git-clone
inputs:
artifacts:
- name: argo-source
# リポジトリの中身を配置するディレクトリ
path: /src
# gitリポジトリ指定
git:
repo: https://github.com/myOrg/myRepo.git
revision: "master"
container:
image: golang:1.10
command: [sh, -c]
args: ["git status && ls && cat VERSION"]
workingDir: /src
プライベートリポジトリからクローンする
前段の方法ではパブリックリポジトリしかクローンできない
プライベートリポジトリからクローンする場合にはgitの認証情報を登録する必要がある
再びinput-artifact-git.yamlを参考にすると下記のようになる
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: input-artifact-git-
spec:
entrypoint: git-clone
templates:
- name: git-clone
inputs:
artifacts:
- name: argo-source
# リポジトリの中身を配置するディレクトリ
path: /src
# gitリポジトリ指定
git:
repo: https://github.com/myOrg/myRepo.git
revision: "master"
# gitの認証情報を指定
# kubernetes Secretから github-creds.usernameを取得する
usernameSecret:
name: github-creds
key: username
# kubernetes Secretから github-creds.passwordを取得する
passwordSecret:
name: github-creds
key: password
container:
image: golang:1.10
command: [sh, -c]
args: ["git status && ls && cat REDOME.md"]
workingDir: /src
パイプラインの定義ファイルに直接認証情報を書くのではなくKubernetesのSecretsに格納された認証情報を呼び出す
今回は github-credsに usernameとpasswordという名前で登録しておく
動かす
argo submit input-artifact-git.yaml
ちゃんとクローンできた
完成
とりあえずgitプライベートリポジトリからクローンができるところまで完成
この後testだったりbuildだったりを記述していく
ここから先は他のciツールと大差ない(と思っている)
つまづいたところは,
- Secret内の認証情報をタスク内で参照するところ
- admin権限を付与するサービスアカウントを間違えていたこと
- タスク内でechoやprintした内容が各podのログに出力されていたこと
各タスクのログはタスクを実行するPodに出力されるのでエラーが起きた際には,
どのタスク内でパイプラインが止まったのかを見て,そのPodの中に入るといった手順が必要
stern などのPod横断で監視できるツールを導入するのが良さそう
そのあと
gitクローンだけではCIとはとても呼べないので,このあとはクローンしたリソースを使ってtest/build/imageプッシュをしていく
また,手動でパイプラインを動かしているのでgithubのwebhookを使って,masterブランチのpushをトリガーにパイプラインの実行ができるようにargo events
を導入する