From c4123fe3833df55c69e6e38bf08f114e4da76962 Mon Sep 17 00:00:00 2001 From: Qiming Teng Date: Fri, 18 Jun 2021 09:31:49 +0800 Subject: [PATCH] Update zh examples with updated test case --- .../docs/tasks/network/validate-dual-stack.md | 39 +- .../stateless-application/guestbook.md | 609 +++++++++++------- .../guestbook/frontend-deployment.yaml | 27 +- .../guestbook/frontend-service.yaml | 11 +- .../guestbook/mongo-deployment.yaml | 31 - .../application/guestbook/mongo-service.yaml | 14 - .../guestbook/redis-follower-deployment.yaml | 30 + .../guestbook/redis-follower-service.yaml | 17 + .../guestbook/redis-leader-deployment.yaml | 30 + .../guestbook/redis-leader-service.yaml | 17 + .../application/job/indexed-job-vol.yaml | 27 + .../examples/application/job/indexed-job.yaml | 35 + content/zh/examples/examples_test.go | 145 +++-- ...c.yaml => dual-stack-ipfamilies-ipv6.yaml} | 6 +- ...aml => dual-stack-prefer-ipv6-lb-svc.yaml} | 5 +- 15 files changed, 664 insertions(+), 379 deletions(-) delete mode 100644 content/zh/examples/application/guestbook/mongo-deployment.yaml delete mode 100644 content/zh/examples/application/guestbook/mongo-service.yaml create mode 100644 content/zh/examples/application/guestbook/redis-follower-deployment.yaml create mode 100644 content/zh/examples/application/guestbook/redis-follower-service.yaml create mode 100644 content/zh/examples/application/guestbook/redis-leader-deployment.yaml create mode 100644 content/zh/examples/application/guestbook/redis-leader-service.yaml create mode 100644 content/zh/examples/application/job/indexed-job-vol.yaml create mode 100644 content/zh/examples/application/job/indexed-job.yaml rename content/zh/examples/service/networking/{dual-stack-ipv4-svc.yaml => dual-stack-ipfamilies-ipv6.yaml} (73%) rename content/zh/examples/service/networking/{dual-stack-ipv6-lb-svc.yaml => dual-stack-prefer-ipv6-lb-svc.yaml} (76%) diff --git a/content/zh/docs/tasks/network/validate-dual-stack.md b/content/zh/docs/tasks/network/validate-dual-stack.md index f738353f2b..b2e1ace523 100644 --- a/content/zh/docs/tasks/network/validate-dual-stack.md +++ b/content/zh/docs/tasks/network/validate-dual-stack.md @@ -64,10 +64,10 @@ There should be one IPv4 block and one IPv6 block allocated. 应该分配一个 IPv4 块和一个 IPv6 块。 -验证节点是否检测到 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 ### 验证 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" >}} ### 创建双协议栈负载均衡服务 -如果云提供商支持配置启用 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" >}} + + +检查服务: + +```shell +kubectl get svc -l app=MyApp +``` @@ -31,244 +32,350 @@ This tutorial shows you how to build and deploy a simple _(not production ready) 一个简单的_(非面向生产)的_多层 web 应用程序。本例由以下组件组成: -* 单实例 [MongoDB](https://www.mongodb.com/) 以保存留言板条目 +* 单实例 [Redis](https://www.redis.com/) 以保存留言板条目 * 多个 web 前端实例 - - - ## {{% heading "objectives" %}} - - -* 启动 Mongo 数据库。 -* 启动留言板前端。 -* 公开并查看前端服务。 -* 清理。 - - +* 启动 Redis 领导者(Leader) +* 启动两个 Redis 跟随者(Follower) +* 公开并查看前端服务 +* 清理 ## {{% heading "prerequisites" %}} - {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} - - - -## 启动 Mongo 数据库 +## 启动 Redis 数据库 -留言板应用程序使用 MongoDB 存储数据。 +留言板应用程序使用 Redis 存储数据。 -### 创建 Mongo 的 Deployment +### 创建 Redis Deployment -下面包含的清单文件指定了一个 Deployment 控制器,该控制器运行一个 MongoDB Pod 副本。 +下面包含的清单文件指定了一个 Deployment 控制器,该控制器运行一个 Redis Pod 副本。 -{{< codenew file="application/guestbook/mongo-deployment.yaml" >}} +{{< codenew file="application/guestbook/redis-leader-deployment.yaml" >}} 1. 在下载清单文件的目录中启动终端窗口。 2. 从 `mongo-deployment.yaml` 文件中应用 MongoDB Deployment: - + - ```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 + ``` 3. 查询 Pod 列表以验证 MongoDB Pod 是否正在运行: - ```shell - kubectl get pods - ``` + ```shell + kubectl get pods + ``` + + + 响应应该与此类似: + + ```shell + NAME READY STATUS RESTARTS AGE + redis-leader-fb76b4755-xjr2n 1/1 Running 0 13s + ``` - 响应应该与此类似: - - ```shell - NAME READY STATUS RESTARTS AGE - mongo-5cfd459dd4-lrcjb 1/1 Running 0 28s - ``` - - 4. 运行以下命令查看 MongoDB Deployment 中的日志: - ```shell - kubectl logs -f deployment/mongo - ``` + ```shell + kubectl logs -f deployment/redis-leader + ``` - -### 创建 MongoDB 服务 +### 创建 Redis 领导者服务 -留言板应用程序需要往 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. 使用下面的 `mongo-service.yaml` 文件创建 MongoDB 的服务: +1. 使用下面的 `redis-leader-service.yaml` 文件创建 Redis的服务: - + - ```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 + ``` -2. 查询服务列表验证 MongoDB 服务是否正在运行: +2. 查询服务列表验证 Redis 服务是否正在运行: - ```shell - kubectl get service - ``` + ```shell + kubectl get service + ``` + + + 响应应该与此类似: + + ```shell + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + kubernetes ClusterIP 10.0.0.1 443/TCP 1m + redis-leader ClusterIP 10.103.78.24 6379/TCP 16s + ``` - 响应应该与此类似: - - ```shell - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - kubernetes ClusterIP 10.0.0.1 443/TCP 1m - mongo ClusterIP 10.0.0.151 27017/TCP 8s - ``` - - {{< note >}} -这个清单文件创建了一个名为 `mongo` 的 Service,其中包含一组与前面定义的标签匹配的标签,因此服务将网络流量路由到 MongoDB Pod 上。 +这个清单文件创建了一个名为 `redis-leader` 的 Service,其中包含一组 +与前面定义的标签匹配的标签,因此服务将网络流量路由到 Redis Pod 上。 {{< /note >}} + +### 设置 Redis 跟随者 + +尽管 Redis 领导者只有一个 Pod,你可以通过添加若干 Redis 跟随者来将其配置为高可用状态, +以满足流量需求。 + +{{< codenew file="application/guestbook/redis-follower-deployment.yaml" >}} + + +1. 应用下面的 `redis-follower-deployment.yaml` 文件创建 Redis Deployment: + + + + ```shell + kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml + ``` + + +2. 通过查询 Pods 列表,验证两个 Redis 跟随者副本在运行: + + ```shell + kubectl get pods + ``` + + + 响应应该类似于这样: + + ``` + 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 + ``` + + +### 创建 Redis 跟随者服务 + +Guestbook 应用需要与 Redis 跟随者通信以读取数据。 +为了让 Redis 跟随者可被发现,你必须创建另一个 +[Service](/zh/docs/concepts/services-networking/service/)。 + +{{< codenew file="application/guestbook/redis-follower-service.yaml" >}} + + +1. 应用如下所示 `redis-follower-service.yaml` 文件中的 Redis Service: + + + + ```shell + kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml + ``` + + +2. 查询 Service 列表,验证 Redis 服务在运行: + + ```shell + kubectl get service + ``` + + + 响应应该类似于这样: + + ``` + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + kubernetes ClusterIP 10.96.0.1 443/TCP 3d19h + redis-follower ClusterIP 10.110.162.42 6379/TCP 9s + redis-leader ClusterIP 10.103.78.24 6379/TCP 6m10s + ``` + +{{< note >}} + +清单文件创建了一个名为 `redis-follower` 的 Service,该 Service +具有一些与之前所定义的标签相匹配的标签,因此该 Service 能够将网络流量 +路由到 Redis Pod 之上。 +{{< /note >}} + + ## 设置并公开留言板前端 -留言板应用程序有一个 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 的用户体验。 - -### 创建留言板前端 Deployment +### 创建 Guestbook 前端 Deployment {{< codenew file="application/guestbook/frontend-deployment.yaml" >}} -1. 从 `frontend-deployment.yaml` 应用前端 Deployment 文件: +1. 应用来自 `frontend-deployment.yaml` 文件的前端 Deployment: - + - ```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 ``` -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 + ``` - - 响应应该与此类似: + + 响应应该与此类似: - ``` - 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 + ``` - ### 创建前端服务 -应用的 `mongo` 服务只能在 Kubernetes 集群中访问,因为服务的默认类型是 +应用的 `Redis` 服务只能在 Kubernetes 集群中访问,因为服务的默认类型是 [ClusterIP](/zh/docs/concepts/services-networking/service/#publishing-services-service-types)。 `ClusterIP` 为服务指向的 Pod 集提供一个 IP 地址。这个 IP 地址只能在集群中访问。 -如果您希望访客能够访问您的留言板,您必须将前端服务配置为外部可见的,以便客户端可以从 Kubernetes 集群之外请求服务。然而即便使用了 `ClusterIP` Kubernetes 用户仍可以通过 `kubectl port-forward` 访问服务。 +如果你希望访客能够访问你的 Guestbook,你必须将前端服务配置为外部可见的, +以便客户端可以从 Kubernetes 集群之外请求服务。 +然而即便使用了 `ClusterIP`,Kubernetes 用户仍可以通过 +`kubectl port-forward` 访问服务。 {{< 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. 从 `frontend-service.yaml` 文件中应用前端服务: +1. 应用来自 `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 + ``` -2. 查询服务列表以验证前端服务正在运行: +2. 查询 Service 列表以验证前端服务正在运行: - ```shell - kubectl get services - ``` + ```shell + kubectl get services + ``` - - 响应应该与此类似: + + 响应应该与此类似: - ``` - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - frontend ClusterIP 10.0.0.112 80/TCP 6s - kubernetes ClusterIP 10.0.0.1 443/TCP 4m - mongo ClusterIP 10.0.0.151 6379/TCP 2m - ``` + ``` + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + frontend ClusterIP 10.97.28.230 80/TCP 19s + kubernetes ClusterIP 10.96.0.1 443/TCP 3d19h + redis-follower ClusterIP 10.110.162.42 6379/TCP 5m48s + redis-leader ClusterIP 10.103.78.24 6379/TCP 11m + ``` 1. 运行以下命令将本机的 `8080` 端口转发到服务的 `80` 端口。 - ```shell - kubectl port-forward svc/frontend 8080:80 - ``` + ```shell + kubectl port-forward svc/frontend 8080:80 + ``` - - 响应应该与此类似: + + 响应应该与此类似: - ``` - 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 + ``` -2. 在浏览器中加载 [http://localhost:8080](http://localhost:8080) 页面以查看留言板。 +2. 在浏览器中加载 [http://localhost:8080](http://localhost:8080) +页面以查看 Guestbook。 - ### 通过 `LoadBalancer` 查看前端服务 -如果您部署了 `frontend-service.yaml`。你需要找到 IP 地址来查看你的留言板。 +如果你部署了 `frontend-service.yaml`,需要找到用来查看 Guestbook 的 +IP 地址。 1. 运行以下命令以获取前端服务的 IP 地址。 - ```shell - kubectl get service frontend - ``` + ```shell + kubectl get service frontend + ``` - - 响应应该与此类似: + + 响应应该与此类似: - ``` - 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 + ``` -2. 复制外部 IP 地址,然后在浏览器中加载页面以查看留言板。 +2. 复制这里的外部 IP 地址,然后在浏览器中加载页面以查看留言板。 + +{{< note >}} + +尝试通过输入消息并点击 Submit 来添加一些留言板条目。 +你所输入的消息会在前端显示。这一消息表明数据被通过你 +之前所创建的 Service 添加到 Redis 存储中。 +{{< /note >}} - ## 扩展 Web 前端 -伸缩很容易是因为服务器本身被定义为使用一个 Deployment 控制器的 Service。 +你可以根据需要执行伸缩操作,这是因为服务器本身被定义为使用一个 +Deployment 控制器的 Service。 1. 运行以下命令扩展前端 Pod 的数量: - ```shell - kubectl scale deployment frontend --replicas=5 - ``` + ```shell + kubectl scale deployment frontend --replicas=5 + ``` 2. 查询 Pod 列表验证正在运行的前端 Pod 的数量: - ```shell - kubectl get pods - ``` + ```shell + kubectl get pods + ``` - - 响应应该类似于这样: + + 响应应该类似于这样: - ``` - 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 + ``` 3. 运行以下命令缩小前端 Pod 的数量: - ```shell - kubectl scale deployment frontend --replicas=2 - ``` + ```shell + kubectl scale deployment frontend --replicas=2 + ``` 4. 查询 Pod 列表验证正在运行的前端 Pod 的数量: - ```shell - kubectl get pods - ``` - - - 响应应该类似于这样: - - ``` - 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 + ``` + + 响应应该类似于这样: + ``` + 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" %}} - -删除 Deployments 和服务还会删除正在运行的 Pod。使用标签用一个命令删除多个资源。 +删除 Deployments 和服务还会删除正在运行的 Pod。 +使用标签用一个命令删除多个资源。 1. 运行以下命令以删除所有 Pod,Deployments 和 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 + ``` - - 响应应该是: - - ``` - 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 + ``` 2. 查询 Pod 列表,确认没有 Pod 在运行: - ```shell - kubectl get pods - ``` + ```shell + kubectl get pods + ``` - - 响应应该是: - - ``` - No resources found. - ``` + + 响应应该是: + ``` + No resources found in default namespace. + ``` ## {{% heading "whatsnext" %}} - - -* 完成 [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) diff --git a/content/zh/examples/application/guestbook/frontend-deployment.yaml b/content/zh/examples/application/guestbook/frontend-deployment.yaml index 613c654aa9..f97f20dab6 100644 --- a/content/zh/examples/application/guestbook/frontend-deployment.yaml +++ b/content/zh/examples/application/guestbook/frontend-deployment.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/application/guestbook/frontend-service.yaml b/content/zh/examples/application/guestbook/frontend-service.yaml index 34ad3771d7..410c6bbaf2 100644 --- a/content/zh/examples/application/guestbook/frontend-service.yaml +++ b/content/zh/examples/application/guestbook/frontend-service.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/application/guestbook/mongo-deployment.yaml b/content/zh/examples/application/guestbook/mongo-deployment.yaml deleted file mode 100644 index 04908ce25b..0000000000 --- a/content/zh/examples/application/guestbook/mongo-deployment.yaml +++ /dev/null @@ -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 diff --git a/content/zh/examples/application/guestbook/mongo-service.yaml b/content/zh/examples/application/guestbook/mongo-service.yaml deleted file mode 100644 index b9cef607bc..0000000000 --- a/content/zh/examples/application/guestbook/mongo-service.yaml +++ /dev/null @@ -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 diff --git a/content/zh/examples/application/guestbook/redis-follower-deployment.yaml b/content/zh/examples/application/guestbook/redis-follower-deployment.yaml new file mode 100644 index 0000000000..c418cf7364 --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-follower-deployment.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/application/guestbook/redis-follower-service.yaml b/content/zh/examples/application/guestbook/redis-follower-service.yaml new file mode 100644 index 0000000000..53283d35c4 --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-follower-service.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/application/guestbook/redis-leader-deployment.yaml b/content/zh/examples/application/guestbook/redis-leader-deployment.yaml new file mode 100644 index 0000000000..9c7547291c --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-leader-deployment.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/application/guestbook/redis-leader-service.yaml b/content/zh/examples/application/guestbook/redis-leader-service.yaml new file mode 100644 index 0000000000..e04cc183d0 --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-leader-service.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/application/job/indexed-job-vol.yaml b/content/zh/examples/application/job/indexed-job-vol.yaml new file mode 100644 index 0000000000..ed40e1cc44 --- /dev/null +++ b/content/zh/examples/application/job/indexed-job-vol.yaml @@ -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'] \ No newline at end of file diff --git a/content/zh/examples/application/job/indexed-job.yaml b/content/zh/examples/application/job/indexed-job.yaml new file mode 100644 index 0000000000..5b80d35264 --- /dev/null +++ b/content/zh/examples/application/job/indexed-job.yaml @@ -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: {} diff --git a/content/zh/examples/examples_test.go b/content/zh/examples/examples_test.go index db80be97fe..f868eb3d4a 100644 --- a/content/zh/examples/examples_test.go +++ b/content/zh/examples/examples_test.go @@ -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{}}, diff --git a/content/zh/examples/service/networking/dual-stack-ipv4-svc.yaml b/content/zh/examples/service/networking/dual-stack-ipfamilies-ipv6.yaml similarity index 73% rename from content/zh/examples/service/networking/dual-stack-ipv4-svc.yaml rename to content/zh/examples/service/networking/dual-stack-ipfamilies-ipv6.yaml index a875f44d6d..7c7239cae6 100644 --- a/content/zh/examples/service/networking/dual-stack-ipv4-svc.yaml +++ b/content/zh/examples/service/networking/dual-stack-ipfamilies-ipv6.yaml @@ -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 \ No newline at end of file diff --git a/content/zh/examples/service/networking/dual-stack-ipv6-lb-svc.yaml b/content/zh/examples/service/networking/dual-stack-prefer-ipv6-lb-svc.yaml similarity index 76% rename from content/zh/examples/service/networking/dual-stack-ipv6-lb-svc.yaml rename to content/zh/examples/service/networking/dual-stack-prefer-ipv6-lb-svc.yaml index 2586ec9b39..0949a75428 100644 --- a/content/zh/examples/service/networking/dual-stack-ipv6-lb-svc.yaml +++ b/content/zh/examples/service/networking/dual-stack-prefer-ipv6-lb-svc.yaml @@ -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 \ No newline at end of file