您现在的位置是:首页 > 文章详情

Pod定义与ConfigMap

日期:2018-06-17点击:379

Pod的作用

在k8s中pod是最小的管理单位,在一个pod中通常会包含一个或多个容器。
在每一个Pod中都有一个特殊的Pause容器和一个或多个业务容器,Pause来源于pause-amd64镜像,Pause容器在Pod中具有非常重要的作用:

  • Pause容器作为Pod容器的根容器,其本地于业务容器无关,它的状态代表了整个pod的状态。
  • Pod里的多个业务容器共享Pause容器的IP,每个Pod被分配一个独立的IP地址,Pod中的每个容器共享网络命名空间,包括IP地址和网络端口。Pod内的容器可以使用localhost相互通信。k8s支持底层网络集群内任意两个Pod之间进行通信。
  • Pod中的所有容器都可以访问共享volumes,允许这些容器共享数据。volumes还用于Pod中的数据持久化,以防其中一个容器需要重新启动而丢失数据。

    kubernetes 的对象定义一般都用YAML或JSON格式的文件,可以使用这个网址验证yaml语法:https://codebeautify.org/yaml-validator

Pod的定义

Kubernetes中所有的资源对象都可以采用YAML或者JSON格式的文件来定义。
我们可以定义含有单个服务容器的pod,但是在另一种场景中,当两个服务应用为紧耦合的关系时,应该将他们组合成一个整体对外提供服务,如下定义,将两个容器打包为一个pod:

apiVersion: v1 kind: Pod metadata: name: redis-php labels: name: redis-php spec: hostNetwork: true # 指定可以通过宿主机访问pod中的服务 containers: - name: frontend image: kubeguide/guestbook-php-frontend:localredis ports: - containerPort: 80 # 指定宿主机映射端口。在不与hostNetwork: true 同时使用时可以指定任意端口,但是在某些使用CNI插件的情况下可能不会生效。 # 与hostNetwork使用的时候,只能与容器端口一致,且可以省略,一般只在测试时使用。 hostPort: 80 - name: redis image: kubeguide/redis-master ports: - containerPort: 6379 hostPort: 6379 

执行此文件:

kubectl create -f pod-test.yaml

查看pod信息,可以查看到容器的创建过程(Event 事件信息):

 kubectl describe pod redis-php

静态Pod

静态pod是仅仅存在于特定Node上的Pod。 它们不能通过API server进行管理,无法与RC,Deployment或者DaemonSet进行关联,并且kubelet也无法对其进行健康检查。
静态Pod总是由kubelet创建,并且总是在kubelet所在的节点Node上运行。
创建静态pod有两种方式:

  • 配置文件方式
  • HTTP方式

配置文件方式

1、首先在特定的节点上创建目录,并创建static-web.yaml的文件,此文件定义了静态pod的信息:

mkdir /etc/kubernetes.d/ cat /etc/kubernetes.d/static-web.yaml apiVersion: v1 kind: Pod metadata: name: static-web labels: name: static-web spec: containers: - name: static-web image: nginx:1.12.2 ports: - name: web containerPort: 80 protocol: TCP 

2、修改kubelet启动文件参数,添加--pod-manifest-path=/etc/kubernetes.d/, 并重启kubelet。
3、Master节点上查看:

# kubectl get pod NAME READY STATUS RESTARTS AGE static-web-10.0.0.3 1/1 Running 0 40s

本地node节点上已经启动:

docker ps|grep nginx 33620ea59551 4037a5562b03 "nginx -g 'daemon ..." 5 minutes ago Up 5 minutes k8s_static-web_static-web-10.0.0.3_default_3fcbc9dd218421884a0a557825af52d5_0 

4、删除此静态pod,由于是在node节点由kubelet创建的,所以在master上执行删除并不会生效,需要到此node节点上删除此文件即可:

rm -f static-web.yaml

HTTP方式

使用HTTP的方式也需要修改对应node节点的kubelet配置参数--manifest-url=<URL>
Kubelet将定期的从参数 --manifest-url=<URL> 配置的地址下载文件,并将其解析为 json/yaml 格式的 pod 描述。
它的工作原理与从 --pod-manifest-path=<directory> 中发现文件执行创建/更新静态 pod 是一样的,即,文件的每次更新都将应用到运行中的静态 pod 中。

Pod共享Volume

Pod的Volume用于同一个pod中的多个容器数据共享。
Kubernetes Volume具有明确的生命周期-与pod相同。因此,Volume的生命周期比Pod中运行的任何容器要持久,在容器重新启动时可以保留数据,当然,当Pod被删除不存在时,Volume也将消失。注意,Kubernetes支持许多类型的Volume,Pod可以同时使用任意类型/数量的Volume。
内部实现中,一个Volume只是一个目录,目录中可能有一些数据,pod的容器可以访问这些数据。至于这个目录是如何产生的、支持它的介质、其中的数据内容是什么,这些都由使用的特定Volume类型来决定。在定义Pod时,需要指定对应的Volume。

本地存储

  • emptyDir: 无需指定宿主机的对应目录路径,由Pod自动创建,Pod移除时数据会永久删除,作为容器间的共享目录。上面的示例就是此格式的Volume。
cat pod-volume.yaml apiVersion: v1 kind: Pod metadata: name: volume-pod spec: containers: - name: tomcat image: tomcat ports: - containerPort: 8080 volumeMounts: - name: app-logs mountPath: /usr/local/tomcat/logs # 容器中的日志目录 - name: logreader # 容器名称,使用kubectl指定容器时需要使用此名称,无法使用容器ID image: busybox command: ["sh","-c","tail -f /logs/catalina*.log"] volumeMounts: - name: app-logs mountPath: /logs volumes: # volume设定的具体信息 - name: app-logs emptyDir: {} # volume的类型,emryDir的参数设置为{} 

这里的示例是将tomcat容器的日志目录和logreader的log目录共享,通过在logreader执行查看日志的命令,就可以在logreader中看到tomcat的启动日志。
查看日志:

 kubectl logs volume-pod -c logreader 

也可以直接登录容器查看:

 kubectl exec -it volume-pod -c tomcat sh

或者不登录直接执行容器命令:

 kubectl exec -it volume-pod -c logreader ls /logs kubectl exec -it volume-pod -c tomcat ls /usr/local/tomcat/logs
  • hostPath: Pod挂载宿主机上的文件和目录,可用于永久保存日志,容器内部访问宿主机数据,定义方式如下:
apiVersion: v1 kind: Pod metadata: name: volume-pod spec: containers: - name: tomcat image: tomcat ports: - containerPort: 8080 volumeMounts: - name: app-logs mountPath: /usr/local/tomcat/logs volumes: - name: app-logs hostPath: # 宿主机的本地目录,需要事先创建,否则pod无法启动 path: /logs # this field is optional type: Directory 

当pod删除时,数据依旧保存在宿主机目录中。

网络存储

k8s 也支持网络存储如NFS,分布式存储GlusterFS,对象存储Cephfs等,这里就不具体介绍,例如使用ceph的yaml配置如下:

apiVersion: v1 kind: Pod metadata: name: cephfs spec: containers: - name: cephfs-rw image: kubernetes/pause volumeMounts: - mountPath: "/mnt/cephfs" name: cephfs volumes: - name: cephfs cephfs: monitors: - 10.16.154.78:6789 - 10.16.154.82:6789 - 10.16.154.83:6789 # by default the path is /, but you can override and mount a specific path of the filesystem by using the path attribute # path: /some/path/in/side/cephfs user: admin secretFile: "/etc/ceph/admin.secret" readOnly: true

ConfigMap

configMap资源提供了一种将配置数据注入到Pod中的方法。在应用中可以使用这种方式来提供应用需要的配置信息。 存储在ConfigMap对象中的数据可以在configMap类型的卷中引用,然后由运行在Pod中的容器化应用程序使用。
当引用一个configMap对象时,你可以简单地在卷中提供它的名字来引用它。 您还可以自定义用于ConfigMap中特定条目的路径。
一般有如下用法:

  • 生成容器内的环境变量
  • 设置容器启动命令的启动参数(需要设置环境变量)
  • 以Volume的方式挂载为容器内部的文件或目录

    在使用configMap时,需要先创建configMap,然后再在其他对象中引用。

一般创建configMap可以通过两种方式:

  • 通过yaml配置文件方式
  • 通过使用kubectl create configmap命令的方式创建

1、通过YAML文件创建ConfigMap资源对象

apiVersion: v1 kind: ConfigMap metadata: name: config-test data: apploglevel: info appdatadir: /var/data 

与一般的yaml文件一致,data区域为配置的参数区域。如果参数很复杂并且很多,使用这种方式并不方便管理和查看。

2、通过使用kubectl create configmap命令创建
命令格式:

 kubectl create configmap <map-name> <data-source>

map-name: 自定义的configMap名称
data-source: 指定的配置文件信息,可以是文件或文件目录。 无论是哪种文件,最终都必须是键值对形式。

指定目录创建

如在/tmp/configmap 有如下文件:

# ll -rw-r--r-- 1 root root 157 Jun 15 17:19 game.properties -rw-r--r-- 1 root root 83 Jun 15 17:26 ui.properties # cat game.properties enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 # cat ui.properties color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice 

创建cofigmap:

 # kubectl create configmap game-config --from-file=/tmp/configmap/

查看configmap:

# kubectl describe configmaps game-config Name: game-config Namespace: default Labels: <none> Annotations: <none> Data ==== ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 Events: <none> 

将两个配置文件内容融合在了一起。也可以使用yaml的格式输出,这和自定义YAML的输出是相同的:

# kubectl get configmaps game-config -o yaml apiVersion: v1 data: game.properties: |- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: | color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice kind: ConfigMap metadata: creationTimestamp: 2018-06-15T09:29:39Z name: game-config namespace: default resourceVersion: "150723" selfLink: /api/v1/namespaces/default/configmaps/game-config uid: a079ab6c-707e-11e8-96f7-000c295f81fb 
指定文件

同理,也可以使用指定文件的方式:

 # kubectl create configmap game-spec --from-file=/tmp/configmap/game.properties
指定键值对

也可直接在命令行通过键值对直接指定:

# kubectl create configmap man-spec --from-literal=name=config.test --from-literal=value=test # kubectl get configmap man-spec -o yaml apiVersion: v1 data: name: config.test value: test kind: ConfigMap metadata: creationTimestamp: 2018-06-15T09:47:35Z name: man-spec namespace: default resourceVersion: "151795" selfLink: /api/v1/namespaces/default/configmaps/man-spec uid: 21b019cb-7081-11e8-96f7-000c295f81fb 
指定环境变量文件

可以使用--from-env-file 参数指定系统中环境变量文件,使用此参数时,指定文件有以下特点:

  • 文件包含列表类型的环境变量
  • 每一行都必须是 key=value 的格式
  • # 开头的行为注释,将会被忽略
  • 空行将会被忽略
  • 引号将不会被特殊处理,它将会作为configMap 值的一部分。

如下,使用环境变量文件,创建一个对应的confmap配置:

# 文件内容: # cat game-env-file.properties enemies=aliens lives=3 allowed="true" # This comment and the empty line above it are ignored # 创建ConfigMap # kubectl create configmap game-env --from-env-file=/tmp/configmap/game-env-file.properties # 查看创建的configmap: # kubectl get configmap game-env -o yaml apiVersion: v1 data: allowed: '"true"' enemies: aliens lives: "3" kind: ConfigMap metadata: creationTimestamp: 2018-06-15T10:17:59Z name: game-env namespace: default resourceVersion: "153612" selfLink: /api/v1/namespaces/default/configmaps/game-env uid: 60bb2081-7085-11e8-96f7-000c295f81fb 
在指定文件的时候指定KEY

使用指定文件的方式定义ConfigMap默认情况是使用的文件名为KEY,其实我们也可以自定义key值:

kubectl create configmap game-3 --from-file=<my-key-name>=<path-to-file>

3、定义Pod使用ConfigMap
Pod中加载ConfigMap常见的有两种方式:

  • 在Pod中定义环境变量参数,引用ConfigMap
  • 通过volume mount使用ConfigMap
Pod中指定引用ConfigMap定义环境变量参数

如果ConfigMap有如下定义:

# cat config-map.yaml apiVersion: v1 kind: ConfigMap metadata: name: config-test data: apploglevel: info appdatadir: /var/data 

在pod中引用此configmap:

# cat configmap-pod.yaml apiVersion: v1 kind: Pod metadata: name: configmap-pod spec: containers: - name: test-container image: busybox command: [ "/bin/sh", "-c", "env|grep TEST" ] # 获取只包含TEST开头的环境变量名称 env: # Define the environment variable - name: TEST-KEY1 # 容器中的环境变量参数 valueFrom: configMapKeyRef: # 参数来源于configmap # The ConfigMap containing the value you want to assign to TEST-KEY1 name: config-test # 指定已经存在的configmap的名称 key: apploglevel # 指定此configmap中需要引用的key - name: TEST-KEY2 valueFrom: configMapKeyRef: # The ConfigMap containing the value you want to assign to TEST-KEY2 name: config-test # 这里可以指定不同configmap key: appdatadir restartPolicy: Never # 执行完启动命令后将退出,不再被系统自动重启 

创建configmap和定义的POD:

kubectl create -f config-map.yaml kubectl create -f configmap-pod.yaml

查看pod,执行完命令之后已经正常退出:

# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE configmap-pod 0/1 Completed 0 57s 10.2.6.3 10.0.0.3 

查看输出的环境变量:

# kubectl logs configmap-pod TEST-KEY1=info TEST-KEY2=/var/data 
Pod中引用指定configmap的所有参数

当我们需要引用configmap中的定义的所有参数和变量时,可以使用envFrom 参数来指定configMap:

# cat pod-configmap1.yaml apiVersion: v1 kind: Pod metadata: name: test-pod spec: containers: - name: test-container image: busybox command: [ "/bin/sh", "-c", "env" ] envFrom: - configMapRef: # 此处不再指定key name: config-test # 指定configmap restartPolicy: Never 

运行pod,可以发现和configmap中定义的参数一致:

# kubectl logs test-pod |grep app apploglevel=info appdatadir=/var/data 
通过VolumeMount使用configmap

我们也可以在定义pod时,将configmap以卷的形式挂载到容器中的目录,这样就相当于容器直接使用这个配置文件了:

apiVersion: v1 kind: Pod metadata: name: volume-test-pod spec: containers: - name: test-container image: busybox command: [ "/bin/sh", "-c", "ls -l /etc/config/" ] volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: # Provide the name of the ConfigMap containing the files you want # to add to the container name: config-test restartPolicy: Never 

这样就将对应的参数挂载到了容器中的/etc/config目录,登录容器,可以看到:

 # ls -l /etc/config/ total 0 lrwxrwxrwx 1 root root 17 Jun 17 09:07 appdatadir -> ..data/appdatadir lrwxrwxrwx 1 root root 18 Jun 17 09:07 apploglevel -> ..data/apploglevel 

对应的文件中记录了参数值,/etc/config 路径下如果有其他文件,使用这种方式会清除此路径下之前的所有文件。

在实际的应用中,一般是通过configmap指定文件,挂载的configmap卷中会有一个以key值命名的文件,文件中包含了参数信息:

# kubectl get configmap game-config -o yaml apiVersion: v1 data: game.properties: |- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: | color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice kind: ConfigMap metadata: creationTimestamp: 2018-06-15T09:29:39Z name: game-config namespace: default resourceVersion: "150723" selfLink: /api/v1/namespaces/default/configmaps/game-config uid: a079ab6c-707e-11e8-96f7-000c295f81fb 

创建使用volume挂载此configmap的pod:

apiVersion: v1 kind: Pod metadata: name: volume-test-pod spec: containers: - name: test-container image: busybox command: [ "/bin/sh", "-c", "sleep 150" ] volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: # Provide the name of the ConfigMap containing the files you want # to add to the container name: game-config restartPolicy: Never 

登录此容器,可以看到对应的两个文件game.propertiesui.properties,里面的参数都是以键值存储:

# kubectl exec -it volume-test-pod sh / # ls -l /etc/config/ total 0 lrwxrwxrwx 1 root root 22 Jun 17 09:22 game.properties -> ..data/game.properties lrwxrwxrwx 1 root root 20 Jun 17 09:22 ui.properties -> ..data/ui.properties /etc/config # cat game.properties enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30/etc/config # /etc/config # cat ui.properties color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice 

当然,这里我们也可以定义挂载的文件名称和路径,使用path指定,对上面的例子进行修改:

apiVersion: v1 kind: Pod metadata: name: volume-test-pod spec: containers: - name: test-container image: busybox command: [ "/bin/sh", "-c", "sleep 150" ] volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: # Provide the name of the ConfigMap containing the files you want # to add to the container name: game-config items: - key: ui.properties # 这里的KEY为confmap中的data 的key path: ui/keys # 文件路径,这里表示参数文件为 /etc/config/ui/keys restartPolicy: Never 

登录pod后,查看内容如下:

/etc/config # ls ui /etc/config # cat ui/keys color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice 

使用volume的方式指定路径后,此路径的下之前的文件都会被清除,只能显示指定的item文件

使用ConfigMap的限制条件:

  • ConMap必须在Pod之前创建,否则将无法创建需要引用configMap的Pod,除非Pod中指定此ConfigMap为可选。
  • ConMap受Namespace限制,只有处于相同namespace中的Pod才可以引用它。
  • kebulete只支持可以被API Server管理的Pod使用ConfigMap。kubelet在本地Node上通过Kubelet REST API,--manifest-url或--config自动创建的静态Pod将无法引用ConfigMap。
  • 在Pod对configMap进行挂载时,挂载的目录下如果原来还有其他文件,则容器内的该目录将会被挂载的ConfigMap覆盖。如果应用程序要保留原来的其他文件,需要进行特殊处理。
  • 特殊处理思路:可以将ConfigMap挂载到容器的临时目录,再通过启动脚本将配置文件复制到或者链接到应用所用的实际配置目录下。
原文链接:https://blog.51cto.com/tryingstuff/2130193
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章