Kubernetes官方j(luò)ava客戶端之四:內(nèi)部應(yīng)用

歡迎訪問(wèn)我的GitHub

https://github.com/zq2599/blog_demos

內(nèi)容:所有原創(chuàng)文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;

概覽

  1. 本文是《Kubernetes官方j(luò)ava客戶端》系列的第四篇,以下提到的java客戶端都是指client-jar.jar;

  2. 前文《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)如下:

    在這里插入圖片描述

  3. 除了前文中部署在外部的方式,還有一種常見(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)如下:


    在這里插入圖片描述
  4. 本文的內(nèi)容就是開(kāi)發(fā)上圖中名為<font color="blue">DemoApplication</font>的應(yīng)用,并且部署在K8S環(huán)境中進(jìn)行驗(yàn)證;

額外準(zhǔn)備

  1. SpringBoot制作成docker鏡像,首選官方推薦的方式,參考《體驗(yàn)SpringBoot(2.3)應(yīng)用制作Docker鏡像(官方方案)》、《詳解SpringBoot(2.3)應(yīng)用制作Docker鏡像(官方方案)》
  2. SpringBoot應(yīng)用在K8S環(huán)境下的探針技術(shù),參考《掌握SpringBoot-2.3的容器探針:基礎(chǔ)篇》、《掌握SpringBoot-2.3的容器探針:深入篇》《掌握SpringBoot-2.3的容器探針:實(shí)戰(zhàn)篇》

源碼下載

  1. 如果您不想編碼,可以在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é)議
  1. 這個(gè)git項(xiàng)目中有多個(gè)文件夾,本章的應(yīng)用在<font color="blue">kubernetesclient</font>文件夾下,如下圖紅框所示:


    在這里插入圖片描述

開(kāi)發(fā)K8S環(huán)境內(nèi)的應(yīng)用:DemoApplication

  1. 打開(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>
  1. 編寫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());
    }
}
  1. 還記得《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參與序列化操作;
  2. 應(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"]
  1. 在子工程pom.xml文件所在目錄執(zhí)行以下命令完成編譯構(gòu)建:
mvn clean package -U -DskipTests
  1. 接下來(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)自行嘗試;
  2. 在Dockerfile所在目錄執(zhí)行以下命令即可創(chuàng)建docker鏡像文件:
docker build -t 192.168.50.43:5888/common/helloworld:1.0-SNAPSHOT .
  1. 上述命令執(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)):


    在這里插入圖片描述
  2. 鏡像準(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"
  1. helloworld.yaml所在目錄執(zhí)行命令:<font color="blue">kubectl apply -f helloworld.yaml</font>


    在這里插入圖片描述
  2. 我這邊,上圖中的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)一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 數(shù)據(jù)庫(kù)+中間件系列
  6. DevOps系列

歡迎關(guān)注公眾號(hào):程序員欣宸

微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容