文章图片
什么是 Kubernetes?
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化工作负载和服务,有助于声明式配置和自动化。它拥有庞大且快速发展的生态系统。Kubernetes 服务、支持和工具广泛可用。
Kubernetes 这个名字来源于希腊语,意思是舵手或飞行员。K8s 作为一个缩写,是通过计算“K”和“s”之间的八个字母得出的。Google 于 2014 年开源了 Kubernetes 项目。现在各大厂商都在进行容器化改造,那么为什么选择kubernetes,那它能做什么呢?有什么用呢?下面详解:
为什么需要 Kubernetes 以及它可以做什么
容器是捆绑和运行应用程序的好方法。在生产环境中,您需要管理运行应用程序的容器并确保没有停机。例如,如果一个容器出现故障,则需要启动另一个容器。如果这种行为由系统处理,会不会更容易?
这就是 Kubernetes 来救援的方式!Kubernetes 为您提供了一个框架来弹性地运行分布式系统。它负责您的应用程序的扩展和故障转移,提供部署模式等等。例如,Kubernetes 可以轻松地为您的系统管理金丝雀部署。
Kubernetes:
- 服务发现和负载平衡 Kubernetes 可以使用 DNS 名称或使用自己的 IP 地址公开容器。如果容器的流量很高,Kubernetes 能够负载均衡和分配网络流量,从而使部署稳定。
- 自动推出和回滚 您可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为所需状态。例如,您可以自动化 Kubernetes 为您的部署创建新容器、删除现有容器并将其所有资源用于新容器。
- 存储编排 Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商等。
- 自动装箱 你为 Kubernetes 提供了一个节点集群,它可以用来运行容器化的任务。你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。Kubernetes 可以将容器安装到您的节点上,以充分利用您的资源。
- 自我修复 Kubernetes 会重新启动失败的容器、替换容器、杀死不响应用户定义的健康检查的容器,并且在它们准备好服务之前不会将它们通告给客户端。
- 秘密和配置管理 Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 SSH 密钥。您可以部署和更新机密和应用程序配置,而无需重新构建容器映像,也无需在堆栈配置中公开机密。
Master节点是集群控制节点,负责整个集群的管理和控制,基本上Kubernetes所有的控制命令都是发给它,它来负责具体的执行过程。
由于Master节点的重要性,它通常会独占一个物理机或虚拟机。
Master节点外的其它机器被称为Node节点,Node节点是集群中的工作负载节点,每个Node都会被Master分配一些工作负载(如Docker容器),当某个Node宕机时,其工作负载会被Master自动转移到其他节点上。
文章图片
Kubernetes术语理念 Mashi ter节点组件提供整个集群的控制面板:
kube-apiserver: 暴露API操作接口,是kubernetes里面所有资源增,删,改,查等操作的唯一入口;也是集群控制的入口。etcd: 集群的主数据库,集群里面的所有数据都存储于此。kube-controller-manager: kubernetes里所有资源对象的自动化控制中心, 控制器的大管家。kube-scheduler: 负责资源调度(Pod调度)的进程,为新创建的Pod分配Node节点去运行。
Node节点组件维持Pods的运行:
kubelet: 负责Pod对应容器的创建,启动,停止等任务; 同时与Master节点密切协作,实现集群管理的基本功能。kube-proxy: 实现Service的通信和负载均衡机制的重要组件。docker: docker引擎,负责本节点的容器创建和管理工作。supervisord: 进程监控,保持kubelet和docker的正常运行。fluentd: 日志收集
kubernetes集群中的对象或资源
pod:是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。label:一组绑定到kubernetes对象上的键/值对,同一对象的labels属性的Key必须独一无二。label selector: kubernetes核心的分组机制,通过它客户端能够识别一组有共同特征或属性的kubernetes对象。serivece: pod副本组成的集群实例。主要由一个IP和一个label selector组成。 实现pod集群的IP代理和负载均衡。voLume:类似于虚拟机的磁盘。Pod中能被多个容器访问的共享目录。namespaces:用于多租户的资源隔离。replicaSet:决定一个pod有多少同时允许的副本,并保证这些副本的期望状态与当前状态保持一致。Deployment: replicaset的升级版DaemonSet: 让所有Node节点运行同一个podJob: 类似于QuartzstatefulSet: 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。
pod是什么?
Pod:是Kubernetes的最重要最基本的概念。它是能够被创建,调度和管理的最小部署单元。一个Pod代表集群中一个运行的进程。
pod的组成
一个Pod由一个特殊的根容器Pause容器和若干个紧密相关的用户业务容器组成。Pause容器作为Pod的根容器,它的状态代表整个容器组的状态。Pod里的多个容器共享Pause容器的IP,共享Pause容器挂载的Volume.Kubernetes为每个Pod都分配了唯一的IP地址,称之为Pod IP,一个Pod里的多个容器共享Pod IP地址。
Kubernetes要求底层网络支持集群内任意两个Pod之间的TCP/IP直接通信,这通常采用虚拟二层网络技术来实现。
一个Pod里的容器与另外主机上的Pod容器能够直接通信。Pod里面的容器除了共享网络和存储外,还共享:PID namespace:一个Pod内的容器能够看到对方容器的进程
IPC namespace:一个Pod内的容器能够使用POSIX消息队列进行通信
UTS namespace : 一个Pod内的容器共享主机名。
文章图片
Pod生命周期
取值 | 描述 |
---|---|
Pending(悬决) | Pod已被 Kubernetes系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待Pod被调度的时间和通过网络下载镜像的时间。 |
Running(运行中) | Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded(成功) | Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed(失败) | Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown(未知) | 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
Always:只要退出就重启(默认)。OnFailure:失败退出时(exit code不为0)才重启。Never:永远不重启。
restartPolicy 适用于 Pod 中的所有容器。restartPolicy 仅针对同一节点上 kubelet 的容器重启动作。当 Pod 中的容器退出时,kubelet 会按指数回退 方式计算重启的延迟(10s、20s、40s、...),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题,kubelet 对该容器的重启回退计时器执行 重置操作。
Pod健康检查 livenessProbe:指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。
startupProbe: 指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器,而容器依其 重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。
readinessProbe:指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。
- ExecAction:在容器内部执行一个命令,如果该命令的返回值为0,则表示容器健康。
- TCPSocketAction:通过容器ip地址和端口号执行TCP检查,如果能够建立tcp连接表明容器健康。
- HTTPGetAction:通过容器Ip地址、端口号及路径调用http get方法,如果响应的状态吗大于200且小于400,则认为容器健康。
Pod自动调度 nodeSelector: 定向调度
Kubernetes Master上的scheduler服务(kube-Scheduler进程)负责实现Pod的调度,整个过程通过一系列复杂的算法,最终为每个Pod计算出一个最佳的目标节点,通常我们无法知道Pod最终会被调度到哪个节点上。实际情况中,我们需要将Pod调度到我们指定的节点上,可以通过Node的节点标签和pod的nodeSelector属性相匹配来达到目的。
NodeAffinity: 亲和性调度
调度策略是将来替换NodeSelector的新一代调度策略。由于NodeSelector通过Node的Label进行精确匹配,所有NodeAffinity增加了In、NotIn、Exists、DoesNotexist、Gt、Lt等操作符来选择Node。调度侧露更加灵活
NotIn 和 DoesNotExist 可用来实现节点反亲和性行为。
给节点添加标签
kubectl get nodes --show-labels #列出集群中的节点及其标签
kubectl label nodes disktype=ssd #选择一个节点,给它添加一个标签
下面清单描述了一个 Pod,它有一个节点亲和性配置requiredDuringSchedulingIgnoredDuringExecution,disktype=ssd。 这意味着 pod 只会被调度到具有 disktype=ssd 标签的节点上。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Pod的文件配置 Kubernetes里的所有资源对象都采用yaml或者JSON格式的文件来定义或描述,下面是Pod资源定义文件的模板:
#yaml格式的pod定义文件完整内容:
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #必选,Pod所属的命名空间
labels: #自定义标签
- name: string #自定义标签名字
annotations: #自定义注释列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口号名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存清楚,容器启动的初始可用数量
livenessProbe: #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: [Always | Never | OnFailure] #Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
Label和Label Selector
- 什么是Label
- Label是Kubernetes系列中另外一个核心概念。是一组绑定到K8s资源对象上的key/value对。同一个对象的labels属性的key必须唯一。label可以附加到各种资源对象上,如Node,Pod,Service,RC等。
- 什么是Label selector
- Label selector是Kubernetes核心的分组机制,通过label selector客户端/用户能够识别一组有共同特征或属性的资源对象。
- Label Selector 使用场合
- kube-controller进程通过资源对象RC,上定义的Label Selector来筛选要监控的Pod副本数量,从而实现Pod副本的数量始终符合预期设定的全自动控制流程。
- 通过对某些Node定义特定的Label,并且在Pod定义文件中使用NodeSelector这种标签调度策略,Kube-scheduler进程可以实现Pod定向调度的特性
- kupe-proxy进程通过Service的Label Selector来选择对应的Pod,自动建立器每个Service到对应Pod的请求转发路由表,从而实现Service的智能负载均衡机制
- Pod期待的副本数(replicas)
- 用于筛选目标Pod的Label Selector
- 当Pod的副本数量小于预期数量的时候,用于创建新Pod的Pod模板。
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
以下命令检查 ReplicationController 的状态
kubectl describe replicationcontrollers/nginx
要以机器可读的形式列出属于 ReplicationController 的所有 Pod,可以使用如下命令:
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
ReplicaSet ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。
Replica Sets是下一代的RC,它与RC当前存在的唯一区别是,它支持基于集合的Label selector; 而RC只支持基于等式的Label Selector。
kubectl命令行工具适用于RC的绝大部分命令都同样适用于Replica Sets. 当前我们很少单独使用Replica Set, 它主要被Deployment 这个更高层的资源对象所使用,从而形成一整套Pod创建,删除更新的编排机制。
示例如下:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# 按你的实际情况修改副本数
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
Deployments 一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力。
文章图片
以下是 Deployments 的典型用例:
- 创建 Deployment 以将 ReplicaSet 上线。 ReplicaSet 在后台创建 Pods。 检查 ReplicaSet 的上线状态,查看其是否成功。
- 更新 Deployments 的 PodTemplateSpec,声明 Pod 的新状态 。 新的 ReplicaSet 会被创建,Deployment 以受控速率将 Pod 从旧 ReplicaSet 迁移到新 ReplicaSet。 每个新的 ReplicaSet 都会更新 Deployment 的修订版本。
- Deployment 的当前状态不稳定,回滚到较早的 Deployment 版本。 每次回滚都会更新 Deployment 的修订版本。
- 扩大 Deployment 规模以承担更多负载
- 暂停 Deployment 以应用对 PodTemplateSpec 所作的多项修改, 然后恢复其执行以启动新的上线版本。
- 使用 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
在检查集群中的 Deployment 时,所显示的字段有:
1. NAME 列出了集群中 Deployment 的名称。
2. READY 显示应用程序的可用的“副本”数。显示的模式是“就绪个数/期望个数”。
3. UP-TO-DATE 显示为了达到期望状态已经更新的副本数。
4. AVAILABLE 显示应用可供用户使用的副本数。
5. AGE 显示应用程序运行的时间。
要查看 Deployment 上线状态 运行:
kubectl rollout status deployment/nginx-deployment
要查看 Deployment 创建的 ReplicaSet(rs),运行 kubectl get rs。 输出类似于:
NAMEDESIREDCURRENTREADYAGE
nginx-deployment-75675f589733318s
ReplicaSet 输出中包含以下字段:
1. NAME 列出名字空间中 ReplicaSet 的名称;
2. DESIRED 显示应用的期望副本个数,即在创建 Deployment 时所定义的值。 此为期望状态;
3. CURRENT 显示当前运行状态中的副本个数;
4. READY 显示应用中有多少副本可以为用户提供服务;
5. AGE 显示应用已经运行的时间长度。
要查看每个 Pod 自动生成的标签,运行:
kubectl get pods --show-labels
StatefulSet StatefulSet 是用来管理有状态应用的工作负载 API 对象,管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。
StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
文章图片
使用 StatefulSet的意义:
- 稳定的、唯一的网络标识符。
- 稳定的、持久的存储。
- 有序的、优雅的部署和扩缩。
- 有序的、自动的滚动更新。
下面的示例演示了 StatefulSet 的组件。
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # 必须匹配 .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # 默认值是 1
minReadySeconds: 10 # 默认值是 0
template:
metadata:
labels:
app: nginx # 必须匹配 .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
上述例子中:
- 名为 nginx 的 Headless Service 用来控制网络域名。
- 名为 web 的 StatefulSet 有一个 Spec,它表明将在独立的 3 个 Pod 副本中启动 nginx 容器。
- volumeClaimTemplates 将通过 PersistentVolumes 驱动提供的 PersistentVolumes 来提供稳定的存储。
不能超过 253 个字符
只能包含小写字母、数字,以及 '-' 和 '.'
必须以字母数字开头
必须以字母数字结尾
Job job控制器用于执行单次任务
可以设置运行次数,失败重试的次数,以及并行数。
job的三种使用场景:
- 非并行任务:只启一个pod,pod成功,job正常结束
- 并行任务同时指定成功个数:.spec.completions为指定成功个数,可以指定也可以不指定.spec.parallelism(指定>1,会有多个任务并行运行)。当成功个数达到.spec.completions,任务结束。
- 有工作队列的并行任务:.spec.completions默认为1,.spec.parallelism为大于0的整数。此时并行启动多个pod,只要有一个成功,任务结束,所有pod结束.
- completions:指定job启动的任务(如:pod)成功运行completions次,job才算成功结束
- parallelism:指定job同时运行的任务(如:pod)个数,Parallelism默认为1,如果设置为0,则job会暂停。
- backoffLimit:job建议指定pod的重启策略为never,如:.spec.template.spec.restartPolicy = "Never",然后通过job的backoffLimit来指定失败重试次数。在达到backoffLimit指定的次数后,job状态设置为failed(默认为6次),重试时间采用指数规避(10s, 20s, 40s …),并限制在6分钟内
- activeDeadlineSeconds:通过指定job存活时间,来结束一个job。当job运行时间达到activeDeadlineSeconds指定的时间后,job会停止由它启动的所有任务(如:pod),并设置job的状态为failed, reason: DeadlineExceeded
activeDeadlineSeconds的优先级高于backoffLimit
样例:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl","-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
查看 Job 对应的已完成的 Pod,可以执行
kubectl get pods
以机器可读的方式列举隶属于某 Job 的全部 Pod,你可以使用类似下面这条命令:
pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath='{.items[*].metadata.name}')
echo $pods
CronJob CronJob定时执行任务,实际就是基于Job实现的。
#┌────────────────── 时区 (可选)
#|┌───────────── 分钟 (0 - 59)
#|│ ┌───────────── 小时 (0 - 23)
#|│ │ ┌───────────── 月的某天 (1 - 31)
#|│ │ │ ┌───────────── month (1 - 12)
#|│ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系统上,7 也是星期日)
#|│ │ │ │ │
#|│ │ │ │ │
#|│ │ │ │ │
#CRON_TZ=UTC * * * * *
样例:
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date;
echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
获取CronJob信息:
kubectl get jobs --watch
删除 CronJob:
kubectl delete cronjob
查看Pod日志:
kubectl logs $pods
【Kuberneters及Pod概念详解】如有@侵权,请联系 2787950493@qq.com 改版。