<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      miketwais

      work up

      CI/CD 實踐指南

      1.概念和背景

      IT團隊內(nèi)部為了提升開發(fā)效率,減少不斷發(fā)布耗費的時間,我們會將流程固化下來,這樣避免每次發(fā)布都需要專人,去操作計算機,打包,編譯,運行等。

      這樣就有了Devops,CI CD這些概念,那首先說一下Devops和CICD的關(guān)系?

      DevOps是一種以協(xié)作和自動化為基礎(chǔ)的方法論,旨在促進開發(fā)和運維團隊之間的合作,提高軟件交付的速度和質(zhì)量。而CICD則是一種實踐方法,通過自動化的流程來保證軟件開發(fā)中的持續(xù)集成、測試和部署?。在采用DevOps方法論的組織中,CICD是一個核心的實踐方法。通過持續(xù)集成和持續(xù)交付,團隊能夠頻繁地將代碼集成到主干分支,并自動化地構(gòu)建、測試和部署軟件,從而快速響應用戶需求,減少發(fā)布周期,提高軟件質(zhì)量和可靠性?。CICD是實現(xiàn)DevOps的方法之一。通過自動化工具和流程,CICD支持DevOps的實踐,確保軟件開發(fā)過程中的高質(zhì)量和交付的及時性?2。持續(xù)集成(CI)是在源代碼變更后自動檢測、拉取、構(gòu)建和進行單元測試的過程,而持續(xù)交付(CD)則是在完成CI后,將已驗證的代碼發(fā)布到生產(chǎn)環(huán)境?。

      DevOps(Development和Operations的組合詞)是一組過程、方法與系統(tǒng)的統(tǒng)稱,用于促進開發(fā)、技術(shù)運營和質(zhì)量保障(QA)部門之間的溝通、協(xié)作與整合。

      --可以把DevOps看作開發(fā)、技術(shù)運營和質(zhì)量保障(QA)三者的交集。

       CI/CD 的核心概念是持續(xù)集成、持續(xù)交付和持續(xù)部署。CI/CD 可讓持續(xù)自動化和持續(xù)監(jiān)控貫穿于應用的整個生命周期(從集成和測試階段,到交付和部署)。這些關(guān)聯(lián)的事務通常被統(tǒng)稱為“CI/CD 管道”,由開發(fā)和運維團隊以敏捷方式協(xié)同支持。

      --CI持續(xù)集成(Continuous Integration),可以幫助開發(fā)人員更加頻繁地(有時甚至每天)將代碼更改合并到共享分支或“主干”中。一旦開發(fā)人員對應用所做的更改被合并,系統(tǒng)就會通過自動構(gòu)建應用并運行不同級別的自動化測試,來驗證這些更改,確保這些更改沒有對應用造成破壞。

      --CD 持續(xù)交付(Continuous Delivery),完成 CI 中構(gòu)建及單元測試和集成測試的自動化流程后,持續(xù)交付可自動將已驗證的代碼發(fā)布到存儲庫。為了實現(xiàn)高效的持續(xù)交付流程,務必要確保 CI 已內(nèi)置于開發(fā)管道。持續(xù)交付的目標是擁有一個可隨時部署到生產(chǎn)環(huán)境的代碼庫。

      --CD 持續(xù)部署(Continuous Deployment),持續(xù)部署可以自動將應用發(fā)布到生產(chǎn)環(huán)境,持續(xù)部署意味著開發(fā)人員對應用的更改在編寫后的幾分鐘內(nèi)就能生效(假設(shè)它通過了自動化測試)。

      總而言之,所有這些 CI/CD 的關(guān)聯(lián)步驟都有助于降低應用的部署風險,因此更便于以小件的方式(而非一次性)發(fā)布對應用的更改。不過,由于還需要編寫自動化測試以適應 CI/CD 管道中的各種測試和發(fā)布階段,因此前期投資還是會很大。另外,針對現(xiàn)在較流行的敏捷開發(fā),需要高頻詞發(fā)布,Devops比較適用。簡言之,我們使用CI/CD來高頻且可預測地交付更高質(zhì)量的軟件。

      (PS:我們還應該確保從開始到結(jié)束都將安全性考慮到開發(fā)過程中。這通常被稱為DevSecOps。)

      2.我們的技術(shù)棧?

       講講我們的實現(xiàn),目前我們使用基于springcloud的微服務架構(gòu),運行環(huán)境是K8S,CI工具:Jenkins,CD工具:Argo CD

      Argo CD流程:

      Argo CD 的工作流程如下:

      創(chuàng)建應用程序: 用戶通過 Argo CD 的命令行界面或 Web 界面創(chuàng)建應用程序。在創(chuàng)建應用程序時,用戶需要指定應用程序的名稱、Git 存儲庫的 URL、分支或標簽以及路徑等信息。
      GitOps 同步: Argo CD 定期輪詢配置的 Git 存儲庫,檢測應用程序配置文件的變更。一旦發(fā)現(xiàn)變更,它會觸發(fā)同步過程。
      應用程序同步: Argo CD 從 Git 存儲庫中獲取應用程序的聲明性配置文件(例如 YAML 文件),并將其與當前的實際狀態(tài)進行比較。
      狀態(tài)比較: Argo CD 使用 Kubernetes API 與集群進行通信,獲取當前部署的應用程序的實際狀態(tài)。然后,它將實際狀態(tài)與聲明性配置文件中定義的期望狀態(tài)進行比較。
      狀態(tài)同步: 如果實際狀態(tài)與期望狀態(tài)不一致,Argo CD 將自動采取必要的操作來調(diào)整實際狀態(tài),使其與期望狀態(tài)保持一致。這可能涉及創(chuàng)建、更新或刪除 Kubernetes 資源。
      應用程序健康檢查: Argo CD 監(jiān)測應用程序的健康狀態(tài),以確保部署成功。它可以通過檢查容器的就緒狀態(tài)、服務的可用性和自定義的健康檢查指標來確定應用程序是否正常運行。
      持續(xù)同步: Argo CD 會定期輪詢 Git 存儲庫,以確保應用程序的狀態(tài)與聲明性配置文件保持同步。如果發(fā)現(xiàn)配置文件有更新,它將觸發(fā)新一輪的同步過程,以將實際狀態(tài)調(diào)整為期望狀態(tài)。
      可視化界面和監(jiān)控: Argo CD 提供了一個直觀的 Web 界面,用于查看和管理應用程序的狀態(tài)。用戶可以在界面上查看應用程序的拓撲圖、部署歷史、健康狀態(tài)和同步狀態(tài)。此外,Argo CD 還提供了監(jiān)控和警報功能,以幫助用戶監(jiān)測應用程序的性能和可用性。

      3.如何做?

      3.1.創(chuàng)建代碼庫

      在項目中創(chuàng)建 devops-ci 和 devops-cd 兩個代碼倉庫 。devops-ci : 用于放 Jenkins 腳本,以及 ci 相關(guān)的所有文件 ;devops-cd : 用于放 k8s 部署腳本,ArgoCD 會讀取其中的 yaml。所有環(huán)境的部署腳本都放在 master 分支下,通過目錄結(jié)構(gòu)隔開。

      3.2.CI腳本

      目錄結(jié)構(gòu)為(三個環(huán)境):

      pipeline

      ├─dev

        │ declartion.jenkinsfile

        │ gateway.jenkinsfile

      ├─qa

        │ declartion.jenkinsfile

        │ gateway.jenkinsfile

      └─test

      舉例,一個微服務的構(gòu)建腳本:

      def project_name = "app"
      def service_name = "order"
      def dev_repo_url = "http://***/kra-mobileapp/order.git"
      def branch = "master"
      def target_env = "dev"
      def docker_register_url = "docker-registry.***.net"//內(nèi)部nexues鏡像倉庫
      def git_credential_id = "{git_credential_id}" // 請修改為正確的 credential_id
      def node_name = "{node_name}" // 請修改為對應的 node_name
      @Library('uea-shared-libraries') _
      def ueaCommonUtils = new com.tool.UeaCommonUtils();
      pipeline {
      agent {
      node {
      label node_name
      }
      }
      stages {
      stage("Get code") {
      steps {
      timeout(time:10, unit:"MINUTES") {
      script {
      ueaCommonUtils.checkout(git_credential_id, dev_repo_url,
      branch)
      }
      }
      }
      }
      stage("Maven package") {
      steps {
      timeout(time:30, unit:"MINUTES") {
      script {
      dir('source') {
      ueaCommonUtils.mvnPackage()
      }
      }
      }
      }
      }
      stage("Maven build image") {
      steps {
      timeout(time:30, unit:"MINUTES") {
      script {
      dir('source') {
      ueaCommonUtils.buildDockerImage()
      }
      }
      }
      }
      }
      stage('Push image') {
      steps {
      script {
      timeout(time:10, unit:"MINUTES") {
      ueaCommonUtils.pushImage(project_name, service_name,
      docker_register_url)
      }
      }
      }
      }
      stage('Get DevOps CD') {
      steps {
      script {
      timeout(time:10, unit:"MINUTES") {
      script {
      ueaCommonUtils.checkoutCD(git_credential_id, cd_url)
      }
      }
      }
      }
      }
      stage('Update CD Image tag') {
      steps {
      script {
      timeout(time:10, unit:"MINUTES") {
      script {
      ueaCommonUtils.updateCDImageTag(project_name,
      service_name, docker_register_url, target_env)
      }
      }
      }
      }
      }
      }
      post {
      always {
      2.2.2. gateway 服務構(gòu)建腳本
      script{
      currentBuild.description = "Build Node: ${node_name}"
      }
      }
      success {
      script{
      currentBuild.description += "\n 構(gòu)建成功!"
      }
      }
      failure {
      script{
      currentBuild.description += "\n 構(gòu)建失敗!"
      }
      }
      aborted {
      script{
      currentBuild.description += "\n 構(gòu)建取消!"
      }
      }
      }
      }
      View Code

      ps:shared-libraries

      package com.tool
      
      def checkout(credentials_id, repo_url, branch, targetDir='source', wipeWorkspace=true) {
          def gitExtensions = [
              [
                  $class: 'RelativeTargetDirectory',
                  relativeTargetDir: targetDir
              ]
          ]
      
          if(wipeWorkspace) {
              gitExtensions.add([
                  $class: 'WipeWorkspace'
              ])
          }
              
      
          timeout(time:10, unit:"MINUTES") {
              checkout(
                  poll: false,
                  scm: scmGit(
                      branches: [[name: branch]],
                      extensions: gitExtensions,
                      userRemoteConfigs: [[
                          credentialsId: credentials_id,
                          url: repo_url
                      ]]
                  )
              )
          }
      }
      
      def mvnPackage(){
          sh """
              mvn clean package
          """
      }
      
      
      def buildDockerImage(enableTest=false){
          if(enableTest) {
              sh """
                  mvn -Dprod clean verify -DskipTests -U jib:dockerBuild
              """
          } else {
              sh """
                  mvn -Dprod clean test -U jib:dockerBuild
              """
          }
      }
      
      def pushImage(project_name, service_name, docker_register_url){
          sh """
              docker tag ${project_name}-${service_name}:latest ${docker_register_url}/${project_name}/${service_name}:${build_id}
              sleep 1
              docker push ${docker_register_url}/${project_name}/${service_name}:${build_id}
          """
      }
      
      def checkoutCD(credentials_id, repo_url) {
          checkout(credentials_id, repo_url, 'master', 'devOpsCD', true)
      }
      
      def updateCDImageTag(project_name, service_name, docker_register_url, target_env){
          sh """
              cd devOpsCD/manifests/overlays/${target_env}
              kustomize edit set image ${service_name}-image=${docker_register_url}/${project_name}/${service_name}:${build_id}
              git config --global user.name "Bot UEA DevOps"
              git config --global user.email "**@**.com"
              git checkout master
              git commit -am "ci(UEA auto commit): update image tag to ${build_id}"
              git push origin master
          """
      }
      View Code

      微服務中POM.xml需要調(diào)整打包方式:

      <from>
      <image>docker-registry.***.net/adoptopenjdk:11-jre-hotspot</image>
      </from>
      <to>
      <image>app-order:latest</image>
      </to>
      View Code

      3.3.Jenkins pipeline

      選擇“文件夾”,然后創(chuàng)建item

       

      選擇“pipeline script from SCM”

       script path填寫倉庫中jenkins file 的路徑:

       3.4.CD 腳本

      CD腳本放在上面介紹的devops-cd目錄中

      目錄結(jié)構(gòu)參考:

       service中按照微服務模塊分,不同環(huán)境放在overlays下,如:dev/prod,通過kustomization.yaml 的 namePrefix 和 namespace來確定項目名和環(huán)境名(開發(fā)dev,生產(chǎn)prod)

       kustomization.yaml參考

      # 文件路徑 app/overlays/dev/kustomization.yaml
      resources:
      - ./config/central-config-configmap.yaml
      - ./config/common-configmap.yaml
      - ./network/gateway.yaml
      - ./network/virtual-service.yaml
      - ../../base
      namePrefix: app-order-dev-
      namespace: app-order-dev
      commonAnnotations:
        note: development environment
        # REDIS
        # RABBITMQ
        # DB
        # Registry
        #- DB_GATEWAY_URL=jdbc:oracle:thin:@***:1521:DEV
      secretGenerator:
      - literals:
        - SPRING_REDIS_PASSWORD=**
        - SPRING_RABBITMQ_USERNAME=admin
        - SPRING_RABBITMQ_PASSWORD=**
        - DB_GATEWAY_URL=jdbc:postgresql://***/app_order_dev_gateway?currentSchema=app_order_dev_gateway
        - DB_GATEWAY_USERNAME=app_order_dev_gateway
        - DB_GATEWAY_PASSWORD=dev_gateway
        - DB_CONFIGURATION_URL=jdbc:postgresql://***/app_order_dev_configuration?currentSchema=app_order_dev_configuration
        - DB_CONFIGURATION_USERNAME=app_order_dev_configuration
        - DB_CONFIGURATION_PASSWORD=dev_configuration
        - JHIPSTER_REGISTRY_PASSWORD=admin
        name: common-secret
      apiVersion: kustomize.config.k8s.io/v1beta1
      kind: Kustomization
      images:
      - name: configuration-image
        newName: docker-registry.bullchina.net/order/configuration
        newTag: "5"
      - name: gateway-image
        newName: docker-registry.bullchina.net/order/gateway
        newTag: "11"
      View Code

      微服務配置參考:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: configuration
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: configuration
        template:
          metadata:
            labels:
              app: configuration
          spec:
            nodeSelector:
              "kubernetes.io/os": linux
            containers:
            - name: configuration
              image: configuration-image
              env:
                - name: SPRING_PROFILES_ACTIVE
                  value: "prod"
                - name: MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED
                  value: "false"
                - name: JHIPSTER_CACHE_REDIS_CLUSTER
                  value: "false"
                
                - name: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE
                  valueFrom:
                    configMapKeyRef:
                      name: common-configmap
                      key: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE
                - name: SPRING_CLOUD_CONFIG_URI
                  valueFrom:
                    configMapKeyRef:
                      name: common-configmap
                      key: SPRING_CLOUD_CONFIG_URI
                - name: SPRING_REDIS_HOST
                  valueFrom:
                    configMapKeyRef:
                      name: common-configmap
                      key: SPRING_REDIS_HOST
                - name: SPRING_REDIS_PORT
                  valueFrom:
                    configMapKeyRef:
                      name: common-configmap
                      key: SPRING_REDIS_PORT
                - name: SPRING_RABBITMQ_HOST
                  valueFrom:
                    configMapKeyRef:
                      name: common-configmap
                      key: SPRING_RABBITMQ_HOST
                - name: SPRING_RABBITMQ_PORT
                  valueFrom:
                    configMapKeyRef:
                      name: common-configmap
                      key: SPRING_RABBITMQ_PORT
                
                - name: JHIPSTER_REGISTRY_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: JHIPSTER_REGISTRY_PASSWORD
                - name: SPRING_REDIS_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: SPRING_REDIS_PASSWORD
                - name: SPRING_RABBITMQ_USERNAME
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: SPRING_RABBITMQ_USERNAME
                - name: SPRING_RABBITMQ_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: SPRING_RABBITMQ_PASSWORD
                - name: SPRING_DATASOURCE_URL
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: DB_CONFIGURATION_URL
                - name: SPRING_DATASOURCE_JDBC_URL
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: DB_CONFIGURATION_URL
                - name: SPRING_DATASOURCE_USERNAME
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: DB_CONFIGURATION_USERNAME
                - name: SPRING_DATASOURCE_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: common-secret
                      key: DB_CONFIGURATION_PASSWORD
      
              resources:
                requests:
                  cpu: 10m
                  memory: 128Mi
                limits:
                  cpu: "1"
                  memory: 2Gi
              ports:
                - containerPort: 8082
                  name: http
              startupProbe:
                httpGet:
                  path: /healthcheck
                  port: 8082
                initialDelaySeconds: 20
                periodSeconds: 5
                failureThreshold: 120
              readinessProbe:
                httpGet:
                  path: /healthcheck
                  port: 8082
                periodSeconds: 5
                failureThreshold: 30
              livenessProbe:
                httpGet:
                  path: /healthcheck
                  port: 8082
                periodSeconds: 5
                failureThreshold: 30
      apiVersion: v1
      kind: Service
      metadata:
        name: configuration
      spec:
        ports:
        - port: 8082
          targetPort: 8082
          name: http
        selector:
          app: configuration
      View Code

      3.5.Argo CD配置

      3.5.1.創(chuàng)建命名空間

      # case 項目名稱,env 部署環(huán)境名稱
      kubectl create namespace app-{case}-{env}
      kubectl label namespace app-{case}-{env} istio-injection=enabled
      View Code

      3.5.2.創(chuàng)建項目

      連接CD腳本倉庫:

       

       3.5.3.授權(quán)倉庫和集群給項目

       

      3.5.4創(chuàng)建APP

       到此,完成CI/CD的配置,

      3.5.5.訪問域名配置

      腳本位置:manifests/overlays/dev/network/gateway.yaml,virtual-service.yaml

      apiVersion: networking.istio.io/v1
      kind: VirtualService
      metadata:
        name: virtual-service
      spec:
        gateways:
        - app-order-dev-gateway
        hosts:
        - app-order-dev.k8s.local
        http:
        - match:
          - uri:
              prefix: /
          route:
          - destination:
              host: app-order-dev-gateway
              port:
                number: 8080
      View Code
      apiVersion: networking.istio.io/v1
      kind: Gateway
      metadata:
        name: gateway
      spec:
        selector:
          istio: ingressgateway
        servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
          - app-order-dev.k8s.local
      View Code

      PS:需要將域名與IP映射加入到主機host文件,即可使用上面virtual-service.yaml中配置的hosts地址進行訪問。

       

      posted @ 2024-11-26 10:39  MasonZhang  閱讀(106)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 免费日韩av网在线观看| 成人无码视频| 亚洲欧洲久久激情久av| 精品国产欧美一区二区五十路| 日本丰满熟妇videossex一| 亚洲精品尤物av在线网站| 麻豆一区二区三区蜜桃免费 | 18禁无遮挡啪啪无码网站破解版 | 福利在线视频一区二区| 中文成人无字幕乱码精品区| 久久精品国产福利一区二区| 精品亚洲国产成人| 东北女人毛多水多牲交视频| 日土县| 亚洲日本中文字幕乱码中文| 国产精品中文第一字幕| 开远市| 精品国产一区二区三区国产区| 最近免费中文字幕mv在线视频3| 久久国产乱子伦免费精品无码| 久久久精品94久久精品| 在线观看成人永久免费网站| 久久久精品94久久精品| 精品国产成人亚洲午夜福利| 欧美亚洲综合成人a∨在线| 在国产线视频A在线视频| 亚洲成av人在线播放无码| 国产人与禽zoz0性伦多活几年| 久久99精品久久久久久9| 午夜射精日本三级| 国产999精品2卡3卡4卡| 大屁股肥熟女流白浆| 久久一区二区三区黄色片| 无遮无挡爽爽免费视频| 成人无号精品一区二区三区| 精品国产粉嫩一区二区三区| 亚洲综合一区国产精品| 无套内内射视频网站| 老色99久久九九爱精品| 国产亚洲精品AA片在线播放天| 国产欧美国日产高清|