マイクロサービス 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がサービスディスカバリを実装する方法について話す

推薦する

エッジ コンピューティングと 5G: エンタープライズ IT の今後は?

エッジ実装を推進する明らかな共通点がいくつかあります。コンテナーやその他のクラウドネイティブ テクノ...

Weiboマーケティングに関する誤解についてどれくらい知っていますか?

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス企業であれ個人であれ、W...

AWS + Dahua Technology:海外ビジネス経験におけるイノベーション?バーストポイントが必要です!

「企業は急速な発展の過程で、徐々に洗練された管理を強化し、効率を高め、コストを削減すると同時に、顧客...

Canonical タグと 301 の違いは何ですか?

月収10万元の起業の夢を実現するミニプログラム起業支援プランまず、2つの概念を明確にする必要がありま...

Redisの作者と分散マスターが戦い、最大の勝者はメロンを食べるネットユーザーだった

背景面接では、履歴書に Redis について記載するかどうかに関わらず、基本的に避けられない話題です...

Pinduoduoには価格競争はない

Pinduoduoの成功は価格の安さによるものではなく、無視されていた消費者市場を発掘し、商品の製造...

IoTとエッジコンピューティングのセキュリティ課題への対応

エッジ コンピューティングは、ローカル分析、ストレージ、またはほぼ瞬時の転送を必要とするデータを生成...

母子ブランドのマーケティング戦略を分析!

「三子政策」の実施に伴い、住民一人当たり可処分所得が増加し、育児費が家計支出の重要な部分を占めるよう...

クラウドコンピューティング業界 2017 年末総括

最も寒い冬がついに到来し、それとともに 12 月がやってきます。 2017 年も終わりに近づいていま...

平均すると、毎日 4 つの共同購入 Web サイトが倒産しており、上位 5 つが市場シェアの 90% を占めています。

原題:共同購入サイトは1日平均4件倒産、加盟店と利用者の債権回収は困難データによると、毎日平均 4 ...

パーフェクトダイアリーのトラフィック問題

天井が見えてきたにもかかわらず、 Perfect Diary は依然としてトラフィックのために小切手...

ウェブマスターネットワークレポート:タオバオの偽造注文は空中楼閣に過ぎず、迅雷クラウドブロードキャストも崩壊

1. SNS軍の地下産業チェーンが、タオバオの偽注文は単なる空想であることを暴露最近、SNS軍はさま...

ショップと百度を利用して企業ウェブサイトのロングテールワードを抑制する

多くの企業製品のホームページ上のロングテールワードやキーワードランキングは、すべて分類情報プラットフ...

bluehost、40% 割引コード、cpanel 仮想ホスティング、月額 2.95 ドルから、2 日間限定

Bluehost からプロモーション メールを送信しました: 夏季限定プロモーション、期間は 2 日...

Tencent がクラウド ネイティブ サービス ディスカバリーおよびガバナンス センターをオープンソース化 - Polaris

Polaris は、分散型またはマイクロサービス アーキテクチャにおけるサービスの可視性、フォールト...