1. 控制节点主机名为 controller,设置计算节点主机名为 compute;[root@controller ~]# hostnamectl set-hostname controller && su[root@compute ~]# hostnamectl set-hostname compute && su2.hosts 文件将 IP 地址映射为主机名。[root@controller&&compute ~]#vi /etc/hosts192.168.100.10 controller192.168.100.20 compute[root@controller&&compute ~]#vi /etc/selinux/config更改SELINUX=disabled[root@controller&&compute ~]#setenforce 0[root@controller&&compute ~]#systemctl stop firewalld && systemctl disable firewalld3.配置 yum 源[root@controller ~]rm -rf /etc/yum.repos.d/*[root@controller&&compute ~]# vi /etc/yum.repos.d/http.repo[centos]name=centosbaseurl=http://192.168.133.130/centosgpgcheck=0enabled=1 [openstack]name=openstackbaseurl=http://192.168.133.130/openstack/iaas-repogpgcheck=0enabled=1[root@controller&&compute ~]#yum clean all && yum repolist && yum makecache 2.1.1 部署容器云平台使用 OpenStack 私有云平台创建两台云主机,分别作为 Kubernetes 集群的 master 节点和 node 节点,然后完成 Kubernetes 集群的部署,并完成 Istio 服务网 格、KubeVirt 虚拟化和 Harbor 镜像仓库的部署。创建俩台云主机并配网# Kubernetes 集群的部署[root@localhost ~]# mount -o loop chinaskills_cloud_paas_v2.0.2.iso /mnt/[root@localhost ~]# cp -rfv /mnt/* /opt/[root@localhost ~]# umount /mnt/[root@master ~]# hostnamectl set-hostname master && su[root@worker ~]# hostnamectl set-hostname worker && su# 安装kubeeasy[root@master ~]# mv /opt/kubeeasy /usr/bin/kubeeasy# 安装依赖环境[root@master ~]# kubeeasy install depend \--host 192.168.59.200,192.168.59.201 \--user root \--password 000000 \--offline-file /opt/dependencies/base-rpms.tar.gz# 安装k8s[root@master ~]# kubeeasy install k8s \--master 192.168.59.200 \--worker 192.168.59.201 \--user root \--password 000000 \--offline-file /opt/kubernetes.tar.gz# 安装istio网格[root@master ~]# kubeeasy add --istio istio# 安装kubevirt虚拟化[root@master ~]# kubeeasy add --virt kubevirt# 安装harbor仓库[root@master ~]# kubeeasy add --registry harbor[root@k8s-master-node1 ~]# vim pod.yamlapiVersion: v1kind: Podmetadata: name: examspec: containers: - name: exam image: nginx:latest imagePullPolicy: IfNotPresent env: - name: exam value: "2022"[root@k8s-master-node1 ~]# kubectl apply -f pod.yaml[root@k8s-master-node1 ~]# kubectl get pod#部署 Istio 服务网格[root@k8s-master-node1 ~]# kubectl create ns examnamespace/exam created[root@k8s-master-node1 ~]# kubectl edit ns exam更改为: labels: istio-injection: enabled[root@k8s-master-node1 ~]# kubectl describe ns exam #查看任务 2 容器云服务运维(15 分)2.2.1 容器化部署 Node-Exporter编写 Dockerfile 文件构建 exporter 镜像,要求基于 centos 完成 Node-Exporter 服务的安装与配置,并设置服务开机自启。上传Hyperf.tar包[root@k8s-master-node1 ~]#tar -zxvf Hyperf.tar.gz[root@k8s-master-node1 ~]#cd hyperf/[root@k8s-master-node1 hyperf]#docker load -i centos_7.9.2009.tar上传node_exporter-1.7.0.linux-amd64.tar包[root@k8s-master-node1 hyperf]#vim Dockerfile-exporterFROM centos:centos7.9.2009MAINTAINER ChinaskillsRUN rm -rf /etc/yum.repos.d/*ADD node_exporter-1.7.0.linux-amd64.tar.gz /root/EXPOSE 9100ENTRYPOINT ["./root/node_exporter-1.7.0.linux-amd64/node_exporter"][root@k8s-master-node1 hyperf]#docker build -t monitor-exporter:v1.0 -f Dockerfile-exporter .2.2.2 容器化部署Alertmanager编写 Dockerfile 文件构建 alert 镜像,要求基于 centos:latest 完成 Alertmanager 服务的安装与配置,并设置服务开机自启。上传alertmanager-0.26.0.linux-amd64.tar包[root@k8s-master-node1 hyperf]#vim Dockerfile-alertFROM centos:centos7.9.2009MAINTAINER ChinaskillsRUN rm -rf /etc/yum.repos.d/*ADD alertmanager-0.26.0.linux-amd64.tar.gz /root/EXPOSE 9093 9094ENTRYPOINT ["./root/alertmanager-0.26.0.linux-amd64/alertmanager","--config.file","/root/alertmanager-0.26.0.linux-amd64/alertmanager.yml"][root@k8s-master-node1 hyperf]#docker build -t monitor-alert:v1.0 -f Dockerfile-alert .2.2.3 容器化部署 Grafana编写 Dockerfile 文件构建 grafana 镜像,要求基于 centos 完成 Grafana 服务 的安装与配置,并设置服务开机自启。上传grafana-6.4.1.linux-amd64.tar.gz包[root@k8s-master-node1 hyperf]#vim Dockerfile-grafanaFROM centos:centos7.9.2009MAINTAINER ChinaskillsRUN rm -rf /etc/yum.repos.d/*ADD grafana-6.4.1.linux-amd64.tar.gz /root/EXPOSE 3000ENTRYPOINT ["./root/grafana-6.4.1/bin/grafana-server","-homepath","/root/grafana-6.4.1/"][root@k8s-master-node1 hyperf]#docker build -t monitor-grafana:v1.0 -f Dockerfile-grafana .[root@k8s-master-node1 hyperf]#docker run -d --name grafana-exam-jiance monitor-grafana:v1.0 && sleep 5 && docker exec grafana-exam-jiance ps -aux && docker rm -f grafana-exam-jiance2.2.4 容器化部署 Prometheus 编写 Dockerfile 文件构建 prometheus 镜像,要求基于 centos 完成 Promethues 服务的安装与配置,并设置服务开机自启。上传prometheus-2.13.0.linux-amd64.tar.gz并解压[root@k8s-master-node1 hyperf]#tar -zxvf prometheus-2.13.0.linux-amd64.tar.gz[root@k8s-master-node1 hyperf]#mv prometheus-2.13.0.linux-amd64/prometheus.yml /root/hyperf && rm -rf prometheus-2.13.0.linux-amd64[root@k8s-master-node1 hyperf]#vim Dockerfile-prometheusFROM centos:centos7.9.2009MAINTAINER ChinaskillsRUN rm -rf /etc/yum.repos.d/*ADD prometheus-2.13.0.linux-amd64.tar.gz /root/RUN mkdir -p /data/prometheus/COPY prometheus.yml /data/prometheus/EXPOSE 9090ENTRYPOINT ["./root/prometheus-2.13.0.linux-amd64/prometheus","--config.file","/data/prometheus/prometheus.yml"][root@k8s-master-node1 hyperf]#docker build -t monitor-prometheus:v1.0 -f Dockerfile-prometheus .[root@k8s-master-node1 hyperf]#vim prometheus.yml #改动- job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'node' static_configs: - targets: ['node:9100'] - job_name: 'alertmanager' static_configs: - targets: ['alertmanager:9093'] - job_name: 'node-exporter' static_configs: - targets: ['node:9100']2.2.5 编排部署 Prometheus编写 docker-compose.yaml 文件,使用镜像 exporter、alert、grafana 和 prometheus 完成监控系统的编排部署。[root@k8s-master-node1 hyperf]#vim docker-compose.yaml编排部署prometheusversion: '3'services: node: container_name: monitor-node image: monitor-exporter:v1.0 restart: always hostname: node ports: - 9100:9100 alertmanager: container_name: monitor-alertmanager image: monitor-alert:v1.0 depends_on: - node restart: always hostname: alertmanager links: - node ports: - 9093:9093 - 9094:9094 grafana: container_name: monitor-grafana image: monitor-grafana:v1.0 restart: always depends_on: - node - alertmanager hostname: grafana links: - node - alertmanager ports: - 3000:3000 prometheus: container_name: monitor-prometheus image: monitor-prometheus:v1.0 restart: always depends_on: - node - alertmanager - grafana hostname: prometheus links: - node - alertmanager - grafana ports: - 9090:9090[root@k8s-master-node1 ~]#docker-compose up -d 2.2.6 安装 Jenkins将 Jenkins 部署到 default 命名空间下。要求完成离线插件的安装,设置 Jenkins 的登录信息和授权策略。上传BlueOcean.tar.gz包[root@k8s-master-node1 ~]#tar -zxvf BlueOcean.tar.gz[root@k8s-master-node1 ~]#cd BlueOcean/images/[root@k8s-master-node1 images]# docker load -i java_8-jre.tar[root@k8s-master-node1 images]# docker load -i jenkins_jenkins_latest.tar[root@k8s-master-node1 images]# docker load -i gitlab_gitlab-ce_latest.tar[root@k8s-master-node1 images]# docker load -i maven_latest.tar[root@k8s-master-node1 images]# docker tag maven:latest 192.168.59.200/library/maven[root@k8s-master-node1 images]# docker login 192.168.59.200Username: adminPassword: (Harbor12345)WARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credentials-store[root@k8s-master-node1 images]# docker push 192.168.59.200/library/maven#安装Jenkins[root@k8s-master-node1 BlueOcean]# kubectl create ns devops[root@k8s-master-node1 BlueOcean]# kubectl create deployment jenkins -n devops --image=jenkins/jenkins:latest --port 8080 --dry-run -o yaml > jenkins.yaml[root@k8s-master-node1 BlueOcean]# vim jenkins.yaml # 进入添加apiVersion: apps/v1kind: Deploymentmetadata: creationTimestamp: null labels: app: jenkins name: jenkins namespace: devopsspec: replicas: 1 selector: matchLabels: app: jenkins strategy: {} template: metadata: creationTimestamp: null labels: app: jenkins spec: nodeName: k8s-master-node1 containers: - image: jenkins/jenkins:latest imagePullPolicy: IfNotPresent name: jenkins ports: - containerPort: 8080 name: jenkins8080 securityContext: runAsUser: 0 privileged: true volumeMounts: - name: jenkins-home mountPath: /home/jenkins_home/ - name: docker-home mountPath: /run/docker.sock - name: docker mountPath: /usr/bin/docker - name: kubectl mountPath: /usr/bin/kubectl - name: kube mountPath: /root/.kube volumes: - name: jenkins-home hostPath: path: /home/jenkins_home/ - name: docker-home hostPath: path: /run/docker.sock - name: docker hostPath: path: /usr/bin/docker - name: kubectl hostPath: path: /usr/bin/kubectl - name: kube hostPath: path: /root/.kube[root@k8s-master-node1 BlueOcean]# kubectl apply -f jenkins.yamldeployment.apps/jenkins created[root@k8s-master-node1 ~]# kubectl get pod -n devops NAME READY STATUS RESTARTS AGEjenkins-7d4f5696b7-hqw9d 1/1 Running 0 88s# 进入jenkins,确定docker和kubectl成功安装[root@k8s-master-node1 ~]# kubectl exec -it -n devops jenkins-7d4f5696b7-hqw9d bash[root@k8s-master-node1 BlueOcean]# kubectl expose deployment jenkins -n devops --port=8080 --target-port=30880 --dry-run -o yaml >> jenkins.yaml[root@k8s-master-node1 BlueOcean]# vim jenkins.yaml # 进入修改第二次粘贴在第一此的后面apiVersion: v1kind: Servicemetadata: creationTimestamp: null labels: app: jenkins name: jenkins namespace: devopsspec: ports: - port: 8080 protocol: TCP name: jenkins8080 nodePort: 30880 - name: jenkins port: 50000 nodePort: 30850 selector: app: jenkins type: NodePort[root@k8s-master-node1 BlueOcean]# kubectl apply -f jenkins.yamlservice/jenkins created[root@k8s-master-node1 ~]# kubectl get -n devops svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEjenkins NodePort 10.96.53.170 <none> 8080:30880/TCP 10s# 使用提供的软件包完成Blue Ocean等离线插件的安装[root@k8s-master-node1 BlueOcean]# kubectl -n devops cp plugins/ jenkins-7d4f5696b7-hqw9d:/var/jenkins_home/* *访问 ip:30880 进入jenkins*# 查看密码[root@k8s-master-node1 BlueOcean]# kubectl -n devops exec jenkins-7d4f5696b7-hqw9d --cat /var/jenkins_home/secrets/initialAdminPassword 2.2.7 安装 GitLab 将 GitLab 部署到 default 命名空间下,要求设置 root 用户密码,新建公开项 目,并将提供的代码上传到该项目。[root@k8s-master-node1 BlueOcean]# kubectl create deployment gitlab -n devops --image=gitlab/gitlab-ce:latest --port 80 --dry-run -o yaml > gitlab.yamlW0222 12:00:34.346609 25564 helpers.go:555] --dry-run is deprecated and can be replaced with --dry-run=client.[root@k8s-master-node1 BlueOcean]# vim gitlab.yamljitlab的配置文件apiVersion: apps/v1kind: Deploymentmetadata: creationTimestamp: null labels: app: gitlab name: gitlab namespace: devopsspec: replicas: 1 selector: matchLabels: app: gitlab strategy: {} template: metadata: creationTimestamp: null labels: app: gitlab spec: containers: - image: gitlab/gitlab-ce:latest imagePullPolicy: IfNotPresent name: gitlab-ce ports: - containerPort: 80 env: - name: GITLAB_ROOT_PASSWORD value: admin@123[root@k8s-master-node1 BlueOcean]# kubectl apply -f gitlab.yamldeployment.apps/gitlab created[root@k8s-master-node1 BlueOcean]# kubectl get pod -n devopsNAME READY STATUS RESTARTS AGEgitlab-5b47c8d994-8s9qb 1/1 Running 0 17sjenkins-bbf477c4f-55vgj 1/1 Running 2 (15m ago) 34m[root@k8s-master-node1 BlueOcean]# kubectl expose deployment gitlab -n devops --port=80 --target-port=30888 --dry-run=client -o yaml >> gitlab.yaml[root@k8s-master-node1 BlueOcean]# vim gitlab.yaml # 进入添加---apiVersion: v1kind: Servicemetadata: creationTimestamp: null labels: app: gitlab name: gitlab namespace: devopsspec: ports: - port: 80 nodePort: 30888 selector: app: gitlab type: NodePort[root@k8s-master-node1 BlueOcean]# kubectl apply -f gitlab.yamldeployment.apps/gitlab configuredservice/gitlab created[root@k8s-master-node1 BlueOcean]# kubectl get svc -n devopsNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEgitlab NodePort 10.96.149.160 <none> 80:30888/TCP 6sjenkins NodePort 10.96.174.123 <none> 8080:30880/TCP 8m7s# 等待gitlab启动,访问IP:30888 root , admin@123 登录 Gitlab* # 将springcloud文件夹中的代码上传到该项目,Gitlab提供了代码示例[root@k8s-master-node1 BlueOcean]# cd springcloud/[root@k8s-master-node1 springcloud]# git config --global user.name "Administrator"[root@k8s-master-node1 springcloud]# git config --global user.email "admin@example.com"[root@k8s-master-node1 springcloud]# git remote remove origin[root@k8s-master-node1 springcloud]# git remote add origin http://192.168.100.23:30888/root/springcloud.git[root@k8s-master-node1 springcloud]# git add .[root@k8s-master-node1 springcloud]# git commit -m "Initial commit"# On branch masternothing to commit, working directory clean[root@k8s-master-node1 springcloud]# git push -u origin masterUsername for 'http://192.168.100.23:30888': root Password for 'http://root@192.168.100.23:30888':(admin@123)Counting objects: 3192, done.Delta compression using up to 4 threads.Compressing objects: 100% (1428/1428), done.Writing objects: 100% (3192/3192), 1.40 MiB | 0 bytes/s, done.Total 3192 (delta 1233), reused 3010 (delta 1207)remote: Resolving deltas: 100% (1233/1233), done.To http://192.168.100.23:30888/root/springcloud.git * [new branch] master -> masterBranch master set up to track remote branch master from origin. 2.2.8 配置 Jenkins 与 GitLab 集成在 Jenkins 中新建流水线任务,配置 GitLab 连接 Jenkins,并完成 WebHook 的配置。 * 在 GitLab 中生成名为 jenkins 的“Access Tokens” * 返回 jenkins * 回到 Gitlab ,复制 token * 复制后填写到此 2.2.9 构建 CI/CD 环境在流水线任务中编写流水线脚本,完成后触发构建,要求基于 GitLab 中的 项目自动完成代码编译、镜像构建与推送、并自动发布服务到 Kubernetes 集群 中。# 创建命名空间[root@k8s-master-node1 ~]# kubectl create ns springcloud* *新建流水线* * *添加 Gitlab 用户密码* * Harbor 仓库创建公开项目 springcloud * *返回 Gitlab 准备编写流水线* # 添加映射[root@k8s-master-node1 ~]# cat /etc/hosts192.168.59.200 apiserver.cluster.local # 选择这一行# 进入jenkins 添加映射[root@k8s-master-node1 ~]# kubectl exec -it -n devops jenkins-bbf477c4f-55vgj bashkubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.root@jenkins-bbf477c4f-55vgj:/# echo "192.168.200.59 apiserver.cluster.local" >> /etc/hostsroot@jenkins-bbf477c4f-55vgj:/# cat /etc/hosts # 查看是否成功 # 编写流水线pipeline{ agent none stages{ stage('mvn-build'){ agent{ docker{ image '192.168.3.10/library/maven' args '-v /root/.m2:/root/.m2' } } steps{ sh 'cp -rvf /opt/repository /root/.m2' sh 'mvn package -DskipTests' } } stage('image-build'){ agent any steps{ sh 'cd gateway && docker build -t 192.168.3.10/springcloud/gateway -f Dockerfile .' sh 'cd config && docker build -t 192.168.3.10/springcloud/config -f Dockerfile .' sh 'docker login 192.168.3.10 -u=admin -p=Harbor12345' sh 'docker push 192.168.3.10/springcloud/gateway' sh 'docker push 192.168.3.10/springcloud/config' } } stage('cloud-deployment'){ agent any steps{ sh 'sed -i "s/sqshq\\/piggymetrics-gateway/192.168.3.10\\/springcloud\\/gateway/g" yaml/deployment/gateway-deployment.yaml' sh 'sed -i "s/sqshq\\/piggymetrics-config/192.168.3.10\\/springcloud\\/config/g" yaml/deployment/config-deployment.yaml' sh 'kubectl apply -f /var/jenkins_home/workspace/springcloud/yaml/deployment/gateway-deployment.yaml' sh 'kubectl apply -f /var/jenkins_home/workspace/springcloud/yaml/deployment/config-deployment.yaml' sh 'kubectl apply -f /var/jenkins_home/workspace/springcloud/yaml/svc/gateway-svc.yaml' sh 'kubectl apply -f /var/jenkins_home/workspace/springcloud/yaml/svc/config-svc.yaml' } } }}stages:代表整个流水线的所有执行阶段,通常stages只有1个,里面包含多个stage。stage:代表流水线中的某个阶段,可能出现n个。一般分为拉取代码,编译构建,部署等阶段。steps:代表一个阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等任意内容。* *保存流水线文件,配置Webhook触发构建* * *取消勾选 SSL 选择, Add webhook 创建* * 创建成功进行测试,成功后返回 jenkins 会发现流水线已经开始自动构建 * 流水线执行成功 # 流水线构建的项目全部运行[root@k8s-master-node1 ~]# kubectl get pod -n springcloudNAME READY STATUS RESTARTS AGEconfig-77c74dd878-8kl4x 1/1 Running 0 28sgateway-5b46966894-twv5k 1/1 Running 1 (19s ago) 28s[root@k8s-master-node1 ~]# kubectl -n springcloud get serviceNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEconfig NodePort 10.96.137.40 <none> 8888:30015/TCP 4m3sgateway NodePort 10.96.121.82 <none> 4000:30010/TCP 4m4s* *等待 PIg 微服务启动,访问 ip:30010 查看构建成功*2.2.10 服务网格:创建 Ingress Gateway将 Bookinfo 应用部署到 default 命名空间下,请为 Bookinfo 应用创建一个网 关,使外部可以访问 Bookinfo 应用。上传ServiceMesh.tar.gz包[root@k8s-master-node1 ~]# tar -zxvf ServiceMesh.tar.gz[root@k8s-master-node1 ~]# cd ServiceMesh/images/[root@k8s-master-node1 images]# docker load -i image.tar部署Bookinfo应用到kubernetes集群:[root@k8s-master-node1 images]# cd /root/ServiceMesh/[root@k8s-master-node1 ServiceMesh]# kubectl apply -f bookinfo/bookinfo.yamlservice/details createdserviceaccount/bookinfo-details createddeployment.apps/details-v1 createdservice/ratings createdserviceaccount/bookinfo-ratings createddeployment.apps/ratings-v1 createdservice/reviews createdserviceaccount/bookinfo-reviews createddeployment.apps/reviews-v1 createdservice/productpage createdserviceaccount/bookinfo-productpage createddeployment.apps/productpage-v1 created[root@k8s-master-node1 ServiceMesh]# kubectl get podNAME READY STATUS RESTARTS AGEdetails-v1-79f774bdb9-kndm9 1/1 Running 0 7sproductpage-v1-6b746f74dc-bswbx 1/1 Running 0 7sratings-v1-b6994bb9-6hqfn 1/1 Running 0 7sreviews-v1-545db77b95-j72x5 1/1 Running 0 7s[root@k8s-master-node1 ServiceMesh]# vim bookinfo-gateway.yamlapiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata: name: bookinfo-gatewayspec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*"---apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: bookinfospec: hosts: - "*" gateways: - bookinfo-gateway http: - match: - uri: exact: /productpage - uri: prefix: /static - uri: exact: /login - uri: exact: /logout - uri: prefix: /api/v1/products route: # 定义路由转发目的地列表 - destination: host: productpage port: number: 9080[root@k8s-master-node1 ServiceMesh]# kubectl apply -f bookinfo-gateway.yamlgateway.networking.istio.io/bookinfo-gateway createdvirtualservice.networking.istio.io/bookinfo created[root@k8s-master-node1 ServiceMesh]#kubectl get VirtualService bookinfo -o yamlbookinfo-gateway || exact: /productpage || destination || host: productpage || number: 9080[root@k8s-master-node1 ServiceMesh]#kubectl get gateway bookinfo-gateway -o yamlistio: ingressgateway2.2.11 KubeVirt 运维:创建 VM使用提供的镜像在 kubevirt 命名空间下创建一台 VM,名称为 exam,指定 VM 的内存、CPU、网卡和磁盘等配置。[root@k8s-master-node1 ~]# kubectl explain kubevirt.spec. --recursive |grep use useEmulation <boolean>[root@k8s-master-node1 ~]# kubectl -n kubevirt edit kubevirtspec: certificateRotateStrategy: {} configuration: developerConfiguration: #{} useEmulation: true[root@k8s-master-node1 ~]# vim vm.yamlapiVersion: kubevirt.io/v1kind: VirtualMachinemetadata: name: examspec: running: true template: spec: domain: devices: disks: - name: vm disk: {} resources: requests: memory: 1Gi volumes: - name: vm containerDisk: image: fedora-virt:v1.0 imagePullPolicy: IfNotPresent[root@k8s-master-node1 ~]# kubectl apply -f vm.yamlvirtualmachine.kubevirt.io/exam created[root@k8s-master-node1 ~]# kubectl get virtualmachineNAME AGE STATUS READY exam 31s Running True[root@k8s-master-node1 ~]# kubectl delete -f vm.yamlvirtualmachine.kubevirt.io "exam" deleted
zhuzhubaby04
发表于2025-04-07 08:36:56
2025-04-07 08:36:56
最后回复
18