<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # ***kubernetes 基于Jenkins的動態應用實部署實踐*** ## # 自我介紹 - 光榮的武警戰士 - 紅帽RHCA講師 - 知道創宇高級運維工程師 - 點融網資深運維工程師 ![點融金融](https://box.kancloud.cn/0d59f507459443658eef16bec9fcd27d_247x362.png) # 胡毅 yi.hu@dianrong.com ## # 目錄 - Kubernetes Arch - Why install jenkins in kubernetes - 在kubernetes中使用Jenkins部署一個應用 ## kubernetes Arch - kubespray - k8s-cluser :v1.10.4 - docker: docker-ce-17.03.2.ce-1.el7.centos - nginx-ingress : - coresdns - kube-proxy(IPVS) ![](http://on-img.com/chart_image/5ad55cefe4b04721d61f6f0b.png?_=1535249246166) ## Cluster HA-mode ![image](https://raw.githubusercontent.com/kubernetes-incubator/kubespray/master/docs/figures/loadbalancer_localhost.png) ### kubernets 集群管理策略(一) - Taints and Tolerations master 所有主機添加Taints 規則 kubectl taint nodes dl-demo-k8s-master-01 node.kubernetes.io=unschedulable:NoSchedule kubectl taint nodes dl-demo-k8s-master-02 node.kubernetes.io=unschedulable:NoSchedule kubectl taint nodes dl-demo-k8s-master-03 node.kubernetes.io=unschedulable:NoSchedule 設置效果 Name: dl-demo-k8s-master-01 Roles: ingress,master,node Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/hostname=dl-demo-k8s-master-01 node-role.kubernetes.io/ingress=true node-role.kubernetes.io/master=true node-role.kubernetes.io/node=true Annotations: alpha.kubernetes.io/provided-node-ip=10.34.11.12 flannel.alpha.coreos.com/backend-data={"VtepMAC":"e6:20:4c:cf:4f:2b"} flannel.alpha.coreos.com/backend-type=vxlan flannel.alpha.coreos.com/kube-subnet-manager=true flannel.alpha.coreos.com/public-ip=10.34.11.12 node.alpha.kubernetes.io/ttl=0 volumes.kubernetes.io/controller-managed-attach-detach=true CreationTimestamp: Tue, 10 Jul 2018 15:06:51 +0800 Taints: node.kubernetes.io=unschedulable:NoSchedule master組件Deployment添加Tolerations 規則 tolerations: - key: node.kubernetes.io value: unschedulable effect: NoSchedule ### kubernetes 集群管理策略(二) - LimitRange 給一個namespace 設置全局資源限制規則 apiVersion: v1 kind: LimitRange metadata: name: ftc-demo-limit namespace: ftc-demo spec: limits: - max : # 在一個pod 中最高使用資源 cpu: "2" memory: "6Gi" min: # 在一個pod中最低使用資源 cpu: "100m" memory: "2Gi" type: Pod - default: # 啟動一個Container 默認資源規則 cpu: "1" memory: "4Gi" defaultRequest: cpu: "200m" memory: "2Gi" max: #匹配用戶手動指定Limits 規則 cpu: "1" memory: "4Gi" min: cpu: "100m" memory: "256Mi" type: Container 限制規則說明 * Container 資源限制總量必須 <= Pod 資源限制總和 * 在一個pod 中最高使用2 核6G 內存 * 在一個pod中最低使用100m核 2G 內存 * 默認啟動一個Container服務 強分配cpu 200m,內存2G。Container 最高使用 1 cpu 4G 內存。 * 如果用戶私有指定limits 規則。最高使用1 CPU 4G內存,最低使用 cpu 100m 內存 256Mi ## Why install jenkins in kubernetes ### 傳統的 Jenkins Slave 一主多從方式會存在一些痛點? * 主 Master 發生單點故障時,整個流程都不可用了 * 每個 Slave 的配置環境不一樣,來完成不同語言的編譯打包等操作,但是這些差異化的配置導致管理起來非常不方便,維護起來也是比較費勁 * 資源分配不均衡,有的 Slave 要運行的 job 出現排隊等待,而有的 Slave 處于空閑狀態 * 資源有浪費,每臺 Slave 可能是物理機或者虛擬機,當 Slave 處于空閑狀態時,也不會完全釋放掉資源。 正因為上面的這些種種痛點,我們渴望一種更高效更可靠的方式來完成這個 CI/CD 流程,而 Docker 虛擬化容器技術能很好的解決這個痛點,又特別是在 Kubernetes 集群環境下面能夠更好來解決上面的問題,下圖是基于 Kubernetes 搭建 Jenkins 集群的簡單示意圖 ![](https://blog.qikqiak.com/img/posts/k8s-jenkins-slave.png) 從圖上可以看到 Jenkins Master 和 Jenkins Slave 以 Pod 形式運行在 Kubernetes 集群的 Node 上,Master 運行在其中一個節點,并且將其配置數據存儲到一個 Volume 上去,Slave 運行在各個節點上,并且它不是一直處于運行狀態,它會按照需求動態的創建并自動刪除。 這種方式的工作流程大致為:當 Jenkins Master 接受到 Build 請求時,會根據配置的 Label 動態創建一個運行在 Pod 中的 Jenkins Slave 并注冊到 Master 上,當運行完 Job 后,這個 Slave 會被注銷并且這個 Pod 也會自動刪除,恢復到最初狀態。 那么我們使用這種方式帶來了哪些好處呢? * 服務高可用,當 Jenkins Master 出現故障時,Kubernetes 會自動創建一個新的 Jenkins Master 容器,并且將 Volume 分配給新創建的容器,保證數據不丟失,從而達到集群服務高可用。 * 動態伸縮,合理使用資源,每次運行 Job 時,會自動創建一個 Jenkins Slave,Job 完成后,Slave 自動注銷并刪除容器,資源自動釋放,而且 Kubernetes 會根據每個資源的使用情況,動態分配 Slave 到空閑的節點上創建,降低出現因某節點資源利用率高,還排隊等待在該節點的情況。 * 擴展性好,當 Kubernetes 集群的資源嚴重不足而導致 Job 排隊等待時,可以很容易的添加一個 Kubernetes Node 到集群中,從而實現擴展。 # 光說不練假把式 (實驗演示一) ## # 在Jenkins中部署一個應用 - Pipeline VS Scripte ### 部署 Kubernetes 應用 如何來部署一個原生的 Kubernetes 應用呢? 部署一個kubernetes 應用流程如下: ![](http://on-img.com/chart_image/5b84ad40e4b0d4d65be96283.png?_=1535509752205) 1. pull代碼 2. 測試registry,并登陸registry. 3. 編寫應用 Dockerfile 4. 構建打包 Docker 鏡像 5. 推送 Docker 鏡像到倉庫 6. 更改 Deployment YAML 文件中參數 7. 利用 kubectl 工具部署應用 8. 檢查應用狀態 ### 第一步,Pull 代碼及全局環境變量申明 #!/bin/bash # Filename: k8s-deploy_v0.2.sh # Description: jenkins CI/CD 持續發布腳本 # Author: yi.hu # Email: yi.hu@dianrong.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 } # 函數執行 init # 初始化變量 AppId=$(echo ${AppOrg}_${AppEnv}_${AppName} |sed 's/[^a-zA-Z0-9_-]//g' | tr "[:lower:]" "[:upper:]") CFG_LABEL=${CfgLabelBaseNode}/${AppId} CFG_ADDR=${CFG_ADDR} VERSION=$(echo "${GitBranch}" | sed 's@release/@@') ### 第二步,登錄harbor 倉庫 docker_login () { docker login ${DOCKER_REGISTRY} -u${User} -p${PassWord} } ### 第三步,編譯代碼,制作應用鏡像,上傳鏡像到harbor倉庫。 build() { if [ "x${ACTION}" == "xDEPLOY" ] || [ "x${ACTION}" == "xPRE_DEPLOY" ]; then echo "Test harbor registry: ${DOCKER_REGISTRY}" 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}" 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) echo ${Responed_Code} if [ "${NoCache}" == "true" ] || [ "x${ResponedCode}" != "x200" ] ; then if [ "x${ActionAfterBuild}" != "x" ]; then eval ${ActionAfterBuild} fi echo "生成Dockerfile文件" echo "FROM ${FromImage}" > Dockerfile cat >> Dockerfile <<-EOF ${Dockerfile} EOF echo "同步上層鏡像: ${FromImage}" docker pull ${FromImage} # 同步上層鏡像 echo "構建鏡像,并Push到倉庫: ${ToImage}" docker build --no-cache=${NoCache} -t ${ToImage} . && docker push ${ToImage} || exit 1 # 開始構建鏡像,成功后Push到倉庫 echo "刪除鏡像: ${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 pod -n ${NameSpace} -l app=${AppName} elif [ "x${ACTION}" == "xDEPLOY" ]; then kubectl apply -f ${AppName}-deploy.yaml fi } ### 第五步,查看pod 是否正常啟動,如果失敗則返回1,進而會詳細顯示報錯信息。 check_status() { RETRY_COUNT=5 echo "檢查 pod 運行狀態" while (( $RETRY_COUNT )); do POD_STATUS=$(kubectl get pod -n ${NameSpace} -l app=${AppName} ) AVAILABLE_COUNT=$(kubectl get deploy -n ${NameSpace} -l app=${AppName} | awk '{print $(NF-1)}' | grep -v 'AVAILABLE') if [ "X${AVAILABLE_COUNT}" != "X${Replicas}" ]; then echo "[$(date '+%F %T')] Show pod Status , wait 30s and retry #$RETRY_COUNT " echo "${POD_STATUS}" let RETRY_COUNT-- || true sleep 30 elif [ "X${AVAILABLE_COUNT}" == "X${Replicas}" ]; then echo "Deploy Running successed" break else echo "[$(date '+%F %T')] NOT expected pod status: " echo "${POD_STATUS}" return 1 fi done if [ "X${RETRY_COUNT}" == "X0" ]; then echo "[$(date '+%F %T')] show describe pod status: " echo -e "`kubectl describe pod -n ${NameSpace} -l app=${AppName}`" fi } #主流程函數執行 docker_login build ### 第六步, 更改 YAML 文件中參數 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: ${VERSION} 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: HTTP_SERVER value: ${HTTP_SERVER} - name: CFG_ADDR value: ${CFG_ADDR} - name: DR_CFG_ZOOKEEPER_ENV_URL value: ${DR_CFG_ZOOKEEPER_ENV_URL} - name: ENTRYPOINT valueFrom: configMapKeyRef: name: ${ConfigMap} key: ENTRYPOINT - name: HTTP_TAR_FILES valueFrom: configMapKeyRef: name: ${ConfigMap} key: HTTP_TAR_FILES - name: WITH_SGHUB_APM_AGENT valueFrom: configMapKeyRef: name: ${ConfigMap} key: WITH_SGHUB_APM_AGENT - name: WITH_TINGYUN valueFrom: configMapKeyRef: name: ${ConfigMap} key: WITH_TINGYUN - 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} EOF ### 第七步,創建configmap 環境變量 kubectl delete configmap ${ConfigMap} -n ${NameSpace} kubectl create configmap ${ConfigMap} ${ConfigMapData} -n ${NameSpace} # 執行部署 deploy # 打印配置 cat ${WORKSPACE}/${AppName}-deploy.yaml # 執行啟動狀態檢查 check_status ### 實驗演示(二)
                  <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>

                              哎呀哎呀视频在线观看