04-k8s项目部署
前言
且停且忘且随风,且行且看且从容
10部署
10.1Docker镜像操作
Docker镜像推送阿里云
docker commit
命令用于创建一个新的镜像,以当前容器的状态为基础。它可以将正在运行的容器的更改保存为一个新的 Docker 镜像。
docker commit
说明:
-a "peng"
: 设置作者为 "peng"。-m "nginx"
: 添加提交信息为 "nginx"。<容器ID>
: 替换为你的 Nginx 容器的实际 ID 或名称。pengpeng-namespace/gulimall-nginx:v1.0
: 指定新的镜像名称和标签。
# 创建新的镜像
docker commit -a "peng" -m "nginx" 容器id pengpeng-namespace/gulimall-nginx:v1.0
# 向阿里云推送镜像快照
docker push crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/pengpeng-registry:gulimall-nginx:v1.0
# 登录
docker login --username=pengpengservice crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com
# 创建新的标签
docker tag crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/pengpeng-registry:gulimall-nginx:v1.0 crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/pengpeng-registry:latest
# 推送镜像
docker push crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/pengpeng-registry:latest
修改配置
10.2部署-整合阿里云镜像仓库
参考:https://www.cnblogs.com/makalochen/p/14240796.html
官方地址:https://cr.console.aliyun.com/cn-shanghai/instance/repositories
创建本地仓库
本地仓库创建完成
我们需要留意docker login
、docker pull
、docker push
三条命令
需要留意自己的请求地址、命名空间、仓库名称、账号名称
10.3Jenkins修改阿里云镜像仓库
创建阿里云账号凭证,需要输入自己阿里云的账号密码
在环境变量添加自己阿里云的相关参数,分别是凭证(配置阿里云的账号密码)、请求地址、命名空间、仓库名称、账号名称
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
ALIYUN_CREDENTIAL_ID = 'aliyun-id'
ALIYUN_URL = 'crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com'
ALIYUN_NAMESPACE = 'pengpeng-namespace'
ALIYUN_ACCOUNT = 'pengpengservice'
}
创建阿里云的步骤,login
和push
地址拼对即可,tag
版本号可以小点
stage ('构建镜像-推送阿里云') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker tag $BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
步骤都是成功状态
push
完成
10.4流水线-部署gateway
创建流水线
peng-mall-jenkins-aliyun-cicd
选择git
,输入项目gitee
地址,选择gitee-id
凭证(就是配置的gitee
账号)
我的Jenkinsfile
不在根目录,我这边指定了Jenkinsfile
地址
选择是否开启浅克隆
选择运行,如果首次点击运行没有出现配置的项目参数(分支、PROJECT_VERSION
、PROJECT_NAME
),直接停止,获取不到参数流水线也会失败,运行停止1-2次参数的界面就应该就出来了,然后选择参数再运行
记得在这里删除运行失败的gulimall-gateway
服务部署成功
访问gulimall-gateway
,出现SpringBoot
的404代表部署成功
fatal: tag 'gulimall-gateway-v1.0' already exists
+ git tag -a gulimall-gateway-v1.0 -m v1.0 fatal: tag 'gulimall-gateway-v1.0' already exists script returned exit code 128
记得改一下版本就行了
10.5流水线-部署auth-server
部署gulimall-auth-service
成功后,我们去看pod
访问gulimall-auth-service
,出现SpringBoot
的404代表部署成功
10.6流水线-部署cart
部署gulimall-cart
部署成功后查看pod
访问gulimall-cart
,出现SpringBoot
的404代表部署成功
查看阿里云镜像
查看gulimall-cart
的镜像
10.12最终部署-商城系统上线
10.12.1推送gulimall-nginx
把自己之前部署nginx
挂载目录下的conf
和html
下载下来
查看gulimall-gateway
网关地址
修改nginx
的网关地址
gulimall-gateway-deploy.yaml
配置的网关暴露接口为31000,所以nginx
配置的上游地址是k8s
节点ip:31000
以下是Dockerfile
内容
FROM nginx
MAINTAINER peng
ADD html.tar.gz /usr/share/nginx/html
ADD conf.tar.gz /etc/nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
把html
、conf
上传到k8s
服务器
打包html
目录,只用打包html
下的所有文件,不需要html
目录
tar -czvf html.tar.gz -C html .
打包conf
目录,只用打包conf
下的所有文件,不需要conf
目录
tar -czvf conf.tar.gz -C conf .
然后可以删掉html
、conf
在gulimall-nginx
下进行打包
docker build -t gulimall-nginx:v1.0 -f Dockerfile .
登录阿里云,然后打上标签准备推送
# 登录
docker login --username=pengpengservice crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com
# 标签 0850795a13b6
docker tag [ImageId] crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/gulimall-nginx:v1.0
推送到阿里云
# 推送
docker push crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/gulimall-nginx:v1.0
阿里云上传成功
10.12.2访问gulimall-nginx
创建gulimall-nginx
见10.10.2
查看gulimall-nginx
的静态资源和配置是否修改了
查看静态资源文件
cd /usr/share/nginx
cd html
ls
配置文件
cd /etc/nginx
cat nginx.conf
访问http://192.168.188.181:32419/static/search/img/01.png,静态资源正常访问接口
10.12.3访问所有服务
管理员运行SwitchHosts
,配置k8s
集群的域名方案,我的都在一台电脑上
192.168.188.181 gulimall.com
192.168.188.181 search.gulimall.com
192.168.188.181 item.gulimall.com
192.168.188.181 auth.gulimall.com
192.168.188.181 cart.gulimall.com
192.168.188.181 order.gulimall.com
192.168.188.181 member.gulimall.com
192.168.188.181 seckill.gulimall.com
192.168.188.181 admin.gulimall.com
配置search.gulimall.com
路由规则
配置完成所有服务的路由规则
10.7流水线-部署coupon
部署gulimall-coupon
Jenkinsfile
发布版本的时候先推送到阿里云,然后gitee打标签时带上项目名称
每次推送镜像,版本会滚动升级
10.8流水线-部署完成&bug修改
检查我们部署的服务从31000
端口开始(我没有全部部署,我的电脑已经支不住了)
gulimall-product
商品服务和gulimall-seckill
秒杀服务之前使用Redisson
时地址固定了,这里需要动态读取
@Bean(destroyMethod="shutdown")
public RedissonClient redissonClient(@Value("${spring.redis.host}")String host) throws IOException {
//1、创建配置
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":6379");
//2、根据Config创建出RedissonClient实例
//Redis url should start with redis:// or rediss://
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
10.9流水线-修改为公有仓库
10.10最终部署-第一次部署前置nginx
10.10.1创建阿里云仓库
创建阿里云私有仓库
aliyun-repository
这里只需要输入域名即可,后面的命名仓库和镜像名称不需要
配置完成后,选择验证,验证通过即可
10.10.2创建gulimall-nginx
创建无状态服务
gulimall-nginx
选择自己刚创建的阿里云仓库地址,然后输入自己的ngxin
版本
pengpeng-namespace/gulimall-nginx:v1.0
配置资源和端口
tcp-443 443 443
tcp-80 80 80
不需要挂载存储
选择外网访问,选择开启会话保持
创建完成后,进入查看gulimall-nginx
映射的80端口
然后访问http://192.168.188.181:31868/,出现ngxin
页面即可
10.11最终部署-创建网关与应用路由
10.11.1创建网关
进入项目中,选择高级设置,选择设置网关,选择LoadBalancer
,删除下面掉2个插件,然后点击保存
10.11.2创建路由
选择应用负载,选择应用路由,点击创建
基本信息
gulimall-com
路由规则
选择指定域名,输入域名,选择http协议,选择gulimall-nginx
,选择80
gulimall.com
选择下一步,然后创建
10.11.3访问gulimall-nginx
查看gulimall-nginx
的静态资源和配置是否修改了
查看静态资源文件
cd /usr/share/nginx
cd html
ls
配置文件
cd /etc/nginx
cat nginx.conf
访问http://192.168.188.181:32419/static/search/img/01.png,静态资源正常访问接口
10.13最终部署-部署vue项目
10.13.1打包推送阿里云
配置static\config\index-prod.js
的线上服务地址
前端打包
npm run build
打包完成后上传到服务进行压缩
tar -czvf dist.tar.gz -C dist .
以下是Dockerfile
内容
FROM nginx
MAINTAINER peng
ADD dist.tar.gz /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
打包镜像
docker login --username=用户名 阿里云地址
docker build -t 阿里云地址/命名空间/gulimall-admin-vue-app:v1.0 -f Dockerfile .
docker push 阿里云地址/命名空间/gulimall-admin-vue-app:v1.0
docker login --username=pengpengservice crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com
docker build -t crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/gulimall-admin-vue-app:v1.0 -f Dockerfile .
docker push crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com/pengpeng-namespace/gulimall-admin-vue-app:v1.0
查看阿里云镜像,gulimall-admin-vue-app
已推送上去
10.13.2部署gulimall-admin-vue-app
创建无状态服务
gulimall-admin-vue-app
选择阿里云镜像地址,输入镜像名称
命名空间/gulimall-admin-vue-app:v1.0
配置资源和端口
tcp-80 80 80
不需要挂载存储
高级设置
选择外网访问,选择NodePort,选择开启会话保持
在KubeSphere
中访问gulimall-admin-vue-app
查看服务端口,然后访问http://192.168.188.181:30712/#/login
10.13.3部署renren-fast
本来部署几个服务即可,我的电脑内存实在支不住了,想着还是把这个renren-fast
部署了吧
修改renren-fast
的application-prod.yml
数据库配置和添加nacos
配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://mysql8.peng-mall:3306/mall_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: root
cloud:
nacos:
discovery:
server-addr: nacos.peng-mall:8848
redis:
open: false # 是否开启redis缓存 true开启 false关闭
database: 0
host: redis.peng-mall
修改redis
配置
Jenkinsfile
添加renren-fast
项目
'renren-fast'
构建镜像的时候加上"$PROJECT_NAME" = "renren-fast"
的判断,我的renren-fast
和gulimall-gateway
在同一个目录,和其他service
不在一起
sh """
if [ "$PROJECT_NAME" = "gulimall-gateway" ] || [ "$PROJECT_NAME" = "renren-fast" ]; then
cd $PROJECT_NAME && docker build -f Dockerfile -t "$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER" .
else
cd service/$PROJECT_NAME && docker build -f Dockerfile -t "$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER" .
fi
"""
部署到开发环境的时候也需要修改
script {
if (PROJECT_NAME == "gulimall-gateway" || PROJECT_NAME == "renren-fast") {
kubernetesDeploy(configs: "$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
} else {
kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
Dockerfile
之前也有修改
jdk
版本- 使用
RUN
命令 - 运行内存大小
FROM openjdk:8-jdk-alpine
EXPOSE 8080
VOLUME /tmp
ADD target/*.jar /app.jar
# RUN bash -c 'touch /app.jar'
# 使用 sh 替代 bash
RUN touch /app.jar
ENTRYPOINT ["java", "-jar", "-Xms128m", "-Xmx300m", "/app.jar", "--spring.profiles.active=prod"]
还有renren-fast-deploy.yaml
- 项目名称都改为
renren-fast
- 镜像地址
image
- 外界访问端口
nodePort
kind: Deployment
apiVersion: apps/v1
metadata:
name: renren-fast
namespace: peng-mall
labels:
app: renren-fast
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: renren-fast
version: v1
template:
metadata:
labels:
app: renren-fast
version: v1
spec:
containers:
- name: renren-fast
image: $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest
ports:
- containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 1000m
memory: 500Mi
requests:
cpu: 10m
memory: 10Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
---
kind: Service
apiVersion: v1
metadata:
name: renren-fast
namespace: peng-mall
labels:
app: renren-fast
version: v1
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
nodePort: 31021
selector:
app: renren-fast
type: NodePort
sessionAffinity: None
以上修改完成后记得提交
运行renren-fast
,如果没有出来renren-fast
选项,可以先运行,等一会再停止,然后在运行
运行成功
如果需要重新部署的话
在服务里选择renren-fast
,然后选择工作负载下的renren-fast
选择更多操作,选择重新部署
10.13.4部署效果
10.13.5问题
10.13.5.1部署的pod一直重启
我的gulimall-gateway
和nacos-v1-0
每次启动的虚拟机的时候启动出错
原因是nacos
需要初始化数据,所以没有找到nacos
数据库,但是我的mysql8
是正常的
gulimall-gateway
因为没有找到服务注册中心nacos
,也启动不起来
kubectl get pods -n peng-mall
解决:删掉这俩个pod让他重新部署(没有找到根本原因,我的机器实在扛不住了)
先删nacos
,再删gulimall-gateway
,保证nacos
正常运行,否则其他服务也找不到注册中心
kubectl delete pod nacos-v1-0 -n peng-mall
kubectl delete pod gulimall-gateway-67cbfd4fdd-lwtc6 -n peng-mall
10.13.5.2本地运行成功,sonarqube一直不通过
首先确保你的代码本地运行没有问题,这个只是临时方案,不是根本解决,我的电脑不能同时支持我运行idea
和`k8s集群解决问题,所以才暂时这么做
在Jenkinsfile
里跳过sonarqube
,不通过也继续执行
stage('阈值判断') {
steps {
script {
timeout(time: 1, unit: "HOURS") {
def qualityGate = waitForQualityGate()
if (qualityGate.status != 'OK') {
// error "SonarQube 检测不通过: ${qualityGate.status}"
echo "SonarQube 检测不通过: ${qualityGate.status}"
}
}
}
}
}
10.13.5.3运行版本不能重复
运行版本不能重复
可以去阿里云镜像确认镜像版本
10.13.5.4i.r.common.exception.RRExceptionHandler : null
NullPointerException
和 FontConfiguration
相关的错误通常与 Java 环境中缺少字体文件或配置文件有关。这种情况在使用 Docker 容器时比较常见,因为默认的 Alpine 镜像没有安装许多字体和图形环境。
修改Dockerfile
FROM openjdk:8-jdk-alpine
# 安装 fontconfig 和 DejaVu 字体
RUN apk add --no-cache fontconfig ttf-dejavu
EXPOSE 8080
VOLUME /tmp
ADD target/*.jar /app.jar
RUN touch /app.jar
ENTRYPOINT ["java", "-jar", "-Xms128m", "-Xmx300m", "/app.jar", "--spring.profiles.active=prod"]
安装 fontconfig
和 ttf-dejavu
验证
apk add --no-cache fontconfig ttf-dejavu
fc-list
10.13.5.5Sonaqube
中HttpUtils
不通过
Sonaqube
中HttpUtils
不通过
private static void sslClient(HttpClient httpClient) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
// 获取系统默认的 TrustManager
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
// 初始化 SSLContext,使用默认的 TrustManager
ctx.init(null, trustManagers, new SecureRandom());
// 使用严格的主机名验证
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
// 配置到 HttpClient
ClientConnectionManager ccm = httpClient.getConnectionManager();
SchemeRegistry registry = ccm.getSchemeRegistry();
registry.register(new Scheme("https", 443, ssf));
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException ex) {
throw new RuntimeException(ex);
}
}
10.14最终部署-测试滚动更新部署admin-vue-app
在服务里选择gulimall-admin-vue-app
,然后选择工作负载下的gulimall-admin-vue-app-v1
选择更多操作,选择编辑配置模版,选择容器组模版,选择编辑
选择容器组模版,修改你需要的镜像版本,点击确认即可
后台管理平台
前台界面
我就部署了这么多服务,保证基本功能正常就可以了,因为我的电脑内存马上又要满了
10.15线上预警与监控
admin
登录,选择平台管理,选择平台设置,每个版本可能不一样,我的KubeSphere
的版本v3.1.1
10.15.1配置qq邮箱
登录qq邮箱,选择设置,选择账号,让后向qq邮箱发送一个短信即可
配置邮箱
smtp.qq.com 465
开启服务成功后
我的KubeSphere
的版本v3.1.1
只需要设置完邮箱地址,添加告警策略会自动发送邮件
10.15.2添加告警策略
基本信息
gulimall-gateway-memory
gulimall-gateway
运行内存肯定大于100Mi
了,我们测试一下就行
添加标题和信息,点击创建
触发中
创作不易,感谢支持。