W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
kubectl
?去運行一些標(biāo)準(zhǔn)調(diào)試步驟。與之前的例子類似,我們使用一個 Deployment 來創(chuàng)建兩個 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80
使用如下命令創(chuàng)建 Deployment:
kubectl apply -f https://k8s.io/examples/application/nginx-with-request.yaml
deployment.apps/nginx-deployment created
使用如下命令查看 Pod 狀態(tài):
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-67d4bdd6f5-cx2nz 1/1 Running 0 13s
nginx-deployment-67d4bdd6f5-w6kd7 1/1 Running 0 13s
我們可以使用 ?kubectl describe pod
? 命令來查詢每個 Pod 的更多信息,比如:
kubectl describe pod nginx-deployment-67d4bdd6f5-w6kd7
Name: nginx-deployment-67d4bdd6f5-w6kd7
Namespace: default
Priority: 0
Node: kube-worker-1/192.168.0.113
Start Time: Thu, 17 Feb 2022 16:51:01 -0500
Labels: app=nginx
pod-template-hash=67d4bdd6f5
Annotations: <none>
Status: Running
IP: 10.88.0.3
IPs:
IP: 10.88.0.3
IP: 2001:db8::1
Controlled By: ReplicaSet/nginx-deployment-67d4bdd6f5
Containers:
nginx:
Container ID: containerd://5403af59a2b46ee5a23fb0ae4b1e077f7ca5c5fb7af16e1ab21c00e0e616462a
Image: nginx
Image ID: docker.io/library/nginx@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 17 Feb 2022 16:51:05 -0500
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 128Mi
Requests:
cpu: 500m
memory: 128Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-bgsgp (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-bgsgp:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 34s default-scheduler Successfully assigned default/nginx-deployment-67d4bdd6f5-w6kd7 to kube-worker-1
Normal Pulling 31s kubelet Pulling image "nginx"
Normal Pulled 30s kubelet Successfully pulled image "nginx" in 1.146417389s
Normal Created 30s kubelet Created container nginx
Normal Started 30s kubelet Started container nginx
在這里,你可以看到有關(guān)容器和 Pod 的配置信息(標(biāo)簽、資源需求等), 以及有關(guān)容器和 Pod 的狀態(tài)信息(狀態(tài)、就緒、重啟計數(shù)、事件等) 。
容器狀態(tài)是 Waiting、Running 和 Terminated 之一。 根據(jù)狀態(tài)的不同,還有對應(yīng)的額外的信息 —— 在這里你可以看到, 對于處于運行狀態(tài)的容器,系統(tǒng)會告訴你容器的啟動時間。
Ready 指示是否通過了最后一個就緒態(tài)探測。 (在本例中,容器沒有配置就緒態(tài)探測;如果沒有配置就緒態(tài)探測,則假定容器已經(jīng)就緒。)
Restart Count 告訴你容器已重啟的次數(shù); 這些信息對于定位配置了 “Always” 重啟策略的容器持續(xù)崩潰問題非常有用。
目前,唯一與 Pod 有關(guān)的狀態(tài)是 Ready 狀況,該狀況表明 Pod 能夠為請求提供服務(wù), 并且應(yīng)該添加到相應(yīng)服務(wù)的負(fù)載均衡池中。
最后,你還可以看到與 Pod 相關(guān)的近期事件。 系統(tǒng)通過指示第一次和最后一次看到事件以及看到該事件的次數(shù)來壓縮多個相同的事件。 “From” 標(biāo)明記錄事件的組件, “SubobjectPath” 告訴你引用了哪個對象(例如 Pod 中的容器), “Reason” 和 “Message” 告訴你發(fā)生了什么。
可以使用事件來調(diào)試的一個常見的場景是,你創(chuàng)建 Pod 無法被調(diào)度到任何節(jié)點。 比如,Pod 請求的資源比較多,沒有任何一個節(jié)點能夠滿足,或者它指定了一個標(biāo)簽,沒有節(jié)點可匹配。 假定我們創(chuàng)建之前的 Deployment 時指定副本數(shù)是 5(不再是 2),并且請求 600 毫核(不再是 500), 對于一個 4 個節(jié)點的集群,若每個節(jié)點只有 1 個 CPU,這時至少有一個 Pod 不能被調(diào)度。 (需要注意的是,其他集群插件 Pod,比如 fluentd、skydns 等等會在每個節(jié)點上運行, 如果我們需求 1000 毫核,將不會有 Pod 會被調(diào)度。)
kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-1006230814-6winp 1/1 Running 0 7m
nginx-deployment-1006230814-fmgu3 1/1 Running 0 7m
nginx-deployment-1370807587-6ekbw 1/1 Running 0 1m
nginx-deployment-1370807587-fg172 0/1 Pending 0 1m
nginx-deployment-1370807587-fz9sd 0/1 Pending 0 1m
為了查找 Pod nginx-deployment-1370807587-fz9sd 沒有運行的原因,我們可以使用 ?kubectl describe pod
? 命令描述 Pod,查看其事件:
kubectl describe pod nginx-deployment-1370807587-fz9sd
Name: nginx-deployment-1370807587-fz9sd
Namespace: default
Node: /
Labels: app=nginx,pod-template-hash=1370807587
Status: Pending
IP:
Controllers: ReplicaSet/nginx-deployment-1370807587
Containers:
nginx:
Image: nginx
Port: 80/TCP
QoS Tier:
memory: Guaranteed
cpu: Guaranteed
Limits:
cpu: 1
memory: 128Mi
Requests:
cpu: 1
memory: 128Mi
Environment Variables:
Volumes:
default-token-4bcbi:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-4bcbi
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 48s 7 {default-scheduler } Warning FailedScheduling pod (nginx-deployment-1370807587-fz9sd) failed to fit in any node
fit failure on node (kubernetes-node-6ta5): Node didn't have enough resource: CPU, requested: 1000, used: 1420, capacity: 2000
fit failure on node (kubernetes-node-wul5): Node didn't have enough resource: CPU, requested: 1000, used: 1100, capacity: 2000
這里你可以看到由調(diào)度器記錄的事件,它表明了 Pod 不能被調(diào)度的原因是 ?FailedScheduling
?(也可能是其他值)。 其 message 部分表明沒有任何節(jié)點擁有足夠多的資源。
要糾正這種情況,可以使用 ?kubectl scale
? 更新 Deployment,以指定 4 個或更少的副本。 (或者你可以讓 Pod 繼續(xù)保持這個狀態(tài),這是無害的。)
你在 ?kubectl describe pod
? 結(jié)尾處看到的事件都保存在 etcd 中, 并提供關(guān)于集群中正在發(fā)生的事情的高級信息。 如果需要列出所有事件,可使用命令:
kubectl get events
但是,需要注意的是,事件是區(qū)分名字空間的。 如果你對某些名字空間域的對象(比如 ?my-namespace
? 名字下的 Pod)的事件感興趣, 你需要顯式地在命令行中指定名字空間:
kubectl get events --namespace=my-namespace
查看所有 namespace 的事件,可使用 ?--all-namespaces
? 參數(shù)。
除了 ?kubectl describe pod
? 以外,另一種獲取 Pod 額外信息(除了 ?kubectl get pod
?)的方法 是給 ?kubectl get pod
? 增加 ?-o yaml
? 輸出格式參數(shù)。 該命令將以 YAML 格式為你提供比 ?kubectl describe pod
? 更多的信息 —— 實際上是系統(tǒng)擁有的關(guān)于 Pod 的所有信息。 在這里,你將看到注解(沒有標(biāo)簽限制的鍵值元數(shù)據(jù),由 Kubernetes 系統(tǒng)組件在內(nèi)部使用)、 重啟策略、端口和卷等。
kubectl get pod nginx-deployment-1006230814-6winp -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2022-02-17T21:51:01Z"
generateName: nginx-deployment-67d4bdd6f5-
labels:
app: nginx
pod-template-hash: 67d4bdd6f5
name: nginx-deployment-67d4bdd6f5-w6kd7
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: nginx-deployment-67d4bdd6f5
uid: 7d41dfd4-84c0-4be4-88ab-cedbe626ad82
resourceVersion: "1364"
uid: a6501da1-0447-4262-98eb-c03d4002222e
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 500m
memory: 128Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-bgsgp
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: kube-worker-1
preemptionPolicy: PreemptLowerPriority
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: kube-api-access-bgsgp
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2022-02-17T21:51:01Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2022-02-17T21:51:06Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2022-02-17T21:51:06Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2022-02-17T21:51:01Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: containerd://5403af59a2b46ee5a23fb0ae4b1e077f7ca5c5fb7af16e1ab21c00e0e616462a
image: docker.io/library/nginx:latest
imageID: docker.io/library/nginx@sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767
lastState: {}
name: nginx
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2022-02-17T21:51:05Z"
hostIP: 192.168.0.113
phase: Running
podIP: 10.88.0.3
podIPs:
- ip: 10.88.0.3
- ip: 2001:db8::1
qosClass: Guaranteed
startTime: "2022-02-17T21:51:01Z"
首先,查看受到影響的容器的日志:
kubectl logs ${POD_NAME} ${CONTAINER_NAME}
如果你的容器之前崩潰過,你可以通過下面命令訪問之前容器的崩潰日志:
kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}
如果 容器鏡像 包含調(diào)試程序, 比如從 Linux 和 Windows 操作系統(tǒng)基礎(chǔ)鏡像構(gòu)建的鏡像,你可以使用 ?kubectl exec
? 命令 在特定的容器中運行一些命令:
kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}
Note: ?
-c ${CONTAINER_NAME}
? 是可選擇的。如果Pod中僅包含一個容器,就可以忽略它。
例如,要查看正在運行的 Cassandra pod中的日志,可以運行:
kubectl exec cassandra -- cat /var/log/cassandra/system.log
你可以在 ?kubectl exec
? 命令后面加上 ?-i
? 和 ?-t
? 來運行一個連接到你的終端的 Shell,比如:
kubectl exec -it cassandra -- sh
FEATURE STATE: Kubernetes v1.23 [beta]
當(dāng)由于容器崩潰或容器鏡像不包含調(diào)試程序(例如無發(fā)行版鏡像等) 而導(dǎo)致 ?kubectl exec
? 無法運行時,臨時容器對于排除交互式故障很有用。
你可以使用 ?kubectl debug
? 命令來給正在運行中的 Pod 增加一個臨時容器。 首先,像示例一樣創(chuàng)建一個 pod:
kubectl run ephemeral-demo --image=k8s.gcr.io/pause:3.1 --restart=Never
Note: 本節(jié)示例中使用 ?
pause
?容器鏡像,因為它不包含調(diào)試程序,但是這個方法適用于所有容器鏡像。
如果你嘗試使用 ?kubectl exec
? 來創(chuàng)建一個 shell,你將會看到一個錯誤,因為這個容器鏡像中沒有 shell。
kubectl exec -it ephemeral-demo -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown
你可以改為使用 ?kubectl debug
? 添加調(diào)試容器。 如果你指定 ?-i
? 或者 ?--interactive
? 參數(shù),?kubectl
?將自動掛接到臨時容器的控制臺。
kubectl debug -it ephemeral-demo --image=busybox:1.28 --target=ephemeral-demo
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #
此命令添加一個新的 busybox 容器并將其掛接到該容器。?--target
? 參數(shù)指定另一個容器的進(jìn)程命名空間。 這是必需的,因為 ?kubectl run
? 不能在它創(chuàng)建的pod中啟用 共享進(jìn)程命名空間。
Note: 容器運行時必須支持 ?
--target
? 參數(shù)。 如果不支持,則臨時容器可能不會啟動,或者可能使用隔離的進(jìn)程命名空間啟動, 以便 ?ps
?不顯示其他容器內(nèi)的進(jìn)程。
你可以使用 ?kubectl describe
? 查看新創(chuàng)建的臨時容器的狀態(tài):
kubectl describe pod ephemeral-demo
...
Ephemeral Containers:
debugger-8xzrl:
Container ID: docker://b888f9adfd15bd5739fefaa39e1df4dd3c617b9902082b1cfdc29c4028ffb2eb
Image: busybox
Image ID: docker-pullable://busybox@sha256:1828edd60c5efd34b2bf5dd3282ec0cc04d47b2ff9caa0b6d4f07a21d1c08084
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 12 Feb 2020 14:25:42 +0100
Ready: False
Restart Count: 0
Environment: <none>
Mounts: <none>
...
使用 ?kubectl delete
? 來移除已經(jīng)結(jié)束掉的 Pod:
kubectl delete pod ephemeral-demo
有些時候 Pod 的配置參數(shù)使得在某些情況下很難執(zhí)行故障排查。 例如,在容器鏡像中不包含 shell 或者你的應(yīng)用程序在啟動時崩潰的情況下, 就不能通過運行 ?kubectl exec
? 來排查容器故障。 在這些情況下,你可以使用 ?kubectl debug
? 來創(chuàng)建 Pod 的副本,通過更改配置幫助調(diào)試。
當(dāng)應(yīng)用程序正在運行但其表現(xiàn)不符合預(yù)期時,你會希望在 Pod 中添加額外的調(diào)試工具, 這時添加新容器是很有用的。
例如,應(yīng)用的容器鏡像是建立在 ?busybox
?的基礎(chǔ)上, 但是你需要 ?busybox
?中并不包含的調(diào)試工具。 你可以使用 ?kubectl run
? 模擬這個場景:
kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d
通過運行以下命令,建立 ?myapp
?的一個名為 ?myapp-debug
? 的副本, 新增了一個用于調(diào)試的 Ubuntu 容器,
kubectl debug myapp -it --image=ubuntu --share-processes --copy-to=myapp-debug
Defaulting debug container name to debugger-w7xmf.
If you don't see a command prompt, try pressing enter.
root@myapp-debug:/#
Note:
- 如果你沒有使用 ?
--container
? 指定新的容器名,?kubectl debug
? 會自動生成的。- 默認(rèn)情況下,?
-i
? 標(biāo)志使 ?kubectl debug
? 附加到新容器上。 你可以通過指定 --attach=false 來防止這種情況。 如果你的會話斷開連接,你可以使用 ?kubectl attach
? 重新連接。- ?
--share-processes
? 允許在此 Pod 中的其他容器中查看該容器的進(jìn)程。
不要忘了清理調(diào)試 Pod:
kubectl delete pod myapp myapp-debug
有時更改容器的命令很有用,例如添加調(diào)試標(biāo)志或因為應(yīng)用崩潰。
為了模擬應(yīng)用崩潰的場景,使用 ?kubectl run
? 命令創(chuàng)建一個立即退出的容器:
kubectl run --image=busybox:1.28 myapp -- false
使用 ?kubectl describe pod myapp
? 命令,你可以看到容器崩潰了:
Containers:
myapp:
Image: busybox
...
Args:
false
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1
你可以使用 ?kubectl debug
? 命令創(chuàng)建該 Pod 的一個副本, 在該副本中命令改變?yōu)榻换ナ?nbsp;shell:
kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh
If you don't see a command prompt, try pressing enter.
/ #
現(xiàn)在你有了一個可以執(zhí)行類似檢查文件系統(tǒng)路徑或者手動運行容器命令的交互式 shell。
Note:
- 要更改指定容器的命令,你必須用 ?
--container
? 命令指定容器的名字, 否則 ?kubectl debug
? 將建立一個新的容器運行你指定的命令。- 默認(rèn)情況下,標(biāo)志 ?
-i
? 使 ?kubectl debug
? 附加到容器。 你可通過指定 ?--attach=false
? 來防止這種情況。 如果你的斷開連接,可以使用 ?kubectl attach
? 重新連接。
不要忘了清理調(diào)試 Pod:
kubectl delete pod myapp myapp-debug
在某些情況下,你可能想從正常生產(chǎn)容器鏡像中 把行為異常的 Pod 改變?yōu)榘{(diào)試版本或者附加應(yīng)用的鏡像。
下面的例子,用 ?kubectl run
?創(chuàng)建一個 Pod:
kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d
現(xiàn)在可以使用 ?kubectl debug
? 創(chuàng)建一個副本 并改變?nèi)萜麋R像為 ?ubuntu
?:
kubectl debug myapp --copy-to=myapp-debug --set-image=*=ubuntu
?--set-image
? 與 ?container_name=image
? 使用相同的 ?kubectl set image
? 語法。 ?*=ubuntu
? 表示把所有容器的鏡像改為 ?ubuntu
?。
kubectl delete pod myapp myapp-debug
如果這些方法都不起作用,你可以找到運行 Pod 的節(jié)點,然后在節(jié)點上部署一個運行在宿主名字空間的特權(quán) Pod。
你可以通過?kubectl debug
? 在節(jié)點上創(chuàng)建一個交互式 shell:
kubectl debug node/mynode -it --image=ubuntu
Creating debugging pod node-debugger-mynode-pdx84 with container debugger on node mynode.
If you don't see a command prompt, try pressing enter.
root@ek8s:/#
當(dāng)在節(jié)點上創(chuàng)建調(diào)試會話,注意以下要點:
kubectl debug
? 基于節(jié)點的名字自動生成新的 Pod 的名字。
/host
?。當(dāng)你完成節(jié)點調(diào)試時,不要忘記清理調(diào)試 Pod:
kubectl delete pod node-debugger-mynode-pdx84
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: