Update zh examples with updated test case

This commit is contained in:
Qiming Teng
2021-06-18 09:31:49 +08:00
parent 2c7d774239
commit c4123fe383
15 changed files with 664 additions and 379 deletions
@@ -64,10 +64,10 @@ There should be one IPv4 block and one IPv6 block allocated.
应该分配一个 IPv4 块和一个 IPv6 块。 应该分配一个 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 接口用集群中的有效节点替换节点名称。 验证节点是否检测到 IPv4 和 IPv6 接口用集群中的有效节点替换节点名称。
在此示例中,节点名称为 `k8s-linuxpool1-34450317-0` 在此示例中,节点名称为 `k8s-linuxpool1-34450317-0`
```shell ```shell
kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .status.addresses}}{{printf "%s: %s \n" .type .address}}{{end}}' 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 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 寻址
验证 Pod 已分配了 IPv4 和 IPv6 地址。用集群中的有效 Pod 替换 Pod 名称。 验证 Pod 已分配了 IPv4 和 IPv6 地址。用集群中的有效 Pod 替换 Pod 名称。
在此示例中,Pod 名称为 pod01 在此示例中,Pod 名称为 `pod01`
```shell ```shell
kubectl get pods pod01 -o go-template --template='{{range .status.podIPs}}{{printf "%s \n" .ip}}{{end}}' 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 Kubernetes 将 `service-cluster-ip-range` 配置的 IPv6 地址范围给 Service 分配集群 IP
并将 `.spec.ipFamilyPolicy` 设置为 `SingleStack` 并将 `.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. Use `kubectl` to view the YAML for the Service.
@@ -308,14 +308,24 @@ Events: <none>
<!-- <!--
### Create a dual-stack load balanced Service ### 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 的外部负载均衡器,则创建如下 Service 时将
`IPv6` 并将 `type` 字段设置为 `LoadBalancer` 的方式创建以下服务: `.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. 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` 验证服务是否从 IPv6 地址块中接收到 `CLUSTER-IP` 地址以及 `EXTERNAL-IP`
然后,你可以通过 IP 和端口验证对服务的访问。 然后,你可以通过 IP 和端口验证对服务的访问。
```shell
kubectl get svc -l app=MyApp
``` ```
``` NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-service LoadBalancer fd00::7ebc 2603:1030:805::5 80:30790/TCP 35s
my-service ClusterIP fe80:20d::d06b 2001:db8:f100:4002::9d37:c0d7 80:31868/TCP 30s
``` ```
@@ -1,16 +1,17 @@
--- ---
title: "示例:使用 MongoDB 部署 PHP 留言板应用程序" title: "示例:使用 Redis 部署 PHP 留言板应用程序"
content_type: tutorial content_type: tutorial
weight: 20 weight: 20
card: card:
name: tutorials name: tutorials
weight: 30 weight: 30
title: "无状态应用示例:基于 MongoDB 的 PHP Guestbook" title: "无状态应用示例:基于 Redis 的 PHP Guestbook"
min-kubernetes-server-version: v1.14 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: reviewers:
- ahmetb - ahmetb
content_type: tutorial content_type: tutorial
@@ -18,7 +19,7 @@ weight: 20
card: card:
name: tutorials name: tutorials
weight: 30 weight: 30
title: "Stateless Example: PHP Guestbook with MongoDB" title: "Stateless Example: PHP Guestbook with Redis"
min-kubernetes-server-version: v1.14 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 应用程序。本例由以下组件组成: 一个简单的_(非面向生产)的_多层 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 * Multiple web frontend instances
--> -->
* 单实例 [MongoDB](https://www.mongodb.com/) 以保存留言板条目 * 单实例 [Redis](https://www.redis.com/) 以保存留言板条目
* 多个 web 前端实例 * 多个 web 前端实例
## {{% heading "objectives" %}} ## {{% heading "objectives" %}}
<!-- <!--
* Start up a Mongo database. * Start up a Redis leader.
* Start up two Redis followers.
* Start up the guestbook frontend. * Start up the guestbook frontend.
* Expose and view the Frontend Service. * Expose and view the Frontend Service.
* Clean up. * Clean up.
--> -->
* 启动 Redis 领导者(Leader
* 启动 Mongo 数据库。 * 启动两个 Redis 跟随者(Follower
* 启动留言板前端。 * 公开并查看前端服务
* 公开并查看前端服务。 * 清理
* 清理。
## {{% heading "prerequisites" %}} ## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< include "task-tutorial-prereqs.md" >}}
{{< version-check >}} {{< version-check >}}
<!-- lessoncontent --> <!-- lessoncontent -->
<!-- <!--
## Start up the Mongo Database ## Start up the Redis Database
--> -->
## 启动 Redis 数据库
## 启动 Mongo 数据库
<!-- <!--
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. 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. 在下载清单文件的目录中启动终端窗口。 1. 在下载清单文件的目录中启动终端窗口。
2.`mongo-deployment.yaml` 文件中应用 MongoDB Deployment 2.`mongo-deployment.yaml` 文件中应用 MongoDB Deployment
<!--- <!---
for local testing of the content via relative file path for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/mongo-deployment.yaml kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-deployment.yaml
--> -->
```shell ```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/mongo-deployment.yaml 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: 1. Query the list of Pods to verify that the MongoDB Pod is running:
--> -->
3. 查询 Pod 列表以验证 MongoDB Pod 是否正在运行: 3. 查询 Pod 列表以验证 MongoDB Pod 是否正在运行:
```shell ```shell
kubectl get pods 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: 1. Run the following command to view the logs from the Redis leader Pod:
-->
响应应该与此类似:
```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:
--> -->
4. 运行以下命令查看 MongoDB Deployment 中的日志: 4. 运行以下命令查看 MongoDB Deployment 中的日志:
```shell ```shell
kubectl logs -f deployment/mongo kubectl logs -f deployment/redis-leader
``` ```
<!-- <!--
### Creating the MongoDB Service ### Creating the Redis leader Service
--> -->
### 创建 Redis 领导者服务
### 创建 MongoDB 服务
<!-- <!--
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 for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/mongo-service.yaml kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-service.yaml
--> -->
```shell ```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/mongo-service.yaml 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 ```shell
kubectl get service 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: 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.
-->
响应应该与此类似:
```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.
--> -->
{{< note >}} {{< note >}}
这个清单文件创建了一个名为 `mongo` 的 Service,其中包含一组与前面定义的标签匹配的标签,因此服务将网络流量路由到 MongoDB Pod 上。 这个清单文件创建了一个名为 `redis-leader` 的 Service,其中包含一组
与前面定义的标签匹配的标签,因此服务将网络流量路由到 Redis Pod 上。
{{< /note >}} {{< /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 ## 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. 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.
-->
留言板应用程序有一个 web 前端,服务于用 PHP 编写的 HTTP 请求。 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.
它被配置为连接到 `mongo` 服务以存储留言版条目。 -->
现在你有了一个为 Guestbook 应用配置的 Redis 存储处于运行状态,
接下来可以启动 Guestbook 的 Web 服务器了。
与 Redis 跟随者类似,前端也是使用 Kubernetes Deployment 来部署的。
Guestbook 应用使用 PHP 前端。该前端被配置成与后端的 Redis 跟随者或者
领导者服务通信,具体选择哪个服务取决于请求是读操作还是写操作。
前端对外暴露一个 JSON 接口,并提供基于 jQuery-Ajax 的用户体验。
<!-- <!--
### Creating the Guestbook Frontend Deployment ### Creating the Guestbook Frontend Deployment
--> -->
### 创建 Guestbook 前端 Deployment
### 创建留言板前端 Deployment
{{< codenew file="application/guestbook/frontend-deployment.yaml" >}} {{< codenew file="application/guestbook/frontend-deployment.yaml" >}}
<!-- <!--
1. Apply the frontend Deployment from the `frontend-deployment.yaml` file: 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 for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml
--> -->
```shell ```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml 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: 1. Query the list of Pods to verify that the three frontend replicas are running:
--> -->
2. 查询 Pod 列表,验证三个前端副本是否正在运行: 2. 查询 Pod 列表,验证三个前端副本正在运行:
```shell ```shell
kubectl get pods -l app.kubernetes.io/name=guestbook -l app.kubernetes.io/component=frontend 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 NAME READY STATUS RESTARTS AGE
frontend-3823415956-dsvc5 1/1 Running 0 54s frontend-85595f5bf9-5tqhb 1/1 Running 0 47s
frontend-3823415956-k22zn 1/1 Running 0 54s frontend-85595f5bf9-qbzwm 1/1 Running 0 47s
frontend-3823415956-w9gbt 1/1 Running 0 54s frontend-85595f5bf9-zchwc 1/1 Running 0 47s
``` ```
<!-- <!--
### Creating the Frontend Service ### 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](/zh/docs/concepts/services-networking/service/#publishing-services-service-types)。
`ClusterIP` 为服务指向的 Pod 集提供一个 IP 地址。这个 IP 地址只能在集群中访问。 `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`. 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`. 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 >}} {{< note >}}
一些云提供商,如 Google Compute Engine 或 Google Kubernetes Engine支持外部负载均衡器。如果您的云提供商支持负载均衡器,并且您希望使用它, 一些云提供商,如 Google Compute Engine 或 Google Kubernetes Engine
只需取消注释 `type: LoadBalancer` 即可。 支持外部负载均衡器。如果你的云提供商支持负载均衡器,并且你希望使用它,
只需取消注释 `type: LoadBalancer`。
{{< /note >}} {{< /note >}}
{{< codenew file="application/guestbook/frontend-service.yaml" >}} {{< 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. 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 for local testing of the content via relative file path
kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml
--> -->
```shell ```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml 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: 1. Query the list of Services to verify that the frontend Service is running:
--> -->
2. 查询服务列表以验证前端服务正在运行: 2. 查询 Service 列表以验证前端服务正在运行:
```shell ```shell
kubectl get services 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 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.0.0.112 <none> 80/TCP 6s frontend ClusterIP 10.97.28.230 <none> 80/TCP 19s
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 4m kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
mongo ClusterIP 10.0.0.151 <none> 6379/TCP 2m 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` ### 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` 端口。 1. 运行以下命令将本机的 `8080` 端口转发到服务的 `80` 端口。
```shell ```shell
kubectl port-forward svc/frontend 8080:80 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 127.0.0.1:8080 -> 80
Forwarding from [::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. 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` ### Viewing the Frontend Service via `LoadBalancer`
--> -->
### 通过 `LoadBalancer` 查看前端服务 ### 通过 `LoadBalancer` 查看前端服务
<!-- <!--
If you deployed the `frontend-service.yaml` manifest with type: `LoadBalancer` you need to find the IP address to view your Guestbook. 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. Run the following command to get the IP address for the frontend Service.
--> -->
1. 运行以下命令以获取前端服务的 IP 地址。 1. 运行以下命令以获取前端服务的 IP 地址。
```shell ```shell
kubectl get service frontend 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 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.51.242.136 109.197.92.229 80:32372/TCP 1m 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. 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 ## Scale the Web Frontend
--> -->
## 扩展 Web 前端 ## 扩展 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. Run the following command to scale up the number of frontend Pods:
--> -->
1. 运行以下命令扩展前端 Pod 的数量: 1. 运行以下命令扩展前端 Pod 的数量:
```shell ```shell
kubectl scale deployment frontend --replicas=5 kubectl scale deployment frontend --replicas=5
``` ```
<!-- <!--
1. Query the list of Pods to verify the number of frontend Pods running: 1. Query the list of Pods to verify the number of frontend Pods running:
--> -->
2. 查询 Pod 列表验证正在运行的前端 Pod 的数量: 2. 查询 Pod 列表验证正在运行的前端 Pod 的数量:
```shell ```shell
kubectl get pods kubectl get pods
``` ```
<!-- <!--
The response should look similar to this: The response should look similar to this:
--> -->
响应应该类似于这样: 响应应该类似于这样:
``` ```
NAME READY STATUS RESTARTS AGE NAME READY STATUS RESTARTS AGE
frontend-3823415956-70qj5 1/1 Running 0 5s frontend-85595f5bf9-5df5m 1/1 Running 0 83s
frontend-3823415956-dsvc5 1/1 Running 0 54m frontend-85595f5bf9-7zmg5 1/1 Running 0 83s
frontend-3823415956-k22zn 1/1 Running 0 54m frontend-85595f5bf9-cpskg 1/1 Running 0 15m
frontend-3823415956-w9gbt 1/1 Running 0 54m frontend-85595f5bf9-l2l54 1/1 Running 0 14m
frontend-3823415956-x2pld 1/1 Running 0 5s frontend-85595f5bf9-l9c8z 1/1 Running 0 14m
mongo-1068406935-3lswp 1/1 Running 0 56m 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: 1. Run the following command to scale down the number of frontend Pods:
--> -->
3. 运行以下命令缩小前端 Pod 的数量: 3. 运行以下命令缩小前端 Pod 的数量:
```shell ```shell
kubectl scale deployment frontend --replicas=2 kubectl scale deployment frontend --replicas=2
``` ```
<!-- <!--
1. Query the list of Pods to verify the number of frontend Pods running: 1. Query the list of Pods to verify the number of frontend Pods running:
--> -->
4. 查询 Pod 列表验证正在运行的前端 Pod 的数量: 4. 查询 Pod 列表验证正在运行的前端 Pod 的数量:
```shell ```shell
kubectl get pods 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
```
<!--
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" %}} ## {{% heading "cleanup" %}}
<!-- <!--
Deleting the Deployments and Services also deletes any running Pods. Use labels to delete multiple resources with one command. 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. Run the following commands to delete all Pods, Deployments, and Services.
--> -->
1. 运行以下命令以删除所有 PodDeployments 和 Services。 1. 运行以下命令以删除所有 PodDeployments 和 Services。
```shell ```shell
kubectl delete deployment -l app.kubernetes.io/name=mongo kubectl delete deployment -l app=redis
kubectl delete service -l app.kubernetes.io/name=mongo kubectl delete service -l app=redis
kubectl delete deployment -l app.kubernetes.io/name=guestbook kubectl delete deployment frontend
kubectl delete service -l app.kubernetes.io/name=guestbook kubectl delete service frontend
``` ```
<!-- <!--
The responses should be: The responses should be:
--> -->
响应应该是: 响应应该是:
```
deployment.apps "mongo" deleted
service "mongo" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
```
```
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: 1. Query the list of Pods to verify that no Pods are running:
--> -->
2. 查询 Pod 列表,确认没有 Pod 在运行: 2. 查询 Pod 列表,确认没有 Pod 在运行:
```shell ```shell
kubectl get pods kubectl get pods
``` ```
<!-- <!--
The response should be this: The response should be this:
--> -->
响应应该是: 响应应该是:
```
No resources found.
```
```
No resources found in default namespace.
```
## {{% heading "whatsnext" %}} ## {{% heading "whatsnext" %}}
<!-- <!--
* Complete the [Kubernetes Basics](/docs/tutorials/kubernetes-basics/) Interactive Tutorials * 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) * 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 [connecting applications](/docs/concepts/services-networking/connect-applications-service/)
* Read more about [Managing Resources](/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively) * Read more about [Managing Resources](/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively)
--> -->
* 完成 [Kubernetes 基础](/zh/docs/tutorials/kubernetes-basics/) 交互式教程
* 完成 [Kubernetes Basics](/zh/docs/tutorials/kubernetes-basics/) 交互式教程 * 使用 Kubernetes 创建一个博客,使用
* 使用 Kubernetes 创建一个博客,使用 [MySQL 和 Wordpress 的持久卷](/zh/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/#visit-your-new-wordpress-blog) [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/services-networking/connect-applications-service/)
* 阅读更多关于[管理资源](/zh/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively) * 进一步阅读[管理资源](/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 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: frontend name: frontend
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
spec: spec:
replicas: 3
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: guestbook app: guestbook
app.kubernetes.io/component: frontend tier: frontend
replicas: 3
template: template:
metadata: metadata:
labels: labels:
app.kubernetes.io/name: guestbook app: guestbook
app.kubernetes.io/component: frontend tier: frontend
spec: spec:
containers: containers:
- name: guestbook - name: php-redis
image: paulczar/gb-frontend:v5 image: gcr.io/google_samples/gb-frontend:v5
# image: gcr.io/google-samples/gb-frontend:v4 env:
- name: GET_HOSTS_FROM
value: "dns"
resources: resources:
requests: requests:
cpu: 100m cpu: 100m
memory: 100Mi memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports: ports:
- containerPort: 80 - containerPort: 80
@@ -1,16 +1,19 @@
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: frontend name: frontend
labels: labels:
app.kubernetes.io/name: guestbook app: guestbook
app.kubernetes.io/component: frontend tier: frontend
spec: spec:
# if your cluster supports it, uncomment the following to automatically create # if your cluster supports it, uncomment the following to automatically create
# an external load-balanced IP for the frontend service. # an external load-balanced IP for the frontend service.
# type: LoadBalancer # type: LoadBalancer
#type: LoadBalancer
ports: ports:
# the port that this service should serve on
- port: 80 - port: 80
selector: selector:
app.kubernetes.io/name: guestbook app: guestbook
app.kubernetes.io/component: frontend 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/types"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
// "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps"
@@ -70,7 +69,6 @@ import (
_ "k8s.io/kubernetes/pkg/apis/networking/install" _ "k8s.io/kubernetes/pkg/apis/networking/install"
_ "k8s.io/kubernetes/pkg/apis/policy/install" _ "k8s.io/kubernetes/pkg/apis/policy/install"
_ "k8s.io/kubernetes/pkg/apis/rbac/install" _ "k8s.io/kubernetes/pkg/apis/rbac/install"
_ "k8s.io/kubernetes/pkg/apis/settings/install"
_ "k8s.io/kubernetes/pkg/apis/storage/install" _ "k8s.io/kubernetes/pkg/apis/storage/install"
) )
@@ -100,7 +98,6 @@ func (g TestGroup) Codec() runtime.Codec {
func initGroups() { func initGroups() {
Groups = make(map[string]TestGroup) Groups = make(map[string]TestGroup)
groupNames := []string{ groupNames := []string{
api.GroupName, api.GroupName,
apps.GroupName, apps.GroupName,
@@ -109,7 +106,6 @@ func initGroups() {
networking.GroupName, networking.GroupName,
policy.GroupName, policy.GroupName,
rbac.GroupName, rbac.GroupName,
settings.GroupName,
storage.GroupName, storage.GroupName,
} }
@@ -152,6 +148,19 @@ func getCodecForObject(obj runtime.Object) (runtime.Codec, error) {
} }
func validateObject(obj runtime.Object) (errors field.ErrorList) { 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 // Enable CustomPodDNS for testing
// feature.DefaultFeatureGate.Set("CustomPodDNS=true") // feature.DefaultFeatureGate.Set("CustomPodDNS=true")
switch t := obj.(type) { switch t := obj.(type) {
@@ -186,7 +195,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
opts := validation.PodValidationOptions{ opts := validation.PodValidationOptions{
AllowMultipleHugePageResources: true, AllowMultipleHugePageResources: true,
} }
errors = validation.ValidatePod(t, opts) errors = validation.ValidatePodCreate(t, opts)
case *api.PodList: case *api.PodList:
for i := range t.Items { for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...) errors = append(errors, validateObject(&t.Items[i])...)
@@ -195,12 +204,12 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = validation.ValidatePodTemplate(t) errors = validation.ValidatePodTemplate(t, podValidationOptions)
case *api.ReplicationController: case *api.ReplicationController:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = validation.ValidateReplicationController(t) errors = validation.ValidateReplicationController(t, podValidationOptions)
case *api.ReplicationControllerList: case *api.ReplicationControllerList:
for i := range t.Items { for i := range t.Items {
errors = append(errors, validateObject(&t.Items[i])...) errors = append(errors, validateObject(&t.Items[i])...)
@@ -209,7 +218,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = validation.ValidateResourceQuota(t) errors = validation.ValidateResourceQuota(t, quotaValidationOptions)
case *api.Secret: case *api.Secret:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
@@ -219,7 +228,11 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault 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: case *api.ServiceAccount:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
@@ -233,7 +246,7 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = apps_validation.ValidateStatefulSet(t) errors = apps_validation.ValidateStatefulSet(t, podValidationOptions)
case *autoscaling.HorizontalPodAutoscaler: case *autoscaling.HorizontalPodAutoscaler:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
@@ -254,12 +267,12 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = apps_validation.ValidateDaemonSet(t) errors = apps_validation.ValidateDaemonSet(t, podValidationOptions)
case *apps.Deployment: case *apps.Deployment:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = apps_validation.ValidateDeployment(t) errors = apps_validation.ValidateDeployment(t, podValidationOptions)
case *networking.Ingress: case *networking.Ingress:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
@@ -269,18 +282,30 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(networking.GroupName)[0].Version, Version: legacyscheme.Scheme.PrioritizedVersionsForGroup(networking.GroupName)[0].Version,
} }
errors = networking_validation.ValidateIngressCreate(t, gv) 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: case *policy.PodSecurityPolicy:
errors = policy_validation.ValidatePodSecurityPolicy(t) errors = policy_validation.ValidatePodSecurityPolicy(t, pspValidationOptions)
case *apps.ReplicaSet: case *apps.ReplicaSet:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = apps_validation.ValidateReplicaSet(t) errors = apps_validation.ValidateReplicaSet(t, podValidationOptions)
case *batch.CronJob: case *batch.CronJob:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = batch_validation.ValidateCronJob(t) errors = batch_validation.ValidateCronJob(t, podValidationOptions)
case *networking.NetworkPolicy: case *networking.NetworkPolicy:
if t.Namespace == "" { if t.Namespace == "" {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
@@ -291,6 +316,9 @@ func validateObject(obj runtime.Object) (errors field.ErrorList) {
t.Namespace = api.NamespaceDefault t.Namespace = api.NamespaceDefault
} }
errors = policy_validation.ValidatePodDisruptionBudget(t) errors = policy_validation.ValidatePodDisruptionBudget(t)
case *rbac.ClusterRole:
// clusterole does not accept namespace
errors = rbac_validation.ValidateClusterRole(t)
case *rbac.ClusterRoleBinding: case *rbac.ClusterRoleBinding:
// clusterolebinding does not accept namespace // clusterolebinding does not accept namespace
errors = rbac_validation.ValidateClusterRoleBinding(t) errors = rbac_validation.ValidateClusterRoleBinding(t)
@@ -418,6 +446,7 @@ func TestExampleObjectSchemas(t *testing.T) {
"storagelimits": {&api.LimitRange{}}, "storagelimits": {&api.LimitRange{}},
}, },
"admin/sched": { "admin/sched": {
"clusterrole": {&rbac.ClusterRole{}},
"my-scheduler": {&api.ServiceAccount{}, &rbac.ClusterRoleBinding{}, &rbac.ClusterRoleBinding{}, &apps.Deployment{}}, "my-scheduler": {&api.ServiceAccount{}, &rbac.ClusterRoleBinding{}, &rbac.ClusterRoleBinding{}, &apps.Deployment{}},
"pod1": {&api.Pod{}}, "pod1": {&api.Pod{}},
"pod2": {&api.Pod{}}, "pod2": {&api.Pod{}},
@@ -441,12 +470,12 @@ func TestExampleObjectSchemas(t *testing.T) {
"cassandra-statefulset": {&apps.StatefulSet{}, &storage.StorageClass{}}, "cassandra-statefulset": {&apps.StatefulSet{}, &storage.StorageClass{}},
}, },
"application/guestbook": { "application/guestbook": {
"frontend-deployment": {&apps.Deployment{}}, "frontend-deployment": {&apps.Deployment{}},
"frontend-service": {&api.Service{}}, "frontend-service": {&api.Service{}},
"redis-master-deployment": {&apps.Deployment{}}, "redis-follower-deployment": {&apps.Deployment{}},
"redis-master-service": {&api.Service{}}, "redis-follower-service": {&api.Service{}},
"redis-slave-deployment": {&apps.Deployment{}}, "redis-leader-deployment": {&apps.Deployment{}},
"redis-slave-service": {&api.Service{}}, "redis-leader-service": {&api.Service{}},
}, },
"application/hpa": { "application/hpa": {
"php-apache": {&autoscaling.HorizontalPodAutoscaler{}}, "php-apache": {&autoscaling.HorizontalPodAutoscaler{}},
@@ -456,8 +485,10 @@ func TestExampleObjectSchemas(t *testing.T) {
"nginx-svc": {&api.Service{}}, "nginx-svc": {&api.Service{}},
}, },
"application/job": { "application/job": {
"cronjob": {&batch.CronJob{}}, "cronjob": {&batch.CronJob{}},
"job-tmpl": {&batch.Job{}}, "job-tmpl": {&batch.Job{}},
"indexed-job": {&batch.Job{}},
"indexed-job-vol": {&batch.Job{}},
}, },
"application/job/rabbitmq": { "application/job/rabbitmq": {
"job": {&batch.Job{}}, "job": {&batch.Job{}},
@@ -536,13 +567,15 @@ func TestExampleObjectSchemas(t *testing.T) {
"two-container-pod": {&api.Pod{}}, "two-container-pod": {&api.Pod{}},
}, },
"pods/config": { "pods/config": {
"redis-pod": {&api.Pod{}}, "redis-pod": {&api.Pod{}},
"example-redis-config": {&api.ConfigMap{}},
}, },
"pods/inject": { "pods/inject": {
"dapi-envars-container": {&api.Pod{}}, "dapi-envars-container": {&api.Pod{}},
"dapi-envars-pod": {&api.Pod{}}, "dapi-envars-pod": {&api.Pod{}},
"dapi-volume": {&api.Pod{}}, "dapi-volume": {&api.Pod{}},
"dapi-volume-resources": {&api.Pod{}}, "dapi-volume-resources": {&api.Pod{}},
"dependent-envars": {&api.Pod{}},
"envars": {&api.Pod{}}, "envars": {&api.Pod{}},
"pod-multiple-secret-env-variable": {&api.Pod{}}, "pod-multiple-secret-env-variable": {&api.Pod{}},
"pod-secret-envFrom": {&api.Pod{}}, "pod-secret-envFrom": {&api.Pod{}},
@@ -588,10 +621,11 @@ func TestExampleObjectSchemas(t *testing.T) {
"redis": {&api.Pod{}}, "redis": {&api.Pod{}},
}, },
"policy": { "policy": {
"baseline-psp": {&policy.PodSecurityPolicy{}}, "baseline-psp": {&policy.PodSecurityPolicy{}},
"example-psp": {&policy.PodSecurityPolicy{}}, "example-psp": {&policy.PodSecurityPolicy{}},
"privileged-psp": {&policy.PodSecurityPolicy{}}, "priority-class-resourcequota": {&api.ResourceQuota{}},
"restricted-psp": {&policy.PodSecurityPolicy{}}, "privileged-psp": {&policy.PodSecurityPolicy{}},
"restricted-psp": {&policy.PodSecurityPolicy{}},
"zookeeper-pod-disruption-budget-maxunavailable": {&policy.PodDisruptionBudget{}}, "zookeeper-pod-disruption-budget-maxunavailable": {&policy.PodDisruptionBudget{}},
"zookeeper-pod-disruption-budget-minavailable": {&policy.PodDisruptionBudget{}}, "zookeeper-pod-disruption-budget-minavailable": {&policy.PodDisruptionBudget{}},
}, },
@@ -600,29 +634,42 @@ func TestExampleObjectSchemas(t *testing.T) {
"load-balancer-example": {&apps.Deployment{}}, "load-balancer-example": {&apps.Deployment{}},
}, },
"service/access": { "service/access": {
"frontend": {&api.Service{}, &apps.Deployment{}}, "backend-deployment": {&apps.Deployment{}},
"hello-application": {&apps.Deployment{}}, "backend-service": {&api.Service{}},
"hello-service": {&api.Service{}}, "frontend-deployment": {&apps.Deployment{}},
"hello": {&apps.Deployment{}}, "frontend-service": {&api.Service{}},
"hello-application": {&apps.Deployment{}},
}, },
"service/networking": { "service/networking": {
"curlpod": {&apps.Deployment{}}, "curlpod": {&apps.Deployment{}},
"custom-dns": {&api.Pod{}}, "custom-dns": {&api.Pod{}},
"dual-stack-default-svc": {&api.Service{}}, "dual-stack-default-svc": {&api.Service{}},
"dual-stack-ipv4-svc": {&api.Service{}}, "dual-stack-ipfamilies-ipv6": {&api.Service{}},
"dual-stack-ipv6-lb-svc": {&api.Service{}}, "dual-stack-ipv6-svc": {&api.Service{}},
"dual-stack-ipv6-svc": {&api.Service{}}, "dual-stack-prefer-ipv6-lb-svc": {&api.Service{}},
"hostaliases-pod": {&api.Pod{}}, "dual-stack-preferred-ipfamilies-svc": {&api.Service{}},
"ingress": {&networking.Ingress{}}, "dual-stack-preferred-svc": {&api.Service{}},
"network-policy-allow-all-egress": {&networking.NetworkPolicy{}}, "external-lb": {&networking.IngressClass{}},
"network-policy-allow-all-ingress": {&networking.NetworkPolicy{}}, "example-ingress": {&networking.Ingress{}},
"network-policy-default-deny-egress": {&networking.NetworkPolicy{}}, "hostaliases-pod": {&api.Pod{}},
"network-policy-default-deny-ingress": {&networking.NetworkPolicy{}}, "ingress-resource-backend": {&networking.Ingress{}},
"network-policy-default-deny-all": {&networking.NetworkPolicy{}}, "ingress-wildcard-host": {&networking.Ingress{}},
"nginx-policy": {&networking.NetworkPolicy{}}, "minimal-ingress": {&networking.Ingress{}},
"nginx-secure-app": {&api.Service{}, &apps.Deployment{}}, "name-virtual-host-ingress": {&networking.Ingress{}},
"nginx-svc": {&api.Service{}}, "name-virtual-host-ingress-no-third-host": {&networking.Ingress{}},
"run-my-nginx": {&apps.Deployment{}}, "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": { "windows": {
"configmap-pod": {&api.ConfigMap{}, &api.Pod{}}, "configmap-pod": {&api.ConfigMap{}, &api.Pod{}},
@@ -2,11 +2,13 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: my-service name: my-service
labels:
app: MyApp
spec: spec:
ipFamily: IPv4 ipFamilies:
- IPv6
selector: selector:
app: MyApp app: MyApp
ports: ports:
- protocol: TCP - protocol: TCP
port: 80 port: 80
targetPort: 9376
@@ -5,11 +5,12 @@ metadata:
labels: labels:
app: MyApp app: MyApp
spec: spec:
ipFamily: IPv6 ipFamilyPolicy: PreferDualStack
ipFamilies:
- IPv6
type: LoadBalancer type: LoadBalancer
selector: selector:
app: MyApp app: MyApp
ports: ports:
- protocol: TCP - protocol: TCP
port: 80 port: 80
targetPort: 9376