DevOpsプラットフォームの全ステージで使えるGitLabの技10選 #GitLab #DevOps
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本ブログは「GitLab」社のブログで2021年10月19日に公開された「Top ten GitLab hacks for all stages of the DevOps Platform」の日本語翻訳です。
DevOpsプラットフォームの全ステージで使えるGitLabの技10選
投稿者:Michael Friedrich
GitLabの最初のコミットから10年が経ちました。そこで今日は、DevOpsプラットフォームで最大限活用できる、GitLabの技10選をご紹介します。 開発ライフサイクルのすべてのステージで役立つTIPSです。腕をまくって、さぁ始めましょう!
クイックアクションでより素早く「管理」
ナビゲーションやワークフローを高速化するために、すでにキーボードショートカットをお使いの方もいるかもしれません。まだの方は、GitLabドキュメントからプラットフォーム固有のショートカットをご覧ください。 テキストのコメントフォームへ返信する際に r を押している方は、次のようなクイックアクションを組み合わせることもできます:
/assign_reviewer @ <search username> /label ~ <search label> /label ~enhancement ~workflow::indev /due Oct 8 /rebase /approve /merge
また、多くのイシュー、マージリクエスト、エピックを同時に管理しなければならない場合にも、クイックアクションは便利です。 例えば、既存のイシューを複製する専用のクイックアクションもあります。
クイックアクションについては、こちらで詳しく説明しています。
テンプレートを使用したインストラクションの「計画」
開発チームがエラーを最善の方法で再現させるべく、詳細情報を参照するためにイシュー説明に行ったり来たりしても、結局重要な情報が記載されていない空のイシューだったというような罠に陥ってはいけません。
GitLabでは、いわゆるイシューテンプレートをイシューやマージリクエストで使用できます。
見出しで構造化されたテンプレートだけでなく、タスクリストも追加でき、後に担当者がチェックを入れられます。 基本的にはあらゆることが可能で、GitLab Flavored Markdown(GitLab風マークダウン)とHTMLに対応しています。
さらに、静的なイシューテンプレートとクイックアクションを組み合わせることも可能です。
このようにすることでラベルや担当者、期日などを自動的に設定できるので、GitLabを使う生産性が一段向上します。
<!-- ここはコメントです、Markdownエンジンはレンダリングしません。テンプレートの記入方法をここで説明してください。 --> ### 概要 <!-- 発見したバグの概要を簡潔に要約してください。 --> ### 再現手順 <!-- 問題を再現する方法を記載してください - これは非常に重要です。 --> ### チェックリスト <!-- GitLab.com 上でのバグを報告している場合「このバグは GitLab.com で発生する」と記載してください。 --> #### GitLab 環境に関する情報 <!-- 必要に応じて GitLab 環境に関して適切な情報を記載してください。 --> <details> <summary>展開してアプリに関する情報を表示</summary> <pre> (アプリのバージョンの詳細をここに貼り付けてください) </pre> </details> ### 考えられる修正方法 <!-- 可能なら、コードへのリンクと修正方法を提案してください。 --> ## メンテナーのタスク - [ ] 問題再現 - [ ] ウェイト付与 - [ ] テストで修正を確認 - [ ] ドキュメントの更新要 /label ~"type::bug"
異なるタイプのテンプレートを管理する場合、 issuable_template パラメータでテンプレートの名前を指定することができます。(例: https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal%20%23%20lean )
GitLabでは、イシューやマージリクエストのテンプレートを様々な形で使用しています。GitLabプロジェクト、GitLab全社マーケティングチーム、GitLab社員オンボーディングおよびGitLabプロダクトマネジメントチームはほんの一例です。
自信を持って「作成」
GitLabのイシューやマージリクエストを見ると、 Merge When Pipeline Succeeds を意味する MWPS という略語を目にすることがあります。 これは、パイプラインがすべてのジョブとステージをパスした際に、MR(マージリクエスト)をマージさせる効率良い方法です。また、このワークフローとMRからのキーワードとを組み合わせて、イシューを自動的にクローズさせることも可能です。
Merge When Pipeline Succeeds は、CLIで git コマンドとpush オプションを使っても動作します。この方法で、ローカルのGitブランチからマージリクエストを作成し、パイプラインが成功したときにマージするよう設定可能です。
# mwps BRANCHNAME alias mwps='git push -u origin -o merge_request.create -o merge_request.target=main -o merge_request.merge_when_pipeline_succeeds'
我々のCEOであるSid Sijbrandijのdotfilesリポジトリにある、ZSHエイリアスの例をご覧ください。 この他にも様々なプッシュのオプションがあり、さらに多くのGit CLIのTIPSが tools & tips ハンドブックに掲載されています。
最後にTIPをもう1つ:MRをマージした後などに、リモートブランチが削除されたすべてのローカルブランチを削除する方法
# 上流ブランチが削除されているGitのリモートトラッキングブランチを全て削除 alias git_prune="git fetch --prune && git branch -vv | grep 'origin/.*: gone]' | awk '{print \$1}' | xargs git branch -d"
ローカルのCLI環境に限る必要はありません。Gitpodを使用してクラウドに保存し、クラウド上のVS Codeやpod terminalで使うことも可能です。
CI/CDパイプラインで「検証」
.gitlab-ci.yml に変更をコミットして、それが有効か、あるいはジョブテンプレートが本当にすべての属性を継承しているかを確認していた当時の、古いワークフローを皆さんはまだ覚えていますか?新しいパイプラインエディターにより、この作業は非常に簡単になりました。今すぐ CI/CD メニューに移動してCI/CDパイプラインの構築を開始してみてください。
しかし、このエディタは単なるYAMLエディタではありません。ライブ・リントにより、配列リストのダッシュが抜けていないか、間違ったキーワードが使われていないかなどを、コミットする前に確認できます。また、ジョブやステージ、パイプラインを効率化する needs による非同期の依存関係もプレビューできます。
パイプラインエディターはまた、jqとCI/CD lintingに関するこのブログ記事で以前に説明したように、 /ci/lint API エンドポイントを使用してマージされたYAML設定をフェッチします。こうすることで、extendsと!reference タグを持つジョブテンプレートが、設計した通りに動作することを素早く検証できます。また、インクルードされたファイルや、インクルードされたSASTセキュリティテンプレートのステージの変更といったジョブのオーバーライドの展開も可能になります。
簡単な例をやってみましょう。新規プロジェクトを作成し、 server.c という新しいファイルを次の通りに作成します:
#include <stdio.h> #include <string.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> int main(void) { size_t pagesize = getpagesize(); char * region = mmap( (void*) (pagesize * (1 << 20)), pagesize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0); strcpy(region, "Hello GitLab SAST!"); printf("Contents of region: %s\n", region); FILE *fp; fp = fopen("devops.platform", "r"); fprintf(fp, "10 years of GitLab 🦊 🥳"); fclose(fp); chmod("devops.platform", S_IRWXU|S_IRWXG|S_IRWXO); return 0; }
CI/CDパイプラインエディターを開き、次のように設定を追加します。SASTとCコードのために semgrep-sast ジョブに追加の secureステージを割り当てましょう。
stages: - build - secure - test - deploy include: - template: Security/SAST.gitlab-ci.yml semgrep-sast: stage: secure
Merged YAML タブ を開いて完全にコンパイルされたCI/CD設定を確認します。変更をコミットして、見つかった脆弱性を非同期で確認することもできます。 この例題はこのプロジェクトに置いてあります。
アプリケーションの「パッケージ化」
パッケージレジストリが持つ可能性は非常に大きく、今後さらに多くの言語やパッケージマネージャーがリリースされる予定です。インフラストラクチャではTerraform、Helm、コンテナ、アプリケーションではMaven、npm、NuGet、PyPI、Composer、Conan、Debian、Go、Ruby Gemsが非常に素晴らしく語りつくせないほどですが、多くの選択肢があるということは明らかです。
私のお気に入りの ワークフローの一つは、既存の CI/CD テンプレートを使って GitLabのコンテナレジストリにコンテナイメージを公開するものです。これにより、アプリケーションをKubernetesクラスターやAWSインスタンスにデプロイする際などに、より効率的な継続的デリバリーが可能になります。
include: - template: 'Docker.gitlab-ci.yml'
CI/CDテンプレートをただインクルードするだけでなく、ジョブの属性をオーバーライドしたり、特定のステージやノンブロッキングな手動実行のルールを定義することもできます。
stages: - build - docker-build - test include: - template: 'Docker.gitlab-ci.yml' # Change Docker build to manual non-blocking docker-build: stage: docker-build rules: - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH' when: manual allow_failure: true
#GitLab10周年を記念して、時間計算に隠れた仕掛けがあるC++のサンプルを作成しました。このプロジェクトでもDocker builderイメージを使用して、より効率的なパイプラインを紹介しています。お勧めは、テスト用のリポジトリでテンプレートの使い方を学び、それから必要なコンテナイメージをすべて管理する専用のグループやプロジェクトを作るというやり方です。コンパイラのツールチェーンを含むビルダーイメージや、エンドツーエンドのテストを実行する特定のスクリプトなどが考えられます。
シークレットの「保護」
ユニットテストを簡略化して本番環境のデータベースで直接実行するような選択をしてしまうと、簡単に暗号鍵や認証トークンなどのシークレットの漏洩を招きます。シークレットがgitの履歴に残るので、個人情報にアクセスしたり、サプライチェーンをさらに悪用する人が出てきます。
防止策として、シークレット検出用CI/CDテンプレートを使用してみましょう。
stages: - test include: - template: Security/Secret-Detection.gitlab-ci.yml
シークレットをリークしてしまうやり方でよく知られているのが、設定とシークレットをリポジトリに保存する .env ファイルをコミットしてしまうということです。以下のスニペットを新しいファイル .env として追加してマージリクエストを作成してみてください。
export AWS_KEY="AKIA1318109798ABCDEF"
レポートのJSONを見て、未加工のレポート構造を確認できます。GitLab Ultimateなら、MRへの統合、セキュリティダッシュボードによる概観など、問題に即応できる機能もご利用いただけます。このプロジェクトでその例を見ることができます。
継続的デリバリー(CD)と「リリース」
カナリアデプロイメントやGitLabページなど、GitLabのリリースステージでは多くの機能が提供されています。また、Terraformによるインフラストラクチャーのデプロイや保護されたクラウドネイティブ環境もあります。
以前、CI/CDパイプラインの効率化ワークショップを作成した際に、ノンブロッキングな子パイプラインを本番環境に許可する親子パイプラインに夢中になって取り組みました。一例として、Kubernetesでのマイクロサービスを題材にしました。
では、やってみましょう!まず新しいプロジェクトを作成し、 child-deploy-staging.yml と child-deploy-prod.yml の2つの子パイプライン設定ファイルを追加します。このファイルは、後ほどメインの .gitlab-ci.yml 設定ファイルで参照するので、名前が重要になります。子パイプラインのジョブは、デプロイをシミュレートするために60秒間スリープします。
child-deploy-staging.yml:
deploy-staging: stage: deploy script: - echo "Deploying microservices to staging" && sleep 60
child-deploy-prod.yml
deploy-prod: stage: deploy script: - echo "Deploying microservices to prod" && sleep 60 monitor-prod: stage: deploy script: - echo "Monitoring production SLOs" && sleep 60
では、 .gitlab-ci.yml 設定ファイルを編集し、ビルド - テスト - デプロイステージのワークフローを作成します。
stages: - build - test - deploy build: stage: build script: echo "Build" test: stage: test script: echo "Test" deploy-staging-trigger: stage: deploy trigger: include: child-deploy-staging.yml #rules: # - if: $CI_MERGE_REQUEST_ID deploy-prod-trigger: stage: deploy trigger: include: child-deploy-prod.yml #strategy: depend #rules: # - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
変更をコミットし、CI/CDパイプラインを確認します。
strategy: depends により、子パイプラインを再びブロッキングにし、親子パイプラインが再び待機するようにできます。prodジョブでこのコメントを解除し、パイプラインビューで検証してみてください。rulesでは、ジョブが実行される範囲を絞り込むことができます。例えば、ステージング子パイプラインはマージリクエスト時にのみ実行させ、本番環境の子パイプラインはデフォルトのメインブランチでのみトリガーさせる場合などです。例全体はこちらのプロジェクトをご覧ください。
TIP:resource_groupsを使用すると、本番環境のデプロイで子パイプラインの同時実行を制限できます。
インフラストラクチャーの「構成」
Terraformのワークフローでは、複数のステップにわたって状態ファイルを保存する必要があります。そこで、HTTPバックエンドである "GitLab managed Terraform state" (GitLabで管理されたTerraformの状態)が大変役に立ちます。定義済みのコンテナイメージやCI/CDテンプレートとともに、Infrastructure as codeを可能な限りスムーズにすることができます。
テンプレートをカスタマイズするか、CI/CD の設定を .gitlab-ci.yml にコピーして、ご自身で手順を編集することもできます。AWSアカウントとIAMユーザーキーペアのみで簡単な例を試してみましょう。 Settings > CI/CD > Variables で、CI/CDの変数 AWS_ACCESS_KEY_ID および AWS_SECRET_ACCESS_KEY を設定します。
次に、 backend.tf ファイルを作成し、httpバックエンドとAWSモジュールの依存関係を指定します。
terraform { backend "http" { } required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } } }
AWSのリージョンを指定する provider.tf を作成します。
provider "aws" { region = "us-east-1" }
main.tf には、S3バケットのリソースが記述されています。
resource "aws_s3_bucket_public_access_block" "publicaccess" { bucket = aws_s3_bucket.demobucket.id block_public_acls = false block_public_policy = false } resource "aws_s3_bucket" "demobucket" { bucket = "terraformdemobucket" acl = "private" }
TIP:上記のHTTPバックエンドをコメントアウトすることで、ローカルのCLI上で設定を確認できます。
GitLab CI/CDの方は、パイプラインエディターを開き以下の設定をします。(なお、Terraformステートファイルは複数を管理できるので、 TF_ROOT と TF_ADDRESS 変数を指定することが重要です。)
variables: TF_ROOT: ${CI_PROJECT_DIR} TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_PROJECT_NAME} include: - template: Terraform.latest.gitlab-ci.yml stages: - init - validate - build - deploy - cleanup destroy: stage: cleanup extends: .terraform:destroy when: manual allow_failure: true
設定をコミットし、パイプラインジョブを確認します。
destroy ジョブはテンプレートでは作成されていないため、手動のジョブとして明示的に追加してあります。このために用意されたTerraform CI/CDテンプレートを確認し、ジョブをご自身の設定にコピーすれば、さらなる変更やスタイル調整が可能になるのでお勧めです。例全体は こちらのプロジェクトをご覧ください。
Prometheusを活用してGitLabで「監視」
Prometheusは、アプリケーションが用意した /metrics HTTPエンドポイントや、サービスやホストの情報を、指定されたメトリクス・フォーマットで提供する、いわゆるエクスポーターから、メトリクスを収集するモニタリング・ソリューションです。一例は、CI/CDパイプライン・インサイトで、ボトルネックを分析し、パイプラインをより効率的にするということです。GitLab CIパイプライン エクスポータープロジェクトでは、Docker-compose、Prometheus、Grafanaを使ったデモセットアップが、5分もかからずあっという間にスタートできます。そこからは、本番の監視環境を構築し、さらにGitLabでモニタリングするのは、すぐです。
Prometheusエクスポーターは、Goクライアントライブラリを使用します。独自のエクスポーターを作成したり、 /metrics を公開するようにアプリケーションコードを実装する際に使用できます。デプロイされたら、再度Prometheusを使用し、例えばKubernetes上のアプリケーションのパフォーマンスを監視したりできます。 さらに他のモニタリングのアイデアに関しては、私の講演スライド「モニタリングからオブザーバビリティへ:SLOをシフトレフトする」をご覧ください。
「防御」
GitLabのCI/CDテンプレートを一つ一つ挿入していくことで、セキュリティ機能を有効にできます。Auto DevOpsを有効にして、セキュリティスキャンにデフォルトのベストプラクティスを適用することで、より簡単に進められます。コンテナスキャンで、アプリケーションのデプロイがコンテナOSレベルで脆弱でないかという確認もできます。
脆弱性が含まれているかもしれないイメージと、上記「パッケージ化」のステージで紹介したDockerテンプレートのTIPを使って、簡単な例を試してみましょう。
新しいプロジェクトで、 Dockerfile を作成します。
FROM debian:10.0
パイプラインエディターを開き、次のCI/CD設定を追加します。
# 1. Automatically build the Docker image # 2. Run container scanning. https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html # 3. Inspect `Security & Compliance > Security Dashboard` # For demo purposes, scan the latest tagged image from 'main' variables: DOCKER_IMAGE: $CI_REGISTRY_IMAGE:latest include: - template: Docker.gitlab-ci.yml - template: Security/Container-Scanning.gitlab-ci.yml
例全体は こちらのプロジェクトをご覧ください。
TIP:さらに安全性を高める方法についてはデプロイされたKubernetesクラスター内のコンテナイメージをスキャンするをご覧ください。
さて次は…?
DevOpsライフサイクルのそれぞれのステージで役立つ便利な技を探してきました。 GitLabには、さらなる技や知られざる裏技がまだまだあります。ぜひ皆さんの技も共有し、DevOpsプラットフォームのステージをさらに探っていきましょう。