在k8s中pod是最小的管理单位,在一个pod中通常会包含一个或多个容器。
在每一个Pod中都有一个特殊的Pause容器和一个或多个业务容器,Pause来源于pause-amd64镜像,Pause容器在Pod中具有非常重要的作用:
kubernetes 的对象定义一般都用YAML或JSON格式的文件,可以使用这个网址验证yaml语法: https://codebeautify.org/yaml-validator
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是仅仅存在于特定Node上的Pod。 它们不能通过API server进行管理,无法与RC,Deployment或者DaemonSet进行关联,并且kubelet也无法对其进行健康检查。
静态Pod总是由kubelet创建,并且总是在kubelet所在的节点Node上运行。
创建静态pod有两种方式:
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的方式也需要修改对应node节点的kubelet配置参数--manifest-url=<URL>
Kubelet将定期的从参数 --manifest-url=<URL> 配置的地址下载文件,并将其解析为 json/yaml 格式的 pod 描述。
它的工作原理与从 --pod-manifest-path=<directory> 中发现文件执行创建/更新静态 pod 是一样的,即,文件的每次更新都将应用到运行中的静态 pod 中。
Pod的Volume用于同一个pod中的多个容器数据共享。
Kubernetes Volume具有明确的生命周期-与pod相同。因此,Volume的生命周期比Pod中运行的任何容器要持久,在容器重新启动时可以保留数据,当然,当Pod被删除不存在时,Volume也将消失。注意,Kubernetes支持许多类型的Volume,Pod可以同时使用任意类型/数量的Volume。
内部实现中,一个Volume只是一个目录,目录中可能有一些数据,pod的容器可以访问这些数据。至于这个目录是如何产生的、支持它的介质、其中的数据内容是什么,这些都由使用的特定Volume类型来决定。在定义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
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资源提供了一种将配置数据注入到Pod中的方法。在应用中可以使用这种方式来提供应用需要的配置信息。 存储在ConfigMap对象中的数据可以在configMap类型的卷中引用,然后由运行在Pod中的容器化应用程序使用。
当引用一个configMap对象时,你可以简单地在卷中提供它的名字来引用它。 您还可以自定义用于ConfigMap中特定条目的路径。
一般有如下用法:
在使用configMap时,需要先创建configMap,然后再在其他对象中引用。
一般创建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 参数指定系统中环境变量文件,使用此参数时,指定文件有以下特点:
如下,使用环境变量文件,创建一个对应的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
使用指定文件的方式定义ConfigMap默认情况是使用的文件名为KEY,其实我们也可以自定义key值:
kubectl create configmap game-3 --from-file=<my-key-name>=<path-to-file>
3、定义Pod使用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
当我们需要引用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
我们也可以在定义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.properties
和 ui.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文件