概要
ArgoCDを使ってプルリクエスト毎にインフラ環境を起動したのでメモ
argo-cd.readthedocs.io
前提
使用ツール
- Kubernets
- Istio
- ArgoCD
- Helm
- aqua.yamlの抜粋
- name: istio/istio/istioctl@1.17.2 - name: kubernetes/kubectl@v1.26.3 - name: argoproj/argo-cd@v2.6.7 - name: helm/helm@v3.11.2
設計
- Pull Request毎にService,Deployment etcを構築する
- Pull Request毎にRoute53レコードを作成する
- アクセス制御はIstioのVirtual Serviceを使う
- DB、キャッシュは共通のものを使う
- アプリケーションリポジトリはモノレポ構成であり、複数のアプリケーションを起動する
ワークフロー
- アプリケーションリポジトリでPull Requesetを作成する
- 変更されたアプリケーションコードを検知して自動でラベルを付与する
例:foo-api,bar-apiなど - 手動でpreviewラベルを貼るとArgoCDが検知してインフラリソースを作成する
- リソースが作成されたらPull ReqeustにURLがコメントされる
Application Setの実装イメージ
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: preview spec: goTemplate: true generators: - pullRequest: github: owner: hogeOrg repo: fugaRepo labels: - preview requeueAfterSeconds: 1800 template: metadata: name: "preview-{{ .number }}" spec: ignoreDifferences: - group: "*" kind: ConfigMap namespace: hoge jsonPointers: - /data sources: - repoURL: "https://github.com/hogeOrg/fugaRepo.git" targetRevision: main ref: repo - repoURL: "ghcr.io/hogeOrg/fugaRepo" targetRevision: 0.0.1 chart: app-a helm: releaseName: app-a-{{ .number }} valueFiles: - $repo/clusters/dev/apps/app-a/values.yaml - secrets://https://$${GITHUB_TOKEN}@raw.githubusercontent.com/hogeOrg/fugaRepo/main/clusters/dev/apps/app-a/values.secrets.yaml parameters: - name: nameOverride value: "app-a-{{ .number }}" - name: "image.tag" value: >- {{if has "app-a" .labels -}} sha-{{ substr 0 7 .head_short_sha }} {{- else -}} main {{- end -}} - name: "image.pullPolicy" value: Always - name: "app.datadogServiceName" value: "app-a-{{ .number }}" values: | resources: requests: cpu: 500m - repoURL: "ghcr.io/hogeOrg/fugaRepo" targetRevision: 0.0.1 chart: virtual-service helm: releaseName: virtual-service-{{ .number }} parameters: - name: nameOverride value: api-virtual-service-{{ .number }} values: | annotations: external-dns.alpha.kubernetes.io/target: gateway.hoge.fuga.com external-dns.alpha.kubernetes.io/alias: "true" hosts: - api-{{ .number }}.hoge.fuga.com httpRoutes: - match: - uri: prefix: /app-a route: - destination: host: app-a-{{ .number }}.hoge.svc.cluster.local port: number: 8000 - match: - uri: prefix: / route: - destination: host: api.hoge.fuga.com port: number: 443 - chart: app-b repoURL: "ghcr.io/hogeOrg/fugaRepo" targetRevision: 0.0.1 helm: releaseName: app-b-{{ .number }} parameters: - name: "nameOverride" value: app-b-{{ .number }} - name: "image.tag" value: >- {{if has "app-b" .labels -}} sha-{{ substr 0 7 .head_short_sha }} {{- else -}} main {{- end -}} - name: "app.datadogServiceName" value: "app-b-{{ .number }}" valueFiles: - $repo/clusters/dev/apps/app-b/values.yaml - secrets://https://$${GITHUB_TOKEN}@raw.githubusercontent.com/hogeOrg/fugaRepo/main/clusters/dev/apps/app-b/values.secrets.yaml values: | resources: requests: cpu: 500m project: "hoge" destination: server: https://kubernetes.default.svc namespace: hoge syncPolicy: syncOptions: - CreateNamespace=true - RespectIgnoreDifferences=true automated: selfHeal: true prune: true
ポイント
一意なリソースを作成する
hosts: - api-{{ .number }}.hoge.fuga.com
識別子にプルリクエスト番号を入れておくことで独立した環境を構築する
イメージの動的な更新
- name: nameOverride value: "app-a-{{ .number }}" - name: "image.tag" value: >- {{if has "app-a" .labels -}} sha-{{ substr 0 7 .head_short_sha }} {{- else -}} main {{- end -}}
このように書いておくことで、
- アプリケーションコードが変更されている場合はプルリクエスト内で変更されたイメージタグ
- アプリケーションコードが変更されていない場合はmainタグ
を利用できる。
ArgoCDのApplicationSetはGo templateを利用できる。
https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/GoTemplate/
Virtual Serviceによるリクエスト制御
IstioのVirtual Serviceを使うことでインフラリソースを短い時間で作成できる。
PRを立ち上げたときに時間がかかるリソースは作らないような設計にする。(ロードバランサー、データベースなどなど)
まとめ
過去やったことをざっくりまとめた。 K8sはエコシステムが充実しているので楽。