概述

本文的核心是:如何处理应用程序的数据配置。

配置应用程序可以使用以下几种途径:

  • 向容器传递命令行参数
  • 为每个容器配置环境变量
  • 通过特殊的卷将配置文件挂载到容器中

向容器传递命令行参数

在Kubernetes中定义容器时,镜像的ENTRYPOINT和CMD都可以被覆盖(但是在Docker中,镜像的ENTRYPOINT是不能覆盖的)。仅需在容器定义中设置command和args的值。

构建一个镜像

loopechodate.sh:接收一个时间间隔的参数,追加输出当前时间到 /tmp/a.txt

#! /bin/sh
trap "exit" SIGINT
echo "interval is : $1"
while :
do
echo -e "$(date)" >> /tmp/a.txt
sleep $1
done

Dockerfile

FROM alpine
COPY loopechodate.sh /bin/
ENTRYPOINT ["/bin/loopechodate.sh"]
CMD ["5"]

构建、推送

-> [root@kube0.vm] [~] docker build -t registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate .
-> [root@kube0.vm] [~] docker push registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate

运行Pod

# cat config-cli.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-cli
spec:
containers:
- name: config-cli
image: registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate
args: ["2"] # 间隔时间2s

创建这个pod,然后查看一下logs

-> [root@kube0.vm] [~] k create -f config-cli.yaml
pod/config-cli created
-> [root@kube0.vm] [~] k exec -it config-cli cat /tmp/a.txt
Sun May 24 15:49:37 UTC 2020
Sun May 24 15:49:39 UTC 2020

为容器设置环境变量

Kubernetes中通过容器的env属性定义环境变量,采用$(VAR)语法在环境变量值中引用其他变量。

定义了两个环境变量FIRST_VAR,和引用了FIRST_VAR的SECOND_VAR。

# config-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-env
spec:
containers:
- name: config-env
image: nginx:alpine
env:
- name: FIRST_VAR
value: "Hello"
- name: SECOND_VAR
value: "$(FIRST_VAR) World!"

创建查看

-> [root@kube0.vm] [~] k create -f config-env.yaml
pod/config-env created -> [root@kube0.vm] [~] k exec config-env env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-env
FIRST_VAR=Hello
SECOND_VAR=Hello World!
.......

ConfigMap

ConfigMap本质上是一个键值对,值可以使短字面量,也可以是文件

创建ConfigMap

kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run] [options]

kubectl create命令支持从字面量(--from-literal),文件、目录(--from-file)、以及环境变量文件(--from-env-file)创建。而且不同选项可以合并,但是--from-env-file不能与--from-literal和--from-file一起指定。

下面是使用字面量、文件、目录合并创建。

-> [root@kube0.vm] [~] k create configmap mycm --from-literal=interval=3 --from-file=Dockerfile --from-file=/root/configdir
configmap/mycm created -> [root@kube0.vm] [~] k describe cm mycm
Name: mycm
Namespace: default
Labels: <none>
Annotations: <none> Data
====
Dockerfile:
----
FROM alpine
COPY loopechodate.sh /bin/
ENTRYPOINT ["/bin/loopechodate.sh"]
CMD ["5"] a.txt:
----
this is configdir/a.txt b.txt:
----
this is configdir/b.txt interval:
----
3
Events: <none>

使用环境变量文件创建

-> [root@kube0.vm] [~] echo -e "env1=1111\nenv2=2222" | tee test.env
env1=1111
env2=2222 -> [root@kube0.vm] [~] k create cm envcm --from-env-file=test.env
configmap/envcm created -> [root@kube0.vm] [~] k describe cm envcm
Name: envcm
Namespace: default
Labels: <none>
Annotations: <none> Data
====
env1:
----
1111
env2:
----
2222
Events: <none>

传递ConfigMap条目作为环境变量

定义一个Pod,引用了mycm中的两个key。

# config-env-cm.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-env-cm
spec:
containers:
- name: config-env-cm
image: nginx:alpine
env:
- name: INTERVAL
valueFrom:
configMapKeyRef: # 引用configMap中的内容
name: mycm # configMap的名字
key: interval # 引用哪个键
- name: ATXT
valueFrom:
configMapKeyRef:
name: mycm
key: a.txt

创建查看

-> [root@kube0.vm] [~] k create -f config-env-cm.yaml
pod/config-env-cm created -> [root@kube0.vm] [~] k exec config-env-cm env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-env-cm
INTERVAL=3
ATXT=this is configdir/a.txt
....

一次性传递ConfigMap所有条目作为环境变量

# config-env-cmall.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-env-cmall
spec:
containers:
- name: config-env-cmall
image: nginx:alpine
envFrom:
- prefix: CONFIG_
configMapRef:
name: mycm

创建查看

-> [root@kube0.vm] [~] k create -f config-env-cmall.yaml
pod/config-env-cmall created -> [root@kube0.vm] [~] k exec config-env-cmall env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-env-cmall
CONFIG_interval=3
CONFIG_Dockerfile=FROM alpine
COPY loopechodate.sh /bin/
ENTRYPOINT ["/bin/loopechodate.sh"]
CMD ["5"] CONFIG_a.txt=this is configdir/a.txt CONFIG_b.txt=this is configdir/b.txt
........

传递ConfigMap条目作为命令行参数

containers.args无法直接引用ConfigMap,但是可以通过$(ENV_VAR_NAME)引用环境变量,间接引用ConfigMap。

# config-cli-cm.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-cli-cm
spec:
containers:
- name: config-cli-cm
image: registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: mycm
key: interval
args: ["$(INTERVAL)"]

创建查看

-> [root@kube0.vm] [~] k create -f config-cli-cm.yaml
pod/config-cli-cm created -> [root@kube0.vm] [~] k logs config-cli-cm
interval is : 3 -> [root@kube0.vm] [~] k exec config-cli-cm cat /tmp/a.txt
Mon May 25 05:11:14 UTC 2020
Mon May 25 05:11:17 UTC 2020
Mon May 25 05:11:20 UTC 2020

将ConfigMap条目暴露为卷

环境变量和命令行参数作为配置值通常适用于变量值较短的场景。如果想暴露ConfigMap中配置文件,可以将ConfigMap或者其条目通过卷的形式挂载到容器。

# config-volume-cm.yaml
apiVersion: v1
kind: Pod
metadata:
name: config-volume-cm
spec:
containers:
- name: config-volume-cm
image: nginx:alpine
volumeMounts:
- name: config
mountPath: /tmp/mycm
readOnly: true
volumes:
- name: config
configMap:
name: mycm

创建查看

-> [root@kube0.vm] [~] k create -f config-volume-cm.yaml
pod/config-volume-cm created -> [root@kube0.vm] [~] k exec config-volume-cm ls /tmp/mycm
Dockerfile
a.txt
b.txt
interval

如果只想暴露指定的条目,可以指定volumes.configMap.items

  volumes:
- name: config
configMap:
name: mycm
items:
- key: interval
path: interval2

输出结果是:

-> [root@kube0.vm] [~] k exec config-volume-cm ls /tmp/mycm
interval2

configMap.defaultMode设置访问权限

挂载文件夹会隐藏该文件夹中已存在的文件,挂载ConfigMap的单独条目不会隐藏其他文件

Secret

Secret与ConfigMap一样都是键值对,也可以作为环境变量传递给容器,条目也能暴露称为卷中的文件。但是为了安全起见,请始终使用Secret卷暴露Secret。Secret只会存储在内存中,永不写入物理存储。Secret条目的内容会被进行Base64编码。

默认令牌

每个pod默认都会挂载一个Secret,该Secret包含ca.crt、namespace、token,包含了从Pod内部安全访问Kubernetes Api服务器所需的全部信息。

先随便找一个pod查看。

-> [root@kube0.vm] [~] k describe pod config-volume-cm
Name: config-volume-cm
Namespace: default
......
Mounts:
/tmp/mycm from config (ro)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-5g447 (ro)
......
Volumes:
......
default-token-5g447:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-5g447
Optional: false
......

再查看一下详情

-> [root@kube0.vm] [~] k describe secrets default-token-5g447
Name: default-token-5g447
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: bd92a729-ed0a-491d-b600-0f86824ad588 Type: kubernetes.io/service-account-token Data
====
ca.crt: 1025 bytes
namespace: 7 bytes
token: eyJhbGciOiJSUzI1....

使nginx支持https

创建私钥和证书

-> [root@kube0.vm] [~/cert] openssl genrsa -o https.key 2048
-> [root@kube0.vm] [~/cert] openssl req -new -x509 -key https.key -out https.cert -days 3650 -subj /CN=www.mysecret.com

创建Secret

创建一个类型为generic的Secret,其他两个类型是docker-registry、tls。

-> [root@kube0.vm] [~/cert] echo bar > foo # 后面会用到

-> [root@kube0.vm] [~/cert] k create secret generic mysecret --from-file=./
secret/mysecret created

将ssl.conf放入ConfigMap中

# ssl.conf
server {
listen 80;
listen 443 ssl;
server_name www.mysecret.com;
ssl_certificate certs/https.cert;
ssl_certificate_key certs/https.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5; location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
-> [root@kube0.vm] [~] k create configmap sslcm --from-file=ssl.conf
configmap/sslcm created

创建查看

先看一下描述文件

# https-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: https-nginx
spec:
containers:
- name: https-nginx
image: nginx:alpine
env:
- name: FOO
valueFrom:
secretKeyRef:
name: mysecret
key: foo
volumeMounts:
- name: sslcm
mountPath: /etc/nginx/conf.d/
readOnly: true
- name: mysecret
mountPath: /etc/nginx/certs/
readOnly: true
ports:
- containerPort: 80
- containerPort: 443
volumes:
- name: sslcm
configMap:
name: sslcm
items:
- key: ssl.conf
path: https.conf
- name: mysecret
secret:
secretName: mysecret

创建、设置端口转发

-> [root@kube0.vm] [~] k create -f https-nginx.yaml
pod/https-nginx created -> [root@kube0.vm] [~] k port-forward https-nginx 443:443
Forwarding from 127.0.0.1:443 -> 443

新开窗口,发送请求

-> [root@kube0.vm] [~] curl -k https://localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
.....

查看Secret通过环境变量暴露的条目

-> [root@kube0.vm] [~] k exec https-nginx env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=https-nginx
FOO=bar
.......

使用私有的镜像仓库

使用方法:创建一个docker-registry类型的secret,然后

创建一个docker-registry类型的secret。 --docker-server 用于指定仓库服务的地址。

k create secret docker-registry dockerregsecret --docker-username=zhangsan --docker-password=123 --docker-email=zhangsan@163.com

在Pod中的containers.imagePullSecrets.name中引用。

apiVersion: v1
kind: Pod
metadata:
name: private-pod
spec:
imagePullSecrets:
- name: dockerregsecret
containers:
- image: username/private:tag
name: main

StringData与二进制数据

采用Base64编码,使Secret也能存储二进制数据,而纯文本值可以在secret.StringData中定义,但StringData字段是只写的,kubectl get -o yaml查看时会被Base64编码显示在data下。

注意事项

  • 在Kubernetes中定义容器时,镜像的ENTRYPOINT和CMD都可以被覆盖。但是在Docker中,镜像的ENTRYPOINT是不能覆盖的。
  • 可以将configMapKeyRef.optional设置为true,这样即使ConfigMap不存在,容器也能启动。

小结

  • 对于环境变量:使用valueFrom.configMapKeyRef引用一个ConfigMap条目;使用envFrom.configMapRef引用全部,envFrom.prefix设置前缀。
  • 对于命令行参数:containers.args无法直接引用ConfigMap,但是可以通过$(ENV_VAR_NAME)引用环境变量,间接引用了ConfigMap。
  • 挂载文件夹会隐藏该文件夹中已存在的文件,挂载ConfigMap的单独条目不会隐藏其他文件
  • 将ConfigMap暴露为卷可以达到热更新的效果。
  • 每个pod默认都会挂载一个Secret,该Secret包含ca.crt、namespace、token,包含了从Pod内部安全访问Kubernetes Api服务器所需的全部信息。
  • 采用Base64编码,使Secret也能存储二进制数据,而纯文本值可以在secret.StringData中定义,但StringData字段是只写的,kubectl get -o yaml查看时会被Base64编码显示在data下。

Kubernetes学习笔记(六):使用ConfigMap和Secret配置应用程序的更多相关文章

  1. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  2. Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  3. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  4. python3.4学习笔记(六) 常用快捷键使用技巧,持续更新

    python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...

  5. Go语言学习笔记六: 循环语句

    Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...

  6. 【opencv学习笔记六】图像的ROI区域选择与复制

    图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...

  7. Linux学习笔记(六) 进程管理

    1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...

  8. Kubernetes 学习笔记(一):基础概念

    个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...

  9. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

随机推荐

  1. Image Filter and Recover

    这是CS50的第四次大作业,顺便学习了图像的入门知识. 基础 黑白图(bitmap)的每个像素点只能取值0/1,1代表白色,0代表黑色. 常见的图片格式有JPEG/PNG/BMP,这些格式都支持RGB ...

  2. 2019 ICPC 银川网络赛 H. Fight Against Monsters

    It is my great honour to introduce myself to you here. My name is Aloysius Benjy Cobweb Dartagnan Eg ...

  3. Git上传本地仓库项目到gitee远程仓库(命令篇)

    前言:最近整理了一下自己之前的自学代码,包括一些练习的项目.发现有些杂乱,故想使用Gitte(码云)管理.加上不少公司使用Git,所以写了这篇文章记录. 如果我们本地有了项目,那么如何上传到码云上呢? ...

  4. C :uthash

    参考: [1] uthash | 学步园 [2] 源码 [3] 官方文档 [4] [5] 一.哈希表的概念及作用 在一般的线性表或者树中,我们所储存的值写它的存储位置的关系是随机的.因此,在查找过程中 ...

  5. Android原生多语言切换方案,兼容Android10

    前言 一个应用若需要国际化,至少需要支持中文和英语这两种语言,而同时随着谷歌的系统的更新,安卓系统可以设置当前语言的首选语言.因此,本文立足于此,多语言的切换方案为:App固定的文字内容,跟随系统,中 ...

  6. 开源 一套 Blazor Server 端精致套件

    Blazor 作为一种 Web 开发的新技术已经发展有一段时间了,有些人标称 无 JS 无 TS,我觉得有点误导新人的意味,也有人文章大肆宣传 Blazor 是 JavaScript 的终结者,是为了 ...

  7. 如何对Code Review的评论进行分级

    我曾写过一篇关于Code Review的文章<Code Review 最佳实践>,在文章中建议对Code Review的评论进行分级: 建议可以对Review的评论进行分级,不同级别的结果 ...

  8. 一文带你深入了解 Lambda 表达式和方法引用

    前言 尽管目前很多公司已经使用 Java8 作为项目开发语言,但是仍然有一部分开发者只是将其设置到 pom 文件中,并未真正开始使用.而项目中如果有8新特性的写法,例如λ表达式.也只是 Idea Al ...

  9. 【Kafka】实时看板案例

    目录 项目需求 项目模型 实现步骤 项目需求 快速计算双十一当天的订单量和销售金额 项目模型 实现步骤 一.创建topic bin/kafka-topics.sh --create --topic i ...

  10. scala 隐式参数

    def test(implicit name: String = "susu"): Unit ={ println(name);} 三种调用方法如下:test("dudu ...