笨兔儿

笨兔儿 查看完整档案

武汉编辑  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

java程序转SRE的行者

个人动态

笨兔儿 赞了文章 · 2020-11-27

从kubectl top看K8S监控

一. 前言

kubectl top 可以很方便地查看node、pod的实时资源使用情况:如CPU、内存。这篇文章会介绍其数据链路和实现原理,同时借kubectl top 阐述 k8s 中的监控体系,窥一斑而知全豹。最后会解释常见的一些问题:

  • kubectl top 为什么会报错?
  • kubectl top node 怎么计算,和节点上直接 top 有什么区别?
  • kubectl top pod 怎么计算,包含 pause 吗?
  • kubectl top pod 和exec 进入 pod 后看到的 top 不一样?
  • kubectl top pod 和 docker stats得到的值为什么不同?

以下命令的运行环境为:

  • k8s 1.8
  • k8s 1.13

二. 使用

kubectl top 是基础命令,但是需要部署配套的组件才能获取到监控值

kubectl top node: 查看node的使用情况

kubectl top pod: 查看 pod 的使用情况

不指定pod 名称,则显示命名空间下所有 pod,--containers可以显示 pod 内所有的container

指标含义:

  • 和k8s中的request、limit一致,CPU单位100m=0.1 内存单位1Mi=1024Ki
  • pod的内存值是其实际使用量,也是做limit限制时判断oom的依据。pod的使用量等于其所有业务容器的总和,不包括 pause 容器,值等于cadvisr中的container_memory_working_set_bytes指标
  • node的值并不等于该node 上所有 pod 值的总和,也不等于直接在机器上运行 top 或 free 看到的值

三. 实现原理

3.1 数据链路

kubectl top 、 k8s dashboard 以及 HPA 等调度组件使用的数据是一样,数据链路如下:

使用 heapster 时:apiserver 会直接将metric请求通过 proxy 的方式转发给集群内的 hepaster 服务。

而使用 metrics-server 时:apiserver是通过/apis/metrics.k8s.io/的地址访问metric

这里可以对比下kubect get pod时的日志:

3.2 metric api

可以发现,heapster使用的是 proxy 转发,而 metric-server 和普通 pod都是使用 api/xx 的资源接口,heapster采用的这种 proxy 方式是有问题的:

    1. proxy只是代理请求,一般用于问题排查,不够稳定,且版本不可控
    1. heapster的接口不能像apiserver一样有完整的鉴权以及client集成,两边都维护的话代价高,如generic apiserver
    1. pod 的监控数据是核心指标(HPA调度),应该和 pod 本身拥有同等地位,即 metric应该作为一种资源存在,如metrics.k8s.io 的形式,称之为 Metric Api

于是官方从 1.8 版本开始逐步废弃 heapster,并提出了上边Metric api 的概念,而metrics-server 就是这种概念下官方的一种实现,用于从 kubelet获取指标,替换掉之前的 heapster

3.3 kube-aggregator

有了metrics-server组件,采集到了需要的数据,也暴露了接口,但走到这一步和 heapster 其实没有区别,最关键的一步就是如何将打到apiserver的/apis/metrics.k8s.io请求转发给metrics-server组件?解决方案就是:kube-aggregator

kube-aggregator是对 apiserver 的有力扩展,它允许k8s的开发人员编写一个自己的服务,并把这个服务注册到k8s的api里面,即扩展 API,metric-server其实在 1.7版本就已经完成了,只是在等kube-aggregator的出现。

kube-aggregator是 apiserver 中的实现,有些 k8s 版本默认没开启,你可以加上这些配置
来开启。他的核心功能是动态注册、发现汇总、安全代理。

如metric-server注册 pod 和 node 时:

3.4 监控体系

在提出 metric api 的概念时,官方页提出了新的监控体系,监控资源被分为了2种:

  • Core metrics(核心指标):从 Kubelet、cAdvisor 等获取度量数据,再由metrics-server提供给 Dashboard、HPA 控制器等使用。
  • Custom Metrics(自定义指标):由Prometheus Adapter提供API custom.metrics.k8s.io,由此可支持任意Prometheus采集到的指标。

核心指标只包含node和pod的cpu、内存等,一般来说,核心指标作HPA已经足够,但如果想根据自定义指标:如请求qps/5xx错误数来实现HPA,就需要使用自定义指标了。

目前Kubernetes中自定义指标一般由Prometheus来提供,再利用k8s-prometheus-adpater聚合到apiserver,实现和核心指标(metric-server)同样的效果。

3.5 kubelet

前面提到,无论是 heapster还是 metric-server,都只是数据的中转和聚合,两者都是调用的 kubelet 的 api 接口获取的数据,而 kubelet 代码中实际采集指标的是 cadvisor 模块,你可以在 node 节点访问 10255 端口 (read-only-port)获取监控数据:

  • Kubelet Summary metrics: 127.0.0.1:10255/metrics,暴露 node、pod 汇总数据
  • Cadvisor metrics: 127.0.0.1:10255/metrics/cadvisor,暴露 container 维度数据

示例,容器的内存使用量:

kubelet虽然提供了 metric 接口,但实际监控逻辑由内置的cAdvisor模块负责,演变过程如下:

  • 从k8s 1.6开始,kubernetes将cAdvisor开始集成在kubelet中,不需要单独配置
  • 从k8s 1.7开始,Kubelet metrics API 不再包含 cadvisor metrics,而是提供了一个独立的 API 接口来做汇总
  • 从k8s 1.12开始,cadvisor 监听的端口在k8s中被删除,所有监控数据统一由Kubelet的API提供

到这里为止,k8s范围内的监控体系就结束了,如果你想继续了解cadvisor和 cgroup 的内容,可以向下阅读

3.6 cadvisor

cadvisor由谷歌开源,使用Go开发,项目地址也是google/cadvisor,cadvisor不仅可以搜集一台机器上所有运行的容器信息,包括CPU使用情况、内存使用情况、网络吞吐量及文件系统使用情况,还提供基础查询界面和http接口,方便其他组件进行数据抓取。在K8S中集成在Kubelet里作为默认启动项,k8s官方标配。

cadvisor 拿到的数据结构示例:

核心逻辑:

通过new出来的memoryStorage以及sysfs实例,创建一个manager实例,manager的interface中定义了许多用于获取容器和machine信息的函数

cadvisor的指标解读:cgroup-v1

cadvisor获取指标时实际调用的是 runc/libcontainer库,而libcontainer是对 cgroup文件 的封装,即 cadvsior也只是个转发者,它的数据来自于cgroup文件。

3.7 cgroup

cgroup文件中的值是监控数据的最终来源,如

  • mem usage的值,来自于

/sys/fs/cgroup/memory/docker/[containerId]/memory.usage_in_bytes

  • 如果没限制内存,Limit = machine_mem,否则来自于

/sys/fs/cgroup/memory/docker/[id]/memory.limit_in_bytes

  • 内存使用率 = memory.usage_in_bytes/memory.limit_in_bytes

一般情况下,cgroup文件夹下的内容包括CPU、内存、磁盘、网络等信息:


如memory下的几个常用的指标含义:

memory.stat中的信息是最全的:

原理到这里结束,这里解释下最开始的kubectl top 的几个问题:

四. 问题

4.1 kubectl top 为什么会报错

一般情况下 top 报错有以下几种,可以 kubectl top pod -v=10看到具体的调用日志

  1. 没有部署 heapster 或者 metric-server,或者pod运行异常,可以排查对应 pod日志
  2. 要看的pod 刚刚建出来,还没来得及采集指标,报 not found 错误,默认1 分钟
  3. 以上两种都不是,可以检查下kubelet 的 10255 端口是否开放,默认情况下会使用这个只读端口获取指标,也可以在heapster或metric-server的配置中增加证书,换成 10250 认证端口

4.2 kubectl top pod 内存怎么计算,包含 pause容器 吗

每次启动 pod,都会有一个 pause 容器,既然是容器就一定有资源消耗(一般在 2-3M 的内存),cgroup 文件中,业务容器和 pause 容器都在同一个 pod的文件夹下。

但 cadvisor 在查询 pod 的内存使用量时,是先获取了 pod 下的container列表,再逐个获取container的内存占用,不过这里的 container 列表并没有包含 pause,因此最终 top pod 的结果也不包含 pause 容器

pod 的内存使用量计算

kubectl top pod 得到的内存使用量,并不是cadvisor 中的container_memory_usage_bytes,而是container_memory_working_set_bytes,计算方式为:

  • container_memory_usage_bytes == container_memory_rss + container_memory_cache + kernel memory
  • container_memory_working_set_bytes = container_memory_usage_bytes - total_inactive_file(未激活的匿名缓存页)

container_memory_working_set_bytes是容器真实使用的内存量,也是limit限制时的 oom 判断依据

cadvisor 中的 container_memory_usage_bytes对应 cgroup 中的 memory.usage_in_bytes文件,但container_memory_working_set_bytes并没有具体的文件,他的计算逻辑在 cadvisor 的代码中,如下:

同理,node 的内存使用量也是container_memory_working_set_bytes

4.3 kubectl top node 怎么计算,和节点上直接 top 有什么区别

kubectl top node得到的 cpu 和内存值,并不是节点上所有 pod 的总和,不要直接相加。top node是机器上cgroup根目录下的汇总统计

在机器上直接 top命令看到的值和 kubectl top node 不能直接对比,因为计算逻辑不同,如内存,大致的对应关系是(前者是机器上 top,后者是kubectl top):

rss + cache = (in)active_anon + (in)active_file

4.4 kubectl top pod 和exec 进入 pod 后看到的 top 不一样

top命令的差异和上边 一致,无法直接对比,同时,就算你对 pod 做了limit 限制,pod 内的 top 看到的内存和 cpu总量仍然是机器总量,并不是pod 可分配量

  • 进程的RSS为进程使用的所有物理内存(file_rss+anon_rss),即Anonymous pages+Mapped apges(包含共享内存)
  • cgroup RSS为(anonymous and swap cache memory),不包含共享内存。两者都不包含file cache

4.5 kubectl top pod 和 docker stats得到的值为什么不同?

docker stats dockerID 可以看到容器当前的使用量:


如果你的 pod中只有一个 container,你会发现docker stats 值不等于kubectl top 的值,既不等于 container_memory_usage_bytes,也不等于container_memory_working_set_bytes。

因为docker stats 和 cadvisor 的计算方式不同,总体值会小于 kubectl top:计算逻辑是:

docker stats = container_memory_usage_bytes - container_memory_cache

五. 后记

一般情况下,我们并不需要时刻关心node 或 pod 的使用量,因为有集群自动扩缩容(cluster-autoscaler)和pod 水平扩缩容(HPA)来应对这两种资源变化,资源指标的意义更适合使用prometheus来持久化 cadvisor 的数据,用于回溯历史或者发送报警。

关于prometheus的内容可以看容器监控系列

其他补充:

  1. 虽然kubectl top help中显示支持Storage,但直到 1.16 版本仍然不支持
  2. 1.13 之前需要 heapster,1.13 以后需要metric-server,这部分kubectl top help的输出 有误,里面只提到了heapster
  3. k8s dashboard 中的监控图默认使用的是 heapster,切换为 metric-server后数据会异常,需要多部署一个metric-server-scraper 的 pod 来做接口转换,具体参考 pr:https://github.com/kubernetes...

六. 参考资料

查看原文

赞 1 收藏 0 评论 0

笨兔儿 发布了文章 · 2020-11-27

本地mac系统通过minikube安装k8s集群

环境准备

  • 安装配置minikube
# 下载对应系统的包
https://github.com/kubernetes/minikube/releases/tag/v1.15.1
# 配置环境变量
vim /etc/profile
export MINIKUBE_PATH=/Users/zengqiang/soft/minikube/
export PATH=$MINIKUBE_PATH:$PATH
# 重载配置
source /etc/profile
  • 安装轻量级的vm

hyperkitgithub地址,传送门 安装需要点时间耐心等待安装完成

brew install hyperkit
  • 安装docker默认使用官方安装指南即可

minikube安装k8s集群

  • 使用minikube安装k8s

这边启动驱动选择使用hyperkit安装需要时间耐心等待安装完成

minikube start --dirver=hyperkit
  • 检验k8s安装情况
kubectl get pod -A
minikube dashboard
查看原文

赞 0 收藏 0 评论 0

笨兔儿 发布了文章 · 2019-11-19

filebeat 7.4 codec.format 变量配置方法

filebeat 7.4 codec.format 变量配置方法

无论你是使用哪个版本的filebeat,当你的output.xx中需要配置code.cormat的变量,最开始是从官网上查询,后来发现有个更方便的方法;
重点就是codec.format中的变量都是从已经生成json的对象中获取,就是信息和元数据都已经生成好准备output目标;
  • 打印outputjson数据
{
    "@timestamp":"2019-11-19T06:42:34.222Z",
    "@metadata":{
        "beat":"filebeat",
        "type":"_doc",
        "version":"7.4.2",
        "topic":"xxx-click"
    },
    "host":{
        "name":"eeexx-asdddd"
    },
    "agent":{
        "version":"7.4.2",
        "type":"filebeat",
        "ephemeral_id":"3969b5f3-9aa2-4c5a-b8bd-971017f480c5",
        "hostname":"eeexx-asdddd",
        "id":"10b92cfc-b641-4dde-a72f-a599e178e05d"
    },
    "log":{
        "offset":48845307,
        "file":{
            "path":"/Log-xxxx.log"
        }
    },
    "message":"2019-11-19 14:42:33.830 INFO  .0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" "" """,
    "input":{
        "type":"log"
    },
    "fields":{
        "log_topic":"xxx-click"
    },
    "ecs":{
        "version":"1.1.0"
    }
}
  • 根据你所需要的配置codec.format
output.kafka:
  codec.format: '%{[fields.log_topic]} %{[agent.hostname]}'

output.kafka 输出信息异常

`client/metadata fetching metadata for [xx-play] from broker 172.16.xx.xx:9092
kafka message: client/metadata found some partitions to be leaderless` 异常信息

  • 异常原因kafka中没有创建xx-play topic创建好之后就能正常输出到topic
  • 发生这样异常信息时,如果有多个output也会有影响,不能正常out 信息
查看原文

赞 0 收藏 0 评论 0

笨兔儿 发布了文章 · 2019-02-27

Prometheus 500 Internal Privoxy Error 异常解决

Prometheus 500 Internal Privoxy Error 异常解决

  • 访问Prometheus web-ui时异常
Privoxy encountered an error while processing your request:
Could not load template file no-server-data or one of its included components.
Please contact your proxy administrator.
If you are the proxy administrator, please put the required file(s)in the (confdir)/templates directory. The location of the (confdir) directory is specified in the main Privoxy config file. (It's typically the Privoxy install directory).
  • 解决方案

翻墙软件因开全局代理导致异常,将全局代理修改为自动代理就解决

查看原文

赞 0 收藏 0 评论 0

笨兔儿 发布了文章 · 2019-01-18

Prometheus HA详解

Prometheus HA详解

以下所有操作都是在k8s集群中完成,如果你是VM或者物理机在配置方面不会有太大区别;

Prometheus 横向扩展

Exporter或者采集信息需要越来越多时就会考虑高可用,高可用优点不会因为集群中某个节点down而导致Prometheus不可用,可以让算力下沉;
缺点是A-PrometheusB-Prometheus这两个实例会定时去scrape数据,并且存储在各本地,这样导致数据会存储两份;

clipboard.png

  • 高可用配置

Prometheus启动两个实例,配置一样只需要暴露的service的端口不同,'Nginx Controller'配置session-affinityservice名称;

Prometheus 联邦

在多个数据中心部署Prometheus需要将多数据中心数据合在一起管理,使用联邦模式非常合适,如果担心数据单点,可以在联邦的基础上再扩展高可用;
优点集中式管理数据,报警,不需要为每个Prometheus实例管理数据,如有些敏感节点报警要求高可以在Prometheus数据节点上加报警信息,可以按功能环境划分启动多个Prometheus采集实例;
缺点数据集中化,网络可能会延时,数据单点等问题;

clipboard.png

终级解决方案

Prometheus 是支持远程读写TSDB数据库,请看官方网站支持哪些数据库的读写,因为有些数据只支持写而不支持读,你内网搭建TSDB集群,你所有启动的Prometheus实例都把数据写入到远程数据库,再使用高可用方案支持查询,只支持远程读,这样就可无限扩展采集实例和查询实例,非常的爽,作者没有实践过只是YY中;

  • 采集的Metrics远程写入TSDB

clipboard.png

  • Prometheus远程读TSDB

clipboard.png

文章会持续更新,文章中有不好之处欢迎留言

我的博客即将同步至 OSCHINA 社区,这是我的 OSCHINA ID:osc_ouf9dku6,邀请大家一同入驻:https://www.oschina.net/shari...

查看原文

赞 1 收藏 1 评论 0

笨兔儿 发布了文章 · 2019-01-09

pushgateway on k8s 部署yaml

pushgateway on k8s 部署yaml

prometheus pushgateway部署的yaml文件

  • pushgatewaydeployment文件内容
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  namespace: kube-ops
  name:  pushgateway-ttt
  labels:
    app:  pushgateway-ttt
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "8080"
spec:
  replicas: 1
  revisionHistoryLimit: 0
  selector:
    matchLabels:
      app:  pushgateway-ttt
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: "25%"
      maxUnavailable: "25%"
  template:
    metadata:
      name:  pushgateway-ttt
      labels:
        app:  pushgateway-ttt
    spec:
      containers:
        - name:  pushgateway-ttt
          image: prom/pushgateway:v0.7.0
          imagePullPolicy: IfNotPresent
          livenessProbe:
            initialDelaySeconds: 600
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 10
            httpGet:
              path: /
              port: 9091
          ports:
            - name: "app-port"
              containerPort: 9091
          resources:
            limits:
              memory: "1000Mi"
              cpu: 1
            requests:
              memory: "1000Mi"
              cpu: 1

prom/pushgateway可以在hub.docker.io查到dockerfile文件及部署说明,启动参数--persistence.file等都是放入spec.args中添加即可生效;
所有启动参数:

--web.listen-address default:9091
--web.telemetry-path  default:/metrics
--web.route-prefix default:""
--persistence.file default: ""
--persistence.interval default: 5m

参数说明地址

  • pushgatewayservice文件内容
apiVersion: v1
kind: Service
metadata:
  name: pushgateway-ttt
  namespace: kube-ops
  labels:
    app: pushgateway-ttt
spec:
  selector:
    app: pushgateway-ttt
  #type: NodePort
  ports:
    - name: pushgateway-ttt
      port: 9091
      targetPort: 9091
  • pushgatewayingress文件内容
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: pushgateway-ingress
  namespace: kube-ops
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: push-prometheus.ttt.mucang.cn
    http:
      paths:
      - path: /
        backend:
          serviceName: pushgateway-ttt
          servicePort: 9091

Prometheus中配置pushgatewaypull pushgateway数据配置

# prometheus配置文件中配置pull pushgateway组件配置
- job_name: 'pushgateway'
  scrape_interval: 60s
  metrics_path: /metrics
  static_configs:
  - targets: ["push-prometheus.xxx.xx.xx]
# prometheus的deployment配置文件配置环境变量,这样prometheus才会去pull pushgateway缓存的数据
# 所有推到pushgateway的数据都会在/metrics接口的体现
查看原文

赞 0 收藏 0 评论 0

笨兔儿 评论了文章 · 2019-01-09

ubuntu 织梦DEDE安装 GD插件 OFF问题

Ubuntu 16.04下安装织梦CMS系统

安装Ubuntu 16.04安装织梦CMS开始发现所有目录没有权限,把源码的用户加入到php用户组下面,目录权限问题解决,接下来php-mysql显示为off,安装好php-mysql后,php-gd显示为off找了半天无解,最后在google下找到解决方案,但是与我碰到问题不一样,最后修改代码成功运行将off显示为on

问题描述

图片描述

解决方案

  • 查看`php5.7-gd` 版本,如果没有安装php5.7-gd请先根据你的php版本安装gd
# php --ri gd
GD Support => enabled
GD headers Version => 2.2.5
GD library Version => 2.2.5
FreeType Support => enabled
FreeType Linkage => with freetype
FreeType Version => 2.6.1
GIF Read Support => enabled
GIF Create Support => enabled
JPEG Support => enabled
libJPEG Version => 8
PNG Support => enabled
libPNG Version => 1.2.54
WBMP Support => enabled
XPM Support => enabled
libXpm Version => 30411
XBM Support => enabled
WebP Support => enabled

Directive => Local Value => Master Value
gd.jpeg_ignore_warning => 0 => 0
  • 因为install/install.inc.php 中返回的版本是2.0,需要将返回版本修改你安装的真实版本2.1.1
function gdversion()
{
  //没启用php.ini函数的情况下如果有GD默认视作2.0以上版本
  //因为我是ubuntu服务器,没有配置php.ini,所以这里返回的是GD2.0版本,然而我的GD版本为2.1.1,所以手动配置版本号
  if(!function_exists('phpinfo'))
  {
      //if(function_exists('imagecreate')) return '2.0';
      if(function_exists('imagecreate')) return '2.1.1';

      else return 0;
  }
  else
  {
    ob_start();
    phpinfo(8);
    $module_info = ob_get_contents();
    ob_end_clean();
    if(preg_match("/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i", $module_info,$matches)) {   $gdversion_h = $matches[1];  }
    else {  $gdversion_h = 0; }
    // return $gdversion_h;
    return '2.1.1';
  }
  • 查看结果

图片描述

查看原文

笨兔儿 发布了文章 · 2019-01-08

mac os 安装 iterm2+fish shell 终端配色及vim语法高亮

mac os 安装 iterm2+fish shell 终端配色及vim语法高亮

安装iterm2fish shell

  • 安装 iterm2

iterm2软件下载地址,直接安装dmg文件

  • 安装 fish shell

fish shell说明及下载地址,根据自己熟悉方式安装fish shell

将fish shell添加到mac的shell列表里,用shell命令sudo vim /etc/shells把/usr/local/bin/fish 追加到文件尾处;
最后,按esc键跳到命令模式,输入:wq命令保存文件,使用 chsh -s /usr/local/bin/fish 切换到fish shell;
打开iterm2时自动打开fish shell,vim ~/bash_profile在文件尾处添加fish命令,使用:wq保存文件即可;
  • vim语法高亮
首先开启语法高亮功能,如果没有这个文件就创建文件:
vim ~/.vimrc
在.vimrc文件尾处添加如下代码:
syntax on
  • vim选择主题
vim 有更多的主题可以选择,使用如下命令可以查看vim所有的color主题:
cd /usr/share/vim/vim73/colors/ && ls

在.vimrc文件中添加vim的color主题,命令如下:
vim ~/.vimrc
添加colorscheme darkblue信息到文件尾处

以上所有配置想看效果需要重新打开iterm2,如文中有错误烦请留言指出,谢谢

查看原文

赞 0 收藏 0 评论 0

笨兔儿 发布了文章 · 2018-12-19

Golang-filepath使用

Golang-filepath 使用

获取当前目录

os.GetPWD()
filepath.Abs(path) # 绝对目录
filepath.Dir(path) # 相对目录
可以 filepath.Abs(filepath.Dir(path))

获取字符目录,前缀,后缀等方法

filepath.Split(path)
filepath.Base(path) # test.txt
filepath.Ext(path) # .txt
查看原文

赞 0 收藏 0 评论 0

笨兔儿 赞了文章 · 2018-11-26

Pod Preset玩转K8S容器时区自动配置

摘要: 通过Pod Preset自动配置容器的时区

缘由

默认的情况,在K8S里启动一个容器,该容器的设置的时区是UTC0,但是对于很多客户而言,其主机环境并不在UTC0。例如中国客户在UTC8。如果不把容器的时区和主机主机设置为一致,则在查找日志等时候将非常不方便,也容易造成误解。但是K8S以及Docker容器没有一个简便的设置/开关在系统层面做配置。都需要我们从单个容器入手做设置,具体方法如下:

纯Docker的时区设置方式

Docker引擎提供了两种设置方式,分别是通过环境变量以及挂载主机文件方式来完成

方式一:设置容器的时区环境变量

先看看没有设置前,容器的情况:

clipboard.png

clipboard.png

从输出可以看出,容器和主机差了8个时区

我们通过环境变量的方式来改变容器的时区:

clipboard.png

clipboard.png

从输出可以看出,虽然没有改变对应的localtime文件,但是容器和主机的时区是一致的了。

方式二:挂载主机的时区文件到容器中

clipboard.png

clipboard.png

从输出可以看出,容器和主机的时区是一致的了,而且使用了本机的时区文件。

Kubernetes的时区设置方式

在K8S中,可以参考Docker的方式进行设置

通过环境变量设置

clipboard.png

通过挂载主机时区文件设置

clipboard.png

这里引出了一个问题,难道每次每个容器都要做这样的配置才可以么?可否在系统层面设置,而无需在对应yaml文件体现呢?不然yaml文件将过于啰嗦。答案是使用K8S的特性Pod Preset来控制容器启动前先配置好对应时区环境变量,或者挂载主机文件。下面我们通过配置环境变量的方式说明,挂载文件是类似的,就不重复了。

通过Pod Preset预设置时区环境变量

激活Pod Preset

Pod Preset目前还是alpha阶段,默认是没有激活的,所以需要通过以下步骤激活:

咱们以阿里云的Kubernetes服务为例(如果还没有,可以尝试一下,一键就可以开通,还免费哦)。阿里云的Kubernetes服务的master组件(API Server, Scheduler, Controller)都是通过Static Pod的方式用Kubelet启动,所以需要更改对应的yaml来激活Pod Preset:

编辑/etc/kubernetes/manifests/kube-apiserver.yaml,

• 在-runtime-config增加settings.k8s.io/v1alpha1=true

• 在--admission-control增加PodPreset`

保存后kubelet会自动重启kube-apiserver组件。我们需要同时更改3台机器的master才可以。在期间你将收到类似以下的告警,在api server重启成功后会自动恢复

clipboard.png

验证配置成功

• 确保api server已经恢复,如果恢复将收到如下通知信息:

clipboard.png

• kubectl可以查询Pod Preset。在开关没有开启成功前,是无法调用以下命令的

clipboard.png

配置设置时区的Pod Preset

对应的Pod Preset对象创建文件如下:

clipboard.png

这里需要注意的地方是,一定需要写selector...matchLabels,但是matchLabels为空,标示应用于所有容器,这个正式我们所期望的

clipboard.png

clipboard.png

可以得到创建成功的Pod Preset列表:

clipboard.png

以普通的方式创建容器,但是环境变量被Pod Preset注入了

clipboard.png

进入容器看看对应的环境变量:

clipboard.png

从输出可以看出,容器已经被默认配置了时区的环境变量,对应的时区是Asia/Shanghai

小结

至此,我们就完成了容器的时区的"自动"配置了。Pod Preset的预设功能还是非常便利的,目前这块还在演进中,但是已经能大大简化了相关的管理工作,将这些配置从开发者手中解脱出来,变成系统管理配置。

需要注意的是,Pod Preset是namespace级别的对象,其作用范围只能是同一个命名空间下容器。

给社区的建议

建议Kubernetes社区可以在kubelet的启动参数重,增加一个开关,用来设置容器的默认时区,毕竟这个是很常见的实践

参考文档

Pod Preset: https://kubernetes.io/docs/co...

Static Pod: https://kubernetes.io/docs/ta...

label-selectors: https://kubernetes.io/docs/co...

本文作者:了哥-duff

阅读原文

本文为云栖社区原创内容,未经允许不得转载。

查看原文

赞 1 收藏 0 评论 0

认证与成就

  • 获得 13 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-04-02
个人主页被 3.1k 人浏览