Kubernetes 支持兩種方式建立資源:node
(1)用 kubectl 命令直接建立,好比:linux
kubectl run httpd-app --image=reg.yunwei.com/learn/httpd:latest --replicas=2
在命令行中經過參數指定資源的屬性。git
(2)經過配置文件和 kubectl apply
建立,要完成前面一樣的工做,可執行命令:vim
kubectl apply -f httpd.yamlapi
httpd.yaml 的內容爲:安全
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: httpd-deployment spec: replicas: 2 template: metadata: labels: name: httpd spec: containers: - name: httpd-app image: reg.yunwei.com/learn/httpd:latest
資源的屬性寫在配置文件中,文件格式爲YAML。bash
[root@ren7 yaml]# kubectl get pod No resources found. [root@ren7 yaml]# kubectl apply -f httpd.yaml deployment.extensions/httpd-deployment created [root@ren7 yaml]# kubectl get pod NAME READY STATUS RESTARTS AGE httpd-deployment-584d5b54cf-g5rqg 1/1 Running 0 5s httpd-deployment-584d5b54cf-tpndt 1/1 Running 0 5s
基於命令的方式:app
(1)簡單直觀快捷,上手快。ide
(2)適合臨時測試或實驗。測試
基於配置文件的方式:
(1)配置文件描述了what,即應用最終要達到的狀態。
(2)配置文件提供了建立資源的模板,可以重複部署。
(3)能夠像管理代碼同樣管理部署。
(4)適合正式的、跨環境的、規模化部署。
(5)這種方式要求熟悉配置文件的語法,有必定的難度。
kubectl apply
不但可以建立 Kubernetes 資源,也能對資源進行更新,很是方便。不過 Kubernetes 還提供了幾個相似的命令,例如 kubectl create
、kubectl replace
、kubectl edit
和 kubectl patch
。
爲避免形成沒必要要的困擾,咱們會盡可能只使用 kubectl apply
,
此命令已經可以應對超過 90% 的場景,事半功倍。
一、deployment 的配置格式
① apiVersion 是當前配置格式的版本。
先執行kubectl api-resources找到全部的資源,再執行命令 kubectl explain deploy 便可獲取到版本和類型信息
[root@ren7 yaml]# kubectl explain deploy
KIND: Deployment
VERSION: extensions/v1beta1
② kind 是要建立的資源類型,這裏是 Deployment。
③ metadata 是該資源的元數據,name 是必需的元數據項。
④ spec 部分是該 Deployment 的規格說明。
⑤ replicas 指明副本數量,默認爲 1。
⑥ template 定義 Pod 的模板,這是配置文件的重要部分。
⑦ metadata 定義 Pod 的元數據,至少要定義一個 label。label 的 key 和 value 能夠任意指定。
⑧ spec 描述 Pod 的規格,此部分定義 Pod 中每個容器的屬性,name 和 image 是必需的。
注意:最後name前面加個橫線是由於container後面是一個列表
[root@ren7 yaml]# kubectl explain deployments.spec.template.spec KIND: Deployment VERSION: extensions/v1beta1 RESOURCE: spec <Object> DESCRIPTION: Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status PodSpec is a description of a pod. FIELDS: containers <[]Object> -required- #列表,後面有橫槓 List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. dnsConfig <Object> #僅僅是一個對象 Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. volumes <[]Object> List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes
查看上文經過kubectl apply建立的pod的各類資源:
[root@ren7 yaml]# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE httpd-deployment 2/2 2 2 45m [root@ren7 yaml]# kubectl get replicaset NAME DESIRED CURRENT READY AGE httpd-deployment-584d5b54cf 2 2 2 46m [root@ren7 yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-deployment-584d5b54cf-g5rqg 1/1 Running 0 46m 172.20.72.140 192.168.11.5 <none> <none> httpd-deployment-584d5b54cf-tpndt 1/1 Running 0 46m 172.20.33.74 192.168.11.6 <none> <none>
Deployment、ReplicaSet、Pod 都已經就緒。若是要刪除這些資源,執行 kubectl delete deployment httpd-deployment 或者 kubectl delete -f httpd.yaml (編寫的httpd.yaml文件不會被刪除)。
[root@ren7 yaml]# kubectl delete -f httpd.yaml deployment.extensions "httpd-deployment" deleted [root@ren7 yaml]# kubectl get pod -o wide No resources found.
二、運行yaml配置文件
執行以下命令:
kubectl apply -f httpd.yaml #運行pod kubectl delete -f http.yaml #刪除pod
(1)伸縮(Scale Up/Down):是指在線增長或減小 Pod 的副本數。直接改寫yaml配置文件的 replicas 參數便可
出於安全考慮,默認配置下 Kubernetes 不會將 Pod 調度到 Master 節點。
(2)節點故障(Failover):若其中一個node故障, Kubernetes 會檢查到 k8s-node3 不可用,將 k8s-node1 上的 Pod 標記爲 Terminating 狀態,並在 k8s-node2 上新建立兩個 Pod,維持總副本數爲原指定副本數 3。
當 k8s-node2 恢復後,Terminating 的 Pod 會被刪除,不過已經運行的 Pod 不會從新調度回 k8s-node2。
(3)用 label 控制 Pod 的位置: 默認配置下,Scheduler 會將 Pod 調度到全部可用的 Node。不過有些狀況咱們但願將 Pod 部署到指定的 Node,好比將有大量磁盤 I/O 的 Pod 部署到配置了 SSD 的 Node;或者 Pod 須要 GPU,須要運行在配置了 GPU 的節點上。
Kubernetes 是經過 label 來實現這個功能的。label 是 key-value 對,各類資源均可以設置 label,靈活添加各類自定義屬性。好比執行以下命令標註 k8s-node3 是配置了 SSD 的節點。
[root@ren8 ~]# kubectl label node 192.168.11.5 disktype=ssd node/192.168.11.5 labeled
而後經過:kubectl get node --show-labels 查看節點的label。
[root@ren8 ~]# kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS 192.168.11.5 Ready <none> 46h v1.14.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=192.168.11.5,kubernetes.io/os=linux 192.168.11.6 Ready <none> 46h v1.14.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192.168.11.6,kubernetes.io/os=linux 192.168.11.7 Ready,SchedulingDisabled <none> 46h v1.14.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192.168.11.7,kubernetes.io/os=linux
disktype=ssd 已經成功添加到 k8s-node3,除了 disktype,Node 還有幾個 Kubernetes 本身維護的 label。
有了 disktype 這個自定義 label,接下來就能夠指定將 Pod 部署到 k8s-node3。編輯 httpd.yaml:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: httpd-deployment spec: replicas: 2 template: metadata: labels: name: httpd spec: containers: - name: httpd-app image: reg.yunwei.com/learn/httpd:latest nodeSelector: disktype: ssd
在 Pod 模板的 spec 裏經過 nodeSelector 指定將此 Pod 部署到具備:label disktype=ssd 的 Node 上。
部署 Deployment 並查看 Pod 的運行節點:
[root@ren7 yaml]# kubectl apply -f . deployment.extensions/httpd-deployment created [root@ren7 yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-deployment-55d95f5b6f-5pfcw 1/1 Running 0 18s 172.20.72.142 192.168.11.5 <none> <none> httpd-deployment-55d95f5b6f-hcpg7 1/1 Running 0 18s 172.20.72.141 192.168.11.5 <none> <none>
所有2個副本都運行在k8s-node3節點上,符合咱們的預期。
要刪除 label disktype,執行以下命令:kubectl label node k8s-node3 disktype- 即刪除。不過此時已建立的pod並不會從新部署,依然在 k8s-node3上運行。
[root@ren7 yaml]# kubectl label node 192.168.11.5 disktype- node/192.168.11.5 labeled [root@ren7 yaml]# kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS 192.168.11.5 Ready <none> 46h v1.14.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192.168.11.5,kubernetes.io/os=linux 192.168.11.6 Ready <none> 46h v1.14.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192.168.11.6,kubernetes.io/os=linux 192.168.11.7 Ready,SchedulingDisabled <none> 46h v1.14.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192.168.11.7,kubernetes.io/os=linux [root@ren7 yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-deployment-55d95f5b6f-5pfcw 1/1 Running 0 5m8s 172.20.72.142 192.168.11.5 <none> <none> httpd-deployment-55d95f5b6f-hcpg7 1/1 Running 0 5m8s 172.20.72.141 192.168.11.5 <none> <none>
除非在 httpd.yaml文件中刪除nodeSelector設置,而後經過kubectl apply從新部署。kubernetes 會刪除以前的pod並調度和運行新的pod。
[root@ren7 yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-deployment-55d95f5b6f-5pfcw 1/1 Running 0 5m8s 172.20.72.142 192.168.11.5 <none> <none> httpd-deployment-55d95f5b6f-hcpg7 1/1 Running 0 5m8s 172.20.72.141 192.168.11.5 <none> <none> [root@ren7 yaml]# vim httpd.yaml #刪除(或註釋)nodeSelector設置 [root@ren7 yaml]# kubectl apply -f . #從新部署pod deployment.extensions/httpd-deployment configured [root@ren7 yaml]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpd-deployment-584d5b54cf-c9d6r 1/1 Running 0 17s 172.20.33.75 192.168.11.6 <none> <none> httpd-deployment-584d5b54cf-vltn8 1/1 Running 0 17s 172.20.72.143 192.168.11.5 <none> <none>
Deployment 部署的副本 Pod 會分佈在各個 Node 上,每一個 Node 均可能運行好幾個副本。DaemonSet 的不一樣之處在於:每一個 Node 上最多隻能運行一個副本。
(2)在每一個節點上運行日誌收集 Daemon,好比 flunentd 或 logstash。
(3)在每一個節點上運行監控 Daemon,好比 Prometheus Node Exporter 或 collectd。
[root@ren8 ~]# kubectl get daemonset -n kube-system NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE calico-node 3 3 3 3 3 <none> 46h
DaemonSet calico-node分別負責在每一個節點上運行 calico-node 組件。
[root@ren8 ~]# kubectl get pod -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES calico-kube-controllers-7dd985b95c-s8q64 1/1 Running 1 46h 192.168.11.6 192.168.11.6 <none> <none> calico-node-fwrnb 2/2 Running 6 46h 192.168.11.7 192.168.11.7 <none> <none> calico-node-tpbgh 2/2 Running 2 46h 192.168.11.6 192.168.11.6 <none> <none> calico-node-z7wxb 2/2 Running 2 46h 192.168.11.5 192.168.11.5 <none> <none> coredns-64d5b756bc-bcmqd 1/1 Running 1 46h 172.20.33.69 192.168.11.6 <none> <none> coredns-64d5b756bc-bmj2v 1/1 Running 2 46h 172.20.72.136 192.168.11.5 <none> <none> heapster-7f48ff4cd9-6zmqr 1/1 Running 1 25h 172.20.33.71 192.168.11.6 <none> <none> kubernetes-dashboard-6f75588d94-g6vcr 1/1 Running 1 46h 172.20.72.137 192.168.11.5 <none> <none> monitoring-grafana-6c76875cb-8zjrv 1/1 Running 1 25h 172.20.33.70 192.168.11.6 <none> <none> monitoring-influxdb-66dbc76bf9-9lsqk 1/1 Running 1 25h 172.20.72.135 192.168.11.5 <none> <none>
由於 calico-node 屬於系統組件,須要在命令行中經過 --namespace=kube-system 指定 namespace kube-system。若是不指定則只返回默認 namespace default 中的資源。
[root@ren8 templates]# pwd /etc/ansible/roles/calico/templates [root@ren8 templates]# vim calico.yaml.j2 # This manifest installs the calico/node container, as well # as the Calico CNI plugins and network config on # each master and worker node in a Kubernetes cluster. kind: DaemonSet apiVersion: extensions/v1beta1 metadata: name: calico-node namespace: kube-system labels: k8s-app: calico-node spec: selector: matchLabels: k8s-app: calico-node updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 template: metadata: labels: k8s-app: calico-node annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: hostNetwork: true tolerations: