1. 概要
Jenkins は、最も人気のある継続的インテグレーション ソリューションの一つです。ソフトウェア開発プロセスの人間以外の重要な部分を自動化するために使用されます。Jenkins を Google Cloud の Kubenetes にデプロイし、GKE プラグインを使用すると、必要に応じてビルド エグゼキュータを迅速かつ自動的にスケーリングできます。Cloud Storage と組み合わせることで、最小限の労力でアプリケーションを構築してテストできます。
演習内容
- Jenkins を Kubernetes クラスタにデプロイする
- Jenkins GKE プラグインをデプロイして構成し、Jenkins がエグゼキュータ ノードとして Pod を作成および破棄できるようにする
- サンプルの SpringBoot アプリケーションをビルドしてテストする
- コンテナをビルドして Google Container Registry に公開する
- サンプル アプリケーションをステージング環境と本番環境の GKE 環境にデプロイする
必要なもの
- 課金が設定されている Google Cloud プロジェクト。アカウントがない場合は、作成する必要があります。
2. 設定方法
この Codelab は、ローカルでのインストールや構成なしで Google Cloud Platform で完全に実行できます。
Cloud Shell
この Codelab では、Cloud Shell のコマンドラインを使用して、さまざまなクラウド リソースとサービスをプロビジョニングして管理します。
API を有効にする
プロジェクトで有効にする必要がある API は次のとおりです。
- Compute Engine API - 仮想マシンを作成して実行します。
- Kubernetes Engine API - コンテナベースのアプリケーションを構築して管理します。
- Cloud Build API - Google Cloud の継続的インテグレーションと継続的デリバリー プラットフォーム
- Service Management API - サービス プロデューサーが Google Cloud Platform でサービスを公開できるようにします。
- Cloud Resource Manager API - Google Cloud リソース コンテナのメタデータの作成、読み取り、更新
次の gcloud コマンドを使用して、必要な API を有効にします。
gcloud services enable compute.googleapis.com \ container.googleapis.com \ cloudbuild.googleapis.com \ servicemanagement.googleapis.com \ cloudresourcemanager.googleapis.com \ --project ${GOOGLE_CLOUD_PROJECT}
GCS バケットを作成する
テスト用ワークをアップロードするには、GCS バケットが必要です。一意の名前を確保するために、名前にプロジェクト ID を使用してバケットを作成します。
gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/
3. Kubernetes クラスタの作成
クラスタを作成する
次に、ワーカーノードとしてディスパッチされる Pod など、Jenkins システムをホストする GKE クラスタを作成します。--scopes
フラグで指定された追加スコープにより、Jenkins は Cloud Source Repositories と Container Registry にアクセスできるようになります。Cloud コンソールで、次のコマンドを実行します。
gcloud container clusters create jenkins-cd \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --scopes "https://www.googleapis.com/auth/source.read_write,cloud-platform" \ --cluster-version latest
また、2 つのクラスタをデプロイして、サンプル アプリケーションのステージング ビルドと本番環境ビルドをホストします。
gcloud container clusters create staging \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --cluster-version latest
gcloud container clusters create prod \ --machine-type n1-standard-2 --num-nodes 2 \ --zone us-east1-d \ --cluster-version latest
確認
クラスタが作成されたら、gcloud container clusters list
を使用してクラスタが実行されていることを確認できます。
出力の STATUS
列に RUNNING
が含まれているはずです。
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS jenkins-cd us-east1-d 1.15.9-gke.9 34.74.77.124 n1-standard-2 1.15.9-gke.9 2 RUNNING prod us-east1-d 1.15.9-gke.9 35.229.98.12 n1-standard-2 1.15.9-gke.9 2 RUNNING staging us-east1-d 1.15.9-gke.9 34.73.92.228 n1-standard-2 1.15.9-gke.9 2 RUNNING
4. Helm を使用して Jenkins をデプロイする
Helm をインストールする
Kubernetes 用のアプリケーション パッケージ マネージャーである Helm を使用して、クラスタに Jenkins をインストールします。まず、Jenkins のデプロイに使用する Kubernetes マニフェストを含むプロジェクトをダウンロードします。
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
現在の作業ディレクトリをプロジェクト ディレクトリに変更します。
cd ~/continuous-deployment-on-kubernetes/
クラスタ ロール バインディングを作成して、cluster-admin ロールの権限を付与します。
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
認証情報を取得して、Jenkins クラスタに接続します。
gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
Helm バイナリを Cloud コンソールにダウンロードします。
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz
ファイルを解凍し、含まれている Helm ファイルを現在の作業ディレクトリにコピーします。
tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \ cp linux-amd64/helm .
Tiller は、Kubernetes クラスタで実行される Helm のサーバーサイドです。tiller
という名前のサービス アカウントを作成します。
kubectl create serviceaccount tiller \ --namespace kube-system
変更できるように、cluster-admin
クラスタロールにバインドします。
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
これで、Helm を初期化してリポジトリを更新できます。
./helm init --service-account=tiller && \ ./helm repo update
確認
./helm version
を使用して、Helm が正常に動作していることを確認します。これにより、クライアントとサーバーのバージョン番号が返されます。
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Jenkins をインストールする
Helm がクラスタにインストールされたので、Jenkins のインストールの準備が整いました。
./helm install stable/jenkins -n cd \ -f jenkins/values.yaml \ --version 1.2.2 --wait
確認
Pod を確認しましょう。
kubectl get pods
出力には、ステータスが RUNNING の Jenkins Pod が表示されます。
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Jenkins サービスが適切に作成されたことを確認します。
kubectl get svc
出力結果は次のようになります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cd-jenkins ClusterIP 10.35.241.170 <none> 8080/TCP 2m27s cd-jenkins-agent ClusterIP 10.35.250.57 <none> 50000/TCP 2m27s kubernetes ClusterIP 10.35.240.1 <none> 443/TCP 75m
Jenkins インストールでは、Kubernetes プラグインを使用してビルダー エージェントを作成します。これらのエージェントは、必要に応じて Jenkins マスターによって自動的に起動されます。エージェントは処理の完了時に自動的に終了されて、エージェントのリソースがクラスタのリソースプールに戻されます。
Jenkins に接続する
Jenkins はクラスタで実行されていますが、UI にアクセスするには、Cloud Shell からポート転送を設定します。
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=cd" -o jsonpath="{.items[0].metadata.name}") && kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &
インストール中に管理者パスワードが生成されました。取得してみましょう。
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
Cloud Shell の上部にあるウェブでプレビュー アイコン をクリックし、[ポート 8080 でプレビュー] を選択します。
Jenkins のログイン画面が表示されます。ここで、ユーザー名として admin
と、前の手順で返されたパスワードを入力します。
[ログイン] をクリックすると、Jenkins のメインページが表示されます。
5. GKE プラグインをインストールして構成する
Google Kubernetes Engine プラグインを使用すると、Jenkins 内でビルドされたデプロイメントを GKE 内で実行されている Kubernetes クラスタに公開できます。プロジェクトの IAM 権限で行う必要がある構成があります。この構成を Terraform を使用してデプロイします。
まず、GKE プラグイン プロジェクトをダウンロードします。
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
IAM 権限の自動構成
現在の作業ディレクトリを、前にクローンを作成した GKE プロジェクトの rbac ディレクトリに変更します。
cd ~/google-kubernetes-engine-plugin/docs/rbac/
gcp-sa-setup.tf
は、制限付きの権限を持つカスタム GCP IAM ロールと、そのロールを付与する GCP サービス アカウントを作成する Terraform 構成ファイルです。このファイルには、プロジェクト、リージョン、サービス アカウント名の変数の値が必要です。これらの値は、まず次の環境変数を宣言することで指定します。
export TF_VAR_project=${GOOGLE_CLOUD_PROJECT} export TF_VAR_region=us-east1-d export TF_VAR_sa_name=kaniko-role
Terraform を初期化してプランを生成し、適用します。
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
サービス アカウントには、Cloud Storage バケットに保存するためのストレージ管理者権限が必要です。
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \ --role 'roles/storage.admin'
また、パイプラインのデプロイ ステージのコンテナ権限も必要です。
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \ serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'
これで、Helm を使用して、gke robot deployer を使用して GKE プラグインのクラスタ権限を設定できます。作業ディレクトリを GKE プロジェクトの helm ディレクトリに変更します。
cd ~/google-kubernetes-engine-plugin/docs/helm/
提供された Helm チャートを使用してインストールします。
export TARGET_NAMESPACE=kube-system && \ envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -
6. Jenkins を構成する
サービス アカウント キー
サービス アカウントが正常に機能するように、秘密鍵ファイルを生成して Kubernetes Secret として追加する必要があります。まず、次の gcloud コマンドでファイルを生成します。
gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
このファイルを使用して、Kubernetes Secret ストアに Secret Key を作成します。
kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json
Cloud Shell の 3 つのドット メニューから [ファイルをダウンロード] アイテムにアクセスして、json ファイルをローカルディスクにダウンロードします。
ファイルパス /tmp/kaniko-secret.json
を入力し、[ダウンロード] をクリックします。
Jenkins ページに戻り、左側のペインで [認証情報]、[システム] の順にクリックします。
ページの [システム] セクションで、左側の [グローバル認証情報]、[認証情報を追加] の順にクリックします。
[Kind] プルダウンで、[Google Service Account from private key] を選択します。名前として「kaniko-role」と入力し、前の手順で作成した JSON キーをアップロードして、[OK] をクリックします。
環境変数
マルチブランチ パイプラインを作成する前に、Jenkins で定義する必要がある環境変数がいくつかあります。それらは次のとおりです。
- JENK_INT_IT_ZONE - Kubernetes クラスタのゾーン。ここでは
us-east1-d
とします。 - JENK_INT_IT_PROJECT_ID - Jenkins のこのインスタンスをホストする GCP プロジェクト ID を参照します。
- JENK_INT_IT_STAGING - ステージング クラスタ名。デモ用に
staging
に設定します。 - JENK_INT_IT_PROD - プロダクション クラスタの名前。デモ用に
prod
にします。 - JENK_INT_IT_BUCKET - 前の手順で作成した Google Cloud Storage バケット
- JENK_INT_IT_CRED_ID - 前の手順で JSON を使用して作成した認証情報を参照します。この値は、指定した名前
kaniko-role
と一致している必要があります。
これらを追加するには、[Manage Jenkins] に移動します。
次に、[Configure System] をクリックします。
[グローバル プロパティ] というセクションがあり、[環境変数] チェックボックスをオンにすると、[追加] ボタンが表示されます。このボタンをクリックして、上記の変数を Key-Value ペアとして追加します。
ページの下部にある [保存] ボタンをクリックして変更を適用します。
7. パイプラインを設定する
Jenkins で [New Item] をクリックします。
名前に「jenkins-integration-sample」と入力し、プロジェクトの種類として [Multibranch Pipeline] を選択し、[OK] をクリックします。
パイプラインの構成ページにリダイレクトされます。[Branch Sources] で、[Project Repository] に https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git と入力します。[ビルド構成] で、[スクリプトパス] に「gke/Jenkinsfile」と入力します。
[保存] をクリックして、これらの設定を適用します。保存すると、Jenkins はリポジトリのスキャンを開始し、ブランチごとにその後のビルドを開始します。ビルドの進行に伴い、[Kubernetes ワークロード] ページに Pod の作成、実行、破棄が表示されます。
ビルドが完了すると、Kubernetes ワークロード ページに「jenkins-integration-samples-gke」という名前の 2 つの項目が表示されます。それぞれ、本番環境クラスタまたはテストクラスタに対応しています。ステータスは OK になります。
次の gcloud コマンドを使用すると、パイプラインに応じて Google Container Registry にコンテナ イメージがアップロードされていることがわかります。
gcloud container images list
ブラウザでワークロードを表示するには、本番環境クラスタの認証情報を取得します。
gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
次を実行して、シェルのポート 8081 からワークロードのポート 8080 へのポート転送を設定します。
export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") && kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &
Cloud Shell の上部にある [ウェブでプレビュー] アイコンをクリックし、[ポート 8081 でプレビュー] を選択します。
8. クリーンアップ
Kubernetes に Jenkins とマルチブランチ パイプラインのサンプルをデプロイする方法について説明しました。次に、作成したリソースをプロジェクトからクリーンアップします。
プロジェクトを削除する
必要に応じて、プロジェクト全体を削除することもできます。GCP Console で、[Cloud Resource Manager] ページに移動します。
プロジェクト リストで、目的のプロジェクトを選択し、[削除] をクリックします。プロジェクト ID を入力するように求められます。入力して [シャットダウン] をクリックします。
または、gcloud を使用してプロジェクト全体を Cloud Shell から直接削除することもできます。
gcloud projects delete $GOOGLE_CLOUD_PROJECT
課金対象コンポーネントを 1 つずつ削除する場合は、次のセクションに進みます。
Kubernetes クラスタ
gcloud を使用して Kubernetes クラスタ全体を削除します。
gcloud container clusters delete jenkins-cd --zone=us-east1-d
ストレージ バケット
アップロードしたファイルをすべて削除し、gsutil を使用してバケットを削除します。
gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket
Google Container Registry イメージ
イメージ ダイジェストを使用して Google Container Registry イメージを削除します。まず、次のコマンドでダイジェストを取得します。
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
次に、返された各ダイジェストに対して次の操作を行います。
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. 完了
これで完了です。GKE に Jenkins をデプロイし、Kubernetes クラスタにジョブをディスパッチする方法について学習しました。
学習した内容
- Kubernetes クラスタをデプロイし、Helm を使用して Jenkins をインストールしました
- Jenkins が Kubernetes クラスタにビルド アーティファクトをデプロイできるように、GKE プラグインをインストールして構成しました。
- GKE クラスタに作業をディスパッチするマルチブランチ パイプラインを設定するように Jenkins を構成しました。