Jenkins を使用した Kubernetes Engine への継続的デプロイ

このチュートリアルでは、次の図に示すように、Jenkins と GKE を使用して継続的デリバリー パイプラインをセットアップする方法について説明します。

Jenkins cd アーキテクチャ

目標

  • サンプル アプリケーションを理解する。
  • アプリケーションを Kubernetes にデプロイする。
  • コードを Cloud Source Repositories にアップロードする。
  • Jenkins にデリバリー パイプラインを作成する。
  • 開発環境をデプロイする。
  • カナリアテストをデプロイする。
  • 本番環境をデプロイする。

料金

このチュートリアルでは、以下を含む Google Cloud Platform(GCP)の課金対象コンポーネントを使用します。

  • Compute Engine
  • Google Kubernetes Engine
  • Cloud Build

料金計算ツールを使うと、このチュートリアルでの予想使用量に基づいて費用の見積もりを出すことができます。 GCP を初めてご利用の場合には、無料トライアルをご利用いただけます。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. GCP プロジェクトを選択または作成します。

    [リソースの管理] ページに移動

  3. プロジェクトに対して課金が有効になっていることを確認します。

    課金を有効にする方法について

  4. Compute Engine、Kubernetes Engine、Cloud Build API を有効にします。

    APIを有効にする

環境の準備

  1. GKE での Jenkins の設定のチュートリアルを完了します。

  2. Cloud Shell で、サンプル アプリケーションのディレクトリに移動します。

    cd continuous-deployment-on-kubernetes/sample-app
    

アプリケーションを理解する

継続的デリバリー パイプラインにサンプル アプリケーション gceme をデプロイします。このアプリケーションは Go で作成され、リポジトリの sample-app ディレクトリに保存されています。Compute Engine インスタンスで gceme バイナリを実行すると、アプリの情報カードにインスタンスのメタデータが表示されます。

gceme 情報カード

このアプリケーションは、2 つのオペレーション モードに対応し、マイクロサービスに似た機能を提供します。

  • バックエンド モードで、gceme はポート 8080 をリッスンし、Compute Engine インスタンスのメタデータを JSON 形式で戻します。

  • フロントエンド モードでは、gceme はバックエンドの gceme サービスにクエリを送信し、ユーザー インターフェースに JSON を表示します。

gceme アーキテクチャ

フロントエンド モードとバックエンド モードでは、次の 2 つの URL をサポートしています。

  • /version は実行中のバージョンを出力します。
  • /healthz はアプリケーションの状態を報告します。バックエンドに接続可能な場合、フロントエンド モードに状態情報が OK として表示されます。

Kubernetes にサンプルアプリをデプロイする

デプロイ環境を記述したマニフェスト ファイルを使用して、gceme のフロントエンドとバックエンドを Kubernetes にデプロイします。このファイルではデフォルトのイメージを使用しています。このイメージはチュートリアルの後半で更新します。

アプリケーションを次の 2 つの環境にデプロイします。

  • 本番環境。ユーザーがアクセスする公開中のサイト。

  • カナリア環境。一定の量のユーザー トラフィックを受信する容量の少ないサイト。この環境では、ライブ環境に公開する前にソフトウェアのサニティ チェックを行います。

まず、アプリケーションを本番環境にデプロイし、実際のコードを使用してパイプラインを設定します。

  1. Kubernetes 名前空間を作成して、デプロイする本番環境を論理的に隔離します。

    kubectl create ns production
    
  2. デプロイするカナリア環境と本番環境、サービスを作成します。

    kubectl --namespace=production apply -f k8s/production
    kubectl --namespace=production apply -f k8s/canary
    kubectl --namespace=production apply -f k8s/services
    
  3. 本番環境のフロントエンドをスケールアップします。

    kubectl --namespace=production scale deployment gceme-frontend-production --replicas=4
    
  4. 本番サービスの外部 IP を取得します。ロードバランサの IP アドレスが表示されるまでに数分かかる場合があります。

    kubectl --namespace=production get service gceme-frontend
    

    プロセスが完了すると、EXTERNAL-IP 列に IP アドレスが表示されます。

    NAME             TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
    gceme-frontend   LoadBalancer   10.35.254.91   35.196.48.78   80:31088/TCP   1m
    

  5. 環境変数にフロントエンド サービスのロードバランサの IP を保存します。

    export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=production services gceme-frontend)
    
  6. ブラウザでフロントエンドの外部 IP アドレスを開き、両方のサービスが正常に動作していることを確認します。

  7. 複数の端末を起動し、本番エンドポイントの /version URL をポーリングします。これにより、次のセクションで行うローリング更新の確認が可能になります。

    while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1;  done
    

サンプルアプリのソースコードをホスティングするリポジトリを作成する

次に、gceme サンプルアプリのコピーを作成し、Cloud Source Repositories のリポジトリに push します。

  1. Cloud Source Repositories でリポジトリを作成します。

    gcloud source repos create gceme
    
  2. ローカルの Git リポジトリを初期化します。

    git init
    git config credential.helper gcloud.sh
    export PROJECT_ID=$(gcloud config get-value project)
    git remote add origin https://source.developers.google.com/p/$PROJECT_ID/r/gceme
    
  3. このリポジトリの Git commit にユーザー名とメールアドレスを設定します。

    git config --global user.email "[EMAIL_ADDRESS]"
    

    [EMAIL_ADDRESS] を Git のメールアドレスに置き換えます。

    git config --global user.name "[USERNAME]"
    

    [USERNAME] を Git のユーザー名に置き換えます。

  4. ファイルの追加、commit、push を行います。

    git add .
    git commit -m "Initial commit"
    git push origin master
    

パイプラインを作成する

gceme のコピーのテスト、作成、Kubernetes へのデプロイに使用するパイプラインを Jenkins を使用して定義します。

サービス アカウントの認証情報を追加する

Jenkins がコード リポジトリにアクセスできるように認証情報を構成します。

  1. Jenkins ユーザー インターフェースで、左側のナビゲーションにある [認証情報] をクリックします。
  2. [認証情報] テーブルの [Jenkins] リンクをクリックします。

    Jenkins 認証情報グループ

  3. [グローバル認証情報] をクリックします。

  4. 左のナビゲーションで [認証情報の追加] をクリックします。
  5. [種類] プルダウンから [メタデータからの Google サービス アカウント] を選択します。
  6. [OK] をクリックします。

これで 2 つのグローバル認証情報が作成されました。2 番目の認証情報の名前をメモしてください。チュートリアルの後半で使用します。

Jenkins 認証情報

Jenkins ジョブを作成する

次に、Jenkins Pipeline 機能を使用してビルド パイプラインを構成します。Jenkins Pipeline ファイルは、Groovy に似た構文で作成されています。

Jenkins のユーザー インターフェースに移動し、次の手順でパイプライン ジョブを構成します。

  1. インターフェースの左上にある Jenkins のリンクをクリックします。

  2. 左側のナビゲーションで [新規ジョブ作成] リンクをクリックします。

  3. プロジェクトに「sample-app」という名前を付けて [Multibranch Pipeline] オプションを選択し、[OK] をクリックします。

  4. 次のページで [Add Source] をクリックし、[git] を選択します。

  5. Cloud Source Repositories 内にある sample-app リポジトリの HTTPS クローン URL を [Project Repository] フィールドに貼り付けます。[PROJECT_ID] は実際のプロジェクト ID に置き換えます。

    https://source.developers.google.com/p/[PROJECT_ID]/r/gceme
    
  6. サービス アカウントの追加時に作成した認証情報の名前を [認証情報] プルダウンから選択します。

  7. [Scan Multibranch Pipeline] セクションで、[Periodically if not otherwise run] ボックスをオンにします。[Interval] の値を「1 minute」に設定します。

  8. [Save] をクリックします。

    Jenkins ジョブ設定を作成する

このステップを完了すると、「Branch indexing」という名前のジョブが実行されます。このメタジョブはリポジトリのブランチを識別し、既存のブランチで変更が発生していないことを確認します。Jenkins を更新すると、このジョブが master ブランチに表示されます。

次のステップでコードを変更するまで、このジョブは失敗します。

パイプラインの定義を変更する

カナリア環境用のブランチを canary という名前で作成します。

git checkout -b canary

パイプラインを定義する Jenkinsfile コンテナが Jenkins Pipeline Groovy 構文で作成されます。Jenkinsfile を使用すると、ビルド パイプライン全体を 1 つのファイルで表し、ソースコードと一緒に公開することができます。パイプラインは並列化などの強力な機能をサポートしていますが、ユーザーが手動で承認する必要があります。

Jenkinsfile を変更し、1 行目にプロジェクト ID を追加します。

カナリアテストのデプロイ

ここまででパイプラインが正しく構成されました。次に、gceme アプリケーションを変更し、パイプラインのテスト、パッケージ化、デプロイを行います。

カナリア環境はカナリアテストとして設定されます。変更は、本番環境のロードバランサの内側にある小規模なポッドにリリースされます。この操作を Kubernetes で行うには、同じラベルを共有する複数デプロイを維持する必要があります。このアプリケーションの場合、gceme-frontend サービスは、app: gcemerole: frontend のラベルが付いたすべてのポッドの負荷分散を行います。k8s/frontend-canary.yaml カナリア マニフェスト ファイルでレプリカを 1 に設定し、gceme-frontend サービスに必要なラベルを追加します。

現在、5 個中 1 個のフロントエンド ポッドがカナリア環境のコードで実行され、残りの 4 個は本番環境のコードで実行されます。すべてのポッドをロールアウトする前に、カナリア環境のコードがユーザーの操作に悪影響を及ぼすことはありません。

  1. html.go を開き、blue の 2 つのインスタンスを orange で置き換えます。
  2. main.go を開き、バージョン番号を 1.0.0 から 2.0.0 に変更します。

     const version string = "2.0.0"
    
  3. 次に、これらのファイルをローカルのリポジトリに追加し、commit します。

     git add Jenkinsfile html.go main.go
     git commit -m "Version 2"
    
  4. 最後に、リモートの Git サーバーに変更を push します。

     git push origin canary
    
  5. 変更が Git リポジトリに push されたら、Jenkins のユーザー インターフェースに移動し、ビルドが開始していることを確認します。

    Jenkins の最初のビルド画面

  6. ビルドの実行後、左側のナビゲーションのビルドの横にある下矢印をクリックして、[Console の出力] を選択します。

    Jenkins コンソールのナビゲーション

  7. ビルドの出力を数分間記録し、[kubectl --namespace=production apply...] メッセージを確認します。処理の開始後、本番の /version URL をポーリングしていた端末を確認し、リクエストの一部の変更を開始して監視します。これで、ユーザーのサブセットに対する変更がロールアウトされました。

  8. カナリア環境に変更をデプロイした後で、master ブランチにコードを統合して Git サーバーにバックアップすることで、残りのユーザーにロールアウトできます。

    git checkout master
    git merge canary
    git push origin master
    
  9. 約 1 分後に、sample-app フォルダ内にある master ジョブが開始します。

    Jenkins マスタージョブ

  10. master リンクをクリックすると、パイプラインのステージ、成否情報、タイミングに関する情報が表示されます。

    Jenkins パイプラインの生成

  11. 本番の URL にポーリングを行い、新しいバージョン 2.0.0 がロールアウトされ、すべてのユーザーからのリクエストを処理していることを確認します。

    export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
    while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1;  done
    

プロジェクトの Jenkinsfile を見ると、ワークフローを確認できます。

開発ブランチをデプロイする

カナリア環境に直接 push できない複雑な変更が必要になる場合があります。開発ブランチは、公開サイトに統合する前にコードのテストを行う一連の環境です。これらの環境では、アプリケーションがスケールダウンしますが、ライブ環境と同じ方法でデプロイできます。

機能ブランチから開発環境を作成する場合、ブランチを Git サーバーに push して、Jenkins で環境をデプロイします。開発シナリオでは、外部に接続しているロードバランサは使用しません。アプリケーションを保護するには、kubectl プロキシを使用します。プロキシは Kubernetes API で自身の認証を行い、ローカルマシンからのリクエストをクラスタ内のサーバーにリダイレクトします。サービスがインターネットに公開されることはありません。

  1. 別のブランチを作成して、Git サーバーに push します。

    git checkout -b new-feature
    git push origin new-feature
    

新しいジョブが作成され、開発環境は作成中になります。ジョブのコンソール出力の最後に、環境へのアクセス方法が表示されます。

  1. バックグラウンドでプロキシを開始します。

    kubectl proxy &
    
  2. localhost を使用して、アプリケーションがアクセス可能かどうかを確認します。

    curl http://localhost:8001/api/v1/proxy/namespaces/new-feature/services/gceme-frontend:80/
    
  3. このブランチにコードを push し、開発環境を更新します。完了したら、ブランチを canary と統合し、コードをカナリア環境にデプロイします。

    git checkout canary
    git merge new-feature
    git push origin canary
    
  4. コードが本番環境で問題にならない場合には、デプロイを開始する前に、canary ブランチを master ブランチと統合します。

    git checkout master
    git merge canary
    git push origin master
    
  5. 開発ブランチでの操作が完了したら、サーバーからブランチを削除し、Kubernetes クラスタから環境を削除します。

    git push origin :new-feature
    kubectl delete ns new-feature
    

クリーンアップ

このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

プロジェクトの削除

課金を停止する最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...