天天看點

docker+kubernetes+springcloud微服務叢集部署,spring-cloud-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能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.11 k8s-master
192.168.0.22 k8s-node1 , docker registry
192.168.0.33 k8s-node2

代碼見https://github.com/heliu0/springcloud-k8s.git

  • 生産者 producer

    • 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-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能docker+kubernetes+springcloud微服務叢集部署,spring-cloud-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能
  • 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正常運作。

  • 消費者 customer

    • 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-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能docker+kubernetes+springcloud微服務叢集部署,spring-cloud-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能
  • 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-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能docker+kubernetes+springcloud微服務叢集部署,spring-cloud-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能
  • 注意問題:

  1. 在ide編輯時一定要用LF格式
    docker+kubernetes+springcloud微服務叢集部署,spring-cloud-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能docker+kubernetes+springcloud微服務叢集部署,spring-cloud-kubernetes,使用k8s部署spring cloud并實作服務注冊、負載均衡、網關等功能
  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