传统的企业服务如何部署在k8s集群中

传统的企业服务如何部署在k8s集群中

在云计算的浪潮下,Kubernetes(简称 K8s)已成为容器编排的 事实标准。那么传统的服务如何部署在容器中并且使用k8s来进行管理?今天,我们就在本地环境进行测试揭秘!

  • k8s集群一套(集群挂载了NFS服务)。
  • 安装了docker的主机一台(可以制作docker镜像)
  • 源码一套(在这以gitee上的开源博客系统拾壹博客为例)

1.部署Mysql

该系统使用mysql数据库进行数据存储并利用redis进行数据缓存

复制代码
step1:编写yaml文件来创建mysql所需的各种资源
vi mysql.yaml
##文件内容
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: default
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs-mysql
  nfs:
    path: /nfs/mysql-data/
    server: 192.168.5.129  #替换为你的 NFS 服务器 IP
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1 # 替换为实际挂载了/nfs/mysql-data 的节点主机名
---------
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: default
spec:
  storageClassName: nfs-mysql
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: default
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: docker.io/library/mysql:8.4.7
        ports:
        - containerPort: 3306
          name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"  # Mysql访问密码
        - name: MYSQL_DATABASE
          value: "myapp"
        - name: MYSQL_USER
          value: "myapp_user"
        - name: MYSQL_PASSWORD
          value: "123456"  # Mysql访问密码
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          exec:
            command: ["mysqladmin", "ping", "-h", "localhost"]
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command: ["mysql", "-h", "localhost", "-u", "root", "-p$(MYSQL_ROOT_PASSWORD)", "-e", "SELECT 1"]
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  namespace: default
spec:
  selector:
    app: mysql
  ports:
  - port: 3306        # 服务端口
    targetPort: 3306  # Pod 端口
    nodePort: 30006   # 节点映射端口 (30000-32767)
  type: NodePort

#step2:以上文件创建后执行以下命令进行应用:
kubectl apply -f redis.yaml ##应用资源

kubectl get pods -o wide | grep redis ##查看pod进行成功运行

kubectl describe pod <pod-name> ##如果pod未成功运行使用此命令查看创建失败原因。

##配置文件说明:上边文件一共创建了4个k8s资源
1.数据存储说明(pv/pvc):mysql服务属于有状态的pod,且需要进行数据持久化存储来保证数据库数据不丢失。
2.deployment资源指定了pod的运行参数
3.service资源定义了pod的访问方式。

2.部署redis

复制代码
step1:编写yaml文件来创建redis各种资源
vi redis.yaml
#文件内容
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: default
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: docker.io/library/redis:6.2.6
        ports:
        - containerPort: 6379
          name: redis
        command:
        - redis-server
        - "--appendonly no"  # 关闭持久化,因为不需要数据持久化
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "250m"
        livenessProbe:
          exec:
            command: ["redis-cli", "ping"]
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command: ["redis-cli", "ping"]
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
  namespace: default
spec:
  selector:
    app: redis
  ports:
  - port: 6379
    targetPort: 6379
    nodePort: 31790
  type: NodePort

##以上文件创建后执行以下命令进行应用:
kubectl apply -f redis.yaml ##应用资源

kubectl get pods -o wide | grep redis ##查看pod进行成功运行

kubectl describe pod <pod-name> ##如果pod未成功运行使用此命令查看创建失败原因。

##配置文件说明:
1.deployment资源定义了pod的运行参数以及副本数还是redis的参数

2.service资源定义了pod内服务的访问方式。

3.导入源码到IDEA中并制作Dcoker镜像

根据实际情况修改图中标记的信息即可

修改完成后,打包项目为jar包并上传到可以制作docker镜像的主机上

制作镜像

复制代码
#step1:编写制作镜像文件内容
vi dockerfile
#指定基础镜像版本
FROM openjdk:8-jdk 
#指定工作目录
WORKDIR /app 
#容器内安装相关命令
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    apt-install net-tools \
    apt-install vim \
    rm -rf /var/lib/apt/lists/* 
#将jar文件复制到容器的工作目录下    
COPY ./mojian-blog-v2.0.0.jar app.jar 

#配置容器时间(将宿主机相关文件映射到容器镜像中)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone
#暴露服务端口        
EXPOSE 8800 

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:8800/actuator/health || exit 1
    
##添加容器内服务运行脚本,容器创建后自动运行
ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-jar", "app.jar"]

#step2:制作镜像
docker build -t <镜像名>:<镜像版本>
docker build -t blog-server:v1.0.0
docker images #查看镜像是否制作完成。

保存本地镜像并上传至k8s集群中

复制代码
#step1:保存本地镜像为.tar文件
docker save -o blog-server.tar blog-server:v1.0.0

#step2:上传镜像至k8s集群的所有node节点并导入镜像
docker load -i <tar文件>
docker load -i blog-server.tar
如果容器使用的是containerd则使用以下命令加载
ctr -n k8s.io images import blog-server.tar

注:由于在测试环境直接利用本地镜像导出和导入即可,也可在阿里云创建个人镜像仓库将制作完成的镜像推送至远程个人仓库,完了直接自动拉取即可。
$ docker login --username=echo crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com
$ docker tag [ImageId] crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com/echo-blog/blog-server:[镜像版本号]
$ docker push crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com/echo-blog/blog-server:[镜像版本号]
##1.登录到远程仓库
##2.将本地镜像定义标签
##3.推送本地镜像到远程仓库

##镜像拉取
$ docker pull crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com/echo-blog/blog:[镜像版本号]
$ ctr -n k8s.io images pull --user <仓库名>:仓库密码 crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com/blog-server:[版本号] ##containerd拉取命令

制作npm镜像

此系统前端和管理端使用了 vue2.0编写,在这需要经前端和管理端制作成镜像即可。

制作镜像前先修改管理端和前端连接后端服务的地址;修该blog-web与blog-admin下的/env.development文件的后端接口地址,在这由于是pod内部相互访问,直接配置成server-name+服务端口即可。

复制代码
#step1:管理端镜像制作(blog-admin)
##镜像制作文件
FROM node:22.21.0-alpine

WORKDIR /app

COPY ./blog-admin /app
    
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
   echo "Asia/Shanghai" > /etc/timezone

#安装依赖
RUN npm install

#暴露的端口
EXPOSE 3000

# 健康检查

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

# 设置启动命令

CMD ["npm", "run", "dev"]

#step2:前端镜像制作(blog-web)
##镜像制作文件
FROM node:22.21.0-alpine

WORKDIR /app

COPY ./blog-web /app
    
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
   echo "Asia/Shanghai" > /etc/timezone

#安装依赖
RUN npm install

#暴露的端口
EXPOSE 3000

# 健康检查

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

# 设置启动命令

CMD ["npm", "run", "dev"]

注:1.将本地的blog-admin与blog-web文件夹分别打包上传至服务器进行解压缩。
	2.先制作blog-admin镜像,根据上边dockerfile文件内容进行制作镜像;制作完毕在制作blog-web镜像。
	3.镜像保存与上传,可采用制作blog-sever的方法进行镜像的保存和导入也可将制作的镜像上传至远程仓库,完了自动拉取即可。

4.创建后端管理端以及前端的Pod

4.1服务端pod创建
复制代码
step1:编写资源文件
vi blog-server.yaml
##文件内容
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blog-server
  namespace: default  # 可根据需要修改命名空间
spec:
  replicas: 1
  selector:
    matchLabels:
      app: blog-server
  template:
    metadata:
      labels:
        app: blog-server
    spec:
      containers:
      - name: blog-server
        image: docker.io/library/blog-server:v1.0.0 # 根据情况修改镜像地址即可
        imagePullPolicy: IfNotPresent  # 关键:避免尝试从远程拉取
        ports:
        - containerPort: 8800
          protocol: TCP
        resources:
          limits:
            memory: "1024Mi"
            cpu: "500m"
          requests:
            memory: "512Mi"
            cpu: "200m"
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: blog-server-svc #此名称要和修改的代码中连接后端服务的地址一致,不然前端无法请求后端
  namespace: default
spec:
  type: NodePort  # 或 ClusterIP / LoadBalancer(根据环境)
  ports:
    - port: 8800
      targetPort: 8800
      nodePort: 30090  # 可选,范围 30000-32767
  selector:
    app: blog-server

step2:应用资源文件
kubectl apply -f blog-server.yaml ##应用资源

kubectl get pods -o wide #查看pod是否创建成功

kubectl get svc | grep blog-server #查看service是否创建成功

kubectl descrieb pod <pod-name> #如果Pod创建不成功可以使用此命令查看你event事件详细描述
4.2管理端pod创建
复制代码
step1:编写pod资源文件
vi blog-admin.yaml
#文件内容
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blog-admin
  namespace: default
  labels:
    app: blog-admin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: blog-admin
  template:
    metadata:
      labels:
        app: blog-admin
    spec:
      containers:
      - name: blog-admin
        image: crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com/echo-blog/blog-admin:v2.0.1  # 请替换为您的第一个镜像名称和标签
        ports:
        - containerPort: 3000
          name: http
        resources:
          requests:
            memory: "512Mi"
            cpu: "200m"
          limits:
            memory: "1024Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: blog-admin
  namespace: default
spec:
  selector:
    app: blog-admin
  ports:
  - name: http
    port: 3000      # Service端口
    targetPort: 3000 # 容器端口
    protocol: TCP
  type: NodePort

step2:应用资源
kubectl apply -f blog-admin.yaml #创建资源

kubectl get pods | grep blog-admin #查看pod是否创建成功以及pod状态(running状态即为成功)

kubectl get svc | grep blog-admin #查看svc是否创建成功

kubectl descrieb pod <pod-name> #如果Pod创建不成功可以使用此命令查看你event事件详细描述

Pod如果创建成功,可以使用任意节点IP+NodePort访问测试

4.3前端镜像制作
复制代码
step1:创建Pod以及其他资源
vi blog-web.yaml
#文件内容
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blog-web
  namespace: default
  labels:
    app: blog-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: blog-web
  template:
    metadata:
      labels:
        app: blog-web
    spec:
      containers:
      - name: blog-web
        image: crpi-o4vqz8nrivn0wa56.cn-hongkong.personal.cr.aliyuncs.com/echo-blog/blog-web:v2.0.1
        ports:
        - containerPort: 3001
          name: http
        resources:
          requests:
            memory: "512Mi"
            cpu: "200m"
          limits:
            memory: "1024Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: blog-web
  namespace: default
spec:
  selector:
    app: blog-web
  ports:
  - name: http
    port: 3001      # Service端口
    targetPort: 3001 # 容器端口
    protocol: TCP
  type: NodePort

step2:资源应用
kubectl apply -f blog-web.yaml #创建资源

kubectl get pods -o wide | grep blog-web #创建pod是否创建成功以及状态

kubectl get svc | grep blog-web #查看service是否创建成功

kubectl descrieb pod <pod-name> #如果Pod创建不成功可以使用此命令查看你event事件详细描述

Pod如果创建成功,可以使用任意节点IP+NodePort访问测试

生产环境部署建议

  • Redis配置"--appendonly no"(不持久化数据)可能造成数据丢失
    • 改进建议:根据业务需求决定是否需要持久化

1. 镜像管理问题

  • 本地镜像导出导入 :这是不推荐 的生产环境做法
    • 改进建议:使用私有镜像仓库(如Harbor、阿里云容器镜像服务)

2. 部署架构问题

  • 单点故障 :所有服务都使用replicas: 1,生产环境应至少部署2个副本
    • 改进建议 :将replicas: 1改为replicas: 3(或根据业务需求调整)
  • 服务暴露方式 :使用NodePort暴露服务(30000-32767端口范围)
    • 改进建议:在生产环境中应使用Ingress控制器或LoadBalancer类型Service

3. 配置管理问题

  • 硬编码配置 :前端配置中直接写后端地址(如blog-server-svc.default.svc.cluster.local
    • 改进建议:使用ConfigMap管理配置,而不是硬编码

4. 存储方案问题

  • NFS存储 :使用NFS作为存储后端
    • 改进建议 :NFS在生产环境中性能和可靠性可能不足,应考虑:
      • 云存储(如阿里云EBS、Ceph)
      • 更适合K8s的存储解决方案(如Rook、Longhorn)

注:喜欢的话就点赞收藏吧

相关推荐
Juchecar4 小时前
超越经典23种设计模式:新模式、反模式与函数式编程
设计模式·云原生·函数式编程
深蓝电商API5 小时前
云原生爬虫:使用Docker和Kubernetes部署与管理分布式爬虫集群
docker·kubernetes
啟明起鸣6 小时前
【Go 与云原生】让一个 Go 项目脱离原生的操作系统——我们开始使用 Docker 制造云容器进行时
docker·云原生·golang
橙色云-智橙协同研发12 小时前
【PLM实施专家宝典】离散制造企业MBD与无纸化制造实施方案:从“图纸驱动”到“数据驱动”的革命
云原生·解决方案·数字化转型·plm·国产plm·专家经验·无纸化
victory043113 小时前
K8S重启之后无法启动故障排查 与 修复
云原生·容器·kubernetes
研究司马懿15 小时前
【ETCD】ETCD常用命令
网络·数据库·云原生·oracle·自动化·运维开发·etcd
java_logo15 小时前
SGLANG Docker容器化部署指南
linux·运维·docker·容器·eureka·1024程序员节
Qayrup16 小时前
各个系统的 docker安装
运维·docker·容器
代码or搬砖16 小时前
Docker 部署 Java 项目实践
java·docker·容器