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的健康狀態檢測:
每類探針都支持三種探測方法:
探針探測的結果有如下三者之一: