本文内容:
替换k8s集群调度器的两种方式:
1:竞争锁的方式
2:kubelet static pod方式
查看集群默认调度器:
kubectl get pods -n kube-system -l component=kube-scheduler
1:
笔记:
k8s默认调度器对应的pod叫做kube-scheduler-xxx,这个xxx默认是master节点的名字,这是个独立的pod,不属于任何deployment/statefulset,默认的调度器的名字叫做defaulter-scheduler,位于kube-system命名空间下面。这个defaulter-scheduler默认是开启选举的,他会竞争kube-system命名空间下的叫做kube-scheduler的leases资源,一旦获取到锁,就会继续往下运行,当获取不到时就会阻塞。
我们的调度器运行时有两种模式,第一种是作为独立的调度器和默认的调度器并存,但是在KubeSchedulerConfiguration.yaml文件中配置一个不同的调度器名字(假设为anotherScheduler,这样我们调度一个pod的时候当该pod的spec.schedulerName字段设置为anotherScheduler时,该pod就会由我们的调度器调度而不是默认的调度器调度;第二种运行模式就是替换掉默认的调度器。
替换掉默认的调度器有两种方式,第一种是设置集群的默认调度器配置文件,麻烦,我们这里不采用;第二种是配置anotherScheduler调度器和默认的调度器竞争同样的锁,同时把anotherScheduler调度器的名字设置为defaulter-scheduler,然后写一个脚本去手动删除kube-scheduler-xxx(不用担心,k8s会自动重新创建该pod,我们这样做是为了让我们的dfautler-scheduler可以更容易获得锁)这个pod和kube-system下叫做kube-scheduler的leases资源(当锁不存在的时候k8s选举系统会自动创建该锁,所以不用担心),然后让他们去竞争锁,如果我们的defaulter-scheduler获取了锁,那么默认的defaulter-scheduler就会挂起,这样我们就可以在不修改配置文件的情况下替换掉系统默认的kube-scheduler,当然运行过程中当我们的调度器pod重启时,有可能defaulter-scheduler会获取到锁,所以我们可以写一个脚本,定时执行删除默认调度器pod的命令,这样pod不存在,获取到锁的概率大大降低。
当集群所有scheduler都不可用时,我们可以在yaml文件中设置pod.spec.nodeName=xxx,这样就可以直接跳过scheduler,因为调度器就是替pod选一个node
都设置好后我们可以写一个脚本,定时删除指定pod,这样因为deployment还在,所以这些pod都会重新调度,从而运行我们的scheduler,从而验证我们的scheduler稳定性
替换默认调度操作(假设默认的调度器pod叫做kube-scheduler-0i:
1.1:配置我们的自己的调度器的配置文件
kind: ConfigMap
apiVersion: v1
metadata:
name: scheduler-config
namespace: crane-system
data:
scheduler-config.yaml: |
apiVersion: kubescheduler.config.k8s.io/v1beta2
kind: KubeSchedulerConfiguration
leaderElection:
leaderElect: true
#resourceName: crane-scheduler-lock #默认就是竞争kube-scheduler锁
resourceLock: leases
#resourceNamespace: kube-system #默认锁就是位于kube-system命名空间下
profiles:
#- schedulerName: local-scheduler
- schedulerName: default-scheduler #名字设置为defaulte-scheduler
plugins:
score:
enabled:
- name: Dynamic
weight: 3
postBind:
enabled:
- name: Dynamic
pluginConfig:
- name: Dynamic
args:
promeAddr: "http://prometheus.crane-system.svc.cluster.local:9090"
metricsUpdatePeriodBySeconds: 5m
clusterName: "cs-test-2"
policyConfigPath: /etc/kubernetes/policy.yaml
1.2:配置我们自己的defaulter-scheduler的deployment文件中spec.replicas字段为3,保证高可用,假设pod叫做myscheduler-xxx
(同样可以设置spec.nodeName: “masterNodeName”,masterNodeName代表我们master节点的名字,这样所有3个pod都会调度到master节点上了)
1.3:部署我们自己的defaulter-scheduler,当pod启动后会处于阻塞状态,因为没有获取到锁
1.4:写一个脚本删除默认的调度器和默认的锁,这样我们的defaulter-scheduler就有大概率来获取到锁
Kubectl delete pod kube-scheduler-0i -n kube-system
kubectl delete leases kube-scheduerl -n kube-system
1.5:然后就是查看我们自己的defaulter-scheduerl的日志,看有没有获取到锁
kubectl logs myscheduler-xxx #因为副本为3,所以可能有三个pod,然后就是查看看他们有没有获取到锁
1.6:脚本定时删除一次指定pod
kubectl get pods --no-headers=true -o custom-columns=:metadata.name -n crane-system --force --grace-period=0
1.7:删除命名空间 kubectl edit如果不生效,就只能用curl方式
kubectl get namespace nginx-example -o json > devtesting.json 然后删除finallize字段
kubectl proxy --port=8080&
curl -k -H "Content-Type: application/json" -X PUT --data-binary @devtesting.json http://127.0.0.1:8080/api/v1/namespaces/nginx-example/finalize
如果kubelet PLEG报错,导致节点notReady,十有八九是该节点上的docker卡死了,去该节点重启docker一般可以解决,短时间调度大量pod就有可能导致这样,暂未排查
k8s的kubelet报错PLEG is not healthy: pleg was last seen active
journalctl -u kubelet -f #查看实时日志
journalctl -u kubelet -n 100 #跳到日志第100行
sudo pkill docker
sudo systemctl stop docker
sudo systemctl stop docker.socket
sudo systemctl restart docker
2:直接替换方式
要点笔记:
1:kubelect启动参数指定了静态pod的路径,kubectl默认每20s扫描一次该目录,然后根据该目录下的yaml文件来创建pod,该目录下的目录不会被读取
2:pod.yaml坑点: 静态pod和普通pod有区别,主要是一个蛋生鸡鸡生蛋的问题,节点还没初始化好,此时静态pod就要创建了,所以有些区别
2.1:不能用serviceAccount,要用kubeconfig方式,即在调度器的启动命令里设置kubeconfig
2.2:必须设置hostNetwork=true,否则会初始化失败
2.3:需要重新设置secure-port,因为默认的调度器已经把默认的10259给占用了
yaml举例:
apiVersion: v1
kind: Pod
metadata:
name: my-scheduler
namespace: kube-system
labels:
component: my-scheduler
spec:
hostNetwork: true #静态pod需要设置这个
volumes:
- name: scheduler-config
hostPath:
path: /etc/kubernetes/manifests/my-scheduler/scheduler-config.yaml
type: File
- name: scheduler-policy
hostPath:
path: /etc/kubernetes/manifests/my-scheduler/policy.yaml
type: File
- name: kubeconfig
hostPath:
path: /etc/kubernetes/manifests/my-scheduler/admin.conf
type: File
containers:
- name: my-scheduler
image: 'xxxxx'
command:
- /scheduler
- --v=3
- --leader-elect=true
- --config=/etc/kubernetes/scheduler-config.yaml
- --secure-port=12345 #容易冲突,所以重新设置一个端口
- --kubeconfig=/etc/kubernetes/scheduler.conf
resources:
requests:
cpu: 500m
volumeMounts:
- name: kubeconfig
mountPath: /etc/kubernetes/scheduler.conf
- name: scheduler-config
mountPath: /etc/kubernetes/scheduler-config.yaml
- name: scheduler-policy
mountPath: /etc/kubernetes/scheduler-policy.yaml
livenessProbe:
httpGet:
path: /healthz
port: 12345 #端口同secure-port
scheme: HTTPS
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: 12345
scheme: HTTPS
restartPolicy: Always
dnsPolicy: ClusterFirst