【读书笔记】每天5分钟玩转Kubernetes(2)

第六章:通过Service访问Pod

Pod是脆弱的,应用是健壮的。

6.1 创建Service

Kubernetes Service有自己的IP,且IP不变。客户端访问Service的IP,Kubernetes负责建立和维护Service与Pod的映射关系。

(1)v1是Service的apiVersion

(2)指明当前资源类型为Service

(3)Service的名字为httpd-svc

(4)selector指明挑选那些label为run:httpd的Pod作为Service的后端

(5)将Service的8080端口映射到Pod的80端口,使用TCP协议

 

Cluster IP通过iptables映射到Pod IP。

 

6.2 Cluster IP 底层实现

Cluster IP是一个虚拟IP,由Kubernetes节点上的iptables规则管理。

可以通过iptables-save命令打印出当前节点的iptables规则,只截取httpd-svc Cluster IP 10.99.229.179 相关的信息,如下图:

这两条规则含义:

(1)如果Cluster内的Pod(源地址来自 10.244.0.0/16)要访问httpd-svc,则允许。

(2)其他源地址访问httpd-svc,跳转到规则KUBE-SVC-RL xxxx DGP。

KUBE-SVC-RL xxxx DGP规则如下:

结论:iptables将访问Service的流量转发到后端Pod,使用类似轮询的负载均衡策略。Cluster的每一个节点都配置了相同的iptables规则,确保整个Cluster集群都能通过Service的Cluster IP访问Service。

 

6.3 DNS访问Service

在Cluster中,除了可以通过Cluster IP访问Service,Kubernetes还提供了更为方便的DNS访问。

kubeadm部署时默认安装kube-dns组件。

kube-dns是一个DNS服务器,每当有新的Service被创建,kube-dns会添加该Service的DNS记录。Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>访问Service。比如可以用httpd-svc.default访问Service httpd-svc

用nslookup可以查看service的DNS信息

6.4 外网如何访问Service

除了Cluster内部可以访问Service,很多情况下也有需要应用的Service能够暴露给Cluster外部。Kubernetes提供了多种类型的Service,默认是ClusterIP。

(1)ClusterIP

Service通过Cluster内部的IP对外提供服务,只有Cluster内的节点和Pod可以访问。

(2)NodePort

Service通过Cluster节点的静态端口对外提供服务。Cluster外部可通过<NodeIP>.<NodePort>访问Service。

(3)LoadBalancer

Service利用cloud provider特有的load balancer对外提供服务。

 

第七章:Rolling Update

7.1 实践

7.2 回滚

kubectl apply每次更新应用时,k8s都会记录下当前的配置,保存为一个revision(版次),方便回滚到某个特定revision。

kubectl apply -f httpd.v1.yml --record

--record可以将当前命令记录到revision记录中,可以方便了解每个revision对应的配置文件,kubectl rollout history deployment httpd可以查看revision

 

第8章:Health Check

强大的自愈能力是K8s这类容器编排引擎的一个重要特性。自愈的默认实现方式是自动重启发生故障的容器。此外,用户可以利用Liveness和Readiness探测机制设置更精细的健康检查,进而实现如下需求:

(1)零停机部署。

(2)避免部署无效的镜像。

(3)更加安全的滚动升级。

 

8.1 默认的健康检查

每个容器启动时都会执行一个进程,此进程由Dockerfile的CMD或ENTRYPOINT指定。如果进程退出时返回码非零,则认为容器发生故障,K8s根据restartPolicy重启容器。

8.2 Liveness探测

Liveness探测让用户可以自定义判断容器是否健康的条件。如果探测失败,K8s就会重启容器。

livenessProbe部分定义如果执行Liveness探测:

(1)探测的方法是:通过cat命令检查/tmp/healthy文件是否存在。如果命令执行成功,返回值为零,K8s认为本次Liveness探测成功;如果命令返回值非零,本次Liveness探测失败。

(2)initialDelaySeconds:10 指定容器启动10s之后开始执行Liveness探测

(3)periodSeconds:5 指定每5s执行一次Liveness探测。K8s如果连续执行3次Liveness探测均失败,就会杀掉并重启容器。

8.3 Readiness探测

Liveness探测可以告诉K8s什么时候通过重启容器实现自愈;Readiness探测则是告诉K8s什么时候可以将容器加入到Service负载均衡池中,对外提供服务。

将liveness改为readiness,配置内容不变:

(1)刚被创建时,READY状态为不可用;

(2)15s后(initialDelaySeconds+periodSeconds),第一次进行Readiness探测并成功返回,设置READY为可用;

(3)30s后,/tmp/heathy被删除,连续3次Readiness探测均失败后,READY被设置为不可用。

Liveness和Readiness探测比较:

(1)Liveness探测和Readiness探测是两种Health Check机制,如果不特意配置,K8s对两种探测采用相同的默认行为,通过判断容器启动进程的返回值是否为零来判断探测是否成功。

(2)两种探测的配置方法一样,支持的配置参数也相同。不同之处在于探测失败后的行为:Liveness探测是重启容器,Readiness探测则是将容器设置为不可用,不接收Service转发的请求。

(3)Liveness探测和Readiness探测是独立执行的,可以单独使用。用Liveness探测判断容器是否需要重启以实现自愈,用Readiness探测判断容器是否已经准备好对外提供服务。

8.4 Health Check在Scale Up中的应用

对于多副本应用,当执行Scale Up时,新副本会作为backend被添加到Service的负载均衡中,与已有副本一起处理请求。

除了执行exec命令,探测部分也支持httpGet探测方法,如果http请求的返回码在200~400之间则探测成功。

 

8.5 Health Check在滚动更新中的应用

滚动更新通过参数来控制副本替换的数量。

  1. maxSurge:控制滚动更新过程中副本总数超过DESIRED的上限。maxSurge可以是具体的整数(比如3),也可以是百分比,向上取整,默认值为25%。

如果DESIRED为10,那么副本总数最大值为roundUp(10+10*25%)=13。

  1. maxUnavailable:控制滚动更新过程中,不可用的副本占DESIRED的最大比例。maxUnavailable可以是具体的整数(比如3),也可以是百分比,向下取整,默认值是25%。

如果DESIRED为10,那么可用的副本数至少要为10-roundDown(10*25%)=8

maxSurge值越大,初始创建的新副本数量就越多;maxUnavailable值越大,初始销毁的旧副本数量就越多。

理想情况下案例滚动更新的过程:

(1)创建3个新副本使副本总数达到13个。

(2)销毁2个旧副本使可用的副本数降到8个。

(3)当2个旧副本成功销毁后,再创建2个新副本,使副本总数保持为13个。

(4)当新副本通过Readiness探测后,会使可用副本数增加,超过8。

(5)进而可以继续销毁更多的旧副本,使可用副本数回到8。

(6)旧副本的销毁使副本总数低于13,这样就允许创建更多的新副本。

(7)这个过程会持续进行,最终所有的旧副本都会被新副本替换,滚动更新完成。

 

第9章:数据管理

主要介绍Kubernetes如何管理存储资源。

 

9.1 Volume

介绍K8s的存储模型Volume,学习如何将各种持久化存储映射到容器。

容器和Pod是短暂的,它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。为了持久化保存容器的数据,可以使用K8s Volume。

Volume的生命周期独立于容器,当Volume被mount到Pod,Pod中的所有容器都可以访问这个Volume。K8s Volume支持多种backend类型,包括emptyDir、hostPath、GCE Persistent Disk、NFS等。Volume提供了对各种backend的抽象,容器在使用Volume读写数据时不需要关心数据到底存在本地节点的文件系统还是云硬盘。对它来说,所有类型的Volume都只有一个目录。

9.1.1 emptyDir

emptyDir是最基础的Volume类型。一个emptyDir Volume是Host上的一个空目录。emptyDir Volume对于容器来说是持久的,对于Pod则不是。当Pod从节点删除时,Volume的内容也会被删除。但如果只是容器被销毁而Pod还在,则Volume不受影响。

结论:emptyDir Volume的生命周期与Pod一致。

emptyDir是Host上创建的临时目录,其优点是能够方便地为Pod中的容器提供共享存储,不需要额外的配置,它不具备持久性,如果Pod不存在了,emptyDir也就没有了。emptyDir特别适合Pod中的容器需要临时共享存储空间的场景。

 

9.1.2 hostPath

hostPath Volume的作用是将Docker Host文件系统中已经存在的目录mount给Pod容器。

 

9.1.3 外部Storage Provider

如果K8s部署在AWS、Azure等公共云上,可以直接使用云硬盘作为Volume。

 

9.2 PersistentVolume和PersistentVolumeClaim

Volume提供了非常好的数据持久化方案,在可管理性上不足。以AWS EBS为例,要使用Volume,Pod必须事先知道如下信息:

(1)当前Volume来自AWS EBS。

(2)EBS Volume已经提前创建,并且知道确切的volume-id。

Pod通常是由应用开发人员维护,而Volume通常由存储系统的管理员维护,存在职责的耦合。K8s给出的解决方案是PersistentVolume和PersistentVolumeClaim。

PersistentVolume(PV)是外部存储系统中的一块存储空间,由管理员创建和维护,PV具有持久性,生命周期独立于Pod。

PersistentVolumeClaim(PVC)是对PV的申请(Claim)。PVC通常由普通用户创建和维护。需要为Pod分配存储资源时,用户可以创建一个PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,K8s会查找并提供满足条件的PV。

有了PersistentVolumeClaim,用户只需要告诉K8s需要什么样的存储资源,而不必关系真正的空间从哪里分配、如何访问等底层细节信息。这些Storage Provider的底层信息交给管理员来处理,只有管理员才应该关心创建PersistentVolume的细节信息。

以NFS来介绍PersistentVolume的使用方法。

 

9.2.1 NFS PersistentVolume

1、k8s-master节点搭建NFS服务器,目录为/nfsdata。

2、创建PV——mypv1,配置文件nfs-pv1.yml

(1)capacity指定PV的容量为1GB。

(2)accessModes指定访问模式为ReadWriteOnce(此外还有ReadOnlyMany、ReadWriteMany)

ReadWriteOnce:PV能以read-write模式mount到单个节点;

ReadOnlyMany:PV能以read-only模式mount到多个节点;

ReadWriteMany:PV能以read-write模式mount到多个节点。

(3)persistentVolumeReclaimPolicy:PV的回收策略为Recycle(此外还有Retain、Delete)

Retain:需要管理员手工回收;

Recycle:清除PV中的数据;

Delete:删除Storage Provider上的对应存储资源。

(4)storageClassName指定PV的class为nfs,相当于为PV设置了一个分类,PVC可以指定class申请相应class的PV。

(5)指定PV在NFS服务器上对应的目录。

 

9.2.2 回收PV

当不需要使用PV时,可用删除PVC回收PV。

 

9.2.3 PV动态供给

在前面的例子中,我们提前创建PV,然后通过PVC申请PV并在Pod中使用,这种方式叫做静态供给(Static Provision)。

与之对应的是动态供给(Dynamical Provision),即如果没有满足PVC条件的PV,会动态创建PV。

 

动态供给是通过StorageClass实现的,StorageClass定义了如何创建PV。

 

9.3 一个数据库例子

演示如何为MySQL数据库提供持久化存储,步骤:

(1)创建PV和PVC;

(2)部署MySQL;

(3)向MySQL添加数据;

(4)模拟节点宕机故障,K8s将MySQL自动迁移到其他节点;

(5)验证数据一致性。

 

第10章:Secret & Configmap

应用启动过程中可能需要一些敏感信息,比如数据库密码。K8s提供Secret方案来加密存储这些信息。Secret会以Volume的形式被mount到Pod,容器可通过文件或者环境变量的方式使用这些数据。

10.1 创建Secret

有四种方法创建Secret:

(1)通过--from-literal:每个--from-literal对应一个信息条目。

(2)通过--from-file:每个文件内容对应一个信息条目。

(3)通过--from-env-file:文件env.txt中每行Key=Value对应一个信息条目。

(4)通过YAML配置文件

 

10.2 查看Secret

kubectl get secret

10.3 在Pod中使用Secret

Pod可以通过Volume或者环境变量的方式使用Secret。

10.3.1 Volume方式

通过Volume使用Secret,容器必须从文件读取数据,稍显麻烦,Kubernetes还支持通过环境变量使用Secret。

以Volume方式使用的Secret支持动态更新;Secret更新后,容器中的数据也会更新。

10.3.2 环境变量方式

 

需要注意的是,环境变量读取Secret很方便,但无法支撑Secret动态更新。

10.4 ConfigMap

Secret可以为Pod提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,可以用ConfigMap。

ConfigMap的创建和使用方式和Secret类似,主要的不同是数据以明文形式存放。

(1)通过--from-literal;

(2)通过--from-file;

(3)通过--from-env-file;

(4)通过YAML配置文件;

第11章:Helm——Kubernetes的包管理器

11.1 Why Helm

Kubernetes能够很好地组织和编排容器,但缺少更高层次的应用打包工具,Helm可以完成这件事。

11.2 Helm架构

Helm重要概念:chart和release。

chart:chart是创建一个应用的信息集合,包括各种K8s对象的配置模板、参数定义、依赖关系、文档说明等。chart是应用部署的自包含逻辑单元,可以将chart想象成apt、yum中的软件安装包。

release:是chart的运行实例,代表了一个正在运行的饮用。当chart被安装到K8s集群,就生成一个release。chart能够多次安装到同一个集群,每次安装都是一个release。

 

Helm是包管理工具,这里的包就是指的chart。Helm能够:

(1)从零创建新chart。

(2)与存储chart的仓库交互,拉取、保存和更新chart。

(3)在K8s集群中安装和卸载release。

(4)更新、回滚和测试release。

11.3 安装Helm

helm init

11.4 使用Helm

Helm安装时默认配置两个仓库:stable和local。stable是官方仓库,local是用户存放自己开发的chart的本地仓库。

11.5 chart详解

11.5.1 chart目录结构

以MySQL chart为例,MySQL chart目录结构如下:

目录名就是chart的名字(不带版本信息),这里是mysql。

(1)Chart.yaml

描述chart的概要信息,name和version是必填项。

(2)README.md

使用文档,文件可选。

(3)LICENSE

描述chart的许可信息,文件可选。

(4)requirements.yaml

chart可能依赖的其他chart。

安装过程中,依赖的chart也会被一起安装。

(5)values.yaml

chart支持在安装时根据参数进行定制化配置,values.yaml提供配置参数的默认值。

(6)templates目录

各类K8s资源的配置模板,Helm将values.yaml中的参数值注入到模板中,生成标准的yaml配置文件。

模板是chart最重要的部分,模板增加了应用部署的灵活性。

(7)templates/NOTES.txt

chart的简易使用文档,chart安装成功后会显示此文档内容。

 

11.5.2 chart模板

Helm采用了Go语言的模板来编写chart。

 

调试chart:

helm lint xxx 参数检查

helm install --dry-run --debug 模拟安装chart,输出每个模板生成的YAML文件

 

第12章:网络

K8s作为编排引擎管理着分布在不同节点上的容器和Pod。Pod、Service、外部组件之间需要一种可靠的方式找到彼此并进行通信,K8s网络则负责提供这个保障。

12.1 Kubernetes网络模型

K8s采用的是基于扁平地址空间的网络模型,集群中的每个Pod都有自己的IP地址,Pod之间不需要配置NAT就能直接通信。另外,同一个Pod中的容器共享Pod的IP,能够通过localhost通信。

1、Pod内容器之间的通信

当Pod被调度到某个节点,Pod中的所有容器都在这个节点上运行,这些容器共享相同的本地文件系统、IPC和网络命名空间。

2、Pod之间的通信

Pod的IP是集群可见的,即集群中的任何其他Pod和节点都可以通过IP直接与Pod通信,这种通信不需要借助任务网络地址转换、隧道或代理技术。Pod内部和外部使用的是同一个IP,这也意味着标准的服务命名和发现机制,比如DNS可以直接使用。

3、Pod与Service的通信

Pod间可以直接通过IP地址通信,Service提供了访问Pod的抽象层。无论后端的Pod如何变化,Service都作为稳定的前端对外提供服务。

4、外部访问

无论是Pod的IP还是Service的Cluster IP,它们只能在K8s集群中可见,对集群外的世界,这些IP是私有的。K8s提供两种方式让外界能够与Pod通信:

NodePort:Service通过Cluster节点的静态端口对外提供服务。外部可以通过<NodeIP>:<NodePort>访问Service。

LoadBalancer:Service利用cloud provider提供的load balancer对外提供服务。

 

12.2 各种网络方案

为了保证网络方案的标准化、扩展性和灵活性,K8s采用Container Networking Interface(CNI)规范。

CNI是由CoreOS提出的容器网络规范,使用了插件(Plugin)模型创建容器的网络栈,CNI的优点是支持多种容器runtime,支持不同组织和公司开发的第三方插件。

 

12.3 Network Policy

Network Policy是K8s的一种资源。Network Policy通过Label选择Pod,并指定其他Pod或外界如何与这些Pod通信。

默认情况下,所有Pod是非隔离的,即任何来源的网络流量都能够访问Pod,没有任何限制。当为Pod定义了Network Policy时,只有Policy允许的流量才能访问Pod。

不过,不是所有的K8s网络方案都支持Network Policy。以Canal为例,Canal用Flannel实现K8s集群网络,用Calico实现Network Policy。

 

12.3.1 部署Canal

部署Canal与部署其他K8s网络方案非常类似,都是在执行了kubeadm init初始化K8s集群之后通过kubectl apply安装相应的网络方案,没有太好的办法直接切换使用不同的网络方案,基本上只能重新创建集群。

要销毁当前集群,最简单的方法是在每个节点上执行kubeadm reset,然后初始化Master。

kubeadm init

Canal作为DaemonSet部署到每个节点,属于kube-system这个namespace。

 

12.3.2 实践Network Policy

 

第13章:Kubernetes Dashboard

除了kubectl外,K8s开发了基于Web的Dashboard,用户可以用K8s Dashboard部署容器化的应用、监控应用的状态、执行故障排查任务以及管理K8s的各种资源。

在K8s Dashboard中可以查看集群中应用的运行状态,也能够创建和修改各种K8s资源。

 

13.1 安装

因为Service是ClusterIP类型

13.2 配置登录权限

13.3 Dashboard界面结构

13.4 典型使用场景

 

第14章:Kubernetes集群监控

14.1 Weave Scope

Weave Scope是Docker和K8s可视化监控工具。Scope提供了自上而下的集群基础设施和应用的完整视图,用户可以轻松对分布式的容器化应用进行实时监控和问题诊断。

Scope部署成功后,包括如下组件:

(1)DaemonSet weave-scope-agent,集群每个节点上都会运行的scope agent程序,负责收集数据;

(2)Deployment weave-scope-app,score是应用,从agent获取数据,通过Web UI展示并与客户交互;

(3)Service weave-scope-app,默认是ClusterIP类型。

14.2 Heapster

Heapster是K8s原生的集群监控方案。Heapster以Pod的形式运行,它会自动发现集群节点,从节点上的kubelet获取监控数据。kubelet则是从节点上的cAdvisor收集数据。

 

14.3 Prometheus Opertator

前面的两种监控方案:Weave Scope和Heapster,主要的监控对象是Node和Pod;除此之外,我们通过还希望监控集群本身的运行状态,比如K8s的API Server、Scheduler、Controller Manager等管理组件是否正常工作以及负荷是否过大等。

Prometheus Operator可以帮助我们实现。Prometheus Operator是CoreOS开发的基于Prometheus的K8s监控方案。

 

14.3.1 Prometheus架构

Prometheus提供了数据搜集、存储、处理、可视化和告警一套完整的解决方案。

1、Prometheus Server

Prometheus Server负责从Exporter拉取和存储监控数据,并提供一套灵活的查询语言(PromQL)供用户使用。

2、Exporter

Exporter负责收集目标对象(host、container等)的性能数据,并通过HTTP接口供Prometheus Server获取。

3、可视化组件

Grafana。

4、Alertmanager

用户可以定义基于监控数据的告警规则,规则会触发告警。

 

14.3.2 Prometheus Operator架构

1、Operator,在K8s中以Deployment运行,职责为部署和管理Prometheus Server,根据ServiceMonitor动态更新Prometheus Server的监控对象。

2、Prometheus Server,作为K8s应用部署到集群中。CoreOS开发了命名为Prometheus的K8s定制化资源。可以把Prometheus看作一种特殊的Deployment。

3、Service。这里的Service是Cluster中的Service资源,也是Prometheus要监控的对象,在Prometheus中叫作Target。每个监控对象都有一个对应的Service,比如要监控K8s Scheduler,就得有一个与Scheduler对应的Service。当然,Kubernetes集群默认没有这个Service,Prometheus Operator负责创建。

4、ServiceMonitor。Operator能够动态更新Prometheus的Target列表,ServiceMonitor就是Target的抽象,比如监控Kubernetes Scheduler,用户可以创建一个与Scheduler Service相映射的ServiceMonitor对象。Operator则会发现这个新的ServiceMonitor,并将Scheduler的Target添加到Prometheus的监控列表中。

5、AlertManager

Prometheus、ServiceMonitor、Alertmanager是三种K8s定制化资源。

 

14.3.3 部署Prometheus Operator

 

第15章:Kubernetes集群日志管理

K8s开发了一个Elasticsearch附加组件来实现集群的日志管理。这是Elasticsearch、Fluentd和Kibana的组合。Elasticsearch是一个搜索引擎,负责存储日志并提供查询接口;Fluentd负责从K8s搜集日志并发送给Elasticsearch;Kibana提供了一个Web GUI,用户可以浏览和搜索存储在Elasticsearch中的日志。

posted @ 2022-07-08 20:52  stay_heart  阅读(235)  评论(0)    收藏  举报