容器化技术与微服务结合---结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)
目录系列更换成阿里云仓库开通阿里云镜像服务创建仓库本地k8s切换成阿里云的镜像仓库测试阿里云镜像准备简单的微服务服务设计服务配置打成镜像并以docker方式运行部署k8s系列容器化技术与微服务结合—docker(一)容器化技术与微服务结合—Kubernetes基本介绍(二)容器化技术与微服务结合—Pod详解(三)容器化技术与微服务结合—实操service并部署一个简单对外开放的sprin...
目录
系列
容器化技术与微服务结合—docker(一)
容器化技术与微服务结合—Kubernetes基本介绍(二)
容器化技术与微服务结合—Pod详解(三)
容器化技术与微服务结合—实操service并部署一个简单对外开放的springboot HelloWord服务(四)
容器化技术与微服务结合—结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)
容器化技术与微服务结合—SpringCloud框架与阿里云serverless k8s的结合(六)
更换成阿里云仓库
首先,k8s默认的是docker hub的源。网络实在太卡,我们先切换成国内的。
开通阿里云镜像服务
这个服务免费的
进入控制台,开通镜像服务
创建仓库
点击创建仓库,然后填写完。这里博主选择公开,毕竟用于本地和云上测试(企业级必须私有哦。并且云上k8s保持同一个vpc内)
这里选择本地仓库。你可以使用阿里云的自动化构建。不过这里博主选择自己手动搞
可以看到。只要在本地登录docker之后。便可以轻松操作了。
密码在访问凭证里可以设定
随便打几个镜像上传到阿里云仓库把。发现已经上传完毕:
本地k8s切换成阿里云的镜像仓库
创建访问阿里云docker的secret对象,这里是阿里云docker的账号密码
kubectl create secret docker-registry aliyun-docker-test \
--docker-server=registry.cn-shanghai.aliyuncs.com \
--docker-username=登陆阿里云docker的用户名 \
--docker-password=登陆阿里云docker的密码 \
--docker-email=选填
请注意上线命令中的命名:aliyun-docker-test 如果需要使用这个docker源。那么就要在pod里面指定是用这个名称获取镜像
使用kubectl get secrets查看所有的镜像仓库。可以看到刚才我们创建的aliyun-docker-test已经好了
测试阿里云镜像
我们将pod配置修改为:
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloword
labels:
app: helloword
spec:
minReadySeconds: 30 #启动pod之后延迟多少时间
strategy:
# indicate which strategy we want for rolling update
type: RollingUpdate #滚动发布
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 2
selector:
matchLabels:
app: helloword
template:
metadata:
labels:
app: helloword
spec:
containers:
- name: helloword
image: registry.cn-shanghai.aliyuncs.com/emper_test/k8s-test:v1
imagePullPolicy: Always
ports:
- containerPort: 9999
imagePullSecrets:
- name: default/aliyun-docker-test #指定是阿里云docker的资源,斜杠前面是命名空间,创建不指定的话默认是default命名空间, 这里不加命名空间会拉不到镜像
---
apiVersion: v1
kind: Service
metadata:
name: helloword-service
labels:
app: helloword
spec:
ports:
- port: 9999
protocol: TCP
type: NodePort
selector:
app: helloword
注意imagePullSecrets的名称一定要加命名空间,最开始博主没加,结果各种获取不了镜像
- minReadySeconds:
这个值默认是0,Kubernetes会假设该容器启动起来后就可以提供服务了,会导致用户访问异常
这里需要估一个比较合理的值,从容器启动到应用正常提供服务
如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了
如果没有设置该值,在某些极端情况下可能会造成服务不正常运行- maxSurge:
升级过程中最多可以比原先设置多出的POD数量
例如:maxSurage=1,replicas=5,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有5+1个POD。- maxUnavaible:
升级过程中最多有多少个POD处于无法提供服务的状态
当maxSurge不为0时,该值也不能为0
例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态。- 注意如果实在不想过于复杂的滚动发布,那么将minReadySeconds设置一个合理的值(比如确认1分钟之内应用都能启动),这样可以让应用无间断发布
再次执行kubectl apply -f helloword-deployment.yaml,发现成功,访问http://192.168.99.110:31125/hello,得到“aliyun docker version:1”返回。
将镜像版本改为v2. 也成功得到“aliyun docker version:2”。
切换成阿里云docker成功
准备简单的微服务
我们来准备三个服务:eureka、demo-a、demo-b。
demo-a提供两个接口:
- /demo/a,返回I am demo-a
- /demo/a/from/b,调用demo-b服务返回feign: from demo-b
demo-b提供两个接口:
- /demo/b,返回I am demo-b
- /demo/b/from/a,调用demo-a服务返回feign: from demo-a
eureka
应用配置
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>k8s.demo</groupId>
<artifactId>eureka</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<run.jvmArguments/>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.3.RELEASE</version>
<executions>
<execution>
<goals>
<goal>build-info</goal>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
启动类如下:
package k8s.demo.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class Boot {
public static void main(String[] args) {
SpringApplication.run(Boot.class, args);
}
}
配置文件:
server:
port: 8761
spring:
profiles:
active: dev
application:
name: eureka
eureka:
server:
#是否开启自我保护(运行期间spring会统计信条失败的比例在15分钟之内是否低于85%,如果不低于85%,Eureka会将实例注册信息保护起来,让这些实例不会过期)
enable-self-preservation: false
eviction-interval-timer-in-ms: 3000 #3秒钟自动剔除失效的节点
response-cache-update-interval-ms: 3000 #eureka server刷新readCacheMap的时间
#注意,client读取的是readCacheMap,这个时间决定了多久会把readWriteCacheMap的缓存更新到readCacheMap上
instance:
hostname: server-eureka-server
client:
register-with-eureka: false #自己也注册到注册中心
fetch-registry: false #需要从其他eureka节点获取注册信息
service-url:
default-zone: http://${eureka.instance.hostname}:${server.port}/eureka #设置与eureka交互的地址
这里注意: hostname: server-eureka-server 是用于k8s中service名称匹配。
k8s配置:
创建一个文件k8s-eureka-server.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-eureka-server
spec:
# 注册中心部署一个即可,集群的话,比较麻烦
replicas: 1
selector:
matchLabels:
app: eureka-server
template:
metadata:
labels:
app: eureka-server
spec:
containers:
- name: eureka-server
image: registry.cn-shanghai.aliyuncs.com/emper_test/eureka-server:v2
imagePullPolicy: Always
ports:
- containerPort: 8761
imagePullSecrets:
- name: default/aliyun-docker-test
---
apiVersion: v1
kind: Service
metadata:
# service的名字非常重要,必须跟application.properties的eureka.client.serviceUrl.defaultZone=http://server-eureka-server:8761/eureka/ 中的域名相同
name: server-eureka-server
spec:
selector:
app: eureka-server
# 使用NodePort类型的Service,绑定service的10001端口到宿主机,以便在物理机浏览器上看注册中心的信息
type: NodePort
ports:
- port: 8761
targetPort: 8761
demo-a
应用配置
Pom文件就不多做展示了,比较简单,引入springcloud以及feign等jar即可
我们下一个路由:
package k8s.demo.a;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Router {
@Autowired
private Client client;
/**
* demo-a服务的接口
* @return
*/
@GetMapping("/demo/a")
public String hello() {
return "I am demo-a";
}
/**
* demo-a请求demo-b的feign接口返回
* @return
*/
@GetMapping("/demo/a/from/b")
public String fromB() {
return client.feign();
}
/**
* 提供给demo-b的feign内部接口
* @return
*/
@GetMapping("/demo/a/feign")
public String feign() {
return "feign: from demo-a";
}
}
再加入feign接口用于调用demo-b服务:
package k8s.demo.a;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("demo-b")
public interface Client {
@GetMapping("/demo/b/feign")
public String feign();
}
yaml配置文件如下:
server:
port: 9998
spring:
application:
name: demo-a
eureka:
instance:
prefer-ip-address: true
lease-expiration-duration-in-seconds: 20 #服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除(默认90秒)
lease-renewal-interval-in-seconds: 5 #服务刷新时间配置,每隔这个时间会主动心跳一次(默认30秒)
client:
service-url:
defaultZone: http://server-eureka-server:8761/eureka/
registry-fetch-interval-seconds: 10 #重新刷新服务地址的时间
这里注意defaultZone: http://server-eureka-server:8761/eureka/ 这个连接是k8s的service名称
k8s配置
Dockerfile:
FROM openjdk:8-jre-alpine
RUN mkdir -p /docker/demo
RUN mkdir -p /docker/demo/logs
ADD ./target/demo-a.jar /docker/demo/demo-a.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/docker/demo/demo-a.jar"]
k8s的pod配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-demo-a
labels:
app: deployment-demo-a
spec:
minReadySeconds: 30
strategy:
# indicate which strategy we want for rolling update
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 1
selector:
matchLabels:
app: demo-a
template:
metadata:
labels:
app: demo-a
spec:
containers:
- name: demo-a
image: registry.cn-shanghai.aliyuncs.com/emper_test/demo-a:v1
imagePullPolicy: Always
ports:
- containerPort: 9998
imagePullSecrets:
- name: default/aliyun-docker-test #指定是阿里云docker的资源,斜杠前面是命名空间,创建不指定的话默认是default命名空间, 这里不加命名空间会拉不到镜像
---
apiVersion: v1
kind: Service
metadata:
name: demo-a-service
labels:
app: demo-a-service
spec:
ports:
- port: 9998
selector:
app: demo-a #选择所有为demo-a的pod
demo-b
和demo-a基本一样
应用配置
写一个路由:
package k8s.demo.b;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Router {
@Autowired
private Client client;
/**
* demo-b服务的接口
* @return
*/
@GetMapping("/demo/b")
public String hello() {
return "I am demo-b";
}
/**
* demo-b请求demo-a的feign接口返回
* @return
*/
@GetMapping("/demo/b/from/a")
public String fromA() {
return client.feign();
}
/**
* 提供给demo-a的feign内部接口
* @return
*/
@GetMapping("/demo/b/feign")
public String feign() {
return "feign: from demo-b";
}
}
再来一个feign:
package k8s.demo.b;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient("demo-a")
public interface Client {
@GetMapping("/demo/a/feign")
String feign();
}
应用配置文件如下:
server:
port: 9999
spring:
application:
name: demo-b
eureka:
instance:
prefer-ip-address: true
lease-expiration-duration-in-seconds: 20 #服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除(默认90秒)
lease-renewal-interval-in-seconds: 5 #服务刷新时间配置,每隔这个时间会主动心跳一次(默认30秒)
client:
service-url:
defaultZone: http://server-eureka-server:8761/eureka/
registry-fetch-interval-seconds: 10 #重新刷新服务地址的时间
k8s配置
Dockerfile:
FROM openjdk:8-jre-alpine
RUN mkdir -p /docker/demo
RUN mkdir -p /docker/demo/logs
ADD ./target/demo-b.jar /docker/demo/demo-b.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/docker/demo/demo-b.jar"]
k8s的pod配置如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-demo-b
labels:
app: deployment-demo-b
spec:
minReadySeconds: 30
strategy:
# indicate which strategy we want for rolling update
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
replicas: 1
selector:
matchLabels:
app: demo-b
template:
metadata:
labels:
app: demo-b
spec:
containers:
- name: demo-b
image: registry.cn-shanghai.aliyuncs.com/emper_test/demo-b:v1
imagePullPolicy: Always
ports:
- containerPort: 9999
imagePullSecrets:
- name: default/aliyun-docker-test #指定是阿里云docker的资源,斜杠前面是命名空间,创建不指定的话默认是default命名空间, 这里不加命名空间会拉不到镜像
---
apiVersion: v1
kind: Service
metadata:
name: demo-b-service
labels:
app: demo-b-service
spec:
ports:
- port: 9999
selector:
app: demo-b #选择所有为demo-b的pod
打成镜像docker镜像并上传到阿里云镜像服务
首先对每个服务进行mvn package spring-boot:repackage 打包操作。
然后我们使用docker进行build:
docker build -t 你的阿里云镜像路径:版本号 .
然后使用docker push 镜像:版本号,将其push到阿里云镜像仓库
部署k8s
部署eureka
在eureka的k8s配置文件目录下执行:
kubectl apply -f k8s-eureka-server.yaml
略微等待,因为我们对eureka开启了外部ip,启动完毕之后,我们使用
minikube ip, 查看到虚拟机ip是:http://192.168.99.110
使用kubectl get service,查看到所有service的ip和端口:
我们在浏览器输入:http://192.168.99.110:31095/,返现eureka启动,并且两个服务已注册上:
部署demo-a和demo-b
使用:
kubectl apply -f k8s-demo-a.yaml
kubectl apply -f k8s-demo-b.yaml
分别创建对应的service、pod
两个服务都是内网ip,不对外部提供ip
根据上面的图,发现:
- demo-a内部ip是:10.100.194.238:9998
- demo-b内部ip是:10.96.126.63:9998
使用minikube ssh进入虚拟机内。分别用两个服务的地址调用接口:
curl http://10.100.194.238:9998/demo/a
curl http://10.100.194.238:9998/demo/a/from/b
curl http://10.96.126.63:9998/demo/b
curl http://10.96.126.63:9998/demo/b/from/a
发现调用成功无误
结尾
由于k8s判定服务是否可用是基于pod,但是有可能出现容器内部的应用还没启动,所以会造成短暂的不可用。
参考:Kubernetes–k8s—滚动更新–零停机不停服发布服务
更多推荐
所有评论(0)