惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
C
Cisco Blogs
The Hacker News
The Hacker News
T
Threatpost
S
Schneier on Security
K
Kaspersky official blog
Spread Privacy
Spread Privacy
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
NISL@THU
NISL@THU
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
Security Latest
Security Latest
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
News and Events Feed by Topic
爱范儿
爱范儿
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Project Zero
Project Zero
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
GbyAI
GbyAI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Apple Machine Learning Research
Apple Machine Learning Research
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
Forbes - Security
Forbes - Security
博客园 - 三生石上(FineUI控件)
C
Cyber Attacks, Cyber Crime and Cyber Security
N
News and Events Feed by Topic
V
V2EX
Webroot Blog
Webroot Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
Scott Helme
Scott Helme
Simon Willison's Weblog
Simon Willison's Weblog
L
LangChain Blog
W
WeLiveSecurity
Cloudbric
Cloudbric

lvbibir's Blog

shell | 磁盘空间分析脚本 Linux cat 和 tee 命令写入文件 python | 使用 uv 管理你的 python 环境 Claude Code 完整配置指南 windows | mihomo 内核独立部署指南 linux | 磁盘扩容 wsl | 释放长久运行占用的磁盘空间 mysql | 线程上限问题处理 麒麟 7.6 安装谷歌 OTP 认证模块 suse 12sp5 升级 openssh 及 openssl suse 12sp5 部署 mysql 5.7 《谁的青春不迷茫》 docker | centos7 部署 docker vim | 基础配置和使用 windows | rime 输入法 & 雾凇方案 shell | sshpass 批量传输文件及执行命令 wsl | 原生 linux 方式安装 docker nodejs | fnm + pnpm 开发环境配置 wsl | 安装配置 miniconda 虚拟环境 wsl | 自动更新系统代理 wsl | bashrc 环境变量不正确加载的处理方法 wsl | win10 安装 wsl2 troubleshooting | ssh 成功但是 scp 失败 linux | 常用命令总结 docker 部署 piclist shell | 检测网站存活并自动钉钉告警 Zabbix | 监控端口连通性并自动追踪 TCP 路由 windows | 自定义开机快速启动项 windows | miniconda 配置 python 虚拟环境 Zabbix | 监控主机到指定 ip 的流量大小 shell | centos 初始化 loki (二) 部署 loki (一) 简介 prometheus (六) Alertmanager prometheus (五) 记录规则与告警规则 prometheus (四) 黑盒监控 prometheus (三) 服务发现 prometheus (二) 静态配置 prometheus (一) 简介及部署 traefik (四) TraefikService 服务 traefik (三) Middleware 中间件 traefik (二) ingressRoute 路由 traefik (一) 简介、部署和配置 kubernetes | Gateway API 简介及部署 linux | dns 配置文件中 search 和 options ndots 详解 kubernetes | command args 和 dockerfile 中的 ENTRYPOINT CMD kubernetes | statefulset 控制器详解 docker | dockerfile 最佳实践 docker | dockerfile 指令详解 linux | kill 命令详解以及 linux 中的信号 troubleshooting | elasticsearch 安装插件报错 shell | if 条件判断 docker | 下载外网镜像的几种方式 python | 鬼谷子数学问题 steam挂刀教程 linux | history 命令的格式化输出 shell | 将本地镜像批量推送到 harbor windows | hosts 文件修复 kubernetes | configmap & secret kubernetes | RBAC 鉴权和 NetworkPolicy kubernetes | service & ingress kubernetes | 滚动升级和自动伸缩 kubernetes | 控制器 kubernetes | 日志 kubernetes | 调度 kubernetes | pod kubernetes | 杂记 linux | set 命令详解 ceph | openeuler 部署 ceph-v16 ceph | ceph-v16 离线安装解决方案 pxe 如何应对复杂的服务器硬件环境 python | 批量修改目录下文件名 《微习惯》 ceph | openeuler (aarch64) 部署 ceph-v16 troubleshooting | glibc 误升级后修复 pxe 安装配置大全 《人间失格》 跑步日常 [置顶] Hello, hugo! shell | 检索某 url 中所有文件的内容 shell | 不同执行方式的区别 shell | 开启 debug 模式 vscode | 常见问题 windows & linux 多网卡时设置默认路由以及添加静态路由 mysql (二) 主从复制原理 GTID 并行复制 mysql (一) 部署 mysql | 杂记 cicd | jenkins 部署 mall-swarm 项目 httpd 源码打包编译成 rpm 包 openssl 源码打包编译成 rpm 包 centos7 | 修改网卡名称 ceph | pool pg_num 配置 docker | 脚本方式批量导出/导入镜像 centos 密码尝试次数过多问题处理 centos7 | 升级内核至 5.10 CVE-1999-0526 ceph | centos7 部署 ceph-v12 python | 修改 pip 源 troubleshooting | 安装 cloud-init 后导致 ssh 连接失败 windows | autohotkey 常用脚本
kubernetes | 存储
lvbibir · 2022-10-07 · via lvbibir's Blog

0 前言

基于 centos7.9docker-ce-20.10.18kubelet-1.22.3-0

为什么需要数据卷

  1. 启动时需要的初始数据,录入配置文件
  2. 启动过程中产生的临时数据,该临时数据需要多个容器间共享
  3. 启动过程中产生的持久化数据,例如 mysql 的 data

数据卷概述

  • kubernetes 中的 volume 提供了在容器中挂载外部存储的能力
  • Pod 需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的 Volume

常用的数据卷:

  • 本地(hostPath,emptyDir)
  • 网络(NFS,Ceph,GlusterFS)
  • 公有云(AWS EBS)
  • K8S 资源(configmap,secret)

1 emptyDir(临时存储卷)

emptyDir 卷:是一个临时存储卷,与 Pod 生命周期绑定一起,如果 Pod 删除了卷也会被删除。

应用场景:Pod 中容器之间数据共享

emptyDir 的实际存储路径在 pod 所在节点的 /var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~empty-dir 目录下

查看 pod 的 uid

kubectl get pod <pod-name> -o jsonpath='{.metadata.uid}'

示例如下

apiVersion: v1
kind: Pod
metadata:
  name: demo-emptydir
spec:
  terminationGracePeriodSeconds: 5
  containers:
  - name: write
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "for i in $(seq 100); do echo $i >> /data/hello; sleep 1; done"]
    volumeMounts:
    - name: data
      mountPath: /data
  - name: read
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "tail -f /data/hello"]
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    emptyDir: {}

查看日志

[root@k8s-node1 ~]# kubectl logs -f demo-emptydir -c read 
1
2
3
...

2 hostPath(节点存储卷)

hostPath 卷:挂载 Node 文件系统(Pod 所在节点)上文件或者目录到 Pod 中的容器。

应用场景:Pod 中容器需要访问宿主机文件

示例 yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-hostpath
spec:
  terminationGracePeriodSeconds: 5
  containers:
  - name: busybox
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh", "-c", "sleep 36000"]
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    hostPath:
      path: /tmp
      type: Directory

3 NFS(网络存储卷)

NFS 卷提供对 NFS 挂载支持,可以自动将 NFS 共享路径挂载到 Pod 中

配置 nfs 服务端,

yum install nfs-utils # nfs-utils包每个节点都需安装
mkdir -p /nfs
echo "/nfs 1.1.1.0/24(rw,async,no_root_squash)" >> /etc/exports
# 格式:NFS共享的目录 客户端地址1(参数1,参数2,...) 客户端地址2(参数1,参数2,...))
systemctl enable --now nfs
systemctl enable --now rpcbind
  • 常用选项:
    • ro:客户端挂载后,其权限为只读,默认选项;
    • rw: 读写权限;
    • sync:同时将数据写入到内存与硬盘中;
    • async:异步,优先将数据保存到内存,然后再写入硬盘;
    • Secure:要求请求源的端口小于 1024
  • 用户映射:
    • root_squash: 当 NFS 客户端使用 root 用户访问时,映射到 NFS 服务器的匿名用户;
    • no_root_squash: 当 NFS 客户端使用 root 用户访问时,映射到 NFS 服务器的 root 用户;
    • all_squash: 全部用户都映射为服务器端的匿名用户;
    • anonuid=UID:将客户端登录用户映射为此处指定的用户 uid;
    • anongid=GID:将客户端登录用户映射为此处指定的用户 gid

客户端测试

[root@k8s-node2 ~]# mount -t nfs k8s-node1:/nfs /mnt/
[root@k8s-node2 ~]# df -hT | grep k8s-node1
k8s-node1:/nfs nfs4       44G  4.0G   41G   9% /mnt

示例 yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-nfs
  labels:
    app: demo-nfs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-nfs
  template:
    metadata:
      labels:
        app: demo-nfs
    spec:
      terminationGracePeriodSeconds: 5
      containers:
      - name: demo-nfs
        image: nginx:1.22.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: www
        nfs:
          server: k8s-node1
          path: /nfs/
---
apiVersion: v1
kind: Service
metadata:
  name: demo-nfs
  labels:
    app: demo-nfs
spec:
  selector:
    app: demo-nfs
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30003
  type: NodePort

验证

[root@k8s-node1 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
demo-nfs     NodePort    10.97.209.119   <none>        80:30003/TCP   5m41s
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        5d2h
[root@k8s-node1 ~]# echo "hello, nfs" > /nfs/index.html
[root@k8s-node1 ~]# curl 10.97.209.119
hello, nfs

4 pv 和 pvc(持久存储卷)

4.1 基础概念

  • PersistentVolume(PV):存储资源创建和使用抽象化,使得存储作为集群中的资源管理
  • PersistentVolumeClaim(PVC):让用户不需要关心具体的 Volume 实现细节

image-20221006103106669

pvc 如何匹配到 pv

  • 存储空间的请求
    • 匹配最接近的 pv,如果没有满足条件的 pv,则 pod 处于 pending 状态
  • 访问模式的设置

存储空间字段能否限制实际可用容量

  • 不能,存储空间字段只用于匹配到 pv,具体可用容量取决于网络存储

4.2 pv 生命周期

AccessModes(访问模式):

AccessModes 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

  • ReadWriteOnce(RWO):可被一个 node 读写挂载
  • ReadOnlyMany(ROX):可被多个 node 只读挂载
  • ReadWriteMany(RWX):可被多个 node 读写挂载

RECLAIM POLICY(回收策略):

目前 PV 支持的策略有三种:

  • Retain(保留): 保留数据,需要管理员手工清理数据
  • Recycle(回收):清除 PV 中的数据,效果相当于执行 rm -rf /ifs/kuberneres/*
  • Delete(删除):与 PV 相连的后端存储同时删除

STATUS(状态):

一个 PV 的生命周期中,可能会处于 4 中不同的阶段:

  • Available(可用):表示可用状态,还未被任何 PVC 绑定
  • Bound(已绑定):表示 PV 已经被 PVC 绑定
  • Released(已释放):PVC 被删除,但是资源还未被集群重新声明
  • Failed(失败): 表示该 PV 的自动回收失败

pv 示例

apiVersion: v1
kind: PersistentVolume
metadata:
  name: demo-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
  - ReadWriteMany
  nfs:
    server: k8s-node1
    path: /nfs

pvc 示例

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: demo-pvc
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

deployment & service 示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-pvc
  labels:
    app: demo-pvc
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-pvc
  template:
    metadata:
      labels:
        app: demo-pvc
    spec:
      terminationGracePeriodSeconds: 5
      containers:
      - name: demo-pvc
        image: nginx:1.22.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www-pvc
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: www-pvc
        persistentVolumeClaim:
          claimName: demo-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: demo-pvc
  labels:
    app: demo-pvc
spec:
  selector:
    app: demo-pvc
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

验证

[root@k8s-node1 ~]# echo "pvc for NFS is successful" > /nfs/index.html
[root@k8s-node1 ~]# kubectl get svc -l app=demo-pvc
NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
demo-pvc   ClusterIP   10.97.28.93   <none>        80/TCP    102s
[root@k8s-node1 ~]# curl 10.97.28.93
pvc for NFS is successful

4.3 pv 动态供给

之前的 PV 使用方式称为静态供给,需要 K8s 运维工程师提前创建一堆 PV,供开发者使用

因此,K8s 开始支持 PV 动态供给,使用 StorageClass 对象实现。

查看 k8s 原生支持的共享存储

image-20221006112111133

基于 NFS 实现自动创建 pv 插件

自动创建的 pv 挂载路径为 <nfs-path>/<namespace>-<pvc-name>-<pv-name>

  • pvc-name:默认情况下为 yaml 中自定义的 pvc-name,使用 statefulset 控制器时 pvc 的名字为 <volumeClaimTemplates-name>-<pod-name>
  • pv-name:pv 的名字为 pvc-<pvc-uid>

k8s-1.20 版本后默认禁止使用 selfLink,需要打开一下

修改 k8s 的 apiserver 参数,改完 apiserver 会自动重启

[root@k8s-node1 ~]#  vi /etc/kubernetes/manifests/kube-apiserver.yaml
apiVersion: v1
···
    - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
    - --feature-gates=RemoveSelfLink=false # 添加这个配置

4.3.1 部署 NFS 插件

此组件是对 nfs-client-provisioner 的扩展,nfs-client-provisioner 已经不提供更新,且 nfs-client-provisioner 的 Github 仓库已经迁移到 NFS-Subdir-External-Provisioner 的仓库

rbac

创建 nfs-rbac.yml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: kube-system
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  namespace: kube-system
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: kube-system
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

nfs-subdir-external-provisioner

创建 nfs-provisioner-deploy.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: kube-system
  labels:
    app: nfs-client-provisioner
spec:
  replicas: 1
  strategy: 
    type: Recreate     # 设置升级策略为删除再创建(默认为滚动更新)
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
      - name: nfs-client-provisioner
        #image: gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0
        image: registry.cn-hangzhou.aliyuncs.com/lvbibir/nfs-subdir-external-provisioner:v4.0.2
        volumeMounts:
        - name: nfs-client-root
          mountPath: /persistentvolumes
        env:
        - name: PROVISIONER_NAME     # Provisioner的名称,以后设置的storageclass要和这个保持一致
          value: nfs-client 
        - name: NFS_SERVER           # NFS服务器地址,需和valumes参数中配置的保持一致
          value: 1.1.1.1
        - name: NFS_PATH             # NFS服务器数据存储目录,需和valumes参数中配置的保持一致
          value: /nfs/kubernetes
      volumes:
      - name: nfs-client-root
        nfs:
          server: 1.1.1.1            # NFS服务器地址
          path: /nfs/kubernetes      # NFS服务器数据存储目录

storageClass

创建 nfs-sc.yml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"  ## 是否设置为默认的storageclass
provisioner: nfs-client                                   ## 动态卷分配者名称,必须和deployment的PROVISIONER_NAME变量中设置的Name一致
parameters:
  archiveOnDelete: "false"                                 ## 设置为"false"时删除PVC不会保留数据,"true"则保留数据
mountOptions: 
  - hard                                                  ## 指定为硬挂载方式
  - nfsvers=4                                             ## 指定NFS版本,这个需要根据NFS Server版本号设置

创建上述资源

[root@k8s-node1 nfs]# mkdir /nfs/kubernetes/
[root@k8s-node1 nfs]# kubectl apply -f .
deployment.apps/nfs-client-provisioner created
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
storageclass.storage.k8s.io/nfs created

4.3.2 示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-auto-pv
  labels:
    app: demo-auto-pv
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-auto-pv
  template:
    metadata:
      labels:
        app: demo-auto-pv
    spec:
      terminationGracePeriodSeconds: 5
      containers:
      - name: demo-auto-pv
        image: nginx:1.22.1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html/
      volumes:
      - name: www
        persistentVolumeClaim:
          claimName: pvc-auto
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-auto
spec:
  storageClassName: "nfs"
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi

测试验证

[root@k8s-node1 ~]# kubectl get pods
NAME                                          READY   STATUS    RESTARTS   AGE
pod/demo-auto-pv-7c974689b4-4cwr6             1/1     Running   0          47s
pod/demo-auto-pv-7c974689b4-bb9v8             1/1     Running   0          47s
pod/demo-auto-pv-7c974689b4-p525n             1/1     Running   0          47s
pod/nfs-client-provisioner-66d6cb77fd-47hsf   1/1     Running   0          4m15s
[root@k8s-node1 ~]# kubectl get pvc
NAME                             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
persistentvolumeclaim/pvc-auto   Bound    pvc-22b65e10-ab97-47eb-aaa1-6c354a749a55   2Gi        RWO            managed-nfs-storage   47s
[root@k8s-node1 ~]# kubectl get pv
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS          REASON   AGE
persistentvolume/pvc-22b65e10-ab97-47eb-aaa1-6c354a749a55   2Gi        RWO            Delete           Bound    default/pvc-auto   managed-nfs-storage            47s
[root@k8s-node1 ~]# ls -l /nfs/
total 4
drwxrwxrwx. 2 root root  6 Apr 11 17:37 default-pvc-auto-pvc-22b65e10-ab97-47eb-aaa1-6c354a749a55

以上