狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

一文詳解:項目如何從Docker慢慢演變成了K8s部署

freeflydom
2025年2月11日 9:53 本文熱度 744

今天,我們將深入探討一個項目部署的演變過程。在這篇文章中,為了緊扣主題,我們將從 Docker 開始講解,分析為什么一個傳統(tǒng)的項目逐步演變成了今天流行的 Kubernetes(K8s)集群部署架構(gòu)。我們將通過一個簡單的 Java 項目來闡述這一過程。

為了更清晰地闡述,我在本地搭建了一個 gRPC 入門項目。考慮到篇幅和內(nèi)容的專注性,我將這一部分的詳細講解單獨撰寫成了一篇文章。具體內(nèi)容可以參考這篇文章獲取更多信息和背景知識:https://www.cnblogs.com/guoxiaoyu/p/18555031

接下來,我們將逐步展開,深入講解從 Docker 容器化到 K8s 集群化的過渡,分析這個過程中面臨的挑戰(zhàn)和技術(shù)演進,并討論為什么 Kubernetes 已經(jīng)成為現(xiàn)代云原生應(yīng)用部署的標配。

好了,現(xiàn)在我們正式開始本篇文章的講解。

Docker

這部分內(nèi)容大家應(yīng)該都比較熟悉了。對于個人開發(fā)者來說,Docker幾乎是每個項目中不可或缺的一部分,學(xué)習(xí)如何使用 Docker 命令是每個開發(fā)者的必修課。因此,關(guān)于 Docker 的安裝過程,我就不再贅述了。大家可以根據(jù)官方文檔或者教程輕松完成安裝,過程也相對簡單明了。

在使用 Docker 進行項目部署時,首先需要一個名為 Dockerfile 的配置文件,它定義了如何構(gòu)建和封裝項目容器。具體內(nèi)容如下:

# 使用官方的 OpenJDK 鏡像作為基礎(chǔ)鏡像
FROM openjdk:8-jdk-alpine
# 將構(gòu)建好的Spring Boot JAR文件復(fù)制到容器中
COPY grpc-server/target/grpc-server-1.0-SNAPSHOT.jar /app/grpc-server-1.0-SNAPSHOT.jar
# 設(shè)置工作目錄
WORKDIR /app
# 暴露 gRPC 應(yīng)用程序的端口
EXPOSE 9090
# 運行 gRPC 服務(wù)
CMD ["java", "-jar", "grpc-server-1.0-SNAPSHOT.jar"]

在使用 Maven 編譯和打包 Java 項目時,如果我們需要啟動一個可執(zhí)行的 JAR 包,就必須指定一個入口類,即啟動類。我們需要單獨配置一個編譯插件,通常是 spring-boot-maven-plugin(如果是 Spring Boot 項目)。

這樣做可以確保在執(zhí)行 mvn package 命令時,Maven 會將啟動類作為項目的入口,并生成正確的可執(zhí)行 JAR 文件。以下是一個配置示例:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

接下來,我們正常執(zhí)行mvn命令即可。執(zhí)行完后,我們通常可以在服務(wù)器上直接通過docker命令進行構(gòu)建docker鏡像。這樣所有環(huán)境集成都有了,直接啟動docker鏡像即可。跟我們本地的環(huán)境一點關(guān)系沒有。命令如下:

mvn clean package

docker build -t grpc-server .

docker run -p 9090:9090 -v /data/logs:/app/logs grpc-server

過程如圖所示:

我們暴露出來了一個服務(wù)器端口供外網(wǎng)調(diào)用。這里我測試一下,是正常的,效果如圖所示:

綜合上述所有條件,我們可以得出一個重要結(jié)論:Docker 在環(huán)境隔離方面確實具有顯著的優(yōu)勢。通過 Docker,我們無需在本地系統(tǒng)上手動安裝和配置各種依賴環(huán)境,從而避免了因環(huán)境配置不同而導(dǎo)致的問題。只需要執(zhí)行一個簡單的 Docker 命令,就能自動拉取所需的鏡像并啟動項目,這大大簡化了開發(fā)和部署過程。

尤其是對于大多數(shù)開源項目而言,幾乎都提供了官方或社區(qū)維護的 Docker 鏡像,這使得用戶能夠快速入門,無需深入了解復(fù)雜的配置細節(jié)。

那么問題來了?

公司項目的部署遠遠不止于簡單地啟動一個 Docker 容器,而是涉及到多個復(fù)雜的組件和服務(wù)的協(xié)同工作。具體來說,除了 Docker 容器之外,我們通常還需要部署和配置 Nginx、前端服務(wù)、后端服務(wù)、數(shù)據(jù)庫等一系列基礎(chǔ)設(shè)施組件。每個項目都會根據(jù)實際需求涉及到不同的服務(wù)和環(huán)境配置,處理起來并不簡單。

更重要的是,考慮到每次部署時可能都需要執(zhí)行大量的命令來啟動這些服務(wù),難道我們真的要把這些命令手動記錄在記事本中,然后每次上線時都逐一敲入這些命令嗎?看下這段命令:

docker run -d \
  --name grpc-server-container \                 # 設(shè)置容器名稱
  -p 9090:9090 \                                 # 映射容器的 9090 端口到主機的 9090 端口
  -p 8080:8080 \                                 # 映射容器的 8080 端口到主機的 8080 端口
  -v /data/logs:/logs \                          # 將主機的 /data/logs 目錄掛載到容器的 /logs 目錄
  -v /path/to/app/config:/app/config \           # 掛載應(yīng)用配置文件夾
  -v /path/to/db:/var/lib/postgresql/data \      # 將主機數(shù)據(jù)庫目錄掛載到容器的數(shù)據(jù)庫目錄
  -e LOG_LEVEL=debug \                           # 設(shè)置環(huán)境變量 LOG_LEVEL
  -e DB_USER=admin \                             # 設(shè)置數(shù)據(jù)庫用戶名環(huán)境變量
  --restart unless-stopped \                     # 設(shè)置容器的重啟策略,除非手動停止,否則容器會自動重啟
  --network host \                               # 使用主機網(wǎng)絡(luò)模式,可以與主機共享網(wǎng)絡(luò)資源
  --log-driver=json-file \                       # 設(shè)置日志驅(qū)動為 json-file(默認)
  grpc-server                                    # 使用 grpc-server 鏡像

那么,針對這種繁瑣的手動輸入命令和配置的情況,是否存在一些工具或者方式,能夠幫助我們提前將這些命令和配置都寫好,并且每次只需執(zhí)行一個文件,就能順利啟動整個項目,避免重復(fù)操作和人為失誤呢?

答案是肯定的,正是基于這種需求,我們有了 Docker Compose 這樣的編排工具。

Docker-compose

編排文件采用一種固定的格式來書寫,目的是確保 Docker 在執(zhí)行時能夠正確地識別和啟動所需的所有服務(wù)和容器。

接下來,我們將以 grpc-server 項目為例,展示如何將該項目配置到 Docker Compose 的編排文件中,文件內(nèi)容如下:

version: '3.8'
services:
  grpc-server:
    image: grpc-server           # 使用 grpc-server 鏡像
    ports:
      - "9090:9090"              # 映射端口 9090
    volumes:
      - /data/logs:/app/logs         # 掛載主機目錄 /data/logs 到容器的 /logs 目錄
    restart: unless-stopped      # 如果容器停止,除非手動停止,否則會重新啟動容器

其實,這個過程非常簡單和直觀。如果你需要啟動多個容器,只需在 Docker Compose 的編排文件中繼續(xù)添加相應(yīng)的服務(wù)配置,每個服務(wù)都會自動與其他服務(wù)進行協(xié)同工作。

對于每個容器的配置,你只需按需擴展,每新增一個容器,只要在文件中繼續(xù)添加對應(yīng)的服務(wù)定義即可,這樣一來,整個項目中的所有服務(wù)都會被包含在編排文件內(nèi),實現(xiàn)一次性啟動多個容器。命令如下:

啟動多個指定容器:

docker-compose up

后臺啟動所有容器:

docker-compose up -d

通過使用編排文件,我們幾乎不再需要手動維護各種 Docker 啟動命令,而是可以通過統(tǒng)一的配置文件進行管理和部署。這種方式的最大優(yōu)點在于,它顯著簡化了普通 Docker 啟動命令的維護和執(zhí)行過程,避免了手動操作帶來的復(fù)雜性和出錯風(fēng)險。

同時,這種自動化的部署方法基本上解決了小型公司在項目部署中的諸多困難,使得項目的部署更加高效、穩(wěn)定和可重復(fù),從而大大提升了團隊的生產(chǎn)力和項目的交付速度。

那么問題來了

盡管項目本身的復(fù)雜度沒有顯著增加,但隨著用戶量的不斷上升,我們面臨的挑戰(zhàn)也隨之加劇。由于機器的帶寬和內(nèi)存是有限的,單純依靠一個 Docker 實例已經(jīng)無法滿足當前用戶的訪問需求。在這種情況下,我們通常需要通過增加機器來進行水平擴展,通常是在新的機器上重新執(zhí)行相同的部署命令。

然而,這種反復(fù)手動操作的方式會導(dǎo)致運維人員的工作量呈指數(shù)級增長,每次版本發(fā)布和擴容時,運維人員不僅需要投入大量的精力,還容易感到身心疲憊,工作負擔(dān)越來越重,效率也大大降低。

正因如此,集群部署的需求變得尤為迫切,而 Kubernetes(K8s)作為現(xiàn)代化容器編排平臺應(yīng)運而生,并迅速成為解決這一問題的利器。

K8s

很多人其實也聽說過Docker Swarm,它是Docker原生的集群部署方式,具有一定的自動化和容錯能力,但相比于Google設(shè)計的Kubernetes(K8s),其功能和生態(tài)系統(tǒng)的完善程度明顯不足,因此未能獲得像K8s那樣廣泛的應(yīng)用和好評。

話不多說,我們現(xiàn)在回到重點,繼續(xù)深入講解K8s的部署方式。為了方便演示,我已經(jīng)在本地提前配置好了一個簡化版的K8s環(huán)境,接下來的內(nèi)容將不再贅述其具體安裝過程。

如果對Kubernetes(K8s)還不太了解的朋友,可以先參考我之前寫的這篇文章,它將幫助你快速掌握K8s的基本概念和架構(gòu):https://www.cnblogs.com/guoxiaoyu/p/17876335.html

面臨的一個實際問題是:大多數(shù)人手中都有現(xiàn)成的Docker Compose編排文件,而如何將這些文件高效地遷移到K8s環(huán)境中呢?幸運的是,這里有一個非常流行的工具,它能夠幫助你輕松實現(xiàn)這一遷移,不需要手動編寫復(fù)雜的K8s部署文件或進行繁瑣的配置。

kompose:Convert your Docker Compose file to Kubernetes

Kompose的主要目標就是幫助開發(fā)者快速將現(xiàn)有的Docker Compose編排文件轉(zhuǎn)換為Kubernetes(K8s)所需的資源配置文件,簡化從Docker Compose到K8s的遷移過程。我們看下如何使用,需要通過以下命令安裝Kompose:

Linux:curl -L https://github.com/kubernetes/kompose/releases/download/v1.34.0/kompose-linux-amd64 -o kompose

Linux ARM64:curl -L https://github.com/kubernetes/kompose/releases/download/v1.34.0/kompose-linux-arm64 -o kompose

chmod +x kompose

sudo mv ./kompose /usr/local/bin/kompose

上面的命令執(zhí)行完后,基本上我們就可以正常使用了。效果如圖所示:

我們直接通過執(zhí)行文件的方式轉(zhuǎn)化我們的編排文件。命令如下:

kompose convert -f docker-compose.yaml

執(zhí)行完后,通常情況下官方的教程是直接就可以進行kubelet apply部署,但是注意一些坑,我們一起來看下。

首先,在 Kubernetes 中,每個容器都可以通過掛載目錄來持久化其數(shù)據(jù)。盡管 Kubernetes 默認會將容器的日志存儲在 /var/log/containers/ 目錄下,但對于像 MySQL 這樣的數(shù)據(jù)庫服務(wù),僅依賴 Kubernetes 自帶的日志目錄是不足夠的。因為容器的重啟或停啟操作可能會導(dǎo)致數(shù)據(jù)丟失,因此必須通過掛載持久化存儲卷(例如,使用 Persistent Volumes 或 HostPath 等方式)來保證數(shù)據(jù)庫的數(shù)據(jù)安全和持久性。

在本示例中,我僅僅是為了演示目的,簡單地掛載了日志目錄,而未涉及更復(fù)雜的數(shù)據(jù)存儲掛載配置。

數(shù)據(jù)掛載

這里有幾個新的關(guān)鍵名詞,在之前我是沒有講過的,如下:

PV(Persistent Volume):是一個具體的存儲資源(可以是本地磁盤、云存儲等),由管理員配置。PV 存儲的內(nèi)容是持久化的,不會因容器的銷毀而丟失。

PVC(Persistent Volume Claim):是用戶或應(yīng)用向 Kubernetes 請求存儲資源的方式。用戶聲明他們需要多大的存儲、訪問模式等,Kubernetes 會根據(jù)這些要求找到合適的 PV。

PV 與 PVC 的關(guān)系:PVC 向 Kubernetes 提出存儲需求。PV 提供實際的存儲資源,且由 Kubernetes 根據(jù) PVC 的要求動態(tài)綁定。

通過將 PVC 掛載到 Pod 中,容器就能使用持久化存儲的數(shù)據(jù)。通過這種方式,Kubernetes 可以高效地管理存儲,確保容器應(yīng)用的數(shù)據(jù)不會丟失,即使容器被銷毀或重新部署,數(shù)據(jù)仍然得以保留。

為了實現(xiàn)文件共享和數(shù)據(jù)存儲,我們需要搭建一個NFS(Network File System)服務(wù)器。這個服務(wù)器可以選擇由云服務(wù)商提供,也可以使用本地服務(wù)器的磁盤資源。在本例中,我們將以本地服務(wù)器為例,詳細介紹如何搭建一個NFS 服務(wù)器,并進行相關(guān)配置。

NFS 服務(wù)器

我們不能直接使用kubelet apply部署,相反,我們需要對 PVC 文件進行一定的修改,以確保它能夠正確地創(chuàng)建所需的存儲資源。具體來說,我們需要在 PVC 文件中指定使用的 StorageClass。

使用以下命令獲取當時集群的StorageClass,如果無StorageClass則需要先創(chuàng)建。

kubelet get storageclass

因為我這是剛搭建的K8s環(huán)境,所以我這里顯示的是沒有,那么先搭建一個本地NFS服務(wù)器。

查看系統(tǒng)是否已安裝NFS

rpm -qa | grep nfs

rpm -qa | grep rpcbind

安裝NFS 、RPC

yum -y install nfs-utils rpcbind

啟動服務(wù)

systemctl start nfs rpcbind

創(chuàng)建目錄

mkdir -p /nfs-server/log/

chmod 666 /nfs-server/log/

編輯export文件

vim /etc/exports

/nfs-server *(rw,sync,no_root_squash)

配置生效

exportfs -r

啟動rpcbind、nfs服務(wù)

systemctl restart rpcbind

systemctl restart nfs

自我測試一下是否可以聯(lián)機

showmount -e localhost

測試效果正常:

Storageclass啟動

首先,我們需要啟動StorageClass,文件內(nèi)容如下:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
provisioner: kubernetes.io/nfs
parameters:
  server: 192.168.56.5
  path: /nfs-server

可以看到這里是以本地IP為NFS服務(wù)器的。直接使用命令啟動即可。

k apply -f st.yaml

kubectl get storageclass

效果如下,啟動成功:

PV啟動

然后配置一下pv文件,并啟動:

kind: PersistentVolume
apiVersion: v1
metadata:
  name: nfs-pv-test
  namespace: database
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 1.5Gi
  persistentVolumeReclaimPolicy: Retain
  storageClassName: nfs
  nfs:
    path: /nfs-server/log
    server: 192.168.56.5

kubectl apply -f pv.yaml

啟動成功,效果如圖所示:

項目啟動

接下來,我們就需要啟動當時kompose生成的三個文件,我們挨個執(zhí)行,命令如下:

k apply -f grpc-server-xiaoyu-claim0-persistentvolumeclaim.yaml

k apply -f grpc-server-xiaoyu-deployment.yaml

k apply -f grpc-server-xiaoyu-service.yaml

最后,正常啟動service服務(wù)后可以看到正常分配了內(nèi)網(wǎng)ip,但并不會被外網(wǎng)訪問到。

為了方便演示,我們簡單修改一下grpc-server-xiaoyu-service.yaml,讓外網(wǎng)ip可以訪問到,內(nèi)容如下:

apiVersion: v1
kind: Service
metadata:
  annotations:
    kompose.cmd: kompose convert -f docker-compose.yml
    kompose.version: 1.34.0 (cbf2835db)
  labels:
    io.kompose.service: grpc-server-xiaoyu
  name: grpc-server-xiaoyu
spec:
  ports:
    - name: "9091"
      port: 9093
      targetPort: 9093
  type: NodePort
  selector:
    io.kompose.service: grpc-server-xiaoyu

再次啟動,效果如圖所示:

最后啟動成功:

改下我們本地的連接端口:

public class Main {
    public static void main(String[] args) {
        ManagedChannel channel = ManagedChannelBuilder.forAddress("192.168.56.5", 30238)
                .usePlaintext()
                .build();
        // 創(chuàng)建一元式阻塞式存根
        GreeterGrpc.GreeterBlockingStub blockingStub = GreeterGrpc.newBlockingStub(channel);
        // 創(chuàng)建請求對象
        HelloRequest request = HelloRequest.newBuilder()
                .setName("World")
                .build();
        // 發(fā)送請求麥位列表信息并接收響應(yīng)
        HelloReply response = blockingStub.sayHello(request);
        // 處理麥位列表信息響應(yīng)
        System.out.println("Received  response: " + response);
    }
}

日志輸出成功:

在 Kubernetes 中,容器的日志默認存儲在宿主機的 /var/log/containers/ 目錄下。每個容器的日志文件名通常包括容器的名稱、Pod 名稱、命名空間和容器運行的唯一標識符(例如 Pod 的 UID)。這種路徑結(jié)構(gòu)確保了每個容器的日志都是唯一的,不會與其他容器的日志混合。

我們看下默認日志目錄下生成的日志。

由于我們已經(jīng)成功掛載了數(shù)據(jù)盤,因此相應(yīng)的掛載目錄也已創(chuàng)建并可供使用。效果如圖所示:

動態(tài)擴容

為了應(yīng)對容器編排中可能出現(xiàn)的容器實例數(shù)量增加的問題,Kubernetes 提供了靈活的擴展機制,既可以通過自動擴容來根據(jù)負載自動增加或減少容器實例數(shù)量,也可以通過手動擴容的方式來快速響應(yīng)突發(fā)的高并發(fā)用戶訪問需求。

在此,我們將演示如何手動增加容器實例的數(shù)量。命令如下:

kubectl scale deployment grpc-server-xiaoyu --replicas=2

執(zhí)行成功,效果如圖所示:

總體而言,Kubernetes 以其靈活性和強大的功能,基本上已經(jīng)能夠滿足現(xiàn)代化項目的絕大部分需求,尤其是在容器實例擴展和自動化管理等方面,極大地降低了手動干預(yù)的復(fù)雜度。

那么問題來了

綜上所述,雖然 Kubernetes(K8s)在日常運維和管理方面為開發(fā)者和運維團隊提供了極大的便利,自動化的擴展、負載均衡、容錯處理等功能也大大提升了系統(tǒng)的可靠性和可維護性,但在初期的服務(wù)器搭建和集群配置過程中,K8s 的復(fù)雜性卻無可避免地帶來了不少挑戰(zhàn)。

由于 K8s 本身是一個高度模塊化的系統(tǒng),其組件間的依賴性較強,任何一項配置錯誤都可能導(dǎo)致集群運行異常。這就增加了集群部署和維護的難度,尤其對于中小型企業(yè)或者缺乏深厚運維經(jīng)驗的團隊來說,如何快速部署并確保集群穩(wěn)定性,依然是一個需要解決的難題。那么,面對這一挑戰(zhàn),如何能夠降低 K8s 部署和管理的門檻,并使其更易于使用呢?

上云

在這方面,實際上不必過多贅述。當前,各大云服務(wù)提供商的 Kubernetes 集群部署服務(wù)已經(jīng)相當成熟,基本上能夠滿足絕大多數(shù)企業(yè)對集群服務(wù)的需求,并且提供了完善的生態(tài)支持。比如,監(jiān)控與報警系統(tǒng)、日志收集、自動化擴容、負載均衡等一整套解決方案,幾乎涵蓋了現(xiàn)代化應(yīng)用所需的所有基礎(chǔ)設(shè)施和運維功能。

相較于自行搭建和管理 Kubernetes 集群,使用云廠商提供的服務(wù)無疑是更加便捷和高效的。只需通過云平臺的控制臺進行幾次點擊,相關(guān)服務(wù)就能自動化部署,極大地縮短了上線周期。對于技術(shù)團隊來說,這種便捷的集群部署方式,幾乎可以做到即插即用,快速上手,降低了對復(fù)雜操作和配置的依賴。

此外,云服務(wù)商通常都會提供豐富的官方文檔支持,幫助用戶解決常見問題。在遇到更復(fù)雜的情況時,用戶還能直接提交工單,享受一對一的專屬技術(shù)支持,這對于解決實際運維中的疑難問題至關(guān)重要。因此,相比于傳統(tǒng)的自行搭建集群,云服務(wù)的方案在穩(wěn)定性、易用性和服務(wù)質(zhì)量上都有著無可比擬的優(yōu)勢。

總結(jié)

通過本文的深入探討,我們已經(jīng)詳細了解了一個項目從 Docker 容器化到 Kubernetes 集群化的演變過程。在這個過程中,我們不僅分析了 Docker 的基礎(chǔ)使用方法和 Docker Compose 的便捷性,還介紹了 Kubernetes 在處理大型、復(fù)雜系統(tǒng)中的重要作用。

雖然 Kubernetes 在初期的配置和維護上可能帶來一定的復(fù)雜性,但隨著云服務(wù)的成熟,各大云平臺提供了全面的 Kubernetes 集群管理解決方案,極大地簡化了部署流程。云服務(wù)商的自動化工具和技術(shù)支持,幫助企業(yè)快速上手 Kubernetes,避免了許多傳統(tǒng)集群部署中的難題。

因此,Kubernetes 已經(jīng)成為現(xiàn)代云原生應(yīng)用部署的標配,它的靈活性、擴展性和高度自動化特性,使得它在容器編排和微服務(wù)架構(gòu)的管理中占據(jù)了無可替代的地位。對于開發(fā)者來說,掌握 Kubernetes 是未來工作中不可或缺的一項技能,它不僅能提高項目的交付速度,還能有效降低運維復(fù)雜度,為企業(yè)提供更高效、可靠的服務(wù)。

最后,無論采用何種方式,我們都應(yīng)根據(jù)實際情況出發(fā),避免盲目追求華而不實,無論是 Docker、編排工具,還是 Kubernetes,總有一種方式最適合你的需求。

?https://www.cnblogs.com/guoxiaoyu/p/18562675


該文章在 2025/2/11 10:01:46 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved