K8s上部署java网站项目流程

第一步:制作镜像
像java,C,GO都是编译型语言,使用前需要编译。
解释型语言:php,python
# 下载Java项目
[root@k8s-master01 ~]# git clone https://gitee.com/xinghaik8s/java-demo.git
# 安装环境
[root@k8s-master01 ~]# yum install java-1.8.0-openjdk-devel maven -y
# 代码编译
[root@k8s-master01 java-demo]# mvn clean package
# 解压部署文件
[root@k8s-master01 java-demo]# unzip target/*.war -d target/ROOT
#修改maven源为阿里源
[root@k8s-master01 java-demo]# vi /etc/maven/settings.xml
<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->
<mirrors>
<!-- 阿里云镜像(代理了Central、JCenter、Spring等) -->
<mirror>
<id>aliyun</id>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
<!-- 星号 * 表示匹配所有仓库,几乎所有的下载都会走这个镜像,速度最快 -->
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
制作新镜像并推入镜像仓
#根据当前目录下的 Dockerfile 和其他上下文文件,构建一个名为 java-demo:v1 的 Docker 镜像。
[root@k8s-master01 java-demo]# docker build -t java-demo:v1 . #根据当前目录的 Dockerfile 构建一个新的 Docker 镜像
# 为镜像打上仓库标签
[root@k8s-master01 java-demo]# docker tag java-demo:v1 core.harbor.domain/java-demo/java-demo:v1 #要推送到 Harbor 仓库,标签格式必须严格遵守:仓库地址/项目名/镜像名:版本
#登录harbor
[root@k8s-master01 java-demo]# docker login core.harbor.domain
Authenticating with existing credentials... [Username: admin]
i Info → To login with a different account, run 'docker logout' followed by 'docker login'
Login Succeeded
# 推送镜像到仓库
[root@k8s-master01 java-demo]# docker push core.harbor.domain/java-demo/java-demo:v1
The push refers to repository [core.harbor.domain/java-demo/java-demo]
a02a4930cb5d: Pushed
675ab56ce773: Pushed
a2328b746f7b: Pushed
12ac6c660ca4: Pushed
e114a9aff6a2: Pushed
e6f0733c3ee9: Pushed
v1: digest: sha256:85d9e1ab2d7db6b21fe91eae8d6f507b23b6fc5431eadbc485739c7ae25c6ba1 size: 856
第二步:使用工作负载资源部署镜像
#预生成一个 Kubernetes Deployment(部署)的 YAML 配置文件,而不会在集群中实际创建任何资源
[root@k8s-master01 java-demo]# kubectl create deployment java-demo --image=core.harbor.domain/java-demo/java-demo:v1 --replicas=2 --dry-run=client -o yaml > deployment.yaml
#apply部署一下
[root@k8s-master01 java-demo]# kubectl apply -f deployment.yaml
deployment.apps/java-demo created
#创建service,为现有的 java-demo Deployment 生成一个 Service(服务)的配置模板,以便将您的 Java 应用暴露给网络访问。
[root@k8s-master01 java-demo]# kubectl expose deployment java-demo --port=80 --target-port=8080 --dry-run=client -o yaml > service.yaml
#为了方便从外部访问,可以把type改为NodePort
#Service 类型是 NodePort。31594就是 Kubernetes 自动分配的一个"节点端口",它允许你通过集群中任意节点的 IP 地址(比如你的 192.168.175.11、12、13)加上这个端口来从外部访问服务。
#Service 类型是默认的 ClusterIP,它只提供一个集群内部的 IP 地址 (10.10.167.74),因此只能在 Kubernetes 集群内部被访问。
[root@k8s-master01 java-demo]# vi service.yaml
[root@k8s-master01 java-demo]# cat service.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: java-demo
name: java-demo
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: java-demo
status:
loadBalancer: {}

#进入java服务里面看一下
[root@k8s-master01 java-demo]# kubectl get pod
NAME READY STATUS RESTARTS AGE
java-demo-f497fcd95-44z9h 1/1 Running 0 31m
java-demo-f497fcd95-zn89x 1/1 Running 0 31m
[root@k8s-master01 java-demo]# kubectl exec -it java-demo-f497fcd95-44z9h sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
sh-4.2# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs temp webapps work
sh-4.2# cd webapps/
sh-4.2# ls
ROOT
sh-4.2# cd ROOT/
sh-4.2# ls
META-INF WEB-INF
sh-4.2# cd WEB-INF/
sh-4.2# ls
classes lib
sh-4.2# cd classes/
sh-4.2# ls
application.yml com static templates
sh-4.2# cat application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&&serverTimezone=CST
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
freemarker:
allow-request-override: false
cache: true
check-template-location: true
charset: UTF-8
content-type: text/html; charset=utf-8
expose-request-attributes: false
expose-session-attributes: false
expose-spring-macro-helpers: false
suffix: .ftl
template-loader-path:
- classpath:/templates/
sh-4.2#
#创建configmap,configmap里面的内容和项目里面的application.yml是一致的
[root@k8s-master01 java-demo]# vi configmap.yaml
[root@k8s-master01 java-demo]# cat configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: java-demo-config
data:
# 键 application.yml 对应的值是一个多行字符串
application.yml: |
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://java-web-demo-db:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=CST
username: root
password: "123456"
driver-class-name: com.mysql.jdbc.Driver
freemarker:
allow-request-override: false
cache: true
check-template-location: true
charset: UTF-8
content-type: text/html; charset=utf-8
expose-request-attributes: false
expose-session-attributes: false
expose-spring-macro-helpers: false
suffix: .ftl
template-loader-path:
- classpath:/templates/
[root@k8s-master01 java-demo]# kubectl apply -f configmap.yaml
configmap/java-demo-config created
#在deployment上增加挂在卷,修改一下deployment文件,要把数据保存到本地
#[root@k8s-master01 java-demo]# vi deployment.yaml
[root@k8s-master01 java-demo]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: java-demo
name: java-demo
spec:
replicas: 2
selector:
matchLabels:
app: java-demo
strategy: {}
template:
metadata:
labels:
app: java-demo
spec:
containers:
- image: core.harbor.domain/java-demo/java-demo:v1
name: java-demo
volumeMounts: #容器挂载配置 (volumeMounts)
- name: config #引用下面定义的卷名称
mountPath: /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/application.yml #容器内的目标路径
subPath: application.yml #只挂载卷中的特定文件,而不是整个卷
volumes:
- name: config #定义卷的名称
configMap:
name: java-demo-config #引用的 ConfigMap 名称
items:
- key: application.yml
path: application.yml
重启java服务生效
kubectl rollout restart deployment java-demo
初始化数据库
#[root@k8s-master01 opt]# vi mysql.yaml
[root@k8s-master01 opt]# cat mysql.yaml
apiVersion: v1
kind: Secret #作用:安全存储敏感数据
metadata:
name: java-web-demo-db #名称:java-web-demo-db
type: Opaque #类型:Opaque(通用类型)/
data:
mysql-root-password: "MTIzNDU2" #数据:mysql-root-password 的值是 MTIzNDU2(这是 "123456" 的 base64 编码)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-web-demo-db
spec:
selector: #标签选择器:选择带有project: www和app: mysql标签的Pod
matchLabels:
project: www
app: mysql
template:
metadata:
labels:
project: www
app: mysql
spec:
# 关键修复1:添加Pod级别的securityContext
securityContext:
fsGroup: 999 # Kubernetes 会自动设置卷组权限
# 关键修复2:添加initContainer修复权限
initContainers:
- name: volume-permission-fix
image: busybox:latest
command: ["sh", "-c", "chmod -R 777 /var/lib/mysql"]
volumeMounts:
- name: data
mountPath: /var/lib/mysql
containers:
- name: db
image: mysql:8.0.33
# 关键修复3:添加容器级别的securityContext
securityContext:
runAsUser: 999 # 以mysql用户运行
runAsGroup: 999 # 以mysql组运行
allowPrivilegeEscalation: false
resources:
requests:
cpu: 500m # 0.5核
memory: 1Gi
limits:
cpu: 800m # 0.8核
memory: 2Gi
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: java-web-demo-db
key: mysql-root-password
ports:
- name: mysql
containerPort: 3306
livenessProbe:
exec:
command:
- sh
- -c
- "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD}"
initialDelaySeconds: 120 # 容器启动30秒后开始检查
periodSeconds: 30 # 每30秒检查一次
readinessProbe:
exec:
command:
- sh
- -c
- "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD}"
initialDelaySeconds: 30
periodSeconds: 30
volumeMounts:
- name: data #要挂载的卷名称(必须与上面volumes中定义的匹配)
mountPath: /var/lib/mysql # 容器内部的挂载路径
volumes:
- name: data
persistentVolumeClaim:
claimName: java-web-demo-db
---
apiVersion: v1
kind: PersistentVolumeClaim #持久卷声明
metadata:
name: java-web-demo-db
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce # 单节点读写
resources:
requests:
storage: 8Gi # 请求8GB存储空间
---
apiVersion: v1
kind: Service #服务
metadata:
name: java-web-demo-db
spec:
type: ClusterIP #只能在集群内部访问
ports:
- name: mysql
port: 3306 # 服务端口
targetPort: mysql # 容器端口
selector:
project: www
app: mysql
#命令将本地的 user.sql 文件复制到 Pod 的根目录 / 下(文件名为 user.sql)。
[root@k8s-master01 db]# kubectl cp user.sql java-web-demo-db-6dbfd87646-95hxf:/tmp/user.sql

java项目部署到k8s集群实验完毕!