欢迎访问我的博客,你的支持,是我最大的动力!

kubernetes权威指南笔记(一)

Docker 小马奔腾 165℃ 评论
目录:
[显示]

kubernetes入门

Pod有两种类型:普通pod和静态pod (static pod)
静态pod没有存储到etcd中,而是被存放在具体node的一个文件夹下,具只在此node上启动运行

selector中同时设置了matchLabels和matchExpressions,则两者之间是AND关系,必须都满足

kubectl get deployments xxx
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
UP-TO-DATE:最新版本的Pod的副本数量,用于指示在滚动升级过程中,有多少个Pod副本已经成功升级

HPA
cpu指标是所有pod的算数平均值,其中每个pod的计算方法为:cpu当前用量/request的量

快速创建命令
kubectl autoscale deployment php-apache --cpu-percent=90 --min=1 --max=10

service多端口问题
当一个service有多个端口时,即拥有多个ep,要求每个ep都必须定义一个名称来区分,如

kubernetes安装配置指南

kubeadm会将配置文件以configmap的方式存保存到kube-system命令空间
kubectl get configmaps -n kube-system kubeadm-config -o yaml
部署时,一般是先导出默认配置文件,然后修改为适合使用的
kubeadm config print init-defaults > init.defaults.yaml # 输出kubeadm init默认参数文件
kubeadm config print join-defaults > join.defaults.yaml # 输出kubeadm join默认参数文件
kubeadm init --config=init.defaults.yaml
kubeadm join --config=join.defaults.yaml
# 默认使用kubeadm部署的集群没有网络插件,需要单独部署

hyperkube 包含了所有服务的程序,可以启动任一服务

获取多种对象的信息
kubectl get pod/mypod deploy/mypod

kubectl使用命令行插件
kubectl <plugin-name>
插件的可执行文件名需要有前缀 kubectl- 且放于$PATH目录中

深入掌握pod

Pod编排文件
spec.hostNetwork bool 是否使用主机网络模式,值为true时,使用宿主机网络,不再使用docker网桥,一台宿主机只能启动pod的一个副本

静态Pod
由kubelet管理的仅存在于特定node上的pod,不能通过apiserver进行管理,且kubelet无法对它们进行健康检查
静态pod不能使用configmap
若执行kubectl delete pod xxxx 将会使pod进入pending状态且不能被删除
两种创建方式:
- 配置文件方式
需设置kubelet启动参数中有 --config 用于指定需要监控的目录,kubelet会定期扫描该目录,并根据目录下的.yaml或.json文件执行创建动作
- HTTP方式
设置kubelet启动参数中设置 --manifest-url 会定期从该url地址下载pod定义文件,并以.yaml或.json文件格式进行解析,然后创建pod

查看已停止的pod
kubectl get pods --show-all #这会显示如completed状态的pod

使用configmap的限制条件
- 必须在pod前创建
- 受namespace限制
- configmap中配额管理未实现
- 静态pod不能使用configmap
- 在pod对configmap进行volume挂载操作时,只能挂载为目录,无法挂载为文件。目录下会包含configmap的项目,若目录下原来还有文件,将会被覆盖 (解决方法,添加subPath参数)

initalDelaySeconds,启动容器后进行首次健康检查的等待时间
timeoutSeconds,健康检查发送请求后等待响应的超时时间

Readiness探测机制的扩展
kubectl explain pod.spec.readinessGates
1.14版达到GA稳定,Pod Readiness Gates
用户可以将自定义的ReadinessProbe探测方式设置在pod上,辅助k8s设置pod何时达到可用状态(Ready)
需部署一个外部控制器Controller设置相应的Condition状态,k8s会在判断全部readinessGates条件都为True时,才设置Pod服务可用壮态为Ready

删除deploy时,不删除对应的pod
kubectl delete deploy my-deploy --cascade=false

NodeAffinity
如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个匹配成功即可
如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该pod

pod亲和性调度
如果在具有标签X的node上运行一个或多个符合条件Y的pod,那么pod应该/拒绝运行在这个node上
其中X是一个集群中的节点、机架、区域等概念,通过内置标签中的key来进行声明,即topologyKey(注意,不是value)

pod亲和性调度对topologyKey的限制
- 在Pod亲和性和RequiredDuringScheduling的pod互斥性定义中,不允许使用空的topologyKey
- 若Admission controller包含LimitPodHardAntiAffinityTopology,那么针对Required DuringScheduling的pod互斥会被限制为kubernetes.io/hostname,此时不能使用自定义的topologyKey
- 在PreferredDuringScheduling类型的Pod互斥性定义中,空的topologyKey会被解释为kubernetes.io/hostname failure-domain.beta.kubernetes.io/zone 及 failure-domain.beta.kubernetes.io/region的组合
- 若不是上述情况,就可采用任意合法的topologyKey
- 还可指定namespace列表进行限制,使用Label Selector对namespace进行选择(namespacep定义与topologyKey同级),省略namespace表示同定义文件所在ns相同;为空表示所有namespace
- 在所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全满足后,pod才能被调度

# 为node添加污点
kubectl taint nodes xxxx key=value:NoSchedule
## taint的键为key,值为value,效果为NoSchedule

pod的toleration
key和effect需要与taint的设置保持一致,并满足如下条件之一
- operator的值为Exists(无需指定value)
- operator的值为Equal且value相等
若不指定operator,默认为Equal
特例
- 空的key配合Exists能够匹配所有键和值
- 空的effect匹配所有的effect

PreferNoSchedule 软限制调度
NoExecute 驱逐 tolerationSeconds 允许在该node上保留的时长

pod驱逐行为
NoExecute这个taint效果可用于pod驱逐
- 没有配置toleration的pod会被立刻驱逐
- 配置了对应toleration,但没有tolerationSeconds赋值,会一直留在节点上
- 配置了对应toleration,且定义了tolerationSeconds,在指定时间后驱逐
- 若节点发生故障,会自动标记taint(只针对node unreachable和node not ready)。该功能依赖TaintBasedEvictions=controller

daemonset
可以在pod定义中使用nodeSeceltor或nodeAffinity指定满足条件的node范围进行调度
daemonset的默认更新策略为RollingUpdate 可选OnDelete
spec.updateStrategy.type=RollingUpdate

--watch
kubectl get pods --watch

使用自定义调度器
若提供自定义调度器,则会由该自定义调度器调度,忽略默认调度器;若自定义调度器不可用,pod将一直处理pending状态

自定义调度器示例
使用bash实现,调度策略为随机选择一个node (该调度器需通过kubectl proxy运行)

init container容器
若多个init容器都定义了资源请求/限制,则取最大值作为所有init容器的资源请求/限制
pod的有效资源请求/限制取以下二者中较大值
- 所有应用容器资源请求/限制值之和
- init容器有效资源请求/限制值
在pod重启时,init容器会重新运行
pod重启的几种场景
- init容器镜像被更新时,init容器会重新运行,导致pod重启;仅更新应用容器镜像只会使应用容器被重启
- pod的infrastructure容器更新时,pod会重启
- 若pod中所有应用容器都终止,且RestartPolicy=Always,则pod会重启

更新镜像版本
kubectl set image deployment/nginx-deploy nginx=nginx:1.9.1
# 其中nginx= 这个是容器的名称

查看更新状态
kubectl rollout status deployment/nginx-deploy

滚动更新
需要注意多重更新的情况 Rollover
上一次更新还在进行的时候,用户又发起新的更新,即多重更新
需要注意的是,多重更新时,不会等上一次更新安成才进行新的更新,而是直接进行最新版本的更新

关于更新deploy标签选择器
新增或更新标签,原来的rs和pod将会脱离deploy的管控,也不会被删除
删除标签选择器,即删除一个或多个标签,不会有什么影响,被删除的标签仍会存在于现有pod和rs中

deploy回滚
kubectl rollout status deployments nginx
# 查看历史版本 (--record)
kubectl rollout history deployment/nginx
# 查看某个版本的配置详情
kubectl rollout history deployment/nginx --revision=3
# 撤销本次发布 回滚到上个部署版本
kubectl rollout undo deployment/nginx
# 回滚到指定版本
kubectl rollout undo deployment/nginx --ro-revision=2
# 暂停deploy部署操作
kubectl rollout pause deployment/nginx
-- 此时对配置的多次更新均不会触发部署
# 恢复
kubectl rollout resume deploy nginx

设置资源限制
kubectl set resources deployments nginx -c=nginx --limits=cpu=200m,memory=512Mi

其他管理对像的更新策略
DaemonSet
- OnDelete ,需手动删除旧pod才会触发更新
- RollingUpdate
StatefulSet
- RollingUpdate
- Paritioned
- OnDelete

deploy的扩缩容
kubectl scale deployment nginx --replicas 5

hpa自动扩缩容
hpa探测周期由kube-controller-manager启动参数 --horizontal-pod-autoscaler-sync-period 定义,默认15s
指标类型
- Resource,基于资源的指标值,如cpu/mem
- Pods,基于pod的指标,对全部pod进行平均值计算
- Object,基于某种资源对象,如ingress或应用系统的任意自定义指标
API版本
- autoscaling/v1 ,仅支持cpu使用率
- autoscaling/v2beta2 ,支持所有指标

k8s推荐尽量使用type为Object的HPA配置方式,这可以通过使用Operator模式,将外部指标通过CRD定义为API资源对象来实现

通过k8s的Metrics Aggregation 层将自定义指标API注册到API Server中,以 /api/custom.metrics.k8s.io 路径提供指标数据
prometheus-operator

书上有一个使用prometheus作为自定义hpa的完整示例
参考:基于自定义指标的HPA实践 page 249-263

# 裸查询
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests?selector=app%3Dsample-app"

# 查看hpa状态
kubectl describe -n dev hpa.v2beta2.autoscaling sample-app
kubeprod describe -n dev horizontalpodautoscalers.autoscaling sample-app

Headless Service
spec.clusterIP: None

深入掌握 Service

多端口时,每个端口需要命名

外部服务service
没有 Label Selector 的svc,再手动创建一个同名的endpoint,用于指向实际后端服务

Headless Service
不设置 ClusterIP 即 clusterIP: None
对其进行访问会获得全部pod列表,然后由客户端自行决定如何处理这个ip列表
如 statefulset 就使用到了headless service
示例:搭建 cassandra集群 page285

从集群外部访问pod/svc
- 容器级别的 hostPort
- pod级别的 spec.hostNetwork=true
- svc级别的 设置nodePort 同时设置type类型为 NodePort
- svc级别的 LoadBalancer模式 loadBalancerIP 同时设置type类型为 LoadBalancer

coredns服务
前置条件
- kubelet启动参数添加 --cluster=<dns-svc-clusterip> --cluster-domain=cluster.local
- 创建coredns应用,需要configmap/deployment/service三种资源
- 若启用了brac,还需要设置 ServiceAccount/ClusterRole/ClusterRoleBinding
ConfigMap主要设置CoreDNS的配置文件 Corefile ,可定义各种域名解析方式和使用的插件

CoreDNS配置说明
CoreDNS主要功能是通过插件系统实现的,将DNS逻辑抽象成一个个插件,能灵活组合
插件会以从上到下的顺序依次执行
常用插件
loadbalance,提供基于dns的负载均衡功能
loop,检测dns解析中出现的简单循环问题
cache,提供前端缓存功能
health,对endpoint进行健康检查
kubernetes,从集群中读取zone数据
etcd,从etcd中读取zone数据,可用于自定义域名记录
file,从RFC1035格式文件中读取zone数据
hosts,从/etc/hosts文件或者其他文件读取zone数据,可用于自定义域名记录
auto,从磁盘中自动加载区域文件
reload,定时自动重新加载corefile配置文件
forward,转发域名查询到上游dns服务器
proxy,转发特定的域名查询到多个其他dns服务器,同时提供到多个dns服务器的负载均衡功能
prometheus,为prometheus提供采集性能指标数据的url
pprof,在url路径/debug/pprof下提供运行时的性能数据
log,对dns查询进行日志记录
errors,对错误信息进行日志记录

Pod级别的dns配置
spec.dnsPolicy: Default
- Default 继承Pod所有宿主机的dns设置
- ClusterFirst 优先使用集群的dns服务,并将无法解析的域名转发到宿主机继承的dns服务器
- ClusterFirstWithHostNet 与ClusterFirst相同,对以hostNetwork模式运行的pod,应明确指定使用该策略
- None 忽略k8s环境的dns配置,通过spec.dnsConfig自定义DNS配置
-- nameservers dns服务器列表,最多可设置3个
-- searches 用于域名搜索的dns域名后缀,最多可设置6个
-- options 可选的dns参数

ingress原理
ingress会将请求直接转发到后端 endpoint 上,ingress需要一个默认后端 (kube-system/default-http-backend一种方式)
基本逻辑
1、监听API Server,获取全部Ingress定义 (api server的 /ingress端口)
2、基于ingress定义,生成配置文件 /etc/nginx/nginx.conf
3、执行 nginx -s reload 命令,重新加载配置文件

kubectl geet ingress -o wide
可通过 ADDRESS 列看是否有pod的ip而判断该ingress规则是否生效

curl带域名访问方法
#注:部分curl不支持该参数 --resolve <host:port:address>
curl --resolve mywebsite.com:80:192.168.18.3 http://mywebsite.com/demo/
curl -H 'Host:mywebsite.com' http://192.168.18.3/demo/

无域名ingress转发
<ingress-controller-ip>/demo
默认会强制启用HTTPS,http请求会301到https
要阻止此默认形为,添加 annotation: ingress.kubernetes.io/ssl-redirect=false

核心组件运行机制

API Server 原理

API Server本身也是一个Service,名称为kubernetes,它的Cluster IP地址是ClusterIP地址池里的第一个地址
在常见公有云环境中,一个3节点etcd集群在轻负载环境中处理一个请求的时间低于1ms;在重负载环境中可以每秒处理超过3w个请求

etcd有Watch API接口;API Server也提供自己的Watch接口
客户端调用API Server的List接口获取相关资源的全量数据并存放在内存中,然后启用对应资源的Watch协程
在接收到Watch事件后,对内存中的对象进行增删改操作,从而可以实现增量式、高性能、近乎实时的数据同步

Proxy API 接口
直接从node取数据,而不是从etcd (数据可能会和etcd中有短暂不一致)
API Server把收到的请求转发到某个node的kubelet守护进程的REST端口,由该kubelet进程负责响应
/api/v1/proxy/nodes/{节点名称或IP}/pods/ #列出指定节点所有pod信息
/api/v1/proxy/nodes/{节点名称或IP}/stats/ #列出指定节点物理资源统计信息
/api/v1/proxy/nodes/{节点名称或IP}/spec/ #列出指定节点概要信息
/api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*} #访问Pod的某个子接口(不需要端口号)
/api/v1/namespaces/{namespace}/pods/{name}/proxy/{path:*} #访问Pod的某个子接口(不需要端口号)
/api/v1/proxy/namespaces/{namespace}/pods/{name} #访问Pod的首页(不需要端口号)
/api/v1/namespaces/{namespace}/pods/{name}/proxy #访问Pod的首页(不需要端口号)
也有service的接口,和pod的类似

为缓解集群名模块对API Server的访问压力,各功能模块都采用缓存机制缓存数据
定时从API Server获取指定资源对象信息(List-Watch方法)并缓存到内存
然后通过访问缓存数据间接访问API Server

Controller Manager 原理

controller manager 是自动化功能的核心,里面有各种控制器

Node Controller
若controller manager设置了--cluster-cidr参数,则控制器负责为每个Node配置spec.PodCIDR

ResourceQuota Controller
三个层次的资源配额管理
- 容器级别 对cpu和mem进行限制
- Pod级别
- Namespace级别 pod数量、rc数量、svc数量、ResourceQuota数量、secret数量、pv数量
配额管理是通过Admission Control控制
LimitRanger作用于pod和container;ResourceQuota作用于namespace

Endpoints Controller
监测Sevice,若svc被删除,则删除和该svc同名的Endpoints对象
Endpoints对象是由每个node上的kube-proxy使用的

Scheduler 原理

Scheduler 将待调度的pod通过计算找到最佳目标节点,然后绑定到该节点上
包含预选过程(xxx Predicates) 和 优选过程(xxx Priority)
一个调度算法就是一组预选策略和一组优选策略的组合

预选策略
- NoDiskConflict 判断是否有gce、aws存储卷冲突
- PodFitsResources 判断节点cpu/mem资源是否充足
- PodSelectorMatchs 判断spec.nodeSelector是否满足
- PodFitsHost 判断spec.nodeName是否满足
- CheckNodeLabelPresence 判断策略列出的标签是否存在
- CheckServiceAffinity 判断备选节点是否包含策略指定的标签,或包含和备选pod在相同service和namespace下的pod所在节点的标签
- PodFitsPorts 判断端口是否被占用
优选策略
- LeastRequestedPriority 选择资源消耗最小的节点
- CalculateNodeLabelPriority 检查标签
- BalancedResourceAllocation 选择资源使用率最均衡的节点

kubelet 运行机制

kubelet 处理master下发到本节点的任务,管理pod及pod中的容器
启动参数 --register-node true 启用向api server注册自己
--node-status-update-frequency 多长时间报告一次自己状态 默认为10s
--config 指定目录下的配置文件是 static pod;默认为 /etc/kubernetes/manifests/ --file-check-frequency 检查频率,默认20s
--manifest-url --http-check-frequency 默认也是20s
api server会为static pod创建一个Mirror Pod与之匹配,Mirror Pod的状态将真实反映Static Pod的状态;当static pod删除后,与之对应的mirror pod也将删除

cAdvisor
默认,cAdvisor通过所在Node节点4194端口暴露一个简单UI (k8s 1.12版本以前)

kube-proxy 运行机制

Service只是一个概念,而将Service落实的是kube-proxy
kube-proxy 在运行中动态创建与Service相关的iptables规则
IPVS(IP Virtual Server) 稳定的推荐的方式
iptables与ipvs虽都是基于Netfilter实现,但因定位不同,二者有本质区别
iptables是为防火墙设计;ipvs专门用于高性能负载均衡,使用更高效的数据结构(Hash表),允许几乎无限规模扩张

ipvs使用了ipset功能,可动态修改这个集合

 

转载请注明:轻风博客 » kubernetes权威指南笔记(一)

喜欢 (0)or分享 (0)