K8S--存储

时间:2021-08-04
本文章向大家介绍K8S--存储,主要包括K8S--存储使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、Volumes

  Voumes是用来挂在数据的,其生命周期独立于pod中容器的生命周期,容器可能会被销毁或重建,但是Volumes会被保留,但是如果Pod不存在,Volumes也会随即消失。

  对于可以挂在的卷其实有很多的选择,例如可以选择本地卷、网络卷、云盘、K8S自身资源等。

    本地卷:直接挂载到宿主机文件的类型,直接绑定的node节点

    网络卷:例如NFS、ClusterFs等

    云盘:例如AWS、微软等

    K8S自身的资源:例如secret、configmap、downwardAPI等。

(一)本地卷

  1、emptyDir

  emptyDir类似于docker的volume,但是docker删除容器时,数据卷还会存在,而emptyDir删除容器,数据卷也会丢失,一般这个只做临时数据卷来使用。

  emptyDir的主要应用场景就是Pod中容器间数据共享:

    当pod被分配节点时,首先创建emptyDir卷,并且只要该pod在该节点上运行,该卷就会存在,该卷刚被创建时是控的,pod中的容器可以读取和写入emptyDir卷中的相同文件。

  这里特殊说明一点,容器崩溃不会从节点中移除pod,因此emptyDir卷中的数据在容器崩溃时是安全的

  举个例子:

apiVersion: v1
kind: Pod
metadata:
  name: test-pod1
spec:
  containers:
  - image: hub.lcl.com/library/myapp:v1
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}
    

---
apiVersion: v1
kind: Pod
metadata:
  name: test-pod2
spec:
  containers:
  - image: hub.lcl.com/library/myapp:v1
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  - name: test-1
    image: hub.lcl.com/library/busybox:v1
    command: ["/bin/sh","-c","sleep 3600s"]
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

  2、HostPath

  挂载Node文件系统上文件或者目录到Pod中的容器。

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

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - image: hub.lcl.com/library/myapp:v1
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    hostPath:
      path: /data
      type: Directory

  这里创建的数据和我们被分配的Node节点的数据都是一样的,创建的数据都会更新上去,删除容器,不会删除数据卷的数据。

  除了所需的path属性外,还可以为hostPath卷指定type

      

 (二)NFS网络存储

  nfs就是一个网络文件存储服务器,装完nfs之后,共享一个目录,其他的服务器就可以通过这个目录挂载到本地了,在本地写到这个目录的文件,就会同步到远程服务器上,实现一个共享存储的功能,一般都是做数据的共享存储,比如多台web服务器,肯定需要保证这些web服务器的数据一致性,那就会用到这个共享存储了,要是将nfs挂载到多台的web服务器上,网站根目录下,网站程序就放在nfs服务器上,这样的话。每个网站,每个web程序都能读取到这个目录,一致性的数据,这样的话就能保证多个节点,提供一致性的程序了。

  1、搭建nfs服务器

  https://www.cnblogs.com/diantong/p/10895954.html

  2、示例

# mkdir wwwroot
# vim nfs.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nfs
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: hub.kaikeba.com/library/myapp:v1
        volumeMounts:
        - name: wwwroot
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
      - name: wwwroot
        nfs:
          server: 192.168.66.13
          path: /opt/k8s/wwwroot
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
  type: NodePort

  我们在源pod的网页目录下写入数据,并查看我们的nfs服务器目录下也会共享

二、ConfigMap

(一)概述ConfigMap

  镜像往往是一个应用基础,还有很多需要自定义的参数或配置,这些配置很多,有的还需要保密,例如密码等信息,因此这些配置不能放在镜像中,K8S提供了ConfigMap和Secret来解决这个问题。

  ConfigMap对象是一系列配置的集合,K8S会将这一系列的配置注入到对应的Pod中,注入的方式有两种:挂载存储卷和传递变量

  ConfigMap被引用之前必须存在,属于名称空间级别,不能跨命名空间使用内容显示明文。ConfigMap中的内容修改后,必须重新加载配置才会生效,但是,如果应用程序支持热更新,则不需要重启。

(二)传递变量创建ConfigMap

  对比一下K8S传递变量和docker中传递变量

Docker K8S 描述
ENTRYPOINT command 容器中的可执行文件
CMD args 需要传递给可执行文件的参数

  如果要向容器中传递参数,可以在yaml文件中通过command和args或环境变量的方式实现。示例配置如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: print-greeting
spec:
  containers:
  - name: env-print-demo
    image: hub.kaikeba.com/java12/bash:v1
    env:
    - name: GREETING
      value: "Warm greetings to"
    - name: HONORIFIC
      value: "The Most Honorable"
    - name: NAME
      value: "Kubernetes"
    command: ["echo"]
    args: ["$(GREETING) $(HONORIFIC) $(NAME)"]

  创建后,命令 echo Warm greetings to The Most Honorable Kubernetes 将在容器中运行,也就是环境变量中的值被传递到了容器中。 查看pod就可以看出 

kubectl logs podname

(三)使用存储卷创建ConfigMap

  1、创建方式概述

  使用:kubectl create  configmap --help可以查看使用存储卷创建ConfigMap的样例和方式,输出结果如下所示:

[root@k8s-master01 ~]# kubectl create  configmap --help
Create a configmap based on a file, directory, or specified literal value.

Aliases:
configmap, cm

Examples:
  # #从目录创建  文件名称为键  文件内容为值?
  # Create a new configmap named my-config based on folder bar
  kubectl create configmap my-config --from-file=path/to/bar

  # #从文件创建 key1为键 文件内容为值
  # Create a new configmap named my-config with specified keys instead of file basenames on disk
  kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

  # 直接命令行给定,键为key1 值为config1
  # Create a new configmap named my-config with key1=config1 and key2=config2
  kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2

  # 从文件创建 文件名为键 文件内容为值
  # Create a new configmap named my-config from the key=value pairs in the file
  kubectl create configmap my-config --from-file=path/to/bar

  # 从env文件创建 文件名为键 文件内容为值
  # Create a new configmap named my-config from an env file
  kubectl create configmap my-config --from-env-file=path/to/bar.env

  下面就是对上面几种使用挂在卷方式创建ConfigMap的详细说明。

  2、根据目录创建ConfigMap

  (1)创建目录,用于存放configMap

mkdir /docs/user-guide/configmap

  创建game.properties,ui.properties,game.cnf ui.conf ,game.yaml。

  (2)创建game.properties

enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

  (3)创建ui.properties

color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

  (4)创建ConfigMap

#创建configmap ,指令
# game-config :configmap的名称
# --from-file:指定一个目录,目录下的所有内容都会被创建出来。以键值对的形式
# --from-file指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容
kubectl create configmap game-config --from-file=docs/user-guide/configmap

  (5)查看ConfigMap

# 查看configmap文件
kubectl get cm 
# 查看详细信息
kubectl get cm game-config -o yaml   
kubectl describe cm

  3、根据文件创建ConfigMap

  只需要指定为一个文件就可以从单个文件中创建ConfigMap

# 指定创建的文件即可
kubectl create configmap game-config-2 --from-file=/docs/user-guide/configmap/game.propertes

  查看

#查看
kubectl get configmaps game-config-2 -o yaml

  说明:--from-file这个参数可以使用多次,可以分别指定game.properties,ui.propertes.效果和指定整个目录是一样的

  4、文字创建ConfigMap

# 使用--from-literal 方式直接创建configmap
# Create the ConfigMap
$ kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2
configmap "my-config" created 

# Get the ConfigMap Details for my-config
$ kubectl get configmaps my-config -o yaml
apiVersion: v1
data:
  key1: value1
  key2: value2
kind: ConfigMap
metadata:
  creationTimestamp: 2017-05-31T07:21:55Z
  name: my-config
  namespace: default
  resourceVersion: "241345"
  selfLink: /api/v1/namespaces/default/configmaps/my-config
  uid: d35f0a3d-45d1-11e7-9e62-080027a46057
  
# 文字方式
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

#查看
kubectlget configmaps special-config -o yaml 

  说明:使用文字方式创建,利用 --from-literal 参数传递配置信息,改参数可以使用多次

  5、直接创建

  直接通过配置文件进行创建configMap

apiVersion: v1
data:
  game.properties: |
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
  name: game-config
  namespace: default

(四)ConfigMap在Pod中的应用

  ConfigMap在Pod中有三种应用方式:使用ConfigMap来替代环境变量、用ConfigMap设置命令行参数、通过数据卷插件使用ConfigMap

  1、使用ConfigMap替代环境变量

  使用ConfigMap替代环境变量有两种方式:在env中导入、直接使用envFrom导入

# 创建configMap,   special.how: very   键名:键值
apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
  
# 创建第二个configMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

# 第一种方式: 在pod中使用configmap配置,使用ConfigMap来替代环境变量
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-container
      image: hub.kaikeba.com/library/myapp:v1 
      command: ["/bin/sh", "-c", "env"]
      env:
        - name: SPECIAL_LEVEL_KEY 
          valueFrom:
            configMapKeyRef: 
              name: special-config  # 第一种导入方式:在env中导入
              key: special.how              
        - name: SPECIAL_TYPE_KEY
          valueFrom: 
            configMapKeyRef: 
              name: special-config 
              key: special.type 
      envFrom:                      # 第二种导入方式,直接使用envFrom导入
        - configMapRef: 
            name: env-config 
  restartPolicy: Never

  查看日志

kubectl  logs  test-pod

  2、用ConfigMap设置命令行参数

  用作命令行参数,将 ConfigMap 用作命令行参数时,需要先把 ConfigMap 的数据保存在环境变量中,然后通过 $(VAR_NAME) 的方式引用环境变量

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-container
      image: hub.kaikeba.com/library/myapp:v1
      command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] 
      env:
        - name: SPECIAL_LEVEL_KEY 
          valueFrom: 
            configMapKeyRef: 
              name: special-config 
              key: special.how 
        - name: SPECIAL_TYPE_KEY 
          valueFrom: 
            configMapKeyRef: 
              name: special-config 
              key: special.type 
  restartPolicy: Never

  3、通过数据卷插件使用ConfigMap

  在数据卷里面使用这个ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容

apiversion: v1
kind: Pod
metadata:
  name: test-pod3
spec:
  containers:
    - name: test-container
      image: hub.kaikeba.com/library/myapp:v1
      command: [ "/bin/sh", "-c", "sleep 600s" ] 
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config # 表示把conifg-volume挂载卷挂载到容器的/etc/config目录下
  volumes:    # 开启挂载外部configmap
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

  然后再登录容器查看/etc/config目录下是否挂在成功。

(五)ConfigMap热更新

  配置文件

# ConfigMap的热更新
apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level:INFO
---
apiVersion: extensions/v1beta1 
kind: Deployment 
metadata: 
  name: my-nginx 
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
        - name: my-nginx
          image: hub.kaikeba.com/java12/myapp:v1 
          ports:
            - containerPort: 80 
          volumeMounts:
            - name: config-volume 
              mountPath: /etc/config 
      volumes:
        - name: config-volume 
          configMap:
            name: log-config

  获取值&输出:

# 获取值
kubectl exec my-nginx-7b55868ff4-wqh2q -it -- cat /etc/config/log_level
#输出
INFO

  修改ConfigMap,修改log-level的值为DEBUG等待大概10秒钟时间,再次查看环境变量的值

kubectl edit configmap log-config

三、Secret

  Secret和ConfigMap一样,都是用来解决配置文件不打到镜像中的问题,Serect与ConfigMap的区别是Serect存储的是使用Base64加密的密文,一般用于存储敏感信息,而ConfigMap存储的是明文。

  Serect一般有两种创建方式,使用kubectl create创建和使用serect配置文件创建。

  Serect有四种类型:Service Account、Opaque、Kubernetes.io/dockerconfigjson、kubernetes.io/tls

    Service Account :用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中;

    Opaque :base64编码格式的Secret,用来存储密码、密钥、信息、证书等,类型标识符为generic;

    kubernetes.io/dockerconfigjson :用来存储私有docker registry的认证信息,类型标识为docker-registry。

    kubernetes.io/tls:用于为SSL通信模式存储证书和私钥文件,命令式创建类型标识为tls

(一)Service Account

  Service Account用来访问Kubernetes API,由K8S自动创建,并且会挂载到Pod的/run/serect/kubernetes.io/serviceaccount目录中

  Service Account不需要我们自己去管理,此证书由K8S创建并维护。

# 创建pod
kubectl run my-nginx --image=hub.kaikeba.com/java12/nginx:v1 
# 查看证书
kubctl exec -it podName -- sh
# 进入证书目录/run/secrets/kubernetes.io/serviceaccount查看即可
ca
namespace
token

(二)opaque Serect

  1、创建示例:

# base64对用户名,密码加密效果演示
echo -n "admin" | base64
YWRtaW4=

echo -n "abcdefgh" | base64
YWJjZGVmZ2g=


# secret.yaml配置文件方式
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
 password: YWJjZGVmZ2g=
 username: YWRtaW4=

  2、使用方式

  (1)将secret挂载到volume中

apiVersion: v1
kind: pod
metadata:
 name: secret-test
 labels:
   name: secret-test
spec:
  volumes:
  - name: secrets
    secret:
      secretName: mysecret
  containers:
  - image: hub.kaikeba.com/java12/myapp:v1
    name: db
    volumeMounts:
    - name: secrets
      mountPath: "/etc/secrets"
      readOnly: true

  (2)将secret导出到环境变量中

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
 name: secret-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: pod-deployment
    spec:
      containers:
      - name: pod-1
        image: hub.kaikeba.com/java12/myapp:v1
        ports:
        - containerPort: 80
        env:
        - name: TEST_USER
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: TEST_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password
------------------------------------------------------------------
-----------------------------------------------------------
---------------------------------------------
朦胧的夜 留笔~~

原文地址:https://www.cnblogs.com/liconglong/p/15086864.html