CKA-真题练习 (上)

环境说明

ssh登录node01(11.0.1.112),使用candidate帐号做题,密码为123,在node01上可以免密切换到其他节点,如 ssh master01 或 ssh node02,candidate帐号也可以免密切换到root,如 sudo -i

11.0.1.112
root/123456

切换到candidate帐号
su candidate

# 目录准备
cd ~   # cd /home/candidate/
mkdir -p /home/candidate/k8sYaml
cd  k8sYaml

虚拟机和宿主机共享目录:

candidate@node01:~$ sudo -i
root@node01:~# find / -name macshare
/mnt/hgfs/macshare
root@node01:~# 
/mnt/hgfs/macshare

查看目录:

candidate@node01:~/k8sYaml$ pwd
/home/candidate/k8sYaml
candidate@node01:~/k8sYaml$ ls -l
total 32
-rw-r--r-- 1 candidate candidate 391 Feb 16 10:02 ingress-05.yaml
-rw-r--r-- 1 candidate candidate  52 Feb 16 10:02 namespace-dev.yaml
-rw-r--r-- 1 candidate candidate 333 Feb 16 10:02 networkpolicy.yaml
-rw-r--r-- 1 candidate candidate 176 Feb 16 10:02 nodeSelect-07.yaml
-rw-r--r-- 1 candidate candidate 210 Feb 16 10:02 pod-kucc-09.yaml
-rw-r--r-- 1 candidate candidate 233 Feb 16 10:02 pv-10.yaml
-rw-r--r-- 1 candidate candidate 195 Feb 16 10:02 pvc-11.yaml
-rw-r--r-- 1 candidate candidate 311 Feb 16 10:02 pvc-pod-11.yaml
candidate@node01:~/k8sYaml$ 

在vim中复制,可使用 :set paste 命令,要不然格式会乱。

0、环境准备

为了和考试环境一样,这里练习环境需要创建 k8s context (上下文)。

命名空间:

vim namespace-dev.yaml

apiVersion: v1
kind: Namespace
metadata:
 name: dev

创建命名空间

kubectl create -f namespace-dev.yaml

设置上下文:

kubectl config set-context k8s --namespace=dev --cluster=kubernetes --user=kubernetes-admin

注:–cluster=kubernetes --user=kubernetes-admin,cluster和user这里使用k8s集群本身的cluster和user,这样直接使用集群的密钥进行认证。

查看 kubeconfig内容:

root@node01:~/k8sYaml# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://11.0.1.111:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    namespace: dev
    user: kubernetes-admin
  name: k8s
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
root@node01:~/k8sYaml# 

从current-context看到当前的上下文为:kubernetes-admin@kubernetes

上下文切换:

root@node01:~/k8sYaml# kubectl config use-context k8s
Switched to context "k8s".

1、权限控制 RBAC

1、切换环境
kubectl config use-context kubernetes

2、配置
kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployments,daemonsets,statefulsets
kubectl create serviceaccount cicd-token -n app-team1
# 题目中写了“限于 namespace app-team1 中”,则创建 rolebinding。没有写的话,则创建 clusterrolebinding。
kubectl create rolebinding cicd-token-rolebinding --serviceaccount=app-team1:cicd-token --clusterrole=deployment-clusterrole -n app-team1
# rolebinding 后面的名字 cicd-token-rolebinding 随便起的,因为题目中没有要求,如果题目中有要求,就不能随便起了。

3、验证
#稍微验证下
kubectl describe rolebinding cicd-token-rolebinding -napp-team1

注意:我们可以用 describle 命令看下刚才新建的 rolebinding 来验证下:

root@node01:~/k8sYaml# kubectl describe rolebinding cicd-token-rolebinding -n app-team1
Name:         cicd-token-rolebinding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  deployment-clusterrole
Subjects:
  Kind            Name        Namespace
  ----            ----        ---------
  ServiceAccount  cicd-token  app-team1
root@node01:~/k8sYaml# 

2、统计使用 CPU 最高的 Pod

考点:kubectl top -l 命令的使用。

1、切换环境
kubectl config use-context kubernetes

2、配置
kubectl top pod -l name=cpu-utilizer --sort-by="cpu" -A #-A是所有namespace 不要忘记写哦,-l也要记得写哦。。。
echo "<podname>" > /opt/KUR00401.txt # 将第一个 Pod 名称写到文件

#写完后记得检查下那个保存结果的文件

3、验证
cat /opt/KUR00401.txt

第3题 网络策略NetworkPolicy

考题:

 设置配置环境:
[candidate@node-1] $ kubectl config use-context hk8s
Task
在现有的 namespace my-app 中创建一个名为 allow-port-from-namespace 的新 NetworkPolicy。
确保新的 NetworkPolicy 允许 namespace echo 中的 Pods 连接到 namespace my-app 中的 Pods 的 9000 端口。
进一步确保新的 NetworkPolicy: 不允许对没有在监听 端口 9000 的 Pods 的访问 不允许非来自 namespace echo 中的 Pods 的访问

双重否定就是肯定,所以最后两句话的意思就是:
仅允许端口为 9000 的 pod 方法。
仅允许 echo 命名空间中的 pod 访问。

考点:NetworkPolicy 的创建,k8s官网|网络策略

开始操作:
查看所有 ns 的标签 label

kubectl get ns --show-labels

结果打印:

root@node01:~/k8sYaml# kubectl get ns --show-labels
NAME               STATUS   AGE    LABELS
app-team1          Active   212d   kubernetes.io/metadata.name=app-team1
calico-apiserver   Active   215d   kubernetes.io/metadata.name=calico-apiserver,name=calico-apiserver
calico-system      Active   215d   kubernetes.io/metadata.name=calico-system,name=calico-system
cpu-top            Active   212d   kubernetes.io/metadata.name=cpu-top
default            Active   215d   kubernetes.io/metadata.name=default
echo               Active   212d   kubernetes.io/metadata.name=echo
ing-internal       Active   212d   kubernetes.io/metadata.name=ing-internal
ingress-nginx      Active   212d   kubernetes.io/metadata.name=ingress-nginx
internal           Active   212d   kubernetes.io/metadata.name=internal
kube-node-lease    Active   215d   kubernetes.io/metadata.name=kube-node-lease
kube-public        Active   215d   kubernetes.io/metadata.name=kube-public
kube-system        Active   215d   kubernetes.io/metadata.name=kube-system
my-app             Active   212d   kubernetes.io/metadata.name=my-app
tigera-operator    Active   215d   kubernetes.io/metadata.name=tigera-operator,name=tigera-operator

如果访问者的 namespace 没有标签 label,则需要手动打一个。如果有一个独特的标签 label,则也可以直接使用。

kubectl label ns echo project=echo

结果打印:

root@node01:~/k8sYaml# kubectl get ns --show-labels
NAME               STATUS   AGE    LABELS
app-team1          Active   212d   kubernetes.io/metadata.name=app-team1
calico-apiserver   Active   215d   kubernetes.io/metadata.name=calico-apiserver,name=calico-apiserver
calico-system      Active   215d   kubernetes.io/metadata.name=calico-system,name=calico-system
cpu-top            Active   212d   kubernetes.io/metadata.name=cpu-top
default            Active   215d   kubernetes.io/metadata.name=default
echo               Active   212d   kubernetes.io/metadata.name=echo,project=echo
ing-internal       Active   212d   kubernetes.io/metadata.name=ing-internal
ingress-nginx      Active   212d   kubernetes.io/metadata.name=ingress-nginx
internal           Active   212d   kubernetes.io/metadata.name=internal
kube-node-lease    Active   215d   kubernetes.io/metadata.name=kube-node-lease
kube-public        Active   215d   kubernetes.io/metadata.name=kube-public
kube-system        Active   215d   kubernetes.io/metadata.name=kube-system
my-app             Active   212d   kubernetes.io/metadata.name=my-app
tigera-operator    Active   215d   kubernetes.io/metadata.name=tigera-operator,name=tigera-operator
root@node01:~/k8sYaml# 

编写一个 yaml 文件
vim networkpolicy.yaml

注意 :set paste,防止 yaml 文件空格错序。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: my-app #被访问者的命名空间 spec:
podSelector: #这两行必须要写,或者也可以写成一行为 podSelector: {} matchLabels: {} # 注意 matchLabels:与{}之间有一个空格
policyTypes:
- Ingress #策略影响入栈流量 ingress:
- from: #允许流量的来源
- namespaceSelector: matchLabels:
project: echo #访问者的命名空间的标签 label
#- podSelector: {} #注意,这个不写。如果 ingress 里也写了- podSelector: {},则会导致 my-app 中的 pod 可以访问 my-app 中 pod 的 9000 了,这样不 满足题目要求不允许非来自 namespace echo 中的 Pods 的访问。
ports:
- protocol: TCP
port: 9000 #被访问者公开的端口

创建

kubectl apply -f networkpolicy.yaml

检查

kubectl describe networkpolicy -n my-app

执行结果:

root@node01:~/k8sYaml# kubectl apply -f networkpolicy.yaml 
networkpolicy.networking.k8s.io/allow-port-from-namespace created
root@node01:~/k8sYaml# kubectl describe networkpolicy -n my-app
Name:         allow-port-from-namespace
Namespace:    my-app
Created on:   2023-02-15 14:09:44 +0800 CST
Labels:       <none>
Annotations:  <none>
Spec:
  PodSelector:     <none> (Allowing the specific traffic to all pods in this namespace)
  Allowing ingress traffic:
    To Port: 9000/TCP
    From:
      NamespaceSelector: project=echo
  Not affecting egress traffic
  Policy Types: Ingress
root@node01:~/k8sYaml# 

第4题 SVC 暴露应用(强制记忆)

考题:

设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
请重新配置现有的 deployment front-end 以及添加名为 http 的端口规范来公开现有容器 nginx 的端口 80/tcp。 创建一个名为 front-end-svc 的新 service,以公开容器端口 http。
配置此 service,以通过各个 Pod 所在的节点上的 NodePort 来公开他们。

考点:将现有的 deploy 暴露成 nodeport 的 service。

解答:

# 解答
kubectl config view

# 切换为默认default环境
# kubectl config use-context kubernetes

2、配置
kubectl edit deployment front-end
…
    containers:
    - image: nginx
      imagePullPolicy: Always
      name: nginx
      ports:
      - name: http #额额,这里要加一个-横杠的。。。
        protocol: TCP #protocol不写也是可以的,因为默认就是TCP
        containerPort: 80
…
kubectl expose deployment front-end --port=80 --target-port=80 --type=NodePort --name=front-end-svc #注意:这里--name(不要忘记了。。。。)svc类型:NodePort/ClusterIP;  --port是svc的端口号,--target-port是deployment里pod的容器的端口号

#验证:(看下他们的SELECTOR标签是否一致)
kubectl get svc front-end-svc -owide
kubectl get deployment front-end -owide

curl 节点名/节点ip:NodePort
curl svcIP:port

执行结果:

root@node01:~/k8sYaml# kubectl expose deployment front-end --type=NodePort --port=80 --target-port=80 --name=front-end-svcservice/front-end-svc exposed
root@node01:~/k8sYaml# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
front-end-svc   NodePort    10.103.219.85   <none>        80:31538/TCP   8s
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        215d
root@node01:~/k8sYaml# 

root@node01:~/k8sYaml# curl 10.103.219.85
Hello World ^_^

第5题 Ingress创建(拷贝yaml)

Task
如下创建一个新的 nginx Ingress 资源:
名称: ping
Namespace: ing-internal
使用服务端口 5678 在路径 /hello 上公开服务 hello
可以使用以下命令检查服务 hello 的可用性,该命令应返回 hello: curl -kL <INTERNAL_IP>/hello

解答:

考试时务必执行,切换集群。模拟环境中不需要执行。

kubectl config use-context k8s 开始操作

方法 1:(推荐)
拷贝官文的 yaml 案例,修改相关参数即可 vim ingress.yaml

#注意 :set paste,防止 yaml 文件空格错序。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: pong
  namespace: ing-internal
  annotations:
    kubernetes.io/ingress.class: "nginx"  # 1.23以上需要这行,否则ingress 服务获取不到IP
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /hello
        pathType: Prefix
        backend:
          service:
            name: hello
            port:
              number: 5678
~                             

file

file

创建

kubectl apply -f ingress.yaml

12、查看pod日志

考题

设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Task
监控 pod foo 的日志并:
提取与错误 RLIMIT_NOFILE 相对应的日志行 将这些日志行写入 /opt/KUTR00101/foo

考点:kubectl logs 命令

解答:

candidate@node01:~/k8sYaml$ kubectl logs -f foo | grep RLIMIT_NOFILE
2023/02/16 01:56:27 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
^C
candidate@node01:~/k8sYaml$ kubectl logs -f foo | grep RLIMIT_NOFILE > /opt/KUTR00101/foo
^C
candidate@node01:~/k8sYaml$ kubectl logs foo | grep "RLIMIT_NOFILE" > /opt/KUTR00101/foo
candidate@node01:~/k8sYaml$ cat /opt/KUTR00101/foo
2023/02/16 01:56:27 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
candidate@node01:~/k8sYaml$ 

13、使用 sidecar 代理容器日志

考题

设置配置环境:
[candidate@node-1] $ kubectl config use-context k8s
Context
将一个现有的 Pod 集成到 Kubernetes 的内置日志记录体系结构中(例如 kubectl logs)。 添加 streaming sidecar 容器是实现此要求的一种好方法。
Task
使用 busybox Image 来将名为 sidecar 的 sidecar 容器添加到现有的 Pod 11-factor-app 中。 新的 sidecar 容器必须运行以下命令:
/bin/sh -c tail -n+1 -f /var/log/11-factor-app.log
使用挂载在/var/log 的 Volume,使日志文件 11-factor-app.log 可用于 sidecar 容器。 除了添加所需要的 volume mount 以外,请勿更改现有容器的规格。

考题翻译成白话,就是:
添加一个名为 sidecar 的边车容器(使用 busybox 镜像),加到已有的 pod 11-factor-app 中。 确保 sidecar 容器能够输出 /var/log/11-factor-app.log 的信息。
使用 volume 挂载 /var/log 目录,确保 sidecar 能访问 11-factor-app.log 文件

考点: pod 两个容器共享存储卷

官方文档示例:
https://kubernetes.io/zh-cn/docs/concepts/cluster-administration/logging/

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox:1.28
    args:
    - /bin/sh
    - -c
    - >
      i=0;
      while true;
      do
        echo "$i: $(date)" >> /var/log/1.log;
        echo "$(date) INFO $i" >> /var/log/2.log;
        i=$((i+1));
        sleep 1;
      done      
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-1
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/1.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: count-log-2
    image: busybox:1.28
    args: [/bin/sh, -c, 'tail -n+1 -F /var/log/2.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  volumes:
  - name: varlog
    emptyDir: {}

解答:

# 考试时务必执行,切换集群。模拟环境中不需要执行。
# kubectl config use-context k8s

通过 kubectl get pod -o yaml 的方法备份原始 pod 信息,删除旧的 pod 11-factor-app copy 一份新 yaml 文件,添加 一个名称为 sidecar 的容器
新建 emptyDir 的卷,确保两个容器都挂载了 /var/log 目录
新建含有 sidecar 的 pod,并通过 kubectl logs 验证
开始操作
# 导出这个pod的yaml文件
kubectl get pod 11-factor-app -o yaml > varlog.yaml # 备份 yaml 文件,防止改错了,回退。
cp varlog.yaml varlog-bak.yaml
# 修改 varlog.yaml 文件 vim varlog.yaml

varlog-bak.yaml 文件:

candidate@node01:~/k8sYaml$ cat varlog-13-bak.yaml 
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/containerID: 8e842cf03c4aa6c6e76114d63bffe2bfc9f1dfc0f43e5cf85d3d608e005403b2
    cni.projectcalico.org/podIP: 10.244.196.175/32
    cni.projectcalico.org/podIPs: 10.244.196.175/32
  creationTimestamp: "2022-07-17T10:25:09Z"
  name: 11-factor-app
  namespace: default
  resourceVersion: "67719"
  uid: cc165dff-c835-47de-8b03-2d9a59ab8028
spec:
  containers:
  - args:
    - /bin/sh
    - -c
    - |
      i=0; while true; do
        echo "$(date) INFO $i" >> /var/log/11-factor-app.log;
        i=$((i+1));
        sleep 1;
      done
    image: busybox
    imagePullPolicy: IfNotPresent
    name: count
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-7m2k4
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: node01
  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-7m2k4
    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-07-17T10:25:09Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2023-02-16T01:56:23Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2023-02-16T01:56:23Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2022-07-17T10:25:09Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: containerd://5ebc410712146c1c32f5f6c325cb3637997ce1f9bb101d36bb91d2ae9b5603b3
    image: docker.io/library/busybox:latest
    imageID: sha256:62aedd01bd8520c43d06b09f7a0f67ba9720bdc04631a8242c65ea995f3ecac8
    lastState:
      terminated:
        containerID: containerd://0d7c9f4c0be1c2360b470e9644b550e9153807d7487a7c38df9acc83969b745b
        exitCode: 255
        finishedAt: "2023-02-16T01:55:20Z"
        reason: Unknown
        startedAt: "2022-08-26T07:19:27Z"
    name: count
    ready: true
    restartCount: 7
    started: true
    state:
      running:
        startedAt: "2023-02-16T01:56:23Z"
  hostIP: 11.0.1.112
  phase: Running
  podIP: 10.244.196.175
  podIPs:
  - ip: 10.244.196.175
  qosClass: BestEffort
  startTime: "2022-07-17T10:25:09Z"
candidate@node01:~/k8sYaml$ 

修改后的完整的yaml文件:

candidate@node01:~/k8sYaml$ cat varlog-13.yaml 
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/containerID: 8e842cf03c4aa6c6e76114d63bffe2bfc9f1dfc0f43e5cf85d3d608e005403b2
    cni.projectcalico.org/podIP: 10.244.196.175/32
    cni.projectcalico.org/podIPs: 10.244.196.175/32
  creationTimestamp: "2022-07-17T10:25:09Z"
  name: 11-factor-app
  namespace: default
  resourceVersion: "67719"
  uid: cc165dff-c835-47de-8b03-2d9a59ab8028
spec:
  containers:
  - args:
    - /bin/sh
    - -c
    - |
      i=0; while true; do
        echo "$(date) INFO $i" >> /var/log/11-factor-app.log;
        i=$((i+1));
        sleep 1;
      done
    image: busybox
    imagePullPolicy: IfNotPresent
    name: count
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-7m2k4
      readOnly: true
    - name: varlog
      mountPath: /var/log
  - name: sidecar
    image: busybox
    imagePullPolicy: IfNotPresent
    args: [/bin/sh, -c, 'tail -n+1 -f /var/log/11-factor-app.log']
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: node01
  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-7m2k4
    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
  - name: varlog
    emptyDir: {}
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2022-07-17T10:25:09Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2023-02-16T01:56:23Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2023-02-16T01:56:23Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2022-07-17T10:25:09Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: containerd://5ebc410712146c1c32f5f6c325cb3637997ce1f9bb101d36bb91d2ae9b5603b3
    image: docker.io/library/busybox:latest
    imageID: sha256:62aedd01bd8520c43d06b09f7a0f67ba9720bdc04631a8242c65ea995f3ecac8
    lastState:
      terminated:
        containerID: containerd://0d7c9f4c0be1c2360b470e9644b550e9153807d7487a7c38df9acc83969b745b
        exitCode: 255
        finishedAt: "2023-02-16T01:55:20Z"
        reason: Unknown
        startedAt: "2022-08-26T07:19:27Z"
    name: count
    ready: true
    restartCount: 7
    started: true
    state:
      running:
        startedAt: "2023-02-16T01:56:23Z"
  hostIP: 11.0.1.112
  phase: Running
  podIP: 10.244.196.175
  podIPs:
  - ip: 10.244.196.175
  qosClass: BestEffort
  startTime: "2022-07-17T10:25:09Z"
candidate@node01:~/k8sYaml$ 

打印 volumes 的 emptyDir 在节点 node1 上的位置:

root@node01:~# find / -name varlog
/var/lib/kubelet/pods/fd1bfe55-8d60-40c8-b6b9-e185b4ba89a7/volumes/kubernetes.io~empty-dir/varlog
/var/lib/kubelet/pods/fd1bfe55-8d60-40c8-b6b9-e185b4ba89a7/plugins/kubernetes.io~empty-dir/varlog
root@node01:~# cd /var/lib/kubelet/pods/fd1bfe55-8d60-40c8-b6b9-e185b4ba89a7/volumes/kubernetes.io~empty-dir/varlog
root@node01:/var/lib/kubelet/pods/fd1bfe55-8d60-40c8-b6b9-e185b4ba89a7/volumes/kubernetes.io~empty-dir/varlog# ls -l
total 48
-rw-r--r-- 1 root root 44325 Feb 16 16:12 11-factor-app.log
root@node01:/var/lib/kubelet/pods/fd1bfe55-8d60-40c8-b6b9-e185b4ba89a7/volumes/kubernetes.io~empty-dir/varlog# tail -n 10 11-factor-app.log 
Thu Feb 16 08:12:15 UTC 2023 INFO 1168
Thu Feb 16 08:12:16 UTC 2023 INFO 1169
Thu Feb 16 08:12:17 UTC 2023 INFO 1170
Thu Feb 16 08:12:18 UTC 2023 INFO 1171
Thu Feb 16 08:12:19 UTC 2023 INFO 1172
Thu Feb 16 08:12:20 UTC 2023 INFO 1173
Thu Feb 16 08:12:21 UTC 2023 INFO 1174
Thu Feb 16 08:12:22 UTC 2023 INFO 1175
Thu Feb 16 08:12:23 UTC 2023 INFO 1176
Thu Feb 16 08:12:24 UTC 2023 INFO 1177
root@node01:/var/lib/kubelet/pods/fd1bfe55-8d60-40c8-b6b9-e185b4ba89a7/volumes/kubernetes.io~empty-dir/varlog# 

知识延伸:

Docker 也有卷(Volume) 的概念,但对它只有少量且松散的管理。 Docker 卷是磁盘上或者另外一个容器内的一个目录。 Docker 提供卷驱动程序,但是其功能非常有限。

Kubernetes 支持很多类型的卷。 Pod 可以同时使用任意数目的卷类型。 临时卷类型的生命周期与 Pod 相同,但持久卷可以比 Pod 的存活期长。 当 Pod 不再存在时,Kubernetes 也会销毁临时卷;不过 Kubernetes 不会销毁持久卷。 对于给定 Pod 中任何类型的卷,在容器重启期间数据都不会丢失。

卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。

使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的容器镜像 的初始内容以及挂载在容器中的卷(如果定义了的话)所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作,如果被允许的话,都会影响接下来容器中进程访问文件系统时所看到的内容。

卷挂载在镜像中的指定路径下。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。

emptyDir

emptyDir的生命周期与所属的pod相同。pod删除时,其emptyDir中的数据也会被删除。

emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配 一个目录,因此无需指定宿主机node上对应的目录文件

emptyDir Volume主要用于某些应用程序无需永久保存的临时目录,多个容器的共享目录等。

下面是一个pod挂载emptyDir的示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - image: test-webserver
    name: test-container
    volumeMounts:
    - name: cache-volume
      mountPath: /cache
  volumes:
  - name: cache-volume
    emptyDir: {}

相关文章:
互联网最全cka真题解析-2022.9.9
Kubernetes官方文档
k8s 卷 volumes | 官方文档
ETCD文档

为者常成,行者常至