k8s 的基本概念
Kubernetes是一個可以移植、可擴展的開源平臺,使用 聲明式的配置 并依據配置信息自動地執行容器化應用程序的管理。在所有的容器編排工具中(類似的還有 docker swarm / mesos等),Kubernetes的生態系統更大、增長更快,有更多的支持、服務和工具可供用戶選擇。
Kubernetes的名字起源于希臘語,含義是 舵手
、領航員
、向導
。Google于2014年將Brog系統開源為Kubernetes。Kubernetes構建在Google Brog 十五年運行大規模分布式系統的經驗 (opens new window)基礎之上,并結合了開源社區最好的想法和實踐。
Master組件
-
Kube-apiserver: 集群的控制中心,各個模塊直接的通信和信息傳輸都要經過我們kube-apiserver,它同時負責集群的管理,資源的分配,整個集群的安全機制入口。
-
controller-manager: 集群的狀態管理器,保證pod或其他資源都達到期望值。也就是和Kube-apiserver進行通信,在需要的時候創建更新或者刪除資源。
-
scheduler調度中心,它會根據指定條件去做篩選,選擇一個或者一批最佳的節點然后部署我們的pod。
-
Etcd 鍵值數據庫,保存一些集群的信息,一般生成環境建議是三個節點(奇數臺)
Node組件
-
Kubelet:負責監聽節點上pod的狀態,同時負責上報節點和節點上面pod的狀態,負責與master節點通信,并且管理pod。
-
Kube-proxy:負責pod之間通信和負載均衡,將制定的流量分發到后端正確的機器上。查看kube-proxy工作模式
netstat -lntp | grep kube-proxy
curl 127.0.0.1:10249/proxyMode
iptables:監聽Master節點增加和刪除service以及endpoint的消息,對于每一個service它會用iptables規則,將servcie的cluster代理到pod上面
ipvs:監聽Master節點增加和刪除service以及endpoint的消息,調用ipvs規則映射到pod上面。
calico:網絡插件,給每個pod生成唯一的ip地址,并把每個節點當做一個路由。
coredns:用于service解析,可以讓pod把service名稱解析成ip地址,然后通過service的ip地址鏈接到對應的應用上。
docker:容器引擎,負責容器管理。
pod
k8s最小管理單元、
kubectl get pod
一個pod它是一組或者一個或者多個容器組成。每個pod還包含了一個pause容器,pause容器就是pod的父容器,主要負責僵尸進程的回收管理,通過pause容器可以使同一個pod里面的多個容器實現共享存儲網絡PID ipc等
管理pod:pod容器可以進行替換,不一定是哪一種。
定義一個pod
apiVersion: v1 # 必選,API的版本號
kind: Pod # 必選,類型Pod
metadata: # 必選,元數據name: nginx # 必選,符合RFC 1035規范的Pod名稱# namespace: default # 可選,Pod所在的命名空間,不指定默認為default,可以使用-n 指定namespace labels: # 可選,標簽選擇器,一般用于過濾和區分Podapp: nginxrole: frontend # 可以寫多個annotations: # 可選,注釋列表,可以寫多個app: nginx
spec: # 必選,用于定義容器的詳細信息
# initContainers: # 初始化容器,在容器啟動之前執行的一些初始化操作
# - command:
# - sh
# - -c
# - echo "I am InitContainer for init some configuration"
# image: busybox
# imagePullPolicy: IfNotPresent
# name: init-containercontainers: # 必選,容器列表- name: nginx # 必選,符合RFC 1035規范的容器名稱image: nginx:1.8 # 必選,容器所用的鏡像的地址imagePullPolicy: IfNotPresent # 可選,鏡像拉取策略, IfNotPresent: 如果宿主機有這個鏡像,那就不需要拉取了. Always: 總是拉取, Never: 不管是否存儲都不拉去command: # 可選,容器啟動執行的命令 ENTRYPOINT, arg --> cmd- nginx - -g- "daemon off;"workingDir: /usr/share/nginx/html # 可選,容器的工作目錄
# volumeMounts: # 可選,存儲卷配置,可以配置多個
# - name: webroot # 存儲卷名稱
# mountPath: /usr/share/nginx/html # 掛載目錄
# readOnly: true # 只讀ports: # 可選,容器需要暴露的端口號列表- name: http # 端口名稱containerPort: 80 # 端口號protocol: TCP # 端口協議,默認TCPenv: # 可選,環境變量配置列表- name: TZ # 變量名value: Asia/Shanghai # 變量的值- name: LANGvalue: en_US.utf8
# resources: # 可選,資源限制和資源請求限制
# limits: # 最大限制設置
# cpu: 1000m
# memory: 1024Mi
# requests: # 啟動所需的資源
# cpu: 100m
# memory: 512Mi
# startupProbe: # 可選,檢測容器內進程是否完成啟動。注意三種檢查方式同時只能使用一種。
# httpGet: # httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。
# path: /api/successStart # 檢查路徑
# port: 80
# readinessProbe: # 可選,健康檢查。注意三種檢查方式同時只能使用一種。
# httpGet: # httpGet檢測方式,生產環境建議使用httpGet實現接口級健康檢查,健康檢查由應用程序提供。
# path: / # 檢查路徑
# port: 80 # 監控端口
# livenessProbe: # 可選,健康檢查#exec: # 執行容器命令檢測方式#command: #- cat#- /health#httpGet: # httpGet檢測方式# path: /_health # 檢查路徑# port: 8080# httpHeaders: # 檢查的請求頭# - name: end-user# value: Jason
# tcpSocket: # 端口檢測方式
# port: 80
# initialDelaySeconds: 60 # 初始化時間
# timeoutSeconds: 2 # 超時時間
# periodSeconds: 5 # 檢測間隔
# successThreshold: 1 # 檢查成功為2次表示就緒
# failureThreshold: 2 # 檢測失敗1次表示未就緒
# lifecycle:
# postStart: # 容器創建完成后執行的指令, 可以是exec httpGet TCPSocket
# exec:
# command:
# - sh
# - -c
# - 'mkdir /data/ '
# preStop:
# httpGet:
# path: /
# port: 80# exec:# command:# - sh# - -c# - sleep 9restartPolicy: Always # 可選,默認為Always,容器故障或者沒有啟動成功,那就自動該容器,Onfailure: 容器以不為0的狀態終止,自動重啟該容器, Never:無論何種狀態,都不會重啟#nodeSelector: # 可選,指定Node節點# region: subnet7
# imagePullSecrets: # 可選,拉取鏡像使用的secret,可以配置多個
# - name: default-dockercfg-86258
# hostNetwork: false # 可選,是否為主機模式,如是,會占用主機端口
# volumes: # 共享存儲卷列表
# - name: webroot # 名稱,與上述對應
# emptyDir: {} # 掛載目錄
# #hostPath: # 掛載本機目錄
# # path: /etc/hosts
pod工作原理
我們很少在Kubernetes中直接創建單個Pod。這是因為Pods被設計成相對短暫的、一次性的實體。 當一個POD被創建(直接創建,或間接由控制器創建)時,它被安排在集群中的節點上運行。 在進程終止、pod對象被刪除、pod由于缺乏資源而被驅逐或節點失敗之前,POD仍然位于該節點上。
**注意:**不要將重新啟動Pod中的容器與重新啟動Pod混淆。POD不是一個進程,而是一個運行容器的環境。Pod一直存在直到被刪除為止。
pod本身無法自我修復。如果將Pod調度到發生故障的節點,或者調度操作本身失敗,則將Pod刪除;同樣,由于缺乏資源或Node維護,Pod也被刪除。Kubernetes使用稱為控制器的更高級別的抽象來處理管理相對一次性的Pod實例的工作。因此,雖然可以直接使用Pod,但在Kubernetes中使用控制器來管理Pod更為常見。
pod和控制器關系
你可以使控制器創建和管理多個pod。控制器在pod失敗的情況下可以處理副本、更新以及自動修復。例如,如果某個節點發生故障,則控制器會注意到該節點上的Pod已停止工作,并創建了一個替換Pod。調度程序將替換的Pod放置到健康的節點上。可以使用deployment、statefulset、daemonset等控制器管理pod。
pod模板介紹
控制器(如deployment、daemonset、statefulset等)是通過創建pod模板來創建和管理pod的,PodTemplate是用于創建pod的規范,并且包含在deployment、job和daemonset中。每個控制器使用自己內部的Pod模板來創建實際的Pod。PodTemplate是運行應用程序所需的任何控制器的一部分。下面的示例是一個簡單的Job的清單,包含一個podtemplate,這個是用來生成pod的模板。該Pod中的容器會打印一條消息,然后暫停。
vi job-template.yaml
apiVersion: batch/v1
kind: Job
metadata:name: hello
spec:template:# This is the pod templatespec:containers:- name: helloimage: busyboxcommand: ['sh', '-c', 'echo "Hello, Kuboard!" && sleep 3600']restartPolicy: OnFailure# The pod template ends here
修改pod template或切換到新的pod tmplate對已經存在的pod沒有影響。 POD不直接接收模板更新,而是創建一個新的POD來匹配修改后的POD模板。例如,控制器可確保正在運行的Pod與當前Pod模板匹配。如果模板已更新,則控制器必須刪除現有的Pod并根據更新的模板創建新的Pod。每個控制器都實現自己的規則來處理Pod模板的更改。在節點上,kubelet不直接觀察或管理有關Pod模板和更新的任何詳細信息。
pod 相關的文檔查看
和pod相關的api對象
kubectl explain pods
上面命令可以看到和pod相關的api對象有哪些,也就是通過資源清單yaml部署一個pod時需要哪些字段
apiVersion
apiVersion定義了此對象表示的版本化模式。服務器應將已識別的模式轉換為最新的內部值,并可能拒絕無法識別的值。更多信息參考:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
查看k8s集群支持的apiVersion有哪些,可以使用下面的命令:
kubectl api-versions
顯示如下支持apiVersion信息:
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
crd.projectcalico.org/v1
discovery.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
metrics.k8s.io/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1
kind
Kind是表示此對象表示的REST資源的字符串值。服務器可以從客戶端提交請求的端點推斷出這一點,說白了就是表示我們要創建什么資源,如deployment、statefulset、pod、service、ingress
查看更詳細信息可參考:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata
標準對象的元數據。更多信息:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec
指定容器的所需行為。更多信息:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status
最近觀察到的pod的狀態。此數據可能不是最新的。Status不需要在pod或者其他資源中定義,這個默認是存在的,更多信息:https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
怎么命令行工具創建pod?
1.通過定義資源清單yaml文件(就是以yaml結尾的文件)創建pod,在k8s的master節點操作查看定義資源清單需要哪些字段
kubectl explain pods
kubectl explain pods.apiVersion
kubectl explain pods.kind
kubectl explain pods.metadata
kubectl explain pods.speccat pod.yaml
apiVersion: v1
kind: Pod
metadata:name: webnamespace: defaultlabels:web: nginx
spec:containers:- name: nginxdemoimage: nginx:1.8imagePullPolicy: IfNotPresent
#通過kubectl apply創建一個pod
kubectl apply -f pod.yaml
#查看pod創建的情況
kubectl get pods
顯示如下:
NAME READY STATUS RESTARTS AGE
web 0/1 ContainerCreating 0 37s#查看pod的詳細信息
kubectl describe pods web# pod.yaml定義的所有資源都刪除掉
kubectl delete -f pod.yaml yaml#查看pod調度到哪個節點
kubectl get pods -o wide
顯示如下:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web 1/1 Running 0 5m30s 10.244.1.21 node1 <none> <none>#查看pod日志
kubectl logs web#查看pod里指定容器的日志
kubectl logs -c nginxdemo web#進入到剛才創建的pod,剛才創建的pod名字是web
kubectl exec -it web -- /bin/bash#假如pod里有多個容器,進入到pod里的指定容器,按如下命令:
kubectl exec -it web -c nginxdemo -- /bin/bash 我們上面創建的pod是一個自主式pod,也就是通過pod創建一個應用程序,如果pod出現故障停掉,那么我們通過pod部署的應用也就會停掉,不安全,所以還有一種pod,
還有一種控制器管理的pod,通過控制器創建pod,可以對pod的生命周期做管理,如定義pod的副本數,如果有一個pod意外停掉,那么會自動起來一個pod替代之前的pod,之后會講解pod的控制器kubectl get pods
可查看到剛才創建的pod
標簽
-
給node添加一個label標簽
kubectl label node k8s-node1 "node=node1"
-
查看label標簽
kubectl get node -l "node=node1"
- 刪除label標簽,只需要在命令行最后指定label的key名,并加一個減號就可以了。
kubectl label node k8s-node1 role-
- 將節點調度到指定Node
- 首先給對應需要調度的node打上標簽,然后創建資源清單時添加上nodeSelector屬性對應即可
kubectl label nodes k8s-node1 role=k8s-Node[root@master NetworkPolicy]# cat pod-demo-2.yaml
apiVersion: v1
kind: Pod
metadata:name: pod2labels:app: nginx
spec:containers:- name: app-2image: ikubernetes/myapp:v1
nodeSelector:node: kube-Node
重啟策略
#查看重啟策略restartPolicy怎么定義的:
kubectl explain pods.spec.restartPolicy
-
Always:只要容器掛了就重啟
-
OnFailure:只有容器狀態為錯誤的時候才重啟
-
Never:從不重啟容器
默認重啟策略就是Always
名稱空間-namespace
一、什么是命名空間
Kubernetes 支持多個虛擬集群,它們底層依賴于同一個物理集群。 這些虛擬集群被稱為命名空間。
二、何時使用多個命名空間
使用命名空間 命名空間和 DNS 并非所有對象都在命名空間中 接下來 何時使用多個命名空間
命名空間適用于存在很多跨多個團隊或項目的用戶的場景。對于只有幾到幾十個用戶的集群,根本不需要創建或考慮命名空間。當需要名稱空間提供的功能時,請開始使用它們。命名空間為名稱提供了一個范圍。資源的名稱需要在命名空間內是唯一的,但不能跨命名空間。命名空間不能相互嵌套,每個 Kubernetes
資源只能在一個命名空間中。命名空間是在多個用戶之間劃分集群資源的一種方法(通過資源配額)。
在 Kubernetes 未來版本中,相同命名空間中的對象默認將具有相同的訪問控制策略。
不需要使用多個命名空間來分隔輕微不同的資源,例如同一軟件的不同版本:使用 labels 來區分同一命名空間中的不同資源。
使用命名空間 命名空間的創建和刪除已在命名空間的管理指南文檔中進行了描述。
三、查看命名空間
您可以使用以下命令列出集群中現存的命名空間:
[root@k8s1 ~]# kubectl get namespace
NAME STATUS AGE
default Active 2d1h
kube-node-lease Active 2d1h
kube-public Active 2d1h
kube-system Active 2d1h
123456
也可以使用 ns 代替,效果與namespace 一樣
kubectl get ns
Kubernetes 會創建三個初始命名空間:
- default 沒有指明使用其它命名空間的對象所使用的默認命名空間
- kube-system Kubernetes 系統創建對象所使用的命名空間
- kube-public 這個命名空間是自動創建的,所有用戶(包括未經過身份驗證的用戶)都可以讀取它。這個命名空間主要用于集群使用,以防某些資源在整個集群中應該是可見和可讀的。這個命名空間的公共方面只是一種約定,而不是要求。
3.1 創建命名空間
[root@k8s1 ~]# kubectl create namespace orange
namespace/orange created查看命名空間
[root@k8s1 ~]# kubectl get namespace
NAME STATUS AGE
default Active 2d1h
kube-node-lease Active 2d1h
kube-public Active 2d1h
kube-system Active 2d1h
orange Active 5s
1234567891011
3.2當然也可以使用yaml來創建命名空間
[root@k8s1 namespace]# cat my-namespace.yaml
kind: Namespace #類型為Namespace
apiVersion: v1 #類型為Namespace
metadata:name: orange-test #命名空間名稱labels:name: orange-test-v1 創建命名空間
[root@k8s1 namespace]# kubectl create -f my-namespace.yaml
namespace/orange-test created查看命名空間
[root@k8s1 namespace]# kubectl get namespace
NAME STATUS AGE
default Active 2d1h
kube-node-lease Active 2d1h
kube-public Active 2d1h
kube-system Active 2d1h
orange Active 9m44s
orange-test Active 25s
3.3 pod使用命名空間
[root@k8s1 namespace]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
llxxyy/centos-pure 7.6 c21f6df29f79 About an hour ago 1.04GB
123
[root@k8s1 namespace]# cat my-pod-namespace.yaml
apiVersion: v1
kind: Pod
metadata:name: my-pod-namespace ##pod名稱namespace: orange ##命名空間名稱labels:app: bashtir: backend
spec:containers:- name: bash-containerimage: llxxyy/centos-pure:7.6 ##鏡像名稱:tagcommand: ['sh','-c','echo hello myfirstpod && sleep 3600']
[root@k8s1 namespace]# kubectl create -f my-pod-namespace.yaml
pod/my-pod-namespace created
[root@k8s1 namespace]# kubectl get pods -n=orange
NAME READY STATUS RESTARTS AGE
my-pod-namespace 1/1 Running 0 5s
3.4 刪除名稱空間
語法
kubectl delete namespaces <insert-some-namespace-name>
12
[root@k8s1 namespace]# kubectl delete namespaces orange
namespace "orange" deleted
標簽是什么
標簽是k8s特色的管理方式,便于分類管理資源對象。
一個標簽可以對應多個資源,一個資源也可以有多個標簽,它們是多對多的關系。
一個資源擁有多個標簽,可以實現不同維度的管理。
可以使用標簽選擇器來指定能使用哪些標簽。
1、標簽組成
key=value
- key:只能使用 字母 數字 _ - . (只能以字母數字開頭,不能超過63給字符)
- value: 可以為空 只能使用 字母 數字開頭
2**、定義標簽**
kubectl get pods --show-labels #查看pod所有標簽信息
kubectl get pods -l app #過濾包含app的標簽
kubectl get pods -L app #過濾包含app的標簽及顯示值
kubectl label pods pod-demo release=canary #給pod-demo增加標簽
kubectl label pods pod-demo release=stable --overwrite #修改標簽
二、標簽選擇器
給資源打上標簽后,可以使用標簽選擇器過濾指定的標簽
標簽選擇器目前有兩個:基于等值關系和基于集合關系
- 等值關系操作符:=, == , !=
#使用格式
kubectl get pods -l run=myapp
kubectl get pods -l run=myapp --show-labels
kubectl get pods -l run!=client --show-labels
- 集合關系的操作符:in,notin,exists
#使用格式
kubectl get pods -l "run in (client,myapp,alpha)" --show-labels #三個值有一個匹配上都可以
kubectl get pods -l "run notin (client,myapp,alpha)" --show-labels
1、匹配符合條件的標簽,部署pod
a、給node02節點打標簽,如果多個主機都有ssd標簽,會隨機匹配某一個
kubectl label nodes node02 disktype=ssd #給node02打上ssd標簽
kubectl get nodes --show-labels
b、修改yaml文件,增加標簽選擇器
[root@master manifests]# cat pod-with-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-with-nodeselectorlabels:env: testing
spec:containers:- name: myappimage: nginx:1.8nodeSelector:disktype: ssd
c、創建pod,驗證
kubectl create -f pod-with-nodeselector.yaml
kubectl get nodes -o wide
2、通過主機名,部署pod到指定的主機
方式一:
[root@master manifests]# cat pod-with-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-with-nodeselectorlabels:env: testing
spec:containers:- name: myappimage: ikubernetes/myapp:v1nodeSelector:kubernetes.io/hostname: node01.linux.com
方式二:使用sepc.nodeName
[root@master manifests]# cat pod-with-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-with-nodeselectorlabels:env: testing
spec:containers:- name: myappimage: ikubernetes/myapp:v1nodeName: node01
基于pod的標簽
(2)查看所有pod資源對象的標簽
kubectl get pods --show-labels
(3)查看帶有指定標簽的pod
kubectl get pods -L web1
顯示所有資源對象下web1這個標簽的標簽值
(4)kubectl get pods -l web1 --show-labels
查看擁有web1這個標簽的資源對象,并且把標簽顯示出來
(5)想修改資源的標簽,比方說想給web加上個release標簽
給資源對象打標簽要使用label命令,指定給某個類型下的某個資源打標簽,資源中的key/value可以是多個,因此在web(pod名字)這個資源下再打個標簽release,用如下命令
kubectl label pods web release=new
查看標簽是否打成功:kubectl get pods --show-labels
顯示如下,顯示如下,說明標簽達成功了;
NAME READY STATUS RESTARTS AGE LABELS
web 1/1 Running 1 21