pod與容器
一個pod是一組緊密相關的容器,它們總是一起執行在同一個節點上,以及同一個LInux名稱空間中。
每個pod擁有自己的ip,包含若干個容器。pod分佈在不同的節點上。
為什麼需要pod
為什麼需要pod,而不是直接使用容器:
因為容器被設計為只執行一個程式,由於不能夠將多個程式聚集在一個單獨的容器中,就需要另一種結構將容器繫結在一起,並將它們作為一個單元管理,這就是pod的根本原理。
pod中容器的隔離共享
在同一個pod中,多個容器有些資源是共享的,有些是隔離的。
同一個pod中的所有容器都執行在相同的network、UTS、IPC空間下。所以它們共享網路介面、主機名,可以通過IPC互相通訊。
同一個pod中的所有容器的檔案系統是隔離的。
何時在pod中使用多個容器
- 它們是否是一個整體?
- 它們是否需要在一起執行?
- 它們是否要一起擴縮容?
執行pod
pod和其他Kubernetes資源通常都是通過向Kubernetes REST API提供JSON或者YAML檔案來建立的。
我們使用nginx映象建立一個pod。
nginx.yaml
apiVersion: v1 # API版本
kind: Pod # 資源型別
metadata:
name: nginx # pod的名稱
spec:
containers:
- image: nginx # 建立容器所用的映象地址
name: nginx # 容器名稱
ports:
- containerPort: 80 # 應用監聽的埠
protocol: TCP
這裡只給出了一個簡單的描述檔案,大部分欄位沒有給出。
kubectl explain
kubectl explain相當於一個文件,可以檢視每個API物件支援哪些欄位。
-> [root@kube0.vm] [~] k explain pod
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is
created by clients and scheduled onto hosts.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
.................
kubectl create
使用kubectl create
建立pod
-> [root@kube0.vm] [~] k create -f nginx.yaml
pod/nginx created
kubectl get
使用kubectl get
檢視,指定-o wide
檢視更多欄位
-> [root@kube0.vm] [~] k get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 11s
-> [root@kube0.vm] [~] k get -o wide pods
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 22s 10.244.2.6 kube2.vm <none> <none>
完整定義
使用kubectl get -o yaml
或者kubectl get -o json
檢視pod的完整定義。這個定義包含以下三大部分:
- metadata:包括名稱、名稱空間、標籤和關於該pod的其他資訊
- spec:包含pod內容的實際說明,如容器、卷等
- status:包含執行中pod的當前資訊,如pod IP、宿主機IP、每個容器的描述和狀態
-> [root@kube0.vm] [~] k get -o yaml pod/nginx
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-05-20T00:32:43Z"
name: nginx
namespace: default
resourceVersion: "109529"
selfLink: /api/v1/namespaces/default/pods/nginx
uid: a2b83142-9f17-4cfe-a9ac-04f57de82053
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-vlqvz
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: kube2.vm
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-vlqvz
secret:
defaultMode: 420
secretName: default-token-vlqvz
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2020-05-20T02:46:50Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2020-05-20T02:46:57Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2020-05-20T02:46:57Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2020-05-20T00:32:43Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://b63c67379def88a5253e8da543655552185f14e6eb962926d65ec74c5a7ab6f7
image: nginx:latest
imageID: docker-pullable://nginx@sha256:30dfa439718a17baafefadf16c5e7c9d0a1cde97b4fd84f63b69e13513be7097
lastState: {}
name: nginx
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2020-05-20T02:46:57Z"
hostIP: 192.168.199.212
phase: Running
podIP: 10.244.2.6
podIPs:
- ip: 10.244.2.6
qosClass: BestEffort
startTime: "2020-05-20T02:46:50Z"
kubectl logs
kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER] [options]
使用kubectl logs
可以檢視pod中的日誌。如果pod中有多個容器,可以使用-c <container>
指定容器。比如:
-> [root@kube0.vm] [~] k logs nginx -c nginx -f
kubectl port-forward
kubectl port-forward TYPE/NAME [options] [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]
pod已經執行了,那如何向叢集中的pod發出請求呢。我們通過kubectl port-forward
命令,將本地埠對映到指定pod的埠上。
- 視窗1:執行kubectl port-forward
-> [root@kube0.vm] [~] k port-forward nginx 8000:80
Forwarding from 127.0.0.1:8000 -> 80
Forwarding from [::1]:8000 -> 80
Handling connection for 8000 # curl請求發出後出現
- 視窗2:執行kubectl logs
-> [root@kube0.vm] [~] k logs nginx -f
127.0.0.1 - - [20/May/2020:03:19:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-" # curl請求發出後出現
- 視窗3:curl發出請求
-> [root@kube0.vm] [~] curl http://localhost:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
........
標籤
通俗的講,標籤就是用於將Pod和其他Kubernetes資源進行分類,每個資源都可以有多個標籤
標籤是可以附加到資源上的鍵值對,用以選擇具有該標籤的資源(通過標籤選擇器完成)。
nginx-labels.yaml
建立一個帶有標籤的描述檔案
-> [root@kube0.vm] [~] cat nginx-labels.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-labels
labels: # 新增了兩個標籤
env: prod
app: order
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
protocol: TCP
檢視標籤
使用--show-labels
檢視標籤,po是pod的簡寫
-> [root@kube0.vm] [~] k create -f nginx-labels.yaml
pod/nginx-labels created
-> [root@kube0.vm] [~] k get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 0/1 ContainerCreating 0 3s app=order,env=prod
使用-L
檢視指定標籤,並且單獨成列。
-> [root@kube0.vm] [~] k get po -L app,env
NAME READY STATUS RESTARTS AGE APP ENV
nginx-labels 1/1 Running 0 4m13s order prod
kubectl label
多個標籤以空格分隔
新增
-> [root@kube0.vm] [~] k label po nginx-labels test=123
pod/nginx-labels labeled
-> [root@kube0.vm] [~] k get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 6m23s app=order,env=prod,test=123
修改
修改已存在的標籤,需要指定--overwrite
選項
-> [root@kube0.vm] [~] k label po nginx-labels test=456 --overwrite
pod/nginx-labels labeled
-> [root@kube0.vm] [~] k get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 7m24s app=order,env=prod,test=456
刪除
-> [root@kube0.vm] [~] k label po nginx-labels test-
pod/nginx-labels labeled
-> [root@kube0.vm] [~] k get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 8m8s app=order,env=prod
標籤選擇器
標籤選擇器可以使我們獲取具有特定標籤的pod子集。規則通過-l
選項指定,多個用逗號分隔。
選擇規則
- key:選擇存在標籤key的
- !key:選擇不存在標籤key的
- key=value:key存在並且值等於value
- key!= value:選擇"key=value"的補集。也就存在key並且不等value的,或者不存在key的。
- key in (value1,value2):key存在且值為value1或者value2
- key notin (value1,value2):key存在且值不為value1和value2
實操
準備幾個不同label的pod:
-> [root@kube0.vm] [~] k get po --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 40m app=order,env=prod
nginx-labels-1 1/1 Running 0 9m42s env=debug
nginx-labels-2 1/1 Running 0 8m8s app=user,env=dev
app
-> [root@kube0.vm] [~] k get po --show-labels -l app
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 50m app=order,env=prod
nginx-labels-2 1/1 Running 0 18m app=user,env=dev
!app
-> [root@kube0.vm] [~] k get po --show-labels -l '!app'
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels-1 1/1 Running 0 20m env=debug
app=order
-> [root@kube0.vm] [~] k get po --show-labels -l app=order
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 77m app=order,env=prod
app!=order
-> [root@kube0.vm] [~] k get po --show-labels -l app!=order
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels-1 1/1 Running 0 46m env=debug
nginx-labels-2 1/1 Running 0 45m app=user,env=dev
env in (dev,prod)
-> [root@kube0.vm] [~] k get po --show-labels -l 'env in (dev,prod)'
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels 1/1 Running 0 78m app=order,env=prod
nginx-labels-2 1/1 Running 0 46m app=user,env=dev
env notin (prod)
-> [root@kube0.vm] [~] k get po --show-labels -l 'env notin (prod)'
NAME READY STATUS RESTARTS AGE LABELS
nginx-labels-1 1/1 Running 0 48m env=debug
nginx-labels-2 1/1 Running 0 46m app=user,env=dev
使用標籤選擇器約束pod排程
其核心思想是,為工作節點(node)打上標籤,比如地區、機房、CPU密集、IO密集等。然後在建立pod的描述檔案時指定對應標籤,排程器就會將pod排程到符合標籤選擇器規則的工作節點上。
現在假設一個場景:需要將新建的pod排程到IO密集的工作節點上。
給node打標籤
-> [root@kube0.vm] [~] k label node kube1.vm io=true
node/kube1.vm labeled
-> [root@kube0.vm] [~] k get node -L io
NAME STATUS ROLES AGE VERSION IO
kube0.vm Ready master 19h v1.17.3
kube1.vm Ready <none> 19h v1.17.3 true
kube2.vm Ready <none> 19h v1.17.3
nginx-io.yaml
帶有選擇器的yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-io
spec:
nodeSelector: # 選擇器
io: "true"
containers:
- image: nginx
name: nginx
建立pod,檢視結果確實是執行在kube1.vm上。
-> [root@kube0.vm] [~] k create -f nginx-io.yaml
pod/nginx-io created
-> [root@kube0.vm] [~] k get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-io 1/1 Running 0 42s 10.244.1.7 kube1.vm <none> <none>
註解
註解也是鍵值對,與標籤類似,但註解並不用於標識和選擇物件。
註解主要為Pod和其他API物件新增說明,以便每個使用叢集的人可以快速查詢與物件有關的資訊。
kubectl annotate
使用kubectl annotate
為pod新增註解,同樣修改已存在的註解需要指定--overwrite
-> [root@kube0.vm] [~] k annotate po nginx-io my.com/someannotation="123"
pod/nginx-io annotated
檢視
-> [root@kube0.vm] [~] k describe po nginx-io
..........
Annotations: my.com/someannotation: 123
..........
名稱空間
簡單講,名稱空間為Pod等資源提供了作用域,在不同名稱空間內的資源名稱可以相同。
我們之前一致使用的是預設名稱空間:default
,之前的 nginx-xxx 這些pod都位於這個名稱空間。
檢視名稱空間
-> [root@kube0.vm] [~] k get ns #ns是namespace縮寫
NAME STATUS AGE
default Active 21h
kube-node-lease Active 21h
kube-public Active 21h
kube-system Active 21h
kubectl create namespace
使用kubectl create
建立一個namespace,當然也可以寫一個描述檔案建立(麻煩了點)。
-> [root@kube0.vm] [~] k create ns test
namespace/test created
-> [root@kube0.vm] [~] k get ns -o wide
NAME STATUS AGE
........
test Active 94s
為資源指定名稱空間
可以在描述檔案的metadata
下新增一個欄位namespace: test
,或者在命令列的時候指定kubectl create -f xxx.yaml -n test
。
名稱空間的誤解
首先要明確的是:名稱空間並不提供對正在執行的物件的任何隔離。
舉個例子:兩個pod並不會因為在不同的名稱空間而無法進行網路通訊,是否可以通訊不取決於名稱空間,而取決於網路解決方案。
kubectl delete
按名字刪除pod
k delete po nginx-io
使用標籤選擇器刪除
k delete po -l app
刪除所有pod
k delete po --all
刪除名稱空間
k delete ns test
刪除名稱空間(幾乎)所有資源
第一個 all 表示當前名稱空間所有資源型別,第二個 --all 表示所有資源例項。
k delete all --all
小結
- 如何決定多個容器是否應該放在一個pod
- 通過提交描述檔案建立API物件
- 使用標籤組織API物件
- 通過標籤選擇器排程pod
- 名稱空間使不同團隊很方便的使用同一個叢集
- 一些命令:create、get、delete、label、annotate、port-forward、describe、logs、explain