存储与资源

2024/05/28

配置

配置最佳实践

Secret

Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。将这些信息放在 Secret 中会更加的灵活和安全。

k8s可以创建三种类型的 Secret:

$ kubectl create secret --help Available Commands: docker-registry 创建一个给 Docker registry 使用的 Secret generic Create a secret from a local file, directory, or literal value tls 创建一个 TLS secret
bash

docker-registry

创建一个 docker 镜像的拉取秘钥。

用法:

$ kubectl create secret docker-registry NAME --docker-username=user --docker-password=password --docker-email=email \ [--docker-server=string] [--from-file=[key=]source] [--dry-run=server|client|none] [options]
bash

一般只需要提供如下参数:

  • docker-username: 用户名
  • docker-password: 密码
  • docker-server:私有仓库服务器

创建完成后,可以直接在 Pod 的 spec.imagePullSecrets 中使用:

kind: Pod spec: imagePullSecrets: - name: secret-name1 - name: secret-name2
yaml

generic

genericsecret 一般有下面的几种类型:

内置类型用法
Opaque用户定义的任意数据
kubernetes.io/service-account-token服务账号令牌
kubernetes.io/dockercfg~/.dockercfg文件的序列化形式
kubernetes.io/dockerconfigjson~/.docker/config.json 文件的序列化形式
kubernetes.io/basic-auth用于基本身份认证的凭据
kubernetes.io/ssh-auth用于SSH身份认证的凭据
kubernetes.io/tls用于TLS客户端或者服务器端的数据
bootstrap.kubernetes.io/token启动引导令牌数据

常见用例:

kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-iteral=password=abc123 ## 生成如下的yaml apiVersion: v1 kind: Secret metadata: name dev-db-secret data: password: <base64: devuser> username: <base64: abc123>
bash

使用Secret

可以通过环境变量使用 Secret:

apiVersion: v1 kind: Pod metadata: name: pod-secret spec: containers: - name: pod-secret image: busybox command: ["sh", "echo", "$MY_SECRET_ENV"] env: # 通过环境变量使用Secret - name: MY_SECRET_ENV valueFrom: secretKeyRef: name: <secret-name> key: <secret-key>
yaml

引用配置

使用kubectl explain pod.spec.containers.env.valueFrom既可查看所有能够引用的类型。

apiVersion: v1 kind: Pod metadata: name: pod-test spec: containers: - name: pod-test image: busybox resources: limits: cpu: 5m env: - name: SECRET_REF valueFrom: # 引用一个 Secret secretKeyRef: name: <secret-name> key: <secret-key> - name: FIELD_REF valueFrom: # 引用一个属性 fieldRef: fieldPath: metadata.name - name: RESOURCE_REF valueFrom: # 引用一个资源 resourceFieldRef: containerName: pod-test resource: limit.cpu
yaml
  • filedRef可用值:metadata.name, metadata.namespace, metadata.labels['<KEY>'], metadata.annotations['<KEY>'], spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs
  • resourceFieldRef可用值: limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage

环境变量引用的方式不会被自动更新

PVC

持久卷

PVC 用于抽象存储,当 Pod 需要使用一块空间时只需要申请就可以了,并不需要关心这块存储是如何实现的,只需提供自己所需要的空间,K8s就能够自动进行分配。

申请一块存储空间

kubectl explain pod.spec.volumes.persistentVolumeClaim

apiVerson: v1 kind: Pod spec: volumes: - name: pvc # 申请一个持久卷,关联一个PV(PersistentVolume) persistentVolumeClaim: # 指定一份申请书 (PVC) claimName: my-pvc --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: storageClassName: <storage-class-name> accessModes: - ReadWriteOnce resources: requests: # 申请 50 MB storage: 50m
yaml

创建 PV 池

静态供应

PV 池可以提前被创建好,使用下面的 yaml 就可以创建一个 PV:

apiVersion: v1 kind: PersistentVolume metadata: name: my-pv spec: # 可以填任意名称 storageClassName: my-storage-class-name capacity: # 存储空间 storage: 10m accessModes: - ReadWriteOnce # 使用 hostPath 存储 hostPath: path: "/mnt/data" # 或者使用 nfs 存储 nfs: server: 10.0.0.1 path: /nfs/data/abc
yaml

storageClassName 用于分组,一个 storageClassName 下可以创建多个 PV。

动态供应

动态供应,则是把应该由运维手动创建的 PV 转交给 provisioner(供应商) 来进行创建。


使用 nfs 进行供应:文档

使用手动部署方式,进入仓库的 /deploy 文件夹,里面的 class.yamldeployment.yamlrbac.yaml.

apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME' parameters: archiveOnDelete: "false" --- apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: default 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: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: # 和上面的 StorageClass 的 provisioner 值对应 - name: PROVISIONER_NAME value: k8s-sigs.io/nfs-subdir-external-provisioner - name: NFS_SERVER value: 10.3.243.101 - name: NFS_PATH value: /ifs/kubernetes volumes: - name: nfs-client-root nfs: server: 10.3.243.101 path: /ifs/kubernetes --- # # rbac.yaml 中的内容 #
yaml

创建完成后,PVC 的 spec.storageClassName 只需要填上指定的 StorageClass 就可以实现动态供应了。

PV 的回收策略

当存在一个 PVC 时,当时没有对应的可用组员,它会先处于 Pending 状态。当有合适的 PV 时,PVC 会自动绑定。

当 PVC 绑定了一个 PV 后,当这个 PVC 被删除后,默认情况下这个 PVC 所绑定的 PV 不会被释放。

每个持久卷会处于以下阶段(Phase)之一:

  • Available: 卷是一个空闲资源,尚未绑定到任何申领
  • Bound: 该卷已经绑定到某申领
  • Released: 所绑定的申领已被删除,但是关联存储资源尚未被集群回收
  • Failed: 卷的自动回收操作失败

保留 (Retain)

当 PVC 被删除后仍然保留 PV,即用户需要手动回收资源,此时卷的状态为 RELEASED

[docker@VM-12-7-opencloudos pvc]$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE my-pv10m 10m RWO Retain Available my-storage-class-name <unset> 11m my-pv50m 50m RWO Retain Released default/my-pvc-40m my-storage-class-name <unset> 10m
bash

可以通过下面的步骤来手动回收:

  1. 删除 PV 对象。删除 PV 对象并不会删除其对应的文件夹中的资源。
  2. 根据需要手动清除 PV 对应的文件夹上的资源
  3. 删除对应的关联存储资产
  4. 如果需要,重新创建 PV

删除 (Delete)

K8s 会直接将 PV 删除,同时删除对应的关联资源。

使用 Delete 必须要求对应的存储实现提供相关的删除插件,否则会删除失败。例如 AWS EBS、GCE PD等.

回收 (Recycle)

回收会直接清除 PV 对应目录上的数据(会执行 rm -rf)。执行完成后,该 PV 将允许重新使用。

资源限制

ResourceQuota

ResourceQuota

kubectl explain ResourceQuota

资源配额,通过 ResourceQuota 对象来定义,对每个命名空间的资源消耗总量提供限制。它可以限制命名空间中某种类型对象的总数目上限,也可以限制命名空间中 Pod 可以使用的计算资源总上限。

  • 如果名称空间的计算资源 (如 cpumemory) 的配额被启用,则用户必须为这些资源设定请求值 (request) 和约束值 (limit),否则配额系统将拒绝 Pod 的创建。可以使用 LimitRanger 准入控制器来为没有设置计算资源需求的 Pod 设置默认值。

  • 如果资源创建或者更新违反了配额约束,那么该请求就会报错 (HTTP 403 FORBIDDEN),并在消息中给出有可能违反的约束。

计算资源配额

资源名称描述
limits.cpu所有非终止状态的Pod,其 CPU 限额总量不能超过该值
limits.memory所有非终止状态的Pod,其内存限额总量不能超过该值
requests.cpu所有非终止状态的Pod,其 CPU 需求总量不能超过该值
request.memory所有非终止状态的Pod,其内存需求总量不能超过该值
hugepages-对于所有非终止状态的Pod,针对指定尺寸的巨页请求总数不能超过该值

存储资源配额

资源名称描述
requests.storage所有PVC,存储资源的需求总量不能超过该值
persistentvolumeclaims在该命名空间中所允许的 PVC 总量
.storageclass.storage.k8s.io/requests.storage限制对应的storageClass所能拥有的 PVC 总量
.storageclass.storage.k8s.io/persistentvolumeclaims限制对应的storageClass所能拥有的 PVC 数量

对象数量配额

可以通过下面的写法来限制 Kubernetes API 中一种特定资源类型的总数:

  • count/.:用于非核心(core)组的资源
  • count/:用于核心组的资源

常用的一些资源:

  • count/persistentvolumeclaims
  • count/services
  • count/secrets
  • count/configmaps
  • count/replicationcontrollers
  • count/deployments.apps
  • count/replicasets.apps
  • count/statefulsets.apps
  • count/jobs.batch
  • count/cronjobs.batch