跳到主要内容

基于容器、Pod或卷生成Kubernetes YAML

概要

podman kube generate [选项] container... | pod... | volume...

描述

podman kube generate 根据Podman的容器、Pod或卷生成Kubernetes YAML(v1规范)。不论输入是容器还是Pod,Podman默认将规范生成为Pod。输入可以是一个或多个容器、Pod或卷的名称或ID。

Podman 容器或Pod

在生成的YAML中,卷会根据两种不同的卷类型出现。绑定挂载的卷会变成hostPath卷类型,而命名卷会变成persistentVolumeClaim卷类型。生成的hostPath卷类型根据主机路径的状态,分为三种子类型:当主机上不存在文件或目录时,为DirectoryOrCreate;当主机路径是目录时,为Directory;当主机路径是文件时,为File。对于persistentVolumeClaimclaimName值,则是Podman中注册的命名卷的名称。

为了避免潜在的卷名称冲突,每种卷类型都使用标准命名方案。hostPath卷类型根据主机上的路径命名,将正斜杠替换为连字符,并去掉任何前导和尾随的正斜杠。文件系统根目录/的特殊情况,会转换为名称root。此外,名称还会加上-host后缀,以避免与persistentVolumeClaim卷命名冲突。每个persistentVolumeClaim卷类型都使用其关联的命名卷的名称,并加上-pvc后缀。

请注意,如果创建了类型为once的初始化容器,并且Pod已经启动,则它不会显示在生成的kube YAML中,因为once类型的初始化容器在运行后会被删除。如果Pod仅被创建而未被启动,则它会出现在生成的kube YAML中。

使用类型为always的初始化容器始终会在kube YAML中生成,因为它们即使运行完成后也不会被删除。

注意:在SELinux启用的系统上,当使用卷并为非特权和rootless的podman容器生成Kubernetes YAML时,必须完成以下选项之一:

  • 在pod规范中添加"privileged: true"选项
  • 在pod规范的securityContext seLinuxOptions下添加type: spc_t
  • 通过CLI命令chcon -t container_file_t -R <directory>重新标记卷

完成后,当在Kubernetes集群中创建pod/容器时,会有正确的权限来访问该卷。

请注意,生成的Kubernetes YAML文件可以通过podman-play-kube(1)重新运行部署。

另外请注意,如果生成的Pod是使用--infra-name标志创建的,那么生成的kube yaml将具有io.podman.annotations.infra.name设置,其值为用户设置的基础容器名称。

还请注意,Deployment和DaemonSet的restartPolicy只能设置为Always

选项

--filename, -f=filename

将输出写入指定的文件而不是STDOUT。如果文件已存在,kube generate会拒绝替换它并返回错误。

--podman-only

在生成的YAML文件中添加仅Podman使用的保留注解(Kubernetes无法使用)。

--replicas, -r=replica count

在生成Deployment类型时,设置replicas的值。 注意:此选项只能与--type=deployment一起使用。

--service, -s

除了Pods外,还生成一个Kubernetes服务对象。用于为相应的Pod输出生成服务规范。特别是,如果对象具有端口映射绑定,服务规范将包括一个NodePort声明以暴露服务。Podman将在规范中分配一个随机端口。

--type, -t=pod | deployment | daemonset

在YAML文件中生成的Kubernetes类型。目前,唯一支持的Kubernetes规范是PodDeploymentDaemonSet。默认情况下,生成Pod规范。

示例

为指定的容器创建Kubernetes Pod YAML。

$ podman kube generate some-mariadb
# 保存此文件的输出,并使用kubectl create -f将其导入到Kubernetes中。
#
# 使用podman-4.8.2创建

# 注意:如果您在启用了SELinux的系统上从一个非特权和rootless的podman容器生成了这个yaml,
# 请查阅podman generate kube的手册页面,以了解如何确保您的pod/容器具有访问添加的卷的适当权限。
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2024-01-09T02:24:55Z"
labels:
app: some-mariadb-pod
name: some-mariadb-pod
spec:
containers:
- args:
- mariadbd
env:
- name: MARIADB_ROOT_PASSWORD
value: x
image: docker.io/library/mariadb:10.11
name: some-mariadb
ports:
- containerPort: 3306
hostPort: 34891
volumeMounts:
- mountPath: /var/lib/mysql
name: mariadb_data-pvc
volumes:
- name: mariadb_data-pvc
persistentVolumeClaim:
claimName: mariadb_data

在此示例中,我们为名为some-mariadb的容器生成了Kubernetes Pod YAML。生成的YAML文件描述了Pod的规范,包括容器的名称、环境变量、要使用的镜像、暴露的端口以及要挂载的卷。这里假设有一个名为mariadb_data的PersistentVolumeClaim(PVC),它将用于提供持久存储给MariaDB数据库。

请注意,生成的YAML文件中的creationTimestamp是一个占位符,实际部署到Kubernetes集群时,Kubernetes会设置正确的创建时间戳。另外,如果此YAML是从一个非特权和rootless的podman容器在启用了SELinux的系统上生成的,您可能需要按照手册页面的说明进行操作,以确保您的pod/容器具有访问卷的适当权限。

您可以将此YAML文件保存下来,并使用kubectl create -f命令将其导入到Kubernetes集群中。这样,您就可以在Kubernetes环境中运行和管理MariaDB容器了。

为指定的容器创建具有3个副本的Kubernetes Deployment YAML。

$ podman kube generate --type deployment --replicas 3 my-container
# 保存此文件的输出,并使用kubectl create -f将其导入到Kubernetes中。
#
# 使用podman-x.x.x创建
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: "xxxx-xx-xxTxx:xx:xxZ"
labels:
app: my-container-pod
name: my-container-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-container-pod
template:
metadata:
labels:
app: my-container-pod
name: my-container-pod
spec:
containers:
- image: docker.io/library/my-container-image:tag
name: my-container

请注意,上述命令中的my-container应替换为您要为其生成Deployment的实际容器名称,并且docker.io/library/my-container-image:tag应替换为容器的实际镜像名称和标签。此外,creationTimestamp将是一个占位符,实际部署到Kubernetes集群时,Kubernetes会设置正确的创建时间戳。

为指定的容器创建Kubernetes Pod YAML,将主机目录/home/user/my-data绑定挂载到容器路径/volume

$ podman kube generate --filename pod-with-bind-mount.yaml --podman-only my-container-with-data
# 保存此文件的输出为pod-with-bind-mount.yaml,并使用kubectl create -f将其导入到Kubernetes中。
#
# 使用podman-x.x.x创建
apiVersion: v1
kind: Pod
metadata:
labels:
app: my-container-with-data
name: my-container-with-data
spec:
containers:
- image: docker.io/library/my-container-image:tag
name: my-container-with-data
volumeMounts:
- mountPath: /volume
name: my-data-volume
volumes:
- hostPath:
path: /home/user/my-data
type: Directory
name: my-data-volume

同样,my-container-with-data应替换为实际的容器名称,docker.io/library/my-container-image:tag应替换为容器的实际镜像名称和标签。此命令还将输出保存到名为pod-with-bind-mount.yaml的文件中,这是通过--filename选项指定的。如果您不使用此选项,输出将直接打印到终端。

创建具有命名卷 priceless-data 挂载到容器路径 /volume 的指定容器的 Kubernetes Pod YAML 文件:

apiVersion: v1
kind: Pod
metadata:
labels:
app: my-container-using-priceless-data
name: my-container-using-priceless-data
spec:
containers:
- image: docker.io/library/my-container-image:tag
name: my-container
volumeMounts:
- mountPath: /volume
name: priceless-data
volumes:
- name: priceless-data
persistentVolumeClaim:
claimName: priceless-data-pvc
restartPolicy: Never

请注意,您需要将 docker.io/library/my-container-image:tag 替换为您的容器镜像的实际名称和标签。此外,priceless-data-pvc 应为已经存在于您的 Kubernetes 集群中的 PersistentVolumeClaim 的名称。

创建包含服务的指定 Pod 的 Kubernetes Pod YAML 文件:

apiVersion: v1
kind: Pod
metadata:
labels:
app: demoweb
name: demoweb-pod
spec:
containers:
- command:
- python3
- /root/code/graph.py
image: quay.io/baude/demoweb:latest
name: demoweb-container
tty: true
workingDir: /root/code
---
apiVersion: v1
kind: Service
metadata:
labels:
app: demoweb
name: demoweb-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: demoweb
apiVersion: v1
kind: Service
metadata:
labels:
app: demoweb
name: demoweb-service
spec:
ports:
- name: http
port: 80 # Service 监听的端口
targetPort: 8080 # Pod 中容器监听的端口
selector:
app: demoweb # 匹配带有此标签的 Pod
type: NodePort # 如果希望从集群外部访问服务,则使用 NodePort 类型

请注意,如果您想要从集群外部访问这个服务,并且集群允许使用 NodePort,那么您可以在上面的 YAML 中保留 type: NodePort。但是,如果您仅在集群内部需要访问这个服务,您可以将 type 改为 ClusterIP

targetPort: 0 意味着 Service 将尝试自动发现 Pod 中容器的端口。但是,为了明确性和可靠性,通常建议明确指定 targetPort

对于 nodePort: 31269,它表示在集群的每个节点上,该服务都将在 31269 端口上可访问。如果您没有特殊需求,通常不需要手动设置这个值,Kubernetes 会为您自动分配一个可用的 NodePort。

status 字段通常是由 Kubernetes 集群自动填充的,因此在创建 Service 时通常不需要包含它。

请确保将 quay.io/baude/demoweb:latest 替换为实际要使用的镜像,并根据您的应用程序的实际需要调整服务端口和目标端口。

另请参阅

podman(1), podman-container(1), podman-pod(1), podman-kube-play(1), podman-kube-down(1)

历史

2018年12月,最初由Brent Baude整理编写