運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

DevOps

demo原始碼見:https://gitee。com/zhengqingya/java-workspace

基於

kubesphere 3。2。1

自動檢出 (Checkout) 程式碼、測試、分析、構建、部署併發布

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

一、建立DevOps專案

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

二、DevOps憑證

1、gitee倉庫認證gitee-auth

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

2、阿里雲docker倉庫認證aliyun-docker-registry-auth

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

3、k8s憑證kubeconfig-auth

# k8s許可權配置檔案cat /root/。kube/config

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

將內容中的

https://lb。kubesphere。local:6443

->

https://指定IP:6443

,不然之後部署可能會出現問題。。。

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

最終

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

三、maven配置阿里雲中央倉庫

平臺管理

->

叢集管理

->

default

->

配置

->

配置字典

->

ks-devops-agent

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

編輯設定

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

<!—— 國內中央倉庫的配置-阿里雲中央倉庫 ——> nexus-aliyun central Nexus aliyun http://maven。aliyun。com/nexus/content/groups/public

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

四、k8s-專案配置

阿里雲docker倉庫認證aliyun-docker-registry-auth

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

# 也可透過命令檢視憑證kubectl get secrets -n my-project

五、建立流水線

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

進入後可以點選

編輯流水線

,提供了一些模板

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

ex: 第一步拉取程式碼

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

這裡自己點著玩吧,很簡單。。。 根據自己的需求去定製即可。。。

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

六、其它

Jenkinsfile

pipeline { agent { node { label ‘maven’ } } environment { DOCKER_REGISTRY_AUTH = “aliyun-docker-registry-auth” DOCKER_REGISTRY = ‘registry。cn-hangzhou。aliyuncs。com’ DOCKER_REGISTRY_NAMESPACE = ‘zhengqingya’ APP_DOCKER_IMAGE = “${DOCKER_REGISTRY}/${DOCKER_REGISTRY_NAMESPACE}/${APP_NAME}:${BRANCH_NAME}” PROJECT_GIT_URL = ‘https://gitee。com/zhengqingya/test。git’ APP_NAME = ‘test’ BRANCH_NAME = ‘master’ IS_SKIP_BUILD = ‘false’ JAVA_OPTS = “-XX:+UseG1GC -Xms100m -Xmx100m -Dserver。port=8080” }// parameters {// string(name: ‘BRANCH_NAME’, defaultValue: ‘master’, description: ‘git分支名’)// choice(name: ‘IS_SKIP_BUILD’, choices: [‘false’, ‘true’], description: ‘是否跳過構建,直接部署’)// choice(name: ‘SERVICE_NAMES’, choices: [‘test’, ‘system’ ,‘all’], description: ‘請選擇要構建的服務,支援單個服務釋出或全部服務釋出’)// } stages { stage(‘引數驗證’) { agent none steps { container(‘maven’) { sh “”“ echo ”分支: ${BRANCH_NAME}“ echo ”是否跳過構建,直接部署(tips:適用於之前已經進行過構建打包的情景):${IS_SKIP_BUILD}“ echo ”app映象: ${APP_DOCKER_IMAGE}“ echo ”構建執行ID: ${BUILD_NUMBER}“ echo ”JAVA_OPTS: ${JAVA_OPTS}“ ”“” } } } stage(‘拉取程式碼’) { agent none steps { container(‘maven’) { git(credentialsId: ‘gitee-auth’, url: “${PROJECT_GIT_URL}”, branch: “${BRANCH_NAME}”, changelog: true, poll: false) sh ‘ls -al’ } } } stage(‘專案編譯’) { agent none steps { container(‘maven’) { sh ‘mvn clean package -Dmaven。test。skip=true’ sh ‘ls -al’ } } } stage(‘docker映象構建&推送’) { agent none steps { container(‘maven’) { sh ‘cp target/*。jar docker’ sh “”“ cd docker ls echo ”app映象: ${APP_DOCKER_IMAGE}“ docker build -f Dockerfile -t ${APP_DOCKER_IMAGE} 。 ——no-cache ”“” withCredentials([usernamePassword(credentialsId: “${DOCKER_REGISTRY_AUTH}”, passwordVariable: ‘DOCKER_PASSWORD’, usernameVariable: ‘DOCKER_USERNAME’,)]) { sh ‘echo “$DOCKER_PASSWORD” | docker login $DOCKER_REGISTRY -u “$DOCKER_USERNAME” ——password-stdin’ sh ‘docker push ${APP_DOCKER_IMAGE}’ sh “echo 映象推送成功:${APP_DOCKER_IMAGE}” sh ‘ls -al’ } } } } stage(‘釋出到k8s’) { agent none steps { container(‘maven’) { sh ‘ls -al’ withCredentials([kubeconfigFile(credentialsId: ‘kubeconfig-auth’, variable: ‘KUBECONFIG’)]) { // envsubst: 將相關引數傳給該yml檔案 sh ‘envsubst < k8s/k8s-deploy。yml | kubectl apply -f -’ } } } } }}

k8s-deploy。yml

——-# 定義工作負載apiVersion: apps/v1kind: Deployment # 無狀態部署metadata: name: ${APP_NAME} namespace: my-project # TODO 名稱空間 labels: app: ${APP_NAME}spec: replicas: 3 # TODO 3個副本 strategy: rollingUpdate: # 由於replicas為3,則整個升級,pod個數在2-4個之間 maxSurge: 1 # 滾動升級時會先啟動1個pod maxUnavailable: 1 # 滾動升級時允許的最大Unavailable的pod個數 selector: matchLabels: app: ${APP_NAME} template: metadata: labels: app: ${APP_NAME} spec: imagePullSecrets: - name: aliyun-docker-registry-auth # TODO 提前在專案下配置訪問阿里雲倉庫的賬號密碼 containers: - name: ${APP_NAME} image: ${APP_DOCKER_IMAGE} # TODO 映象地址 imagePullPolicy: Always env: # 環境變數 - name: JAVA_OPTS value: ${JAVA_OPTS} ports: - name: http containerPort: 8080 protocol: TCP # CPU記憶體限制 resources: limits: cpu: 300m memory: 600Mi # 就緒探針# readinessProbe:# httpGet:# path: /actuator/health# port: 8080# timeoutSeconds: 10# failureThreshold: 30# periodSeconds: 5——-# 定義服務apiVersion: v1kind: Servicemetadata: name: ${APP_NAME} # TODO 服務名 namespace: my-project # TODO 名稱空間spec: selector: app: ${APP_NAME} # TODO label selector配置,將選擇具有label標籤的Pod作為管理 type: ClusterIP # 訪問方式 ClusterIP/NodePort ports: - name: http # 埠名稱 port: 8080 protocol: TCP # 埠協議,支援TCP和UDP,預設TCP targetPort: 8080 # nodePort: 666 # TODO 當`type = NodePort`時 對外開放埠 sessionAffinity: None # 是否支援session

k8s yaml 線上編寫工具

• https://k8syaml。com

報錯ERROR: java。lang。RuntimeException: io。kubernetes。client。openapi。ApiException: java。net。UnknownHostException: lb。kubesphere。local: Name or service not known

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

Deploy to Kubernetes14。66 s失敗Starting Kubernetes deploymentLoading configuration: /home/jenkins/agent/workspace/devops-testp5hsh/test/k8s/k8s-deploy。ymlERROR: ERROR: java。lang。RuntimeException: io。kubernetes。client。openapi。ApiException: java。net。UnknownHostException: lb。kubesphere。local: Name or service not knownhudson。remoting。ProxyException: java。lang。RuntimeException: io。kubernetes。client。openapi。ApiException: java。net。UnknownHostException: lb。kubesphere。local: Name or service not known at com。microsoft。jenkins。kubernetes。wrapper。ResourceManager。handleApiExceptionExceptNotFound(ResourceManager。java:180) at com。microsoft。jenkins。kubernetes。wrapper。V1ResourceManager$DeploymentUpdater。getCurrentResource(V1ResourceManager。java:213) at com。microsoft。jenkins。kubernetes。wrapper。V1ResourceManager$DeploymentUpdater。getCurrentResource(V1ResourceManager。java:201) at com。microsoft。jenkins。kubernetes。wrapper。ResourceManager$ResourceUpdater。createOrApply(ResourceManager。java:93) at com。microsoft。jenkins。kubernetes。wrapper。KubernetesClientWrapper。handleResource(KubernetesClientWrapper。java:289) at com。microsoft。jenkins。kubernetes。wrapper。KubernetesClientWrapper。apply(KubernetesClientWrapper。java:256) at com。microsoft。jenkins。kubernetes。command。DeploymentCommand$DeploymentTask。doCall(DeploymentCommand。java:172) at com。microsoft。jenkins。kubernetes。command。DeploymentCommand$DeploymentTask。call(DeploymentCommand。java:124) at com。microsoft。jenkins。kubernetes。command。DeploymentCommand$DeploymentTask。call(DeploymentCommand。java:106) at hudson。remoting。UserRequest。perform(UserRequest。java:212) at hudson。remoting。UserRequest。perform(UserRequest。java:54) at hudson。remoting。Request$2。run(Request。java:369) at hudson。remoting。InterceptingExecutorService$1。call(InterceptingExecutorService。java:72) at java。util。concurrent。FutureTask。run(FutureTask。java:266) at java。util。concurrent。ThreadPoolExecutor。runWorker(ThreadPoolExecutor。java:1149) at java。util。concurrent。ThreadPoolExecutor$Worker。run(ThreadPoolExecutor。java:624) at hudson。remoting。Engine$1。lambda$newThread$0(Engine。java:93) at java。lang。Thread。run(Thread。java:748) Suppressed: hudson。remoting。Channel$CallSiteStackTrace: Remote call to JNLP4-connect connection from 10。233。70。143/10。233。70。143:51962 at hudson。remoting。Channel。attachCallSiteStackTrace(Channel。java:1800) at hudson。remoting。UserRequest$ExceptionResponse。retrieve(UserRequest。java:357) at hudson。remoting。Channel。call(Channel。java:1001) at hudson。FilePath。act(FilePath。java:1160) at com。microsoft。jenkins。kubernetes。command。DeploymentCommand。execute(DeploymentCommand。java:68) at com。microsoft。jenkins。kubernetes。command。DeploymentCommand。execute(DeploymentCommand。java:45) at com。microsoft。jenkins。azurecommons。command。CommandService。runCommand(CommandService。java:88) at com。microsoft。jenkins。azurecommons。command。CommandService。execute(CommandService。java:96) at com。microsoft。jenkins。azurecommons。command。CommandService。executeCommands(CommandService。java:75) at com。microsoft。jenkins。azurecommons。command。BaseCommandContext。executeCommands(BaseCommandContext。java:77) at com。microsoft。jenkins。kubernetes。KubernetesDeploy。perform(KubernetesDeploy。java:42) at com。microsoft。jenkins。azurecommons。command。SimpleBuildStepExecution。run(SimpleBuildStepExecution。java:54) at com。microsoft。jenkins。azurecommons。command。SimpleBuildStepExecution。run(SimpleBuildStepExecution。java:35) at org。jenkinsci。plugins。workflow。steps。SynchronousNonBlockingStepExecution。lambda$start$0(SynchronousNonBlockingStepExecution。java:47) at java。util。concurrent。Executors$RunnableAdapter。call(Executors。java:511) at java。util。concurrent。FutureTask。run(FutureTask。java:266) at java。util。concurrent。ThreadPoolExecutor。runWorker(ThreadPoolExecutor。java:1149) at java。util。concurrent。ThreadPoolExecutor$Worker。run(ThreadPoolExecutor。java:624) 。。。 1 moreCaused by: hudson。remoting。ProxyException: io。kubernetes。client。openapi。ApiException: java。net。UnknownHostException: lb。kubesphere。local: Name or service not known at io。kubernetes。client。openapi。ApiClient。execute(ApiClient。java:898) at io。kubernetes。client。openapi。apis。AppsV1Api。readNamespacedDeploymentWithHttpInfo(AppsV1Api。java:7299) at io。kubernetes。client。openapi。apis。AppsV1Api。readNamespacedDeployment(AppsV1Api。java:7275) at com。microsoft。jenkins。kubernetes。wrapper。V1ResourceManager$DeploymentUpdater。getCurrentResource(V1ResourceManager。java:210) 。。。 16 moreCaused by: hudson。remoting。ProxyException: java。net。UnknownHostException: lb。kubesphere。local: Name or service not known at java。net。Inet4AddressImpl。lookupAllHostAddr(Native Method) at java。net。InetAddress$2。lookupAllHostAddr(InetAddress。java:929) at java。net。InetAddress。getAddressesFromNameService(InetAddress。java:1324) at java。net。InetAddress。getAllByName0(InetAddress。java:1277) at java。net。InetAddress。getAllByName(InetAddress。java:1193) at java。net。InetAddress。getAllByName(InetAddress。java:1127) at okhttp3。Dns。lambda$static$0(Dns。java:39) at okhttp3。internal。connection。RouteSelector。resetNextInetSocketAddress(RouteSelector。java:171) at okhttp3。internal。connection。RouteSelector。nextProxy(RouteSelector。java:135) at okhttp3。internal。connection。RouteSelector。next(RouteSelector。java:84) at okhttp3。internal。connection。ExchangeFinder。findConnection(ExchangeFinder。java:187) at okhttp3。internal。connection。ExchangeFinder。findHealthyConnection(ExchangeFinder。java:108) at okhttp3。internal。connection。ExchangeFinder。find(ExchangeFinder。java:88) at okhttp3。internal。connection。Transmitter。newExchange(Transmitter。java:169) at okhttp3。internal。connection。ConnectInterceptor。intercept(ConnectInterceptor。java:41) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:142) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:117) at okhttp3。internal。cache。CacheInterceptor。intercept(CacheInterceptor。java:94) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:142) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:117) at okhttp3。internal。http。BridgeInterceptor。intercept(BridgeInterceptor。java:93) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:142) at okhttp3。internal。http。RetryAndFollowUpInterceptor。intercept(RetryAndFollowUpInterceptor。java:88) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:142) at okhttp3。internal。http。RealInterceptorChain。proceed(RealInterceptorChain。java:117) at okhttp3。RealCall。getResponseWithInterceptorChain(RealCall。java:221) at okhttp3。RealCall。execute(RealCall。java:81) at io。kubernetes。client。openapi。ApiClient。execute(ApiClient。java:894) 。。。 19 moreApi call failed with code 0, detailed message: nullKubernetes deployment ended with HasError

解決:

kubesphere 3。2。1

流水線調整

第一步:替換kubernetesDeploy部署方式

https://github。com/kubesphere/website/pull/2098

stage(‘釋出到k8s’) { agent none steps { container(‘maven’) { // 廢棄。。。 // kubernetesDeploy(enableConfigSubstitution: true, deleteResource: false, kubeconfigId: ‘kubeconfig-auth’, configs: ‘k8s/**’) // 改為下面這種方式 withCredentials([kubeconfigFile(credentialsId: ‘kubeconfig-auth’, variable: ‘KUBECONFIG’)]) { // envsubst: 將相關引數傳給該yml檔案 sh ‘envsubst < k8s/k8s-deploy。yml | kubectl apply -f -’ } } }}

第二步:修改DevOps憑證kubeconfig

將內容中的

https://lb。kubesphere。local:6443

->

https://指定IP:6443

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

最終釋出成功

運維(39) 透過KubeSphere部署SpringBoot到K8S案例 DevOps

在這裡插入圖片描述

今日分享語句: 天再高又怎樣,踮起腳尖就更接近陽光。