1. Kubernetes简介
使用Minikube创建群集
Kubernetes协调一个高度可用的计算机集群,这些计算机连接起来作为一个单元工作。Kubernetes以更有效的方式自动化跨集群分发和调度应用程序容器。Kubernetes集群包含两种类型的资源:
- Master协调集群
- Nodes是运行应用程序的工作者,是VM或物理计算机
Nodes使用Master公开的Kubernetes API与Master进行通信。
Minikube是一种轻量级Kubernetes实现,可在本地计算机上创建VM并部署仅包含一个节点的简单集群。
使用kubectl创建部署
部署指示Kubernetes如何创建和更新应用程序的实例。
如果托管实例的节点关闭或被删除,则Deployment控制器会替换它。 这提供了一种自我修复机制来解决机器故障或维护问题。创建部署时,需要指定应用程序的容器映像以及要运行的副本数。
查看Pods和Nodes
Pods
创建部署时,Kubernetes创建了一个Pod来托管您的应用程序实例。Pod是一组一个或多个应用程序容器(例如Docker或rkt),包括共享存储(卷),IP地址和有关如何运行它们的信息。
Nodes
Pod总是在Node上运行。 Node是Kubernetes中的工作机器,可以是虚拟机器,也可以是物理机器,具体取决于集群。
使用服务公开您的应用程序
Kubernetes中的服务是一个抽象,它定义了一组逻辑Pod和一个访问它们的策略。服务启用从属Pod之间的松散耦合。与所有Kubernetes对象一样,使用YAML(首选)或JSON定义服务。通过在ServiceSpec中指定类型,可以以不同方式公开服务:
- ClusterIP(默认) - 在群集中的内部IP上公开服务。此类型使服务只能从群集中访问。
- NodePort - 使用NAT在集群中每个选定节点的同一端口上公开服务。使用<NodeIP>:<NodePort>使集群外部的服务可访问。 ClusterIP的超集。
- LoadBalancer - 在当前云中创建外部负载均衡器(如果支持),并为服务分配固定的外部IP。 NodePort的超级用户。
- ExternalName - 通过返回带有名称的CNAME记录,使用任意名称(在规范中由externalName指定)公开服务。没有使用代理。此类型需要v1.7或更高版本的kube-dns。
2. 使用Kubernetes,Spring Boot 2.0和Docker创建微服务
有三个独立的应用程序(员工服务,部门服务,组织服务),它们通过REST API相互通信。 这些Spring Boot微服务使用Kubernetes提供的一些内置机制:用于分布式配置的配置映射和机密,用于服务发现的etcd,以及用于API网关的入口。
微服务部署后Kubernetes的管理界面如下
使用配置映射和秘密注入配置
配置文件mongodb-configMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb
data:
database-name: microservices
加密配置文件mongodb-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mongodb
type: Opaque
data:
database-password: MTIzNDU2
database-user: cGlvdHI=
分别执行kubectl apply -f mongodb-configMap.yaml
和kubectl apply -f mongodb-secret.yaml
创建配置映射。
使用Kubernetes构建服务发现
在服务中添加Spring Cloud Kubernetes依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
<version>0.3.0.RELEASE</version>
</dependency>
在服务启动类中开启服务发现
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableMongoRepositories
@EnableSwagger2
public class EmployeeApplication {
public static void main(String[] args) {
SpringApplication.run(EmployeeApplication.class, args);
}
}
使用Spring Cloud Kubernetes Ribbon来进行微服务之间的通信
在服务中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
<version>0.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
它使用@EnableFeignClients批注启用Feign客户端。 它的工作原理与基于Spring Cloud Netflix Eureka的发现相同。 OpenFeign使用Ribbon进行客户端负载平衡。 Spring Cloud Kubernetes Ribbon提供了一些bean,强制Ribbon通过Fabric8 KubernetesClient与Kubernetes API进行通信。
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableMongoRepositories
@EnableSwagger2
public class EmployeeApplication {
public static void main(String[] args) {
SpringApplication.run(EmployeeApplication.class, args);
}
}
使用Docker构建微服务并在Kubernetes上部署
Docker构建文件
FROM openjdk:8-jre-alpine
ENV APP_FILE employee-1.0.jar
ENV APP_HOME /usr/apps
EXPOSE 8080
COPY target/$APP_FILE $APP_HOME/
WORKDIR $APP_HOME
ENTRYPOINT ["sh", "-c"]
CMD ["exec java -jar $APP_FILE"]
创建服务镜像
cd employee
docker build -t jiangjj/employee:1.0 .
cd department
docker build -t jiangjj/department:1.0 .
cd organization
docker build -t jiangjj/organization:1.0 .
服务在Kubernetes上创建部署和服务的配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: employee
labels:
app: employee
spec:
replicas: 1
selector:
matchLabels:
app: employee
template:
metadata:
labels:
app: employee
spec:
containers:
- name: employee
image: jiangjj/employee:1.0
ports:
- containerPort: 8080
env:
- name: MONGO_DATABASE
valueFrom:
configMapKeyRef:
name: mongodb
key: database-name
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
name: mongodb
key: database-user
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb
key: database-password
---
apiVersion: v1
kind: Service
metadata:
name: employee
labels:
app: employee
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: employee
创建服务的配置
kubectl apply -f k8s\employee-deployment.yaml
kubectl apply -f k8s\department-deployment.yaml
kubectl apply -f k8s\organization-deployment.yaml
使用Kubernetes Ingress构建API网关
Ingress是一组规则,允许传入请求到达下游服务。 在我们的微服务架构中,ingress扮演着API网关的角色。
ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: gateway-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
backend:
serviceName: default-http-backend
servicePort: 80
rules:
- host: microservices.info
http:
paths:
- path: /employee
backend:
serviceName: employee
servicePort: 8080
- path: /department
backend:
serviceName: department
servicePort: 8080
- path: /organization
backend:
serviceName: organization
servicePort: 8080
必须执行以下命令才能将上述配置应用于Kubernetes集群
kubectl apply -f k8s\ingress.yaml
使用Swagger2在网关上启用API规范
Zuul将仅作为服务Swagger API的网关,这是网关服务项目中使用的依赖项列表
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes</artifactId>
<version>0.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
<version>0.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
Kubernetes发现客户端将检测群集上公开的所有服务。我们只想显示三个微服务的文档,这就是为Zuul定义以下路由的原因
zuul:
routes:
department:
path: /department/**
employee:
path: /employee/**
organization:
path: /organization/**
现在我们可以使用ZuulProperties bean从Kubernetes发现中获取路由的地址,并将它们配置为Swagger资源
@Component
public class GatewayApi {
@Autowired
ZuulProperties properties;
@Primary
@Bean
public SwaggerResourcesProvider swaggerResourcesProvider() {
return () -> {
List resources = new ArrayList();
properties.getRoutes().values().stream()
.forEach(route -> resources.add(createResource(route.getId(), "2.0")));
return resources;
};
}
private SwaggerResource createResource(String location, String version) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(location);
swaggerResource.setLocation("/" + location + "/v2/api-docs");
swaggerResource.setSwaggerVersion(version);
return swaggerResource;
}
}
gateway在Kubernetes上的配置如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
labels:
app: gateway
spec:
replicas: 1
selector:
matchLabels:
app: gateway
template:
metadata:
labels:
app: gateway
spec:
containers:
- name: gateway
image: jiangjj/gateway:1.0
ports:
- containerPort: 8080
env:
- name: MONGO_DATABASE
valueFrom:
configMapKeyRef:
name: mongodb
key: database-name
- name: MONGO_USERNAME
valueFrom:
secretKeyRef:
name: mongodb
key: database-user
- name: MONGO_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb
key: database-password
---
apiVersion: v1
kind: Service
metadata:
name: gateway
labels:
app: gateway
spec:
type: NodePort
ports:
- port: 8080
nodePort: 31237
protocol: TCP
selector:
app: gateway
部署后通过gateway查看API页面