レビューアプリ

レビューアプリはパイプラインによって自動的にデプロイされます。

どのように機能するのですか?

CI/CDアーキテクチャ図

graph TD A["build-qa-image, gitlab:assets:compile pull-cache
(canonical default refs only)"]; B[review-build-cng]; C[review-deploy]; D[CNG-mirror]; E[review-qa-smoke]; A -->|once the `prepare` stage is done| B B -.->|triggers a CNG-mirror pipeline and wait for it to be done| D D -.->|polls until completed| B B -->|once the `review-build-cng` job is done| C C -->|once the `review-deploy` job is done| E subgraph "1. gitlab `prepare` stage" A end subgraph "2. gitlab `review-prepare` stage" B end subgraph "3. gitlab `review` stage" C["review-deploy

Helm deploys the Review App using the Cloud
Native images built by the CNG-mirror pipeline.

Cloud Native images are deployed to the `review-apps`
Kubernetes (GKE) cluster, in the GCP `gitlab-review-apps` project."] end subgraph "4. gitlab `qa` stage" E[review-qa-smoke

gitlab-qa runs the smoke suite against the Review App.] end subgraph "CNG-mirror pipeline" D>Cloud Native images are built]; end

詳細説明

  1. test ステージでは、パイプラインごとにgitlab:assets:compile のジョブが自動的に開始されます。
    • それが完了すると、次のステップでトリガーされるCNG-mirror パイプラインがそれに依存するため、review-build-cng手動ジョブを開始します。
  2. review-build-cng ジョブはCNG-mirror プロジェクトのパイプラインをトリガーします。
    • CNG-mirror パイプラインは、GitLab パイプラインからのコミットに基づいて、各コンポーネントの Docker イメージ (gitlab-rails-ee,gitlab-shell,gitaly など) を作成し、レジストリに保存します。
    • CNG, (Cloud Native GitLab)プロジェクトのレジストリに多くの一時的なDockerイメージが過負荷にならないように、CNG-mirror プロジェクトを使用しています。
    • 公式CNG画像は、cloud-native-imageジョブによってビルドされます。このジョブはタグのためだけに実行され、CNG パイプラインをトリガーします。
  3. test ステージが完了したら、review-deploy ジョブは公式 GitLab Helm チャートを使ってレビューアプリを GCP 上のreview-appsKubernetes クラスタにデプロイします。
  4. review-deploy ジョブが成功すると、MR ウィジェットからレビューアプリに直接リンクされるため、レビューアプリを使用できるようになります。 レビューアプリにログインするには、以下の「レビューアプリにログインしますか?

追記

  • review-deploy ジョブが失敗し続ける場合 (すでに 2 回再試行していることに注意してください)、#g_qe_engineering_productivity チャンネルにメッセージを投稿するか、マージリクエストへのリンクを含む~"Engineering Productivity" ~"ep::review apps" ~bugイシューを作成してください。 デプロイの失敗によって、マージリクエストで導入された実際の問題が明らかになる可能性があることに注意してください (つまり、これは必ずしも一過性の失敗ではありません)!
  • review-qa-smoke のジョブが失敗し続ける場合 (すでに2回リトライしていることに注意してください)、ジョブのログをチェックしてください: あなたのマージリクエストで導入された実際の問題を発見できるかもしれません。 また、失敗が発生したときのページのスクリーンショットを見るためにアーティファクトをダウンロードすることもできます。 失敗の原因が見つからない場合、もしくはあなたの変更とは無関係と思われる場合、#quality チャンネルにメッセージを投稿するか、もしくはあなたのマージリクエストへのリンクを含む ~Quality ~bug issue を作成してください。
  • 手動review-stop はレビューアプリを手動で停止させるのに使えます。また、マージリクエストのブランチがマージ後に削除されると、GitLab によって開始されます。
  • Kubernetesクラスタは、GitLabのKubernetesインテグレーションを使ってgitlab-{ce,ee} プロジェクトに接続されています。 これにより、基本的にマージリクエストウィジェットから直接レビューアプリにリンクすることができます。

レビューアプリの自動停止

レビューアプリは、環境自動停止機能により、最後のデプロイから2日後に自動的に停止します。

レビューアプリをより長い時間立ち上げておく必要がある場合は、その環境を固定するか、review-deploy ジョブを再試行して「最新のデプロイ時」に更新することができます。

スケジュールされたパイプラインで自動的に実行されるreview-cleanup ジョブ (マージリクエストでは手動) は、5日後に古いレビューアプリを停止し、6日後にその環境を削除し、7日後にぶら下がっている Helm リリースと Kubernetes リソースをクリーンアップします。

スケジュールされたパイプラインで自動的に実行される(マージリクエストでは手動で実行される)review-gcp-cleanup ジョブは、Kubernetes リソースと一緒に削除されなかったぶら下がっている GCP ネットワークリソースを削除します。

QAラン

qa ステージ (review ステージの後) のすべてのパイプラインでreview-qa-smoke ジョブが自動的に開始され、QA スモークスイートが実行されます。

手動でreview-qa-allを起動することもできます:完全なQAスイートを実行します。

パフォーマンス・メトリクス

qa ステージのすべてのパイプラインでreview-performance ジョブが自動的に開始されます。このジョブは、Sitespeed.ioコンテナを使用して基本的なブラウザのパフォーマンステストを行います。

クラスター構成

ノードプール

review-apps クラスターは現在、以下のノードプールでセットアップされています:

  • e2-highcpu-16 (16vCPU、16GBメモリ)プリエンプティブノード、オートスケーリング機能付き

Helm

使用される Helm のバージョンは、review-deployreview-stop のジョブで使用されるregistry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14 イメージで定義されています。

どのように

GCPレビューアプリクラスターへのアクセス

gcp-review-apps-sg GCPグループへのアクセスリクエスト(内部リンク)を開く必要があります。 グループに参加するには、アクセスリクエストで希望するGCPロールを指定する必要があります。 ロールは、レビューアプリコンテナに参加するための特定の権限を付与するものです。

以下は、あなたが持ちたいと思う権限と、それを与えるロールです:

レビューアプリへのログイン

デフォルトのユーザー名はroot で、パスワードは 1Password セキュアノートgitlab-{ce,ee} Review App's root passwordに記載されています。

レビューアプリの機能フラグを有効にします。

  1. レビューアプリを開き、上記の手順でログインします。
  2. 個人アクセストークンを作成します。
  3. 機能フラグAPIを使用して機能フラグを有効にします。

レビューアプリのスラッグを探す

  1. review-deploy ジョブを開きます。
  2. Checking for previous deployment of review-*を探してください。
  3. 例えばChecking for previous deployment of review-qa-raise-e-12chm0の場合、レビューアプリのスラッグはreview-qa-raise-e-12chm0 となります。

Railsコンソールの実行

  1. まずクラスターへのアクセス権限とcontainer.pods.exec 権限があることを確認してください。
  2. レビューアプリのスラッグ(例:review-qa-raise-e-12chm0)でワークロードをフィルタリングします。
  3. review-qa-raise-e-12chm0-task-runnerなど、task-runner デプロイを見つけて開いてください。
  4. 管理対象ポッド」セクションのポッドをクリックします(例:review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz)。
  5. KUBECTL ドロップダウンをクリックし、Exec ->task-runner
  6. -c task-runner -- ls をデフォルトコマンドの-it -- gitlab-rails console に置き換えるか、または
    • kubectl exec --namespace review-apps review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console を実行してください。
      • review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvzをポッドの名前に置き換えてください。

ポッドの過去ログを探る

  1. まずクラスターへのアクセス権限とcontainer.pods.getLogs 権限があることを確認してください。
  2. レビューアプリのスラッグ(例:review-qa-raise-e-12chm0)でワークロードをフィルタリングします。
  3. review-qa-raise-e-12chm0-migrations.1など、migrations デプロイを見つけて開いてください。
  4. 管理対象ポッド」セクションのポッドをクリックします(例:review-qa-raise-e-12chm0-migrations.1-nqwtx)。
  5. Container logs リンクをクリックしてください。

不健康なレビューアプリのリリース診断

レビューアプリの安定性が低下した場合は、review-apps-ce/ee クラスターが不健全であることを示すシグナルである可能性があります。先行指標としては、再起動につながるヘルスチェックの失敗や、レビューアプリのデプロイの大半の失敗が考えられます。

レビューアプリの概要ダッシュボードは、クラスターの負荷スパイクを特定し、ノードに問題がある場合やクラスター全体が不健全な傾向にある場合に役立ちます。

でリリースに失敗しました。ImagePullBackOff

考えられる原因

ImagePullBackoff ステータスが表示された場合は、Docker イメージが不足していないか確認してください。

さらなるデバッグのための場所

Dockerイメージが作成されたことを確認するには、以下のDockerコマンドを実行します:

`DOCKER_CLI_EXPERIMENTAL=enabled docker manifest repository:tag`

このコマンドの出力は、Dockerイメージが存在するかどうかを示します。 例えば、以下のようになります:

DOCKER_CLI_EXPERIMENTAL=enabled docker manifest inspect registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-rails-ee:39467-allow-a-release-s-associated-milestones-to-be-edited-thro

Dockerイメージが存在しない場合:

  • helm upgrade --install コマンドのimage.repositoryimage.tag オプションが、CNG-mirror パイプラインで使用されるリポジトリ名と一致していることを確認します。
  • review-build-cng ジョブの対応する下流のCNG-ミラーパイプラインをさらに見てください。

ノード数は常に増加(つまり、安定することも減少することもない)

考えられる原因

これはreview-cleanup ジョブが古いレビューアプリと Kubernetes リソースのクリーンアップに失敗しているサインかもしれません。

さらなるデバッグのための場所

最新のreview-cleanup ジョブログを見て、予期せぬ障害が発生していないか確認してください。

p99のCPU使用率は、ほとんどのノードおよび/または多くのコンポーネントで100%です。

考えられる原因

これは、Helmがレビューアプリのデプロイに失敗している兆候かもしれません。HelmにFAILED リリースが多い場合、CPU使用率が増加しているようですが、これはおそらくHelmまたはKubernetesがコンポーネントを再作成しようとしているためです。

さらなるデバッグのための場所

最近のreview-deploy のジョブ・ログを見てください。

便利なコマンド

# Identify if node spikes are common or load on specific nodes which may get rebalanced by the Kubernetes scheduler
kubectl top nodes | sort --key 3 --numeric

# Identify pods under heavy CPU load
kubectl top pods | sort --key 2 --numeric

logging/user/events/FailedMount チャートが上昇しています。

考えられる原因

これは、古いシークレットやコンフィギュレーションマップが多すぎるサインかもしれません。

さらなるデバッグのための場所

コンフィギュレーションまたはkubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-'のリストを見てください。

5日以上前のシークレットや構成マップは疑わしいので削除してください。

便利なコマンド

# List secrets and config maps ordered by created date
kubectl get secret,cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-'

# Delete all secrets that are 5 to 9 days old
kubectl get secret --sort-by='{.metadata.creationTimestamp}' | grep '^review-' | grep '[5-9]d$' | cut -d' ' -f1 | xargs kubectl delete secret

# Delete all secrets that are 10 to 99 days old
kubectl get secret --sort-by='{.metadata.creationTimestamp}' | grep '^review-' | grep '[1-9][0-9]d$' | cut -d' ' -f1 | xargs kubectl delete secret

# Delete all config maps that are 5 to 9 days old
kubectl get cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' | grep -v 'dns-gitlab-review-app' | grep '[5-9]d$' | cut -d' ' -f1 | xargs kubectl delete cm

# Delete all config maps that are 10 to 99 days old
kubectl get cm --sort-by='{.metadata.creationTimestamp}' | grep 'review-' | grep -v 'dns-gitlab-review-app' | grep '[1-9][0-9]d$' | cut -d' ' -f1 | xargs kubectl delete cm

K9の使用

K9sは、ラベルでフィルタリングできる強力なコマンドラインダッシュボードです。 これは、レビューアプリのリソース要求を超えるアプリの傾向を特定するのに役立ちます。 Kubernetesは、リソース要求に基づいてポッドをノードにスケジューリングし、上限までのCPU使用を許可します。

  • K9sでは、/ 文字を入力することで、並べ替えやフィルタの追加ができます。
    • -lrelease=<review-app-slug> - これは、1つのデプロイで何が問題になっているかを判断するのに役立ちます。
    • -lapp=<app> - これは、アプリごとのリソース使用量を判断するのに役立ちます。
  • Kubernetesリソースまでスクロールし、d(describe)、s(shell)、l(logs)をクリックすると、より深く調べることができます。

K9s

保留中のdns-gitlab-review-app-external-dns デプロイのトラブルシューティング

問題の発見

過去にdns-gitlab-review-app-external-dns デプロイが保留状態になり、すべてのレビューアプリに DNS レコードが割り当てられず、ドメイン名でアクセスできなくなることがありました。

その結果、レビューアプリの他のコンポーネントが正しく起動しなくなりました(例:gitlab-runner)。

いくつかの調査の結果、systemd-mountのトランジェント・スコープ(ポッドなど)を使用した場合、新しいマウントが失敗することがわかりました:

MountVolume.SetUp failed for volume "dns-gitlab-review-app-external-dns-token-sj5jm" : mount failed: exit status 1
Mounting command: systemd-run
Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm --scope -- mount -t tmpfs tmpfs /var/lib/kubelet/pods/06add1c3-87b4-11e9-80a9-42010a800107/volumes/kubernetes.io~secret/dns-gitlab-review-app-external-dns-token-sj5jm
Output: Failed to start transient scope unit: Connection timed out

これはおそらく、GitLabのChartが67個のリソースを作成し、基盤となるGCPノードに多くのマウントポイントが作成されたために起こったと思われます。

根本的なイシューは、systemd のバグで、systemd v237で修正されたようです。 残念ながら、私たちのGCPノードは現在、v232を使用しています。

ちなみに、このイシューを発見するためのデバッグ手順は以下の通り:

  1. kubectlのコンテキストをreview-apps-ceに切り替えます(kubectxの使用をお勧めします)
  2. kubectl get pods | grep dns
  3. kubectl describe pod <pod name> 正確なエラーメッセージの確認
  4. 正確なエラーメッセージをウェブ検索し、関連するKubernetesバグレポートへのラビットホールをたどります。
  5. GCPコンソールからSSH経由でノードにアクセスします(Computer Engine > VMインスタンスの順にクリックし、dns-gitlab-review-app-external-dns ポッドが実行されているノードの「SSH」ボタンをクリックします)。
  6. ノード内部:systemctl --version =>systemd 232
  7. もっと情報を集めてください:
    • mount | grep kube | wc -l => 例:290
    • systemctl list-units --all | grep -i var-lib-kube | wc -l => 例:142
  8. 悪い状態のポッドがいくつあるか確認してください:
    • 指定したノードで動作しているすべてのポッドを取得します:kubectl get pods --field-selector=spec.nodeName=NODE_NAME
    • 指定したノード上のRunning ポッドをすべて取得します:kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running
    • 指定されたノードのバッド状態のポッドをすべて取得します:kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep -v 'Running' | grep -v 'Completed'

問題の解決

この問題を解決するためには、いくつかのノードから(強制的に)水を抜く必要がありました:

  1. Kubernetes が自動的に別のノードに移動するように、dns-gitlab-review-app-external-dnsポッドが実行されているノードで通常のドレインを試してください:kubectl drain NODE_NAME
  2. それでもうまくいかない場合は、すべてのポッドを削除してノードを強制的に「ドレイン」することもできます:kubectl delete pods --field-selector=spec.nodeName=NODE_NAME
  3. ノードの中で:
    • systemctl daemon-reload を実行し、死活ユニット/不活性ユニットを取り除きます。
    • それでも問題が解決しない場合は、ハード再起動を行ってください:sudo systemctl reboot
  4. コード化されたノードのコードを解除します:kubectl uncordon NODE_NAME

並行して、ほとんどのレビューアプリが壊れた状態にあったため、それらを削除してRunning 以外のポッドのリストを整理しました。以下は、最終デプロイ日(現在の日付は当時6月6日)に基づいてレビューアプリを削除するコマンドです。

helm ls -d | grep "Jun  4" | cut -f1 | xargs helm delete --purge

将来この問題を回避するために講じられた緩和策

今後、マシンが “マウントポイントが多すぎる “問題にぶつかる可能性が低くなるように、小さいマシンで新しいノードプールを作りました。

よくある質問

テスト実行のたびにCNGイメージのビルドをトリガーするのはやりすぎではありませんか? これでは何千もの未使用のDockerイメージができてしまいます。

また、CNG-mirrorプロジェクトを使ってDockerイメージを保存しているので、ある時点でレジストリを消去して、新しく空のものを使うことができます。

アプリは世界中に公開されているので、私たちだけに限定する方法を見つける必要があります。

これはフォークでは有効ではありません。

その他のリソース

便利なコマンドラインツール

  • K9s- ポッド全体でCLIダッシュボードを使用可能にし、ラベルによるフィルタリングを可能にします。
  • Stern- ラベル/フィールドセレクタに基づいてポッド間のログ尾行を可能にします。

テストドキュメントに戻る