150 个练习的最后一部分,这部分主要包含三个模块:
- 状态存储
- 配置
- 监控
- 服务与网络
四. 状态存储篇
这部分的练习主要是熟悉持久卷和持久卷声明的相关使用。
96. 查看集群中的所有持久卷
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
example-pv 1Gi RWO Delete Bound default/example-local-claim local-storage 2d22h
97. 创建一个 hostpath 类型的持久卷,设置存储容量为 10G,读写权限是 ReadWriteOnce, 挂载到 /mnt/data 目录
- yaml 文件
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
- 创建并查看
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 3s
98. 创建持久卷声明,设置 storage 要求为 3Gi,访问权限是 ReadWriteOnce
- yaml 文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
- 创建并查看 PVC
$ kubectl create -f task-pv-claim.yaml
persistentvolumeclaim/task-pv-claim created
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 12s
99. 删除上面创建的 PV 和 PVC
$ kubectl delete pvc task-pv-claim
persistentvolumeclaim "task-pv-claim" deleted
$ kubectl delete pv task-pv-volume
persistentvolume "task-pv-volume" deleted
100. 创建 Pod,运行一个 Redis 容器并配置一个卷
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
- 创建 Pod
$ kubectl create -f redis-storage.yaml
pod/redis created
101. 进入 Pod 创建 file.txt 文件,然后打开另一个命令窗口进入 Pod 查看新创建的文件
# 第一个命令行窗口,创建文件
# 进入 Pod
$ kubectl exec -it redis -- /bin/sh
# 进入 yaml 中卷的挂载目录
cd /data/redis
# 创建文件
echo 'This is called the file' > file.txt
# 第二个命令行窗口
$ kubectl exec -it redis -- /bin/sh
# cat /data/redis/file.txt
This is called the file
#
102. 删除 Redis Pod 重新创建,然后查看文件是否会保留
kubectl delete pod redis
kubectl create -f redis-storage.yaml
kubectl exec -it redis /bin/sh
# 新的 Pod 并没有旧的文件
cat /data/redis/file.txt // file doesn't exist
103. 重新创建 PV 和 PVC
$ kubectl create -f task-pv-volume.yaml
persistentvolume/task-pv-volume created
$ kubectl create -f task-pv-claim.yaml
persistentvolumeclaim/task-pv-claim created
104. 创建运行 Nginx 的 Pod,并配置持久卷,挂载到 “/usr/share/nginx/html” 路径
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
- 创建 Pod
kubectl create -f task-pv-pod.yaml
五. 配置篇
这部分的练习的主要目标是:
- 了解 ConfigMap
- 了解 SecurityContexts
- 定义一个应用的资源要求
- 创建与使用 Secret
- 了解 ServiceAccounts
105. 查看所有的 ConfigMap
$ kubectl get configmaps
$ kubectl get cm
No resources found in default namespace.
106. 基于字面量创建 configmap
$ kubectl create cm myconfigmap --from-literal=appname=myapp
configmap/myconfigmap created
107. 查看刚创建的 configmap 的数据
$ kubectl get cm
NAME DATA AGE
myconfigmap 1 91s
$ kubectl describe cm
Name: myconfigmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
appname:
----
myapp
Events: <none>
$ kubectl get cm -o yaml
108. 删除刚创建的 configmap
kubectl delete cm myconfigmap
109. 创建一个待用文件,包含 key1=value1 和 key2=value2 两个键值对
$ cat >> config.txt << EOF
key1=value1
key2=value2
EOF
# 查看文件
$ cat config.txt
key1=value1
key2=value2
110. 基于上面创建的文件创建 configmap 并查看其数据
# 基于文件创建 configmap
$ kubectl create cm keyvalcfgmap --from-file=config.txt
configmap/keyvalcfgmap created
$ kubectl get cm
NAME DATA AGE
keyvalcfgmap 1 15s
# ubuntu @ VM-0-4-ubuntu in ~ [9:09:32]
$ kubectl describe cm keyvalcfgmap
Name: keyvalcfgmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
config.txt:
----
key1=value1
key2=value2
$ kubectl get cm keyvalcfgmap -o yaml
apiVersion: v1
data:
config.txt: |
key1=value1
key2=value2
kind: ConfigMap
metadata:
creationTimestamp: "2020-04-27T01:09:17Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:config.txt: {}
manager: kubectl
operation: Update
time: "2020-04-27T01:09:17Z"
name: keyvalcfgmap
namespace: default
resourceVersion: "4394095"
selfLink: /api/v1/namespaces/default/configmaps/keyvalcfgmap
uid: 4d750f64-9abd-44cd-a400-66884b3b5f29
111. 创建运行 Nginx 容器的 Pod,从上面创建的 configmap 中加载配置
- 配置 yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
# 从指定的 configmap 中加载环境变量
envFrom:
- configMapRef:
name: keyvalcfgmap
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 查看环境变量后删除
$ kubectl exec -it nginx -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=nginx
TERM=xterm
config.txt=key1=value1
key2=value2
$ kubectl delete po nginx
112. 创建 file.env 并基于此文件创建 configmap
$ echo var1=val1 > file.env
cat file.env
var1=val1
$ kubectl create cm envcfgmap --from-env-file=file.env
configmap/envcfgmap created
$ kubectl describe cm envcfgmap
Name: envcfgmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
var1:
----
val1
Events: <none>
$ kubectl get cm envcfgmap -o yaml
apiVersion: v1
data:
var1: val1
kind: ConfigMap
metadata:
creationTimestamp: null
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:var1: {}
manager: kubectl
operation: Update
time: "2020-04-27T01:16:15Z"
name: envcfgmap
selfLink: /api/v1/namespaces/default/configmaps/envcfgmap
113. 基于上面创建的 envcfmap 创建 Nginx 容器的 Pod
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
envFrom:
# 配置 configmap
- configMapRef:
name: envcfgmap
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 查看配置后删除
$ kubectl exec -it nginx -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=nginx
TERM=xterm
var1=val1
$ kubectl delete po nginx
pod "nginx" deleted
114. 创建 Pod,并设置存储卷从 configmap 读取数据
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
# 创建 configmap 卷
volumes:
- name: nginx-volume
configMap:
name: cfgvolume
containers:
- image: nginx
name: nginx
resources: {}
volumeMounts:
# 挂载卷到 /etc/cfg
- name: nginx-volume
mountPath: /etc/cfg
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建 yaml 文件并查看对应目录的数据
$ kubectl create -f nginx-volume.yaml
pod/nginx created
$ kubectl exec -it nginx -- /bin/sh
# cd /etc/cfg
# ls
var1 var2
115. 创建 busybox 的 Pod,并设置 securityContext,所有进程都运行在 user ID 1000 和 组 ID 为 2000 的context 下。
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: secbusybox
name: secbusybox
spec:
# 创建 securityContext
securityContext: # add security context
runAsUser: 1000
runAsGroup: 2000
containers:
- args:
- /bin/sh
- -c
- sleep 3600;
image: busybox
name: secbusybox
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建 Pod 并查看容器的 id 信息
$ kubectl create -f busybox.yaml
pod/secbusybox created
$ kubectl exec -it secbusybox -- sh
/ $ id
uid=1000 gid=2000
116. 创建和上面一样的 Pod,分别在 Pod 和容器层面设置 securityContext,容器层面的 securityContext 会覆盖掉 Pod 层面的设置
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: secbusybox
name: secbusybox
spec:
# Pod 设置
securityContext:
runAsUser: 1000
containers:
- args:
- /bin/sh
- -c
- sleep 3600;
image: busybox
# 容器层面的设置
securityContext:
runAsUser: 2000
name: secbusybox
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 Pod 中的 id 信息
$ kubectl delete pod secbusybox
pod "secbusybox" deleted
$ kubectl create -f busybox.yaml
pod/secbusybox created
$ kubectl exec -it secbusybox -- sh
/ $ id
# 和容器层面的设置一样,覆盖掉了 Pod 层面的设置
uid=2000 gid=0(root)
/ $
117. 创建 Nginx Pod,并配置 NET_ADMIN 和 SYS_TIME
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
securityContext:
capabilities:
add: ["SYS_TIME", "NET_ADMIN"]
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看信息
$ kubectl create -f nginx.yaml
pod/nginx created
# ubuntu @ VM-0-4-ubuntu in ~ [9:41:15]
$ kubectl exec -it nginx -- sh
# cd /proc/1
# cat status
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
118. 创建 Nginx 的 Pod 并设置内存使用限制
- yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
# 设置内存使用
requests:
memory: "100Mi"
limits:
memory: "200Mi"
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 Pod 的内存使用
$ kubectl create -f nginx.yaml
pod/nginx created
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
nginx 0m 2Mi
119. 创建 Nginx 的 Pod 并设置 CPU 使用限制
- yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
# 设置 CPU 的使用限制
requests:
cpu: "0.5"
limits:
cpu: "1"
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 CPU 使用
$ kubectl create -f nginx.yaml
pod/nginx created
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
nginx 0m 0Mi
120. 创建 Pod, 同时设置 CPU 和 内存使用限制
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
requests:
memory: "100Mi"
cpu: "0.5"
limits:
memory: "200Mi"
cpu: "1"
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看资源使用
$ kubectl create -f nginx.yaml
pod/nginx created
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
nginx 0m 0Mi
121.创建运行 Nginx 的 Pod 并设置内存上下限为 100Gi 和 200Gi,查看 Pod 信息
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
requests:
memory: "100Gi"
cpu: "0.5"
limits:
memory: "200Gi"
cpu: "1"
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 查看 Pod 信息
$ kubectl create -f nginx.yaml
pod/nginx created
$ kubectl describe pod nginx
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 5s (x2 over 5s) default-scheduler 0/2 nodes are available: 2 Insufficient memory.
122. 创建一个 Secret,设置字面量值为 user=myuser 和 password=mypassword
$ kubectl create secret generic my-secret --from-literal=username=user --from-literal=password=mypassword
secret/my-secret created
123. 查看所有的 secret
$ kubectl get secret --all-namespaces
NAMESPACE NAME TYPE DATA AGE
default default-token-wqvj8 kubernetes.io/service-account-token 3 21d
default my-secret Opaque 2 27s
ingress-nginx default-token-xrdhk kubernetes.io/service-account-token 3 21d
ingress-nginx nginx-ingress-serviceaccount-token-dxt72 kubernetes.io/service-account-token 3 21d
kube-node-lease default-token-d79ll kubernetes.io/service-account-token 3 21d
kube-public default-token-k2lm9 kubernetes.io/service-account-token 3 21d
kube-system attachdetach-controller-token-4qt2z kubernetes.io/service-account-token 3 21d
kube-system bootstrap-signer-token-x2z8q kubernetes.io/service-account-token 3 21d
kube-system calico-kube-controllers-token-dhxsb kubernetes.io/service-account-token 3 21d
kube-system calico-node-token-w44hg kubernetes.io/service-account-token 3 21d
kube-system certificate-controller-token-rjjgp kubernetes.io/service-account-token 3 21d
124. 查看 secret 的 yaml 信息
kubectl get secret my-secret -o yaml
125. 创建运行 Nginx 的 Pod,并从 secret 中读取指定信息
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
env:
# 从 secret 中读取数据
- name: USER_NAME
valueFrom:
secretKeyRef:
name: my-secret
key: username
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 nginx Pod 的环境变量
$ kubectl create -f nginx.yaml
pod/nginx created
$ kubectl exec -it nginx -- env
HOSTNAME=nginx
USER_NAME=user
126. 创建运行 nginx Pod 并加载 secret 中的所有字段为环境变量
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
envFrom:
# 加载整个 secret
- secretRef:
name: my-secret
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建 Pod 查看环境变量
$ kubectl create -f nginx.yaml
pod/nginx created
$ kubectl exec -it nginx -- env
...
password=mypassword
username=user
127. 获取 default 命名空间下的 service accounts
$ kubectl get sa
NAME SECRETS AGE
default 1 21d
128. 获取所有的 service accounts
kubectl get sa --all-namespaces
129. 创建名为 admin 的 service account
$ kubectl create sa admin
serviceaccount/admin created
130. 查看上面创建的 service account 的 yaml 信息
$ kubectl get sa admin -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2020-04-27T13:31:22Z"
name: admin
namespace: default
resourceVersion: "4502353"
selfLink: /api/v1/namespaces/default/serviceaccounts/admin
uid: 3995f3da-6850-4a38-ac11-a5451fa6b5d2
secrets:
- name: admin-token-tpcpv
131. 创建运行 busybox 的 Pod 并设置 serviceAccount
- yaml 文件设置
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
serviceAccountName: admin
containers:
- args:
- /bin/sh
- -c
- sleep 3600
image: busybox
name: busybox
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 Pod
kubectl create -f busybox.yml
// verify
kubectl describe po busybox
六. 集群监控篇
这部分练习主要涉及下面一些目标:
- 理解存活探针 livenessProbes and ReadinessProbes
- 了解容器日志
- 了解如何监控 K8S 中运行的应用
- 了解 K8S 的 debug
132. 创建带有 Readiness 的 Nginx Pod
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 readiness
$ kubectl create -f nginx-pod.yaml
pod/nginx created
$ kubectl describe pod nginx | grep -i readiness
Readiness: http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3
133. 创建带有 livenessProbe 的 Nginx Pod
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /healthz
port: 80
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 Pod
$ kubectl create -f nginx-pod.yaml
pod/nginx created
$ kubectl describe pod nginx | grep -i readiness
$ kubectl describe pod nginx | grep -i liveiness
$ kubectl describe pod nginx | grep -i liveness
Liveness: http-get http://:80/healthz delay=0s timeout=1s period=10s #success=1 #failure=3
Warning Unhealthy 7s kubelet, vm-0-2-ubuntu Liveness probe failed: HTTP probe failed with statuscode: 404
134. 创建 Nginx Pod,添加 liveness 和 readiness
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /healthz
port: 80
readinessProbe:
httpGet:
path: /
port: 80
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建并查看 Pod
kubectl create -f nginx-pod.yaml
// verify
kubectl describe pod nginx | grep -i readiness
kubectl describe pod nginx | grep -i liveness
135. 查看 liveness 和 reeadiness 的命令选项
kubectl explain Pod.spec.containers.livenessProbe
kubectl explain Pod.spec.containers.readinessProbe
136. 创建带有 readiness 和 liveness 的 Pod,并设置初次检测时间与检测间隔
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
livenessProbe:
# 启动 20s 后开始检测
initialDelaySeconds: 20
# 每 25 秒检测一次
periodSeconds: 25
httpGet:
path: /healthz
port: 80
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 25
httpGet:
path: /
port: 80
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
137. 创建 busybox 并打印信息
# 创建 Pod
$ kubectl run busybox --image=busybox --restart=Never -- /bin/sh -c "echo I am from busybox pod; sleep 3600;"
pod/busybox created
# 打印日志
$ kubectl logs busybox
I am from busybox pod
138. 将上面 Pod 的日志存入文件 busybox-logs.txt
$ kubectl logs busybox > busybox-logs.txt
$ cat busybox-logs.txt
I am from busybox pod
139. 查看所有 events,基于 timestamp 排序,并将 events 信息存入到 file.log 文件中
kubectl get events --sort-by=.metadata.creationTimestamp
$ kubectl get events --sort-by=.metadata.creationTimestamp > file.log
$ cat file.log
LAST SEEN TYPE REASON OBJECT MESSAGE
16m Normal Killing pod/nginx Stopping container nginx
16m Normal Scheduled pod/nginx Successfully assigned default/nginx to vm-0-2-ubuntu
16m Normal Pulling pod/nginx Pulling image "nginx"
15m Normal Started pod/nginx Started container nginx
15m Normal Created pod/nginx Created container nginx
15m Normal Pulled pod/nginx Successfully pulled image "nginx"
140. 创建 imgee 为 alpine 的 Pod 并执行命令每 5s 打印一次日志
# 创建 Pod
$ kubectl run hello --image=alpine --restart=Never -- /bin/sh -c "while true; do echo 'Hi I am from Alpine'; sleep 5;done"
pod/hello created
# 查看日志
$ kubectl logs --follow hello
Hi I am from Alpine
Hi I am from Alpine
Hi I am from Alpine
141. 基于下面命令创建 Pod ,启动失败时查看错误原因并修正
# 创建 Pod
$ kubectl create -f https://gist.githubusercontent.com/bbachi/212168375b39e36e2e2984c097167b00/raw/1fd63509c3ae3a3d3da844640fb4cca744543c1c/not-running.yml
pod/not-running created
# 查看 Pod
$ kubectl get pod not-running
NAME READY STATUS RESTARTS AGE
not-running 0/1 ImagePullBackOff 0 7s
$ kubectl describe po not-running
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 39s default-scheduler Successfully assigned default/not-running to vm-0-2-ubuntu
Normal SandboxChanged 34s kubelet, vm-0-2-ubuntu Pod sandbox changed, it will be killed and re-created.
Normal Pulling 19s (x2 over 37s) kubelet, vm-0-2-ubuntu Pulling image "ngin"
Warning Failed 16s (x2 over 35s) kubelet, vm-0-2-ubuntu Failed to pull image "ngin": rpc error: code = Unknown desc = Error response from daemon: pull access denied for ngin, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
Warning Failed 16s (x2 over 35s) kubelet, vm-0-2-ubuntu Error: ErrImagePull
Normal BackOff 1s (x4 over 33s) kubelet, vm-0-2-ubuntu Back-off pulling image "ngin"
Warning Failed 1s (x4 over 33s) kubelet, vm-0-2-ubuntu Error: ImagePullBackOff
# 修改错误
kubectl edit pod not-running
or
kubectl set image pod/not-running not-running=nginx
142. 利用下面命令创建 4 个 namespace 和 4 个 pods,查看错误的 Pod 并修正
$ kubectl create -f https://gist.githubusercontent.com/bbachi/1f001f10337234d46806929d12245397/raw/84b7295fb077f15de979fec5b3f7a13fc69c6d83/problem-pod.yaml
namespace/namespace1 created
namespace/namespace2 created
namespace/namespace3 created
namespace/namespace4 created
pod/pod1 created
pod/pod2 created
pod/pod3 created
pod/pod4 created
$ kubectl get po --all-namespaces
$ kubectl get po -n namespace2
NAME READY STATUS RESTARTS AGE
pod2 0/1 ImagePullBackOff 0 46s
$ kubectl set image pod/pod2 pod2=nginx -n namespace2
pod/pod2 image updated
$ kubectl get po -n namespace2
NAME READY STATUS RESTARTS AGE
pod2 1/1 Running 0 55s
143. 查看所有 Pod 的 CPU 与内存使用并查找出 CPU 使用率最高的三个
$ kubectl top pod --all-namespaces | sort --reverse --key 3 --numeric | head -3
kube-system kube-apiserver-vm-0-4-ubuntu 23m 308Mi
kube-system calico-node-njsrv 23m 29Mi
kube-system calico-node-ltpqg 17m 28Mi
# 将信息写入文件
$ kubectl top pod --all-namespaces | sort --reverse --key 3 --numeric | head -3 > cpu-usage.txt
$ cat cpu-usage.txt
kube-system kube-apiserver-vm-0-4-ubuntu 23m 308Mi
kube-system calico-node-njsrv 23m 29Mi
kube-system calico-node-ltpqg 17m 28Mi
七. 服务与网络篇
这部分的了解主要有下面两个目的:
- 了解 Service
- 对 NetworkPolicies 有一个基本了解
144. 创建 Nginx Pod,打上 app=my-nginx 标签并开放 80 端口
- yaml 文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
app: my-nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Never
status: {}
- 创建 Pod
$ kubectl create -f nginx.yaml
pod/nginx created
145. 为 Pod 创建 Service
- yaml 文件
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-nginx
ports:
- protocol: TCP
port: 80
targetPort: 9376
- 创建 service
$ kubectl create -f nginx-svc.yaml
service/my-service created
146. 查看 Pod 与 Service
$ kubectl get po nginx --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 2m17s app=my-nginx
$ kubectl get svc my-service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
my-service ClusterIP 10.104.9.185 <none> 80/TCP 38s app=my-nginx
147. 删除 my-service,并使用 kubectl expose 命令重建
$ kubectl delete svc my-service
service "my-service" deleted
$ kubectl expose po nginx --port=80 --target-port=9376
service/nginx exposed
$ kubectl get svc -l app=my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP 10.109.228.97 <none> 80/TCP 6s
148. 删除上面创建的 Service 并重建,指定 type 为 NodePort
$ kubectl delete svc nginx
service "nginx" deleted
$ kubectl expose po nginx --port=80 --type=NodePort
service/nginx exposed
149. 创建临时 busybox Pod 并通过 nginx Service 访问 Nginx Pod
$ kubectl get svc nginx -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx NodePort 10.108.87.189 <none> 80:31305/TCP 2m1s app=my-nginx
$ kubectl run busybox --image=busybox --restart=Never -it --rm -- wget -o- 10.108.87.189:80
Connecting to 10.108.87.189:80 (10.108.87.189:80)
saving to 'index.html'
index.html 100% |********************************| 612 0:00:00 ETA
'index.html' saved
pod "busybox" deleted
150. 创建 NetworkPolicy,拒绝所有入口流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
spec:
podSelector: {}
policyTypes:
- Ingress
- 创建 networkpolicy
$ kubectl create -f network-policy.yaml
networkpolicy.networking.k8s.io/default-deny created
以上就是完整的 150 个练习了,K8S 的学习是理论与实践并重的,既要理解集群、组件的设计思想与原理,还要熟练掌握各种 API 的操作,唯一的方法就是不断练习练习再练习。
不过上面的 150 个练习我觉得内容设置的并不合理,有些地方重复了,而有些地方比如网络这一块练习量又不够,后面有时间了在这几篇文章的基础之上补充一部分其他的练习。
我是 AhriJ邹同学,前后端、小程序、DevOps 都搞的炸栈工程师。博客持续更新,欢迎小伙伴关注或与我私信交流,互相学习,共同进步。