kubectl taint nodes node1 key=value:NoSchedule --新的不能容忍的pod不能再调度过来,可是老的运行在node上不受影响html
kubectl taint nodes node1 key=value:NoExecute --新的不能容忍的pod不能调度过来,老的pod也会被驱逐前端
kubectl taint nodes node1 key=value:PreferNoSchedule --pod会尝试将pod分配到该节点node
能够参考连接详细学习:https://www.qikqiak.com/post/kubernetes-affinity-scheduler/mysql
nodeSelector调度:强制调度pod到某个节点上nginx
亲和性和反亲和性调度:git
nodeAffinity(节点亲和性)、podAffinity(pod 亲和性) 以及 podAntiAffinity(pod 反亲和性)github
亲和性调度能够分红软策略和硬策略两种方式:web
对于亲和性和反亲和性都有这两种规则能够设置: preferredDuringSchedulingIgnoredDuringExecution和requiredDuringSchedulingIgnoredDuringExecution,前面的就是软策略,后面的就是硬策略。sql
affinity:后端
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node03
preferredDuringSchedulingIgnoredDuringExecution: # 软策略
- weight: 1
preference:
matchExpressions:
- key: com
operator: In
values:
- youdianzhishi
nodeSelectorTerms属性类型
若是nodeSelectorTerms下面有多个选项的话,知足任何一个条件就能够了;若是matchExpressions有多个选项的话,则必须同时知足这些条件才能正常调度 POD。
工做负载型资源对象(workload):POD,ReplicaSet,Deployment,StatefulSet,DaemonSet,Job,Cronjob ...
服务发现及均衡资源对象:Service,Ingress ...
配置与存储资源对象:Volume(存储卷),CSI(容器存储接口,能够扩展各类各样的第三方存储卷),ConfigMap,Secret,DownwardAPI
集群级资源:Namespace,Node,Role,ClusterRole,RoleBinding,ClusterRoleBinding
元数据型资源:HPA,PodTemplate,LimitRange
一.本地存储
1,EmptyDir
若是在此目录中建立删除文件,都将对容器中的/data目录有影响,若是删除Pod,文件将所有删除,即便是在宿主机上建立的文件也是如此,在宿主机上删除容器则k8s会再自动建立一个容器,此时文件仍然存在。
2.HostDir
在宿主机上指定一个目录,挂载到Pod的容器中,其实跟上面的写法不尽相同,这里只截取不一样的部分,当pod删除时,本地仍然保留文件
二.网络数据卷(NFS)
1.NFS
如何加入NFS文件系统
# 安装nfs服务
[root@nfs01 ~]# yum install nfs-utils rpcbind
# 建立nfs挂载目录
[root@nfs01 ~]# mkdir /data/volums/data01/ -p
# 启动服务
[root@nfs01 ~]# systemctl start rpcbind
[root@nfs01 ~]# systemctl enable rpcbind
[root@nfs01 ~]# systemctl start nfs-server
[root@nfs01 ~]# systemctl enable nfs-server
# 配置nfs服务
[root@nfs01 ~]# cat /etc/exports
/data/volums/data01 *(async,insecure,no_root_squash,no_subtree_check,rw)
# 查看nfs状态
[root@nfs01 ~]# showmount -e 192.168.17.195
Export list for 192.168.17.195:
/data/volums/data01 192.168.17.0/24
注意:对应的节点须要安装客户端:yum install nfs-utils
采用nfc存储的yaml样例
spec:
containers:
- name: web
image: nginx
imagePullPolicy: Never #若是已经有镜像,就不须要再拉取镜像
ports:
- name: web
containerPort: 80
hostPort: 80 #将容器的80端口映射到宿主机的80端口
volumeMounts:
- name : nfs #指定名称必须与下面一致
mountPath: "/usr/share/nginx/html" #容器内的挂载点
volumes:
- name: nfs #指定名称必须与上面一致
nfs: #nfs存储
server: 192.168.30.32 #nfs服务器ip或是域名
path: "/nfs-data" #nfs服务器共享的目录
在/test目录中建立index.html文件后,这个文件也将在容器中生效,当Pod删除时,文件不受影响,实现了数据持久化。
三. Persistent Volume(PV)和Persistent Volume Claim(PVC)
其实这两种数据卷也属于网络数据卷,单拎出来是由于我以为这个比前面的数据卷要酷多了,有种大数据,云平台的意思,当用户要使用数据存储的时候他是否还须要知道是什么类型的数据存储,答案是不须要,用户只想要安全可靠的数据存储,并且实现起来很简单,管理员创建一个存储平台,用户按本身的需求消费就能够了
PersistentVolume (PV) 是外部存储系统中的一块存储空间,由管理员建立和维护。与 Volume 同样,PV 具备持久性,生命周期独立于 Pod。
PersistentVolumeClaim (PVC) 是对 PV 的申请 (Claim)。PVC 一般由普通用户建立和维护。须要为 Pod 分配存储资源时,用户能够建立一个 PVC,指明存储资源的容量大小和访问模式(好比只读)等信息,Kubernetes 会查找并提供知足条件的 PV。
静态Pvc的示例
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: efk-pvc
namespace: kube-system #注意pvc所在的命名空间和所引用的pod须要在同一个
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
storageClassName: efk-nfs
pod如何引用pvc
volumeMounts:
- name: elasticsearch-logging
mountPath: /data
env:
- name: "NAMESPACE"
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumes:
- name: elasticsearch-logging
persistentVolumeClaim:
claimName: efk-pvc
具体建立和使用参考:
https://blog.51cto.com/forall/2135152
动态pvc的使用
建立和使用参考连接:https://blog.51cto.com/goome/2423200
过程当中遇到的问题
nfs-client-provisioner这个pod一直报错error retrieving resource lock default/fuseim.pri-ifs: Unauthorized
最后参考连接
https://github.com/kubernetes-incubator/external-storage/issues/953
把下面这段替换rbac.yaml文件就行,大概的缘由是rbac分配给nfs-client的权限不够
kind: ClusterRoleapiVersion: rbac.authorization.k8s.io/v1metadata:
name: efs-provisioner-runnerrules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
再也不须要再建立pod前先申请pvc而后再挂载进pod,能够经过在部署pod的yaml文件中采用StatefulSet
statefulset,能够翻译成有状态的设定.
和deployment的对比
deployment部署建立的pod是无状态的,从新调度pod,pod名字hostname,启动pod顺序删除pod顺序都是随机的.deployment使用的是共享存储,全部pod共用一个存储卷.
statefulset部署建立的pod是有状态的,从新调度pod,pod名字hostname保持固定不变,启动pod顺序删除pod顺序均可以根据定义的顺序有序执行操做,有序的动态更新,statefulset使用的存储,不是共用一个存储卷,一个pod对应一个存储卷(pv).pod从新建立调度挂载的存储卷保持不变.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-testspec:
serviceName: headless-svc
replicas: 3
selector:
matchLabels:
app: headless-pod
template:
metadata:
labels:
app: headless-pod
spec:
containers:
- image: httpd
name: myhttpd
ports:
- containerPort: 80
name: httpd
volumeMounts:
- mountPath: /mnt
name: test
volumeClaimTemplates:
- metadata:
name: test
annotations:
volume.beta.kubernetes.io/storage-class: managed-nfs-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Mi
accessModes
用于定义资源的访问方式,受限于存储底层的支持,访问方式包括如下几种:
ReadWriteOnce – 被单个节点mount为读写rw模式
ReadOnlyMany – 被多个节点mount为只读ro模式
ReadWriteMany – 被多个节点mount为读写rw模式
service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,通常把service称为微服务
服务类型
ClusterIP:
分配一个内部集群IP地址,只能在集群内部访问(同Namespace内的Pod),默认ServiceType。
Service对象在Cluster IP range池中分配到的IP只能在内部访问,若是服务做为一个应用程序内部的层次,仍是很合适的。若是这个Service做为前端服务,准备为集群外的客户提供业务,咱们就须要给这个服务提供公共IP了。
NodePort:
分配一个内部集群IP地址,并在每一个节点上启用一个端口来暴露服务,能够在集群外部访问。
访问地址:<NodeIP>:<NodePort>
LoadBalancer:
分配一个内部集群IP地址,并在每一个节点上启用一个端口来暴露服务。
除此以外,Kubernetes会请求底层云平台上的负载均衡器,将每一个Node([NodeIP]:[NodePort])做为后端添加进去。
service的类型
ClusterIP 默认模式,只能在集群内部访问
NodePort 在每一个节点上都监听一个一样的端口号(30000-32767),ClusterIP和路由规则会自动建立。集群外部能够访问<NodeIP>:<NodePort>联系到集群内部服务,能够配合外部负载均衡使用(我如今公司用的就是这个模式配合阿里云的SLB)
LoadBalancer 要配合支持公有云负载均衡使用好比GCE、AWS。其实也是NodePort,只不过会把<NodeIP>:<NodePort>自动添加到公有云的负载均衡当中
ExternalName 建立一个dns别名指到service name上,主要是防止service name发生变化,要配合dns插件使用,用户能够指定一个任意的名字,做为该service被解析的CNAME,这种类型的servcie不用指定clusterIP,所以kube-proxy不会管理这类service,这类service须要使用1.7版本以上的kubedns。好比用户想建立一个service,但要让全部容器访问该service的请求都引导到用户本身定义的外部域名服务,就能够经过这个方式实现。能够说这个是最自由的一个方式:你但愿服务被如何解析,服务就能被如何解析。你甚至能够给多个service配置同一个externalName。
---
kind: Service
apiVersion: v1
metadata:
name: mysql-5-7-01-service
spec:
type: ExternalName
externalName: ai-production-mysql-bot.cfyipcsxzevb.rds.cn-northwest-1.amazonaws.com.cn
---
经过上面建立的servicename去访问对应的aws上的mysql服务
集群中容器访问集群外部服务
DNS
Service type:ExternalName
在Docker环境中,因为Docker Engine自带 DNS Server,咱们使用容器名来访问其它容器,由于容器是不稳定的,当容器宕掉,再从新启动相同镜像的容器,IP地址会改变,因此咱们不使用IP访问其它容器;一样的,在Kubernetes集群中,因为咱们使用 kube-DNS,咱们经常使用Service名称来访问某个服务,Service资源对象能保证其背后的容器副本始终是最新的IP。
所以,咱们能够利用这个特性,对Service名称和外部服务地址作一个映射,使之访问Service名称既是访问外部服务。例以下面的例子是将 svc1 和 xxx.xxx.xxx.xxx 作了对等关系。
kind: Service
apiVersion: v1
metadata:
name: svc1
namespace: default
spec:
type: ExternalName
externalName: somedomain.org
设置 Service 的 EndPoint
在Kubernetes集群中,同一个微服务的不一样副本会对集群内或集群外(取决于服务对外暴露类型)暴露统一的服务名称,一个服务背后是多个 EndPoint,EndPoint解决映射到某个容器的问题,在 EndPoint 中不只能够指定集群内容器的IP,还能够指定集群外的IP,咱们能够利用这个特性使用集群外部的服务。
EndPoint 方式的缺点是只能指定IP,不能使用网址,好比网址,好比RDS的地址,这种状况下只能使用ExternalName来解决。
apiVersion: v1
kind: Service
metadata:
name: mysql-production
spec:
ports:
- port: 3306
---
kind: Endpoints
apiVersion: v1
metadata:
name: mysql-production
namespace: default
subsets:
- addresses:
- ip: 192.168.1.25
ports:
- port: 3306
总结
本文介绍了集群内部访问外部服务的两种方法,ExternalName 类型的服务适用于外部服务使用域名的方式,缺点是不能指定端口;而EndPoint的方式适合于外部服务是IP的状况,可是能够指定端口。根据须要使用吧!
下面是如何给一个pod分配cpu和内存
在Kubernetes系统上,l个单位的CPU至关于虚拟机上的l颗虚拟CPU(vCPU)或物理机上的一个超线程(Hyperthread,或称为一个逻辑CPU),它支持分数计量方式,一个核心(1core)至关于1000个微核心(millicores),所以500m至关因而0.5个核心
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
spec:
containers:
- name: memory-demo-ctr
image: vish/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
args:
- -mem-total
- 150Mi
- -mem-alloc-size
- 10Mi
- -mem-alloc-sleep
- 1s
超出容器的内存限制报错
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
配置超出节点能力范围的内存申请,pod会一直处于pending状态
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
查看具体报错信息以下
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
若是不配置内存限制
若是不给容器配置内存限制,那下面的任意一种状况可能会出现:
容器使用内存资源没有上限,容器可使用当前节点上全部可用的内存资源。
容器所运行的命名空间有默认内存限制,容器会自动继承默认的限制。
内存申请和限制的缘由
经过配置容器的内存申请和限制,你能够更加有效充分的使用集群里内存资源。配置较少的内存申请, 可让Pod跟任意被调度。设置超过内存申请的限制,能够达到如下效果:
Pod能够在负载高峰时更加充分利用内存。
能够将Pod的内存使用限制在比较合理的范围。
Always 老是拉取镜像
IfNotPresent 本地有则使用本地镜像,不拉取
Never 只使用本地镜像,从不拉取,即便本地没有
若是省略imagePullPolicy 镜像tag为 :latest 策略为always ,不然 策略为 IfNotPresent
对于Pod的健康状态检测,kubernetes提供了两类探针(Probe)来执行对Pod的健康状态检测:
每类探针都支持三种探测方法:
探针探测的结果有如下三者之一: