歡迎訪問(wèn)我的GitHub
https://github.com/zq2599/blog_demos
內(nèi)容:所有原創(chuàng)文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;
概覽
本文是《Kubernetes官方j(luò)ava客戶端》系列的第四篇,以下提到的java客戶端都是指client-jar.jar;
-
前文《Kubernetes官方j(luò)ava客戶端之三:外部應(yīng)用》中,咱們開(kāi)發(fā)了一個(gè)名為<font color="blue">OutsideclusterApplication</font>的SpringBoot應(yīng)用,該應(yīng)用并未部署在K8S環(huán)境,而是遠(yuǎn)程訪問(wèn)K8S環(huán)境內(nèi)部的API Server,整體結(jié)構(gòu)如下:
在這里插入圖片描述 -
除了前文中部署在外部的方式,還有一種常見(jiàn)場(chǎng)景:使用java客戶端的應(yīng)用自身也部署在K8S環(huán)境中,如下圖所示,名為<font color="blue">DemoApplication的SpringBoot</font>應(yīng)用部署在K8S環(huán)境內(nèi),調(diào)用java客戶端庫(kù)的API對(duì)K8S進(jìn)行各種操作,整體結(jié)構(gòu)如下:
在這里插入圖片描述 本文的內(nèi)容就是開(kāi)發(fā)上圖中名為<font color="blue">DemoApplication</font>的應(yīng)用,并且部署在K8S環(huán)境中進(jìn)行驗(yàn)證;
額外準(zhǔn)備
- 前文《Kubernetes官方j(luò)ava客戶端之三:外部應(yīng)用》的實(shí)戰(zhàn)是一次常規(guī)的SpringBoot應(yīng)用開(kāi)發(fā),本文的實(shí)戰(zhàn)和前文略有不同,您需要對(duì)以下知識(shí)點(diǎn)有所了解:
- SpringBoot制作成docker鏡像,首選官方推薦的方式,參考《體驗(yàn)SpringBoot(2.3)應(yīng)用制作Docker鏡像(官方方案)》、《詳解SpringBoot(2.3)應(yīng)用制作Docker鏡像(官方方案)》
- SpringBoot應(yīng)用在K8S環(huán)境下的探針技術(shù),參考《掌握SpringBoot-2.3的容器探針:基礎(chǔ)篇》、《掌握SpringBoot-2.3的容器探針:深入篇》、《掌握SpringBoot-2.3的容器探針:實(shí)戰(zhàn)篇》
源碼下載
- 如果您不想編碼,可以在GitHub下載所有源碼,地址和鏈接信息如下表所示(https://github.com/zq2599/blog_demos):
| 名稱 | 鏈接 | 備注 |
|---|---|---|
| 項(xiàng)目主頁(yè) | https://github.com/zq2599/blog_demos | 該項(xiàng)目在GitHub上的主頁(yè) |
| git倉(cāng)庫(kù)地址(https) | https://github.com/zq2599/blog_demos.git | 該項(xiàng)目源碼的倉(cāng)庫(kù)地址,https協(xié)議 |
| git倉(cāng)庫(kù)地址(ssh) | git@github.com:zq2599/blog_demos.git | 該項(xiàng)目源碼的倉(cāng)庫(kù)地址,ssh協(xié)議 |
-
這個(gè)git項(xiàng)目中有多個(gè)文件夾,本章的應(yīng)用在<font color="blue">kubernetesclient</font>文件夾下,如下圖紅框所示:
在這里插入圖片描述
開(kāi)發(fā)K8S環(huán)境內(nèi)的應(yīng)用:DemoApplication
- 打開(kāi)《Kubernetes官方j(luò)ava客戶端:準(zhǔn)備》中創(chuàng)建的的<font color="blue">kubernetesclient</font>工程,在里面創(chuàng)建子工程,名為<font color="red">helloworld</font>,這是個(gè)SpringBoot工程,pom.xml內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>kubernetesclient</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>helloworld</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
<!--該配置會(huì)在jar中增加layer描述文件,以及提取layer的工具-->
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 編寫java代碼,創(chuàng)建<font color="blue">DemoApplication.java</font>,這里為了簡(jiǎn)單起見(jiàn),將引導(dǎo)類和web controller的代碼都寫在DemoApplication類中:
package com.bolingcavalry.demo;
import com.google.gson.Gson;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1PodList;
import io.kubernetes.client.util.Config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
@SpringBootApplication
@RestController
@Slf4j
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@RequestMapping(value = "/hello")
public List<String> hello() throws Exception {
ApiClient client = Config.defaultClient();
Configuration.setDefaultApiClient(client);
CoreV1Api api = new CoreV1Api();
// 調(diào)用客戶端API取得所有pod信息
V1PodList v1PodList = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);
// 使用Gson將集合對(duì)象序列化成JSON,在日志中打印出來(lái)
log.info("pod info \n{}", new Gson().toJson(v1PodList));
return v1PodList
.getItems()
.stream()
.map(value ->
value.getMetadata().getNamespace()
+ ":"
+ value.getMetadata().getName())
.collect(Collectors.toList());
}
}
- 還記得《Kubernetes官方j(luò)ava客戶端之二:序列化和反序列化問(wèn)題》提到的序列化問(wèn)題嗎?上述代碼中,log.info那段代碼里對(duì)<font color="blue">V1PodList</font>執(zhí)行序列化的是Gson,并且hello方法返回的也不是V1PodList實(shí)例,而是新做的一個(gè)List實(shí)例,這樣做是因?yàn)閖ackson對(duì)V1PodList做序列化會(huì)導(dǎo)致異常,這里要避免jackson參與序列化操作;
- 應(yīng)用的代碼已經(jīng)寫完,接下來(lái)是鏡像制作用到的Dockerfile文件,該文件和剛才創(chuàng)建的pom.xml文件在同一個(gè)目錄下(即子工程<font color="blue">helloworld</font>的文件夾下),Dockerfile文件內(nèi)容如下:
# 指定基礎(chǔ)鏡像,這是分階段構(gòu)建的前期階段
FROM openjdk:8u212-jdk-stretch as builder
# 執(zhí)行工作目錄
WORKDIR application
# 配置參數(shù)
ARG JAR_FILE=target/*.jar
# 將編譯構(gòu)建得到的jar文件復(fù)制到鏡像空間中
COPY ${JAR_FILE} application.jar
# 通過(guò)工具spring-boot-jarmode-layertools從application.jar中提取拆分后的構(gòu)建結(jié)果
RUN java -Djarmode=layertools -jar application.jar extract
# 正式構(gòu)建鏡像
FROM openjdk:8u212-jdk-stretch
WORKDIR application
# 前一階段從jar中提取除了多個(gè)文件,這里分別執(zhí)行COPY命令復(fù)制到鏡像空間中,每次COPY都是一個(gè)layer
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
- 在子工程pom.xml文件所在目錄執(zhí)行以下命令完成編譯構(gòu)建:
mvn clean package -U -DskipTests
- 接下來(lái)要制作鏡像文件了,請(qǐng)確保當(dāng)前電腦已經(jīng)安裝并運(yùn)行了docker,另外構(gòu)建docker鏡像的操作<font color="red">我僅在macOS和Linux操作系統(tǒng)下執(zhí)行成功</font>,在Windows環(huán)境能否成功請(qǐng)自行嘗試;
- 在Dockerfile所在目錄執(zhí)行以下命令即可創(chuàng)建docker鏡像文件:
docker build -t 192.168.50.43:5888/common/helloworld:1.0-SNAPSHOT .
-
上述命令執(zhí)行成功后,鏡像文件還只是在本機(jī)的docker倉(cāng)庫(kù)中,請(qǐng)放置到K8S環(huán)境可以訪問(wèn)的地方,我這里是在內(nèi)網(wǎng)部署了鏡像倉(cāng)庫(kù)Harbor,執(zhí)行以下命令即可從本地倉(cāng)庫(kù)推送到Harbor(可能需要先登錄,與Harbor的設(shè)置有關(guān)):
在這里插入圖片描述 鏡像準(zhǔn)備完成,接下來(lái)就是在K8S環(huán)境部署了,在K8S環(huán)境創(chuàng)建名為helloworld.yaml的文件,內(nèi)容如下,可見(jiàn)deployment和service都配置好了,另外請(qǐng)注意serviceAccountName屬性的值為kubernates-client-service-account,此serviceAccountName是在《Kubernetes官方j(luò)ava客戶端之一:準(zhǔn)備》一文中創(chuàng)建好的RBAC資源,令咱們開(kāi)發(fā)的helloworld應(yīng)用有權(quán)限請(qǐng)求API Server:
apiVersion: v1
kind: Service
metadata:
name: helloworld
namespace : kubernetesclient
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30100
selector:
name: helloworld
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace : kubernetesclient
name: helloworld
spec:
replicas: 1
template:
metadata:
labels:
name: helloworld
spec:
serviceAccountName: kubernates-client-service-account
containers:
- name: helloworld
image: 192.168.50.43:5888/common/helloworld:1.0-SNAPSHOT
tty: true
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 5
failureThreshold: 10
timeoutSeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 10
periodSeconds: 5
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "1000m"
-
helloworld.yaml所在目錄執(zhí)行命令:<font color="blue">kubectl apply -f helloworld.yaml</font>
在這里插入圖片描述 -
我這邊,上圖中的Pod所在宿主機(jī)IP地址是<font color="blue">192.168.50.135</font>,因此用瀏覽器訪問(wèn)<font color="blue">http://192.168.50.135:30100/hello</font>,如下圖,可見(jiàn)當(dāng)前K8S環(huán)境下所有Pod名稱都返回了:
在這里插入圖片描述
至此,SpringBoot應(yīng)用通過(guò)K8S官方j(luò)ava客戶端,成功獲取了自身所在K8S環(huán)境的信息,通過(guò)前文和本章,咱們對(duì)K8S官方j(luò)ava客戶端已經(jīng)有了基本的認(rèn)識(shí),接下來(lái)的實(shí)戰(zhàn)會(huì)開(kāi)啟這個(gè)客戶端更豐富的能力;
你不孤單,欣宸原創(chuàng)一路相伴
歡迎關(guān)注公眾號(hào):程序員欣宸
微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos





