使用kubernetes部署云服务
这个小项目通过kubernetes部署,包括eureka服务器,userService,adminService,并部署mysql服务存储持久化对象
加入各类组件并实现基本功能
以user-service的pom为例,加入eureka、mysql、springcloud各类组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>io.daocloud</groupId>
<artifactId>user-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-client</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>user-service</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>编码实现基本功能,以添加用户为例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package io.daocloud.userservice.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import io.daocloud.userservice.dao.UserDao;
import io.daocloud.userservice.domain.User;
/**
* Author: Garroshh date: 2020/7/9 8:19 下午
*/
public class UserService {
private UserDao userDao;
public User add(User user) {
return userDao.save(user);
}
public User get(long id) {
return userDao.getOne(id);
}
}启动mysql服务
- 拉取镜像
1
2docker pull mysql:8.0.33
//这个版本要与deployment.yaml和pv.yaml里面的版本一致- 部署mysql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44piVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
clusterIP: None
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:8.0.33
name: mysql
env:
# 在实际中使用 secret
- name: MYSQL_ROOT_PASSWORD
value: dangerous
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
hostPath:
# 注意这里改成服务器上的一个空文件夹路径
path: "/Users/lyl/moss"
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi- apply
1
2kubectl apply -f mysql-deployment.yaml
kubectl apply -f mysql-pv.yaml- 在容器中创建user database
1
2
3
4
5
6
7
8
9kubectl run -it --rm --image=mysql:8.0.33 --restart=Never mysqlclient -- mysql -h mysql -pdangerous
If you don't see a command prompt, try pressing enter.
create database user;
Query OK, 1 row affected (0.03 sec)
^C
exit
Bye- 查看资源
1
2
3
4
5
6
7kubectl get po,svc
NAME READY STATUS RESTARTS AGE
pod/mysql-7b99cd9bc9-js7lh 1/1 Running 0 23m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 176m
service/mysql ClusterIP None <none> 3306/TCP 23m- 这里可能会遇到一个问题:The PersistentVolume “mysql-pv-volume” is invalid: spec.persistentvolumesource: Forbidden: spec.persistentvolumesource is immutable after creation,这是因为这个mysql服务已经存在了,解决方案是换一个名字或者把原来服务的删除
1
2
3
4kubectl get pv
kubectl get pvc
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv-volume接下来将三个服务的jar包打好
在三个服务的子文件夹下运行
1
mvn -B -Dmaven.test.skip clean package
接下来根据dockerfile将容器build出来
特别注意这里的标签名要和development.yaml里面的名字相符
1
2
3docker build -t user-service:2023 .
docker build -t admin-service:2023 .
docker build -t eureka:2023 .接下来我们apply,通过kubernetes部署三个service
1
2
3kubectl apply -f admin-deployment.yaml
kubectl apply -f admin-service.yaml
//user-service和eureka以此类推现在我们查看资源:
1
2
3
4
5
6
7
8
9
10
11
12
13kubectl get po,svc
NAME READY STATUS RESTARTS AGE
pod/admin-service-84444789db-mtrdt 1/1 Running 0 7m20s
pod/eurkea-76cff4d569-j2hbt 1/1 Running 0 9m41s
pod/mysql-7b99cd9bc9-js7lh 1/1 Running 0 55m
pod/user-service-7cb8755bd7-xhd6w 1/1 Running 0 9m2s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/admin-service NodePort 10.108.205.242 <none> 10000:30521/TCP 7m7s
service/eureka NodePort 10.104.237.255 <none> 8080:31011/TCP 9m28s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h27m
service/mysql ClusterIP None <none> 3306/TCP 55m
service/user-service NodePort 10.99.98.6 <none> 9090:32657/TCP 8m50s验证部署已经成功
向user-service发送一个post请求
1
curl -H "Content-Type: application/json" -X POST -d '{"name":"张三", "pwd":"888"}' http://localhost:32657/user
收到回应
1
{"id":1,"name":"张三","pwd":"888"}
向user-service发送错误的post请求,收到报错
同时也可以访问eureka服务
访问特定的id
在admin-service中编码
1
2
3
4
public Object get({ UserDto id)
return userService.get(id);
}发送请求
1
curl http://localhost:30521/user?id=1
收到回应
1
{"id":1,"name":"张三"}
负载均衡
直接使用自带服务中的RandomRule服务
在admin_service中的UserFeign.java中设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package io.daocloud.adminservice.fegin;
import com.netflix.loadbalancer.RandomRule;
import io.daocloud.adminservice.dto.UserDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
/**
* Author: Garroshh
* date: 2020/7/9 8:39 下午
*/
//使用随机策略
public interface UserFeign {
Object add(UserDto userDto);
String port();
}接下来我们启动两个user-service服务,分别注册端口9090和9000
application.properties
1
2spring.application.name=user-service
server.port=9090 //另一个就是9000更改user_deployment和user_service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service-1 //另一个就是-2
labels:
app: user-service-1
spec:
replicas: 1
selector:
matchLabels:
app: user-service-1
template:
metadata:
labels:
app: user-service-1
spec:
hostname: user-service-1
containers:
- name: user-service-1
image: user-service-1:2023
imagePullPolicy: IfNotPresent
env:
- name: EUREKA_URL
value: http://eureka:8080/eureka
ports:
- containerPort: 8080
resources:
requests:
cpu: 0.5
memory: 256Mi
limits:
cpu: 0.5
memory: 256Mi1
2
3
4
5
6
7
8
9
10
11
12
13apiVersion: v1
kind: Service
metadata:
name: user-service-1 //另一个就是-2
labels:
app: user-service-1
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
selector:
app: user-service重新运行之后就可以看到新的服务在eureka上注册了
这时访问admin-service的port地址,就可以发现相应的user-service是随机的