macOS 终于可以完美使用 Podman 了!

2024-03-17 00:32

本文主要是介绍macOS 终于可以完美使用 Podman 了!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


更多奇技淫巧欢迎订阅博客:https://fuckcloudnative.io

前言

Podman 是一个无守护程序与 Docker 命令兼容的下一代 Linux 容器工具,该项目由 RedHat 主导,其他的细节可以参考 Podman 使用指南[1],本文的重点不是这个。

Podman 一直以来只能跑在 Linux 系统上,macOSWindows 只能通过 CLI 远程连接 Podman 的 API 来管理容器。事实上 Docker 也不支持 macOS 和 Windows,但 Docker 针对 Windows 和 macOS 推出了专门的客户端,客户端里面集成了虚拟化相关的设置,通过嵌套一层虚拟化来支持 Docker。对于 Podman 来说,想要在 macOS 上运行也只能通过虚拟化来实现,网上也有不少方案,基本上都是通过 Virtualbox 来实现,都不太优雅。本文将介绍一种相对更优雅的方案,虽然不是很完美,但我已经尽力做到接近完美了。。

HyperKit 介绍

HyperKit 是一个具有 hyperisor 能力的轻量级虚拟化工具集,包含了基于 xhyve(The BSD Hypervisor)的完整 hypervisor。HyperKit 设计成上层组件诸如 VPNKit[2] 和 DataKit[3] 的接口。xhyve 是 基于 bhyve 的 Mac OS X 移植版本,而 bhyve 又是 FreeBSD 下的虚拟化技术。。。

我们知道,Docker 在 Linux 上利用了 Linux 原生支持的容器方式实现资源和环境的隔离,直接利用宿主内核,性能接近原生。然而,在 macOS 上却仍然需要虚拟化的技术。早期的 Docker 干脆直接在开源的 VirtualBox 中构建虚拟机,性能低下。后期的 Docker 基于轻量化的虚拟化框架 HyperKit[4] 开发,据说性能得到很大提升。

本文将介绍如何通过 HyperKit 来使用 Podman。方法也很简单,先通过 Hyperkit 创建一个轻量级虚拟机,然后在虚拟机中安装 Podman,并开启 remote API,最后在本地通过 CLI 连接虚拟机中的 Podman。这和 macOS 中的 Docker 实现原理是一样的,只不过 Podman 是没有 Daemon 的,与 Docker 相比可以节省不少资源。

2. 安装 HyperKit

你可以自己下载源代码编译 HyperKit,但我不建议这么做,不同的 macOS 版本会遇到各种各样的错误。我这里推荐两种超级简单的方法:

  1. 直接通过安装 Docker 来获得 HyperKit,因为 Docker Desktop on Mac 就是基于 HyperKit 实现的,所以安装 Docker Desktop on Mac 就能够获得完整的 HyperKit 运行环境。整个过程会非常顺畅和简单。安装完 Docker 之后可以永远不用打开 Docker,直接使用 HyperKit 就好。或者你可以直接卸载 Docker,卸载之前先把 hyperkit 二进制文件备份出来,因为卸载 Docker 也会删掉 hyperkit 二进制文件。

  2. 直接通过安装 Multipass 来获得 HyperKit。Multipass 是 Canonical 公司(Ubuntu)开发的基于不同操作系统内建原生 Hypervisor 实现的工作站。由于 Windows(Hyper-V),macOS(hyperkit)和 Linux(KVM)都原生支持 hypervisor,这样通过 multipass shell 命令就能够在一个 shell 中实现创建运行 Ubuntu 虚拟机。在 macOS 平台,默认的后端是 hyperkit,需要 macOS Yosemite (10.10.3) 以上版本并且需要安装在 2010 以后生产的 Mac 设备。安装方法很简单:

$ brew cask install multipass

安装好了之后可以在 /Library/Application Support/com.canonical.multipass/bin/ 目录下找到 hyperkit 二进制文件。

3. 创建虚拟机

你可以直接通过 hyperkit 来创建虚拟机,但参数比较复杂,有兴趣的自己研究吧。我推荐直接通过 multipass 来创建,命令特别简单:

$ multipass launch -c 2 -d 10G -m 2G -n podman
  • -n : 指定启动实例名字

  • -c : 分配 CPU 数量

  • -d : 设置磁盘容量

  • -m : 设置内存容量

第一次启动虚拟机的时候会去拉去镜像,国内网速可能会很慢。

查看已经启动的虚拟机:

$ multipass list
Name                    State             IPv4             Image
podman                  Running           192.168.64.2     Ubuntu 20.04 LTS

进入虚拟机:

$ multipass shell podman
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-52-generic x86_64)* Documentation:  https://help.ubuntu.com* Management:     https://landscape.canonical.com* Support:        https://ubuntu.com/advantageSystem information as of Sun Nov  8 19:30:29 CST 2020System load:  0.0                Processes:               119Usage of /:   13.4% of 11.46GB   Users logged in:         0Memory usage: 11%                IPv4 address for enp0s2: 192.168.64.2Swap usage:   0%0 updates can be installed immediately.
0 of these updates are security updates.Last login: Sun Nov  8 17:38:31 2020 from 192.168.64.1
ubuntu@podman:~$

4. 安装 Podman

在虚拟机中安装 Podman:

ubuntu@podman:~$ . /etc/os-release
ubuntu@podman:~$ echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
ubuntu@podman:~$ curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -
ubuntu@podman:~$ sudo apt-get update
ubuntu@podman:~$ sudo apt-get -y upgrade
ubuntu@podman:~$ sudo apt-get -y install podman

5. 建立 Podman Socket

Podman 依赖于 systemd 的 socket activation[5] 特性。假设 Daemon B 依赖于 Daemon A,那么它就必须等到 Daemon A 完成启动后才能启动。socket activation的思想就是:Daemon B 启动时其实并不需要 Daemon A 真正运行起来,它只需要 Daemon A 建立的 socket 处于 listen 状态就 OK 了。而这个 socket 不必由 Daemon A 建立, 而是由 systemd 在系统初始化时就建立。当 Daemon B 发起启动时发起连接,systemd 再将 Daemon A 启动,当 Daemon A 启动后,再将 socket 归还给 Daemon A。

Podman 会通过 podman.socket 先创建一个处于监听状态的 socket 文件 /run/podman/podman.sock,当有进程向该 socket 发起连接时,systemd 会启动同名的 service:podman.service,以接管该 socket。先看看 podman.socket 和 podman.service 长啥样:

ubuntu@podman:~$ sudo systemctl cat podman.socket
# /lib/systemd/system/podman.socket
[Unit]
Description=Podman API Socket
Documentation=man:podman-system-service(1)[Socket]
ListenStream=%t/podman/podman.sock
SocketMode=0660[Install]
WantedBy=sockets.targetubuntu@podman:~$ sudo systemctl cat podman.service
# /lib/systemd/system/podman.service
[Unit]
Description=Podman API Service
Requires=podman.socket
After=podman.socket
Documentation=man:podman-system-service(1)
StartLimitIntervalSec=0[Service]
Type=notify
KillMode=process
ExecStart=/usr/bin/podman system service

设置开机自启 podman.socket,并立即启动:

ubuntu@podman:~$ sudo systemctl enable podman.socket --now

确认 socket 是否正处于监听状态:

ubuntu@podman:~$ podman --remote info
host:arch: amd64buildahVersion: 1.16.1cgroupManager: systemdcgroupVersion: v1conmon:package: 'conmon: /usr/libexec/podman/conmon'path: /usr/libexec/podman/conmonversion: 'conmon version 2.0.20, commit: 'cpus: 2...

3. 客户端 CLI 设置

接下来所有的设置,如不作特殊说明,都在 macOS 本地终端执行。

Podman 远程连接依赖 SSH,所以需要设置免密登录,先生成秘钥文件:

$ ssh-keygen -t rsa   # 一路回车到底

然后将本地的公钥 ~/.ssh/id_rsa.pub 追加到虚拟机的 /root/.ssh/authorized_keys 文件中。

安装 Podman CLI:

$ brew install podman

添加远程连接:

$ podman system connection add ubuntu --identity ~/.ssh/id_rsa ssh://root@192.168.64.2/run/podman/podman.sock

查看已经建立的连接:

$ podman system connection list
Name     Identity                 URI
podman*  /Users/Ryan/.ssh/id_rsa  ssh://root@192.168.64.2:22/run/podman/podman.sock

由于这是第一个连接,所以被直接设置为默认连接(podman 后面加了 *)。

测试远程连接是否可用:

$ podman ps
CONTAINER ID  IMAGE   COMMAND  CREATED  STATUS  PORTS   NAMES$ podman pull nginx:alpine
Trying to pull docker.io/library/nginx:alpine...
Getting image source signatures
Copying blob sha256:188c0c94c7c576fff0792aca7ec73d67a2f7f4cb3a6e53a84559337260b36964
Copying blob sha256:9dd8e8e549988a3e2c521f27f805b7a03d909d185bb01cdb4a4029e5a6702919
Copying blob sha256:85defa007a8b33f817a5113210cca4aca6681b721d4b44dc94928c265959d7d5
Copying blob sha256:f2dc206a393cd74df3fea6d4c1d3cefe209979e8dbcceb4893ec9eadcc10bc14
Copying blob sha256:0ca72de6f95718a4bd36e45f03fffa98e53819be7e75cb8cd1bcb0705b845939
Copying config sha256:e5dcd7aa4b5e5d2df8152b9e58aba32a05edd9b269816f5d8b7ced535743d16c
Writing manifest to image destination
Storing signatures
e5dcd7aa4b5e5d2df8152b9e58aba32a05edd9b269816f5d8b7ced535743d16c$ podman image ls
REPOSITORY                TAG     IMAGE ID      CREATED      SIZE
docker.io/library/nginx   alpine  e5dcd7aa4b5e  2 days ago   23.3 MB

现在我们就可以直接在本地用 podman 愉快地玩耍了!

如果你建立了多个连接,可用使用 --connection 参数指定远程连接,或者使用 podman system connection default <NAME> 来设置默认的远程连接。

最后,我们来看看 hyperkit 的内存占用:

物理内存只占用了 921M,如果你觉得这个内存占用很多,不妨去对比下 Docker Desktop 的内存占用。

总结

本文介绍了在 macOS 中使用 podman 的方法,通过 HyperKit 创建 Ubuntu 虚拟机运行 Podman,并建立 Podman Socket,然后客户端通过 SSH 连接服务端的 Socket,以实现通过远程连接来管理容器。

参考资料

[1]

Podman 使用指南: https://fuckcloudnative.io/posts/podman-sidecar/

[2]

VPNKit: https://github.com/moby/vpnkit

[3]

DataKit: https://github.com/moby/datakit

[4]

HyperKit: https://github.com/moby/hyperkit

[5]

socket activation: http://0pointer.de/blog/projects/socket-activation.html


你可能还喜欢

点击下方图片即可阅读

天天叨叨云原生,你知道云原生是啥么?

云原生是一种信仰 ????

码关注公众号

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具,只需一条命令,连 ssh 都不需要!

点击 "阅读原文" 获取更好的阅读体验!

❤️给个「在看」,是对我最大的支持❤️

这篇关于macOS 终于可以完美使用 Podman 了!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/817259

相关文章

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

golang1.23版本之前 Timer Reset方法无法正确使用

《golang1.23版本之前TimerReset方法无法正确使用》在Go1.23之前,使用`time.Reset`函数时需要先调用`Stop`并明确从timer的channel中抽取出东西,以避... 目录golang1.23 之前 Reset ​到底有什么问题golang1.23 之前到底应该如何正确的

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

python管理工具之conda安装部署及使用详解

《python管理工具之conda安装部署及使用详解》这篇文章详细介绍了如何安装和使用conda来管理Python环境,它涵盖了从安装部署、镜像源配置到具体的conda使用方法,包括创建、激活、安装包... 目录pytpshheraerUhon管理工具:conda部署+使用一、安装部署1、 下载2、 安装3