如何把文件传到容器中?
在云容器引擎(CCE)中部署业务应用时,应用通常需要读取配置文件、数据库密码、证书等数据才能正常运行。例如,一个Web应用需要读取数据库连接地址和端口,一个微服务需要加载Nginx配置文件,一个安全组件需要读取TLS证书。这些数据如果直接硬编码在容器镜像中,每次修改都需要重新构建镜像,效率低且不灵活。
CCE基于Kubernetes,提供了多种向Pod中传递数据的方式,使您可以在不重新构建镜像的前提下,灵活地将配置信息、敏感数据和持久化数据注入到容器中。本文将介绍常见的几种数据传递方式及其适用场景,帮助您根据业务需求选择合适的方法。
如何选择数据传递方式
不同场景下推荐的数据传递方式如下:
| 数据类型 | 推荐方式 | 数据是否持久化 | 典型场景 |
|---|---|---|---|
| 非敏感配置参数(少量) | 环境变量 | 否 | 数据库连接地址、超时时间等简单参数 |
| 非敏感配置文件 | ConfigMap | 否 | Nginx配置文件、应用配置文件 |
| 敏感数据(密码、密钥) | Secret | 否 | 数据库密码、TLS证书、API密钥 |
| 需持久化的大体量数据 | PVC | 是 | 数据库数据、日志文件、上传文件 |
| Pod内多容器共享临时数据 | emptyDir | 否 | Init容器与主容器之间的数据传递 |
| 调试或特殊场景 | hostPath | 是 | 访问节点上的Docker socket或系统文件 |
通过环境变量传递数据
环境变量适合传递少量的简单配置参数,如数据库连接地址、端口号等。您可以直接在Pod定义中设置环境变量的值,也可以引用ConfigMap或Secret中的数据作为环境变量。
直接设置环境变量
以下示例将数据库地址和端口通过环境变量直接注入到容器中:
apiVersion: apps/v1
kind: Deployment
metadata:
name: env-deployment
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx:latest
env:
- name: DB_HOST
value: "192.168.1.100"
- name: DB_PORT
value: "3306"
imagePullSecrets:
- name: default-secret 容器启动后,应用程序可通过读取环境变量 DB_HOST 和 DB_PORT 获取数据库连接信息。
从ConfigMap引用环境变量
如果配置参数需要被多个工作负载共享或集中管理,建议先创建ConfigMap,再在工作负载中引用。
- 创建ConfigMap。
apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: default data: DB_HOST: "192.168.1.100" DB_PORT: "3306" LOG_LEVEL: "debug"
- 在工作负载中引用ConfigMap作为环境变量。
apiVersion: apps/v1 kind: Deployment metadata: name: configmap-env-deployment namespace: default spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: containers: - name: myapp image: nginx:latest envFrom: - configMapRef: name: app-config imagePullSecrets: - name: default-secret使用envFrom可以将ConfigMap中的所有键值对一次性注入为环境变量。如果只需引用部分键值,可使用env + configMapKeyRef的方式:
env: - name: DB_HOST valueFrom: configMapKeyRef: name: app-config key: DB_HOST - 工作负载创建完成后,可通过以下命令验证环境变量是否注入成功:
kubectl exec configmap-env-deployment-<pod-name-suffix> -- env | grep DB_HOST
其中<pod-name-suffix>为Pod名称后缀,可通过kubectl get pods -l app=myapp查看。若回显显示DB_HOST=192.168.1.100,说明环境变量注入成功。
通过ConfigMap挂载为配置文件
当您需要将配置文件(如Nginx配置、应用YAML文件)注入到容器中时,可以将ConfigMap挂载为文件到指定目录。
- 创建包含配置文件内容的ConfigMap。
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: default data: nginx.conf: | server { listen 80; server_name localhost; location / { proxy_pass http://backend:8080; } } - 创建工作负载并挂载ConfigMap为文件。
apiVersion: apps/v1 kind: Deployment metadata: name: configmap-volume-deployment namespace: default spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: imagePullSecrets: - name: default-secret containers: - name: nginx image: nginx:latest volumeMounts: - name: config-volume mountPath: /etc/nginx/conf.d volumes: - name: config-volume configMap: name: nginx-config上述配置将ConfigMap中的nginx.conf文件挂载到容器的/etc/nginx/conf.d目录下,容器内的Nginx会自动读取该配置文件。
- 通过以下命令查看挂载的配置文件内容:
kubectl exec configmap-volume-deployment-<pod-name-suffix> -- cat /etc/nginx/conf.d/nginx.conf
若回显显示ConfigMap中定义的Nginx配置内容,说明挂载成功。
通过Secret传递敏感数据
Secret用于存储密码、密钥、证书等敏感信息。Secret中的数据以Base64编码存储,在使用时自动解码为明文注入到容器中。
- 创建Secret。
以下命令创建一个包含数据库用户名和密码的Secret:
kubectl create secret generic db-secret \ --from-literal=username=admin \ --from-literal=password=xxxxx
也可以通过YAML文件创建:
apiVersion: v1 kind: Secret metadata: name: db-secret namespace: default type: Opaque data: username: YWRtaW4= password: TXlQxxxx
YAML方式创建Secret时,data字段的值必须是Base64编码后的字符串。可使用 echo -n 'admin' | base64 命令进行编码。命令行方式(kubectl create secret)创建时会自动编码,无需手动转换。
- 在工作负载中使用Secret。 在工作负载中以环境变量方式引用Secret:
apiVersion: apps/v1 kind: Deployment metadata: name: secret-env-deployment namespace: default spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: imagePullSecrets: - name: default-secret containers: - name: myapp image: nginx:latest env: - name: DB_USERNAME valueFrom: secretKeyRef: name: db-secret key: username - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-secret key: password在工作负载中以文件方式挂载Secret
如果需要将证书文件挂载到容器中(如TLS证书),可以将Secret挂载为文件。
apiVersion: apps/v1 kind: Deployment metadata: name: secret-volume-deployment namespace: default spec: replicas: 2 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: imagePullSecrets: - name: default-secret containers: - name: myapp image: nginx:latest volumeMounts: - name: secret-volume mountPath: /etc/ssl readOnly: true volumes: - name: secret-volume secret: secretName: tls-secret - 通过以下命令验证Secret是否注入成功:
kubectl exec secret-env-deployment-<pod-name-suffix> -- env | grep DB_PASSWORD
若回显显示DB_PASSWORD=xxxxx,说明Secret已成功注入。
通过PVC挂载持久化存储
当需要将大体量数据持久化存储到Pod中,且Pod删除后数据仍需保留时,建议使用PVC挂载持久卷。CCE支持多种存储类型,包括云硬盘(EVS)、弹性文件服务(SFS Turbo)、对象存储(OBS)等。
- 创建PVC。以下示例创建一个使用云硬盘(EVS)存储的PVC,通过CCE提供的 csi-disk StorageClass动态创建云硬盘:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: data-pvc namespace: default annotations: everest.io/disk-volume-type: SSD everest.io/volume-reclaim-policy: retain labels: failure-domain.beta.kubernetes.io/region: <your_region> # 替换为您待部署应用的节点所在的区域 failure-domain.beta.kubernetes.io/zone: <your_zone> # 替换为您待部署应用的节点所在的可用区 spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi storageClassName: csi-disk - 创建工作负载并挂载PVC。
apiVersion: apps/v1 kind: Deployment metadata: name: pvc-deployment namespace: default spec: replicas: 1 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: imagePullSecrets: - name: default-secret containers: - name: myapp image: nginx:latest volumeMounts: - name: data-volume mountPath: /data volumes: - name: data-volume persistentVolumeClaim: claimName: data-pvc上述配置将PVC挂载到容器的 /data 目录,应用程序可将数据写入该目录,数据会持久化到后端存储中,即使Pod被删除,数据也不会丢失。
使用云硬盘(EVS)存储时,PVC的访问模式为ReadWriteOnce,仅支持单节点挂载。如果工作负载replicas大于1,多个副本会争抢同一块云硬盘导致挂载失败。多副本场景请使用SFS Turbo(csi-sfsturbo)或OBS(csi-obs),该类型支持ReadWriteMany多节点读写。
- 通过以下命令验证PVC是否挂载成功:
kubectl get pvc data-pvc
若STATUS显示为 Bound,说明PVC已成功绑定PV。再执行以下命令验证Pod中是否可读写数据:
kubectl exec pvc-deployment-<pod-name-suffix> -- sh -c "echo 'test data' > /data/test.txt && cat /data/test.txt"
若回显显示 test data,说明PVC挂载成功且数据可正常读写。
通过emptyDir共享临时数据
emptyDir用于Pod内多个容器之间共享临时数据。典型场景是Init容器准备数据后,主容器读取使用。
apiVersion: apps/v1
kind: Deployment
metadata:
name: emptydir-deployment
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
imagePullSecrets:
- name: default-secret
volumes:
- name: shared-data
emptyDir: {}
initContainers:
- name: init-container
image: busybox:latest
command: ["/bin/sh", "-c", "echo 'config data' > /shared/config.txt"]
volumeMounts:
- name: shared-data
mountPath: /shared
containers:
- name: main-container
image: nginx:latest
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html 上述示例中,Init容器将配置数据写入 /shared/config.txt,主容器从 /usr/share/nginx/html 目录读取该文件。emptyDir的生命周期与Pod一致,Pod删除后数据随之清除。
您可以通过以下命令验证数据是否共享成功:
kubectl exec emptydir-deployment-<pod-name-suffix> -- cat /usr/share/nginx/html/config.txt
若回显显示 config data,说明数据共享成功。
通过hostPath挂载节点文件
hostPath将节点(宿主机)上的文件或目录直接挂载到Pod中。典型场景包括:容器需要访问节点的Docker socket(如监控容器运行时)、读取节点系统文件(如 /proc、/sys)、或与节点上运行的其他服务共享数据。
hostPath直接访问节点文件系统,存在安全风险。Pod被调度到不同节点时,挂载的数据也不同,可能导致行为不一致。生产环境请优先使用PVC,仅在调试或特殊场景下使用hostPath。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostpath-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
imagePullSecrets:
- name: default-secret
containers:
- name: myapp
image: nginx:latest
volumeMounts:
- name: host-data
mountPath: /host-data
volumes:
- name: host-data
hostPath:
path: /data/node # 节点上的目录或文件路径
type: Directory # 挂载类型,指定路径的存在性校验规则:Directory(必须存在且为目录)、File(必须存在且为文件)、DirectoryOrCreate(不存在则创建目录)、FileOrCreate(不存在则创建文件)、""(不校验,向后兼容) 您可以通过以下命令验证hostPath是否挂载成功:
kubectl exec hostpath-deployment-<pod-name-suffix> -- ls /host-data
若回显显示节点 /data/node 目录下的文件列表,说明挂载成功。也可通过以下命令确认Pod所在节点,再到该节点上验证数据一致性:
kubectl get pod hostpath-deployment-<pod-name-suffix> -o wide
查看NODE列确认Pod调度的节点,登录该节点执行 ls /data/node 对比内容。
相关文档
- 存储概述:了解CCE支持的存储类型(EVS、SFS、OBS)及CSI存储架构。
- 存储基础知识:了解Kubernetes Volume机制及emptyDir、hostPath等存储卷基础概念。
- 通过kubectl连接集群:如需通过kubectl操作集群,请先参考此文档完成连接配置。
- 使用配置项:了解ConfigMap的创建及在工作负载环境变量、数据卷中的使用方法。
- 使用密钥:了解Secret的创建及在工作负载环境变量、数据卷中的使用方法。