k8s投射数据卷 Projected Volume
在 k8s 中,有几种特殊的 Volume,它们的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换。"而是为容器提供预先定义好的数据。"
从容器的角度来看,这些 Volume 里的信息仿佛是被 k8s "投射"(Project)进入容器当中的。
k8s 支持的 Projected Volume 一共有四种:
Secret
ConfigMap
Downward API
ServiceAccountToken 不常用没有写
Secret
secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。用户可以创建自己的secret,系统也会有自己的secret。Pod需要先引用才能使用某个secret
Pod有2种方式来使用secret:
1. 作为volume的一个域被一个或多个容器挂载
2. 在拉取镜像的时候被kubelet引用。
內建的Secrets: 由ServiceAccount创建的API证书附加的秘钥k8s自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信
创建自己的Secret:
1:使用kubectl create secret命令
2:yaml文件创建Secret
命令方式创建secret:
假如某个Pod要访问数据库,需要用户名密码,分别存放在2个文件中:username.txt,password.txt
echo -n 'admin' > ./username.txt
echo -n '12345678' > ./password.txt
kubectl create secret指令将用户名密码写到secret中,并在apiserver创建Secret
kubectl create secret generic user-pass --from-file=./username.txt --from-file=./password.txt
kubectl get secrets 查看创建结果
kubectl describe secret user-pass 查看详细信息
get或describe指令都不会展示secret的实际内容,这是出于对数据的保护的考虑,要查看实际内容使用命令:
kubectl get secret user-pass -o json
base64解码:
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
yaml方式创建Secret:
创建一个secret.yaml文件,内容用base64编码:明文显示容易被别人发现。
echo -n 'admin' | base64
echo -n '1f2d1e2e67df' | base64
vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
name: myuser-pass
type: Opaque #模糊
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
使用Secret:Pod中引用Secret
vim pod_use_secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: testredis
image: daocloud.io/library/redis
volumeMounts: #挂载一个卷
- name: user-pass #这个名字需要与定义的卷的名字一致
mountPath: "/etc" #挂载到容器里哪个目录下,随便写
readOnly: true #只读权限,不加默认有读写
volumes: #数据卷的定义
- name: user-pass #卷的名字这个名字自定义
secret: #卷是直接使用的secret。
secretName: user-pass #调用刚才定义的secret
kubectl apply -f pod_use_secret.yaml 创建
kubectl exec -it mypod /bin/bash
可以看到我们定义的文件映射进来了
被挂载的secret内容会自动更新
vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: cWlhbmZlbmcK
password: MTIzNDU2Nzg5Cg== #修改为123456789的base64加密后的
kubectl apply -f secret.yml 修改完直接创建即可在次来到容器查看已经变了
ConfigMap
ConfigMap 与 Secret 类似,用来存储配置文件的kubernetes资源对象,所有的配置内容都存储在etcd中。
ConfigMap 保存的是不需要加密的、应用所需的配置信息。
ConfigMap 的用法几乎与 Secret 完全相同:可以使用 kubectl create configmap 从文件或者目录创建 ConfigMap,也可以直接编写 ConfigMap 对象的 YAML 文件。
创建ConfigMap的方式有4种:
命令行方式:
1:通过直接在命令行中指定configmap参数创建,即--from-literal
2:通过指定文件创建,即将一个配置文件创建为一个ConfigMap,--from-file=<文件>
3:通过指定目录创建,即将一个目录下的所有配置文件创建为一个ConfigMap,--from-file=<目录>
4:事先写好标准的configmap的yaml文件,然后kubectl create -f 创建
1、通过命令行参数--from-literal创建
kubectl create configmap configmap --from-literal=user=admin --from-literal=pass=2023888
kubectl get configmap configmap -o yaml 查看相关内容
2、通过指定文件创建
编辑配置文件properties
vim properties
property.1 = user-1
property.2 = user-2
property.3 = user-3
[mysqld]
!include /data/mysql/mysqld.cnf
port = 3306
socket = /data/mysql/mysql.sock
pid-file = /data/mysql/mysql.pid
kubectl create configmap configmap-2 --from-file=properties 创建
kubectl get configmap configmap-2 -o yaml 查看内容
3、指定目录创建
指定目录创建时,configmap内容中的各个文件会创建一个key/value对,key是文件名,value是文件内容。
mkdir test
cd test/
vim test-1
123
456
789
a=10
vim test-2
aaa
bbb
ccc
d=AAA
kubectl create configmap configmap-3 --from-file=/root/test 创建
kubectl get configmap configmap-3 -o yaml 查看内容
4、通过事先写好configmap的标准yaml文件创建
vim configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-4
namespace: default
data:
cache_host: redis
cache_port: "6379"
cache_prefix: redis
my.cnf: |
[mysqld]
log-bin = mysql-bin
haha = hehe
kubectl apply -f configmap.yaml 创建
kubectl get configmap configmap-4 -o yaml 查看内容
kubectl describe configmap 查看所有configmap的详细信息
kubectl describe configmap configmap名称 查看单独configmaop的详细信息
kubectl delete configmap configmap名称 删除对应configmap
使用ConfigMap
通过envFrom、configMapRef、name使得configmap中的所有key/value对儿 都自动变成环境变量
vim testpod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: daocloud.io/library/nginx
envFrom: #固定写法
- configMapRef: #固定写法
name: configmap-2 已创建的configmap名称
restartPolicy: Never #重启策略-从不
kubectl apply -f testpod.yml 创建pod
kubectl exec -it dapi-test-pod /bin/bash 进入pod容器
输入env 查看一下变量 可以看到configmap-2里面定义的内容都有
作为volume挂载使用
vim volupod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-configmap
spec:
containers:
- name: nginx-configmap
image: daocloud.io/library/nginx
volumeMounts:
- name: volume4
mountPath: "/home/config-4"
volumes:
- name: volume4
configMap:
name: configmap-4
kubectl apply -f volupod.yml 创建pod
kubectl exec -it nginx-configmap /bin/bash 进入到容器查看
在config-4文件夹下以每一个key为文件名value为值创建了多个文件
Downward API
用于在容器中获取 POD 的基本信息,kubernetes原生支持
Downward API提供了两种方式用于将 POD 的信息注入到容器内部:
1.环境变量:用于单个变量,可以将 POD 信息和容器信息直接注入容器内部。
2.Volume挂载:将 POD 信息生成为文件,直接挂载到容器内部中去。
环境变量的方式:
通过Downward API来将 POD 的 IP、名称以及所对应的 namespace 注入到容器的环境变量中去,然后在容器中打印全部的环境变量来进行验证
使用环境变量的方式
vim test-env-pod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: test-env-pod
namespace: kube-system
spec:
containers:
- name: test-env-pod
image: daocloud.io/library/nginx
env:
- name: POD_NAME #第一个环境变量的名字
valueFrom: #使用valueFrom方式设置
fieldRef: #关联一个字段metadata.name
fieldPath: metadata.name #这个字段从当前运行的pod详细信息查看
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
kubectl apply -f test-env-pod.yml 创建pod
kubectl exec -it test-env-pod /bin/bash -n kube-system 进入容器内部查看
env | grep POD
Volume挂载
vim test-volume-pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: test-volume-pod
namespace: kube-system
labels:
k8s-app: test-volume
node-env: test
spec:
containers:
- name: test-volume-pod-container
image: daocloud.io/library/nginx
volumeMounts:
- name: podinfo
mountPath: /data
volumes:
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
kubectl apply -f test-volume-pod.yaml 创建pod
kubectl exec -it test-volume-pod /bin/bash -n kube-system 进入容器内部
将元数据 labels 和 annotaions 以文件的形式挂载到了/data
在实际应用中,如果你的应用有获取 POD 的基本信息的需求,就可以利用Downward API来获取基本信息,然后编写一个启动脚本或者利用initContainer将 POD 的信息注入到容器中去,然后在自己的应用中就可以正常的处理相关逻辑
目前 Downward API 支持的字段使用 fieldRef 可以声明使用:
spec.nodeName - 宿主机名字
status.hostIP - 宿主机 IP
metadata.name - Pod 的名字
metadata.namespace - Pod 的 Namespace
status.podIP - Pod 的 IP
spec.serviceAccountName - Pod 的 Service Account 的名字
metadata.uid - Pod 的 UID
metadata.labels['<KEY>'] - 指定 <KEY> 的 Label 值
metadata.annotations['<KEY>'] - 指定 <KEY> 的 Annotation 值
metadata.labels - Pod 的所有 Label
metadata.annotations - Pod 的所有 Annotation
ServiceAccount
Service Account它并不是给kubernetes集群的用户使用的,而是给pod里面的进程使用的,它为pod提供必要的身份认证。----专门为pod里面的进程和apiserver通信提供认证的。
Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同。很少会使用到操作略
挂载目录的方法
vim test.yml
---
apiVersion: v1
kind: Pod
metadata:
name: mypod-3
spec:
containers:
- name: mycontainer
image: daocloud.io/library/nginx
volumeMounts:
- name: myvolume #挂载名称
mountPath: /home #容器内路径
volumes:
- name: myvolume #和上方一致
hostPath:
path: /data/test #被映射路径