美文网首页持续集成
Spring on Kubernetes 最佳实践(一)基本篇

Spring on Kubernetes 最佳实践(一)基本篇

作者: yongaliang | 来源:发表于2020-04-18 17:30 被阅读0次

    通过此篇文章你讲会学会什么

    • 创建一个基本的Spring Boot应用
    • 为Spring Boot应用构建一个Docker镜像
    • 自动提交镜像到镜像仓库(下一篇)
    • 在Kubernetes上创建一个Deployment和Service
    • 在Kubernetes上部署Spring Boot应用
    • 额外的Kubernetes配置和服务发现(下一篇)

    环境准备

    • 了解Spring和Kubernetes基本的知识
    • JDK 8 或者更高的版本
    • 安装Docker Desktop
    • 安装一个IDE, 推荐 IntelliJ

    现阶段Docker Desktop 对Kubernetes有良好的支持,可以开箱即用,搭建本地Kubernetes集群. 参考官方文档安装Docker Desktop


    创建一个Spring Boot 应用

    • 下载一个基本的Spring Boot应用, 或者在 start.spring.io 创建
    • 解压下载的zip文件,并使用IDE打开项目

    添加一个RestController

    修改 K8sDemoApplication.java 添加 @RestController , 添加一个@GetMapping

    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;
    
    @SpringBootApplication
    @RestController
    public class K8sDemoAppApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(K8sDemoAppApplication.class, args);
        }
    
        @GetMapping("/")
        public String hello() {
            return "Hello World";
        }
    }
    

    运行Spring Boot应用

    在命令行输入

    ./mvnw clean package && java -jar ./target/*.jar
    

    测试Spring Boot应用

    访问一个HTTP请求 http://localhost:8080

    $curl http://localhost:8080
    Hello World
    

    测试Spring Boot Actuator Endpoint

    在Spring Boot应用添加了Actuator包之后, Spring会提供一些Production ready Features

    $ curl localhost:8080/actuator; echo
    {
      "_links": {
        "self": {
          "href": "http://localhost:8080/actuator",
          "templated": false
        },
        "health": {
          "href": "http://localhost:8080/actuator/health",
          "templated": false
        },
        "info": {
          "href": "http://localhost:8080/actuator/info",
          "templated": false
        }
    }
    

    继续下面的步骤前先确保停止之前启动的Spring Boot应用, 否则可能会导致端口冲突因为端口8080被占用


    容器化应用

    在Kubernetes上运行该应用程序的第一步是为该应用生成一个镜像,然后将其部署到Kubernetes


    构建一个Docker容器

    • Spring Boot 2.3.x 支持直接构建一个Docker容器无需任何额外的配置文件或者插件

    • 使用命令构建Docker容器

      $ ./mvnw spring-boot:build-image

    运行 docker images 查看构建的Docker容器

    docker images | grep k8s-demo-app
    k8s-demo-app                         0.0.1-SNAPSHOT            c7f56cf022f7        40 years ago        224MB
    

    使用Docker命令运行Docker容器

    $ docker run --name k8s-demo-app -p 8080:8080 k8s-demo-app:0.0.1-SNAPSHOT
    

    测试在Docker运行中的Spring Boot应用

    $ curl http://localhost:8080
    Hello World
    

    继续下面的步骤前先确保停止在Docker运行的应用


    部署到Kubernetes

    我们现在可以在本地Kubernetes集群上运行打包好的应用. 如果需要在非本地Kubernetes集群运行的话,需要推送镜像到镜像仓库,此处先略过推送到镜像仓库的步骤,下一篇会讲。


    Deployment 描述文件

    Deployment 官方概念的概述

    • Kubernetes 使用yaml文件提供了一种方法来描述如何将应用部署到集群
    • 你可以使用Kubernetes文档作为参考如何编写这些文件
    • 或者你可以使用kubectel来生成一个Deployment文件
    • 使用—dry-run 标记运行我们生成文件而且不会真正的运行kubectl命令
    mkdir k8s
    kubectl create deployment k8s-demo-app --image k8s-demo-app:0.0.1-SNAPSHOT -o yaml --dry-run > k8s/deployment.yaml
    

    生成的deployment.yaml文件如下

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      creationTimestamp: null
      labels:
        app: k8s-demo-app
      name: k8s-demo-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: k8s-demo-app
      strategy: {}
      template:
        metadata:
          creationTimestamp: null
          labels:
            app: k8s-demo-app
        spec:
          containers:
          - image: k8s-demo-app:0.0.1-SNAPSHOT
            name: k8s-demo-app
            imagePullPolicy: IfNotPresent
            resources: {}
    status: {}
    

    注意需要在deployment.yaml 文件需要添加一个imagePullPolicy: IfNotPresent,因为我们还没有将镜像推送到镜像仓库中,因此需要使用本地镜像


    Service 描述文件

    • 将运行在一组Pod上的应用程序公开为网络服务的抽象方法。
        $ kubectl create service clusterip k8s-demo-app --tcp 80:8080 -o yaml --dry-run > k8s/service.yaml
    

    生成的service.yaml文件如下

    apiVersion: v1
    kind: Service
    metadata:
      creationTimestamp: null
      labels:
        app: k8s-demo-app
      name: k8s-demo-app
    spec:
      ports:
      - name: 80-8080
        port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: k8s-demo-app
      type: ClusterIP
    status:
      loadBalancer: {}
    
    

    部署 Deployment 和 Service YAML

    • Deployment 和Service 通过命令创建在k8s文件夹里面
    • 运行它们
    $kubectl apply -f ./k8s
    deployment.apps/k8s-demo-app created
    service/k8s-demo-app created
    $kubectl get all
    NAME                                READY   STATUS    RESTARTS   AGE
    pod/k8s-demo-app-56bb6b8ddf-2w9ct   1/1     Running   0          3s
    
    NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    service/k8s-demo-app   ClusterIP   10.109.188.161   <none>        80/TCP    3s
    
    NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/k8s-demo-app   1/1     1            1           3s
    
    NAME                                      DESIRED   CURRENT   READY   AGE
    replicaset.apps/k8s-demo-app-56bb6b8ddf   1         1         1       3s
    

    测试运行在Kubernetes上的应用

    • Service 的类型是 ClusterIP, 这意味着只有集群内部才可以访问
    NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
    service/k8s-demo-app   ClusterIP   10.109.188.161   <none>        80/TCP    3s
    
    • 可以使用 kubectl pord-forward 命令来访问 Service
        kubectl port-forward service/k8s-demo-app 8080:80
    
        $ curl http://localhost:8080
        Hello World
    

    Congrats you have deployed your first app to Kubernetes 🎉

    继续下面的步骤前先确保停止在Docker运行的应用, 使用命令 docker rm -f k8s-demo-app


    公开应用服务

    NOTE: LoadBalancer 类型的 Service 是基于特定平台的, 更改为此类型后,应用的可见性很大程度上取决于其部署位置(Google Cloud Platform 等),因此在本地测试我们可以使用NodePort 类型来暴露服务

    修改service.yaml 里面type为NotePort,且添加nodePort参数,注意nodePort范围为(30000-32767)

    apiVersion: v1
    kind: Service
    metadata:
      creationTimestamp: null
      labels:
        app: k8s-demo-app
      name: k8s-demo-app
    spec:
      ports:
      - name: 80-8080
        port: 80
        protocol: TCP
        targetPort: 8080
        nodePort: 30081
      selector:
        app: k8s-demo-app
      type: NodePort
    status:
      loadBalancer: {}
    
    
    • 更新文件后,使用命令使其生效
        kubectl apply -f ./k8s
    

    测试公开的服务

    现在我们可以通过 http://{任何集群节点的IP}:{NodePort} 的方式来访问

    $ kubectl get service k8s-demo-app -w
    NAME           TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
    k8s-demo-app   NodePort   10.109.188.161   <none>        80:30080/TCP   7m41s
    
    curl http://localhost:30080
    hello World
    

    恭喜, 你已经将你的Spring Boot 应用成功部署到Kubernetes!

    相关文章

      网友评论

        本文标题:Spring on Kubernetes 最佳实践(一)基本篇

        本文链接:https://www.haomeiwen.com/subject/qmyivhtx.html