两种特殊类型存储卷,其多数情况下目的不是给pod提供存储空间来用的,而是给管理员或用户提供了从 集群外部向 pod内部的应用注入配置信息的方式, 理论来源
command, args:['xx','xx']
当我们在一个Pod控制器下,有多个Pod时,这些Pod的配置信息应该都是一样的,意味着它们会共享一个存储卷,当存储卷内容被修改,这些Pod都能加载到新的内容,但这些Pod都会被重载,尤其是当我们使用Hpa控制器时,它会根据用户访问量来自定义伸缩Pod副本,那此时就会不知道重载哪些pod,所以在这种环境下最好能提供一种机制,当我们修改配置信息后能自动关连相关的Pod重载,最好只需要改一次,所有加载该配置文件的Pod都能被自动重载;
k8s中用于实现配置自动重载功能的组件,它们分别是 ConfigMap、Secret,它们都是用于将配置文件配置为k8s资源
ConfigMap用于提供非敏感配置
Secre用于提供敏感配置信息(密码、密钥等)进行编码存放
它们在内部都是对键值对的方式存在,键做为配置参数,值可以是整个文件,比如说 可以将配置文件文件名做为键,整个文件的配置做为值
特殊类型的存储卷,configMap | secret也是存储卷,但它们目的不是为给pod提供存储空间,而是给管理员或用户提供从集群外部向pod内部的应用注入配置信息的方式,集群配置管理资源, 信息明文存放
configMap也属于名称空间级别的资源, 字段查看
kubectl explain cm
ConfigMap做为一个键值存储系统,我们的配置文件几乎都可以被实例为ConfigMap的键值对象,在k8s中pod的ConfigMap调用有两种方式:
为了将配置文件从镜像中解耦,从而增强应用的可移植性以及可复用性,一个configMap就是一系列配置数据的集合,而这些数据将来可以注入到pod对象容器中所使用,而注入方式有两种
Aliases:
configmap, cm
Examples:
# --from-file=path/to/bar 文件名当键, 文件当值
kubectl create configmap my-config --from-file=path/to/bar
# --from-file=key1=/path/to/bar/file1.txt 指定键是key, 值是某个文件
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
# 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
在pod容器上使用env或volueFrom来获取
~]# kubectl explain pods.spec.containers
env
name: 变量名
value: 数据是什么
valueFrom: 数据引用另一个变量
configMapKeyRef: configMap资源
fieldRef: 引用pod资源的字段
resourceFieldRef: 资源需求 | 资源限制
secretKeyRef: 引用secretKey配置资源
创建
# 创建一个临时的键值对
~]# kubectl create cm nginx-test --from-literal=NGINX_NAME=t1.xiong.com --from-literal=NGINX_PORT=80
查看
~]# kubectl get cm
NAME DATA AGE
nginx-test 2 6s
# 查看详细内容
~]# kubectl describe cm nginx-test
Name: nginx-test
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
NGINX_NAME:
----
t1.xiong.com
NGINX_PORT:
----
80
Events: <none>
创建pod
]# cat nginx_cm.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
configMap/test: "nginx"
name: nginx-cm-test
labels:
app: nginx-cm
release: qa
spec:
containers:
- name: nginx-cm
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
env:
- name: NGINX_PORT
valueFrom:
configMapKeyRef:
name: nginx-test
key: NGINX_PORT
- name: NGINX_NAME
valueFrom:
configMapKeyRef: # 来源
name: nginx-test
key: NGINX_NAME
]# kubectl apply -f nginx_cm.yaml
]# kubectl exec -it nginx-cm-test -- /bin/sh
/ # env
NGINX_PORT=80
NGINX_NAME=t1.xiong.com
编辑configMap
]# kubectl edit cm nginx-test # 将port修改为8080
# 在查看pod, env
NGINX_PORT=80 # 当使用环境变量注入时,只在系统启动时有效
创建
]# cat t2.xiong.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
]# kubectl create cm nginx-test --from-file=t2.xiong.conf
查看
]# kubectl describe cm nginx-test
Name: t2-xiong
Namespace: default
Data
====
t2.xiong.conf: # key就是文件名
---- # 值是文本中的全部内容
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
以存储卷方式挂载
]# cat t3_cm.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
configMap/test: "nginx"
name: t3-xiong
labels:
app: t3-xiong
release: qa
spec:
containers:
- name: nginx-cm
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginx
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: nginx
configMap:
name: nginx-test
# 或挂载多个
volumes:
- name: conf # 该volumes的名字
configMap:
name: nginx-conf # 要使用configMap的名字
items:
- key: server1 # 要使用指定configMap里面的键名
path: s1.conf # 挂载之后的文件名
- key: server2 # 要使用指定configMap里面的键名
path: s2.conf # 挂载之后的文件名
测试
~]# kubectl exec -it t3-xiong -- /bin/sh
/etc/nginx/conf.d # ls -lh
lrwxrwxrwx 1 root root 20 May 7 06:02 t2.xiong.conf -> ..data/t2.xiong.conf
# root目录下创建xx.html 内容 hello world
]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
t3-xiong 1/1 Running 0 69s 10.244.1.2 slave1
]# curl 10.244.1.2/xx.html
hello world
ENV 是在容器启动的时候注入的,启动之后 kubernetes 就不会再改变环境变量的值,且同一个 namespace 中的 pod 的环境变量是不断累加的,为了更新容器中使用 ConfigMap 挂载的配置,可以通过滚动更新 pod 的方式来强制重新挂载 ConfigMap,也可以在更新了 ConfigMap 后,先将副本数设置为 0,然后再扩容。
Kubernetes用来配置分布式或者负载均衡集群化的配置中心,比如如果在nginx后面维护有20个tomcat,需要改修tomcat配置文件的一些配置信息,比如在修改tomcat连接redis的账号密码,那如何让20个tomcat都应用到新配置,此前的做法就是使用ansible,然后分批推,推的时候还需要以灰度的方式进行,如果一下全部推送那在某一时刻服务都无法访问了,所以即使借助了ansible来编排,也得一个一个来,但这种才20个,但是如果有30个或者更多这就比较麻烦了,所以很多规模非常大的网站都不会通过这种方式来配置应用程序,而是让应用程序所有配置都不通过本地配置文件加载,而是通过联系一个配置中心的服务去加载配置,所以称之为配置中心;
启动多个应用程序时,抛弃了传统从本地文件加载配置的方法,而是通过一个中心服务器来加载配置,这个服务叫做配置中心,随后我们在这个配置中心修改了配置以后,会通知给每一个进程,让进程自动进行重载,就能完成所有的进程进行重载,还可以以灰度的方式通知,那么他们就可以以灰度的方式去更新自己的配置信息;
国内有两个项目,为非容器化应用程序提供配置中心,协程的Apollo、百度的Distconf,所以在非容器化模式中,也可以使用配置中心,要使用配置中心还需要我们的程序支持从配置中心加载配置才行;
功能与configMap一样,信息以 base64编码存放 (相当于加密)
ConfigMap和Secret都作为k8s的标准资源,用于实现为Pod中容器提供配置信息,而这个配置信息它还扮演着K8s系统之上一组类似应用的配置中心,当配置发生变量时,我们只需要修改配置中心的配置,而后配置中心应用程序会自动更新配置信息并让其重载应用;
配置中心都需要存储大量的配置数据,那么这些配置数据可以存储在各式各样的存储系统当中,KV存储最为常见,比如zookepper、etcd这些配置工具,ConfigMap提供的配置信息,一般而言可以被我们的Pod容器以两种方式进行加载,所以Pod中的容器加载ConfigMap资源中的信息
第一种为环境变量为容器提供环境变量实现;
第二种方式就是通过volumes存储卷的方式配置;
而因为ConfigMap和Pod都是名称空间级别的资源,因此而者必须在同一名称空间下面引用;
ConfigMap允许我们在必要时进行修改,修改存储卷中内容在过一段随机时间之后会同步到Pod的容器中,但如果容器本身不支持自动重载,我们可以在外部发送重载命令,让其进行重载,也可以以灰度的方式进行,从这个角度上来说它的发布可能会有一定的问题,有一部分建构在k8s之上的高级工具也能够帮助我们完成k8s所不支持的各式各样的功能;
构建ConfigMap资源有如下几种方式
kubectl create secret -h
generic的方式主要是存储一些用户自定义的密码,非tls类型的,比如MySQL密码等,示例如下
可选参数
]# kubectl create secret generic -h
Examples:
# 可以指定文件,key为文件名
kubectl create secret generic my-secret --from-file=path/to/bar
# 指定key名,value为文件内容
kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-file=ssh-publickey=path/to/id_rsa.pub
# 手动指定kv
kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
创建一个 generic 资源
]# kubectl create secret generic mysql-pass --from-literal=password=xiong@123
secret/mysql-pass created
查看
]# kubectl get secret
NAME TYPE DATA AGE
mysql-pass Opaque 1 7s
]# kubectl describe secrets mysql-pass
Data
====
password: 9 bytes # key为password, 其值就是一个隐藏结果只显示字符串长度
# 查看更详细结果
]# kubectl get secrets mysql-pass -o yaml
apiVersion: v1
data:
password: eGlvbmdAMTIz # 通过-o yaml可以查看到其结果为base64编码
kind: Secret
metadata:
creationTimestamp: "2020-05-07T06:34:29Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:password: {}
f:type: {}
manager: kubectl
operation: Update
time: "2020-05-07T06:34:29Z"
name: mysql-pass
namespace: default
resourceVersion: "25605"
selfLink: /api/v1/namespaces/default/secrets/mysql-pass
uid: 4075a4d2-f81d-4e26-8d98-61df0f8eab51
type: Opaque
# 解码 base64
]# echo eGlvbmdAMTIz | base64 -d # 相对的来说如果有心加密的值也能被显示出来
xiong@123
通过环境变量方式注入
]# cat s1_secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: s1-secret
namespace: default
labels:
app: s1-secret
release: qa
spec:
containers:
- name: s1-secret
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
env:
- name: mysql_pass
valueFrom:
secretKeyRef:
name: mysql-pass # 指定secret定义的名称
key: password # 指定secret定义的key,注意这个key需要存在对应的资源中
验证
~]# kubectl exec s1-secret -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=s1-secret
mysql_pass=xiong@123
volume是通过文件的方式载入配置,比如tomcat的默认配置有指定一个管理的user,那么这个时候我们就可以把这个文件提取出来,载入Kubernetes作为Secret,而后通过volume的方式挂在到指定的目录下(可以挂载单个文件),覆盖原有文件;