Kubernetes官方java客戶端之四:內部應用

程式設計師欣宸發表於2021-01-06

歡迎訪問我的GitHub

https://github.com/zq2599/blog_demos

內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;

概覽

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

  2. 前文《Kubernetes官方java客戶端之三:外部應用》中,我們們開發了一個名為OutsideclusterApplication的SpringBoot應用,該應用並未部署在K8S環境,而是遠端訪問K8S環境內部的API Server,整體結構如下:
    在這裡插入圖片描述

  3. 除了前文中部署在外部的方式,還有一種常見場景:使用java客戶端的應用自身也部署在K8S環境中,如下圖所示,名為DemoApplication的SpringBoot應用部署在K8S環境內,呼叫java客戶端庫的API對K8S進行各種操作,整體結構如下:
    在這裡插入圖片描述

  4. 本文的內容就是開發上圖中名為DemoApplication的應用,並且部署在K8S環境中進行驗證;

額外準備

  1. SpringBoot製作成docker映象,首選官方推薦的方式,參考《體驗SpringBoot(2.3)應用製作Docker映象(官方方案)》《詳解SpringBoot(2.3)應用製作Docker映象(官方方案)》
  2. SpringBoot應用在K8S環境下的探針技術,參考《掌握SpringBoot-2.3的容器探針:基礎篇》《掌握SpringBoot-2.3的容器探針:深入篇》《掌握SpringBoot-2.3的容器探針:實戰篇》

原始碼下載

  1. 如果您不想編碼,可以在GitHub下載所有原始碼,地址和連結資訊如下表所示(https://github.com/zq2599/blog_demos):
名稱 連結 備註
專案主頁 https://github.com/zq2599/blog_demos 該專案在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該專案原始碼的倉庫地址,https協議
git倉庫地址(ssh) git@github.com:zq2599/blog_demos.git 該專案原始碼的倉庫地址,ssh協議
  1. 這個git專案中有多個資料夾,本章的應用在kubernetesclient資料夾下,如下圖紅框所示:
    在這裡插入圖片描述

開發K8S環境內的應用:DemoApplication

  1. 開啟《Kubernetes官方java客戶端:準備》中建立的的kubernetesclient工程,在裡面建立子工程,名為helloworld,這是個SpringBoot工程,pom.xml內容如下:
<?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>
                <!--該配置會在jar中增加layer描述檔案,以及提取layer的工具-->
                <configuration>
                    <layers>
                        <enabled>true</enabled>
                    </layers>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  1. 編寫java程式碼,建立DemoApplication.java,這裡為了簡單起見,將引導類和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();

        // 呼叫客戶端API取得所有pod資訊
        V1PodList v1PodList = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);

        // 使用Gson將集合物件序列化成JSON,在日誌中列印出來
        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官方java客戶端之二:序列化和反序列化問題》提到的序列化問題嗎?上述程式碼中,log.info那段程式碼裡對V1PodList執行序列化的是Gson,並且hello方法返回的也不是V1PodList例項,而是新做的一個List例項,這樣做是因為jackson對V1PodList做序列化會導致異常,這裡要避免jackson參與序列化操作;
  2. 應用的程式碼已經寫完,接下來是映象製作用到的Dockerfile檔案,該檔案和剛才建立的pom.xml檔案在同一個目錄下(即子工程helloworld的資料夾下),Dockerfile檔案內容如下:
# 指定基礎映象,這是分階段構建的前期階段
FROM openjdk:8u212-jdk-stretch as builder
# 執行工作目錄
WORKDIR application
# 配置引數
ARG JAR_FILE=target/*.jar
# 將編譯構建得到的jar檔案複製到映象空間中
COPY ${JAR_FILE} application.jar
# 通過工具spring-boot-jarmode-layertools從application.jar中提取拆分後的構建結果
RUN java -Djarmode=layertools -jar application.jar extract

# 正式構建映象
FROM openjdk:8u212-jdk-stretch
WORKDIR application
# 前一階段從jar中提取除了多個檔案,這裡分別執行COPY命令複製到映象空間中,每次COPY都是一個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檔案所在目錄執行以下命令完成編譯構建:
mvn clean package -U -DskipTests
  1. 接下來要製作映象檔案了,請確保當前電腦已經安裝並執行了docker,另外構建docker映象的操作我僅在macOS和Linux作業系統下執行成功,在Windows環境能否成功請自行嘗試;
  2. 在Dockerfile所在目錄執行以下命令即可建立docker映象檔案:
docker build -t 192.168.50.43:5888/common/helloworld:1.0-SNAPSHOT .
  1. 上述命令執行成功後,映象檔案還只是在本機的docker倉庫中,請放置到K8S環境可以訪問的地方,我這裡是在內網部署了映象倉庫Harbor,執行以下命令即可從本地倉庫推送到Harbor(可能需要先登入,與Harbor的設定有關):
    在這裡插入圖片描述

  2. 映象準備完成,接下來就是在K8S環境部署了,在K8S環境建立名為helloworld.yaml的檔案,內容如下,可見deployment和service都配置好了,另外請注意serviceAccountName屬性的值為kubernates-client-service-account,此serviceAccountName是在《Kubernetes官方java客戶端之一:準備》一文中建立好的RBAC資源,令我們們開發的helloworld應用有許可權請求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所在目錄執行命令:kubectl apply -f helloworld.yaml
    在這裡插入圖片描述

  2. 我這邊,上圖中的Pod所在宿主機IP地址是192.168.50.135,因此用瀏覽器訪問http://192.168.50.135:30100/hello,如下圖,可見當前K8S環境下所有Pod名稱都返回了:
    在這裡插入圖片描述

至此,SpringBoot應用通過K8S官方java客戶端,成功獲取了自身所在K8S環境的資訊,通過前文和本章,我們們對K8S官方java客戶端已經有了基本的認識,接下來的實戰會開啟這個客戶端更豐富的能力;

你不孤單,欣宸原創一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 資料庫+中介軟體系列
  6. DevOps系列

歡迎關注公眾號:程式設計師欣宸

微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界...
https://github.com/zq2599/blog_demos

相關文章