<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 將您的Spring Boot應用程序部署到Kubernetes 在構建在云中運行的Java應用程序時, 無疑是 [Spring和Spring Boot 最愛](https://www.jrebel.com/blog/2020-java-technology-report) 。 越來越明顯的是,諸如Docker和Kubernetes之類的技術 [在Spring社區中扮演著重要的角色](https://tanzu.vmware.com/content/ebooks/state-of-spring-2020) 。 ![圖像](https://github.com/spring-guides/top-spring-on-kubernetes/raw/master/extracted-media/media/image1.png) [將您的Spring Boot應用程序打包到Docker容器中](https://spring.io/guides/gs/spring-boot-docker/) 并將該應用程序部署到Kubernetes已經有一段時間了,并且花費很少的精力。 由于“使罐子不打架”的座右銘,將Spring Boot應用程序容器化所需的全部就是帶有JRE的容器來運行該罐子。 有了Docker容器后,在Kubernetes中運行容器化的Spring Boot應用程序僅是運行容器的問題。 也就是說,隨著越來越多的人將Spring Boot應用程序部署到Kubernetes,我們顯然可以做得更好。 為此,我們 [在Spring Boot 2.3 了一些增強,](https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html#cloud-deployment-kubernetes) 中 并 [進行 在即將發布的Spring Boot 2.4版本 更多改進,](https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4) 中進行了 以使在Kubernetes上運行Spring Boot的體驗更好。 本指南的目的是向您展示如何在Kubernetes上運行Spring Boot應用程序,以及如何利用一些平臺功能來構建云原生應用程序。 ## 入門:start.spring.io 那么,您需要如何開始在Kubernetes上運行Spring Boot應用程序? 只是快速訪問“每個人在互聯網上最喜歡的地方: [start.spring.io](https://start.spring.io) ”。 為您的應用程序創建目錄。 然后運行以下cURL命令從start.spring.io生成一個應用程序: ~~~ $ curl https://start.spring.io/starter.tgz -d dependencies=webflux,actuator | tar -xzvf - ~~~ 或者, [單擊此處](https://start.spring.io/#!type=maven-project&language=java&platformVersion=2.3.4.RELEASE&packaging=jar&jvmVersion=11&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&dependencies=webflux,actuator) 以正確的配置打開start.spring.io,然后單擊“生成”以下載項目。 使用基本的Spring Boot Web應用程序,我們現在需要創建一個Docker容器。 使用Spring Boot 2.3,我們可以使用Spring Boot Maven或Gradle插件為我們完成此操作,而無需修改應用程序。 為了使構建映像插件正常工作,您需要在 [本地安裝Docker](https://docs.docker.com/get-docker/) 。 ~~~ $ ./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=spring-k8s/gs-spring-boot-k8s ~~~ 構建完成后,我們現在應該為我們的應用程序創建一個Docker映像,我們可以使用以下命令進行檢查: ~~~ $ docker images spring-k8s/gs-spring-boot-k8s REPOSITORY TAG IMAGE ID CREATED SIZE spring-k8s/gs-spring-boot-k8s latest 21f21558c005 40 years ago 257MB ~~~ 現在,我們可以啟動容器映像并確保其有效: ~~~ $ docker run -p 8080:8080 --name gs-spring-boot-k8s -t spring-k8s/gs-spring-boot-k8s ~~~ 我們可以通過向執行器/運行狀況端點發出HTTP請求來測試一切是否正常: ~~~ $ curl http://localhost:8080/actuator/health; echo {"status":"UP"} ~~~ 在繼續前進之前,請務必停止正在運行的容器。 ~~~ $ docker stop gs-spring-boot-k8s ~~~ ## 到Kubernetes 有了我們應用程序的容器映像(只需要訪問start.spring.io!),我們就可以在Kubernetes上運行我們的應用程序了。 為此,我們需要做兩件事: 1. Kubernetes CLI(kubectl) 2. 將我們的應用程序部署到的Kubernetes集群 請按照以下 [說明](https://kubernetes.io/docs/tasks/tools/install-kubectl/) 安裝Kubernetes CLI。 任何Kubernetes集群都可以工作,但是,出于本文的目的,我們在本地啟動了一個集群,以使其盡可能簡單。 在本地運行Kubernetes集群的最簡單方法是使用名為 的工具 [Kind](https://kind.sigs.k8s.io/) 。 請按照以下 [說明](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) 安裝Kind。 安裝Kind之后,我們現在可以創建集群。 ~~~ $ kind create cluster ~~~ Kind創建集群后,它將自動配置Kubernetes CLI指向該集群。 為確保所有設置均正確,請運行: ~~~ $ kubectl cluster-info ~~~ 如果沒有看到任何錯誤,則可以將應用程序部署到Kubernetes。 ### 部署到州長 要將我們的應用程序部署到Kubernetes,我們需要生成一些YAML,以便Kubernetes可以使用它來部署,運行和管理我們的應用程序,并將該應用程序暴露給集群的其余部分。 首先為我們的YAML創建目錄: ~~~ $ mkdir k8s ~~~ 現在我們可以使用kubectl生成所需的基本YAML: ~~~ $ kubectl create deployment gs-spring-boot-k8s --image spring-k8s/gs-spring-boot-k8s:snapshot -o yaml --dry-run=client > k8s/deployment.yaml ~~~ 這 `deployment.yaml`該文件告訴Kubernetes如何部署和管理我們的應用程序,但是它不允許我們的應用程序成為其他應用程序的網絡服務。 為此,我們需要一種服務資源。 Kubectl可以幫助我們為服務資源生成YAML: ~~~ $ kubectl create service clusterip gs-spring-boot-k8s --tcp 80:8080 -o yaml --dry-run=client > k8s/service.yaml ~~~ 在將這些YAML文件應用于Kubernetes集群之前,我們需要將Docker映像加載到Kind集群中。 如果我們不這樣做,Kubernetes會嘗試在Docker Hub中為我們的映像找到容器,而該容器當然是不存在的。 ~~~ $ docker tag spring-k8s/gs-spring-boot-k8s spring-k8s/gs-spring-boot-k8s:snapshot $ kind load docker-image spring-k8s/gs-spring-boot-k8s:snapshot ~~~ 我們為圖像創建一個新標簽,因為使用最新標簽的圖像的默認Kubernetes拉策略是 Always。 由于該映像在Docker存儲庫中不存在于外部,因此我們想使用以下映像拉取策略 Never 或者 IfNotPresent。 當使用最新標簽以外的標簽時,默認的Kubernetes拉策略為 IfNotPresent. 現在我們準備將YAML文件應用于Kubernetes: ~~~ $ kubectl apply -f ./k8s ~~~ 然后,您可以運行: ~~~ $ kubectl get all ~~~ 您應該看到我們新創建的部署,服務和Pod正在運行: ~~~ NAME READY STATUS RESTARTS AGE pod/gs-spring-boot-k8s-779d4fcb4d-xlt9g 1/1 Running 0 3m40s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/gs-spring-boot-k8s ClusterIP 10.96.142.74 <none> 80/TCP 3m40s service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4h55m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/gs-spring-boot-k8s 1/1 1 1 3m40s NAME DESIRED CURRENT READY AGE replicaset.apps/gs-spring-boot-k8s-779d4fcb4d 1 1 1 3m40s ~~~ 不幸的是,我們不能直接向Kubernetes中的服務發出HTTP請求,因為該請求沒有暴露在集群網絡之外。 借助kubectl,我們可以將HTTP流量從本地計算機轉發到集群中運行的服務: ~~~ $ kubectl port-forward svc/gs-spring-boot-k8s 9090:80 ~~~ 運行port-forward命令后,我們現在可以向localhost:9090發出HTTP請求,并將其轉發到在Kubernetes中運行的服務: ~~~ $ curl http://localhost:9090/actuator; echo ~~~ ~~~ { "_links":{ "self":{ "href":"http://localhost:9090/actuator", "templated":false }, "health-path":{ "href":"http://localhost:9090/actuator/health/{*path}", "templated":true }, "health":{ "href":"http://localhost:9090/actuator/health", "templated":false }, "info":{ "href":"http://localhost:9090/actuator/info", "templated":false } } } ~~~ 在繼續前進之前,請務必停止 `port-forward` 上面的命令。 ### 最佳實踐 我們的應用程序在Kubernetes上運行,但是,為了使我們的應用程序最佳運行,我們建議實現以下幾種最佳實踐: 1. [添加準備和活躍度探針](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-kubernetes-probes) 2. [等待容器生命周期過程完成](https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html#cloud-deployment-kubernetes-container-lifecycle) 3. [啟用正常關機](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-graceful-shutdown) 打開 `k8s/deployment.yaml` 在文本編輯器中,將就緒,活躍度和生命周期屬性添加到您的文件中: k8s / deployment.yaml ~~~ apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: gs-spring-boot-k8s name: gs-spring-boot-k8s spec: replicas: 1 selector: matchLabels: app: gs-spring-boot-k8s strategy: {} template: metadata: creationTimestamp: null labels: app: gs-spring-boot-k8s spec: containers: - image: spring-k8s/gs-spring-boot-k8s:snapshot name: gs-spring-boot-k8s resources: {} livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 lifecycle: preStop: exec: command: ["sh", "-c", "sleep 10"] status: {} ~~~ 這照顧到最佳實踐1和2。 為了解決第三個最佳實踐,我們需要在我們的應用程序配置中添加一個屬性。 由于我們在Kubernetes上運行我們的應用程序,因此我們可以利用 [Kubernetes ConfigMaps](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) 來外部化此屬性,就像一個優秀的云開發人員應該的那樣。 現在,我們來看看如何做到這一點。 ### 使用ConfigMap外部化配置 要在Spring Boot應用程序中啟用正常關機,我們需要設置 `server.shutdown=graceful`. 我們可以創建一個屬性文件,以啟用正常關閉并公開所有的Actuator端點。 我們可以使用Actuator端點作為一種驗證應用程序是否將ConfigMap中的屬性文件添加到PropertySources列表的方法。 創建一個新文件,名為 `application.properties` 在里面 `k8s`目錄。 在該文件中添加以下屬性。 application.properties ~~~ server.shutdown=graceful management.endpoints.web.exposure.include=* ~~~ 另外,您可以通過運行以下命令,從命令行通過一個簡單的步驟來執行此操作。 ~~~ $ cat <<EOF >./k8s/application.properties server.shutdown=graceful management.endpoints.web.exposure.include=* EOF ~~~ 創建屬性文件后,我們現在可以 [創建ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#create-configmaps-from-files) 使用kubectl 。 ~~~ $ kubectl create configmap gs-spring-boot-k8s --from-file=./k8s/application.properties ~~~ 創建了ConfigMap后,我們可以看到它的外觀: ~~~ $ kubectl get configmap gs-spring-boot-k8s -o yaml ~~~ ~~~ apiVersion: v1 data: application.properties: | server.shutdown=graceful management.endpoints.web.exposure.include=* kind: ConfigMap metadata: creationTimestamp: "2020-09-10T21:09:34Z" name: gs-spring-boot-k8s namespace: default resourceVersion: "178779" selfLink: /api/v1/namespaces/default/configmaps/gs-spring-boot-k8s uid: 9be36768-5fbd-460d-93d3-4ad8bc6d4dd9 ~~~ 最后一步是 [將此ConfigMap作為卷安裝](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#add-configmap-data-to-a-volume) 在容器中。 為此,我們需要修改我們的部署YAML,以首先創建該卷,然后將該卷安裝在容器中: k8s / deployment.yaml ~~~ apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: gs-spring-boot-k8s name: gs-spring-boot-k8s spec: replicas: 1 selector: matchLabels: app: gs-spring-boot-k8s strategy: {} template: metadata: creationTimestamp: null labels: app: gs-spring-boot-k8s spec: containers: - image: spring-k8s/gs-spring-boot-k8s:snapshot name: gs-spring-boot-k8s resources: {} livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 lifecycle: preStop: exec: command: ["sh", "-c", "sleep 10"] volumeMounts: - name: config-volume mountPath: /workspace/config volumes: - name: config-volume configMap: name: gs-spring-boot-k8s status: {} ~~~ 實施所有最佳實踐后,我們可以將新部署應用于Kubernetes。 這將部署另一個Pod并停止舊的Pod(只要新的Pod成功啟動)。 ~~~ $ kubectl apply -f ./k8s ~~~ 如果正確配置了活動性和就緒性探針,則Pod將成功啟動并轉換為就緒狀態。 如果Pod從未達到就緒狀態,請返回并檢查您的就緒探針配置。 如果您的Pod達到就緒狀態,但是Kubernetes不斷重啟Pod,則您的活動探針配置不正確。 如果吊艙啟動并保持靜止,則一切正常。 您可以通過單擊來驗證是否已安裝ConfigMap卷以及應用程序正在使用屬性文件。 `/actuator/env` 端點。 ~~~ $ kubectl port-forward svc/gs-spring-boot-k8s 9090:80 ~~~ 現在,如果您訪問 [http:// localhost:9090 / actuator / env,](http://localhost:9090/actuator/env) 您將看到屬性源是由我們的已裝載卷貢獻的。 ~~~ { "name":"applicationConfig: [file:./config/application.properties]", "properties":{ "server.shutdown":{ "value":"graceful", "origin":"URL [file:./config/application.properties]:1:17" }, "management.endpoints.web.exposure.include":{ "value":"*", "origin":"URL [file:./config/application.properties]:2:43" } } } ~~~ 在繼續操作之前,請務必停止 `port-forward` 命令。 ### 服務發現和負載平衡 對于本指南的這一部分,您應該安裝 [Kustomize](https://kustomize.io/) 。 當使用Kubernetes并針對不同的環境(開發,測試,登臺,生產)時,Kustomize是一個有用的工具。 我們使用它來生成YAML,以將另一個應用程序部署到Kubernetes,然后我們將能夠使用服務發現來調用它。 運行以下命令以部署 的實例 [name-service](https://github.com/ryanjbaxter/k8s-spring-workshop/tree/master/name-service) : ~~~ $ kustomize build "github.com/ryanjbaxter/k8s-spring-workshop/name-service/kustomize/multi-replica/" | kubectl apply -f - ~~~ 這應該部署 `name-service`到您的Kubernetes集群。 部署應為以下對象創建兩個副本 `name-service`: ~~~ $ kubectl get pods --selector app=k8s-workshop-name-service NAME READY STATUS RESTARTS AGE k8s-workshop-name-service-56b986b664-6qt59 1/1 Running 0 7m26s k8s-workshop-name-service-56b986b664-wjcr9 1/1 Running 0 7m26s ~~~ 為了演示該服務的作用,我們可以對其進行請求: ~~~ $ kubectl port-forward svc/k8s-workshop-name-service 9090:80 $ curl http://localhost:9090 -i; echo HTTP/1.1 200 k8s-host: k8s-workshop-name-service-56b986b664-6qt59 Content-Type: text/plain;charset=UTF-8 Content-Length: 4 Date: Mon, 14 Sep 2020 15:37:51 GMT Paul ~~~ 如果發出多個請求,則應該看到返回的不同名稱。 另請注意標題: `k8s-host`。 這應該與為請求提供服務的廣告連播的ID保持一致。 使用port-forwarding命令時,它僅向單個pod發出一個請求,因此您只會在響應中看到一個主機。 確保停止 `port-forward` 在繼續之前先執行命令。 隨著我們的服務運行,我們可以修改我們的應用程序以向 `name-service`. Kubernetes設置DNS條目,以便我們可以將服務ID用于 `name-service`在不知道Pod的IP地址的情況下向服務發出HTTP請求。 Kubernetes服務還在所有Pod之間平衡這些請求的負載。 在您的應用程序中,打開 `DemoApplication.java` 在 `src/main/java/com/example/demo`。 修改代碼,如下所示: ~~~ package com.example.demo; import reactor.core.publisher.Mono; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; @SpringBootApplication @RestController public class DemoApplication { private WebClient webClient = WebClient.create(); public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @GetMapping public Mono<String> index() { return webClient.get().uri("http://k8s-workshop-name-service") .retrieve() .toEntity(String.class) .map(entity -> { String host = entity.getHeaders().get("k8s-host").get(0); return "Hello " + entity.getBody() + " from " + host; }); } } ~~~ 請注意網址中的網址 `WebClient` 請求是 `k8s-workshop-name-service`。 這是我們在Kubernetes中服務的ID。 由于我們更新了應用程序代碼,因此我們需要構建一個新映像并將其部署到Kubernetes: ~~~ $ ./mvnw clean spring-boot:build-image -Dspring-boot.build-image.imageName=spring-k8s/gs-spring-boot-k8s $ docker tag spring-k8s/gs-spring-boot-k8s:latest spring-k8s/gs-spring-boot-k8s:snapshot $ kind load docker-image spring-k8s/gs-spring-boot-k8s:snapshot ~~~ 部署新映像的一種簡單方法是刪除應用程序容器。 Kubernetes會使用我們剛剛加載到集群中的新映像自動創建另一個Pod。 ~~~ $ kubectl delete pod --selector app=gs-spring-boot-k8s ~~~ 新的Pod啟動并運行后,您可以將轉發請求移植到服務: ~~~ $ kubectl port-forward svc/gs-spring-boot-k8s 9090:80 ~~~ 現在,如果您對服務進行請求,則應該看到將請求發送到名稱服務的哪一個窗格: ~~~ $ curl http://localhost:9090; echo Hello Paul from k8s-workshop-name-service-56b986b664-wjcr9 ~~~ 驗證負載平衡可能會更具挑戰性。 您可以不斷地發出相同的cURL請求,并觀察Pod ID是否更改。 諸如watch之類的工具可能對此非常有用: ~~~ $ watch -n 1 curl http://localhost:9090 ~~~ watch命令每秒發出一次cURL請求。 缺點是您必須注意終端并等待。 最終,盡管如此,您應該注意到吊艙ID發生了變化。 查看事物切換的一種更快的方法是運行watch命令,然后刪除當前正在為請求提供服務的pod: ~~~ $ kubectl delete pod k8s-workshop-name-service-56b986b664-wjcr9 ~~~ 執行此操作時,您應該立即注意到watch命令中的pod ID發生了變化。 讓Kubernetes上運行的Spring Boot應用程序只需要訪問 [start.spring.io即可](https://start.spring.io) 。 Spring Boot的目標一直是盡可能簡化構建和運行Java應用程序的過程,無論您選擇如何運行應用程序,我們都會嘗試實現這一點。 用Kubernetes構建云原生應用程序只需要創建一個使用Spring Boot內置映像生成器的映像并利用Kubernetes平臺的功能即可。 在我們關于Spring Boot和Kubernetes的第二部分中,我們將探討Spring Cloud如何適合這個故事。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看