Merge pull request #23200 from tengqm/zh-links-tasks-9

[zh] Tidy up and fix links in tasks section (9/10)
This commit is contained in:
Kubernetes Prow Robot
2020-08-22 20:57:41 -07:00
committed by GitHub
9 changed files with 780 additions and 716 deletions
@@ -1,20 +1,17 @@
---
reviewers:
- chenopis
title: 使用 CronJob 运行自动化任务
content_type: task
weight: 10
min-kubernetes-server-version: v1.8
---
<!--
---
title: Running Automated Tasks with a CronJob
reviewers:
- chenopis
content_type: task
weight: 10
---
min-kubernetes-server-version: v1.8
-->
<!-- overview -->
@@ -31,14 +28,15 @@ Cron jobs can also schedule individual tasks for a specific time, such as if you
CronJobs 在创建周期性以及重复性的任务时很有帮助,例如执行备份操作或者发送邮件。CronJobs 也可以在特定时间调度单个任务,例如你想调度低活跃周期的任务。
{{< note >}}
<!--
CronJob resource in `batch/v2alpha1` API group has been deprecated starting from cluster version 1.8.
You should switch to using `batch/v1beta1`, instead, which is enabled by default in the API server.
Examples in this document use `batch/v1beta1` in all examples.
-->
从集群版本1.8开始,`batch/v2alpha1` API 组中的 CronJob 资源已经被废弃。
你应该切换到 API 服务器默认启用的 `batch/v1beta1` API 组。本文中的所有示例使用了`batch/v1beta1`
{{< note >}}
从集群版本 1.8 开始,`batch/v2alpha1` API 组中的 CronJob 资源已经被废弃
你应该切换到 API 服务器默认启用的 `batch/v1beta1` API 组。
本文中的所有示例使用了 `batch/v1beta1`
{{< /note >}}
<!--
@@ -47,30 +45,15 @@ For example, in certain circumstances, a single cron job can create multiple job
Therefore, jobs should be idempotent.
For more limitations, see [CronJobs](/docs/concepts/workloads/controllers/cron-jobs).
-->
CronJobs 有一些限制和特点。
例如,在特定状况下,同一个 CronJob 可以创建多个任务。
因此,任务应该是幂等的。
查看更多限制,请参考 [CronJobs](/zh/docs/concepts/workloads/controllers/cron-jobs)。
## {{% heading "prerequisites" %}}
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!--
* You need a working Kubernetes cluster at version >= 1.8 (for CronJob). For previous versions of cluster (< 1.8)
you need to explicitly enable `batch/v2alpha1` API by passing `--runtime-config=batch/v2alpha1=true` to
the API server (see [Turn on or off an API version for your cluster](/docs/admin/cluster-management/#turn-on-or-off-an-api-version-for-your-cluster)
for more), and then restart both the API server and the controller manager
component.
-->
* 你需要一个版本 >=1.8 且工作正常的 Kubernetes 集群。对于更早的版本( <1.8 ),你需要对 API 服务器设置 `--runtime-config=batch/v2alpha1=true` 来开启 `batch/v2alpha1` API(更多信息请查看 [为你的集群开启或关闭 API 版本](/zh/docs/tasks/administer-cluster/cluster-management/#打开或关闭集群的-api-版本)
), 然后重启 API 服务器和控制管理器。
<!-- steps -->
@@ -80,7 +63,6 @@ component.
Cron jobs require a config file.
This example cron job config `.spec` file prints the current time and a hello message every minute:
-->
## 创建 CronJob
CronJob 需要一个配置文件。
@@ -91,61 +73,69 @@ CronJob 需要一个配置文件。
<!--
Run the example cron job by downloading the example file and then running this command:
-->
想要运行示例的 CronJob,可以下载示例文件并执行命令:
```shell
$ kubectl create -f ./cronjob.yaml
cronjob "hello" created
kubectl create -f ./cronjob.yaml
```
<!--
Alternatively, you can use `kubectl run` to create a cron job without writing a full config:
-->
或者你也可以使用 `kubectl run` 来创建一个 CronJob 而不需要编写完整的配置:
```shell
$ kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"
cronjob "hello" created
```
cronjob.batch/hello created
```
<!--
After creating the cron job, get its status using this command:
-->
创建好 CronJob 后,使用下面的命令来获取其状态:
```shell
$ kubectl get cronjob hello
NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE
hello */1 * * * * False 0 <none>
kubectl get cronjob hello
```
<!--
The output is similar to this:
-->
输出类似于:
```
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 50s 75s
```
<!--
As you can see from the results of the command, the cron job has not scheduled or run any jobs yet.
Watch for the job to be created in around one minute:
-->
就像你从命令返回结果看到的那样,CronJob 还没有调度或执行任何任务。大约需要一分钟任务才能创建好。
```shell
$ kubectl get jobs --watch
NAME DESIRED SUCCESSFUL AGE
hello-4111706356 1 1 2s
kubectl get jobs --watch
```
```
NAME COMPLETIONS DURATION AGE
hello-4111706356 0/1 0s
hello-4111706356 0/1 0s 0s
hello-4111706356 1/1 5s 5s
```
<!--
Now you've seen one running job scheduled by the "hello" cron job.
You can stop watching the job and view the cron job again to see that it scheduled the job:
-->
现在你已经看到了一个运行中的任务被 “hello” CronJob 调度。你可以停止监视这个任务,然后再次查看 CronJob 就能看到它调度任务:
现在你已经看到了一个运行中的任务被 “hello” CronJob 调度。
你可以停止监视这个任务,然后再次查看 CronJob 就能看到它调度任务:
```shell
$ kubectl get cronjob hello
NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE
hello */1 * * * * False 0 Mon, 29 Aug 2016 14:34:00 -0700
kubectl get cronjob hello
```
<!--
The output is similar to this:
-->
输出类似于:
```
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 0 50s 75s
```
<!--
@@ -155,21 +145,34 @@ There are currently 0 active jobs, meaning that the job has completed or failed.
Now, find the pods that the last scheduled job created and view the standard output of one of the pods.
Note that the job name and pod name are different.
-->
你应该能看到 “hello” CronJob 在 `LAST-SCHEDULE` 声明的时间点成功的调度了一次任务。有0个活跃的任务意味着任务执行完毕或者执行失败。
你应该能看到 “hello” CronJob 在 `LAST-SCHEDULE` 声明的时间点成功的调度了一次任务。
有 0 个活跃的任务意味着任务执行完毕或者执行失败。
现在,找到最后一次调度任务创建的 Pod 并查看一个 Pod 的标准输出。请注意任务名称和 Pod 名称是不同的。
<!--
The job name and pod name are different.
-->
{{< note >}}
Job 名称和 Pod 名称不同。
{{< /note >}}
```shell
# Replace "hello-4111706356" with the job name in your system
$ pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items..metadata.name})
# 在你的系统上将 "hello-4111706356" 替换为 Job 名称
pods=$(kubectl get pods --selector=job-name=hello-4111706356 --output=jsonpath={.items..metadata.name})
```
$ echo $pods
hello-4111706356-o9qcm
<!--
Show pod log:
-->
查看 Pod 日志:
$ kubectl logs $pods
Mon Aug 29 21:34:09 UTC 2016
```shell
kubectl logs $pods
```
```
Fri Feb 22 11:02:09 UTC 2019
Hello from the Kubernetes cluster
```
@@ -179,41 +182,42 @@ Hello from the Kubernetes cluster
When you don't need a cron job any more, delete it with `kubectl delete cronjob`:
-->
## 删除 CronJob
当你不再需要 CronJob 时,可以用 `kubectl delete cronjob` 删掉它:
```shell
$ kubectl delete cronjob hello
cronjob "hello" deleted
kubectl delete cronjob hello
```
<!--
Deleting the cron job removes all the jobs and pods it created and stops it from creating additional jobs.
You can read more about removing jobs in [garbage collection](/docs/concepts/workloads/controllers/garbage-collection/).
-->
删除 CronJob 会清除它创建的所有任务和 Pod,并阻止它创建额外的任务。你可以查阅 [垃圾收集](/zh/docs/concepts/workloads/controllers/garbage-collection/)。
删除 CronJob 会清除它创建的所有任务和 Pod,并阻止它创建额外的任务。你可以查阅
[垃圾收集](/zh/docs/concepts/workloads/controllers/garbage-collection/)。
<!--
## Writing a Cron Job Spec
As with all other Kubernetes configs, a cron job needs `apiVersion`, `kind`, and `metadata` fields. For general
information about working with config files, see [deploying applications](/docs/user-guide/deploying-applications),
and [using kubectl to manage resources](/docs/user-guide/working-with-resources) documents.
information about working with config files, see [deploying applications](/docs/tasks/run-application/run-stateless-application-deployment/),
and [using kubectl to manage resources](/docs/concepts/overview/working-with-objects/object-management/) documents.
A cron job config also needs a [`.spec` section](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
-->
## 编写 CronJob 声明信息
像 Kubernetes 的其他配置一样,CronJob 需要 `apiVersion` `kind` `metadata` 域。配置文件的一般信息,请参考 [部署应用](/zh/docs/tasks/run-application/run-stateless-application-deployment/) 和 [使用 kubectl 管理资源](/zh/docs/concepts/overview/working-with-objects/object-management/).
像 Kubernetes 的其他配置一样,CronJob 需要 `apiVersion``kind`、和 `metadata` 域。
配置文件的一般信息,请参考
[部署应用](/zh/docs/tasks/run-application/run-stateless-application-deployment/) 和
[使用 kubectl 管理资源](/zh/docs/concepts/overview/working-with-objects/object-management/).
CronJob 配置也需要包括[`.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
CronJob 配置也需要包括
[`.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).
{{< note >}}
<!--
All modifications to a cron job, especially its `.spec`, are applied only to the following runs.
-->
{{< note >}}
对 CronJob 的所有改动,特别是它的 `.spec`,只会影响将来的运行实例。
{{< /note >}}
@@ -223,16 +227,16 @@ All modifications to a cron job, especially its `.spec`, are applied only to the
The `.spec.schedule` is a required field of the `.spec`.
It takes a [Cron](https://en.wikipedia.org/wiki/Cron) format string, such as `0 * * * *` or `@hourly`, as schedule time of its jobs to be created and executed.
-->
### 时间安排
`.spec.schedule``.spec` 需要的域。它使用了 [Cron](https://en.wikipedia.org/wiki/Cron) 格式串,例如 `0 * * * *` or `@hourly` ,做为它的任务被创建和执行的调度时间。
`.spec.schedule``.spec` 需要的域。它使用了 [Cron](https://en.wikipedia.org/wiki/Cron)
格式串,例如 `0 * * * *` or `@hourly` ,做为它的任务被创建和执行的调度时间。
<!--
The format also includes extended `vixie cron` step values. As explained in the [FreeBSD manual](https://www.freebsd.org/cgi/man.cgi?crontab%285%29):
-->
该格式也包含了扩展的 `vixie cron` 步长值。[FreeBSD 手册](https://www.freebsd.org/cgi/man.cgi?crontab%285%29)中解释如下:
该格式也包含了扩展的 `vixie cron` 步长值。
[FreeBSD 手册](https://www.freebsd.org/cgi/man.cgi?crontab%285%29)中解释如下:
<!--
> Step values can be used in conjunction with ranges. Following a range
@@ -244,13 +248,14 @@ The format also includes extended `vixie cron` step values. As explained in the
-->
> 步长可被用于范围组合。范围后面带有 `/<数字>` 可以声明范围内的步幅数值。
> 例如,`0-23/2` 可被用在小时域来声明命令在其他数值的小时数执行( V7 标准中对应的方法是`0,2,4,6,8,10,12,14,16,18,20,22`)。
> 例如,`0-23/2` 可被用在小时域来声明命令在其他数值的小时数执行
> ( V7 标准中对应的方法是`0,2,4,6,8,10,12,14,16,18,20,22`)。
> 步长也可以放在通配符后面,因此如果你想表达 "每两小时",就用 `*/2` 。
{{< note >}}
<!--
A question mark (`?`) in the schedule has the same meaning as an asterisk `*`, that is, it stands for any of available value for a given field.
-->
{{< note >}}
调度中的问号 (`?`) 和星号 `*` 含义相同,表示给定域的任何可用值。
{{< /note >}}
@@ -258,14 +263,18 @@ A question mark (`?`) in the schedule has the same meaning as an asterisk `*`, t
### Job Template
The `.spec.jobTemplate` is the template for the job, and it is required.
It has exactly the same schema as a [Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/), except that it is nested and does not have an `apiVersion` or `kind`.
For information about writing a job `.spec`, see [Writing a Job Spec](/docs/concepts/workloads/controllers/jobs-run-to-completion/#writing-a-job-spec).
It has exactly the same schema as a [Job](/docs/concepts/workloads/controllers/job/),
except that it is nested and does not have an `apiVersion` or `kind`.
For information about writing a job `.spec`, see
[Writing a Job Spec](/docs/concepts/workloads/controllers/job/#writing-a-job-spec).
-->
### 任务模版
`.spec.jobTemplate`是任务的模版,它是必须的。它和 [Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/)的语法完全一样,除了它是嵌套的没有 `apiVersion``kind`
编写任务的 `.spec` ,请参考 [编写任务的Spec](/docs/concepts/workloads/controllers/jobs-run-to-completion/#writing-a-job-spec)。
`.spec.jobTemplate`是任务的模版,它是必须的。它和
[Job](/zh/docs/concepts/workloads/controllers/job/)的语法完全一样,
除了它是嵌套的没有 `apiVersion``kind`
编写任务的 `.spec` ,请参考
[编写 Job 的Spec](/zh/docs/concepts/workloads/controllers/job/#writing-a-job-spec)。
<!--
### Starting Deadline
@@ -276,8 +285,7 @@ After the deadline, the cron job does not start the job.
Jobs that do not meet their deadline in this way count as failed jobs.
If this field is not specified, the jobs have no deadline.
-->
### 开始的最后期限
### 开始的最后期限 {#starting-deadline}
`.spec.startingDeadlineSeconds` 域是可选的。
它表示任务如果由于某种原因错过了调度时间,开始该任务的截止时间的秒数。过了截止时间,CronJob 就不会开始任务。
@@ -294,11 +302,15 @@ field is set (not null), the CronJob controller counts how many missed jobs occu
schedules occurred in the last 200 seconds. In that case, if there were more than 100 missed schedules in the
last 200 seconds, the cron job is no longer scheduled.
-->
CronJob 控制器会统计错过了多少次调度。如果错过了100次以上的调度,CronJob 就不再调度了。当没有设置 `.spec.startingDeadlineSeconds` 时,CronJob 控制器统计从`status.lastScheduleTime`到当前的调度错过次数。
例如一个 CronJob 期望每分钟执行一次,`status.lastScheduleTime`是 5:00am,但现在是 7:00am。那意味着120次调度错过了,所以 CronJob 将不再被调度
如果设置了 `.spec.startingDeadlineSeconds` 域(非空),CronJob 控制器统计从 `.spec.startingDeadlineSeconds` 到当前时间错过了多少次任务。
例如设置了 `200`,它会统计过去200秒内错过了多少次调度。在那种情况下,如果过去200秒内错过了超过100次的调度,CronJob 不再调度。
CronJob 控制器会统计错过了多少次调度。如果错过了100次以上的调度,CronJob 就不再调度了。
当没有设置 `.spec.startingDeadlineSeconds` 时,CronJob 控制器统计从
`status.lastScheduleTime` 到当前的调度错过次数
例如一个 CronJob 期望每分钟执行一次,`status.lastScheduleTime``5:00am`
但现在是 `7:00am`。那意味着 120 次调度被错过了,所以 CronJob 不再调度。
如果设置了 `.spec.startingDeadlineSeconds` 域(非空),CronJob 控制器统计从
`.spec.startingDeadlineSeconds` 到当前时间错过了多少次任务。
例如设置了 `200`,它会统计过去 200 秒内错过了多少次调度。
在那种情况下,如果过去 200 秒内错过了超过 100 次的调度,CronJob 就不再调度。
<!--
### Concurrency Policy
@@ -314,10 +326,10 @@ the spec may specify only one of the following concurrency policies:
Note that concurrency policy only applies to the jobs created by the same cron job.
If there are multiple cron jobs, their respective jobs are always allowed to run concurrently.
-->
### 并发性规则
`.spec.concurrencyPolicy` 也是可选的。它声明了 CronJob 创建的任务执行时发生重叠如何处理。spec 仅能声明下列规则中的一种:
`.spec.concurrencyPolicy` 也是可选的。它声明了 CronJob 创建的任务执行时发生重叠如何处理。
spec 仅能声明下列规则中的一种:
* `Allow` (默认):CronJob 允许并发任务执行。
* `Forbid`: CronJob 不允许并发任务执行;如果新任务的执行时间到了而老任务没有执行完,CronJob 会忽略新任务的执行。
@@ -333,17 +345,18 @@ If it is set to `true`, all subsequent executions are suspended.
This setting does not apply to already started executions.
Defaults to false.
-->
### 挂起
`.spec.suspend`域也是可选的。如果设置为 `true` ,后续发生的执行都会挂起。这个设置对已经开始的执行不起作用。默认是关闭的。
`.spec.suspend`域也是可选的。如果设置为 `true` ,后续发生的执行都会挂起。
这个设置对已经开始的执行不起作用。默认是关闭的。
{{< caution >}}
<!--
Executions that are suspended during their scheduled time count as missed jobs.
When `.spec.suspend` changes from `true` to `false` on an existing cron job without a [starting deadline](#starting-deadline), the missed jobs are scheduled immediately.
-->
在调度时间内挂起的执行都会被统计为错过的任务。当 `.spec.suspend``true` 改为 `false` 时,且没有 [开始的最后期限](#starting-deadline),错过的任务会被立即调度。
{{< caution >}}
在调度时间内挂起的执行都会被统计为错过的任务。当 `.spec.suspend``true` 改为 `false` 时,
且没有 [开始的最后期限](#starting-deadline),错过的任务会被立即调度。
{{< /caution >}}
<!--
@@ -353,7 +366,6 @@ The `.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit` fields
These fields specify how many completed and failed jobs should be kept.
By default, they are set to 3 and 1 respectively. Setting a limit to `0` corresponds to keeping none of the corresponding kind of jobs after they finish.
-->
### 任务历史限制
`.spec.successfulJobsHistoryLimit``.spec.failedJobsHistoryLimit`是可选的。
@@ -1,5 +1,6 @@
---
title: 使用工作队列进行粗粒度并行处理
min-kubernetes-server-version: v1.8
content_type: task
weight: 30
---
@@ -7,6 +8,7 @@ weight: 30
<!--
---
title: Coarse Parallel Processing Using a Work Queue
min-kubernetes-server-version: v1.8
content_type: task
weight: 30
---
@@ -30,7 +32,6 @@ Here is an overview of the steps in this example:
1. **Start a Job that works on tasks from the queue**. The Job starts several pods. Each pod takes
one task from the message queue, processes it, and repeats until the end of the queue is reached.
-->
本例中,我们会运行包含多个并行工作进程的 Kubernetes Job。
本例中,每个 Pod 一旦被创建,会立即从任务队列中取走一个工作单元并完成它,然后将工作单元从队列中删除后再退出。
@@ -44,8 +45,6 @@ Here is an overview of the steps in this example:
1. **启动一个在队列中执行这些任务的 Job**。该 Job 启动多个 Pod。每个 Pod 从消息队列中取走一个任务,处理它,然后重复执行,直到队列的队尾。
## {{% heading "prerequisites" %}}
@@ -54,12 +53,11 @@ Be familiar with the basic,
non-parallel, use of [Job](/docs/concepts/jobs/run-to-completion-finite-workloads/).
-->
要熟悉 Job 基本用法(非并行的),请参考 [Job](/docs/concepts/jobs/run-to-completion-finite-workloads/)。
要熟悉 Job 基本用法(非并行的),请参考
[Job](/zh/docs/concepts/workloads/controllers/job/)。
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
@@ -72,7 +70,6 @@ cluster and reuse it for many jobs, as well as for long-running services.
Start RabbitMQ as follows:
-->
## 启动消息队列服务
本例使用了 RabbitMQ,使用其他 AMQP 类型的消息服务应该比较容易。
@@ -82,9 +79,17 @@ Start RabbitMQ as follows:
按下面的方法启动 RabbitMQ
```shell
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.3/examples/celery-rabbitmq/rabbitmq-service.yaml
kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.3/examples/celery-rabbitmq/rabbitmq-service.yaml
```
```
service "rabbitmq-service" created
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.3/examples/celery-rabbitmq/rabbitmq-controller.yaml
```
```shell
kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes/release-1.3/examples/celery-rabbitmq/rabbitmq-controller.yaml
```
```
replicationcontroller "rabbitmq-controller" created
```
@@ -103,7 +108,6 @@ and experiment with queues.
First create a temporary interactive Pod.
-->
## 测试消息队列服务
现在,我们可以试着访问消息队列。我们将会创建一个临时的可交互的 Pod,在它上面安装一些工具,然后用队列做实验。
@@ -112,7 +116,9 @@ First create a temporary interactive Pod.
```shell
# 创建一个临时的可交互的 Pod
$ kubectl run -i --tty temp --image ubuntu:14.04
kubectl run -i --tty temp --image ubuntu:14.04
```
```
Waiting for pod default/temp-loe07 to be running, status is Pending, pod ready: false
... [ previous line repeats several times .. hit return when it stops ] ...
```
@@ -122,7 +128,6 @@ Note that your pod name and command prompt will be different.
Next install the `amqp-tools` so we can work with message queues.
-->
请注意你的 Pod 名称和命令提示符将会不同。
接下来安装 `amqp-tools` ,这样我们就能用消息队列了。
@@ -148,10 +153,6 @@ Next, we will check that we can discover the rabbitmq service:
<!--
# Note the rabbitmq-service has a DNS name, provided by Kubernetes:
-->
<!--
# Your address will vary.
-->
```
# 请注意 rabbitmq-service 有Kubernetes 提供的 DNS 名称,
@@ -162,54 +163,43 @@ Address: 10.0.0.10#53
Name: rabbitmq-service.default.svc.cluster.local
Address: 10.0.147.152
# 你的 IP 地址将会发生变化。
# 你的 IP 地址会不同
```
<!--
If Kube-DNS is not setup correctly, the previous step may not work for you.
You can also find the service IP in an env var:
-->
如果 Kube-DNS 没有正确安装,上一步可能会出错。
你也可以在环境变量中找到服务 IP。
<!--
# Your address will vary.
-->
```
# env | grep RABBIT | grep HOST
RABBITMQ_SERVICE_SERVICE_HOST=10.0.147.152
# 你的 IP 地址将会发生变化。
# 你的 IP 地址会有所不同
```
<!--
Next we will verify we can create a queue, and publish and consume messages.
-->
接着我们将要确认可以创建队列,并能发布消息和消费消息。
<!--
# In the next line, rabbitmq-service is the hostname where the rabbitmq-service
# can be reached. 5672 is the standard port for rabbitmq.
-->
<!--
# If you could not resolve "rabbitmq-service" in the previous step,
# then use this command instead:
# root@temp-loe07:/# BROKER_URL=amqp://guest:guest@$RABBITMQ_SERVICE_SERVICE_HOST:5672
# Now create a queue:
-->
<!--
# and publish a message to it:
-->
<!--
# and get it back.
-->
```shell
# 下一行,rabbitmq-service 是访问 rabbitmq-service 的主机名。5672是 rabbitmq 的标准端口。
@@ -232,6 +222,7 @@ root@temp-loe07:/# /usr/bin/amqp-consume --url=$BROKER_URL -q foo -c 1 cat && ec
Hello
root@temp-loe07:/#
```
<!--
In the last command, the `amqp-consume` tool takes one message (`-c 1`)
from the queue, and passes that message to the standard input of an arbitrary command. In this case, the program `cat` is just printing
@@ -255,7 +246,6 @@ In a practice, the content of the messages might be:
- configuration parameters to a simulation
- frame numbers of a scene to be rendered
-->
## 为队列增加任务
现在让我们给队列增加一些任务。在我们的示例中,任务是多个待打印的字符串。
@@ -283,9 +273,9 @@ In practice, you might write a program to fill the queue using an amqp client li
例如,我们创建队列并使用 amqp 命令行工具向队列中填充消息。实践中,你可以写个程序来利用 amqp 客户端库来填充这些队列。
```shell
$ /usr/bin/amqp-declare-queue --url=$BROKER_URL -q job1 -d job1
$ for f in apple banana cherry date fig grape lemon melon
/usr/bin/amqp-declare-queue --url=$BROKER_URL -q job1 -d job1
for f in apple banana cherry date fig grape lemon melon
do
/usr/bin/amqp-publish --url=$BROKER_URL -r job1 -p -b $f
done
@@ -302,7 +292,6 @@ We will use the `amqp-consume` utility to read the message
from the queue and run our actual program. Here is a very simple
example program:
-->
这样,我们给队列中填充了8个消息。
## 创建镜像
@@ -322,10 +311,14 @@ and [worker.py](/examples/application/job/rabbitmq/worker.py). In either case,
build the image with this command:
-->
现在,编译镜像。如果你在用源代码树,那么切换到目录 `examples/job/work-queue-1`否则的话,创建一个临时目录,切换到这个目录。下载 [Dockerfile](/examples/application/job/rabbitmq/Dockerfile),和 [worker.py](/examples/application/job/rabbitmq/worker.py)。无论哪种情况,都可以用下面的命令编译镜像
现在,编译镜像。如果你在用源代码树,那么切换到目录 `examples/job/work-queue-1`
否则的话,创建一个临时目录,切换到这个目录。下载
[Dockerfile](/examples/application/job/rabbitmq/Dockerfile),和
[worker.py](/examples/application/job/rabbitmq/worker.py)。
无论哪种情况,都可以用下面的命令编译镜像
```shell
$ docker build -t job-wq-1 .
docker build -t job-wq-1 .
```
<!--
@@ -333,8 +326,8 @@ For the [Docker Hub](https://hub.docker.com/), tag your app image with
your username and push to the Hub with the below commands. Replace
`<username>` with your Hub username.
-->
对于 [Docker Hub](https://hub.docker.com/), 给你的应用镜像打上标签,标签为你的用户名,然后用下面的命令推送到 Hub。用你的 Hub 用户名替换 `<username>`
对于 [Docker Hub](https://hub.docker.com/), 给你的应用镜像打上标签,
标签为你的用户名,然后用下面的命令推送到 Hub。用你的 Hub 用户名替换 `<username>`
```shell
docker tag job-wq-1 <username>/job-wq-1
@@ -347,8 +340,9 @@ Registry](https://cloud.google.com/tools/container-registry/), tag
your app image with your project ID, and push to GCR. Replace
`<project>` with your project ID.
-->
如果你在用[谷歌容器仓库](https://cloud.google.com/tools/container-registry/)用你的项目 ID 作为标签打到你的应用镜像上,然后推送到 GCR。用你的项目 ID 替换 `<project>`
如果你在用[谷歌容器仓库](https://cloud.google.com/tools/container-registry/)
用你的项目 ID 作为标签打到你的应用镜像上,然后推送到 GCR。
用你的项目 ID 替换 `<project>`
```shell
docker tag job-wq-1 gcr.io/<project>/job-wq-1
@@ -361,7 +355,6 @@ gcloud docker -- push gcr.io/<project>/job-wq-1
Here is a job definition. You'll need to make a copy of the Job and edit the
image to match the name you used, and call it `./job.yaml`.
-->
## 定义 Job
这里给出一个 Job 定义 yaml文件。你需要拷贝一份并编辑镜像以匹配你使用的名称,保存为 `./job.yaml`
@@ -377,7 +370,6 @@ done. So we set, `.spec.completions: 8` for the example, since we put 8 items i
So, now run the Job:
-->
本例中,每个 Pod 使用队列中的一个消息然后退出。这样,Job 的完成计数就代表了完成的工作项的数量。本例中我们设置 `.spec.completions: 8`,因为我们放了8项内容在队列中。
## 运行 Job
@@ -395,7 +387,10 @@ Now wait a bit, then check on the job.
稍等片刻,然后检查 Job。
```shell
$ kubectl describe jobs/job-wq-1
kubectl describe jobs/job-wq-1
```
```
Name: job-wq-1
Namespace: default
Selector: controller-uid=41d75705-92df-11e7-b85e-fa163ee3c11f
@@ -434,11 +429,8 @@ Events:
<!--
All our pods succeeded. Yay.
-->
我们所有的 Pod 都成功了。耶!
<!-- discussion -->
<!--
@@ -451,12 +443,12 @@ It does require that you run a message queue service.
If running a queue service is inconvenient, you may
want to consider one of the other [job patterns](/docs/concepts/jobs/run-to-completion-finite-workloads/#job-patterns).
-->
## 替代方案
本文所讲述的处理方法的好处是你不需要修改你的 "worker" 程序使其知道工作队列的存在。
本文所描述的方法需要你运行一个消息队列服务。如果不方便运行消息队列服务,你也许会考虑另外一种[任务模式](/docs/concepts/jobs/run-to-completion-finite-workloads/#job-patterns)。
本文所描述的方法需要你运行一个消息队列服务。如果不方便运行消息队列服务,你也许会考虑另外一种
[任务模式](/zh/docs/concepts/workloads/controllers/job/#job-patterns)。
<!--
This approach creates a pod for every work item. If your work items only take a few seconds,
@@ -470,9 +462,15 @@ A [different example](/docs/tasks/job/fine-parallel-processing-work-queue/), sho
communicate with the work queue using a client library.
-->
本文所述的方法为每个工作项创建了一个 Pod。如果你的工作项仅需数秒钟,为每个工作项创建 Pod会增加很多的常规消耗。可以考虑另外的方案请参考[示例](/docs/tasks/job/fine-parallel-processing-work-queue/),这种方案可以实现每个 Pod 执行多个工作项。
本文所述的方法为每个工作项创建了一个 Pod。
如果你的工作项仅需数秒钟,为每个工作项创建 Pod会增加很多的常规消耗。
可以考虑另外的方案请参考[示例](/zh/docs/tasks/job/fine-parallel-processing-work-queue/)
这种方案可以实现每个 Pod 执行多个工作项。
示例中,我们使用 `amqp-consume` 从消息队列读取消息并执行我们真正的程序。这样的好处是你不需要修改你的程序使其知道队列的存在。要了解怎样使用客户端库和工作队列通信,请参考[不同的示例](/docs/tasks/job/fine-parallel-processing-work-queue/)。
示例中,我们使用 `amqp-consume` 从消息队列读取消息并执行我们真正的程序。
这样的好处是你不需要修改你的程序使其知道队列的存在。
要了解怎样使用客户端库和工作队列通信,请参考
[不同的示例](/zh/docs/tasks/job/fine-parallel-processing-work-queue/)。
<!--
## Caveats
@@ -491,15 +489,14 @@ exits with success, or if the node crashes before the kubelet is able to post th
back to the api-server, then the Job will not appear to be complete, even though all items
in the queue have been processed.
-->
## 友情提醒
如果设置的完成数量小于队列中的消息数量,会导致一部分消息项不会被执行。
如果设置的完成数量大于队列中的消息数量,当队列中所有的消息都处理完成后,Job 也会显示为未完成。Job 将创建 Pod 并阻塞等待消息输入。
如果设置的完成数量大于队列中的消息数量,当队列中所有的消息都处理完成后,
Job 也会显示为未完成。Job 将创建 Pod 并阻塞等待消息输入。
当发生下面两种情况时,即使队列中所有的消息都处理完了,Job 也不会显示为完成状态:
* 在 amqp-consume 命令拿到消息和容器成功退出之间的时间段内,执行杀死容器操作;
* 在 kubelet 向 api-server 传回 Pod 成功运行之前,发生节点崩溃。
@@ -1,16 +1,14 @@
---
cn-approvers:
- linyouchong
title: 使用工作队列进行精细的并行处理
content_type: task
min-kubernetes-server-version: v1.8
weight: 40
---
<!--
---
title: Fine Parallel Processing Using a Work Queue
content_type: task
weight: 40
---
min-kubernetes-server-version: v1.8
-->
<!-- overview -->
@@ -24,14 +22,12 @@ worker processes in a given pod.
<!--
In this example, as each pod is created, it picks up one unit of work
from a task queue, processes it, and repeats until the end of the queue is reached.
Here is an overview of the steps in this example:
-->
在这个例子中,当每个pod被创建时,它会从一个任务队列中获取一个工作单元,处理它,然后重复,直到到达队列的尾部。
<!--
Here is an overview of the steps in this example:
-->
下面是这个示例的步骤概述
下面是这个示例的步骤概述:
<!--
1. **Start a storage service to hold the work queue.** In this example, we use Redis to store
@@ -41,77 +37,55 @@ Here is an overview of the steps in this example:
as Redis once and reuse it for the work queues of many jobs, and other things.
-->
1. **启动存储服务用于保存工作队列。** 在这个例子中,我们使用 Redis 来存储工作项。在上一个例子中,我们使用了 RabbitMQ。在这个例子中,由于 AMQP 不能为客户端提供一个良好的方法来检测一个有限长度的工作队列是否为空,我们使用了 Redis 和一个自定义的工作队列客户端库。在实践中,您可能会设置一个类似于 Redis 的存储库,并将其同时用于多项任务或其他事务的工作队列。
1. **启动存储服务用于保存工作队列。** 在这个例子中,我们使用 Redis 来存储工作项。
在上一个例子中,我们使用了 RabbitMQ。
在这个例子中,由于 AMQP 不能为客户端提供一个良好的方法来检测一个有限长度的工作队列是否为空,
我们使用了 Redis 和一个自定义的工作队列客户端库。
在实践中,你可能会设置一个类似于 Redis 的存储库,并将其同时用于多项任务或其他事务的工作队列。
<!--
1. **Create a queue, and fill it with messages.** Each message represents one task to be done. In
this example, a message is just an integer that we will do a lengthy computation on.
-->
2. **创建一个队列,然后向其中填充消息。** 每个消息表示一个将要被处理的工作任务。在这个例子中,消息只是一个我们将用于进行长度计算的整数。
2. **创建一个队列,然后向其中填充消息。** 每个消息表示一个将要被处理的工作任务。
在这个例子中,消息只是一个我们将用于进行长度计算的整数。
<!--
1. **Start a Job that works on tasks from the queue**. The Job starts several pods. Each pod takes
one task from the message queue, processes it, and repeats until the end of the queue is reached.
-->
3. **启动一个 Job 对队列中的任务进行处理**。这个 Job 启动了若干个 Pod 。每个 Pod 从消息队列中取出一个工作任务,处理它,然后重复,直到到达队列的尾部。
{{< toc >}}
3. **启动一个 Job 对队列中的任务进行处理**。这个 Job 启动了若干个 Pod 。
每个 Pod 从消息队列中取出一个工作任务,处理它,然后重复,直到到达队列的尾部。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
Be familiar with the basic,
non-parallel, use of [Job](/docs/concepts/jobs/run-to-completion-finite-workloads/).
non-parallel, use of [Job](/docs/concepts/workloads/controllers/job/).
-->
秋基础知识,非并行方式运行 [Job](/docs/concepts/jobs/run-to-completion-finite-workloads/)。
悉基本的、非并行的 [Job](/zh/docs/concepts/workloads/controllers/job/)。
<!-- steps -->
<!--
## Starting Redis
-->
## 启动 Redis
<!--
For this example, for simplicity, we will start a single instance of Redis.
See the [Redis Example](https://github.com/kubernetes/examples/tree/master/guestbook) for an example
of deploying Redis scalably and redundantly.
-->
## 启动 Redis
对于这个例子,为了简单起见,我们将启动一个单实例的 Redis。
了解如何部署一个可伸缩、高可用的 Redis 例子,请查看 [Redis 样例](https://github.com/kubernetes/examples/tree/master/guestbook)
了解如何部署一个可伸缩、高可用的 Redis 例子,请查看
[Redis 示例](https://github.com/kubernetes/examples/tree/master/guestbook)
<!--
If you are working from the website source tree, you can go to the following
directory and start a temporary Pod running Redis and a service so we can find it.
You could also download the following files directly:
-->
如果您在使用本文档库的源代码目录,您可以进入如下目录,然后启动一个临时的 Pod 用于运行 Redis 和 一个临时的 service 以便我们能够找到这个 Pod
```shell
$ cd content/en/examples/application/job/redis
$ kubectl create -f ./redis-pod.yaml
pod/redis-master created
$ kubectl create -f ./redis-service.yaml
service/redis created
```
<!--
If you're not working from the source tree, you could also download the following
files directly:
-->
如果您没有使用本文档库的源代码目录,您可以直接下载如下文件:
你可以直接下载如下文件:
- [`redis-pod.yaml`](/examples/application/job/redis/redis-pod.yaml)
- [`redis-service.yaml`](/examples/application/job/redis/redis-service.yaml)
@@ -122,22 +96,22 @@ files directly:
<!--
## Filling the Queue with tasks
Now let's fill the queue with some "tasks". In our example, our tasks are just strings to be
printed.
Start a temporary interactive pod for running the Redis CLI.
-->
## 使用任务填充队列
<!--
Now let's fill the queue with some "tasks". In our example, our tasks are just strings to be
printed.
-->
现在,让我们往队列里添加一些“任务”。在这个例子中,我们的任务只是一些将被打印出来的字符串。
<!--
Start a temporary interactive pod for running the Redis CLI.
-->
启动一个临时的可交互的 pod 用于运行 Redis 命令行界面。
```shell
$ kubectl run -i --tty temp --image redis --command "/bin/sh"
kubectl run -i --tty temp --image redis --command "/bin/sh"
```
```
Waiting for pod default/redis2-c7h78 to be running, status is Pending, pod ready: false
Hit enter for command prompt
```
@@ -188,29 +162,26 @@ So, the list with key `job2` will be our work queue.
Note: if you do not have Kube DNS setup correctly, you may need to change
the first step of the above block to `redis-cli -h $REDIS_SERVICE_HOST`.
-->
注意:如果还没有正确地配置 Kube DNS可能需要将上面的第一步改为 `redis-cli -h $REDIS_SERVICE_HOST`
注意:如果还没有正确地配置 Kube DNS可能需要将上面的第一步改为
`redis-cli -h $REDIS_SERVICE_HOST`
<!--
## Create an Image
-->
创建镜像
<!--
Now we are ready to create an image that we will run.
-->
现在我们已经准备好创建一个我们要运行的镜像
<!--
We will use a python worker program with a redis client to read
the messages from the message queue.
-->
我们会使用一个带有 redis 客户端的 python 工作程序从消息队列中读出消息。
<!--
A simple Redis work queue client library is provided,
called rediswq.py ([Download](/examples/application/job/redis/rediswq.py)).
-->
## 创建镜像
现在我们已经准备好创建一个我们要运行的镜像
我们会使用一个带有 redis 客户端的 python 工作程序从消息队列中读出消息。
这里提供了一个简单的 Redis 工作队列客户端库,叫 rediswq.py ([下载](/examples/application/job/redis/rediswq.py))。
<!--
@@ -222,12 +193,12 @@ Job 中每个 Pod 内的 “工作程序” 使用工作队列客户端库获取
{{< codenew language="python" file="application/job/redis/worker.py" >}}
<!--
If you are working from the source tree,
change directory to the `content/en/examples/application/job/redis/` directory.
Otherwise, download [`worker.py`](/examples/application/job/redis/worker.py), [`rediswq.py`](/examples/application/job/redis/rediswq.py), and [`Dockerfile`](/examples/application/job/redis/Dockerfile)
You could download [`worker.py`](/examples/application/job/redis/worker.py), [`rediswq.py`](/examples/application/job/redis/rediswq.py), and [`Dockerfile`](/examples/application/job/redis/Dockerfile)
using above links. Then build the image:
-->
如果您在使用本文档库的源代码目录,请将当前目录切换到 `content/en/examples/application/job/redis/`。否则,请点击链接下载 [`worker.py`](/examples/application/job/redis/worker.py)、 [`rediswq.py`](/examples/application/job/redis/rediswq.py) 和 [`Dockerfile`](/examples/application/job/redis/Dockerfile)。然后构建镜像:
你也可以下载 [`worker.py`](/examples/application/job/redis/worker.py)、
[`rediswq.py`](/examples/application/job/redis/rediswq.py) 和
[`Dockerfile`](/examples/application/job/redis/Dockerfile)。然后构建镜像:
```shell
docker build -t job-wq-2 .
@@ -235,15 +206,15 @@ docker build -t job-wq-2 .
<!--
### Push the image
-->
### Push 镜像
<!--
For the [Docker Hub](https://hub.docker.com/), tag your app image with
your username and push to the Hub with the below commands. Replace
`<username>` with your Hub username.
-->
对于 [Docker Hub](https://hub.docker.com/),请先用您的用户名给镜像打上标签,然后使用下面的命令 push 您的镜像到仓库。请将 `<username>` 替换为您自己的用户名。
### Push 镜像
对于 [Docker Hub](https://hub.docker.com/),请先用你的用户名给镜像打上标签,
然后使用下面的命令 push 你的镜像到仓库。请将 `<username>` 替换为你自己的用户名。
```shell
docker tag job-wq-2 <username>/job-wq-2
@@ -254,7 +225,8 @@ docker push <username>/job-wq-2
You need to push to a public repository or [configure your cluster to be able to access
your private repository](/docs/concepts/containers/images/).
-->
需要将镜像 push 到一个公共仓库或者 [配置集群访问您的私有仓库](/docs/concepts/containers/images/)。
需要将镜像 push 到一个公共仓库或者
[配置集群访问你的私有仓库](/zh/docs/concepts/containers/images/)。
<!--
If you are using [Google Container
@@ -262,8 +234,8 @@ Registry](https://cloud.google.com/tools/container-registry/), tag
your app image with your project ID, and push to GCR. Replace
`<project>` with your project ID.
-->
如果使用的是 [Google Container
Registry](https://cloud.google.com/tools/container-registry/)请先用的 project ID 给的镜像打上标签,然后 push 到 GCR 。请将 `<project>` 替换为自己的 project ID
如果使用的是 [Google Container Registry](https://cloud.google.com/tools/container-registry/)
请先用的 project ID 给的镜像打上标签,然后 push 到 GCR 。请将 `<project>` 替换为自己的 project ID
```shell
docker tag job-wq-2 gcr.io/<project>/job-wq-2
@@ -272,12 +244,11 @@ gcloud docker -- push gcr.io/<project>/job-wq-2
<!--
## Defining a Job
Here is the job definition:
-->
## 定义一个 Job
<!--
Here is the job definition:
-->
这是 job 定义:
{{< codenew file="application/job/redis/job.yaml" >}}
@@ -286,7 +257,7 @@ Here is the job definition:
Be sure to edit the job template to
change `gcr.io/myproject` to your own path.
-->
请确保将 job 模板中的 `gcr.io/myproject` 更改为自己的路径。
请确保将 job 模板中的 `gcr.io/myproject` 更改为自己的路径。
<!--
In this example, each pod works on several items from the queue and then exits when there are no more items.
@@ -297,21 +268,25 @@ exits with success, the controller knows the work is done, and the Pods will exi
So, we set the completion count of the Job to 1. The job controller will wait for the other pods to complete
too.
-->
在这个例子中,每个 pod 处理了队列中的多个项目,直到队列中没有项目时便退出。因为是由工作程序自行检测工作队列是否为空,并且 Job 控制器不知道工作队列的存在,所以依赖于工作程序在完成工作时发出信号。工作程序以成功退出的形式发出信号表示工作队列已经为空。所以,只要有任意一个工作程序成功退出,控制器就知道工作已经完成了,所有的 Pod 将很快会退出。因此,我们将 Job 的 completion count 设置为 1 。尽管如此,Job 控制器还是会等待其它 Pod 完成。
在这个例子中,每个 pod 处理了队列中的多个项目,直到队列中没有项目时便退出。
因为是由工作程序自行检测工作队列是否为空,并且 Job 控制器不知道工作队列的存在,
所以依赖于工作程序在完成工作时发出信号。
工作程序以成功退出的形式发出信号表示工作队列已经为空。
所以,只要有任意一个工作程序成功退出,控制器就知道工作已经完成了,所有的 Pod 将很快会退出。
因此,我们将 Job 的完成计数(Completion Count)设置为 1 。
尽管如此,Job 控制器还是会等待其它 Pod 完成。
<!--
## Running the Job
So, now run the Job:
-->
## 运行 Job
<!--
So, now run the Job:
-->
现在运行这个 Job
```shell
kubectl create -f ./job.yaml
kubectl apply -f ./job.yaml
```
<!--
@@ -320,7 +295,10 @@ Now wait a bit, then check on the job.
稍等片刻,然后检查这个 Job。
```shell
$ kubectl describe jobs/job-wq-2
kubectl describe jobs/job-wq-2
```
```
Name: job-wq-2
Namespace: default
Selector: controller-uid=b1c7e4e3-92e1-11e7-b85e-fa163ee3c11f
@@ -345,9 +323,15 @@ Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
33s 33s 1 {job-controller } Normal SuccessfulCreate Created pod: job-wq-2-lglf8
```
查看日志:
$ kubectl logs pods/job-wq-2-7r7b2
```shell
kubectl logs pods/job-wq-2-7r7b2
```
```
Worker with sessionID: bbd72d0a-9e5c-4dd6-abf6-416cc267991f
Initial queue state: empty=False
Working on banana
@@ -358,22 +342,21 @@ Working on lemon
<!--
As you can see, one of our pods worked on several work units.
-->
可以看到,其中的一个 pod 处理了若干个工作单元。
可以看到,其中的一个 pod 处理了若干个工作单元。
<!-- discussion -->
<!--
## Alternatives
-->
## 其它
## 替代方案
<!--
If running a queue service or modifying your containers to use a work queue is inconvenient, you may
want to consider one of the other [job patterns](/docs/concepts/jobs/run-to-completion-finite-workloads/#job-patterns).
-->
如果不方便运行一个队列服务或者修改的容器用于运行一个工作队列,可以考虑其它的 [job 模式](/docs/concepts/jobs/run-to-completion-finite-workloads/#job-patterns)。
如果不方便运行一个队列服务或者修改的容器用于运行一个工作队列,可以考虑其它的
[Job 模式](/zh/docs/concepts/workloads/controllers/job/#job-patterns)。
<!--
If you have a continuous stream of background processing work to run, then
@@ -381,6 +364,7 @@ consider running your background workers with a `replicationController` instead,
and consider running a background processing library such as
[https://github.com/resque/resque](https://github.com/resque/resque).
-->
如果有连续的后台处理业务,那么可以考虑使用 `replicationController` 来运行的后台业务,和运行一个类似 [https://github.com/resque/resque](https://github.com/resque/resque) 的后台处理库。
如果有连续的后台处理业务,那么可以考虑使用 `replicationController` 来运行的后台业务,
和运行一个类似 [https://github.com/resque/resque](https://github.com/resque/resque)
的后台处理库。