Kubernetes部署SpringBoot前后端分离应用

文章详细描述了在MacOS环境中使用DockerDesktop和Kubernetes1.25.2部署MySQL、Redis、SpringBoot应用,并配置Ingress以暴露前端。涉及的内容包括创建PV和PVC、部署策略、服务配置以及Ingress的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0.前置知识

  • 了解docker的安装,docker desktop开启k8s,docker镜像制作
  • 了解kubernetes的基本使用命令和基本api资源的使用,推荐Kubernetes入门实战课
  • 了解ingress、ingress-controller、ingress-class的作用与关系,推荐这篇文章和这篇文档
  • 了解前后端分离,了解nginx配置,了解基本linux命令

1.任务描述

在单节点Kubernetes环境下部署Mysql和Redis,部署前后端分离单体应用,部署ingress暴露前端应用。

项目名:黑马点评

项目地址:https://gitee.com/huyi612

系统环境:macOS 13.2.1

Docker Desktop Version:4.15.0

Docker Engine Version: 20.10.21

Kubernetes Version:1.25.2

2. Kubernetes部署MySQL

使用deployment部署单节点mysql,选择mysql8.0版本;

(1).创建PersistentVolume,将数据持久化到宿主机;PV一般是运维工程师创建的,这里为了简便,选择本地存储。storageClassName: manual表示手动创建pv,实际生产环境可以设置其他的storageClassName对pv进行自动化管理。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: hm-pv
  labels:
    type: local
spec:
  storageClassName: manual
  capacity: 
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/Users/data/kdata1"

(2).创建PersistentVolumeClaim,绑定存储

apiVersion: v1
kind: PersistentVolumeClaim
metadata: 
  name: hm-mysql-pvc
  labels:
    type: local
    app: hmdp-mysql
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

(3).创建deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hmdp-mysql
  labels:
    app: hmdp-mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hmdp-mysql
  template:
    metadata:
      labels:
        app: hmdp-mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0.19
        ports:
        - containerPort: 3306
        env: # 设置环境变量,建议使用Secret
        - name: MYSQL_ROOT_PASSWORD
          value: "root"
        resources:
          limits:
            cpu: 2000m
            memory: 512Mi
          requests:
            cpu: 2000m
            memory: 512Mi
        args:
        - "--character-set-server=utf8mb4"
        - "--collation-server=utf8mb4_unicode_ci"
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
        - name: localtime
          readOnly: true
          mountPath: /etc/localtime
      volumes: 
      - name: data
        persistentVolumeClaim:
          claimName: hm-mysql-pvc
      - name: localtime
        hostPath:
          type: File
          path: /etc/localtime

(4).创建service

为了便于调试和使用Navcat进行操作,这里将svc以NodePort的形式暴露出去。

apiVersion: v1
kind: Service
metadata:
  name: hmdp-mysql-svc
  labels:
    app: hmdp-mysql
spec:
  ports:
  - port: 3306
    protocol: TCP
    targetPort: 3306
    nodePort: 30036 
  selector:
    app: hmdp-mysql
  type: NodePort

按顺序将上述资源部署,使用navcat连接数据库,注意端口号是是svc中设置的nodePort: 30036 ,随后创建数据库hmdp,导入hmdp.sql的表结构与数据。
Navcat连接截图如图所示:
在这里插入图片描述

3. Kubernetes部署Redis

使用deployment部署单节点redis,选择redis6.2.14版本;这里简单部署,没有使用pvc,也没有给redis设置密码;

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:6.2.14
        ports:
        - containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: redis
  labels:
    app: redis
spec:
  ports:
  - port: 6379
    protocol: TCP
    targetPort: 6379
    nodePort: 30079
  type: NodePort
  selector:
    app: redis

这里redis的Service中设置NodePort是为了便于调试,实际可以关闭。

4.Kubernetes部署SpringBoot项目

(1).对项目配置进行修改,将数据库url、数据库密码、redis缓存host等用${}表达式替代,便于镜像部署时使用环境变量进行替换。

# application.yaml
server:
  port: 8081
spring:
  application:
    name: hmdp
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: ${DB_URL:jdbc:mysql://127.0.0.1:3306/hmdp?useSSL=false&serverTimezone=UTC}
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD:root}
  redis:
    host: ${REDIS_HOST:127.0.0.1}
    port: 6379
    lettuce:
      pool:
        max-active: 10
        max-idle: 10
        min-idle: 1
        time-between-eviction-runs: 10s
    database: 2
  jackson:
    default-property-inclusion: non_null # JSON处理时忽略非空字段
mybatis-plus:
  type-aliases-package: com.hmdp.entity # 别名扫描包
logging:
  level:
    com.hmdp: debug

(2). 编译项目:mvn package

(3).将jar包拷贝到Dockerfile同级目录下,例如都在/User/your_name/images

(4).编写Dockerfile

FROM openjdk:8-jdk
# 设置时区,例如:Asia/Shanghai
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
# 设置工作目录
WORKDIR /app
# 将SpringBoot应用的JAR文件添加到镜像中
ADD hm-dianping-0.0.1-SNAPSHOT.jar /app/hm-dianping.jar
# 设置容器启动命令
ENTRYPOINT ["java", "-jar", "/app/hm-dianping.jar"]
# 开放8081端口
EXPOSE 8081

(5). 使用命令docker build -t hmdp-app:v1 .制作镜像

(6). 编写yaml并部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hmdp-app
spec:
  selector:
    matchLabels:
      app: hmdp-app
  replicas: 1
  template:
    metadata:
      labels:
        app: hmdp-app
    spec:
      containers:
      - name: hmdp
        image: hm-dianping:v1
        ports:
        - containerPort: 8081
        env:
        - name: DB_URL
          value: "jdbc:mysql://hmdp-mysql-svc:3306/hmdp"
        - name: DB_USERNAME
          value: "root"
        - name: DB_PASSWORD
          value: "root"
        - name: REDIS_HOST
          value: "redis"
---
apiVersion: v1
kind: Service
metadata:
  name: hmdp-svc
  labels:
    app: hmdp-app
spec:
  ports:
  - port: 8081
    targetPort: 8081
    nodePort: 30081
  selector:
    app: hmdp-app
  type: NodePort

这里为了便于调试,Service采用NodePort模式,部署完成后可以浏览器Get请求访问localhost:30081/shop-type/list查看是否得到店铺类型的json。

5. Kubernetes部署前端项目

黑马点评的前端项目是已经打包好的静态文件放到了nginx下,这里制作镜像也选择使用nginx;

(1). 将hmdp的前端静态资源文件夹、nginx的配置文件以及Dockerfile放置于同一个目录下,其中nginx的配置修改如下:

# nginx.conf

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/json;

    sendfile        on;
    
    keepalive_timeout  65;

    server {
        listen       8080;
        server_name  localhost;
        # 指定前端项目所在的位置
        location / {
            root   /usr/share/nginx/html/hmdp; # 覆盖默认路径
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }


        location /api {  
            default_type  application/json;
            #internal;  
            keepalive_timeout   30s;  
            keepalive_requests  1000;  
            #支持keep-alive  
            proxy_http_version 1.1;  
            rewrite /api(/.*) $1 break;  
            proxy_pass_request_headers on;
            #more_clear_input_headers Accept-Encoding;  
            proxy_next_upstream error timeout;  
            proxy_pass http://hmdp-svc.default.svc.cluster.local:8081; # 修改后端访问域名
            #proxy_pass http://backend;
        }
    }

    upstream backend {
        # 修改后端访问域名
        server hmdp-svc.default.svc.cluster.local:8081 max_fails=5 fail_timeout=10s weight=1;
        #server 127.0.0.1:8082 max_fails=5 fail_timeout=10s weight=1;
    }  
}

(2).编写Dockerfile

# 使用官方的nginx镜像作为基础
FROM nginx:alpine
# 将前端静态文件复制到容器中的nginx默认目录下
COPY hmdp/ /usr/share/nginx/html/hmdp/
# 复制nginx配置文件到容器中
COPY ./nginx.conf /etc/nginx/nginx.conf
# 暴露端口
EXPOSE 8080

(3).使用命令docker build -t hmdp-web:v1 .制作镜像

(4).编写yaml,并部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hmdp-web
  labels:
    app: hmdp-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hmdp-web
  template:
    metadata:
      labels:
        app: hmdp-web
    spec:
      containers:
      - name: hmdp-web
        image: hmdp-web:v1
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: hmdp-web-svc
  labels:
    app: hmdp-web
spec:
  type: NodePort
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 30080
  selector:
    app: hmdp-web

这里为了便于调试,Service采用NodePort模式,部署完成后可以浏览器Get请求访问localhost:30080查看是否可以访问到黑马点评的首页。
在这里插入图片描述
如果这里出现访问不到的问题,可以log一下pod的日志或者查询一下自己复制的文件有没有在容器中

# 查找pod名称
kubectl get pod                                   
NAME                         READY   STATUS    RESTARTS      AGE
hmdp-app-5f65ff68d5-jz9kn    1/1     Running   0              1h
hmdp-mysql-cfdbf66d7-w6qcv   1/1     Running   0              3h
hmdp-web-794567cc45-k4pgr    1/1     Running   0              1h
redis-69b78f8595-9mgnm       1/1     Running   0              3h
# 查看日志
kubectl logs hmdp-web-794567cc45-k4pgr -c hmdp-web
# 查看文件
kubectl exec -it hmdp-web-794567cc45-k4pgr  -c hmdp-web -- ls /usr/share/nginx/html

6.Kubernetes部署ingress-nginx

(1)、下载nginx-ingress-controller配置文件

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml

(2)、修改deploy中ingress-nginx-controller的Service,更改为NodePort

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.8.2
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Local
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: NodePort

(3)、部署deploy.yaml后查看pod,此时ingress-controller就创建好了

kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-rmmnr        0/1     Completed   0          11m
ingress-nginx-admission-patch-dppgg         0/1     Completed   2          11m
ingress-nginx-controller-6f4df7b5d6-4t5hx   1/1     Running     0          11m

(4)、部署之后可以发现ingressclass已经创建好了

kubectl get ingressclass        
NAME    CONTROLLER             PARAMETERS   AGE
nginx   k8s.io/ingress-nginx   <none>       4h14m

(5)、创建自己的ingress,并绑定ingressclass

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hmdp-ingress
spec:
  # 绑定ingressClass: 写kubectl get ingressclass查到的name
  ingressClassName: nginx
  rules:
  - host: "www.dianping.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hmdp-web-svc
            port:
              number: 8080

(6)、在SwitchHost中修改自己本机的host
在这里插入图片描述
(7)、查看ingress-controller的service的NodePort端口是什么(如果deploy设定了的话,直接用设定好的即可)

kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.105.173.184   <none>        80:30638/TCP,443:32219/TCP   4h20m
ingress-nginx-controller-admission   ClusterIP   10.102.112.202   <none>        443/TCP                      4h20m

(8)、访问www.dianping.com:30638,得到如下结果。
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值