1 缘起
本应该是学习K8S的第一课,
但是,我目前的状态是应用大于理论,
先学会用,再补充理论,每次使用K8S部署服务都是在Deployment中的template中创建Pod,
但是,配置文件中并没有体现Pod,所以,抽时间学习了Pod是啥?由什么管理?
分享如下:
Pod官网文档:https://kubernetes.io/docs/concepts/workloads/pods/#pods-and-controllers
2 Pods
Pod是K8S中创建和管理用于计算的最小可部署单元。
Pod是一个或多个共享存储和网络资源容器组成的集合,是运行容器的规范。
Pod的内容总是共享调度、共享协作地运行在共享的上下文中。Pod为特定应用的“逻辑主机”建模,Pod包含一个或多个相对紧密耦合的应用程序容器。在非云端上下文中,应用在相同的物理机或者虚拟机上运行和云应用在相同逻辑主机上运行是类似的。
与应用容器一样,Pod可以包含初始化容器(运行与Pod启动期间),同时,如果集群允许,可以注入临时容器供调试使用。
3 What is a Pod?
注意
:虽然Kubernetes支持的容器运行时比Docker丰富,但是,Docker是最为人熟知的运行时,这有助于使用Docker术语描述Pod。
Pod共享的上下文是一系列的Linux命名空间、控制组和其他隔离的资源(与Docker容器的隔离一样)。Pod上下文内,个别应用可能进行进一步次级隔离。
根据Docker的概念,Pod与Docker容器共享命名空间和文件系统卷是相似的。
4 Using Pods
下面是Pod的样例,该Pod的容器中运行的镜像为nginx:1.14.2。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
创建上面的Pod,使用下面的命令:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
Pod通常不会直接创建,而是使用工作负载资源创建。通过使用Pods查看更多关于Pod如何使用工作负载资源的信息。
5 管理Pod负载资源
管理Pod负载资源
相关人员通常不需要直接创建Pod,即使是单个Pod,而是使用负载资源创建Pod,如Deployment或者Job。如果需要跟踪Pod状态,可以使用StatefulSet资源。
Kubernetes集群中有主要通过两种方式使用Pod:
- Pod运行在单独的容器
一个Pod一个容器是Kubernetes最常用的方式,这种模式中,可将Pod看做是容器的外壳,Kubernetes管理Pod而不是直接管理容器。 - Pod运行在多个容器
Pod可以将多个密切关联的和需要共享资源的协作容器应用封装在一起。协作容器形成一个内聚的服务单元,如,一个容器在共享卷中提供数据存储服务,同时,一个独立的sidecar容器刷新或更新这些文件。Pod将这些容器、存储资源和临时网络标识打包在一起,形成一个整体。
注意
:将多个相互协作和共同管理的容器打包到一个Pod中是相对高阶的应用,使用者应该尽在特定密切关联的实例中使用。
每个Pod意味着运行一个给定应用的实例。如果想水平扩展应用(通过运行更多实例提供更多资源),应该使用多个Pod,一个Pod对用一个实例。Kubernetes中,水平扩容即复制。复制的Pod通常由工作负载资源和其对应的控制器进行创建和管理。
查看Pods 和 controllers了解Kubernetes如何使用工作负载资源和控制器扩展应用和自愈。
6 Pod如何管理多个镜像
Pod支持多协作进程(如容器)形成内聚的服务单元。Pod中的容器在相同物理机或者集群中虚拟主机自动协同和调度。容器可以共享资源、依赖、与其他容器通信及协作何时以及如何终止。
比如,某个容器共享卷作为Web文件服务器,独立的sidebar容器从远程资源更新这些文件,示意图如下:
某些容器有初始化容器如app容器。初始化容器在app容器启动前运行并完成。
Pod为内部的容器原生提供两中资源共享方式:networking和storage。
7 Pod工作
工作人员很少在Kubernetes中创建独立的Pod,即使一个Pod,因为Pod设计的理念即相对短暂、一次性的实体。当创建Pod(直接创建或者通过Controller间接创建),新的Pod调度会在集群节点中运行。
Pod保留在Node中的阶段:
- Pod执行结束前
- Pod对象被删除前
- 资源不足被逐出前
- Node失败前
注意
:不应混淆Pod中重启容器和重启Pod。Pod不是一个进程,而是运行容器的环境,被删除前Pod都会存在。
8 Pod和Controller
开发人员可以使用工作负载资源创建和管理多个Pod,Controller用于复制Pod、展示Pod和自动治愈Pod当Pod失败时。如,当某个Node失败,Controller发现在Node中的Pod停止工作时会创建Pod副本。调度器会将创建的Pod副本部署在健康的Node运行。
下面有三个负载资源管理一个多或多个Pod样例:
- Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
- StatefulSet
apiVersion: apps/v1
kind: StatefulSet
...
spec:
persistentVolumeClaimRetentionPolicy:
whenDeleted: Retain
whenScaled: Delete
...
- DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
# these tolerations are to have the daemonset runnable on control plane nodes
# remove them if your control plane nodes should not run pods
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
9 Pod模板
Controller为工作负载资源提供:从pod模板创建Pod和管理Pod服务。
Pod模板是创建Pod的规范,在工作负载资源中使用,如Deployments,Jobs和DaemonSets。
工作负载资源的每个Controller使用Pod模板是为了创建实际的Pod,Pod模板是使用工作负载资源运行应用所需状态的一部分。
下面的Job样例使用模板启动容器,Pod中的容器打印消息并暂停。
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 这是Pod模板
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# Pod模板结束
修改Pod模板或者替换为新的Pod模板不会直接影响已经存在的Pod,如果想改变工作负载资源的Pod模板,需要在资源中使用更新的模板创建Pod副本。
比如,StatefulSet Controller可以为每个StatefulSet对象保证运行中的Pod匹配当前Pod模板。如果编辑StatefulSet来改变其Pod模板,StatefulSet会基于更新的模板创建新的Pod,最终,所有旧的Pod会被新Pod替换,完成更新。
每个工作负载资源都有自己的实现规则来处理Pod模板的更新,获取更多SatefulSet信息请查看Update strategy中StatefuuSet基础教程。
Node中,kubelet不会直接观测或管理任何Pod模板细节和及其更新,这些细节被抽象化,关注点的抽象和分离简化了系统语义,并使不改变现有代码的前提下扩展集群成为可能。
10 Pod更新和替换
如上面所讲,工作负载资源中Pod模板发生改变时,Controller会基于变更的模板创建新的Pod,而不是更新已存在的Pod或在已存的Pod上打补丁。
Kubernetes不会阻止用户直接管理Pod,虽然可以直接更新正在运行Pod的某些属性,但是,Pod更新操作如patch和replace有一些限制:
- Pod的大部分元数据是不可变的。比如,不可改变namespace、name、uid或者creationTimestamp这些属性,generation尚需经是唯一的。Pod能接收的更新只有增加属性的当前值。
- 如果meta.deletionTimestamp已经设置,所有新实体都不能添加到metadata.finalizers列表中。
- Pod可以变更的属性有spec.containers[].image、spec.initContainers[].image、spec.activeDeadlineSeconds
或者spec.tolerations,对于spec.tolerations属性可以只在新实体中添加。 - 更新spec.activeDeadlineSeconds属性时,会同时变更:
(1)给未分配的属性设置为正数;
(2)减小属性值(非负数)。
11 资源共享和通信
Pod允许内部的容器共享数据和通信。
11.1 Pod存储
Pod可以指定共享卷。Pod中所有的容器可以访问共享卷,允许这些容器共享数据。Pod中卷可以持久化数据,预防某个容器重启丢失数据。
11.2 Pod网络
每个Pod为每个地址族分配一个唯一的IP地址,Pod中的每个容器共享网络空间,包括IP地址和网络端口。Pod内部,Pod的容器可以使用localhost与其他容器通信。Pod中的容器与另一个Pod通信则必须协调如何使用共享网络资源。Pod中,容器共享IP地址和port,并且可以通过localhost找到彼此。Pod中的容器当然可以使用标准内部进程通信,如SystemV信号量或者POSIX共享内存。容器在不同的Pod中有不同的IP地址,未经特殊配置,无法通过操作系统级别IPC进行通信。不同Pod中的容器通信可以通过IP网络。
Pod内的容器将系统的hostname视为Pod的name配置。
12 容器特权
Linux操作系统中,Pod中的任何容器都可以使用容器规范的安全上下文privileged标识启用特权模式。这对于容器使用操作系统管理员权限(如操作网络堆栈或访问硬件服务)非常有用。
如果集群开启WindowsHostProcessContainers特征,可以在Pod规范的安全上下文中通过设置windowsOptions.hostProcess创建Windows HostProcess pod。
这些Pod中的容器必须运行Windows HostProcess容器。HostProcess pod直接运行在主机中,并且可用于执行管理员任务,就像拥有Linux特权的容器一样。
13 静态Pod
静态Pod在特定的Node上由kubelet守护进程直接管理,没有API服务监测。然而大部分Pod可以通过控制面(如Deployment)管理,对于静态Pod,由kubelet直接监控。
特定的Node上,静态Pod总是与一个Kubelet绑定。静态Pod主要用于运行宿主机的控制面,即使用kubelet监控控制面组件。
在Kubernetes API服务器中,kubelet为每个静态Pod自动尝试创建镜像Pod,即Node中运行的Pod对于API服务器是可见的,但不能以此控制Pod。
14 容器探针
探针是容器中kubelet周期性执行的诊断程序。kubelet可以通过三种方式执行诊断:
- Exec
借助于容器运行时,执行shell脚本 - TCPSocket
由kubelet直接检测,TCP检测Pod的IP和port是否开通 - Http
由kubelet直接检测,发送Http Get请求
15 小结
核心:
(1)Pod是K8S中创建和管理的用于计算的可部署最小单元,是容器的外壳,不是进程;
(2)每个Pod可以包含一个或多个容器,一个Pod中的多个容器共享存储和网络;
(3)通常使用工作负载资源(如Deployments,Jobs和DaemonSets)创建Pod,而不是直接创建Pod;
(4)Controller用于复制Pod和自愈Pod,在模板中创建和管理Pod;
(5)Pod的模板更新是新建Pod副本,而不是在原有的Pod中更新或者添加补丁;
(6)静态Pod由kubelet守护进程管理,API服务器无法检测。