This commit is contained in:
yJunS
2021-07-11 21:46:30 +08:00
696 changed files with 24489 additions and 3093 deletions
@@ -285,5 +285,4 @@ Kubernetes 允许你运行一个稳定的控制平面,这样即使某些内置
的一些基本知识
* 进一步学习 [Kubernetes API](/zh/docs/concepts/overview/kubernetes-api/)
* 如果你想编写自己的控制器,请看 Kubernetes 的
[扩展模式](/zh/docs/concepts/extend-kubernetes/extend-cluster/#extension-patterns)。
[扩展模式](/zh/docs/concepts/extend-kubernetes/#extension-patterns)。
@@ -279,7 +279,7 @@ DC 上运行的 VMware)也在[这里](https://portworx.com/architects-corner-k
[Calico](https://docs.projectcalico.org/) 是一个开源的联网及网络安全方案,
用于基于容器、虚拟机和本地主机的工作负载。
Calico 支持多个数据面,包括:纯 Linux eBPF 的数据面、标准的 Linux 联网数据面
以及 Windwos HNS 数据面。Calico 在提供完整的联网堆栈的同时,还可与
以及 Windows HNS 数据面。Calico 在提供完整的联网堆栈的同时,还可与
[云驱动 CNIs](https://docs.projectcalico.org/networking/determine-best-networking#calico-compatible-cni-plugins-and-cloud-provider-integrations) 联合使用,以保证网络策略实施。
<!--
@@ -52,7 +52,7 @@ The aggregation layer runs in-process with the kube-apiserver. Until an extensio
<!--
The most common way to implement the APIService is to run an *extension API server* in Pod(s) that run in your cluster. If you're using the extension API server to manage resources in your cluster, the extension API server (also written as "extension-apiserver") is typically paired with one or more {{< glossary_tooltip text="controllers" term_id="controller" >}}. The apiserver-builder library provides a skeleton for both extension API servers and the associated controller(s).
-->
APIService 的最常见实现方式是在集群中某 Pod 内运行 *扩展 API 服务器*
APIService 的最常见实现方式是在集群中某 Pod 内运行 *扩展 API 服务器*
如果你在使用扩展 API 服务器来管理集群中的资源,该扩展 API 服务器(也被写成“extension-apiserver”)
一般需要和一个或多个{{< glossary_tooltip text="控制器" term_id="controller" >}}一起使用。
apiserver-builder 库同时提供构造扩展 API 服务器和控制器框架代码。
@@ -71,7 +71,7 @@ If your extension API server cannot achieve that latency requirement, consider m
扩展 API 服务器与 kube-apiserver 之间需要存在低延迟的网络连接。
发现请求需要在五秒钟或更短的时间内完成到 kube-apiserver 的往返。
如果你的扩展 API 服务器无法满足这一延迟要求,应考虑如何更改配置满足需要。
如果你的扩展 API 服务器无法满足这一延迟要求,应考虑如何更改配置满足需要。
## {{% heading "whatsnext" %}}
@@ -87,4 +87,3 @@ If your extension API server cannot achieve that latency requirement, consider m
开始使用聚合层。
* 也可以学习怎样[使用自定义资源定义扩展 Kubernetes API](/zh/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)。
* 阅读 [APIService](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#apiservice-v1-apiregistration-k8s-io) 的规范
@@ -21,6 +21,7 @@ These virtual clusters are called namespaces.
-->
Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。
这些虚拟集群被称为名字空间。
在一些文档里名字空间也称为命名空间。
<!-- body -->
@@ -17,7 +17,7 @@ weight: 30
<!--
PodSecurityPolicy is deprecated as of Kubernetes v1.21, and will be removed in v1.25.
-->
PodSecurityPolicy 在 Kubernetes v1.21 版本中被用,将在 v1.25 中删除。
PodSecurityPolicy 在 Kubernetes v1.21 版本中被用,将在 v1.25 中删除。
<!--
Pod Security Policies enable fine-grained authorization of pod creation and
@@ -244,7 +244,7 @@ Finalizers: [kubernetes.io/pvc-protection]
You can see that a PV is protected when the PV's status is `Terminating` and the `Finalizers` list includes `kubernetes.io/pv-protection` too:
-->
你也可以看到当 PV 对象的状态为 `Terminating` 且其 `Finalizers` 列表中包含
`kubernetes.io/pvc-protection` 时,PV 对象是处于被保护状态的。
`kubernetes.io/pv-protection` 时,PV 对象是处于被保护状态的。
```shell
kubectl describe pv task-pv-volume
@@ -1038,12 +1038,12 @@ metadata:
provisioner: kubernetes.io/azure-disk
parameters:
storageaccounttype: Standard_LRS
kind: Shared
kind: managed
```
<!--
* `storageaccounttype`: Azure storage account Sku tier. Default is empty.
* `kind`: Possible values are `shared` (default), `dedicated`, and `managed`.
* `kind`: Possible values are `shared`, `dedicated`, and `managed` (default).
When `kind` is `shared`, all unmanaged disks are created in a few shared
storage accounts in the same resource group as the cluster. When `kind` is
`dedicated`, a new dedicated storage account will be created for the new
@@ -1055,7 +1055,7 @@ parameters:
placed in the same resource group as the current Kubernetes cluster.
-->
* `storageaccounttype`:Azure 存储帐户 Sku 层。默认为空。
* `kind`:可能的值是 `shared`(默认)`dedicated``managed`
* `kind`:可能的值是 `shared``dedicated``managed`(默认)
`kind` 的值是 `shared` 时,所有非托管磁盘都在集群的同一个资源组中的几个共享存储帐户中创建。
`kind` 的值是 `dedicated` 时,将为在集群的同一个资源组中新的非托管磁盘创建新的专用存储帐户。
* `resourceGroup`: 指定要创建 Azure 磁盘所属的资源组。必须是已存在的资源组名称。
@@ -482,7 +482,7 @@ replication controllers, replica sets or stateful sets that the Pod belongs to.
An example configuration might look like follows:
-->
你可以在 [调度方案(Schedulingg Profile](/zh/docs/reference/scheduling/config/#profiles)
你可以在 [调度方案(Scheduling Profile](/zh/docs/reference/scheduling/config/#profiles)
中将默认约束作为 `PodTopologySpread` 插件参数的一部分来设置。
约束的设置采用[如前所述的 API](#api),只是 `labelSelector` 必须为空。
选择算符是根据 Pod 所属的服务、副本控制器、ReplicaSet 或 StatefulSet 来设置的。
@@ -224,7 +224,7 @@ Please check [installation caveats](https://acme.com/docs/v1/caveats) ...
- 标点符号是英文命令的一部分;
- 标点符号是 Markdown 语法的一部分。
英文排比句式中采用的逗号,在译文中要使用顿号代替,合中文书写习惯。
英文排比句式中采用的逗号,在译文中要使用顿号代替,以便符合中文书写习惯。
## 更新译文
@@ -309,8 +309,8 @@ Website 的仓库中 `scripts/linkchecker.py` 是一个工具,可用来检查
井号(`#`)转换为全角,导致链接失效。
{{< /warning >}}
英文中 "you" 翻译成 "你" 不必是 “您"
文章内的链接用英文例如 (#deploying ),在对应的标题上后面加上 {#deploying}
英文中 "you" 翻译成 "你" 不必是 “您"
文章内的链接用英文例如 (#deploying),在对应的标题上后面加上 {#deploying}
## 术语
@@ -126,12 +126,13 @@ state for some duration:
<!--
## Signers
All signers should provide information about how they work
Custom signerNames can also be specified. All signers should provide information about how they work
so that clients can predict what will happen to their CSRs.
This includes:
-->
## 签名者 {#signers}
也可以指定自定义 signerName。
所有签名者都应该提供自己工作方式的信息,
以便客户端可以预期到他们的 CSR 将发生什么。
此类信息包括:
@@ -423,8 +424,8 @@ O is the group that this user will belong to. You can refer to
你可以参考 [RBAC](/zh/docs/reference/access-authn-authz/rbac/) 了解标准组的信息。
```shell
openssl genrsa -out john.key 2048
openssl req -new -key john.key -out john.csr
openssl genrsa -out myuser.key 2048
openssl req -new -key myuser.key -out myuser.csr
```
<!--
@@ -443,7 +444,7 @@ cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: john
name: myuser
spec:
groups:
- system:authenticated
@@ -459,13 +460,13 @@ Some points to note:
- `usages` has to be '`client auth`'
- `request` is the base64 encoded value of the CSR file content.
You can use this command to get that ```cat john.csr | base64 | tr -d "\n"```
You can get the content using this command: ```cat myuser.csr | base64 | tr -d "\n"```
-->
需要注意的几点:
- `usage` 字段必须是 '`client auth`'
- `request` 字段是 CSR 文件内容的 base64 编码值。
要得到该值,可以执行命令 `cat john.csr | base64 | tr -d "\n"`
要得到该值,可以执行命令 `cat myuser.csr | base64 | tr -d "\n"`
<!--
### Approve certificate signing request
@@ -490,7 +491,7 @@ Approve the CSR:
批准 CSR
```shell
kubectl certificate approve john
kubectl certificate approve myuser
```
<!--
@@ -503,14 +504,23 @@ Retrieve the certificate from the CSR.
从 CSR 取得证书:
```shell
kubectl get csr/john -o yaml
kubectl get csr/myuser -o yaml
```
<!--
The Certificate value is in Base64-encoded format under `status.certificate`.
Export the issued certificate from the CertificateSigningRequest.
-->
证书的内容使用 base64 编码,存放在字段 `status.certificate`
从 CertificateSigningRequest 导出颁发的证书。
```
kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt
```
<!--
### Create Role and Role Binding
@@ -536,14 +546,13 @@ This is a sample command to create a RoleBinding for this new user:
下面是为这个新用户创建 RoleBinding 的示例命令:
```shell
kubectl create rolebinding developer-binding-john --role=developer --user=john
kubectl create rolebinding developer-binding-myuser --role=developer --user=myuser
```
<!--
### Add to kubeconfig
The last step is to add this user into the kubeconfig file.
We assume the key and crt files are located here "/home/vagrant/work/".
First, we need to add new credentials:
-->
@@ -555,7 +564,7 @@ First, we need to add new credentials:
首先,我们需要添加新的凭据:
```shell
kubectl config set-credentials john --client-key=/home/vagrant/work/john.key --client-certificate=/home/vagrant/work/john.crt --embed-certs=true
kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true
```
@@ -565,16 +574,16 @@ Then, you need to add the context:
然后,你需要添加上下文:
```shell
kubectl config set-context john --cluster=kubernetes --user=john
kubectl config set-context myuser --cluster=kubernetes --user=myuser
```
<!--
To test it, change context to `john`
To test it, change the context to `myuser`:
-->
来测试一下,把上下文切换为 `john`
来测试一下,把上下文切换为 `myuser`
```shell
kubectl config use-context john
kubectl config use-context myuser
```
<!--
@@ -684,12 +693,12 @@ status:
<!--
It's usual to set `status.conditions.reason` to a machine-friendly reason
code using TitleCase; this is a convention but you can set it to anything
you like. If you want to add a note just for human consumption, use the
you like. If you want to add a note for human consumption, use the
`status.conditions.message` field.
-->
`status.conditions.reason` 字段通常设置为一个首字母大写的对机器友好的原因码;
这是一个命名约定,但你也可以随你的个人喜好设置。
如果你想添加一个供人类使用的注释,那就用 `status.conditions.message` 字段。
如果你想添加一个供人类使用的注释,那就用 `status.conditions.message` 字段。
<!--
## Signing
@@ -1,4 +1,8 @@
---
title: 命令行工具参考
title: 组件工具
weight: 60
---
<!--
title: Component tools
weight: 60
-->
@@ -1349,7 +1349,7 @@ Each feature gate is designed for enabling/disabling a specific feature:
- `ValidateProxyRedirects`: This flag controls whether the API server should
validate that redirects are only followed to the same host. Only used if the
`StreamingProxyRedirects` flag is enabled.
- 'VolumeCapacityPriority`: Enable support for prioritizing nodes in different
- `VolumeCapacityPriority`: Enable support for prioritizing nodes in different
topologies based on available PV capacity.
- `VolumePVCDataSource`: Enable support for specifying an existing PVC as a DataSource.
- `VolumeScheduling`: Enable volume topology aware scheduling and make the
@@ -1361,7 +1361,7 @@ Each feature gate is designed for enabling/disabling a specific feature:
-->
- `ValidateProxyRedirects`: 这个标志控制 API 服务器是否应该验证只跟随到相同的主机的重定向。
仅在启用 `StreamingProxyRedirects` 标志时被使用。
- 'VolumeCapacityPriority`: 基于可用 PV 容量的拓扑,启用对不同节点的优先级支持。
- `VolumeCapacityPriority`: 基于可用 PV 容量的拓扑,启用对不同节点的优先级支持。
- `VolumePVCDataSource`:启用对将现有 PVC 指定数据源的支持。
- `VolumeScheduling`:启用卷拓扑感知调度,并使 PersistentVolumeClaimPVC
绑定能够了解调度决策;当与 PersistentLocalVolumes 特性门控一起使用时,
@@ -96,7 +96,8 @@ the host's default interface will be used.
The map from metric-label to value allow-list of this label. The key's format is &lt;MetricName&gt;,&lt;LabelName&gt;. The value's format is &lt;allowed_value&gt;,&lt;allowed_value&gt;...e.g. metric1,label1='v1,v2,v3', metric1,label2='v1,v2,v3' metric2,label1='v1,v2,v3'.
-->
允许使用的指标标签到指标值的映射列表。键的格式为 &lt;MetricName&gt;,&lt;LabelName&gt;.
格式为 &lt;allowed_value&gt;,&lt;allowed_value&gt;...。 例如:<code>metric1,label1='v1,v2,v3', metric1,label2='v1,v2,v3' metric2,label1='v1,v2,v3'</code>。
格式为 &lt;allowed_value&gt;,&lt;allowed_value&gt;...。
例如:<code>metric1,label1='v1,v2,v3', metric1,label2='v1,v2,v3' metric2,label1='v1,v2,v3'</code>。
</p></td>
</tr>
@@ -2251,7 +2252,7 @@ are permanently removed in the release after that.
-->
你要显示隐藏指标的先前版本。仅先前的次要版本有意义,不允许其他值。
格式为 &lt;major&gt;.&lt;minor&gt;,例如:"1.16"。
这种格式的目的是确保有机会注意到下一个版本是否隐藏了其他指标,
这种格式的目的是确保有机会注意到下一个版本是否隐藏了其他指标,
而不是在此之后将它们从发行版中永久删除时感到惊讶。
</td>
</tr>
@@ -342,7 +342,7 @@ The instance prefix for the cluster.
Filename containing a PEM-encoded X509 CA certificate used to issue cluster-scoped certificates. If specified, no more specific --cluster-signing-* flag may be specified.
-->
包含 PEM 编码格式的 X509 CA 证书的文件名。该证书用来发放集群范围的证书。
如果设置了此标志,则不需要锦衣设置 <code>--cluster-signing-*</code> 标志。
如果设置了此标志,则不能指定更具体的<code>--cluster-signing-*</code> 标志。
</td>
</tr>
File diff suppressed because it is too large Load Diff
@@ -299,8 +299,7 @@ A kubelet authenticating using bootstrap tokens is authenticated as a user in th
<!--
As this feature matures, you
should ensure tokens are bound to a Role Based Access Control (RBAC) policy
which limits requests (using the [bootstrap
token](/docs/reference/access-authn-authz/bootstrap-tokens/)) strictly to client
which limits requests (using the [bootstrap token](/docs/reference/access-authn-authz/bootstrap-tokens/)) strictly to client
requests related to certificate provisioning. With RBAC in place, scoping the
tokens to a group allows for great flexibility. For example, you could disable a
particular bootstrap group's access when you are done provisioning the nodes.
@@ -335,7 +334,7 @@ The process is two-fold:
<!--
From the kubelet's perspective, one token is like another and has no special meaning.
From the kube-apiserver's perspective, however, the bootstrap token is special. Due to its `Type`, `namespace` and `name`, kube-apiserver recognizes it as a special token,
From the kube-apiserver's perspective, however, the bootstrap token is special. Due to its `type`, `namespace` and `name`, kube-apiserver recognizes it as a special token,
and grants anyone authenticating with that token special bootstrap rights, notably treating them as a member of the `system:bootstrappers` group. This fulfills a basic requirement
for TLS bootstrapping.
-->
@@ -354,7 +353,7 @@ If you want to use bootstrap tokens, you must enable it on kube-apiserver with t
如果你希望使用启动引导令牌,你必须在 kube-apiserver 上使用下面的标志启用之:
```
```console
--enable-bootstrap-token-auth=true
```
@@ -373,7 +372,7 @@ kube-apiserver 能够将令牌视作身份认证依据。
至少 128 位混沌数据。这里的随机数生成器可以是现代 Linux 系统上的
`/dev/urandom`。生成令牌的方式有很多种。例如:
```
```shell
head -c 16 /dev/urandom | od -An -t x | tr -d ' '
```
@@ -388,7 +387,7 @@ values can be anything and the quoted group name should be as depicted:
令牌文件看起来是下面的例子这样,其中前面三个值可以是任何值,用引号括起来
的组名称则只能用例子中给的值。
```
```console
02b50b05283e98dd0fd71db496ef01e8,kubelet-bootstrap,10001,"system:bootstrappers"
```
@@ -406,9 +405,13 @@ further details.
<!--
### Authorize kubelet to create CSR
Now that the bootstrapping node is _authenticated_ as part of the `system:bootstrappers` group, it needs to be _authorized_ to create a certificate signing request (CSR) as well as retrieve it when done. Fortunately, Kubernetes ships with a `ClusterRole` with precisely these (and just these) permissions, `system:node-bootstrapper`.
Now that the bootstrapping node is _authenticated_ as part of the
`system:bootstrappers` group, it needs to be _authorized_ to create a
certificate signing request (CSR) as well as retrieve it when done.
Fortunately, Kubernetes ships with a `ClusterRole` with precisely these (and
only these) permissions, `system:node-bootstrapper`.
To do this, you just need to create a `ClusterRoleBinding` that binds the `system:bootstrappers` group to the cluster role `system:node-bootstrapper`.
To do this, you only need to create a `ClusterRoleBinding` that binds the `system:bootstrappers` group to the cluster role `system:node-bootstrapper`.
-->
### 授权 kubelet 创建 CSR {#authorize-kubelet-to-create-csr}
@@ -420,7 +423,7 @@ To do this, you just need to create a `ClusterRoleBinding` that binds the `syste
为了实现这一点,你只需要创建 `ClusterRoleBinding`,将 `system:bootstrappers`
组绑定到集群角色 `system:node-bootstrapper`
```
```yaml
# 允许启动引导节点创建 CSR
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
@@ -495,7 +498,7 @@ kubelet 身份认证,很重要的一点是为控制器管理器所提供的 CA
要将 Kubernetes CA 密钥和证书提供给 kube-controller-manager,可使用以下标志:
```
```shell
--cluster-signing-cert-file="/etc/path/to/kubernetes/ca/ca.crt" --cluster-signing-key-file="/etc/path/to/kubernetes/ca/ca.key"
```
@@ -504,7 +507,7 @@ For example:
-->
例如:
```
```shell
--cluster-signing-cert-file="/var/lib/kubernetes/ca.pem" --cluster-signing-key-file="/var/lib/kubernetes/ca-key.pem"
```
@@ -513,7 +516,7 @@ The validity duration of signed certificates can be configured with flag:
-->
所签名的证书的合法期限可以通过下面的标志来配置:
```
```shell
--cluster-signing-duration
```
@@ -602,7 +605,7 @@ collection.
-->
作为 [kube-controller-manager](/zh/docs/reference/generated/kube-controller-manager/)
的一部分的 `csrapproving` 控制器是自动被启用的。
该控制器使用 [`SubjectAccessReview` API](/docs/reference/access-authn-authz/authorization/#checking-api-access)
该控制器使用 [`SubjectAccessReview` API](/zh/docs/reference/access-authn-authz/authorization/#checking-api-access)
来确定是否某给定用户被授权请求 CSR,之后基于鉴权结果执行批复操作。
为了避免与其它批复组件发生冲突,内置的批复组件不会显式地拒绝任何 CSRs。
该组件仅是忽略未被授权的请求。
@@ -682,7 +685,7 @@ The important elements to note are:
<!--
The format of the token does not matter, as long as it matches what kube-apiserver expects. In the above example, we used a bootstrap token.
As stated earlier, _any_ valid authentication method can be used, not just tokens.
As stated earlier, _any_ valid authentication method can be used, not only tokens.
Because the bootstrap `kubeconfig` _is_ a standard `kubeconfig`, you can use `kubectl` to generate it. To create the above example file:
-->
@@ -8,13 +8,15 @@ weight: 28
<!--
The kubelet is the primary "node agent" that runs on each node. It can register the node with the apiserver using one of: the hostname; a flag to override the hostname; or specific logic for a cloud provider.
The kubelet is the primary "node agent" that runs on each
node. It can register the node with the apiserver using one of: the hostname; a flag to override the hostname; or specific logic for a cloud provider.
-->
kubelet 是在每个 Node 节点上运行的主要 “节点代理”。它可以使用以下之一向 apiserver 注册:
主机名(hostname);覆盖主机名的参数;某云驱动的特定逻辑。
<!--
The kubelet works in terms of a PodSpec. A PodSpec is a YAML or JSON object that describes a pod. The kubelet takes a set of PodSpecs that are provided through various mechanisms (primarily through the apiserver) and ensures that the containers described in those PodSpecs are running and healthy. The kubelet doesn't manage containers which were not created by Kubernetes.
The kubelet works in terms of a PodSpec. A PodSpec is a YAML or JSON object
that describes a pod. The kubelet takes a set of PodSpecs that are provided through various mechanisms (primarily through the apiserver) and ensures that the containers described in those PodSpecs are running and healthy. The kubelet doesn't manage containers which were not created by Kubernetes.
-->
kubelet 是基于 PodSpec 来工作的。每个 PodSpec 是一个描述 Pod 的 YAML 或 JSON 对象。
kubelet 接受通过各种机制(主要是通过 apiserver)提供的一组 PodSpec,并确保这些
@@ -431,9 +433,9 @@ kubelet 将从此标志所指的文件中加载其初始配置。此路径可以
<tr>
<td></td><td style="line-height: 130%; word-wrap: break-word;">
<!--
&lt;Warning: Beta feature&gt; Set the maximum number of container log files that can be present for a container. The number must be &ge; 2. This flag can only be used with `--container-runtime=remote`. (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)
Set the maximum number of container log files that can be present for a container. The number must be &ge; 2. This flag can only be used with `--container-runtime=remote`. (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)
-->
&lt;警告:beta 特性&gt; 设置容器的日志文件个数上限。此值必须不小于 2。
设置容器的日志文件个数上限。此值必须不小于 2。
此标志只能与 <code>--container-runtime=remote</code> 标志一起使用。
已弃用:应在 <code>--config</code> 所给的配置文件中进行设置。
<a href="https://kubernetes.io/zh/docs/tasks/administer-cluster/kubelet-config-file/">进一步了解</a>
@@ -446,10 +448,9 @@ kubelet 将从此标志所指的文件中加载其初始配置。此路径可以
<tr>
<td></td><td style="line-height: 130%; word-wrap: break-word;">
<!--
&lt;Warning: Beta feature&gt; Set the maximum size (e.g. 10Mi) of container log file before it is rotated. This flag can only be used with `--container-runtime=remote`. (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)
Set the maximum size (e.g. 10Mi) of container log file before it is rotated. This flag can only be used with `--container-runtime=remote`. (DEPRECATED: This parameter should be set via the config file specified by the Kubelet's --config flag. See https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/ for more information.)
-->
&lt;警告:beta 特性&gt; 设置容器日志文件在轮换生成新文件时之前的最大值
(例如,<code>10Mi</code>)。
设置容器日志文件在轮换生成新文件时之前的最大值(例如,<code>10Mi</code>)。
此标志只能与 <code>--container-runtime=remote</code> 标志一起使用。
已弃用:应在 <code>--config</code> 所给的配置文件中进行设置。
<a href="https://kubernetes.io/zh/docs/tasks/administer-cluster/kubelet-config-file/">进一步了解</a>
@@ -892,7 +893,6 @@ AppArmor=true|false (BETA - default=true)<br/>
BalanceAttachedNodeVolumes=true|false (ALPHA - default=false)<br/>
BoundServiceAccountTokenVolume=true|false (ALPHA - default=false)<br/>
CPUManager=true|false (BETA - default=true)<br/>
CRIContainerLogRotation=true|false (BETA - default=true)<br/>
CSIInlineVolume=true|false (BETA - default=true)<br/>
CSIMigration=true|false (BETA - default=true)<br/>
CSIMigrationAWS=true|false (BETA - default=false)<br/>
@@ -984,7 +984,6 @@ AppArmor=true|false (BETA - 默认值为 true)<br/>
BalanceAttachedNodeVolumes=true|false (ALPHA - 默认值为 false)<br/>
BoundServiceAccountTokenVolume=true|false (ALPHA - 默认值为 false)<br/>
CPUManager=true|false (BETA - 默认值为 true)<br/>
CRIContainerLogRotation=true|false (BETA - 默认值为 true)<br/>
CSIInlineVolume=true|false (BETA - 默认值为 true)<br/>
CSIMigration=true|false (BETA - 默认值为 true)<br/>
CSIMigrationAWS=true|false (BETA - 默认值为 false)<br/>
@@ -1814,10 +1813,12 @@ The CIDR to use for pod IP addresses, only used in standalone mode. In cluster m
<tr>
<td></td><td style="line-height: 130%; word-wrap: break-word;">
<!--
The image whose network/IPC namespaces containers in each pod will use. This docker-specific flag only works when container-runtime is set to `docker`.
Specified image will not be pruned by the image garbage collector. When container-runtime is set to `docker`, all containers in each pod will use the network/ipc namespaces from this image. Other CRI implementations have their own configuration to set this image.
-->
指定基础设施镜像,Pod 内所有容器与其共享网络和 IPC 命名空间
当容器运行环境设置为 <code>docker</code> 时,此特定于 docker 的参数才有效。
指定的镜像不会被镜像垃圾收集器删除
当容器运行环境设置为 <code>docker</code> 时,各个 Pod 中的所有容器都会
使用此镜像中的网络和 IPC 名字空间。
其他 CRI 实现有自己的配置来设置此镜像。
</td>
</tr>
View File
@@ -42,6 +42,6 @@ Kubernetes terms that an _involuntary disruption_.
See [Disruptions](/docs/concepts/workloads/pods/disruptions/) for more information.
-->
如果您作为一个集群操作人员,销毁了一个从属于某个应用的 Pod, Kubernetes 视之为 _自愿干扰(Voluntary Disruption_。如果由于节点故障
或者影响更大区域故障的断电导致 Pod 离线,Kubrenetes 视之为 _非愿干扰(Involuntary Disruption_
或者影响更大区域故障的断电导致 Pod 离线,kubernetes 视之为 _非愿干扰(Involuntary Disruption_
更多信息请查阅[Disruptions](/zh/docs/concepts/workloads/pods/disruptions/)
@@ -29,4 +29,4 @@ tags:
<!--
A manifest specifies the desired state of an object that Kubernetes will maintain when you apply the manifest. Each configuration file can contain multiple manifests.
-->
清单指定了在应用该清单时 Kubrenetes 将维护的对象的期望状态。每个配置文件可包含多个清单。
清单指定了在应用该清单时 kubernetes 将维护的对象的期望状态。每个配置文件可包含多个清单。
@@ -39,3 +39,4 @@ Namespaces are used to organize objects in a cluster and provide a way to divide
-->
名字空间用来组织集群中对象,并为集群资源划分提供了一种方法。同一名字空间内的资源名称必须唯一,但跨名字空间时不作要求。
在一些文档里名字空间也称为命名空间。
View File
@@ -44,7 +44,7 @@ Others develop closed-source commercial or site-specific extensions.
平台开发人员可以使用[定制资源](/zh/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
或[使用汇聚层扩展 Kubernetes API](/zh/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/)
来为其 Kubernetes 实例增加功能,特别是为其应用程序添加功能。
一些平台开发人员也是 Kubrenetes {{< glossary_tooltip text="贡献者" term_id="contributor" >}}
一些平台开发人员也是 kubernetes {{< glossary_tooltip text="贡献者" term_id="contributor" >}}
他们会开发贡献给 Kubernetes 社区的扩展。
另一些平台开发人员则开发封闭源代码的商业扩展或用于特定网站的扩展。
+16 -17
View File
@@ -3,7 +3,7 @@ title: JSONPath 支持
content_type: concept
weight: 25
---
<!--
<!--
---
title: JSONPath Support
content_type: concept
@@ -13,34 +13,34 @@ weight: 25
<!-- overview -->
<!--
Kubectl supports JSONPath template.
Kubectl supports JSONPath template.
-->
Kubectl 支持 JSONPath 模板。
<!-- body -->
<!--
<!--
JSONPath template is composed of JSONPath expressions enclosed by curly braces {}.
Kubectl uses JSONPath expressions to filter on specific fields in the JSON object and format the output.
In addition to the original JSONPath template syntax, the following functions and syntax are valid:
In addition to the original JSONPath template syntax, the following functions and syntax are valid:
-->
JSONPath 模板由 {} 包起来的 JSONPath 表达式组成。Kubectl 使用 JSONPath 表达式来过滤 JSON 对象中的特定字段并格式化输出。除了原始的 JSONPath 模板语法,以下函数和语法也是有效的:
<!--
<!--
1. Use double quotes to quote text inside JSONPath expressions.
2. Use the `range`, `end` operators to iterate lists.
3. Use negative slice indices to step backwards through a list. Negative indices do not "wrap around" a list and are valid as long as `-index + listLength >= 0`.
3. Use negative slice indices to step backwards through a list. Negative indices do not "wrap around" a list and are valid as long as `-index + listLength >= 0`.
-->
1. 使用双引号将 JSONPath 表达式内的文本引起来。
2. 使用 `range``end` 运算符来迭代列表。
3. 使用负片索引后退列表。负索引不会“环绕”列表,并且只要 `-index + listLength> = 0` 就有效。
{{< note >}}
<!--
<!--
- The `$` operator is optional since the expression always starts from the root object by default.
- The result object is printed as its String() function.
- The result object is printed as its String() function.
-->
- `$` 运算符是可选的,因为默认情况下表达式总是从根对象开始。
@@ -48,8 +48,8 @@ JSONPath 模板由 {} 包起来的 JSONPath 表达式组成。Kubectl 使用 JSO
{{< /note >}}
<!--
Given the JSON input:
<!--
Given the JSON input:
-->
给定 JSON 输入:
@@ -90,7 +90,7 @@ Given the JSON input:
}
```
<!--
<!--
Function | Description | Example | Result
--------------------|---------------------------|-----------------------------------------------------------------|------------------
`text` | the plain text | `kind is {.kind}` | `kind is List`
@@ -102,7 +102,7 @@ Function | Description | Example
`[,]` | union operator | `{.items[*]['metadata.name', 'status.capacity']}` | `127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]`
`?()` | filter | `{.users[?(@.name=="e2e")].user.password}` | `secret`
`range`, `end` | iterate list | `{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}` | `[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]]`
`''` | quote interpreted string | `{range .items[*]}{.metadata.name}{'\t'}{end}` | `127.0.0.1 127.0.0.2`
`''` | quote interpreted string | `{range .items[*]}{.metadata.name}{'\t'}{end}` | `127.0.0.1 127.0.0.2`
-->
函数 | 描述 | 示例 | 结果
--------------------|---------------------------|-----------------------------------------------------------------|------------------
@@ -117,8 +117,8 @@ Function | Description | Example
`range`, `end` | 迭代列表 | `{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}` | `[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]]`
`''` | 引用解释执行字符串 | `{range .items[*]}{.metadata.name}{'\t'}{end}` | `127.0.0.1 127.0.0.2`
<!--
Examples using `kubectl` and JSONPath expressions:
<!--
Examples using `kubectl` and JSONPath expressions:
-->
使用 `kubectl` 和 JSONPath 表达式的示例:
@@ -131,7 +131,7 @@ kubectl get pods -o=jsonpath="{.items[*]['metadata.name', 'status.capacity']}"
kubectl get pods -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.startTime}{"\n"}{end}'
```
<!--
<!--
{{< note >}}
On Windows, you must _double_ quote any JSONPath template that contains spaces (not single quote as shown above for bash). This in turn means that you must use a single quote or escaped double quote around any literals in the template. For example:
@@ -142,7 +142,7 @@ kubectl get pods -o=jsonpath="{range .items[*]}{.metadata.name}{\"\t\"}{.status.
{{< /note >}}
-->
{{< note >}}
在 Windows 上,您必须用双引号把任何包含空格的 JSONPath 模板(不是上面 bash 所示的单引号)。
在 Windows 上,对于任何包含空格的 JSONPath 模板,您必须使用双引号(不是上面 bash 所示的单引号)。
反过来,这意味着您必须在模板中的所有文字周围使用单引号或转义的双引号。
例如:
@@ -176,4 +176,3 @@ kubectl get pods -o jsonpath='{.items[?(@.metadata.name=~/^test$/)].metadata.nam
kubectl get pods -o json | jq -r '.items[] | select(.metadata.name | test("test-")).spec.containers[].image'
```
{{< /note >}}
@@ -69,7 +69,7 @@ To install kubeadm, see the [installation guide](/docs/setup/production-environm
用于管理 `kubeadm join` 使用的令牌
* [kubeadm reset](/zh/docs/reference/setup-tools/kubeadm/kubeadm-reset)
用于恢复通过 `kubeadm init` 或者 `kubeadm join` 命令对节点进行的任何变更
* [kubeadm certs](/docs/reference/setup-tools/kubeadm/kubeadm-certs)
* [kubeadm certs](/zh/docs/reference/setup-tools/kubeadm/kubeadm-certs)
用于管理 Kubernetes 证书
* [kubeadm kubeconfig](/docs/reference/setup-tools/kubeadm/kubeadm-kubeconfig)
用于管理 kubeconfig 文件
+101
View File
@@ -0,0 +1,101 @@
---
title: 其他工具
content_type: concept
weight: 80
no_list: true
---
<!--
title: Other Tools
reviewers:
- janetkuo
content_type: concept
weight: 80
no_list: true
-->
<!-- overview -->
<!--
Kubernetes contains several built-in tools to help you work with the Kubernetes system.
-->
Kubernetes 包含多个内置工具来帮助你使用 Kubernetes 系统。
<!-- body -->
<!--
## Minikube
[`minikube`](https://minikube.sigs.k8s.io/docs/) is a tool that
runs a single-node Kubernetes cluster locally on your workstation for
development and testing purposes.
-->
## Minikube
[`minikube`](https://minikube.sigs.k8s.io/docs/)
是一种在你的工作站上本地运行单节点 Kubernetes 集群的工具,用于开发和测试。
<!--
## Dashboard
[`Dashboard`](/docs/tasks/access-application-cluster/web-ui-dashboard/), the web-based user interface of Kubernetes, allows you to deploy containerized applications
to a Kubernetes cluster, troubleshoot them, and manage the cluster and its resources itself.
-->
## 仪表盘
[`Dashboard`](/zh/docs/tasks/access-application-cluster/web-ui-dashboard/)
基于 Web 的 Kubernetes 用户界面,
允许你将容器化的应用程序部署到 Kubernetes 集群,
对它们进行故障排查,并管理集群及其资源本身。
<!--
## Helm
[`Kubernetes Helm`](https://github.com/kubernetes/helm) is a tool for managing packages of pre-configured
Kubernetes resources, aka Kubernetes charts.
-->
## Helm
[`Kubernetes Helm`](https://github.com/kubernetes/helm)
是一个用于管理预配置 Kubernetes 资源包的工具,也就是 Kubernetes 图表。
<!--
Use Helm to:
* Find and use popular software packaged as Kubernetes charts
* Share your own applications as Kubernetes charts
* Create reproducible builds of your Kubernetes applications
* Intelligently manage your Kubernetes manifest files
* Manage releases of Helm packages
-->
使用 Helm 来:
* 查找和使用打包为 Kubernetes 图表的流行软件
* 将你自己的应用程序共享为 Kubernetes 图表
* 为你的 Kubernetes 应用程序创建可重现的构建
* 智能管理你的 Kubernetes 清单文件
* 管理 Helm 包的发布
<!--
## Kompose
[`Kompose`](https://github.com/kubernetes/kompose) is a tool to help Docker Compose users move to Kubernetes.
-->
## Kompose
[`Kompose`](https://github.com/kubernetes/kompose)
是一个帮助 Docker Compose 用户迁移到 Kubernetes 的工具。
<!--
Use Kompose to:
* Translate a Docker Compose file into Kubernetes objects
* Go from local Docker development to managing your application via Kubernetes
* Convert v1 or v2 Docker Compose `yaml` files or [Distributed Application Bundles](https://docs.docker.com/compose/bundles/)
-->
使用 Kompose
* 将 Docker Compose 文件翻译成 Kubernetes 对象
* 从本地 Docker 开发转到通过 Kubernetes 管理你的应用程序
* 转换 Docker Compose v1 或 v2 版本的 `yaml` 文件或[分布式应用程序包](https://docs.docker.com/compose/bundles/)
@@ -463,7 +463,7 @@ Accept: application/json;as=Table;g=meta.k8s.io;v=v1beta1, application/json
<!--
## Alternate representations of resources
By default Kubernetes returns objects serialized to JSON with content type `application/json`. This is the default serialization format for the API. However, clients may request the more efficient Protobuf representation of these objects for better performance at scale. The Kubernetes API implements standard HTTP content type negotiation: passing an `Accept` header with a `GET` call will request that the server return objects in the provided content type, while sending an object in Protobuf to the server for a `PUT` or `POST` call takes the `Content-Type` header. The server will return a `Content-Type` header if the requested format is supported, or the `406 Not acceptable` error if an invalid content type is provided.
By default, Kubernetes returns objects serialized to JSON with content type `application/json`. This is the default serialization format for the API. However, clients may request the more efficient Protobuf representation of these objects for better performance at scale. The Kubernetes API implements standard HTTP content type negotiation: passing an `Accept` header with a `GET` call will request that the server return objects in the provided content type, while sending an object in Protobuf to the server for a `PUT` or `POST` call takes the `Content-Type` header. The server will return a `Content-Type` header if the requested format is supported, or the `406 Not acceptable` error if an invalid content type is provided.
See the API documentation for a list of supported content types for each API.
@@ -983,7 +983,7 @@ The meaning of the get and list semantics are:
- **Any:** Return data at any resource version. The newest available resource version is preferred,
but strong consistency is not required; data at any resource version may be served. It is possible
for the request to return data at a much older resource version that the client has previously
observed, particularly in high availabiliy configurations, due to partitions or stale
observed, particularly in high availability configurations, due to partitions or stale
caches. Clients that cannot tolerate this should not use this semantic.
-->
GET 和 LIST 操作的语义含义如下:
@@ -1142,7 +1142,7 @@ reply with a `410 Gone` HTTP response.
<!--
### Unavailable resource versions
Servers are not required to serve unrecognized resource versions. List and Get requests for unrecognized resource versions may wait briefly for the resource version to become available, should timeout with a `504 (Gateway Timeout)` if the provided resource versions does not become available in a resonable amount of time, and may respond with a `Retry-After` response header indicating how many seconds a client should wait before retrying the request. Currently the kube-apiserver also identifies these responses with a "Too large resource version" message. Watch requests for a unrecognized resource version may wait indefinitely (until the request timeout) for the resource version to become available.
Servers are not required to serve unrecognized resource versions. List and Get requests for unrecognized resource versions may wait briefly for the resource version to become available, should timeout with a `504 (Gateway Timeout)` if the provided resource versions does not become available in a reasonable amount of time, and may respond with a `Retry-After` response header indicating how many seconds a client should wait before retrying the request. Currently the kube-apiserver also identifies these responses with a "Too large resource version" message. Watch requests for a unrecognized resource version may wait indefinitely (until the request timeout) for the resource version to become available.
-->
### 不可用的资源版本 {#unavailable-resource-versions}
@@ -5,13 +5,11 @@ weight: 30
---
<!--
---
title: Client Libraries
reviewers:
- ahmetb
content_type: concept
weight: 30
---
-->
<!-- overview -->
@@ -58,22 +56,21 @@ The following client libraries are officially maintained by
<!--
| Language | Client Library | Sample Programs |
|----------|----------------|-----------------|
| Go | [github.com/kubernetes/client-go/](https://github.com/kubernetes/client-go/) | [browse](https://github.com/kubernetes/client-go/tree/master/examples)
| Python | [github.com/kubernetes-client/python/](https://github.com/kubernetes-client/python/) | [browse](https://github.com/kubernetes-client/python/tree/master/examples)
| Java | [github.com/kubernetes-client/java](https://github.com/kubernetes-client/java/) | [browse](https://github.com/kubernetes-client/java#installation)
| dotnet | [github.com/kubernetes-client/csharp](https://github.com/kubernetes-client/csharp) | [browse](https://github.com/kubernetes-client/csharp/tree/master/examples/simple)
| JavaScript | [github.com/kubernetes-client/javascript](https://github.com/kubernetes-client/javascript) | [browse](https://github.com/kubernetes-client/javascript/tree/master/examples)
| Go | [github.com/kubernetes/client-go/](https://github.com/kubernetes/client-go/) | [browse](https://github.com/kubernetes/client-go/tree/master/examples)
| Haskell | [github.com/kubernetes-client/haskell](https://github.com/kubernetes-client/haskell) | [browse](https://github.com/kubernetes-client/haskell/tree/master/kubernetes-client/example)
| Java | [github.com/kubernetes-client/java](https://github.com/kubernetes-client/java/) | [browse](https://github.com/kubernetes-client/java#installation)
| JavaScript | [github.com/kubernetes-client/javascript](https://github.com/kubernetes-client/javascript) | [browse](https://github.com/kubernetes-client/javascript/tree/master/examples)
| Python | [github.com/kubernetes-client/python/](https://github.com/kubernetes-client/python/) | [browse](https://github.com/kubernetes-client/python/tree/master/examples)
-->
| 语言 | 客户端库 | 样例程序 |
|----------|----------------|-----------------|
| Go | [github.com/kubernetes/client-go/](https://github.com/kubernetes/client-go/) | [浏览](https://github.com/kubernetes/client-go/tree/master/examples)
| Python | [github.com/kubernetes-client/python/](https://github.com/kubernetes-client/python/) | [浏览](https://github.com/kubernetes-client/python/tree/master/examples)
| Java | [github.com/kubernetes-client/java](https://github.com/kubernetes-client/java/) | [浏览](https://github.com/kubernetes-client/java#installation)
| 语言 | 客户端库 | 样例程序 |
|---------|-----------------|-----------------|
| dotnet | [github.com/kubernetes-client/csharp](https://github.com/kubernetes-client/csharp) | [浏览](https://github.com/kubernetes-client/csharp/tree/master/examples/simple)
| JavaScript | [github.com/kubernetes-client/javascript](https://github.com/kubernetes-client/javascript) | [浏览](https://github.com/kubernetes-client/javascript/tree/master/examples)
| Go | [github.com/kubernetes/client-go/](https://github.com/kubernetes/client-go/) | [浏览](https://github.com/kubernetes/client-go/tree/master/examples)
| Haskell | [github.com/kubernetes-client/haskell](https://github.com/kubernetes-client/haskell) | [浏览](https://github.com/kubernetes-client/haskell/tree/master/kubernetes-client/example)
| Java | [github.com/kubernetes-client/java](https://github.com/kubernetes-client/java/) | [浏览](https://github.com/kubernetes-client/java#installation)
| JavaScript | [github.com/kubernetes-client/javascript](https://github.com/kubernetes-client/javascript) | [浏览](https://github.com/kubernetes-client/javascript/tree/master/examples)
| Python | [github.com/kubernetes-client/python/](https://github.com/kubernetes-client/python/) | [浏览](https://github.com/kubernetes-client/python/tree/master/examples)
<!--
## Community-maintained client libraries
@@ -92,6 +89,10 @@ their authors, not the Kubernetes team.
| Language | Client Library |
| -------------------- | ---------------------------------------- |
| Clojure | [github.com/yanatan16/clj-kubernetes-api](https://github.com/yanatan16/clj-kubernetes-api) |
| DotNet | [github.com/tonnyeremin/kubernetes_gen](https://github.com/tonnyeremin/kubernetes_gen) |
| DotNet (RestSharp) | [github.com/masroorhasan/Kubernetes.DotNet](https://github.com/masroorhasan/Kubernetes.DotNet) |
| Elixir | [github.com/obmarg/kazan](https://github.com/obmarg/kazan/) |
| Elixir | [github.com/coryodaniel/k8s](https://github.com/coryodaniel/k8s) |
| Go | [github.com/ericchiang/k8s](https://github.com/ericchiang/k8s) |
| Java (OSGi) | [bitbucket.org/amdatulabs/amdatu-kubernetes](https://bitbucket.org/amdatulabs/amdatu-kubernetes) |
| Java (Fabric8, OSGi) | [github.com/fabric8io/kubernetes-client](https://github.com/fabric8io/kubernetes-client) |
@@ -114,19 +115,20 @@ their authors, not the Kubernetes team.
| Python | [github.com/Frankkkkk/pykorm](https://github.com/Frankkkkk/pykorm) |
| Ruby | [github.com/abonas/kubeclient](https://github.com/abonas/kubeclient) |
| Ruby | [github.com/Ch00k/kuber](https://github.com/Ch00k/kuber) |
| Ruby | [github.com/k8s-ruby/k8s-ruby](https://github.com/k8s-ruby/k8s-ruby) |
| Ruby | [github.com/kontena/k8s-client](https://github.com/kontena/k8s-client) |
| Rust | [github.com/clux/kube-rs](https://github.com/clux/kube-rs) |
| Rust | [github.com/ynqa/kubernetes-rust](https://github.com/ynqa/kubernetes-rust) |
| Scala | [github.com/hagay3/skuber](https://github.com/hagay3/skuber) |
| Scala | [github.com/joan38/kubernetes-client](https://github.com/joan38/kubernetes-client) |
| DotNet | [github.com/tonnyeremin/kubernetes_gen](https://github.com/tonnyeremin/kubernetes_gen) |
| DotNet (RestSharp) | [github.com/masroorhasan/Kubernetes.DotNet](https://github.com/masroorhasan/Kubernetes.DotNet) |
| Elixir | [github.com/obmarg/kazan](https://github.com/obmarg/kazan/) |
| Elixir | [github.com/coryodaniel/k8s](https://github.com/coryodaniel/k8s) |
-->
| 语言 | 客户端库 |
| -------------------- | ---------------------------------------- |
| Clojure | [github.com/yanatan16/clj-kubernetes-api](https://github.com/yanatan16/clj-kubernetes-api) |
| DotNet | [github.com/tonnyeremin/kubernetes_gen](https://github.com/tonnyeremin/kubernetes_gen) |
| DotNet (RestSharp) | [github.com/masroorhasan/Kubernetes.DotNet](https://github.com/masroorhasan/Kubernetes.DotNet) |
| Elixir | [github.com/obmarg/kazan](https://github.com/obmarg/kazan/) |
| Elixir | [github.com/coryodaniel/k8s](https://github.com/coryodaniel/k8s) |
| Go | [github.com/ericchiang/k8s](https://github.com/ericchiang/k8s) |
| Java (OSGi) | [bitbucket.org/amdatulabs/amdatu-kubernetes](https://bitbucket.org/amdatulabs/amdatu-kubernetes) |
| Java (Fabric8, OSGi) | [github.com/fabric8io/kubernetes-client](https://github.com/fabric8io/kubernetes-client) |
@@ -149,16 +151,11 @@ their authors, not the Kubernetes team.
| Python | [github.com/Frankkkkk/pykorm](https://github.com/Frankkkkk/pykorm) |
| Ruby | [github.com/abonas/kubeclient](https://github.com/abonas/kubeclient) |
| Ruby | [github.com/Ch00k/kuber](https://github.com/Ch00k/kuber) |
| Ruby | [github.com/k8s-ruby/k8s-ruby](https://github.com/k8s-ruby/k8s-ruby) |
| Ruby | [github.com/kontena/k8s-client](https://github.com/kontena/k8s-client) |
| Rust | [github.com/clux/kube-rs](https://github.com/clux/kube-rs) |
| Rust | [github.com/ynqa/kubernetes-rust](https://github.com/ynqa/kubernetes-rust) |
| Scala | [github.com/hagay3/skuber](https://github.com/hagay3/skuber) |
| Scala | [github.com/joan38/kubernetes-client](https://github.com/joan38/kubernetes-client) |
| Swift | [github.com/swiftkube/client](https://github.com/swiftkube/client) |
| DotNet | [github.com/tonnyeremin/kubernetes_gen](https://github.com/tonnyeremin/kubernetes_gen) |
| DotNet (RestSharp) | [github.com/masroorhasan/Kubernetes.DotNet](https://github.com/masroorhasan/Kubernetes.DotNet) |
| Elixir | [github.com/obmarg/kazan](https://github.com/obmarg/kazan/) |
| Elixir | [github.com/coryodaniel/k8s](https://github.com/coryodaniel/k8s) |
@@ -171,7 +171,8 @@ This covers the [maximum supported version skew of 2 releases](/docs/setup/relea
* **Beta: 9 个月或者 3 个发布版本(取其较长者)**
* **Alpha: 0 个发布版本**
这里也包含了关于[最大支持 2 个发布版本的版本偏差](/zh/docs/setup/release/version-skew-policy/)的约定。
这里也包含了关于[最大支持 2 个发布版本的版本偏差](/zh/docs/setup/release/version-skew-policy/)
的约定。
<!--
Until [#52185](https://github.com/kubernetes/kubernetes/issues/52185) is
@@ -181,7 +182,7 @@ deprecation timelines in this document), but the API server must remain capable
of decoding/converting previously persisted data from storage.
-->
{{< note >}}
在[#52185](https://github.com/kubernetes/kubernetes/issues/52185)被解决之前,
[#52185](https://github.com/kubernetes/kubernetes/issues/52185) 被解决之前,
已经被保存到持久性存储中的 API 版本都不可以被去除。
你可以禁止这些版本所对应的 REST 末端(在符合本文中弃用时间线的前提下),
但是 API 服务器必须仍能解析和转换存储中以前写入的数据。
@@ -699,6 +700,14 @@ therefore the rules for deprecation are as follows:
特性门控的版本管理与之前讨论的组件版本管理不同,因此其对应的弃用策略如下:
<!--
**Rule #8: Feature gates must be deprecated when the corresponding feature they control
transitions a lifecycle stage as follows. Feature gates must function for no less than:**
* **Beta feature to GA: 6 months or 2 releases (whichever is longer)**
* **Beta feature to EOL: 3 months or 1 release (whichever is longer)**
* **Alpha feature to EOL: 0 releases**
-->
**规则 #8:特性门控所对应的功能特性经历下面所列的成熟性阶段转换时,特性门控
必须被弃用。特性门控弃用时必须在以下时长内保持其功能可用:**
@@ -730,8 +739,7 @@ this impacts removal of a metric during a Kubernetes release. These classes
are determined by the perceived importance of the metric. The rules for
deprecating and removing a metric are as follows:
-->
### 弃用度量值 {#Deprecating a metric}
### 弃用度量值 {#deprecating-a-metric}
Kubernetes 控制平面的每个组件都公开度量值(通常是 `/metrics` 端点),它们通常由集群管理员使用。
并不是所有的度量值都是同样重要的:一些度量值通常用作 SLIs 或被使用来确定 SLOs,这些往往比较重要。
@@ -755,20 +763,25 @@ Kubernetes 控制平面的每个组件都公开度量值(通常是 `/metrics`
-->
**规则 #9a: 对于相应的稳定性类别,度量值起作用的周期必须不小于:**
* **STABLE: 4 个发布版本或者 12 个月 (取其较长者)**
* **ALPHA: 0 个发布版本**
* **STABLE: 4 个发布版本或者 12 个月 (取其较长者)**
* **ALPHA: 0 个发布版本**
**规则 #9b: 在度量值被宣布启用之后,它起作用的周期必须不小于:**
* **STABLE: 3 个发布版本或者 9 个月 (取其较长者)**
* **ALPHA: 0 个发布版本**
* **STABLE: 3 个发布版本或者 9 个月 (取其较长者)**
* **ALPHA: 0 个发布版本**
<!--
Deprecated metrics will have their description text prefixed with a deprecation notice
string '(Deprecated from x.y)' and a warning log will be emitted during metric
registration. Like their stable undeprecated counterparts, deprecated metrics will
be automatically registered to the metrics endpoint and therefore visible.
-->
已弃用的度量值将在其描述文本前加上一个已弃用通知字符串 '(Deprecated from x.y)'
并将在度量值被记录期间发出警告日志。就像稳定的、未被弃用的度量指标一样,
被弃用的度量值将自动注册到 metrics 端点,因此被弃用的度量值也是可见的。
<!--
On a subsequent release (when the metric's `deprecatedVersion` is equal to
_current_kubernetes_version - 3_)), a deprecated metric will become a _hidden_ metric.
**_Unlike_** their deprecated counterparts, hidden metrics will _no longer_ be
@@ -779,15 +792,11 @@ escape hatch to properly migrate off of a deprecated metric, if they were not
able to react to the earlier deprecation warnings. Hidden metrics should be
deleted after one release.
-->
已弃用的度量值将在其描述文本前加上一个已弃用通知字符串 '(Deprecated from x.y)'
并将在度量值被记录期间发出警告日志。就像稳定的、未被弃用的度量指标一样,
被弃用的度量值将自动注册到 metrics 端点,因此被弃用的度量值也是可见的。
在随后的版本中(当度量值 `deprecatedVersion` 等于_当前 Kubernetes 版本 - 3_),
被弃用的度量值将变成 _隐藏(Hidden_ metric 度量值。
与被弃用的度量值不同,隐藏的度量值将不再被自动注册到 metrics 端点(因此被隐藏)。
但是,它们可以通过可执行文件的命令行标志显式启用`--show-hidden-metrics-for-version=`)。
但是,它们可以通过可执行文件的命令行标志显式启用
`--show-hidden-metrics-for-version=`)。
如果集群管理员不能对早期的弃用警告作出反应,这一设计就为他们提供了抓紧迁移弃用度量值的途径。
隐藏的度量值应该在再过一个发行版本后被删除。
@@ -5,7 +5,6 @@ weight: 25
min-kubernetes-server-version: 1.16
---
<!--
---
title: Server-Side Apply
reviewers:
- smarterclayton
@@ -15,7 +14,6 @@ reviewers:
content_type: concept
weight: 25
min-kubernetes-server-version: 1.16
---
-->
<!-- overview -->
@@ -25,15 +23,15 @@ min-kubernetes-server-version: 1.16
<!--
## Introduction
Server Side Apply helps users and controllers manage their resources via
declarative configurations. It allows them to create and/or modify their
Server Side Apply helps users and controllers manage their resources through
declarative configurations. Clients can create and/or modify their
[objects](/docs/concepts/overview/working-with-objects/kubernetes-objects/)
declaratively, simply by sending their fully specified intent.
declaratively by sending their fully specified intent.
-->
## 简介 {#introduction}
服务器端应用协助用户、控制器通过声明式配置的方式管理他们的资源。
发送完整描述的目标(A fully specified intent),
客户端可以发送完整描述的目标(A fully specified intent),
声明式地创建和/或修改
[对象](/zh/docs/concepts/overview/working-with-objects/kubernetes-objects/)。
@@ -84,7 +82,7 @@ Server side apply is meant both as a replacement for the original `kubectl
apply` and as a simpler mechanism for controllers to enact their changes.
If you have Server Side Apply enabled, the control plane tracks managed fields
for all newlly created objects.
for all newly created objects.
-->
服务器端应用既是原有 `kubectl apply` 的替代品,
也是控制器发布自身变化的一个简化机制。
@@ -133,7 +131,7 @@ the appliers, results in a conflict. Shared field owners may give up ownership
of a field by removing it from their configuration.
Field management is stored in a`managedFields` field that is part of an object's
[`metadata`](/docs/reference/generated/kubernetes-api/{{< latest-version >}}/#objectmeta-v1-meta).
[`metadata`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#objectmeta-v1-meta).
A simple example of an object created by Server Side Apply could look like this:
-->
@@ -142,7 +140,8 @@ A simple example of an object created by Server Side Apply could look like this:
共享字段的所有者可以放弃字段的所有权,这只需从配置文件中删除该字段即可。
字段管理的信息存储在 `managedFields` 字段中,该字段是对象的
[`metadata`](/docs/reference/generated/kubernetes-api/{{< latest-version >}}/#objectmeta-v1-meta)中的一部分。
[`metadata`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#objectmeta-v1-meta)
中的一部分。
服务器端应用创建对象的简单示例如下:
@@ -356,15 +355,14 @@ would have failed due to conflicting ownership.
The merging strategy, implemented with Server Side Apply, provides a generally
more stable object lifecycle. Server Side Apply tries to merge fields based on
the fact who manages them instead of overruling just based on values. This way
it is intended to make it easier and more stable for multiple actors updating
the same object by causing less unexpected interference.
the actor who manages them instead of overruling based on values. This way
multiple actors can update the same object without causing unexpected interference.
-->
## 合并策略 {#merge-strategy}
由服务器端应用实现的合并策略,提供了一个总体更稳定的对象生命周期。
服务器端应用试图依据管理它们来合并字段,而不是根据值来否决。
这么做是为了多个参与者可以更简单、更稳定的更新同一个对象,且避免引起意外干扰。
服务器端应用试图依据负责管理它们的主体来合并字段,而不是根据值来否决。
这么做是为了多个主体可以更新同一个对象,且不会引起意外的相互干扰。
<!--
When a user sends a "fully-specified intent" object to the Server Side Apply
@@ -387,7 +385,7 @@ merging, see
A number of markers were added in Kubernetes 1.16 and 1.17, to allow API
developers to describe the merge strategy supported by lists, maps, and
structs. These markers can be applied to objects of the respective type,
in Go files or in the OpenAPI schema definition of the
in Go files or in the OpenAPI schema definition of the
[CRD](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io):
-->
Kubernetes 1.16 和 1.17 中添加了一些标记,
@@ -399,18 +397,116 @@ Kubernetes 1.16 和 1.17 中添加了一些标记,
<!--
| Golang marker | OpenAPI extension | Accepted values | Description | Introduced in |
|---|---|---|---|---|
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | Applicable to lists. `atomic` and `set` apply to lists with scalar elements only. `map` applies to lists of nested types only. If configured as `atomic`, the entire list is replaced during merge; a single manager manages the list as a whole at any one time. If `set` or `map`, different managers can manage entries separately. | 1.16 |
| `//+listMapKey` | `x-kubernetes-list-map-keys` | Slice of map keys that uniquely identify entries for example `["port", "protocol"]` | Only applicable when `+listType=map`. A slice of strings whose values in combination must uniquely identify list entries. While there can be multiple keys, `listMapKey` is singular because keys need to be specified individually in the Go type. | 1.16 |
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | Applicable to lists. `set` applies to lists that include only scalar elements. These elements must be unique. `map` applies to lists of nested types only. The key values (see `listMapKey`) must be unique in the list. `atomic` can apply to any list. If configured as `atomic`, the entire list is replaced during merge. At any point in time, a single manager owns the list. If `set` or `map`, different managers can manage entries separately. | 1.16 |
| `//+listMapKey` | `x-kubernetes-list-map-keys` | List of field names, e.g. `["port", "protocol"]` | Only applicable when `+listType=map`. A list of field names whose values uniquely identify entries in the list. While there can be multiple keys, `listMapKey` is singular because keys need to be specified individually in the Go type. The key fields must be scalars. | 1.16 |
| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to maps. `atomic` means that the map can only be entirely replaced by a single manager. `granular` means that the map supports separate managers updating individual fields. | 1.17 |
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to structs; otherwise same usage and OpenAPI annotation as `//+mapType`.| 1.17 |
-->
| Golang 标记 | OpenAPI extension | 可接受的值 | 描述 | 引入版本 |
|---|---|---|---|---|
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | 适用于 list。 `atomic``set` 适用于包含标量元素的 list。 `map` 适用于包含嵌套类型的 list。 如果配置为 `atomic`, 合并时整个列表会被替换掉; 任何时候,唯一的管理器都把列表作为一个整体来管理。如果是 `set``map` ,不同的管理器也可以分开管理条目。 | 1.16 |
| `//+listMapKey` | `x-kubernetes-list-map-keys` | 用来唯一标识条目的 map keys 切片,例如 `["port", "protocol"]` | 仅当 `+listType=map` 时适用。组合值的字符串切片必须唯一标识列表中的条目。尽管有多个 key`listMapKey` 是单数的,这是因为 key 需要在 Go 类型中单独的指定。 | 1.16 |
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | 适用于 list。`set` 适用于包含标量元素的列表。这些元素必须是不重复的。`map` 适用于包含嵌套类型的列表。列表中的键(参见 `listMapKey`)不可以重复。`atomic` 适用于任何类型的列表。如果配置为 `atomic`,则合并时整个列表会被替换掉任何时候,只有一个管理器负责管理指定列表。如果配置为 `set``map`,不同的管理器也可以分开管理条目。 | 1.16 |
| `//+listMapKey` | `x-kubernetes-list-map-keys` | 字段名称的列表,例如`["port", "protocol"]` | 仅当 `+listType=map` 时适用。取值为字段名称的列表,这些字段值的组合能够唯一标识列表中的条目。尽管可以存在多个键`listMapKey` 是单数的,这是因为键名需要在 Go 类型中各自独立指定。键字段必须是标量。 | 1.16 |
| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 map。 `atomic` 指 map 只能被单个的管理器整个的替换。 `granular` 指 map 支持多个管理器各自更新自己的字段。 | 1.17 |
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 structs;否则就像 `//+mapType` 有相同的用法和 openapi 注释.| 1.17 |
<!--
If `listType` is missing, the API server interprets a
`patchMergeStrategy=merge` marker as a `listType=map` and the
corresponding `patchMergeKey` marker as a `listMapKey`.
The `atomic` list type is recursive.
These markers are specified as comments and don't have to be repeated as
field tags.
-->
若未指定 `listType`API 服务器将 `patchMergeStrategy=merge` 标记解释为
`listType=map` 并且视对应的 `patchMergeKey` 标记为 `listMapKey` 取值。
`atomic` 列表类型是递归的。
这些标记都是用源代码注释的方式给出的,不必作为字段标签(tag)再重复。
<!--
### Compatibility across topology changes
-->
### 拓扑变化时的兼容性 {#compatibility-across-toplogy-changes}
<!--
On rare occurences, a CRD or built-in type author may want to change the
specific topology of a field in their resource without incrementing its
version. Changing the topology of types, by upgrading the cluster or
updating the CRD, has different consequences when updating existing
objects. There are two categories of changes: when a field goes from
`map`/`set`/`granular` to `atomic` and the other way around.
-->
在极少的情况下,CRD 或者内置类型的作者可能希望更改其资源中的某个字段的
拓扑配置,同时又不提升版本号。
通过升级集群或者更新 CRD 来更改类型的拓扑信息与更新现有对象的结果不同。
变更的类型有两种:一种是将字段从 `map`/`set`/`granular` 更改为 `atomic`
另一种是做逆向改变。
<!--
When the `listType`, `mapType`, or `structType` changes from
`map`/`set`/`granular` to `atomic`, the whole list, map or struct of
existing objects will end-up being owned by actors who owned an element
of these types. This means that any further change to these objects
would cause a conflict.
-->
`listType``mapType``structType``map`/`set`/`granular` 改为
`atomic` 时,现有对象的整个列表、映射或结构的属主都会变为这些类型的
元素之一的属主。这意味着,对这些对象的进一步变更会引发冲突。
<!--
When a list, map, or struct changes from `atomic` to
`map`/`set`/`granular`, the API server won't be able to infer the new
ownership of these fields. Because of that, no conflict will be produced
when objects have these fields updated. For that reason, it is not
recommended to change a type from `atomic` to `map`/`set`/`granular`.
Take for example, the custom resource:
-->
当一个列表、映射或结构从 `atomic` 改为 `map`/`set`/`granular` 之一
时,API 服务器无法推导这些字段的新的属主。因此,当对象的这些字段
再次被更新时不会引发冲突。出于这一原因,不建议将某类型从 `atomic` 改为
`map`/`set`/`granular`
以下面的自定义资源为例:
```yaml
apiVersion: example.com/v1
kind: Foo
metadata:
name: foo-sample
managedFields:
- manager: manager-one
operation: Apply
apiVersion: example.com/v1
fields:
f:spec:
f:data: {}
spec:
data:
key1: val1
key2: val2
```
<!--
Before `spec.data` gets changed from `atomic` to `granular`,
`manager-one` owns the field `spec.data`, and all the fields within it
(`key1` and `key2`). When the CRD gets changed to make `spec.data`
`granular`, `manager-one` continues to own the top-level field
`spec.data` (meaning no other managers can delete the map called `data`
without a conflict), but it no longer owns `key1` and `key2`, so another
manager can then modify or delete those fields without conflict.
-->
`spec.data``atomic` 改为 `granular` 之前,`manager-one`
`spec.data` 字段及其所包含字段(`key1``key2`)的属主。
当对应的 CRD 被更改,使得 `spec.data` 变为 `granular` 拓扑时,
`manager-one` 继续拥有顶层字段 `spec.data`(这意味着其他管理者想
删除名为 `data` 的映射而不引起冲突是不可能的),但不再拥有
`key1``key2`。因此,其他管理者可以在不引起冲突的情况下更改
或删除这些字段。
<!--
### Custom Resources
@@ -435,7 +531,7 @@ type.
这些注解将在合并此类型的对象时使用。
<!--
### Using Server-Side Apply in a controller
## Using Server-Side Apply in a controller
As a developer of a controller, you can use server-side apply as a way to
simplify the update logic of your controller. The main differences with a
@@ -450,7 +546,7 @@ read-modify-write and/or patch are the following:
It is strongly recommended for controllers to always "force" conflicts, since they
might not be able to resolve or act on these conflicts.
-->
### 在控制器中使用服务器端应用 {#using-server-side-apply-in-controller}
## 在控制器中使用服务器端应用 {#using-server-side-apply-in-controller}
控制器的开发人员可以把服务器端应用作为简化控制器的更新逻辑的方式。
读-改-写 和/或 patch 的主要区别如下所示:
@@ -463,7 +559,7 @@ might not be able to resolve or act on these conflicts.
强烈推荐:设置控制器在冲突时强制执行,这是因为冲突发生时,它们没有其他解决方案或措施。
<!--
### Transferring Ownership
## Transferring Ownership
In addition to the concurrency controls provided by [conflict resolution](#conflicts),
Server Side Apply provides ways to perform coordinated
@@ -476,7 +572,7 @@ resource and its accompanying controller.
Say a user has defined deployment with `replicas` set to the desired value:
-->
### 转移所有权 {#transferring-ownership}
## 转移所有权 {#transferring-ownership}
除了通过[冲突解决方案](#conflicts)提供的并发控制,
服务器端应用提供了一些协作方式来将字段所有权从用户转移到控制器。
@@ -526,7 +622,7 @@ is not what the user wants to happen, even temporarily.
<!--
There are two solutions:
- (easy) Leave `replicas` in the configuration; when HPA eventually writes to that
- (basic) Leave `replicas` in the configuration; when HPA eventually writes to that
field, the system gives the user a conflict over it. At that point, it is safe
to remove from the configuration.
@@ -539,9 +635,9 @@ First, the user defines a new configuration containing only the `replicas` field
-->
这里有两个解决方案:
- 容易) `replicas` 留在配置文件中;当 HPA 最终写入那个字段,
- 基本操作)`replicas` 留在配置文件中;当 HPA 最终写入那个字段,
系统基于此事件告诉用户:冲突发生了。在这个时间点,可以安全的删除配置文件。
- (高级)然而,如果用户不想等待,比如他们想为合作伙伴保持集群清晰,
- (高级操作)然而,如果用户不想等待,比如他们想为合作伙伴保持集群清晰,
那他们就可以执行以下步骤,安全的从配置文件中删除 `replicas`
首先,用户新定义一个只包含 `replicas` 字段的配置文件:
@@ -561,13 +657,13 @@ kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment-replic
<!--
If the apply results in a conflict with the HPA controller, then do nothing. The
conflict just indicates the controller has claimed the field earlier in the
conflict indicates the controller has claimed the field earlier in the
process than it sometimes does.
At this point the user may remove the `replicas` field from their configuration.
-->
如果应用操作和 HPA 控制器产生冲突,那什么都不做。
冲突只是表明控制器在更早的流程中已经对字段声明过所有权。
冲突表明控制器在更早的流程中已经对字段声明过所有权。
在此时间点,用户可以从配置文件中删除 `replicas`
@@ -583,7 +679,7 @@ automatically deleted. No clean up is required.
这里不需要执行清理工作。
<!--
## Transferring Ownership Between Users
### Transferring Ownership Between Users
Users can transfer ownership of a field between each other by setting the field
to the same value in both of their applied configs, causing them to share
@@ -591,7 +687,7 @@ ownership of the field. Once the users share ownership of the field, one of them
can remove the field from their applied configuration to give up ownership and
complete the transfer to the other user.
-->
## 在用户之间转移所有权 {#transferring-ownership-between-users}
### 在用户之间转移所有权 {#transferring-ownership-between-users}
通过在配置文件中把一个字段设置为相同的值,用户可以在他们之间转移字段的所有权,
从而共享了字段的所有权。
@@ -763,7 +859,7 @@ Data: [{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]
<!--
This will overwrite the managedFields with a list containing a single empty
entry that then results in the managedFields being stripped entirely from the
object. Note that just setting the managedFields to an empty list will not
object. Note that setting the managedFields to an empty list will not
reset the field. This is on purpose, so managedFields never get stripped by
clients not aware of the field.
@@ -772,9 +868,9 @@ than the managedFields, this will result in the managedFields being reset
first and the other changes being processed afterwards. As a result the
applier takes ownership of any fields updated in the same request.
-->
这一操作将用只包含一个空条目的 list 覆写 managedFields
这一操作将用只包含一个空条目的列表覆写 managedFields
来实现从对象中整个的去除 managedFields。
注意,只把 managedFields 设置为空 list 并不会重置字段。
注意,只把 managedFields 设置为空列表并不会重置字段。
这么做是有目的的,所以 managedFields 将永远不会被与该字段无关的客户删除。
在重置操作结合 managedFields 以外其他字段更改的场景中,
@@ -804,7 +900,8 @@ should have the same flag setting.
-->
## 禁用此功能 {#disabling-the-feature}
服务器端应用是一个 beta 版特性,默认启用。
服务器端应用是一个 Beta 版特性,默认启用。
要关闭此[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates)
你需要在启动 `kube-apiserver` 时包含参数 `--feature-gates ServerSideApply=false`
如果你有多个 `kube-apiserver` 副本,他们都应该相同的标记设置
如果你有多个 `kube-apiserver` 副本,它们的标志设置应该相同。
@@ -169,7 +169,10 @@ Install containerd:
{{% tab name="Linux" %}}
<!--
1. Install the `containerd.io` package from the official Docker repositories. Instructions for setting up the Docker repository for your respective Linux distribution and installing the `containerd.io` package can be found at [Install Docker Engine](https://docs.docker.com/engine/install/#server).
1. Install the `containerd.io` package from the official Docker repositories.
Instructions for setting up the Docker repository for your respective Linux distribution and
installing the `containerd.io` package can be found at
[Install Docker Engine](https://docs.docker.com/engine/install/#server).
-->
1. 从官方Docker仓库安装 `containerd.io` 软件包。可以在
[安装 Docker 引擎](https://docs.docker.com/engine/install/#server)
@@ -199,9 +202,10 @@ Install containerd:
{{% tab name="Windows (PowerShell)" %}}
<!--
Start a Powershell session, set `$Version` to the desired version (ex: `$Version=1.4.3`), and then run the following commands:
Start a Powershell session, set `$Version` to the desired version (ex: `$Version=1.4.3`),
and then run the following commands:
-->
启动 Powershell 会话,将 `$Version` 设置为所需的版本(例如:`$ Version=1.4.3`),
启动 Powershell 会话,将 `$Version` 设置为所需的版本(例如:`$Version=1.4.3`),
然后运行以下命令:
<!--
@@ -382,7 +386,8 @@ sudo apt-get install cri-o cri-o-runc
{{% tab name="Ubuntu" %}}
<!--
To install on the following operating systems, set the environment variable `OS` to the appropriate field in the following table:
To install on the following operating systems, set the environment variable `OS`
to the appropriate field in the following table:
| Operating system | `$OS` |
| ---------------- | ----------------- |
@@ -438,7 +443,8 @@ sudo apt-get install cri-o cri-o-runc
{{% tab name="CentOS" %}}
<!--
To install on the following operating systems, set the environment variable `OS` to the appropriate field in the following table:
To install on the following operating systems, set the environment variable `OS`
to the appropriate field in the following table:
| Operating system | `$OS` |
| ---------------- | ----------------- |
@@ -527,7 +533,7 @@ Start CRI-O:
```shell
sudo systemctl daemon-reload
sudo systemctl enable crio --no
sudo systemctl enable crio --now
```
<!--
@@ -569,7 +575,10 @@ in sync.
### Docker
<!--
1. On each of your nodes, install the Docker for your Linux distribution as per [Install Docker Engine](https://docs.docker.com/engine/install/#server). You can find the latest validated version of Docker in this [dependencies](https://git.k8s.io/kubernetes/build/dependencies.yaml) file.
1. On each of your nodes, install the Docker for your Linux distribution as per
[Install Docker Engine](https://docs.docker.com/engine/install/#server).
You can find the latest validated version of Docker in this
[dependencies](https://git.k8s.io/kubernetes/build/dependencies.yaml) file.
-->
1. 在每个节点上,根据[安装 Docker 引擎](https://docs.docker.com/engine/install/#server)
为你的 Linux 发行版安装 Docker。
@@ -597,7 +606,8 @@ in sync.
{{< note >}}
<!--
`overlay2` is the preferred storage driver for systems running Linux kernel version 4.0 or higher, or RHEL or CentOS using version 3.10.0-514 and above.
`overlay2` is the preferred storage driver for systems running Linux kernel version 4.0 or higher,
or RHEL or CentOS using version 3.10.0-514 and above.
-->
对于运行 Linux 内核版本 4.0 或更高版本,或使用 3.10.0-51 及更高版本的 RHEL
或 CentOS 的系统,`overlay2`是首选的存储驱动程序。
@@ -333,8 +333,8 @@ kubeadm 包含生成下述证书所需的所有必要的密码学工具;在这
```shell
root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config=/home/ubuntu/kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config=/home/ubuntu/kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config=/tmp/${HOST1}/kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config=/tmp/${HOST2}/kubeadmcfg.yaml
```
<!--
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,14 @@
---
title: Kubernetes 中调度 Windows 容器的指南
title: Kubernetes 中 Windows 容器的调度指南
content_type: concept
weight: 75
---
<!--
reviewers:
- michmike
- patricklang
- jayunit100
- jsturtevant
- marosset
- perithompson
title: Guide for scheduling Windows containers in Kubernetes
content_type: concept
weight: 75
@@ -15,7 +17,8 @@ weight: 75
<!-- overview -->
<!--
Windows applications constitute a large portion of the services and applications that run in many organizations. This guide walks you through the steps to configure and deploy a Windows container in Kubernetes.
Windows applications constitute a large portion of the services and applications that run in many organizations.
This guide walks you through the steps to configure and deploy a Windows container in Kubernetes.
-->
Windows 应用程序构成了许多组织中运行的服务和应用程序的很大一部分。
本指南将引导您完成在 Kubernetes 中配置和部署 Windows 容器的步骤。
@@ -36,20 +39,28 @@ Windows 应用程序构成了许多组织中运行的服务和应用程序的很
<!--
## Before you begin
* Create a Kubernetes cluster that includes a [master and a worker node running Windows Server](../user-guide-windows-nodes)
* It is important to note that creating and deploying services and workloads on Kubernetes behaves in much the same way for Linux and Windows containers. [Kubectl commands](/docs/reference/kubectl/overview/) to interface with the cluster are identical. The example in the section below is provided simply to jumpstart your experience with Windows containers.
* Create a Kubernetes cluster that includes a
[master and a worker node running Windows Server](../user-guide-windows-nodes)
* It is important to note that creating and deploying services and workloads on Kubernetes
behaves in much the same way for Linux and Windows containers.
[Kubectl commands](/docs/reference/kubectl/overview/) to interface with the cluster are identical.
The example in the section below is provided to jumpstart your experience with Windows containers.
-->
## 在你开始之前
* 创建一个 Kubernetes 集群,其中包括一个
[运行 Windows 服务器的主节点和工作节点](/zh/docs/tasks/administer-cluster/kubeadm/adding-windows-nodes/)
* 重要的是要注意,对于 Linux 和 Windows 容器,在 Kubernetes 上创建和部署服务和工作负载的行为几乎相同。
与集群接口的 [Kubectl 命令](/zh/docs/reference/kubectl/overview/)相同。提供以下部分中的示例只是为了快速启动 Windows 容器的使用体验
* 重要的是要注意,对于 Linux 和 Windows 容器,在 Kubernetes
上创建和部署服务和工作负载的行为几乎相同
与集群接口的 [kubectl 命令](/zh/docs/reference/kubectl/overview/)相同。
提供以下部分中的示例只是为了快速启动 Windows 容器的使用体验。
<!--
## Getting Started: Deploying a Windows container
To deploy a Windows container on Kubernetes, you must first create an example application. The example YAML file below creates a simple webserver application. Create a service spec named `win-webserver.yaml` with the contents below:
To deploy a Windows container on Kubernetes, you must first create an example application.
The example YAML file below creates a simple webserver application.
Create a service spec named `win-webserver.yaml` with the contents below:
-->
## 入门:部署 Windows 容器
@@ -102,7 +113,8 @@ spec:
```
<!--
Port mapping is also supported, but for simplicity in this example the container port 80 is exposed directly to the service.
Port mapping is also supported, but for simplicity in this example
the container port 80 is exposed directly to the service.
-->
{{< note >}}
端口映射也是支持的,但为简单起见,在此示例中容器端口 80 直接暴露给服务。
@@ -128,9 +140,12 @@ Port mapping is also supported, but for simplicity in this example the container
* Two containers per pod on the Windows node, use `docker ps`
* Two pods listed from the Linux master, use `kubectl get pods`
* Node-to-pod communication across the network, `curl` port 80 of your pod IPs from the Linux master to check for a web server response
* Pod-to-pod communication, ping between pods (and across hosts, if you have more than one Windows node) using docker exec or kubectl exec
* Service-to-pod communication, `curl` the virtual service IP (seen under `kubectl get services`) from the Linux master and from individual pods
* Node-to-pod communication across the network, `curl` port 80 of your pod IPs from the Linux master
to check for a web server response
* Pod-to-pod communication, ping between pods (and across hosts, if you have more than one Windows node)
using docker exec or kubectl exec
* Service-to-pod communication, `curl` the virtual service IP (seen under `kubectl get services`)
from the Linux master and from individual pods
* Service discovery, `curl` the service name with the Kubernetes [default DNS suffix](/docs/concepts/services-networking/dns-pod-service/#services)
* Inbound connectivity, `curl` the NodePort from the Linux master or machines outside of the cluster
* Outbound connectivity, `curl` external IPs from inside the pod using kubectl exec
@@ -155,34 +170,90 @@ Port mapping is also supported, but for simplicity in this example the container
* Windows 节点上每个 Pod 有两个容器,使用 `docker ps`
* Linux 主机列出两个 Pod,使用 `kubectl get pods`
* 跨网络的节点到 Pod 通信,从 Linux 主服务器 `curl` 您的 pod IPs 的端口80,以检查 Web 服务器响应
* Pod 到 Pod 的通信,使用 docker exec 或 kubectl exec 在 pod 之间(以及跨主机,如果您有多个 Windows 节点)进行 ping 操作
* 服务到 Pod 的通信,从 Linux 主服务器和各个 Pod 中 `curl` 虚拟服务 IP(在 `kubectl get services` 下可见)
* 服务发现,使用 Kubernetes `curl` 服务名称[默认 DNS 后缀](/zh/docs/concepts/services-networking/dns-pod-service/#services)
* Pod 到 Pod 的通信,使用 docker exec 或 kubectl exec 在 Pod 之间
(以及跨主机,如果你有多个 Windows 节点)进行 ping 操作
* 服务到 Pod 的通信,从 Linux 主服务器和各个 Pod 中 `curl` 虚拟服务 IP
(在 `kubectl get services` 下可见)
* 服务发现,使用 Kubernetes `curl` 服务名称
[默认 DNS 后缀](/zh/docs/concepts/services-networking/dns-pod-service/#services)
* 入站连接,从 Linux 主服务器或集群外部的计算机 `curl` NodePort
* 出站连接,使用 kubectl exec 从 Pod 内部 curl 外部 IP
<!--
Windows container hosts are not able to access the IP of services scheduled on them due to current platform limitations of the Windows networking stack. Only Windows pods are able to access service IPs.
Windows container hosts are not able to access the IP of services scheduled on them due to current platform limitations of the Windows networking stack.
Only Windows pods are able to access service IPs.
-->
{{< note >}}
由于当前平台对 Windows 网络堆栈的限制,Windows 容器主机无法访问在其上调度的服务的 IP。只有 Windows pods 才能访问服务 IP。
{{< /note >}}
<!--
## Observability
### Capturing logs from workloads
-->
## 可观测性 {#observability}
### 抓取来自工作负载的日志
<!--
Logs are an important element of observability; they enable users to gain insights
into the operational aspect of workloads and are a key ingredient to troubleshooting issues.
Because Windows containers and workloads inside Windows containers behave differently from Linux containers,
users had a hard time collecting logs, limiting operational visibility.
Windows workloads for example are usually configured to log to ETW (Event Tracing for Windows)
or push entries to the application event log.
[LogMonitor](https://github.com/microsoft/windows-container-tools/tree/master/LogMonitor), an open source tool by Microsoft,
is the recommended way to monitor configured log sources inside a Windows container.
LogMonitor supports monitoring event logs, ETW providers, and custom application logs,
piping them to STDOUT for consumption by `kubectl logs <pod>`.
-->
日志是可观测性的重要一环;使用日志用户可以获得对负载运行状况的洞察,
因而日志是故障排查的一个重要手法。
因为 Windows 容器中的 Windows 容器和负载与 Linux 容器的行为不同,
用户很难收集日志,因此运行状态的可见性很受限。
例如,Windows 工作负载通常被配置为将日志输出到 Windows 事件跟踪
Event Tracing for WindowsETW),或者将日志条目推送到应用的事件日志中。
[LogMonitor](https://github.com/microsoft/windows-container-tools/tree/master/LogMonitor)
是 Microsoft 提供的一个开源工具,是监视 Windows 容器中所配置的日志源
的推荐方式。
LogMonitor 支持监视时间日志、ETW 提供者模块以及自定义的应用日志,
并使用管道的方式将其输出到标准输出(stdout),以便 `kubectl logs <pod>`
这类命令能够读取这些数据。
<!--
Follow the instructions in the LogMonitor GitHub page to copy its binaries and configuration files
to all your containers and add the necessary entrypoints for LogMonitor to push your logs to STDOUT.
-->
请遵照 LogMonitor GitHub 页面上的指令,将其可执行文件和配置文件复制到
你的所有容器中,并为其添加必要的入口点(Entrypoint),以便 LogMonitor
能够将你的日志输出推送到标准输出(stdout)。
<!--
## Using configurable Container usernames
Starting with Kubernetes v1.16, Windows containers can be configured to run their entrypoints and processes with different usernames than the image defaults. The way this is achieved is a bit different from the way it is done for Linux containers. Learn more about it [here](/docs/tasks/configure-pod-container/configure-runasusername/).
Starting with Kubernetes v1.16, Windows containers can be configured to run their entrypoints and processes
with different usernames than the image defaults.
The way this is achieved is a bit different from the way it is done for Linux containers.
Learn more about it [here](/docs/tasks/configure-pod-container/configure-runasusername/).
-->
## 使用可配置的容器用户名
从 Kubernetes v1.16 开始,可以为 Windows 容器配置与其镜像默认值不同的用户名来运行其入口点和进程。
从 Kubernetes v1.16 开始,可以为 Windows 容器配置与其镜像默认值不同的用户名
来运行其入口点和进程。
此能力的实现方式和 Linux 容器有些不同。
在[此处](/zh/docs/tasks/configure-pod-container/configure-runasusername/)可了解更多信息。
在[此处](/zh/docs/tasks/configure-pod-container/configure-runasusername/)
可了解更多信息。
<!--
## Managing Workload Identity with Group Managed Service Accounts
Starting with Kubernetes v1.14, Windows container workloads can be configured to use Group Managed Service Accounts (GMSA). Group Managed Service Accounts are a specific type of Active Directory account that provides automatic password management, simplified service principal name (SPN) management, and the ability to delegate the management to other administrators across multiple servers. Containers configured with a GMSA can access external Active Directory Domain resources while carrying the identity configured with the GMSA. Learn more about configuring and using GMSA for Windows containers [here](/docs/tasks/configure-pod-container/configure-gmsa/).
Starting with Kubernetes v1.14, Windows container workloads can be configured to use Group Managed Service Accounts (GMSA).
Group Managed Service Accounts are a specific type of Active Directory account that provides automatic password management,
simplified service principal name (SPN) management, and the ability to delegate the management to other administrators across multiple servers.
Containers configured with a GMSA can access external Active Directory Domain resources while carrying the identity configured with the GMSA.
Learn more about configuring and using GMSA for Windows containers [here](/docs/tasks/configure-pod-container/configure-gmsa/).
-->
## 使用组托管服务帐户管理工作负载身份
@@ -190,7 +261,8 @@ Starting with Kubernetes v1.14, Windows container workloads can be configured to
组托管服务帐户是 Active Directory 帐户的一种特定类型,它提供自动密码管理,
简化的服务主体名称(SPN)管理以及将管理委派给跨多台服务器的其他管理员的功能。
配置了 GMSA 的容器可以访问外部 Active Directory 域资源,同时携带通过 GMSA 配置的身份。
在[此处](/zh/docs/tasks/configure-pod-container/configure-gmsa/)了解有关为 Windows 容器配置和使用 GMSA 的更多信息。
在[此处](/zh/docs/tasks/configure-pod-container/configure-gmsa/)了解有关为
Windows 容器配置和使用 GMSA 的更多信息。
<!--
## Taints and Tolerations
@@ -198,7 +270,10 @@ Starting with Kubernetes v1.14, Windows container workloads can be configured to
## 污点和容忍度
<!--
Users today need to use some combination of taints and node selectors in order to keep Linux and Windows workloads on their respective OS-specific nodes. This likely imposes a burden only on Windows users. The recommended approach is outlined below, with one of its main goals being that this approach should not break compatibility for existing Linux workloads.
Users today need to use some combination of taints and node selectors in order to
keep Linux and Windows workloads on their respective OS-specific nodes.
This likely imposes a burden only on Windows users. The recommended approach is outlined below,
with one of its main goals being that this approach should not break compatibility for existing Linux workloads.
-->
目前,用户需要将 Linux 和 Windows 工作负载运行在各自特定的操作系统的节点上,
因而需要结合使用污点和节点选择算符。 这可能仅给 Windows 用户造成不便。
@@ -210,7 +285,8 @@ Users today need to use some combination of taints and node selectors in order t
### 确保特定操作系统的工作负载落在适当的容器主机上
<!--
Users can ensure Windows containers can be scheduled on the appropriate host using Taints and Tolerations. All Kubernetes nodes today have the following default labels:
Users can ensure Windows containers can be scheduled on the appropriate host using Taints and Tolerations.
All Kubernetes nodes today have the following default labels:
-->
用户可以使用污点和容忍度确保 Windows 容器可以调度在适当的主机上。目前所有 Kubernetes 节点都具有以下默认标签:
@@ -218,7 +294,10 @@ Users can ensure Windows containers can be scheduled on the appropriate host usi
* kubernetes.io/arch = [amd64|arm64|...]
<!--
If a Pod specification does not specify a nodeSelector like `"kubernetes.io/os": windows`, it is possible the Pod can be scheduled on any host, Windows or Linux. This can be problematic since a Windows container can only run on Windows and a Linux container can only run on Linux. The best practice is to use a nodeSelector.
If a Pod specification does not specify a nodeSelector like `"kubernetes.io/os": windows`,
it is possible the Pod can be scheduled on any host, Windows or Linux.
This can be problematic since a Windows container can only run on Windows and a Linux container can only run on Linux.
The best practice is to use a nodeSelector.
-->
如果 Pod 规范未指定诸如 `"kubernetes.io/os": windows` 之类的 nodeSelector,则该 Pod
可能会被调度到任何主机(Windows 或 Linux)上。
@@ -226,7 +305,11 @@ If a Pod specification does not specify a nodeSelector like `"kubernetes.io/os":
最佳实践是使用 nodeSelector。
<!--
However, we understand that in many cases users have a pre-existing large number of deployments for Linux containers, as well as an ecosystem of off-the-shelf configurations, such as community Helm charts, and programmatic Pod generation cases, such as with Operators. In those situations, you may be hesitant to make the configuration change to add nodeSelectors. The alternative is to use Taints. Because the kubelet can set Taints during registration, it could easily be modified to automatically add a taint when running on Windows only.
However, we understand that in many cases users have a pre-existing large number of deployments for Linux containers,
as well as an ecosystem of off-the-shelf configurations, such as community Helm charts, and programmatic Pod generation cases, such as with Operators.
In those situations, you may be hesitant to make the configuration change to add nodeSelectors.
The alternative is to use Taints. Because the kubelet can set Taints during registration,
it could easily be modified to automatically add a taint when running on Windows only.
-->
但是,我们了解到,在许多情况下,用户都有既存的大量的 Linux 容器部署,以及一个现成的配置生态系统,
例如社区 Helm charts,以及程序化 Pod 生成案例,例如 Operators。
@@ -239,7 +322,9 @@ For example: `--register-with-taints='os=windows:NoSchedule'`
例如:`--register-with-taints='os=windows:NoSchedule'`
<!--
By adding a taint to all Windows nodes, nothing will be scheduled on them (that includes existing Linux Pods). In order for a Windows Pod to be scheduled on a Windows node, it would need both the nodeSelector to choose Windows, and the appropriate matching toleration.
By adding a taint to all Windows nodes, nothing will be scheduled on them (that includes existing Linux Pods).
In order for a Windows Pod to be scheduled on a Windows node,
it would need both the nodeSelector to choose Windows, and the appropriate matching toleration.
-->
向所有 Windows 节点添加污点后,Kubernetes 将不会在它们上调度任何负载(包括现有的 Linux Pod)。
为了使某 Windows Pod 调度到 Windows 节点上,该 Pod 既需要 nodeSelector 选择 Windows
@@ -266,18 +351,22 @@ The Windows Server version used by each pod must match that of the node. If you
Server versions in the same cluster, then you should set additional node labels and nodeSelectors.
-->
每个 Pod 使用的 Windows Server 版本必须与该节点的 Windows Server 版本相匹配。
如果要在同一集群中使用多个 Windows Server 版本,则应该设置其他节点标签和 nodeSelector。
如果要在同一集群中使用多个 Windows Server 版本,则应该设置其他节点标签和
nodeSelector。
<!--
Kubernetes 1.17 automatically adds a new label `node.kubernetes.io/windows-build` to simplify this. If you're running an older version, then it's recommended to add this label manually to Windows nodes.
Kubernetes 1.17 automatically adds a new label `node.kubernetes.io/windows-build` to simplify this.
If you're running an older version, then it's recommended to add this label manually to Windows nodes.
-->
Kubernetes 1.17 自动添加了一个新标签 `node.kubernetes.io/windows-build` 来简化此操作。
如果您运行的是旧版本,则建议手动将此标签添加到 Windows 节点。
<!--
This label reflects the Windows major, minor, and build number that need to match for compatibility. Here are values used today for each Windows Server version.
This label reflects the Windows major, minor, and build number that need to match for compatibility.
Here are values used today for each Windows Server version.
-->
此标签反映了需要兼容的 Windows 主要、次要和内部版本号。以下是当前每个 Windows Server 版本使用的值。
此标签反映了需要兼容的 Windows 主要、次要和内部版本号。以下是当前每个
Windows Server 版本使用的值。
| 产品名称 | 内部编号 |
|--------------------------------------|------------------------|
@@ -292,15 +381,19 @@ This label reflects the Windows major, minor, and build number that need to matc
### 使用 RuntimeClass 简化
<!--
[RuntimeClass] can be used to simplify the process of using taints and tolerations. A cluster administrator can create a `RuntimeClass` object which is used to encapsulate these taints and tolerations.
[RuntimeClass] can be used to simplify the process of using taints and tolerations.
A cluster administrator can create a `RuntimeClass` object which is used to encapsulate these taints and tolerations.
-->
[RuntimeClass](/zh/docs/concepts/containers/runtime-class/) 可用于简化使用污点和容忍度的过程。
[RuntimeClass](/zh/docs/concepts/containers/runtime-class/) 可用于
简化使用污点和容忍度的过程。
集群管理员可以创建 `RuntimeClass` 对象,用于封装这些污点和容忍度。
<!--
1. Save this file to `runtimeClasses.yml`. It includes the appropriate `nodeSelector` for the Windows OS, architecture, and version.
1. Save this file to `runtimeClasses.yml`. It includes the appropriate `nodeSelector`
for the Windows OS, architecture, and version.
-->
1. 将此文件保存到 `runtimeClasses.yml` 文件。它包括适用于 Windows 操作系统、体系结构和版本的 `nodeSelector`
1. 将此文件保存到 `runtimeClasses.yml` 文件。
它包括适用于 Windows 操作系统、体系结构和版本的 `nodeSelector`
```yaml
apiVersion: node.k8s.io/v1
@@ -324,7 +417,7 @@ This label reflects the Windows major, minor, and build number that need to matc
1. Run `kubectl create -f runtimeClasses.yml` using as a cluster administrator
1. Add `runtimeClassName: windows-2019` as appropriate to Pod specs
-->
2. 集群管理员`kubectl create -f runtimeClasses.yml` 操作
2. 集群管理员`kubectl create -f runtimeClasses.yml` 操作
3. 根据需要向 Pod 规约中添加 `runtimeClassName: windows-2019`
<!--
@@ -22,7 +22,7 @@ To learn how to install and use Node Problem Detector, see
[Node Problem Detector project documentation](https://github.com/kubernetes/node-problem-detector).
-->
*节点问题检测器(Node Problem Detector)*是一个守护程序,用于监视和报告节点的健康状况。
*节点问题检测器(Node Problem Detector* 是一个守护程序,用于监视和报告节点的健康状况。
你可以将节点问题探测器以 `DaemonSet` 或独立守护程序运行。
节点问题检测器从各种守护进程收集节点问题,并以
[NodeCondition](/zh/docs/concepts/architecture/nodes/#condition) 和
@@ -203,7 +203,7 @@ Kernel monitor watches the kernel log and detects known kernel issues following
-->
## 内核监视器
*内核监视器(Kernel Monitor)*是节点问题检测器中支持的系统日志监视器守护进程。
*内核监视器(Kernel Monitor* 是节点问题检测器中支持的系统日志监视器守护进程。
内核监视器观察内核日志并根据预定义规则检测已知的内核问题。
<!--
@@ -82,12 +82,12 @@ Alternatively, you can use an existing 3rd party solution, such as [apiserver-bu
1. Create a Kubernetes role binding from the service account in your namespace to the `extension-apiserver-authentication-reader` role. This allows your extension api-server to access the `extension-apiserver-authentication` configmap.
-->
8. 确保你的扩展 apiserver 从该卷中加载了那些证书,并在 HTTPS 握手过程中使用它们。
9. 在你的命空间中创建一个 Kubernetes 服务账号。
9. 在你的命空间中创建一个 Kubernetes 服务账号。
10. 为资源允许的操作创建 Kubernetes 集群角色。
11. 用你命空间中的服务账号创建一个 Kubernetes 集群角色绑定,绑定到你创建的角色上。
12. 用你命空间中的服务账号创建一个 Kubernetes 集群角色绑定,绑定到 `system:auth-delegator`
11. 用你命空间中的服务账号创建一个 Kubernetes 集群角色绑定,绑定到你创建的角色上。
12. 用你命空间中的服务账号创建一个 Kubernetes 集群角色绑定,绑定到 `system:auth-delegator`
集群角色,以将 auth 决策委派给 Kubernetes 核心 API 服务器。
13. 以你命空间中的服务账号创建一个 Kubernetes 集群角色绑定,绑定到
13. 以你命空间中的服务账号创建一个 Kubernetes 集群角色绑定,绑定到
`extension-apiserver-authentication-reader` 角色。
这将让你的扩展 api-server 能够访问 `extension-apiserver-authentication` configmap。
@@ -114,4 +114,3 @@ Alternatively, you can use an existing 3rd party solution, such as [apiserver-bu
并启用 apiserver 的相关参数。
* 高级概述,请参阅[使用聚合层扩展 Kubernetes API](/zh/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation)。
* 了解如何[使用 Custom Resource Definition 扩展 Kubernetes API](/zh/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)。
@@ -230,9 +230,9 @@ It takes a [Cron](https://en.wikipedia.org/wiki/Cron) format string, such as `0
格式串,例如 `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):
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` 步长值。
该格式也包含了扩展的 "Vixie cron" 步长值。
[FreeBSD 手册](https://www.freebsd.org/cgi/man.cgi?crontab%285%29)中解释如下:
<!--
@@ -0,0 +1,214 @@
---
title: 配置 kubelet 镜像凭据提供程序
description: 配置 kubelet 的镜像凭据提供程序插件
content_type: task
---
<!--
title: Configure a kubelet image credential provider
reviewers:
- liggitt
- cheftako
description: Configure the kubelet's image credential provider plugin
content_type: task
-->
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
<!-- overview -->
<!--
Starting from Kubernetes v1.20, the kubelet can dynamically retrieve credentials for a container image registry
using exec plugins. The kubelet and the exec plugin communicate through stdio (stdin, stdout, and stderr) using
Kubernetes versioned APIs. These plugins allow the kubelet to request credentials for a container registry dynamically
as opposed to storing static credentials on disk. For example, the plugin may talk to a local metadata server to retrieve
short-lived credentials for an image that is being pulled by the kubelet.
-->
从 Kubernetes v1.20 开始,kubelet 可以使用 exec 插件动态检索容器镜像注册中心的凭据。
kubelet 和 exec 插件使用 Kubernetes 版本化 API 通过标准输入输出(标准输入、标准输出和标准错误)通信。
这些插件允许 kubelet 动态请求容器注册中心的凭据,而不是将静态凭据存储在磁盘上。
例如,插件可能会与本地元数据通信,以检索 kubelet 正在拉取的镜像的短期凭据。
<!--
You may be interested in using this capability if any of the below are true:
* API calls to a cloud provider service are required to retrieve authentication information for a registry.
* Credentials have short expiration times and requesting new credentials frequently is required.
* Storing registry credentials on disk or in imagePullSecrets is not acceptable.
This guide demonstrates how to configure the kubelet's image credential provider plugin mechanism.
-->
如果以下任一情况属实,你可能对此功能感兴趣:
* 需要调用云提供商的 API 来检索注册中心的身份验证信息。
* 凭据的到期时间很短,需要频繁请求新凭据。
* 将注册中心凭据存储在磁盘或者 imagePullSecret 是不可接受的。
## {{% heading "prerequisites" %}}
<!--
* The kubelet image credential provider is introduced in v1.20 as an alpha feature. As with other alpha features,
a feature gate `KubeletCredentialProviders` must be enabled on only the kubelet for the feature to work.
* A working implementation of a credential provider exec plugin. You can build your own plugin or use one provided by cloud providers.
-->
* kubelet 镜像凭证提供程序在 v1.20 版本作为 alpha 功能引入。
与其他 alpha 功能一样,当前仅当在 kubelet 启动 `KubeletCredentialProviders` 特性门禁才能使该功能正常工作。
* 凭据提供程序 exec 插件的工作实现。你可以构建自己的插件或使用云提供商提供的插件。
<!-- steps -->
<!--
## Installing Plugins on Nodes
A credential provider plugin is an executable binary that will be run by the kubelet. Ensure that the plugin binary exists on
every node in your cluster and stored in a known directory. The directory will be required later when configuring kubelet flags.
-->
## 在节点上安装插件 {#installing-plugins-on-nodes}
凭据提供程序插件是将由 kubelet 运行的可执行二进制文件。
确保插件二进制存在于你的集群的每个节点上,并存储在已知目录中。
稍后配置 kubelet 标志需要该目录。
<!--
## Configuring the Kubelet
In order to use this feature, the kubelet expects two flags to be set:
* `--image-credential-provider-config` - the path to the credential provider plugin config file.
* `--image-credential-provider-bin-dir` - the path to the directory where credential provider plugin binaries are located.
-->
## 配置 kubelet {#configuring-the-kubelet}
为了使用这个特性,kubelet 需要设置以下两个标志:
* `--image-credential-provider-config` —— 凭据提供程序插件配置文件的路径。
* `--image-credential-provider-bin-dir` —— 凭据提供程序插件二进制文件所在目录的路径。
<!--
### Configure a kubelet credential provider
The configuration file passed into `--image-credential-provider-config` is read by the kubelet to determine which exec plugins
should be invoked for which container images. Here's an example configuration file you may end up using if you are using the [ECR](https://aws.amazon.com/ecr/)-based plugin:
-->
### 配置 kubelet 凭据提供程序 {#configure-a-kubelet-credential-provider}
kubelet 会读取传入 `--image-credential-provider-config` 的配置文件文件,
以确定应该为哪些容器镜像调用哪些 exec 插件。
如果你正在使用基于 [ECR](https://aws.amazon.com/ecr/) 插件,
这里有个样例配置文件你可能最终会使用到:
```yaml
kind: CredentialProviderConfig
apiVersion: kubelet.config.k8s.io/v1alpha1
# providers 是将由 kubelet 启用的凭证提供程序插件列表。
# 多个提供程序可能与单个镜像匹配,在这种情况下,来自所有提供程序的凭据将返回到 kubelet。
# 如果为单个镜像调用多个提供程序,则结果会合并。
# 如果提供程序返回重叠的身份验证密钥,则使用提供程序列表中较早的值。
providers:
# name 是凭据提供程序的必需名称。
# 它必须与 kubelet 看到的提供程序可执行文件的名称相匹配。
# 可执行文件必须在 kubelet 的 bin 目录中
# (由 --image-credential-provider-bin-dir 标志设置)。
- name: ecr
# matchImages 是一个必需的字符串列表,用于匹配镜像以确定是否应调用此提供程序。
# 如果其中一个字符串与 kubelet 请求的镜像相匹配,则该插件将被调用并有机会提供凭据。
# 镜像应包含注册域和 URL 路径。
#
# matchImages 中的每个条目都是一个模式,可以选择包含端口和路径。
# 通配符可以在域中使用,但不能在端口或路径中使用。
# 支持通配符作为子域(例如“*.k8s.io”或“k8s.*.io”)和顶级域(例如“k8s.*”)。
# 还支持匹配部分子域,如“app*.k8s.io”。
# 每个通配符只能匹配一个子域段,因此 *.io 不匹配 *.k8s.io。
#
# 当以下所有条件都为真时,镜像和 matchImage 之间存在匹配:
# - 两者都包含相同数量的域部分并且每个部分都匹配。
# - imageMatch 的 URL 路径必须是目标镜像 URL 路径的前缀。
# - 如果 imageMatch 包含端口,则该端口也必须在图像中匹配。
#
# matchImages 的示例值:
# - 123456789.dkr.ecr.us-east-1.amazonaws.com
# - *.azurecr.io
# - gcr.io
# - *.*.registry.io
# - registry.io:8080/path
matchImages:
- "*.dkr.ecr.*.amazonaws.com"
- "*.dkr.ecr.*.amazonaws.cn"
- "*.dkr.ecr-fips.*.amazonaws.com"
- "*.dkr.ecr.us-iso-east-1.c2s.ic.gov"
- "*.dkr.ecr.us-isob-east-1.sc2s.sgov.gov"
# defaultCacheDuration 是插件将在内存中缓存凭据的默认持续时间
# 如果插件响应中未提供缓存持续时间。此字段是必需的。
defaultCacheDuration: "12h"
# exec CredentialProviderRequest 的必需输入版本。
# 返回的 CredentialProviderResponse 必须使用与输入相同的编码版本。当前支持的值为:
# - credentialprovider.kubelet.k8s.io/v1alpha1
apiVersion: credentialprovider.kubelet.k8s.io/v1alpha1
# 执行命令时传递给命令的参数。
# +可选
args:
- get-credentials
# env 定义了额外的环境变量以暴露给进程。
# 这些与主机环境以及 client-go 用于将参数传递给插件的变量结合在一起。
# +可选
env:
- name: AWS_PROFILE
value: example_profile
```
<!--
The `providers` field is a list of enabled plugins used by the kubelet. Each entry has a few required fields:
* `name`: the name of the plugin which MUST match the name of the executable binary that exists in the directory passed into `--image-credential-provider-bin-dir`.
* `matchImages`: a list of strings used to match against images in order to determine if this provider should be invoked. More on this below.
* `defaultCacheDuration`: the default duration the kubelet will cache credentials in-memory if a cache duration was not specified by the plugin.
* `apiVersion`: the api version that the kubelet and the exec plugin will use when communicating.
Each credential provider can also be given optional args and environment variables as well. Consult the plugin implementors to determine what set of arguments and environment variables are required for a given plugin.
-->
`providers` 字段是 kubelet 使用的已启用插件列表。每个条目都有几个必填字段:
* `name`:插件的名称,必须与传入`--image-credential-provider-bin-dir`
的目录中存在的可执行二进制文件的名称相匹配。
* `matchImages`:用于匹配图像以确定是否应调用此提供程序的字符串列表。更多相关信息如下。
* `defaultCacheDuration`:如果插件未指定缓存持续时间,kubelet 将在内存中缓存凭据的默认持续时间。
* `apiVersion`kubelet 和 exec 插件在通信时将使用的 api 版本。
每个凭证提供程序也可以被赋予可选的参数和环境变量。
咨询插件实现者以确定给定插件需要哪些参数和环境变量集。
<!--
#### Configure image matching
The `matchImages` field for each credential provider is used by the kubelet to determine whether a plugin should be invoked
for a given image that a Pod is using. Each entry in `matchImages` is an image pattern which can optionally contain a port and a path.
Globs can be used in the domain, but not in the port or the path. Globs are supported as subdomains like `*.k8s.io` or `k8s.*.io`,
and top-level domains such as `k8s.*`. Matching partial subdomains like `app*.k8s.io` is also supported. Each glob can only match
a single subdomain segment, so `*.io` does NOT match `*.k8s.io`.
-->
#### 配置镜像匹配 {#configure-image-matching}
kubelet 使用每个凭证提供程序的 `matchImages` 字段来确定是否应该为 Pod 正在使用的给定镜像调用插件。
`matchImages` 中的每个条目都是一个镜像模式,可以选择包含端口和路径。
通配符可以在域中使用,但不能在端口或路径中使用。
支持通配符作为子域,如 `*.k8s.io``k8s.*.io`,以及顶级域,如 `k8s.*`
还支持匹配部分子域,如 `app*.k8s.io`。每个通配符只能匹配一个子域段,
因此 `*.io` 不匹配 `*.k8s.io`
<!--
A match exists between an image name and a `matchImage` entry when all of the below are true:
* Both contain the same number of domain parts and each part matches.
* The URL path of match image must be a prefix of the target image URL path.
* If the imageMatch contains a port, then the port must match in the image as well.
Some example values of `matchImages` patterns are:
-->
当以下所有条件都为真时,镜像名称和 `matchImage` 条目之间存在匹配:
* 两者都包含相同数量的域部分并且每个部分都匹配。
* 匹配图片的 URL 路径必须是目标图片 URL 路径的前缀。
* 如果 imageMatch 包含端口,则该端口也必须在镜像中匹配。
`matchImages` 模式的一些示例值:
* `123456789.dkr.ecr.us-east-1.amazonaws.com`
* `*.azurecr.io`
* `gcr.io`
* `*.*.registry.io`
* `foo.registry.io:8080/path`
@@ -10,7 +10,7 @@ reviewers:
- rickypai
- thockin
title: Adding entries to Pod /etc/hosts with HostAliases
content_type: concept
content_type: task
weight: 60
min-kubernetes-server-version: 1.7
-->
@@ -29,7 +29,7 @@ Modification not using HostAliases is not suggested because the file is managed
建议通过使用 HostAliases 来进行修改,因为该文件由 Kubelet 管理,并且
可以在 Pod 创建/重启过程中被重写。
<!-- body -->
<!-- steps -->
<!--
## Default Hosts File Content
@@ -64,10 +64,10 @@ There should be one IPv4 block and one IPv6 block allocated.
应该分配一个 IPv4 块和一个 IPv6 块。
<!--
Validate that the node has an IPv4 and IPv6 interface detected (replace node name with a valid node from the cluster. In this example the node name is k8s-linuxpool1-34450317-0):
Validate that the node has an IPv4 and IPv6 interface detected. Replace node name with a valid node from the cluster. In this example the node name is `k8s-linuxpool1-34450317-0`:
-->
验证节点是否检测到 IPv4 和 IPv6 接口用集群中的有效节点替换节点名称。
在此示例中,节点名称为 `k8s-linuxpool1-34450317-0`
验证节点是否检测到 IPv4 和 IPv6 接口用集群中的有效节点替换节点名称。
在此示例中,节点名称为 `k8s-linuxpool1-34450317-0`
```shell
kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .status.addresses}}{{printf "%s: %s \n" .type .address}}{{end}}'
@@ -81,12 +81,12 @@ InternalIP: 2001:1234:5678:9abc::5
<!--
### Validate Pod addressing
Validate that a Pod has an IPv4 and IPv6 address assigned. (replace the Pod name with a valid Pod in your cluster. In this example the Pod name is pod01)
Validate that a Pod has an IPv4 and IPv6 address assigned. Replace the Pod name with a valid Pod in your cluster. In this example the Pod name is `pod01`.
-->
### 验证 Pod 寻址
验证 Pod 已分配了 IPv4 和 IPv6 地址。用集群中的有效 Pod 替换 Pod 名称。
在此示例中,Pod 名称为 pod01
验证 Pod 已分配了 IPv4 和 IPv6 地址。用集群中的有效 Pod 替换 Pod 名称。
在此示例中,Pod 名称为 `pod01`
```shell
kubectl get pods pod01 -o go-template --template='{{range .status.podIPs}}{{printf "%s \n" .ip}}{{end}}'
@@ -209,7 +209,7 @@ Create the following Service that explicitly defines `IPv6` as the first array e
Kubernetes 将 `service-cluster-ip-range` 配置的 IPv6 地址范围给 Service 分配集群 IP,
并将 `.spec.ipFamilyPolicy` 设置为 `SingleStack`
{{< codenew file="service/networking/dual-stack-ipv6-svc.yaml" >}}
{{< codenew file="service/networking/dual-stack-ipfamilies-ipv6.yaml" >}}
<!--
Use `kubectl` to view the YAML for the Service.
@@ -308,14 +308,24 @@ Events: <none>
<!--
### Create a dual-stack load balanced Service
If the cloud provider supports the provisioning of IPv6 enabled external load balancer, create the following Service with both the `ipFamily` field set to `IPv6` and the `type` field set to `LoadBalancer`
If the cloud provider supports the provisioning of IPv6 enabled external load balancers, create the following Service with `PreferDualStack` in `.spec.ipFamilyPolicy`. `IPv6` as the first element of the `.spec.ipFamilies` array and the `type` field set to `LoadBalancer`.
-->
### 创建双协议栈负载均衡服务
如果云提供商支持配置启用 IPv6 的外部负载均衡器,则`ipFamily` 字段设置为
`IPv6` 并将 `type` 字段设置为 `LoadBalancer` 的方式创建以下服务:
如果云提供商支持配置启用 IPv6 的外部负载均衡器,则创建如下 Service 时将
`.spec.ipFamilyPolicy` 设置为 `PreferDualStack`, 并将 `spec.ipFamilies` 字段
的第一个元素设置为 `IPv6`,将 `type` 字段设置为 `LoadBalancer`
{{< codenew file="service/networking/dual-stack-ipv6-lb-svc.yaml" >}}
{{< codenew file="service/networking/dual-stack-prefer-ipv6-lb-svc.yaml" >}}
<!--
Check the Service:
-->
检查服务:
```shell
kubectl get svc -l app=MyApp
```
<!--
Validate that the Service receives a `CLUSTER-IP` address from the IPv6 address block along with an `EXTERNAL-IP`. You may then validate access to the service via the IP and port.
@@ -323,11 +333,8 @@ Validate that the Service receives a `CLUSTER-IP` address from the IPv6 address
验证服务是否从 IPv6 地址块中接收到 `CLUSTER-IP` 地址以及 `EXTERNAL-IP`
然后,你可以通过 IP 和端口验证对服务的访问。
```shell
kubectl get svc -l app=MyApp
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service ClusterIP fe80:20d::d06b 2001:db8:f100:4002::9d37:c0d7 80:31868/TCP 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service LoadBalancer fd00::7ebc 2603:1030:805::5 80:30790/TCP 35s
```
@@ -169,6 +169,13 @@ The following methods exist for installing kubectl on macOS:
sudo chown root: /usr/local/bin/kubectl
```
{{< note >}}
<!--
Make sure `/usr/local/bin` is in your PATH environment variable.
-->
确保 `/usr/local/bin` 在你的 PATH 环境变量中。
{{< /note >}}
<!--
1. Test to ensure the version you installed is up-to-date:
-->
@@ -1,16 +1,17 @@
---
title: "示例:使用 MongoDB 部署 PHP 留言板应用程序"
title: "示例:使用 Redis 部署 PHP 留言板应用程序"
content_type: tutorial
weight: 20
card:
name: tutorials
weight: 30
title: "无状态应用示例:基于 MongoDB 的 PHP Guestbook"
title: "无状态应用示例:基于 Redis 的 PHP Guestbook"
min-kubernetes-server-version: v1.14
source: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
---
<!--
title: "Example: Deploying PHP Guestbook application with MongoDB"
title: "Example: Deploying PHP Guestbook application with Redis"
reviewers:
- ahmetb
content_type: tutorial
@@ -18,7 +19,7 @@ weight: 20
card:
name: tutorials
weight: 30
title: "Stateless Example: PHP Guestbook with MongoDB"
title: "Stateless Example: PHP Guestbook with Redis"
min-kubernetes-server-version: v1.14
-->
@@ -31,244 +32,350 @@ This tutorial shows you how to build and deploy a simple _(not production ready)
一个简单的_(非面向生产)的_多层 web 应用程序。本例由以下组件组成:
<!--
* A single-instance [MongoDB](https://www.mongodb.com/) to store guestbook entries
* A single-instance [Redis](https://www.redis.com/) to store guestbook entries
* Multiple web frontend instances
-->
* 单实例 [MongoDB](https://www.mongodb.com/) 以保存留言板条目
* 单实例 [Redis](https://www.redis.com/) 以保存留言板条目
* 多个 web 前端实例
## {{% heading "objectives" %}}
<!--
* Start up a Mongo database.
* Start up a Redis leader.
* Start up two Redis followers.
* Start up the guestbook frontend.
* Expose and view the Frontend Service.
* Clean up.
-->
* 启动 Mongo 数据库。
* 启动留言板前端。
* 公开并查看前端服务。
* 清理。
* 启动 Redis 领导者(Leader
* 启动两个 Redis 跟随者(Follower
* 公开并查看前端服务
* 清理
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
{{< version-check >}}
<!-- lessoncontent -->
<!--
## Start up the Mongo Database
## Start up the Redis Database
-->
## 启动 Mongo 数据库
## 启动 Redis 数据库
<!--
The guestbook application uses MongoDB to store its data.
The guestbook application uses Redis to store its data.
-->
留言板应用程序使用 MongoDB 存储数据。
留言板应用程序使用 Redis 存储数据。
<!--
### Creating the Mongo Deployment
### Creating the Redis Deployment
-->
### 创建 Mongo 的 Deployment
### 创建 Redis Deployment
<!--
The manifest file, included below, specifies a Deployment controller that runs a single replica MongoDB Pod.
The manifest file, included below, specifies a Deployment controller that runs a single replica Redis Pod.
-->
下面包含的清单文件指定了一个 Deployment 控制器,该控制器运行一个 MongoDB Pod 副本。
下面包含的清单文件指定了一个 Deployment 控制器,该控制器运行一个 Redis Pod 副本。
{{< codenew file="application/guestbook/mongo-deployment.yaml" >}}
{{< codenew file="application/guestbook/redis-leader-deployment.yaml" >}}
<!--
1. Launch a terminal window in the directory you downloaded the manifest files.
1. Apply the MongoDB Deployment from the `mongo-deployment.yaml` file:
1. Apply the Redis Deployment from the `redis-leader-deployment.yaml` file:
-->
1. 在下载清单文件的目录中启动终端窗口。
2. 从 `mongo-deployment.yaml` 文件中应用 MongoDB Deployment
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/mongo-deployment.yaml
-->
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-deployment.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/mongo-deployment.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
```
<!--
1. Query the list of Pods to verify that the MongoDB Pod is running:
-->
3. 查询 Pod 列表以验证 MongoDB Pod 是否正在运行:
```shell
kubectl get pods
```
```shell
kubectl get pods
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
```shell
NAME READY STATUS RESTARTS AGE
redis-leader-fb76b4755-xjr2n 1/1 Running 0 13s
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
```shell
NAME READY STATUS RESTARTS AGE
mongo-5cfd459dd4-lrcjb 1/1 Running 0 28s
```
<!--
1. Run the following command to view the logs from the MongoDB Deployment:
1. Run the following command to view the logs from the Redis leader Pod:
-->
4. 运行以下命令查看 MongoDB Deployment 中的日志:
```shell
kubectl logs -f deployment/mongo
```
```shell
kubectl logs -f deployment/redis-leader
```
<!--
### Creating the MongoDB Service
### Creating the Redis leader Service
-->
### 创建 MongoDB 服务
### 创建 Redis 领导者服务
<!--
The guestbook application needs to communicate to the MongoDB to write its data. You need to apply a [Service](/docs/concepts/services-networking/service/) to proxy the traffic to the MongoDB Pod. A Service defines a policy to access the Pods.
The guestbook application needs to communicate to the Redis to write its data. You need to apply a [Service](/docs/concepts/services-networking/service/) to proxy the traffic to the Redis Pod. A Service defines a policy to access the Pods.
-->
留言板应用程序需要往 MongoDB 中写数据。因此,需要创建 [Service](/zh/docs/concepts/services-networking/service/) 来代理 MongoDB Pod 的流量。Service 定义了访问 Pod 的策略。
留言板应用程序需要往 MongoDB 中写数据。因此,需要创建
[Service](/zh/docs/concepts/services-networking/service/) 来转发 Redis Pod
的流量。Service 定义了访问 Pod 的策略。
{{< codenew file="application/guestbook/mongo-service.yaml" >}}
{{< codenew file="application/guestbook/redis-leader-service.yaml" >}}
<!--
1. Apply the MongoDB Service from the following `mongo-service.yaml` file:
1. Apply the Redis Service from the following `redis-leader-service.yaml` file:
-->
1. 使用下面的 `mongo-service.yaml` 文件创建 MongoDB 的服务:
1. 使用下面的 `redis-leader-service.yaml` 文件创建 Redis的服务:
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/mongo-service.yaml
-->
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-service.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/mongo-service.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
```
<!--
1. Query the list of Services to verify that the MongoDB Service is running:
1. Query the list of Services to verify that the Redis Service is running:
-->
2. 查询服务列表验证 MongoDB 服务是否正在运行:
2. 查询服务列表验证 Redis 服务是否正在运行:
```shell
kubectl get service
```
```shell
kubectl get service
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
```shell
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 16s
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
```shell
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
mongo ClusterIP 10.0.0.151 <none> 27017/TCP 8s
```
<!--
This manifest file creates a Service named `mongo` with a set of labels that match the labels previously defined, so the Service routes network traffic to the MongoDB Pod.
This manifest file creates a Service named `redis-leader` with a set of labels that match the labels previously defined, so the Service routes network traffic to the Redis Pod.
-->
{{< note >}}
这个清单文件创建了一个名为 `mongo` 的 Service,其中包含一组与前面定义的标签匹配的标签,因此服务将网络流量路由到 MongoDB Pod 上。
这个清单文件创建了一个名为 `redis-leader` 的 Service,其中包含一组
与前面定义的标签匹配的标签,因此服务将网络流量路由到 Redis Pod 上。
{{< /note >}}
<!--
### Set up Redis followers
Although the Redis leader is a single Pod, you can make it highly available and meet traffic demands by adding a few Redis followers, or replicas.
-->
### 设置 Redis 跟随者
尽管 Redis 领导者只有一个 Pod,你可以通过添加若干 Redis 跟随者来将其配置为高可用状态,
以满足流量需求。
{{< codenew file="application/guestbook/redis-follower-deployment.yaml" >}}
<!--
1. Apply the Redis Service from the following `redis-follower-deployment.yaml` file:
-->
1. 应用下面的 `redis-follower-deployment.yaml` 文件创建 Redis Deployment
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/redis-follower-deployment.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
```
<!--
1. Verify that the two Redis follower replicas are running by querying the list of Pods:
-->
2. 通过查询 Pods 列表,验证两个 Redis 跟随者副本在运行:
```shell
kubectl get pods
```
<!--
The response should be similar to this:
-->
响应应该类似于这样:
```
NAME READY STATUS RESTARTS AGE
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 37s
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 38s
redis-leader-fb76b4755-xjr2n 1/1 Running 0 11m
```
<!--
### Creating the Redis follower service
The guestbook application needs to communicate with the Redis followers to read data. To make the Redis followers discoverable, you must set up another [Service](/docs/concepts/services-networking/service/).
-->
### 创建 Redis 跟随者服务
Guestbook 应用需要与 Redis 跟随者通信以读取数据。
为了让 Redis 跟随者可被发现,你必须创建另一个
[Service](/zh/docs/concepts/services-networking/service/)。
{{< codenew file="application/guestbook/redis-follower-service.yaml" >}}
<!--
1. Apply the Redis Service from the following `redis-follower-service.yaml` file:
-->
1. 应用如下所示 `redis-follower-service.yaml` 文件中的 Redis Service
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/redis-follower-service.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
```
<!--
1. Query the list of Services to verify that the Redis Service is running:
-->
2. 查询 Service 列表,验证 Redis 服务在运行:
```shell
kubectl get service
```
<!--
The response should be similar to this:
-->
响应应该类似于这样:
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 9s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 6m10s
```
{{< note >}}
<!--
This manifest file creates a Service named `redis-follower` with a set of labels that match the labels previously defined, so the Service routes network traffic to the Redis Pod.
-->
清单文件创建了一个名为 `redis-follower` 的 Service,该 Service
具有一些与之前所定义的标签相匹配的标签,因此该 Service 能够将网络流量
路由到 Redis Pod 之上。
{{< /note >}}
<!--
## Set up and Expose the Guestbook Frontend
-->
## 设置并公开留言板前端
<!--
The guestbook application has a web frontend serving the HTTP requests written in PHP. It is configured to connect to the `mongo` Service to store Guestbook entries.
-->
留言板应用程序有一个 web 前端,服务于用 PHP 编写的 HTTP 请求。
它被配置为连接到 `mongo` 服务以存储留言版条目。
Now that you have the Redis storage of your guestbook up and running, start the guestbook web servers. Like the Redis followers, the frontend is deployed using a Kubernetes Deployment.
The guestbook app uses a PHP frontend. It is configured to communicate with either the Redis follower or leader Services, depending on whether the request is a read or a write. The frontend exposes a JSON interface, and serves a jQuery-Ajax-based UX.
-->
现在你有了一个为 Guestbook 应用配置的 Redis 存储处于运行状态,
接下来可以启动 Guestbook 的 Web 服务器了。
与 Redis 跟随者类似,前端也是使用 Kubernetes Deployment 来部署的。
Guestbook 应用使用 PHP 前端。该前端被配置成与后端的 Redis 跟随者或者
领导者服务通信,具体选择哪个服务取决于请求是读操作还是写操作。
前端对外暴露一个 JSON 接口,并提供基于 jQuery-Ajax 的用户体验。
<!--
### Creating the Guestbook Frontend Deployment
-->
### 创建留言板前端 Deployment
### 创建 Guestbook 前端 Deployment
{{< codenew file="application/guestbook/frontend-deployment.yaml" >}}
<!--
1. Apply the frontend Deployment from the `frontend-deployment.yaml` file:
-->
1. `frontend-deployment.yaml` 应用前端 Deployment 文件
1. 应用来自 `frontend-deployment.yaml` 文件的前端 Deployment
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml
-->
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
```
<!--
1. Query the list of Pods to verify that the three frontend replicas are running:
-->
2. 查询 Pod 列表,验证三个前端副本是否正在运行:
2. 查询 Pod 列表,验证三个前端副本正在运行:
```shell
kubectl get pods -l app.kubernetes.io/name=guestbook -l app.kubernetes.io/component=frontend
```
```shell
kubectl get pods -l app=guestbook -l tier=frontend
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
<!--
The response should be similar to this:
-->
响应应该与此类似:
```
NAME READY STATUS RESTARTS AGE
frontend-3823415956-dsvc5 1/1 Running 0 54s
frontend-3823415956-k22zn 1/1 Running 0 54s
frontend-3823415956-w9gbt 1/1 Running 0 54s
```
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5tqhb 1/1 Running 0 47s
frontend-85595f5bf9-qbzwm 1/1 Running 0 47s
frontend-85595f5bf9-zchwc 1/1 Running 0 47s
```
<!--
### Creating the Frontend Service
-->
### 创建前端服务
<!--
The `mongo` Services you applied is only accessible within the Kubernetes cluster because the default type for a Service is [ClusterIP](/docs/concepts/services-networking/service/#publishing-services-service-types). `ClusterIP` provides a single IP address for the set of Pods the Service is pointing to. This IP address is accessible only within the cluster.
The `Redis` Services you applied is only accessible within the Kubernetes cluster because the default type for a Service is [ClusterIP](/docs/concepts/services-networking/service/#publishing-services-service-types). `ClusterIP` provides a single IP address for the set of Pods the Service is pointing to. This IP address is accessible only within the cluster.
-->
应用的 `mongo` 服务只能在 Kubernetes 集群中访问,因为服务的默认类型是
应用的 `Redis` 服务只能在 Kubernetes 集群中访问,因为服务的默认类型是
[ClusterIP](/zh/docs/concepts/services-networking/service/#publishing-services-service-types)。
`ClusterIP` 为服务指向的 Pod 集提供一个 IP 地址。这个 IP 地址只能在集群中访问。
<!--
If you want guests to be able to access your guestbook, you must configure the frontend Service to be externally visible, so a client can request the Service from outside the Kubernetes cluster. However a Kubernetes user you can use `kubectl port-forward` to access the service even though it uses a `ClusterIP`.
-->
如果希望访客能够访问您的留言板,您必须将前端服务配置为外部可见的,以便客户端可以从 Kubernetes 集群之外请求服务。然而即便使用了 `ClusterIP` Kubernetes 用户仍可以通过 `kubectl port-forward` 访问服务。
如果希望访客能够访问你的 Guestbook,你必须将前端服务配置为外部可见的,
以便客户端可以从 Kubernetes 集群之外请求服务。
然而即便使用了 `ClusterIP`Kubernetes 用户仍可以通过
`kubectl port-forward` 访问服务。
<!--
Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, support external load balancers. If your cloud provider supports load balancers and you want to use it, uncomment `type: LoadBalancer`.
-->
{{< note >}}
一些云提供商,如 Google Compute Engine 或 Google Kubernetes Engine支持外部负载均衡器。如果您的云提供商支持负载均衡器,并且您希望使用它,
只需取消注释 `type: LoadBalancer` 即可。
一些云提供商,如 Google Compute Engine 或 Google Kubernetes Engine
支持外部负载均衡器。如果你的云提供商支持负载均衡器,并且你希望使用它,
只需取消注释 `type: LoadBalancer`
{{< /note >}}
{{< codenew file="application/guestbook/frontend-service.yaml" >}}
@@ -276,37 +383,38 @@ Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, su
<!--
1. Apply the frontend Service from the `frontend-service.yaml` file:
-->
1. `frontend-service.yaml` 文件中应用前端服务:
1. 应用来自 `frontend-service.yaml` 文件中前端服务:
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml
-->
<!---
for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
```
<!--
1. Query the list of Services to verify that the frontend Service is running:
-->
2. 查询服务列表以验证前端服务正在运行:
2. 查询 Service 列表以验证前端服务正在运行:
```shell
kubectl get services
```
```shell
kubectl get services
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
<!--
The response should be similar to this:
-->
响应应该与此类似:
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.0.0.112 <none> 80/TCP 6s
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 4m
mongo ClusterIP 10.0.0.151 <none> 6379/TCP 2m
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.97.28.230 <none> 80/TCP 19s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 5m48s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 11m
```
<!--
### Viewing the Frontend Service via `kubectl port-forward`
@@ -319,200 +427,209 @@ Some cloud providers, like Google Compute Engine or Google Kubernetes Engine, su
-->
1. 运行以下命令将本机的 `8080` 端口转发到服务的 `80` 端口。
```shell
kubectl port-forward svc/frontend 8080:80
```
```shell
kubectl port-forward svc/frontend 8080:80
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
<!--
The response should be similar to this:
-->
响应应该与此类似:
```
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
```
```
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
```
<!--
1. load the page [http://localhost:8080](http://localhost:8080) in your browser to view your guestbook.
-->
2. 在浏览器中加载 [http://localhost:8080](http://localhost:8080) 页面以查看留言板。
2. 在浏览器中加载 [http://localhost:8080](http://localhost:8080)
页面以查看 Guestbook。
<!--
### Viewing the Frontend Service via `LoadBalancer`
-->
### 通过 `LoadBalancer` 查看前端服务
<!--
If you deployed the `frontend-service.yaml` manifest with type: `LoadBalancer` you need to find the IP address to view your Guestbook.
-->
如果部署了 `frontend-service.yaml`。你需要找到 IP 地址来查看你的留言板。
如果部署了 `frontend-service.yaml`需要找到用来查看 Guestbook 的
IP 地址。
<!--
1. Run the following command to get the IP address for the frontend Service.
-->
1. 运行以下命令以获取前端服务的 IP 地址。
```shell
kubectl get service frontend
```
```shell
kubectl get service frontend
```
<!--
The response should be similar to this:
-->
响应应该与此类似:
<!--
The response should be similar to this:
-->
响应应该与此类似:
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.51.242.136 109.197.92.229 80:32372/TCP 1m
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.51.242.136 109.197.92.229 80:32372/TCP 1m
```
<!--
1. Copy the external IP address, and load the page in your browser to view your guestbook.
-->
2. 复制外部 IP 地址,然后在浏览器中加载页面以查看留言板。
2. 复制这里的外部 IP 地址,然后在浏览器中加载页面以查看留言板。
{{< note >}}
<!--
Try adding some guestbook entries by typing in a message, and clicking Submit. The message you typed appears in the frontend. This message indicates that data is successfully added to Redis through the Services you created earlier.
-->
尝试通过输入消息并点击 Submit 来添加一些留言板条目。
你所输入的消息会在前端显示。这一消息表明数据被通过你
之前所创建的 Service 添加到 Redis 存储中。
{{< /note >}}
<!--
## Scale the Web Frontend
-->
## 扩展 Web 前端
<!--
Scaling up or down is easy because your servers are defined as a Service that uses a Deployment controller.
You can scale up or down as needed because your servers are defined as a Service that uses a Deployment controller.
-->
伸缩很容易是因为服务器本身被定义为使用一个 Deployment 控制器的 Service。
你可以根据需要执行伸缩操作,这是因为服务器本身被定义为使用一个
Deployment 控制器的 Service。
<!--
1. Run the following command to scale up the number of frontend Pods:
-->
1. 运行以下命令扩展前端 Pod 的数量:
```shell
kubectl scale deployment frontend --replicas=5
```
```shell
kubectl scale deployment frontend --replicas=5
```
<!--
1. Query the list of Pods to verify the number of frontend Pods running:
-->
2. 查询 Pod 列表验证正在运行的前端 Pod 的数量:
```shell
kubectl get pods
```
```shell
kubectl get pods
```
<!--
The response should look similar to this:
-->
响应应该类似于这样:
<!--
The response should look similar to this:
-->
响应应该类似于这样:
```
NAME READY STATUS RESTARTS AGE
frontend-3823415956-70qj5 1/1 Running 0 5s
frontend-3823415956-dsvc5 1/1 Running 0 54m
frontend-3823415956-k22zn 1/1 Running 0 54m
frontend-3823415956-w9gbt 1/1 Running 0 54m
frontend-3823415956-x2pld 1/1 Running 0 5s
mongo-1068406935-3lswp 1/1 Running 0 56m
```
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5df5m 1/1 Running 0 83s
frontend-85595f5bf9-7zmg5 1/1 Running 0 83s
frontend-85595f5bf9-cpskg 1/1 Running 0 15m
frontend-85595f5bf9-l2l54 1/1 Running 0 14m
frontend-85595f5bf9-l9c8z 1/1 Running 0 14m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 97m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 97m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 108m
```
<!--
1. Run the following command to scale down the number of frontend Pods:
-->
3. 运行以下命令缩小前端 Pod 的数量:
```shell
kubectl scale deployment frontend --replicas=2
```
```shell
kubectl scale deployment frontend --replicas=2
```
<!--
1. Query the list of Pods to verify the number of frontend Pods running:
-->
4. 查询 Pod 列表验证正在运行的前端 Pod 的数量:
```shell
kubectl get pods
```
<!--
The response should look similar to this:
-->
响应应该类似于这样:
```
NAME READY STATUS RESTARTS AGE
frontend-3823415956-k22zn 1/1 Running 0 1h
frontend-3823415956-w9gbt 1/1 Running 0 1h
mongo-1068406935-3lswp 1/1 Running 0 1h
```
```shell
kubectl get pods
```
<!--
The response should look similar to this:
-->
响应应该类似于这样:
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-cpskg 1/1 Running 0 16m
frontend-85595f5bf9-l9c8z 1/1 Running 0 15m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 98m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 98m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 109m
```
## {{% heading "cleanup" %}}
<!--
Deleting the Deployments and Services also deletes any running Pods. Use labels to delete multiple resources with one command.
-->
删除 Deployments 和服务还会删除正在运行的 Pod。使用标签用一个命令删除多个资源。
删除 Deployments 和服务还会删除正在运行的 Pod。
使用标签用一个命令删除多个资源。
<!--
1. Run the following commands to delete all Pods, Deployments, and Services.
-->
1. 运行以下命令以删除所有 PodDeployments 和 Services。
```shell
kubectl delete deployment -l app.kubernetes.io/name=mongo
kubectl delete service -l app.kubernetes.io/name=mongo
kubectl delete deployment -l app.kubernetes.io/name=guestbook
kubectl delete service -l app.kubernetes.io/name=guestbook
```
```shell
kubectl delete deployment -l app=redis
kubectl delete service -l app=redis
kubectl delete deployment frontend
kubectl delete service frontend
```
<!--
The responses should be:
-->
响应应该是:
```
deployment.apps "mongo" deleted
service "mongo" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
```
<!--
The responses should be:
-->
响应应该是:
```
deployment.apps "redis-follower" deleted
deployment.apps "redis-leader" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
```
<!--
1. Query the list of Pods to verify that no Pods are running:
-->
2. 查询 Pod 列表,确认没有 Pod 在运行:
```shell
kubectl get pods
```
```shell
kubectl get pods
```
<!--
The response should be this:
-->
响应应该是:
```
No resources found.
```
<!--
The response should be this:
-->
响应应该是:
```
No resources found in default namespace.
```
## {{% heading "whatsnext" %}}
<!--
* Complete the [Kubernetes Basics](/docs/tutorials/kubernetes-basics/) Interactive Tutorials
* Use Kubernetes to create a blog using [Persistent Volumes for MySQL and Wordpress](/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/#visit-your-new-wordpress-blog)
* Read more about [connecting applications](/docs/concepts/services-networking/connect-applications-service/)
* Read more about [Managing Resources](/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively)
-->
* 完成 [Kubernetes Basics](/zh/docs/tutorials/kubernetes-basics/) 交互式教程
* 使用 Kubernetes 创建一个博客,使用 [MySQL 和 Wordpress 的持久卷](/zh/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/#visit-your-new-wordpress-blog)
* 阅读更多关于[连接应用程序](/zh/docs/concepts/services-networking/connect-applications-service/)
* 阅读更多关于[管理资源](/zh/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively)
* 完成 [Kubernetes 基础](/zh/docs/tutorials/kubernetes-basics/) 交互式教程
* 使用 Kubernetes 创建一个博客,使用
[MySQL 和 Wordpress 的持久卷](/zh/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/#visit-your-new-wordpress-blog)
* 进一步阅读[连接应用程序](/zh/docs/concepts/services-networking/connect-applications-service/)
* 进一步阅读[管理资源](/zh/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively)
@@ -1,32 +1,29 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
replicas: 3
app: guestbook
tier: frontend
template:
metadata:
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
app: guestbook
tier: frontend
spec:
containers:
- name: guestbook
image: paulczar/gb-frontend:v5
# image: gcr.io/google-samples/gb-frontend:v4
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v5
env:
- name: GET_HOSTS_FROM
value: "dns"
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
- containerPort: 80
@@ -1,16 +1,19 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1
kind: Service
metadata:
name: frontend
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
app: guestbook
tier: frontend
spec:
# if your cluster supports it, uncomment the following to automatically create
# an external load-balanced IP for the frontend service.
# type: LoadBalancer
#type: LoadBalancer
ports:
# the port that this service should serve on
- port: 80
selector:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
app: guestbook
tier: frontend
@@ -1,31 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo
labels:
app.kubernetes.io/name: mongo
app.kubernetes.io/component: backend
spec:
selector:
matchLabels:
app.kubernetes.io/name: mongo
app.kubernetes.io/component: backend
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: mongo
app.kubernetes.io/component: backend
spec:
containers:
- name: mongo
image: mongo:4.2
args:
- --bind_ip
- 0.0.0.0
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 27017
@@ -1,14 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
app.kubernetes.io/name: mongo
app.kubernetes.io/component: backend
spec:
ports:
- port: 27017
targetPort: 27017
selector:
app.kubernetes.io/name: mongo
app.kubernetes.io/component: backend
@@ -0,0 +1,30 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-follower
labels:
app: redis
role: follower
tier: backend
spec:
replicas: 2
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
role: follower
tier: backend
spec:
containers:
- name: follower
image: gcr.io/google_samples/gb-redis-follower:v2
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
@@ -0,0 +1,17 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1
kind: Service
metadata:
name: redis-follower
labels:
app: redis
role: follower
tier: backend
spec:
ports:
# the port that this service should serve on
- port: 6379
selector:
app: redis
role: follower
tier: backend
@@ -0,0 +1,30 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-leader
labels:
app: redis
role: leader
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
role: leader
tier: backend
spec:
containers:
- name: leader
image: "docker.io/redis:6.0.5"
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
@@ -0,0 +1,17 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1
kind: Service
metadata:
name: redis-leader
labels:
app: redis
role: leader
tier: backend
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
role: leader
tier: backend
@@ -0,0 +1,27 @@
apiVersion: batch/v1
kind: Job
metadata:
name: 'indexed-job'
spec:
completions: 5
parallelism: 3
completionMode: Indexed
template:
spec:
restartPolicy: Never
containers:
- name: 'worker'
image: 'docker.io/library/busybox'
command:
- "rev"
- "/input/data.txt"
volumeMounts:
- mountPath: /input
name: input
volumes:
- name: input
downwardAPI:
items:
- path: "data.txt"
fieldRef:
fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index']
@@ -0,0 +1,35 @@
apiVersion: batch/v1
kind: Job
metadata:
name: 'indexed-job'
spec:
completions: 5
parallelism: 3
completionMode: Indexed
template:
spec:
restartPolicy: Never
initContainers:
- name: 'input'
image: 'docker.io/library/bash'
command:
- "bash"
- "-c"
- |
items=(foo bar baz qux xyz)
echo ${items[$JOB_COMPLETION_INDEX]} > /input/data.txt
volumeMounts:
- mountPath: /input
name: input
containers:
- name: 'worker'
image: 'docker.io/library/busybox'
command:
- "rev"
- "/input/data.txt"
volumeMounts:
- mountPath: /input
name: input
volumes:
- name: input
emptyDir: {}
+96 -49
View File
@@ -32,7 +32,6 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apimachinery/pkg/util/yaml"
// "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apps"
@@ -70,7 +69,6 @@ import (
_ "k8s.io/kubernetes/pkg/apis/networking/install"
_ "k8s.io/kubernetes/pkg/apis/policy/install"
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
_ "k8s.io/kubernetes/pkg/apis/settings/install"
_ "k8s.io/kubernetes/pkg/apis/storage/install"
)
@@ -100,7 +98,6 @@ func (g TestGroup) Codec() runtime.Codec {
func initGroups() {
Groups = make(map[string]TestGroup)
groupNames := []string{
api.GroupName,
apps.GroupName,
@@ -109,7 +106,6 @@ func initGroups() {
networking.GroupName,
policy.GroupName,
rbac.GroupName,
settings.GroupName,
storage.GroupName,
}
@@ -152,6 +148,19 @@ func getCodecForObject(obj runtime.Object) (runtime.Codec, error) {
}
func validateObject(obj runtime.Object) (errors field.ErrorList) {
podValidationOptions := validation.PodValidationOptions{
AllowMultipleHugePageResources: true,
AllowDownwardAPIHugePages: true,
}
quotaValidationOptions := validation.ResourceQuotaValidationOptions{
AllowPodAffinityNamespaceSelector: true,
}
pspValidationOptions := policy_validation.PodSecurityPolicyValidationOptions{
AllowEphemeralVolumeType: true,
}
// Enable CustomPodDNS for testing
// feature.DefaultFeatureGate.Set("CustomPodDNS=true")
switch t := obj.(type) {
@@ -186,7 +195,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
opts := validation.PodValidationOptions{
AllowMultipleHugePageResources: true,
}
errors = validation.ValidatePod(t, opts)
errors = validation.ValidatePodCreate(t, opts)
case *api.PodList:
for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...)
@@ -195,12 +204,12 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = validation.ValidatePodTemplate(t)
errors = validation.ValidatePodTemplate(t, podValidationOptions)
case *api.ReplicationController:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = validation.ValidateReplicationController(t)
errors = validation.ValidateReplicationController(t, podValidationOptions)
case *api.ReplicationControllerList:
for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...)
@@ -209,7 +218,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = validation.ValidateResourceQuota(t)
errors = validation.ValidateResourceQuota(t, quotaValidationOptions)
case *api.Secret:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
@@ -219,7 +228,11 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = validation.ValidateService(t, true)
// handle clusterIPs, logic copied from service strategy
if len(t.Spec.ClusterIP) > 0 && len(t.Spec.ClusterIPs) == 0 {
t.Spec.ClusterIPs = []string{t.Spec.ClusterIP}
}
errors = validation.ValidateService(t)
case *api.ServiceAccount:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
@@ -233,7 +246,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = apps_validation.ValidateStatefulSet(t)
errors = apps_validation.ValidateStatefulSet(t, podValidationOptions)
case *autoscaling.HorizontalPodAutoscaler:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
@@ -254,12 +267,12 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = apps_validation.ValidateDaemonSet(t)
errors = apps_validation.ValidateDaemonSet(t, podValidationOptions)
case *apps.Deployment:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = apps_validation.ValidateDeployment(t)
errors = apps_validation.ValidateDeployment(t, podValidationOptions)
case *networking.Ingress:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
@@ -269,18 +282,30 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(networking.GroupName)[0].Version,
}
errors = networking_validation.ValidateIngressCreate(t, gv)
case *networking.IngressClass:
/*
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
gv := schema.GroupVersion{
Group: networking.GroupName,
Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(networking.GroupName)[0].Version,
}
*/
errors = networking_validation.ValidateIngressClass(t)
case *policy.PodSecurityPolicy:
errors = policy_validation.ValidatePodSecurityPolicy(t)
errors = policy_validation.ValidatePodSecurityPolicy(t, pspValidationOptions)
case *apps.ReplicaSet:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = apps_validation.ValidateReplicaSet(t)
errors = apps_validation.ValidateReplicaSet(t, podValidationOptions)
case *batch.CronJob:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
}
errors = batch_validation.ValidateCronJob(t)
errors = batch_validation.ValidateCronJob(t, podValidationOptions)
case *networking.NetworkPolicy:
if t.Namespace == "" {
t.Namespace = api.NamespaceDefault
@@ -291,6 +316,9 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
t.Namespace = api.NamespaceDefault
}
errors = policy_validation.ValidatePodDisruptionBudget(t)
case *rbac.ClusterRole:
// clusterole does not accept namespace
errors = rbac_validation.ValidateClusterRole(t)
case *rbac.ClusterRoleBinding:
// clusterolebinding does not accept namespace
errors = rbac_validation.ValidateClusterRoleBinding(t)
@@ -418,6 +446,7 @@ func TestExampleObjectSchemas(t *testing.T) {
"storagelimits": {&api.LimitRange{}},
},
"admin/sched": {
"clusterrole": {&rbac.ClusterRole{}},
"my-scheduler": {&api.ServiceAccount{}, &rbac.ClusterRoleBinding{}, &rbac.ClusterRoleBinding{}, &apps.Deployment{}},
"pod1": {&api.Pod{}},
"pod2": {&api.Pod{}},
@@ -441,12 +470,12 @@ func TestExampleObjectSchemas(t *testing.T) {
"cassandra-statefulset": {&apps.StatefulSet{}, &storage.StorageClass{}},
},
"application/guestbook": {
"frontend-deployment": {&apps.Deployment{}},
"frontend-service": {&api.Service{}},
"redis-master-deployment": {&apps.Deployment{}},
"redis-master-service": {&api.Service{}},
"redis-slave-deployment": {&apps.Deployment{}},
"redis-slave-service": {&api.Service{}},
"frontend-deployment": {&apps.Deployment{}},
"frontend-service": {&api.Service{}},
"redis-follower-deployment": {&apps.Deployment{}},
"redis-follower-service": {&api.Service{}},
"redis-leader-deployment": {&apps.Deployment{}},
"redis-leader-service": {&api.Service{}},
},
"application/hpa": {
"php-apache": {&autoscaling.HorizontalPodAutoscaler{}},
@@ -456,8 +485,10 @@ func TestExampleObjectSchemas(t *testing.T) {
"nginx-svc": {&api.Service{}},
},
"application/job": {
"cronjob": {&batch.CronJob{}},
"job-tmpl": {&batch.Job{}},
"cronjob": {&batch.CronJob{}},
"job-tmpl": {&batch.Job{}},
"indexed-job": {&batch.Job{}},
"indexed-job-vol": {&batch.Job{}},
},
"application/job/rabbitmq": {
"job": {&batch.Job{}},
@@ -536,13 +567,15 @@ func TestExampleObjectSchemas(t *testing.T) {
"two-container-pod": {&api.Pod{}},
},
"pods/config": {
"redis-pod": {&api.Pod{}},
"redis-pod": {&api.Pod{}},
"example-redis-config": {&api.ConfigMap{}},
},
"pods/inject": {
"dapi-envars-container": {&api.Pod{}},
"dapi-envars-pod": {&api.Pod{}},
"dapi-volume": {&api.Pod{}},
"dapi-volume-resources": {&api.Pod{}},
"dependent-envars": {&api.Pod{}},
"envars": {&api.Pod{}},
"pod-multiple-secret-env-variable": {&api.Pod{}},
"pod-secret-envFrom": {&api.Pod{}},
@@ -588,10 +621,11 @@ func TestExampleObjectSchemas(t *testing.T) {
"redis": {&api.Pod{}},
},
"policy": {
"baseline-psp": {&policy.PodSecurityPolicy{}},
"example-psp": {&policy.PodSecurityPolicy{}},
"privileged-psp": {&policy.PodSecurityPolicy{}},
"restricted-psp": {&policy.PodSecurityPolicy{}},
"baseline-psp": {&policy.PodSecurityPolicy{}},
"example-psp": {&policy.PodSecurityPolicy{}},
"priority-class-resourcequota": {&api.ResourceQuota{}},
"privileged-psp": {&policy.PodSecurityPolicy{}},
"restricted-psp": {&policy.PodSecurityPolicy{}},
"zookeeper-pod-disruption-budget-maxunavailable": {&policy.PodDisruptionBudget{}},
"zookeeper-pod-disruption-budget-minavailable": {&policy.PodDisruptionBudget{}},
},
@@ -600,29 +634,42 @@ func TestExampleObjectSchemas(t *testing.T) {
"load-balancer-example": {&apps.Deployment{}},
},
"service/access": {
"frontend": {&api.Service{}, &apps.Deployment{}},
"hello-application": {&apps.Deployment{}},
"hello-service": {&api.Service{}},
"hello": {&apps.Deployment{}},
"backend-deployment": {&apps.Deployment{}},
"backend-service": {&api.Service{}},
"frontend-deployment": {&apps.Deployment{}},
"frontend-service": {&api.Service{}},
"hello-application": {&apps.Deployment{}},
},
"service/networking": {
"curlpod": {&apps.Deployment{}},
"custom-dns": {&api.Pod{}},
"dual-stack-default-svc": {&api.Service{}},
"dual-stack-ipv4-svc": {&api.Service{}},
"dual-stack-ipv6-lb-svc": {&api.Service{}},
"dual-stack-ipv6-svc": {&api.Service{}},
"hostaliases-pod": {&api.Pod{}},
"ingress": {&networking.Ingress{}},
"network-policy-allow-all-egress": {&networking.NetworkPolicy{}},
"network-policy-allow-all-ingress": {&networking.NetworkPolicy{}},
"network-policy-default-deny-egress": {&networking.NetworkPolicy{}},
"network-policy-default-deny-ingress": {&networking.NetworkPolicy{}},
"network-policy-default-deny-all": {&networking.NetworkPolicy{}},
"nginx-policy": {&networking.NetworkPolicy{}},
"nginx-secure-app": {&api.Service{}, &apps.Deployment{}},
"nginx-svc": {&api.Service{}},
"run-my-nginx": {&apps.Deployment{}},
"curlpod": {&apps.Deployment{}},
"custom-dns": {&api.Pod{}},
"dual-stack-default-svc": {&api.Service{}},
"dual-stack-ipfamilies-ipv6": {&api.Service{}},
"dual-stack-ipv6-svc": {&api.Service{}},
"dual-stack-prefer-ipv6-lb-svc": {&api.Service{}},
"dual-stack-preferred-ipfamilies-svc": {&api.Service{}},
"dual-stack-preferred-svc": {&api.Service{}},
"external-lb": {&networking.IngressClass{}},
"example-ingress": {&networking.Ingress{}},
"hostaliases-pod": {&api.Pod{}},
"ingress-resource-backend": {&networking.Ingress{}},
"ingress-wildcard-host": {&networking.Ingress{}},
"minimal-ingress": {&networking.Ingress{}},
"name-virtual-host-ingress": {&networking.Ingress{}},
"name-virtual-host-ingress-no-third-host": {&networking.Ingress{}},
"namespaced-params": {&networking.IngressClass{}},
"network-policy-allow-all-egress": {&networking.NetworkPolicy{}},
"network-policy-allow-all-ingress": {&networking.NetworkPolicy{}},
"network-policy-default-deny-egress": {&networking.NetworkPolicy{}},
"network-policy-default-deny-ingress": {&networking.NetworkPolicy{}},
"network-policy-default-deny-all": {&networking.NetworkPolicy{}},
"nginx-policy": {&networking.NetworkPolicy{}},
"nginx-secure-app": {&api.Service{}, &apps.Deployment{}},
"nginx-svc": {&api.Service{}},
"run-my-nginx": {&apps.Deployment{}},
"simple-fanout-example": {&networking.Ingress{}},
"test-ingress": {&networking.Ingress{}},
"tls-example-ingress": {&networking.Ingress{}},
},
"windows": {
"configmap-pod": {&api.ConfigMap{}, &api.Pod{}},
@@ -2,11 +2,13 @@ apiVersion: v1
kind: Service
metadata:
name: my-service
labels:
app: MyApp
spec:
ipFamily: IPv4
ipFamilies:
- IPv6
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
@@ -5,11 +5,12 @@ metadata:
labels:
app: MyApp
spec:
ipFamily: IPv6
ipFamilyPolicy: PreferDualStack
ipFamilies:
- IPv6
type: LoadBalancer
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376