Kubernetes带你从头到尾捋一遍

Posted 果子哥丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes带你从头到尾捋一遍相关的知识,希望对你有一定的参考价值。

Kubernetes最全

k8s技术实践

为什么要学习 Kubernetes?
虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集群管理、资源调度、文件管理等等。

kubernetes 介绍

Kubernetes 解决的核心问题

  • 服务发现和负载均衡
    • Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果到容器的流量很大,Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。
  • 存储编排
    • Kubernetes 允许您自动挂载您选择的存储系统,例如本地存储、公共云提供商等。
  • 自动部署和回滚
    • 您可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态更改为所需状态。例如,您可以自动化 Kubernetes 来为您的部署创建新容器,删除现有容器并将它们的所有资源用于新容器。
  • 自动二进制打包
    • Kubernetes 允许您指定每个容器所需 CPU 和内存(RAM)。当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。
  • 自我修复
    • Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。
  • 密钥与配置管理
    • Kubernetes 允许您存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。您可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

Kubernetes 的出现不仅主宰了容器编排的市场,更改变了过去的运维方式,不仅将开发与运维之间边界变得更加模糊,而且让 DevOps 这一角色变得更加清晰,每一个软件工程师都可以通过 Kubernetes 来定义服务之间的拓扑关系、线上的节点个数、资源使用量并且能够快速实现水平扩容、蓝绿部署等在过去复杂的运维操作。

Kubernetes 知识图谱

Kubernetes 软件架构


架构说明
Kubernetes 遵循非常传统的客户端/服务端的架构模式,客户端可以通过 RESTful 接口或者直接使用 kubectl 与 Kubernetes 集群进行通信,这两者在实际上并没有太多的区别,后者也只是对 Kubernetes 提供的 RESTful API 进行封装并提供出来。每一个 Kubernetes 集群都是由一组 Master 节点和一系列的 Worker 节点组成,其中 Master 节点主要负责存储集群的状态并为 Kubernetes 对象分配和调度资源。

主节点服务 - Master 架构
作为管理集群状态的 Master 节点,它主要负责接收客户端的请求,安排容器的执行并且运行控制循环,将集群的状态向目标状态进行迁移。Master 节点内部由下面三个组件构成:

  • API Server: 负责处理来自用户的请求,其主要作用就是对外提供 RESTful 的接口,包括用于查看集群状态的读请求以及改变集群状态的写请求,也是唯一一个与 etcd 集群通信的组件。
  • etcd: 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。
  • Scheduler: 主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。
  • controller-manager: 在主节点上运行控制器的组件,从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。这些控制器包括:节点控制器(负责在节点出现故障时进行通知和响应)、副本控制器(负责为系统中的每个副本控制器对象维护正确数量的 Pod)、端点控制器(填充端点 Endpoints 对象,即加入 Service 与 Pod))、服务帐户和令牌控制器(为新的命名空间创建默认帐户和 API 访问令牌)。

工作节点 - Node 架构
Worker 节点实现就相对比较简单了,它主要由 kubelet 和 kube-proxy 两部分组成。

  • kubelet: 是工作节点执行操作的 agent,负责具体的容器生命周期管理,根据从数据库中获取的信息来管理容器,并上报 pod 运行状态等。
  • kube-proxy: 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上同一类标签的 Pod。kube-proxy 实质就是通过操作防火墙规则(iptables或者ipvs)来实现 Pod 的映射。
  • Container Runtime: 容器运行环境是负责运行容器的软件,Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI(容器运行环境接口)。


主要由以下几个核心组件组成:

  • apiserver
    所有服务访问的唯一入口,提供认证、授权、访问控制、API 注册和发现等机制
  • controller manager
    负责维护集群的状态,比如副本期望数量、故障检测、自动扩展、滚动更新等
  • scheduler
    负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上
  • etcd
    键值对数据库,保存了整个集群的状态
  • kubelet
    负责维护容器的生命周期,同时也负责 Volume 和网络的管理
  • kube-proxy
    负责为 Service 提供 cluster 内部的服务发现和负载均衡
  • Container runtime
    负责镜像管理以及 Pod 和容器的真正运行

除了核心组件,还有一些推荐的插件:

  • CoreDNS
    可以为集群中的 SVC 创建一个域名 IP 的对应关系解析的 DNS 服务
  • Dashboard
    给 K8s 集群提供了一个 B/S 架构的访问入口
  • Ingress Controller
    官方只能够实现四层的网络代理,而 Ingress 可以实现七层的代理
  • Prometheus
    给 K8s 集群提供资源监控的能力
  • Federation
    提供一个可以跨集群中心多 K8s 的统一管理功能,提供跨可用区的集群

❤Kubernetes安装

安装v1.16.0版本,竟然成功了。记录在此,避免后来者踩坑。

本章节,安装大步骤如下:
安装docker-ce 18.09.9(所有机器)
设置k8s环境前置条件(所有机器)
安装k8s v1.16.0 master管理节点
安装k8s v1.16.0 node工作节点
安装flannel(master)
详细安装步骤参考:CentOS 搭建 K8S,一次性成功,收藏了!

集群安装教程请参考:全网最新、最详细基于V1.20版本,无坑部署最小化 K8S 集群教程

Kubernetes Pod实现原理

Pod 就是最小并且最简单的 Kubernetes 对象

Pod、Service、Volume 和 Namespace 是 Kubernetes 集群中四大基本对象,它们能够表示系统中部署的应用、工作负载、网络和磁盘资源,共同定义了集群的状态。Kubernetes 中很多其他的资源其实只对这些基本的对象进行了组合。

  • Pod -> 集群中的基本单元
  • Service -> 解决如何访问 Pod 里面服务的问题
  • Volume -> 集群中的存储卷
  • Namespace -> 命名空间为集群提供虚拟的隔离作用

详细介绍请参考:Kubernetes 之 Pod 实现原理

Kubernetes 之 Pod 实现原理

https://mp.weixin.qq.com/s?__biz=MzI0MDQ4MTM5NQ==&mid=2247511562&idx=2&sn=cc8aa9ddbf373a41af579186cd889574&chksm=e918cb16de6f42003fe7d8fdc623c246daf2beff249166e225e6fb5c045c88bd82d24f7673d7&cur_album_id=1790241575034290179&scene=21#wechat_redirect

Harbor仓库

Kuternetes 企业级 Docker 私有仓库 Harbor 工具。

Harbor 的每个组件都是以 Docker 容器的形式构建的,使用 Docker Compose 来对它进行部署。用于部署 Harbor 的 Docker Compose 模板位于 /Deployer/docker-compose.yml 中,其由 5 个容器组成,这几个容器通过 Docker link 的形式连接在一起,在容器之间通过容器名字互相访问。对终端用户而言,只需要暴露 Proxy(即nginx) 的服务端口即可。

  • Proxy
    • 由Nginx服务器构成的反向代理
  • Registry
    • 由Docker官方的开源官方的开源Registry镜像构成的容器实例
  • UI
    • 即架构中的core services服务,构成此容器的代码是Harbor项目的主体
  • mysql
    • 由官方MySQL镜像构成的数据库容器
  • Log
    • 运行着rsyslogd的容器,通过log-driver的形式收集其他容器的日志

详细介绍与搭建步骤请参考:企业级环境中基于 Harbor 搭建

企业级环境中基于 Harbor 搭建

https://mp.weixin.qq.com/s?__biz=MzI0MDQ4MTM5NQ==&mid=2247512177&idx=2&sn=e14e94410df53c74e99aac958a9b5658&chksm=e918d56dde6f5c7bc9ff13c39f6c8add6398babe3cdeb188bf38fd7be6a3ca527f53e11d3472&scene=21&cur_album_id=1790241575034290179#wechat_redirect

❤K8s服务发现

Kubernetes 中为了实现服务实例间的负载均衡和不同服务间的服务发现,创造了 Service 对象,同时又为从集群外部访问集群创建了 Ingress 对象。

可参考:Kubernetes 之服务发现

Kubernetes 中为了实现服务实例间的负载均衡和不同服务间的服务发现,创造了 Service 对象,同时又为从集群外部访问集群创建了 Ingress 对象。

Service服务

Service 在 K8S 中有以下四种类型

VIP(虚拟 IP 地址)和 Service 代理

  • 在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟IP)的形式,而不是 ExternalName 的形式。
  • 在 Kubernetes v1.0 版本,代理完全在 userspace。在 Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。从 Kubernetes v1.2 起,默认就是,iptables 代理。在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理。
  • 在 Kubernetes 1.14 版本开始默认使用 ipvs 代理。在 Kubernetes v1.0 版本,Service 是 “4 层”(TCP/UDP over IP)概念。在 Kubernetes v1.1 版本,新增了 Ingress API(beta版),用来表示 “7 层”(HTTP)服务。

注意,ipvs 模式假定在运行 kube-proxy 之前的节点上都已经安装了 IPVS 内核模块。当 kube-proxy 以 ipvs 代理模式启动时,kube-proxy 将验证节点上是否安装了 IPVS 模块。如果未安装的话,则 kube-proxy 将回退到 iptables 的代理模式。

为什么不适用 Round-robin DNS 的形式进行负载均衡呢?

  • 熟悉 DNS 的话,都知道 DNS 会在客户端进行缓存。当后端服务发生变动的话,我们是无法得到最新的地址的,从而无法达到负载均衡的作用了。

代理模式
使用 iptables代理模式

使用 ipvs 代理模式
这种模式,kube-proxy 会监视 Kubernetes Service 对象和 Endpoints,调用 netlink 接口以相应地创建 ipvs 规则并定期与 Kubernetes Service 对象和 Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod。

与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如:

# 启动服务
$ kubectl create -f myapp-deploy.yaml
$ kubectl create -f myapp-service.yaml

# 查看SVC服务
$ ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port         Forward  Weight  ActiveConn  InActConn
TCP  10.96.0.1:443 rr
 -> 192.168.66.10:6443         Masq     1       0           0

# 查看对应的IPVS防火墙规则
$ kubectl get svc -n default
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)     AGE
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP     125d

ClusterIP
ClusterIP 主要在每个 node 节点使用 ipvs/iptables,将发向 ClusterIP 对应端口的数据,转发到 kube-proxy 中。然后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 Service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口。

为了实现图上的功能,主要需要以下几个组件的协同工作:

  • apiserver 用户通过 kubectl命令向 apiserver 发送创建 service 的命令,apiserver 接收到请求后将数据存储到 etcd 中。
  • kube-proxy 在 kubernetes 的每个节点中都有一个叫做 kube-porxy 的进程,这个进程负责感知 service 和 pod 的变化,并将变化的信息写入本地的 ipvs/iptables 规则中。
  • ipvs/iptables 使用 NAT 等技术将 VirtualIP 的流量转至 endpoint 中。

对应配置文件,如下所示:
myapp-deploy.yaml

# myapp-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
        env: test
      spec:
        containers:
          - name: myapp
            image: escape/nginx:v2
            imagePullPolicy: IfNotPresent
            ports:
              - name: http
                containerPort: 80
  • 正确的Deployment书写方式,是要让spec.selector.matchLabels值和spec.template.metadata.lables值完全匹配,这样才不会报错。

  • 在定义pod模板时,必须定义spec.template.metadata.lables,因为spec.selector.matchLabels是必须字段,而它又必须和spec.template.metadata.lables的键值一致

myapp-service.yaml

apiVersion: apps/v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
    - name: http
      port: 80
      targetPort: 80

启动服务之后,可以查到对应的防火墙规则和默认的 SVC 服务。

# 启动服务
$ kubectl create -f myapp-deploy.yaml
$ kubectl create -f myapp-service.yaml

# 查看SVC服务
$ kubectl get svc -n default
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP     125d
myapp        ClusterIP   10.99.10.103    <none>        80/TCP      12s

# 查看POD服务
$ kubectl get pod -n default
NAME                           READY   STATUS    RESTARTS   AGE    IP            NODE           NOMINATED NODE   READINESS GATES
myapp-deploy-5cxxc8c94-4fb9g   1/1     Running   0          18s    10.244.1.66    k8s-node01    <none>           <none>
myapp-deploy-ddxx88794-r5qgw   1/1     Running   0          18s    10.244.1.68    k8s-node01    <none>           <none>
myapp-deploy-68xxfd677-5q4s2   1/1     Running   0          18s    10.244.1.69    k8s-node01    <none>           <none>

# 查看对应的IPVS防火墙规则
$ ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port         Forward  Weight  ActiveConn  InActConn
TCP  10.99.10.103:80 rr
 -> 10.244.1.66:80         Masq     1       0           0
 -> 10.244.1.68:80         Masq     1       0           0
 -> 10.244.1.69:80         Masq     1       0           0

Headless:
有时不需要或不想要负载均衡,以及单独的 Service IP。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP) 的值为 “None” 来创建 Headless Service。这类 Service 并不会分配 Cluster IP,kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由。
Headless Services 应用场景

  • 第一种:自主选择权,有时候 client 想自己来决定使用哪个Real Server,可以通过查询DNS来获取 Real Server 的信息。
  • 第二种:Headless Service 的对应的每一个 Endpoints,即每一个Pod,都会有对应的DNS域名,这样Pod之间就可以互相访问。
# myapp-svc-headless.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
  clusterIP: "None"
  ports:
    - port: 80
      targetPort: 80

启动服务之后,可以查到对应的防火墙规则和默认的 SVC 服务。

# 启动服务
$ kubectl create -f myapp-svc-headless.yaml

# 查看SVC服务
$ kubectl get svc -n default
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP     125d
myapp-headless  ClusterIP   none            <none>        80/TCP      19m

# 查找K8S上面的DNS服务对应IP地址(任意一个即可)
$ kubectl get pod -n kube-system -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP            NODE           NOMINATED NODE   READINESS GATES
coredns-12xxcxc5a-4129z   1/1     Running   3          23h    10.244.0.7    k8s-master01   <none>           <none>

# 查找对应无头服务的SVC解析的A记录
$ dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.7
;; ANSWER SECTION:
myapp-headless.default.svc.cluster.local.  30  IN  A 10.244.1.66
myapp-headless.default.svc.cluster.local.  30  IN  A 10.244.1.68
myapp-headless.default.svc.cluster.local.  30  IN  A 10.244.1.69

NodePort
nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod。

对应配置文件,如下所示:

# myapp-svc-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: NodePort
  selector:
    app: myapp
    release: stabel
  ports:
    - name: http
      port: 80
      targetPort: 80

service的spec.selector.app与deployment的pod名字保持一致
启动服务之后,可以查到对应的防火墙规则和默认的 SVC 服务。

# 启动服务
$ kubectl create -f myapp-svc-nodeport.yaml

# 查看SVC服务
$ kubectl get svc -n default
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP        125d
myapp           NodePort    10.99.10.103    <none>        80:30715/TCP   1m
myapp-headless  ClusterIP   none            <none>        80/TCP         19m

# 通过Node的服务器地址访问
$ curl -I http://192.168.66.21:30715

# 查询流程(在Node02上面查询的结果)
$ ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port         Forward  Weight  ActiveConn  InActConn
TCP  192.168.66.21:30715 rr
 -> 10.244.1.66:80         Masq     1       0           0
 -> 10.244.1.68:80         Masq     1       0           0
 -> 10.244.1.69:80         Masq     1       0           0

LoadBalancer
loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用 cloud provider 去创建 LB 来向节点导流。

ExternalName
这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容,例如:hub.escapelife.site。ExternalName Service是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。

当查询主机 my-service.defalut.svc.cluster.local 时,集群的 DNS 服务将返回一个值 hub.escapelife.site 的 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。

对应配置文件,如下所示:

# myapp-svc-externalname.yaml
# SVC_NAME.NAMESPACE.svc.cluster.local

kind: Service
apiVersion: v1
metadata:
  name: my-service-1
  namespace: default
spec:
  type: ExternalName
  externalName: hub.escapelife.site

启动服务之后,可以查到对应的防火墙规则和默认的 SVC 服务。

# 查看SVC服务
$ kubectl get svc -n default
NAME            TYPE            CLUSTER-IP      EXTERNAL-IP           PORT(S)        AGE
kubernetes      ClusterIP       10.96.0.1       <none>                443/TCP        125d
my-service-1    ExternalName    <none>          hub.escapelife.site   <none>         3m
myapp           NodePort        10.99.10.103    <none>                80:30715/TCP   24m
myapp-headless  ClusterIP       none            <none>                80/TCP         45m

# 查找对应无头服务的SVC解析的A记录
$ dig -t A my-service-1.default.svc.cluster.local. @10.244.0.7
;; ANSWER SECTION:
my-service-1.default.svc.cluster.local.  30  IN  CNAME  hub.escapelife.site

Ingress服务

https://kubernetes.github.io/ingress-nginx/deploy/
https://github.com/kubernetes/ingress-nginx/blob/main/docs/deploy/index.md
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml

K8s数据存储

地址:K8s

ConfigMap

ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象

ConfigMap的创建

  • 使用目录创建
    --from-file指定在目录下的所有文件都会用在ConfigMap里面创建一个键值对,键的名字就是文件名,值就是文件的内容。
$ ls docs/user-guide/config-map/kubectl/
game.properties
ui.properties

# game.properties
$ cat docs/user-guide/config-map/kubectl/game.properties
enemies=aliens
lives= 3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives= 30

# ui.properties
$ cat docs/user-guide/config-map/kubectl/ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

# 创建名称为game-config的ConfigMap配置
$ kubectl create configmap game-config \\
    --from-file=docs/user-guide/config-map/kubectl

# 查看存储的ConfigMap列表
$  kubectl get configmap
NAME               DATA   AGE
game-config        2      22s

# 查看对应内容
$ kubectl describe configmap game-config
$ kubectl get configmap game-config -o yaml
  • 使用文件创建
    只要指定为一个文件就可以从单个文件中创建 ConfigMap。--from-file 这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的。
# 创建名称为game-config-2的ConfigMap配置
$ kubectl create configmap game-config-2 \\
    --from-file=docs/user-guide/config-map/kubectl/game.properties

# 查看存储的ConfigMap列表
$  kubectl get configmap
NAME               DATA   AGE
game-config        2      34s
game-config-2      1      2s

# 查看对应内容
$ kubectl describe configmap game-config-2
$ kubectl get configmap game-config-2 -o yaml
  • 使用字面值创建
    使用文字值创建,利用 --from-literal 参数传递配置信息,该参数可以使用多次,格式如下。
# 创建名称为special-config的ConfigMap配置
$ kubectl create configmap special-config \\
    --from-literal=special.how=very \\
    --from-literal=special.type=charm

# 查看对应内容
$ kubectl get configmaps special-config -o yaml

ConfigMap 的使用

  • 使用 ConfigMap 来替代环境变量
apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO
yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-test-pod
spec:
  restartPolicy: Never
  containers:
    - name: test-container
      image: hub.escape.com/library/myapp:v1
      command: ["/bin/sh", "-c", "env"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how

        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
          name: env-config
  • 用 ConfigMap 设置命令行参数
apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-test-pod
spec:
  restartPolicy: Never
  containers:
    - name: test-container
      image: hub.escape.com/library/myapp:v1
      command: ["/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
  • 通过数据卷插件使用 ConfigMap
    在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。
apiVersion: v1
kind: ConfigMap
metadata:
  name: special-config
  namespace: default
data:
  special.how: very
  special.type: charm
yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-test-pod
spec:
  restartPolicy: Never
  containers:
    - name: test-container
      image: hub.escape.com/library/myapp:v1
      command: ["/bin/sh", "-c", "cat /etc/config/special.how"]
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config

ConfigMap 热更新
正常情况下,我们可以通过如下配置,在启动的 Pod 容器里面获取到 ConfigMap 中配置的信息。

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
  namespace: default
data:
  log_level: INFO

---
apiVersion: extensions/v1beta
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
        - name: my-nginx
          image: hub.escape.com/library/myapp:v1
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-volume
              mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: log-config
# 查找对应信息
$ kubectl exec \\
    `kubectl get pods -l run=my-nginx -o=name | cut -d "/" -f2` \\
    cat /etc/config/log_level
INFO

修改 ConfigMap 配置,修改 log_level 的值为 DEBUG 等待大概 10 秒钟时间,再次查看环境变量的值。

# 修改ConfigMap配置
$ kubectl edit configmap log-config

# 查找对应信息
$ kubectl exec \\
    `kubectl get pods -l run=my-nginx -o=name|cut -d "/" -f2` \\
    cat /etc/config/log_level
DEBUG

ConfigMap 更新后滚

以上是关于Kubernetes带你从头到尾捋一遍的主要内容,如果未能解决你的问题,请参考以下文章

「Docker入门指北」容器很难理解?带你从头到尾捋一遍(上)

带你从头到尾捋一遍MySQL索引结构

索引很难么?带你从头到尾捋一遍MySQL索引结构,不信你学不会

「Docker入门指北」容器很难理解?带你从头到尾捋一遍

索引很难么?带你从头到尾捋一遍MySQL索引结构,不信你学不会!

iOS:从头捋一遍VC的生命周期