从 k8s changelog 了解 k8s

本文从 k8s 的更新日志中了解 k8s 的变迁,,从版本跨度从1.2-1.10。GitHub 地址:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md

v1.0 - 201507

Google宣布成立CNCF基金会,Kubernetes 1.0正式发布。已投入生产的Kubernetes有着如下特性:

APP服务,网络,存储

  • 在生产环境中部署和管理工作负载,包括DNS、负载均衡、扩展、应用级别的健康检查和服务记录。
  • 与各种本地和网络卷的状态应用支持,如谷歌计算引擎永久磁盘,AWS弹性块存储和NFS。
  • 在pod中部署容器,pod与容器密切相关,支持简单更新和回滚。
  • 用命令执行检查和调试应用,通过CLI和UI进行端口转发,日志收集,资源监控。

集群管理

  • 实时升级以及扩展。
  • 通过命名空间分割集群,更深层次的管控资源。例如,你可以将集群细分给不同的应用或测试生产环境。

性能和稳定性

  • API响应速度快,平均容器调用时间小于5秒。
  • 扩展测试,每个集群中,容器1000秒,节点100秒。
  • 稳定的API

v1.1 - 201511

v1.2 - 201603

  1. 显著增加集群规模

    支撑的集群规模增加400%。单个节点性能提升四倍。

  2. 简化应用部署和管理

    1. Dynimic Configuration 功能(动态配置)。
    2. TurnKey Deployments 应用部署和滚动升级的自动化。
  3. 自动化集群管理

    1. 在同一个云平台上实现跨区扩展。一个Service下的Pod会自动扩展到其它可用区,从而做到跨区容错。
    2. 简化One-Pod-Per-Node应用的部署管理(通过Extensions API中的DaemonSet API实现)。Kubernetes的调度机制能够保证一个应用每个节点上运行同样的Pod,并且只运行一个,比如logging agent。
    3. 支持TLS和7层网络(通过Extensions API中的ingress API实现,目前为Beta版)。基于TLS和基于HTTP的七层网络路由,Kubernetes可以更方便地集成到传统的网络环境中。
    4. 支持Graceful Node Shutdown(及Node Drain)。新增的“kubelet drain”命令可以很优雅地将pod从某些节点驱逐出去,从而为节点维护做准备(比如升级kernel
    5. 支持自定义Autoscaling的指标(通过Autoscaling API中的HorizontalPodAutoscaler API实现)。Horizontal Pod Autoscaling支持自定义模版(目前为Alpha版),允许用户指定应用级别的指标和应用自动伸缩的阈值。
    6. 新的控制台(dashboard)具备与kubelet commandline类似的功能,允许用户通过一种新方式与kubernetes集群交互。

其它重要的改进

  • Job在v1.1中为Beta版,在1.2中可以投入生产环境。
  • Kube-Proxy默认采用基于iptables的方式。
  • 可以在kubelet中设置系统保留资源来提高Node节点的稳定性。参数为 –system-reserved 和 –kube-reserved。
  • Liveness和readiness探针支持更多的参数选项,包括periodSeconds、successThreshold和failureThreshold。
  • 新的ReplicaSet API(Extensions API中,目前处于Beta版)
  • 命令kubelet run默认产生Deployments(而不是ReplicationControllers)和Jobs(而不是Pods)对象。
  • Pods能够使用环境变量中的Secret数据,并将其作为commandline参数传递给container
  • 产生Heapster的稳定版,并支持最多1000个节点:更多的监控指标、减少延迟、减少CPU和内存消耗(大约4M每个节点)。

v1.3 - 201607

该版本包含的特性主要是为了实现两个用户愿望:

  • 一个是跨集群、区域和云边界部署服务;
  • 另一个是在容器中运行更为多样化的工作负载,包括有状态服务。

新特性:

  • 提升规模和自动化——允许用户根据应用程序需求自动向上和向下扩展他们的服务。简化集群的自动向上和向下扩展,并且将每个集群的最大节点数量提升至原来的两倍。

  • 有状态应用程序的alpha支持—— Kubernetes API新增了一个“PetSet”对象:

    • 多次重启也不会变化的永久性主机名;
    • 自动为每个容器配置永久性磁盘,可以在容器生命周期结束后继续存在;
    • 组内唯一标识,允许群集和群首选举;
    • 初始化容器,对启动集群应用程序至关重要。
  • 简化本地开发——引入了Minikube,只要一条命令,开发人员就可以在笔记本上启动一个本地Kubernetes集群,而且与一个完整Kubernetes集群的API兼容。

  • 支持rkt容器镜像和OCI&CNI 容器标准。

  • 更新dashboard UI。

v1.4 - 201609

  • 创建kubernetes集群只需要两条命令
  • 增强了对有状态应用的支持
  • 增加了集群联盟(Federation)API
    • 跨kubernetes集群均匀的调度任务负载
    • 将一个最便宜的kubernetes集群的工作负载进行最大化,如果超出了这个kubernetes集群的承受能力,那么将额外的工作负载路由到一个更昂贵的kubernetes集群中
    • 根据应用地理区域需求,调度工作负载到不同的kubernetes集群中,对于不同的终端用户,提供更高的带宽和更低的延迟。
  • 支持容器安全控制
  • 增强包括调度在内的Kubernetes基础架构
  • 通过Kubernetes DashBoard UI已经可以实现90%的命令行操作

v1.5 - 201612

1、API 机制

  • [beta] kube-apiserver支持OpenAPI从alpha移动到beta, 第一个non-go客户端是基于此特性。

2、应用

  • [Stable]当replica sets不能创建Pods时,它们将通过API报告失败的详细底层原因。
  • [Stable] kubectl apply现可通过–prune删除不再需要的资源
  • [beta] Deployments现可通过API升级到新版本,而之前是无法通过滚动来进行升级的
  • [beta] StatefulSets(原PetSet)允许要求持久化identity或单实例存储的工作负载从而在Kubernetes创建和管理。
  • [beta]为了提供安全保障,集群不会强行删除未响应节点上的Pods,如果用户通过CLI强行删除Pods会收到警告。

3、认证

  • [Alpha]改进了基于角色的访问控制alpha API。(包括一组默认的集群角色)
  • [Beta]添加了对Kubelet API访问的认证/授权机制。

4、AWS

  • [stable]角色出现在kubectl get nodes的结果里。

5、集群生命周期

  • [alpha] 提升了kubeadm二进制包的交互和可用性,从而更易于新建一个运行集群。

6、集群运维

  • [alpha] 在GCE上使用kube-up/kube-down脚本来创建/移除集群高可用(复制)的主节点。

7、联邦

  • [beta] 支持联邦ConfigMaps。
  • [alpha] 支持联邦Daemonsets。
  • [alpha] 支持联邦Deployments。
  • [alpha]集群联邦:为联邦资源添加对于DeleteOptions.OrphanDependents的支持。
  • [alpha]引入新命令行工具:kubefed,简化联邦控制台的部署以及集群注册/注销体验。

8、网络

  • [stable]服务可以通过DNS名称被其他服务引用,而不是只有在pods里才可以。
  • [beta]为NodePort类型和LoadBalancer的服务保留源IP的选项。
  • [stable]启用beta ConfigMap参数支持的DNS水平自动伸缩

9、节点

  • [alpha]支持在容器运行时启用用户命名空间重映射的时候,保留对宿主用户命名空间的访问。
  • [alpha]引入了v1alpha1版本的CRI(容器运行时接口) API,它允许可插拔的容器运行时;现有一个已经就绪的用于测试和反馈的docker-CRI集成。
  • [alpha]Kubelet基于QoS层在每个Pod的CGroup层级里启动容器。
  • [beta]Kubelet集成了memcg提示消息API,来检测是否超过阈值。
  • [beta]引入了Beta版本的容器化节点一致性测试: gcr.io/google_containers/node-test:0.2。从而让用户验证node设置。

10、调度

  • [alpha]添加了对不透明整数资源(node级)的审计支持。
  • [beta] PodDisruptionBudget已经升级到Beta版,当想要应用SLO时,可以用来安全地drain节点。

11、UI

  • [stable]Dashboard UI如今显示面向用户的对象及它们的资源使用情况。

12、Windows

  • [alpha]添加了对Windows Server 2016节点和调度Windows Server Container的支持。

v1.6 - 201703

  1. 扩大集群规模,加强集群联邦功能

    将Kubernetes底层架构预设改成etcd v3版本,可支持的集群规模也扩大至5,000个节点,可支持的Pod规模也增加到15万个

  2. 靠角色访问控制机制加强安全

    直接用API来取得不同账号的权限管理政策,来控制使用者账号或服务,可将系统资源指派给特定命名空间,让所属账号来存取。

  3. 储存动态分配

    PV PVC StorageClass

  4. 强化使用者对Pod的控制

    指定每个Pod一个节点标签(Node Label),限制Pod只能在特定节点中运行,也可以将Pod排除于特定节点上运作。

  5. 更新容器Runtime接口及常驻程序

v1.7 - 20170629

转自https://jimmysong.io/kubernetes-handbook/appendix/kubernetes-1.7-changelog.html

2017年6月29日,kuberentes1.7发布。该版本的kubernetes在安全性、存储和可扩展性方面有了很大的提升。改版本的详细更新文档请查看Changelog

这些新特性中包含了安全性更高的加密的secret、pod间通讯的网络策略,限制kubelet访问的节点授权程序以及客户端/服务器TLS证书轮换。

对于那些在Kubernetes上运行横向扩展数据库的人来说,这个版本有一个主要的特性,可以为StatefulSet添加自动更新并增强DaemonSet的更新。我们还宣布了对本地存储的Alpha支持,以及用于更快地缩放StatefulSets的突发模式。

此外,对于高级用户,此发行版中的API聚合允许使用用于自定义的API与API server同时运行。其他亮点包括支持可扩展的准入控制器,可插拔云供应商程序和容器运行时接口(CRI)增强功能。

新功能

安全

  • Network Policy API 提升为稳定版本。用户可以通过使用网络插件实现的网络策略来控制哪些Pod之间能够互相通信。
  • 节点授权和准入控制插件是新增加的功能,可以用于限制kubelet可以访问的secret、pod和其它基于节点的对象。
  • 加密的Secret和etcd中的其它资源,现在是alpha版本。
  • Kubelet TLS bootstrapping现在支持客户端和服务器端的证书轮换。
  • 由API server存储的审计日志现在更具可定制性和可扩展性,支持事件过滤和webhook。它们还为系统审计提供更丰富的数据。

有状态负载

  • StatefulSet更新是1.7版本的beta功能,它允许使用包括滚动更新在内的一系列更新策略自动更新诸如Kafka,Zookeeper和etcd等有状态应用程序。
  • StatefulSets现在还支持对不需要通过Pod管理策略进行排序的应用程序进行快速扩展和启动。这可以是主要的性能改进。
  • 本地存储(alpha)是有状态应用程序最常用的功能之一。用户现在可以通过标准的PVC/PV接口和StatefulSet中的StorageClass访问本地存储卷。
  • DaemonSet——为每个节点创建一个Pod,现在有了更新功能,在1.7中增加了智能回滚和历史记录功能。
  • 新的StorageOS Volume插件可以使用本地或附加节点存储中以提供高可用的集群范围的持久卷。

可扩展性

  • 运行时的API聚合是此版本中最强大的扩展功能,允许高级用户将Kubernetes风格的预先构建的第三方或用户创建的API添加到其集群中。
  • 容器运行时接口(CRI)已经增强,可以使用新的RPC调用从运行时检索容器度量。 CRI的验证测试已经发布,与containerd进行了Alpha集成,现在支持基本的生命周期和镜像管理。参考深入介绍CRI的文章。

其它功能

  • 引入了对外部准入控制器的Alpha支持,提供了两个选项,用于向API server添加自定义业务逻辑,以便在创建对象和验证策略时对其进行修改。
  • 基于策略的联合资源布局提供Alpha版本,用于根据自定义需求(如法规、定价或性能)为联合(federated)集群提供布局策略。

弃用

  • 第三方资源(TPR)已被自定义资源定义(Custom Resource Definitions,CRD)取代,后者提供了一个更清晰的API,并解决了TPR测试期间引发的问题和案例。如果您使用TPR测试版功能,则建议您迁移,因为它将在Kubernetes 1.8中被移除。

v1.8 - 20170928

2017年9月28日,kubernetes1.8版本发布。该版本中包括了一些功能改进和增强,并增加了项目的成熟度,将强了kubernetes的治理模式,这些都将有利于kubernetes项目的持续发展。

聚焦安全性

Kubernetes1.8的基于角色的访问控制(RBAC)成为stable支持。RBAC允许集群管理员动态定义角色对于Kubernetes API的访问策略。通过网络策略筛选出站流量的Beta支持,增强了对入站流量进行过滤的现有支持。 RBAC和网络策略是强化Kubernetes内组织和监管安全要求的两个强大工具。

Kubelet的传输层安全性(TLS)证书轮换成为beta版。自动证书轮换减轻了集群安全性运维的负担。

聚焦工作负载支持

Kubernetes 1.8通过apps/v1beta2组和版本推动核心工作负载API的beta版本。Beta版本包含当前版本的Deployment、DaemonSet、ReplicaSet和StatefulSet。 工作负载API是将现有工作负载迁移到Kubernetes以及开发基于Kubernetes的云原生应用程序提供了基石。

对于那些考虑在Kubernetes上运行大数据任务的,现在的工作负载API支持运行kubernetes原生支持的Apache Spark

批量工作负载,比如夜间ETL工作,将从CronJobs的beta版本中受益。

自定义资源定义(CRD)在Kubernetes 1.8中依然为测试版。CRD提供了一个强大的机制来扩展Kubernetes和用户定义的API对象。 CRD的一个用例是通过Operator Pattern自动执行复杂的有状态应用,例如键值存储、数据库和存储引擎。随着稳定性的继续推进,预计将继续加强对CRD的验证

更多

Volume快照、PV调整大小、自动taint、pod优先级、kubectl插件等!

v1.9 - 20171215

2017年12月15日,kubernetes1.9版本发布。Kubernetes依然按照每三个月一个大版本发布的速度稳定迭代,这是今年发布的第四个版本,也是今年的最后一个版本,该版本最大的改进是Apps Workloads API成为稳定版本,这消除了很多潜在用户对于该功能稳定性的担忧。还有一个重大更新,就是测试支持了Windows了,这打开了在kubernetes中运行Windows工作负载的大门。

  • Workloads API GA

    apps/v1 Workloads API成为GA(General Availability),且默认启用。 Apps Workloads API将DaemonSetDeploymentReplicaSetStatefulSet API组合在一起,作为Kubernetes中长时间运行的无状态和有状态工作负载的基础。

    Deployment和ReplicaSet是Kubernetes中最常用的两个对象,经过一年多的实际使用和反馈后,现在已经趋于稳定。SIG apps同时将这些经验应用到另外的两个对象上,使得DaemonSet和StatefulSet也能顺利毕业走向成熟。v1(GA)意味着已经生产可用,并保证长期的向后兼容。

  • Windows支持(beta)

    Kubernetes最初是为Linux系统开发的,但是用户逐渐意识到容器编排的好处,我们看到有人需要在Kubernetes上运行Windows工作负载。在12个月前,我们开始认真考虑在Kubernetes上支持Windows Server的工作。 SIG-Windows现在已经将这个功能推广到beta版本,这意味着我们可以评估它的使用情况

  • 增强存储

    kubernetes从第一个版本开始就支持多种持久化数据存储,包括常用的NFS或iSCSI,以及对主要公共云和私有云提供商的存储解决方案的原生支持。随着项目和生态系统的发展,Kubernetes的存储选择越来越多。然而,为新的存储系统添加volume插件一直是一个挑战。

    容器存储接口(CSI)是一个跨行业标准计划,旨在降低云原生存储开发的障碍并确保兼容性。 SIG-StorageCSI社区正在合作提供一个单一接口,用于配置、附着和挂载与Kubernetes兼容的存储。

    Kubernetes 1.9引入了容器存储接口(CSI)的alpha实现,这将使挂载新的volume插件就像部署一个pod一样简单,并且第三方存储提供商在开发他们的解决方案时也无需修改kubernetes的核心代码。

    由于该功能在1.9版本中为alpha,因此必须明确启用该功能,不建议用于生产使用,但它为更具扩展性和基于标准的Kubernetes存储生态系统提供了清晰的路线图。

  • 其它功能

    自定义资源定义(CRD)校验,现在已经成为beta,默认情况下已启用,可以用来帮助CRD作者对于无效对象定义给出清晰和即时的反馈。

    SIG Node硬件加速器转向alpha,启用GPU,从而实现机器学习和其他高性能工作负载。

    CoreDNS alpha可以使用标准工具来安装CoreDNS。

    kube-proxy的IPVS模式进入beta版,为大型集群提供更好的可扩展性和性能。

    社区中的每个特别兴趣小组(SIG)继续提供其所在领域的用户最迫切需要的功能。有关完整列表,请访问发行说明

v1.10 - 20180326

2018年3月26日,kubernetes1.10版本发布,这是2018年发布的第一个版本。该版本的Kubernetes主要提升了Kubernetes的成熟度、可扩展性与可插入性。

该版本提升了三大关键性功能的稳定度,分别为存储、安全与网络。另外,此次新版本还引入了外部kubectl凭证提供程序(处于alpha测试阶段)、在安装时将默认的DNS服务切换为CoreDNS(beta测试阶段)以及容器存储接口(简称CSI)与持久化本地卷的beta测试版。

下面再分别说下三大关键更新。

  • 存储
    • CSI(容器存储接口)迎来Beta版本,可以通过插件的形式安装存储。
    • 持久化本地存储管理也迎来Beta版本。
    • 对PV的一系列更新,可以自动阻止Pod正在使用的PVC的删除,阻止已绑定到PVC的PV的删除操作,这样可以保证所有存储对象可以按照正确的顺序被删除。
  • 安全
    • kubectl可以对接不同的凭证提供程序
    • 各云服务供应商、厂商以及其他平台开发者现在能够发布二进制插件以处理特定云供应商IAM服务的身价验证
  • 网络
    • 将原来的kube-dns切换为CoreDNS

kubernetes 创建 charts 的示例

本文记录将 eclipse 的物联网开源应用 kapua 容器化为 kubernetes charts 的要点。 项目demo也在我的github上面:kelvinblood/kapua-kubernetes

一 docker-compose

首先我们在官网上 https://www.eclipse.org/kapua/getting-started.php 看到 kapua 的启动命令:

$ docker run -td --name kapua-sql -p 8181:8181 -p 3306:3306 kapua/kapua-sql:0.3.2

$ docker run -td --name kapua-elasticsearch -p 9200:9200 -p 9300:9300 elasticsearch:5.4.0 -Ecluster.name=kapua-datastore -Ediscovery.type=single-node -Etransport.host=_site_ -Etransport.ping_schedule=-1 -Etransport.tcp.connect_timeout=30s

$ docker run -td --name kapua-broker --link kapua-sql:db --link kapua-elasticsearch:es --env commons.db.schema.update=true -p 1883:1883 -p 61614:61614 kapua/kapua-broker:0.3.2

$ docker run -td --name kapua-console --link kapua-sql:db --link kapua-broker:broker --link kapua-elasticsearch:es --env commons.db.schema.update=true -p 8080:8080 kapua/kapua-console:0.3.2

$ docker run -td --name kapua-api --link kapua-sql:db --link kapua-broker:broker --link kapua-elasticsearch:es --env commons.db.schema.update=true -p 8081:8080 kapua/kapua-api:0.3.2

在这里可以看到 kapua 一共分成五个组件:

  • sql
  • es
  • broker
  • console
  • api

我们先将这几个命令行组合起了成为一个 docker-compose 文件,便于管理:

version: '2'
services:
  kapua-sql:
    image: iot/kapua-sql:0.3.2
    restart: always

  kapua-elasticsearch:
    image: elasticsearch:5.4.0
    restart: always
    command:
    - -Ecluster.name=kapua-datastore
    - -Ediscovery.type=single-node
    - -Etransport.host=_site_
    - -Etransport.ping_schedule=-1
    - -Etransport.tcp.connect_timeout=30s

  kapua-broker:
    image: iot/kapua-broker:0.3.2
    restart: always
    links:
      - kapua-sql:db
      - kapua-elasticsearch:es
    environment:
      - commons.db.schema.update=true
      - DB_PORT_3306_TCP_PORT=3306
    ports:
      - "1883:1883"
      - "61614:61614"

  kapua-console:
    image: iot/kapua-console:0.3.2
    restart: always
    links:
      - kapua-sql:db
      - kapua-elasticsearch:es
      - kapua-broker:broker
    environment:
      - commons.db.schema.update=true
    ports:
      - "8080:8080"

  kapua-api:
    image: iot/kapua-api:0.3.2
    restart: always
    links:
      - kapua-sql:db
      - kapua-elasticsearch:es
      - kapua-broker:broker
    environment:
      - commons.db.schema.update=true
    ports:
      - "8080:8080"

有了这个文件,在单机上我们可以直接使用 docker-compose up -d 部署应用。

二 转换为chart

入门

对于新手来说,有一个很好的应用,可以快速辅助你将 docker-compose 文件转换成 kubernetes 的应用—— kompose 。使用方法也很简单

# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.14.0/kompose-linux-amd64 -o kompose

# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.14.0/kompose-darwin-amd64 -o kompose

chmod +x kompose
sudo mv ./kompose /usr/local/bin/kompose

以上安装完成后使用以下命令转换

kompose convert -f docker-compose.yaml 

即可将文件转换成 kubernetes chart 文件。下图就是使用命令转换后的文件列表(templates目录)。

之后,我们使用 helm 创建 charts 的命令行创建chart,清空 templates 目录后将刚才的文件挪进去。

修改

不过使用 kompose 转换的文件还是有一些问题的,直接放到文件夹中并不好用。比如它没有使用values.yaml,没有生成namespace,没有资源限制等等,我们需要用以下的方式将其改造的更符合我们的要求。

注意事项:

  1. name: 字段不允许使用骆驼峰模式,可使用分隔符 -,英文需要全部小写。
  2. value.yaml中的变量,不要使用分隔符 - ,会与变量解释器产生冲突,编译的时候报错。可以使用骆驼峰。
  3. 注意缩进问题,缩进不对或者带tab也会报错。

接下来做一些改造:

  1. 在 template 文件夹中使用_helpers.tpl文件,以便在 yaml 文件中使用重复的字段。

    我做了一个简单的小改造:

    这里面定义了两个变量,name和fullname,可以在yaml文件中直接使用:

  2. 使用 ingress:

    我这里使用的是traefik作为ingress的实现方式,需要事先安装好traefik。ingress.yaml 配置如下:

  3. 创建 namespace

  4. 配置灵活的 values.yaml,将镜像前缀设置成可配的(方便内网应用部署)

  5. 为Java虚拟机 jvm 做资源限制,以console作为例子

    在values.yaml中配置如下:

    kapuaConsole:
      containerPort: 8080
      javaOpts: -Xms80m -Xmx80m -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Xmn10m -XX:PermSize=16M -XX:MaxPermSize=64M
      service:
        type: NodePort
    
  6. 使用service的name为服务创建别名,以broker作为例子:

  7. 限制pod和container的资源

参考资料


防止容器因 jvm 占用资源过多被杀死而频繁重启

本文记录 jvm 和 elasticsearch 在容器中的设置要点。

JVM

不完全翻译自https://blog.csanchez.org/2017/05/31/running-a-jvm-in-a-container-without-getting-killed/

JDK 8u131 在 JDK 9 中有一个特性,可以在 Docker 容器运行时能够检测到多少内存的能力,这个功能在我看来,颇为流氓。

在容器内部运行 JVM,它在大多数情况下将如何默认最大堆为主机内存的1/4,而非容器内存的1/4。如果对 Java 容器中的jvm虚拟机不做任何限制,当我们同时运行几个 java 容器时,很容易导致服务器的内存耗尽、负载飙升而宕机;而如果我们对容器直接进行限制,就会导致内核在某个时候杀死 jvm 容器而导致频繁重启。

例如:

$ docker run -m 100MB openjdk:8u121 java -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 444.50M
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

下面我们尝试 JDK 8u131 中的实验性参数 -XX:+UseCGroupMemoryLimitForHeap

$ docker run -m 100MB openjdk:8u131 java \
  -XX:+UnlockExperimentalVMOptions \
  -XX:+UseCGroupMemoryLimitForHeap \
  -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 44.50M
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

JVM能够检测容器只有100MB,并将最大堆设置为44M。

下面尝试一个更大的容器

$ docker run -m 1GB openjdk:8u131 java \
  -XX:+UnlockExperimentalVMOptions \
  -XX:+UseCGroupMemoryLimitForHeap \
  -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 228.00M
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

嗯,现在容器有1GB,但JVM仅使用228M作为最大堆。

除了JVM正在容器中运行以外,我们是否还可以优化它呢?

$ docker run -m 1GB openjdk:8u131 java \
  -XX:+UnlockExperimentalVMOptions \
  -XX:+UseCGroupMemoryLimitForHeap \
  -XX:MaxRAMFraction=1 -XshowSettings:vm -version
VM settings:
    Max. Heap Size (Estimated): 910.50M
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

使用-XX:MaxRAMFraction 我们告诉JVM使用可用内存/ MaxRAMFraction作为最大堆。使用-XX:MaxRAMFraction=1我们几乎所有可用的内存作为最大堆。

elasticsearch

不完全翻译自https://www.elastic.co/guide/en/elasticsearch/reference/5.4/heap-size.html

Elasticsearch 将通过Xms(最小堆大小)和Xmx(最大堆大小)设置来分配 jvm.options 指定的整个堆,默认使用最小和最大大小为2 GB的堆。这些设置的值取决于服务器上可用的内存。在生产环境时,要确保 Elasticsearch 有足够的可用堆。

一些好的经验是:

  • 将最小堆大小(Xms)和最大堆大小(Xmx)设置为彼此相等。

  • Elasticsearch 可用的堆越多,可用于缓存的内存就越多。但太多的堆会导致一直进行垃圾回收。

  • 将 Xmx 设置为不超过物理内存的50%,以确保有足够的物理内存留给内核文件系统缓存。

  • 不要将 Xmx 设置为J VM 用于压缩对象指针(压缩oops)的临界值以上,接近32 GB。可以通过在日志中查找一行来验证您是否处于限制之下,如下所示:

    heap size [1.9gb], compressed ordinary object pointers [true]
    
  • Even better, try to stay below the threshold for zero-based compressed oops; the exact cutoff varies but 26 GB is safe on most systems, but can be as large as 30 GB on some systems. You can verify that you are under the limit by starting Elasticsearch with the JVM options -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode and looking for a line like the following:

    heap address: 0x000000011be00000, size: 27648 MB, zero based Compressed Oops
    

    showing that zero-based compressed oops are enabled instead of

    heap address: 0x0000000118400000, size: 28672 MB, Compressed Oops with base: 0x00000001183ff000
    

以下是如何通过jvm.options文件设置堆大小的示例:

-Xms2g 
-Xmx2g 

也可以通过环境变量设置堆大小。

ES_JAVA_OPTS ="- Xms2g -Xmx2g"./bin/elasticsearch 
ES_JAVA_OPTS ="- Xms4000m -Xmx4000m"./bin/elasticsearch 

参考资料


Linux:集群工具ClusterShell

ClusterShell 是一个轻量级的运维工具,可以在一台机器上向多台机器发送指令,轻松实现类似《黑客帝国》中批量关闭电厂的效果:

ClusterShell每天在Linux超级计算机(拥有超过5000个计算节点)上使用。使用很简单,只要在主控机上配置好子节点的ssh密钥登陆,同时做好节点配置即可,非常便捷。这篇文章介绍它的安装和简单使用。

安装

yum install -y clustershell
// or
apt-get install clustershell

解决 Firefox is already running, but is not responding 错误

远程vnc的时候,发现firefox没办法启动,报了这个错误:

Firefox is already running, but is not responding. To open a new window, you must first close the existing Firefox process, or restart your system.

即使将 Firefox 的进程全部杀死,仍然会报这个错误。

解决方法如下:

在linux的终端输入:

firefox -profilemanager 

# 或者
firefox -p

在出现的页面中将当前出错的 Profile 删除掉,然后新建个即可。


kubernetes kubectl 命令行

本文记录常用的kubectl命令行。

官方参考手册:https://kubernetes.io/docs/reference/

蚂蚁金服的 Jimmy Song(宋净超) 主导了一个Kubernetes Handbook 的开源项目,里面有官方手册中这一部分的中文参考,对英文苦手的可以看看:https://jimmysong.io/kubernetes-handbook/guide/command-usage.html

在此之前我们可以先看看命令行的帮助:

kubectl help

从帮助给我们划分了几个 kubectl 的命令主题:

  • 入门命令
  • 部署命令 deployment
  • 集群管理命令 cluster
  • 问题定位命令
  • 高级命令
  • 设置命令
  • 其它

下文的分类是我自己分配的,不按照帮助的显示顺序。

自动补全

$ source <(kubectl completion bash) # setup autocomplete in bash, bash-completion package should be installed first.
$ source <(kubectl completion zsh)  # setup autocomplete in zsh

或者永久性设置(bash):
kubectl completion bash >> ~/.bashrc
source ~/.bashrc

帮助命令

$ kubectl help
$ kubectl explain pods,svc                       # get the documentation for pod and svc manifests

入门命令

  1. kubectl create

    kubectl run

    也可以用 kubectl apply

    $ kubectl create -f ./my-manifest.yaml           # create resource(s)
    $ kubectl create -f ./my1.yaml -f ./my2.yaml     # create from multiple files
    $ kubectl create -f ./dir                        # create resource(s) in all manifest files in dir
    $ kubectl create -f https://git.io/vPieo         # create resource(s) from url
    
    $ kubectl run nginx --image=nginx                # start a single instance of nginx
    
  2. $ kubectl delete -f ./pod.json                                              # Delete a pod using the type and name specified in pod.json
    $ kubectl delete pod,service baz foo                                        # Delete pods and services with same names "baz" and "foo"
    $ kubectl delete pods,services -l name=myLabel                              # Delete pods and services with label name=myLabel
    $ kubectl delete pods,services -l name=myLabel --include-uninitialized      # Delete pods and services, including uninitialized ones, with label name=myLabel
    $ kubectl -n default delete pv --all                                      # 删除 default 下所有的pv
    $ kubectl delete node xxx                                                 # 删除 node
    
  3. kubectl get xxx

    kubectl describe nodes xxx

    # 查询资源
    $ kubectl get services                          # List all services in the namespace
    $ kubectl get pods --all-namespaces             # List all pods in all namespaces
    $ kubectl get pods -o wide                      # List all pods in the namespace, with more details
    $ kubectl get deployment my-dep                 # List a particular deployment
    $ kubectl get pods --include-uninitialized      # List all pods in the namespace, including uninitialized ones
    
    # 资源详细描述
    $ kubectl describe nodes my-node
    $ kubectl describe pods my-pod
    
    # 排序
    $ kubectl get services --sort-by=.metadata.name
    $ kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
    
    # 选择标签
    $ kubectl get pods --selector=app=cassandra rc -o \
      jsonpath='{.items[*].metadata.labels.version}'
    $ kubectl get pods --field-selector=status.phase=Running
    
    # ExternalIPs
    $ kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="ExternalIP")].address}'
    
    # 列出所有密钥
    $ kubectl get pods -o json | jq '.items[].spec.containers[].env[]?.valueFrom.secretKeyRef.name' | grep -v null | sort | uniq
    
    # 列出事件按时间排序
    $ kubectl get events --sort-by=.metadata.creationTimestamp
    
  4. 用于更新 API 对象的命令有:

    kubectl patch,

    kubectl annotate,

    kubectl edit,

    kubectl replace,

    kubectl scale,

    kubectl apply,

    kubectl expose

    • 更改pod

      # 从json文件滚动升级pods的镜像
      $ kubectl rolling-update frontend-v1 -f frontend-v2.json       
      
      # 重命名 + 升级pod镜像
      $ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2  
      
      # 回滚pod
      $ kubectl rolling-update frontend-v1 frontend-v2 --rollback
      
      # 从json文件替换pod
      $ cat pod.json | kubectl replace -f - 
      
      # 强制替换pod
      $ kubectl replace --force -f ./pod.json
      
      # 暴露端口
      $ kubectl expose rc nginx --port=80 --target-port=8000
      
      # 更新pod镜像
      $ kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f -
      
      $ kubectl label pods my-pod new-label=awesome                      # Add a Label
      $ kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq       # Add an annotation
      $ kubectl autoscale deployment foo --min=2 --max=10                # Auto scale a deployment "foo"
      
      $ kubectl edit svc/docker-registry                      # Edit the service named docker-registry
      $ KUBE_EDITOR="nano" kubectl edit svc/docker-registry   # Use an alternative editor
      
    • patch 补丁

      kubectl patch 命令接受 YAML 或 JSON 格式的补丁,且补丁能够以文件或直接以命令行参数的形式进行传递

      kubectl patch 命令拥有一个 type 参数,可以将其设置为以下值:

      参数值 合并类型
      json JSON 补丁, RFC 6902
      merge JSON 合并补丁, RFC 7386
      strategic 默认值,策略性合并补丁

      使用JSON 合并补丁更新一个列表,必须重新定义整个列表。新的列表会完全替换掉原先的列表。

      # 策略性合并补丁
      $ kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}' 
      $ kubectl patch deployment patch-demo --patch "$(cat patch-file.yaml)"
      $ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
      
      # 查看补丁情况
      # kubectl get deployment patch-demo --output yaml
      
      $ kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'
      $ kubectl patch deployment valid-deployment  --type json   -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/livenessProbe"}]'
      
      # 增加新值
      $ kubectl patch sa default --type='json' -p='[{"op": "add", "path": "/secrets/1", "value": {"name": "whatever" } }]'
      
    • scale

      $ kubectl scale --replicas=3 rs/foo                                 # Scale a replicaset named 'foo' to 3
      $ kubectl scale --replicas=3 -f foo.yaml                            # Scale a resource specified in "foo.yaml" to 3
      $ kubectl scale --current-replicas=2 --replicas=3 deployment/mysql  # If the deployment named mysql's current size is 2, scale mysql to 3
      $ kubectl scale --replicas=5 rc/foo rc/bar rc/baz                   # Scale multiple replication controllers
      
      
  5. 资源类型

    资源类型 简写
    all  
    certificatesigningrequests csr
    clusterrolebindings  
    clusterroles  
    componentstatuses cs
    configmaps cm
    controllerrevisions  
    cronjobs  
    customresourcedefinition crd, crds
    daemonsets ds
    deployments deploy
    endpoints ep
    events ev
    horizontalpodautoscalers hpa
    ingresses ing
    jobs  
    limitranges limits
    namespaces ns
    networkpolicies netpol
    nodes no
    persistentvolumeclaims pvc
    persistentvolumes pv
    poddisruptionbudgets pdb
    podpreset  
    pods po
    podsecuritypolicies psp
    podtemplates  
    replicasets rs
    replicationcontrollers rc
    resourcequotas quota
    rolebindings  
    roles  
    secrets  
    serviceaccount sa
    services svc
    statefulsets sts
    storageclasses sc
  6. 输出格式

    -o 或者 -output 标签

Output format Description
-o=custom-columns=<spec> Print a table using a comma separated list of custom columns
-o=custom-columns-file=<filename> Print a table using the custom columns template in the <filename> file
-o=json Output a JSON formatted API object
-o=jsonpath=<template> Print the fields defined in a jsonpath expression
-o=jsonpath-file=<filename> Print the fields defined by the jsonpath expression in the <filename> file
-o=name Print only the resource name and nothing else
-o=wide Output in the plain-text format with any additional information, and for pods, the node name is included
-o=yaml Output a YAML formatted API object
  1. 输出debug级别

    -v 或者 --v 标志

级别 描述
--v=0 Generally useful for this to ALWAYS be visible to an operator.
--v=1 A reasonable default log level if you don’t want verbosity.
--v=2 Useful steady state information about the service and important log messages that may correlate to significant changes in the system. This is the recommended default log level for most systems.
--v=3 Extended information about changes.
--v=4 Debug level verbosity.
--v=6 Display requested resources.
--v=7 Display HTTP request headers.
--v=8 Display HTTP request contents.
--v=9 Display HTTP request contents without truncation of contents.

问题定位命令

  1. 集群信息

    $ kubectl cluster-info                                                  # 集群信息
    $ kubectl cluster-info dump                                             # 更详细的集群信息
    $ kubectl cluster-info dump --output-directory=/path/to/cluster-state   # 输出到文件
    
    $ kubectl config current-context
    
  2. top

    $ kubectl top pod POD_NAME --containers               # Show metrics for a given pod and its containers
    $ kubectl top node my-node                                              # Show metrics for a given node
    
  3. 维护模式

    $ kubectl cordon my-node                                                # 设置节点不可调度
    $ kubectl drain my-node                                                 # 将节点的pod 平滑 迁移到其他节点
    $ kubectl uncordon my-node                                              # 取消节点不可调度。
    
    # 参考 Kubernetes中的Taint和Toleration(污点和容忍): https://jimmysong.io/posts/kubernetes-taint-and-toleration/
    # Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,
    # 具有 taint 的 node 和 pod 是互斥关系,而具有节点亲和性关系的 node 和 pod 是相吸的。
    
    # 为 node1 设置 taint:
    kubectl taint nodes node1 key1=value1:NoSchedule
    kubectl taint nodes node1 key1=value1:NoExecute
    kubectl taint nodes node1 key2=value2:NoSchedule
    # 删除 taint:
    kubectl taint nodes node1 key1:NoSchedule-
    kubectl taint nodes node1 key1:NoExecute-
    kubectl taint nodes node1 key2:NoSchedule-
    
    # 为 pod 设置 toleration
    只要在 pod 的 spec 中设置 tolerations 字段即可,可以有多个 key:
    tolerations:
    - key: "key1"
      operator: "Equal"
      value: "value1"
      effect: "NoSchedule"
    - key: "key1"
      operator: "Equal"
      value: "value1"
      effect: "NoExecute"
    - key: "node.alpha.kubernetes.io/unreachable"
      operator: "Exists"
      effect: "NoExecute"
      tolerationSeconds: 6000
    value 的值可以为 NoSchedule、PreferNoSchedule 或 NoExecute。
    tolerationSeconds 是当 pod 需要被驱逐时,可以继续在 node 上运行的时间。
    
  4. Pods 互动

    kubectl logs

    kubectl attach

    kubectl exec

    $ kubectl logs my-pod                                 # dump pod logs (stdout)
    $ kubectl logs my-pod -c my-container                 # dump pod container logs (stdout, multi-container case)
    $ kubectl logs -f my-pod                              # stream pod logs (stdout)
    $ kubectl logs -f my-pod -c my-container              # stream pod container logs (stdout, multi-container case)
    $ kubectl run -i --tty busybox --image=busybox -- sh  # Run pod as interactive shell
    $ kubectl attach my-pod -i                            # Attach to Running Container
    
    $ kubectl exec my-pod -- ls /                         # Run command in existing pod (1 container case)
    $ kubectl exec my-pod -c my-container -- ls /         # Run command in existing pod (multi-container case)
    
    
  5. 暴露端口

    kubectl port-forward 暴露本地端口给pod

    kubectl proxy 使API server监听在本地端口

    $ kubectl port-forward my-pod 5000:6000               # Listen on port 5000 on the local machine and forward to port 6000 on my-pod
    
    $ kubectl proxy --address='0.0.0.0'  --accept-hosts='^*$'
    

1 2 3 4 5 6 63 64 65 66 67