Convert site to Hugo (#8316)

This commit converts content and layout to use Hugo.
This commit is contained in:
Bjørn Erik Pedersen
2018-05-05 18:00:51 +02:00
committed by k8s-ci-robot
parent 7745f0e0c5
commit 7f3b633aa0
2327 changed files with 10928 additions and 171503 deletions
@@ -0,0 +1,187 @@
---
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"
content_template: templates/task
---
{{% capture overview %}}
本文旨在说明如何让一个 Pod 内的两个容器使用一个卷(Volume)进行通信。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 创建一个包含两个容器的 Pod
在这个练习中,你会创建一个包含两个容器的 Pod。两个容器共享一个卷用于他们之间的通信。
Pod 的配置文件如下:
{{< code file="two-container-pod.yaml" >}}
在配置文件中,你可以看到 Pod 有一个共享卷,名为 `shared-data`
配置文件中的第一个容器运行了一个 nginx 服务器。共享卷的挂载路径是 `/usr/share/nginx/html`
第二个容器是基于 debian 镜像的,有一个 `/pod-data` 的挂载路径。第二个容器运行了下面的命令然后终止。
echo Hello from the debian container > /pod-data/index.html
注意,第二个容器在 nginx 服务器的根目录下写了 `index.html` 文件。
创建一个包含两个容器的 Pod
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/two-container-pod.yaml
查看 Pod 和容器的信息:
kubectl get pod two-containers --output=yaml
这是输出的一部分:
apiVersion: v1
kind: Pod
metadata:
...
name: two-containers
namespace: default
...
spec:
...
containerStatuses:
- containerID: docker://c1d8abd1 ...
image: debian
...
lastState:
terminated:
...
name: debian-container
...
- containerID: docker://96c1ff2c5bb ...
image: nginx
...
name: nginx-container
...
state:
running:
...
你可以看到 debian 容器已经被终止了,而 nginx 服务器依然在运行。
进入 nginx 容器的 shell
kubectl exec -it two-containers -c nginx-container -- /bin/bash
在 shell 中,确认 nginx 还在运行。
root@two-containers:/# ps aux
输出类似于这样:
USER PID ... STAT START TIME COMMAND
root 1 ... Ss 21:12 0:00 nginx: master process nginx -g daemon off;
回忆一下,debian 容器在 nginx 的根目录下创建了 `index.html` 文件。
使用 `curl` 向 nginx 服务器发送一个 GET 请求:
root@two-containers:/# apt-get update
root@two-containers:/# apt-get install curl
root@two-containers:/# curl localhost
输出表示 nginx 提供了 debian 容器写的页面:
Hello from the debian container
{{% /capture %}}
{{% capture discussion %}}
## 讨论
Pod 能有多个容器的主要原因是为了支持辅助应用(helper applications),以协助主应用(primary application)。
辅助应用的典型例子是数据抽取,数据推送和代理。辅助应用和主应用经常需要相互通信。
就如这个练习所示,通信通常是通过共享文件系统完成的,或者,也通过回环网络接口 localhost 完成。
举个网络接口的例子,web 服务器带有一个协助程序用于拉取 Git 仓库的更新。
在本练习中的卷为 Pod 生命周期中的容器相互通信提供了一种方法。如果 Pod 被删除或者重建了,
任何共享卷中的数据都会丢失。
{{% /capture %}}
{{% capture whatsnext %}}
* 更多学习内容
[混合容器的方式](http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html)。
* 学习 [模块化架构的混合容器](http://www.slideshare.net/Docker/slideshare-burns)。
* 参见 [配置一个使用存储卷的 Pod](/docs/tasks/configure-pod-container/configure-volume-storage/)。
* 参见 [](/docs/api-reference/{{< param "version" >}}/#volume-v1-core)。
* 参见 [Pod](/docs/api-reference/{{< param "version" >}}/#pod-v1-core).
{{% /capture %}}
@@ -0,0 +1,318 @@
---
title: 配置对多集群的访问
content_template: templates/task
---
{{% capture overview %}}
本文展示如何使用配置文件来配置对多个集群的访问。 在将集群、用户和上下文定义在一个或多个配置文件中之后,用户可以使用 `kubectl config use-context` 命令快速地在集群之间进行切换。
{{< note >}}
**注意:** 用于配置集群访问的文件有时被称为 *kubeconfig 文件*
这是一种引用配置文件的通用方式,并不意味着存在一个名为 `kubeconfig` 的文件。
{{< /note >}}
{{% /capture %}}
{{% capture prerequisites %}}
需要安装 [`kubectl`](/docs/tasks/tools/install-kubectl/) 命令行工具。
{{% /capture %}}
{{% capture steps %}}
## 定义集群、用户和上下文
假设用户有两个集群,一个用于正式开发工作,一个用于其它临时用途(scratch)。
`development` 集群中,前端开发者在名为 `frontend` 的名字空间下工作,
存储开发者在名为 `storage` 的名字空间下工作。 在 `scratch` 集群中,
开发人员可能在默认名字空间下工作,也可能视情况创建附加的名字空间。 访问开发集群需要通过证书进行认证。 访问其它临时用途的集群需要通过用户名和密码进行认证。
创建名为 `config-exercise` 的目录。 在
`config-exercise` 目录中,创建名为 `config-demo` 的文件,其内容为:
```yaml
apiVersion: v1
kind: Config
preferences: {}
clusters:
- cluster:
name: development
- cluster:
name: scratch
users:
- name: developer
- name: experimenter
contexts:
- context:
name: dev-frontend
- context:
name: dev-storage
- context:
name: exp-scratch
```
配置文件描述了集群、用户名和上下文。 `config-demo` 文件中含有描述两个集群、两个用户和三个上下文的框架。
进入 `config-exercise` 目录。 输入以下命令,将群集详细信息添加到配置文件中:
```shell
kubectl config --kubeconfig=config-demo set-cluster development --server=https://1.2.3.4 --certificate-authority=fake-ca-file
kubectl config --kubeconfig=config-demo set-cluster scratch --server=https://5.6.7.8 --insecure-skip-tls-verify
```
将用户详细信息添加到配置文件中:
```shell
kubectl config --kubeconfig=config-demo set-credentials developer --client-certificate=fake-cert-file --client-key=fake-key-seefile
kubectl config --kubeconfig=config-demo set-credentials experimenter --username=exp --password=some-password
```
将上下文详细信息添加到配置文件中:
```shell
kubectl config --kubeconfig=config-demo set-context dev-frontend --cluster=development --namespace=frontend --user=developer
kubectl config --kubeconfig=config-demo set-context dev-storage --cluster=development --namespace=storage --user=developer
kubectl config --kubeconfig=config-demo set-context exp-scratch --cluster=scratch --namespace=default --user=experimenter
```
打开 `config-demo` 文件查看添加的详细信息。 也可以使用 `config view` 命令进行查看:
```shell
kubectl config --kubeconfig=config-demo view
```
输出展示了两个集群、两个用户和三个上下文:
```yaml
apiVersion: v1
clusters:
- cluster:
certificate-authority: fake-ca-file
server: https://1.2.3.4
name: development
- cluster:
insecure-skip-tls-verify: true
server: https://5.6.7.8
name: scratch
contexts:
- context:
cluster: development
namespace: frontend
user: developer
name: dev-frontend
- context:
cluster: development
namespace: storage
user: developer
name: dev-storage
- context:
cluster: scratch
namespace: default
user: experimenter
name: exp-scratch
current-context: ""
kind: Config
preferences: {}
users:
- name: developer
user:
client-certificate: fake-cert-file
client-key: fake-key-file
- name: experimenter
user:
password: some-password
username: exp
```
每个上下文包含三部分(集群、用户和名字空间),例如,
`dev-frontend` 上下文表明:使用 `developer` 用户的凭证来访问 `development` 集群的 `frontend` 名字空间。
设置当前上下文:
```shell
kubectl config --kubeconfig=config-demo use-context dev-frontend
```
现在当输入 `kubectl` 命令时,相应动作会应用于 `dev-frontend` 上下文中所列的集群和名字空间,同时,命令会使用 `dev-frontend` 上下文中所列用户的凭证。
使用 `--minify` 参数,来查看与当前上下文相关联的配置信息。
```shell
kubectl config --kubeconfig=config-demo view --minify
```
输出结果展示了 `dev-frontend` 上下文相关的配置信息:
```yaml
apiVersion: v1
clusters:
- cluster:
certificate-authority: fake-ca-file
server: https://1.2.3.4
name: development
contexts:
- context:
cluster: development
namespace: frontend
user: developer
name: dev-frontend
current-context: dev-frontend
kind: Config
preferences: {}
users:
- name: developer
user:
client-certificate: fake-cert-file
client-key: fake-key-file
```
现在假设用户希望在其它临时用途集群中工作一段时间。
将当前上下文更改为 `exp-scratch`
```shell
kubectl config --kubeconfig=config-demo use-context exp-scratch
```
现在用户 `kubectl` 下达的任何命令都将应用于 `scratch` 集群的默认名字空间。 同时,命令会使用 `exp-scratch` 上下文中所列用户的凭证。
查看更新后的当前上下文 `exp-scratch` 相关的配置:
```shell
kubectl config --kubeconfig=config-demo view --minify
```
最后,假设用户希望在 `development` 集群中的 `storage` 名字空间下工作一段时间。
将当前上下文更改为 `dev-storage`
```shell
kubectl config --kubeconfig=config-demo use-context dev-storage
```
查看更新后的当前上下文 `dev-storage` 相关的配置:
```shell
kubectl config --kubeconfig=config-demo view --minify
```
## 创建第二个配置文件
`config-exercise` 目录中,创建名为 `config-demo-2` 的文件,其中包含以下内容:
```yaml
apiVersion: v1
kind: Config
preferences: {}
contexts:
- context:
cluster: development
namespace: ramp
user: developer
name: dev-ramp-up
```
上述配置文件定义了一个新的上下文,名为 `dev-ramp-up`
## 设置 KUBECONFIG 环境变量
查看是否有名为 `KUBECONFIG` 的环境变量。 如有,保存 `KUBECONFIG` 环境变量当前的值,以便稍后恢复。
例如,在 Linux 中:
```shell
export KUBECONFIG_SAVED=$KUBECONFIG
```
`KUBECONFIG` 环境变量是配置文件路径的列表,该列表在 Linux 和 Mac 中以冒号分隔,在 Windows 中以分号分隔。 如果有 `KUBECONFIG` 环境变量,请熟悉列表中的配置文件。
临时添加两条路径到 `KUBECONFIG` 环境变量中。 例如,在 Linux 中:
```shell
export KUBECONFIG=$KUBECONFIG:config-demo:config-demo-2
```
`config-exercise` 目录中输入以下命令:
```shell
kubectl config view
```
输出展示了 `KUBECONFIG` 环境变量中所列举的所有文件合并后的信息。 特别地, 注意合并信息中包含来自 `config-demo-2` 文件的 `dev-ramp-up` 上下文和来自 `config-demo` 文件的三个上下文:
```yaml
contexts:
- context:
cluster: development
namespace: frontend
user: developer
name: dev-frontend
- context:
cluster: development
namespace: ramp
user: developer
name: dev-ramp-up
- context:
cluster: development
namespace: storage
user: developer
name: dev-storage
- context:
cluster: scratch
namespace: default
user: experimenter
name: exp-scratch
```
更多关于 kubeconfig 文件如何合并的信息,请参考
[使用 kubeconfig 文件组织集群访问](/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
## 探索 $HOME/.kube 目录
如果用户已经拥有一个集群,可以使用 `kubectl` 与集群进行交互。 那么很可能在 `$HOME/.kube` 目录下有一个名为 `config` 的文件。
进入 `$HOME/.kube` 目录, 看看那里有什么文件。 通常会有一个名为
`config` 的文件,目录中可能还有其他配置文件。 请简单地熟悉这些文件的内容。
## 将 $HOME/.kube/config 追加到 KUBECONFIG 环境变量中
如果有 `$HOME/.kube/config` 文件,并且还未列在 `KUBECONFIG` 环境变量中,
那么现在将它追加到 `KUBECONFIG` 环境变量中。
例如,在 Linux 中:
```shell
export KUBECONFIG=$KUBECONFIG:$HOME/.kube/config
```
在配置练习目录中输入以下命令,来查看当前 `KUBECONFIG` 环境变量中列举的所有文件合并后的配置信息:
```shell
kubectl config view
```
## 清理
`KUBECONFIG` 环境变量还原为原始值。 例如,在 Linux 中:
```shell
export KUBECONFIG=$KUBECONFIG_SAVED
```
{{% /capture %}}
{{% capture whatsnext %}}
* [使用 kubeconfig 文件组织集群访问](/docs/concepts/configuration/organize-cluster-access-kubeconfig/)
* [kubectl 配置](/docs/user-guide/kubectl/{{< param "version" >}}/)
{{% /capture %}}
@@ -0,0 +1,126 @@
---
approvers:
- bprashanth
- davidopp
title: 配置你的云平台防火墙
---
许多云服务商(比如 Google Compute Engine)定义防火墙以防止服务无意间暴露到 internet 上。
当暴露服务给外网时,你可能需要在防火墙上开启一个或者更多的端口来支持服务。
本文描述了这个过程,以及其他云服务商的具体信息。
## 负载均衡(LoadBalancer)服务的访问限制
当以 `spec.type: LoadBalancer` 使用服务时,你可以使用 `spec.loadBalancerSourceRanges` 指定允许访问负载均衡的 IP 段。
这个字段采用 CIDR 的 IP 段,Kubernetes 会使用这个段配置防火墙。支持这个功能的平台目前有 Google Compute EngineGoogle Kubernetes Engine 和 AWS。
如果云服务商不支持这个功能,这个字段会被忽略。
假设 10.0.0.0/8 是内部的子网。在下面这个例子中,会创建一个只有集群内部 ip 可以访问的负载均衡器。
集群外部的客户端是无法访问这个负载均衡器的。
```yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
ports:
- port: 8765
targetPort: 9376
selector:
app: example
type: LoadBalancer
loadBalancerSourceRanges:
- 10.0.0.0/8
```
这个例子中,会创建一个只能被 IP 为 130.211.204.1 和 130.211.204.2 的客户端访问的负载据衡器。
```yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
ports:
- port: 8765
targetPort: 9376
selector:
app: example
type: LoadBalancer
loadBalancerSourceRanges:
- 130.211.204.1/32
- 130.211.204.2/32
```
### 谷歌计算引擎(Google Compute Engine
当以 `spec.type: LoadBalancer` 使用服务时,防火墙会被自动打开。
然而,当以 `spec.type: NodePort` 使用服务时,防火墙默认 *不会* 被打开。
Google Compute Engine 的防火墙文档在[别处](https://cloud.google.com/compute/docs/networking#firewalls_1)。
你可以使用 `gcloud` 命令行工具添加一个防火墙:
```shell
$ gcloud compute firewall-rules create my-rule --allow=tcp:<port>
```
**注意**
使用 Google Compute Engine 平台的防火墙时有一个重要的关于安全的注意点:
在 Kubernetes v1.0.0 版本,GCE 防火墙是定义按虚拟机(VM)来的,而不是按 ip 来的。
这就意味着当你在防火墙上打开一个服务端口时,任何在那台虚拟机 IP 上的同一端口的服务
都有被外部访问的潜在可能。注意,这对于其他 Kubernetes 服务来说不是问题,因为他们监
听的 IP 地址与主机节点的外部 IP 地址不同。
考虑一下:
* 你创建了一个服务,使用了外部服务均衡 (IP 地址为 1.2.3.4) 和 80 端口。
* 你在防火墙上为集群的所有节点都打开了 80 端口,所以外部的服务可以向你的
服务发送数据包。
* 你又在虚拟机(IP 为2.3.4.5)上使用 80 端口启动了一台 nginx 服务器.
这个 nginx 在虚拟机的外部 IP 地址上也被暴露到了 internet 上。
因此,在 Google Compute Engine 或者 Google Kubernetes Engine 上开启防火墙端口时请
小心。你可能无意间把其他服务也暴露给了 internet。
这个问题会在 Kubernetes 后续版本中被修复。
### 其他云服务商
即将更新
@@ -0,0 +1,224 @@
---
title: 使用 Service 把前端连接到后端
content_template: templates/tutorial
---
{{% capture overview %}}
本任务会描述如何创建前端微服务和后端微服务。后端微服务是一个 hello 欢迎程序。
前端和后端的连接是通过 Kubernetes 服务对象(Service object)完成的。
{{% /capture %}}
{{% capture objectives %}}
* 使用部署对象(Deployment object)创建并运行一个微服务
* 从后端将流量路由到前端
* 使用服务对象把前端应用连接到后端应用
{{% /capture %}}
{{% capture prerequisites %}}
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
* 本任务使用 [外部负载均衡服务](/docs/tasks/access-application-cluster/create-external-load-balancer/)
所以需要对应的可支持此功能的环境。如果你的环境不能支持,你可以使用
[NodePort](/docs/user-guide/services/#type-nodeport) 类型的服务代替。
{{% /capture %}}
{{% capture lessoncontent %}}
### 使用部署对象(Deployment)创建后端
后端是一个简单的 hello 欢迎微服务应用。这是后端应用的 Deployment 配置文件:
{{< code file="hello.yaml" >}}
创建后端 Deployment
```
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/hello.yaml
```
查看后端的 Deployment 信息:
```
kubectl describe deployment hello
```
输出类似于:
```
Name: hello
Namespace: default
CreationTimestamp: Mon, 24 Oct 2016 14:21:02 -0700
Labels: app=hello
tier=backend
track=stable
Selector: app=hello,tier=backend,track=stable
Replicas: 7 updated | 7 total | 7 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: <none>
NewReplicaSet: hello-3621623197 (7/7 replicas created)
Events:
...
```
### 创建后端服务对象(Service object
前端连接到后端的关键是 Service。Service 创建一个固定 IP 和 DNS 解析名入口,
使得后端微服务可达。Service 使用 selector 标签来寻找目标 Pod。
首先,浏览 Service 的配置文件:
{{< code file="hello-service.yaml" >}}
配置文件中,你可以看到 Service 将流量路由到包含 `app: hello``tier: backend` 标签的 Pod。
创建 `hello` Service
```
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/hello-service.yaml
```
此时,你已经有了一个在运行的后端 Deployment,你也有了一个 Service 用于路由网络流量。
### 创建前端应用
既然你已经有了后端应用,你可以创建一个前端应用连接到后端。前端应用通过 DNS 名连接到后端的工作 Pods。
DNS 名是 "hello",也就是 Service 配置文件中 `name` 字段的值。
前端 Deployment 中的 Pods 运行一个 nginx 镜像,这个已经配置好镜像去寻找后端的 hello Service。
只是 nginx 的配置文件:
{{< code file="frontend/frontend.conf" >}}
与后端类似,前端用包含一个 Deployment 和一个 Service。Service 的配置文件包含了 `type: LoadBalancer`
也就是说,Service 会使用你的云服务商的默认负载均衡设备。
{{< code file="frontend.yaml" >}}
创建前端 Deployment 和 Service
```
kubectl create -f https://k8s.io/docs/tasks/access-application-cluster/frontend.yaml
```
通过输出确认两个资源都已经被创建:
```
deployment "frontend" created
service "frontend" created
```
**注意**:这个 nginx 配置文件是被打包在 [容器镜像](/docs/tasks/access-application-cluster/frontend/Dockerfile) 里的。
更好的方法是使用 [ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/),这样的话你可以更轻易地更改配置。
### 与前端 Service 交互
一旦你创建了 LoadBalancer 类型的 Service,你可以使用这条命令查看外部 IP:
```
kubectl get service frontend
```
外部 IP 字段的生成可能需要一些时间。如果是这种情况,外部 IP 会显示为 `<pending>`
```
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend 10.51.252.116 <pending> 80/TCP 10s
```
使用相同的命令直到它显示外部 IP 地址:
```
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend 10.51.252.116 XXX.XXX.XXX.XXX 80/TCP 1m
```
### 通过前端发送流量
前端和后端已经完成连接了。你可以使用 curl 命令通过你的前端 Service 的外部 IP 访问服务端点。
```
curl http://<EXTERNAL-IP>
```
后端生成的消息输出如下:
```
{"message":"Hello"}
```
{{% /capture %}}
{{% capture whatsnext %}}
* 了解更多 [Services](/docs/concepts/services-networking/service/)
* 了解更多 [ConfigMaps](/docs/tasks/configure-pod-container/configure-pod-configmap/)
{{% /capture %}}
@@ -0,0 +1,34 @@
kind: Service
apiVersion: v1
metadata:
name: frontend
spec:
selector:
app: hello
tier: frontend
ports:
- protocol: "TCP"
port: 80
targetPort: 80
type: LoadBalancer
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
template:
metadata:
labels:
app: hello
tier: frontend
track: stable
spec:
containers:
- name: nginx
image: "gcr.io/google-samples/hello-frontend:1.0"
lifecycle:
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
@@ -0,0 +1,11 @@
upstream hello {
server hello;
}
server {
listen 80;
location / {
proxy_pass http://hello;
}
}
@@ -0,0 +1,12 @@
kind: Service
apiVersion: v1
metadata:
name: hello
spec:
selector:
app: hello
tier: backend
ports:
- protocol: TCP
port: 80
targetPort: http
@@ -0,0 +1,19 @@
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: hello
spec:
replicas: 7
template:
metadata:
labels:
app: hello
tier: backend
track: stable
spec:
containers:
- name: hello
image: "gcr.io/google-samples/hello-go-gke:1.0"
ports:
- name: http
containerPort: 80
@@ -0,0 +1,33 @@
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis
redis-sentinel: "true"
role: master
name: redis-master
spec:
containers:
- name: master
image: k8s.gcr.io/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.1"
volumeMounts:
- mountPath: /redis-master-data
name: data
- name: sentinel
image: kubernetes/redis:v1
env:
- name: SENTINEL
value: "true"
ports:
- containerPort: 26379
volumes:
- name: data
emptyDir: {}
@@ -0,0 +1,27 @@
apiVersion: v1
kind: Pod
metadata:
name: two-containers
spec:
restartPolicy: Never
volumes:
- name: shared-data
emptyDir: {}
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
- name: debian-container
image: debian
volumeMounts:
- name: shared-data
mountPath: /pod-data
command: ["/bin/sh"]
args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]
@@ -0,0 +1,111 @@
---
title: 访问集群上运行的服务
redirect_from:
- "/docs/user-guide/accessing-the-cluster/"
- "/docs/user-guide/accessing-the-cluster.html"
content_template: templates/task
---
{{% capture overview %}}
本文展示了如何连接 Kubernetes 集群上运行的服务。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% 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 的方式可能不能理解代理路径前缀。
{{% /capture %}}
@@ -0,0 +1,412 @@
---
approvers:
- 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"
content_template: templates/task
---
{{% capture overview %}}
本示例展示了在一个 namespace 中控制资源用量的典型设置。
本文展示了以下资源的使用: [Namespace](/docs/admin/namespaces), [ResourceQuota](/docs/concepts/policy/resource-quotas/) 和 [LimitRange](/docs/tasks/configure-pod-container/limit-range/)。
{{% /capture %}}
{{% capture prerequisites %}}
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% 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 上的预期持久程度来为它们指定配额。
{{% /capture %}}
{{% capture discussion %}}
## 总结
消耗节点 cpu 和 memory 资源的动作受到 namespace 配额定义的硬性配额限制的管制。
任意消耗那些资源的动作能够被调整,或者获得一个 namespace 级别的默认值以符合你最终的目标。
可以基于服务质量或者在你集群中节点上的预期持久程度来分配配额。
{{% /capture %}}
@@ -0,0 +1,75 @@
---
approvers:
- caseydavenport
title: 使用 Calico 来提供 NetworkPolicy
content_template: templates/task
---
{{% capture overview %}}
本页展示怎么样使用 Calico 来提供 NetworkPolicy
{{% /capture %}}
{{% capture prerequisites %}}
* 为 Kubernetes 安装 Calico
{{% /capture %}}
{{% capture steps %}}
## 使用 Calico 部署一个集群
使用如下命令,您可以在默认的 [GCE 部署环境中](/docs/getting-started-guides/gce) 部署一个使用 Calico 来提供网络策略的集群:
```shell
export NETWORK_POLICY_PROVIDER=calico
export KUBE_NODE_OS_DISTRIBUTION=debian
curl -sS https://get.k8s.io | bash
```
如果希望了解其它的部署选项,请您参考 [Calico 项目文档](http://docs.projectcalico.org/)
{{% /capture %}}
{{% capture discussion %}}
## 理解 Calico 组件
部署使用 Calico 的集群其实是增加了支持 Kubernetes NetworkPolicy 的 Pods 这些 Pods 运行在 `kube-system` 命名空间下。
使用如下方式去查看这些运行的 Pods:
```shell
kubectl get pods --namespace=kube-system
```
您可以看到类似下面这样的一个 Pods 列表:
```console
NAME READY STATUS RESTARTS AGE
calico-node-kubernetes-minion-group-jck6 1/1 Running 0 46m
calico-node-kubernetes-minion-group-k9jy 1/1 Running 0 46m
calico-node-kubernetes-minion-group-szgr 1/1 Running 0 46m
calico-policy-controller-65rw1 1/1 Running 0 46m
...
```
主要有两种组件
- 在集群的每个节点上都会运行一个以 `calico-node` 开头命名的 Pod,用于配置 iptables 去实现那些机器上 Pods 的出/入网络策略
- 整个集群环境只有一个以 `calico-policy-controller` 开头命名的 Pod,用于从 Kubernetes API 中读取策略和标签信息,适当的对 Calico 进行配置
{{% /capture %}}
{{% capture whatsnext %}}
集群部署完成之后,您可以通过 [NetworkPolicy 入门指南](/docs/getting-started-guides/network-policy/walkthrough)去尝试使用 Kubernetes NetworkPolicy
{{% /capture %}}
@@ -0,0 +1,95 @@
---
title: 改变默认 StorageClass
content_template: templates/task
---
{{% capture overview %}}
本文展示了如何改变默认的 Storage Class,它用于为没有特殊需求的 PersistentVolumeClaims 配置 volumes。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% 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
{{% /capture %}}
{{% capture whatsnext %}}
* 了解更多关于 [StorageClasses](/docs/concepts/storage/persistent-volumes/)。
{{% /capture %}}
@@ -0,0 +1,81 @@
---
title: 更改 PersistentVolume 的回收策略
content_template: templates/task
---
{{% capture overview %}}
本文展示了如何更改 Kubernetes PersistentVolume 的回收策略。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 为什么要更改 PersistentVolume 的回收策略
`PersistentVolumes` 可以有多种回收策略,包括 "Retain"、"Recycle" 和 "Delete"。对于动态配置的 `PersistentVolumes` 来说,默认回收策略为 "Delete"。这表示当用户删除对应的 `PersistentVolumeClaim` 时,动态配置的 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` 时,它不会被自动删除。
{{% /capture %}}
{{% capture whatsnext %}}
* 了解更多关于 [PersistentVolumes](/docs/concepts/storage/persistent-volumes/)的信息。
* 了解更多关于 [PersistentVolumeClaims](/docs/user-guide/persistent-volumes/#persistentvolumeclaims) 的信息。
### 参考
* [PersistentVolume](/docs/api-reference/{{< param "version" >}}/#persistentvolume-v1-core)
* [PersistentVolumeClaim](/docs/api-reference/{{< param "version" >}}/#persistentvolumeclaim-v1-core)
* 查阅 [PersistentVolumeSpec](/docs/api-reference/{{< param "version" >}}/#persistentvolumeclaim-v1-core) 的 `persistentVolumeReclaimPolicy` 字段。
{{% /capture %}}
@@ -0,0 +1,226 @@
---
approvers:
- lavalamp
- thockin
title: 集群管理
---
{{< 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 Kubernetes Engine 集群
Google Kubernetes Engine 自动升级 master 组件(例如 `kube-apiserver``kube-scheduler`)至最新版本。它还负责 master 运行的操作系统和其它组件。
节点升级过程由用户初始化,[Google Kubernetes Engine 文档](https://cloud.google.com/kubernetes-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 或者 Google Kubernetes Engine,这将通过调整管理节点的实例组的大小完成。在 [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 或者 Google Kubernetes Engine,您可以配置您的集群,使其能够基于 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)或节点池(Google Kubernetes Engine)上配置。
如果您使用 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
```
在 Google Kubernetes Engine 上,您可以在创建、更新集群或创建一个特别的节点池(您希望自动伸缩的)时,通过给对应的 `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,13 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-cpu-demo-2
spec:
containers:
- name: constraints-cpu-demo-2-ctr
image: nginx
resources:
limits:
cpu: "1.5"
requests:
cpu: "500m"
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-cpu-demo-4
spec:
containers:
- name: constraints-cpu-demo-4-ctr
image: nginx
resources:
limits:
cpu: "800m"
requests:
cpu: "100m"
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-cpu-demo-4
spec:
containers:
- name: constraints-cpu-demo-4-ctr
image: vish/stress
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-cpu-demo
spec:
containers:
- name: constraints-cpu-demo-ctr
image: nginx
resources:
limits:
cpu: "800m"
requests:
cpu: "500m"
@@ -0,0 +1,11 @@
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-min-max-demo-lr
spec:
limits:
- max:
cpu: "800m"
min:
cpu: "200m"
type: Container
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo-2
spec:
containers:
- name: default-cpu-demo-2-ctr
image: nginx
resources:
limits:
cpu: "1"
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo-3
spec:
containers:
- name: default-cpu-demo-3-ctr
image: nginx
resources:
requests:
cpu: "0.75"
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Pod
metadata:
name: default-cpu-demo
spec:
containers:
- name: default-cpu-demo-ctr
image: nginx
@@ -0,0 +1,11 @@
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-limit-range
spec:
limits:
- default:
cpu: 1
defaultRequest:
cpu: 0.5
type: Container
@@ -0,0 +1,145 @@
---
title: 控制节点上的CPU管理策略
---
{{< toc >}}
按照设计,Kubernetes 对 pod 执行相关的很多方面进行了抽象,使得用户不必关心。然而,为了正常运行,有些工作负载要求在延迟和/或性能方面有更强的保证。 为此,kubelet 提供方法来实现更复杂的负载放置策略,同时保持抽象,避免显式的放置指令。
## CPU 管理策略
默认情况下,kubelet 使用 [CFS 配额](https://en.wikipedia.org/wiki/Completely_Fair_Scheduler) 来执行 pod 的 CPU 约束。当节点上运行了很多 CPU 密集的 pod 时,工作负载可能会迁移到不同的 CPU 核,这取决于调度时 pod 是否被扼制,以及哪些 CPU 核是可用的。许多工作负载对这种迁移不敏感,因此无需任何干预即可正常工作。
然而,有些工作负载的性能明显地受到 CPU 缓存亲和性以及调度延迟的影响,对此,kubelet 提供了可选的 CPU 管理策略,来确定节点上的一些分配偏好。
### 配置
CPU 管理器(CPU Manager)作为 alpha 特性引入 Kubernetes 1.8 版本。 必须在 kubelet 特性开关中显式启用:
`--feature-gates=CPUManager=true`
CPU 管理策略通过 kubelet 参数 `--cpu-manager-policy` 来指定,
有两种支持策略:
* `none`:默认策略,表示现有的调度行为。
* `static`:允许为节点上具有某些资源特征的 pod 赋予增强的 CPU 亲和性和独占性。
CPU管理器定期通过 CRI 写入资源更新,以保证内存中 CPU 分配与 cgroupfs 一致。同步频率通过新增的 Kubelet 配置参数
`--cpu-manager-reconcile-period` 来设置。 如不指定,默认与 `--node-status-update-frequency` 的周期相同。
### None 策略
`none` 策略显式地启用现有的默认 CPU 亲和方案,不提供操作系统调度器默认行为之外的亲和性策略。 通过 CFS 配额来实现
[Guaranteed pods](/docs/tasks/configure-pod-container/quality-service-pod/) 的 CPU 使用限制。
### Static 策略
`static` 策略针对具有整数型 CPU `requests` 的 pod ,它允许该类 pod 中的容器访问节点上的独占 CPU 资源。这种独占性是使用 [cpuset cgroup 控制器](https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt) 来实现的。
{{< note >}}
**注意:** 诸如容器运行时和 kubelet 本身的系统服务可以继续在这些独占 CPU 上运行。独占性仅针对其他 pod。
{{< /note >}}
{{< note >}}
**注意:** 该策略的 alpha 版本不保证 Kubelet 重启前后的静态独占性分配。
{{< /note >}}
该策略管理一个共享 CPU 资源池,最初,该资源池包含节点上所有的 CPU 资源。可用的独占性 CPU 资源数量等于节点的 CPU 总量减去通过 `--kube-reserved``--system-reserved` 参数保留的 CPU 。通过这些参数预留的 CPU 是以整数方式,按物理内核 ID 升序从初始共享池获取的。 共享池是 `BestEffort``Burstable` pod 运行的 CPU 集合。`Guaranteed` pod 中的容器,如果声明了非整数值的 CPU `requests` ,也将运行在共享池的 CPU 上。只有 `Guaranteed` pod 中,指定了整数型 CPU `requests` 的容器,才会被分配独占 CPU 资源。
{{< note >}}
**注意:** 当启用 static 策略时,要求使用 `--kube-reserved` 和/或 `--system-reserved` 来保证预留的 CPU 值大于零。 这是因为零预留 CPU 值可能使得共享池变空。
{{< /note >}}
`Guaranteed` pod 调度到节点上时,如果其容器符合静态分配要求,相应的 CPU 会被从共享池中移除,并放置到容器的 cpuset 中。因为这些容器所使用的 CPU 受到调度域本身的限制,所以不需要使用 CFS 配额来进行 CPU 的绑定。换言之,容器 cpuset 中的 CPU 数量与 pod 规格中指定的整数型 CPU `limit` 相等。这种静态分配增强了 CPU 亲和性,减少了 CPU 密集的工作负载在节流时引起的上下文切换。
考虑以下 Pod 规格的容器:
```yaml
spec:
containers:
- name: nginx
image: nginx
```
该 pod 属于 `BestEffort` 服务质量类型,因为其未指定 `requests`
`limits` 值。 所以该容器运行在共享 CPU 池中。
```yaml
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
```
该 pod 属于 `Burstable` 服务质量类型,因为其资源 `requests` 不等于
`limits` 且未指定 `cpu` 数量。所以该容器运行在共享 CPU 池中。
```yaml
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
requests:
memory: "100Mi"
cpu: "1"
```
该 pod 属于 `Burstable` 服务质量类型,因为其资源 `requests` 不等于 `limits`。所以该容器运行在共享 CPU 池中。
```yaml
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
requests:
memory: "200Mi"
cpu: "2"
```
该 pod 属于 `Guaranteed` 服务质量类型,因为其 `requests` 值与 `limits`相等。
同时,容器对 CPU 资源的限制值是一个大于或等于 1 的整数值。所以,该 `nginx` 容器被赋予 2 个独占 CPU。
```yaml
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "1.5"
requests:
memory: "200Mi"
cpu: "1.5"
```
该 pod 属于 `Guaranteed` 服务质量类型,因为其 `requests` 值与 `limits`相等。但是容器对 CPU 资源的限制值是一个小数。所以该容器运行在共享 CPU 池中。
```yaml
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
```
该 pod 属于 `Guaranteed` 服务质量类型,因其指定了 `limits` 值,
同时当未显式指定时,`requests` 值被设置为与 `limits` 值相等。同时,容器对 CPU 资源的限制值是一个大于或等于 1 的整数值。所以,该 `nginx` 容器被赋予 2 个独占 CPU。
@@ -0,0 +1,259 @@
---
approvers:
- derekwaynecarr
- janetkuo
title: 设置 Pod CPU 和内存限制
redirect_from:
- "/docs/admin/limitrange/"
- "/docs/admin/limitrange/index.html"
- "/docs/tasks/configure-pod-container/limit-range/"
- "/docs/tasks/configure-pod-container/limit-range.html"
content_template: templates/task
---
{{% capture overview %}}
默认情况下,Pod 运行没有限制 CPU 使用量和内存使用量。
这意味着当前系统中的任何 Pod 能够使用该 Pod 运行节点的所有 CPU 和内存资源。
这个例子演示了如何限制 Kubernetes [Namespace](/docs/tasks/administer-cluster/namespaces-walkthrough/),以此来控制每个 Pod 的最小/最大资源限额。
另外,这个例子演示了当终端用户没有为 Pod 设置资源限额时,如何使用默认的资源限额。
{{% /capture %}}
{{% capture prerequisites %}}
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 创建 Namespace
这个例子将使用一个自定义的 Namespace 来演示相关的概念。
让我们创建一个名称为 limit-example 的 Namespace
```shell
$ kubectl create namespace limit-example
namespace "limit-example" created
```
可以看到 `kubectl` 命令将打印出被创建或修改的资源的类型和名称,也会在后面的命令中使用到:
```shell
$ kubectl get namespaces
NAME STATUS AGE
default Active 51s
limit-example Active 45s
```
## 对 Namespace 应用限制
在我们的 Namespace 中创建一个简单的限制:
```shell
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/limits.yaml --namespace=limit-example
limitrange "mylimits" created
```
让我们查看一下在该 Namespace 中被强加的限制:
```shell
$ kubectl describe limits mylimits --namespace=limit-example
Name: mylimits
Namespace: limit-example
Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio
---- -------- --- --- --------------- ------------- -----------------------
Pod cpu 200m 2 - - -
Pod memory 6Mi 1Gi - - -
Container cpu 100m 2 200m 300m -
Container memory 3Mi 1Gi 100Mi 200Mi -
```
在这个场景下,指定了如下限制:
1. 如果一个资源被指定了最大约束(在该例子中为 2 CPU 和 1Gi 内存),则必须为跨所有容器的该资源指定限制(limits)。
当尝试创建该 Pod 时,指定限额失败将导致一个验证错误。
注意,一个默认的限额通过在 `limits.yaml` 文件中的 *default* 来设置(300m CPU 和 200Mi 内存)。
2. 如果一个资源被指定了最小约束(在该例子中为 100m CPU 和 3Mi 内存),则必须跨所有容器的该资源指定请求(requests)。
当尝试创建该 Pod 时,指定的请求失败将导致一个验证错误。
注意,一个默认的请求的值通过在 `limits.yaml` 文件中的 *defaultRequest* 来设置(200m CPU 和 100Mi 内存)。
3. 对任意 Pod,所有容器内存 requests 值之和必须 >= 6Mi,所有容器内存 limits 值之和必须 <= 1Gi
所有容器 CPU requests 值之和必须 >= 200m,所有容器 CPU limits 值之和必须 <= 2。
## 创建时强制设置限制
当集群中的 Pod 创建和更新时,在一个 Namespace 中列出的限额是强制设置的。
如果将该限额修改成一个不同的值范围,它不会影响先前在该 Namespace 中创建的 Pod。
如果资源(CPU 或内存)被设置限额,用户将在创建时得到一个错误,并指出了错误的原因。
首先让我们启动一个 [Deployment](/docs/concepts/workloads/controllers/deployment/),它创建一个单容器 Pod,演示了如何将默认值应用到每个 Pod 上:
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example
deployment "nginx" created
```
注意,在 >= v1.2 版本的 Kubernetes 集群中,`kubectl run` 创建了名称为 “nginx” 的 Deployment。如果在老版本的集群上运行,相反它会创建 ReplicationController。
如果想要获取老版本的行为,使用 `--generator=run/v1` 选项来创建 ReplicationController。查看 [`kubectl run`](/docs/user-guide/kubectl/v1.6/#run) 获取更多详细信息。
Deployment 管理单容器 Pod 的 1 个副本。让我们看一下它是如何管理 Pod 的。首先,查找到 Pod 的名称:
```shell
$ kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx-2040093540-s8vzu 1/1 Running 0 11s
```
以 yaml 输出格式来打印这个 Pod,然后 `grep` 其中的 `resources` 字段。注意,您自己的 Pod 的名称将不同于上面输出的:
```shell
$ kubectl get pods nginx-2040093540-s8vzu --namespace=limit-example -o yaml | grep resources -C 8
resourceVersion: "57"
selfLink: /api/v1/namespaces/limit-example/pods/nginx-2040093540-ivimu
uid: 67b20741-f53b-11e5-b066-64510658e388
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: 300m
memory: 200Mi
requests:
cpu: 200m
memory: 100Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
```
注意,我们的 Nginx 容器已经使用了 Namespace 的默认 CPU 和内存资源的 *limits**requests*
让我们创建一个 Pod,它具有一个请求 3 CPU 核心的容器,这超过了被允许的限额:
```shell
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/invalid-pod.yaml --namespace=limit-example
Error from server: error when creating "http://k8s.io/docs/tasks/configure-pod-container/invalid-pod.yaml": Pod "invalid-pod" is forbidden: [Maximum cpu usage per Pod is 2, but limit is 3., Maximum cpu usage per Container is 2, but limit is 3.]
```
让我们创建一个 Pod,使它在允许的最大限额范围之内:
```shell
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/valid-pod.yaml --namespace=limit-example
pod "valid-pod" created
```
现在查看该 Pod 的 resources 字段:
```shell
$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
uid: 3b1bfd7a-f53c-11e5-b066-64510658e388
spec:
containers:
- image: k8s.gcr.io/serve_hostname
imagePullPolicy: Always
name: kubernetes-serve-hostname
resources:
limits:
cpu: "1"
memory: 512Mi
requests:
cpu: "1"
memory: 512Mi
```
注意到这个 Pod 显式地指定了资源 *limits**requests*,所以它不会使用该 Namespace 的默认值。
注意:在物理节点上默认安装的 Kubernetes 集群中,CPU 资源的 *limits* 是被强制使用的,该 Kubernetes 集群运行容器,除非管理员在部署 kublet 时使用了如下标志:
```shell
$ kubelet --help
Usage of kubelet
....
--cpu-cfs-quota[=true]: Enable CPU CFS quota enforcement for containers that specify CPU limits
$ kubelet --cpu-cfs-quota=false ...
```
## 清理
基于使用的该示例来清理资源,可以通过如下命令删除名称为 limit-example 的 Namespace
```shell
$ kubectl delete namespace limit-example
namespace "limit-example" deleted
$ kubectl get namespaces
NAME STATUS AGE
default Active 12m
```
{{% /capture %}}
{{% capture discussion %}}
## 设置资限额制的动机
可能由于对资源使用的各种原因,用户希望对单个 Pod 的资源总量进行强制限制。
例如:
1. 集群中每个节点有 2GB 内存。集群操作员不想接受内存需求大于 2GB 的 Pod,因为集群中没有节点能支持这个要求。
为了避免 Pod 永远无法被调度到集群中的节点上,操作员会选择去拒绝超过 2GB 内存作为许可控制的 Pod。
2. 一个集群被一个组织内部的 2 个团体共享,分别作为生产和开发工作负载来运行。
生产工作负载可能消耗多达 8GB 内存,而开发工作负载可能消耗 512MB 内存。
集群操作员为每个工作负载创建了一个单独的 Namespace,为每个 Namespace 设置了限额。
3. 用户会可能创建一个资源消耗低于机器容量的 Pod。剩余的空间可能太小但很有用,然而对于整个集群来说浪费的代价是足够大的。
结果集群操作员会希望设置限额:为了统一调度和限制浪费,Pod 必须至少消耗它们平均节点大小 20% 的内存和 CPU。
## 总结
想要限制单个容器或 Pod 消耗资源总量的集群操作员,能够为每个 Kubernetes Namespace 定义可允许的范围。
在没有任何明确指派的情况下,Kubernetes 系统能够使用默认的资源 *limits**requests*,如果需要的话,限制一个节点上的 Pod 的资源总量。
{{% /capture %}}
{{% capture whatsnext %}}
* 查看 [LimitRange 设计文档](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/resource-management/admission_control_limit_range.md) 获取更多信息。
* 查看 [资源](/docs/concepts/configuration/manage-compute-resources-container/) 获取关于 Kubernetes 资源模型的详细描述。
{{% /capture %}}
@@ -0,0 +1,148 @@
---
approvers:
- caseydavenport
- danwinship
title: 声明网络策略
content_template: templates/task
---
{{% capture overview %}}
本文可以帮助您开始使用 Kubernetes 的 [NetworkPolicy API](/docs/concepts/services-networking/network-policies/) 声明网络策略去管理 Pod 之间的通信
{{% /capture %}}
{{% capture prerequisites %}}
您首先需要有一个支持网络策略的 Kubernetes 集群。已经有许多支持 NetworkPolicy 的网络提供商,包括:
* [Calico](/docs/tasks/configure-pod-container/calico-network-policy/)
* [Romana](/docs/tasks/configure-pod-container/romana-network-policy/)
* [Weave 网络](/docs/tasks/configure-pod-container/weave-network-policy/)
**注意**:以上列表是根据产品名称按字母顺序排序,而不是按推荐或偏好排序。下面示例对于使用了上面任何提供商的 Kubernetes 集群都是有效的
{{% /capture %}}
{{% capture steps %}}
## 创建一个`nginx` deployment 并且通过服务将其暴露
为了查看 Kubernetes 网络策略是怎样工作的,可以从创建一个`nginx` deployment 并且通过服务将其暴露开始
```console
$ kubectl run nginx --image=nginx --replicas=2
deployment "nginx" created
$ kubectl expose deployment nginx --port=80
service "nginx" exposed
```
在 default 命名空间下运行了两个 `nginx` pod,而且通过一个名字为 `nginx` 的服务进行了暴露
```console
$ kubectl get svc,pod
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/kubernetes 10.100.0.1 <none> 443/TCP 46m
svc/nginx 10.100.0.16 <none> 80/TCP 33s
NAME READY STATUS RESTARTS AGE
po/nginx-701339712-e0qfq 1/1 Running 0 35s
po/nginx-701339712-o00ef 1/1 Running 0 35s
```
## 测试服务能够被其它的 pod 访问
您应该可以从其它的 pod 访问这个新的 `nginx` 服务。为了验证它,从 default 命名空间下的其它 pod 来访问该服务。请您确保在该命名空间下没有执行孤立动作。
启动一个 busybox 容器,然后在容器中使用 `wget` 命令去访问 `nginx` 服务:
```console
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
Waiting for pod default/busybox-472357175-y0m47 to be running, status is Pending, pod ready: false
Hit enter for command prompt
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.100.0.16:80)
/ #
```
## 限制访问 `nginx` 服务
如果说您想限制 `nginx` 服务,只让那些拥有标签 `access: true` 的 pod 访问它,那么您可以创建一个只允许从那些 pod 连接的 `NetworkPolicy`
```yaml
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
run: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
```
## 为服务指定策略
使用 kubectl 工具根据上面的 nginx-policy.yaml 文件创建一个 NetworkPolicy
```console
$ kubectl create -f nginx-policy.yaml
networkpolicy "access-nginx" created
```
## 当访问标签没有定义时测试访问服务
如果您尝试从没有设定正确标签的 pod 中去访问 `nginx` 服务,请求将会超时:
```console
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
Waiting for pod default/busybox-472357175-y0m47 to be running, status is Pending, pod ready: false
Hit enter for command prompt
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.100.0.16:80)
wget: download timed out
/ #
```
## 定义访问标签后再次测试
创建一个拥有正确标签的 pod,您将看到请求是被允许的:
```console
$ kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh
Waiting for pod default/busybox-472357175-y0m47 to be running, status is Pending, pod ready: false
Hit enter for command prompt
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.100.0.16:80)
/ #
```
{{% /capture %}}
@@ -0,0 +1,162 @@
---
approvers:
- bowei
- zihongz
title: 在 Kubernetes 中配置私有 DNS 和上游域名服务器
content_template: templates/task
---
{{% capture overview %}}
本页展示了如何添加自定义私有 DNS 域(存根域)和上游域名服务器。
{{% /capture %}}
{{% capture prerequisites %}}
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
* Kubernetes 1.6 及其以上版本。
* 集群必须配置使用 `kube-dns` 插件。
{{% /capture %}}
{{% capture steps %}}
## 配置存根域和上游 DNS 服务器
通过为 kube-dns `kube-system:kube-dns`)提供 ConfigMap,集群管理员能够指定自定义存根域和上游域名服务器。
例如,下面的 ConfigMap 建立了一个 DNS 配置,它具有一个单独的存根域和两个上游域名服务器:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{“acme.local”: [“1.2.3.4”]}
upstreamNameservers: |
[“8.8.8.8”, “8.8.4.4”]
```
按如上说明,具有 “.acme.local” 后缀的 DNS 请求被转发到 DNS 1.2.3.4。Google 公共 DNS服务器 为上游查询提供服务。
下表描述了具有特定域名的查询如何映射到它们的目标 DNS 服务器:
| 域名 | 响应查询的服务器 |
| ----------- | -------------------------- |
| kubernetes.default.svc.cluster.local| kube-dns |
| foo.acme.local| 自定义 DNS (1.2.3.4) |
| widget.com | 上游 DNS (8.8.8.8, 8.8.4.4,其中之一) |
查看 [ConfigMap 选项](#configmap-options) 获取更多关于配置选项格式的详细信息。
{{% /capture %}}
{{% capture discussion %}}
## 理解 Kubernetes 中名字解析
可以为每个 Pod 设置 DNS 策略。
当前 Kubernetes 支持两种 Pod 特定的 DNS 策略:“Default” 和 “ClusterFirst”。
可以通过 `dnsPolicy` 标志来指定这些策略。
*注意:“Default” 不是默认的 DNS 策略。如果没有显式地指定 `dnsPolicy`,将会使用 “ClusterFirst”。*
### "Default" DNS 策略
如果 `dnsPolicy` 被设置为 “Default”,则名字解析配置会继承自 Pod 运行所在的节点。
自定义上游域名服务器和存根域不能够与这个策略一起使用。
### "ClusterFirst" DNS 策略
如果 `dnsPolicy` 被设置为 "ClusterFirst",处理名字解析有所不同,*依赖于是否配置了存根域和上游 DNS 服务器*。
**未进行自定义配置**:没有匹配上配置的集群域名后缀的任何请求,例如 “www.kubernetes.io”,将会被转发到继承自节点的上游域名服务器。
**进行自定义配置**:如果配置了存根域和上游 DNS 服务器(类似于 [前面示例](#configuring-stub-domain-and-upstream-dns-servers) 配置的内容),DNS 查询将基于下面的流程对请求进行路由:
1. 查询首先被发送到 kube-dns 中的 DNS 缓存层。
1. 从缓存层,检查请求的后缀,并根据下面的情况转发到对应的 DNS 上:
* *具有集群后缀的名字*(例如 ".cluster.local"):请求被发送到 kube-dns。
* *具有存根域后缀的名字*(例如 ".acme.local"):请求被发送到配置的自定义 DNS 解析器(例如:监听在 1.2.3.4)。
* *未能匹配上后缀的名字*(例如 "widget.com"):请求被转发到上游 DNS(例如:Google 公共 DNS 服务器,8.8.8.8 和 8.8.4.4)。
![DNS 查询流程](/docs/tasks/administer-cluster/dns-custom-nameservers/dns.png)
## ConfigMap 选项
kube-dns `kube-system:kube-dns` 对应的 ConfigMap 选项如下所示:
| 字段 | 格式 | 描述 |
| ----- | ------ | ----------- |
| `stubDomains`(可选)| 使用 DNS 后缀作为键(例如 “acme.local”)的 JSON map,以及由 DNS IP 的 JSON 数组组成的值。 | 目标域名服务器可能是一个 Kubernetes Service。例如,可以运行自己的 dnsmasq 副本,将 DNS 名字暴露到 ClusterDNS namespace 中。|
| `upstreamNameservers`(可选)| DNS IP 的 JSON 数组。 | 注意:如果指定,则指定的值会替换掉被默认从节点的 `/etc/resolv.conf` 中获取到的域名服务器。限制:最多可以指定三个上游域名服务器。|
## 附加示例
### 示例:存根域
在这个例子中,用户有一个 Consul DNS 服务发现系统,他们希望能够与 kube-dns 集成起来。
Consul 域名服务器地址为 10.150.0.1,所有的 Consul 名字具有后缀 “.consul.local”。
要配置 Kubernetes,集群管理员只需要简单地创建一个 ConfigMap 对象,如下所示:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{“consul.local”: [“10.150.0.1”]}
```
注意,集群管理员不希望覆盖节点的上游域名服务器,所以他们不会指定可选的 `upstreamNameservers` 字段。
### 示例:上游域名服务器
在这个示例中,集群管理员不希望显式地强制所有非集群 DNS 查询进入到他们自己的域名服务器 172.16.0.1。
而且这很容易实现:他们只需要创建一个 ConfigMap,`upstreamNameservers` 字段指定期望的域名服务器即可:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-dns
namespace: kube-system
data:
upstreamNameservers: |
[“172.16.0.1”]
```
{{% /capture %}}
@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-dns-autoscaler
namespace: kube-system
labels:
k8s-app: kube-dns-autoscaler
spec:
selector:
matchLabels:
k8s-app: kube-dns-autoscaler
template:
metadata:
labels:
k8s-app: kube-dns-autoscaler
spec:
containers:
- name: autoscaler
image: k8s.gcr.io/cluster-proportional-autoscaler-amd64:1.1.1
resources:
requests:
cpu: "20m"
memory: "10Mi"
command:
- /cluster-proportional-autoscaler
- --namespace=kube-system
- --configmap=kube-dns-autoscaler
- --target=<SCALE_TARGET>
# When cluster is using large nodes(with more cores), "coresPerReplica" should dominate.
# If using small nodes, "nodesPerReplica" should dominate.
- --default-params={"linear":{"coresPerReplica":256,"nodesPerReplica":16,"min":1}}
- --logtostderr=true
- --v=2
@@ -0,0 +1,54 @@
---
approvers:
- davidopp
- filipg
- piosz
title: 关键插件 Pod 的调度保证
---
{{< toc >}}
## 概览
除了 Kubernetes 核心组件,像运行在 master 机器上的 api-server、scheduler、controller-manager,由于各种原因,还有很多插件必须运行在一个普通的集群节点上(而不是 Kubernetes master)。
这些插件中的一些对于一个功能完备的集群来说是非常关键的,例如 Heapster、DNS 以及 UI。
如果一个关键的插件被移除(或者手动,或是类似升级这样具有副作用的其它操作),或者变成挂起状态(例如,当集群利用率过高,以及或者其它被调度到该空间中的挂起 Pod 被清理关键插件 Pod 给移除,或者由于其它原因导致节点上可用资源的总量发生变化),集群可能会停止正常工作。
## 二次调度器:关键插件的调度保证
二次调度器确保关键的插件总是能被调度(假定普通的 Pod 不存在时,集群具有足够的资源去运行关键插件 Pod)。
如果调度器确定没有节点有足够资源去运行关键插件 Pod,假使有 Pod 已经运行在集群中(通过将关键插件 Pod 的条件 PodScheduled 设置为 false,原因设置为 Unschedulable 来指示),这时二次调度器通过清理一些 Pod 尽量去释放空间,然后调度器将调度该插件 Pod。
为了避免这种情况,当另一个 Pod 被调度到该空间,为了该关键插件,被选择的节点导致临时变成 "CriticalAddonsOnly" 的 taint(查看 [更多详情](https://git.k8s.io/community/contributors/design-proposals/taint-toleration-dedicated.md))。
每个关键插件不得不容忍它,然而其它一些 Pod 不可能容忍该 taint。一旦该插件被成功调度,该 taint 会被移除。
*警告:* 当前对选中哪个节点,以及为了调度该关键 Pod 杀掉哪个 Pod 并没有任何保证,所以如果启用了二次调度器,任何 Pod 都可能被偶然的杀掉以达到目的。
## 配置
二次调度器应该被 [作为 static Pod 默认启用](https://git.k8s.io/kubernetes/cluster/saltbase/salt/rescheduler/rescheduler.manifest)。
它没有任何面向用户的配置(组件配置),或者 API,可以通过如下方式来禁用:
* 在集群安装过程中通过设置 `ENABLE_RESCHEDULER` 标志为 `false`
* 在运行中的集群中从 master 节点删除它的 manifest(默认路径 `/etc/kubernetes/manifests/rescheduler.manifest`
### 标记关键插件
想变成关键插件,必须运行在 `kube-system` Namespace 中(是基于标志可配置的),并且:
*`scheduler.alpha.kubernetes.io/critical-pod` annotation 设置为空字符串,并且
* 将 PodSpec 的 `tolerations` 字段设置为 `[{"key":"CriticalAddonsOnly", "operator":"Exists"}]`
第一个表示是一个关键 Pod。第二个是二次调度器算法必需的。
@@ -0,0 +1,66 @@
---
approvers:
- mtaufen
- dawnchen
cn-approvers:
- xiaosuiba
cn-reviwers:
- pigletfly
- zjj2wry
- chentao1596
title: 通过配置文件设置 Kubelet 参数
content_template: templates/task
---
{{% capture overview %}}
{{< feature-state state="alpha" >}}
在 Kubernetes 1.8 版本上,除了可以通过命令行参数外,还可以通过保存在硬盘的配置文件设置 Kubelet 的配置子集。
将来,大部分现存的命令行参数都将被废弃,取而代之以配置文件的方式提供参数,以简化节点部署过程。
{{% /capture %}}
{{% capture prerequisites %}}
- 需要安装 1.8 版本或更高版本的 Kubelet 二进制文件。
{{% /capture %}}
{{% capture steps %}}
## 创建配置文件
`KubeletConfiguration` 结构体定义了可以通过文件配置的 Kubelet 配置子集,该结构体在 [这里(v1alpha1](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/apis/kubeletconfig/v1alpha1/types.go) 可以找到。配置文件必须是这个结构体中参数的 JSON 或 YAML 表现形式。请注意,这个结构体及配置文件 API 仍然为 alpha 版本,对其稳定性不作保证。
在单独的文件夹中创建一个名为 `kubelet` 的文件,并保证 Kubelet 可以读取该文件夹及文件。您应该在这个 `kubelet` 文件中编写 Kubelet 配置。
作为一个小技巧,您可以从活动节点生成配置文件,相关方法请查看 [重新配置活动集群节点的 Kubelet](/docs/tasks/administer-cluster/reconfigure-kubelet)。
## 启动通过配置文件配置的 Kubelet 进程
启动 Kubelet 需要将其 `--init-config-dir` 标志设置为包含 `kubelet` 文件的文件夹路径。Kubelet 将从 `kubelet` 文件中读取由 `KubeletConfiguration` 定义的参数,而不是从参数相关的命令行标志中读取。
{{% /capture %}}
{{% capture discussion %}}
## 与动态 Kubelet 配置的关系
如果您正在使用 [动态 Kubelet 配置(Dynamic Kubelet Configuration](/docs/tasks/administer-cluster/reconfigure-kubelet) 特性,那么自动回滚机制将认为通过 `--init-config-dir` 提供的配置是“最后已知正常(last known good)”的配置。
请注意,`--init-config-dir` 文件的布局结构镜像了 ConfigMap 中用于动态 Kubelet 配置的数据结构;文件命名和 ConfigMap 的 key 相同,文件的内容是 ConfigMap 中相同数据结构的 JSON 或 YAML 表现形式。虽然以后可能会出现更多,但目前只有 kubelet:KubeletConfiguration 配置对。更多信息请查阅 [重新配置活动集群节点的 Kubelet](/docs/tasks/administer-cluster/reconfigure-kubelet)。
{{% /capture %}}
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-2
spec:
containers:
- name: constraints-mem-demo-2-ctr
image: nginx
resources:
limits:
memory: "1.5Gi"
requests:
memory: "800Mi"
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-3
spec:
containers:
- name: constraints-mem-demo-3-ctr
image: nginx
resources:
limits:
memory: "800Mi"
requests:
memory: "100Mi"
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-4
spec:
containers:
- name: constraints-mem-demo-4-ctr
image: nginx
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo
spec:
containers:
- name: constraints-mem-demo-ctr
image: nginx
resources:
limits:
memory: "800Mi"
requests:
memory: "600Mi"
@@ -0,0 +1,11 @@
apiVersion: v1
kind: LimitRange
metadata:
name: mem-min-max-demo-lr
spec:
limits:
- max:
memory: 1Gi
min:
memory: 500Mi
type: Container
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: default-mem-demo-2
spec:
containers:
- name: defalt-mem-demo-2-ctr
image: nginx
resources:
limits:
memory: "1Gi"
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: default-mem-demo-3
spec:
containers:
- name: default-mem-demo-3-ctr
image: nginx
resources:
requests:
memory: "128Mi"
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Pod
metadata:
name: default-mem-demo
spec:
containers:
- name: default-mem-demo-ctr
image: nginx
@@ -0,0 +1,11 @@
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256Mi
type: Container
@@ -0,0 +1,43 @@
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
component: scheduler
tier: control-plane
name: my-scheduler
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
component: scheduler
tier: control-plane
version: second
spec:
containers:
- command:
- /usr/local/bin/kube-scheduler
- --address=0.0.0.0
- --leader-elect=false
- --scheduler-name=my-scheduler
image: gcr.io/my-gcp-project/my-kube-scheduler:1.0
livenessProbe:
httpGet:
path: /healthz
port: 10251
initialDelaySeconds: 15
name: kube-second-scheduler
readinessProbe:
httpGet:
path: /healthz
port: 10251
resources:
requests:
cpu: '0.1'
securityContext:
privileged: false
volumeMounts: []
hostNetwork: false
hostPID: false
volumes: []
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: no-annotation
labels:
name: multischeduler-example
spec:
containers:
- name: pod-with-no-annotation-container
image: k8s.gcr.io/pause:2.0
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: annotation-default-scheduler
labels:
name: multischeduler-example
spec:
schedulerName: default-scheduler
containers:
- name: pod-with-default-annotation-container
image: k8s.gcr.io/pause:2.0
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: annotation-second-scheduler
labels:
name: multischeduler-example
spec:
schedulerName: my-scheduler
containers:
- name: pod-with-second-annotation-container
image: k8s.gcr.io/pause:2.0
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: quota-mem-cpu-demo-2
spec:
containers:
- name: quota-mem-cpu-demo-2-ctr
image: redis
resources:
limits:
memory: "1Gi"
cpu: "800m"
requests:
memory: "700Mi"
cpu: "400m"
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: quota-mem-cpu-demo
spec:
containers:
- name: quota-mem-cpu-demo-ctr
image: nginx
resources:
limits:
memory: "800Mi"
cpu: "800m"
requests:
memory: "600Mi"
cpu: "400m"
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-demo
spec:
hard:
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
@@ -0,0 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-quota-demo-2
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
@@ -0,0 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-quota-demo
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
@@ -0,0 +1,9 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: object-quota-demo
spec:
hard:
persistentvolumeclaims: "1"
services.loadbalancers: "2"
services.nodeports: "0"
@@ -0,0 +1,14 @@
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: pod-quota-demo
spec:
replicas: 3
template:
metadata:
labels:
purpose: quota-demo
spec:
containers:
- name: pod-quota-demo
image: nginx
@@ -0,0 +1,134 @@
---
title: 配置命名空间下pod总数
---
{{% capture overview %}}
本文主要描述如何配置一个命名空间下可运行的pod总数。资源配额详细信息可查看:[资源配额](/docs/api-reference/v1.7/#resourcequota-v1-core)
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 创建一个命名空间
首先创建一个命名空间,这样可以将本次操作中创建的资源与集群其他资源隔离开来。
```shell
kubectl create namespace quota-pod-example
```
## 创建资源配额
下面是一个资源配额的配置文件:
{{< code file="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的配置文件:
{{< code file="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
```
{{% /capture %}}
{{% 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/)
{{% /capture %}}
@@ -0,0 +1,7 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: pod-demo
spec:
hard:
pods: "2"
@@ -0,0 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-quota-demo-2
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
@@ -0,0 +1,51 @@
---
approvers:
- chrismarino
title: 使用 Romana 来提供 NetworkPolicy
content_template: templates/task
---
{{% capture overview %}}
本页展示怎么样使用 Romana 来提供 NetworkPolicy
{{% /capture %}}
{{% capture prerequisites %}}
完成 [kubeadm 入门指南](/docs/getting-started-guides/kubeadm/)中的步骤1、2和3
{{% /capture %}}
{{% capture steps %}}
## 使用 kubeadm 安装 Romana
按照[容器化安装指南](https://github.com/romana/romana/tree/master/containerize)中使用 kubeadm 的方式安装
## 应用网络策略
要应用网络策略,请使用以下方式之一:
* [Romana 网络策略](https://github.com/romana/romana/wiki/Romana-policies)
* [Romana 网络策略示例](https://github.com/romana/core/tree/master/policy)
* NetworkPolicy API
{{% /capture %}}
{{% capture whatsnext %}}
Romana 安装完成之后,您可以通过 [NetworkPolicy 入门指南](/docs/getting-started-guides/network-policy/walkthrough)去尝试使用 Kubernetes NetworkPolicy
{{% /capture %}}
@@ -0,0 +1,125 @@
---
approvers:
- jsafrane
title: 静态Pods
---
**如果你正在运行Kubernetes集群并且使用静态pods在每个节点上起一个pod,那么最好使用[DaemonSet](/cn/docs/concepts/workloads/controllers/daemonset/)!**
*静态pods*直接由特定节点上的kubelet进程来管理,不通过主控节点上的API服务器。静态pod不关联任何replication controller,它由kubelet进程自己来监控,当pod崩溃时重启该pod。对于静态pod没有健康检查。静态pod始终绑定在某一个kubelet,并且始终运行在同一个节点上。
Kubelet自动为每一个静态pod在Kubernetes的API服务器上创建一个镜像PodMirror Pod),因此可以在API服务器查询到该pod,但是不被API服务器控制(例如不能删除)。
## 静态pod创建
静态pod有两种创建方式:用配置文件或者通过HTTP。
### 配置文件
配置文件就是放在特定目录下的标准的JSON或YAML格式的pod定义文件。用`kubelet --pod-manifest-path=<the directory>`来启动kubelet进程,kubelet将会周期扫描<the directory>这个目录,根据这个目录下出现或消失的YAML/JSON文件来创建或删除静态pod。
下面例子用静态pod的方式启动一个nginx的Web服务器:
1. 选择一个节点来运行静态pod。这个例子中就是`my-node1`
```
[joe@host ~] $ ssh my-node1
```
2. 选择一个目录,例如/etc/kubelet.d,把web服务器的pod定义文件放在这个目录下,例如`/etc/kubelet.d/static-web.yaml`:
```
[root@my-node1 ~] $ mkdir /etc/kubelet.d/
[root@my-node1 ~] $ cat <<EOF >/etc/kubelet.d/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
```
3.配置节点上的kubelet使用这个目录,kubelet启动时增加`--pod-manifest-path=/etc/kubelet.d/`参数。如果是Fedora系统,在Kubelet配置文件/etc/kubernetes/kubelet中添加下面这行:
```
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubelet.d/"
```
如果是其它Linux发行版或者其它Kubernetes安装方式,配置方法可能会不一样。
4. 重启kubelet。如果是Fedora系统,就是:
```
[root@my-node1 ~] $ systemctl restart kubelet
```
## 通过HTTP创建静态Pods
Kubelet周期地从--manifest-url=<URL>参数指定的地址下载文件,并且把它翻译成JSON/YAML格式的pod定义。此后的操作方式与--pod-manifest-path=<directory>相同,kubelet会不时地重新下载该文件,当文件变化时对应地终止或启动静态pod(如下)。
## 静态pods的动作行为
kubelet启动时,由`--pod-manifest-path=` or `--manifest-url=`参数指定的目录下定义的所有pod都会自动创建,例如,我们示例中的static-web。 (可能要花些时间拉取nginx镜像,耐心等待...)
```shell
[joe@my-node1 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
```
如果我们查看Kubernetes的API服务器(运行在主机 `my-master`),可以看到这里创建了一个新的镜像Pod:
```shell
[joe@host ~] $ ssh my-master
[joe@my-master ~] $ kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 2m
```
静态pod的标签会传递给镜像Pod,可以用来过滤或筛选。
需要注意的是,我们不能通过API服务器来删除静态pod(例如,通过 [`kubectl`](/docs/user-guide/kubectl/) 命令),kebelet不会删除它。
```shell
[joe@my-master ~] $ kubectl delete pod static-web-my-node1
pods/static-web-my-node1
[joe@my-master ~] $ kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 12s
```
返回`my-node1`主机,我们尝试手动终止容器,可以看到kubelet很快就会自动重启容器。
```shell
[joe@host ~] $ ssh my-node1
[joe@my-node1 ~] $ docker stop f6d05272b57e
[joe@my-node1 ~] $ sleep 20
[joe@my-node1 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
```
## 静态pods的动态增加和删除
运行中的kubelet周期扫描配置的目录(我们这个例子中就是`/etc/kubelet.d`)下文件的变化,当这个目录中有文件出现或消失时创建或删除pods。
```shell
[joe@my-node1 ~] $ mv /etc/kubelet.d/static-web.yaml /tmp
[joe@my-node1 ~] $ sleep 20
[joe@my-node1 ~] $ docker ps
// no nginx container is running
[joe@my-node1 ~] $ mv /tmp/static-web.yaml /etc/kubelet.d/
[joe@my-node1 ~] $ sleep 20
[joe@my-node1 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
```
@@ -0,0 +1,119 @@
---
approvers:
- bboreham
title: 使用 Weave 网络来提供 NetworkPolicy
content_template: templates/task
---
{{% capture overview %}}
本页展示怎么样使用 Weave 网络来提供 NetworkPolicy
{{% /capture %}}
{{% capture prerequisites %}}
完成 [kubeadm 入门指南](/docs/getting-started-guides/kubeadm/)中的步骤1、2和3
{{% /capture %}}
{{% capture steps %}}
## 安装 Weave 网络插件
按照[通过插件方式集成到 Kubernetes ](https://www.weave.works/docs/net/latest/kube-addon/)指南完成安装
Kubernetes 的 Weave 网络插件配有一个[网络策略控制器](https://www.weave.works/docs/net/latest/kube-addon/#npc),它监控所有命名空间下 NetworkPolicy 相关的注解,然后配置 iptables 规则生成允许或者阻断通信的策略
{{% /capture %}}
{{% capture example %}}
## 命名空间隔离示例
1. 创建携带 `DefaultDeny` 标识的命名空间
```yaml
kind: Namespace
apiVersion: v1
metadata:
name: myns
annotations:
net.beta.kubernetes.io/network-policy: |
{
"ingress": {
"isolation": "DefaultDeny"
}
}
```
2. 在命名空间下创建2个 pod
```yaml
kind: Pod
apiVersion: v1
metadata:
name: pod1
namespace: myns
labels:
inns: "yes"
spec:
containers:
- name: pod1
image: nginx
---
kind: Pod
apiVersion: v1
metadata:
name: pod2
namespace: myns
labels:
inns: "yes"
spec:
containers:
- name: pod2
image: nginx
```
3. 获取 pod 的 IP 地址
```shell
kubectl get po -n myns -o wide
```
**注意:** 如果您对 pod 的 cURL 请求是被禁止的,请尝试在 pod 中访问其它的 pod
4. 创建一个允许 pod 访问命名空间内其它 pod 的 Kubernetes NetworkPolicy
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: aaa
namespace: myns
spec:
podSelector:
matchExpressions:
- {key: inns, operator: In, values: ["yes"]}
ingress:
- from:
- podSelector:
matchExpressions:
- {key: inns, operator: In, values: ["yes"]}
```
Weave 网络插件安装完成之后,您可以通过 [NetworkPolicy 入门指南](/docs/getting-started-guides/network-policy/walkthrough)去尝试使用 Kubernetes NetworkPolicy
{{% /capture %}}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-2
spec:
containers:
- name: cpu-demo-ctr-2
image: vish/stress
resources:
limits:
cpu: "100"
requests:
cpu: "100"
args:
- -cpus
- "2"
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
@@ -0,0 +1,26 @@
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
image: k8s.gcr.io/busybox
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
@@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
args:
- /server
image: k8s.gcr.io/liveness
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
@@ -0,0 +1,30 @@
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# These containers are run during pod initialization
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
@@ -0,0 +1,11 @@
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256Mi
type: Container
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
spec:
containers:
- name: memory-demo-2-ctr
image: vish/stress
resources:
requests:
memory: 50Mi
limits:
memory: "100Mi"
args:
- -mem-total
- 250Mi
- -mem-alloc-size
- 10Mi
- -mem-alloc-sleep
- 1s
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
spec:
containers:
- name: memory-demo-3-ctr
image: vish/stress
resources:
limits:
memory: "1000Gi"
requests:
memory: "1000Gi"
args:
- -mem-total
- 150Mi
- -mem-alloc-size
- 10Mi
- -mem-alloc-sleep
- 1s
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
spec:
containers:
- name: memory-demo-ctr
image: vish/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
args:
- -mem-total
- 150Mi
- -mem-alloc-size
- 10Mi
- -mem-alloc-sleep
- 1s
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: oir-demo-2
spec:
containers:
- name: oir-demo-2-ctr
image: nginx
resources:
requests:
pod.alpha.kubernetes.io/opaque-int-resource-dongle: 2
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: oir-demo
spec:
containers:
- name: oir-demo-ctr
image: nginx
resources:
requests:
pod.alpha.kubernetes.io/opaque-int-resource-dongle: 3
@@ -0,0 +1,138 @@
---
title: 给容器分配非透明整型资源
content_template: templates/task
---
{{% capture overview %}}
本页展示了如何给容器分配非透明整型资源。
{{< feature-state state="alpha" >}}
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
在做这个练习之前,请在[给节点配置非透明整型资源](/docs/tasks/administer-cluster/opaque-integer-resource-node/)文档中进行练习,
该文档介绍了在一个节点上配置dongle资源。
{{% /capture %}}
{{% capture steps %}}
## 给Pod分配非透明整型资源
为了请求一个非透明整型资源,需要在容器配置文件中包含`resources:requests`字段。
非透明整型资源类型前缀是`pod.alpha.kubernetes.io/opaque-int-resource-`
下面是含有一个容器的Pod的配置文件:
{{< code file="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资源。
{{< code file="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
```
{{% /capture %}}
{{% 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/)
{{% /capture %}}
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regsecret
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Pod
metadata:
name: test-projected-volume
spec:
containers:
- name: test-projected-volume
image: busybox
args:
- sleep
- "86400"
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: user
- secret:
name: pass
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
@@ -0,0 +1,11 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
pods: "4"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: gcr.io/google-samples/node-hello:1.0
securityContext:
runAsUser: 2000
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: gcr.io/google-samples/node-hello:1.0
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
fsGroup: 2000
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: gcr.io/google-samples/node-hello:1.0
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
@@ -0,0 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
@@ -0,0 +1,22 @@
kind: Pod
apiVersion: v1
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
@@ -0,0 +1,14 @@
kind: PersistentVolume
apiVersion: v1
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp/data"
@@ -0,0 +1,22 @@
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
@@ -0,0 +1,177 @@
---
title: 应用故障排查
---
本指南帮助用户来调试kubernetes上那些没有正常运行的应用。
本指南*不能*调试集群。如果想调试集群的话,请参阅[这里](/docs/admin/cluster-troubleshooting)。
{{< toc >}}
## 诊断问题
故障排查的第一步是先给问题分下类。这个问题是什么?PodsReplication Controller或者Service
* [Debugging Pods](#debugging-pods)
* [Debugging Replication Controllers](#debugging-replication-controllers)
* [Debugging Services](#debugging-services)
### Debugging Pods
调试pod的第一步是看一下这个pod的信息,用如下命令查看一下pod的当前状态和最近的事件:
```shell
$ kubectl describe pods ${POD_NAME}
```
查看一下pod中的容器所处的状态。这些容器的状态都是`Running`吗?最近有没有重启过?
后面的调试都是要依靠pods的状态的。
#### pod停留在pending状态
如果一个pod卡在`Pending`状态,则表示这个pod没有被调度到一个节点上。通常这是因为资源不足引起的。
敲一下`kubectl describe ...`这个命令,输出的信息里面应该有显示为什么没被调度的原因。
常见原因如下:
* **资源不足**:
你可能耗尽了集群上所有的CPU和内存,此时,你需要删除pods,调整资源请求,或者增加节点。
更多信息请参阅[Compute Resources document](/docs/user-guide/compute-resources/#my-pods-are-pending-with-event-message-failedscheduling)
* **使用了`hostPort`**:
如果绑定一个pod到`hostPort`,那么能创建的pod个数就有限了。
多数情况下,`hostPort`是非必要的,而应该采用服务来暴露pod。
如果确实需要使用`hostPort`,那么能创建的pod的数量就是节点的个数。
#### pod停留在waiting状态
如果一个pod卡在`Waiting`状态,则表示这个pod已经调试到节点上,但是没有运行起来。
再次敲一下`kubectl describe ...`这个命令来查看相关信息。
最常见的原因是拉取镜像失败。可以通过以下三种方式来检查:
* 使用的镜像名字正确吗?
* 镜像仓库里有没有这个镜像?
*`docker pull <image>`命令手动拉下镜像试试。
#### pod处于crashing状态或者unhealthy
首先,看一下容器的log:
```shell
$ kubectl logs ${POD_NAME} ${CONTAINER_NAME}
```
如果容器是crashed的,用如下命令可以看到crash的log:
```shell
$ kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME}
```
或者,用`exec`在容器内运行一些命令:
```shell
$ kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN}
```
注意:当一个pod内只有一个容器时,可以不带参数`-c ${CONTAINER_NAME}`
例如,名为Cassandra的pod,处于running态,要查看它的log,可运行如下命令:
```shell
$ kubectl exec cassandra -- cat /var/log/cassandra/system.log
```
如果以上方法都不起作用,找到这个pod所在的节点并用SSH登录进去做进一步的分析。
通常情况下,是不需要在Kubernetes API中再给出另外的工具的。
因此,如果你发现需要ssh进一个主机来分析问题时,请在GitHub上提一个特性请求,描述一个你的场景并说明为什么已经提供的工具不能满足需求。
#### pod处于running态,但是没有正常工作
如果创建的pod不符合预期,那么创建pod的描述文件应该是存在某种错误的,并且这个错误在创建pod时被忽略掉。
通常pod的定义中,章节被错误的嵌套,或者一个字段名字被写错,都可能会引起被忽略掉。
例如,希望在pod中用命令行执行某个命令,但是将`command`写成`commnd`,pod虽然可以创建,但命令并没有执行。
如何查出来哪里出错?
首先,删掉这个pod再重新创建一个,重创时,像下面这样带着`--validate`这个参数:
`kubectl create --validate -f mypod.yaml``command`写成`commnd`的拼写错误就会打印出来了。
```shell
I0805 10:43:25.129850 46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973 46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod
```
<!-- TODO: Now that #11914 is merged, this advice may need to be updated -->
如果上面方法没有看到相关异常的信息,那么接下来就要验证从apiserver获取到的pod是否与期望的一致,比如创建Pod的yaml文件是mypod.yaml。
运行如下命令来获取apiserver创建的pod信息并保存成一个文件:
`kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml`
然后手动对这两个文件进行比较:
apiserver获得的yaml文件中的一些行,不在创建pod的yaml文件内,这是正常的。
如果创建Pod的yaml文件内的一些行,在piserver获得的yaml文件中不存在,可以说明创建pod的yaml中的定义有问题。
### Debugging Replication Controllers
RC相当简单。他们要么能创建pod,要么不能。如果不能创建pod,请参阅上述[Debugging Pods](#debugging-pods)。
也可以使用`kubectl describe rc ${CONTROLLER_NAME}`命令来监视RC相关的事件。
### Debugging Services
服务提供了多个Pod之间的负载均衡功能。
有一些常见的问题可以造成服务无法正常工作。以下说明将有助于调试服务的问题。
首先,验证服务是否有端点。对于每一个Service对像,apiserver使`endpoints`资源可用。
通过如下命令可以查看endpoints资源:
```shell
$ kubectl get endpoints ${SERVICE_NAME}
```
确保endpoints与服务内容器个数一致。
例如,如果你创建了一个nginx服务,它有3个副本,那么你就会在这个服务的endpoints中看到3个不同的IP地址。
#### 服务缺少endpoints
如果缺少endpoints,请尝试使用服务的labels列出所有的pod。
假如有一个服务,有如下的label
```yaml
...
spec:
- selector:
name: nginx
type: frontend
```
你可以使用如下命令列出与selector相匹配的pod,并验证这些pod是否归属于创建的服务:
```shell
$ kubectl get pods --selector=name=nginx,type=frontend
```
如果pod列表附合预期,但是endpoints仍然为空,那么可能没有暴露出正确的端口。
如果服务指定了`containerPort`,但是列表中的Pod没有列出该端口,则不会将其添加到端口列表。
验证该pod的`containerPort`与服务的`containerPort`是否匹配。
#### 网络业务不工作
如果可以连接到服务上,但是连接立即被断开了,并且在endpoints列表中有endpoints,可能是代理和pods之间不通。
确认以下3件事情:
* Pods工作是否正常? 看一下重启计数,并参阅[Debugging Pods](#debugging-pods)
* 可以直接连接到pod上吗?获取pod的IP地址,然后尝试直接连接到该IP上;
* 应用是否在配置的端口上进行服务?Kubernetes不进行端口重映射,所以如果应用在8080端口上服务,那么`containerPort`字段就需要设定为8080。
#### 更多信息
如果上述都不能解决你的问题,请按照[Debugging Service document](/docs/user-guide/debugging-services)中的介绍来确保你的`Service`处于running态,有`Endpoints``Pods`真正的在服务;你有DNS在工作,安装了iptables规则,kube-proxy也没有异常行为。
你也可以访问[troubleshooting document](/docs/troubleshooting/)来获取更多信息。
@@ -0,0 +1,114 @@
---
title: 集群故障排查
---
本篇文档是介绍集群故障排查的;我们假设对于你碰到的问题,你已经排除了是由应用程序造成的。
对于应用的调试,请参阅[应用故障排查指南](/cn/docs/tasks/debug-application-cluster/debug-application)。
你也可以访问[troubleshooting document](/docs/troubleshooting/)来获取更多的信息。
## 显示出集群的节点列表
调试的第一步是查看所有的节点是否都正确的注册。
运行
```shell
kubectl get nodes
```
接下来,验证你的所有节点都能够显示出来,并且都处于`Ready`状态。
## 查看logs
现在,挖掘出集群更深层的信息就需要登录到相关的机器上。下面是相关log文件所在的位置。
(注意,对于基于systemd的系统,你可能需要使用`journalctl`)
### Master
* /var/log/kube-apiserver.log - API Server, 提供API服务
* /var/log/kube-scheduler.log - Scheduler, 负责调度决策
* /var/log/kube-controller-manager.log - 管理replication controllers的控制器
### Worker Nodes
* /var/log/kubelet.log - Kubelet, 管控节点上运行的容器
* /var/log/kube-proxy.log - Kube Proxy, 负责服务的负载均衡
## 集群故障模式的概述
下面是一个不完整的列表,列举了一些可能出错的场景,以及通过调整集群配置来解决相关问题的方法。
根本原因:
- VM(s)关机
- 集群之间,或者集群和用户之间网络分裂
- Kubernetes软件本身崩溃了
- 数据丢失或者持久化存储不可用(如:GCE PD 或 AWS EBS卷)
- 操作错误,如:Kubernetes或者应用程序配置错误
具体情况:
- Apiserver所在的VM关机或者apiserver崩溃
- 结果
- 不能停止,更新,或者启动新的podsservicesreplication controller
- 现有的pods和services在不依赖Kubernetes API的情况下应该能继续正常工作
- Apiserver 后端存储丢失
- 结果
- apiserver应该不能起来
- kubelets将不能访问它,但是能够继续运行之前的Pods和提供相同的服务代理
- 在apiserver重启之前,需要手动恢复或者重创apiserver的状态
- Kubernetes服务组件(节点控制器,副本控制器,调度器等等)所在的VM关机或者崩溃
- 当前,这些控制器是和apiserver共存的,它们不可用的现象是与apiserver类似的
- 将来,这些控制器也会复制为多份,并且可能为非共存的
- 它们没有自己的持久状态
- 单个节点(VM或者物理机)关机
- 结果
- 此节点上的所有Pods都停止运行
- 网络分裂(Network partition)
- 结果
- partition A认为partition B中所有的节点都down掉了;partition B认为apiserver是down掉了(假定master所在的VM位于partition A内)。
- Kubelet软件故障
- 结果
- 崩溃的kubelet就不能在其所在的节点上启动新的pods
- kubelet可能删掉pods或者不删
- 节点被标识为非健康态
- 副本控制器会在其它的节点上启动新的pods
- 集群操作错误
- 结果
- 丢失pods,服务等等
- 丢失apiserver后端存储
- 用户无法读取API
- 等等
缓解措施:
- 措施:对于IaaS上的VMs,使用IaaS的自动VM重启功能
- 缓解:Apiserver VM关机或apiserver崩溃
- 缓解:Kubernetes服务组件所在的VM关机或崩溃
- 措施: 对于具有apiserver+etcd的VM,使用IaaS提供的可靠的存储(例如GCE PD或者AWS EBS卷)
- 缓解:Apiserver后端存储的丢失
- 措施:使用(实验)[高可用性](/docs/admin/high-availability)的配置
- 缓解:master VM关机或者master组件(scheduler, API server, controller-managing)崩馈
- 将容许一个或多个节点或组件同时出现故障
- 缓解:apiserver后端存储(例如etcd的数据目录)丢失
- 假定你使用了集群化的etcd。
- 措施:定期的对apiserver的PDs/EBS卷进行快照
- 缓解:apiserver后端存储丢失
- 缓解:一些操作错误的场景
- 缓解:一些Kubernetes软件本身故障的场景
- 措施:在pods的前面使用副本控制器或服务
- 缓解:节点关机
- 缓解:Kubelet软件故障
- 措施:应用(容器)设计成容许异常重启
- 缓解:节点关机
- 缓解:Kubelet软件故障
- 措施:[多个独立的集群](/docs/admin/multi-cluster)(并且避免一次性地对所有的集群进行有风险性的修改)
- 缓解:以上列出的所有情况
@@ -0,0 +1,86 @@
---
title: 调试Pods和Replication Controllers
---
{{< 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,78 @@
---
title: 调试StatefulSet
content_template: templates/task
---
{{% capture overview %}}
此任务展示如何调试StatefulSet。
{{% /capture %}}
{{% capture prerequisites %}}
* 你需要有一个Kubernetes集群,通过必要的配置使kubectl命令行工具与您的集群进行通信。
* 你应该有一个运行中的StatefulSet,以便用于调试。
{{% /capture %}}
{{% 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
```
{{% /capture %}}
{{% capture whatsnext %}}
点击链接[调试init-container](/docs/tasks/troubleshoot/debug-init-containers/),了解更多信息。
{{% /capture %}}
@@ -0,0 +1,13 @@
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"]
restartPolicy: OnFailure
@@ -0,0 +1,45 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-resourcefieldref
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox:1.24
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_CPU_REQUEST MY_CPU_LIMIT;
printenv MY_MEM_REQUEST MY_MEM_LIMIT;
sleep 10;
done;
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
env:
- name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: requests.cpu
- name: MY_CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.cpu
- name: MY_MEM_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: requests.memory
- name: MY_MEM_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.memory
restartPolicy: Never
@@ -0,0 +1,38 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-fieldref
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
sleep 10;
done;
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MY_POD_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
restartPolicy: Never
@@ -0,0 +1,54 @@
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example-2
spec:
containers:
- name: client-container
image: k8s.gcr.io/busybox:1.24
command: ["sh", "-c"]
args:
- while true; do
echo -en '\n';
if [[ -e /etc/podinfo/cpu_limit ]]; then
echo -en '\n'; cat /etc/podinfo/cpu_limit; fi;
if [[ -e /etc/cpu_request ]]; then
echo -en '\n'; cat /etc/podinfo/cpu_request; fi;
if [[ -e /etc/mem_limit ]]; then
echo -en '\n'; cat /etc/podinfo/mem_limit; fi;
if [[ -e /etc/mem_request ]]; then
echo -en '\n'; cat /etc/podinfo/mem_request; fi;
sleep 5;
done;
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
readOnly: false
volumes:
- name: podinfo
downwardAPI:
items:
- path: "cpu_limit"
resourceFieldRef:
containerName: client-container
resource: limits.cpu
- path: "cpu_request"
resourceFieldRef:
containerName: client-container
resource: requests.cpu
- path: "mem_limit"
resourceFieldRef:
containerName: client-container
resource: limits.memory
- path: "mem_request"
resourceFieldRef:
containerName: client-container
resource: requests.memory
@@ -0,0 +1,39 @@
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
annotations:
build: two
builder: john-doe
spec:
containers:
- name: client-container
image: k8s.gcr.io/busybox
command: ["sh", "-c"]
args:
- while true; do
if [[ -e /etc/podinfo/labels ]]; then
echo -en '\n\n'; cat /etc/podinfo/labels; fi;
if [[ -e /etc/podinfo/annotations ]]; then
echo -en '\n\n'; cat /etc/podinfo/annotations; fi;
sleep 5;
done;
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
readOnly: false
volumes:
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
@@ -0,0 +1,130 @@
---
title: 为容器设置启动时要执行的命令及其入参
content_template: templates/task
---
{{% capture overview %}}
本页将展示如何为Kubernetes Pod下的容器设置启动时要执行的命令及其入参。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 创建Pod时为其下的容器设置启动时要执行的命令及其入参
创建Pod时,可以为其下的容器设置启动时要执行的命令及其入参。如果要设置命令,就
填写在配置文件的`command`字段下,如果要设置命令的入参,就填写在配置文件的`args
`字段下。一旦Pod创建完成,该命令及其入参就无法再进行更改了。
如果在配置文件中设置了容器启动时要执行的命令及其入参,那么容器镜像中自带的命令
与入参将会被覆盖而不再执行。如果配置文件中只是设置了入参,却没有设置其对应的命
令,那么容器镜像中自带的命令会使用该新入参作为其执行时的入参。
本示例中,将创建一个只包含单个容器的Pod。在Pod配置文件中设置了一个命令与两个入参:
{{< code file="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/configure-pod-configmap/)
[Secrets](/docs/concepts/configuration/secret/).
{{< note >}}
**注意:** 环境变量需要加上括号,类似于`"$(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]` |
{{% /capture %}}
{{% 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/{{< param "version" >}}/#container-v1-core).
{{% /capture %}}
@@ -0,0 +1,73 @@
---
title: 为容器设置环境变量
content_template: templates/task
---
{{% capture overview %}}
本页将展示如何为kubernetes Pod下的容器设置环境变量。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 为容器设置一个环境变量
创建Pod时,可以为其下的容器设置环境变量。通过配置文件的`env`或者`envFrom` 字段来设置环境变量。
本示例中,将创建一个只包含单个容器的Pod。Pod的配置文件中设置环境变量的名称为`DEMO_GREETING`
其值为`"Hello from the environment"`。下面是Pod的配置文件内容:
{{< code file="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`退出命令终端。
{{% /capture %}}
{{% 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/{{< param "version" >}}/#envvarsource-v1-core)资源的信息。
{{% /capture %}}
@@ -0,0 +1,167 @@
---
title: 使用 Secret 安全地分发凭证
content_template: templates/task
---
{{% capture overview %}}
本文展示如何安全地将敏感数据(如密码和加密密钥)注入到 Pods 中。
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## 将 secret 数据转换为 base-64 形式
假设用户想要有两条 secret 数据:用户名 `my-app` 和密码
`39528$vdg7Jb`。 首先使用 [Base64 编码](https://www.base64encode.org/) 将用户名和密码转化为 base-64 形式。 这里是一个 Linux 示例:
echo -n 'my-app' | base64
echo -n '39528$vdg7Jb' | base64
结果显示 base-64 形式的用户名为 `bXktYXBw`
base-64 形式的密码为 `Mzk1MjgkdmRnN0pi`
## 创建 Secret
这里是一个配置文件,可以用来创建存有用户名和密码的 Secret:
{{< code file="secret.yaml" >}}
1. 创建 Secret
kubectl create -f secret.yaml
{{< note >}}
**注意:** 如果想要跳过 Base64 编码的步骤,可以使用 `kubectl create secret` 命令来创建 Secret
{{< /note >}}
kubectl create secret generic test-secret --from-literal=username='my-app' --from-literal=password='39528$vdg7Jb'
1. 查看 Secret 相关信息:
kubectl get secret test-secret
输出:
NAME TYPE DATA AGE
test-secret Opaque 2 1m
1. 查看 Secret 相关的更多详细信息:
kubectl describe secret test-secret
输出:
Name: test-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 13 bytes
username: 7 bytes
## 创建可以通过卷访问 secret 数据的 Pod
这里是一个可以用来创建 pod 的配置文件:
{{< code file="secret-pod.yaml" >}}
1. 创建 Pod
kubectl create -f secret-pod.yaml
1. 确认 Pod 正在运行:
kubectl get pod secret-test-pod
输出:
NAME READY STATUS RESTARTS AGE
secret-test-pod 1/1 Running 0 42m
1. 在 Pod 中运行的容器中获取一个 shell:
kubectl exec -it secret-test-pod -- /bin/bash
1. secret 数据通过挂载在 `/etc/secret-volume` 目录下的卷暴露在容器中。
在 shell 中,进入 secret 数据被暴露的目录:
root@secret-test-pod:/# cd /etc/secret-volume
1. 在 shell 中,列出 `/etc/secret-volume` 目录的文件:
root@secret-test-pod:/etc/secret-volume# ls
输出显示了两个文件,每个对应一条 secret 数据:
password username
1. 在 shell 中,显示 `username``password` 文件的内容:
root@secret-test-pod:/etc/secret-volume# cat username; echo; cat password; echo
输出为用户名和密码:
my-app
39528$vdg7Jb
## 创建通过环境变量访问 secret 数据的 Pod
这里是一个可以用来创建 pod 的配置文件:
{{< code file="secret-envars-pod.yaml" >}}
1. 创建 Pod
kubectl create -f secret-envars-pod.yaml
1. 确认 Pod 正在运行:
kubectl get pod secret-envars-test-pod
输出:
NAME READY STATUS RESTARTS AGE
secret-envars-test-pod 1/1 Running 0 4m
1. 在 Pod 中运行的容器中获取一个 shell:
kubectl exec -it secret-envars-test-pod -- /bin/bash
1. 在 shell 中,显示环境变量:
root@secret-envars-test-pod:/# printenv
输出包括用户名和密码:
...
SECRET_USERNAME=my-app
...
SECRET_PASSWORD=39528$vdg7Jb
{{% /capture %}}
{{% capture whatsnext %}}
* 了解更多关于 [Secrets](/docs/concepts/configuration/secret/)。
* 了解 [Volumes](/docs/concepts/storage/volumes/)。
### 参考
* [Secret](/docs/api-reference/{{< param "version" >}}/#secret-v1-core)
* [Volume](/docs/api-reference/{{< param "version" >}}/#volume-v1-core)
* [Pod](/docs/api-reference/{{< param "version" >}}/#pod-v1-core)
{{% /capture %}}

Some files were not shown because too many files have changed in this diff Show More