k8s之深入解剖Pod(一)
上文说了一下k8s的简单使用,接下来就让我们来具体深入了解一下Pod。为了避免篇幅太长,所以会分成几篇。
目录:
- Pod定义详解
- 静态Pod
- Pod容器共享Volume
一、Pod定义详解
先看一个简单的nginx的Pod定义:
apiVersion: v1 kind: Pod metadata: nam: nginx-test labels: app: nginx-test spec: containers: - name: nginx-test image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80
上述是一个Pod内包含一个容器,容器中运行nginx,容器对外暴漏80端口
Pod定义主要分成四大块:
(1)api
apiVersion: v1
(2)kind
kind: Pod
(3)metadata
metadata是Pod的元数据定义
metadata: #元数据 name: string #Pod名称 namespace: string #Pod所属命名空间,缺省默认是default labels: #自定义标签列表 - key: value annotations: #自定义注解列表 - key: value
(4)spec
spec是Pod中容器的详细定义,主要分成以下几块
containers
containers是Pod中的容器列表,数组类型。
spec: containers: #容器列表 - name: string #容器名称 image: string #所用镜像 imagePullPolicy: [Always|Never|IfNotPresent] #镜像拉取策略 command: [string] #容器的启动命令列表 args: [string] #启动命令参数列表 workingDir: string #工作目录 volumeMounts: #挂载在容器内部的存储卷配置 - name: string #共享存储卷名称 mountPath: string #存储卷绝对路径 readOnly: boolean #是否只读 ports: #容器需要暴露的端口号列表 - name: string #端口名称 containerPort: int #容器监听端口 hostPort: int #映射宿主机端口 protocol: string #端口协议 env: #环境变量 - name: string value: string resources: #资源限制 limits: cpu: string #单位是core memory: string #单位是MiB、GiB livenessProbe: #探针,对Pod各容器健康检查的设置,如几次无回应,则会自动重启 exec: command: [string] httpGet: path: string port: number host: string scheme: string httpHeaders: - name: string value: string tcpSocket: port: number initialDelaySeconds: 0 #启动后多久进行检测 timeoutSeconds: 0 #超时时间 periodSeconds: 0 #间隔时间 successThreshold: 0 # failureThreshold: 0 securityContext: #权限设置 privileged: false #是否允许创建特权模式的Pod
探针测试:
列出文件或文件夹aaa(此目录是不存在的),容器启动后5s开始执行探针,每隔5s执行一次,
apiVersion: v1 kind: Pod metadata: name: nginx-test labels: app: nginx-test spec: containers: - name: nginx-test image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 livenessProbe: exec: command: ["ls","aaa"] initialDelaySeconds: 5 timeoutSeconds: 5
查看探针三次失败后是否有重启容器:
使用如下命令查看容器的Event项
kubectl describe pods/nginx-test
从上图可以看到,容器重启了5次
restartPolicy
容器重启策略:
spec: restartPolicy: [Always|Never|OnFailure]
- Always:Pod一旦终止运行,kubelet都会进行重启,这也是默认值
- Never:不会进行重启
- OnFailure:容器非正常退出(即是退出码不为0),kubelet会重启容器,反之不会重启。
nodeSelector
指定Pod被调度到哪个节点运行。
spec: nodeSelector: K: V
比如想把一个Pod调度给cnode-2节点运行:
获取集群中所有节点列表:
给cnode-2节点打标签:
kubectl label nodes/cnode-2 name=cnode-2
查看cnode-2节点标签信息:
定义Pod的yaml文件:nginx-ns.yaml
apiVersion: v1 kind: Pod metadata: name: nginx-test labels: app: nginx-test spec: containers: - name: nginx-test image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 nodeSelector: name: cnode-2
使用如下命令创建Pod:
kubectl create -f nginx-ns.yaml
查看这个Pod运行在哪个节点:
imagePullSecrets
拉取镜像时使用的Secret名称,以name:secretKey格式指定
spec: imagePullSecrets: name: secretKey
Secret是用来保存私密凭据的,比如密码等信息
hostNetwork
是否使用主机网络模式
spec: hostNetwork: true|false
如果使用主机网络模式的话,Pod的IP就是跟宿主机IP是一样的
例如:创建下列Pod
apiVersion: v1 kind: Pod metadata: name: nginx-test labels: app: nginx-test spec: containers: - name: nginx-test image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 nodeSelector: name: cnode-3 hostNetwork: true
然后查看Pod被分配的IP与主机IP是否相同
volumes
Pod上定义的共享存储列表:
spec: volumes: #存储卷 - name: string emptyDir: {} #表示与Pod同生命周期的一个临时目录 hostPath: #宿主机Host path: string secret: #挂载集群预定义的secret对象到容器内部 secretName: string items: - key: string path: string configMap: #挂载集群预定义的configMap对象到容器内部 name: string items: - key: string path: string
二、静态Pod
由kubelet管理的仅存在于特定Node上的Pod,不能通过API Service进行管理,无法与RC、deployment或DaemonSet进行关联,并且kubelet也无法对他们进行健康检查,有kubelet创建并运行在kubelet所在的Node上运行。
静态Pod的yaml文件在修改之后,kubelet会进行自动重启该Pod至配置文件生效
创建静态Pod有两种方式:配置文件或者HTTP方式。
下面说一下配置文件的创建方式:
配置文件
需要设置kubelet启动参数“--config”,指定kubelet需要监控的配置文件所在的目录,kubelet会定期扫描该目录,并根据目录中的yaml或json文件进行创建操作
(1)如果集群是通过kubeadm创建的,那么已经配置好了静态pod的路径
查看kubelet的启动参数配置文件路径:
systemctl status kubelet
查看配置文件:
启动参数配置在一个叫/var/lib/kubelet/config.yaml的文件中
在此文件中会发现由下图中的配置,也就是静态Pod路径配置为/etc/kubernetes/manifests路径
所以只需要将静态Pod的yaml文件放置在此目录下即可。
这四个Master上运行的核心组件就是通过此方式进行创建的。
例如上图中我将static-nginx.yaml放到/etc/kubernetes/manifests目录下:
apiVersion: v1 kind: Pod metadata: name: static-nginx labels: name: static-nginx spec: containers: - name: static-nginx image: nginx ports: - containerPort: 80
此时使用kubelet get pods就可以查看到相应的Pod
(2)如果不是由kubeadm创建的集群,则需要在kubelet启动参数配置文件中添加如下一行:
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true
修改配置之后需要重启kubelet
systemctl stop kubelet systemctl daemon-reload systemctl start kubelet
例如我在cnode-2上配置了kubelet的启动参数,将静态Pod文件目录设置为/usr/soft/k8s/yaml/staticPod,然后重启kubelet
此时在目录下放置一个yaml文件
保存后就可以查看到相应的Pod是否已创建
【注意】如果Pod没创建成功,可以使用如下命令查看日志
systemctl status kubelet -l
我这边因为是之前配置了Pod安全策略,所以导致无法创建,我排查了一天啊我天
,痛苦的教训
Http方式
通过设置kubelet的启动参数“--manifest-url”,kubelet将会定期从该URL地址下载Pod的定义文件,并以.yaml或.json文件的格式进行解析, 然后创建Pod。其实现方式与配置文件方式是一致的。
【注意】静态Pod无法通过kubectl delete进行删除,只能删除对应的yaml文件
三、Pod容器共享Volume
在同一个Pod中的多个容器能够共享Pod级别的存储卷Volume,可以定义为各种类型,至于Volume是何种类型,在k8s基本概念中已有提到,多个容器各自进行挂载,将一个Volume挂在为容器内部需要的目录
比如:Pod里面有两个容器,分别是tomcat和busybox,tomcat往/usr/local/tomcat/logs写日志,busybox从/logs目录读取日志。
新建一个yaml文件:
这里设置的Volume名为app-logs,类型为emptyDir,挂载到tomcat容器内 的/usr/local/tomcat/logs目录,同时挂载到busybox容器内的/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 - name: busybox image: busybox command: ["sh","-c","tail -f /logs/catalina*.log"] volumeMounts: - name: app-logs mountPath: /logs volumes: - name: app-logs emptyDir: {}
创建之后查看busybox的日志输出:
kubectl logs pods/volume-pod -c busybox
进入tomcat容器中查看日志文件:
#进入tomcat容器,-c参数指明是哪个容器 kubectl exec -it pods/volume-pod -c tomcat /bin/bash
进入在Pod创建时设置的日志目录:
/usr/local/tomcat/logs
===============================
我是Liusy,一个喜欢健身的程序员。
欢迎关注微信公众号【Liusy01】,一起交流Java技术及健身,获取更多干货,领取Java进阶干货,领取最新大厂面试资料,一起成为Java大神。
来都来了,关注一波再溜呗。