调度管理
- 1.1 调度框架
- 1.1.1 调度体系
- 1.1.2 资源调度
- 1.2 资源调度
- 1.2.1 节点调度
- 1.2.2 节点亲和
- 1.2.3 Pod亲和
- 1.2.4 Pod反亲和
- 1.2.5 污点&容忍度
- 1.2.6 污点实践
- 1.3 流量调度
- 1.3.1 Ingress基础
- 1.3.2 Ingress实践
- 1.3.3 Ingress进阶
- 1.3.4 Ingress认证
- 1.3.5 Ingress扩展
1.1 调度框架
1.1.1 调度体系
学习目标
这一节,我们从 流程调度、调度细节、小结 三个方面来学习。
流程调度
集群层面-节点调度
kube-scheduler负责将接收到的资源调度到指定的节点中
资源层面 - k8s集群资源的管控
网络层面 - k8s集群资源的访问
认证层面 - k8s集群资源的认证
调度细节
pod周期 - pod创建的完整流程
pod组成 - pod创建到成功,经历了什么
存储层面 - pod数据是如何整合的
创建层面 - 资源使用的数据同步
资源层面
角度 | 解析 |
---|---|
资源配置项 | Kubernetes技术已经对Pod做了相应的资源配额设置,目前主要包括两方面:CPU和内存 |
配额限制 | Kubernetes中,对于每种资源的配额限定都需要两个参数:申请配额(Requests)和最大配额(Limits) |
存活状态 | pod层面主要是根据探针来实现的服务质量的检测:livenessProbe和readinessProbe。 |
对象分组 | 在kubernetes内部,尤其是pod层面,通过 标签和标签选择器 或者 nodeName 等机制实现资源的分组管理。 |
服务质量 | 在Kubernetes内部靠实时的监控各种资源对象的状态值,对比相应的"期望状态值",然后由内部的组件做出自动的资源调整。 |
小结
1.1.2 资源调度
学习目标
这一节,我们从 调度框架、原理解析、小结 三个方面来学习。
调度框架
基本框架
kubernetes在进行资源调度的时候,是遵循一个基本原则的:
预选原则 - 把不合适的剔除,剩余满足条件的。
优选原则 - 满足条件的评优,选择一个最好的。
调度框架
新型的调度框架是在传统调度逻辑的基础上,进行了整合再拆分。基本流程还是一样:队列-预选-评分-绑定,将这个基本流程划分为了三个部分:
任务队列 - 接收所有待分配的任务,任务本身会根据优先级合理调整队列的顺序。
调度循环 - 通过扩展接口的方式整合大量的预选机制和评分机制,同时为了方便扩展,预留了备用接口
绑定循环 - 先后通过预绑定队列(防止突发的高优先级任务出现),然后进行正常的节点任务绑定。
常见的 预选参数和优选参数
无论是传统的调度功能还是新型的调度功能,对于各种功能函数来说,本质上的逻辑变化不大,只不过在实现细节上稍微有些不同。而且为了让调度的能力符合通用的使用,默认情况下,开启了一部分通用的策略,没有开启的策略可以通过配置参数的方式来进行扩展加载。
原理解析
调度梳理
根据上面对调度功能函数的了解,上面的大部分功能函数都是静态的函数,只管调用即可,只有个别的一些函数支持用户自定义的场景。
对于节点预选功能,主要是基于资源的各种限制来进行管控,我们可以通过不同的调度器配置来进行定制。而对于优选策略的配置,是我们比较关注的高阶调度。根据我们的梳理,这些高阶的调度主要包括如下几个方面
调度策略 | 解析 |
---|---|
节点调度 | 为即将执行的任务,选择合理的节点 |
Pod调度 | 为即将执行的任务,分配合理的逻辑关联搭配 |
污点调度 | 在任务调度的时候,设定一些避免措施 |
拓扑调度 | 在任务已确定调度的前提下,合理的分配任务,实现资源的高效利用 |
调度思路
名称 | 解析 |
---|---|
亲和 与 反亲和 | 满足条件后,就分配 或者 远离 指定的节点。 |
硬亲和 与 软亲和 | 不会遵循绝对的条件阈值,而是根据实际情况,做出倾向性策略硬亲和会考量预选和优选策略,而软亲和仅考虑优选策略 |
小结
1.2 资源调度
1.2.1 节点调度
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
简介
关于资源对于节点的调度来说,主要有两种场景:
指定节点 - 根据节点的标签,直接将应用部署到指定的节点
节点亲和 - 根据任务的配置倾向,选择合适的节点来进行资源的配置
指定节点
指定节点
将pod调度到特定的节点上,我们可以根据名称或者标签的方式来实现
指定名称
kubectl explain pod.spec.nodeName
指定标签
kubectl explain pod.spec.nodeSelector
节点亲和
对于节点的调度主要有以下两种场景:
节点亲和
kubectl explain pod.spec.affinity.nodeAffinity
节点软亲和
- preferredDuringSchedulingIgnoredDuringExecution
节点硬亲和
- requiredDuringSchedulingIgnoredDuringExecution
注意:
这些调度策略,仅在调度时候有用,一旦调度成功后,节点状态无法满足调度要求,也不会影响正常运行的pod
简单实践
准备工作
创建工作节点
[root@kubernetes-master1 ~]# mkdir /data/kubernetes/schduler; cd /data/kubernetes/schduler
名称节点调度
定制资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 01_kubernetes_scheduler_nodename.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-nodename
spec:
nodeName: kubernetes-node2
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 01_kubernetes_scheduler_nodename.yaml
pod/superopsmsb-nodename created
查看资源对象效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-nodename -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-nodename 1/1 Running 0 9s 10.244.2.8 kubernetes-node2 <none> <none>
[
移除资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 01_kubernetes_scheduler_nodename.yaml
标签节点调度
定制资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 02_kubernetes_scheduler_selector.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-nodeselector
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
nodeSelector:
node: ssd
配置解析:
将应用调度到包含node标签,并且值为ssd的节点主机上
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 02_kubernetes_scheduler_selector.yaml
pod/superopsmsb-nodeselector created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-nodeselector -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-nodeselector 0/1 Pending 0 7s <none> <none> <none> <none>
查看节点
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get node --show-labels | grep ssd
[root@kubernetes-master1 /data/kubernetes/schduler]#
查看pod
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe pod superopsmsb-nodeselector
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 22s (x2 over 89s) default-scheduler 0/6 nodes are available: 3 node(s) didn't match Pod's node affinity/selector, 3 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
后续操作
为节点添加标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label nodes kubernetes-node2 node=ssd
node/kubernetes-node2 labeled
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get node --show-labels | grep ssd
kubernetes-node2 Ready <none> 18h v1.23.8 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=kubernetes-node2,kubernetes.io/os=linux,node=ssd
查看pod效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-nodeselector -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-nodeselector 1/1 Running 0 2m39s 10.244.2.9 kubernetes-node2 <none> <none>
结果显示
一旦有节点满足需求,pod自然就被调度到指定的node节点上了
收尾动作
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 02_kubernetes_scheduler_selector.yaml
pod "superopsmsb-nodeselector" deleted
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node2 node-
node/kubernetes-node2 unlabeled
小结
1.2.2 节点亲和
学习目标
这一节,我们从 软亲和、硬亲和、小结 三个方面来学习。
软亲和
属性解析
查看pod关于节点亲和相关的属性
kubectl explain pod.spec.affinity.nodeAffinity
- preferredDuringSchedulingIgnoredDuringExecution 软亲和性 能满足最好,不满足也没关系。
preference 优先级
matchExpressions
matchFields
weight 权重值,1-100
对于满足所有调度要求的每个节点,调度程序将通过迭代此字段的元素计算总和
并在节点与对应的节点匹配时将“权重”添加到总和。
注意:
与硬亲和属性不同,这里需要注意的是软亲和属性是一个列表对象,而preference不是一个列表项了。
实践-将pod最好部署到包含env标签值是dev 或者 test的结点上,都没有的话也就随便找一个了
定制资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 03_kubernetes_scheduler_preferred_affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-node-preferred-affinity
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 50
preference:
matchExpressions:
- key: env
operator: In
values:
- test
- weight: 20
preference:
matchExpressions:
- key: env
operator: In
values:
- dev
注意:
软亲和的权重配置是与硬亲和的区别所在。
应用资源定义文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 03_kubernetes_scheduler_preferred_affinity.yaml
pod/superopsmsb-node-preferred-affinity created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-node-preferred-affinity -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-node-preferred-affinity 1/1 Running 0 18s 10.244.3.6 kubernetes-node3 <none> <none>
删除资源
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 03_kubernetes_scheduler_preferred_affinity.yaml
后续操作
准备节点标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node1 env=dev
node/kubernetes-node1 labeled
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node2 env=test
node/kubernetes-node2 labeled
再次运行资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 03_kubernetes_scheduler_preferred_affinity.yaml
pod/superopsmsb-node-preferred-affinity created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-node-preferred-affinity -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-node-preferred-affinity 1/1 Running 0 19s 10.244.2.10 kubernetes-node2 <none> <none>
收尾动作
删除资源
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 03_kubernetes_scheduler_preferred_affinity.yaml
移除标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node1 env-
node/kubernetes-node1 unlabeled
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node2 env-
node/kubernetes-node2 unlabeled
硬亲和
属性解析
查看pod关于节点亲和相关的属性
kubectl explain pod.spec.affinity.nodeAffinity
- requiredDuringSchedulingIgnoredDuringExecution 硬亲和性 必须满足亲和性。
nodeSelectorTerms: 节点选择主题
matchExpressions 匹配表达式,可用大量运算符:
In label 的值在某个列表中
NotIn label 的值不在某个列表中
Gt label 的值大于某个值
Lt label 的值小于某个值
Exists 某个 label 存在
DoesNotExist 某个 label 不存在
matchFields 匹配字段,可以不定义标签值
实践-将pod只部署到包含env标签值是dev 或者 test的节点上
定制资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 04_kubernetes_scheduler_required_affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-node-required-affinity
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: env
operator: In
values:
- dev
- test
应用资源定义文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 04_kubernetes_scheduler_required_affinity.yaml
pod/superopsmsb-node-required-affinity created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-node-required-affinity
NAME READY STATUS RESTARTS AGE
superopsmsb-node-required-affinity 0/1 Pending 0 20s
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe pod superopsmsb-node-required-affinity
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 48s default-scheduler 0/6 nodes are available: 3 node(s) didn't match Pod's node affinity/selector, 3 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
任一结点添加标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node2 env=dev
node/kubernetes-node2 labeled
确认效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-node-required-affinity -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-node-required-affinity 1/1 Running 0 95s 10.244.2.11 kubernetes-node2 <none> <none>
结果显示:
只有节点上存在符合标签后,该资源才会被创建到指定结点
收尾动作
删除资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 04_kubernetes_scheduler_required_affinity.yaml
pod "superopsmsb-node-required-affinity" deleted
清理标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node2 env-
node/kubernetes-node2 unlabeled
小结
1.2.3 Pod亲和
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
场景需求
所谓的pod调度,主要说的是pod彼此之间的亲和性,也就是说,哪些pod应该在一起。
比如:我们的k8s集群的节点分布在不同的区域或者不同的机房
当服务A和服务B需要高效的交流数据的话,要求部署在同一个区域或者同一机房的时候。
当服务A需要做冗余操作,那么多个服务A必须在不同的位置
属性解析
查看pod级别的亲和性属性
kubectl explain pod.spec.affinity.podAffinity
requiredDuringSchedulingIgnoredDuringExecution -- 硬亲和性:
labelSelector 选择跟那组Pod亲和,前提得知道如何判断
namespaces 选择哪个命名空间进行条件匹配
topologyKey 指定节点上的哪个键,这是一个必选项
注意:这三个条件是一个逻辑与的关系
preferredDuringSchedulingIgnoredDuringExecution -- 软亲和性:
podAffinityTerm 与权重关联的亲和选项,这是一个必选项
labelSelector
namespaces 表示仅在指定的命名空间中查找
topologyKey 在指定节点上的标签关键字
weight 权重,这是一个必选项
简单实践
准备工作
准备主机节点标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node1 env=dev
node/kubernetes-node1 labeled
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node2 env=test
node/kubernetes-node2 labeled
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node3 env=release
node/kubernetes-node3 labeled
创建基础资源配置
[root@kubernetes-master1 /data/kubernetes/schduler]# for env in {dev,test,release}
do
cat >> 05_kubernetes_scheduler_pod_base.yaml <<-EOF
---
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-$env
labels:
env: $env
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
nodeSelector:
env: $env
EOF
done
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 05_kubernetes_scheduler_pod_base.yaml
pod/superopsmsb-pod-dev created
pod/superopsmsb-pod-test created
pod/superopsmsb-pod-release created
确认效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -o wide | grep pod
superopsmsb-pod-dev 1/1 Running ... 10.244.1.5 kubernetes-node1 ...
superopsmsb-pod-release 1/1 Running ... 10.244.3.7 kubernetes-node3 ...
superopsmsb-pod-test 1/1 Running ... 10.244.2.12 kubernetes-node2 ...
结果显示:
每个节点上都有1个pod而且标签不一样
硬亲和实践1- pod和只和携带标签env=release的pod部署在一起
创建资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 06_kubernetes_scheduler_pod_require-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-affinity
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: env, operator: In, values: ["release"]}
topologyKey: kubernetes.io/hostname
属性解析:
属性详解:
topologyKey的来源:
]# kubectl get nodes -o yaml | grep kubernetes.io/hostname
kubernetes.io/hostname: kubernetes-master1
kubernetes.io/hostname: kubernetes-master2
kubernetes.io/hostname: kubernetes-master3
kubernetes.io/hostname: kubernetes-node1
kubernetes.io/hostname: kubernetes-node2
kubernetes.io/hostname: kubernetes-node3
其实指定 kubernetes.io/hostname 和 主机名 效果是一样的,只不过一个是自动获取,一个是手工指定
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 06_kubernetes_scheduler_pod_require-affinity.yaml
pod/superopsmsb-pod-affinity created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-affinity -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-pod-affinity 1/1 Running 0 21s 10.244.2.13 kubernetes-node3 <none> <none>
删除资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 06_kubernetes_scheduler_pod_require-affinity.yaml
pod "superopsmsb-pod-affinity" deleted
清理pod对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete pod superopsmsb-pod-release
pod "superopsmsb-pod-release" deleted
再次创建资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 06_kubernetes_scheduler_pod_require-affinity.yaml
pod/superopsmsb-pod-affinity created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-affinity -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-pod-affinity 0/1 Pending 0 7s <none> <none> <none> <none>
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe pod superopsmsb-pod-affinity
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 30s default-scheduler 0/6 nodes are available: 3 node(s) didn't match pod affinity rules, 3 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
删除资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 06_kubernetes_scheduler_pod_require-affinity.yaml
pod "superopsmsb-pod-affinity" deleted
软亲和实践2- pod最好和携带标签env=dev的pod部署在一起
创建资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 07_kubernetes_scheduler_pod_prefer_affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-preferred
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 60
podAffinityTerm:
labelSelector:
matchExpressions:
- {key: env, operator: In, values: ["dev"]}
topologyKey: kubernetes.io/hostname
- weight: 30
podAffinityTerm:
labelSelector:
matchExpressions:
- {key: env, operator: In, values: ["test"]}
topologyKey: kubernetes.io/hostname
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 07_kubernetes_scheduler_pod_prefer_affinity.yaml
pod/superopsmsb-pod-preferred created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-preferred -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-pod-preferred 1/1 Running 0 14s 10.244.1.6 kubernetes-node1 <none> <none>
结果显示:
pod直接去找最好的地方了
清理资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 07_kubernetes_scheduler_pod_prefer_affinity.yaml
小结
1.2.4 Pod反亲和
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
简介
所谓的反亲和,其实就是满足条件的话,就离这个pod远远的,从此不见面。与亲和正好相反
属性解析
查看pod反亲和实践
kubectl explain pod.spec.affinity.podAntiAffinity
requiredDuringSchedulingIgnoredDuringExecution -- 硬亲和性:
labelSelector 选择跟那组Pod亲和,前提得知道如何判断
namespaces 选择哪个命名空间进行条件匹配
topologyKey 指定节点上的哪个键,这是一个必选项
注意:这三个条件是一个逻辑与的关系
preferredDuringSchedulingIgnoredDuringExecution -- 软亲和性:
podAffinityTerm 与权重关联的亲和选项,这是一个必选项
labelSelector
namespaces
topologyKey
weight 权重,这是一个必选项
注意:Pod反亲和性场景,当应用服务A和数据库服务B要求尽量不要在同一台节点上的时候。
简单实践
准备工作
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 05_kubernetes_scheduler_pod_base.yaml
pod/superopsmsb-pod-dev created
pod/superopsmsb-pod-test created
pod/superopsmsb-pod-release created
硬性反亲和实践- pod不和携带标签env=dev的pod部署在一起
创建资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 08_kubernetes_scheduler_pod_required_antiaffinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-required
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: env, operator: In, values: ["dev"]}
topologyKey: kubernetes.io/hostname
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 08_kubernetes_scheduler_pod_required_antiaffinity.yaml
pod/superopsmsb-pod-required created
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-required -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-pod-required 1/1 Running 0 20s 10.244.3.8 kubernetes-node3 <none> <none>
结果显示:
随便找了一个不携带env=dev的pod在一起了
清理环境
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 08_kubernetes_scheduler_pod_required_antiaffinity.yaml
软性反亲和实践-pod最好不和携带标签env=dev的pod部署在一起
创建资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 09_kubernetes_scheduler_pod_preferred_antiaffinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-preferred
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- {key: env, operator: In, values: ["dev"]}
topologyKey: kubernetes.io/hostname
- weight: 50
podAffinityTerm:
labelSelector:
matchExpressions:
- {key: env, operator: In, values: ["test"]}
topologyKey: kubernetes.io/hostname
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 09_kubernetes_scheduler_pod_preferred_antiaffinity.yaml
pod/superopsmsb-pod-preferred created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-preferred -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-pod-preferred 1/1 Running 0 15s 10.244.3.9 kubernetes-node3 <none> <none>
结果显示:
pod去找了一个清净的地方来玩了
收尾实践
清理所有的资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl delete -f 09_kubernetes_scheduler_pod_preferred_antiaffinity.yaml -f 05_kubernetes_scheduler_pod_base.yaml
小结
1.2.5 污点&容忍度
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
需求
我们之前所学的所有调度策略,都是基于pod的属性来选择我们新的pod资源应该如何创建,而实际的生产角度上,往往会出现基于node节点的属性来选择是否让新的pod资源进行创建,但是对于节点来说,没有所谓的节点反亲和性,但是有一种类似的策略:污点和容忍度。
术语解析
术语 | 解析 |
---|---|
污点(taints) | 是定义在node节点上的键值属性数据。主要作用是让节点拒绝pod,尤其是不符合node规则的pod。 |
容忍度(tolerations) | 是定义在Pod上的键值属性数据,用于配置可容忍的污点,调度器将其调度至容忍污点的节点上或无污点的节点 |
应用
Taint(污点)和 Toleration(容忍)是相互配合的,可以用来避免 pod 被分配到不合适的节点上,每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。
比如:A节点是集群中很重要的节点,不要将无关的pod来我这里运行,那么我们就可以在A上面添加一些污点标识。
污点功能
Kubernetes自1.6起支持使用污点自动标识问题节点,它通过节点控制器在特定条件下自动为节点添加污点信息实现。它们都使用NoExecute效用标识,因此非能容忍此类污点的现在Pod对象也会遭到驱逐。目前,内建使用的此类污点有如下几个。
node.kubernetes.io/not-ready:节点进入NotReady状态时被自动添加的污点。
node.alpha.kubernetes.io/unreachable:节点进入NotReachable状态时被自动添加的污点。
node.kubernetes.io/out-of-disk:节点进入OutOfDisk状态时被自动添加的污点。
node.kubernetes.io/memory-pressure:节点内存资源面临压力。
node.kubernetes.io/disk-pressure:节点磁盘资源面临压力。
node.kubernetes.io/network-unavailable:节点网络不可用。
node.cloudprovider.kubernetes.io/uninitialized:kubelet由外部的云环境程序启动时,它自动为节点添加此污点,待到云控制器管理器中的控制器初始化此节点时再将其删除。
不过,Kubernetes的核心组件通常都要容忍此类的污点,以确保其相应的DaemonSet控制器能够无视此类污点于节点上部署相应的关键Pod对象,例如kube-proxy或kube-flannel等。
属性示例
查看污点和污点容忍度
]# kubectl describe pod kube-apiserver-master -n kube-system
...
Tolerations: :NoExecute
]# kubectl describe pod kube-proxy -n kube-system
...
Node-Selectors: kubernetes.io/os=linux
Tolerations: op=Exists 污点容忍度
node.kubernetes.io/disk-pressure:NoSchedule op=Exists
node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/network-unavailable:NoSchedule op=Exists
node.kubernetes.io/not-ready:NoExecute op=Exists
node.kubernetes.io/pid-pressure:NoSchedule op=Exists
node.kubernetes.io/unreachable:NoExecute op=Exists
node.kubernetes.io/unschedulable:NoSchedule op=Exists
]# kubectl get node master -o yaml
...
taints: 污点
- effect: NoSchedule 效用标识,
key: node-role.kubernetes.io/master
...
简单实践
Taints污点-属性解析
Taint是节点上属性,我们看一下Taints如何定义
kubectl explain node.spec.taints(对象列表)
effect pod不能容忍这个污点时,他的行为是什么,
他有三个值:NoSchedule、PreferNoSchedule、NoExecute
key 定义一个key=value:effect
value 定义一个值,这是一个必选项
timeAdded
effect的属性值
属性 | 解析 |
---|---|
NoSchedule | 不能容忍此污点的Pod对象不可调度至当前节点,属于强制型约束关系,但添加污点对节点上现存的Pod对象不产生影响 |
PreferNoSchedule | NoSchedule的柔性约束版本,即调度器尽量确保不会将那些不能容忍此污点的Pod对象调度至当前节点,除非不存在其他任何能够容忍此污点的节点可用;添加该类效用的污点同样对节点上现存的Pod对象不产生影响。 |
NoExecute | 不能容忍此污点的新Pod对象不可调度至当前节点,属于强制型约束关系,而且节点上现存的Pod对象因节点污点变动或Pod容忍度变动而不再满足匹配条件时,Pod对象将会被驱逐。 |
Tolerations 容忍度- 属性解析
Tolerations 是Pod上属性,我们看一下Tolerations如何定义
kubectl explain pod.spec.tolerations
effect 节点调度后的操作
key 被容忍的key
operator Exists只要key在就可以调度,Equal(等值比较)必须是值要相同
tolerationSeconds 资源被驱逐的宽限时间,默认是0 就是立即被驱逐
value 被容忍key的值
容忍度的判断方式
在Pod对象上定义容忍度时,它支持两种操作符,
一种是等值比较,表示容忍度与污点必须在key、value和effect三者之上完全匹配,
一种是存在性判断(Exists),表示二者的key和effect必须完全匹配,而容忍度中的value字段要用空值。
当不指定key值和effect值时,且operator为Exists,表示容忍所有的污点
tolerations:
- operator: "Exists"
当不指定effect值时,则能匹配污点key对应的所有effects情况
tolerations:
- key: "key"
operator: "Exists"
容忍度的匹配原则
一个节点可以配置使用多个污点,而一个Pod对象也可以有多个容忍度,将一个Pod对象的容忍度套用到特定节点的污点之上进行匹配度检测时,时将遵循如下逻辑:
1)首先处理每个有着与之匹配的容忍度的污点;
2)对于不能匹配到容忍度的所有污点,若存在一个污点使用了NoSchedule效用标识,则拒绝调度当前Pod至该节点;
3)对于不能匹配到容忍度的所有污点,若都不具有NoSchedule效用标识,但至少有一个污点使用了PreferNoScheduler效用标准,则调度器会尽量避免将当前Pod对象调度至该节点。
4)如果至少有一个不能匹配容忍度的污点使用了NoExecute效用标识,节点将立即驱逐当前Pod对象,或者不允许该Pod调度至给定的节点;而且,即便容忍度可以匹配到使用了NoExecute效用标识的污点,若在Pod上定义容忍度时同时使用tolerationSeconds属性定义了容忍时限,则在超出时限后当前脚Pod也将会被节点所驱逐。
小结
1.2.6 污点实践
学习目标
这一节,我们从 污点实践、容忍度实践、小结 三个方面来学习。
污点实践
命令格式
查看污点:
kubectl describe nodes | grep -i taint
添加污点:
kubectl taint node <node-name> <key>=<value>:<effect> ...
删除污点:
kubectl taint node <node-name> <key>[:<effect>]-
简单实践
查看污点
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe nodes | egrep 'Hostname|Taints'
Taints: node-role.kubernetes.io/master:NoSchedule
Hostname: kubernetes-master1
Taints: node-role.kubernetes.io/master:NoSchedule
Hostname: kubernetes-master2
Taints: node-role.kubernetes.io/master:NoSchedule
Hostname: kubernetes-master3
Taints: <none>
Hostname: kubernetes-node1
Taints: <none>
Hostname: kubernetes-node2
Taints: <none>
Hostname: kubernetes-node3
添加污点
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl taint node kubernetes-node1 node-type=production:NoSchedule
node/kubernetes-node1 tainted
确认效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe nodes kubernetes-node1 | egrep 'Hostname|Taints'
Taints: node-type=production:NoSchedule
Hostname: kubernetes-node1
给node1增加标签
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl label node kubernetes-node1 env=dev --overwrite
node/kubernetes-node1 not labeled
创建资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 10_kubernetes_scheduler_pod_taint_test.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-taint
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
nodeSelector:
env: dev
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 10_kubernetes_scheduler_pod_taint_test.yaml pod/superopsmsb-pod-taint created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-taint
NAME READY STATUS RESTARTS AGE
superopsmsb-pod-taint 0/1 Pending 0 6s
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe pod superopsmsb-pod-taint
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 52s default-scheduler 0/6 nodes are available: 1 node(s) had taint {node-type: production}, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector, 3 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
结果显示:
由于污点原因,无法将pod创建到指定结点上
删除key为node-type,effect为NoSchedule的污点
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl taint node kubernetes-node1 node-type-
node/kubernetes-node1 untainted
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe nodes kubernetes-node1 | egrep 'Hostname|Taints'
Taints: <none>
Hostname: kubernetes-node1
再次查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-taint
NAME READY STATUS RESTARTS AGE
superopsmsb-pod-taint 1/1 Running 0 2m9s
结果显示:
因为node1上的污点消除后,立刻就有pod正常运行了
简单实践
容忍度实践
为node1定制特殊污点
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl taint node kubernetes-node1 node-type=production:NoSchedule
node/kubernetes-node1 tainted
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe nodes kubernetes-node1 | egrep 'Hostname|Taints'
Taints: node-type=production:NoSchedule
Hostname: kubernetes-node1
创建资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 11_kubernetes_scheduler_pod_tolerations_test.yaml
apiVersion: v1
kind: Pod
metadata:
name: superopsmsb-pod-tolerations
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
nodeSelector:
env: dev
tolerations:
- key: "node-type"
operator: "Equal"
value: "production"
effect: "NoSchedule"
应用资源定义文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 11_kubernetes_scheduler_pod_tolerations_test.yaml
pod/superopsmsb-pod-tolerations created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod superopsmsb-pod-tolerations
NAME READY STATUS RESTARTS AGE
superopsmsb-pod-tolerations 1/1 Running 0 4s
结果显示:
pod的容忍度配置成功了
容忍度驱离方法
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -o wide | grep node1
superopsmsb-pod-tolerations 1/1 Running 0 95s 10.244.1.10 kubernetes-node1 <none> <none>
强制节点驱离pod
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl taint node kubernetes-node1 diskfull=true:NoExecute
node/kubernetes-node1 tainted
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -o wide | grep node1
superopsmsb-pod-tolerations 1/1 Terminating 0 108s 10.244.1.10 kubernetes-node1 <none> <none>
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -o wide | grep node1
No resources found in default namespace.
结果显示:
node1一旦被打上标签,其上的pod就被删除了
注意:
一旦节点被打上diskfull=true:NoExecute,除了集群运行所需要的pod之外,其他都被清理,包括flannel的pod都会被驱离
清理措施
清理污点
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl taint node kubernetes-node1 node-type-
node/kubernetes-node1 untainted
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl taint node kubernetes-node1 diskfull-
node/kubernetes-node1 untainted
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -n kube-flannel -o wide
NAME ... RESTARTS AGE IP NODE ...
kube-flannel-ds-2z4bb ... 0 18s 10.0.0.15 kubernetes-node1 ...
kube-flannel-ds-8f2tz ... 2 (10h ago) 23h 10.0.0.17 kubernetes-node3 ...
kube-flannel-ds-dg9bb ... 2 (10h ago) 23h 10.0.0.14 kubernetes-master3 ...
kube-flannel-ds-h4mkp ... 2 (10h ago) 23h 10.0.0.13 kubernetes-master2 ...
kube-flannel-ds-mctqk ... 2 (10h ago) 23h 10.0.0.16 kubernetes-node2 ...
kube-flannel-ds-pjkl5 ... 1 (10h ago) 23h 10.0.0.12 kubernetes-master1 ...
结果显示:
一旦污点被驱离,flannel的pod立刻就回来了
小结
1.3 流量调度
1.3.1 Ingress基础
学习目标
这一节,我们从 场景需求、方案解读、小结 三个方面来学习。
场景需求
简介
在实际的应用中,kubenetes接受的不仅仅有内部的流量,还有外部流量,我们可以通过两种方式实现将集群外部的流量引入到集群的内部中来,从而实现外部客户的正常访问。
service方式:
nodePort、externalIP 等service对象方式,借助于 namespace、iptables、ipvs 等代理模式实现流量的转发。
Host方式:
通过node节点的 hostNetwork 与 hostPort 及配套的port映射,以间接的方式实现service的效果
k8s网络
在业内有一个不成文的说法,就是:
将集群内部 pod之类对象 之间的网络通信称为 东西向流量;
将集群外部应用 和 集群内部之间对象 之间的网络通信 称为 南北向流量。
南入↓ -- ingress
北出↑ -- egress
问题
1 在实际的应用中,虽然我们可以基于service或host等多种方式实现集群内外的网络通信,但是这些内容都是基于四层协议来进行调度的,而且服务级别的健康检查功能很难实现。
2 而对于外部流量的接入,一般都是http(s)协议的数据,四层协议是无法实现的。尤其是涉及到各种ssl会话的管理,由于其位于osi七层模型的会话层,要高于传输层的四层,service和host是无法正常实现的。
3 虽然service能够实现将外部流量引入到集群内部,但是其本质上,是通过网络规则方式来进行转发的,形象的说法就是在墙上打洞,将集群内部的服务暴露到外部。甚至这些洞和洞之间根本没有关联关系。
方案
为了解决上述的问题,就引入了一种新的解决方法ingress,简单来说,它可以解决上面提出的三个问题:
1 可以基于https的方式,将集群外部的流量统一的引入到集群内部
2 通过一个统一的流量入口,避免将集群内部大量的"洞"暴露给外部。
ingress这种利用应用层协议来进行流量的负载均衡效果,它可以实现让用户通过域名来访问相应的service就可以了,无需关心Node IP及Port是什么,避免了信息的泄露。
ingress 是k8s上的一种标准化资源格式,它为了剥离与特定负载均衡功能实现软件的相关性,而抽象出来的一种公共的统一的声明式配置格式。然后借助于特定的ingress controller功能负责将其加载并转换成k8s集群内部的配置信息。
ingress的特点符合我们之前对于CRD的学习 - ingress + controller,所以,其具备了动态更新并加载新配置的特性。而且ingress本身是不具备实现集群内外流量通信的功能的,这个功能是通过 controller来实现的。
方案解读
实现
Ingress由任何具有反向代理功能的程序实现,如Nginx、Traefik、Envoy、HAProxy、Vulcand等,Ingress本身是运行于集群中的Pod资源对象。
ingress 主要包含两个组件Ingress Controller和Ingress。
组件 | 解析 |
---|---|
Ingress | 将Nginx的配置抽象成一个Ingress对象,每个服务对应一个ingress的yaml配置文件 |
Ingress Controller | 将新加入的Ingress转化成Nginx的配置文件并使之生效 |
问题梳理
如果我们将ingress 以pod的方式部署到k8s集群内部,那么就会遇到多个问题:
1 ingress的pod如何引入外部流量
- 通过一个专用的service就可以实现了
2 ingress的pod如何把流量负载均衡到其他pod
- 关于pod负载均衡的流量,直接通过controller转发给后端pod即可。
3 后端应用的pod很多,如何知道谁是我们要转发的目标?
- 通过k8s的server对所有的pod进行分组管理,借助于controller内部的负载均衡配置,找到对应的目标。
原理解析
Ingress是授权入站连接到达集群服务的规则集合。
从外部流量调度到nodeport上的service
从service调度到ingress-controller
ingress-controller根据ingress[Pod]中的定义(虚拟主机或者后端的url)
根据虚拟主机名直接调度到后端的一组应用pod中
注意:
整个流程中涉及到了两处service内容
service ingress-nginx 是帮ingress controller接入外部流量的
虚线表示service对后端的应用进行分组,实现是ingress实际的访问流程
常见的解决方案
对于ingress controller的软件实现,其实没有特殊的要求,只要能够实现七层的负载均衡功能效果即可,各种组织对于ingress的controller虽然实现方式不同,但是功能基本上一样,常见的实现方式有:
Ingress-Nginx: Kong
HAProxy
性能相对于nginx来说,较稳定
Envoy:
基于C++语言开发,本身就为动态环境设计的,支持配置动态加载的XDS API
不能像ingress-nginx一样,直接加载配置文件并动态加载转换成对应的应用配置,所以需要借助于其他控制平面工具来实现。
常见解决方案:Contour, Gloo
Traefik
注意:ingress 自从 1.6版本引入后,在1.19 正式进入了一个稳定版本状态。
小结
1.3.2 Ingress实践
学习目标
这一节,我们从 环境部署、简单实践、小结 三个方面来学习。
环境部署
参考资料:https://github.com/kubernetes/ingress-nginx
安装文档:https://kubernetes.github.io/ingress-nginx/deploy/
配置文件解析
apiVersion: networking.k8s.io/v1 # 资源所属的API群组和版本
kind: Ingress # 资源类型标识符
metadata: # 元数据
name <string> # 资源名称
annotations: # 资源注解,v1beta1使用下面的注解来指定要解析该资源的控制器类型
kubernetes.io/ingress.class: <string> # 适配的Ingress控制器类别,便于多ingress组件场景下,挑选针对的类型
namespace <string> # 名称空间
spec:
rules <[]Object> # Ingress规则列表,也就是http转发时候用到的 url关键字
- host <string> # 虚拟主机的FQDN,支持“*”前缀通配,不支持IP,不支持指定端口
http <Object>
paths <[]Object> # 虚拟主机PATH定义的列表,由path和backend组成
- path <string> # 流量匹配的HTTP PATH,必须以/开头
pathType <string> # 支持Exact、Prefix和ImplementationSpecific,必选
backend <Object> # 匹配到的流量转发到的目标后端
resource <Object> # 引用的同一名称空间下的资源,与下面两个字段互斥
service <object> # 关联的后端Service对象
name <string> # 后端Service的名称
port <object> # 后端Service上的端口对象
name <string> # 端口名称
number <integer> # 端口号
tls <[]Object> # TLS配置,用于指定上rules中定义的哪些host需要工作HTTPS模式
- hosts <[]string> # 使用同一组证书的主机名称列表
secretName <string> # 保存于数字证书和私钥信息的secret资源名称,用于主机认证
backend <Object> # 默认backend的定义,可嵌套字段及使用格式跟rules字段中的相同
ingressClassName <string> # ingress类名称,用于指定适配的控制器,类似于注解的功能
环境部署
获取配置文件
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# mkdir ingress ; cd ingress
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/1.24/deploy.yaml
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# mv deploy.yaml ingress-deploy.yaml
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# cp ingress-deploy.yaml{,.bak}
获取镜像
for i in nginx-ingress-controller:v1.3.0 kube-webhook-certgen:v1.1.1
do
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$i
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$i kubernetes-register.superopsmsb.com/google_containers/$i
docker push kubernetes-register.superopsmsb.com/google_containers/$i
docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$i
done
修改基础镜像
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# grep image: ingress-deploy.yaml
image: kubernetes-register.superopsmsb.com/google_containers/nginx-ingress-controller:v1.3.0
image: kubernetes-register.superopsmsb.com/google_containers/kube-webhook-certgen:v1.1.1
image: kubernetes-register.superopsmsb.com/google_containers/kube-webhook-certgen:v1.1.1
开放访问入口地址
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# vim ingress-deploy.yaml
...
334 apiVersion: v1
335 kind: Service
...
344 namespace: ingress-nginx
345 spec:
...
348 ipFamilyPolicy: SingleStack
349 externalIPs: ['10.0.0.12'] # 增加一个外网访问的入口ip
350 ports:
351 - appProtocol: http
352 name: http
353 port: 80
...
628 failurePolicy: Ignore # 为了避免默认的准入控制限制,改为Ignore
...
应用资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# kubectl apply -f ingress-deploy.yaml
确认效果
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-s5p7h 0/1 Completed 0 105s
pod/ingress-nginx-admission-patch-qnjmv 0/1 Completed 0 105s
pod/ingress-nginx-controller-6cc467dfd9-c2dfg 1/1 Running 0 105s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller NodePort 10.109.163.145 10.0.0.12 80:31547/TCP,443:31185/TCP 105s
service/ingress-nginx-controller-admission ClusterIP 10.96.223.121 <none> 443/TCP 105s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 105s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-6cc467dfd9 1 1 1 105s
NAME COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-create 1/1 8s 105s
job.batch/ingress-nginx-admission-patch 1/1 7s 105s
测试访问页面
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# curl 10.0.0.12:31547
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
直接获取状态码
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# curl -I -o /dev/null -s -w %{http_code}"\n" 10.0.0.12:31547
404
简单实践
创建deployment
定义资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 12_kubernetes_scheduler_ingress_deployment_nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: superopsmsb-nginx-deployment
spec:
replicas: 4
selector:
matchLabels:
app: nginx-web
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx-web
image: kubernetes-register.superopsmsb.com/superopsmsb/nginx_web:v0.1
---
apiVersion: v1
kind: Service
metadata:
name: superopsmsb-nginx-service
spec:
selector:
app: nginx-web
ports:
- name: nginx
port: 80
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 12_kubernetes_scheduler_ingress_deployment_nginx.yaml
deployment.apps/superopsmsb-nginx-deployment created
service/superopsmsb-nginx-service created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
superopsmsb-nginx-deployment 4/4 4 4 25s
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d14h
superopsmsb-nginx-service ClusterIP 10.97.149.207 <none> 80/TCP 25s
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
superopsmsb-cm-nginx 1/1 Running 0 18h 10.244.1.19 kubernetes-node1 <none> <none>
superopsmsb-nginx-deployment-64fc5c5f6c-c2vmm 1/1 Running 0 25s 10.244.1.21 kubernetes-node1 <none> <none>
superopsmsb-nginx-deployment-64fc5c5f6c-dt4hx 1/1 Running 0 25s 10.244.1.22 kubernetes-node1 <none> <none>
superopsmsb-nginx-deployment-64fc5c5f6c-mxxbh 1/1 Running 0 25s 10.244.3.19 kubernetes-node3 <none> <none>
superopsmsb-nginx-deployment-64fc5c5f6c-zn57z 1/1 Running 0 25s 10.244.2.16 kubernetes-node2 <none> <none>
superopsmsb-secret-nginx 1/1 Running 0 16h 10.244.1.20 kubernetes-node1 <none> <none>
创建ingress
定义资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 13_kubernetes_scheduler_ingress_test.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: superopsmsb-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: nginx.superopsmsb.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: superopsmsb-nginx-service
port:
number: 80
属性解析:
注释信息,对于不同的ingress的内容是不一样的
对于ingress来说,最终要的就是rules了,这里的hosts是一个自定义的域名
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 13_kubernetes_scheduler_ingress_test.yaml
ingress.networking.k8s.io/superopsmsb-ingress created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
superopsmsb-ingress <none> nginx.superopsmsb.com 80 17s
查看详细信息
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe ingress superopsmsb-ingress
Name: superopsmsb-ingress
Labels: <none>
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
nginx.superopsmsb.com
/ superopsmsb-nginx-service:80 (10.244.1.21:80,10.244.1.22:80,10.244.2.16:80 + 1 more...)
Annotations: kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 23s nginx-ingress-controller Scheduled for sync
结果显式:
ingress 将 后端的superopsmsb-nginx-service:80 的样式自动与 ingress 的 url(/) 关联在一起了
访问效果
[root@kubernetes-master1 /data/kubernetes/schduler]# curl 10.0.0.12
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
为了更好的演示域名的效果,我们为externalIPs的ip地址做一个域名绑定
[root@kubernetes-master1 /data/kubernetes/schduler]# echo '10.0.0.12 nginx.superopsmsb.com' >> /etc/hosts
确认效果
[root@kubernetes-master1 /data/kubernetes/schduler]# curl nginx.superopsmsb.com
Hello Nginx, superopsmsb-nginx-deployment-64fc5c5f6c-dt4hx-1.23.0
结果显式:
通过域名可以正常的访问后端的服务,而非域名访问方式受到了限制
非域名方式进行访问
[root@kubernetes-master1 /data/kubernetes/schduler]# curl http://10.0.0.12
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@kubernetes-master1 /data/kubernetes/schduler]# curl http://10.0.0.12 -H "Host:nginx.superopsmsb.com"
Hello Nginx, superopsmsb-nginx-deployment-64fc5c5f6c-zn57z-1.23.0
结果显示:
通过自定义携带域名的方式可以正常访问。
小结
1.3.3 Ingress进阶
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
需求
nginx controller的功能远不止我们所说的主机域名的管理,在实际的工作需求中,肯定会遇到,不同的功能服务以子路径的方式来进行访问,以及与https相关的访问。
准备工作
单独再来一个flask的服务
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 14_kubernetes_scheduler_ingress_deployment_flask.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: superopsmsb-flask-deployment
spec:
replicas: 4
selector:
matchLabels:
app: flask-web
template:
metadata:
labels:
app: flask-web
spec:
containers:
- name: flask-web
image: kubernetes-register.superopsmsb.com/superopsmsb/flask_web:v0.1
---
apiVersion: v1
kind: Service
metadata:
name: superopsmsb-flask-service
spec:
selector:
app: flask-web
ports:
- name: flask
port: 80
配置解析
为了避免多个service使用同一个后端端口,我们这里一定要为service的端口命名
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 14_kubernetes_scheduler_ingress_deployment_flask.yaml
deployment.apps/superopsmsb-flask-deployment created
service/superopsmsb-flask-service created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
superopsmsb-flask-deployment 3/4 4 3 17s
superopsmsb-nginx-deployment 4/4 4 4 55m
简单实践
- 多主机访问实践
需求
访问 flask.superopsmsb.com/的时候,返回flask的结果
访问 nginx.superopsmsb.com/的时候,返回nginx的结果
资源配置文件
编辑资源定义文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 15_kubernetes_scheduler_ingress_mulhost.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: superopsmsb-ingress-mulhost
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: nginx.superopsmsb.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: superopsmsb-nginx-service
port:
name: nginx
- host: flask.superopsmsb.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: superopsmsb-flask-service
port:
name: flask
配置解析:
这里面有两个主机访问的地址是同一个后端端口,如果还用number的话,就无法正常的识别导致同一个地址访问不同的后端效果
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 15_kubernetes_scheduler_ingress_mulhost.yaml
ingress.networking.k8s.io/superopsmsb-ingress-mulhost created
查看ingress效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
superopsmsb-ingress-mulhost <none> nginx.superopsmsb.com,flask.superopsmsb.com 10.0.0.17 80 30s
查看ingress详情
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe ingress superopsmsb-ingress-mulhost
Name: superopsmsb-ingress-mulhost
Labels: <none>
Namespace: default
Address: 10.0.0.17
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
nginx.superopsmsb.com
/ superopsmsb-nginx-service:nginx (10.244.1.21:80,10.244.1.22:80,10.244.2.16:80 + 1 more...)
flask.superopsmsb.com
/ superopsmsb-flask-service:flask (10.244.1.23:80,10.244.2.20:80,10.244.3.25:80 + 1 more...)
Annotations: kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 2s (x2 over 31s) nginx-ingress-controller Scheduled for sync
实践
提前准备多个后端主机的域名
echo '10.0.0.12 flask.superopsmsb.com nginx.superopsmsb.com' >> /etc/hosts
访问效果
- 单域名多url访问
需求
访问 shuji.superopsmsb.com/flask的时候,返回flask的结果
访问 shuji.superopsmsb.com/nginx的时候,返回nginx的结果
注意事项:
由于这里涉及到了域名的url转发,而后端服务有可能不存在,随意我们需要在后端url转发的时候,取消转发关键字。
方法就是,在annotation中添加一个重写的规则
nginx.ingress.kubernetes.io/rewrite-target: /
即,所有的请求,把ingress匹配到的url关键字清除掉
测试效果
编辑资源定义文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 16_kubernetes_scheduler_ingress_mulurl.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: superopsmsb-ingress-mulurl
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: shuji.superopsmsb.com
http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: superopsmsb-nginx-service
port:
name: nginx
- path: /flask
pathType: Prefix
backend:
service:
name: superopsmsb-flask-service
port:
name: flask
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 16_kubernetes_scheduler_ingress_mulurl.yaml ingress.networking.k8s.io/superopsmsb-ingress-mulurl created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
superopsmsb-ingress-mulurl <none> shuji.superopsmsb.com 80 33s
查看ingress资源详情
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe ingress superopsmsb-ingress-mulurl
Name: superopsmsb-ingress-mulurl
Labels: <none>
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
shuji.superopsmsb.com
/nginx superopsmsb-nginx-service:nginx (10.244.1.21:80,10.244.1.22:80,10.244.2.16:80 + 1 more...)
/flask superopsmsb-flask-service:flask (10.244.1.24:80,10.244.2.21:80,10.244.2.22:80 + 1 more...)
Annotations: kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 33s nginx-ingress-controller Scheduled for sync
准备域名解析
[root@kubernetes-master1 /data/kubernetes/schduler]# echo '10.0.0.12 shuji.superopsmsb.com' >> /etc/hosts
浏览器访问效果
[root@kubernetes-master1 /data/kubernetes/schduler]# curl shuji.superopsmsb.com/flask
Hello Flask-V0.1, 来访者ip: 10.244.3.24, 主机名: superopsmsb-flask-deployment-766544c668-qgm92, Pod地址: 10.244.1.24!
[root@kubernetes-master1 /data/kubernetes/schduler]# curl shuji.superopsmsb.com/nginx
Hello Nginx, superopsmsb-nginx-deployment-64fc5c5f6c-mxxbh-1.23.0
小结
1.3.4 Ingress认证
学习目标
这一节,我们从 web认证、集群认证、小结 三个方面来学习。
web认证
需求
我们准备对基础的flask应用进行https方式来进行访问
方法:
ingress的tls规则就可以帮助我们实现对http应用进行https升级
简单实践
定制secret文件
[root@kubernetes-master1 /data/kubernetes/schduler]# mkdir ingress-tls && cd ingress-tls
[root@kubernetes-master1 /data/kubernetes/schduler/ingress-tls]# (umask 077; openssl genrsa -out tls.key 2048)
Generating RSA private key, 2048 bit long modulus
......................................................................................+++
...............................+++
e is 65537 (0x10001)
[root@kubernetes-master1 /data/kubernetes/schduler/ingress-tls]# openssl req -new -x509 -key tls.key -out tls.crt -subj "/CN=shuji.superopsmsb.com" -days 365
[root@kubernetes-master1 /data/kubernetes/schduler/ingress-tls]# kubectl create secret tls superopsmsb-ingress-tls --cert=./tls.crt --key=./tls.key
secret/ingress-tls created
确认效果
[root@kubernetes-master1 /data/kubernetes/schduler/ingress-tls]# ls
tls.crt tls.key
编辑资源定义文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 17_kubernetes_scheduler_ingress_tls.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: superopsmsb-ingress-tls
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: shuji.superopsmsb.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: superopsmsb-nginx-service
port:
number: 80
tls:
- hosts:
- shuji.superopsmsb.com
secretName: superopsmsb-ingress-tls
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 17_kubernetes_scheduler_ingress_tls.yaml
ingress.networking.k8s.io/superopsmsb-ingress-tls created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
superopsmsb-ingress-mulurl <none> shuji.superopsmsb.com 10.0.0.17 80 16m
superopsmsb-ingress-tls <none> shuji.superopsmsb.com 80, 443 19s
查看ingress详情
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe ingress superopsmsb-ingress-tls
Name: superopsmsb-ingress-tls
Labels: <none>
Namespace: default
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
superopsmsb-ingress-tls terminates shuji.superopsmsb.com
Rules:
Host Path Backends
---- ---- --------
shuji.superopsmsb.com
/ superopsmsb-nginx-service:80 (10.244.1.21:80,10.244.1.22:80,10.244.2.16:80 + 1 more...)
Annotations: kubernetes.io/ingress.class: nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 19s nginx-ingress-controller Scheduled for sync
结果显示:
所有访问 shuji.superopsmsb.com的请求都需要进行tls的处理,否则失效。
访问测试效果
[root@kubernetes-master1 /data/kubernetes/schduler]# curl shuji.superopsmsb.com
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@kubernetes-master1 /data/kubernetes/schduler]# curl https://shuji.superopsmsb.com.com
curl: (35) Peer reports it experienced an internal error.
[root@kubernetes-master1 /data/kubernetes/schduler]# curl -k https://shuji.superopsmsb.com
Hello Nginx, superopsmsb-nginx-deployment-64fc5c5f6c-c2vmm-1.23.0
集群认证
需求
我们知道,对于k8s的dashboard来说,它所实现的功能还是比较多的,而且原则上要求必须是https方式来进行访问。我们之前是通过service的方式实现正常的请求访问。有了ingress,我们也可以自由的访问dashboard了。比如我们访问k8s的dashboard的首页地址是
https://10.0.0.12:nodeport/#/login
思路
除了我们之前所说的动态url的方式之外,就需要tls认证了。关于对集群内部的ingress的tls访问方式,可以借助于ingress controller的annotation的方式向nginx中传递一些属性,从而上nginx支持相应的功能。这与我们上一节的方式有所不同
1 通过两个annotation中的规则
ingress.kubernetes.io/ssl-passthrough: "true"
- 以为后面的dashboard本身就做了tls功能,所以这里进行tls代理即可
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- 对后端直接启动https协议访问即可。
参考资料:
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/
定制ingress资源配置文件
[root@kubernetes-master1 /data/kubernetes/schduler]# cat 18_kubernetes_scheduler_ingress_tls_dashboard.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: superopsmsb-ingress-dashboard
namespace: kubernetes-dashboard
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: shuji.superopsmsb.com
http:
paths:
- path: /dashboard(/|$)(.*)
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443
应用资源文件
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 18_kubernetes_scheduler_ingress_tls_dashboard.yaml
ingress.networking.k8s.io/superopsmsb-ingress-dashboard created
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get ingress -n kubernetes-dashboard
NAME CLASS HOSTS ADDRESS PORTS AGE
superopsmsb-ingress-dashboard <none> shuji.superopsmsb.com 80 17s
查看ingress详情
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe ingress -n kubernetes-dashboard
Name: superopsmsb-ingress-dashboard
Labels: <none>
Namespace: kubernetes-dashboard
Address:
Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
Host Path Backends
---- ---- --------
shuji.superopsmsb.com
/dashboard(/|$)(.*) kubernetes-dashboard:443 (10.244.3.28:8443)
Annotations: ingress.kubernetes.io/ssl-passthrough: true
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: HTTPS
nginx.ingress.kubernetes.io/rewrite-target: /$2
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 17s nginx-ingress-controller Scheduled for sync
浏览器访问 https://shuji.superopsmsb.com/dashboard/ 查看效果
结果显示:
借助于nginx-controller的tls功能可以正常的实现相关的https的效果。
小结
1.3.5 Ingress扩展
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习。
基础知识
简介
默认情况下,Ingress是通过 Deployment + nodePort的方式将集群内部的服务暴露出去的,而且默认情况下,整个kubernetes集群中只有一个ingress-nginx实例。
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl get pod -n ingress-nginx | grep controll
ingress-nginx-controller-6cc467dfd9-c2dfg 1/1 Running 0 52m
思路:
如果集群中唯一的ingress-nginx出现了故障,将导致整个kubernetes集群不可用。所以我们需要将这个集群业务的唯一入口进行高可用处理,根据我们之前的kubernetes资源对象知识,我们可以按照以下思路来进行:
1 借助于Daemonset的方式实现ingress的多节点部署
2 为了限制ingress-controller仅仅部署到master节点上,我们这里采用nodeSeler的方式来筛选master节点
3 为了避免NodePort的劣势凸显,可以直接使用宿主机的80和443端口,我们可以采用HostNetwork的方式实现Cluster和node的网络互通,让Cluster直接监听node的端口。前提是宿主机的这两个端口不被占用
所以最终我们可以确定 DaemonSet + HostNetwork + nodeSelector方式来部署ingress-nginx高可用集群。
准备工作
文件备份
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# cp ingress-deploy.yaml ingress-daemonset.yaml
检查主机环境
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# for i in {12..14}; do ssh root@10.0.0.$i "netstat -tnulp | egrep '443|80'"; done
tcp 0 0 10.0.0.12:2380 0.0.0.0:* LISTEN 2146/etcd
tcp6 0 0 :::6443 :::* LISTEN 31072/kube-apiserve
tcp 0 0 10.0.0.13:2380 0.0.0.0:* LISTEN 2234/etcd
tcp6 0 0 :::6443 :::* LISTEN 28944/kube-apiserve
tcp 0 0 10.0.0.14:2380 0.0.0.0:* LISTEN 2186/etcd
tcp6 0 0 :::6443 :::* LISTEN 29045/kube-apiserve
简单实践
修改文件
修改资源清单文件
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# vim ingress-daemonset.yaml
...
390 apiVersion: apps/v1
391 kind: DaemonSet # 将Deployment修改为 DaemonSet
...
491 dnsPolicy: ClusterFirst
492 hostNetwork: true # 增加cluster和node网络的互通
493 tolerations:
494 - operator: Exists
495 nodeSelector:
496 ingressSelect: "true" # 专属的节点部署标签,而且必须加上双引号
497 kubernetes.io/os: linux
所有master节点添加标识
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# for i in 1 2 3
do
kubectl label node kubernetes-master$i ingressSelect=true
done
应用资源清单文件
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# kubectl apply -f ingress-daemonset.yaml
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-mn4tl 0/1 Completed 0 116s 10.244.2.25 kubernetes-node2 <none> <none>
ingress-nginx-admission-patch-rbtl5 0/1 Completed 0 116s 10.244.3.31 kubernetes-node3 <none> <none>
ingress-nginx-controller-85c26 1/1 Running 0 116s 10.0.0.14 kubernetes-master3 <none> <none>
ingress-nginx-controller-88w6j 1/1 Running 0 116s 10.0.0.12 kubernetes-master1 <none> <none>
ingress-nginx-controller-v2k7z 1/1 Running 0 116s 10.0.0.13 kubernetes-master2 <none> <none>
[root@kubernetes-mas
端口检查效果
[root@kubernetes-master1 /data/kubernetes/schduler/ingress]# for i in {12..14}; do ssh root@10.0.0.$i "netstat -tnulp | egrep ':(443|80)'"; done
tcp 0 0 0.0.0.0:443 ...78308/nginx: master
tcp 0 0 0.0.0.0:80 ...78308/nginx: master
tcp6 0 0 :::443 ...78308/nginx: master
tcp6 0 0 :::80 ...78308/nginx: master
tcp 0 0 0.0.0.0:80 ...72502/nginx: master
tcp 0 0 0.0.0.0:443 ...72502/nginx: master
tcp6 0 0 :::80 ...72502/nginx: master
tcp6 0 0 :::443 ...72502/nginx: master
tcp 0 0 0.0.0.0:80 ...72415/nginx: master
tcp 0 0 0.0.0.0:443 ...72415/nginx: master
tcp6 0 0 :::80 ...72415/nginx: master
tcp6 0 0 :::443 ...72415/nginx: master
确认效果
创建资源对象
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl apply -f 17_kubernetes_scheduler_ingress_tls.yaml
查看效果
[root@kubernetes-master1 /data/kubernetes/schduler]# kubectl describe ingress superopsmsb-ingress-tls
Name: superopsmsb-ingress-tls
Labels: <none>
Namespace: default
Address: 10.0.0.12,10.0.0.13,10.0.0.14
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 17s (x2 over 40s) nginx-ingress-controller Scheduled for sync
Normal Sync 17s (x2 over 40s) nginx-ingress-controller Scheduled for sync
Normal Sync 17s (x2 over 40s) nginx-ingress-controller Scheduled for sync
查看访问效果
[root@kubernetes-master1 /data/kubernetes/schduler]# curl https://shuji.superopsmsb.com -k
Hello Nginx, superopsmsb-nginx-deployment-64fc5c5f6c-mhgcs-1.23.0
小结