docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku

作者:神秘网友 发布时间:2020-10-15 16:56:35

docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku

docker+kubernetes+springcloud微服务集群部署,spring-cloud-kubernetes,使用k8s部署spring cloud并实现服务注册、负载均衡、网关等功能

docker+kubernetes+springcloud微服务集群部署,spring-cloud-kubernetes,使用k8s部署spring cloud并实现服务注册、负载均衡、网关等功能

  • 官方地址: https://github.com/spring-cloud/spring-cloud-kubernetes

  • 参考:https://blog.csdn.net/boling_cavalry/article/details/91346780

    https://blog.csdn.net/u013360850/article/details/100635405

  • 本机环境

地址服务
192.168.0.11k8s-master
192.168.0.22k8s-node1 , docker registry
192.168.0.33k8s-node2

代码见https://github.com/heliu0/springcloud-k8s.git

    • 1, 创建spring cloud项目。并编写ProducerApplication.java,ProducerController.java,Dockerfile,application.yaml, pom.xml,producer-service.yaml。
      • 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-k8s-parent</artifactId>
        <groupId>com.yayiyo.k8s</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-k8s-producer</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-openfegin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>${spring-boot.version}</version>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring-boot.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes</artifactId>
            <version>${spring-cloud.k8s}</version>
        </dependency>
    </dependencies>

</project>
  • ProducerApplication.java
package com.yayiyo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ProducerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProducerApplication.class, args);
    }
}

  • RpcController.java
package com.yayiyo.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.InetAddress;
import java.net.UnknownHostException;

@Controller
public class RpcController {
    @GetMapping("/ping")
    @ResponseBody
    public String ping() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            return "Pong";
        }
    }
}

  • application.yaml
spring:
  application:
    name: producer-service
  cloud:
    kubernetes:
      config:
        sources:
          - name: ${spring.application.name}
            namespace: default
      reload:
        enabled: true
        mode: event
      discovery:
        all-namespaces: true
server:
  port: 8082

management:
  endpoint:
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: restart

  • 2. idea上配置docker服务,执行Dockerfile,打包镜像并把镜像推到docker服务器上。

    • Dockerfile
FROM openjdk:8-jdk-alpine

LABEL version="1.0" maintainer="[email protected]"
VOLUME /tmp
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ARG JAR_FILE
ADD target/springcloud-k8s-producer-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar","/app.jar"]
EXPOSE 8082
  • idea的docker配置

docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku

  • 3. 把镜像推到docker仓库里面

#查看本地仓库里面是否有该镜像
docker images
# 推到远程镜像仓库
docker push 镜像名
  • 4.在k8s-master服务器上 编写 producer-service.yaml并执行

kubectl apply -f  producer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: producer-service
  labels:
    app.kubernetes.io/name: producer-service
spec:
  type: ClusterIP
  ports:
    - port: 8082
      targetPort: 8082
      nodePort: 8082
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: producer-service

---
apiVersion: apps/v1producer-service
kind: Deployment
metadata:
  name: producer-service
  labels:
    app.kubernetes.io/name: producer-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: producer-service
  template:
    metadata:
      labels:
        app.kubernetes.io/name: producer-service
        app.kubernetes.io/instance: sad-markhor
    spec:
      containers:
        - name: producer-service
          # 镜像名需要与仓库中的镜像名一致
          image: "192.168.0.22:5000/spring-cloud-k8s-producer:1.0" 
          imagePullPolicy: Always
          ports:
            - name: http
              containerPort: 8082
              protocol: TCP

可以看到有 producer-service 的pod正常运行。

    • 1, 创建spring cloud项目。并编写CustomerApplication.java,CustomerController.java,ProducerClient.java,ProducerClientFallback Dockerfile,application.yaml, pom.xml,customer-service.yaml。
      • 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud-k8s-parent</artifactId>
        <groupId>com.yayiyo.k8s</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-k8s-customer</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-openfegin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>${spring-cloud-openfegin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>${spring-boot.version}</version>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring-boot.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes</artifactId>
            <version>${spring-cloud.k8s}</version>
        </dependency>
    </dependencies>


</project>
  • CustomerApplication.java
package com.yayiyo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class CustomerApplication {
    public static void main(String[] args) {
        SpringApplication.run(CustomerApplication.class, args);
    }
}

  • RpcController.java
package com.yayiyo.controllers;

import com.yayiyo.client.ProducerClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@Slf4j
public class CoustomerController {
    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ProducerClient producerClient;


    @GetMapping("/service")
    public Object getClient() {
        return discoveryClient.getServices();
    }

    @GetMapping("/instance")
    public List<ServiceInstance> getInstance(String instanceId) {
        return discoveryClient.getInstances(instanceId);
    }

    @GetMapping("/ping")
    public String ping() {
        return producerClient.ping();
    }
}


  • ProducerClient.java
package com.yayiyo.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name = "http://producer-service:8082", url = "http://producer-service:8082", fallback = ProducerClientFallback.class)
public interface  ProducerClient {
    @RequestMapping(value = "/ping", method = RequestMethod.GET)
    String  ping();
}

@Component
class ProducerClientFallback implements ProducerClient{

    @Override
    public String ping() {
        return "Error";
    }
}

  • application.yaml
spring:
  application:
    name: customer-service
  cloud:
    kubernetes:
      config:
        sources:
          - name: ${spring.application.name}
            namespace: default
      reload:
        enabled: true
        mode: event
      discovery:
        all-namespaces: true
server:
  port: 8081

management:
  endpoint:
    restart:
      enabled: true
  endpoints:
    web:
      exposure:
        include: restart

  • 2. idea上配置docker服务,执行Dockerfile,打包镜像并把镜像推到docker服务器上。

    • Dockerfile
FROM openjdk:8-jdk-alpine

LABEL version="1.0" maintainer="[email protected]"
VOLUME /tmp
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ARG JAR_FILE
ADD target/springcloud-k8s-customer-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar","/app.jar"]
EXPOSE 808

  • idea的docker配置

docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku

  • 3. 把镜像推到docker仓库里面

#查看本地仓库里面是否有该镜像
docker images
# 推到远程镜像仓库
docker push 镜像名
  • 4.在k8s-master服务器上 编写 customer-service.yaml并执行

kubectl apply -f  customer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: customer-service
  labels:
    app.kubernetes.io/name: customer-service
spec:
  # 可以直接使用NodePort方式放开端口,这里使用ClusterIP+nginx的方式,其好处是使用负载均衡以及nginx代理。
  # 注意:如果使用NodePort方式,则不用编写ingress-nginx-controller以及tcp-services-configmap
  type: ClusterIP
  ports:
    - port: 8081
      targetPort: 8081
      nodePort: 8081
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: customer-service

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: customer-service
  labels:
    app.kubernetes.io/name: customer-service
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: customer-service
  template:
    metadata:
      labels:
        app.kubernetes.io/name: customer-service
        app.kubernetes.io/instance: sad-markhor
    spec:
      containers:
        - name: customer-service
          image: "192.168.0.22:5000/spring-cloud-k8s-customer:1.0"
          imagePullPolicy: Always
          ports:
            - name: http
              containerPort: 8081
              protocol: TCP
---
# Source: ingress-nginx/templates/controller-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    helm.sh/chart: ingress-nginx-2.13.0
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 0.35.0
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  externalTrafficPolicy: Cluster
  ports:
    # 该名称需要与消费者service中的name保持一致
    - name: customer-service
      port: 8081
      protocol: TCP
      targetPort: 8081
      nodePort: 8081
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller
---
apiVersion: v1
kind: ConfigMap
metadata:
  # 该文件需要在ingress-nginx-controller中引用。
  name: tcp-services-configmap
  namespace: ingress-nginx
data:
  "8081": "default/customer-service:8081"

正常可以在浏览器中看到:
docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku

  • 注意问题:

  1. 在ide编辑时一定要用LF格式
    docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku
  2. 执行dockerfile后记得在服务器上push镜像。
  3. customer中的producerCLient.java中FeignClient 的url要写ip:port,只写服务名是找不到该服务的。
@FeignClient(name = "http://producer-service:8082", url = "http://producer-service:8082", fallback = ProducerClientFallback.class)
  1. 如果想在本机测试,可以在host里面设置producer-service
127.0.0.1 producer-service 

docker+kubernetes+springcloud微服务集群部署,spring-cloud-ku相关教程