
Kubernetes 应用配置管理
需求来源
背景问题
除了依托容器镜像来定义运行的Container,Pod还需要解决如下问题:
1. 不可变基础设施(容器)的可变配置
2. 敏感信息的存储与使用(如密码、Token等)
3. 集群中Pod自我的身份认证
4. 容器运行的资源配置的管理
6. 容器启动前置条件校验等
在Kubernetes里面,我们可以参考下图来解释它是如何做这些配置管理
ConfigMap
ConfigMap介绍
主要管理容器配置内所需要的配置文件,环境变量,命令行参数等可变配置。用于解耦容器镜像和可变配置,从而保障工作负载(Pod)的可移植性。(简单示例如下)
这是 ConfigMap 本身的一个定义,它包括两个部分:一个是 ConfigMap 元信息,我们关注 name 和 namespace 这两个信息。接下来这个 data 里面,可以看到它管理了两个配置文件。它的结构其实是这样的:从名字看ConfigMap中包含Map单词,Map 其实就是 key:value,key 是一个文件名,value 是这个文件的内容。
ConfigMap创建
创建的命令: kubectl create configmap [NAME][DATA]
其中[DATA]
有两个参数:
—from-file 指定目录或者文件
—from-literal 指定键值对
cd /home
echo "{ "name":"k1" }" > myjson1.json
kubectl create configmap kube-myjson-config --from-file=/home/myjson1.json -n default
kubectl get configmap kube-myjson-config -o yaml -n default
创建的命令所生成的ConfigMap如下所示:
apiVersion: v1
data:
myjson1.json: |
{ name:k1 }
kind: ConfigMap
metadata:
creationTimestamp: "2021-03-09T06:29:22Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:myjson1.json: {}
manager: kubectl
operation: Update
time: "2021-03-09T06:29:22Z"
name: kube-myjson-config
namespace: default
resourceVersion: "10750078"
selfLink: /api/v1/namespaces/default/configmaps/kube-myjson-config
uid: a878eba6-d69d-46d2-ace3-7cbd341534d6
接着我们通过键值对的方式对其进行创建:
kubectl create configmap mykv-configmap --from-literal=bob.foo=foo --from-literal=bob.boo=boo
kubectl get configmap mykv-configmap -o yaml
apiVersion: v1
data:
bob.boo: boo
bob.foo: foo
kind: ConfigMap
metadata:
creationTimestamp: "2021-03-09T07:09:23Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:bob.boo: {}
f:bob.foo: {}
manager: kubectl
operation: Update
time: "2021-03-09T07:09:23Z"
name: mykv-configmap
namespace: rabbitmq-test
resourceVersion: "10754107"
selfLink: /api/v1/namespaces/rabbitmq-test/configmaps/mykv-configmap
uid: 196d0930-d3b2-415a-95ac-b8a3e283f647
ConfigMap使用
ConfigMap主要被Pod使用,一般用于挂载Pod用的配置文件,环境变量,命令行参数等。
(下面代码举例)
apiVersion: v1
kind: Pod
metadata:
name: cm-env-test
spec:
containers:
- name: test-container
image: docker.io/busybox
command: [ "/bin/sh","-c","env" ]
env:
# 用mykv-configmap中的bob.foo定义环境变量
- name: MYKV
valueFrom:
configMapKeyRef:
name: mykv-configmap
key: bob.foo
restartPolicy: Never
### 查看一下日志情况
# kubectl logs pods/cm-env-test
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.43.0.1:443
HOSTNAME=cm-env-test
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.43.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.43.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.43.0.1
PWD=/
MYKV=foo
也可以直接在命令行中使用ConfigMap定义的环境变量,例如我们稍作修改
(大家自己尝试一下啊)
apiVersion: v1
kind: Pod
metadata:
name: cm-env-test
spec:
containers:
- name: test-container
image: docker.io/busybox
command: [ "/bin/sh","-c","echo $(MYKV)" ]
env:
- name: MYKV
valueFrom:
configMapKeyRef:
name: mykv-configmap
key: bob.foo
restartPolicy: Never
还可以用ConfigMap挂载配置文件
apiVersion: v1
kind: Pod
metadata:
name: cm-env-test
spec:
containers:
- name: test-container
image: docker.io/busybox
command: [ "/bin/sh","-c","ls -al /etc/config" ]
# ConfigMap中指定的内容以文件形式挂载在容器中的/etc/config目录下
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: mykv-configmap
restartPolicy: Never
# kubectl logs pods/cm-env-test
total 12
drwxrwxrwx 3 root root 4096 Mar 9 08:06 .
drwxr-xr-x 1 root root 4096 Mar 9 08:07 ..
drwxr-xr-x 2 root root 4096 Mar 9 08:06 ..2021_03_09_08_06_58.974275824
lrwxrwxrwx 1 root root 31 Mar 9 08:06 ..data -> ..2021_03_09_08_06_58.974275824
lrwxrwxrwx 1 root root 14 Mar 9 08:06 bob.boo -> ..data/bob.boo
lrwxrwxrwx 1 root root 14 Mar 9 08:06 bob.foo -> ..data/bob.foo
不可变更的 ConfigMap
当集群中Pod的状态很多的时候我们想保证ConfigMap只能删除不能修改可以通过ImmutableEphemeralVolumes
特性来控制,我们可以通过在Yaml中0级添加immutable: true
来进行设定
ConfigMap使用注意点
1. ConfigMap文件大小限制:1MB(ETCD要求)
2. Pod只能引用相同Namespace中的ConfigMap
3. Pod引用的ConfigMap不存在时,Pod无法创建成功。即Pod创建前需要先创建好ConfigMap
4. 使用envFrom从ConfigMap来配置环境变量时,如果ConfigMap中的某些key被认为无效(比如key名称中带有数字),该环境变量将不会注入容器,但是Pod可以正常创建。
5. 只有通过k8s api创建的pod才能使用ConfigMap,其他方式创建的pod(如manifest创建的static pod)不能使用ConfigMap
以往关于ConfigMap的文章
Secret
Secret介绍
Secret是在集群中用于存储密码,token等敏感信息用的资源对象。其中敏感信息采用base-64编码保存,相比存储在明文的ConfigMap中更规范,更安全。
关于 Secret 的类型,它的通过不同的类型应用于不同的场景,下面我将列一下
Secret 的类型 | |
---|---|
Opaque | 用户定义的任意数据 |
kubernetes.io/service-account-token | 服务账号令牌 |
kubernetes.io/dockercfg | ~/.dockercfg 文件的序列化形式 |
kubernetes.io/dockerconfigjson | ~/.docker/config.json 文件的序列化形式 |
kubernetes.io/basic-auth | 用于基本身份认证的凭据 |
kubernetes.io/ssh-auth | 用于 SSH 身份认证的凭据 |
kubernetes.io/tls | 用于 TLS 客户端或者服务器端的数据 |
bootstrap.kubernetes.io/token | 启动引导令牌数据 |
Secret创建
Secret创建可以是用户自己创建,也有Secret是系统自动创建
- 比如: K8s为每个namespace的默认用户(default ServiceAccount)创建的Secret
手动创建命令:kubectl create secret generic [NAME] [DATA] [TYPE]
其中Data:可以指定文件/键值对
另外TYPE:默认为Opaque
# 创建数据库账号和密码的Secret
kubectl create secret generic mysql-auth --from-literal=username=root --from-literal=password=ikubernetes
# 查看secrets的情况
# kubectl get secrets mysql-auth -o yaml
apiVersion: v1
data:
password: aWt1YmVybmV0ZXM=
username: cm9vdA==
kind: Secret
metadata:
creationTimestamp: "2021-03-10T02:39:38Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:password: {}
f:username: {}
f:type: {}
manager: kubectl
operation: Update
time: "2021-03-10T02:39:38Z"
name: mysql-auth
namespace: rabbitmq-test
resourceVersion: "10872072"
selfLink: /api/v1/namespaces/rabbitmq-test/secrets/mysql-auth
uid: e71db921-5082-480d-af94-3e8d0037d515
type: Opaque
# 如果想解码可以执行: echo aWt1YmVybmV0ZXM= | base64 -d
Docker 配置 Secret可以使用如下命令
kubectl create secret docker-registry secret-tiger-docker \
--docker-username=tiger \
--docker-password=pass113 \
--docker-email=tiger@acme.com
TLS 配置 Secret可以使用如下命令
kubectl create secret tls my-tls-secret \
--cert=path/to/cert/file \
--key=path/to/key/file
Secret使用
Secret 主要被Pod使用,一般通过volume挂载到指定的容器目录,供容器中业务使用。另外在需要访问私有镜像仓库时,也可以引用Secret来实现
使用私有镜像库
私有镜像仓库的信息可以通过Secret存储在集群中,Pod如果需要使用私有镜像仓库,可以通过如下两种方式来配置:
1. Pod.spec.imagePullSecrets来指定secret
2. ServiceAccount中设置imagesPullSecrets,然后自动为使用该SA的Pod注入imagePullSecrets信息
Secret使用的注意点
1. Secret 文件大小限制:1MB
2. Secret虽然采用base-64编码,但是可以简单解码查看原始信息。因此机密信息采用Secret存储仍需要慎重考虑或者Secret访问者进行控制。对Secret加密有较强需求,可以考虑结合Kubernetes + Vault来解决敏感信息的加密和权限管理。
3. Secret最佳实践:因为list/watch方式获取Secret信息。而推荐使用GET来获取需要的Secret,从而减少更多Secret暴露的可能性。
ServiceAccount介绍
ServiceAccount主要用于解决Pod在集群中的身份认证问题。其中认证使用的授权信息,则利用前面讲到Secret(type=kubernetes.io/service-account-token)进行管理
# kubectl get serviceaccount -o yaml
apiVersion: v1
items:
- apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2021-02-06T08:45:14Z"
name: default
namespace: rabbitmq-test
resourceVersion: "6264276"
selfLink: /api/v1/namespaces/rabbitmq-test/serviceaccounts/default
uid: 67618b0b-2819-402f-bd31-d7dbd8448eaf
secrets:
- name: default-token-mf7gv
kind: List
metadata:
resourceVersion: ""
selfLink: ""
我们发现每一个AccountService它都有一个用于访问API的Secret对象,它所对应的Secret又包含重要的crt,token,namespace的信息用于访问API的时候确认身份信息,但具体如何确认身份是通过RBAC的方式进行管理的。
# kubectl get secret/default-token-mf7gv -o yaml
apiVersion: v1
data:
ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJWakNCL3FBREFnRUNBZ0VBTUFvR0NDcUdTTTQ5QkFNQ01DTXhJVEFmQmdOVkJBTU1HR3N6Y3kxelpYSjIKWlhJdFkyRkFNVFl3TkRZek5UWXpOekFlRncweU1ERXhNRFl3TkRBM01UZGFGdzB6TURFeE1EUXdOREEzTVRkYQpNQ014SVRBZkJnTlZCQU1NR0dzemN5MXpaWEoyWlhJdFkyRkFNVFl3TkRZek5UWXpOekJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQkhqM1QzZWVWNEtkeEx5bHp0V1NUUGVpZDA4blJybzkzOVQvSDZLVW9jcEQKMVZDN2x2elpJSUdqbXl5RFYybWFzY0RtV3JZT1JtVDMyUFJMVnpQbEd1R2pJekFoTUE0R0ExVWREd0VCL3dRRQpBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUdxeFF1ZVp1SkZECmU4M3JDVWoyTEYrUnRqWUhhTVR3VkRoVHQ1Y2NhMGRCQWlCM0RiZXNNQ21aNTd5aVBBd1Rhdm5nZXNzV1V6T1EKbTdndE9scTd1TVlOV0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
namespace: cmFiYml0bXEtdGVzdA==
token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklrMWljVFZ0YjBSQ09FVTFWbUZRUVcxVGJHbFZOemRxY2treWJubGpjamd0Y25JeE9EQlhSVGQ2T0dzaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUp5WVdKaWFYUnRjUzEwWlhOMElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WldOeVpYUXVibUZ0WlNJNkltUmxabUYxYkhRdGRHOXJaVzR0YldZM1ozWWlMQ0pyZFdKbGNtNWxkR1Z6TG1sdkwzTmxjblpwWTJWaFkyTnZkVzUwTDNObGNuWnBZMlV0WVdOamIzVnVkQzV1WVcxbElqb2laR1ZtWVhWc2RDSXNJbXQxWW1WeWJtVjBaWE11YVc4dmMyVnlkbWxqWldGalkyOTFiblF2YzJWeWRtbGpaUzFoWTJOdmRXNTBMblZwWkNJNklqWTNOakU0WWpCaUxUSTRNVGt0TkRBeVppMWlaRE14TFdRM1pHSmtPRFEwT0dWaFppSXNJbk4xWWlJNkluTjVjM1JsYlRwelpYSjJhV05sWVdOamIzVnVkRHB5WVdKaWFYUnRjUzEwWlhOME9tUmxabUYxYkhRaWZRLk1mbElISFg1SDVzbjk0cWgxeko1dlpzYThDa09ZTndCVVRPc2xMZUQtM2ZTRlM1cTYtbWhrY2RWRHRNTzdrdVV6QnI3aTRZZEt5QV93UU1fQVhoWDBpcUxXTDdCS21fQjIweDNiYnA0MldMZlVqVmctMndFd0N6cGY0MjBtMXk0VkJ3TTgyajRzbkRLMHdxSWdPUjlaOEpIbHVVZXVMaGd0Z1pIdmNGNl90cVZ3Um1EWFNrdUFWcE91WUNtU21EdzdMTkpGOUZrUHZpUzBmRG9jcnBrNGtyYlZkQnpsUFVTbzBtZ1ZCQ1N6Sks2OVVuUUd3X2E0cmhteWs5eWpGZ0RzSHByNHFrelZsckxXRWNoWU5ITUJlc29CdWRqa2YzTllhX2ZydlIzZ3YxdE1WMkExYmpyS09tUkt5dmNSYl9KY3NZazU3blktbE83cDNOVW82RzlrQQ==
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 67618b0b-2819-402f-bd31-d7dbd8448eaf
creationTimestamp: "2021-02-06T08:45:14Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:ca.crt: {}
f:namespace: {}
f:token: {}
f:metadata:
f:annotations:
.: {}
f:kubernetes.io/service-account.name: {}
f:kubernetes.io/service-account.uid: {}
f:type: {}
manager: k3s
operation: Update
time: "2021-02-06T08:45:14Z"
name: default-token-mf7gv
namespace: rabbitmq-test
resourceVersion: "6264275"
selfLink: /api/v1/namespaces/rabbitmq-test/secrets/default-token-mf7gv
uid: 01af3784-5106-42aa-874a-a901f8ac3134
type: kubernetes.io/service-account-token
当在Pod中使用指定私有的镜像仓库(imagePullSecret)的时候也可以添加对应的Secret,可以进行CA认证
Resource(容器资源配置管理)
当您指定一个Pod,您可以选择指定每个资源的数量容器需求。指定的最常见资源是CPU和内存(RAM)。
支持资源类型
- CPU: 单位 millicore(1 Core = 1000 millicore)
- Memory: 单位 Byte
- ephemeral storage(临时存储):单位 Byte
- 自定义资源:配置时必须为整数
配置方法
资源配置分为request/limit两种类型
- CPU
Pod.spec.containers[].resources.limits.cpu
Pod.spec.containers[].resources.requests.cpu
- Memory
Pod.spec.containers[].resources.limits.memory
Pod.spec.containers[].resources.requests.memory
- ephemeral storage(临时存储)
Pod.spec.containers[].resources.limits.ephemeral-storage
Pod.spec.containers[].resources.requests.ephemeral-storage
想了解更多详细的细节可以通过kubectl explain Pod.spec.containers.resources.limits.cpu
的方式进行获取信息
举个例子
以下 Pod 有两个 Container。每个 Container 的请求为 0.25 cpu 和 64MiB(226 字节)内存, 每个容器的资源约束为 0.5 cpu 和 128MiB 内存。 你可以认为该 Pod 的资源请求为 0.5 cpu 和 128 MiB 内存,资源限制为 1 cpu 和 256MiB 内存。
apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: app
image: images.my-company.example/app:v4
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: log-aggregator
image: images.my-company.example/log-aggregator:v6
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
关于QOS
Security Context
Security Context介绍
安全上下文(Security Context)定义 Pod 或 Container 的特权与访问控制设置。
1. 容器级别的Security Context:仅对指定容器生效
2. Pod级别的Security Context:对指定Pod中的所有容器生效
3. Pod Security Policies(PSP):对集群内所有的Pod生效
权限和访问控制设置项
1. 自主访问控制(Discretionary Access Control):基于用户 ID(UID)和组 ID(GID). 来判定对对象(例如文件)的访问权限。
2. SELinux:通过SELinux的策略配置控制用户,进程等对文件等访问控制。
3. privileged:容器是否为特权模式。
4. Linux Capabilities:给特定进程配置privileged能力
5. AppArmor:控制可执行文件的访问控制权限(读写文件/目录,网络端口读写等)。
6. Seccomp:控制进程可以操作的系统调用。
7. AllowPrivilegeEscalation:控制进程是否可以获得超出其父进程的特权。 此布尔值直接控制是否为容器进程设置 no_new_privs标志。 当容器以特权模式运行或者具有 CAP_SYS_ADMIN 权能时,AllowPrivilegeEscalation 总是为 true。
8. readOnlyRootFilesystem:以只读方式加载容器的根文件系统。
InitContainer
InitContainer和普通Container的区别
1. InitContainer会先于普通Container启动执行,直到所以InitContainer执行成功后,普通Container才会被启动
2. Pod中多个InitContainer之间是按次序依次启动执行,而Pod中多个普通Container是并行启动
3. InitContainer执行成功后就结束退出了,而普通容器可能会一直执行或者重启(restartPolicy!=Never)
InitContainer用途
基于InitContainer和普通Container的区别,一般InitContainer用于普通Container启动钱的初始化(如配置文件准备)或者普通Container启动的前置条件检验(如网络连通检验)如下图所示:
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

