一、前言
本章节我们继续学习Namespace、ConfigMap、Secret基础概念,了解他们基本用法和操作。NameSpace为命名空间,在同一集群中试下资源隔离。ConfigMap通过key-value的方式实现明文配置数据的保存,Secret与ConfigMap类似,不过是采用密文方式保存。
二、Namespace(命名空间)
K8S集群可以通过Namespace创建多个"虚拟的集群",这些虚拟的集群之间可以完成隔离,包括访问权限,资源,支持了多租户特性,这点在实际工程中非常重要,比如对外的产品系统与内部的IT系统虽然都位于同一集群中,但是我们不希望他们之前可以有任何交互,此时就可以使用不同的Namespace进行隔离。
1、Namespace查看
我们看下目前K8s中有哪些预置的Namespace,使用kubectl get ns指令
[root@k8s-master yaml]# kubectl get ns
NAME STATUS AGE
default Active 43d
kube-public Active 43d
kube-system Active 43d
kubernetes-dashboard Active 42d
一般情况下,环境安装完成后,就会有kube-system,default两个命名空间,与集群管理相关的,为整个集群提供服务的pod都放在kube-system,比如etcd,apiserver等。可以使用kubectl get pod -n <namespace>查看该命名空间下的pod列表。
[root@k8s-master yaml]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-6b8c67b6b5-fsp65 1/1 Running 0 42d
calico-node-bwcfh 1/1 Running 0 42d
calico-node-f976g 1/1 Running 0 42d
coredns-6d8c4cb4d-9n8jg 1/1 Running 0 43d
coredns-6d8c4cb4d-kmh4l 1/1 Running 0 43d
etcd-k8s-master 1/1 Running 0 43d
kube-apiserver-k8s-master 1/1 Running 0 43d
kube-controller-manager-k8s-master 1/1 Running 0 43d
kube-proxy-db9dm 1/1 Running 0 43d
kube-proxy-jqnnq 1/1 Running 0 42d
kube-scheduler-k8s-master 1/1 Running 0 43d
而普通用户创建的pod,如果不指定Namespace,将统一放到default中,比如前一章节创建的busybox-pod就在default命名空间下。
[root@k8s-master yaml]# kubectl get pod -n default
NAME READY STATUS RESTARTS AGE
busybox-pod 1/1 Running 0 31m
2、Namespace创建
Namespace可以通过命令直接创建,也可以使用yaml文件创建
(1)使用命令创建
命令创建非常简单,指令为kubectl create ns <namespace>,如下例创建dev的命名空间。
[root@k8s-master yaml]# kubectl create ns dev
namespace/dev created
[root@k8s-master yaml]# kubectl get ns
NAME STATUS AGE
default Active 43d
dev Active 9s
kube-public Active 43d
kube-system Active 43d
kubernetes-dashboard Active 42d
(2)使用yaml文件
编辑namespace-demo.yaml,内容如下:
[root@k8s-master yaml]# cat namespace-demo.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dev
执行该yaml文件,创建dev命名空间。
[root@k8s-master yaml]# kubectl apply -f namespace-demo.yaml
namespace/dev created
[root@k8s-master yaml]# kubectl get ns
NAME STATUS AGE
default Active 43d
dev Active 8s
kube-public Active 43d
kube-system Active 43d
kubernetes-dashboard Active 42d
(3)使用namespace,创建pod
接下来我们创建一个pod,指定命名空间为dev,编辑ns-pod.yaml文件,其内如如下:
[root@k8s-master yaml]# cat ns-dev-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: ns-pod
namespace: dev
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.8
在metadata中指定namespace为dev,通过yaml文件创建pod,并查看命名空间下的pod列表。
[root@k8s-master yaml]# kubectl apply -f ns-dev-pod.yaml
pod/ns-pod created
[root@k8s-master yaml]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
ns-pod 1/1 Running 0 86s
可以看到pod正确创建,并在dev的命名空间下。
3、Namespace的删除
下面我们将dev的namespace删除
[root@k8s-master yaml]# kubectl delete ns dev
namespace "dev" deleted
该Namespace下的所有Pod也将一并删除。
关于Namspace的对于网络,计算资源的隔离性,我们将后续章节介绍。
三、ConfigMap
在实际工程中,我们需要将配置数据与代码进行分离,比如说 Nginx 的 nginx.conf、Redis 的 redis.conf、MySQL 的 my.cnf 等等,这些配置文件会根据不同环境配置不同的数据,且在运行过程中,需要做到动态调整,及时更新。
K8S提供了ConfigMap对象,用来保存配置数据,实现配置和镜像的解耦,便于应用配置的修改。
1、ConfigMap创建
ConfigMap保存的是多组key-value键值对数据,其创建方式可以有多种,包括使用yaml文件,以及通过命令行创建。
(1)yaml文件
编辑 data-config.yaml文件,其内容如下:
[root@k8s-master yaml]# cat data-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: data-config
data:
username: 'root'
pwd: 'qwert'
这个yaml文件比较简单,前面几个属性,如apiVersion,kind,metadata都比较熟悉了,这里主要介绍下data部分,定义了多组健值对,实现配置数据的定义,比如本例的username和pwd。
使用命令创建ConfigMap对象。
[root@k8s-master yaml]# kubectl apply -f data-config.yaml
创建完成后,查看configMap列表和详情
[root@k8s-master yaml]# kubectl get cm
NAME DATA AGE
data-config 2 79m
kube-root-ca.crt 1 49d
[root@k8s-master yaml]# kubectl describe cm data-config
Name: data-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
pwd:
----
qwert
username:
----
root
BinaryData
====
Events: <none>
可以看到已创建名为data-config的ConfigName对象。
(2)命名行
一般使用命令行,最常用的是通过已存在配置文件,直接生成ConfigMap对象。配置文件可以是具体的文件,也可以是配置文件的目录。接下来,我们演示下通过配置文件目录生成ConfigMap对象。
首先创建config目录,再在该目录下创建username,pwd两个文件,其内容分别是其对应的value值,结果如下:
[root@k8s-master yaml]# cd config
[root@k8s-master config]# ls
pwd username
[root@k8s-master config]# cat pwd
123456
[root@k8s-master config]# cat username
root
使用命令根据config目录创建configMap对象。其命令行kubectl create configmap <configmap name> --from-file=< file path>
[root@k8s-master config]# kubectl create configmap file-configmap --from-file=./
configmap/file-configmap created
--from-file表示通过指定的文件或者目录来创建,本例中指定该目录为当前目录,即config。
同样看下创建结果。
[root@k8s-master config]# kubectl get cm
NAME DATA AGE
data-config 2 93m
file-configmap 3 71s
kube-root-ca.crt 1 49d
[root@k8s-master config]# kubectl describe cm file-configmap
Name: file-configmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
pwd:
----
123456
username:
----
root
BinaryData
====
.pwd.swp: 159744 bytes
Events: <none>
当使用文件创建configMap时,默认情况下,key是文件名,value是文件里的内容。当然也可以使用kubectl create configmap <configmap name> --from-file=<key>=< file path>自定义key值。
2、ConfigMap的使用
配置数据生成后,需要在容器中挂载并使用,这里也有两种使用方式,一种是环境变量方式,另一种是使用Volume 的方式。
(1)环境变量方式
创建Pod的yaml文件configmap-env-pod.yaml ,其内容如下:
[root@k8s-master yaml]# cat configmap-env-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmap-env-pod
spec:
containers:
- name: test-busybox
image: busybox
imagePullPolicy: IfNotPresent
args:
- sleep
- "3600"
env:
- name: name
valueFrom:
configMapKeyRef:
name: data-config
key: username
- name: password
valueFrom:
configMapKeyRef:
name: data-config
key: pwd
该Pod配置一个busybox镜像的容器,容器启动了sleep 3600s,以便我们有时间进入容器进行操作。最核心的是env的配置,这里数据来源于前面的配置的data-config对象。这里我们用下面一张图来描述如何关联的。
env变量的valueFrom使用configMapKeyRef,表明数据来源于configMap,name是指定该configMap的名称,即ConfigMap对象在metadata定义的name值,本例指定的是data-config;key指定使用该configMap的哪条健值,比如本例中,env定义了两个环境变量name和password,其值分别为data-configmap的配置的username以及pwd。
下面我们创建该Pod,并进入到容器内部,打印出这两个环境变量的值。
[root@k8s-master yaml]# kubectl exec -it configmap-env-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo $name
root
/ # echo $password
qwert
可以看到其环境变量的值,就是我们之前在data-config配置的。
(2)Volume 的方式
除了环境变量的方式,还支持Volume的方式,至于Volume的内容我们K8S初级入门系列之九-共享存储会详细介绍,这里可以理解是容器挂载一个存储目录。
同样,我们编辑pod的yaml文件。内如如下;
[root@k8s-master yaml]# cat configmap-volume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: configmap-volume-pod
spec:
containers:
- name: test-busybox
image: busybox
imagePullPolicy: IfNotPresent
args:
- sleep
- "3600"
volumeMounts:
- name: config-volume
mountPath: /tmp/config
volumes:
- name: config-volume
configMap:
name: data-config
用图示的方式描述下之间的关系:
containers容器的volumeMounts属性,定义一个volume挂载点,并挂载到指定目录mountPath(本例的/tmp/config)。该挂载点内容在Pod的volumes的定义,本例中volumes关联到指定的configMap,其名称为data-config。所以从分析看,容器里会创建/tmp/config目录,且该目录下能查看到data-config配置的内容。
创建pod,并进入容器查看。
[root@k8s-master yaml]# kubectl exec -it configmap-volume-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /tmp/config
/tmp/config # ls
pwd username
/tmp/config # cat pwd
qwert
/tmp/config # cat username
root
/tmp/config #
可以看到,在/tmp/config目录下生成了两个文件,分别为key值,即pwd,username,其内容对应的value值,与前面的分析保持一致。
前面讲过,在实际工程中,配置文件是需要实时更新并生效的,我们看下configMap是否支持。修改data-config.yaml文件,将pwd改为"123456",并更新。
[root@k8s-master yaml]# cat data-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: data-config
data:
username: 'root'
pwd: '123456'
[root@k8s-master yaml]# kubectl apply -f data-config.yaml
configmap/data-config configured
再进入 容器内容看下是否有更新
[root@k8s-master yaml]# kubectl exec -it configmap-volume-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /tmp/config
/tmp/config # ls
pwd username
/tmp/config # cat pwd
123456
/tmp/config #
看到已经更新,这个延时在秒级,需要注意的是,同步更新仅针对Volume挂载 的方式,而对于环境变量的方式是不生效的。有兴趣的同学可以测试下。
四、Secret
configMap配置的数据是明文的,但是很多情况下,对于一些敏感数据,我们不希望暴露明文,需要采用加密的方式保存,比如上面例子中的username和pwd。K8S提供了secret对象实现密文配置数据的保存。
Secret有多种类型,这里我们了解最常用的,也是最简单的Opaque 类型,其实质就是对字符进行base64格式编码。我们使用Opaque 类型介绍Secret的创建和使用方式,它与configMap非常类似。
1、Secret创建
Secret的创建也分为命令行和yaml文件。
(1)命令行方式
采用kubectl create secret generic <secret name> --from-file=<file path>命令创建基于文件或目录的secret对象。我们还是以前面的config目录下的文件为例
[root@k8s-master yaml]# kubectl create secret generic file-secret --from-file=./config/
secret/file-secret created
再看下该secret对象的详情
[root@k8s-master yaml]# kubectl describe secret file-secret
Name: file-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
.pwd.swp: 159744 bytes
pwd: 7 bytes
username: 5 bytes
可以看到,详情中看不到实际的值。
(2)yaml文件方式
采用yaml文件方式,我们需要将value值进行base64编码。
[root@k8s-master yaml]# echo -n 'root' | base64
cm9vdA==
[root@k8s-master yaml]# echo -n 'qwert' | base64
cXdlcnQ=
然后将值写入到yaml中,yaml文件内容如下:
[root@k8s-master yaml]# cat data-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: data-secret
data:
username: cm9vdA==
pwd: cXdlcnQ=
执行该文件,并查看详情
[root@k8s-master yaml]# kubectl describe secret data-secret
Name: data-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
pwd: 6 bytes
username: 4 bytes
2、Secret使用
Secret使用方式与configMap也很类似,分为环境变量和volume挂载两种。
(1)环境变量方式
创建Pod的yaml文件,内容如下:
[root@k8s-master yaml]# cat secret-env-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: test-busybox
image: busybox
imagePullPolicy: IfNotPresent
args:
- sleep
- "3600"
env:
- name: name
valueFrom:
secretKeyRef:
name: data-secret
key: username
- name: password
valueFrom:
secretKeyRef:
name: data-secret
key: pwd
可以看到与configMap的结构一致,仅将configMapKeyRef换成secretKeyRef,并将name修改为指定secret对象的name。
创建该Pod,进入到容器内部查看环境变量
[root@k8s-master yaml]# kubectl exec -it secret-env-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # echo $name
root
/ # echo $password
qwert
容器内可以正确的打印出解密后的字符。
(2)volume挂载方式
创建Pod的yaml文件,内容如下:
[root@k8s-master yaml]# cat secret-volume-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: secret-volume-pod
spec:
containers:
- name: test-busybox
image: busybox
imagePullPolicy: IfNotPresent
args:
- sleep
- "3600"
volumeMounts:
- name: config-volume
mountPath: /tmp/config
volumes:
- name: config-volume
secret:
secretName: data-secret
其与configMap的结构也一致,仅volumes的定义指定来源是secret,要主要使用secretName属性指定secret的对象。
创建pod,并进入容器内部查看
[root@k8s-master yaml]# kubectl exec -it secret-volume-pod sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /tmp/config
/tmp/config # ls
pwd username
/tmp/config # cat pwd
qwert
/tmp/config # cat username
root
/tmp/config #
可以看到正确的读取数据了。与configMap一样,其同步更新仅对volume挂载方式有效。
五、总结
本篇主要介绍了Namespace,ConfigMap以及secret的基本用法。
Namespace可以在K8S集群中创建多个"虚拟集群",集群间实现隔离,本篇主要介绍了Namespace的创建,查看,删除以及如何创建指定Namespace的Pod。
ConfigMap通过key-value的方式实现明文配置数据的保存,其创建方式包括yaml文件,以及通过命令行使用指定的配置文件或者目录,Pod使用ConfigMap对象也包括两种方式,环境变量方式和volume挂载方式,其中volume挂载方式可实现同步更新。
Secret和ConfigMap在创建和使用方式上非常类似,区别在于其以密文的方式保存配置数据,一般用于用户名密码,token等敏感数据配置。
附:
K8S初级入门系列之一-概述
K8S初级入门系列之二-集群搭建
K8S初级入门系列之三-Pod的基本概念和操作
K8S初级入门系列之四-Namespace/ConfigMap/Secret
K8S初级入门系列之五-Pod的高级特性
K8S初级入门系列之六-控制器(RC/RS/Deployment)
K8S初级入门系列之七-控制器(Job/CronJob/Daemonset)
K8S初级入门系列之八-网络
K8S初级入门系列之九-共享存储
K8S初级入门系列之十-控制器(StatefulSet)
K8S初级入门系列之十一-安全
K8S初级入门系列之十二-计算资源管理