pod定义详解
下面是一个完整的yaml格式定义的文件,注意格式,子集包含关系,不要有tab,要用空格。不是所有的元素都要写,按照实际应用场景配置即可。
定义一个简单pod(最好把docker源改成国内的)
apiVersion: v1
kind: Pod
metadata:
name: hello-world
namespace: default
spec:
restartPolicy: OnFailure
containers:
- name: hello
image: "ubuntu:14.04"
command: ["/bin/echo","hello","world"]
pod文件解释:
apiVersion: v1//k8s版本
kind: pod//声明API对象类型这里是pod
metadata:
name:hello-word //pod名字必须在namespace中是唯一
spec://配置pod具体配置
restartPolicy: OnFailure // pod重启策略 [Always默认策略,当容器退出时总是重启容器|Never当容器退出时,从不重启|OnFailure容器正常退出不会再重新启动,退出码非0时才重启容器]
containers: //pod中的容器列表,可以有多个容器
- name: hello //容器名字,在一个pod中唯一
image: "ubuntu:14.04" //镜像名字
command: ["/bin/echo","hello","word"]//设置容器的启动命令
创建pod
[root@kubernetes-master pods]# kubectl create -f helloworld.yml
pod "hello-word" created
查看pod状态,状态不是runing而是完成,说明容器运行完成已经退出了
查看容器log输出
[root@kubernetes-master pods]# kubectl logs hello-world
hello world
这里要说一下command和args2个参数:
pod中定义env
容器获取pod信息
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: print-pod-info 5 namespace: default 6 spec: 7 containers: 8 - name: my-pod 9 image: busybox 10 resources: 11 requests: 12 memory: "32Mi" 13 cpu: "125m" 14 limits: 15 memory: "64Mi" 16 cpu: "250m" 17 env: 18 - name: MY_POD 19 valueFrom: 20 fieldRef: 21 fieldPath: metadata.name 22 - name: MY_POD_NAMESPACE 23 valueFrom: 24 fieldRef: 25 fieldPath: metadata.namespace 26 - name: MY_POD_IP 27 valueFrom: 28 fieldRef: 29 fieldPath: status.podIP 30 - name: MY_POD_SERVICE_ACCOUNT 31 valueFrom: 32 fieldRef: 33 fieldPath: spec.serviceAccountName 34 - name: MY_CPU_REQUEST 35 valueFrom: 36 resourceFieldRef: 37 containerName: my-pod 38 resource: requests.cpu 39 - name: MY_CPU_LIMIT 40 valueFrom: 41 resourceFieldRef: 42 containerName: my-pod 43 resource: limits.cpu 44 - name: MY_MEM_REQUEST 45 valueFrom: 46 resourceFieldRef: 47 containerName: my-pod 48 resource: requests.memory 49 - name: MY_MEM_LIMIT 50 valueFrom: 51 resourceFieldRef: 52 containerName: my-pod 53 resource: limits.memory 54 command: ["/bin/sh","-c","while true;do sleep 5;done"]
解释:
env:
- name: MY_POD 定义的变量名字最好是大写
valueFrom: 获取pod中的信息这个是固定的
fieldRef: 获取pod中的信息这个是固定的
fieldPath: metadata.name 获取pod中的信息这个是固定的
定义普通变量:
env:
- name: MY_POD 定义的变量名字最好是大写
value: "massage......" 变量的值
端口:
配置nginx
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: my-nginx 5 namespace: default 6 spec: 7 containers: 8 - image: nginx 9 imagePullPolicy: IfNotPresent 10 name: nginx 11 ports: 12 - name: web 13 containerPort: 80 //容器内部端口 14 protocol: TCP //协议可选 15 hostIP: 0.0.0.0 //worknodeIP可选,0.0.0.0就是任意选择 16 hostPort: 8000 //worknode(宿主机)上的端口
提示:
ports.name 这个值在pod中也是唯一的,当配置一个端口的时候是可选的,多个端口是必选。
如果同时2个pod的的宿主机端口都是80那么k8s会将容器分别调度到没有占用80端口机器上启动
数据持久化和共享
1 piVersion: v1 2 kind: Pod 3 metadata: 4 name: newhello 5 namespace: default 6 spec: 7 restartPolicy: Never 8 containers: 9 - name: write 10 image: "ubuntu:14.04" 11 command: ["/bin/sh","-c","echo "hello word" >> /data/hello"] 12 volumeMounts: 13 - name: data 挂在下面定义卷data 14 mountPath: /data 挂载到容器中的目录 15 - name: read 16 image: "ubuntu:14.04" 17 command: ["bash","-c","sleep 10; cat /data/hello"] 18 volumeMounts: 19 - name: data 20 mountPath: /data 21 volumes: 定义卷 22 - name: data 卷名字 23 hostPath: 宿主机 24 path: /tmp 宿主机路径
查看结果
[root@kubernetes-master pods]# kubectl logs newhello read
hello word
pod生命周期:
1、 Pending:kubernetes已经开始创建Pod,但是Pod中的一个或多个容器还没有被启动。比如Pod正处在应该被分配到哪个节点上这个调度过程中,或者kubernetes还在从镜像仓库中下载Pod中容器镜像这个下载过程中。
2、 Running:kubernetes已经将Pod分配到节点上,并且Pod中的所有容器都启动了。还包括Pod中至少有一个容器仍然在运行状态,或者正在重新启动状态。
3、 Succeeded:Pod中的所有容器都处在终止状态,并且这些容器是自主正常退出到终止状态的,也就是退出代码为0,而且kubernetes也没有重启任何容器。
4、 Failed:Pod中的所有容器都处在终止状态,并且至少有一个容器不是正常终止的,也就是退出代码不为0,或者是由于系统强行终止的。
5、 Unknown:由于一些特殊情况无法获取Pod状态,比如由于网络原因无法同Pod所在的主机通讯。
变量Phase的取值还取决于结构体PodSpec中的RestartPolicy变量,这个RestartPolicy变量是用来设置Pod中容器重启策略的,包括三个可选值,分别是Always、OnFailure和Never。
这三个值得含义分别是:
1、Always:表示对容器一直执行重启策略。如果不设置RestartPolicy,那么Always是默认值。
2、OnFailure:表示在容器失败的时候重启容器。
3、 Never:表示在对容器不执行重启策略。
总结一下pod重启策略和容器退出后。pod状态
pod生命周期回调
主要作用就是在容器开始的时候做一个动作,容器停止的时候做一个动作
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: javaweb2 5 namespace: default 6 spec: 7 containers: 8 - image:ubuntu:14.04 9 name: war 10 lifecycle: 11 postStart: 12 exec: 13 command: 14 - "cp" 15 - "/sample.war" 16 - "/app" 17 preStop: 18 httpGet: 19 host: monitor.com 20 path: /warning 21 port: 8080 22 scheme: HTTP
PostStart:容器创建成功后回调
PreStop :容器终止前回调
自定义pod检查
在很多实际场景下,仅仅使用进程级健康检查还远远不够。有时,从Docker的角度来看,容器进程依旧在运行;但是如果从应用程序的角度来看,代码处于死锁状态,即容器永远都无法正常响应用户的业务
为了解决以上问题,Kubernetes引人了一个在容器内执行的活性探针(Liveness Probe)和(Readiness Probe)的概念,以支持用户自己实现应用业务级的健康检查。这些检查项由Kubelet代为执行,以确保用户的应用程序正确运转,至于什么样的状态才算“正确”,则由用户自己定义。
1Liveness Probe 容器自定义检查,检查失败容器被杀死,然后根据pod重启策略来做
2Readiness Probe 检查失败直接从代理后端移除,既不会分发请求给改pod。
Kubernetes支持3种类型的应用健康检查动作,分别为HTTP Get、Container Exec和TCP Socket。个人感觉exec的方式还是最通用的,因为不是每个服务都有http服务,但每个服务都可以在自己内部定义健康检查的job,定期执行,然后将检查结果保存到一个特定的文件中,外部探针就不断的查看这个健康文件就OK了。
HTTPget:
path URL路径
port 端口
host 请求IP
scheme:求情协议默认HTTP
Kubelet将调用容器内Web应用的web hook,如果返回的HTTP状态码在200和399之间,则认为容器运转正常,否则认为容器运转不正常。每进行一次HTTP健康检查都会访问一次指定的URL。给出httpGet的简单示例如下:
1 [root@k8s-master livenessProbe]# cat test-livenessprobe.yaml 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 labels: 6 name: test-livenessprobe 7 name: test-livenessprobe 8 spec: 9 containers: 10 - name: test-livenessprobe 11 image: registry:5000/back_demon:1.0 12 livenessProbe: 13 httpGet: 14 path: /starott_cloud_client/test/overview-frontend 15 port: 8080 16 initialDelaySeconds: 15 17 periodSeconds: 5 18 timeoutSeconds: 1 19 command: 20 - /run.sh
TCP Socket:
tcpSocket:
port:8080
检查tcp端口8080是否正常
Exec:
exec:
command:
这里拿exec做例子演示Liveness Probe和Readiness Probe区别:
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: livemess-probe 5 labels: 6 test: liveness 7 spec: 8 containers: 9 - name: libeness 10 image: "ubuntu:14.04" 11 command: 12 - /bin/sh 13 - -c 14 - echo ok > /tmp/health; sleep 30;rm -rf /tmp/health;sleep 600 15 livenessProbe: 16 exec: 17 command: 18 - cat 19 - /tmp/health 20 initialDelaySeconds: 15 21 timeoutSeconds: 1
注意看restarts数值
30秒后容器重启了
查看错误日志
kubectl describe pod livemess-probe |grep Unhealthy
Readiness Probe实验
容器状态还是running但是k8s不会往这个pod上转发数据
日志查询:
一个pod中2个容器,一个正常退出一个异常退出。重启策略O:nFailure,异常退出时在重启容器
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: logs-pod 5 namespace: default 6 spec: 7 restartPolicy: OnFailure 8 containers: 9 - name: cont1 10 image: "ubuntu:14.04" 11 command: ["bash","-c","echo "cont1:`date --rfc-3339 ns`";exit 0"] 12 - name: cont2 13 image: "ubuntu:14.04" 14 command: ["bash","-c","echo "cont2:`date --rfc-3339 ns`";exit 1"]
查看容器1和容器2日志
[root@kubernetes-master pods]# kubectl logs logs-pod cont1
cont1:2017-07-11 13:15:41.122936441+00:00
[root@kubernetes-master pods]# kubectl logs logs-pod cont2
cont2:2017-07-11 13:21:40.452165906+00:00
查看日志历史,有的时候会出现查询不到当前日志,我们就 可意查询上一次容器打的日志。加上这个--previous
[root@kubernetes-master pods]# kubectl logs logs-pod cont2 --previous
cont2:2017-07-11 13:21:40.452165906+00:00
定义持久化日志
1 apiVersion: v1 2 kind: Pod 3 metadata: 4 name: logs-pod 5 namespace: default 6 spec: 7 restartPolicy: OnFailure 8 containers: 9 - name: cont1 10 terminationMessagePath: /dev/termination-log 11 image: "ubuntu:14.04" 12 command: ["bash","-c","echo "cont1:`date --rfc-3339 ns`" >> /dev/termination-log;"]
用到的参数terminationMessagePath:
[root@kubernetes-master pods]# kubectl get pod logs-pod --template="{{range .status.containerStatuses}}{{.state.terminated.message}}{{end}}" --show-all
cont1:2017-07-11 13:28:03.421374195+00:00
远程连接容器
1、exec(功能强大)
2、attach(这个比较麻烦)
远程执行命令并返回
[root@kubernetes-master pods]# kubectl exec mysql -- date
Tue Jul 11 13:42:44 UTC 2017
进入pod容器
[root@kubernetes-master pods]# kubectl exec -ti mysql /bin/bash