k8s部署springcloud框架开发的电商项目-模拟在线购物

一、私有镜像仓库Harbor的安装和配置

1、Harbor简介

Harbor是私有镜像仓库,用来存储和分发镜像的

docker还有一个官方的镜像仓库docker hub,免费用户只能简单的使用,创建一个私有镜像仓库,存储镜像,付费用户才可以拥有更多的权限,默认docekr pull拉取镜像就是从dockerhub上拉取,速度极慢,不利于生产环境使用。

harbor私有镜像仓库拉取镜像速度极快,属于内网传输,功能也很强大。

2、Harbor功能

1.基于角色访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限。

2、镜像复制:镜像可以在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景。

3、图形化界面:用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间。

4、部署简单:提供在线和离线两种安装工具

5、LDAP:Harbor可以集成企业内部已有的AD/LDAP,用于鉴权认证管理

3、初始化和安装docker

3.1 配置静态ip

1
2
nmcli con add con-name eth0-static ifname eth0 type ethernet ipv4.method manual ipv4.addresses 192.168.106.30/24 ipv4.gateway 192.168.106.2 ipv4.dns 114.114.114.114 connection.autoconnect yes
nmcli con up eth0-static;nmcli con delete eth0

3.2 关闭防火墙与selinux

1
2
3
systemctl disable firewalld --now
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

3.3 修改主机名

1
hostnamectl set-hostname harbor

3.4 配置yum源

1
2
3
4
yum install -y yum-utils
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo

3.5 配置时间同步

1
2
3
4
yum install chrony -y
sed -i 's/^server.*//' /etc/chrony.conf
sed -i 's/# Please.*/server ntp.aliyun.com iburst/' /etc/chrony.conf
systemctl enable chronyd --now

3.6 修改内核参数

1
2
3
4
5
6
7
8
9
10
modprobe br_netfilter
echo 'modprobe br_netfilter' >> /etc/profile
cat > /etc/sysctl.d/k8s.conf<<END
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
END
sysctl -p /etc/sysctl.d/k8s.conf
chmod +x /etc/rc.d/rc.local
echo "sysctl -p /etc/sysctl.d/k8s.conf" >> /etc/rc.d/rc.local

3.7 修改host文件

1
2
3
4
5
6
7
8
9
10
11
cat > /etc/hosts<<END
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.106.11 master1
192.168.106.12 master2
192.168.106.13 master2
192.168.106.21 node1
192.168.106.22 node2
192.168.106.22 node3
192.168.106.30 harbor
END

3.8 安装docker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#安装基础软件包
yum install -y wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack


#安装docker-ce
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce -y
sudo mkdir -p /etc/docker
sudo mkdir -p /data/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"data-root":"/data/docker",
"registry-mirrors": ["https://oym4jkot.mirror.aliyuncs.com"],
"insecure-registries":["registry.access.redhat.com","quay.io","192.168.106.30"],
"bip":"172.106.30.1/24",
"live-restore":true
}
EOF
systemctl enable docker --now

4、为harbor签发证书

1
2
3
4
5
6
7
mkdir /data/ssl -p
cd /data/ssl/


#生成ca证书
openssl genrsa -out ca.key 3072
openssl req -new -x509 -days 3650 -key ca.key -out ca.pem

image-20230107195427407

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#生成域名的证书
openssl genrsa -out harbor.key 3072
openssl req -new -key harbor.key -out harbor.csr

Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:NJ
Locality Name (eg, city) [Default City]:NJ
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:harbor
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:


#签发证书
openssl x509 -req -in harbor.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out harbor.pem -days 3650


#查看证书是否有效
openssl x509 -noout -text -in harbor.pem

5、harbor安装

5.1 修改配置文件

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
mkdir /data/install -p
cd /data/install
tar xf harbor-offline-installer-v2.3.0-rc3.tgz
cd /data/install/harbor


[root@harbor harbor]# cat harbor.yml | egrep -v ^.*# | egrep -v "^$"
hostname: harbor #需要修改的地方
http:
port: 80
https:
port: 443
certificate: /data/ssl/harbor.pem #需要修改的地方
private_key: /data/ssl/harbor.key #需要修改的地方
harbor_admin_password: Harbor12345
database:
password: root123
max_idle_conns: 100
max_open_conns: 900
data_volume: /data
trivy:
ignore_unfixed: false
skip_update: false
insecure: false
jobservice:
max_job_workers: 10
notification:
webhook_job_max_retry: 10
chart:
absolute_url: disabled
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
_version: 2.3.0
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy

5.2 安装docker-compose

1
2
3
4
5
6
7
8
9
cat >  /etc/yum.repos.d/kubernetes.repo  <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
EOF

yum install docker-compose -y

5.3 导入镜像包

1
2
3
docker load -i docker-harbor-2-3-0.tar.gz
cd /data/install/harbor
./install

二、安装和配置ingress-Controller

1、Ingress介绍

Ingress官网定义:Ingress可以把进入到集群内部的请求转发到集群中的一些服务上,从而可以把服务映射到集群外部。Ingress 能把集群内Service 配置成外网能够访问的 URL,流量负载均衡,提供基于域名访问的虚拟主机等。

Ingress简单的理解就是你原来需要改Nginx配置,然后配置各种域名对应哪个 Service,现在把这个动作抽象出来,变成一个 Ingress 对象,你可以用 yaml 创建,每次不要去改Nginx 了,直接改yaml然后创建/更新就行了;那么问题来了:”Nginx 该怎么处理?”

Ingress Controller 这东西就是解决 “Nginx 的处理方式” 的;Ingress Controller 通过与 Kubernetes API 交互,动态的去感知集群中Ingress规则变化,然后读取它,按照他自己模板生成一段 Nginx 配置,再写到 Nginx Pod 里,最后 reload 一下 。

2、Ingress Controller介绍

Ingress Controller是一个七层负载均衡调度器,客户端的请求先到达这个七层负载均衡调度器,由七层负载均衡器在反向代理到后端pod,常见的七层负载均衡器有nginx、traefik,以我们熟悉的nginx为例,假如请求到达nginx,会通过upstream反向代理到后端pod应用,但是后端pod的ip地址是一直在变化的,因此在后端pod前需要加一个service,这个service只是起到分组的作用,那么我们upstream只需要填写service地址即可。

使用七层负载均衡调度器ingress controller时,当客户端访问kubernetes集群内部的应用时,数据包走向如下图流程所示:

image-20230110085638622

Ingress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API 交互,实时获取后端Service、Pod的变化,比如新增、删除等,结合Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 或者trafik负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。

Ingress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的 Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。

3、使用Ingress Controller代理k8s内部应用的流程

(1)部署Ingress controller,我们ingress controller使用的是nginx

(2)创建Pod应用,可以通过控制器创建pod

(3)创建Service,用来分组pod

(4)创建Ingress http,测试通过http访问应用

(5)创建Ingress https,测试通过https访问应用

4、安装Nginx Ingress Controller

4.1 导入镜像

Ingress-controller官网:

1
https://github.com/kubernetes/ingress-nginx/
1
2
3
4
5
6
7
8
9
10
11
docker load -i ingress-nginx-controllerv1.1.1.tar.gz 
docker load -i kube-webhook-certgen-v1.1.1.tar.gz

kubectl create clusterrolebinding clusterrolebinding-user-3 --clusterrole=cluster-admin --user=system:serviceaccount:ingress-nginx:ingress-nginx

#查看ingress-controller
[root@master1 ingress]# kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-9cgzz 0/1 Completed 0 58m
ingress-nginx-admission-patch-p2tjm 0/1 Completed 0 58m
ingress-nginx-controller-7bdc767c4c-dx99h 1/1 Running 0 58m

5、测试ingress HTTP代理tomcat

5.1 部署tomcat后端

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
[root@master1 ingress]# cat ingress-demo.yaml 
apiVersion: v1
kind: Service
metadata:
name: tomcat
namespace: default
spec:
selector:
app: tomcat
release: canary
ports:
- name: http
targetPort: 8080
port: 8080
- name: ajp
targetPort: 8009
port: 8009
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: tomcat
release: canary
template:
metadata:
labels:
app: tomcat
release: canary
spec:
containers:
- name: tomcat
image: tomcat:8.5.34-jre8-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
name: ajp
containerPort: 8009

5.2 部署ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@master1 ingress]# cat ingress-myapp.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-myapp
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: tomcat.lucky.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tomcat
port:
number: 8080

5.3 测试部署是否成功

1
2
3
4
5
[root@master1 ingress]# curl tomcat.lucky.com -I 
HTTP/1.1 200
Date: Tue, 10 Jan 2023 11:32:48 GMT
Content-Type: text/html;charset=UTF-8
Connection: keep-alive

6、测试ingress HTTPS代理tomcat

6.1 构建TLS站点

1
2
3
4
5
6
7
8
9
10
11
12
13
#准备证书文件
openssl genrsa -out tls.key 2048


openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Beijing/L=Beijing/O=DevOps/CN=tomcat.lucky.com


kubectl create secret tls tomcat-ingress-secret --cert=tls.crt --key=tls.key


#查看生成的secret
[root@master1 ingress]# kubectl get secret | grep tomcat-ingress-secret
tomcat-ingress-secret kubernetes.io/tls 2 61s

6.2 创建ingress

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@master1 ingress]# cat ingress-tomcat-tls.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tomcat-tls
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- hosts:
- tomcat.lucky.com
secretName: tomcat-ingress-secret
rules:
- host: tomcat.lucky.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: tomcat
port:
number: 8080

三、微服务介绍

1、什么是微服务

微服务是用于构建应用程序的架构风格,一个大的系统可由一个或者多个微服务组成,微服务架构可将应用拆分成多个核心功能,每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作和出现故障的时候不会相互影响。

2、大型电商平台的微服务功能图

image-20230110230315385

总结: 微服务架构是把一个大的系统按照不同的业务单元分解成多个职责单一的小系统,并利用简单的方法使多个小系统相互协作,组合成一个大系统,各个小的系统是独立部署的,它们之间是松耦合的。

3、为什么要用微服务

3.1 单体架构扩展性差、维护成本高、不可靠

image-20230110230523621

在单体架构下修改代码,需要把整个代码重新编译,重新部署,这个时间周期会很长;

单体架构下的所有代码模块都耦合在一起,代码量大,维护困难,想要更新一个模块的代码,也可能会影响其他模块,不能很好的定制化代码。

所有模块都用同一个数据库,存储方式比较单一。

微服务中可以有java编写、有Python编写的,他们都是靠restful架构风格统一成一个系统的,所以微服务本身与具体技术无关、扩展性强

4、 微服务的特性

1)灵活部署、独立扩展

传统的单体架构是以整个系统为单位进行部署,而微服务则是以每一个独立组件(例如订单服务,商品服务)为单位进行部署。

2)资源的有效隔离

每一个微服务拥有独立的数据源,假如微服务A想要读写微服务B的数据库,只能调用微服务B对外暴露的接口来完成。这样有效避免了服务之间争用数据库和缓存资源所带来的问题。另外微服务各模块部署在k8s中,可以进行CPU、内存等资源的限制和隔离。

3)高度可扩展性

随着某些服务模块的不断扩展,可以跨多个服务器和基础架构进行部署,充分满足业务需求。

4)易于部署

相对于传统的单体式应用,基于微服务的应用更加模块化且小巧,且易于部署。

5)服务组件化

在微服务架构中,需要我们对服务进行组件化分解,服务是一种进程外的组件,它通过HTTP等通信协议进行协作,而不是像传统组件那样镶入式的方式协同工作,每一个服务都独立开发、部署、可以有效避免一个服务的修改引起整个系统的重新部署。

6)去中心化治理

在整个微服务架构,通过采用轻量级的契约定义接口,使得我们对服务本身的具体技术平台不再那么敏感,这样整个微服务架构系统中的各个组件就能针对不同的业务特点选择不同的技术平台。

7)容错设计

在微服务架构中,快速检测出故障源并尽可能地自动恢复服务是必须被设计考虑的,通常我们都希望在每个服务中实现监控和日志记录。比如对服务状态、断路器状态、吞吐量、网络延迟等关键数据进行可视化展示。

8)技术栈不受限

在微服务架构中,可以结合项目业务及团队的特点,合理地选择技术栈。

9)局部修改容易部署

单体应用只要有修改,就得重新部署整个应用,微服务解决了这样的问题。

10)易于开发和维护

一个微服务只会关注一个特定的业务功能,所以它业务清晰,代码量较少。

5、什么样的项目适合使用微服务?

在复杂度比较低的项目中,单体架构就可以满足需求,而且部署效率也会比较高,在复杂度比较高的项目中,单体架构就不能满足了,需要进行微服务化。

微服务可以按照业务功能本身的独立性来划分,如果系统提供的业务是非常底层的,如:操作系统内核、存储系统、网络系统、数据库系统等,这类系统都偏底层,功能和功能之间有着紧密的配合关系,如果强制拆分为较小的服务单元,会让集成工作量急剧上升,并且这种人为的切割无法带来业务上的真正的隔离,所以无法做到独立部署和运行,也就不适合做成微服务了。

\1. 业务并发量大,项目复杂,访问流量高,为了将来更好的扩展,随时对代码更新维护,可以使用微服务

\2. 代码依赖程度高,想要解耦合,交给多个开发团队维护

\3. 业务初期,服务器数量少,可以使用微服务,能有效节省资源。

\4. 从思想上: 对未来有清晰的认识,对技术更新要保持着一种自信,超前思维,知道这个东西在将来肯定会发展起来。

这就告诉了我们一个道理,在学习技术的时候,适合自己的才是最好的,比方说很多人说我们公司单体架构用的也挺好的啊,为什么还要用微服务,其实他们再用单体可能适合他们业务需求,但是我们公司可能业务规模大,项目复杂,我就想要用微服务,或者我们在未来上有更大的远见,那我也会选择用微服务,不要说看别人用,我也用,而是我用是符合我们实际需求的,一切脱离实际业务的微服务都是耍流氓。

6、使用微服务需要考虑的问题

6.1 统一的配置管理中心

服务拆分以后,服务的数量非常多,如果所有的配置都以配置文件的方式放在应用本地的话,非常难以管理,可以想象当有几百上千个进程中有一个配置出现了问题,是很难将它找出来的,因而需要有统一的配置中心,来管理所有的配置,进行统一的配置下发。

在微服务中,配置往往分为几类,一类是几乎不变的配置,这种配置可以直接打在容器镜像里面,第二类是启动时就会确定的配置,这种配置往往通过环境变量,在容器启动的时候传进去,第三类就是统一的配置,需要通过配置中心进行下发,例如在大促的情况下,有些功能需要降级,哪些功能可以降级,哪些功能不能降级,都可以在配置文件中统一配置。

6.2 全链路监控

1)链路和应用的监控

监控系统和服务的健康状态和性能瓶颈,当系统出现异常的时候,监控系统可以配合告警系统,及时的发现,通知,干预,从而保障系统地顺利运行。

2)调用关系的监控

对代码调用关系进行监控

6.3 日志收集

业务层面、代码层面、系统层面

7、常见的微服务框架

7.1 第一代微服务框架 SpringCloud

SpringCloud为开发者提供了快速构建分布式系统的通用模型的工具(包括配置管理、服务发现注册、熔断器、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态、负载均衡、数据监控等)

7.2 第二代微服务框架 dubbo

dubbo是一个阿里巴巴开源出来的一个分布式框架、致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案

7.3 第三代微服务框架 ServiceMesh、k8s

istio是开源的ServiceMesh(服务网格),ServiceMesh翻译成中文就是服务网格

8、对不同的微服务框架进行对比分析

8.1 SpringCloud

来源于SpringSource,具有Spring社区的强大背景支持,还有Netflix强大的后盾与技术输出。

Netflix作为一家成功时间微服务架构的互联网公司,在几年就把几乎整个微服务框架开源贡献给了社区,这些框架开源的整套微服务架构套件是SpringCloud的核心。

Eureka:服务注册发现框架

Zuul:服务网关

Karyon: 服务端框架

Ribbon:客户端框架

Hystrix: 服务容错组件

Archaius: 服务配置组件

Servo:Metriics组件

Blitz4j:日志组件

Pinpoint:全链路监控组件

8.2 Dubbo

Dubbo是一个分布式的框架,是国内互联网公司开源做的比较不错的阿里开放的微服务化治理框架,致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。其核心部分包含(官网):

远程通讯:提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。

集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。

自动发现:基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑的增加或者减少机器。

Dubbo也是采用全Spring的配置方式,透明化接入应用,对应用没有任何的API侵入,只需要用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。当然也支持官方不推荐的API调用方式。

8.3 k8s、istio

作为用于微服务服务聚合层管理的新锐项目,是Google、IBM、Lyft(海外共享出行公司、Uber劲敌)首个共同联合开源的项目,提供了统一的连接,安全,管理和监控微服务的方案。

目前是针对Kubernetes环境的,社区宣称在未来几个月内会为虚拟机和Cloud Foundry 等其他环境增加支持。istio将流量管理添加到微服务中,并为增值功能(如安全性、监控、路由、连接管理和策略)创造的基础。

HTTP、gRPC和TCP网络流量的自动负载均衡

提供了丰富的路由规则,实现细粒度的网络流量行为控制

流量加密、服务间认证、以及强身份声明

全范围(Fleet-wide)的策略执行

深度遥测和报告

8.4 开源社区活跃度对比

SpringCloud:github–>所有项目均更新于(一小时)内

Dubbo:github–>核心项目最近更新于(一个月或数月)前

istio:github–>所有项目均更新于(30分钟)内

在社区活跃度上Istio>SpringCloud>Dubbo,综合稳定性来看,对于使用Java开发业务较多的企业,SpringCloud是相对更优的选择,对于更多企业来说,与语言几乎无绑定的Istio也是可以期待一下的。

总结:结合项目背景、提供功能、社区更新活跃度,SpringClouud是目前阶段发展最早的微服务框架方案,IIstio作为Kubernetes的优先支持来讲,也是一个值得关注的方案,而且发展潜力巨大,相信不久的将来百分之90的k8s用户都会使用iistio。目前对比来看,dubbo则显得稍逊色下来。

四、SpringCloud概述

image-20230111155101267

1、SpringCloud是什么

SpringCloud是一系列框架的有序结合。它利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到意见启动和部署。SpringCloud并没有重复造轮子,它只是将各家公司开发的比较成熟的、经得起考验的服务框架结合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和以维护的分布式系统开发工具包。

2、SpringCloud和SpringBoot什么关系

SpringBoot专注于快速方便的开发单个个体微服务

SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,SpringBoot可以离开SpringCloud独立开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系。

3、SpringCloud优缺点

1)SpringCloud来源于Spring,质量、稳定性、持续性都可以得到保证。

SpringCloud以SpringBoot为基础开发框架,可以给开发者大量的微服务开发经验,例如,只要极少量的标签,你就可以创建一个配置服务器,再加上一些标签,你就可以得到一个客户端库来配置你的服务,更加便于业务的落地。

2)SpringCloud是Java领域最适合做微服务的框架,对Java开发者来说很容易进行开发。

3)耦合度低,不影响其他模块

4)多个开发团队可以并行开发项目,提高开发效率

5)直接写自己的代码即可,然后暴漏接口,通过组件进行服务通信。

缺点:

只能针对Java进行开发

部署麻烦、组件多

每个微服务都可以用一个数据库,导致数据管理复杂

一套完整的微服务包括自动化部署,调度,资源管理,进程隔离,自愈,构建流水线功能,单靠SpringCloud是无法进行实现的,所以Spring+K8s才是最好的方案

4、为何要将SpringCloud项目部署到k8s平台

image-20230111161222377

SpringCloud只能用在SpringBoot的Java环境中,而kubernetes可以适用于任何开发语言,只要能被放进docker的应用,都可以在kubernetes上运行,而且更轻量、更简单。

每个微服务可以部署多个,没有多少依赖,并且有负载均衡能力,比如一个服务部署一个副本或五个副本,通过k8s可以更好地去扩展我们的应用。

Spring提供应用的打包,Docker和Kubernetes提供部署和调度。Spring通过Hystrix线程池提供应用内的隔离,而Kubernetes通过资源,进程和命名空间来提供隔离。Spring为每个微服务提供健康终端,而Kubernetes执行健康检查,且把流量导到健康服务。Spring外部化配置并更新它们,而Kubernetes分发配置到每个微服务。

SpringCloud很多功能都跟Kunernetes重合,比如服务发现、负载均衡、配置管理,所以如果把SpringCloud部署到k8s,那么很多功能就可以直接使用k8s原生的,减少复杂度。

SpringCloud容易上手,是对开发者比较友好的平台;Kubernetes是可以实现DevOps流程的,SpringCloud和kubernetes各有优点,只要结合起来,才能发挥更大的作用,达到最佳的效果。

5、SpringCloud项目部署到k8s的流程

制作镜像–>控制管理pod–>暴漏应用–>对外发布应用–>数据持久化–>日志/监控

1、制作镜像:应用程序、运行环境、文件系统

2、控制管理pod:deployment无状态部署、statefulset有状态部署、Daemonset守护进程部署、Job&cronjob部署

3、暴露应用:服务发现、负载均衡

4、对外发布应用:service、Ingress HTTP/HTTPS访问

5、pod 数据持久化:分布式存储 ceph和 gluster

6、日志/监控:efk、prometheus、pinpoint等

五、SpringCloud组件介绍

1、服务发现与注册组件Eureka

Eureka是Netflix开发的服务发现框架, SpringCloud将它集成在自己的子项目spring-cloud-netflix中,以实现SpringCloud中服务发现和注册功能。Eureka包含两个组件:Eureka Server和Eureka Client。

Netflix是什么?

Netflix在SpringCloud项目中占着重要的作用,Netflix公司提供了包括Eureka、Hystrix、Zuul、Archaius等在内的很多组件,在微服务架构中至关重要。

服务发现与注册

我们在买车的时候,需要找中介,如果不找中介,我们自己去找厂商或者个人车主,这是很麻烦的,也很浪费时间,所以为了方便,我们一般去找中介公司,把我们的需求说出来,他们就会按需给我们推荐车型,我们相当于微服务架构中的消费者Consumer,中介相当于微服务架构中的提供者Provider,Consumer需要调用Provider提供的一些服务,就像是我们要买的车一样。

1.1 Eureka组件

Eureka Server

Eureka Server提供服务注册中心,各个节点启动后,会将自己的IP和端口等网络信息注册到Eureka Server中,这样Eureka Server服务注册表中将会存储所有可用服务节点的信息,在Eureka的图形化界面可以看到所有注册的节点信息。

Eureka Client

Eureka Client是一个java客户端,在应用启动后,Eureka客户端将会向Eureka Server端发送心跳,默认周期是30s,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个**服务节点移除(默认90秒)**。

Eureka Client分为两个角色,分别是Application Service和Application Client

Application Service是服务提供方,是注册到Eureka Server中的服务。

Application Client是服务消费方,通过Eureka Server发现其他服务并消费

image-20230111223415343

Register(服务注册):当Eureka客户端向Eureka Server注册时,会把自己的IP、端口、运行状况等信息注册给Eureka Server。

Renew(服务续约):Eureka客户端会每隔30s发送一次心跳来续约,通过续约来告诉Eureka Server自己正常,没有出现问题。正常情况下,如果 Eureka Server 在90秒没有收到 Eureka 客户的续约,它会将实例从其注册表中删除。

Cancel(服务下线):Eureka客户端在程序关闭时向Eureka服务器发送取消请求。 发送请求后,该客户端实例信息将从服务器的实例注册表中删除,防止consumer调用到不存在的服务。该下线请求不会自动完成,它需要调用以下内容:DiscoveryManager.getInstance().shutdownComponent();

Get Registry(获取服务注册列表):获取其他服务列表。
Replicate(集群中数据同步):eureka集群中的数据复制与同步。
Make Remote Call(远程调用):完成服务的远程调用。

2、客户端负载均衡之Ribbon

2.1 Ribbon简介

Ribbon是一个基于HTTP和TCP的客户端负载均衡器,主要提供客户侧的软件负载均衡算法,运行在消费者端。客户端负载均衡是当浏览器向后台发出请求的时候,客户端会向Eureka Server读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略,抉择出向哪台服务器发送请求。在客户端就进行负载均衡算法分配。Ribbon客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。下面是用到的

一些负载均衡策略:

随机策略—随机选择server

轮询策略-–轮询选择, 轮询index,选择index对应位置的Server

重试策略–在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server

最低并发策略–逐个考察server,如果server断路器打开,则忽略,再选择其中并发链接最低的server

可用过滤策略–过滤掉一直失败并被标记为circuit tripped的server,过滤掉那些高并发链接的server(active connections超过配置的阈值)或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个Server的运行状态;

响应时间加权重策略--根据server的响应时间分配权重,响应时间越长,权重越低,被选择到的概率也就越低。响应时间越短,权重越高,被选中的概率越高,这个策略很贴切,综合了各种因素,比如:网络,磁盘,io等,都直接影响响应时间;

区域权重策略–综合判断server所在区域的性能,和server的可用性,轮询选择server并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server。

举个列子说明ribbon

比如我们设计了一个秒杀系统,但是为了整个系统的 高可用 ,我们需要将这个系统做一个集群,而这个时候我们消费者就可以拥有多个秒杀系统的调用途径了,如下图。

image-20230111224525493

如果这个时候我们没有进行一些 均衡操作 ,如果我们对 秒杀系统1 进行大量的调用,而另外两个基本不请求,就会导致 秒杀系统1 崩溃,而另外两个就变成了傀儡,那么我们为什么还要做集群,我们高可用体现的意义又在哪呢?

所以 Ribbon 出现了,注意我们上面加粗的几个字——运行在消费者端 。指的是,Ribbon 是运行在消费者端的负载均衡器,如下图。

image-20230111224714659

其工作原理就是 Consumer 端获取到了所有的服务列表之后,在其内部 使用负载均衡算法 ,进行对多个系统的调用。

2.2 Ribbon的功能

易于与服务发现组件(比如Eureka)集成

使用Archaius完成运行时配置

使用JMX暴露运维指标,使用Servo发布

多种可插拔的序列化选择

异步和批处理操作

自动SLA框架

系统管理/指标控制台

2.3 Ribbon与 nginx对比分析

区别:

Ribbon实现的是客户端负载均衡,它可以在客户端经过一系列算法来均衡调用服务。Ribbon 工作时分两步:

第一步:从Eureka Server中获取服务注册信息列表,它优先选择在同一个 Zone 且负载较少的 Server。

第二步:根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址,其中Ribbon提供了多种策略,例如轮询、随机等。

image-20230111225114721

Nginx是服务器端负载均衡,所有请求统一交给nginx,由nginx实现负载均衡请求转发,属于服务器端负载均衡。

image-20230111225150166

3、服务网关zuul

Zuul是SpringCloud中的微服务网关,首先是一个微服务。也是会在Eureka注册中心中进行服务的注册和发现。也是一个网关,请求应该通过Zuul来进行路由。Zuul网关不是必要的,是推荐使用的。

互动:网关是什么?

是一个网络整体系统中的前置门户入口。请求首先通过网关,进行路径的路由,定位到具体的服务节点上。

Zuul网关的作用:

统一入口:为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性。

鉴权校验:识别每个请求的权限,拒绝不符合要求的请求。

动态路由:动态的将请求路由到不同的后端集群中。

减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射。

image-20230111225738837

4、熔断器Hystrix

Hystrix的中文名字是“豪猪”,豪猪是满身长满了刺,能够保护自己不受天敌的伤害,代表了一种防御机制,Hystrix在SpringCloud中负责服务熔断和服务降级的作用。

什么是服务熔断?(熔断可以保护服务):

在讲熔断之前先看个概念: 服务雪崩

假设有A、B、C三个服务,服务A调用服务B和C,链路关系如下:

image-20230111225923659

假设服务C因为请求量大,扛不住请求,变得不可用,这样就是积累大量的请求,服务B的请求也会阻塞,会逐渐耗尽线程资源,使得服务B变得不可用,那么服务A在调用服务B就会出现问题,导致服务A也不可用,那么整条链路的服务调用都失败了,我们称之为雪崩。

接下来看下服务熔断:

举个生活中的例子

当电路发生故障或异常时,伴随着电流不断升高,并且升高的电流有可能能损坏电路中的某些重要器件,也有可能烧毁电路甚至造成火灾。若电路中正确地安置了保险丝,那么保险丝就会在电流异常升高到一定的高度和热度的时候,自身熔断切断电流,从而起到保护电路安全运行的作用。

在微服务架构中,在高并发情况下,如果请求数量达到一定极限(可以自己设置阈值),超出了设置的阈值,Hystrix会自动开启服务保护功能,然后通过服务降级的方式返回一个友好的提示给客户端。假设当10个请求中,有10%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到10s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。

服务降级(提高用户体验效果):

在高并发的场景下,当服务器的压力剧增时,根据当前业务以及流量的情况,对一些服务和页面进行策略控制,对这些请求做简单的处理或者不处理,来释放服务器资源用以保证核心业务不受影响,确保业务可以正常对外提供服务,比如电商平台,在针对618、双11的时候会有一些秒杀场景,秒杀的时候请求量大,可能会返回报错标志“当前请求人数多,请稍后重试”等,如果使用服务降级,无法提供服务的时候,消费者会调用降级的操作,返回服务不可用等信息,或者返回提前准备好的静态页面写好的信息。

5、API网关Springcloud Gateway

为什么学习了网关Zuul,又要讲Spring Cloud Gateway呢?

原因很简单,就是Spring Cloud已经放弃Zuul了。现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是基于过滤器的,是阻塞IO,不支持长连接,spring官网上也已经没有zuul的组件了,所以给大家讲下SpringCloud原生的网关产品Gateway。

Spring Cloud Gateway是Spring Cloud新推出的网关框架,之前是 Netflix Zuul,由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技术开发的网关,该项目提供了一个构建在Spring Ecosystem之上的API网关,旨在提供一种简单而有效的途径来发送API,并向他们提供交叉关注点,例如:安全性,监控/指标和弹性.

SpringCloud Gateway 特征:

SpringCloud官方对SpringCloud Gateway 特征介绍如下:

(1)集成 Hystrix 断路器

(2)集成 Spring Cloud DiscoveryClient

(3)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters

(4)具备一些网关的高级功能:动态路由、限流、路径重写

从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。

简单说明一下上文中的三个术语:

1)Filter(过滤器):

和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

2)Route(路由):

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。

3)Predicate(断言):

这是一个Java8的Predicate,可以使用它来匹配来自HTTP请求的任何内容,例如headers或参数。断言的输入类型是一个ServerWebExchange。

6、配置中心SprigCloud Config

SpringCloud Config是一个解决分布式系统的配置管理方案,它包含了server和client 两个部分。 server 用来获取远程的配置信息(默认为 Git 仓库),并且以接口的形式提供出去,client 根据 server 提供的接口读取配置文件,以便于初始化自己的应用。如果配置中心出现了问题,将导致灾难性的后果,因此在生产环境下配置中心都会做集群,来保证高可用。此处配置高可用实际就是把多个配置中心(指定同一个 Git 远程仓库)注册到注册中心。

7、将SpringCloud项目部署到K8S平台的注意事项

1、如何进行服务发现?

2、如何进行配置管理?

3、如何进行负载均衡?

4、如何访问k8s中的服务?

5、如何通过k8s进行服务的编排

6、k8s部署Spring Cloud项目的整体发布流程

7.1 如何进行服务发现

可以通过SpringCloud中的Eureka,也可以通过k8s自身的coreDNS。如果是把SpringCloud项目迁移到k8s,可以使用原来的Eureka,这样可以避免开发人员对原来的代码进行大量的修改。通常情况下,我们的线上的服务在迁移到k8s环境下的时候,都是采用平滑迁移的方案。服务治理与注册中心等都是采用原先的组件。比如SpringCloud应用,在k8s环境下还是用原来的一套注册中心(如eureka),服务器治理(hystrix,ribbon)。

使用Kubernetes service发现pod:

Kubernetes中的pod是有生命周期的,可以被创建、也可以被销毁,k8s中的pod可以有多组,每组pod可以称为一个微服务,那么怎么能让这些微服务相互访问呢?需要在每组pod前端有一个固定的接入层,叫做service,service解决了对后端pod进行负载均衡和自动发现的能力,但是我们怎么还需要知道service的ip,这样才能被其他服务访问,那么怎么解决这一问题呢?

使用coreDNS发现service(服务):

coredns可以解决service的发现问题,k8s将service的名称当作域名注册到coredns中,通过service的名称就可以访问其提供的服务。coredns支持的格式:

<service.name>..svc.<cluster.domain>

默认的域名是<service.name>..svc.cluster.local

7.2 如何进行配置管理

通过k8s中部署SpringCloud Config,也可以通过k8s自带的configmap。还可以使用srping-cloud-kubernetes进行配置管理。

如果微服务架构中没有使用统一配置中心时,所存在问题:

配置文件分散在各个项目里面,不方便维护

配置内容安全与权限,实际开发中,开发人员是不知道线上环境的配置的

更新配置后,项目需要重启

k8s中自带的configmap怎么存配置?

ConfigMap用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。

ConfigMap跟secret很类似,但它可以更方便地处理不包含敏感信息的字符串

怎么通过ConfigMap达到配置中心的作用?

创建一个configmap资源,对应着一份配置文件,可以将该资源通过数据卷的形式映射到Pod上,这样Pod就能用上这个配置文件了,以管理mysql配置文件为例用下图演示:

image-20230112104849239

Spring-cloud-starter-kubernetes-config

spring-cloud-starter-kubernetes-config是spring-cloud-starter-kubernetes框架下的一个库,作用是将kubernetes的configmap与SpringCloud Config结合起来,通过spring-cloud-starter-kubernetes-config,我们的应用就像在通过SpringCloud Config取得配置信息,只不过这里的配置信息来自kubernetes的configmap,而不是SpringCloud Config server,SpringCloud Config来配置的应用几乎不用修改代码,仅仅调整了配置和依赖,就能顺利迁移到kubernetes之上,直接使用原生的配置服务,并且SpringCloud Config Server也可以不用在kubernetes上部署了。

7.3 如何进行负载均衡

通过springcloud的Ribbon,也可以通过k8s的service、ingress Controller

7.4 如何对外发布应用

通过ingress

image-20230112105956863

如何通过k8s进行服务编排?

通过编写yaml文件,对每个微服务进行发布

7.5 k8s部署Spring Cloud项目的整体发布流程

image-20230112110236171

开发代码->提交代码到代码仓库->Jenkins调k8s API->动态生成Jenkins Slave Pod->Slave Pod拉取git上的代码->编译代码->打包镜像->推送镜像到镜像仓库harbor或者docker hub->Slave Pod工作完成之后自动删除->通过k8s编排服务发布到测试、生产平台->通过Ingress发布服务

7.6 如何通过k8s进行服务编排

事先写好资源清单文件,然后放到gitlab,我们在调用jenkins的时候,通过pipeline里写上kubectl apply 更新yaml文件,就可以实现自动编排了。

六、安装和配置数据存储仓库MySQL

1.MySQL简介

2.MySQL特点

3.安装和配置MySQL

4.在MySQL数据库导入数据

5.对MySQL数据库进行授权

1、MySQL简介

MySQL 是一款安全、跨平台、高效的,并与PHP、Java等主流编程语言紧密结合的数据库系统。该数据库系统是由瑞典的MySQL AB公司开发、发布并支持,由 MySQL的初始开发人员 David Axmark 和 Michael Monty Widenius 于 1995 年建立的。MySQL 的象征符号是一只名为 Sakila 的海豚,代表着 MySQL 数据库的速度、能力、精确和优秀本质。

目前 MySQL 被广泛地应用在 Internet 上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,使得很多公司都采用 MySQL 数据库以降低成本。

MySQL 数据库可以称得上是目前运行速度最快的SQL语言数据库之一。除了具有许多其他数据库所不具备的功能外,MySQL 数据库还是一种完全免费的产品,用户可以直接通过网络下载 MySQL 数据库,而不必支付任何费用。

2、MySQL特点

1) 功能强大

MySQL 中提供了多种数据库存储引擎,各引擎各有所长,适用于不同的应用场合,用户可以选择最合适的引擎以得到最高性能,可以处理每天访问量超过数亿的高强度的搜索 Web 站点。MySQL5 支持事务、视图、存储过程、触发器等。

2) 支持跨平台

MySQL 支持至少 20 种以上的开发平台,包括 Linux、Windows、FreeBSD 、IBMAIX、AIX、FreeBSD 等。这使得在任何平台下编写的程序都可以进行移植,而不需要对程序做任何的修改。

3) 运行速度快

高速是 MySQL 的显著特性。在 MySQL 中,使用了极快的 B 树磁盘表(MyISAM)和索引压缩;通过使用优化的单扫描多连接,能够极快地实现连接;SQL 函数使用高度优化的类库实现,运行速度极快。

4) 支持面向对象

PHP 支持混合编程方式。编程方式可分为纯粹面向对象、纯粹面向过程、面句对象与面向过程混合 3 种方式。

5) 安全性高

灵活和安全的权限与密码系统,允许基本主机的验证。连接到服务器时,所有的密码传输均采用加密形式,从而保证了密码的安全。

6) 成本低

MySQL 数据库是一种完全免费的产品,用户可以直接通过网络下载。

7) 支持各种开发语言

MySQL 为各种流行的程序设计语言提供支持,为它们提供了很多的 API 函数,包括 PHP、ASP.NET、Java、Eiffel、Python、Ruby、Tcl、C、C++、Perl 语言等。

8) 数据库存储容量大

MySQL 数据库的最大有效表尺寸通常是由操作系统对文件大小的限制决定的,而不是由 MySQL 内部限制决定的。InnoDB 存储引擎将 InnoDB 表保存在一个表空间内,该表空间可由数个文件创建,表空间的最大容量为 64TB,可以轻松处理拥有上千万条记录的大型数据库。

9) 支持强大的内置函数

PHP 中提供了大量内置函数,几乎涵盖了 Web 应用开发中的所有功能。它内置了数据库连接、文件上传等功能,MySQL 支持大量的扩展库,如 MySQLi 等,可以为快速开发 Web 应用提供便利。

3、安装MySQL

1
2
3
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
rpm -ivh mysql-community-release-el7-5.noarch.rpm
yum install mysql-server -y

3.1 权限设置

1
chown mysql:mysql -R /var/lib/mysql

3.2 初始化MySQL

1
mysqld --initialize/mysql_secure_installation

3.3 启动MySQL

1
systemctl enable mysqld --now

3.4 设置密码

1
mysqladmin -u root password "111111"

3.5 测试登录数据库

1
mysql -uroot -p111111

3.6 创建数据库tb_order、tb_product、tb_stock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
create database tb_order;
create database tb_product;
create database tb_stock;


#查看是否创建成功
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| tb_order |
| tb_product |
| tb_stock |
+--------------------+
6 rows in set (0.00 sec)

4、在Mysql数据库中导入数据

把相应的sql语句上传到mysql机器的root目录下,sql文件分别是order.sql、product.sql、stock.sql,这些文件在课件里大家可以搜索,会搜索到,按如下方法导入:

1
2
3
4
5
6
7
8
9
10
use tb_order
source /root/order.sql


use tb_stock
source /root/stock.sql


use tb_product
source /root/product.sql

5、对MySQL数据库授权

1
2
grant all on *.* to 'root'@'%' identified by '111111';
flush privileges;

七、将SpringCloud微服务项目部署到K8S平台

1、SpringCloud的微服务电商框架

image-20230112232442951

2、安装openjdk和maven

1
yum install java-1.8.0-openjdk  maven-3.0.5* -y

3、上传微服务源码包到K8S的控制节点上

1
2
unzip microservic-test.zip
cd microservic-test

4、修改源代码,更改数据库连接地址

4.1 修改库存数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master1 ~]# cat   /root/microservic-test/stock-service/stock-service-biz/src/main/resources/application-fat.yml
spring:
datasource:
url: jdbc:mysql://192.168.106.12:3306/tb_stock?characterEncoding=utf-8
username: root
password: 111111
driver-class-name: com.mysql.jdbc.Driver

eureka:
instance:
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka-0.eureka.ms:8888/eureka,http://eureka-1.eureka.ms:8888/eureka,http://eureka-2.eureka.ms:8888/eureka

4.2 修改产品数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master1 ~]# cat   /root/microservic-test/product-service/product-service-biz/src/main/resources/application-fat.yml 
spring:
datasource:
url: jdbc:mysql://192.168.106.12:3306/tb_product?characterEncoding=utf-8
username: root
password: 111111
driver-class-name: com.mysql.jdbc.Driver

eureka:
instance:
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka-0.eureka.ms:8888/eureka,http://eureka-1.eureka.ms:8888/eureka,http://eureka-2.eureka.ms:8888/eureka

4.2 修改订单数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@master1 ~]# cat  /root/microservic-test/order-service/order-service-biz/src/main/resources/application-fat.yml
spring:
datasource:
url: jdbc:mysql://192.168.106.12:3306/tb_order?characterEncoding=utf-8
username: root
password: 111111
driver-class-name: com.mysql.jdbc.Driver

eureka:
instance:
prefer-ip-address: true
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka-0.eureka.ms:8888/eureka,http://eureka-1.eureka.ms:8888/eureka,http://eureka-2.eureka.ms:8888/eureka

5、通过maven编译、打包、构建源代码

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
[root@master1 ~]# cd microservic-test/
[root@master1 microservic-test]# mvn clean package -D maven.test.skip=true


[INFO] simple-microservice ............................... SUCCESS [5.519s]
[INFO] basic-common ...................................... SUCCESS [0.006s]
[INFO] basic-common-core ................................. SUCCESS [7:44.118s]
[INFO] gateway-service ................................... SUCCESS [2:27.665s]
[INFO] eureka-service .................................... SUCCESS [42.257s]
[INFO] product-service ................................... SUCCESS [0.006s]
[INFO] product-service-api ............................... SUCCESS [1.118s]
[INFO] stock-service ..................................... SUCCESS [0.003s]
[INFO] stock-service-api ................................. SUCCESS [1.267s]
[INFO] product-service-biz ............................... SUCCESS [17.198s]
[INFO] stock-service-biz ................................. SUCCESS [1.522s]
[INFO] order-service ..................................... SUCCESS [0.002s]
[INFO] order-service-api ................................. SUCCESS [1.242s]
[INFO] order-service-biz ................................. SUCCESS [1.678s]
[INFO] basic-common-bom .................................. SUCCESS [0.002s]
[INFO] portal-service .................................... SUCCESS [3.073s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12:17.705s
[INFO] Finished at: Mon Jan 16 20:28:39 CST 2023
[INFO] Final Memory: 72M/260M
[INFO] ------------------------------------------------------------------------

6、在k8s中部署Eureka组件

6.1 修改k8s的控制和工作节点的docker的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@master1 ~]# cat /etc/docker/daemon.json 
{
"data-root":"/data/docker",
"registry-mirrors": ["https://oym4jkot.mirror.aliyuncs.com"],
"insecure-registries":["registry.access.redhat.com","quay.io","192.168.106.30","harbor"],
"bip":"172.106.11.1/24",
"live-restore":true,
"exec-opts": ["native.cgroupdriver=systemd"]
}


#登录镜像仓库
[root@master1 ~]# docker login 192.168.106.30

6.2 创建拉取私有镜像仓库需要的secret

1
kubectl create ns ms && kubectl create secret docker-registry registry-pull-secret --docker-server=192.168.106.30 --docker-username=admin --docker-password=Harbor12345  -n ms

6.3 在harbor上创建一个项目microservice

image-20230116212904899

6.4 构建镜像

1
2
3
4
5
6
7
[root@master1 ~]# gg docker pull java:8-jdk-alpine
[root@master1 ~]# cd /root/microservic-test/eureka-service
[root@master1 eureka-service]# docker build -t 192.168.106.30/microservice/eureka:v1 .


#上传镜像仓库到harbor中
[root@master1 eureka-service]# docker push 192.168.106.30/microservice/eureka:v1

6.5 部署服务

更改eureka.yaml文件,把镜像变成image:192.168.106.30/microservice/eureka:v1

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
[root@master1 ~]# cd /root/microservic-test/k8s


[root@master1 k8s]# cat eureka.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: eureka
namespace: ms
annotations: #注解信息
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: eureka.ctnrs.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: eureka
port:
number: 8888
---
apiVersion: v1
kind: Service
metadata:
name: eureka
namespace: ms
spec:
clusterIP: None
ports:
- port: 8888
name: eureka
selector:
project: ms
app: eureka

---

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: eureka
namespace: ms
spec:
replicas: 3
selector:
matchLabels:
project: ms
app: eureka
serviceName: "eureka"
template:
metadata:
labels:
project: ms
app: eureka
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: eureka
image: 192.168.106.30/microservice/eureka:v1
ports:
- protocol: TCP
containerPort: 8888
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
requests:
cpu: 0.5
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
readinessProbe:
tcpSocket:
port: 8888
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8888
initialDelaySeconds: 60
periodSeconds: 10


[root@master1 k8s]# kubectl apply -f eureka.yaml

7、在k8s中部署Gateway服务

7.1 构建镜像

1
2
3
cd  microservic-test/gateway-service/
docker build -t 192.168.106.30/microservice/gateway:v1 .
docker push 192.168.106.30/microservice/gateway:v1

7.2 部署服务

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
79
80
81
82
83
84
cd /root/microservic-test/k8s/


[root@master1 k8s]# cat gateway.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gateway
namespace: ms
annotations: #注解信息
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: gateway.ctnrs.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gateway
port:
number: 9999
---
apiVersion: v1
kind: Service
metadata:
name: gateway
namespace: ms
spec:
ports:
- port: 9999
name: gateway
selector:
project: ms
app: gateway
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
namespace: ms
spec:
replicas: 1
selector:
matchLabels:
project: ms
app: gateway
template:
metadata:
labels:
project: ms
app: gateway
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: gateway
image: 192.168.106.30/microservice/gateway:v1
imagePullPolicy: Always
ports:
- protocol: TCP
containerPort: 9999
resources:
requests:
cpu: 0.5
memory: 256Mi
limits:
cpu: 1
memory: 1Gi
readinessProbe:
tcpSocket:
port: 9999
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 9999
initialDelaySeconds: 60
periodSeconds: 10


kubectl apply -f gateway.yaml

7.3 查看pod运行状态

1
2
[root@master1 k8s]# kubectl get pods -n ms| grep gateway
gateway-d586c5655-k8d74 1/1 Running 0 96s

8、在k8s中部署前端portal服务

8.1 构建镜像

1
2
3
cd /root/microservic-test/portal-service
docker build -t 192.168.106.30/microservice/portal:v1 .
docker push 192.168.106.30/microservice/portal:v1

8.2 部署服务

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
[root@master1 k8s]# cat portal.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal
namespace: ms
annotations: #注解信息
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: portal.ctnrs.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: portal
port:
number: 8080
---
apiVersion: v1
kind: Service
metadata:
name: portal
namespace: ms
spec:
ports:
- port: 8080
name: portal
selector:
project: ms
app: portal
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: portal
namespace: ms
spec:
replicas: 1
selector:
matchLabels:
project: ms
app: portal
template:
metadata:
labels:
project: ms
app: portal
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: portal
image: 192.168.106.30/microservice/portal:v1
imagePullPolicy: Always
ports:
- protocol: TCP
containerPort: 8080
resources:
limits:
cpu: 1
memory: 1Gi
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 60
periodSeconds: 10


kubectl apply -f portal.yaml

9、在k8s中部署订单order服务

9.1 构建镜像

1
2
3
cd  /root/microservic-test/order-service/order-service-biz
docker build -t 192.168.106.30/microservice/order:v1 .
docker push 192.168.106.30/microservice/order:v1

9.2 部署服务

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
[root@master1 k8s]# cat order.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order
namespace: ms
spec:
replicas: 1
selector:
matchLabels:
project: ms
app: order
template:
metadata:
labels:
project: ms
app: order
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: order
image: 192.168.106.30/microservice/order:v1
imagePullPolicy: Always
ports:
- protocol: TCP
containerPort: 8020
readinessProbe:
tcpSocket:
port: 8020
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8020
initialDelaySeconds: 60
periodSeconds: 10


kubectl apply -f order.yaml

10、在k8s中部署产品product服务

10.1 构建镜像

1
2
3
cd  /root/microservic-test/product-service/product-service-biz
docker build -t 192.168.106.30/microservice/product:v1 .
docker push 192.168.106.30/microservice/product:v1

10.2 部署服务

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
cd /root/microservic-test/k8s
[root@master1 k8s]# cat product.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: product
namespace: ms
spec:
replicas: 1
selector:
matchLabels:
project: ms
app: product
template:
metadata:
labels:
project: ms
app: product
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: product
image: 192.168.106.30/microservice/product:v1
imagePullPolicy: Always
ports:
- protocol: TCP
containerPort: 8010
resources:
limits:
cpu: 1
memory: 1Gi
readinessProbe:
tcpSocket:
port: 8010
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8010
initialDelaySeconds: 60
periodSeconds: 10


kubectl apply -f product.yaml

11、在k8s中部署库存stock服务

11.1 构建镜像

1
2
3
cd  /root/microservic-test/stock-service/stock-service-biz
docker build -t 192.168.106.30/microservice/stock:v1 .
docker push 192.168.106.30/microservice/stock:v1

11.2 部署服务

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
cd /root/microservic-test/k8s
[root@master1 k8s]# cat stock.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: stock
namespace: ms
spec:
replicas: 1
selector:
matchLabels:
project: ms
app: stock
template:
metadata:
labels:
project: ms
app: stock
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: stock
image: 192.168.106.30/microservice/stock:v1
imagePullPolicy: Always
ports:
- protocol: TCP
containerPort: 8030
resources:
limits:
cpu: 1
memory: 1Gi
readinessProbe:
tcpSocket:
port: 8030
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8030
initialDelaySeconds: 60
periodSeconds: 10


kubectl apply -f stock.yaml

上面都部署成功之后,在浏览器访问eureka.ctnrs.com可看到gateway、portal、product、order、stock等服务都已经注册到eureka了,在浏览器访问portal.ctnrs.com登陆前端页面,可看到如下内容:

image-20230118172247600

点击查询商品服务,出现如下:

image-20230118172256808

选择手机,点击购买,然后再点击查询订单服务,出现如下:

image-20230118172312577

12、微服务的扩容和缩容

12.1 扩容

修改yaml文件里的replicas数量,如原来是2,可以修改成3,然后通过kubectl apply 重新更新yaml即可

12.2 缩容

修改yaml文件里的replicas数量,如原来是3,可以修改成2,然后通过kubectl apply 重新更新yaml即可

12.3 发布流程

开发提交代码到gitlab->触发自动构建(通过mvn打包代码)->把代码打包成镜像->把镜像上传到私有镜像仓库>把新的镜像更新到对应服务的yaml文件里->然后kubectl apply更新yaml文件->发布服务


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!