java調用k8s的簡單介紹

本文目錄一覽:

springboot2.X使用k8s的configmap

處於項目需要使用kubernetes 的configmap作為配置中心。

這裡的 app-config 是configmap 的名稱可根據不同項目不同環境來自定義如: test-app-main-config 或者 test-redis-config 等等。

創建完成後 使用如下命令查看k8s中的configmap 我這裡查看的默認 namespace 下的cm 。

使用下列命令查看 configmap中的 內容

會把指定文件夾下的 文件都存入configmap中,這裡不展開贅述

這裡的 –from-literal 可以指定多個 key-value 鍵值對

創建的配置到此創建完畢。接下來說重點

配置完成後 reimport 一下

在springboot項目 — resources 文件下創建 bootstrap.yml 文件 如果有其他配置文件建議都移動到 自己新建一個文件下面

文件內容如下

這裡的 @ConfigurationProperties(prefix = “common.redis”) 需要注意 common.redis 這個東西是配置文件中讀取的前綴。需要更具自己的項目所用的配置來定義

如propertes 文件

創建RedisConfigProperties.java

自行寫個controller 來測試,當然我這邊也提供一個 方便大家複製粘貼

至此springboot 中獲取 configmap主要配置結束。本地如果有k8s環境則可以直接啟動訪 上面controller的連接來驗證是否加載了配置。

注意 如果使用 @Vaule 註解來獲取配置 時不會在configmap有變化的時候 獲取到變化的值

這個配置到算簡單。重點是在你的springboot項目部署到 pod 中時 會提示無法訪問 configmap 。是因為在k8s集群環境中 創建的 pod 默認使用的是 RBAC 模式授權 ,使用的是default的權限,然而 default 權限無法在pod內訪問到 APIservice 開放的 restful 接口。

思路:創建 RBAC 模式的 角色 和權限

創建 config-reader-role.yml 文件 。

文件內容如下:

創建文件完成後直接執行如下命令:

創建完成後需要在我們創建部署的 deployment.yml 文件中指定 使用 config-reader 的權限 。在下面節點

spec– template– spec 添加 serviceAccountName: config-reader

下面貼出 deployment.yml 文件內容:

如此依賴 啟動的 pod 內 springboot項目就能獲取到configmap 的配置文件了。

Jenkins-配置K8S負載

隨着Jenkins被大量使用,單台打包機完全無法應對打包慢,線程不夠等一系列問題

這時候可以添加固定Node的方式去解決問題,但是慢慢你會發現固定Node也無法解決問題,如果並不是超級多的打包任務,或者根本沒得使用K8S的這個條件請移步 Jenkins配置從節點 來解決單台打包機性能不夠的問題

其中最主要的矛盾如下

1.不同的打包環境指定不同的打包機

2.集中在一個時間段打包,特別是在發版本的前夕,所有項目組都在打包,顯得特別無力

3.大部分時間閑置的打包負載顯得有點浪費

這時候就急需一個可以動態縮放的Node來解決這個問題。

將K8S作為Jenkins負載就是為了解決動態縮放,不同環境需要指定不同打包機的問題(Windows和Mac還是需要單獨處理)。

官網文檔 在 Kubernetes 上擴展 Jenkins

首先在Jenkins中搜索 Kubernetes 這個插件,安裝上

配置K8S荷載

其中這個Kubernetes地址就是K8S-Api-Server的地址,可以在kube.config中找到

然後點擊連接測試,出現如下就對了,但是講道理會出現一個

找不到 /var/lib/jenkins/.kube/config.json 的錯誤,出現這個錯誤就要將kubeConfig放到這個位置

(Tips:如果你是Rancher搭建的K8S集群就在這個位置找API-Server的地址和kubeConfig)

這裡是比較重要的,Pod模板是為了方便打包的, jnlp 這個鏡像是必須要的,沒有這個鏡像就無法連接上Jenkins,這個鏡像是可以拓展的。

不建議再這個鏡像中安裝Docker,安裝Dotnet,安裝Java,安裝NodeJs,因為這些都可以用多容器和Jenkins插件來解決

可以在這個鏡像中安裝例如解壓縮這樣的小工具。

重寫的配置如下

這種K8S中的Node有一個很大的缺陷就是緩存的問題,如Nuget緩存,這時候就需要掛載一個盤去進行緩存了,有條件的建議掛載一個PVC,但是像我這樣沒條件的HostPath也香。

PS:這裡用Dotnet打包為例子

Dotnet打包需要用到的鏡像是dotnetsdk,所以需要在jnlp的基礎上再加上一個其他鏡像,使用的時候就

利用 container 這個指令去指定容器。後面的名稱就是容器模板中定義的名稱,需要唯一指定。

Dotnet打包要想快就要將Nuget的包全部緩存下來,所以需要將~/.nuget 這個文件夾裏面的東西用PV緩存起來(鄙人沒這個條件,用的HostPath)

使用 node 這個命令去指定節點

然後再NodeManager中查看就會看到出現了一個新的節點了,這個節點就是K8S中調度的,在打包完成後就會回收掉這個Pod。

到這裡為Jenkins配置K8S的負載就全部完畢了。

Kubernetes 的REST API指的是什麼?

REST API是Kubernetes系統的重要部分,組件之間的所有操作和通信均由API Server處理的REST API調用,大多數情況下,API定義和實現都符合標準的HTTP REST格式,可以通過 kubectl命令管理工具或其他命令行工具來執行。

API 版本

為了在兼容舊版本的同時不斷升級新的API,Kubernetes支持多種API版本,每種API版本都有不同的API路徑,例如/api/v1或 /apis/extensions/v1beta1。

API版本規則是通過基於API level選擇版本,而不是基於資源和域級別選擇,是為了確保API能夠描述一個清晰的連續的系統資源和行為的視圖,能夠控制訪問的整個過程和控制實驗性API的訪問。

JSON和Protobuf序列化模式遵循相同的模式變化原則,以下所有描述都涵蓋了這兩種模式。

需要注意,API版本和軟件的版本沒有直接關係,不同API版本有不同程度穩定性,API文檔中詳細描述了每個級別的標準。

Alpha級別:

包含alpha名稱的版本(例如v1alpha1)。

該軟件可能包含錯誤。啟用一個功能可能會導致bug。默認情況下,功能可能會被禁用。

隨時可能會丟棄對該功能的支持,恕不另行通知。

API可能在以後的軟件版本中以不兼容的方式更改,恕不另行通知。

該軟件建議僅在短期測試集群中使用,因為錯誤的風險增加和缺乏長期支持。

Beta級別:

包含beta名稱的版本(例如v2beta3)。

該軟件經過很好的測試。啟用功能被認為是安全的。默認情況下功能是開啟的。

細節可能會改變,但功能在後續版本不會被刪除

對象的模式或語義在隨後的beta版本或Stable版本中可能以不兼容的方式發生變化。如果這種情況發生時,官方會提供遷移操作指南。這可能需要刪除、編輯和重新創建API對象。

該版本在後續可能會更改一些不兼容地方,所以建議用於非關鍵業務,如果你有多個可以獨立升級的集群,你也可以放寬此限制。

大家使用過的Beta版本後,可以多給社區反饋,如果此版本在後續更新後將不會有太大變化。

Stable級別:

該版本名稱命名方式:vX這裡X是一個整數。

Stable版本的功能特性,將出現在後續發佈的軟件版本中。

Kubernetes API 概述

給 運行在 k8s 里的 springboot 指定 jvm 參數

我們知道,對於 tomcat 來說,設置 JAVA_OPTS 就可以給 jvm 設置一些參數, 比如 -Xms -Xmx 之類的堆大小參數

但是 對於 Spring boot 來說,因為是直接運行 java -jar 的,除非你修改 dockerfile , 不然直接設置 JAVA_OPTS 是沒有效果的

最近在網上找了一些資料,得到了答案,分享到這裡

如果容器是直接運行 tomcat 的, 那麼 入口其實是指定運行 catalina.sh

JAVA_OPTS 是 catalina.sh 使用到的一個環境變量,在運行 org.apache.catalina.startup.Bootstrap 前, 會把 JAVA_OPTS 參數拼到前面

所以這是我們直接在 k8s yaml 里設置變量 JAVA_OPTS 可以生效的原因

大概看下 catalina.sh

Spring boot 項目打出來的一般是 jar , 我們的 dockerfile 入口一般也是 java -jar xxx.jar

修改 dockerfile, 變成 java $JAVA_OPTS -jar xxx.jar 思路肯定是可行的,但是裏面有些坑,

此處不詳細描述,可以見 stackoverflow

在不修改 dockerfile 的情況下有一種很簡單的方法,可以達到傳遞 jvm 參數的效果

就是使用 JAVA_TOOL_OPTIONS

我們以 初始堆大小 參數為例,來看一下

我們什麼環境變量都不加

可以看到默認 大小是 24MB

命令解釋一下:

執行三個命令

jps 看下運行的java進程pid 是啥

jinfo -flag InitialHeapSize {pid} 看下 初始堆大小參數是多少, 去掉 -flag InitialHeapSize 看所有的參數(具體看jvm廠商有沒有實現這個功能,據我所知,oracle 的 openjdk 實現了,IcedTea的OpenJdk沒有實現)

echo $(( {size} 10 10)) 位運算,jinfo 輸出的是 byte, 除以1024 是 KB, 再除以1024 是 MB, 1024=2^10,所以除以1024等於位運算右移10位,計算更快

JAVA_OPTS -XX:InitialHeapSize=66m

可以看到 還是 24MB

細心的應該注意到了 exec 的 pod name 變了,因為我修改了環境變量,需要重啟,重啟之後pod name 自然就變了

可以看到 變成 66MB 了,符合我們的設置

另外,執行 jps 的時候,就輸出了 Picked up JAVA_TOOL_OPTIONS: -XX:InitialHeapSize=66m

前面兩種場景是沒有輸出的哦

開發和運維對K8S中的應用都做了什麼?

在應用的整個生命周期里,開發和運維都和它密不可分。一個塑造它,一個保養它。

如果應用需要部署到K8S中,開發和運維在其中都做了什麼呢?

從開發側來說,我們的應用應該具備以下能力:

健康 檢測接口用於檢測應用的 健康 狀態,在K8S中,使用Readiness和Liveness分別來探測應用是否就緒和是否存活,如果未就緒或者未存活,K8S會採取相應的措施來確保應用可用。

如果我們應用未定義好相應的 健康 檢測接口,K8S就無法判斷應用是否正常可用,整個應用對我們來說就是黑匣子,也就談不上應用穩定性了。

定義一個簡單的 健康 檢測接口如下:

如上我們定義了 health 接口,當應用啟動後,只需要探測這個接口,如果返回OK,表示應用是正常的。

當然,上面的接口是非常簡單的,在實際情況下,應用本身也許還依賴起來應用,比如redis,mysql,mq等,如果它們異常,應用是不是異常的呢?那我們的應用 健康 檢測需不需要檢測其他應用的 健康 狀態呢?

既然我們定義好了 健康 檢測接口,那我們的YAML模板就可以增加 健康 檢測功能,如下:

應用發版是常規不能再常規的操作,通常情況下都是滾動更新的方式上線,也就是先起一個新應用,再刪一個老應用。

如果這時候老應用有部分的流量,突然把老應用的進程殺了,這部分流量就無法得到正確的處理,部分用戶也會因此受到影響。

怎麼才會不受影響呢?

假如我們在停止應用之前先告訴網關或者註冊中心,等對方把我們應用摘除後再下線,這樣就不會有任何流量受到影響了。

在K8S中,當我們要刪除Pod的時候,Pod會變成Terminating狀態,kubelet看到Pod的狀態如果為Terminating,就會開始執行關閉Pod的流程,給Pod發SIGTERM信號,如果達到寬限期Pod還未結束就給Pod發SIGKILL信號,從Endpoints中摘除Pod等。

從上面可知,Pod在停止之前會收到SIG信號,如果應用本身沒有處理這些信號的能力,那應用如果知道什麼時候該結束呢?

下面簡單定義一個處理SIG信號的功能。

當接收到SIG信號的時候,就會調用 Shutdown 方法做應用退出處理。

除此,還要結合K8S的 PreStop Hook 來定義結束前的鉤子,如下:

如果使用註冊中心,比如nacos,我們可以在 PreStop Hook 中先告訴nacos要下線,如下:

Metrics主要用來暴露應用指標,可以根據實際情況自定義指標,以便於監控工具Prometheus進行數據收集展示。

有些語言有現成的exporter,比如java的jmx_exporter,沒有的就需要自己在應用中集成。

比如:

這種會暴露默認的Http指標,可以通過 curl 127.0.0.1:9527/metrics 獲取指標。

如果需要自定義指標的話,只需按規則定義即可,如下:

這樣就定義了 httpserver_request_total 和 httpserver_request_duration_seconds 指標,引用過後就能在 /metrics 中看到對應的數據。

定義好了指標,下面就是收集了。既可以通過自定義收集規則收集,也可以通過自動發現的方式收集,為了方便,主要採用自動發現的方式。

我們只需要在deployment的templates中定義好annotation,prometheeus就會自動添加採集目標,如下:

Trace用於跟蹤,每個請求都會生成一個 TraceID ,這個ID會伴隨請求的整個生命周期,我們也可以根據這個ID查詢請求的整個鏈路情況。

鏈路追蹤,目前市面上有很多開源系統,比如Skywalking,Jeager,Zipkin等,它們各有各的特點,如下。

我比較推薦使用Jaeger,它是CNCF的畢業項目,成長空間和雲原生的系統架構兼容性比較好。

不過,我這裡採用的Skywalking。

Skywalking有許多現成的客戶端,比如Java、Python等,可以直接使用,它們都會自動埋點,但是對於Go來說就只有自己手動埋點了,需要我們自己去寫代碼。

比如:

定義reporter用於上報數據給Skywalking,這就是一個簡單的集成Trace的例子。

應用的可觀測性主要來源日誌、監控、鏈路追蹤,標準的日誌有利於日誌收集以及排查問題。

原則上,不論是什麼類型的日誌輸出,什麼格式的日誌內容,都能收集。但是為了方便友好,建議把日誌輸出到標準輸出,這樣收集更方便。

我個人理解,在K8s中,完全沒必要把日誌輸出到文件,浪費不說,沒多大意義,因為所有的日誌我們都會收集到日誌系統,而輸出到文件的日誌也會隨着應用發版而丟失,所以輸出到文件的意義是什麼呢?

開發把系統開發完,就會交付給運維部署。為了保障應用的穩定性,運維在部署應用的時候應該考慮以下幾點。

K8S中可以部署有狀態應用,也可以部署無狀態應用。對於有狀態應用,我其實很少部署到K8S中,大部分還是部署的無狀態應用,至於為什麼,用多了就曉得了。

對於業務應用,強烈建議使其保持無狀態,就算有需要持久化的東西,要麼保存到數據庫,要麼保存到對象存儲或者其他單獨的文件系統中,不要掛載到應用Pod上。

這樣的好處是,應用和數據是分開的,應用可以隨意啟停、擴展、遷移等。

保持高可用應該是每個運維人員的使命。

在K8S中,我們應該怎麼配置呢?(1)應用Pod應該是多副本

(2)應用Pod之間做反親和性,避免同一應用調度到同一台主機,如下。

(3) 為了避免應用因為節點維護等原因驅逐Pod,導致全部Pod被驅逐,特別配置了PodDisruptionBudget,保障應用至少有一個可用,如下。

(4)如果某個節點因為一些原因需要驅逐一些Pod,為了避免重要應用被驅逐,應該給應用配置較高的QoS,如下:

所謂優雅上線能力,就是要確保應用能夠提供服務了,再接入外界流量,不能在還沒完全啟動的情況下就提供服務。

在K8S中,應用在啟動後會加入endpoints中,然後通過service接入流量,那在什麼情況下才算啟動成功呢?主要是通過K8S的 ReadinessProbe 來進行檢測。這時候開發的 健康 檢測接口就派上用場了,如下:

所以我們K8S的YAML文件應該加上如上的配置。

所謂異常自愈,就是應用本身在出現Crash,或者應用Pod所在節點出現異常的情況,應用能夠自動重啟或者遷移。這時候就需要通過K8S的 LivenessProbe 來進行檢測了,如下。

當K8S的YAML清單加上如上配置過後,就會定時去探測應用是否正常,如果異常,就會觸發重啟的動作。如果是節點異常,K8S會對Pod進行重新調度。

應用通過HTTPS訪問是比較常見的,企業級應用建議自己購買相應的SSL證書,然後進行配置即可。

比如。

上面介紹了開發和運維對於應用上線應該做的工作, 不全但夠用 。

在不同的企業都有不同的尿性,但是作為運維,我們都要牢牢記住 穩定 永遠是第一尿性。通過上面的梳理,我們的應用模板就整理如下:

如果我的文章對你有所幫助,還請幫忙一下,你的支持會激勵我輸出更高質量的文章,非常感謝!

你還可以把我的公眾號設為「 星標 」,這樣當公眾號文章更新時,你會在第一時間收到推送消息,避免錯過我的文章更新。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/200509.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-05 20:01
下一篇 2024-12-05 20:01

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發佈。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Python簡單數學計算

    本文將從多個方面介紹Python的簡單數學計算,包括基礎運算符、函數、庫以及實際應用場景。 一、基礎運算符 Python提供了基礎的算術運算符,包括加(+)、減(-)、乘(*)、除…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • Python滿天星代碼:讓編程變得更加簡單

    本文將從多個方面詳細闡述Python滿天星代碼,為大家介紹它的優點以及如何在編程中使用。無論是剛剛接觸編程還是資深程序員,都能從中獲得一定的收穫。 一、簡介 Python滿天星代碼…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29

發表回復

登錄後才能評論