对于K8S这样一个云上服务管理集群来说
将文件等持久化数据放在本地存储是不可靠的,所以需要将数据放在远端持久化存储中
基本架构如下图
容器通过挂载点和远端的存储进行沟通
而在Kubernetes中,支持的挂载存储多达28种数据卷类型
非持久化村存储,也就是服务器本地存储
emptyDir
HostPath
网络存储
SAN:iSCSI,ScaleIO Volumes FC
NFS: nfs,cfs
分布式存储
Glusterfs
RBD
CephFS
Portworx Volumes
Quobyte Volumes
云端存储
GCEPersistentDisk
AWSElasticBlockStore
AzureFile
AzureDisk
Cinder (OpenStack block storage)
VsphereVolume
StorageOS
以及配置相关的
Configmap
Secret
然后在其中,Secret和Configmap使我们需要说的
Secret用于保存敏感信息,比如密码,OAuth令牌,SSH秘钥等
将这些放在K8S中保存比明文更加灵活,类型主要包含下面
关于如何创建和Secret和Pod如何使用Secret,是我们接下来要讲解的对象
1. 创建Secret
首先可以使用基本字符串
Kubectl create secret generic dev-db-secret \
–from-literal=username=devuser
–from-liternal=password=’S!B\*d$zDsb=’
这样我们创建的Secret中存储的数据,是被Base64加密过得
或者我们使用文件来创建Secret
echo -n ‘admin’ > ./username.txt
echo -n ‘1f2d1e2e67df’ > ./password.txt
kubectl create secret generic db-user-pass \
–from-file=./username.txt \
–from-file=./password.txt
这样创建出来的Secret 中数据也是被Base64加密过的
最后是使用yaml文件创造出来的
apiVersion: v1
kind: Secret
metadata:
name: dev-db-secret
data:
password: UyFCXCpkJHpEc2I9 ## base64编码了一下
username: ZGV2dXNlcg==
这样创建出来的Secret中存储的数据就是我们声明的数据
其次是关于Secret的挂载使用
我们之前说过了使用Secret来挂载访问Docekr私仓
即配置
Spec:
Containers:
– Name: nginx
Image: xxxx
ImagePullSecrets:
– Name :secretname
其次我们可以使用环境变量引用的方式来使用Secret
在对应的env中声明valueFrom,表明为secretKeyRef,从而使用secret的属性
# secret保存在集群的etcd里面
apiVersion: v1 kind: Pod metadata: name: “pod-secret” namespace: default labels: app: “pod-secret” spec: containers: – name: pod-secret image: “busybox” command: [“/bin/sh”,”-c”,”sleep 3600″] ## echo $My_USR resources: limits: cpu: 10m ### 1核代表1000m requests: cpu: 5m env: – name: MY_USR ### 容器里的环境变量名字 valueFrom: secretKeyRef: ## secret的内容 name: dev-db-secret #指定secret名字 key: username ### 自动base64解码 – name: POD_NAME valueFrom: fieldRef: ## 属性引用 fieldPath: metadata.name ## 取出资源对象信息 – name: POD_LIMIT_MEM valueFrom: resourceFieldRef: containerName: pod-secret ## 取出指定容器的相关资源值 resource: limits.cpu |
除此之外,还可以使用
ResourceFieldReg,来取出容器相关的资源之
比如limits.cpu
以及fieldRef,取出资源对象相关的信息
比如metadata.namespaces
但是有着对应的缺点,就是在Secret文件更新的时候,不会自动刷新环境变量
还有一种办法就是以文件的方式挂载到Pod的指定目录中
首先在pod的containers中同级的volumes
声明一个secret
Secret中可以配置项并不少
包含defaultmode,items这些
然后在containers中声明使用volumeMounts 使用
然后是configmap
其实使用方式和Secret类似,由于是不加密的,所以适合存储环境变量等信息
创建方式也是可以直接书写
kubectl create configmap my-config –from-literal=key1=config1 –from-literal=key2=config2或者通过指定key和文件
kubectl create configmap my-config –from-literal=key1=config1 –from-literal=key2=config2
以及通过yaml文件声明
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
# 类属性键;每一个键都映射到一个简单的值
player_initial_lives: “3”
ui_properties_file_name: “user-interface.properties”
# 类文件键
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
上面我们使用:冒号后面跟着一个 |来表示
这个key后面跟着多个value,这种方式方便我们未来进行挂载
对于使用来说
也是可以进行设置为环境变量
也和上面的使用方式一样
在pod.spec.containers.port中,有可填项 configMapKeyRef
– name: PLAYER_INITIAL_LIVES # 请注意这里和 ConfigMap 中的键名是不一样的
valueFrom:
configMapKeyRef:
name: game-demo # 这个值来自 ConfigMap
key: player_initial_lives # 需要取值的键
name仍然为ConfigMap
key为要取值的键
同样,缺点在于如果环境变量,是没有办法进行热更新的
其次是通过volume方式进行挂载
仍然是在containers同级中volumes中声明一个volume
volumes:
# 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中 – name: config configMap: # 提供你想要挂载的 ConfigMap 的名字 name: game-demo # 来自 ConfigMap 的一组键,将被创建为文件 items: – key: “game.properties” path: “game.properties” – key: “user-interface.properties” path: “user-interface.properties” |
其中我们制定了
挂载的configmap的name
然后是可选项的item
其中有key和path是必填的
Key指定了configMap中的key,path指定了具体挂载的路径
这一点可以触发自动更新
之后是关于Kuberentes中的临时存储
分为了emptyDir 和 hostPath
首先是emptyDir
EmptyDir是K8S随机生成的宿主机上的目录,供不同的容器进行读写
在Pod被删除的时候,其中的数据也会被永久删除
但是当容器被删除的时候,数据不会发生改变
一个典型的声明了挂载emptyDir的yaml文件如下
apiVersion: v1
kind: Pod
metadata:
name: “multi-container-pod”
namespace: default
labels:
app: “multi-container-pod”
spec:
volumes: ### 以后见到的所有名字 都应该是一个合法的域名方式
– name: nginx-vol
emptyDir: {} ### docker匿名挂载,外部创建一个位置 /abc
containers: ## kubectl exec -it podName -c nginx-container(容器名)– /bin/sh
– name: nginx-container
image: “nginx”
volumeMounts: #声明卷挂载 -v
– name: nginx-vol
mountPath: /usr/share/nginx/html
– name: content-container
image: “alpine”
command: [“/bin/sh”,”-c”,”while true;do sleep 1; date > /app/index.html;done;”]
volumeMounts:
– name: nginx-vol
mountPath: /app
无论是hostPath还是emptyDir
都是可以在volumeMount中配置subPath
但是需要注意,如果configMap或者Secret配置了subPath,那么当上述两者发生变化的时候,不会自动更新
而在emptyDir中,还有些可选配置项
其中medium选项可以配置””空字符串或者memory
如果配置为空字符串,那么就生成一个临时文件夹,设置为memory,就是将文件放在内存中
SizeLimit 配合上面的memory 使用的,设置内存大小
其次是hostPath
就是讲容器内部和宿主机做一个映射
基本的yaml如下
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
– image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
– mountPath: /test-pd
name: test-volume
volumes:
– name: test-volume
hostPath:
# 宿主上目录位置
path: /data
# 此字段为可选
type: Directory
就是在hostPath上声明一个宿主机路径,将其挂载到容器内部的目录中
下面的type为Directory,表示是一个目录,除了这个type还有一些如下
在hostPath的最后,来看一个典型案例
apiVersion: v1
kind: Pod
metadata:
name: busy-box-test
namespace: default
spec:
restartPolicy: OnFailure
containers:
– name: busy-box-test
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
– name: date-config
mountPath: /etc/localtime
command: [“sleep”, “60000”]
volumes:
– name: date-config
hostPath:
path: /etc/localtime
将宿主机的时间分享给容器内部,保证时间一致,类似的还有,将宿主机上的docker socket分享给容器内部,让容器可以调用宿主机的docker 接口