文章目录
一. 深入掌握Pod
1. Pod定义详解
2. Pod的基本用法
-
Pod的基本用法为:Pod可由1个或多个容器组合而成。
- 一个容器的Pod例子
[root@node2 test]# cat frontend-controller.yaml apiVersion: v1 kind: ReplicationController metadata: name: frontend labels: name: frontend spec: replicas: 3 selector: name: frontend template: metadata: labels: name: frontend spec: containers: - name: frontend image: kubeguide/guestbook-php-frontend env: - name: GET_HOSTS_FROM value: env ports: - containerPort: 80
这个frontend Pod在成功启动之后,将启动一个Docker容器;另一种场景是当frontend和redis两个容器应用为紧耦合的关系,应该组合成一个整体对外提供服务,则应该将这两个容器打包为一个Pod。
- 配置文件frontend-localredis-pod.yaml 如下:
apiVersion: v1
kind: Pod
metadata:
name: redis-php
labels:
name: redis-php
spec:
containers:
- name: frontend
image: kubeguide/guestbook-php-frontend
ports:
- containerPort: 80
- name: redis
image: kubeguide/redis-master
ports:
- containerPort: 6379
属于一个Pod的多个容器应用之间互相访问时需要通过localhost就可以通信,使得这一组容器被"绑定"在了一个环境中。
- 查看Pod,REDY为2/2,表示这个Pod的两个容器都成功运行了。
[root@node2 test]# kubectl get pods | grep redis-php
redis-php 2/2 Running 0 3m
- 查看Pod详细信息
[root@node2 test]# kubectl describe pod redis-php
3. 静态Pod
- 由kubelet进行创建,并且在kubelet所在的Node上运行。
- 静态Pod由kubelet进行管理的仅存于特定Node上的Pod。不能通过API Server进行管理。无法与RC、Deployment、DaemonSet进行关联。
- kubelet无法对它们进行健康检查。
- 作用:有效预防通过kubectl、或管理工具操作的误删除,可以用来部署核心组件应用。保障应用服务总是运行稳定数量和提供稳定服务。
创建静态Pod有两种方式:配置文件或者HTTP方式。
4. Pod容器共享Volume
- 在同一个Pod中的多个容器可以共享Pod级别的存储卷Volume。
- Volume可以被定义为各种类型,多个容器各自挂载为内部目录使用。
例子:Pod内包含两个容器,tomcat和busybox,在Pod级别设置Volume“app-logs”,用于tomcat向其中写日志文件,busybox读写日志文件。
[root@node2 kubernetes]# cat pod-volume-applogs.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: busybox
image: busybox
command: ["sh","-c","tail -f /logs/catalina*.log"]
volumeMounts:
- name: app-logs
mountPath: /logs
volumes:
- name: app-logs
emptyDir: {}
这里设置的 Volume名为app-logs,类型为 empty Dir(也可以设置为其他类型),挂载到 tomcat容器内的/usr/local/tomcat/logs目录,同时挂载到 logreader容器内的/logs目录。 tomcat容器在启动后会向/usr/local/tomcat/logs目录中写文件, logreader容器就可以读取其中的文件了。
创建Volume:
[root@node2 kubernetes]# kubectl apply -f pod-volume-applogs.yaml
pod/volume-pod created
查看logreader容器的输出内容:
[root@node2 kubernetes]# kubectl logs volume-pod -c busybox
30-Nov-2021 05:38:07.996 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
30-Nov-2021 05:38:08.017 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [1.2.31] using APR version [1.7.0].
30-Nov-2021 05:38:08.017 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
这个文件即为tomcat生成的日志文件/usr/local/tomcat/logs/catalina..log的内容,登录tomcat容器进行查看:
[root@node2 kubernetes]# kubectl exec -it volume-pod -c tomcat -- ls /usr/local/tomcat/logs
catalina.2021-11-30.log localhost_access_log.2021-11-30.txt
[root@node2 kubernetes]# kubectl exec -it volume-pod -c tomcat -- tail /usr/local/tomcat/logs/catalina.2021-11-30.log
30-Nov-2021 05:38:07.996 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
30-Nov-2021 05:38:08.017 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [1.2.31] using APR version [1.7.0].
30-Nov-2021 05:38:08.017 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
30-Nov-2021 05:38:08.024 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1k 25 Mar 2021]
30-Nov-2021 05:38:08.570 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
5. Pod的配置管理
将应用打包为容器镜像以后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入,但在大规模容器集群的环境中,对多个容器进行不同的配置将变得非常复杂,于是出现了一个统一的集群管理方案——ConfigMap。
5.1 ConfigMap:容器应用的配置管理
ConfigMap供容器使用的典型用法如下:
- 生成容器内的环境变量。
- 设置容器启动命令的启动参数(需设置为环境变量)。
- 以Volume的形式挂载为容器内部的文件或目录。
ConfigMap以一个或多个key:value的形式保存在K8S系统中供应用使用,即可用于表示一个变量的值(例如apploglevel=info),也可以用于表示一个完整配置文件的内容。
可以通过yaml配置文件或者直接使用kubectl create configMap命令行的方式创建ConfigMap。
yaml文件方式
[lab-user@bastion ~]$ cat cm-appvars.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
apploglevel: info
appdatadir: /var/data
创建及查看ConfigMap
[lab-user@bastion ~]$ kubectl create -f cm-appvars.yaml
configmap/cm-appvars created
[lab-user@bastion ~]$ kubectl get configmap
NAME DATA AGE
cm-appvars 2 15s
[lab-user@bastion ~]$ kubectl describe configmap cm-appvars
Name: cm-appvars
Namespace: myproject
Labels: <none>
Annotations: <none>
Data
====
appdatadir:
----
/var/data
apploglevel:
----
info
Events: <none>
[lab-user@bastion ~]$ kubectl get configmap cm-appvars -o yaml
apiVersion: v1
data:
appdatadir: /var/data
apploglevel: info
kind: ConfigMap
metadata:
creationTimestamp: "2021-12-01T09:38:39Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:appdatadir: {}
f:apploglevel: {}
manager: kubectl-create
operation: Update
time: "2021-12-01T09:38:39Z"
name: cm-appvars
namespace: myproject
resourceVersion: "356330"
selfLink: /api/v1/namespaces/myproject/configmaps/cm-appvars
uid: f10af38e-0f72-4828-ac78-661aa361ffbe
kubectl命令行方式
- 直接通过kubectl create configmap创建ConfigMap
- 使用参数–from-file或–from-literal指定文件内容,并且可以在一行命令中指定多个参数。
kubectl create configmap NAME --from-file=[key=]source --from-file=[key=]source
- 通过–from-file参数从文件中进行创建,可以指定key的名称,也可以在一个命令行中创建包含多个key的ConfigMap。
- 例子
当前目录下含有配置文件server.xml,可以创建一个包含该文件内容的ConfigMap
kubectl create configmap cm-appvars.yaml --from-file=server.xml
kubectl create configmap NAME --from-file=config-files-dir
- 通过–from-file参数从目录中进行创建,该目录下的每个配置文件名都被设置为key,文件内容都被设置为value。
- 例子
假设 configfiles目录下包含两个配置文件 server xml和 logging properties,创建一个包含这两个文件内容的 Configmap:
kubectl create configmap cm-appconf --from-file=configfiles
kubectl create configmap NAME --from-literal=key1=value1 --from-literal=key2=value2
- 通过–from-literal参数从文本中进行创建,直接将指定的key#=value#创建为ConfigMap的内容。
- 例子
kubectl create configmap cm-appenv --from-literal=loglevel=info --from-literal=appdatadir=/var/data
5.2 ConfigMap的使用
容器应用对 Configmap的使用有以下两种方法:
(1)通过环境变量获取 ConfigMap中的内容。
(2)通过 Volume挂载的方式将 ConfigMap中的内容挂载为容器内部的文件或目录。
环境变量方式
以cm-appvars.yaml为例:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-appvars
data:
apploglevel: info
appdatadir: /var/data
在Pod“cm-test-pod”的定义中,将ConfigMap“cm-appvars”中的内容以环境变量(APPLOGLEVEL和APPDATADIR)设置为容器内部的环境变量,容器的启动命令将显示这两个环境变量的值(“env | grep APP")
[lab-user@bastion ~]$ cat cm-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cm-test-pod
spec:
containers:
- name: cm-test
image: busybox
command: [ "/bin/sh","-c","env | grep APP" ]
env:
- name: APPLOGLEVEL #定义环境变量名称
valueFrom: #key"apploglevel”对应的值
configMapKeyRef:
name: cm-appvars #环境变量的值取自cm-appvars中
key: apploglevel #key为“apploglevel”
- name: APPDATADIR #定义环境变量名称
valueFrom: #key"appdatadir”对应的值
configMapKeyRef:
name: cm-appvars #环境变量的值取自cm-appvars中
key: appdatadir #key为“appdatadir”
restartPolicy: Never
查看该Pod的日志,可以看到启动命令“ env grep APP”的执行结果如下
kubectl logs cm-test-pod
APPDATADIR=/var/data
APPLOGLEVEL=info
说明容器内部的环境变量使用 Config Map cm- appears中的值进行了正确的设置。
volumeMount模式
如果在引用ConfigMap时不指定items,则使用volumeMount方式在容器内的目录中为每个items生成一个文件名为key的文件。
5.3 使用ConfigMap的限制条件
限制条件如下:
- ConfigMap必须在Pod之前创建。
- ConfigMap也可以定义为属于某个 Namespace。只有处于相同 Namespaces中的Pod可以引用它。
- ConfigMap中的配额管理还未能实现。
- kubelet只支持可以被 API Server i管理的Pod使用 ConfigMap. kubelet在本Node上通–manifest-url或–config自动创建的静态Pod将无法引用 ConfigMap
- 在Pod对 ConfigMap进行挂载( volumeMount)操作时,容器内部只能挂载为“目录”无法挂载为“文件”。在挂载到容器内部后,目录中将包含 ConfigMap定义的每个item,如果该目录下原先还有其他文件,则容器内的该目录将会被挂载的 ConfigMap进行覆盖。如果应用程序需要保留原来的其他文件,则需要进行额外的处理。可以通过将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或者链接(cp或link操作)到应用所用的实际配置目录下。
6.Pod生命周期和重启策略
Pod的完整生命周期过程被定义为各种状态,包括以下几种:
状态值 | 描述 |
---|---|
Pending | API Server已经创建该Pod,但Pod内至少还有一个或多个容器的镜像没有创建,包括正在下载镜像的过程。 |
Running | Pod内所有容器均已创建,且至少还有一个容器处于运行状态、正在启动状态或正在重启状态。 |
Succeeded | Pod内所有容器均已退出,但是少还有一个容器退出为失败状态 |
Failed | Pod内所有容器均已退出,但至少有一个容器退出为失败状态 |
Unknown | 由于某种原因无法获取该Pod的状态,可能是网络故障 |
Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据RestartPolicy的设置来进行相应的操作。
Pod的重启策略包括Always、OnFailure和Never,默认值为Always。
- Always:当容器失效时,由 kubelet自动重启该容器。
- OnFailure:当容器终止运行且退出码不为0时,由 kubelet自动重启该容器。
- Never:不论容器运行状态如何, kubelet都不会重启该容器。
Pod的重启策略与控制方式相关,当前可用于管理Pod的控制器包括ReplicationController, Job、 Daemonset及直接通过 kubelet管理(静态Pod)。每种控制器对Pod的重启策略要求如下。
- RC和 Daemonset:必须设置为 Always,需要保证该容器持续运行。
- Job: OnFailure或 Never,确保容器执行完成后不再重启。
- kubelet:在Pod失效时自动重启它,不论 RestartPolicy设置为什么值,并且也不会对Pod进行健康检査。
结合Pod状态和重启策略,一些常见的状态转换场景如下:
7.Pod健康检查
通过两类探针检查:
- LivenessProbe:判断是否running
- 如果探测到容器不健康,则kubelet会kill掉该容器,并根据重启策略做处理。
- 如果容器不包含此探针,则认为容器探针返回值为success。
- ReadinesProbe:判断是否ready
- 如果探测失败,则Pod的状态将被修改。
kubelet定期执行 Livenessprobe探针来诊断容器的健康状况。 Livenessprobe有以下三种实现方式。
(1) Execaction:在容器内部执行一个命令,如果该命令的返回码为0,则表明容器健康。
(2)TCPSocketAction:通过容器的P地址和端口号执行TCP检查,如果能够建立TCP连接,则表明容器健康。
(3)HTTPGetAction:通过容器的IP地址、端口号及路径调用HTTP Get方法,如果响应的状态码大于等于200且小于等于400,则认为容器状态健康。
对于每种探测方式,都需要设置 initialDelaySeconds和 timeoutSeconds两个参数,它们的含义分别如下
- initialDelaySeconds:启动容器后进行首次健康检查的等待时间,单位为秒。
- timeoutSeconds:健康检査发送请求后等待响应的超时时间,单位为秒。当超时发生时,kubelet会认为容器已经无法提供服务,将会重启该容器
8. Pod调度
Pod在大部分场景下都只是容器的载体,需要通过RC、Deployment、DaemonSet、Job等对象来完成Pod的调度与自动控制功能。
8.1 RC、Deployment调度
RC的主要功能之一就是自动部署一个容器应用的多份副本以及持续监控副本的数量,在集群内维护用户指定的副本数量。
(未完待续)