Kubernetes存储卷与进阶功能详解

Pod容器数据持久化方案之emptyDir

概念

  • emptyDir是一个空目录,用于将容器的数据做临时的存储。
  • 应用场景多用于一个Pod内多个容器共享数据的场景。
  • 特点就是随着Pod删除,其数据丢失。

资源清单模板:一个pod容器做数据存储

[root@master231 volumes]# cat 01-pods-emptyDir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volumes-emptydir
spec:
  nodeName: worker232
  # 定义存储卷
  volumes:
    # 定义存储卷的名称
  - name: data
    # 指定存储卷类型为emptyDir,本质上是在Pod的数据目录中创建一个临时目录。
    # 该目录随着Pod删除(是pod,不是docker进程),目录的数据也会一并删除!
    emptyDir: {}

  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2

    # 容器引用Pod定义的存储卷
    volumeMounts:
      # 引用存储卷的名称
    - name: data
      # 指定挂载点,如果挂载点之前存在数据则会清空该目录数据。
      mountPath: /usr/share/nginx/html

资源清单模板:两个pod做数据共享

  1. 编写资源清单:挂载到同一个存储卷叫data,假如c1往它挂载的目录下的文件写数据,c2可以看到。
[root@master231 volumes]# cat 02-pods-emptyDir-multiple.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volumes-multiple-emptydir
spec:
  nodeName: worker232
  volumes:
  - name: data
    emptyDir: {}

  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    volumeMounts:
    - name: data
      mountPath: /oldboyedu

  - name: c2
    image: harbor250.oldboyedu.com/oldboyedu-elasticstack/filebeat:7.17.25
    volumeMounts:
    - name: data
      mountPath: /linux99/xixi

测试

测试1:删除docker业务容器c1,发现重新启动后数据也在。删除pod后,数据丢失。

# 验证:查看数据存储的实际路径
ll /var/lib/kubelet/pods/dd8856e4-fee3-463f-a6da-56320d7f7f0b/volumes/kubernetes.io~empty-dir/
# 本质上数据存储在该目录下。

测试2:在c1写入数据,c2对应的挂载目录可以看到。

[root@master231 volumes]# kubectl exec -it volumes-multiple-emptydir -c c1 -- sh
for i in `seq 1000`;do sleep 0.5;echo $i >> /oldboyedu/haha.log;done &

测试3:c2采集c1的数据。

filebeat@volumes-multiple-emptydir:~$ cat > /tmp/test.conf <<EOF
filebeat.inputs:
- type: filestream
  paths:
    - /linux99/xixi/haha.log
output.console:
  pretty: true
EOF

Pod容器数据持久化方案之hostPath

概念

hostPath主要作用就是让Pod的容器访问worker节点宿主机的某个特定路径。删除pod后数据目录依旧存在。

资源清单

# 在worker节点上创建目录和文件
[root@worker233 ~]# mkdir /data
[root@worker233 ~]# echo www.oldboyedu.com > /data/index.html
[root@worker233 ~]# ls -l /data/
# 资源清单:此时 /usr/share/nginx/html 和 /data/ 里的数据一致
[root@master231 volumes]# cat 05-pods-hostPath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volumes-hostpath
spec:
  nodeName: worker233
  volumes:
  - name: data
    # 指定存储卷的类型是hostPath,并指定worker宿主机的路径
    hostPath:
      path: /data
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    volumeMounts:
    - name: data
      mountPath: /usr/share/nginx/html

测试

修改容器的数据

[root@master231 volumes]# kubectl exec -it volumes-hostpath -- sh
/ # echo linux99 > /usr/share/nginx/html/index.html
/ #
[root@master231 volumes]# curl 10.100.2.86
linux99

验证worker宿主机的数据是否变化:发生了变化,因为指向同一个数据。

[root@worker233 ~]# cat /data/index.html
linux99

存储卷之DownwardAPI实战

概念

DownwardAPI只是一种将Pod的metadata、spec或status中的字段值注入到其内部Container里的方式。

资源清单模板

功能:注入两个环境变量进容器,在启动业务容器之前就可以进行注入。

[root@master231 volumes]# cat 03-pods-downwardAPI-env.yaml  # 这个案例记住
apiVersion: v1
kind: Pod
metadata:
  name: volumes-downwardapi-env
spec:
  nodeName: worker232
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    env:
    - name: oldboyedu-PODNAME
      # 值表示从一个地方引用
      valueFrom:
        # 基于字段引用
        fieldRef:
          # 指的字段的路径
          fieldPath: metadata.name

    - name: oldboyedu-IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP

测试

进入容器查看环境变量是否存在:

[root@master231 volumes]# kubectl exec -it volumes-downwardapi-env -- env | grep oldboyedu
oldboyedu-PODNAME=volumes-downwardapi-env
oldboyedu-IP=10.100.1.29

初始化容器实战

概念

  1. 什么是初始化容器:先有基础架构容器,然后跑初始化容器,最后有业务容器。
  2. 所谓的初始化容器就是为Pod提供初始化的相关操作,在基础架构容器启动后先执行所有的初始化容器。
  3. 当所有的初始化容器执行完成后,才能执行业务容器。因此,初始化容器可以定义多个。

资源清单主要是格式

[root@master231 pods]# cat 12-pods-initContainers.yaml
apiVersion: v1
kind: Pod
metadata:
  name: initcontainers-casedemo
spec:
  # 初始化容器定义
  initContainers:
  - name: i1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    command:
    - sleep
    - "10"

  - name: i2
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    command:
    - sleep
    - "30"
  # 业务容器定义
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2

测试:查看节点的启动顺序

# 2.3 查看worker节点的容器创建顺序
[root@worker233 ~]# docker ps -a | grep initcontainers-casedemo
95c2d9178ebe   d65adc8a2f32                                        "sleep 30"               14 seconds ago   Up 13 seconds                         k8s_i2_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0
22085e7c4d7a   d65adc8a2f32                                        "sleep 10"               25 seconds ago   Exited (0) 14 seconds ago             k8s_i1_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0
63dbd311539a   registry.aliyuncs.com/google_containers/pause:3.6   "/pause"                 25 seconds ago   Up 24 seconds                         k8s_POD_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0

[root@worker233 ~]# docker ps -a | grep initcontainers-casedemo
6c5d74ba481b   d65adc8a2f32                                        "/docker-entrypoint.…"   8 seconds ago    Up 7 seconds                    (业务容器)      k8s_c1_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0
95c2d9178ebe   d65adc8a2f32                                        "sleep 30"               38 seconds ago   Exited (0) 7 seconds ago              k8s_i2_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0
22085e7c4d7a   d65adc8a2f32                                        "sleep 10"               49 seconds ago   Exited (0) 38 seconds ago      (初始化容器)       k8s_i1_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0
63dbd311539a   registry.aliyuncs.com/google_containers/pause:3.6   "/pause"                 49 seconds ago   Up 48 seconds           (基础架构容器)              k8s_POD_initcontainers-casedemo_default_82e809a0-d078-4f6b-9e7d-cb0b13e2d067_0

综合案例:rc, downwardApi, emptyDir, svc

需求

初始化nginx的站点首页,要求如下:

    1. 使用rc控制器创建3个副本的Pod;
    1. 首页文件(“index.html”)返回获取各个Pod的IP地址,Pod的名称;
    1. 使用Service暴露服务,并基于Service访问测试;

编写资源清单

[root@master231 case-demo]# cat 01-rc-svc-downwardAPI-volume-initContainers.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: rc-xiuxian
spec:
  replicas: 3
  selector:
    version: v1
  # 定义副本的模板
  template:
    metadata:
      labels:
        app: xiuxian
        version: v1
    # 定义存储卷,连接了data的目录都可以实现数据的共享
    spec:
      volumes:
      - name: data
        emptyDir: {}
      # 初始化容器的时候注入一些环境变量,并将它挂载到对应的/data目录
      initContainers:
      - name: i1
        image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
        volumeMounts:
        - name: data
          mountPath: /data
        # 环境变量
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        # 命令执行,在启动业务容器之前就把两个环境变量注入到文件data目录下的文件中
        command:
        - /bin/sh
        - -c
        - echo "${POD_NAME}, ${POD_IP}" > /data/index.html
      # 启动业务容器,共享目录连接存储卷/data,该文件可以查看到环境变量
      containers:
      - name: c1
        image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
        ports:
        - containerPort: 80
          name: web

        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
---
# 进行service,实现服务发现,负载,和外部进行访问的作用。即使pod重启clusterIP进行变化,依旧可以访问service的IP查看
apiVersion: v1
kind: Service
metadata:
  name: svc-xiuxian-nodeport
spec:
  type: NodePort
  selector:
    app: xiuxian
  ports:
  - port: 80
    targetPort: web
    nodePort: 30081

测试

[root@master231 case-demo]# kubectl get rc,svc,po -o wide

[root@master231 case-demo]# for i in `seq 10`; do curl 10.0.0.233:30081;done
rc-xiuxian-mj9hf, 10.100.1.40
rc-xiuxian-2qwm8, 10.100.2.78
rc-xiuxian-mj9hf, 10.100.1.40
rc-xiuxian-hmftr, 10.100.2.77
rc-xiuxian-2qwm8, 10.100.2.78
rc-xiuxian-hmftr, 10.100.2.77
rc-xiuxian-2qwm8, 10.100.2.78
rc-xiuxian-hmftr, 10.100.2.77
rc-xiuxian-mj9hf, 10.100.1.40
rc-xiuxian-2qwm8, 10.100.2.78

名称空间

概念

说白了,就是用来隔离K8S集群资源的。但并不是所有的资源都支持名称空间进行隔离,不支持名称空间的资源我们称之为全局资源,支持名称空间的资源称之为局部资源。

命令行操作

# 查看现有的名称空间
kubectl get ns
# 或者
kubectl get ns -o wide

# 创建名称空间
kubectl create ns xixi

# 查看名称空间的标签
kubectl get ns --show-labels

# 删除名称空间
kubectl delete ns xixi

# 查看指定名称空间的资源
kubectl get po -o wide --namespace kube-system
# 或者直接
kubectl get po -o wide -n kube-system

在指定的名称空间下创建pod

[root@master231 namespace]# cat 01-pods-ns.yaml
apiVersion: v1
kind: Pod
metadata:
  name: xixi
  # 指定资源的名称空间,若不指定,则默认为default
  namespace: kube-public
spec:
  containers:
  - name: c1
    image: registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
# 查看指定名称空间的pod
kubectl get pods -n kube-public -o wide

删除名称空间

kubectl delete ns oldboyedu  # 删除名称空间,它下面的pod都被删除

全局资源在任意名称空间查看的结果都相同

kubectl get nodes = kubectl get nodes -n kube-system

查看所有名称空间的资源

kubectl get po -A
kubectl get svc -A

kuboard管理k8s集群实战(见笔记)

2. 下载镜像

[root@harbor250 ~]# wget http://192.168.16.253/Resources/Kubernetes/Project/kuboard/kuboard-on-docker/oldboyedu-kuboard-v3.tar.gz
[root@harbor250 ~]# docker load -i oldboyedu-kuboard-v3.tar.gz

3. 安装kuboard

[root@harbor250 ~]# docker run -d \
  --restart=unless-stopped \
  --privileged \
  --name=kuboard \
  -p 90:80/tcp \
  -p 10081:10081/tcp \
  -e KUBOARD_ENDPOINT="http://10.0.0.250:90" \
  -e KUBOARD_AGENT_SERVER_TCP_PORT="10081" \
  -v /root/kuboard-data:/data \
  swr.cn-east-2.myhuaweicloud.com/kuboard/kuboard:v3

4. 访问Kuboard

http://10.0.0.250:90/

5. 登录

  • 用户名:admin
  • 密 码:Kuboard123

6. 添加K8S集群并且创建工作负载

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

静态pod技术

概念

所谓的静态Pod指的是kubelet组件无需经过API-server发号指令,而自发监控一个本地的宿主机路径下的资源清单。该路径下的所有Pod类型的资源清单都会自动被识别,并创建相应的Pod。创建的Pod名称后会自动加一个"-${NODENAME}“,例如:”-master231",“-worker233”。

测试

其他worker节点使用静态Pod技术:将资源清单移动到别的节点静态pod目录下,那么会直接运行该资源清单。

[root@master231 pods]# scp 01-pods-single-xiuxian.yaml 10.0.0.232:/etc/kubernetes/manifests
[root@master231 pods]# scp 01-pods-single-xiuxian.yaml 10.0.0.233:/etc/kubernetes/manifests

[root@master231 pods]# kubectl get pods -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
xixi-worker232   1/1     Running   0          1s    10.100.1.44   worker232   <none>           <none>
xixi-worker233   1/1     Running   0          21s   10.100.2.85   worker233   <none>           <none>

只能将目录删除或者移走才能删除静态pod,无法手动删除。

为什么注入环境变量要在初始化容器的时候完成,而不在启动业务容器的时候完成?

初始化容器的价值在于"前置准备,扫清障碍",确保业务容器启动时就能"开箱即用"。
如果将环境变量注入放到业务容器启动后,会引入竞态条件和服务不可用的风险,违背K8s容器设计的最佳实践。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐