当前位置: 首页 > article >正文

k8s 部署 ruoyi 前后端分离项目

本文视频版: https://www.bilibili.com/video/BV17ugkePEeN

参考

https://blog.csdn.net/qq_50247813/article/details/136934090

https://gitee.com/nasaa/RuoYi-Vue-cloud

https://www.itsgeekhead.com/tuts/kubernetes-129-ubuntu-22-04-3/

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

https://github.com/Joxit/docker-registry-ui/issues/140

前置条件

三台虚拟机:

hostnameip作用
node80192.168.10.80k8s 节点,控制平面
node81192.168.10.81k8s 节点
node82192.168.10.82k8s 节点
node84192.168.10.84镜像仓库

三台虚拟机都配置了主机名和 ip 的映射,windows 也配置了主机名到 ip 的映射。

三台虚拟机都能访问互联网,最好能访问国外镜像仓库。

安装 k8s

下面这些步骤需要在每一个 k8s 节点上执行。

确保 k8s 在启动时加载内核模块 overlaybr_netfilter两个内核模块:

printf "overlay\nbr_netfilter\n" >> /etc/modules-load.d/containerd.conf

立即加载 overlaybr_netfilter 内核模块:

modprobe overlay
modprobe br_netfilter

配置 k8s 的网络:

printf "net.bridge.bridge-nf-call-iptables = 1\nnet.ipv4.ip_forward = 1\nnet.bridge.bridge-nf-call-ip6tables = 1\n" >> /etc/sysctl.d/99-kubernetes-cri.conf

重新加载配置:

sysctl --system

安装 containerd:

wget https://github.com/containerd/containerd/releases/download/v1.7.13/containerd-1.7.13-linux-amd64.tar.gz -P /opt/software/
tar Cxzvf /usr/local /opt/software/containerd-1.7.13-linux-amd64.tar.gz
wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -P /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now containerd

安装 runc:

wget https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64 -P /opt/software/
install -m 755 /opt/software/runc.amd64 /usr/local/sbin/runc

安装 cni 网络插件:

wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz -P /opt/software/
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin /opt/software/cni-plugins-linux-amd64-v1.4.0.tgz

修改 containerd 的配置并重启 containerd:

mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
vim /etc/containerd/config.toml
# 修改 SystemdCgroup 配置项的值为 true

systemctl restart containerd

关闭 swap:

vim /etc/fstab

注释掉最后一行:

更新 apt-get 并信任 k8s 官网链接:

apt-get update
apt-get install -y apt-transport-https ca-certificates curl gpg

mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

apt-get update

重启:

reboot

下载 k8s 软件包:

apt-get install -y kubelet=1.29.1-1.1 kubeadm=1.29.1-1.1 kubectl=1.29.1-1.1
apt-mark hold kubelet kubeadm kubectl

apt-mark hold kubelet kubeadm kubectl 命令的作用是将 kubeletkubeadmkubectl 这三个软件包标记为“保留”状态。这意味着这些软件包不会被系统自动升级或删除

检查 swap 是否关闭,确保 swap 是 0:

free -m

下面这些步骤仅仅需要在控制平面节点执行:

# 这个命令会比较耗时,这里的 node80 需要改为你自己的 k8s master 的 hostname,这里需要网络状况良好,能畅通的访问国外仓库,否则,容易发生拉取镜像失败,建议执行前切换为网速较好的节点
kubeadm init --pod-network-cidr 10.10.0.0/16 --kubernetes-version 1.29.1 --node-name node80

# 这种切换方式重启后会失效,可以向 ~/.bashrc 文件末尾添加 export KUBECONFIG=/etc/kubernetes/admin.conf 后,再使用 source ~/.bashrc 使配置永久生效
export KUBECONFIG=/etc/kubernetes/admin.conf

# add Calico 3.27.2 CNI
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/tigera-operator.yaml
wget https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/custom-resources.yaml
# 将 CIDR 配置为 10.10.0.0/16
vim custom-resources.yaml
kubectl apply -f custom-resources.yaml

# 获取 worker 节点加入到集群的命令
kubeadm token create --print-join-command

在 worker 节点执行上面获取到的将 worker 节点加入到集群的命令将当前节点加入到 k8s 集群中:

kubeadm join 192.168.10.80:6443 --token pecvqm.rlxcsywbvm2resvv \
        --discovery-token-ca-cert-hash sha256:fac6cb7a265dc30d7560517dc64debaf933592215a58a8912453f6a56bde7701

–pod-network-cidr 明确了 Kubernetes 集群中 Pod 网络的 IP 地址范围

安装镜像仓库 registry

安装 htpasswd 工具:

sudo apt-get update
sudo apt-get install apache2-utils

创建挂载容器的目录以及密码文件:

mkdir -p /docker/volume/registry/auth/
htpasswd -Bc /docker/volume/registry/auth/htpasswd root
# 输入 root 的密码

创建 registry 容器挂载数据的目录:

mkdir -p /docker/volume/registry/data

创建 registry 挂载配置文件的目录,并创建配置文件:

mkdir -p /docker/volume/registry/conf
vim /docker/volume/registry/conf/config.yml
version: 0.1
log:
  level: debug
  fields:
    service: registry
    environment: production
storage:
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    Access-Control-Allow-Origin: ['http://node84:8080','http://192.168.10.84']
    Access-Control-Allow-Methods: ['HEAD', GET', 'OPTIONS', 'DELETE', 'POST', 'PUT']
    Access-Control-Allow-Headers: ['Authorization','Accept']
  http2:
    disabled: false
auth:
  htpasswd:
    realm: basic-realm
    path: /auth/htpasswd

创建 docker 网络:

docker network create registry-net

启动 registry 容器:

docker run -d \
  --name registry \
  --network registry-net \
  -v /docker/volume/registry/auth:/auth \
  -v /docker/volume/registry/data:/var/lib/registry \
  -v /docker/volume/registry/conf/config.yml:/etc/docker/registry/config.yml \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -e REGISTRY_HTTP_SECRET=secretkey \
  -p 5000:5000 \
  registry:2

修改 containerd 的配置(所有 k8s 节点都需要修改),配置 containerd 以允许从私有镜像仓库 node84:5000 拉取和推送镜像,并且跳过证书验证:

mkdir -p /etc/containerd/certs.d/node84:5000

tee /etc/containerd/certs.d/node84:5000/hosts.toml << 'EOF'
server = "http://node84:5000"

[host."http://node84:5000"]
  capabilities = ["pull", "resolve", "push"]
  skip_verify = true
EOF

systemctl restart containerd.service

添加配置(所有 k8s 节点都需要修改)告诉 containerd,当它需要拉取镜像时,首先从自定义的镜像仓库 http://node84:5000 获取镜像,这样才能拉取到我们自己打到 registry 私有镜像仓库的镜像:

如果不喜欢用 nano,也可以使用 vim 编辑文件

[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."node84:5000"]
    endpoint = ["http://node84:5000"]

注意:上面的 node84 是 registry 的地址,如果 registry 地址不是 node84,两个 node84 都需要更改为你的 registry 的地址,所有 k8s 机器都需要修改

sudo systemctl restart containerd

因为我们需要将 docker 上的镜像(第四台机器,node84)推送到 registry 中,所以,也需要修改 docker 的配置(第四台机器,node84),将 node84 添加到 docker 的安全镜像仓库名单中,避免使用 docker 推送镜像到 registry 中报错,将 "insecure-registries": ["192.168.56.10:5000"]' 加入到 /etc/docker/daemon.json 中,再使用 systemctl restart docker 重启 Docker 就可以了。

{
    "insecure-registries": ["node84:5000"]
}

安装 registry 可视化工具

启动一个 registry-browser 容器并连接到自定义网络:

docker run -d \
  --name registry-browser \
  --network registry-net \
  -e REGISTRY_TITLE="Docker Registry Browser" \
  -e NGINX_PROXY_PASS_URL="http://registry:5000" \
  -e REGISTRY_AUTH="true" \
  -e REGISTRY_AUTH_USER="root" \
  -e REGISTRY_AUTH_PASSWORD="123456" \
  -p 8080:80 \
  joxit/docker-registry-ui:latest

比较老的版本中使用 -e REGISTRY_URL=“http://registry:5000” \ 配置 registry 的地址,如果新版本中使用这个配置,在前端会出现 An error occured: Check your connection and your registry must have Access-Control-Allow-Origin header set to http://node84:8080这个异常,需要使用 NGINX_PROXY_PASS_URL 这个配置

访问主机的 8080 端口即可看到 registry 中的镜像。

部署 ruoyi 前后端分离项目

制作后端镜像

编写 Dockerfile 文件:

# 使用官方的 OpenJDK 8 镜像作为基础镜像
FROM openjdk:8-jdk-alpine
# 创建存放上传文件的目录
RUN mkdir -p /opt/project/ruoyi/ruoyi-backend/upload-file-path
# 创建存放日志的目录
RUN mkdir -p /opt/project/ruoyi/ruoyi-backend/logs
# 安装字体文件
RUN mkdir -p /etc/apk/
RUN touch /etc/apk/repositories
RUN echo -e 'https://mirrors.aliyun.com/alpine/v3.6/main/\nhttps://mirrors.aliyun.com/alpine/v3.6/community/' > /etc/apk/repositories
RUN set -xe && apk --no-cache add ttf-dejavu fontconfig
# 设置工作目录
WORKDIR /opt/project/ruoyi/ruoyi-backend
# 将构建好的 JAR 文件复制到容器中
COPY ./ruoyi-admin/target/ruoyi-admin.jar ruoyi-admin.jar
# 暴露应用程序端口
EXPOSE 8080
# 启动应用程序
CMD ["nohup","java","-jar","/opt/project/ruoyi/ruoyi-backend/ruoyi-admin.jar", ">", "/opt/project/ruoyi/ruoyi-backend/logs/nohup.log", "&"]

直接用 idea 连接到我们虚拟机中的 Docker 上,在 idea 中点击 Dockerfile 中的绿色箭头将后端打成镜像。

在虚拟机中查看镜像是否好了:

docker images

将打好的后端镜像推送到 registry 中:

#推送后端镜像
#修改镜像tag
docker tag ruoyi-backend:1.0 node84:5000/ruoyi-backend:1.0

# 因为 registry 设置了用户名和密码,所以需要先登录才能推送镜像
docker login -u root -p 123456 node84:5000

#推送到私有镜像仓库中
docker push node84:5000/ruoyi-backend:1.0

制作前端镜像

编写前端的 Dockerfile:

# 使用 Nginx 作为基础镜像
FROM nginx:1.12.2
# 将 nginx.conf 拷贝到容器中
COPY nginx.conf /etc/nginx/nginx.conf
# 创建存放前端编译后代码的目录
RUN mkdir -p /opt/project/ruoyi/ruoyi-front-code
# 将构建好的应用拷贝到 Nginx 的默认 web 目录
COPY dist /opt/project/ruoyi/ruoyi-front-code
# Expose 端口
EXPOSE 80
# 启动 Nginx 服务器
CMD ["nginx", "-g", "daemon off;"]

直接用 webstorm 连接到我们虚拟机中的 Docker 上,在 webstorm 中点击 Dockerfile 中的绿色箭头将后端打成镜像。

在虚拟机中查看镜像是否好了:

docker images

将打好的前端镜像推送到 registry 中:

#推送前端镜像
#修改镜像tag
docker tag ruoyi-frontend:1.0 node84:5000/ruoyi-frontend:1.0

# 因为 registry 设置了用户名和密码,所以需要先登录才能推送镜像
docker login -u root -p 123456 node84:5000

#推送到私有镜像仓库中
docker push node84:5000/ruoyi-frontend:1.0

k8s 部署后端

将后端初始化的两个 sql 文件创建为 configmap

将 ruoyi 后端的两个初始化 sql 文件放入 /opt/ruoyi/sql 中:

mkdir -p /opt/ruoyi/sql

切换成 k8s 的管理员:

export KUBECONFIG=/etc/kubernetes/admin.conf

这种切换方式重启后会失效,可以向 ~/.bashrc 文件末尾添加 export KUBECONFIG=/etc/kubernetes/admin.conf 后,再使用 source ~/.bashrc 使配置永久生效

使用如下命令检查是否切换成功:

kubectl cluster-info

创建一个为我们当前机器分配在 default 空间下创建 configmap 权限的配置文件:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: configmap-creator
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create", "update", "patch", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: configmap-creator-binding
  namespace: default
subjects:
- kind: User
  name: system:node:node80
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: configmap-creator
  apiGroup: rbac.authorization.k8s.io

使这个配置文件生效:

kubectl apply -f role-config.yaml

当前节点就有在 default 空间下创建 configmap 的权限了。

根据 ruoyi 后端的初始化 SQL 文件创建 configMap:

注意:sql 文件头部要加上:use ry-vue; SET NAMES utf8;

kubectl create configmap ruoyi-init-sql-config-map --from-file=/opt/ruoyi/sql
# 查看这个 configmap 的详情
kubectl describe configmap/ruoyi-init-sql-config-map

将需要修改的后端配置创建为 configmap

后端的镜像中,application.yaml 配置文件中 MySQL 和 Redis 的地址都是写死的,需要我们根据要求创建在 k8s 中使用的 configMap。

拷贝一份 application.yaml 配置文件,将其中的 ip 地址改为对应 service 的服务名地址:

# 数据源配置
spring:
    redis:
      # 地址
      host: ruoyi-redis-service
      # 端口,默认为6379
      port: 6379
      # 数据库索引
      database: 0
      # 密码
      password: 123456
      # 连接超时时间
      timeout: 10s
      lettuce:
        pool:
          # 连接池中的最小空闲连接
          min-idle: 0
          # 连接池中的最大空闲连接
          max-idle: 8
          # 连接池的最大数据库连接数
          max-active: 8
          # #连接池最大阻塞等待时间(使用负值表示没有限制)
          max-wait: -1ms
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://ruoyi-mysql-service:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&connectTimeout=1000&socketTimeout=30000&autoReconnect=true&failOverReadOnly=false
                username: root
                password: 123456
            # 从库数据源
            slave:
                # 从数据源开关/默认关闭
                enabled: false
                url:
                username:
                password:
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置连接超时时间
            connectTimeout: 30000
            # 配置网络超时时间
            socketTimeout: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username: ruoyi
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true

根据这个配置文件生成 configMap:

kubectl create configmap ruoyi-admin-config --from-file=/opt/ruoyi/application-k8s.yaml
kubectl describe configmap/ruoyi-admin-config

将 redis 服务的配置 redis.conf 创建为 configmap

下载需要的 redis 对应版本,解压后拷贝 redis.conf 文件,修改配置文件中的如下部分:

# 注释掉 bind 127.0.0.1,bind 用于限制访问 Redis 的机器 ip,直接关掉
# bind 127.0.0.1

# 修改 daemonize no 为 yes,让 Redis 可以后台启动
daemonize yes

# 设置密码
requirepass 123456

根据这个 redis.conf 配置文件生成 configMap:

kubectl create configmap ruoyi-redis-config-map --from-file=/opt/ruoyi/redis.conf
kubectl describe configmap/ruoyi-redis-config-map

将 registry 的用户名和密码创建为 secret

创建一个 secret 用于存储我们的 registry 仓库的用户名和密码,在 k8s 资源编排 yaml 文件中,在 deployment 中使用 imagePullSecrets 字段就可以引用这个 Secret 对象,这样 Kubernetes 就可以在拉取镜像时使用这个 Secret 对象中的认证信息。

kubectl create secret registry-user-pwd-secret \
    --docker-server=http://node84:5000 \
    --docker-username=root \
    --docker-password=123456

部署后端服务

后端部署的 k8s 资源清单:

# 数据库
apiVersion: apps/v1
kind: Deployment
metadata:
  name: database
  namespace: default
spec:
  selector:
    matchLabels:
      app: database
  template:
    metadata:
      labels:
        app: database
    spec:
      containers:
        - name: database
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
            - name: MYSQL_DATABASE
              value: "ry-vue"
          volumeMounts:
            - mountPath: /docker-entrypoint-initdb.d
              name: ruoyi-init-sql
          resources:
            limits:
              memory: "512Mi"
              cpu: "500m"
          ports:
            - containerPort: 3306
      volumes:
        - name: ruoyi-init-sql
          configMap:
            name: ruoyi-init-sql-config-map
      imagePullSecrets:
        - name: registry-user-pwd-secret

---
apiVersion: v1
kind: Service
metadata:
  name: ruoyi-mysql-service
  namespace: default
spec:
  selector:
    app: database
  ports:
    - port: 3306
      targetPort: 3306

---
# redis
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:7.2.0
          resources:
            limits:
              memory: "512Mi"
              cpu: "500m"
          ports:
            - containerPort: 6379
          volumeMounts:
            - mountPath: /usr/local/etc/redis/redis.conf
              name: ruoyi-redis-config
      volumes:
        - name: ruoyi-redis-config
          configMap:
            name: ruoyi-redis-config-map
      imagePullSecrets:
        - name: registry-user-pwd-secret

---
apiVersion: v1
kind: Service
metadata:
  name: ruoyi-redis-service
  namespace: default
spec:
  selector:
    app: redis
  ports:
    - port: 6379
      targetPort: 6379

# ruoyi 后端
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ruoyi-java
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ruoyi-java
  template:
    metadata:
      labels:
        app: ruoyi-java
    spec:
      initContainers:
        - name: wait-for-mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
          command:
            - sh
            - -c
            - |
              set -e
              maxTries=10
              while [ "$$maxTries" -gt 0 ] \
                    && ! mysqladmin ping --connect-timeout=3 -s \
                                    -hruoyi-mysql-service -uroot -p$$MYSQL_ROOT_PASSWORD
              do 
                  echo 'Waiting for MySQL to be available'
                  sleep 5
                  let maxTries--
              done
              if [ "$$maxTries" -le 0 ]; then
                  echo >&2 'error: unable to contact MySQL after 10 tries'
                  exit 1
              fi
        - name: wait-for-redis
          image: redis:7.2.0
          env:
            - name: REDIS_PASSWORD
              value: "123456"
          command:
            - sh
            - -c
            - |
              set -e
              maxTries=10
              while [ "$$maxTries" -gt 0 ] \
                    && ! timeout 3 redis-cli -h ruoyi-redis-service -a $$REDIS_PASSWORD ping
              do 
                  echo 'Waiting for Redis to be available'
                  sleep 5
                  let maxTries--
              done
              if [ "$$maxTries" -le 0 ]; then
                  echo >&2 'error: unable to contact Redis after 10 tries'
                  exit 1
              fi
      containers:
        - name: ruoyi-java
          image: node84:5000/ruoyi-backend:1.0
          resources:
            limits:
              memory: "512Mi"
              cpu: "512m"
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
          # /app/ruoyi/ 是 dockerfile 中拷贝 jar 包所到的目录
          # springboot 启动时,会从 jar 包所在的目录的 config 子目录中查找配置文件
          volumeMounts:
            - mountPath: /opt/project/ruoyi/ruoyi-backend/config
              name: config
          # 使用 application-k8s.yaml 作为配置文件
          args:
            ["java", "-jar", "ruoyi-admin.jar", "--spring.profiles.active=k8s"]
      volumes:
        - name: config
          configMap:
            name: ruoyi-admin-config
      imagePullSecrets:
        - name: registry-user-pwd-secret
---
apiVersion: v1
kind: Service
metadata:
  name: ruoyi-backend-service
  namespace: default
spec:
  selector:
    app: ruoyi-java
  ports:
    - port: 8080
      targetPort: 8080

根据资源清单部署后端:

kubectl apply -f ruoyi-k8s-backend.yaml

k8s 部署前端

将前端的 nginx.conf 创建为 configmap

Nginx 的配置文件:

server {
  listen       80;
  server_name  localhost;
  charset utf-8;

  location / {
    # dockerfile中WORKDIR目录
    root   /opt/project/ruoyi/ruoyi-front-code;
    try_files $uri $uri/ /index.html;
    index  index.html index.htm;
  }

  location /prod-api/ {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # 后端 service 的 DNS
    proxy_pass http://ruoyi-backend-service.default:8080/;
  }

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

根据 Nginx 配置文件创建 configMap:

kubectl create configmap ruoyi-ui-config --from-file=/opt/ruoyi/nginx.conf
kubectl describe configmap/ruoyi-ui-config

部署前端服务

前端部署的 k8s 资源清单:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ruoyi-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ruoyi-nginx
  template:
    metadata:
      labels:
        app: ruoyi-nginx
    spec:
      initContainers:
        - name: wait-for-ruoyi-backend-service
          image: alpine
          command:
            - sh
            - -c
            - |
              apk add --no-cache curl
              echo "Starting to wait for ruoyi-backend-service..."
              until curl -s -f -m 3 http://ruoyi-backend-service:8080
              do
                echo "Waiting for ruoyi-backend-service...";
                sleep 5;
              done
              echo "ruoyi-backend-service is available now."
      containers:
        - name: ruoyi-nginx
          image: node84:5000/ruoyi-frontend:1.0
          resources:
            limits:
              memory: "512Mi"
              cpu: "512m"
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: /etc/nginx/conf.d
              name: config
      volumes:
        - name: config
          configMap:
            name: ruoyi-ui-config
            items:
              - key: nginx.conf
                path: default.conf
      imagePullSecrets:
        - name: registry-user-pwd-secret

---
apiVersion: v1
kind: Service
metadata:
  name: ruoyi-fronted-service
  namespace: default
spec:
  type: NodePort
  selector:
    app: ruoyi-nginx
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30000

根据资源清单启动前端:

kubectl apply -f ruoyi-k8s-fronted.yaml

前端通过 nodePort 暴露出去了,访问任意 k8s 节点的 30000 端口即可访问前端。

遇到的问题

拉取镜像失败

只要出现这种情况:

ctr: failed to copy: httpReadSeeker: failed open: failed to do request: Get "https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/52/52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5/data?verify=1719112771-ZRsD38JmAnzgLW0YPDJ4BVoEmvw%3D": dial tcp 162.220.12.226:443: connect: connection refused

就是网络不通,需要开代理。

可以使用如下命令测试拉取镜像是否能成功:

sudo ctr images pull docker.io/library/redis:7.2.0

可以配置 containerd 使用阿里云的镜像仓库加速:

vim /etc/containerd/config.toml
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."node63:5000"]
          endpoint = ["http://node63:5000"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://6zemac9k.mirror.aliyuncs.com"]

修改后重启 containerd:

sudo systemctl restart containerd

配置完后,拉取镜像的时候并没有从 aliyun 拉取,不知道为什么。

最后我还是选择了使用代理。

拉取前后端镜像失败

containerd 的配置 /etc/containerd/config.toml 中:

   [plugins."io.containerd.grpc.v1.cri".registry.mirrors]

    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."<font style="background-color:#FBDE28;">node63:5000</font>"]

      endpoint = ["http://node63:5000"]

    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]

      endpoint = ["https://6zemac9k.mirror.aliyuncs.com"]

registry.mirrors.“node63:5000” 之前因为忘了修改,应该要改成现在的 registry 的地址 node63:5000。


http://www.kler.cn/a/304344.html

相关文章:

  • RK3588在Android13/14如何查看GPU,NPU,DDR,RGA数据
  • 300多种复古手工裁剪拼贴艺术时尚字母、数字、符号海报封面Vlog视频MOV+PNG素材
  • 命令手动更新 Navigator
  • Django 模型中使用选择(choices):全面指南
  • RGCL:A Review-aware Graph Contrastive Learning Framework for Recommendation
  • VMware vCenter保姆级安装部署(VMware VCenter Nanny Level Installation and Deployment)
  • 《企业实战分享 · SonarQube10.x 详细教程》
  • React 组件的基本使用,useState 状态变量的使用
  • 【Linux基础】02 权限
  • VUE+Tailwind网页开发
  • 大数据中一些常用的集群启停命令
  • oracle 如何查询表被锁
  • Vue自定义组件:解密v-model,轻松实现双向数据绑定
  • Nacos rce-0day漏洞复现(nacos 2.3.2)
  • 如何准备技术面试?
  • 利用AI驱动智能BI数据可视化-深度评测Amazon Quicksight(二)
  • Stream流的思想和获取Stream流
  • 设计模式重新整理
  • 中秋出游热度十足!喆啡酒店如何巧妙捕捉多元旅游需求?
  • 遥感技术在生态系统碳储量、碳收支、碳排放、碳循环以及人为源排放反演等领域的技术发展,实践角度解决遥感技术在生态、能源、大气等领域的碳排放监测及模拟问题
  • C++ | Leetcode C++题解之第397题整数替换
  • Coggle数据科学 | 科大讯飞AI大赛:人岗匹配挑战赛 赛季3
  • 怎么将几个pdf合成为一个?把几个PDF合并成为一个的8种方法
  • opencv图像透视处理
  • 机器学习(西瓜书)第 6 章 支持向量机
  • Jupyter notebook配置与使用(安装过程+环境配置+运行实例)