This commit is contained in:
zhangqx2010
2017-09-30 21:45:14 +08:00
116 changed files with 4002 additions and 1409 deletions
+8 -8
View File
@@ -8,7 +8,7 @@ title: Webhook Mode
---
{% capture overview %}
WebHook 是一 HTTP 回调:某些事情发生时的一个 HTTP POST 请求;通过 HTTP POST 发送的一个简单事件通知。一个继续 web 应用实现的 WebHook 会在特定事件发生时把消息发送给特定的 URL 。
WebHook 是一 HTTP 回调:某些条件下触发的 HTTP POST 请求;通过 HTTP POST 发送的简单事件通知。一个基于 web 应用实现的 WebHook 会在特定事件发生时把消息发送给特定的 URL 。
{% endcapture %}
{% capture body %}
@@ -28,8 +28,8 @@ WebHook 是一个 HTTP 回调:当某些事情发生时的一个 HTTP POST 请
clusters:
- name: name-of-remote-authz-service
cluster:
certificate-authority: /path/to/ca.pem # 用于确认远程服务的CA.
server: https://authz.example.com/authorize # 远程服务的查询 URL. 必须 'https'.
certificate-authority: /path/to/ca.pem # 对远程服务进行身份认证的CA
server: https://authz.example.com/authorize # 远程服务的查询 URL. 必须使用 'https'
# users 代表 API 服务器的 webhook 配置.
users:
@@ -38,7 +38,7 @@ users:
client-certificate: /path/to/cert.pem # webhook plugin 使用的 cert。
client-key: /path/to/key.pem # cert 所对应的 key。
# kubeconfig 文件必须有上下文. 需要提供一个给 API 服务器.
# kubeconfig 文件必须有 context 。 需要提供一个给 API 服务器
current-context: webhook
contexts:
- context:
@@ -52,8 +52,8 @@ contexts:
在做认证决策时,API 服务器会 POST 一个 JSON 序列化的 api.authorization.v1beta1.SubjectAccessReview 对象来描述这个动作。这个对象包含了描述用户请求的字段,同时也包含了需要被访问资源或者请求特征的具体信息。
需要注意的是 webhook API 对象对于 [versioning compatibility rules](/docs/api/) 和其他 Kuberntes API 来说是同一个主题
实施人员应该了解 beta 对象的松耦合承诺,同时确认请求的 "apiVersion" 字段以确保能被正确地反序列化。
需要注意的是 webhook API 对象与其他 Kubernetes API 对象一样都同样都服从 [版本兼容规则](/docs/api/)
实施人员应该了解 beta 对象的更宽松的兼容性承诺,同时确认请求的 "apiVersion" 字段以确保能被正确地反序列化。
此外,API 服务器还必须启用 `authorization.k8s.io/v1beta1` API 扩展组(`--runtime-config=authorization.k8s.io/v1beta1=true`)。
@@ -80,7 +80,7 @@ contexts:
```
远程服务被预期能填写请求和反馈的 SubjectAccessReviewStatus 字段,无论是允许访问还是拒绝访问。
反馈内容的 "spec" 字段是被忽略的,也是可以被省略的。一个允许的反馈的返回值会是
反馈内容的 "spec" 字段是被忽略的,也是可以被省略的。当请求是被允许的时候,返回的响应如下例所示
```json
{
@@ -131,7 +131,7 @@ contexts:
非资源类的路径包括:`/api`, `/apis`, `/metrics`, `/resetMetrics`,
`/logs`, `/debug`, `/healthz`, `/swagger-ui/`, `/swaggerapi/`, `/ui`, and
`/version`。 客户端需要访问 `/api`, `/api/*`, `/apis`, `/apis/*`, 和 `/version` 以便
能发现服务器上有什么资源和版本。对于其他非资源类的路径访问在没有 REST api 访问限制的情况下拒绝。
能发现服务器上有什么资源和版本。对于其他非资源类的路径访问在没有 REST API 访问限制的情况下拒绝。
更多信息可以参考 uthorization.v1beta1 API 对象和
+34 -35
View File
@@ -2,7 +2,7 @@
assignees:
- jbeda
title: Webhook 模式
title: 使用启动引导令牌(Bootstrap Tokens)认证
---
* TOC
@@ -17,10 +17,10 @@ title: Webhook 模式
启动引导令牌是一种简单的 bearer token ,这种令牌是在新建集群或者在现有集群中添加新加新节点时使用的。
它被设计成能支持 [`kubeadm`](/docs/admin/kubeadm/),但是也可以被用在其他上下文中以便用户在
不使用 `kubeadm` 的情况下启动cluster。它也被设计成可以通过 RBAC 策略,结合[Kubelet TLS
Bootstrapping](/cn/docs/admin/kubelet-tls-bootstrapping/) 系统进行工作。
启动引导令牌是一种简单的持有者令牌(Bearer Token,这种令牌是在新建集群或者在现有集群中添加新加新节点时使用的。
它被设计成能支持 [`kubeadm`](/docs/admin/kubeadm/),但是也可以被用在其他 context 中以便用户在
不使用 `kubeadm` 的情况下启动集群。它也被设计成可以通过 RBAC 策略,结合 [Kubelet TLS
Bootstrapping](/docs/admin/kubelet-tls-bootstrapping/) 系统进行工作。
@@ -29,15 +29,14 @@ Bootstrapping](/cn/docs/admin/kubelet-tls-bootstrapping/) 系统进行工作。
启动引导令牌被定义成一个特定类型的secrets (`bootstrap.kubernetes.io/token`),并存在于
启动引导令牌被定义成一个特定类型的 secrets(`bootstrap.kubernetes.io/token`),并存在于
`kube-system` 命名空间中。然后这些 secrets 会被 API 服务器上的启动引导的认证器读取。
过期的令牌与令牌清除控制器会被控制管理器一起清除。令牌也会被用于创建签名,签名用于
启动引导签名控制器在 "discovery" 程中特定的 configmap
过期的令牌与 TokenCleaner 会被控制管理器一起清除。令牌也会被用于创建特定 configmap 的签名,
而这个 configmap 会通过启动引导签名控制器在 "discovery" 程中使用
目前,启动引导令牌处于 **alpha** 阶段,但是预期也不会有大的突破性的变化。
目前,启动引导令牌处于 **alpha** 阶段,但是预期也不会有大的突破性变化。
## 令牌格式
@@ -51,14 +50,14 @@ Bootstrapping](/cn/docs/admin/kubelet-tls-bootstrapping/) 系统进行工作。
令牌的第一部分是 "Token ID" ,它是公共信息。它被用于引用一个 token 用于认证而不会泄漏保密部分。
令牌的第一部分是 "Token ID" ,它是公共信息。它被用于引用一个用于认证的令牌而不会泄漏令牌的保密部分。
第二部分是 "Token Secret",它应该只能被信任方共享。
## 启用启动引导令牌
所有启动引导令牌的特在 Kubernetes v1.6 版本中都是默认禁用的。
所有启动引导令牌的特在 Kubernetes v1.6 版本中默认都是禁用的。
@@ -68,7 +67,7 @@ Bootstrapping](/cn/docs/admin/kubelet-tls-bootstrapping/) 系统进行工作。
你可以在 API 服务器上通过 `--experimental-bootstrap-token-auth` 参数启用启动引导令牌。
你可以在控制管理器上通过 `--controllers` 参数,比如 `--controllers=*,tokencleaner,bootstrapsigner` 来启用启动引导令牌。
在使用 `kubeadm` 时,这是自动完成的。
在使用 `kubeadm` 时,这是自动完成的。
HTTPS 调用中的令牌是这样使用的:
@@ -84,13 +83,13 @@ Authorization: Bearer 07401b.f395accd246ae52d
每个合法的令牌是通过一个 `kube-system` 命名空间中的 secret 隐藏的。
你可以从[这里](https://git.k8s.io/community/contributors/design-proposals/bootstrap-discovery.md)找到完整设计文档。
你可以从 [这里](https://git.k8s.io/community/contributors/design-proposals/bootstrap-discovery.md) 找到完整设计文档。
这是 secret 看起来的样子。注意,`base64(string)` 表示应该通过 base64 编码
这里使用的是解码版本以便于阅读。
这是 secret 看起来的样子。注意,`base64(string)` 表示应该通过 base64 对值进行编码。
这里使用的是解码版本以便于阅读。
```yaml
apiVersion: v1
@@ -113,12 +112,12 @@ data:
secret的类型必须是 `bootstrap.kubernetes.io/token` ,而名字必须是 `bootstrap-token-<token id>`
secret 的类型必须是 `bootstrap.kubernetes.io/token` ,而名字必须是 `bootstrap-token-<token id>`
`description` 是人类可读的描述,而不应该是机器可读的信息。令牌 ID 和 Secret 是包含在数据字典中的。
The `usage-bootstrap-*` members indicate what this secret is intended to be used
for. A value must be set to `true` to be enabled.
`usage-bootstrap-*` 成员代表了这个 secret 被用于什么。启用时,值必须设置为 `true`
`usage-bootstrap-*` 成员表示这个 secret 的用途。启用时,值必须设置为 `true`
@@ -127,7 +126,7 @@ for. A value must be set to `true` to be enabled.
`usage-bootstrap-authentication` 表示令牌可以用于 API 服务器的认证。认证器会以
`system:bootstrap:<Token ID>` 认证。它被包含在 `system:bootstrappers` 组中。
命名和组是故意受限制的,以阻碍用户在启动引导后再使用这些令牌。
命名和组是故意受限制的,以防止用户在启动引导后再使用这些令牌。
@@ -136,8 +135,8 @@ for. A value must be set to `true` to be enabled.
`expiration` 数据成员列举了令牌在失效后的时间。这是通过 RFC3339 进行编码的 UTC 时间。
令牌清理控制器会删除过期的令牌。
`expiration` 数据成员列举了令牌在失效后的时间。这是遵循 RFC3339 进行编码的 UTC 时间。
TokenCleaner 控制器会删除过期的令牌。
## 使用 `kubeadm` 管理令牌
@@ -147,18 +146,18 @@ for. A value must be set to `true` to be enabled.
你可以`kubeadm` 工具管理正在运行集群的令牌。它会从 `kubeadm` 创建的集群(`/etc/kubernetes/admin.conf`)
自动抓取默认管理员密码。你可以对下面命令指定一个另外的 kubeconfig 文件抓取密码,参数使用 `--kubeconfig`
你可以使`kubeadm` 工具管理正在运行集群的令牌。它会从 `kubeadm` 创建的集群(`/etc/kubernetes/admin.conf`)
自动抓取默认管理员密码。你可以通过参数 `--kubeconfig` 对下面命令指定一个另外的 kubeconfig 文件抓取密码。
* `kubeadm token list` 列举了令牌,同时显示了它们的过期时间和用途。
* `kubeadm token create` 创建一个新令牌。
* `--description` 设置新令牌的描述。
* `--ttl duration` 设置令牌从 "现在" 起到过期时间增量
* `--ttl duration` 设置令牌从 "现在" 起到过期时间的差值
默认是 0 ,也就是不过期。
* `--usages` 设置令牌被使用的方式。默认是 `signing,authentication`。用途在上面已经描述。
* `kubeadm token delete <token id>|<token id>.<token secret>` 删除令牌。
令牌可以只用 ID 来确认,或者用整个令牌的值。如果只用 ID,密文不符合的令牌也会被删除。
令牌可以只用 ID 来确认,也可以用整个令牌的值。如果只用 ID 的情况下,密文不匹配的令牌也会被删除。
### ConfigMap签名
@@ -166,16 +165,16 @@ for. A value must be set to `true` to be enabled.
除了认证之外,令牌可以用于签名 ConfigMap。这在集群启动程的早期,在客户端信任 API服务器之前被使用。
签名的 ConfigMap 可以通过共享令牌被认证。
除了认证之外,令牌可以用于签名 ConfigMap。这在集群启动程的早期,在客户端信任 API 服务器之前被使用。
签名的 ConfigMap 可以通过共享令牌被认证。
签名的 ConfigMap 是 `kube-public` 命名空间中`cluster-info`
典型的工作流中,客户端读取这个 ConfigMap 而不管认证和 TLS 报错
它会通过 ConfigMap 中嵌入的签名校验 ConfigMap 的载荷。
签名的 ConfigMap 是 `cluster-info`,存在于 `kube-public` 命名空间中。
典型的工作流中,客户端在未经认证和忽略 TLS 报错的状态下读取这个 ConfigMap。
通过 ConfigMap 中嵌入的签名校验 ConfigMap 的载荷。
ConfigMap 会是这个样子的:
@@ -206,7 +205,7 @@ data:
ConfigMap 的 `kubeconfig` 成员是一个填好了集群信息的配置文件。
这里主要交换的信息是 `certificate-authority-data`。在将来可能会扩展。
这里主要交换的信息是 `certificate-authority-data`。在将来可能会扩展。
@@ -216,6 +215,6 @@ ConfigMap 的 `kubeconfig` 成员是一个填好了集群信息的配置文件
签名是一个 JWS 签名,使用了 "detached" 模式。为了检验签名,用户应该按照 JWS 规则
(base64 编码而忽略结尾的 `=`)对 `kubeconfig` 载荷进行编码。那样编码载荷会被通过插入 JWS 并存在于两个点的中间
,用于形成一个完整的 JWS。可以使用令牌的完整信息(比如 `07401b.f395accd246ae52d`)作为共享密钥,
(base64 编码而忽略结尾的 `=`)对 `kubeconfig` 载荷进行编码。完成编码载荷会被通过插入 JWS 并存在于两个点的中间
,用于形成一个完整的 JWS。可以使用令牌的完整信息比如 `07401b.f395accd246ae52d`作为共享密钥,
通过 `HS256` 方式 (HMAC-SHA256) 对 JWS 进行校验。 用户 _必须_ 确保使用了 HS256。
+31 -31
View File
@@ -3,23 +3,23 @@ assignees:
- davidopp
- lavalamp
title搭建大型集群
title: 搭建大型集群
---
## 支持
在 {{page.version}} 版本中,Kubernetes 支持集群节点数可达1000个。更具体地说,我们配置能够支持*所有*如下条件:
在 {{page.version}} 版本中,Kubernetes 支持集群节点node数可达1000个。更具体地说,我们配置能够支持*所有*如下条件:
* 不超过2000个
* 不超过总共6000个 pods
* 不超过总共12000个节点容器
* 单节点不超过100个 pods
* 不超过2000个节点
* 不超过总共6000个 pod
* 不超过总共12000个 container
* 单节点不超过100个 pod
<br>
@@ -30,13 +30,13 @@ title:搭建大型集群
## 安装
集群是一组运行着 Kubernetes 代理的节点(物理或者虚机),被 "主服务器" (集群层面的控制台)所管理。
集群是一组运行着 Kubernetes 代理的节点(物理或者虚机),被 "主服务器" 集群层面的控制台所管理。
通常来说,集群中的节点数是通过平台相关`config-default.sh` 文件(例子参考[GCE's `config-default.sh`](http://releases.k8s.io/{{page.githubbranch}}/cluster/gce/config-default.sh)中的 `NUM_NODES` 值控制的。
通常来说,集群中的节点数是通过平台特定`config-default.sh` 文件例子参考 [GCE's `config-default.sh`](http://releases.k8s.io/{{page.githubbranch}}/cluster/gce/config-default.sh) 中的 `NUM_NODES` 值控制的。
然而,单单把这个值更改到很大会导致脚本在许多云服务商平台上运行失败。例如 GCE 部署,会有配额问题导致集群启动失败。
然而,单单把这个值更改到很大的数值会导致安装脚本在许多云服务商平台上运行失败。例如 GCE 部署,会有配额问题导致集群启动失败。
当需要建立大规模 Kubernetes 集群时,必须考虑下列问题:
@@ -45,26 +45,26 @@ title:搭建大型集群
### 配额问题
为了避免云服务商的配额导致问题,当创建一个许多节点的集群,要考虑:
为了避免云服务商平台上发生配额问题,当创建一个许多节点的集群,要考虑:
* 增加这些资源的配额,比如 CPU ,IP 地址等等。
* 在 [GCE 中,举个例子](https://cloud.google.com/compute/docs/resource-quotas) 你会需要增加:
* CPU
* 虚拟机实例
* 总共保留的永久磁盘
* 永久磁盘的预留总量
* 在使用的 IP 地址
* 防火墙规则
* 转发规则
* 路由
* 目标池
* 调整好安装脚本,让它能够在创建虚拟机节点的批处理间能有等待时间,因为很多云服务商对于虚拟机创建频率限制。
* 调整好安装脚本,让它能够在创建虚拟机节点的批处理有等待时间,因为很多云服务商平台对于虚拟机创建频率限制。
### Etcd 存储
为了提高大规模集群的性能,我们将 events 存储在一个独立的特定的etcd实例中。
为了提高大规模集群的性能,我们将 event 存储在一个独立的 etcd 实例中。
当创建一个集群时,现有的 salt 脚本会:
@@ -72,14 +72,14 @@ title:搭建大型集群
* 启动并配置额外的 etcd 实例
* 配置 api-server 使用它来储存 events
* 配置 api-server 用于储存 event
### 主服务器和主服务器组件的规格
在 GCE/GKE 和 AWS 上,`kube-up` 自动为你的主服务器配置合适的虚拟机规格,规格取决于集群中的节点数量。
对于其他云服务商,你需要进行手工配置。作为参考,我们在 GCE 上使用的规格是:
对于其他云服务商平台,你需要手工配置。作为参考,我们在 GCE 上使用的规格是:
* 1-5 节点: n1-standard-1
@@ -101,13 +101,13 @@ title:搭建大型集群
* 超过 500 节点: c4.8xlarge
注意这些主服务器节点规格只能在集群启动设置,如果后续对于集群扩容或者缩容(比如,手工或者使用集群自动扩展器删除或增加节点),规格是不会调整的。
注意主服务器节点规格只能在集群启动设置,如果后续对于集群扩容或者缩容比如,使用手工或集群自动扩展器进行增加或删除节点,规格是不会调整的。
### Addon (插件)资源
### 插件(Addon资源
为了防止[集群 addons](https://releases.k8s.io/{{page.githubbranch}}/cluster/addons) 内存泄漏或者其他资源问题导致消耗完节点的所有资源,Kubernetes 对 addon 容器设定了资源限制,以限制他们使用 CPU 和内存资源。(参见 PR [#10653](http://pr.k8s.io/10653/files) 和 [#10778](http://pr.k8s.io/10778/files))
为了防止 [集群插件](https://releases.k8s.io/{{page.githubbranch}}/cluster/addons) 内存泄漏或者其他资源问题导致消耗完节点的所有资源,Kubernetes 对插件容器设定了资源限制,以限制他们使用 CPU 和内存资源。参见 PR [#10653](http://pr.k8s.io/10653/files) 和 [#10778](http://pr.k8s.io/10778/files)
举例:
@@ -123,38 +123,38 @@ title:搭建大型集群
```
除了 Heapster,这些限制是固定的,并且是基于我们对于 addon 运行在4节点集群的采样数据(见 [#10335](http://issue.k8s.io/10335#issuecomment-117861225))。运行在大规模集群上时,addon 会消耗更多的资源(见 [#5880](http://issue.k8s.io/5880#issuecomment-113984085))。所以,如果大规模集群没有调整这些参数时,addon 可能会被持续杀死,因为他们总是达到限制。
除了 Heapster 之外,这些限制是固定的,并且是基于我们对于插件运行在4节点集群的采样数据见 [#10335](http://issue.k8s.io/10335#issuecomment-117861225)。运行在大规模集群上时,插件会消耗更多的资源见 [#5880](http://issue.k8s.io/5880#issuecomment-113984085)。所以,如果大规模集群没有调整这些参数时,插件容器可能会被持续杀死,因为他们总是达到限制。
为了避免集群的 addon 资源问题出现,当创建一个许多节点的集群,考虑如下问题:
为了避免集群的插件资源问题出现,当创建一个许多节点的集群,考虑如下问题:
* 为以下每个 addon 调整内存和 CPU 限制,使用时,随着你的集群扩容 (每个 addon 有一个 replica 来处理整个集群,所以 CPU/内存 使用量会随着集群的 规模/负载 按比例增加):
* 为以下每个插件调整内存和 CPU 限制,使用时,随着你的集群扩容(每个插件有一个 replica 来处理整个集群,所以 CPU/内存 使用量会随着集群的 规模/负载 按比例增加:
* [InfluxDB and Grafana](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/cluster-monitoring/influxdb/influxdb-grafana-controller.yaml)
* [kubedns, dnsmasq, and sidecar](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/kubedns-controller.yaml.in)
* [Kibana](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml)
* 为以下这些 addon 调整 replicas 数量, 使用时, 随着集群规模数量一起调整 (每个 addon 会有多个 replicas, 所以增加 replicas 应该能帮助处理增加的负载,但是,由于每个 replica 的负载也稍稍增加, 同时需要考虑增加 CPU/内存 限制):
* 为以下这些插件调整 replicas 数量, 使用时, 随着集群规模数量一起调整(每个插件会有多个 replicas, 所以增加 replicas 应该能帮助处理增加的负载,但是,由于每个 replica 的负载也稍稍增加, 同时需要考虑增加 CPU/内存 限制:
* [elasticsearch](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-elasticsearch/es-controller.yaml)
* 为以下这些 addon 稍稍增加 memory 和 CPU 使用限制, 使用时, 随着集群规模数量一起调整 (每个节点有一个 replica,但是 CPU/内存 使用量集群的 负载/规模 会稍稍增加):
* 为以下这些插件稍稍增加内存和 CPU 使用限制, 使用时, 随着集群规模数量一起调整每个节点有一个 replica,但是 CPU/内存 使用量随着集群的 负载/规模 会稍稍增加:
* [FluentD with ElasticSearch Plugin](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml)
* [FluentD with GCP Plugin](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml)
Heapseter 的资源限制是基于集群的初始规模动态配置的 (见 [#16185](http://issue.k8s.io/16185) 和 [#22940](http://issue.k8s.io/22940))
如果你发现 Hepaster 的资源不够,你应该调整 heapster 对于内存的请求公式 (详见这些 PRs)
Heapster 的资源限制是基于集群的初始规模动态配置的见 [#16185](http://issue.k8s.io/16185) 和 [#22940](http://issue.k8s.io/22940)
如果你发现 Heapster 的资源不够,你应该调整 Heapster 对于内存的请求的计算公式(详见这些 PRs
对于如何检查 addon 容器是否达到了资源使用限制,参考 [Troubleshooting section of Compute Resources](/docs/concepts/configuration/manage-compute-resources-container/#troubleshooting)。
对于如何检查插件容器是否达到了资源使用限制,参考 [计算资源的问题排查章节](/docs/concepts/configuration/manage-compute-resources-container/#troubleshooting)。
在[未来](http://issue.k8s.io/13048),我们预期会基于集群规模来设置所有集群 addon 的资源限制,并且会在你的集群扩容或缩容时进行动态调整。
我们欢迎实现这些功能的 PR 。
[未来](http://issue.k8s.io/13048),我们预期会基于集群规模来设置所有集群插件的资源限制,并且会在你的集群扩容或缩容时进行动态调整。
我们欢迎致力于实现这些功能的 PR 。
### 允许少数节点在启动时失败
由于各种原因 (详细信息见 [#18969](https://github.com/kubernetes/kubernetes/issues/18969)),运行 `kube-up.sh` 建立非常大
`NUM_NODES` 集群会由于个别的节点启动失败而失败。目前你有两个选择:重启集群 (再次运行 `kube-down.sh``kube-up.sh`)
或者,在运行 `kube-up.sh` 之前,将 `ALLOWED_NOTREADY_NODES` 环境变量设置成你觉得合适值。这会让 `kube-up.sh` 在少于 `NUM_NODES`
节点启动的时候成功完成。根据不同的失败原因,这些额外的节点可以在稍后再加入集群,或者集群可以保持在 `NUM_NODES - ALLOWED_NOTREADY_NODES` 的规模。
`NUM_NODES` 数量的集群会由于个别的节点启动失败而失败。目前你有两个选择:重启集群再次运行 `kube-down.sh``kube-up.sh`
或者,在运行 `kube-up.sh` 之前,将 `ALLOWED_NOTREADY_NODES` 环境变量设置成合适值。这会让 `kube-up.sh` 在少于 `NUM_NODES`
节点启动的时候成功完成。根据不同的失败原因,这些额外的节点可以在稍后再加入集群,或者集群可以保持在 `NUM_NODES - ALLOWED_NOTREADY_NODES` 的规模。
+22
View File
@@ -0,0 +1,22 @@
---
assignees:
- thockin
title: Kubernetes OpenVSwitch GRE/VxLAN 网络
---
本文档介绍了如何使用OpenVSwitch,在跨nodes的pods之间设置网络。
隧道类型可以是GRE或者是VxLAN。如需在网络内执行大规模隔离时,最好使用VxLAN。
![OVS Networking](/images/docs/ovs-networking.png)
Kubernetes中Vagrant的设置如下:
docker网桥被brctl生成的Linux网桥(kbr0)所代替,kbr0是具有256个地址空间的子网。总的来说,node会得到10.244.x.0/24的子网,docker上配置使用的网桥会代替默认docker0的网桥。
另外,OVS网桥创建(obr0),并将其作为端口添加到kbr0的网桥中。所有OVS网桥通过GRE隧道连接所有的nodes。因此,每个node都有一个到其他nodes的出站GRE隧道。这个隧道没有必要是一个完整的网状物,但是越像网状结构越好。在网桥上开启STP(生成树)模式以防止环路的发生。
路由规则允许任何10.244.0.0/16通过与隧道相连的OVS网桥到达目标。
+34 -36
View File
@@ -4,53 +4,53 @@ assignees:
- davidopp
- lavalamp
- liggitt
title: Managing Service Accounts
title: 管理服务帐号(Service Accounts
---
*本文是 service accounts 管理员手册。需要[Service Accounts 用户手册](/cn/docs/user-guide/service-accounts)的知识背景。*
*对于 authorization 和 user accounts 支持已经在计划中,但是还未完成。为了更好地解释 service
accounts,有时会提到一些未完成的功能特性。*
*本文是服务帐户管理员手册。需要[服务帐户用户手册](/docs/user-guide/service-accounts)的知识背景。*
*对于认证和用户帐号(user accounts)的支持已经在计划中,但是还未完成。为了更好地解释用户帐户,有时会提到一些未完成的功能特性。*
## 用户账号 vs 服务账号
Kubernetes 将 user account 和 service account 的概念区分开,主要基于以下几个原因:
Kubernetes 将用户账号和服务账号的概念区分开,主要基于以下几个原因:
- user account 是给人使用的。servcice account是给 pod 中运行的进程使用的。
- user account 为全局设计。命名必须在一个集群的所有命名空间中唯一,未来的用户资源不会被设计到命名空间中。
service account 是按命名空间的。
- 典型场景中,一个集群的 user account 是来自于企业数据库的,在数据库中新用户一般需要特殊权限,并且账号是与复杂业务流程关联的。
service account的创建往往更轻量,允许集群用户为特定的任务创建service account(即,权限最小化原则)。
- 用户账号是给人使用的。服务账号是给 pod 中运行的进程使用的。
- 用户账号为全局设计。命名必须在一个集群的所有命名空间中唯一,未来的用户资源不会被设计到命名空间中。
服务账号是在命名空间的。
- 典型场景中,一个集群的用户账号是从企业数据库的同步来的,在数据库中新用户帐号一般需要特殊权限,并且账号是与复杂业务流程关联的。
服务账号的创建往往更轻量,允许集群用户为特定的任务创建服务账号(即,权限最小化原则)。
- 对于人和服务的账号,审计要求会是不同的。
- 对于复杂系统而言,配置包可以包含该系统各类组件的 service account 定义,
因为 service account 可以有临时创建需求和自己的命名空间,这类配置是便携式的。
- 对于复杂系统而言,配置包可以包含该系统各类组件的服务账号定义,
因为服务账号能被临时创建,并且有命名空间分类的名字,这类配置是便携式的。
## 服务账号自动化
service accounts 的自动化由三个独立的组共同配合实现:
服务账号的自动化由三个独立的组共同配合实现:
- A Service account admission controller (service account 准入控制器)
- A Token controller (令牌控制器)
- A Service account controller (service account 控制器)
- 用户账号准入控制器(A Service account admission controller
- 令牌控制器(A Token controller
- 服务账号控制器(A Service account controller
### 服务账号准入控制器
对于 pods 的操作是通过一个叫做 [准入控制器](/cn/docs/admin/admission-controllers) 的插件实现的。它是 apiserver 的一部分。
准入控制器被创建或更新时,他会对 pod 同步进行操作。当这个插件活动状态时(大部分版本默认是活动状态),在 pod 被创建或者更改时,
对于 pods 的操作是通过一个叫做 [准入控制器](/docs/admin/admission-controllers) 的插件plugin实现的。它是 APIserver 的一部分。
pod 被创建或更新时,它会同步更改 pod。当这个插件活动状态时(大部分版本默认是活动状态),在 pod 被创建或者更改时,
它会做如下操作:
1. 如果 pod 没有配置 `ServiceAccount`,它会将 `ServiceAccount` 设置为 `default`
2. 它会确保被 pod 关联的 `ServiceAccount` 是存在的,否则就拒绝请求。
4. 如果 pod 没有包含任何的 `ImagePullSecrets`,那么 `ServiceAccount``ImagePullSecrets` 就会被添加到 pod
5. 它会把一个 `volume` 添加给 pod, 该 pod 包含有一个用于 API 访问的 token
6. 它会把一个 `volumeSource` 添加到 pod 的每个 container,并挂载到 `/var/run/secrets/kubernetes.io/serviceaccount`
1. 如果 pod 没有配置 `ServiceAccount`,它会将 `ServiceAccount` 设置为 `default`
2. 确保被 pod 关联的 `ServiceAccount` 是存在的,否则就拒绝请求。
3. 如果 pod 没有包含任何的 `ImagePullSecrets`,那么 `ServiceAccount``ImagePullSecrets` 就会被添加到 pod。
4. 它会把 `volume` 添加给 pod,该 pod 包含有一个用于 API 访问的令牌
5. 它会把 `volumeSource` 添加到 pod 的每个容器,挂载到 `/var/run/secrets/kubernetes.io/serviceaccount`
### 令牌控制器
@@ -59,21 +59,20 @@ service accounts 的自动化由三个独立的组建共同配合实现:
令牌控制器(TokenController)作为 controller-manager 的一部分运行。它异步运行。它会:
- 监听对于 serviceAccount 的创建动作,并创建对应的 Secret 以允许 API 访问。
- 监听对于 serviceAccount 的删除动作,并删除所有对应的 ServiceAccountToken Secrets
- 监听对于 secret 的添加动作,确保相关联的 ServiceAccount 是存在的,并根据需要为 secret 添加一个 token
- 监听对于 serviceAccount 的删除动作,并删除所有对应的 ServiceAccountToken Secret。
- 监听对于 secret 的添加动作,确保相关联的 ServiceAccount 是存在的,并根据需要为 secret 添加一个令牌
- 监听对于 secret 的删除动作,并根据需要删除对应 ServiceAccount 的关联。
你必须给令牌控制器token controller)传递一个 service account 的私钥(private key),可以通过 `--service-account-private-key-file` 参数完成。
传递的私钥将被用来对 service account tokens 进行签名。类似的,你必须给 kube-apiserver 传递一个公钥(public key),通过 `--service-account-key-file`
参数完成。传递的公钥会被用来验证认证过程中的令牌(token)。
你必须给令牌控制器传递一个服务帐号的私钥(private key),通过 `--service-account-private-key-file` 参数完成。传递的私钥将被用来对服务帐号令牌进行签名。
类似的,你必须给 kube-apiserver 传递一个公钥(public key),通过 `--service-account-key-file` 参数完成。传递的公钥在认证过程中会被用于验证令牌。
#### 创建额外的 API 令牌
#### 创建额外的 API 令牌API token
控制器的循环运行会确保对于每个 service account 都存在一个带有 API tokenAPI 令牌)的secret。
如需要为一个 service account 创建一个额外的 API 令牌API token,可以创建一个 `ServiceAccountToken`
类型的 secret,并添加与 service account 对应的 annotation 属性,控制器会为它更新 token
控制器的循环运行会确保对于每个服务帐号都存在一个带有 API 令牌的 secret。
如需要为服务帐号创建一个额外的 API 令牌,可以创建一个 `ServiceAccountToken`
类型的 secret,并添加与服务帐号对应的 annotation 属性,控制器会为它更新令牌
secret.json:
@@ -97,7 +96,7 @@ kubectl describe secret mysecretname
```
#### 删除作废服务账号令牌
#### 删除/作废服务账号令牌
```shell
kubectl delete secret mysecretname
@@ -107,5 +106,4 @@ kubectl delete secret mysecretname
### 服务账号控制器
Service Account Controller 在 namespaces 内管理 ServiceAccount,需要保证名为 "default" 的
ServiceAccount在每个命名空间中存在。
服务帐号控制器在命名空间内管理 ServiceAccount,需要保证名为 "default" 的 ServiceAccount 在每个命名空间中存在。
@@ -0,0 +1,71 @@
---
approvers:
- dchen1107
- roberthbailey
- liggitt
title: Master 节点通信
---
* TOC
{:toc}
## 概览
本文对 Master 节点(确切说是 apiserver)和 Kubernetes 集群之间的通信路径进行了分类。目的是为了让用户能够自定义他们的安装,对网络配置进行加固,使得集群能够在不可信的网络上(或者在一个云服务商完全公共的 IP 上)运行。
## Cluster -> Master
所有从集群到 master 的通信路径都终止于 apiserver(其它 master 组件没有被设计为可暴露远程服务)。在一个典型的部署中,apiserver 被配置为在一个安全的 HTTPS 端口(443)上监听远程连接并启用一种或多种形式的客户端[身份认证](/docs/admin/authentication/)机制。一种或多种客户端[身份认证](/docs/admin/authentication/)机制应该被启用,特别是在允许使用 [匿名请求](/docs/admin/authentication/#anonymous-requests) 或 [service account tokens](/docs/admin/authentication/#service-account-tokens) 的时候。
应该使用集群的公共根证书开通节点,如此它们就能够基于有效的客户端凭据安全的连接 apiserver。例如:在一个默认的 GCE 部署中,客户端凭据以客户端证书的形式提供给 kubelet。请查看 [kubelet TLS bootstrapping](/docs/admin/kubelet-tls-bootstrapping/) 获取如何自动提供 kubelet 客户端证书。
想要连接到 apiserver 的 Pods 可以使用一个 service account 安全的进行连接。这种情况下,当 Pods 被实例化时 Kubernetes 将自动的把公共根证书和一个有效的不记名令牌注入到 pod 里。`kubernetes` service (所有 namespaces 中)都配置了一个虚拟 IP 地址,用于转发(通过 kube-proxy)请求到 apiserver 的 HTTPS endpoint。
Master 组件通过非安全(没有加密或认证)端口和集群的 apiserver 通信。这个端口通常只在 master 节点的 localhost 接口暴露,这样,所有在相同机器上运行的 master 组件就能和集群的 apiserver 通信。一段时间以后,master 组件将变为使用带身份认证和权限验证的安全端口(查看[#13598](https://github.com/kubernetes/kubernetes/issues/13598))。
这样的结果使得从集群(在节点上运行的 nodes 和 pods)到 master 的缺省连接操作模式默认被保护,能够在不可信或公网中运行。
## Master -> Cluster
从 masterapiserver)到集群有两种主要的通信路径。第一种是从 apiserver 到集群中每个节点上运行的 kubelet 进程。第二种是从 apiserver 通过它的代理功能到任何 node、pod 或者 service。
### apiserver -> kubelet
从 apiserver 到 kubelet 的连接用于获取 pods 日志、连接(通过 kubectl)运行中的 pods,以及使用 kubele 的端口转发功能。这些连接终止于 kubelet 的 HTTPS endpoint。
默认的,apiserver 不会验证 kubelet 的服务证书,这会导致连接遭到中间人攻击,因而在不可信或公共网络上是不安全的。
为了对这个连接进行认证,请使用 `--kubelet-certificate-authority` 标记给 apiserver 提供一个根证书捆绑,用于 kubelet 的服务证书。
如果这样不可能,又要求避免在不可信的或公共的网络上进行连接,请在 apiserver 和 kubelet 之间使用 [SSH 隧道](/docs/concepts/architecture/master-node-communication/#ssh-tunnels)。
最后,应该启用[Kubelet 用户认证和/或权限认证](/docs/admin/kubelet-authentication-authorization/)来保护 kubelet API。
### apiserver -> nodes, pods, and services
从 apiserver 到 node、pod或者service 的连接默认为纯 HTTP 方式,因此既没有认证,也没有加密。他们能够通过给API URL 中的 node、pod 或 service 名称添加前缀 `https:` 来运行在安全的 HTTPS 连接上。但他们即不会认证 HTTPS endpoint 提供的证书,也不会提供客户端证书。这样虽然连接是加密的,但它不会提供任何完整性保证。这些连接**目前还不能安全的**在不可信的或公共的网络上运行。
### SSH 隧道
[Google Container Engine](https://cloud.google.com/container-engine/docs/) 使用 SSH 隧道保护 Master -> Cluster 通信路径。在这种配置下,apiserver 发起一个到集群中每个节点的 SSH 隧道(连接到在 22 端口监听的 ssh 服务)并通过这个隧道传输所有到 kubelet、node、pod 或者 service 的流量。这个隧道保证流量不会在集群运行的私有 GCE 网络之外暴露。
+234
View File
@@ -0,0 +1,234 @@
---
assignees:
- caesarxuchao
- dchen1107
title: Nodes
redirect_from:
- "/docs/admin/node/"
- "/docs/admin/node.html"
- "/docs/concepts/nodes/node/"
- "/docs/concepts/nodes/node.html"
---
* TOC
{:toc}
## Node 是什么?
`Node` 是 Kubernetes 的工作节点,以前叫做 `minion`。取决于你的集群,Node 可以是一个虚拟机或者物理机器。每个 node 都有用于运行 [pods](/docs/user-guide/pods) 的必要服务,并由 master 组件管理。Node 上的服务包括 Docker、kubelet 和 kube-proxy。请查阅架构设计文档中 [The Kubernetes Node](https://git.k8s.io/community/contributors/design-proposals/architecture/architecture.md#the-kubernetes-node) 一节获取更多细节。
## Node 状态
一个 node 的状态包含以下信息:
* [地址](#地址)
* ~~[阶段](#阶段)~~ **已废弃**
* [条件](#条件)
* [容量](#容量)
* [信息](#信息)
下面对每个章节进行详细描述。
### 地址
这些字段组合的用法取决于你的云服务商或者裸金属配置。
* HostNameHostName 和 node 内核报告的相同。可以通过 kubelet 的 `--hostname-override` 参数覆盖。
* ExternalIP:通常是可以外部路由的 node IP 地址(从集群外可访问)。
* InternalIP:通常是仅可在集群内部路由的 node IP 地址。
### 阶段
一废弃:node 阶段已经不再使用。
### 条件
`conditions` 字段描述了所有 `Running` nodes 的状态。
| Node 条件 | 描述 |
| ---------------- | ---------------------------------------- |
| `OutOfDisk` | `True` 表示 node 的空闲空间不足以用于添加新 pods, 否则为 `False` |
| `Ready` | `True` 表示 node 是健康的并已经准备好接受 pods;`False` 表示 node 不健康而且不能接受 pods;`Unknown` 表示 node 控制器在最近 40 秒内没有收到 node 的消息 |
| `MemoryPressure` | `True` 表示 node 不存在内存压力 -- 即 node 内存用量低, 否则为 `False` |
| `DiskPressure` | `True` 表示 node 不存在磁盘压力 -- 即磁盘用量低, 否则为 `False` |
Node 条件使用一个 JSON 对象表示。例如,下面的响应描述了一个健康的 node。
```json
"conditions": [
{
"kind": "Ready",
"status": "True"
}
]
```
如果 Ready 条件处于状态 "Unknown" 或者 "False" 的时间超过了 `pod-eviction-timeout`(一个传递给 [kube-controller-manager](/docs/admin/kube-controller-manager/) 的参数),node 上的所有 Pods 都会被 Node 控制器计划删除。默认的删除超时时长为**5分钟**。某些情况下,当 node 不可访问时,apiserver 不能和其上的 kubelet 通信。删除 pods 的决定不能传达给 kubelet,直到它重新建立和 apiserver 的连接为止。与此同时,被计划删除的 pods 可能会继续在分区 node 上运行。
在 1.5 版本之前的 Kubernetes 里,node 控制器会将不能访问的 pods 从 apiserver 中[强制删除](/docs/concepts/workloads/pods/pod/#force-deletion-of-pods)。但在 1.5 或更高的版本里,在node 控制器确认这些 pods 已经在集群里停运行前不会强制删除它们。你可以看到这些处于 "Terminating" 或者 "Unknown" 状态的 pods 可能在无法访问的 node 上运行。为了防止 kubernetes 不能从底层基础设施中推断出一个 node 是否已经永久的离开了集群,集群管理员可能需要手动删除这个 node 对象。从 Kubernetes 删除 node 对象将导致 apiserver 删除 node 上所有运行的 Pod 对象并释放它们的名字。
### 容量
描述 node 上的可用资源:CPU、内存和可以调度到 node 上的 pods 的最大数量。
### 信息
关于 node 的通用信息,例如内核版本、Kubernetes 版本(kubelet 和 kube-proxy 版本)、Docker 版本 (如果使用了)和 OS 名。这些信息由 Kubelet 从 node 搜集而来。
## 管理
与 [pods](/docs/user-guide/pods) 和 [services](/docs/user-guide/services) 不同,node 并不是在 Kubernetes 内部创建的:它是被外部的云服务商创建,例如 Google Compute Engine 或者你的集群中的物理或者虚拟机。这意味着当 Kubernetes 创建一个 node 时,它其实仅仅创建了一个对象来代表这个 node。创建以后,Kubernetes 将检查这个 node 是否可用。例如,如果你尝试使用如下内容创建一个 node:
```json
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
```
Kubernetes 会在内部创一个 node 对象(象征 node),并基于 `metadata.name` 字段(我们假设 `metadata.name` 能够被解析)通过健康检查来验证 node。如果 node 可用,意即所有必要服务都已运行,它就符合了运行一个 pod 的条件;否则它将被所有的集群动作忽略指导变为可用。请注意,Kubernetes 将保存不可用 node 的对象,除非它被客户端显式的删除。Kubernetes 将持续检查 node 是否变的可用。
当前,有3个组件同 Kubernetes node 接口交互:node 控制器、kubelet 和 kubectl。
### Node 控制器
Node 控制器是一个 Kubernetes master 组件,管理 nodes 的方方面面。
Node 控制器在 node 的生命周期中扮演了多个角色。第一个是当 node 注册时为它分配一个 CIDR block(如果打开了 CIDR 分配)。
第二个是使用云服务商提供了可用节点列表保持 node 控制器内部的 nodes 列表更新。如果在云环境下运行,任何时候当一个 node 不健康时 node 控制器将询问云服务 node 的虚拟机是否可用。如果不可用,node 控制器会将这个 node 从它的 nodes 列表删除。
第三个是监控 nodes 的健康情况。Node 控制器负责在 node 不能访问时(也即是 node 控制器因为某些原因没有收到心跳,例如 node 宕机)将它的 NodeStatus 的 NodeReady 状态更新为 ConditionUnknown。后续如果 node 持续不可访问,Node 控制器将删除 node 上的所有 pods(使用优雅终止)。(默认情况下 40s 开始报告 ConditionUnknown,在那之后 5m 开始删除 pods。)Node 控制器每隔 `--node-monitor-period` 秒检查每个 node 的状态。
在 Kubernetes 1.4 中我们更新了 node 控制器逻辑以更好的处理大批量 nodes 访问 master 出问题的情况(例如 master 的网络出了问题)。从 1.4 开始,node 控制器在决定删除 pod 之前会检查集群中所有 nodes 的状态。
大部分情况下, node 控制器把删除频率限制在每秒 `--node-eviction-rate` 个(默认为 0.1)。这表示它在 10 秒钟内不会从超过一个 node 上删除 pods。
当一个 availability zone 中的 node 变为不健康时,它的删除行为将发生改变。Node 控制器会同时检查 zone 中不健康(NodeReady 状态为 ConditionUnknown 或 ConditionFalse)的 nodes 的百分比。如果不健康 nodes 的部分超过 `--unhealthy-zone-threshold` (默认为 0.55),删除速率将会减小:如果集群较小(意即小于等于 `--large-cluster-size-threshold` 个 nodes - 默认为50),删除将会停止,否则删除速率将降为每秒 `--secondary-node-eviction-rate` 个(默认为 0.01)。在单个 availability zone 实施这些策略的原因是当一个 availability zone 可能从 master 分区时其它的仍然保持连接。如果你的集群没有跨越云服务商的多个 availability zones,那就只有一个 availability zone(整个集群)。
在多个 availability zones 分布你的 nodes 的一个关键原因是当整个 zone 故障时,工作负载可以转移到健康的 zones。因此,如果一个 zone 中的所有 nodes 都不健康时,node 控制器会以正常的速率 `--node-eviction-rate` 删除。在所有的 zones 都不健康(也即集群中没有健康 node)的极端情况下,node 控制器将假设 master 的连接出了某些问题,它将停止所有删除动作直到一些连接恢复。
从 Kubernetes 1.6 开始,NodeController 还负责删除运行在拥有 `NoExecute` taints 的 nodes 上的 pods,如果这些 pods 没有 tolerate 这些 taints。此外,作为一个默认禁用的 alpha 特性,NodeController 还负责根据 node 故障(例如 node 不可访问或没有 ready)添加 taints。请查看 [这个文档](/docs/concepts/configuration/assign-pod-node/#taints-and-tolerations-beta-feature)了解关于 `NoExecute` taints 和这个 alpha 特性。
### Nodes 自注册
当 kubelet 标志 `--register-node` 为 true (默认)时,它会尝试向 API 服务注册自己。这是首选模式,被绝大多数发行版选用。
对于自注册模式,kubelet 使用下列参数启动:
- `--api-servers` - apiservers 地址。
- `--kubeconfig` - 用于向 apiserver 验证自己的凭据路径。
- `--cloud-provider` - 如何从云服务商读取关于自己的元数据。
- `--register-node` - 自动向 API 服务注册。
- `--register-with-taints` - 使用 taints 列表(逗号分隔的 `<key>=<value>:<effect>`)注册 node。当 `register-node` 为 false 时无效。
- `--node-ip` - node IP 地址。
- `--node-labels` - 向集群注册时给 node 添加的 labels。
- `--node-status-update-frequency` - 指定 kubelet 向 master 发送状态的频率。
目前,任何 kubelet 都被授权可以创建/修改任意 node 资源,但通常只对自己的进行创建/修改。(未来我们计划只允许一个 kubelet 修改它自己 node 的资源。)
#### 手动 Node 管理
集群管理员可以创建及修改 node 对象。
如果管理员希望手动创建 node 对象,请设置 kubelet 标记 `--register-node=false`
管理员可以修改 node 资源(忽略 `--register-node` 设置)。修改包括在 node 上设置 labels及标记它为不可调度。
Nodes 上的 labels 可以和 pods 的 node selectors 一起使用来控制调度,例如限制一个 pod 只能在一个符合要求的 nodes 子集上运行。
标记一个 node 为不可调度的将防止新建 pods 调度到那个 node 之上,但不会影响任何已经在它之上的 pods。这是重启 node 等操作之前的一个有用的准备步骤。例如,标记一个 node 为不可调度的,执行以下命令:
```shell
kubectl cordon $NODENAME
```
请注意,被 daemonSet 控制器创建的 pods 将忽略 Kubernetes 调度器,且不会遵照 node 上不可调度的属性。这个假设基于守护程序属于节点机器,即使在准备重启而隔离应用的时候。
### Node 容量
Node 的容量(cpu 数量和内存容量)是 node 对象的一部分。通常情况下,在创建 node 对象时,它们会注册自己并报告自己的容量。如果你正在执行[手动 node 管理](#manual-node-administration),那么你需要在添加 node 时手动设置 node 容量。
Kubernetes 调度器保证一个 node 上有足够的资源供其上的所有 pods 使用。它会检查 node 上所有容器要求的总和不会超过 node 的容量。这包括所有 kubelet 启动的容器,但不包含 Docker 启动的容器和不在容器中的进程。
如果希望显式的为非 pod 进程预留资源,你可以创建一个占位 pod。使用如下模板:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-reserver
spec:
containers:
- name: sleep-forever
image: gcr.io/google_containers/pause:0.8.0
resources:
requests:
cpu: 100m
memory: 100Mi
```
设置 `cpu``memory` 值为你希望预留的资源量。将文件放在清单文件夹中(kubelet 的 `--config=DIR` 标志)。当你希望预留资源时,在每个 kubelet 上都这样执行。
## API 对象
Node 是 Kubernetes REST API 的顶级资源。更多关于 API 对象的细节可以在这里找到: [Node API
object](/docs/api-reference/{{page.version}}/#node-v1-core).``
@@ -0,0 +1,45 @@
---
title: 安装扩展(Addons
---
## 概览
Add-ons 扩展了 Kubernetes 的功能。
本文列举了一些可用的 add-ons 以及到它们各自安装说明的链接。
每个 add-ons 按字母顺序排序 - 顺序不代表任何优先地位。
## 网络和网络策略
* [Calico](http://docs.projectcalico.org/latest/getting-started/kubernetes/installation/hosted/) 是一个安全的 L3 网络和网络策略提供者。
* [Canal](https://github.com/tigera/canal/tree/master/k8s-install) 结合 Flannel 和 Calico, 提供网络和网络策略。
* [Cilium](https://github.com/cilium/cilium) 是一个 L3 网络和网络策略插件, 能够透明的实施 HTTP/API/L7 策略。 同时支持路由(routing)和叠加/封装( overlay/encapsulation)模式。
* [Contiv](http://contiv.github.io) 为多种用例提供可配置网络(使用 BGP 的原生 L3,使用 vxlan 的 overlay,经典 L2 和 Cisco-SDN/ACI)和丰富的策略框架。Contiv 项目完全[开源](http://github.com/contiv)。[安装工具](http://github.com/contiv/install)同时提供基于和不基于 kubeadm 的安装选项。
* [Flannel](https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel.yml) 是一个可以用于 Kubernetes 的 overlay 网络提供者。
* [Romana](http://romana.io) 是一个 pod 网络的层 3 解决方案,并且支持 [NetworkPolicy API](/docs/concepts/services-networking/network-policies/)。Kubeadm add-on 安装细节可以在[这里](https://github.com/romana/romana/tree/master/containerize)找到。
* [Weave Net](https://www.weave.works/docs/net/latest/kube-addon/) 提供了在网络分组两端参与工作的网络和网络策略,并且不需要额外的数据库。
* [CNI-Genie](https://github.com/Huawei-PaaS/CNI-Genie) 使 Kubernetes 无缝连接到一种 CNI 插件,例如:Flannel、Calico、Canal、Romana 或者 Weave。
## 可视化管理
* [Dashboard](https://github.com/kubernetes/dashboard#kubernetes-dashboard) 是一个 Kubernetes 的 web 控制台界面。
* [Weave Scope](https://www.weave.works/documentation/scope-latest-installing/#k8s) 是一个图形化工具,用于查看你的 containers、 pods、services等。 请和一个 [Weave Cloud account](https://cloud.weave.works/) 一起使用,或者自己运行 UI。
## 遗留 Add-ons
还有一些其它 add-ons 归档在已废弃的 [cluster/addons](https://git.k8s.io/kubernetes/cluster/addons) 路径中。
维护完善的 add-ons 应该被链接到这里。欢迎提出 PRs!
@@ -0,0 +1,86 @@
---
approvers:
- davidopp
- lavalamp
title: 集群管理概述
---
{% capture overview %}
集群管理概述面向任何创建和管理 Kubernetes 集群的读者人群。我们假设你对 [用户指南](/docs/user-guide/)中的概念有一些熟悉。
{% endcapture %}
{% capture body %}
## 规划集群
查阅 [选择正确解决方案](/docs/setup/pick-right-solution/) 中的指导,获取如何规划、建立以及配置 Kubernetes 集群的示例。本文所列的文章称为*发行版*。
在选择一个指南前,有一些因素需要考虑:
- 你是打算在你的电脑上尝试 Kubernetes,还是要构建一个高可用的多节点集群?请选择最适合你需求的发行版。
- **如果你正在设计一个高可用集群**,请了解[在多个 zones 中配置集群](/docs/admin/multi-cluster)。
- 你的集群是在**本地**还是**云(IaaS**上?Kubernetes 不能直接支持混合集群。作为代替,你可以建立多个集群。
- **如果你在本地配置 Kubernetes**,需要考虑哪种[网络模型](/docs/admin/networking)最适合。一种自定义网络的选项是 [*OpenVSwitch GRE/VxLAN 网络*](/docs/admin/ovs-networking/),它使用 OpenVSwitch 在跨 Kubernetes 节点的 pods 之间建立起网络。
- 你的 Kubernetes 在 **裸金属硬件** 还是 **虚拟机(VMs)**上运行?
- 你**只想运行一个集群**,还是打算**活动开发 Kubernetes 项目代码**?如果是后者,请选择一个活动开发的发行版。某些发行版只提供二进制发布版,但提供更多的选择。
- 让你自己熟悉运行一个集群所需的[组件](/docs/admin/cluster-components) 。
请注意:不是所有的发行版都被积极维护着。请选择测试过最近版本的 Kubernetes 的发行版。
如果你正在使用和 Salt 有关的指南,请查阅 [使用 Salt 配置 Kubernetes](/docs/admin/salt)。
## 管理集群
[管理集群](/docs/concepts/cluster-administration/cluster-management/)叙述了和集群生命周期相关的几个主题:创建一个新集群、升级集群的 master 和 worker 节点、执行节点维护(例如内核升级)以及升级活动集群的 Kubernetes API 版本。
## 保护集群
* [Kubernetes 容器环境](/docs/concepts/containers/container-environment-variables/) 描述了 Kubernetes 节点上由 Kubelet 管理的容器的环境。
* [控制到 Kubernetes API 的访问](/docs/admin/accessing-the-api) 描述了如何为用户和 service accounts 建立权限许可.
* [用户认证](/docs/admin/authentication) 阐述了 Kubernetes 中的认证功能,包括许多认证选项。
* [授权](/docs/admin/authorization)从认证中分离出来,用于控制如何处理 HTTP 请求。
* [使用 Admission Controllers](/docs/admin/admission-controllers) 阐述了在认证和授权之后拦截到 Kubernetes API 服务的请求的插件。
* [在 Kubernetes Cluster 中使用 Sysctls](/docs/concepts/cluster-administration/sysctl-cluster/) 描述了管理员如何使用 `sysctl` 命令行工具来设置内核参数。
* [审计](/docs/tasks/debug-application-cluster/audit/) 描述了如何与 Kubernetes 的审计日志交互。
### 保护 kubelet
* [Master 节点通信](/docs/concepts/cluster-administration/master-node-communication/)
* [TLS 引导](/docs/admin/kubelet-tls-bootstrapping/)
* [Kubelet 认证/授权](/docs/admin/kubelet-authentication-authorization/)
## 可选集群服务
* [DNS 与 SkyDNS 集成](/docs/concepts/services-networking/dns-pod-service/)描述了如何将一个 DNS 名解析到一个Kubernetes service。
* [记录和监控集群活动](/docs/concepts/cluster-administration/logging/) 阐述了Kubernetes 的日志如何工作以及怎样实现。
{% endcapture %}
{% include templates/concept.md %}
@@ -3,8 +3,8 @@ title: 同 Pod 内的容器使用共享卷通信
redirect_from:
- "/docs/user-guide/pods/multi-container/"
- "/docs/user-guide/pods/multi-container.html"
- "docs/tasks/configure-pod-container/communicate-containers-same-pod/"
- "docs/tasks/configure-pod-container/communicate-containers-same-pod.html"
- "/docs/tasks/configure-pod-container/communicate-containers-same-pod/"
- "/docs/tasks/configure-pod-container/communicate-containers-same-pod.html"
---
@@ -12,7 +12,7 @@ redirect_from:
本文旨在说明如何使用一个卷(Volume让一个 Pod 内的两个容器进行通信
本文旨在说明如何让一个 Pod 内的两个容器使用一个卷(Volume进行通信
{% endcapture %}
@@ -27,7 +27,7 @@ redirect_from:
{% capture steps %}
## 创建一个两个容器的 Pod
## 创建一个包含两个容器的 Pod
@@ -46,7 +46,7 @@ Pod 的配置文件如下:
配置文件中的第一个容器运行了一个 nginx 服务器。共享卷的挂载路径是 `/usr/share/nginx/html`
第二个容器是基于 debian 镜像的,有一个挂载路径是 `/pod-data`。第二个容器运行了下面的命令然后终止。
第二个容器是基于 debian 镜像的,有一个 `/pod-data` 的挂载路径。第二个容器运行了下面的命令然后终止。
echo Hello from the debian container > /pod-data/index.html
@@ -126,7 +126,7 @@ Pod 的配置文件如下:
root@two-containers:/# curl localhost
输出显示了 nginx 提供了 debian 容器写的页面:
输出表示 nginx 提供了 debian 容器写的页面:
Hello from the debian container
@@ -145,9 +145,10 @@ Pod 的配置文件如下:
Pod 能有多个容器的主要原因是为了支持协助主应用的辅助应用。辅助应用的典型例子是数据抽取,数据推送和代理
辅助应用和主应用经常需要相互通信。通常这是通过共享文件系统完成的,就如这个练习所示,或者通过回环网络接口
localhost 完成。网络接口的例子是 web 服务器带有一个协助程序用于拉取 Git 仓库的更新
Pod 能有多个容器的主要原因是为了支持辅助应用(helper applications),以协助主应用(primary application
辅助应用的典型例子是数据抽取,数据推送和代理。辅助应用和主应用经常需要相互通信。
就如这个练习所示,通信通常是通过共享文件系统完成的,或者,也通过回环网络接口 localhost 完成
举个网络接口的例子,web 服务器带有一个协助程序用于拉取 Git 仓库的更新。
@@ -167,17 +168,17 @@ localhost 完成。网络接口的例子是 web 服务器带有一个协助程
* 学习[模块化架构的混合容器](http://www.slideshare.net/Docker/slideshare-burns)。
* 学习 [模块化架构的混合容器](http://www.slideshare.net/Docker/slideshare-burns)。
* 参见[配置一个使用存储卷的 Pod](/cn/docs/tasks/configure-pod-container/configure-volume-storage/)。
* 参见 [配置一个使用存储卷的 Pod](/docs/tasks/configure-pod-container/configure-volume-storage/)。
* 参见 [](/cn/docs/api-reference/v1.6/#volume-v1-core)。
* 参见 [](/docs/api-reference/v1.6/#volume-v1-core)。
* 参见 [Pod](/cn/docs/api-reference/v1.6/#pod-v1-core).
* 参见 [Pod](/docs/api-reference/v1.6/#pod-v1-core).
{% endcapture %}
@@ -8,8 +8,8 @@ title: 使用 Service 把前端连接到后端
这项任务会描述如何创建一个前端和一个后端微服务。后端微服务是一个 hello 欢迎程序。
前端和后端的连接是通过 Kubernetes Service 对象完成的。
任务会描述如何创建前端微服务和后端微服务。后端微服务是一个 hello 欢迎程序。
前端和后端的连接是通过 Kubernetes 服务对象(Service object完成的。
{% endcapture %}
@@ -19,9 +19,9 @@ title: 使用 Service 把前端连接到后端
* 使用 Deployment 对象创建并运行一个微服务
* 使用部署对象(Deployment object创建并运行一个微服务
* 从后端将流量路由到前端
* 使用 Service 对象把前端应用连接到后端应用
* 使用服务对象把前端应用连接到后端应用
{% endcapture %}
@@ -31,9 +31,9 @@ title: 使用 Service 把前端连接到后端
* {% include task-tutorial-prereqs.md %}
*任务使用[外部负载均衡服务](/cn/docs/tasks/access-application-cluster/create-external-load-balancer/)
所以需要对应的可支持此功能的环境。如果你的环境不能支持,你可以使用[NodePort](/cn/docs/user-guide/services/#type-nodeport)
的类型 Service 来代替。
* 本任务使用 [外部负载均衡服务](/docs/tasks/access-application-cluster/create-external-load-balancer/)
所以需要对应的可支持此功能的环境。如果你的环境不能支持,你可以使用
[NodePort](/docs/user-guide/services/#type-nodeport) 类型的服务代替。
{% endcapture %}
@@ -41,7 +41,7 @@ title: 使用 Service 把前端连接到后端
{% capture lessoncontent %}
### 使用 Deployment 创建后端
### 使用部署对象(Deployment创建后端
@@ -85,14 +85,14 @@ Events:
```
### 创建后端 Service 对象
### 创建后端服务对象(Service object
前端连接到后端的关键是 Service。Service 创建一个固定 IP 和 DNS 解析名入口,
使得后端微服务可达。Service 使用 selector 标签来寻找目的地 Pods
使得后端微服务可达。Service 使用 selector 标签来寻找目 Pod。
首先,浏览 Service 的配置文件:
@@ -101,7 +101,7 @@ Events:
配置文件中,你可以看到 Service 将流量路由到包含 `app: hello``tier: backend` 标签的 Pods
配置文件中,你可以看到 Service 将流量路由到包含 `app: hello``tier: backend` 标签的 Pod。
创建 `hello` Service
@@ -147,7 +147,7 @@ kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/frontend.
```
输出确认两个资源都已经被创建:
通过输出确认两个资源都已经被创建:
```
deployment "frontend" created
@@ -159,8 +159,8 @@ service "frontend" created
**注意**:这个 nginx 配置文件是被打包在[容器镜像](/cn/docs/tasks/access-application-cluster/frontend/Dockerfile)里的。
更好的方法是使用 [ConfigMap](/cn/docs/tasks/configure-pod-container/configmap/),这样的话你可以更轻易地更改配置。
**注意**:这个 nginx 配置文件是被打包在 [容器镜像](/docs/tasks/access-application-cluster/frontend/Dockerfile) 里的。
更好的方法是使用 [ConfigMap](/docs/tasks/configure-pod-container/configmap/),这样的话你可以更轻易地更改配置。
### 与前端 Service 交互
@@ -175,7 +175,7 @@ kubectl get service frontend
外部 IP 字段的生成可能需要一些时间。如果是这种情况,外部 IP 会显示为 `<pending>`
外部 IP 字段的生成可能需要一些时间。如果是这种情况,外部 IP 会显示为 `<pending>`
```
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
@@ -215,8 +215,8 @@ curl http://<EXTERNAL-IP>
* 了解更多 [Services](/cn/docs/concepts/services-networking/service/)
* 了解更多 [ConfigMaps](/cn/docs/tasks/configure-pod-container/configmap/)
* 了解更多 [Services](/docs/concepts/services-networking/service/)
* 了解更多 [ConfigMaps](/docs/tasks/configure-pod-container/configmap/)
{% endcapture %}
@@ -0,0 +1,110 @@
---
title: 访问集群上运行的服务
redirect_from:
- "/docs/user-guide/accessing-the-cluster/"
- "/docs/user-guide/accessing-the-cluster.html"
---
{% capture overview %}
本文展示了如何连接 Kubernetes 集群上运行的服务。
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 访问集群上运行的服务
在 Kubernetes 里, [nodes](/docs/admin/node)、[pods](/docs/user-guide/pods) 和 [services](/docs/user-guide/services) 都有它们自己的 IP。许多情况下,集群上的 node IP、pod IP 和某些 service IP 路由不可达,所以不能从一个集群之外的节点访问它们,例如从你自己的台式机。
### 连接方式
你有多种从集群外连接 nodes、pods 和 services 的选项:
- 通过公共 IP 访问 services。
- 使用具有 `NodePort``LoadBalancer` 类型的 service,可以从外部访问它们。请查阅 [services](/docs/user-guide/services) 和 [kubectl expose](/docs/user-guide/kubectl/v1.6/#expose) 文档。
- 取决于你的集群环境,你可以仅把 service 暴露在你的企业网络环境中,也可以将其暴露在因特网上。需要考虑暴露的 service 是否安全,它是否有自己的用户认证?
- 将 pods 放置于 services 背后。如果要访问一个副本集合中特定的 pod,例如用于调试目的时,请给 pod 指定一个独特的标签并创建一个新 service 选择这个标签。
- 大部分情况下,都不需要应用开发者通过节点 IP 直接访问 nodes。
- 通过 Proxy Verb 访问 services、nodes 或者 pods。
- 在访问 Apiserver 远程服务之前是否经过认证和授权?如果你的服务暴露到因特网中不够安全,或者需要获取 node IP 之上的端口,又或者处于调试目的时,请使用这个特性。
- Proxies 可能给某些应用带来麻烦。
- 仅适用于 HTTP/HTTPS。
- 在[这里](#manually-constructing-apiserver-proxy-urls)描述
- 从集群中的 node 或者 pod 访问。
- 运行一个 pod,然后使用 [kubectl exec](/docs/user-guide/kubectl/v1.6/#exec) 连接到它的一个shell。从那个 shell 连接其他的 nodes、pods 和 services。
- 某些集群可能允许你 ssh 到集群中的节点。你可能可以从那儿访问集群服务。这是一个非标准的方式,可能在一些集群上能工作,但在另一些上却不能。浏览器和其他工具可能安装或可能不会安装。集群 DNS 可能不会正常工作。
### 发现内置服务
典型情况下,kube-system 会启动集群中的几个服务。使用 `kubectl cluster-info` 命令获取它们的列表:
```shell
$ kubectl cluster-info
Kubernetes master is running at https://104.197.5.247
elasticsearch-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy
kibana-logging is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kibana-logging/proxy
kube-dns is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/kube-dns/proxy
grafana is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
heapster is running at https://104.197.5.247/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy
```
这显示了用于访问每个服务的 proxy-verb URL。例如,这个集群启用了(使用 Elasticsearch)集群层面的日志,如果提供合适的凭据可以通过 `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/` 访问,或通过一个 kubectl 代理地址访问,如:`http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/`。(请查看 [上文](#accessing-the-cluster-api) 关于如何传递凭据或者使用 kubectl 代理的说明。)
#### 手动构建 apiserver 代理 URLs
如同上面所提到的,你可以使用 `kubectl cluster-info` 命令取得 service 的代理 URL。为了创建包含 service endpoints、suffixes 和 parameters 的代理 URLs,你可以简单的在 service 的代理 URL中 添加:
`http://`*`kubernetes_master_address`*`/api/v1/namespaces/`*`namespace_name`*`/services/`*`service_name[:port_name]`*`/proxy`
如果还没有为你的端口指定名称,你可以不用在 URL 中指定 *port_name*
##### 示例
* 你可以通过 `http://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy` 访问 Elasticsearch service endpoint `_search?q=user:kimchy`
* 你可以通过 `https://104.197.5.247/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true` 访问 Elasticsearch 集群健康信息 endpoint `_cluster/health?pretty=true`
```json
{
"cluster_name" : "kubernetes_logging",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 1,
"number_of_data_nodes" : 1,
"active_primary_shards" : 5,
"active_shards" : 5,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 5
}
```
#### 通过 web 浏览器访问集群中运行的服务
你或许能够将 apiserver 代理的 url 放入浏览器的地址栏,然而:
- Web 服务器不总是能够传递令牌,所以你可能需要使用基本(密码)认证。 Apiserver 可以配置为接受基本认证,但你的集群可能并没有这样配置。
- 某些 web 应用可能不能工作,特别是那些使用客户端侧 javascript 的应用,它们构造 url 的方式可能不能理解代理路径前缀。
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,411 @@
---
assignees:
- derekwaynecarr
- janetkuo
title: 应用资源配额和限额
redirect_from:
- "/docs/admin/resourcequota/walkthrough/"
- "/docs/admin/resourcequota/walkthrough.html"
- "/docs/tasks/configure-pod-container/apply-resource-quota-limit/"
- "/docs/tasks/configure-pod-container/apply-resource-quota-limit.html"
---
{% capture overview %}
本示例展示了在一个 namespace 中控制资源用量的典型设置。
本文展示了以下资源的使用: [Namespace](/docs/admin/namespaces), [ResourceQuota](/docs/concepts/policy/resource-quotas/) 和 [LimitRange](/docs/tasks/configure-pod-container/limit-range/)。
{% endcapture %}
{% capture prerequisites %}
* {% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 场景
集群管理员正在操作一个代表用户群体的集群,他希望控制一个特定 namespace 中可以被使用的资源总量,以达到促进对集群的公平共享及控制成本的目的。
集群管理员有以下目标:
* 限制运行中 pods 使用的计算资源数量
* 限制 persistent volume claims 数量以控制对存储的访问
* 限制 load balancers 数量以控制成本
* 防止使用 node ports 以保留稀缺资源
* 提供默认计算资源请求以实现更好的调度决策
## 创建 namespace
本示例将在一个自定义的 namespace 中运行,以展示相关概念。
让我们创建一个叫做 quota-example 的新 namespace
```shell
$ kubectl create namespace quota-example
namespace "quota-example" created
$ kubectl get namespaces
NAME STATUS AGE
default Active 2m
kube-system Active 2m
quota-example Active 39s
```
## 应用 object-count 配额到 namespace
集群管理员想要控制下列资源:
* persistent volume claims
* load balancers
* node ports
我们来创建一个简单的配额,用于控制这个 namespace 中那些资源类型的对象数量。
```shell
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-object-counts.yaml --namespace=quota-example
resourcequota "object-counts" created
```
配额系统将察觉到有一个配额被创建,并且会计算 namespace 中的资源消耗量作为响应。这应该会很快发生。
让我们显示一下配额来观察这个 namespace 中当前被消耗的资源:
```shell
$ kubectl describe quota object-counts --namespace=quota-example
Name: object-counts
Namespace: quota-example
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 2
services.loadbalancers 0 2
services.nodeports 0 0
```
配额系统现在将阻止用户创建比各个资源指定数量更多的资源。
## 应用计算资源配额到 namespace
为了限制这个 namespace 可以被使用的计算资源数量,让我们创建一个跟踪计算资源的配额。
```shell
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-compute-resources.yaml --namespace=quota-example
resourcequota "compute-resources" created
```
让我们显示一下配额来观察这个 namespace 中当前被消耗的资源:
```shell
$ kubectl describe quota compute-resources --namespace=quota-example
Name: compute-resources
Namespace: quota-example
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
pods 0 4
requests.cpu 0 1
requests.memory 0 1Gi
```
配额系统现在会防止 namespace 拥有超过 4 个没有终止的 pods。此外它还将强制 pod 中的每个容器配置一个 `request` 并为 `cpu``memory` 定义 `limit`
## 应用默认资源请求和限制
Pod 的作者很少为它们的 pods 指定资源请求和限制。
既然我们对项目应用了配额,我们来看一下当终端用户通过创建一个没有 cpu 和 内存限制的 pod 时会发生什么。这通过在 pod 里创建一个 nginx 容器实现。
作为演示,让我们来创建一个运行 nginx 的 deployment
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
deployment "nginx" created
```
现在我们来看一下创建的 pods。
```shell
$ kubectl get pods --namespace=quota-example
```
发生了什么?我一个 pods 都没有!让我们 describe 这个 deployment 来看看发生了什么。
```shell
$ kubectl describe deployment nginx --namespace=quota-example
Name: nginx
Namespace: quota-example
CreationTimestamp: Mon, 06 Jun 2016 16:11:37 -0400
Labels: run=nginx
Selector: run=nginx
Replicas: 0 updated | 1 total | 0 available | 1 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: <none>
NewReplicaSet: nginx-3137573019 (0/1 replicas created)
...
```
Deployment 创建了一个对应的 replica set 并尝试按照大小来创建一个 pod。
让我们看看 replica set 的更多细节。
```shell
$ kubectl describe rs nginx-3137573019 --namespace=quota-example
Name: nginx-3137573019
Namespace: quota-example
Image(s): nginx
Selector: pod-template-hash=3137573019,run=nginx
Labels: pod-template-hash=3137573019
run=nginx
Replicas: 0 current / 1 desired
Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed
No volumes.
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
4m 7s 11 {replicaset-controller } Warning FailedCreate Error creating: pods "nginx-3137573019-" is forbidden: Failed quota: compute-resources: must specify limits.cpu,limits.memory,requests.cpu,requests.memory
```
Kubernetes API server 拒绝了 replica set 创建一个 pod 的请求,因为我们的 pods 没有为 `cpu``memory` 指定 `requests``limits`
因此,我们来为 pod 指定它可以使用的 `cpu``memory` 默认数量。
```shell
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-limits.yaml --namespace=quota-example
limitrange "limits" created
$ kubectl describe limits limits --namespace=quota-example
Name: limits
Namespace: quota-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Container memory - - 256Mi 512Mi -
Container cpu - - 100m 200m -
```
如果 Kubernetes API server 发现一个 namespace 中有一个创建 pod 的请求,并且 pod 中的容器没有设置任何计算资源请求时,作为准入控制的一部分,一个默认的 request 和 limit 将会被应用。
在本例中,创建的每个 pod 都将拥有如下的计算资源限制:
```shell
$ kubectl run nginx \
--image=nginx \
--replicas=1 \
--requests=cpu=100m,memory=256Mi \
--limits=cpu=200m,memory=512Mi \
--namespace=quota-example
```
由于已经为我们的 namespace 申请了默认的计算资源,我们的 replica set 应该能够创建它的 pods 了。
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
nginx-3137573019-fvrig 1/1 Running 0 6m
```
而且如果打印出我们在这个 namespace 中的配额使用情况:
```shell
$ kubectl describe quota --namespace=quota-example
Name: compute-resources
Namespace: quota-example
Resource Used Hard
-------- ---- ----
limits.cpu 200m 2
limits.memory 512Mi 2Gi
pods 1 4
requests.cpu 100m 1
requests.memory 256Mi 1Gi
Name: object-counts
Namespace: quota-example
Resource Used Hard
-------- ---- ----
persistentvolumeclaims 0 2
services.loadbalancers 0 2
services.nodeports 0 0
```
就像你看到的,创建的 pod 消耗了明确的计算资源量,并且正被 Kubernetes 正确的追踪着。
## 高级配额 scopes
让我们想象一下如果你不希望为你的 namespace 指定默认计算资源使用量。
作为替换,你希望用户在它们的 namespace 中运行指定数量的 `BestEffort` pods,以从宽松的计算资源中获得好处。然后要求用户为需要更高质量服务的 pods 配置一个显式的资源请求。
让我们新建一个拥有两个配额的 namespace 来演示这种行为:
```shell
$ kubectl create namespace quota-scopes
namespace "quota-scopes" created
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-best-effort.yaml --namespace=quota-scopes
resourcequota "best-effort" created
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-not-best-effort.yaml --namespace=quota-scopes
resourcequota "not-best-effort" created
$ kubectl describe quota --namespace=quota-scopes
Name: best-effort
Namespace: quota-scopes
Scopes: BestEffort
* Matches all pods that have best effort quality of service.
Resource Used Hard
-------- ---- ----
pods 0 10
Name: not-best-effort
Namespace: quota-scopes
Scopes: NotBestEffort
* Matches all pods that do not have best effort quality of service.
Resource Used Hard
-------- ---- ----
limits.cpu 0 2
limits.memory 0 2Gi
pods 0 4
requests.cpu 0 1
requests.memory 0 1Gi
```
在这种场景下,一个没有配置计算资源请求的 pod 将会被 `best-effort` 配额跟踪。
而配置了计算资源请求的则会被 `not-best-effort` 配额追踪。
让我们创建两个 deployments 作为演示:
```shell
$ kubectl run best-effort-nginx --image=nginx --replicas=8 --namespace=quota-scopes
deployment "best-effort-nginx" created
$ kubectl run not-best-effort-nginx \
--image=nginx \
--replicas=2 \
--requests=cpu=100m,memory=256Mi \
--limits=cpu=200m,memory=512Mi \
--namespace=quota-scopes
deployment "not-best-effort-nginx" created
```
虽然没有指定默认的 limits`best-effort-nginx` deployment 还是会创建 8 个 pods。这是由于它被 `best-effort` 配额追踪,而 `not-best-effort` 配额将忽略它。`not-best-effort` 配额将追踪 `not-best-effort-nginx` deployment,因为它创建的 pods 具有 `Burstable` 服务质量。
让我们列出 namespace 中的 pods
```shell
$ kubectl get pods --namespace=quota-scopes
NAME READY STATUS RESTARTS AGE
best-effort-nginx-3488455095-2qb41 1/1 Running 0 51s
best-effort-nginx-3488455095-3go7n 1/1 Running 0 51s
best-effort-nginx-3488455095-9o2xg 1/1 Running 0 51s
best-effort-nginx-3488455095-eyg40 1/1 Running 0 51s
best-effort-nginx-3488455095-gcs3v 1/1 Running 0 51s
best-effort-nginx-3488455095-rq8p1 1/1 Running 0 51s
best-effort-nginx-3488455095-udhhd 1/1 Running 0 51s
best-effort-nginx-3488455095-zmk12 1/1 Running 0 51s
not-best-effort-nginx-2204666826-7sl61 1/1 Running 0 23s
not-best-effort-nginx-2204666826-ke746 1/1 Running 0 23s
```
如你看到的,所有 10 个 pods 都已经被准许创建。
让我们 describe 这个 namespace 当前的配额使用情况:
```shell
$ kubectl describe quota --namespace=quota-scopes
Name: best-effort
Namespace: quota-scopes
Scopes: BestEffort
* Matches all pods that have best effort quality of service.
Resource Used Hard
-------- ---- ----
pods 8 10
Name: not-best-effort
Namespace: quota-scopes
Scopes: NotBestEffort
* Matches all pods that do not have best effort quality of service.
Resource Used Hard
-------- ---- ----
limits.cpu 400m 2
limits.memory 1Gi 2Gi
pods 2 4
requests.cpu 200m 1
requests.memory 512Mi 1Gi
```
如你看到的,`best-effort` 配额追踪了我们在 `best-effort-nginx` deployment 中创建的 8 个 pods 的资源用量,而 `not-best-effort` 配额追踪了我们在 `not-best-effort-nginx` deployment 中创的两个 pods 的用量。
Scopes 提供了一种来对任何配额文档追踪的资源集合进行细分的机制,给操作人员部署和追踪资源消耗带来更大的灵活性。
`BestEffort``NotBestEffort` scopes 之外,还有用于限制长时间运行和有时限 pods 的scopes。`Terminating` scope 将匹配任何 `spec.activeDeadlineSeconds` 不为 `nil` 的 pod。`NotTerminating` scope 将匹配任何 `spec.activeDeadlineSeconds``nil` 的 pod。这些 scopes 允许你基于 pods 在你集群中 node 上的预期持久程度来为它们指定配额。
{% endcapture %}
{% capture discussion %}
## 总结
消耗节点 cpu 和 memory 资源的动作受到 namespace 配额定义的硬性配额限制的管制。
任意消耗那些资源的动作能够被调整,或者获得一个 namespace 级别的默认值以符合你最终的目标。
可以基于服务质量或者在你集群中节点上的预期持久程度来分配配额。
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,94 @@
---
title: 改变默认 StorageClass
---
{% capture overview %}
本文展示了如何改变默认的 Storage Class,它用于为没有特殊需求的 PersistentVolumeClaims 配置 volumes。
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 为什么要改变默认 storage class
取决于安装模式,您的 Kubernetes 集群可能和一个被标记为默认的已有 StorageClass 一起部署。这个默认的 StorageClass 以后将被用于动态的为没有特定 storage class 需求的 PersistentVolumeClaims 配置存储。更多细节请查看 [PersistentVolumeClaim 文档](/docs/user-guide/persistent-volumes/#class-1)。
预先安装的默认 StorageClass 可能不能很好的适应您期望的工作负载;例如,它配置的存储可能太过昂贵。如果是这样的话,您可以改变默认 StorageClass,或者完全禁用它以防止动态配置存储。
简单的删除默认 StorageClass 可能行不通,因为它可能会被您集群中的扩展管理器自动重建。请查阅您的安装文档中关于扩展管理器的细节,以及如何禁用单个扩展。
## 改变默认 StorageClass
1. 列出您集群中的 StorageClasses
kubectl get storageclass
输出类似这样:
NAME TYPE
standard (default) kubernetes.io/gce-pd
gold kubernetes.io/gce-pd
默认 StorageClass 以 `(default)` 标记。
2. 标记默认 StorageClass 非默认:
默认 StorageClass 的注解 `storageclass.kubernetes.io/is-default-class` 设置为 `true`。注解的其它任意值或者缺省值将被解释为 `false`
要标记一个 StorageClass 为非默认的,您需要改变它的值为 `false`
kubectl patch storageclass <your-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
这里的 `<your-class-name>` 是您选择的 StorageClass 的名字。
3. 标记一个 StorageClass 为默认的:
和前面的步骤类似,您需要添加/设置注解 `storageclass.kubernetes.io/is-default-class=true`
kubectl patch storageclass <your-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
请注意,最多只能有一个 StorageClass 能够被标记为默认。如果它们中有两个或多个被标记为默认,Kubernetes 将忽略这个注解,也就是它将表现为没有默认 StorageClass。
4. 验证您选用的 StorageClass 为默认的:
kubectl get storageclass
输出类似这样:
NAME TYPE
standard kubernetes.io/gce-pd
gold (default) kubernetes.io/gce-pd
{% endcapture %}
{% capture whatsnext %}
* 了解更多关于 [StorageClasses](/docs/concepts/storage/persistent-volumes/)。
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,80 @@
---
title: 更改 PersistentVolume 的回收策略
---
{% capture overview %}
本文展示了如何更改 Kubernetes PersistentVolume 的回收策略。
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 为什么要更改 PersistentVolume 的回收策略
`PersistentVolumes` 可以有多种回收策略,包括 "Retain"、"Recycle" 和 "Delete"。对于动态配置的 `PersistentVolumes` 来说,默认回收策略为 "Delete"。这表示当用户删除对应的 `PeristentVolumeClaim` 时,动态配置的 volume 将被自动删除。如果 volume 包含重要数据时,这种自动行为可能是不合适的。那种情况下,更适合使用 "Retain" 策略。使用 "Retain" 时,如果用户删除 `PersistentVolumeClaim`,对应的 `PersistentVolume` 不会被删除。相反,它将变为 `Released` 状态,表示所有的数据可以被手动恢复。
## 更改 PersistentVolume 的回收策略
1. 列出你集群中的 PersistentVolumes
kubectl get pv
输出类似于这样:
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
pvc-b6efd8da-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim1 10s
pvc-b95650f8-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim2 6s
pvc-bb3ca71d-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim3 3s
这个列表同样包含了绑定到每个 volume 的 claims 名称,以便更容易的识别动态配置的 volumes。
2. 选择你的 PersistentVolumes 中的一个并更改它的回收策略:
kubectl patch pv <your-pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
这里的 `<your-pv-name>` 是你选择的 PersistentVolume 的名字。
3. 验证你选择的 PersistentVolume 拥有正确的策略:
kubectl get pv
输出类似于这样:
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
pvc-b6efd8da-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim1 40s
pvc-b95650f8-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Delete Bound default/claim2 36s
pvc-bb3ca71d-b7b5-11e6-9d58-0ed433a7dd94 4Gi RWO Retain Bound default/claim3 33s
在前面的输出中,你可以看到绑定到 claim `default/claim3` 的 volume 拥有的回收策略为 `Retain`。当用户删除 claim `default/claim3` 时,它不会被自动删除。
{% endcapture %}
{% capture whatsnext %}
* 了解更多关于 [PersistentVolumes](/docs/concepts/storage/persistent-volumes/)的信息。
* 了解更多关于 [PersistentVolumeClaims](/docs/user-guide/persistent-volumes/#persistentvolumeclaims) 的信息。
### 参考
* [PersistentVolume](/docs/api-reference/{{page.version}}/#persistentvolume-v1-core)
* [PersistentVolumeClaim](/docs/api-reference/{{page.version}}/#persistentvolumeclaim-v1-core)
* 查阅 [PersistentVolumeSpec](/docs/api-reference/{{page.version}}/#persistentvolumeclaim-v1-core) 的 `persistentVolumeReclaimPolicy` 字段。
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,227 @@
---
approvers:
- lavalamp
- thockin
title: 集群管理
---
* TOC
{:toc}
本文描述了和集群生命周期相关的几个主题:创建新集群、更新集群的 master 和 worker 节点、执行节点维护(例如升级内核)以及升级运行中集群的 Kubernetes API 版本。
## 创建和配置集群
要在一组机器上安装 Kubernetes, 请根据您的环境,查阅现有的 [入门指南](/docs/getting-started-guides/)
## 升级集群
集群升级当前是配套提供的,某些发布版本在升级时可能需要特殊处理。推荐管理员在升级他们的集群前,同时查阅 [发行说明](https://git.k8s.io/kubernetes/CHANGELOG.md) 和版本具体升级说明。
* [升级到 1.6](/docs/admin/upgrade-1-6)
### 升级 Google Compute Engine 集群
Google Compute Engine Open Source (GCE-OSS) 通过删除和重建 master 来支持 master 升级。通过维持相同的 Persistent Disk (PD) 以保证在升级过程中保留数据。
GCE 的 Node 升级采用 [管理实例组](https://cloud.google.com/compute/docs/instance-groups/),每个节点将被顺序的删除,然后使用新软件重建。任何运行在那个节点上的 Pod 需要用 Replication Controller 控制,或者在扩容之后手动重建。
开源 Google Compute Engine (GCE) 集群上的升级过程由 `cluster/gce/upgrade.sh` 脚本控制。
运行 `cluster/gce/upgrade.sh -h` 获取使用说明。
例如,只将 master 升级到一个指定的版本 (v1.0.2):
```shell
cluster/gce/upgrade.sh -M v1.0.2
```
或者,将整个集群升级到最新的稳定版本:
```shell
cluster/gce/upgrade.sh release/stable
```
### 升级 Google Container Engine (GKE) 集群
Google Container Engine 自动升级 master 组件(例如 `kube-apiserver``kube-scheduler`)至最新版本。它还负责 master 运行的操作系统和其它组件。
节点升级过程由用户初始化,[GKE 文档](https://cloud.google.com/container-engine/docs/clusters/upgrade) 里有相关描述。
### 在其他平台上升级集群
不同的供应商和工具管理升级的过程各不相同。建议您查阅它们有关升级的主要文档。
* [kops](https://github.com/kubernetes/kops)
* [kubespray](https://github.com/kubernetes-incubator/kubespray)
* [CoreOS Tectonic](https://coreos.com/tectonic/docs/latest/admin/upgrade.html)
* ...
## 调整集群大小
如果集群资源短缺,您可以轻松的添加更多的机器,如果集群正运行在[节点自注册模式](/docs/admin/node/#self-registration-of-nodes)下的话。如果正在使用的是 GCE 或者 GKE,这将通过调整管理节点的实例组的大小完成。在 [Google Cloud Console page](https://console.developers.google.com) 的 `Compute > Compute Engine > Instance groups > your group > Edit group` 下修改实例数量或使用 gcloud CLI 都可以完成这个任务。
```shell
gcloud compute instance-groups managed resize kubernetes-minion-group --size 42 --zone $ZONE
```
实例组将负责在新机器上放置恰当的镜像并启动它们。Kubelet 将向 API server 注册它的节点以使其可以用于调度。如果您对 instance group 进行缩容,系统将会随机选取节点来终止。
在其他环境上,您可能需要手动配置机器并告诉 Kubelet API server 在哪台机器上运行。
### 集群自动伸缩
如果正在使用 GCE 或者 GKE,您可以配置您的集群,使其能够基于 pod 需求自动重新调整大小。
如 [Compute Resource](/docs/concepts/configuration/manage-compute-resources-container/) 所述,用户可以控制预留多少 CPU 和内存来分配给 pod。这个信息被 Kubernetes scheduler 用来寻找一个运行 pod 的地方。如果没有一个节点有足够的空闲容量(或者不能满足其他 pod 的需求),这个 pod 就需要等待某些 pod 结束,或者一个新的节点被添加。
集群 autoscaler 查找不能被调度的 pod 并检查添加一个新节点(和集群中其它节点类似的)是否有帮助。如果是的话,它将调整集群的大小以容纳等待调度的 pod。
如果发现在一段延时时间内(默认10分钟,将来有可能改变)某些节点不再需要,集群 autoscaler 也会缩小集群。
集群 autoscaler 在每一个实例组(GCE)或节点池(GKE)上配置。
如果您使用 GCE,那么您可以在使用 kube-up.sh 脚本创建集群的时候启用它。要想配置集群 autoscaler,您需要设置三个环境变量:
* `KUBE_ENABLE_CLUSTER_AUTOSCALER` - 如果设置为 true 将启用集群 autoscaler。
* `KUBE_AUTOSCALER_MIN_NODES` - 集群的最小节点数量。
* `KUBE_AUTOSCALER_MAX_NODES` - 集群的最大节点数量。
示例:
```shell
KUBE_ENABLE_CLUSTER_AUTOSCALER=true KUBE_AUTOSCALER_MIN_NODES=3 KUBE_AUTOSCALER_MAX_NODES=10 NUM_NODES=5 ./cluster/kube-up.sh
```
在 GKE 上,您可以在创建、更新集群或创建一个特别的节点池(您希望自动伸缩的)时,通过给对应的 `gcloud` 命令传递 `--enable-autoscaling` `--min-nodes``--max-nodes` 来配置集群 autoscaler。
示例:
```shell
gcloud container clusters create mytestcluster --zone=us-central1-b --enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5
```
```shell
gcloud container clusters update mytestcluster --enable-autoscaling --min-nodes=1 --max-nodes=15
```
**集群 autoscaler 期望节点未被手动修改过(例如通过 kubectl 添加标签),因为那些属性可能不能被传递到相同节点组中的新节点上。**
## 维护节点
如果需要重启节点(例如内核升级、libc 升级、硬件维修等),且停机时间很短时,当 Kubelet 重启后,它将尝试重启调度到节点上的 pod。如果重启花费较长时间(默认时间为 5 分钟,由 controller-manager 的 `--pod-eviction-timeout` 控制),节点控制器将会结束绑定到这个不可用节点上的 pod。如果存在对应的 replica set(或者 replication controller)时,则将在另一个节点上启动 pod 的新副本。所以,如果所有的 pod 都是复制而来,那么在不是所有节点都同时停机的前提下,升级可以在不需要特殊调整情况下完成。
如果您希望更多的控制升级过程,可以使用下面的工作流程:
使用 `kubectl drain` 优雅的结束节点上的所有 pod 并同时标记节点为不可调度:
```shell
kubectl drain $NODENAME
```
在您正试图使节点离线时,这将阻止新的 pod 落到它们上面。
对于有 replica set 的 pod 来说,它们将会被新的 pod 替换并且将被调度到一个新的节点。此外,如果 pod 是一个 service 的一部分,则客户端将被自动重定向到新的 pod。
对于没有 replica set 的 pod,您需要手动启动 pod 的新副本,并且如果它不是 service 的一部分,您需要手动将客户端重定向到这个 pod。
在节点上执行维护工作。
重新使节点可调度:
```shell
kubectl uncordon $NODENAME
```
如果删除了节点的虚拟机实例并重新创建,那么一个新的可调度节点资源将被自动创建(只在您使用支持节点发现的云服务提供商时;当前只有 Google Compute Engine,不包括在 Google Compute Engine 上使用 kube-register 的 CoreOS)。相关详细信息,请查阅 [节点](/docs/admin/node)。
## 高级主题
### 升级到不同的 API 版本
当新的 API 版本发布时,您可能需要升级集群支持新的 API 版本(例如当 'v2' 发布时从 'v1' 切换到 'v2')。
这不是一个经常性的事件,但需要谨慎的处理。这里有一系列升级到新 API 版本的步骤。
1. 开启新 API 版本。
2. 升级集群存储来使用新版本。
3. 升级所有配置文件。识别使用旧 API 版本 endpoint 的用户。
4. 运行 `cluster/update-storage-objects.sh` 升级存储中的现有对象为新版本。
5. 关闭旧 API 版本。
### 打开或关闭集群的 API 版本
可以在启动 API server 时传递 `--runtime-config=api/<version>` 标志来打开或关闭特定的 API 版本。例如:要关闭 v1 API,请传递 `--runtime-config=api/v1=false`。运行时配置还支持两个特殊键值:api/all 和 api/legacy,分别控制全部和遗留 API。例如要关闭除 v1 外全部 API 版本,请传递 `--runtime-config=api/all=false,api/v1=true`。对于这些标志来说,_legacy_ API 指那些被显式废弃的 API(例如 `v1beta3`)。
### 切换集群存储的 API 版本
存储于磁盘中,用于在集群内部代表 Kubernetes 活跃资源的对象使用特定的 API 版本书写。当支撑的 API 改变时,这些对象可能需要使用更新的 API 重写。重写失败将最终导致资源不再能够被 Kubernetes API server 解析或使用。
`kube-apiserver` 二进制文件的 `KUBE_API_VERSIONS` 环境变量控制了集群支持的 API 版本。列表中的第一个版本被用作集群的存储版本。因此,要设置特定的版本为存储版本,请将其放在 `KUBE_API_VERSIONS` 参数值版本列表的最前面。您需要重启 `kube-apiserver` 二进制以使这个变量的改动生效。
### 切换配置文件为新 API 版本
可以使用 `kubectl convert` 命令对不同 API 版本的配置文件进行转换。
```shell
kubectl convert -f pod.yaml --output-version v1
```
更多选项请参考 [kubectl convert](/docs/user-guide/kubectl/v1.6/#convert) 命令用法。
@@ -0,0 +1,134 @@
---
title: 配置命名空间下pod总数
---
{% capture overview %}
本文主要描述如何配置一个命名空间下可运行的pod总数。资源配额详细信息可查看:[资源配额](/docs/api-reference/v1.7/#resourcequota-v1-core)
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 创建一个命名空间
首先创建一个命名空间,这样可以将本次操作中创建的资源与集群其他资源隔离开来。
```shell
kubectl create namespace quota-pod-example
```
## 创建资源配额
下面是一个资源配额的配置文件:
{% include code.html language="yaml" file="quota-pod.yaml" ghlink="/docs/tasks/administer-cluster/quota-pod.yaml" %}
创建这个资源配额:
```shell
kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-pod.yaml --namespace=quota-pod-example
```
查看资源配额的详细信息:
```shell
kubectl get resourcequota pod-demo --namespace=quota-pod-example --output=yaml
```
从输出的信息我们可以看到,该命名空间下pod的配额是2个,目前创建的pods数为0,配额使用率为0。
```yaml
spec:
hard:
pods: "2"
status:
hard:
pods: "2"
used:
pods: "0"
```
下面是一个Deployment的配置文件:
{% include code.html language="yaml" file="quota-pod-deployment.yaml" ghlink="/docs/tasks/administer-cluster/quota-pod-deployment.yaml" %}
在配置文件中, `replicas: 3` 告诉kubernetes尝试创建三个pods,且运行相同的应用。
创建这个Deployment
```shell
kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-pod-deployment.yaml --namespace=quota-pod-example
```
查看Deployment的详细信息:
```shell
kubectl get deployment pod-quota-demo --namespace=quota-pod-example --output=yaml
```
从输出的信息我们可以看到,尽管尝试创建三个pod,但是由于配额的限制,只有两个pod能被成功创建。
```yaml
spec:
...
replicas: 3
...
status:
availableReplicas: 2
...
lastUpdateTime: 2017-07-07T20:57:05Z
message: 'unable to create pods: pods "pod-quota-demo-1650323038-" is forbidden:
exceeded quota: pod-demo, requested: pods=1, used: pods=2, limited: pods=2'
```
## 清理
删除命名空间:
```shell
kubectl delete namespace quota-pod-example
```
{% endcapture %}
{% capture whatsnext %}
### 对于集群管理
* [配置命名空间下,内存默认的request值和limit值](/docs/tasks/administer-cluster/memory-default-namespace/)
* [配置命名空间下,CPU默认的request值和limit值](/docs/tasks/administer-cluster/cpu-default-namespace/)
* [配置命名空间下,内存的最小值和最大值](/docs/tasks/administer-cluster/memory-constraint-namespace/)
* [配置命名空间下,CPU的最小值和最大值](/docs/tasks/administer-cluster/cpu-constraint-namespace/)
* [配置命名空间下,内存和CPU的配额](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)
* [配置命名空间下,API对象的配额](/docs/tasks/administer-cluster/quota-api-object/)
### 对于应用开发
* [给容器和pod分配内存资源](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [给容器和pod分配CPU资源](/docs/tasks/configure-pod-container/assign-cpu-resource/)
* [配置pod的QoS](/docs/tasks/configure-pod-container/quality-service-pod/)
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,137 @@
---
title: 给容器分配非透明整型资源
---
{% capture overview %}
本页展示了如何给容器分配非透明整型资源。
{% include feature-state-alpha.md %}
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
在做这个练习之前,请在[给节点配置非透明整型资源](/docs/tasks/administer-cluster/opaque-integer-resource-node/)文档中进行练习,
该文档介绍了在一个节点上配置dongle资源。
{% endcapture %}
{% capture steps %}
## 给Pod分配非透明整型资源
为了请求一个非透明整型资源,需要在容器配置文件中包含`resources:requests`字段。
非透明整型资源类型前缀是`pod.alpha.kubernetes.io/opaque-int-resource-`
下面是含有一个容器的Pod的配置文件:
{% include code.html language="yaml" file="oir-pod.yaml" ghlink="/cn/docs/tasks/configure-pod-container/oir-pod.yaml" %}
在配置文件中,可以看到容器请求了3个dongles资源。
创建Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/oir-pod.yaml
```
验证Pod是否正在运行:
```shell
kubectl get pod oir-demo
```
查询Pod的状态:
```shell
kubectl describe pod oir-demo
```
输出显示了dongle请求:
```yaml
Requests:
pod.alpha.kubernetes.io/opaque-int-resource-dongle: 3
```
## 尝试创建第二个Pod
下面是含有一个容器的Pod的配置文件。该容器请求了两个dongles资源。
{% include code.html language="yaml" file="oir-pod-2.yaml" ghlink="/docs/tasks/configure-pod-container/oir-pod-2.yaml" %}
Kubernetes无法再满足两个dongles的请求,因为第一个Pod已经使用了四个可用dongles中的三个。
尝试创建Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/oir-pod-2.yaml
```
查询Pod的状态
```shell
kubectl describe pod oir-demo-2
```
输出显示该Pod无法被调度,因为没有节点有两个可用的dongles资源:
```
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (oir-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient pod.alpha.kubernetes.io/opaque-int-resource-dongle (1)
```
查看Pod的状态:
```shell
kubectl get pod oir-demo-2
```
输出显示Pod已创建,但是没有被调度并运行在节点上。
它的状态为Pending:
```yaml
NAME READY STATUS RESTARTS AGE
oir-demo-2 0/1 Pending 0 6m
```
## 删除
删除本练习中创建的Pod:
```shell
kubectl delete pod oir-demo
```
{% endcapture %}
{% capture whatsnext %}
### 对于应用开发者
* [分配内存资源](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [分配CPU资源](/docs/tasks/configure-pod-container/assign-cpu-resource/)
### 对于集群管理员
* [给节点配置非透明整型资源](/docs/tasks/administer-cluster/opaque-integer-resource-node/)
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,87 @@
---
title: 调试Pods和Replication Controllers
---
* TOC
{:toc}
## 调试Pods
调试一个pod的第一步是观察它。使用下面的命令检查这个pod的当前状态和最近事件:
$ kubectl describe pods ${POD_NAME}
看看pod中的容器的状态。他们都是`Running`吗?有最近重启了吗?
根据pod的状态继续调试。
### 我的Pod保持Pending
如果一个pod被卡在`Pending`中,就意味着它不能调度在某个节点上。一般来说,这是因为某种类型的资源不足
阻止调度。 看看上面的命令`kubectl describe ...`的输出。调度器的消息中应该会包含无法调度Pod的原因。
理由包括:
#### 资源不足
您可能已经耗尽了集群中供应的CPU或内存。在这个情况下你可以尝试几件事情:
* [添加更多节点](/docs/admin/cluster-management/#resizing-a-cluster) 到集群。
* [终止不需要的pod](/docs/user-guide/pods/single-container/#deleting_a_pod)
为pending中的pods提供空间。
* 检查该pod是否不大于您的节点。例如,如果全部节点具有`cpu:1`容量,那么具有`cpu: 1.1`请求的pod永远不会被调度。
您可以使用`kubectl get nodes -o <format>`命令来检查节点容量。
下面是一些能够提取必要信息的命令示例:
kubectl get nodes -o yaml | grep '\sname\|cpu\|memory'
kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, cap: .status.capacity}'
可以考虑配置[资源配额](/docs/concepts/policy/resource-quotas/)来限制可耗用的资源总量。如果与命名空间一起使用,它可以防止一个团队吞噬所有的资源。
#### 使用hostPort
当你将一个pod绑定到一个`hostPort`时,这个pod能被调度的位置数量有限。
在大多数情况下,`hostPort`是不必要的; 尝试使用服务对象来暴露您的pod。
如果你需要`hostPort`,那么你可以调度的Pod数量不能超过集群的节点个数。
### 我的Pod一直在Waiting
如果一个pod被卡在`Waiting`状态,那么它已被调度在某个工作节点,但它不能在该机器上运行。
再次,来自`kubectl describe ...`的内容应该是可以提供信息的。
最常见的原因`Waiting`的pod是无法拉取镜像。有三件事要检查:
* 确保您的镜像的名称正确。
* 您是否将镜像推送到存储库?
* 在您的机器上手动运行`docker pull <image>`,看看是否可以拉取镜像。
### 我的Pod一直Crashing或者有别的不健康状态
首先,查看当前容器的日志:
$ kubectl logs ${POD_NAME} ${CONTAINER_NAME}
如果您的容器先前已崩溃,则可以访问上一个容器的崩溃日志:
$ kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}
或者,您可以使用`exec`在该容器内运行命令:
$ kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}
请注意,`-c ${CONTAINER_NAME}`是可选的,对于pod只包含一个容器可以省略。
例如,要查看正在运行的Cassandra pod的日志,可以运行:
$ kubectl exec cassandra -- cat /var/log/cassandra/system.log
如果这些方法都不起作用,您可以找到该运行pod所在的主机并SSH到该主机。
## 调试Replication Controllers
Replication Controllers相当简单。他们能或不能创建pod。如果他们无法创建pod,那么请参考
[上面的说明](#debugging_pods)来调试你的pod。
您也可以使用`kubectl describe rc ${CONTROLLER_NAME}`来检查和Replication Controllers有关的事件。
@@ -0,0 +1,77 @@
---
title: 调试StatefulSet
---
{% capture overview %}
此任务展示如何调试StatefulSet。
{% endcapture %}
{% capture prerequisites %}
* 你需要有一个Kubernetes集群,通过必要的配置使kubectl命令行工具与您的集群进行通信。
* 你应该有一个运行中的StatefulSet,以便用于调试。
{% endcapture %}
{% capture steps %}
## 调试StatefulSet
由于StatefulSet在创建时设置了`app=myapp`标签,列出仅属于该StatefulSet的所有pod时,可以使用以下命令:
```shell
kubectl get pods -l app=myapp
```
如果您发现列出的任何Pods长时间处于`Unknown``Terminating`状态,关于如何处理它们的说明任务,请参阅[删除 StatefulSet Pods](/docs/tasks/manage-stateful-set/delete-pods/)。您可以参考[调试 Pods](/docs/user-guide/debugging-pods-and-replication-controllers/#debugging-pods)指南来调试StatefulSet中的各个Pod。
StatefulSets提供调试机制,可以使用注解来暂停所有控制器在Pod上的操作。在任何StatefulSet Pod上设置`pod.alpha.kubernetes.io/initialized`注解为`"false"`将*暂停* StatefulSet的所有操作。暂停时,StatefulSet将不执行任何伸缩操作。一旦调试钩子设置完成后,就可以在StatefulSet pod的容器内执行命令,而不会造成伸缩操作的干扰。您可以通过执行以下命令将注解设置为`"false"`
```shell
kubectl annotate pods <pod-name> pod.alpha.kubernetes.io/initialized="false" --overwrite
```
当注解设置为`"false"`时,StatefulSet在其Pods变得不健康或不可用时将不会响应。StatefulSet不会创建副本Pod直到每个Pod上删除注解或将注解设置为`"true"`
### 逐步初始化
创建StatefulSet之前,您可以通过使用和上文相同的注解,即将yaml文件中`.spec.template.metadata.annotations`里的`pod.alpha.kubernetes.io/initialized`字段设置为`"false"`,对竞态条件的StatefulSet进行调试。
```yaml
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: my-app
spec:
serviceName: "my-app"
replicas: 3
template:
metadata:
labels:
app: my-app
annotations:
pod.alpha.kubernetes.io/initialized: "false"
...
...
...
```
设置注解后,如果创建了StatefulSet,您可以等待每个Pod来验证它是否正确初始化。StatefulSet将不会创建任何后续的Pods,直到在已经创建的每个Pod上将调试注解设置为`"true"` (或删除)。 您可以通过执行以下命令将注解设置为`"true"`
```shell
kubectl annotate pods <pod-name> pod.alpha.kubernetes.io/initialized="true" --overwrite
```
{% endcapture %}
{% capture whatsnext %}
点击链接[调试init-container](/docs/tasks/troubleshoot/debug-init-containers/),了解更多信息。
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: command-demo
labels:
purpose: demonstrate-command
spec:
containers:
- name: command-demo-container
image: debian
command: ["printenv"]
args: ["HOSTNAME", "KUBERNETES_PORT"]
@@ -0,0 +1,128 @@
---
title: 为容器设置启动时要执行的命令及其入参
---
{% capture overview %}
本页将展示如何为Kubernetes Pod下的容器设置启动时要执行的命令及其入参。
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 创建Pod时为其下的容器设置启动时要执行的命令及其入参
创建Pod时,可以为其下的容器设置启动时要执行的命令及其入参。如果要设置命令,就
填写在配置文件的`command`字段下,如果要设置命令的入参,就填写在配置文件的`args
`字段下。一旦Pod创建完成,该命令及其入参就无法再进行更改了。
如果在配置文件中设置了容器启动时要执行的命令及其入参,那么容器镜像中自带的命令
与入参将会被覆盖而不再执行。如果配置文件中只是设置了入参,却没有设置其对应的命
令,那么容器镜像中自带的命令会使用该新入参作为其执行时的入参。
本示例中,将创建一个只包含单个容器的Pod。在Pod配置文件中设置了一个命令与两个入参:
{% include code.html language="yaml" file="commands.yaml" ghlink="/cn/docs/tasks/inject-data-application/commands.yaml" %}
1. 基于YAML文件创建一个Pod
kubectl create -f https://k8s.io/docs/tasks/inject-data-application/commands.yaml
1. 获取一下当前正在运行的Pods信息:
kubectl get pods
查询结果显示在command-demo这个Pod下运行的容器已经启动完成
1. 如果要获取容器启动时执行命令的输出结果,可以通过Pod的日志进行查看
kubectl logs command-demo
日志中显示了HOSTNAME 与KUBERNETES_PORT 这两个环境变量的值:
command-demo
tcp://10.3.240.1:443
## 使用环境变量来设置入参
在上面的示例中,我们直接将一串字符作为命令的入参。除此之外,我们还可以
将环境变量作为命令的入参。
env:
- name: MESSAGE
value: "hello world"
command: ["/bin/echo"]
args: ["$(MESSAGE)"]
这样一来,我们就可以将那些用来设置环境变量的方法应用于设置命令的入参,其
中包括了[ConfigMaps](/docs/tasks/configure-pod-container/configmap/)
[Secrets](/docs/concepts/configuration/secret/).
**注意:** 环境变量需要加上括号,类似于`"$(VAR)"`。这是在`command`
`args`字段使用变量的格式要求。
{: .note}
## 通过shell来执行命令
有时候,需要通过shell来执行命令。 例如,命令可能由多个命令组合而成,抑或包含
在一个shell脚本中。这时,就可以通过如下方式在shell中执行命令:
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
## 注意
下表给出了Docker 与 Kubernetes中对应的字段名称。
| Description | Docker field name | Kubernetes field name |
|----------------------------------------|------------------------|-----------------------|
| The command run by the container | Entrypoint | command |
| The arguments passed to the command | Cmd | args |
如果要覆盖默认的Entrypoint 与 Cmd,需要遵循如下规则:
* 如果在容器配置中没有设置`command` 或者 `args`,那么将使用Docker镜像自带的命
令及其入参。
* 如果在容器配置中只设置了`command`但是没有设置`args`,那么容器启动时只会执行该
命令,Docker镜像中自带的命令及其入参会被忽略。
* 如果在容器配置中只设置了`args`,那么Docker镜像中自带的命令会使用该新入参作为
其执行时的入参。
* 如果在容器配置中同时设置了`command``args`,那么Docker镜像中自带的命令及
其入参会被忽略。容器启动时只会执行配置中设置的命令,并使用配置中设置的入参作为
命令的入参。
下表涵盖了各类设置场景:
| Image Entrypoint | Image Cmd | Container command | Container args | Command run |
|--------------------|------------------|---------------------|--------------------|------------------|
| `[/ep-1]` | `[foo bar]` | &lt;not set&gt; | &lt;not set&gt; | `[ep-1 foo bar]` |
| `[/ep-1]` | `[foo bar]` | `[/ep-2]` | &lt;not set&gt; | `[ep-2]` |
| `[/ep-1]` | `[foo bar]` | &lt;not set&gt; | `[zoo boo]` | `[ep-1 zoo boo]` |
| `[/ep-1]` | `[foo bar]` | `[/ep-2]` | `[zoo boo]` | `[ep-2 zoo boo]` |
{% endcapture %}
{% capture whatsnext %}
* 获取更多资讯可参考 [containers and commands](/docs/user-guide/containers/).
* 获取更多资讯可参考 [configuring pods and containers](/docs/tasks/).
* 获取更多资讯可参考 [running commands in a container](/docs/tasks/debug-application-cluster/get-shell-running-container/).
* 参考 [Container](/docs/api-reference/{{page.version}}/#container-v1-core).
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,72 @@
---
title: 为容器设置环境变量
---
{% capture overview %}
本页将展示如何为kubernetes Pod下的容器设置环境变量。
{% endcapture %}
{% capture prerequisites %}
{% include task-tutorial-prereqs.md %}
{% endcapture %}
{% capture steps %}
## 为容器设置一个环境变量
创建Pod时,可以为其下的容器设置环境变量。通过配置文件的`env`或者`envFrom` 字段来设置环境变量。
本示例中,将创建一个只包含单个容器的Pod。Pod的配置文件中设置环境变量的名称为`DEMO_GREETING`
其值为`"Hello from the environment"`。下面是Pod的配置文件内容:
{% include code.html language="yaml" file="envars.yaml" ghlink="/docs/tasks/inject-data-application/envars.yaml" %}
1. 基于YAML文件创建一个Pod:
kubectl create -f https://k8s.io/docs/tasks/inject-data-application/envars.yaml
1. 获取一下当前正在运行的Pods信息:
kubectl get pods -l purpose=demonstrate-envars
查询结果应为:
NAME READY STATUS RESTARTS AGE
envar-demo 1/1 Running 0 9s
1. 进入该Pod下的容器并打开一个命令终端:
kubectl exec -it envar-demo -- /bin/bash
1. 在命令终端中通过执行`printenv`打印出环境变量。
root@envar-demo:/# printenv
打印结果应为:
NODE_VERSION=4.4.2
EXAMPLE_SERVICE_PORT_8080_TCP_ADDR=10.3.245.237
HOSTNAME=envar-demo
...
DEMO_GREETING=Hello from the environment
1. 通过键入`exit`退出命令终端。
{% endcapture %}
{% capture whatsnext %}
* 有关环境变量的更多信息,请参阅[这里](/docs/tasks/configure-pod-container/environment-variable-expose-pod-information/)。
* 有关如何通过环境变量来使用Secret,请参阅[这里](/docs/user-guide/secrets/#using-secrets-as-environment-variables)。
* 关于[EnvVarSource](/docs/api-reference/{{page.version}}/#envvarsource-v1-core)资源的信息。
{% endcapture %}
{% include templates/task.md %}
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: envar-demo
labels:
purpose: demonstrate-envars
spec:
containers:
- name: envar-demo-container
image: gcr.io/google-samples/node-hello:1.0
env:
- name: DEMO_GREETING
value: "Hello from the environment"
@@ -0,0 +1,225 @@
---
approvers:
- janetkuo
title: 基于Replication Controller执行滚动升级
---
* TOC
{:toc}
## 概述
**注**: 创建副本应用的首选方法是使用[Deployment](/docs/api-reference/{{page.version}}/#deployment-v1beta1-apps)Deployment使用[ReplicaSet](/docs/api-reference/{{page.version}}/#replicaset-v1beta1-extensions)来进行副本控制。
更多信息, 查看[使用Deployment运行一个无状态应用](/docs/tasks/run-application/run-stateless-application-deployment/)。
为了在更新服务的同时不中断业务, `kubectl` 支持['滚动更新'](/docs/user-guide/kubectl/v1.6/#rolling-update),它一次更新一个pod,而不是同时停止整个服务。 有关更多信息,请参阅 [滚动更新设计文档](https://git.k8s.io/community/contributors/design-proposals/simple-rolling-update.md) 和 [滚动更新示例](/docs/tasks/run-application/rolling-update-replication-controller/)。
请注意, `kubectl rolling-update` 仅支持Replication Controllers。 但是,如果使用Replication Controllers部署应用,请考虑将其切换到[Deployments](/docs/concepts/workloads/controllers/deployment/). Deployment是一种被推荐使用的更高级别的控制器,它可以对应用进行声明性的自动滚动更新。 如果您仍然希望保留您的Replication Controllers并使用 `kubectl rolling-update`进行滚动更新, 请继续往下阅读:
滚动更新可以对replication controller所管理的Pod的配置进行变更,变更可以通过一个新的配置文件来进行,或者,如果只更新镜像,则可以直接指定新的容器镜像。
滚动更新的工作流程:
1. 通过新的配置创建一个replication controller
2. 在新的控制器上增加副本数,在旧的上面减少副本数,直到副本数达到期望值
3. 删除之前的replication controller
使用`kubectl rolling-update`命令来进行滚动更新:
$ kubectl rolling-update NAME \
([NEW_NAME] --image=IMAGE | -f FILE)
## 通过配置文件更新
通过配置文件来进行滚动更新,需要在`kubectl rolling-update`命令后面带上新的配置文件:
$ kubectl rolling-update NAME -f FILE
这个配置文件必须满足以下条件:
* 指定不同的`metadata.name`
* 至少要修改`spec.selector`中的一个标签值
* `metadata.namespace`字段必须相同
Replication Controllers的配置文件详细介绍见[创建Replication Controllers](/docs/tutorials/stateless-application/run-stateless-ap-replication-controller/).
### 示例
// 通过新的配置文件frontend-v2.json来更新frontend-v1的pods
$ kubectl rolling-update frontend-v1 -f frontend-v2.json
// 将frontend-v2.json数据传到标准输入来更新frontend-v1的pods
$ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f -
## 更新容器镜像
仅更新容器镜像的话,可通过如下命令,该命令可以指定一个新的控制器名称(可选),通过`--image`参数来指定新的镜像名称和标签。
$ kubectl rolling-update NAME [NEW_NAME] --image=IMAGE:TAG
`--image`参数仅支持单容器pod,多容器pod使用`--image`参数会返回错误。
如果没有指定 `NEW_NAME` ,新的replication controller创建后会使用一个临时名称,当更新完成,旧的controller被删除后,新的controller名称会被更新成旧的controller名称。
如果`IMAGE:TAG` 和当前值相同,更新就会失败。 因此,我们建议使用版本号来作为标签,而不是使用 `:latest`。从一个 `image:latest`镜像升级到一个新的 `image:latest` 镜像将会失败,即使这两个镜像不是相同的。
所以,我们不建议使用 `:latest` 来作为标签,详细信息见[最佳配置实践](/docs/concepts/configuration/overview/#container-images) 。
### 示例
// 更新frontend-v1的pod到frontend-v2
$ kubectl rolling-update frontend-v1 frontend-v2 --image=image:v2
// 更新frontend的pods,不更改replication controller的名称
$ kubectl rolling-update frontend --image=image:v2
## 必选和可选字段
必选字段:
* `NAME`: 需要进行滚动更新的replication controller名称
下面两个字段选其一:
* `-f FILE`: 新的replication controller的配置文件,JSON或者YAML格式均可。配置文件必须指定一个新的顶层`id`值,且至少包含一个现有`spec.selector`中的键值对。
详细信息见[通过Replication Controller运行无状态应用](/docs/tutorials/stateless-application/run-stateless-ap-replication-controller/#replication-controller-configuration-file)。
<br>
<br>
或者:
<br>
<br>
* `--image IMAGE:TAG`: 更新后的镜像的名称和标签。必须和当前的image:tag不同。
可选字段包括:
* `NEW_NAME`: 只和 `--image` 一起使用,不和 `-f FILE` 一起使用。标识新的replication controller的名称。
* `--poll-interval DURATION`: 在更新后轮询控制器状态的间隔时间。有效单位有 `ns` (纳秒),`us``µs`(微秒),`ms`(毫秒),`s`(秒),`m`(分钟)或 `h`(小时)。 单位可以自由组合(例如 `1m30s`)。 默认值为 `3s`
* `--timeout DURATION`: 退出更新之前,等待控制器更新一个pod的最大时间。默认是`5m0s`。有效单位如`--poll-interval`所述。
* `--update-period DURATION`: 更新两个pod之间等待的时间,默认值是`1m0s`。有效单位如`--poll-interval`所述。
有关`kubectl rolling-update`命令的更多信息见[`kubectl`参考](/docs/user-guide/kubectl/v1.6/#rolling-update).
## 实践
现在你运行了一个1.7.9版本的nginx应用:
```yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
```
要更新到1.9.1版本,你可以使用[`kubectl rolling-update --image`](https://git.k8s.io/community/contributors/design-proposals/simple-rolling-update.md)来指定一个新的镜像:
```shell
$ kubectl rolling-update my-nginx --image=nginx:1.9.1
Created my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
```
在终端上打开另一个窗口 ,你可以看到`kubectl` 给每个pod都增加了一个值为配置文件哈希值的 `deployment` 标签,用来区分新旧pod
```shell
$ kubectl get pods -l app=nginx -L deployment
NAME READY STATUS RESTARTS AGE DEPLOYMENT
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-k156z 1/1 Running 0 1m ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-v95yh 1/1 Running 0 35s ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-divi2 1/1 Running 0 2h 2d1d7a8f682934a254002b56404b813e
my-nginx-o0ef1 1/1 Running 0 2h 2d1d7a8f682934a254002b56404b813e
my-nginx-q6all 1/1 Running 0 8m 2d1d7a8f682934a254002b56404b813e
```
使用`kubectl rolling-update`可以实时看到更新的进度:
```
Scaling up my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 from 0 to 3, scaling down my-nginx from 3 to 0 (keep 3 pods available, don't exceed 4 pods)
Scaling my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 up to 1
Scaling my-nginx down to 2
Scaling my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 up to 2
Scaling my-nginx down to 1
Scaling my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 up to 3
Scaling my-nginx down to 0
Update succeeded. Deleting old controller: my-nginx
Renaming my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 to my-nginx
replicationcontroller "my-nginx" rolling updated
```
如果遇到问题,你可以中途停止滚动更新,并且使用 `--rollback` 来回滚到以前的版本:
```shell
$ kubectl rolling-update my-nginx --rollback
Setting "my-nginx" replicas to 1
Continuing update with existing controller my-nginx.
Scaling up nginx from 1 to 1, scaling down my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 from 1 to 0 (keep 1 pods available, don't exceed 2 pods)
Scaling my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 down to 0
Update succeeded. Deleting my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
replicationcontroller "my-nginx" rolling updated
```
这个例子说明容器的不变性是个巨大的优点。
如果你不仅仅是需要更新镜像,(例如,更新命令参数,环境变量等),你可以创建一个新的replication controller配置文件,包含一个新的名称和不同的标签值,例如:
```yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx-v4
spec:
replicas: 5
selector:
app: nginx
deployment: v4
template:
metadata:
labels:
app: nginx
deployment: v4
spec:
containers:
- name: nginx
image: nginx:1.9.2
args: ["nginx", "-T"]
ports:
- containerPort: 80
```
然后使用它来进行更新:
```shell
$ kubectl rolling-update my-nginx -f ./nginx-rc.yaml
Created my-nginx-v4
Scaling up my-nginx-v4 from 0 to 5, scaling down my-nginx from 4 to 0 (keep 4 pods available, don't exceed 5 pods)
Scaling my-nginx-v4 up to 1
Scaling my-nginx down to 3
Scaling my-nginx-v4 up to 2
Scaling my-nginx down to 2
Scaling my-nginx-v4 up to 3
Scaling my-nginx down to 1
Scaling my-nginx-v4 up to 4
Scaling my-nginx down to 0
Scaling my-nginx-v4 up to 5
Update succeeded. Deleting old controller: my-nginx
replicationcontroller "my-nginx-v4" rolling updated
```
## 故障分析
如果更新过程中,达到超时时长`timeout`后还没更新完成,则更新会失败。这时,一些pod会属于新的replication controller,一些会属于旧的。
如果更新失败,可以尝试使用同样的命令来继续更新过程。
在尝试更新之前如果需要回滚到之前的状态,可在之前的命令后面添加`--rollback=true`参数,这将回退所有的更改。
@@ -0,0 +1,226 @@
---
title: 运行一个单实例有状态应用
---
{% capture overview %}
本文介绍在Kubernetes中使用PersistentVolume和Deployment如何运行一个单实例有状态应用. 该应用是MySQL.
{% endcapture %}
{% capture objectives %}
* 在环境中通过磁盘创建一个PersistentVolume.
* 创建一个MySQL Deployment.
* 在集群内以一个已知的DNS名将MySQL暴露给其他pods.
{% endcapture %}
{% capture prerequisites %}
* {% include task-tutorial-prereqs.md %}
* 为了数据持久性我们将在环境上通过磁盘创建一个持久卷. 环境支持的类型见这里[here](/docs/user-guide/persistent-volumes/#types-of-persistent-volumes). 本篇文档将介绍 `GCEPersistentDisk` . `GCEPersistentDisk`卷只能工作在Google Compute Engine平台上.
{% endcapture %}
{% capture lessoncontent %}
## 在环境中设置一个磁盘
你可以为有状态的应用使用任何类型的持久卷. 有关支持环境的磁盘列表,请参考持久卷类型[Types of Persistent Volumes](/docs/user-guide/persistent-volumes/#types-of-persistent-volumes). 对于Google Compute Engine, 请运行:
```
gcloud compute disks create --size=20GB mysql-disk
```
接下来创建一个指向刚创建的 `mysql-disk`磁盘的PersistentVolume. 下面是一个PersistentVolume的配置文件,它指向上面创建的Compute Engine磁盘:
{% include code.html language="yaml" file="gce-volume.yaml" ghlink="/docs/tasks/run-application/gce-volume.yaml" %}
注意`pdName: mysql-disk` 这行与Compute Engine环境中的磁盘名称相匹配. 有关为其
他环境编写PersistentVolume配置文件的详细信息,请参见持久卷[Persistent Volumes](/docs/concepts/storage/persistent-volumes/).
创建持久卷:
```
kubectl create -f https://k8s.io/docs/tasks/run-application/gce-volume.yaml
```
## 部署MySQL
通过创建Kubernetes Deployment并使用PersistentVolumeClaim将其连接到现已存在的PersistentVolume上来运行一个有状态的应用. 例如, 下面这个YAML文件描述了一个运行MySQL
并引用PersistentVolumeClaim的Deployment. 该文件定义了一个volume其挂载目录为/var/lib/mysql, 然后创建一个内存为20G的卷的PersistentVolumeClaim. 此申领可以通过任
何符合需求的卷来满足, 在本例中满足上面创建的卷.
注意: 在配置的yaml文件中定义密码的做法是不安全的. 具体安全解决方案请参考
[Kubernetes Secrets](/docs/concepts/configuration/secret/).
{% include code.html language="yaml" file="mysql-deployment.yaml" ghlink="/docs/tasks/run-application/mysql-deployment.yaml" %}
1. 部署YAML文件中定义的内容:
kubectl create -f https://k8s.io/docs/tasks/run-application/mysql-deployment.yaml
1. 展示Deployment相关信息:
kubectl describe deployment mysql
Name: mysql
Namespace: default
CreationTimestamp: Tue, 01 Nov 2016 11:18:45 -0700
Labels: app=mysql
Annotations: deployment.kubernetes.io/revision=1
Selector: app=mysql
Replicas: 1 desired | 1 updated | 1 total | 0 available | 1 unavailable
StrategyType: Recreate
MinReadySeconds: 0
Pod Template:
Labels: app=mysql
Containers:
mysql:
Image: mysql:5.6
Port: 3306/TCP
Environment:
MYSQL_ROOT_PASSWORD: password
Mounts:
/var/lib/mysql from mysql-persistent-storage (rw)
Volumes:
mysql-persistent-storage:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: mysql-pv-claim
ReadOnly: false
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
Progressing True ReplicaSetUpdated
OldReplicaSets: <none>
NewReplicaSet: mysql-63082529 (1/1 replicas created)
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
33s 33s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set mysql-63082529 to 1
1. 列举出Deployment创建的pods:
kubectl get pods -l app=mysql
NAME READY STATUS RESTARTS AGE
mysql-63082529-2z3ki 1/1 Running 0 3m
1. 查看持久卷:
kubectl describe pv mysql-pv
Name: mysql-pv
Labels: <none>
Status: Bound
Claim: default/mysql-pv-claim
Reclaim Policy: Retain
Access Modes: RWO
Capacity: 20Gi
Message:
Source:
Type: GCEPersistentDisk (a Persistent Disk resource in Google Compute Engine)
PDName: mysql-disk
FSType: ext4
Partition: 0
ReadOnly: false
No events.
1. 查看PersistentVolumeClaim:
kubectl describe pvc mysql-pv-claim
Name: mysql-pv-claim
Namespace: default
Status: Bound
Volume: mysql-pv
Labels: <none>
Capacity: 20Gi
Access Modes: RWO
No events.
## 访问MySQL实例
前面YAML文件中创建了一个允许集群内其他pods访问数据库的服务. 该服务中选项
`clusterIP: None` 让服务DNS名称直接解析为Pod的IP地址. 当在一个服务下只有一个pod
并且不打算增加pods的数量这是最好的.
运行MySQL客户端以连接到服务器:
```
kubectl run -it --rm --image=mysql:5.6 mysql-client -- mysql -h <pod-ip> -p <password>
```
此命令在集群内创建一个新的Pod并运行MySQL客户端,并通过服务将其连接到服务器.如果连接成功,你就知道有状态的MySQL database正处于运行状态.
```
Waiting for pod default/mysql-client-274442439-zyp6i to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.
mysql>
```
## 更新
Deployment中镜像或其他部分同往常一样可以通过 `kubectl apply` 命令更新. 以下是
特定于有状态应用的一些注意事项:
* 不要弹性伸缩. 弹性伸缩仅适用于单实例应用. 下层的PersistentVolume仅只能挂载一个pod. 对于集群级有状态应用, 请参考StatefulSet文档
[StatefulSet documentation](/docs/concepts/workloads/controllers/statefulset/).
* 在Deployment的YAML文件中使用 `strategy:` `type: Recreate` . 该选项指示Kubernetes不使用滚动升级. 滚动升级将无法工作, 由于一次不能运行多个pod. 在更新配置文件
创建一个新的pod前 `Recreate`策略将先停止第一个pod.
## 删除deployment
通过名称删除部署的对象:
```
kubectl delete deployment,svc mysql
kubectl delete pvc mysql-pv-claim
kubectl delete pv mysql-pv
```
如果使用Compute Engine磁盘,也可以使用如下命令:
```
gcloud compute disks delete mysql-disk
```
{% endcapture %}
{% capture whatsnext %}
* 了解更多Deployment对象请参考 [Deployment objects](/docs/concepts/workloads/controllers/deployment/).
* 了解更多Deployment应用请参考 [Deploying applications](/docs/user-guide/deploying-applications/)
* kubectl run文档请参考[kubectl run documentation](/docs/user-guide/kubectl/v1.6/#run)
* 卷和持久卷请参考[Volumes](/docs/concepts/storage/volumes/) and [Persistent Volumes](/docs/concepts/storage/persistent-volumes/)
{% endcapture %}
{% include templates/tutorial.md %}
@@ -0,0 +1,89 @@
---
approvers:
- bprashanth
- enisoc
- erictune
- foxish
- janetkuo
- kow3ns
- smarterclayton
title: 弹缩StatefulSet
---
{% capture overview %}
本文介绍如何弹缩StatefulSet.
{% endcapture %}
{% capture prerequisites %}
* StatefulSets仅适用于Kubernetes1.5及以上版本.
* **不是所有Stateful应用都适合弹缩.** 在弹缩前您的应用前. 您必须充分了解您的应用, 不适当的弹缩StatefulSet或许会造成应用自身功能的不稳定.
* 仅当您确定该Stateful应用的集群是完全健康才可执行弹缩操作.
{% endcapture %}
{% capture steps %}
## 使用 `kubectl` 弹缩StatefulSets
弹缩请确认 `kubectl` 已经升级到Kubernetes1.5及以上版本. 如果不确定, 执行 `kubectl version` 命令并检查使用的 `Client Version`.
### `kubectl 弹缩`
首先, 找到您想要弹缩的StatefulSet. 记住, 您需先清楚是否能弹缩该应用.
```shell
kubectl get statefulsets <stateful-set-name>
```
改变StatefulSet副本数量:
```shell
kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
```
### 可使用其他命令: `kubectl apply` / `kubectl edit` / `kubectl patch`
另外, 您可以 [in-place updates](/docs/concepts/cluster-administration/manage-deployment/#in-place-updates-of-resources) StatefulSets.
如果您的StatefulSet开始由 `kubectl apply``kubectl create --save-config` 创建,更新StatefulSet manifests中的 `.spec.replicas`, 然后执行命令 `kubectl apply`:
```shell
kubectl apply -f <stateful-set-file-updated>
```
除此之外, 可以通过命令 `kubectl edit` 编辑该字段:
```shell
kubectl edit statefulsets <stateful-set-name>
```
或使用 `kubectl patch`:
```shell
kubectl patch statefulsets <stateful-set-name> -p '{"spec":{"replicas":<new-replicas>}}'
```
## 排查故障
### 缩容工作不正常
当Stateful管理下的任何一个Pod不健康时您不能缩容该StatefulSet. 仅当Stateful下的所有Pods都处于运行和ready状态后才可缩容.
当一个StatefulSet的size > 1, 如果有一个Pod不健康, 没有办法让Kubernetes知道是否是由于永久性故障还是瞬态(升级/维护/节点重启)导致. 如果该Pod不健康是由于永久性
故障导致, 则在不纠正该故障的情况下进行缩容可能会导致一种状态, 即StatefulSet下的Pod数量低于应正常运行的副本数. 这也许会导致StatefulSet不可用.
如果由于瞬态故障而导致Pod不健康,并且Pod可能再次可用,那么瞬态错误可能会干扰您对
StatefulSet的扩容/缩容操作. 一些分布式数据库在节点加入和同时离开时存在问题. 在
这些情况下,最好是在应用级别进行弹缩操作, 并且只有在您确保Stateful应用的集群是完全健康时才执行弹缩.
{% endcapture %}
{% capture whatsnext %}
了解更多 [deleting a StatefulSet](/docs/tasks/manage-stateful-set/deleting-a-statefulset/).
{% endcapture %}
{% include templates/task.md %}