マイクロサービス CI/CD 実践 - GitOps の完全な設計と実装

マイクロサービス CI/CD 実践 - GitOps の完全な設計と実装

[[422238]]

単一のアプリケーションと環境

複数のアプリケーションと環境

CI 継続的インテグレーション

まず、コードベースを準備します。

https://github.com/DevOpsCICDCourse/microservicescicd/blob/main/microservice-demo-service-master.zip

CI パイプラインのステップを整理してみましょう。

  • 今回実装したコードリポジトリタイプは単一リポジトリ、つまり 1 つのリポジトリに複数のサービスモジュールコードが格納され、各サブディレクトリがサービスモジュールとなります。
  • まず、継続的インテグレーション パイプラインは、現在のコミットがどのサービス コードであるかを正しく取得できる必要があります。
  • サービスを決定し、サービス コードをダウンロードして、コンパイルとパッケージ化、単体テスト、コード スキャン、イメージの構築などの手順を実行します。

コミットサービス情報を取得するにはどうすればよいですか?ここでは、GitLab WebHook 関数と Jenkins ジョブ ビルド トリガーを使用してこれを実現します。

ワークフローは次のとおりです。Gitlab でコードを送信すると、GitLab Webhook を通じて Jenkins Scheduler ジョブがトリガーされ、送信されたコードによって生成されたフック データが POST モードで Jenkins ジョブに渡されます。この時点で、Generic Hook プラグインを使用してこの POST リクエストによって送信されたリクエスト本文情報を取得するように Jenkins ジョブを記述できます。これは JSON データです。ジョブの実行後、変更されたサービス モジュール情報を取得するために JSON でデータを解析するパイプラインを記述します。最後に、対応するサービスの CI ジョブが構築のためにトリガーされます。

CI スケジューラ ジョブ

このジョブでは、Webhook を有効にしてトリガー トークン (一意性) を構成することだけが必要です。 hookurl を生成します: http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CI

ジェンキンスファイル

  1. パイプライン
  2. エージェント  
  3.  
  4. ステージ{
  5.  
  6. ステージ( "GetData" ){
  7. ステップ{
  8. スクリプト {
  9. echo "${webHookData}"  
  10.  
  11. データ = readJSON テキスト: "${webHookData}"  
  12.  
  13. println(データ)
  14.  
  15. env.branchName = data.ref - "refs/heads/"  
  16. env.commitId = data.checkout_sha
  17. env.projectId = データ.プロジェクトID
  18. commits = data[ "コミット" ]
  19.  
  20. println( "${env.branchName}" )
  21. println( "${env.commitID}" )
  22. println( "${env.projectId}" )
  23.  
  24. //env.moduleName = "service01"  
  25. 変更サービス = []
  26. コミット コミット){
  27. println(コミット.id)
  28.  
  29. //追加した
  30. 追加  コミット.added) {
  31. s =リストとして.split( "/" )を追加
  32. s.size ()> 1)の場合{
  33. (changeServices.indexOf(s[0]) == -1)の場合{
  34. サービスを変更します。追加(s[0])
  35. }
  36. }
  37. }
  38.  
  39. //変更済み
  40.  コミット.modified) {
  41. s = m.split( "/" )リストとして
  42. // println s
  43. // println s.size ()
  44. // s[0]を印刷する
  45. s.size ()> 1)の場合{
  46. // println changeServices.indexOf(s[0])
  47. (changeServices.indexOf(s[0]) == -1)の場合{
  48. サービスを変更します。追加(s[0])
  49. }
  50. }
  51. }
  52.  
  53. //削除されました
  54. (r場合 コミット.removed) {
  55. s = r.split( "/" )リストとして
  56. 印刷する
  57. s.size ()> 1)の場合{
  58. (changeServices.indexOf(s[0]) == -1)の場合{
  59. サービスを変更します。追加(s[0])
  60. }
  61. }
  62. }
  63. }
  64.  
  65. println(サービスの変更)
  66. //currentBuild.description = "トリガー  ${eventType} ${changeServices}による
  67. }
  68. }
  69. }
  70.  
  71. ステージ( 'DefineService' ){
  72. 手順 {
  73. スクリプト{
  74. println(サービスの変更)
  75. //サービス構築順序制御
  76. サービス = [ 'service02' , 'service01' ]
  77. (サービス内のサービス){
  78. (changeServices.indexOf(サービス) != -1)の場合{
  79. ジョブ名 = 'microservicecicd-' +サービス+ '-service-CI'  
  80. ビルドジョブ: jobName、待機: false 、パラメータ: [string( name : 'branchName' 、値: "${env.branchName}" )、
  81. 文字列(名前: 'commitId' 、値: "${env.commitId}" )、
  82. 文字列(名前: 'projectId' 、値: "${env.projectId}" )]
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }
  89. }

GitLab WebHookの設定

Webhook を有効にし、hookurl を設定します: http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CI

CIパイプライン-CI操作

各マイクロサービスは、ブランチ名、コミット ID、プロジェクト ID の 3 つの文字列パラメータを持つ CI ジョブを作成します。

ジェンキンスファイル

  1. 文字列 branchName = "${env.branchName}"  
  2. 文字列 moduleName = "${JOB_NAME}" .split( "/" )[1].split( "-" )[1]
  3. 文字列 srcUrl = "http://gitlab.idevops.site/microservicecicd/microservicecicd-demo-service.git"  
  4. 文字列 commitId = "${env.commitId}"  
  5. 文字列 projectId = "${env.projectId}"  
  6.  
  7. パイプライン
  8. エージェント { ノード { ラベル"build" } }
  9.  
  10. ステージ {
  11. ステージ( 'GetCode' ){
  12. 手順 {
  13. スクリプト {
  14. チェックアウト([$class: 'GitSCM' ,
  15. ブランチ: [[名前: "${branchName}" ]],
  16. doGenerateSubmoduleConfigurations: false
  17. 拡張機能: [[$class: 'SparseCheckoutPaths' ,
  18. sparseCheckoutPaths: [[パス: "${moduleName}" ],[パス: 'Dockerfile' ]]]],
  19. サブモジュール構成: [],
  20. userRemoteConfigs: [[credentialsId: 'gitlab-admin-user' ,
  21. URL: "${srcUrl}" ]]])
  22. }
  23.                  
  24. }
  25. }
  26.  
  27. ステージ( "ビルド&テスト" ){
  28. ステップ{
  29. スクリプト{
  30. echo "ビルド..........."  
  31.  
  32. sh "" "
  33. cd ${モジュール名}
  34. mvn クリーンパッケージ
  35.  
  36. 「」 「
  37. }
  38. }
  39. 役職 {
  40. いつも {
  41. junit "${moduleName}/target/surefire-reports/*.xml"  
  42. }
  43. }
  44. }
  45.  
  46. ステージ( "SonarScan" ){
  47. ステップ{
  48. スクリプト{
  49.  
  50. def sonarDate = sh returnStdout: true 、スクリプト: 'date +%Y%m%d%H%M%S'  
  51. sonarDate = sonarDate - "\n"  
  52.  
  53. withCredentials([文字列(credentialsId: 'sonar-admin-user' 、変数: 'sonartoken' )、
  54. 文字列(資格情報ID: 'gitlab-user-token' 、変数: 'gitlabtoken' )]) {
  55. //ブロック
  56. sh "" "
  57. cd ${モジュール名}
  58. ソナースキャナー \
  59. -Dsonar.projectKey=${ジョブ名} \
  60. -Dsonar.projectName=${ジョブ名} \
  61. -Dsonar.projectVersion=${sonarDate} \
  62. -Dsonar.ws.タイムアウト=30 \
  63. -Dsonar.projectDescription= "xxxxxxx" \
  64. -Dsonar.links.homepage=http://www.baidu.com \
  65. -Dsonar.sources=src \
  66. -Dsonar.sourceEncoding=UTF-8 \
  67. -Dsonar.java.binaries=ターゲット/クラス\
  68. -Dsonar.java.test.binaries=ターゲット/テストクラス\
  69. -Dsonar.java.surefire.report=ターゲット/surefire-reports \
  70. -Dsonar.host.url= "http://sonar.idevops.site" \
  71. -Dsonar.login=${sonartoken} \
  72. -Dsonar.gitlab.commit_sha=${コミットID} \
  73. -Dsonar.gitlab.ref_name=${ブランチ名} \
  74. -Dsonar.gitlab.project_id=${プロジェクトID} \
  75. -Dsonar.dynamicAnalysis=レポートの再利用\
  76. -Dsonar.gitlab.failure_notification_mode=コミット-ステータス \
  77. -Dsonar.gitlab.url=http://gitlab.idevops.site \
  78. -Dsonar.gitlab.user_token=${gitlabtoken} \
  79. -Dsonar.gitlab.api_version=v4
  80.  
  81. 「」 「
  82.  
  83. }
  84.   
  85. }
  86. }
  87. }
  88.  
  89. ステージ( "BuildImage" ){
  90. ステップ{
  91. スクリプト{
  92.  
  93. withCredentials([usernamePassword(credentialsId: 'aliyun-registry-admin' 、passwordVariable: 'password' 、usernameVariable: 'username' )]) {
  94.                  
  95. env.nowDate = sh returnStdout: true 、スクリプト: 'date +%Y%m%d%H%M%S'  
  96. env.nowDate = env.nowDate - "\n"  
  97.  
  98. env.releaseVersion = "${env.branchName}"  
  99. env.imageTag = "${releaseVersion}-${nowDate}-${commitId}"  
  100. env.dockerImage = "registry.cn-beijing.aliyuncs.com/microservicecicd/microservicecicd-${moduleName}-service:${env.imageTag}"  
  101. env.jarName = "${モジュール名}-${ブランチ名}-${コミットID}"  
  102. sh "" "
  103. docker login -u ${ユーザー名} -p ${パスワード} registry.cn-beijing.aliyuncs.com
  104. cd ${moduleName} && docker build -t ${dockerImage} -f ../Dockerfile --build-arg SERVICE_NAME=${jarName} .  
  105. 睡眠1
  106. docker プッシュ ${dockerImage}
  107. 睡眠1
  108. docker rmi ${dockerImage}
  109. 「」 「
  110. }
  111.  
  112.  
  113. }
  114. }
  115. }
  116.  
  117.          
  118. }
  119. }

GitOps-CI 拡張機能

元の CI ジョブの手順に基づいて、環境を更新する手順が追加されます。 GitOps プラクティスでは、現在の基本環境デプロイメント ファイルを Git リポジトリに保存します。 CI ジョブがイメージのアップロードを完了すると、環境デプロイメント ファイル内のイメージ タグ情報も更新されます。 (そのため、まず環境ファイルを取得して更新する必要があります)

  1. ステージ( "PushFile" ){
  2. //いつ{
  3. // 式 { "${env.branchName}" . ( "RELEASE-" )を含む}
  4. // }
  5. ステップ{
  6. スクリプト{
  7. if ( "${env.branchName}" . contains ( "RELEASE-" )){
  8. println( "ブランチ名 = ブランチ名" )
  9. env.branchName = "マスター"  
  10.  
  11. }それ以外{
  12. env.branchName = "機能"  
  13. }
  14.  
  15. (i = 0; i < 3; i++)の場合{
  16. //バージョンライブラリファイルをダウンロードする
  17. 応答 = GetRepoFile(40, "${moduleName}%2fvalues.yaml" , "${env.branchName}" )
  18. //println(応答)
  19.                      
  20. //ファイル内の内容を置き換える
  21. yamlData = readYaml テキスト: "" "${response}" ""  
  22.  
  23. println(yamlData.image.version)
  24. println( yamlData.image.commit )
  25. yamlData.image.version = "${releaseVersion}-${env.nowDate}"  
  26. yamlData.image.commit = "${commitId}"  
  27.  
  28. yamlData.toString() を println します。
  29.  
  30. sh "rm -fr test.yaml"  
  31. writeYaml 文字セット: 'UTF-8' 、データ: yamlData、ファイル: 'test.yaml'  
  32. newYaml = sh returnStdout: true 、スクリプト: 'cat test.yaml'  
  33.                      
  34. println(新しいYaml)
  35. //gitlabファイルの内容を更新
  36. base64Content = newYaml.bytes.encodeBase64().toString()
  37.  
  38. // 並行して問題が発生し、更新によって同時にエラーが報告されます
  39. 試す {
  40. リポジトリファイルを更新します(40、 "${moduleName}%2fvalues.yaml" 、base64Content、 "${env.branchName}" )
  41. 壊す;
  42. } キャッチ(e){
  43. sh 「睡眠2」  
  44. 続く;
  45. }
  46. }
  47. }
  48. }
  49. }
  50.          
  51. //HTTPリクエストをカプセル化する
  52. def HttpReq(reqType,reqUrl,reqBody){
  53. gitServer を"http://gitlab.idevops.site/api/v4"に設定します 
  54. withCredentials([string(credentialsId: 'gitlab-token' , 変数: 'gitlabToken' )]) {
  55. 結果 = httpRequest customHeaders: [[maskValue: true 名前: 'PRIVATE-TOKEN' 、値: "${gitlabToken}" ]],
  56. httpMode: 要求タイプ、
  57. コンテンツタイプ: "APPLICATION_JSON"
  58. コンソールログレスポンスボディ: true
  59. SSLエラーを無視: true
  60. リクエストボディ: reqBody、
  61. url: "${gitServer}/${reqUrl}"  
  62. // 静か: 
  63. }
  64. 結果を返す
  65. }
  66.  
  67.  
  68. //ファイルの内容を取得する
  69. def GetRepoFile(プロジェクトID,ファイルパス,ブランチ名){
  70. apiUrl = "projects/${projectId}/repository/files/${filePath}/raw?ref=${branchName}"  
  71. レスポンス = HttpReq( 'GET' ,apiUrl, '' )
  72. レスポンスを返す。
  73. }
  74.  
  75. //ファイルの内容を更新する
  76. def UpdateRepoFile(プロジェクトID、ファイルパス、ファイルコンテンツ、ブランチ名){
  77. apiUrl = "プロジェクト/${プロジェクトID}/リポジトリ/ファイル/${ファイルパス}"  
  78. reqBody = "" "{" branch ": " ${branchName} "," encoding ":" base64 ", " content ": " ${fileContent} ", " commit_message ": "新しいファイルを更新"}" ""  
  79. レスポンス = HttpReq( 'PUT' ,apiUrl,reqBody)
  80. println(応答)
  81.  
  82. }

画像

GitOps-CD セクション

CD スケジューラ ジョブ

このジョブは、CI スケジューラ ジョブと同様に、実際に GitLab の webhook リクエストを受信します。違いは、この CD スケジューラ ジョブが環境リポジトリ内のコード変更を受信するために使用されることです。 Webhook を有効にし、トリガー トークンを構成します。 hookurl を生成します: http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CD

ジェンキンスファイル

  1. パイプライン
  2. エージェント 
  3.  
  4. ステージ {
  5. ステージ( 'GetCommitService' ){
  6. 手順 {
  7. スクリプト{
  8. 「こんにちは世界」をエコーし​​ます 
  9. echo "${WebHookData}"  
  10.                      
  11. // Git 情報
  12. webhookdata = readJSON テキスト: "" "${WebHookData}" ""  
  13. イベントタイプ = webhookdata[ "オブジェクトの種類" ]
  14. commits = webhookdata[ "commits" ]
  15. branchName = webhookdata[ "ref" ] - "refs/heads/"  
  16. projectID = webhookdata[ "プロジェクトID" ]
  17. コミットID = webhookdata[ "checkout_sha" ]
  18.  
  19.  
  20. 変更サービス = []
  21. コミット コミット){
  22. println(コミット.id)
  23.  
  24. //追加した
  25. 追加  コミット.added) {
  26. s =リストとして.split( "/" )を追加
  27. s.size ()> 1)の場合{
  28. (changeServices.indexOf(s[0]) == -1)の場合{
  29. サービスを変更します。追加(s[0])
  30. }
  31. }
  32. }
  33.  
  34. //変更済み
  35.  コミット.modified) {
  36. s = m.split( "/" )リストとして
  37. // println s
  38. // println s.size ()
  39. // s[0]を印刷する
  40. s.size ()> 1)の場合{
  41. // println changeServices.indexOf(s[0])
  42. (changeServices.indexOf(s[0]) == -1)の場合{
  43. サービスを変更します。追加(s[0])
  44. }
  45. }
  46. }
  47.  
  48. //削除されました
  49. (r場合 コミット.removed) {
  50. s = r.split( "/" )リストとして
  51. 印刷する
  52. s.size ()> 1)の場合{
  53. (changeServices.indexOf(s[0]) == -1)の場合{
  54. サービスを変更します。追加(s[0])
  55. }
  56. }
  57. }
  58. }
  59.  
  60. println(サービスの変更)
  61. currentBuild.description = " ${eventType} ${changeServices} によってトリガー "  
  62. }
  63. }
  64. }
  65.  
  66. ステージ( 'DefineService' ){
  67. 手順 {
  68. スクリプト{
  69. println(サービスの変更)
  70. //サービス構築順序制御
  71. サービス = [ 'service02' , 'service01' ]
  72. (サービス内のサービス){
  73. (changeServices.indexOf(サービス) != -1)の場合{
  74. ジョブ名 = 'microservicecicd-' +サービス+ '-service-CD'  
  75. ビルドジョブ: jobName、待機: false 、パラメーター: [string( name : 'branchName' 、値: "${branchName}" )]
  76. }
  77. }
  78. }
  79. }
  80. }
  81. }
  82. }

環境ライブラリ構成ウェブフック

Webhook を有効にし、hookurl を設定します: http://jenkins.idevops.site/generic-webhook-trigger/invoke?token=microservicecicd-scheduler-CD

CD製造ライン-CD操作

ジェンキンスファイル

  1. 文字列 serviceName = "${JOB_NAME}" .split( "-" )[1]
  2. 文字列 nameSpace = "${JOB_NAME}" .split( "-" )[0].split( "/" )[-1]
  3.  
  4.  
  5. //パイプライン
  6. パイプライン{
  7. エージェント { ノード { ラベル"k8s" }}
  8.      
  9. ステージ{
  10.  
  11. ステージ( "GetCode" ){
  12. ステップ{
  13. スクリプト{
  14. println( "${branchName}" )
  15. println( "${env.branchName}" . ( "RELEASE-" )が含まれています)
  16. println "コードを取得"  
  17. チェックアウト([$class: 'GitSCM' , ブランチ: [[ name : "${env.branchName}" ]],
  18. doGenerateSubmoduleConfigurations: false
  19. 拡張機能: [[$class: 'SparseCheckoutPaths' ,
  20. sparseCheckoutPaths: [[パス: "${serviceName}" ]]]],
  21. サブモジュール構成: [],
  22. userRemoteConfigs: [[credentialsId: 'gitlab-admin-user' 、url: "http://gitlab.idevops.site/microservicecicd/microservicecicd-env.git" ]]])
  23. }
  24. }
  25. }
  26.  
  27. ステージ( "HelmDeploy" ){
  28. ステップ{
  29. スクリプト{
  30. sh "" "
  31. kubectl はns "${nameSpace}-uat"を作成します||エコー 
  32.  
  33. helm インストール"${serviceName}"   --namespace "${nameSpace}-uat" ./"${serviceName}" || helm アップグレード "${serviceName}" --namespace "${nameSpace}-uat" ./"${serviceName}"  
  34.  
  35. helm list --namespace "${nameSpace}-uat"  
  36. helm 履歴"${serviceName}"   --namespace "${nameSpace}-uat"  
  37.  
  38. 「」 「
  39. }
  40. }
  41. }
  42. }
  43. }

この記事はWeChatのパブリックアカウント「DevOps Cloud Academy」から転載したものです。

<<:  業界で人気のエッジコンピューティングとは一体何でしょうか?

>>:  Kubernetesがサービスディスカバリを実装する方法について話す

推薦する

毎日の話題:ポリアモリーの終焉、Ctripの同城への投資、そしてTuniuのオンライン旅行業界が覆される

A5ウェブマスターネットワーク(www.admin5.com)は5月4日、中国のオンライン旅行市場が...

vmbox-7 USD/3G メモリ VPS/シングルホップ コンピュータ ルーム/フェニックス データ センター

vmbox は、openvz 仮想化を使用して、3G メモリを搭載した VPS を推進しています。サ...

この記事ではPythonの分散プロセスインターフェースを紹介します

[[399138]] 1. はじめにスレッドとプロセスの間では、プロセスの方が安定しており、複数のマ...

ウェブサイトのプロモーションは製品ではなくコンセプトに焦点を当てるべきである

わが国のインターネットの発展速度は日ごとに変化しています。不完全な統計によると、中国のインターネット...

高性能、高可用性の大規模分散Webサイトの構築方法を段階的に学習します

この記事は、大規模な分散 Web サイト アーキテクチャの学習に関する技術的な概要です。高性能、高可...

簡単にウェブサイトを構築できる、PHP オープンソース コンテンツ管理システム (CMS) 20 選

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますコンテンツ...

2022年のクラウド大手の「エコ革命」第一歩:リベートの削減、転売の抑制、発言権の競争

「アリババ、テンセント、ファーウェイクラウドのエコ政策は今年、いずれも大きな変化を遂げるだろう。」最...

2018年雲奇大会で「新杭州物語」が発表され、アリババクラウドが「杭州ソリューション」を世界に輸出

9月19日、2018年杭州雲奇大会で杭州シティブレイン2.0が正式にリリースされました。管轄区域は2...

SEO最適化は評価期間中の記事コンテンツ構築の重要なポイントです - A5 Webmaster Network

皆さんご存知のとおり、新しいウェブサイトを立ち上げるときは、ウェブサイト構造の最適化、コラムの設定、...

Baiduアルゴリズムに関する推測

端午節が終わったばかりで、楽しい時期であるはずだったが、Baidu はウェブマスターと SEO 担当...

データベース業界における50年の変化:伝統的な巨大企業の時代は終わった

「前時代の輝かしいスーパースターは、変化に適応するのが最後になることが多い。」インテルの元CEO、ア...

ハイエンドのXiong Zhanghao検索名刺を設定するにはどうすればいいですか?

月給5,000~50,000のこれらのプロジェクトはあなたの将来です今日は熊張豪の検索名刺設定につい...

A5マーケティング:企業のウェブマスターによる同業ウェブサイトの基本的なSEO状況を分析する方法

かつて、競合他社のウェブサイトの最適化を分析して、自分のウェブサイトを改善したいと思ったことはありま...

iwebfusion: 米国/カナダの専用サーバーが10%オフ、月額44ドルから​​。22年の運営実績を持つ老舗米国企業

iwebfusion は現在、自社の専用サーバーで 10% 割引のプロモーションを実施しており、さま...