Kubernetes云平台基础知识
参考文献:Wolf_Coder
1,k8s介绍
Kubernetes(k8s)是Google开源的容器集群管理系统。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模 容器集群管理的便捷性。
1、k8s的优势
容器编排;轻量级;开源;弹性伸缩;负载均衡
2、重要概念:
`Cluster`: 是计算、存储和网络资源的集合,k8s利用这些资源运行各种基于容器的应用.
`Master`: master是cluster的大脑,他的主要职责是调度,即决定将应用放在那里运行。master运行linux操作系统,可以是物理机或者虚拟机。为了实现高可用,可以运行多个master。
`Node`: 职责是运行容器应用。node由master管理,node负责监控并汇报容器的状态,同时根据master的要求管理容器的生命周期。node运行在linux的操作系统上,可以是物理机或者是虚拟机。
`Pod`: pod是k8s的最小工作单元。每个pod包含一个或者多个容器。pod中的容器会作为一个整体被master调度到一个node上运行。引入pod目的:(1)可管理性(2)通信和资源共享。pods使用方式:(1)运行单一容器(2)运行多容器。
`Controller`: k8s通常不会直接创建pod,而是通过controller来管理pod的。controller中定义了pod的部署特性,比如有几个剧本,在什么样的node上运行等。为了满足不同的业务场景,k8s提供了多种controller,包括deployment、replicaset、daemonset、statefulset、job等。
`Deployment`: 是最常用的controller。deployment可以管理pod的多个副本,并确保pod按照期望的状态运行。
`Replicaset`: 实现了pod的多副本管理。使用deployment时会自动创建replicaset,也就是说deployment是通过replicaset来管理pod的多个副本的,我们通常不需要直接使用replicaset。
`Daemonset`: 用于每个node最多只运行一个pod副本的场景。正如其名称所示的,daemonset通常用于运行daemon。
`Job`: 用于运行结束就删除的应用,而其他controller中的pod通常是长期持续运行的。
`Service`: deployment可以部署多个副本,每个pod 都有自己的IP,外界如何访问这些副本那?答案是service。k8s的 service定义了外界访问一组特定pod的方式。service有自己的IP和端口,service为pod提供了负载均衡。k8s运行容器pod与访问容器这两项任务分别由controller和service执行。
`Namespace`: 可以将一个物理的cluster逻辑上划分成多个虚拟cluster,每个cluster就是一个namespace。不同的namespace里的资源是完全隔离的。
2,k8s架构分析
k8s的集群由master和node组成,节点上运行着若干k8s服务。
1、master节点
master节点之上运行着的后台服务有kube-apiserver 、kube-scheduler、kube-controller-manager、etcd和pod网络(calico)
(1)API Server: API Server是k8s的前端接口,各种客户端工具以及k8s其他组件,可以通过它管理集群的各种资源。
(2)Scheduler: scheduer负责决定将pod放在哪个node上运行。另外scheduler在调度时会充分考虑集群的架构,当前各个节点的负载,以及应用对高可用、性能、数据亲和性的需求。
(3)Controller Manager: 负责管理集群的各种资源,保证资源处于预期的状态。
(4)etcd: 负责保存k8s集群的配置信息和各种资源的状态信息,当数据发生变化时,etcd会快速的通知k8s相关组件。
(5)pod网络:pod要能够相互通信,k8s集群必须掌握pod网络,fannel是其中一个可选的方案,我们用的是calico。
2、node节点
node是pod运行的地方。node上运行的k8s组件有kubelet、kube-proxy和pod网络(例如flannel、calico)
(1)kubelet: 是node的agent,当scheduler去确定在某个node上运行pod后,会将pod的具体配置信息发送给该节点的kubelet,kubelet会根据这些信息创建和运行容器,并向master报告运行状态。
(2)kube-proxy: 每个node都会运行kube-proxy服务,外界通过service访问pod,kube-proxy负责将降访问service的TCP/UDP数据流转发到后端的容器。如果有多个副本,kube-proxy会实现负载均衡。
(3)pod网络:pod能能够互相通信,k8s集群必须部署pod网络,flannel是其中一个可以选择的方案
完整框架:
问题:为什么 k8s-master 上也有 kubelet 和 kube-proxy 呢?
这是因为 Master 上也可以运行应用,即 Master 同时也是一个 Node。
几乎所有的 Kubernetes 组件本身也运行在 Pod 里。
Kubernetes 的系统组件都被放到kube-system namespace 中。这里有一个kube-dns 组件,它为 Cluster 提供 DNS 服务。kube-dns是在执行kubeadm init 时作为附加组件安装的。
kubelet 是唯一没有以容器形式运行的 Kubernetes 组件,它在系统中通过 Systemd 运行。
3、部署过程:
(1)kubectl 发送部署请求到 API Server。
(2)API Server 通知 Controller Manager 创建一个 deployment 资源。
(3)Scheduler 执行调度任务,将两个副本 Pod 分发到 k8s-node1 和 k8s-node2。
(4)k8s-node1 和 k8s-node2 上的 kubectl 在各自的节点上创建并运行 Pod。
补充两点:
(1)应用的配置和当前状态信息保存在 etcd 中,执行 kubectl get pod 时 API Server 会从 etcd 中读取这些数据。
(2)flannel(calico)会为每个 Pod 都分配 IP。因为没有创建 service,目前 kube-proxy 还没参与进来。
4,pod生命周期阶段
pod的生命周期可以简单描述为:首先pod被创建,紧接着pod被调度到node进行部署运行。pod是非常忠诚的,一旦别分配到node后,就不会离开这个node,直到它被删除,生命周期完结。
pod的生命周期被定义为以下几个阶段:
(1)Pending:pod已经别创建,但是一个或者多个容器还未创建,这包括pod调度阶段,以及容器镜像的下载过程。
(2)Running:pod已经被调度到node,所有容器已经创建,并且至少一个容器在运行或者正在重启。
(3)Succeeded:pod中所有容器正常退出。
(4)Failed:pod中所有容器退出,至少有一个容器是一次退出的。
3,创建资源的方式
1、用kubectl命令直接创建,比如:
kubectl run httpd-app --image=reg.yunwei.com/learn/httpd:latest --replicas=2
在命令行中通过参数指定资源的属性。
2、通过配置文件和kubectl apply -f 创建:
kubectl apply -f httpd.yaml
httpd.yaml的内容:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 2
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd-app
image: reg.yunwei.com/learn/httpd:latest
3、比较
基于命令的方式:
(1)简单直观快捷,上手快。
(2)适合临时测试或实验。
基于配置文件的方式:
(1)配置文件描述了what,即应用最终要达到的状态。
(2)配置文件提供了创建资源的模板,能够重复部署。
(3)可以像管理代码一样管理部署。
(4)适合正式的、跨环境的、规模化部署。
(5)这种方式要求熟悉配置文件的语法,有一定的难度。
4,容器
容器按照持续运行的时间可分为两类:服务类容器和工作类容器。
服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等。工作类容器则是一次性任务,比如批处理程序,完成后容器就退出。
Kubernetes 的 Deployment、ReplicaSet 和 DaemonSet 都用于管理服务类容器;对于工作类容器,我们用 Job。
4.1、deployment yaml 文件
1.deployment 的配置格式
① apiVersion 是当前配置格式的版本。
② kind 是要创建的资源类型,这里是 Deployment。
③ metadata 是该资源的元数据,name 是必需的元数据项。
④ spec 部分是该 Deployment 的规格说明。
⑤ replicas 指明副本数量,默认为 1。
⑥ template 定义 Pod 的模板,这是配置文件的重要部分。
⑦ metadata 定义 Pod 的元数据,至少要定义一个 label。label 的 key 和 value 可以任意指定。
⑧ spec 描述 Pod 的规格,此部分定义 Pod 中每一个容器的属性,name 和 image 是必需的。
注意:最后name前面加个横线是因为container后面是一个列表
2.运行yaml文件:
kubectl apply -f httpd.yaml #运行pod
kubectl delete -f http.yaml #删除pod
(1)伸缩(Scale Up/Down):是指在线增加或减少 Pod 的副本数。直接改写yaml配置文件的 replicas 参数即可
(2)节点故障(Failover):若其中一个node故障, Kubernetes 会检查到 k8s-node3 不可用,将 k8s-node1 上的 Pod 标记为 Terminating 状态,并在 k8s-node2 上新创建两个 Pod,维持总副本数为原指定副本数 3。
当 k8s-node2 恢复后,Terminating 的 Pod 会被删除,不过已经运行的 Pod 不会重新调度回 k8s-node2。
(3)用 label 控制 Pod 的位置: 默认配置下,Scheduler 会将 Pod 调度到所有可用的 Node。不过有些情况我们希望将 Pod 部署到指定的 Node,比如将有大量磁盘 I/O 的 Pod 部署到配置了 SSD 的 Node;或者 Pod 需要 GPU,需要运行在配置了 GPU 的节点上。
Kubernetes 是通过 label 来实现这个功能的。label 是 key-value 对,各种资源都可以设置 label,灵活添加各种自定义属性。
给节点添加label:
kubectl label node 192.168.11.5 disktype=ssd
yaml文件中yaml的应用:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd-deployment
spec:
replicas: 2
template:
metadata:
labels:
name: httpd
spec:
containers:
- name: httpd-app
image: reg.yunwei.com/learn/httpd:latest
nodeSelector:
disktype: ssd
4.2、DaemonSet应用
Deployment 部署的副本 Pod 会分布在各个 Node 上,每个 Node 都可能运行好几个副本。DaemonSet 的不同之处在于:每个 Node 上最多只能运行一个副本。
DaemonSet 的典型应用场景有:
(1)在集群的每个节点上运行存储 Daemon,比如 glusterd 或 ceph。
(2)在每个节点上运行日志收集 Daemon,比如 flunentd 或 logstash。
(3)在每个节点上运行监控 Daemon,比如 Prometheus Node Exporter 或 collectd。
4.3、Job
4.3.1,Job应用
1、编写job的yaml文件myjob.yaml:
apiVersion: batch/v1
kind: Job
metadata:
name: job
spec:
template:
spec:
containers:
- name: job
image: reg.yunwei.com/learn/busybox:latest
command: ["echo","hello kubernetes"]
restartPolicy: Never
① batch/v1 是当前 Job 的 apiVersion。
② 指明当前资源的类型为 Job。
③ restartPolicy 指定什么情况下需要重启容器。对于 Job,只能设置为 Never 或者 OnFailure。对于其他 controller(比如 Deployment)可以设置为 Always 。
2、启动job
[root@ren7 yaml]# kubectl apply -f myjob.yaml
job.batch/job created
3、查看job的状态
[root@ren7 yaml]# kubectl get job
NAME COMPLETIONS DURATION AGE
job 1/1 3s 84s
4、查看pod的状态
[root@ren7 yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
job-m9shb 0/1 Completed 0 2m40s
显示completed已经完成
5、查看pod的标准输出
[root@ren7 yaml]# kubectl logs job-m9shb
hello kubernetes
4.3.2,并行执行job
有时,我们希望能同时运行多个pod,提高job的执行效率。
1、设置parallelism
[root@ren7 yaml]# cat myjob.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job
spec:
parallelism: 2
template:
spec:
containers:
- name: job
image: reg.yunwei.com/learn/busybox:latest
restartPolicy: Never
2、执行该yaml文件
[root@ren7 yaml]# kubectl apply -f myjob.yaml
job.batch/job created
3、job一共启动了两个pod,而且AGE相同,可见是并行运行的。
现实中确实存在很多需要并行处理的场景。比如批处理程序,每个副本(Pod)都会从任务池中读取任务并执行,副本越多,执行时间就越短,效率就越高。这种类似的场景都可以用 Job 来实现。
4.3.3,定时执行job
Linux 中有 cron 程序定时执行任务,Kubernetes 的 CronJob 提供了类似的功能,可以定时执行 Job。
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: timing
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: timing
image: reg.yunwei.com/learn/busybox:latest
command: ["echo","hello k8s cronjob!"]
restartPolicy: OnFailure
① batch/v1beta1 是当前 CronJob 的 apiVersion。
② 指明当前资源的类型为 CronJob。
③ schedule 指定什么时候运行 Job,其格式与 Linux cron 一致。这里 */1 * * * * 的含义是每一分钟启动一次。
④ jobTemplate 定义 Job 的模板,格式与前面 Job 一致。
5,service
我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉。Deployment 等 controller 会通过动态创建和销毁 Pod 来保证应用整体的健壮性。换句话说,Pod 是脆弱的,但应用是健壮的。
每个 Pod 都有自己的 IP 地址。当 controller 用新 Pod 替代发生故障的 Pod 时,新 Pod 会分配到新的 IP 地址。这样就产生了一个问题:
如果一组 Pod 对外提供服务(比如 HTTP),它们的 IP 很有可能发生变化,那么客户端如何找到并访问这个服务呢?
Kubernetes 给出的解决方案是 Service。
1,通过service访问pod
Kubernetes Service 从逻辑上代表了一组 Pod,具体是哪些 Pod 则是由 label 来挑选。Service 有自己的 IP,而且这个 IP 是不变的。客户端只需要访问 Service 的 IP,Kubernetes 则负责建立和维护 Service 与 Pod 的映射关系。无论后端 Pod 如何变化,对客户端不会有任何影响,因为 Service 没有变。
#先创建deployment文件,在创建service文件:apiVersion: v1
kind: Service
metadata:
name: httpd-svc
spec:
ports:
- port: 8080
targetPort: 80
protocol: TCP
selector:
run: httpd
① v1 是 Service 的 apiVersion。
② 指明当前资源的类型为 Service。
③ Service 的名字为 httpd-svc。
④ selector 指明挑选那些 label 为 run: httpd 的 Pod 作为 Service 的后端。
⑤ 将 Service 的 8080 端口映射到 Pod 的 80 端口,使用 TCP 协议。
2,Service IP 原理
我们知道 Pod 的 IP 是在容器中配置的,那么 Service 的 Cluster IP 又是配置在哪里的呢?CLUSTER-IP 又是如何映射到 Pod IP 的呢?
答案是 iptables
Service Cluster IP 是一个虚拟 IP,是由 Kubernetes 节点上的 iptables 规则管理的。
[root@ren7 yaml]# iptables-save |grep 10.68.226.108
-A KUBE-SERVICES -d 10.68.226.108/32 -p tcp -m comment --comment "default/httpd-svc: cluster IP" -m tcp --dport 8080 -j KUBE-SVC-RL3JAE4GN7VOGDGP
这条规则的含义是:如果 Cluster 内的 Pod要访问 httpd-svc,跳转到规则 KUBE-SVC-RL3JAE4GN7VOGDGP
KUBE-SVC-RL3JAE4GN7VOGDGP 规则如下:
[root@ren7 yaml]# iptables-save |grep KUBE-SVC-RL3JAE4GN7VOGDGP
:KUBE-SVC-RL3JAE4GN7VOGDGP - [0:0]
-A KUBE-SERVICES -d 10.68.226.108/32 -p tcp -m comment --comment "default/httpd-svc: cluster IP" -m tcp --dport 8080 -j KUBE-SVC-RL3JAE4GN7VOGDGP
-A KUBE-SVC-RL3JAE4GN7VOGDGP -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-AYADGRA7HLSB6YHK
-A KUBE-SVC-RL3JAE4GN7VOGDGP -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-3IGLIDMQNZTXMCRT
-A KUBE-SVC-RL3JAE4GN7VOGDGP -j KUBE-SEP-XLZBWWZ3VO73ZBZY
(1)1/3 的概率跳转到规则 KUBE-SEP-AYADGRA7HLSB6YHK
(2)1/3 的概率(剩下 2/3 的一半)跳转到规则 KUBE-SEP-3IGLIDMQNZTXMCRT
(3)1/3 的概率跳转到规则 KUBE-SEP-XLZBWWZ3VO73ZBZY
即将请求分别转发到后端的三个 Pod。通过上面的分析,我们得到如下结论:
iptables 将访问 Service 的流量转发到后端 Pod,而且使用类似轮询的负载均衡策略。
另外需要补充一点:Cluster 的每一个节点都配置了相同的 iptables 规则,这样就确保了整个 Cluster 都能够通过 Service 的 Cluster IP 访问 Service。
3,DNS访问service
coredns 是一个 DNS 服务器。每当有新的 Service 被创建,coredns 会添加该 Service 的 DNS 记录。Cluster 中的 Pod 可以通过 <SERVICE_NAME>.<NAMESPACE_NAME> 访问 Service。
我们通过另一个容器来访问刚才的pod
(1)启动容器busybox
(2)通过名称访问service中运行的pod(进入到容器busybox中)
wget httpd-svc:80
发现可以访问。但要注意,通过名称访问,只能在同一名称空间。如果不是在同一名称空间,需要指定namespace. 执行如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: httpd2
namespace: kube-public
spec:
replicas: 2
template:
metadata:
labels:
name: httpd2
run: httpd2
spec:
containers:
- name: httpd-app2
image: reg.yunwei.com/learn/httpd:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpd-svc2
namespace: kube-public
spec:
ports:
- port: 8080
targetPort: 80
protocol: TCP
selector:
run: httpd2
同样启动容器busybox,并指定名称空间进行访问
wget httpd2-svc.kube-public:80
或者在启动容器busybox时就指定名称空间
kubectl run -it –image=busybox -n kube-public /bin/sh
4,外网访问service
除了 Cluster 内部可以访问 Service,很多情况我们也希望应用的 Service 能够暴露给 Cluster 外部。Kubernetes 提供了多种类型的 Service,默认是 ClusterIP
。
(1)ClusterIP
Service 通过 Cluster 内部的 IP 对外提供服务,只有 Cluster 内的节点和 Pod 可访问,这是默认的 Service 类型,前面实验中的 Service 都是 ClusterIP。
(2)NodePort
Service 通过 Cluster 节点的静态端口对外提供服务。Cluster 外部可以通过 : 访问 Service。
(3)LoadBalancer
Service 利用 cloud provider 特有的 load balancer 对外提供服务,cloud provider 负责将 load balancer 的流量导向 Service。目前支持的 cloud provider 有 GCP、AWS、Azur 等。
apiVersion: v1
kind: Service
metadata:
name: httpd-svc3
spec:
ports:
- port: 8080
targetPort: 80
protocol: TCP
nodePort: 30000
selector:
run: httpd
type: NodePort
(1)nodePort 是节点上监听的端口。
(2)port 是 ClusterIP 上监听的端口(svc的端口)。
(3)targetPort 是 Pod 监听的端口。
6,k8s健康检查
默认的健康检查
强大的自愈能力是 Kubernetes 这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。除此之外,用户还可以利用 Liveness 和 Readiness 探测机制设置更精细的健康检查,进而实现如下需求:
(1)零停机部署。
(2)避免部署无效的镜像。
(3)更加安全的滚动升级。
每个容器启动时都会执行一个进程,此进程由 Dockerfile 的 CMD 或 ENTRYPOINT 指定。如果进程退出时返回码非零,则认为容器发生故障,Kubernetes 就会根据 restartPolicy 重启容器。
Liveness探测
Liveness 探测让用户可以自定义判断容器是否健康的条件。如果探测失败,Kubernetes 就会重启容器。
livenessProbe 部分定义如何执行 Liveness 探测:
探测的方法是:通过 cat 命令检查 /tmp/healthy 文件是否存在。如果命令执行成功,返回值为零,Kubernetes 则认为本次 Liveness 探测成功;如果命令返回值非零,本次 Liveness 探测失败。
initialDelaySeconds: 10 指定容器启动 10 之后开始执行 Liveness 探测,我们一般会根据应用启动的准备时间来设置。比如某个应用正常启动要花 30 秒,那么 initialDelaySeconds 的值就应该大于 30。
periodSeconds: 5 指定每 5 秒执行一次 Liveness 探测。Kubernetes 如果连续执行 3 次 Liveness 探测均失败,则会杀掉并重启容器。
Readiness 探测
用户通过 Liveness 探测可以告诉 Kubernetes 什么时候通过重启容器实现自愈;Readiness 探测则是告诉 Kubernetes 什么时候可以将容器加入到 Service 负载均衡池中,对外提供服务。
Pod readiness 的 READY 状态经历了如下变化:
刚被创建时,READY 状态为不可用。
15 秒后(initialDelaySeconds + periodSeconds),第一次进行 Readiness 探测并成功返回,设置 READY 为可用。
30 秒后,/tmp/healthy 被删除,连续 3 次 Readiness 探测均失败后,READY 被设置为不可用。
下面对 Liveness 探测和 Readiness 探测做个比较:
Liveness 探测和 Readiness 探测是两种 Health Check 机制,如果不特意配置,Kubernetes 将对两种探测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断探测是否成功。
两种探测的配置方法完全一样,支持的配置参数也一样。不同之处在于探测失败后的行为:Liveness 探测是重启容器;Readiness 探测则是将容器设置为不可用,不接收 Service 转发的请求。
Liveness 探测和 Readiness 探测是独立执行的,二者之间没有依赖,所以可以单独使用,也可以同时使用。用 Liveness 探测判断容器是否需要重启以实现自愈;用 Readiness 探测判断容器是否已经准备好对外提供服务。
7,k8s管理存储资源
7.1,Kubernetes如何管理存储资源
理解Volume
我们经常会说:容器和 Pod 是短暂的。
其含义是它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。
为了持久化保存容器的数据,可以使用Kubernetes Volume。
Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。
本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。Kubernetes Volume 也支持多种 backend 类型,包括 emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等,完整列表可参考
https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes
Volume 提供了对各种 backend 的抽象,容器在使用 Volume 读写数据的时候不需要关心数据到底是存放在本地节点的文件系统中呢还是云硬盘上。对它来说,所有类型的 Volume 都只是一个目录。
7.2,kubernetes Volume种类
1、emptyDir
emptyDir 是最基础的 Volume 类型。一个 emptyDir Volume 是 Host 上的一个空目录。emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。emptyDir Volume 的生命周期与 Pod 一致。
① 文件最底部 volumes 定义了一个 emptyDir 类型的 Volume shared-volume。
② producer 容器将 shared-volume mount 到 /producer_dir 目录。
③ producer 通过 echo 将数据写到文件 hello 里。
④ consumer 容器将 shared-volume mount 到 /consumer_dir 目录。
⑤ consumer 通过 cat 从文件 hello 读数据。
emptyDir 是 Host 上创建的临时目录,其优点是能够方便地为 Pod 中的容器提供共享存储,不需要额外的配置。但它不具备持久性,如果 Pod 不存在了,emptyDir 也就没有了。
2、hostPath Volume
hostPath Volume 的作用是将 Docker Host 文件系统中已经存在的目录 mount 给 Pod 的容器。大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath。
如果 Pod 被销毁了,hostPath 对应的目录也还会被保留,从这点看,hostPath 的持久性比 emptyDir 强。不过一旦 Host 崩溃,hostPath 也就没法访问了。
3、外部Storage Provider
如果 Kubernetes 部署在诸如 AWS、GCE、Azure 等公有云上,可以直接使用云硬盘作为 Volume,下面是 AWS Elastic Block Store 的例子:
Kubernetes Volume 也可以使用主流的分布式存,比如 Ceph、GlusterFS 等,下面是 Ceph 的例子:
相对于 emptyDir 和 hostPath,这些 Volume 类型的最大特点就是不依赖 Kubernetes。Volume 的底层基础设施由独立的存储系统管理,与 Kubernetes 集群是分离的。数据被持久化后,即使整个 Kubernetes 崩溃也不会受损。
4、PV & PVC
PersistentVolume (PV) 是外部存储系统中的一块存储空间,由管理员创建和维护。与 Volume 一样,PV 具有持久性,生命周期独立于 Pod。
PersistentVolumeClaim (PVC) 是对 PV 的申请 (Claim)。PVC 通常由普通用户创建和维护。需要为 Pod 分配存储资源时,用户可以创建一个 PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,Kubernetes 会查找并提供满足条件的 PV。
#NFS pv的编排文件:apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /nfsdata/pv1 #需要创建pv1目录,否则pod起不来
server: 192.168.11.7
① capacity
指定 PV 的容量为 1G。
② accessModes
指定访问模式为 ReadWriteOnce
,支持的访问模式有:
ReadWriteOnce – PV 能以 read-write 模式 mount 到单个节点。
ReadOnlyMany – PV 能以 read-only 模式 mount 到多个节点。
ReadWriteMany – PV 能以 read-write 模式 mount 到多个节点。
③ persistentVolumeReclaimPolicy
指定当 PV 的回收策略为 Recycle
,支持的策略有:
Retain – 需要管理员手工回收。
Recycle – 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*
。
Delete – 删除 Storage Provider 上的对应存储资源,例如 AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume 等。
④ storageClassName
指定 PV 的 class 为 nfs
。相当于为 PV 设置了一个分类,PVC 可以指定 class 申请相应 class 的 PV。
⑤ 指定 PV 在 NFS 服务器上对应的目录。
#PVC的编排文件:apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs
#在pod中使用PVC:apiVersion: v1
kind: Pod
metadata:
name: mypod1
spec:
containers:
- name: mypod1
image: reg.yunwei.com/learn/busybox:latest
args:
- /bin/sh
- -c
- sleep 30000
volumeMounts:
- mountPath: "/mydata"
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: mypvc1
回收pv:
(1)先停掉pod
(2)删除PVC
(3)删除pv
pv的动态供给:
动态供给是通过 StorageClass 实现的
8,机密信息管理(secret)
应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名密码或者秘钥。将这些信息直接保存在容器镜像中显然不妥,Kubernetes 提供的解决方案是 Secret。
Secret 会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。Secret 会以 Volume 的形式被 mount 到 Pod,容器可通过文件的方式使用 Secret 中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。
Secret 可通过命令行或 YAML 创建。比如希望 Secret 中包含如下信息:
1)用户名 admin
2)密码 123456
1、四种常见secret的方法:
(1)通过 --from-literal:
kubectl create secret generic mysecret --from-literal=username=admin --from-literal=password=123
(2)通过 --from-file:
echo -n admin > ./username
echo -n 123456 > ./password
kubectl create secret generic mysecret --from-file=./username --from-file=./password
(3)通过 --from-env-file:
cat << EOF > env.txt
username=admin
password=123456
EOF
kubectl create secret generic mysecret --from-env-file=env.txt
(4)通过 YAML 配置文件:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
data:
username: YWRtaW4=
password: MTIzNDU2
文件中的敏感数据必须是通过 base64 编码后的结果。(-n 不换行)
[root@ren7 ~]# echo -n admin | base64
YWRtaW4=
[root@ren7 ~]# echo -n 123456 | base64
MTIzNDU2
2、volume方式使用secret
Pod 可以通过 Volume 或者环境变量的方式使用 Secret,先学习 Volume 方式。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: reg.yunwei.com/learn/busybox:latest
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
volumeMounts:
- mountPath: "/etc/foo"
name: foo
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
① 定义 volume foo,来源为 secret mysecret
② 将 foo mount 到容器路径 /etc/foo,可指定读写权限为 readOnly
自定义存放数据的文件名:
secret:
secretName: mysecret
items:
- key: username
path: my-group/my-username
- key: password
path: my-group/my-password
以 Volume 方式使用的 Secret 支持动态更新:Secret 更新后,容器中的数据也会更新。
3、环境变量方式使用secret
apiVersion: v1
kind: Pod
metadata:
name: mypod3
spec:
containers:
- name: mypod3
image: reg.yunwei.com/learn/busybox:latest
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
环境变量读取 Secret 很方便,但无法支撑 Secret 动态更新。
Secret 可以为 Pod 提供密码、Token、私钥等敏感数据。
9、配置信息管理(configmap)
Secret 可以为 Pod 提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以用 ConfigMap
ConfigMap 的创建和使用方式与 Secret 非常类似,主要的不同是数据以明文的形式存放。
与 Secret 一样,ConfigMap 也支持四种创建方式:(–from-literal、–from-file、–from-env-file、yaml)
总结:如果信息需要加密,可使用 Secret;如果是一般的配置信息,则可使用ConfigMap。Secret 和 ConfigMap 支持四种定义方法。Pod 在使用它们时,可以选择 Volume 方式或环境变量方式,不过只有 Volume 方式支持动态更新。
10,k8s监控
10.1,Weave Scope
Weave Scope 是 Docker 和 Kubernetes 可视化监控工具。Scope 提供了至上而下的集群基础设施和应用的完整视图,用户可以轻松对分布式的容器化应用进行实时监控和问题诊断。
Weave Scope 的最大特点是会自动生成一张 Docker 容器地图,让我们能够直观地理解、监控和控制容器。
10.2,Heapster
Heapster 是 Kubernetes 原生的集群监控方案。Heapster 以 Pod 的形式运行,它会自动发现集群节点、从节点上的 Kubelet 获取监控数据。Kubelet 则是从节点上的 cAdvisor 收集数据。
Heapster 将数据按照 Pod 进行分组,将它们存储到预先配置的 backend 并进行可视化展示。Heapster 当前支持的 backend 有 InfluxDB(通过 Grafana 展示),Google Cloud Monitoring 等。
10.3,Prometheus
Prometheus是一个开源系统监测和警报工具箱。 Prometheus Operator 是 CoreOS 开发的基于 Prometheus 的 Kubernetes 监控方案,也可能是目前功能最全面的开源方案。
主要特征:
1)多维数据模型(时间序列由metri和key/value定义)
2)灵活的查询语言
3)不依赖分布式存储
4)采用 http 协议,使用 pull 拉取数据
5)可以通过push gateway进行时序列数据推送
6)可通过服务发现或静态配置发现目标
7)多种可视化图表及仪表盘支持
架构图:
Prometheus组件包括:Prometheus server、push gateway 、alertmanager、Web UI等。
Prometheus server 定期从数据源拉取数据,然后将数据持久化到磁盘。Prometheus 可以配置 rules,然后定时查询数据,当条件触发的时候,会将 alert 推送到配置的 Alertmanager。Alertmanager 收到警告的时候,可以根据配置,聚合并记录新时间序列,或者生成警报。同时还可以使用其他 API 或者 Grafana 来将收集到的数据进行可视化。
Prometheus Operator 的目标是尽可能简化在 Kubernetes 中部署和维护 Prometheus 的工作。其架构如下图所示:
图上的每一个对象都是 Kubernetes 中运行的资源。
Operator
Operator 即 Prometheus Operator,在 Kubernetes 中以 Deployment 运行。其职责是部署和管理 Prometheus Server,根据 ServiceMonitor 动态更新 Prometheus Server 的监控对象。
Prometheus Server
Prometheus Server 会作为 Kubernetes 应用部署到集群中。为了更好地在 Kubernetes 中管理 Prometheus,CoreOS 的开发人员专门定义了一个命名为 Prometheus 类型的 Kubernetes 定制化资源。我们可以把 Prometheus看作是一种特殊的 Deployment,它的用途就是专门部署 Prometheus Server。
Service
这里的 Service 就是 Cluster 中的 Service 资源,也是 Prometheus 要监控的对象,在 Prometheus 中叫做 Target。每个监控对象都有一个对应的 Service。比如要监控 Kubernetes Scheduler,就得有一个与 Scheduler 对应的 Service。当然,Kubernetes 集群默认是没有这个 Service 的,Prometheus Operator 会负责创建。
ServiceMonitor
Operator 能够动态更新 Prometheus 的 Target 列表,ServiceMonitor 就是 Target 的抽象。比如想监控 Kubernetes Scheduler,用户可以创建一个与 Scheduler Service 相映射的 ServiceMonitor 对象。Operator 则会发现这个新的 ServiceMonitor,并将 Scheduler 的 Target 添加到 Prometheus 的监控列表中。
ServiceMonitor 也是 Prometheus Operator 专门开发的一种 Kubernetes 定制化资源类型。
Alertmanager
除了 Prometheus 和 ServiceMonitor,Alertmanager 是 Operator 开发的第三种 Kubernetes 定制化资源。我们可以把 Alertmanager 看作是一种特殊的 Deployment,它的用途就是专门部署 Alertmanager 组件。
总结:
Weave Scope 可以展示集群和应用的完整视图。其出色的交互性让用户能够轻松对容器化应用进行实时监控和问题诊断。
Heapster 是 Kubernetes 原生的集群监控方案。预定义的 Dashboard 能够从 Cluster 和 Pods 两个层次监控 Kubernetes。
Prometheus Operator 可能是目前功能最全面的 Kubernetes 开源监控方案。除了能够监控 Node 和 Pod,还支持集群的各种管理组件,比如 API Server、Scheduler、Controller Manager 等。
资源,也是 Prometheus 要监控的对象,在 Prometheus 中叫做 Target。每个监控对象都有一个对应的 Service。比如要监控 Kubernetes Scheduler,就得有一个与 Scheduler 对应的 Service。当然,Kubernetes 集群默认是没有这个 Service 的,Prometheus Operator 会负责创建。
ServiceMonitor
Operator 能够动态更新 Prometheus 的 Target 列表,ServiceMonitor 就是 Target 的抽象。比如想监控 Kubernetes Scheduler,用户可以创建一个与 Scheduler Service 相映射的 ServiceMonitor 对象。Operator 则会发现这个新的 ServiceMonitor,并将 Scheduler 的 Target 添加到 Prometheus 的监控列表中。
ServiceMonitor 也是 Prometheus Operator 专门开发的一种 Kubernetes 定制化资源类型。
Alertmanager
除了 Prometheus 和 ServiceMonitor,Alertmanager 是 Operator 开发的第三种 Kubernetes 定制化资源。我们可以把 Alertmanager 看作是一种特殊的 Deployment,它的用途就是专门部署 Alertmanager 组件。
总结:
Weave Scope 可以展示集群和应用的完整视图。其出色的交互性让用户能够轻松对容器化应用进行实时监控和问题诊断。
Heapster 是 Kubernetes 原生的集群监控方案。预定义的 Dashboard 能够从 Cluster 和 Pods 两个层次监控 Kubernetes。
Prometheus Operator 可能是目前功能最全面的 Kubernetes 开源监控方案。除了能够监控 Node 和 Pod,还支持集群的各种管理组件,比如 API Server、Scheduler、Controller Manager 等。