2020年12月

最近听说了两个技术 —— Podman 与 Buildah

本篇博文记录一下学习了解 Podman 的过程,以作备忘

Docker 是很流行的容器技术,它在运行的时候有一个守护进程,需要把服务启动起来,才能通过CLI管理容器,镜像,守护进程负责处理很多的事情,所以就可能有单点故障登风险,当Docker服务程序挂了,依赖它启动的容器就都不能使用了,另外 这篇文章 还列举可能存在的安全隐患。

Podman 是做什么的呢,它无需守护进程,可以用来管理容器,镜像,以下是它的一些特点

无需安装 Docker,安装 Podman 后就可以进行管理
Podman 的命令与 Docker 几乎相同
Docker 下的镜像 Podman 也可以使用
Podman 存储它的镜像和容器与 Docker 的位置不同(即通过 Podman 载入镜像后,用 Docker 查看镜像是看不到的)
Podman 一个很不错的特性是拥有 rootless 模式,非 root 用户也可以使用 Podman 来启动容器,用户和root用户的镜像/容器是互不影响的。

安装

这里是安装文档:Postman 安装

各个发行版都可以很方便的安装方式,比如 Fedora

$ sudo yum -y install podman

安装测试版本

$ sudo yum distro-sync --enablerepo=updates-testing podman
安装好后,应该有个 “Hello World” 来庆祝一下,别急,在国内需要了解一点先行知识

跟Docker一样,不设置源 pull 镜像会很慢,我了解得知有两个配置文件

/etc/containers/registries.conf
~/.config/containers/registries.conf
上边对应的是全局的配置文件,下边的是用户自己的配置文件,如果用户有自己的配置文件则会忽略全局配置文件

内容大概是这样的:

This is a system-wide configuration file used to

keep track of registries for various container backends.

It adheres to TOML format and does not support recursive

lists of registries.

[registries.search]
registries = ['docker.io', 'registry.fedoraproject.org', 'registry.access.redhat.com']

If you need to access insecure registries, add the registry's fully-qualified name.

An insecure registry is one that does not have a valid SSL certificate or only does HTTP.

[registries.insecure]
registries = ['localhost:5000']
我尝试使用国内Docker源来替换Podman的源,会报错,不清楚什么原因

然后我在下载镜像的时候指定源地址加速常用镜像的下载

$ podman pull daocloud.io/library/nginx
启动Nginx容器

$ podman run --name nginx -p 8080:80 -d nginx
打开浏览器访问 http://[服务器ip]:8080 就能看到 Nginx 的欢迎界面了

容器组——Pod

Podman 正如它的名字,其中的 pod 概念与 kubernetes 的 pod 相仿

可以创建一个容器组,然后在容器组里启动容器,可以统一的管理容器,下面使用一下这个功能

创建 Pod

因为 Podman 的容器组需要一个,后台运行的容器,用来保持容器组状态等。

这个小容器名为 “k8s.gcr.io/pause:3.1” 遗憾的是daocloud源里没有,我是到国外的服务器pull下来导出,下载回来再倒入进来的

如果运行了前边的 Nginx 容器,先删除一下

$ podman rm -f nginx

创建 Pod

$ podman pod create --name super_pod -p 8080:80 -p 6379:6379
此处创建了一个名为 super_pod 的容器组,初始化端口号绑定,这个绑定之后不能进行动态的添加

在 pod 里创建 Nginx

$ podman run --name nginx --pod super_pod -d nginx
在 pod 里创建 Redis

$ podman run -d --name redis --pod super_pod -v /etc/localtime:/etc/localtime:ro redis:latest redis-server --requirepass redis --notify-keyspace-events Ex
因为容器组已经绑定了端口号,那么在容器组里面启动的容器则不需要绑定端口

查看 pod 列表

$ podman pod list
查看运行种的 pod 容器信息

$ podman pod top super_pod
值得一提的是,Pod里面的容器,查看它们的 hostname,都为pod的名称

创建临时容器

$ podman run --rm -it --pod super_pod daocloud.io/library/alpine /bin/sh

查看容器的主机名

$ cat /etc/hostname

Out: super_pod

也就是说,容器组里面的容器可以指定容器名来互相访问

开启启动

相较于 Docker 守护进程指定 --restart 来启动容器,Podman 没有守护进程,该如何在系统启动的时候把容器启动呢?—— systemd

此处以启动一个 Redis 服务为例

创建文件及映射目录

$ sudo mkdir -p /opt/containers/var/lib/redis/data$ sudo mkdir -p /opt/containers/var/lib/redis/data
$ sudo chown 1001:1001 /opt/containers/var/lib/redis/data
$ sudo setfacl -m u:1001:-wx /opt/containers/var/lib/redis/data
创建配置文件 /etc/systemd/system/redis-service.service

[Unit]
Description=Redis Podman Container
After=network.target

[Service]
Type=simple
TimeoutStartSec=5m
ExecStartPre=-/usr/bin/podman rm "redis-service"

ExecStart=/usr/bin/podman run --name redis-service -v /opt/containers/var/lib/redis/data:/var/lib/redis/data:Z -e REDIS_PASSWORD=redis --net host daocloud.io/library/redis:latest

ExecReload=-/usr/bin/podman stop "redis-service"
ExecReload=-/usr/bin/podman rm "redis-service"
ExecStop=-/usr/bin/podman stop "redis-service"
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target
防火墙开放访问权限

$ sudo firewall-cmd --zone=public --add-service=redis
启动 Redis

$ sudo systemctl start redis-service
设置开机启动

$ sudo systemctl enable redis-service
另外:

通过 --net host 启动的容器,其它容器访问这个 Redis,可以使用 127.0.0.1 进行连接
systemctl 启动的容器,切换到 root 用户,用 podman ps 可以查看到
参考:

floating-kwaaaay-with-podman-and-systemd

replacing-docker-with-podman-power-of-podman

podman 命令
镜像容器信息流程
ps 子命令 - 列表容器
描述:打印出关于容器的信息

语法参数

Usage:
podman ps [flags]

Flags:
-a, --all Show all the containers, default is only running containers
-f, --filter strings Filter output based on conditions given

  --format string    Pretty-print containers to JSON or using a Go template

-n, --last int Print the n last created containers (all states) (default -1)
-l, --latest Act on the latest container podman is aware of

                     Not supported with the "--remote" flag
  --no-trunc         Display the extended information
  --ns               Display namespace information

-p, --pod Print the ID and name of the pod the containers are associated with
-q, --quiet Print the numeric IDs of the containers only
-s, --size Display the total file sizes

  --sort choice      Sort output by: command, created, id, image, names, runningfor, size, status
  --sync             Sync container state with OCI runtime

-w, --watch uint Watch the ps output on an interval in seconds
Examples:

1.显示所有容器信息并显示容器所属的pod id

podman ps -ap

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES POD ID PODNAME

15e7d3797552 docker.io/mirrorgcrio/pause:3.2 25 hours ago Up 25 hours ago 73c5a062cb17-infra 73c5a062cb17 HelloWorld

2fd059b66fb6 docker.io/library/hello-world:latest /hello 25 hours ago Exited (0) 25 hours ago friendly_neumann 73c5a062cb17 HelloWorld

2.显示容器信息中指定的列

podman ps -ap --format "{{.ID}} {{.Image}} {{.Labels}} {{.Mounts}} {{.PodName}}"

15e7d3797552 docker.io/mirrorgcrio/pause:3.2 map[] [] HelloWorld

2fd059b66fb6 docker.io/library/hello-world:latest map[] [] HelloWorld

3.显示文件的总大小并根据名称进行排序

podman ps --size --sort names

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE

15e7d3797552 docker.io/mirrorgcrio/pause:3.2 25 hours ago Up 25 hours ago 73c5a062cb17-infra 0B (virtual 683kB)

top 子命令 - 显示容器正在运行的进程
描述:

基础语法:

podman top [options] container [format-descriptors]
podman container top [options] container [format-descriptors]

参数

--latest, -l # 显示通过Podman或以外的方式CRI-O运行容器 (The latest option is not supported on the remote client).

FORMAT DESCRIPTORS

args, capbnd, capeff, capinh, capprm, comm, etime, group, hgroup, hpid, huser, label, nice, pcpu, pgid,pid, ppid, rgroup, ruser, seccomp, state, time, tty, user, vsz

capbn:#Set of bounding capabilities. See capabilities (7) for more information.
capeff:#Set of effective capabilities. See capabilities (7) for more information.
capinh:#Set of inheritable capabilities. See capabilities (7) for more information.
capprm:#Set of permitted capabilities. See capabilities (7) for more information.
hgroup:#The corresponding effective group of a container process on the host.
hpid:#The corresponding host PID of a container process.
huser:#The corresponding effective user of a container process on the host.
label:#Current security attributes of the process.
seccomp:#Seccomp mode of the process (i.e., disabled, strict or filter). See seccomp (2) for more information.
state:#Process state codes (e.g, R for running, S for sleeping). See proc(5) for more information.
stime:#Process start time (e.g, "2019-12-09 10:50:36 +0100 CET).
基础实例:

1.默认情况下,podman-top打印的数据类似ps -ef:

$ sudo podman top 15e7d3797552
# USER PID PPID %CPU ELAPSED TTY TIME COMMAND
# 0 1 0 0.000 46h15m55.488413816s ? 0s /pause

2.可以通过在容器后面指定格式描述符作为参数来控制输出:

$ podman top -l pid seccomp args %C
# PID SECCOMP COMMAND %CPU
# 1 filter sh 0.000
# 8 filter vi /etc/ 0.000
$ podman top -l pid seccomp state args %C
# PID SECCOMP STATE COMMAND %CPU
# 1 filter S nginx: master process nginx -g daemon off; 0.000
# 30 filter S nginx: worker process 0.000
# 31 filter S nginx: worker process 0.000

3.如果指定了未知的描述符,Podman将退回到在容器中执行ps(1)。

$ podman top -l -- aux
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
root 1 0 0.000 1h2m12.497061672s ? 0s sleep 100000
status 子命令 - 查看运行中容器资源使用情况
基础演示:

$podman stats nginx
ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO PIDS
19f105d5dc1e nginx -- 2.036MB / 1.893GB 0.11% 978B / 10.55kB -- / -- 2
log 子命令 - 查看容器运行的日志
基础演示:

podman logs nginx
inspect 子命令 - 镜像Image Layer信息
基础案例演示:

$ podman inspect nginx | grep -i "ipaddress"
"SecondaryIPAddresses": null,
"IPAddress": "10.88.0.110",
2.容器操作管理
pod 子命令 - 管理容器组的工具称为pods
描述:podman pod是一组管理pod或容器组的子命令。

SYNOPSIS(n. 概要,大纲)

podman pod subcommand

SUBCOMMANDS

┌────────┬───────────────────────┬─────────────────────────────┐
│Command │ Man Page │ Description │
├────────┼───────────────────────┼─────────────────────────────┤
│create │ podman-pod-create(1) │ Create a new pod. │
├────────┼───────────────────────┼─────────────────────────────┤
│exists │ podman-pod-exists(1) │ Check if a pod exists in local storage. │
├────────┼───────────────────────┼─────────────────────────────┤
│inspect │ podman-pod-inspect(1) │ Displays information describing a pod. │
├────────┼───────────────────────┼─────────────────────────────┤
│kill │ podman-pod-kill(1) │ Kill the main process of each container in one or more pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│pause │ podman-pod-pause(1) │ Pause one or more pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│prune │ podman-pod-prune(1) │ Remove all stopped pods and their containers. │
├────────┼───────────────────────┼─────────────────────────────┤
│ps │ podman-pod-ps(1) │ Prints out information about pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│restart │ podman-pod-restart(1) │ Restart one or more pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│rm │ podman-pod-rm(1) │ Remove one or more stopped pods and containers. │
├────────┼───────────────────────┼─────────────────────────────┤
│start │ podman-pod-start(1) │ Start one or more pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│stats │ podman-pod-stats(1) │ Display a live stream of resource usage stats for containers in one or more pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│stop │ podman-pod-stop(1) │ Stop one or more pods. │
├────────┼───────────────────────┼─────────────────────────────┤
│top │ podman-pod-top(1) │ Display the running processes of containers in a pod. │
├────────┼───────────────────────┼─────────────────────────────┤
│unpause │ podman-pod-unpause(1) │ Unpause one or more pods. │
└────────┴───────────────────────┴─────────────────────────────
基础实例:

创建名称为 HugoBlog 的 pod

podman pod create --name HugoBlog
# 63cb481fd2fd6a02d97355d8f950e765e06654c3b3a25111bc4431320fae897e

列出当前pod信息

podman pod ps
podman pod list
# POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
# 63cb481fd2fd HugoBlog Running 40 minutes ago 2 6b317ba47f5b
# 73c5a062cb17 HelloWorld Running 47 hours ago 2 15e7d3797552

列出指定pod中容器信息

podman pod top 73c5a062cb17
# USER PID PPID %CPU ELAPSED TTY TIME COMMAND
# 0 1 0 0.000 47h27m58.166822731s ? 0s /pause
podman pod top HugoBlog
# USER PID PPID %CPU ELAPSED TTY TIME COMMAND
# 0 1 0 0.000 41m43.871974181s ? 0s /pause
# root 1 0 0.000 41m43.872432777s ? 0s nginx: master process nginx -g daemon off;
# nginx 30 1 0.000 41m43.872491657s ? 0s nginx: worker process
# nginx 31 1 0.000 41m43.87252457s ? 0s nginx: worker process

停止指定pod或者所有pod(其中的容器也随之停止)

podman pod stop HelloWorld
# 73c5a062cb17b5088072ec13c496c101b0b239f9aba1dcad93ba5d746cdfb12d
podman pod stop $(podman pod ps -q)
# 63cb481fd2fd6a02d97355d8f950e765e06654c3b3a25111bc4431320fae897e
# 73c5a062cb17b5088072ec13c496c101b0b239f9aba1dcad93ba5d746cdfb12d

删除指定Pod或者删除所有已经停止的pod

podman pod rm -f HugoBlog
podman pod rm $(podman pod ps -q)
run 子命令 - 容器运行与构建

在指定pod中运行容器

podman run -d --pod HugoBlog nginx:alpine
Trying to pull docker.io/library/nginx:alpine...
Getting image source signatures
Copying blob f682f0660e7a done
...
Copying config 6f715d38cf done
Writing manifest to image destination
Storing signatures
e2a645aa73da2bf98c8e7598a4a1368f92959d18f60b8500c1af70132fb778ed
将 pod 导出为声明式部署清单:

podman generate kube HugoBlog > HugoBlog.yaml
通过部署清单创建 pod:

podman play kube hugo.yaml
cat HugoBlog.yaml

Generation of Kubernetes YAML is still under development!

Save the output of this file and use kubectl create -f to import

it into Kubernetes.

Created with podman-2.0.6

apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-09-23T04:31:52Z"
labels:

app: HugoBlog

name: HugoBlog
spec:
containers:

  • command:

    • nginx
    • -g
    • daemon off;
      env:
    • name: PATH
      value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    • name: TERM
      value: xterm
    • name: NGINX_VERSION
      value: 1.19.2
    • name: NJS_VERSION
      value: 0.4.3
    • name: PKG_RELEASE
      value: "1"
    • name: container
      value: podman
    • name: HOSTNAME
      value: HugoBlog

    image: docker.io/library/nginx:alpine
    name: inspiringkare
    resources: {}
    securityContext:
    allowPrivilegeEscalation: true
    capabilities: {}
    privileged: false
    readOnlyRootFilesystem: false
    seLinuxOptions: {}
    workingDir: /
    status: {}


metadata:
creationTimestamp: null
spec: {}
status:
loadBalancer: {}
这是一个兼容 kubernetes 的 pod 定义,你可以直接通过 kubectl apply -f hugo.yaml 将其部署在 Kubernetes 集群中,也可以直接通过 podman 部署

如果通过声明式定义来创建 pod,还是无法解决服务发现的问题,除非换个支持静态 IP 的 CNI 插件,而支持静态 IP 的这些 CNI 插件又需要 etcd 作为数据库,我就这么点资源,可不想再加个 etcd,还是手撸命令行吧。

container 子命令 - 容器相关操作以及备份导出
基础演示:

Podman 支持将容器从一台机器迁移到另一台机器。

在源机器上对容器设置检查点并将容器打包到指定位置。

$ sudo podman container checkpoint <container_id> -e /tmp/checkpoint.tar.gz

在目标机器上使用源机器上传输过来的打包文件对容器进行恢复。

$ sudo podman container restore -i /tmp/checkpoint.tar.gz

缘起:

很多人可能遇到过开机重启时,由于Docker守护程序在占用多核CPU使用100%C使用的情况,导致所有容器都无法启动,服务都不能用的情况。很悲催的是这事儿虫虫也遇到了,之前文章中虫虫介绍过利用Docker重构WP博客的新架构。由于VPS机器不是很稳定,时常会重启,重启时候就会遇到这个事情,VPS负载很高,容器都没有起来,网站就无法访问了。这时候只能杀掉所有容器并重启守护进程,才能恢复。经过了解该问题是由于Docker守护进程引起,而且Docker守护进程是以root特权权限启动的,是一个安全问题,那么有什么方法解决呢?

为什么Docker需要一个守护进程呢?

Podman,Skopeo和Buildah

这三个工具都是符合OCI计划下的工具(github/containers)。主要是由RedHat推动的,他们配合可以完成Docker所有的功能,而且不需要守护程序或访问有root权限的组,更加安全可靠,是下一代容器容器工具。

Podman

Podman可以替换Docker中了大多数子命令(RUN,PUSH,PULL等)。Podman不需要守护进程,而是使用用户命名空间来模拟容器中的root,无需连接到具有root权限的套接字保证容器的体系安全。

Podman专注于维护和修改OCI镜像的所有命令和功能,例如拉动和标记。它还允许我们创建,运行和维护从这些图像创建的容器。

Buildah

Buildah用来构建OCI图像。虽然Podman也可以用户构建Docker镜像,但是构建速度超慢,并且默认情况下使用vfs存储驱动程序会耗尽大量磁盘空间。 buildah bud(使用Dockerfile构建)则会非常快,并使用覆盖存储驱动程序。

Buildah专注于构建OCI镜像。 Buildah的命令复制了Dockerfile中的所有命令。可以使用Dockerfiles构建镜像,并且不需要任何root权限。 Buildah的最终目标是提供更低级别的coreutils界面来构建图像。Buildah也支持非Dockerfiles构建镜像,可以允许将其他脚本语言集成到构建过程中。 Buildah遵循一个简单的fork-exec模型,不以守护进程运行,但它基于golang中的综合API,可以存储到其他工具中。

Skopeo

Skopeo是一个工具,允许我们通过推,拉和复制镜像来处理Docker和OC镜像。

Podman和Buildah对比

Buildah构建容器,Podman运行容器,Skopeo传输容器镜像。这些都是由Github容器组织维护的开源工具(github/containers)。这些工具都不需要运行守护进程,并且大多数情况下也不需要root访问权限。

Podman和Buildah之间的一个主要区别是他们的容器概念。 Podman允许用户创建"传统容器"。虽然Buildah容器实际上只是为了允许将内容添加回容器图像而创建的。一种简单方法是buildah run命令模拟Dockerfile中的RUN命令,而podman run命令模拟功能中的docker run命令。

简而言之,Buildah是创建OCI图像的有效方式,而Podman允许我们使用熟悉的容器cli命令在生产环境中管理和维护这些图像和容器。

容器迁移

安装

基本上各大发行版都提供了二进制安装包, 使用系统包管理就可以安装:

Fedora, CentOS:sudo yum -y install podman

Arch & Manjaro Linux: sudo pacman -S podman

Ubuntu安装:

sudo apt-get update -qq

sudo apt-get install -qq -y software-properties-common uidmap

sudo add-apt-repository -y ppa:projectatomic/ppa

sudo apt-get update -qq

sudo apt-get -qq -y install podman

迁移步骤

首先,用podman替换了cron和CI作业中的所有docker实例。

完成后第一步后使用sysdig来捕获对docker的引用,看看是否还有其他东西在调用docker:

sysdig | grep -w docker

如果您对性能敏感,这可能会大大降低系统速度。

现在就可以删除docker了:

sudo:yum remove docker

或者

apt remove -y docker-ce

清理配置文件:

删除/etc/apt/或者/etc/yum.repos.d/中指向Docker的源

删除/etc/docker/*,/etc/default/docker和/var/lib/ docker中的任何遗留文件

删除docker组:delgroup docker

总结

使用Podman,Skopeo和Buildah的新一代容器架构后,可以解决由于docker守护程序导致的启动和安全问题。使用新架构后除了"没有守护进程"和"不需要sudo访问"之外,没有发现很多不同之处。构建的容器都位于用户目录下(~/.local/containers中)而不是全局的(在/var/lib/docker中),即面向用户而不是面向守护进程。与Docker相比,podman pull会并行下载获取所有层。

podman初试-和docker对比
1,什么是docker?
Docker 是一个开源的应用容器引擎,属于 Linux 容器的一种封装,Docker 提供简单易用的容器使用接口,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上。容器是完全使用沙箱机制,相互之间不会有任何接口。

2,什么是Podman?
Podman 是一个开源的容器运行时项目,可在大多数 Linux 平台上使用。Podman 提供与 Docker 非常相似的功能。正如前面提到的那样,它不需要在你的系统上运行任何守护进程,并且它也可以在没有 root 权限的情况下运行。
Podman 可以管理和运行任何符合 OCI(Open Container Initiative)规范的容器和容器镜像。Podman 提供了一个与 Docker 兼容的命令行前端来管理 Docker 镜像。

Podman 官网地址:https://podman.io/
Podman 项目地址:https://github.com/containers/libpod
3,Podman 和docker不同之处?
docker 需要在我们的系统上运行一个守护进程(docker daemon),而podman 不需要
启动容器的方式不同:
docker cli 命令通过API跟 Docker Engine(引擎)交互告诉它我想创建一个container,然后docker Engine才会调用OCI container runtime(runc)来启动一个container。这代表container的process(进程)不会是Docker CLI的child process(子进程),而是Docker Engine的child process。
Podman是直接给OCI containner runtime(runc)进行交互来创建container的,所以container process直接是podman的child process。
因为docke有docker daemon,所以docker启动的容器支持--restart策略,但是podman不支持,如果在k8s中就不存在这个问题,我们可以设置pod的重启策略,在系统中我们可以采用编写systemd服务来完成自启动
docker需要使用root用户来创建容器,但是podman不需要
4,podman的安装
4.1,Arch Linux & Manjaro Linux
sudo pacman -S podman
4.2,Fedora,Centos
sudo yum -y install podman
4.3,Gentoo
sudo emerge app-emulation/libpod
4.4,MacOS
brew cask install podman
5,Podman CLI介绍
Podman CLI 里面87%的指令都和DOcker CLI 相同,官方给出了这么个例子alias docker=podman,所以说经常使用DOcker CLI的人使用podman上手非常快

运行一个容器
podman run -dt -p 80:80 --name nginx -v /data:/data -e NGINX_VERSION=1.16 nginx:1.16.0
列出当前所有的容器

podman ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
19f105d5dc1e docker.io/library/nginx:1.16.0 nginx -g daemon o... 2 minutes ago Up 2 minutes ago 0.0.0.0:80->80/tcp nginx
查看一个镜像信息

podman inspect nginx | grep -i "ipaddress"

        "SecondaryIPAddresses": null,
        "IPAddress": "10.88.0.110",

查看容器运行的日志
podman logs nginx
查看运行中容器资源使用情况

podman top nginx

USER PID PPID %CPU ELAPSED TTY TIME COMMAND
root 1 0 0.000 5m26.420969043s pts/0 0s nginx: master process nginx -g daemon off;
nginx 6 1 0.000 5m26.421085502s pts/0 0s nginx: worker process

podman stats nginx

ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO PIDS
19f105d5dc1e nginx -- 2.036MB / 1.893GB 0.11% 978B / 10.55kB -- / -- 2
迁移容器
Podman 支持将容器从一台机器迁移到另一台机器。
首先,在源机器上对容器设置检查点,并将容器打包到指定位置。

$ sudo podman container checkpoint <container_id> -e /tmp/checkpoint.tar.gz
$ scp /tmp/checkpoint.tar.gz <destination_system>:/tmp
其次,在目标机器上使用源机器上传输过来的打包文件对容器进行恢复。

$ sudo podman container restore -i /tmp/checkpoint.tar.gz
podman的程序如何设置自启动
由于 Podman 不再使用守护进程管理服务,所以不能通过守护进程去实现自动重启容器的功能。那如果要实现开机自动重启容器,又该如何实现呢?
其实方法很简单,现在大多数系统都已经采用 Systemd 作为守护进程管理工具。这里我们就可以使用 Systemd 来实现 Podman 开机重启容器,这里我们以刚才启动的nginx为例。
建立一个 Systemd 服务配置文件。

$ vim /etc/systemd/system/nginx_podman.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
接下来,启用这个 Systemd 服务

$ sudo systemctl daemon-reload
$ sudo systemctl enable nginx_podman.service
$ sudo systemctl start nginx_podman.service
之后每次系统重启后 Systemd 都会自动启动这个服务所对应的容器,容器死亡之后也会启动这个容器,我们可以用下面的例子做测试
打一个sleep 30的docker包,这个容器运行起来一次只能坚持30s

$ vim Dockerfile
FROM busybox:latest
CMD ["sh","-c","sleep 30"]
然后按照上述方式设置启动自启动

演示下Podman 下启动的容器为Podman的子进程
我们刚才启动了一个nginx的podman 现在我们来看一下他的进程

ps -ef | grep [n]ginx

root 19368 19359 0 11:38 pts/0 00:00:00 nginx: master process nginx -g daemon off;
101 19381 19368 0 11:38 pts/0 00:00:00 nginx: worker process
然后查看这个nginx的父进程是那个

ps -ef | grep 19359

root 19359 1 0 11:38 ? 00:00:00 /usr/libexec/podman/conmon 。。。。
所以验证了我上面的说法

一.Cockpit简介

1.1基本介绍

Cockpit是一个免费且开源的基于web的管理工具,系统管理员可以执行诸如存储管理、网络配置、检查日志、管理容器等任务。通过Cockpit提供的友好的 Web 前端界面可以轻松地管理我们的 GNU/Linux 服务器,非常轻量级,Web 界面也非常简单易用。更重要的是通过Cockpit可以实现集中式管理。

1.2 功能特点

下面是 Cockpit的一些功能和特点:

Cockpit使用systemd完成从运行守护进程到服务几乎所有的功能
集中式管理,通过一个会话窗口管理网络中的所有Linux服务器
创建和管理Docker容器
创建和管理KVM、oVirt虚拟机
包括 LVM 在内的存储配置
基本的网络配置管理
用户user account管理
基于web的 终端
图形化的系统性能展示
使用sosreport收集系统配置和诊断信息
支持Debian, Redhat, CentOS, Fedora, Atomic, Arch Linux, and Ubuntu.
1.3 模块

以下是Cockpit的一些软件模块,可以根据自己的需要选择性的安装

Package Name Purpose
cockpit-docker Managing Docker Containers
cockpit-kubernetes Visualizing and Configuring Kubernetes Cluster
cockpit-machines Manage KVM Virtual Machines
cockpit-sosreport Create diagnostic report with the sosreport tool
cockpit-selinux Troubleshoot SELinux Issues
cockpit-kdump Configure Kernel Crash Dumps
cockpit-subscriptions Manage System subscription
cockpit-machines-ovirt Manage oVirt Virtual Machines
cockpit-pcp Reading PCP metrics and Loading PCP archives
二. 安装Cockpit

2.1 确认YUM源可用

这里是在CentOS7中进行安装,CentOS的软件仓库中包含有cockpit安装包。

2.2 开始安装

执行以下命令,安装Cockpit和基本的模块

yum -y install cockpit cockpit-dashboard cockpit-storaged cockpit-packagekit

2.3启动cockpit服务

systemctl enable –now cockpit.socket

2.4 添加防火墙规则

执行以下命令

firewall-cmd –permanent –add-service=cockpit

firewall-cmd –reload

如果防火墙未开启,可忽略此步,到这里cockpit就安装完成了。安装过程非常简单。

三. 使用Cockpit

3.1 登录Cockpit

Cockpit使用9090端口,并且为SSL加密访问,通过浏览器登陆https://ip.add.re.ss:9090

登陆时浏览器会提示链接不安全,如果是Firfox浏览器,点击添加例外

添加例外后,就看到cockpit的登陆界面了

输入安装了cockpit的系统账号(用户名和密码和用于登录linux 服务器的用户名和密码相同)

3.2 主界面

主界面是当前主机的系统信息,可以看到CPU,内存,磁盘以及网络的使用情况

3.3 多主机监控

点击左侧上方的仪表板,然后点击右侧的“+”添加需要监控的主机

输入被监控主机的IP或域名进行添加

列表中为所有被管理的服务器

也可以通过主页右上方来切换查看服务器

3.4 功能选项

Cockpit功能选项中的内容取决于都当装有哪些功能模块。

四. 功能介绍

4.1系统页面

系统页面提供主机的硬件系统,负载概览等

点击硬件名称,可以查看系统硬件信息,可以查看系统的PCI设备

4.2 日志查看器Cockpit将日志信息分为错误、警告、注意等不同的分类,可以看出是按事件的级别来分类的

4.3 存储

Cockpit 可以方便地查看硬盘的读写速度。我们可以查看存储的 Journal 日志以便进行故障排除和修复。在页面中还有一个已用空间的可视化图。在存储页面可以卸载、格式化、删除一块硬盘的某个分区。它还有类似创建 RAID 设备、卷组等功能。

4.4 网络

在网络页面可以看到两个可视化发送和接收速度的图。还可以看到可用网卡的列表,可以对网卡进行绑定设置,桥接,以及配置VLAN。点击网卡就可以进行编辑操作。最下面是网络的 Journal 日志信息。

4.5 虚拟机

如果被监控的主机为KVM主机,那么其中运行的虚拟机也可以在cockpit中进行管理操作,在虚拟机页面中会列出当前主机中的所有KVM虚拟机。

4.6 账户

在账号页面中可以添加或删除系统账户

也可以对账号进行编辑

4.7服务

服务被分成了5个类别:目标、系统服务、套接字、计时器和路径

单击服务名称,可以对其进行更多的管理操作,列如重启,关闭,禁用等

4.8 实时终端

Cockpit界面提供实时终端执行任务,这使我们可以根据需求在Web界面和终端之间自由切换,可以快速执行任务,操作非常方便。这是集中式管理的一个具体体现

4.9 Diagnostic Report

通过cockpit的诊断报告功能,可以快速的生成系统的sosreport,并且可以下载到本地

五. 使用Cockpit部署虚拟机

5.1 说明

前面我们对Cockpit进行了整体的介绍,下面我们演示一下如何通过Cockpit进行KVM虚拟机的部署和管理等操作

5.2 创建虚拟机

5.2.1 进入“虚拟机“页面,点击右上方的”Create New VM“按钮创建虚拟机

5.2.2 填写名称,选择安装源,调整内存和硬盘的参数后,点击“Immediately Start VM”,点击“Create”开始创建虚拟机。

5.2.3 Cockpit中提供图形化的远程控制台,在这里可以直接对安装进行操作。同样对于正在运行的VM,也可以通过图形化的远程控制台进行管理操作。

部署完成,虚拟机已经可以正常使用

5.3 编辑虚拟机

在Cockpit中,可以对虚拟机进行简单的配置编辑,比如修改vCPU数量,移除或添加网卡等

5.4 查看虚拟机状态

5.5 总结

Cockpit中只能对虚拟机做简单的配置编辑
虚拟机创建完成后,不能对内存容量进行修改
新建虚拟机时,无法对网卡进行配置,它会自动使用KVM中的默认设置
新建虚拟机时,无法选择安装到哪个存储池,它会将VM自动安装到KVM中默认的存储池中。
对于虚拟机的管理,使用中发现如果安装了 oVirt Virtual Machines的模块,Cockpit中就无法对KVM虚拟机进行管理。 这一点后续会再做一些测试进行验证
在Cockpit中,被管主机可以是物理主机,也可以是虚拟主机,测试中对物理主机,KVM虚拟机和VMware机都进行了测试,都可以正常管理。
另外,在Fedora Server中,系统默认就已经安装了Cockpit