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
,得到如下结果。