<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                上節課我們實現了在Kubernetes環境中動態生成Jenkins Slave 的方法,這節課我們來給大家講解下如何在 Jenkins 中來部署一個 Kubernetes 應用。 ## Jenkins Pipeline 介紹 要實現在 Jenkins 中的構建工作,可以有多種方式,我們這里采用比較常用的 Pipeline 這種方式。Pipeline,簡單來說,就是一套運行在 Jenkins 上的工作流框架,將原來獨立運行于單個或者多個節點的任務連接起來,實現單個任務難以完成的復雜流程編排和可視化的工作。 Jenkins Pipeline 有幾個核心概念: * Node:節點,一個 Node 就是一個 Jenkins 節點,Master 或者 Agent,是執行 Step 的具體運行環境,比如我們之前動態運行的 Jenkins Slave 就是一個 Node 節點 * Stage:階段,一個 Pipeline 可以劃分為若干個 Stage,每個 Stage 代表一組操作,比如:Build、Test、Deploy,Stage 是一個邏輯分組的概念,可以跨多個 Node * Step:步驟,Step 是最基本的操作單元,可以是打印一句話,也可以是構建一個 Docker 鏡像,由各類 Jenkins 插件提供,比如命令:sh ‘make’,就相當于我們平時 shell 終端中執行 make 命令一樣。 那么我們如何創建 Jenkins Pipline 呢? * Pipeline 腳本是由 Groovy 語言實現的,但是我們沒必要單獨去學習 Groovy,當然你會的話最好 * Pipeline 支持兩種語法:Declarative(聲明式)和 Scripted Pipeline(腳本式)語法 * Pipeline 也有兩種創建方法:可以直接在 Jenkins 的 Web UI 界面中輸入腳本;也可以通過創建一個 Jenkinsfile 腳本文件放入項目源碼庫中 * 一般我們都推薦在 Jenkins 中直接從源代碼控制(SCMD)中直接載入 Jenkinsfile Pipeline 這種方法 ### 創建一個簡單的 Pipeline 我們這里來給大家快速創建一個簡單的 Pipeline,直接在 Jenkins 的 Web UI 界面中輸入腳本運行。 * 新建 Job:在 Web UI 中點擊 New Item -> 輸入名稱:pipeline-demo -> 選擇下面的 Pipeline -> 點擊 OK * 配置:在最下方的 Pipeline 區域輸入如下 Script 腳本,然后點擊保存。 shell node { stage('Clone') { echo "1.Clone Stage" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Stage" } stage('Deploy') { echo "4. Deploy Stage" } } * 構建:點擊左側區域的 Build Now,可以看到 Job 開始構建了 隔一會兒,構建完成,可以點擊左側區域的 Console Output,我們就可以看到如下輸出信息: ![](https://blog.qikqiak.com/img/posts/pipeline-demo1.png) ### 在 Slave 中構建任務 上面我們創建了一個簡單的 Pipeline 任務,但是我們可以看到這個任務并沒有在 Jenkins 的 Slave 中運行,那么如何讓我們的任務跑在 Slave 中呢?還記得上節課我們在添加 Slave Pod 的時候,一定要記住添加的 label 嗎?沒錯,我們就需要用到這個 label,我們重新編輯上面創建的 Pipeline 腳本,給 node 添加一個 label 屬性,如下: node('haimaxy-jnlp') { stage('Clone') { echo "1.Clone Stage" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Stage" } stage('Deploy') { echo "4. Deploy Stage" } } 我們這里只是給 node 添加了一個 haimaxy-jnlp 這樣的一個label,然后我們保存,構建之前查看下 kubernetes 集群中的 Pod: $ kubectl get pods -n kube-ops NAME READY STATUS RESTARTS AGE jenkins-7c85b6f4bd-rfqgv 1/1 Running 4 6d 然后重新觸發立刻構建: $ kubectl get pods -n kube-ops NAME READY STATUS RESTARTS AGE jenkins-7c85b6f4bd-rfqgv 1/1 Running 4 6d jnlp-0hrrz 1/1 Running 0 23s 我們發現多了一個名叫jnlp-0hrrz的 Pod 正在運行,隔一會兒這個 Pod 就不再了: $ kubectl get pods -n kube-ops NAME READY STATUS RESTARTS AGE jenkins-7c85b6f4bd-rfqgv 1/1 Running 4 6d 這也證明我們的 Job 構建完成了,同樣回到 Jenkins 的 Web UI 界面中查看 Console Output,可以看到如下的信息: ![](https://blog.qikqiak.com/img/posts/pipeline-demo2.png) 是不是也證明我們當前的任務在跑在上面動態生成的這個 Pod 中,也符合我們的預期。我們回到 Job 的主界面,也可以看到大家可能比較熟悉的 Stage View 界面: [https://blog.qikqiak.com/img/posts/pipeline-demo3.png](https://blog.qikqiak.com/img/posts/pipeline-demo3.png) ### 部署 Kubernetes 應用 上面我們已經知道了如何在 Jenkins Slave 中構建任務了,那么如何來部署一個原生的 Kubernetes 應用呢? 要部署 Kubernetes 應用,我們就得對我們之前部署應用的流程要非常熟悉才行,我們之前的流程是怎樣的: 1. 編寫代碼 2. 測試 3. 編寫 Dockerfile 4. 構建打包 Docker 鏡像 5. 推送 Docker 鏡像到倉庫 6. 編寫 Kubernetes YAML 文件 7. 更改 YAML 文件中 Docker 鏡像 TAG 8. 利用 kubectl 工具部署應用 我們之前在 Kubernetes 環境中部署一個原生應用的流程應該基本上是上面這些流程吧?現在我們就需要把上面這些流程放入 Jenkins 中來自動幫我們完成(當然編碼除外),從測試到更新 YAML 文件屬于 CI 流程,后面部署屬于 CD 的流程。如果按照我們上面的示例,我們現在要來編寫一個 Pipeline 的腳本,應該怎么編寫呢? node('haimaxy-jnlp') { stage('Clone') { echo "1.Clone Stage" } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Docker Image Stage" } stage('Push') { echo "4.Push Docker Image Stage" } stage('YAML') { echo "5. Change YAML File Stage" } stage('Deploy') { echo "6. Deploy Stage" } } 這里我們來將一個簡單 golang 程序,部署到 kubernetes 環境中,代碼鏈接:https://github.com/cnych/jenkins-demo。如果按照之前的示例,我們是不是應該像這樣來編寫 Pipeline 腳本: * 第一步,clone 代碼,這個沒得說吧 * 第二步,進行測試,如果測試通過了才繼續下面的任務 * 第三步,由于 Dockerfile 基本上都是放入源碼中進行管理的,所以我們這里就是直接構建 Docker 鏡像了 * 第四步,鏡像打包完成,就應該推送到鏡像倉庫中吧 * 第五步,鏡像推送完成,是不是需要更改 YAML 文件中的鏡像 TAG 為這次鏡像的 TAG * 第六步,萬事俱備,只差最后一步,使用 kubectl 命令行工具進行部署了 到這里我們的整個 CI/CD 的流程是不是就都完成了。 接下來我們就來對每一步具體要做的事情進行詳細描述就行了: ### 第一步,Clone 代碼 stage('Clone') { echo "1.Clone Stage" git url: "https://github.com/cnych/jenkins-demo.git" } ### 第二步,測試 由于我們這里比較簡單,忽略該步驟即可. ### 第三步,構建鏡像 stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t cnych/jenkins-demo:${build_tag} ." } 我們平時構建的時候是不是都是直接使用docker build命令進行構建就行了,那么這個地方呢?我們上節課給大家提供的 Slave Pod 的鏡像里面是不是采用的 Docker In Docker 的方式,也就是說我們也可以直接在 Slave 中使用 docker build 命令,所以我們這里直接使用 sh 直接執行 docker build 命令即可,但是鏡像的 tag 呢?如果我們使用鏡像 tag,則每次都是 latest 的 tag,這對于以后的排查或者回滾之類的工作會帶來很大麻煩,我們這里采用和git commit的記錄為鏡像的 tag,這里有一個好處就是鏡像的 tag 可以和 git 提交記錄對應起來,也方便日后對應查看。但是由于這個 tag 不只是我們這一個 stage 需要使用,下一個推送鏡像是不是也需要,所以這里我們把這個 tag 編寫成一個公共的參數,把它放在 Clone 這個 stage 中,這樣一來我們前兩個 stage 就變成了下面這個樣子: stage('Clone') { echo "1.Clone Stage" git url: "https://github.com/cnych/jenkins-demo.git" script { build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } } stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t cnych/jenkins-demo:${build_tag} ." } 第四步,推送鏡像 鏡像構建完成了,現在我們就需要將此處構建的鏡像推送到鏡像倉庫中去,當然如果你有私有鏡像倉庫也可以,我們這里還沒有自己搭建私有的倉庫,所以直接使用 docker hub 即可。 我們知道 docker hub 是公共的鏡像倉庫,任何人都可以獲取上面的鏡像,但是要往上推送鏡像我們就需要用到一個帳號了,所以我們需要提前注冊一個 docker hub 的帳號,記住用戶名和密碼,我們這里需要使用。正常來說我們在本地推送 docker 鏡像的時候,是不是需要使用docker login命令,然后輸入用戶名和密碼,認證通過后,就可以使用docker push命令來推送本地的鏡像到 docker hub 上面去了,如果是這樣的話,我們這里的 Pipeline 是不是就該這樣寫了: stage('Push') { echo "4.Push Docker Image Stage" sh "docker login -u cnych -p xxxxx" sh "docker push cnych/jenkins-demo:${build_tag}" } 如果我們只是在 Jenkins 的 Web UI 界面中來完成這個任務的話,我們這里的 Pipeline 是可以這樣寫的,但是我們是不是推薦使用 Jenkinsfile 的形式放入源碼中進行版本管理,這樣的話我們直接把 docker 倉庫的用戶名和密碼暴露給別人這樣很顯然是非常非常不安全的,更何況我們這里使用的是 github 的公共代碼倉庫,所有人都可以直接看到我們的源碼,所以我們應該用一種方式來隱藏用戶名和密碼這種私密信息,幸運的是 Jenkins 為我們提供了解決方法。 在首頁點擊 Credentials -> Stores scoped to Jenkins 下面的 Jenkins -> Global credentials (unrestricted) -> 左側的 Add Credentials:添加一個 Username with password 類型的認證信息,如下: ![](https://blog.qikqiak.com/img/posts/pipeline-demo4.png) Add Credentials 輸入 docker hub 的用戶名和密碼,ID 部分我們輸入dockerHub,注意,這個值非常重要,在后面 Pipeline 的腳本中我們需要使用到這個 ID 值。 有了上面的 docker hub 的用戶名和密碼的認證信息,現在我們可以在 Pipeline 中使用這里的用戶名和密碼了: stage('Push') { echo "4.Push Docker Image Stage" withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) { sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}" sh "docker push cnych/jenkins-demo:${build_tag}" } } 注意我們這里在 stage 中使用了一個新的函數withCredentials,其中有一個credentialsId值就是我們剛剛創建的 ID 值,然后我們就可以在腳本中直接使用這里兩個變量值來直接替換掉之前的登錄 docker hub 的用戶名和密碼,現在是不是就很安全了,我只是傳遞進去了兩個變量而已,別人并不知道我的真正用戶名和密碼,只有我們自己的 Jenkins 平臺上添加的才知道。 ### 第五步,更改 YAML 上面我們已經完成了鏡像的打包、推送的工作,接下來我們是不是應該更新 Kubernetes 系統中應用的鏡像版本了,當然為了方便維護,我們都是用 YAML 文件的形式來編寫應用部署規則,比如我們這里的 YAML 文件:(k8s.yaml) apiVersion: extensions/v1beta1 kind: Deployment metadata: name: jenkins-demo spec: template: metadata: labels: app: jenkins-demo spec: containers: - image: cnych/jenkins-demo:<BUILD_TAG> imagePullPolicy: IfNotPresent name: jenkins-demo 對于 Kubernetes 比較熟悉的同學,對上面這個 YAML 文件一定不會陌生,我們使用一個 Deployment 資源對象來管理 Pod,該 Pod 使用的就是我們上面推送的鏡像,唯一不同的地方是 Docker 鏡像的 tag 不是我們平常見的具體的 tag,而是一個 的標識,實際上如果我們將這個標識替換成上面的 Docker 鏡像的 tag,是不是就是最終我們本次構建需要使用到的鏡像?怎么替換呢?其實也很簡單,我們使用一個sed命令就可以實現了: stage('YAML') { echo "5. Change YAML File Stage" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" } 上面的 sed 命令就是將 k8s.yaml 文件中的 標識給替換成變量 build_tag 的值。 第六步,部署 Kubernetes 應用的 YAML 文件已經更改完成了,之前我們手動的環境下,是不是直接使用 kubectl apply 命令就可以直接更新應用了啊?當然我們這里只是寫入到了 Pipeline 里面,思路都是一樣的: stage('Deploy') { echo "6. Deploy Stage" sh "kubectl apply -f k8s.yaml" } 這樣到這里我們的整個流程就算完成了。 ### 人工確認 理論上來說我們上面的6個步驟其實已經完成了,但是一般在我們的實際項目實踐過程中,可能還需要一些人工干預的步驟,這是為什么呢?比如我們提交了一次代碼,測試也通過了,鏡像也打包上傳了,但是這個版本并不一定就是要立刻上線到生產環境的,對吧,我們可能需要將該版本先發布到測試環境、QA 環境、或者預覽環境之類的,總之直接就發布到線上環境去還是挺少見的,所以我們需要增加人工確認的環節,一般都是在 CD 的環節才需要人工干預,比如我們這里的最后兩步,我們就可以在前面加上確認,比如: stage('YAML') { echo "5. Change YAML File Stage" def userInput = input( id: 'userInput', message: 'Choose a deploy environment', parameters: [ [ $class: 'ChoiceParameterDefinition', choices: "Dev\nQA\nProd", name: 'Env' ] ] ) echo "This is a deploy step to ${userInput.Env}" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" } 我們這里使用了 input 關鍵字,里面使用一個 Choice 的列表來讓用戶進行選擇,然后在我們選擇了部署環境后,我們當然也可以針對不同的環境再做一些操作,比如可以給不同環境的 YAML 文件部署到不同的 namespace 下面去,增加不同的標簽等等操作: stage('Deploy') { echo "6. Deploy Stage" if (userInput.Env == "Dev") { // deploy dev stuff } else if (userInput.Env == "QA"){ // deploy qa stuff } else { // deploy prod stuff } sh "kubectl apply -f k8s.yaml" } 由于這一步也屬于部署的范疇,所以我們可以將最后兩步都合并成一步,我們最終的 Pipeline 腳本如下: node('haimaxy-jnlp') { stage('Clone') { echo "1.Clone Stage" git url: "https://github.com/cnych/jenkins-demo.git" script { build_tag = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim() } } stage('Test') { echo "2.Test Stage" } stage('Build') { echo "3.Build Docker Image Stage" sh "docker build -t cnych/jenkins-demo:${build_tag} ." } stage('Push') { echo "4.Push Docker Image Stage" withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) { sh "docker login -u ${dockerHubUser} -p ${dockerHubPassword}" sh "docker push cnych/jenkins-demo:${build_tag}" } } stage('Deploy') { echo "5. Deploy Stage" def userInput = input( id: 'userInput', message: 'Choose a deploy environment', parameters: [ [ $class: 'ChoiceParameterDefinition', choices: "Dev\nQA\nProd", name: 'Env' ] ] ) echo "This is a deploy step to ${userInput}" sh "sed -i 's/<BUILD_TAG>/${build_tag}/' k8s.yaml" if (userInput == "Dev") { // deploy dev stuff } else if (userInput == "QA"){ // deploy qa stuff } else { // deploy prod stuff } sh "kubectl apply -f k8s.yaml" } } 現在我們在 Jenkins Web UI 中重新配置 jenkins-demo 這個任務,將上面的腳本粘貼到 Script 區域,重新保存,然后點擊左側的 Build Now,觸發構建,然后過一會兒我們就可以看到 Stage View 界面出現了暫停的情況: ![](https://blog.qikqiak.com/img/posts/pipeline-demo5.png) pipeline demo5 這就是我們上面 Deploy 階段加入了人工確認的步驟,所以這個時候構建暫停了,需要我們人為的確認下,比如我們這里選擇 QA,然后點擊 Proceed,就可以繼續往下走了,然后構建就成功了,我們在 Stage View 的 Deploy 這個階段可以看到如下的一些日志信息: ![](https://blog.qikqiak.com/img/posts/pipeline-demo6.png) 打印出來了 QA,和我們剛剛的選擇是一致的,現在我們去 Kubernetes 集群中觀察下部署的應用: $ kubectl get deployment -n kube-ops NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE jenkins 1 1 1 1 7d jenkins-demo 1 1 1 0 1m $ kubectl get pods -n kube-ops NAME READY STATUS RESTARTS AGE jenkins-7c85b6f4bd-rfqgv 1/1 Running 4 7d jenkins-demo-f6f4f646b-2zdrq 0/1 Completed 4 1m $ kubectl logs jenkins-demo-f6f4f646b-2zdrq -n kube-ops Hello, Kubernetes!I'm from Jenkins CI! 我們可以看到我們的應用已經正確的部署到了 Kubernetes 的集群環境中了 參照以上的方法 我們簡單的使用了pipeline完成了一個應用的部署功能,對于使用pipeline 有一定基礎要求。在此提供一個shell 腳本,實現一個CI/CD 流程。 #!/bin/bash # Filename: k8s-deploy_v0.1.sh # Description: jenkins CI/CD 持續發布腳本 # Author: yi.hu # Email: 345270016@qq.com # Revision: 1.0 # Date: 2018-08-10 # Note: prd # zookeeper基礎服務,依照環境實際地址配置 init() { local lowerEnv="$(echo ${AppEnv} | tr '[:upper:]' 'lower')" case "${lowerEnv}" in dev) CFG_ADDR="10.34.11.186:4181" DR_CFG_ZOOKEEPER_ENV_URL="10.34.11.186:4181" ;; demo) CFG_ADDR="10.34.11.186:4181" DR_CFG_ZOOKEEPER_ENV_URL="10.34.11.186:4181" ;; *) echo "Not support AppEnv: ${AppEnv}" exit 1 ;; esac } # 初始化變量 AppId=$(echo ${AppOrg}_${AppEnv}_${AppName} |sed 's/[^a-zA-Z0-9_-]//g' | tr "[:lower:]" "[:upper:]") CFG_LABEL=${CfgLabelBaseNode}/${AppId} CFG_ADDR=${CFG_ADDR} # 登錄harbor 倉庫 docker_login () { docker login ${DOCKER_REGISTRY} -u${User} -p${PassWord} } # 編譯代碼,制作鏡像 build() { echo $ACTION if [ "x${ACTION}" == "xDEPLOY" ] || [ "x${ACTION}" == "xPRE_DEPLOY" ]; then echo "Test harbor registry: ${DOCKER_REGISTRY}" #curl -X GET --connect-timeout 30 -I ${DOCKER_REGISTRY}/v2/ 2>/dev/null | grep 'HTTP/1.1 200 OK' > /dev/null curl --connect-timeout 30 -I ${DOCKER_REGISTRY}/api/projects 2>/dev/null | grep 'HTTP/1.1 200 OK' > /dev/null echo "Check image EXIST or NOT: ${ToImage}" #Image_Check=$(echo ${ToImage} | sed 's/\([^/]\+\)\([^:]\+\):/\1\/v2\2\/manifests\//') ImageCheck_Harbor=$(echo ${ToImage} | sed 's/\([^/]\+\)\([^:]\+\):/\1\/api\/repositories\2\/tags\//') Responed_Code=$(curl -u${User}:${PassWord} -so /dev/null -w '%{response_code}' ${ImageCheck_Harbor} || true) if [ "${NoCache}" == "true" ] || [ "x${Responed_Code}" != "x200" ] ; then if [ "x${BuildCmd}" == "x" ]; then echo "Generating Dockerfile" echo "FROM ${FromImage}" > Dockerfile cat >> Dockerfile <<- EOF ${Dockerfile} EOF echo "$(<Dockerfile)" else echo -e "Building\n${BuildCmd}" eval ${BuildCmd} echo -e "Packaging\n${TarCmd}" cd ${WORKSPACE} eval ${TarCmd} echo "Copy artifact: ${CodeTarget}" cd ${WORKSPACE} if [ $(expr match "${CodeTarget}" '.*/') -ne 0 ];then CodeBasename=${CodeTarget##*/} cp -av ${CodeTarget} ${CodeBasename} else CodeBasename=${CodeTarget} fi echo "CodeBasename=#${CodeBasename}#" echo "Generate Dockerfile" cat > Dockerfile <<- EOF FROM ${FromImage} MAINTAINER devops <devops@dianrong.com> ADD ${CodeBasename} \${AppCode} EOF echo "$(<Dockerfile)" fi if [ $(expr match "${FromImage}" 'scratch') -eq 0 ];then echo "Sync from image: ${FromImage}" docker pull ${FromImage} # 同步上層鏡像 fi for i in $(sed -n '/FROM/{/scratch$/!{/[[:space:]]\+AS[[:space:]]\+/ba;s/FROM[[:space:]]\+\(.*\)\([[:space:]]*\)\?$/\1/p;:a;s/FROM[[:space:]]\+\(.*\)[[:space:]]\+AS.*/\1/p}}' Dockerfile | uniq);do docker pull ${i} # 同步Dockerfile中鏡像 done echo "Sync intermediate image in Dockerfile done" echo "Build image and push to registry: ${ToImage}" docker build --no-cache=${NoCache} -t ${ToImage} . && docker push ${ToImage} || exit 1 # 開始構建鏡像,成功后Push到倉庫 echo "Remove image: ${ToImage}" docker rmi ${ToImage} || echo # 刪除鏡像 fi fi } # 發布、預發布、停止、重啟 deploy() { if [ "x${ACTION}" == "xSTOP" ]; then # 停止當前實例 kubectl delete -f ${AppName}-deploy.yaml elif [ "x${ACTION}" == "xRESTART" ]; then kubectl delete -f k8s-deploy-script.yaml sleep 10s kubectl apply -f ${AppName}-deploy.yaml elif [ "x${ACTION}" == "xDEPLOY" ]; then kubectl apply -f ${AppName}-deploy.yaml fi } # 函數執行 init docker_login build cat > ${WORKSPACE}/${AppName}-deploy.yaml <<- EOF ##################################################### # # ${ACTION} Deployment # ##################################################### apiVersion: apps/v1beta2 # for versions before 1.8.0 use apps/v1beta1 kind: Deployment metadata: name: ${AppName} namespace: ${NameSpace} labels: app: ${AppName} version: ${GitBranch} AppEnv: ${AppEnv} spec: replicas: ${Replicas} selector: matchLabels: app: ${AppName} template: metadata: labels: app: ${AppName} spec: containers: - name: ${AppName} image: ${ToImage} ports: - containerPort: ${ContainerPort} livenessProbe: httpGet: path: ${HealthCheckURL} port: ${ContainerPort} initialDelaySeconds: 90 timeoutSeconds: 5 periodSeconds: 5 readinessProbe: httpGet: path: ${HealthCheckURL} port: ${ContainerPort} initialDelaySeconds: 5 timeoutSeconds: 5 periodSeconds: 5 # configmap env env: - name: CFG_LABEL value: ${CFG_LABEL} - name: CFG_ADDR valueFrom: configMapKeyRef: name: ${ConfigMap} key: CFG_ADDR - name: DR_CFG_ZOOKEEPER_ENV_URL valueFrom: configMapKeyRef: name: ${ConfigMap} key: DR_CFG_ZOOKEEPER_ENV_URL - name: CFG_FILES valueFrom: configMapKeyRef: name: ${ConfigMap} key: CFG_FILES # configMap volume volumeMounts: - name: applogs mountPath: /volume_logs/ volumes: - name: applogs hostPath: path: /opt/app_logs/${AppName} imagePullSecrets: - name: ${ImagePullSecrets} --- apiVersion: v1 kind: Service metadata: name: ${AppName} namespace: ${NameSpace} labels: app: ${AppName} spec: ports: - port: ${ContainerPort} targetPort: ${ContainerPort} selector: app: ${AppName} --- kind: ConfigMap apiVersion: v1 metadata: name: ${ConfigMap} namespace: ${NameSpace} data: CFG_ADDR: ${CFG_ADDR} DR_CFG_ZOOKEEPER_ENV_URL: ${DR_CFG_ZOOKEEPER_ENV_URL} CFG_FILES: ${Cfs_Files} EOF # 執行部署 deploy # 打印配置 cat ${WORKSPACE}/${AppName}-deploy.yaml
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看