podman

podman

什么是podman?

官网 podman (podman.io)
​ Podman是一个开源项目,可以在大多数Linux平台上使用,可将代码放在[GitHub]上。Podman 是一个无守护容器引擎,用于在 Linux 系统上开发、管理和运行开放容器计划 (OCI) 容器和容器映像。Podman 提供了一个与 Docker 兼容的命令行前端,可以简单地别名 Docker cli,alias docker=podman。Podman还提供了套接字激活的REST API服务,以允许远程应用程序启动按需容器。这个REST API还支持Docker API,允许docker-py和docker-compose的用户与Podman即服务进行交互。

​ Podman 控制下的容器可以由 root 用户运行,也可以由非特权用户运行。Podman 使用[libpod]库管理整个容器生态系统,包括 Pod、容器、容器映像和容器卷。Podman 专注于帮助您维护和修改 OCI 容器映像的所有命令和功能,例如拉取和标记。它允许您在生产环境中创建、运行和维护从这些映像创建的容器。

​ Podman服务仅在Linux平台上运行,但是podman远程REST API客户端存在于Mac和Windows平台上,并且可以通过ssh与Linux机器或VM上运行的Podman服务进行通信。

podman与docker的区别

​podman(Pod Manager)是一个由RedHat公司推出的容器管理工具,它的定位就是docker的替代品,在使用上与docker的体验类似。 podman源于CRI-O项目,可以直接访问OCI的实现(如runC),流程比docker要短。 二者主要的区别在于,podman是一个开源的产品;而docker已经是商业化的产品。 podman的开源代码,由RedHat的OpenShift项目维护。 podman.io上面的文档还不算很健全,作为普通开发者,将其当成docker去用,难度也不算很大。
Podman 原来是 CRI-O 项目的一部分,后来被分离成一个单独的项目叫 libpod。Podman 的使用体验和 Docker 类似,不同的是 Podman 没有 daemon。以前使用 Docker CLI 的时候,Docker CLI 会通过 gRPC API 去跟 Docker Engine 说「我要启动一个容器」,然后 Docker Engine 才会通过 OCI Container runtime(默认是 runc)来启动一个容器。这就意味着容器的进程不可能是 Docker CLI 的子进程,而是 Docker Engine 的子进程。

Podman 比较简单粗暴,它不使用 Daemon,而是直接通过 OCI runtime(默认也是 runc)来启动容器,所以容器的进程是 podman 的子进程。这比较像 Linux 的 fork/exec 模型,而 Docker 采用的是 C/S(客户端/服务器)模型。与 C/S 模型相比,fork/exec 模型有很多优势,比如:

系统管理员可以知道某个容器进程到底是谁启动的。
如果利用 cgroup 对 podman 做一些限制,那么所有创建的容器都会被限制。
SD_NOTIFY : 如果将 podman 命令放入 systemd 单元文件中,容器进程可以通过 podman 返回通知,表明服务已准备好接收任务。
socket 激活 : 可以将连接的 socket 从 systemd 传递到 podman,并传递到容器进程以便使用它们。

概述和范围
从高层次上讲,libpod 和 Podman 的范围如下:

支持多种镜像格式,包括 OCI 和 Docker 镜像格式。
支持多种安全下载图像的方法,包括信任和图像验证。
容器映像管理(管理映像层、覆盖文件系统等)。
全面管理容器生命周期。
支持 Pod 一起管理容器组。
容器和 Pod 的资源隔离。
路线图
有关 podman pod 命令的进一步工作。
无根容器的进一步改进。
支持无根 Podman 与 NFS Homedirs。
支持原生叠加层上的无根 Podman。
增强了图像的加速拉取功能。
Podman 程序,用于设置用于在 Mac 和 Linux 上运行 nativley 的 VM。podman -remote run
podman的安装

podman 安装 (podman.io)

podman 在 CentOS 7 的默认 Extras 存储库中可用,在 CentOS 8 和 Stream 的 AppStream 存储库中可用。

[root@localhost ~]# dnf -y install podma

[root@localhost ~]# rpm -qa | grep podman
podman-3.4.1-3.module_el8.6.0+954+963caf36.x86_64
podman-catatonit-3.4.1-3.module_el8.6.0+954+963caf36.x86_64

# 我们可以给podman定义一个别名叫docker
[root@localhost ~]# alias docker=podman
[root@localhost ~]# docker images
REPOSITORY               TAG         IMAGE ID      CREATED      SIZE

[root@localhost ~]# podman images
REPOSITORY               TAG         IMAGE ID      CREATED      SIZE

查看帮助

[root@localhost ~]# podman --help
Manage pods, containers and images

Usage:
  podman [options] [command]

Available Commands:
  attach      Attach to a running container
  auto-update Auto update containers according to their auto-update policy
  build       Build an image using instructions from Containerfiles
  ...... 

查看帮助文档

[root@localhost ~]# man podman
......

# 查看子命令,示例(example),比如查看 podman run
[root@localhost ~]# man podman-run
.......

poman 的常用命令:
Podman可以使用一些简单的关键字在远程官方仓库上搜索镜像

podman search <search_term>

[root@localhost ~]# podman search nginx
INDEX              NAME                                                          DESCRIPTION                                      STARS       OFFICIAL    AUTOMATED
fedoraproject.org  registry.fedoraproject.org/f29/nginx                                                                           0                       
fedoraproject.org  registry.fedoraproject.org/f29/origin-nginx-router                                                             0                       
redhat.com         registry.access.redhat.com/ubi8/nginx-120                     Platform for running nginx 1.20 or building ...  0                       
redhat.com         registry.access.redhat.com/ubi8/nginx-118                     Platform for running nginx 1.18 or building ...  0                       
redhat.com         registry.access.redhat.com/rhscl/nginx-110-rhel7              Nginx container image that delivers an nginx...  0                       
redhat.com         registry.access.redhat.com/rhscl/nginx-16-rhel7               Nginx 1.6 server and a reverse proxy server      0                       
redhat.com         registry.access.redhat.com/rhscl/nginx-18-rhel7               Nginx 1.8 server and a reverse proxy server      0                       
......
# 搜索的镜像有多个拉取地址,所以拉取的时候要指定具体的地址

还可以使用过滤器增强搜索:

podman search httpd --filter=is-official

[root@localhost ~]# podman search nginx --filter=is-official
INDEX       NAME                     DESCRIPTION               STARS       OFFICIAL    AUTOMATED
docker.io   docker.io/library/nginx  Official build of Nginx.  15928       [OK]        

下载(拉取)镜像

[root@localhost ~]# podman pull docker.io/library/nginx
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
Copying blob 44be98c0fab6 done  
Copying blob 77700c52c969 done  
Copying blob 881ff011f1c9 done  
Copying blob 21e0df283cd6 done  
Copying blob ed835de16acd done  
Copying blob e5ae68f74026 done  
Copying config f652ca386e done  
Writing manifest to image destination
Storing signatures
f652ca386ed135a4cbe356333e08ef0816f81b2ac8d0619af01e2b256837ed3e

# 注意:Podman在不同的注册管理机构中搜索。因此,建议使用完整的映像名称(docker.io/library/httpd而不是httpd)来确保使用正确的映像。

列出本机上存在的所有镜像

[root@localhost ~]# podman images
REPOSITORY               TAG         IMAGE ID      CREATED      SIZE
docker.io/library/nginx  latest      f652ca386ed1  11 days ago  146 MB

运行容器
示例容器将运行一个非常基本的 nginx 服务器,该服务器仅为其索引页提供服务

[root@localhost ~]# podman run -d -p 80:80 docker.io/library/nginx:latest
1bd8ab38aee91dc8951ffb5054263d5c015240edf4e460f8f3b73e97d1315186

列出正在运行的容器
该命令用于列出已创建和正在运行的容器。podman ps

[root@localhost ~]# podman ps 
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS             PORTS               NAMES
1bd8ab38aee9  docker.io/library/nginx:latest  nginx -g daemon o...  12 seconds ago  Up 12 seconds ago  0.0.0.0:80->80/tcp  silly_hodgkin

podman ps -a Podman 将显示所有容器(已创建、已退出、正在运行等)
测试nginx容器

[root@localhost ~]# curl 10.88.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
......

检查正在运行的容器

我们可以"检查"正在运行的容器,以查找有关其自身的元数据和详细信息。 将提供许多有用的信息,如环境变量,网络设置或分配的资源。podman inspect
由于容器在root模式下运行,因此会为容器分配 IP 地址

[root@localhost ~]# podman inspect -l |grep -i ipaddress
            "IPAddress": "10.88.0.2",
                    "IPAddress": "10.88.0.2",

注意:这是最新容器的便利参数。还可以使用容器的 ID 或名称,而不是 long 参数 。-l–latest。-i(忽略大小写)
查看容器的日志
我们也可以使用 Podman 查看容器的日志

[root@localhost ~]# podman logs -l
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/12/14 09:58:49 [notice] 1#1: using the "epoll" event method
2021/12/14 09:58:49 [notice] 1#1: nginx/1.21.4
2021/12/14 09:58:49 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2021/12/14 09:58:49 [notice] 1#1: OS: Linux 4.18.0-257.el8.x86_64

查看容器的 pids
我们可以使用 观察到 容器中的 httpd pid。podman top

[root@localhost ~]# podman top -l
USER        PID         PPID        %CPU        ELAPSED           TTY         TIME        COMMAND
root        1           0           0.000       13m14.971739378s  ?           0s          nginx: master process nginx -g daemon off; 
nginx       31          1           0.000       13m14.971907176s  ?           0s          nginx: worker process 
nginx       32          1           0.000       13m14.971945217s  ?           0s          nginx: worker process 
nginx       33          1           0.000       13m14.971979506s  ?           0s          nginx: worker process 
nginx       34          1           0.000       13m14.972010694s  ?           0s          nginx: worker process 

停止容器

我们可以停止容器:

[root@localhost ~]# podman stop -l
1bd8ab38aee91dc8951ffb5054263d5c015240edf4e460f8f3b73e97d1315186

我们可以使用该命令检查一个或多个容器的状态。在这种情况下,应使用参数列出所有容器。podman ps``-a

[root@localhost ~]#  podman ps -a
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS                     PORTS               NAMES
1bd8ab38aee9  docker.io/library/nginx:latest  nginx -g daemon o...  14 minutes ago  Exited (0) 44 seconds ago  0.0.0.0:80->80/tcp  silly_hodgkin

删除容器

最后,我们可以删除容器:

[root@localhost ~]# podman rm -l
1bd8ab38aee91dc8951ffb5054263d5c015240edf4e460f8f3b73e97d1315186

我们可以通过运行 来验证容器的删除。podman ps -a

[root@localhost ~]# podman ps -a
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

镜像修改标签(改名)

[root@localhost ~]# podman images
REPOSITORY               TAG         IMAGE ID      CREATED      SIZE
docker.io/library/nginx  latest      f652ca386ed1  11 days ago  146 MB

[root@localhost ~]# podman tag docker.io/library/nginx:latest docker.io/luojiatian1904/nginx:v1.0
[root@localhost ~]# podman images
REPOSITORY                      TAG         IMAGE ID      CREATED      SIZE
docker.io/library/nginx         latest      f652ca386ed1  11 days ago  146 MB
docker.io/yanghaixx/nginx  v1.0        f652ca386ed1  11 days ago  146 MB

普通用户使用podman的方式
在允许没有root特权的用户运行Podman之前,管理员必须安装或构建Podman并完成以下配置

cgroup V2Linux内核功能允许用户限制普通用户容器可以使用的资源,如果使用cgroup V2启用了运行Podman的Linux发行版,则可能需要更改默认的OCI运行时。某些较旧的版本runc不适用于cgroup V2,必须切换到备用OCI运行时crun。

[root@localhost ~]# dnf -y install crun     # centos8系统自带

[root@localhost ~]# vim /usr/share/containers/containers.conf 
......
446 # Default OCI runtime
447 # 
448 runtime = "crun"      # 取消注释并将值改为crun
......

[root@localhost ~]# podman run -d -p 80 docker.io/library/nginx
19272fbe35e39748c4fc0aff191f16fb60dbfac43c5cd101400c197f89348bca

[root@localhost ~]# podman inspect -l | grep crun
        "OCIRuntime": "crun",
            "crun",

slirp4netns

slirp4netns包为普通用户提供一种网络模式

[root@localhost ~]# rpm -qa| grep slirp4netns
slirp4netns-1.1.8-1.module_el8.6.0+926+8bef8ae7.x86_64

安装fuse-overlayfs
在普通用户环境中使用Podman时,建议使用fuse-overlayfs而不是VFS文件系统,至少需要版本0.7.6。现在新版本默认就是

[root@localhost ~]# rpm -qa |grep fuse-overlayfs
fuse-overlayfs-1.7.1-1.module_el8.6.0+926+8bef8ae7.x86_64

[root@localhost ~]# vim /etc/containers/storage.conf
......
77 mount_program = "/usr/bin/fuse-overlayfs"     # 取消注释
......

/etc/subuid和/etc/subgid配置

Podman要求运行它的用户在/etc/subuid和/etc/subgid文件中列出一系列UID,shadow-utils或newuid包提供这些文件

[root@localhost ~]# rpm -qa| grep shadow-utils
shadow-utils-4.6-12.el8.x86_64

# 可以在/etc/subuid和/etc/subgid查看,每个用户的值必须唯一且没有任何重叠。

[root@localhost ~]# podman exec -it -l /bin/bash
root@ae278ef29b94:/# id
uid=0(root) gid=0(root) groups=0(root)
root@ae278ef29b94:/# useradd jtluo 
root@ae278ef29b94:/# cat /etc/subuid
yanghaixx:100000:65536
root@ae278ef29b94:/# useradd yanghaix
root@ae278ef29b94:/# cat /etc/subuid
yanghaixx:100000:65536
yanghaix:165536:65536

该文件的格式为USERNAME:UID:RANGE

在/ etc / passwd或getpwent中列出的用户名。
为用户分配的初始uid。
为用户分配的UID范围的大小
用户的配置文件

三个主要的配置文件是container.conf,storage.conf和registries.conf。用户可以根据需要修改这些文件。

container.conf

Podman读取时,按照循序来了,当前面一位找不到时,就去找下一个

1./usr/share/containers/containers.conf
2./etc/containers/containers.conf
3.$HOME/.config/containers/containers.conf

storage.conf

storge.conf则是

/etc/containers/storage.conf
$HOME/.config/containers/storage.conf

在普通用户中/etc/containers/storage.conf的一些字段将被忽略

graphroot=``""`` ``container storage graph ``dir` `(default: ``"/var/lib/containers/storage"``)`` ``Default directory to store all writable content created by container storage programs.` `runroot=``""`` ``container storage run ``dir` `(default: ``"/run/containers/storage"``)`` ``Default directory to store all temporary writable content created by container storage programs.

在普通用户中这些字段默认

graphroot=``"$HOME/.local/share/containers/storage"``runroot=``"$XDG_RUNTIME_DIR/containers"

registries.conf

配置按此顺序读入,这些文件不是默认创建的,可以从/usr/share/containers或复制文件/etc/containers并进行修改

1./etc/containers/registries.conf
2./etc/containers/registries.d/*
3.HOME/.config/containers/registries.conf

授权文件

podman login 登录,默认授权文件在${XDG_RUNTIME_DIR}/containers/auth.json

[root@localhost ~]# cat /run/user/0/containers/auth.json 
{
	"auths": {
		"docker.io": {
			"auth": "********************="
		}
	}
}

podman容器开机自启(root用户与普通用户)

# root用户
[root@localhost ~]# podman run -d -p 80:80 --name nginx docker.io/luojiatian1904/nginx:v1.0
b8398459737417195a9ae7e732b1249a30120c28b91498620f83124788683f4b
[root@localhost ~]# podman ps
CONTAINER ID  IMAGE                                COMMAND               CREATED        STATUS            PORTS               NAMES
b83984597374  docker.io/luojiatian1904/nginx:v1.0  nginx -g daemon o...  9 seconds ago  Up 9 seconds ago  0.0.0.0:80->80/tcp  nginx
配置启动文件
[root@localhost ~]# vim /etc/systemd/system/nginx_conteainer.service
[Unit]
Description=Podman Nginx Service
After=network.target
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/podman start -a nginx
ExecStop=/usr/bin/podman stop -t 10 nginx
Restart=always

[Install]
WantedBy=multi-user.target
重新加载并启动查看
[root@localhost ~]# systemctl daemon-reload 
[root@localhost ~]# systemctl enable --now nginx_conteainer.service 
Created symlink /etc/systemd/system/multi-user.target.wants/nginx_conteainer.service → /etc/systemd/system/nginx_conteainer.service.
#普通用户
[root@localhost ~]# su - yang
[yang@localhost ~]$ 
启动容器
[yang@localhost ~]$  podman run -d --name nginx docker.io/library/nginx
7efac7f3394716f36c46350f3baf00cdd09ebe2764ce0b1f65cc9dac1a0d94cc
[yang@localhost ~]$ podman ps 
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS             PORTS       NAMES
7efac7f33947  docker.io/library/nginx:latest  nginx -g daemon o...  21 seconds ago  Up 21 seconds ago              nginx
生成启动配置文件
[yang@localhost ~]$ mkdir -p .config/systemd/user
[yang@localhost ~]$ cd .config/systemd/user/
[yang@localhost user]$ podman generate  systemd --files --name nginx /home/test/.config/systemd/user/container-nginx.service
[yang@localhost user]$ cat container-nginx.service 
# container-nginx.service
# autogenerated by Podman 3.4.1-dev
# Wed Dec 15 07:09:59 EST 2021

[Unit]
Description=Podman container-nginx.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=/tmp/podman-run-1001/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman start nginx
ExecStop=/usr/bin/podman stop -t 10 nginx
ExecStopPost=/usr/bin/podman stop -t 10 nginx
PIDFile=/tmp/podman-run-1001/containers/overlay-containers/7efac7f3394716f36c46350f3baf00cdd09ebe2764ce0b1f65cc9dac1a0d94cc/userdata/conmon.pid
Type=forking

[Install]
WantedBy=multi-user.target default.target
远程连接用户
[root@localhost ~]# ssh jtluo@localhost
yang@localhost's password: 
Activate the web console with: systemctl enable --now cockpit.socket

Last failed login: Wed Dec 15 07:17:27 EST 2021 from ::1 on ssh:notty
There were 4 failed login attempts since the last successful login.
Last login: Wed Dec 15 07:15:16 2021

设置开机自启
[yang@localhost ~]$  systemctl --user enable --now container-nginx.service 
Created symlink /home/yang/.config/systemd/user/multi-user.target.wants/container-nginx.service → /home/yang/.config/systemd/user/container-nginx.service.
Created symlink /home/yang/.config/systemd/user/default.target.wants/container-nginx.service → /home/yang/.config/systemd/user/container-nginx.service.

podman网络

指定网络运行容器
创建podman网络

# 创建cni-podman2网络
[root@localhost ~]# podman network create cni-podman2
/etc/cni/net.d/cni-podman2.conflist
# --subnet指定subnet创建网络
[root@localhost ~]# podman network create --subnet 192.168.2.0/24 newnet
/etc/cni/net.d/newnet.conflist
# --gateway 指定网关
[root@localhost ~]# podman network create --subnet 192.168.3.0/24 --gateway 192.168.3.1 newnet1 
/etc/cni/net.d/newnet1.conflist
# --ip-range 指定ip起始地址
[root@localhost ~]# podman network create --subnet 192.168.4.0/24 --ip-range 192.168.4.128/25 newnet2
/etc/cni/net.d/newnet2.conflist
# 查看网络
[root@localhost ~]# podman network ls
NETWORK ID    NAME         VERSION     PLUGINS
2f259bab93aa  podman       0.4.0       bridge,portmap,firewall,tuning
603e960751dc  cni-podman2  0.4.0       bridge,portmap,firewall,tuning
884e74728f04  newnet       0.4.0       bridge,portmap,firewall,tuning
45b3499a170b  newnet1      0.4.0       bridge,portmap,firewall,tuning
31213d4efd11  newnet2      0.4.0       bridge,portmap,firewall,tuning
使用创建的网络运行容器并查看信息
[root@localhost ~]# podman run -d --name nginx1 --network cni-podman2 docker.io/yanghaixx/nginx:v1.0 
409fd6f1ca50e183bd118054571b9de9ba4f0ea87acfe1f327ba1ae643039853
[root@localhost ~]# podman inspect nginx1 |grep  IP    
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
                    "IPAddress": "10.89.0.2",
                    "IPPrefixLen": 24,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "IPAMConfig": null,

podman网络管理
启动一个容器后,会出现cni-poman0网卡,容器启动时,默认会连接podman网络

[root@localhost ~]# ip a show cni-podman0
5: cni-podman0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 2e:fa:c6:75:44:f7 brd ff:ff:ff:ff:ff:ff
    inet 10.88.0.1/16 brd 10.88.255.255 scope global cni-podman0
       valid_lft forever preferred_lft forever
    inet6 fe80::2cfa:c6ff:fe75:44f7/64 scope link 
       valid_lft forever preferred_lft forever
#ls查看容器网路
[root@localhost ~]#  podman network ls
NETWORK ID    NAME         VERSION     PLUGINS
2f259bab93aa  podman       0.4.0       bridge,portmap,firewall,tuning
603e960751dc  cni-podman2  0.4.0       bridge,portmap,firewall,tuning
884e74728f04  newnet       0.4.0       bridge,portmap,firewall,tuning
45b3499a170b  newnet1      0.4.0       bridge,portmap,firewall,tuning
31213d4efd11  newnet2      0.4.0       bridge,portmap,firewall,tuning
#disconnect断开网络
[root@localhost ~]# podman network disconnect cni-podman2 nginx1
#reload重启容器网络
[root@localhost ~]# podman network reload  nginx1
409fd6f1ca50e183bd118054571b9de9ba4f0ea87acfe1f327ba1ae643039853
#rm删除podman网络
[root@localhost ~]# podman network rm newnet2
newnet2
[root@localhost ~]# podman network ls
NETWORK ID    NAME         VERSION     PLUGINS
2f259bab93aa  podman       0.4.0       bridge,portmap,firewall,tuning
603e960751dc  cni-podman2  0.4.0       bridge,portmap,firewall,tuning
884e74728f04  newnet       0.4.0       bridge,portmap,firewall,tuning
45b3499a170b  newnet1      0.4.0       bridge,portmap,firewall,tuning
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值