一、本文示例

简单实现一个注册中心两个互相调用服务的SpringCloud应用,制作镜像并在k8s环境部署

本地环境:

minikube v1.6.2

java 8

SpringCloud 2.3.2-RELEASE

为保证minikube中可直接使用本地构建的镜像,需要行进行如下设置,使本地docker命令连接到minikube环境中

执行命令:

eval $(minikube docker-env)


此时docker 命令已经连接到minikube环境中了,可以使用docker images查看已经不是本地的镜像列表了(别担心该命令只改变了当前会话下的docker命令,关闭或重新开户会话就正常了)

然后按正常逻辑构建镜像即可

docker build -t xxx .
1
1
docker build -t xxx .
1

最后在写部署文件的Deployment.yaml中将imagePullPolicy设置为IfNotPresent或Never(不去远程拉取,使用本地)

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: service-customerspec:  replicas: 1  template:    metadata:      labels:        app: service-customer    spec:      containers:      - name: service-customer        image: service-customer        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080
1234567891011121314151617
1234567891011121314151617
apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: service-customerspec:  replicas: 1  template:    metadata:      labels:        app: service-customer    spec:      containers:      - name: service-customer        image: service-customer        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080
1234567891011121314151617

二、创建项目

eureka项目:注册中心

service-provider: 服务提供方

service-customer:服务调用方

下面挑重点说一下,完事代码文末有github地址

1)eureka注册中心

pom.xml:

....		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-actuator</artifactId>		</dependency>		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-web</artifactId>		</dependency>		<dependency>			<groupId>org.springframework.cloud</groupId>			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>		</dependency>....
1234567891011121314
1234567891011121314
....		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-actuator</artifactId>		</dependency>		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-web</artifactId>		</dependency>		<dependency>			<groupId>org.springframework.cloud</groupId>			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>		</dependency>....
1234567891011121314

主要是引入eureka-server依赖

application.yaml

spring:  application:    name: eurekaserver:  port: 8080eureka:  client:    register-with-eureka: true    fetch-registry: false    service-url:      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  instance:    hostname: localhost    instance-id: eureka-8080
1234567891011121314
1234567891011121314
spring:  application:    name: eurekaserver:  port: 8080eureka:  client:    register-with-eureka: true    fetch-registry: false    service-url:      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  instance:    hostname: localhost    instance-id: eureka-8080
1234567891011121314

Dockerfile:

FROM openjdk:8-alpineCOPY target/eureka.jar .CMD java -jar eureka.jar
123
123
FROM openjdk:8-alpineCOPY target/eureka.jar .CMD java -jar eureka.jar
123

k8s部署及创建service k8s.yaml:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: eurekaspec:  replicas: 1  template:    metadata:      labels:        app: eureka    spec:      containers:      - name: eureka        image: eureka        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080---apiVersion: v1kind: Servicemetadata:  name: eurekaspec:  type: NodePort  selector:    app: eureka  ports:  - protocol: TCP    port: 8080    targetPort: 8080
123456789101112131415161718192021222324252627282930
123456789101112131415161718192021222324252627282930
apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: eurekaspec:  replicas: 1  template:    metadata:      labels:        app: eureka    spec:      containers:      - name: eureka        image: eureka        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080---apiVersion: v1kind: Servicemetadata:  name: eurekaspec:  type: NodePort  selector:    app: eureka  ports:  - protocol: TCP    port: 8080    targetPort: 8080
123456789101112131415161718192021222324252627282930

2) service-provider服务提供方

pom.xml

....		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-actuator</artifactId>		</dependency>		<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.springframework.cloud</groupId>			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>		</dependency>....
123456789101112131415161718
123456789101112131415161718
....		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-actuator</artifactId>		</dependency>		<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.springframework.cloud</groupId>			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>		</dependency>....
123456789101112131415161718

引入eureka client依赖

application.yaml:

spring:  application:    name: service-providereureka:  instance:    instance-id: service-provider    hostname: service-provider  client:    service-url:      # eureka地址使用 k8s的service地址      defaultZone: http://eureka:8080/eureka/server:  port: 8080
12345678910111213
12345678910111213
spring:  application:    name: service-providereureka:  instance:    instance-id: service-provider    hostname: service-provider  client:    service-url:      # eureka地址使用 k8s的service地址      defaultZone: http://eureka:8080/eureka/server:  port: 8080
12345678910111213

Dockerfile:

FROM openjdk:8-alpineCOPY target/service-provider.jar .CMD java -jar service-provider.jar
123
123
FROM openjdk:8-alpineCOPY target/service-provider.jar .CMD java -jar service-provider.jar
123

k8s部署及创建service k8s.yaml:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: service-providerspec:  replicas: 1  template:    metadata:      labels:        app: service-provider    spec:      containers:      - name: service-provider        image: service-provider        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080---apiVersion: v1kind: Servicemetadata:  name: service-providerspec:  selector:    app: service-provider  ports:    - protocol: TCP      port: 8080      targetPort: 8080
1234567891011121314151617181920212223242526272829
1234567891011121314151617181920212223242526272829
apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: service-providerspec:  replicas: 1  template:    metadata:      labels:        app: service-provider    spec:      containers:      - name: service-provider        image: service-provider        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080---apiVersion: v1kind: Servicemetadata:  name: service-providerspec:  selector:    app: service-provider  ports:    - protocol: TCP      port: 8080      targetPort: 8080
1234567891011121314151617181920212223242526272829

提供接口服务 HelloController.java:

@RestController@RequestMapping("/")public class HelloController {    @RequestMapping("/hello")    public String hello(){        return "hello world";    }}
123456789
123456789
@RestController@RequestMapping("/")public class HelloController {    @RequestMapping("/hello")    public String hello(){        return "hello world";    }}
123456789

3) service-customer服务调用方

pom.xml

....		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-actuator</artifactId>		</dependency>		<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.springframework.cloud</groupId>			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>		</dependency>....
123456789101112131415161718
123456789101112131415161718
....		<dependency>			<groupId>org.springframework.boot</groupId>			<artifactId>spring-boot-starter-actuator</artifactId>		</dependency>		<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.springframework.cloud</groupId>			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>		</dependency>....
123456789101112131415161718

引入eureka client依赖

application.yaml:

spring:  application:    name: service-customereureka:  client:    service-url:      # eureka地址使用 k8s的service地址      defaultZone: http://eureka:8080/eureka/  instance:    instance-id: service-customer    hostname: service-customerserver:  port: 8080feign:  hystrix:    enabled: true
12345678910111213141516
12345678910111213141516
spring:  application:    name: service-customereureka:  client:    service-url:      # eureka地址使用 k8s的service地址      defaultZone: http://eureka:8080/eureka/  instance:    instance-id: service-customer    hostname: service-customerserver:  port: 8080feign:  hystrix:    enabled: true
12345678910111213141516

Dockerfile:

FROM openjdk:8-alpineCOPY target/service-customer.jar .CMD java -jar service-customer.jar
123
123
FROM openjdk:8-alpineCOPY target/service-customer.jar .CMD java -jar service-customer.jar
123

k8s部署及创建service k8s.yaml:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: service-customerspec:  replicas: 1  template:    metadata:      labels:        app: service-customer    spec:      containers:      - name: service-customer        image: service-customer        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080---apiVersion: v1kind: Servicemetadata:  name: service-customerspec:  selector:    app: service-customer  type: NodePort  ports:    - protocol: TCP      port: 8080      targetPort: 8080
123456789101112131415161718192021222324252627282930
123456789101112131415161718192021222324252627282930
apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: service-customerspec:  replicas: 1  template:    metadata:      labels:        app: service-customer    spec:      containers:      - name: service-customer        image: service-customer        imagePullPolicy: IfNotPresent        ports:        - containerPort: 8080---apiVersion: v1kind: Servicemetadata:  name: service-customerspec:  selector:    app: service-customer  type: NodePort  ports:    - protocol: TCP      port: 8080      targetPort: 8080
123456789101112131415161718192021222324252627282930

测试接口IndexController.java:

@RestController@RequestMapping("/")public class IndexController {    @Resource    private HelloService helloService;    @RequestMapping("/index")    public String index(){        return helloService.hello();    }}
123456789101112
123456789101112
@RestController@RequestMapping("/")public class IndexController {    @Resource    private HelloService helloService;    @RequestMapping("/index")    public String index(){        return helloService.hello();    }}
123456789101112

HelloService.java:

/** * 通过feignClient调用服务提供者 */@FeignClient(name = "service-provider", fallback = HelloServiceFallback.class)public interface HelloService {    @RequestMapping("/hello")    String hello();}
12345678
12345678
/** * 通过feignClient调用服务提供者 */@FeignClient(name = "service-provider", fallback = HelloServiceFallback.class)public interface HelloService {    @RequestMapping("/hello")    String hello();}
12345678

HelloServiceFallback.java:

@Servicepublic class HelloServiceFallback implements HelloService{    @Override    public String hello() {        return "fallback....";    }}
1234567
1234567
@Servicepublic class HelloServiceFallback implements HelloService{    @Override    public String hello() {        return "fallback....";    }}
1234567

三、构建部署

首先保证当前终端已经使用的是minikube的docker(可以docker images看一下,镜像列表不是本地环境的就对了)

首先构建部署eureka(进入eureka项目目录):

# 构建docker build -t eureka .# 查看镜像docker images# 部署k8skubectl apply -f k8s.yaml# 查看deploymentkubectl get deploymentNAME     READY   UP-TO-DATE   AVAILABLE   AGEeureka   1/1     1            1           29s# 查看Servicekubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGEeureka       NodePort    10.101.11.23   <none>        8080:30512/TCP   65s# 查看podkubectl get podNAME                               READY   STATUS    RESTARTS   AGEeureka-8b48665d7-v9wmf             1/1     Running   0          82s
123456789101112131415161718
123456789101112131415161718
# 构建docker build -t eureka .# 查看镜像docker images# 部署k8skubectl apply -f k8s.yaml# 查看deploymentkubectl get deploymentNAME     READY   UP-TO-DATE   AVAILABLE   AGEeureka   1/1     1            1           29s# 查看Servicekubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGEeureka       NodePort    10.101.11.23   <none>        8080:30512/TCP   65s# 查看podkubectl get podNAME                               READY   STATUS    RESTARTS   AGEeureka-8b48665d7-v9wmf             1/1     Running   0          82s
123456789101112131415161718

可以看到service映射到nodeport的 30512 可以使用命令查看minikube的ip:

12

minikube ip192.168.64.2

在浏览器访问 http://192.168.64.2:30512 就可以打开eureka注册中心了

部署service-provider服务提供方(进入service-provider项目目录):

# 构建docker build -t service-provider .# 查看镜像docker images# 部署k8skubectl apply -f k8s.yaml# 查看deploymentkubectl get deploymentNAME               READY   UP-TO-DATE   AVAILABLE   AGEeureka             1/1     1            1           4m18sservice-provider   1/1     1            1           7s# 查看Servicekubectl get svcNAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGEeureka             NodePort    10.101.11.23    <none>        8080:30512/TCP   4m39sservice-provider   ClusterIP   10.103.25.172   <none>        8080/TCP         28s# 查看podkubectl get pod NAME                               READY   STATUS    RESTARTS   AGEeureka-8b48665d7-v9wmf             1/1     Running   0          4m51sservice-provider-57d69f46c-lltgw   1/1     Running   0          40s
123456789101112131415161718192021
123456789101112131415161718192021
# 构建docker build -t service-provider .# 查看镜像docker images# 部署k8skubectl apply -f k8s.yaml# 查看deploymentkubectl get deploymentNAME               READY   UP-TO-DATE   AVAILABLE   AGEeureka             1/1     1            1           4m18sservice-provider   1/1     1            1           7s# 查看Servicekubectl get svcNAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGEeureka             NodePort    10.101.11.23    <none>        8080:30512/TCP   4m39sservice-provider   ClusterIP   10.103.25.172   <none>        8080/TCP         28s# 查看podkubectl get pod NAME                               READY   STATUS    RESTARTS   AGEeureka-8b48665d7-v9wmf             1/1     Running   0          4m51sservice-provider-57d69f46c-lltgw   1/1     Running   0          40s
123456789101112131415161718192021

部署service-customer服务调用方(进入service-customer项目目录):

pod都Running之后,测试一下接口调用 跟上边eureka一样,customer映射到node的prot为 32357

# 构建docker build -t service-customer .# 查看镜像docker images# 部署k8skubectl apply -f k8s.yaml# 查看deploymentkubectl get deploymentNAME               READY   UP-TO-DATE   AVAILABLE   AGEeureka             1/1     1            1           10mservice-customer   1/1     1            1           8sservice-provider   1/1     1            1           6m18s# 查看Servicekubectl get svcNAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGEeureka             NodePort    10.101.11.23     <none>        8080:30512/TCP   10mservice-customer   NodePort    10.104.108.133   <none>        8080:32357/TCP   23sservice-provider   ClusterIP   10.103.25.172    <none>        8080/TCP         6m33s# 查看podkubectl get podNAME                               READY   STATUS    RESTARTS   AGEeureka-8b48665d7-v9wmf             1/1     Running   0          11mservice-customer-898557664-m854c   1/1     Running   0          46sservice-provider-57d69f46c-lltgw   1/1     Running   0          6m56s
123456789101112131415161718192021222324
123456789101112131415161718192021222324
# 构建docker build -t service-customer .# 查看镜像docker images# 部署k8skubectl apply -f k8s.yaml# 查看deploymentkubectl get deploymentNAME               READY   UP-TO-DATE   AVAILABLE   AGEeureka             1/1     1            1           10mservice-customer   1/1     1            1           8sservice-provider   1/1     1            1           6m18s# 查看Servicekubectl get svcNAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGEeureka             NodePort    10.101.11.23     <none>        8080:30512/TCP   10mservice-customer   NodePort    10.104.108.133   <none>        8080:32357/TCP   23sservice-provider   ClusterIP   10.103.25.172    <none>        8080/TCP         6m33s# 查看podkubectl get podNAME                               READY   STATUS    RESTARTS   AGEeureka-8b48665d7-v9wmf             1/1     Running   0          11mservice-customer-898557664-m854c   1/1     Running   0          46sservice-provider-57d69f46c-lltgw   1/1     Running   0          6m56s
123456789101112131415161718192021222324

使用浏览器访问 http://192.168.64.2:32357/index 返回:

hello world
1
1
hello world
1

删除服务提供者的pod:

kubectl delete pod service-provider-57d69f46c-lltgw
1
1
kubectl delete pod service-provider-57d69f46c-lltgw
1

再次请求: http://192.168.64.2:32357/index 返回:

fallback....
1
1
fallback....
1

过一会新的pod启动成功后再访问就恢复正常了