diff --git a/content/zh/docs/.gitkeep b/content/zh/docs/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/content/zh/docs/concepts/architecture/_index.md b/content/zh/docs/concepts/architecture/_index.md new file mode 100755 index 0000000000..5c12c896ab --- /dev/null +++ b/content/zh/docs/concepts/architecture/_index.md @@ -0,0 +1,4 @@ +--- +title: "Kubernetes 架构" +weight: 30 +--- \ No newline at end of file diff --git a/content/zh/docs/concepts/architecture/cloud-controller.md b/content/zh/docs/concepts/architecture/cloud-controller.md index efa9ee49db..12e343d1d8 100644 --- a/content/zh/docs/concepts/architecture/cloud-controller.md +++ b/content/zh/docs/concepts/architecture/cloud-controller.md @@ -1,175 +1,395 @@ -title: 云控制器管理器的基本概念 +--- +title: 云控制器管理器的基础概念 +content_template: templates/concept +weight: 30 +--- -## 云控制器管理器 + -云控制器管理器(CCM)这个概念创建的初衷是为了让特定的云服务供应商代码和Kubernetes核心相互独立演化。云控制器管理器与其他主要组件如Kubernetes控制器管理器,API服务器和调度程序同时运行。云控制器管理器也可以作为Kubernetes的插件启动,这种情况下,CCM运行在Kubernetes系统之上。 -云控制器管理器基于插件机制设计,允许新的云服务供应商通过插件轻松地与Kubernetes集成。目前已经有在Kubernetes上加入新的云服务供应商计划,并为云服务供应商提供从原先的旧模式迁移到新CCM模式的方案。 +{{% capture overview %}} + + + +云控制器管理器(cloud controller manager,CCM)这个概念 (不要与二进制文件混淆)创建的初衷是为了让特定的云服务供应商代码和 Kubernetes 核心相互独立演化。云控制器管理器与其他主要组件(如 Kubernetes 控制器管理器,API 服务器和调度程序)一起运行。它也可以作为 Kubernetes 的插件启动,在这种情况下,它会运行在 Kubernetes 之上。 + + + +云控制器管理器基于插件机制设计,允许新的云服务供应商通过插件轻松地与 Kubernetes 集成。目前已经有在 Kubernetes 上加入新的云服务供应商计划,并为云服务供应商提供从原先的旧模式迁移到新 CCM 模式的方案。 + + 本文讨论了云控制器管理器背后的概念,并提供了相关功能的详细信息。 -下面这张图描述了没有云控制器管理器的Kubernetes集群架构: + + +这是没有云控制器管理器的 Kubernetes 集群的架构: + + + +![没有云控制器管理器的 Kubernetes 架构](/images/docs/pre-ccm-arch.png) + +{{% /capture %}} + + +{{% capture body %}} + + -![无云控制器管理器的 K8s 集群架构](/images/docs/pre-ccm-arch.png) ## 设计 -在上图中,Kubernetes和云服务供应商通过几个不同的组件进行了集成,分别是: + + +在上图中,Kubernetes 和云服务供应商通过几个不同的组件进行了集成,分别是: + + * Kubelet * Kubernetes 控制管理器 -* Kubernetes API服务器 +* Kubernetes API 服务器 -而CCM整合了前三个组件中的所有依赖于云的逻辑,用来创建与云的单点集成。新架构如下图所示: + -![有云控制器管理器的 K8s 集群架构](/images/docs/post-ccm-arch.png) +CCM 整合了前三个组件中的所有依赖于云的逻辑,以创建与云的单一集成点。CCM 的新架构如下所示: -## CCM的组件 + -CCM突破了Kubernetes控制器管理器(KCM)的一些功能,并将其作为一个独立的进程运行。具体而言,它打破了KCM中与云相关的控制器。KCM具有以下依赖于云的控制器引擎: +![含有云控制器管理器的 Kubernetes 架构](/images/docs/post-ccm-arch.png) + + +## CCM 的组成部分 + + + +CCM 打破了 Kubernetes 控制器管理器(KCM)的一些功能,并将其作为一个单独的进程运行。具体来说,它打破了 KCM 中依赖于云的控制器。KCM 具有以下依赖于云的控制器: + + * 节点控制器 * 卷控制器 * 路由控制器 * 服务控制器 + -在1.8版本中,当前运行中的CCM从上面的列表中运行以下控制器: +在 1.9 版本中,CCM 运行前述列表中的以下控制器: + + * 节点控制器 * 路由控制器 * 服务控制器 -另外,它运行另一个名为 PersistentVolumeLabels Controller 的控制器。这个控制器负责对在GCP和AWS云里创建的PersistentVolumes的域(Zone)和区(Region)标签进行设置。 +{{< note >}} + -**注意**:卷控制器被特意设计为CCM之外的一部分。由于其中涉及到的复杂性和对现有供应商特定卷的逻辑抽象,因此决定了卷控制器不会被移动到CCM之中。 +注意卷控制器不属于 CCM,由于其中涉及到的复杂性和对现有供应商特定卷的逻辑抽象,因此决定了卷控制器不会被移动到 CCM 之中。 -原本计划使用CCM来支持卷的目的是为了引入FlexVolume卷来支持可插拔卷。然而,官方正在计划使用更具备竞争力的CSI来取代FlexVolume卷。 +{{< /note >}} -考虑到这些正在进行中的变化,我们决定暂时停止当前工作直至CSI准备就绪。 + -云服务供应商工作组(wg-cloud-provider)正在开展相关工作,以实现通过CCM支持PersistentVolume的功能。详细信息请参见[kubernetes/kubernetes#52371](https://github.com/kubernetes/kubernetes/pull/52371)。 +使用 CCM 支持 volume 的最初计划是使用 Flex volume 来支持可插拔卷,但是现在正在计划一项名为 CSI 的项目以取代 Flex。 -## CCM功能 + -CCM从Kubernetes组件中继承了与云服务供应商相关的功能。本节基于被CCM继承其功能的组件展开描述。 +考虑到这些正在进行中的变化,在 CSI 准备就绪之前,我们决定停止当前的工作。 + + + +## CCM 的功能 + + + +CCM 从依赖于云提供商的 Kubernetes 组件继承其功能,本节基于这些组件组织。 + + ### 1. Kubernetes 控制器管理器 -CCM的大部分功能都来自KCM。 如上一节所述,CCM运行以下控制引擎: + + +CCM 的大多数功能都来自 KCM,如上一节所述,CCM 运行以下控制器。 + + * 节点控制器 * 路由控制器 * 服务控制器 -* PersistentVolumeLabels控制器 + + #### 节点控制器 -节点控制器负责通过从云服务供应商获得有关在集群中运行的节点的信息来初始化节点。节点控制器执行以下功能: + -1.使用云特定域(Zone)/区(Region)标签初始化节点。 +节点控制器负责通过从云提供商获取有关在集群中运行的节点的信息来初始化节点,节点控制器执行以下功能: -1.使用特定于云的实例详细信息初始化节点,例如类型和大小。 + -1.获取节点的网络地址和主机名。 +1. 使用特定于云的域(zone)/区(region)标签初始化节点; +2. 使用特定于云的实例详细信息初始化节点,例如,类型和大小; +3. 获取节点的网络地址和主机名; +4. 如果节点无响应,请检查云以查看该节点是否已从云中删除。如果已从云中删除该节点,请删除 Kubernetes 节点对象。 -1.如果节点无响应,检查该节点是否已从云中删除。如果该节点已从云中删除,则删除Kubernetes节点对象。 + #### 路由控制器 -路由控制器负责为云配置正确的路由,以便Kubernetes集群中不同节点上的容器可以相互通信。路由控制器仅适用于Google Compute Engine平台。 + + +Route 控制器负责适当地配置云中的路由,以便 Kubernetes 集群中不同节点上的容器可以相互通信。route 控制器仅适用于 Google Compute Engine 群集。 + + #### 服务控制器 -服务控制器负责监听服务的创建、更新和删除事件。根据Kubernetes中各个服务的当前状态,它将配置云负载平衡器(如ELB或Google LB)以反映Kubernetes中的服务状态。此外,它还确保云负载均衡器的服务后端保持最新。 + -#### PersistentVolumeLabels 控制器 +服务控制器负责监听服务的创建、更新和删除事件。根据 Kubernetes 中各个服务的当前状态,它配置云负载均衡器(如 ELB 或 Google LB)以反映 Kubernetes 中的服务状态。此外,它还确保云负载均衡器的服务后端是最新的。 -PersistentVolumeLabels控制器在AWS的EBS卷、GCE的PD卷创建时申请标签,这使得用户不再需要手动设置这些卷标签。 - -这些标签对于pod的调度工作是非常重要的,因为这些卷只能在它们所在的域(Zone)/区(Region)内工作,因此所有使用这些卷的pod都必须要在同一个域/区中才能保证进行调度正常进行。 - -PersistentVolumeLabels控制器是专门为CCM创建的; 也就是说,在CCM创建之前它是不存在的。这样做是为了将Kubernetes API服务器(它是一个许可控制器)中的PV标签逻辑移动到CCM。 它不在KCM上运行。 + ### 2. Kubelet -Node控制器包含kubelet中依赖于云的功能。在系统引入CCM组件之前,是由kubelet采用包含云特定信息的方式对节点进行初始化,如IP地址、区(Region)/域(Zone)标签和实例类型信息;引入CCM之后,这部分的初始化操作就从kubelet转移到了CCM中。 + -在引入CCM后的新的模型中,kubelet采用不包含云特定信息的方式初始化一个节点。但是,它会为新创建的节点添加一个污点,使得该节点不可被立即调度,直到CCM使用包含云的特定信息初始化节点后,才会删除该污点,使得该节点可被调度。 +节点控制器包含 kubelet 中依赖于云的功能,在引入 CCM 之前,kubelet 负责使用特定于云的详细信息(如 IP 地址,域/区标签和实例类型信息)初始化节点。CCM 的引入已将此初始化操作从 kubelet 转移到 CCM 中。 -### 3. Kubernetes API服务器 + -PersistentVolumeLabels控制器将Kubernetes API服务器的依赖于云的功能移至CCM,如前面部分所述。 +在这个新模型中,kubelet 初始化一个没有特定于云的信息的节点。但是,它会为新创建的节点添加污点,使节点不可调度,直到 CCM 使用特定于云的信息初始化节点后,才会清除这种污点,便得该节点可被调度。 + + ## 插件机制 -云控制器管理器使用Go接口与外部对接从而实现功能扩展。具体来说,它使用了[这里](https://github.com/kubernetes/kubernetes/blob/master/pkg/cloudprovider/cloud.go)定义的CloudProvider接口。 + -上面强调的四个共享控制器的实现,以及一些辅助设施(scaffolding)和共享的云服务供应商接口,将被保留在Kubernetes核心当中。但云服务供应商特有的实现将会建立在核心之外,并实现核心中定义的接口。 +云控制器管理器使用 Go 接口允许插入任何云的实现。具体来说,它使用[此处](https://github.com/kubernetes/cloud-provider/blob/9b77dc1c384685cb732b3025ed5689dd597a5971/cloud.go#L42-L62)定义的 CloudProvider 接口。 -有关开发插件的更多信息,请参阅 -[开发云控制器管理器](/docs/tasks/administrators-cluster/developing-cloud-controller-manager/)。 + + +上面强调的四个共享控制器的实现,以及一些辅助设施(scaffolding)和共享的 cloudprovider 接口,将被保留在 Kubernetes 核心中。但特定于云提供商的实现将在核心之外构建,并实现核心中定义的接口。 + + + +有关开发插件的更多信息,请参阅[开发云控制器管理器](/docs/tasks/administer-cluster/developing-cloud-controller-manager/)。 + + ## 授权 -本节分解了CCM对各种API对象的访问,以执行其操作。 + + +本节分解了 CCM 执行其操作时各种 API 对象所需的访问权限。 + + ### 节点控制器 -节点控制器仅适用于节点对象。它需要完全访问权限来获取、列出、创建、更新、修补、监视和删除节点对象。 + + +Node 控制器仅适用于 Node 对象,它需要完全访问权限来获取、列出、创建、更新、修补、监视和删除 Node 对象。 + + + +v1/Node: + +- Get +- List +- Create +- Update +- Patch +- Watch +- Delete + + ### 路由控制器 -路由控制器监听节点对象的创建并配置合适的路由。它需要对节点对象的访问权限。 + + +路由控制器侦听 Node 对象创建并适当地配置路由,它需要访问 Node 对象。 + +v1/Node: -v1/Node: - Get + + ### 服务控制器 -服务控制器侦听服务对象创建、更新和删除事件,然后对这些服务的端点进行恰当的配置。 + -要访问服务,它需要罗列和监控权限。要更新服务,它需要修补和更新权限。 +服务控制器侦听 Service 对象创建、更新和删除事件,然后适当地为这些服务配置端点。 -要为服务设置端点,需要访问创建、列表、获取、监视和更新。 + + +要访问服务,它需要列表和监视访问权限。要更新服务,它需要修补和更新访问权限。 + + + +要为服务设置端点,需要访问 create、list、get、watch 和 update。 v1/Service: + - List - Get - Watch - Patch - Update -### PersistentVolumeLabels 控制器 - -PersistentVolumeLabels控制器监听PersistentVolume(PV)创建事件并更新它们。该控制器需要访问列表、查看、获取和更新PV的权限。 - -v1/PersistentVolume: -- Get -- List -- Watch -- Update + ### 其它 -CCM核心的实现需要创建事件的权限,为了确保安全操作,需要创建ServiceAccounts的权限。 + + +CCM 核心的实现需要访问权限以创建事件,并且为了确保安全操作,它需要访问权限以创建服务账户。 v1/Event: + - Create - Patch - Update v1/ServiceAccount: + - Create -针对CCM的RBAC ClusterRole如下所示: + + +针对 CCM 的 RBAC ClusterRole 看起来像这样: ```yaml apiVersion: rbac.authorization.k8s.io/v1 @@ -233,17 +453,49 @@ rules: - update ``` + + ## 供应商实施 -以下云服务供应商为自己的云部署了CCM。 + -* [Digital Ocean](https://github.com/digitalocean/digitalocean-cloud-controller-manager) -* [Oracle](https://github.com/oracle/oci-cloud-controller-manager) -* [Azure](https://github.com/kubernetes/cloud-provider-azure) -* [GCP](https://github.com/kubernetes/cloud-provider-gcp) +以下云服务提供商已实现了 CCM: + + + +* [AWS](https://github.com/kubernetes/cloud-provider-aws) +* [Azure](https://github.com/kubernetes/cloud-provider-azure) +* [BaiduCloud](https://github.com/baidu/cloud-provider-baiducloud) +* [Digital Ocean](https://github.com/digitalocean/digitalocean-cloud-controller-manager) +* [GCP](https://github.com/kubernetes/cloud-provider-gcp) +* [Linode](https://github.com/linode/linode-cloud-controller-manager) +* [OpenStack](https://github.com/kubernetes/cloud-provider-openstack) +* [Oracle](https://github.com/oracle/oci-cloud-controller-manager) + + ## 群集管理 -[这里](/docs/tasks/administer-cluster/running-cloud-controller/#cloud-controller-manager)提供了配置和运行CCM的完整说明。 + + +[这里](/docs/tasks/administer-cluster/running-cloud-controller/#cloud-controller-manager)提供了有关配置和运行 CCM 的完整说明。 + +{{% /capture %}} + diff --git a/content/zh/examples/README.md b/content/zh/examples/README.md new file mode 100644 index 0000000000..dac0f47105 --- /dev/null +++ b/content/zh/examples/README.md @@ -0,0 +1,17 @@ +注意:这些测试是从 kubernetes 导入的代码实际上并不打算在存储库之外使用。 +这就导致了供应商依赖问题。因此,我们必须在 travis 配置这些行: + + +``` +- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/apimachinery +- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/apiserver +- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/client-go +- cp -r $GOPATH/src/k8s.io/kubernetes/vendor/* $GOPATH/src/ +- rm -rf $GOPATH/src/k8s.io/kubernetes/vendor/* +- cp -r $GOPATH/src/k8s.io/kubernetes/staging/src/* $GOPATH/src/ +``` diff --git a/content/zh/examples/admin/cloud/ccm-example.yaml b/content/zh/examples/admin/cloud/ccm-example.yaml new file mode 100644 index 0000000000..4c98162a70 --- /dev/null +++ b/content/zh/examples/admin/cloud/ccm-example.yaml @@ -0,0 +1,69 @@ +# This is an example of how to setup cloud-controller-manger as a Daemonset in your cluster. +# It assumes that your masters can run pods and has the role node-role.kubernetes.io/master +# Note that this Daemonset will not work straight out of the box for your cloud, this is +# meant to be a guideline. + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cloud-controller-manager + namespace: kube-system +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: system:cloud-controller-manager +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: cloud-controller-manager + namespace: kube-system +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + k8s-app: cloud-controller-manager + name: cloud-controller-manager + namespace: kube-system +spec: + selector: + matchLabels: + k8s-app: cloud-controller-manager + template: + metadata: + labels: + k8s-app: cloud-controller-manager + spec: + serviceAccountName: cloud-controller-manager + containers: + - name: cloud-controller-manager + # for in-tree providers we use k8s.gcr.io/cloud-controller-manager + # this can be replaced with any other image for out-of-tree providers + image: k8s.gcr.io/cloud-controller-manager:v1.8.0 + command: + - /usr/local/bin/cloud-controller-manager + - --cloud-provider= # Add your own cloud provider here! + - --leader-elect=true + - --use-service-account-credentials + # these flags will vary for every cloud provider + - --allocate-node-cidrs=true + - --configure-cloud-routes=true + - --cluster-cidr=172.17.0.0/16 + tolerations: + # this is required so CCM can bootstrap itself + - key: node.cloudprovider.kubernetes.io/uninitialized + value: "true" + effect: NoSchedule + # this is to have the daemonset runnable on master nodes + # the taint may vary depending on your cluster setup + - key: node-role.kubernetes.io/master + effect: NoSchedule + # this is to restrict CCM to only run on master nodes + # the node selector may vary depending on your cluster setup + nodeSelector: + node-role.kubernetes.io/master: "" diff --git a/content/zh/examples/admin/cloud/pvl-initializer-config.yaml b/content/zh/examples/admin/cloud/pvl-initializer-config.yaml new file mode 100644 index 0000000000..4a2576cc2a --- /dev/null +++ b/content/zh/examples/admin/cloud/pvl-initializer-config.yaml @@ -0,0 +1,13 @@ +kind: InitializerConfiguration +apiVersion: admissionregistration.k8s.io/v1alpha1 +metadata: + name: pvlabel.kubernetes.io +initializers: + - name: pvlabel.kubernetes.io + rules: + - apiGroups: + - "" + apiVersions: + - "*" + resources: + - persistentvolumes diff --git a/content/zh/examples/admin/dns/busybox.yaml b/content/zh/examples/admin/dns/busybox.yaml new file mode 100644 index 0000000000..31f009d307 --- /dev/null +++ b/content/zh/examples/admin/dns/busybox.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: busybox + namespace: default +spec: + containers: + - name: busybox + image: busybox:1.28 + command: + - sleep + - "3600" + imagePullPolicy: IfNotPresent + restartPolicy: Always diff --git a/content/zh/examples/admin/dns/dns-horizontal-autoscaler.yaml b/content/zh/examples/admin/dns/dns-horizontal-autoscaler.yaml new file mode 100644 index 0000000000..5e6d55a6b2 --- /dev/null +++ b/content/zh/examples/admin/dns/dns-horizontal-autoscaler.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dns-autoscaler + namespace: kube-system + labels: + k8s-app: dns-autoscaler +spec: + selector: + matchLabels: + k8s-app: dns-autoscaler + template: + metadata: + labels: + k8s-app: dns-autoscaler + spec: + containers: + - name: autoscaler + image: k8s.gcr.io/cluster-proportional-autoscaler-amd64:1.1.1 + resources: + requests: + cpu: "20m" + memory: "10Mi" + command: + - /cluster-proportional-autoscaler + - --namespace=kube-system + - --configmap=dns-autoscaler + - --target= + # When cluster is using large nodes(with more cores), "coresPerReplica" should dominate. + # If using small nodes, "nodesPerReplica" should dominate. + - --default-params={"linear":{"coresPerReplica":256,"nodesPerReplica":16,"min":1}} + - --logtostderr=true + - --v=2 diff --git a/content/zh/examples/admin/namespace-dev.json b/content/zh/examples/admin/namespace-dev.json new file mode 100644 index 0000000000..b2b43b0b73 --- /dev/null +++ b/content/zh/examples/admin/namespace-dev.json @@ -0,0 +1,10 @@ +{ + "kind": "Namespace", + "apiVersion": "v1", + "metadata": { + "name": "development", + "labels": { + "name": "development" + } + } +} diff --git a/content/zh/examples/admin/namespace-prod.json b/content/zh/examples/admin/namespace-prod.json new file mode 100644 index 0000000000..d4503f1ac1 --- /dev/null +++ b/content/zh/examples/admin/namespace-prod.json @@ -0,0 +1,10 @@ +{ + "kind": "Namespace", + "apiVersion": "v1", + "metadata": { + "name": "production", + "labels": { + "name": "production" + } + } +} diff --git a/content/zh/examples/admin/resource/quota-objects-pvc-2.yaml b/content/zh/examples/admin/resource/quota-objects-pvc-2.yaml new file mode 100644 index 0000000000..88c165d144 --- /dev/null +++ b/content/zh/examples/admin/resource/quota-objects-pvc-2.yaml @@ -0,0 +1,11 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvc-quota-demo-2 +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 4Gi diff --git a/content/zh/examples/admin/resource/quota-objects-pvc.yaml b/content/zh/examples/admin/resource/quota-objects-pvc.yaml new file mode 100644 index 0000000000..b38256b897 --- /dev/null +++ b/content/zh/examples/admin/resource/quota-objects-pvc.yaml @@ -0,0 +1,11 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvc-quota-demo +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi diff --git a/content/zh/examples/admin/resource/quota-objects.yaml b/content/zh/examples/admin/resource/quota-objects.yaml new file mode 100644 index 0000000000..e97748decd --- /dev/null +++ b/content/zh/examples/admin/resource/quota-objects.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: object-quota-demo +spec: + hard: + persistentvolumeclaims: "1" + services.loadbalancers: "2" + services.nodeports: "0" diff --git a/content/zh/examples/admin/resource/quota-pod-deployment.yaml b/content/zh/examples/admin/resource/quota-pod-deployment.yaml new file mode 100644 index 0000000000..86e85aa468 --- /dev/null +++ b/content/zh/examples/admin/resource/quota-pod-deployment.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pod-quota-demo +spec: + selector: + matchLabels: + purpose: quota-demo + replicas: 3 + template: + metadata: + labels: + purpose: quota-demo + spec: + containers: + - name: pod-quota-demo + image: nginx diff --git a/content/zh/examples/admin/resource/quota-pod.yaml b/content/zh/examples/admin/resource/quota-pod.yaml new file mode 100644 index 0000000000..0a07f055ca --- /dev/null +++ b/content/zh/examples/admin/resource/quota-pod.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: pod-demo +spec: + hard: + pods: "2" diff --git a/content/zh/examples/admin/sched/my-scheduler.yaml b/content/zh/examples/admin/sched/my-scheduler.yaml new file mode 100644 index 0000000000..ab0c385cd6 --- /dev/null +++ b/content/zh/examples/admin/sched/my-scheduler.yaml @@ -0,0 +1,67 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: my-scheduler + namespace: kube-system +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: my-scheduler-as-kube-scheduler +subjects: +- kind: ServiceAccount + name: my-scheduler + namespace: kube-system +roleRef: + kind: ClusterRole + name: kube-scheduler + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + component: scheduler + tier: control-plane + name: my-scheduler + namespace: kube-system +spec: + selector: + matchLabels: + component: scheduler + tier: control-plane + replicas: 1 + template: + metadata: + labels: + component: scheduler + tier: control-plane + version: second + spec: + serviceAccountName: my-scheduler + containers: + - command: + - /usr/local/bin/kube-scheduler + - --address=0.0.0.0 + - --leader-elect=false + - --scheduler-name=my-scheduler + image: gcr.io/my-gcp-project/my-kube-scheduler:1.0 + livenessProbe: + httpGet: + path: /healthz + port: 10251 + initialDelaySeconds: 15 + name: kube-second-scheduler + readinessProbe: + httpGet: + path: /healthz + port: 10251 + resources: + requests: + cpu: '0.1' + securityContext: + privileged: false + volumeMounts: [] + hostNetwork: false + hostPID: false + volumes: [] diff --git a/content/zh/examples/admin/sched/pod1.yaml b/content/zh/examples/admin/sched/pod1.yaml new file mode 100644 index 0000000000..560b6aa0fb --- /dev/null +++ b/content/zh/examples/admin/sched/pod1.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: no-annotation + labels: + name: multischeduler-example +spec: + containers: + - name: pod-with-no-annotation-container + image: k8s.gcr.io/pause:2.0 \ No newline at end of file diff --git a/content/zh/examples/admin/sched/pod2.yaml b/content/zh/examples/admin/sched/pod2.yaml new file mode 100644 index 0000000000..2f065efe65 --- /dev/null +++ b/content/zh/examples/admin/sched/pod2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: annotation-default-scheduler + labels: + name: multischeduler-example +spec: + schedulerName: default-scheduler + containers: + - name: pod-with-default-annotation-container + image: k8s.gcr.io/pause:2.0 diff --git a/content/zh/examples/admin/sched/pod3.yaml b/content/zh/examples/admin/sched/pod3.yaml new file mode 100644 index 0000000000..a1b8db3200 --- /dev/null +++ b/content/zh/examples/admin/sched/pod3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: annotation-second-scheduler + labels: + name: multischeduler-example +spec: + schedulerName: my-scheduler + containers: + - name: pod-with-second-annotation-container + image: k8s.gcr.io/pause:2.0 diff --git a/content/zh/examples/application/cassandra/cassandra-service.yaml b/content/zh/examples/application/cassandra/cassandra-service.yaml new file mode 100644 index 0000000000..31bee74b58 --- /dev/null +++ b/content/zh/examples/application/cassandra/cassandra-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: cassandra + name: cassandra +spec: + clusterIP: None + ports: + - port: 9042 + selector: + app: cassandra diff --git a/content/zh/examples/application/cassandra/cassandra-statefulset.yaml b/content/zh/examples/application/cassandra/cassandra-statefulset.yaml new file mode 100644 index 0000000000..a7bdbedc9c --- /dev/null +++ b/content/zh/examples/application/cassandra/cassandra-statefulset.yaml @@ -0,0 +1,100 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: cassandra + labels: + app: cassandra +spec: + serviceName: cassandra + replicas: 3 + selector: + matchLabels: + app: cassandra + template: + metadata: + labels: + app: cassandra + spec: + terminationGracePeriodSeconds: 1800 + containers: + - name: cassandra + image: gcr.io/google-samples/cassandra:v13 + imagePullPolicy: Always + ports: + - containerPort: 7000 + name: intra-node + - containerPort: 7001 + name: tls-intra-node + - containerPort: 7199 + name: jmx + - containerPort: 9042 + name: cql + resources: + limits: + cpu: "500m" + memory: 1Gi + requests: + cpu: "500m" + memory: 1Gi + securityContext: + capabilities: + add: + - IPC_LOCK + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - nodetool drain + env: + - name: MAX_HEAP_SIZE + value: 512M + - name: HEAP_NEWSIZE + value: 100M + - name: CASSANDRA_SEEDS + value: "cassandra-0.cassandra.default.svc.cluster.local" + - name: CASSANDRA_CLUSTER_NAME + value: "K8Demo" + - name: CASSANDRA_DC + value: "DC1-K8Demo" + - name: CASSANDRA_RACK + value: "Rack1-K8Demo" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + readinessProbe: + exec: + command: + - /bin/bash + - -c + - /ready-probe.sh + initialDelaySeconds: 15 + timeoutSeconds: 5 + # These volume mounts are persistent. They are like inline claims, + # but not exactly because the names need to match exactly one of + # the stateful pod volumes. + volumeMounts: + - name: cassandra-data + mountPath: /cassandra_data + # These are converted to volume claims by the controller + # and mounted at the paths mentioned above. + # do not use these in production until ssd GCEPersistentDisk or other ssd pd + volumeClaimTemplates: + - metadata: + name: cassandra-data + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: fast + resources: + requests: + storage: 1Gi +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: fast +provisioner: k8s.io/minikube-hostpath +parameters: + type: pd-ssd diff --git a/content/zh/examples/application/deployment-patch.yaml b/content/zh/examples/application/deployment-patch.yaml new file mode 100644 index 0000000000..7b32e2fcae --- /dev/null +++ b/content/zh/examples/application/deployment-patch.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: patch-demo +spec: + replicas: 2 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: patch-demo-ctr + image: nginx + tolerations: + - effect: NoSchedule + key: dedicated + value: test-team diff --git a/content/zh/examples/application/deployment-scale.yaml b/content/zh/examples/application/deployment-scale.yaml new file mode 100644 index 0000000000..3bdc7b6f5b --- /dev/null +++ b/content/zh/examples/application/deployment-scale.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 4 # Update the replicas from 2 to 4 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.8 + ports: + - containerPort: 80 diff --git a/content/zh/examples/application/deployment-update.yaml b/content/zh/examples/application/deployment-update.yaml new file mode 100644 index 0000000000..8c683d6dc7 --- /dev/null +++ b/content/zh/examples/application/deployment-update.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 2 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.8 # Update the version of nginx from 1.7.9 to 1.8 + ports: + - containerPort: 80 diff --git a/content/zh/examples/application/deployment.yaml b/content/zh/examples/application/deployment.yaml new file mode 100644 index 0000000000..0f526b16c0 --- /dev/null +++ b/content/zh/examples/application/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 2 # tells deployment to run 2 pods matching the template + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 diff --git a/content/zh/examples/application/guestbook/frontend-deployment.yaml b/content/zh/examples/application/guestbook/frontend-deployment.yaml new file mode 100644 index 0000000000..50d6e1f0d4 --- /dev/null +++ b/content/zh/examples/application/guestbook/frontend-deployment.yaml @@ -0,0 +1,38 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: frontend + labels: + app: guestbook +spec: + selector: + matchLabels: + app: guestbook + tier: frontend + replicas: 3 + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: gcr.io/google-samples/gb-frontend:v4 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # Using `GET_HOSTS_FROM=dns` requires your cluster to + # provide a dns service. As of Kubernetes 1.3, DNS is a built-in + # service launched automatically. However, if the cluster you are using + # does not have a built-in DNS service, you can instead + # access an environment variable to find the master + # service's host. To do so, comment out the 'value: dns' line above, and + # uncomment the line below: + # value: env + ports: + - containerPort: 80 diff --git a/content/zh/examples/application/guestbook/frontend-service.yaml b/content/zh/examples/application/guestbook/frontend-service.yaml new file mode 100644 index 0000000000..6f283f347b --- /dev/null +++ b/content/zh/examples/application/guestbook/frontend-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: guestbook + tier: frontend +spec: + # comment or delete the following line if you want to use a LoadBalancer + type: NodePort + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + ports: + - port: 80 + selector: + app: guestbook + tier: frontend diff --git a/content/zh/examples/application/guestbook/redis-master-deployment.yaml b/content/zh/examples/application/guestbook/redis-master-deployment.yaml new file mode 100644 index 0000000000..fc6f418c39 --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-master-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: redis-master + labels: + app: redis +spec: + selector: + matchLabels: + app: redis + role: master + tier: backend + replicas: 1 + template: + metadata: + labels: + app: redis + role: master + tier: backend + spec: + containers: + - name: master + image: k8s.gcr.io/redis:e2e # or just image: redis + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 diff --git a/content/zh/examples/application/guestbook/redis-master-service.yaml b/content/zh/examples/application/guestbook/redis-master-service.yaml new file mode 100644 index 0000000000..a484014f1f --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-master-service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis-master + labels: + app: redis + role: master + tier: backend +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: redis + role: master + tier: backend diff --git a/content/zh/examples/application/guestbook/redis-slave-deployment.yaml b/content/zh/examples/application/guestbook/redis-slave-deployment.yaml new file mode 100644 index 0000000000..ec4e48bc21 --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-slave-deployment.yaml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: redis-slave + labels: + app: redis +spec: + selector: + matchLabels: + app: redis + role: slave + tier: backend + replicas: 2 + template: + metadata: + labels: + app: redis + role: slave + tier: backend + spec: + containers: + - name: slave + image: gcr.io/google_samples/gb-redisslave:v1 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # Using `GET_HOSTS_FROM=dns` requires your cluster to + # provide a dns service. As of Kubernetes 1.3, DNS is a built-in + # service launched automatically. However, if the cluster you are using + # does not have a built-in DNS service, you can instead + # access an environment variable to find the master + # service's host. To do so, comment out the 'value: dns' line above, and + # uncomment the line below: + # value: env + ports: + - containerPort: 6379 diff --git a/content/zh/examples/application/guestbook/redis-slave-service.yaml b/content/zh/examples/application/guestbook/redis-slave-service.yaml new file mode 100644 index 0000000000..238fd63fb6 --- /dev/null +++ b/content/zh/examples/application/guestbook/redis-slave-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis-slave + labels: + app: redis + role: slave + tier: backend +spec: + ports: + - port: 6379 + selector: + app: redis + role: slave + tier: backend diff --git a/content/zh/examples/application/hpa/php-apache.yaml b/content/zh/examples/application/hpa/php-apache.yaml new file mode 100644 index 0000000000..c73ae7d631 --- /dev/null +++ b/content/zh/examples/application/hpa/php-apache.yaml @@ -0,0 +1,13 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: php-apache + namespace: default +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: php-apache + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 50 diff --git a/content/zh/examples/application/job/job-tmpl.yaml b/content/zh/examples/application/job/job-tmpl.yaml new file mode 100644 index 0000000000..790025b38b --- /dev/null +++ b/content/zh/examples/application/job/job-tmpl.yaml @@ -0,0 +1,18 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: process-item-$ITEM + labels: + jobgroup: jobexample +spec: + template: + metadata: + name: jobexample + labels: + jobgroup: jobexample + spec: + containers: + - name: c + image: busybox + command: ["sh", "-c", "echo Processing item $ITEM && sleep 5"] + restartPolicy: Never diff --git a/content/zh/examples/application/job/job.yaml b/content/zh/examples/application/job/job.yaml new file mode 100644 index 0000000000..4e1a61892b --- /dev/null +++ b/content/zh/examples/application/job/job.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: job-wq-1 +spec: + completions: 8 + parallelism: 2 + template: + metadata: + name: job-wq-1 + spec: + containers: + - name: c + image: gcr.io//job-wq-1 + env: + - name: BROKER_URL + value: amqp://guest:guest@rabbitmq-service:5672 + - name: QUEUE + value: job1 + restartPolicy: OnFailure diff --git a/content/zh/examples/application/job/rabbitmq/Dockerfile b/content/zh/examples/application/job/rabbitmq/Dockerfile new file mode 100644 index 0000000000..cbd36bb620 --- /dev/null +++ b/content/zh/examples/application/job/rabbitmq/Dockerfile @@ -0,0 +1,10 @@ +# Specify BROKER_URL and QUEUE when running +FROM ubuntu:14.04 + +RUN apt-get update && \ + apt-get install -y curl ca-certificates amqp-tools python \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* +COPY ./worker.py /worker.py + +CMD /usr/bin/amqp-consume --url=$BROKER_URL -q $QUEUE -c 1 /worker.py diff --git a/content/zh/examples/application/job/rabbitmq/job.yaml b/content/zh/examples/application/job/rabbitmq/job.yaml new file mode 100644 index 0000000000..4e1a61892b --- /dev/null +++ b/content/zh/examples/application/job/rabbitmq/job.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: job-wq-1 +spec: + completions: 8 + parallelism: 2 + template: + metadata: + name: job-wq-1 + spec: + containers: + - name: c + image: gcr.io//job-wq-1 + env: + - name: BROKER_URL + value: amqp://guest:guest@rabbitmq-service:5672 + - name: QUEUE + value: job1 + restartPolicy: OnFailure diff --git a/content/zh/examples/application/job/rabbitmq/worker.py b/content/zh/examples/application/job/rabbitmq/worker.py new file mode 100644 index 0000000000..a20884515d --- /dev/null +++ b/content/zh/examples/application/job/rabbitmq/worker.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +# Just prints standard out and sleeps for 10 seconds. +import sys +import time +print("Processing " + sys.stdin.lines()) +time.sleep(10) diff --git a/content/zh/examples/application/job/redis/Dockerfile b/content/zh/examples/application/job/redis/Dockerfile new file mode 100644 index 0000000000..2de23b3c98 --- /dev/null +++ b/content/zh/examples/application/job/redis/Dockerfile @@ -0,0 +1,6 @@ +FROM python +RUN pip install redis +COPY ./worker.py /worker.py +COPY ./rediswq.py /rediswq.py + +CMD python worker.py diff --git a/content/zh/examples/application/job/redis/redis-pod.yaml b/content/zh/examples/application/job/redis/redis-pod.yaml new file mode 100644 index 0000000000..ae0c43a793 --- /dev/null +++ b/content/zh/examples/application/job/redis/redis-pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis-master + labels: + app: redis +spec: + containers: + - name: master + image: redis + env: + - name: MASTER + value: "true" + ports: + - containerPort: 6379 diff --git a/content/zh/examples/application/job/redis/redis-service.yaml b/content/zh/examples/application/job/redis/redis-service.yaml new file mode 100644 index 0000000000..85f2ca2271 --- /dev/null +++ b/content/zh/examples/application/job/redis/redis-service.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: redis diff --git a/content/zh/examples/application/job/redis/rediswq.py b/content/zh/examples/application/job/redis/rediswq.py new file mode 100644 index 0000000000..ceda8bd1e3 --- /dev/null +++ b/content/zh/examples/application/job/redis/rediswq.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python + +# Based on http://peter-hoffmann.com/2012/python-simple-queue-redis-queue.html +# and the suggestion in the redis documentation for RPOPLPUSH, at +# http://redis.io/commands/rpoplpush, which suggests how to implement a work-queue. + + +import redis +import uuid +import hashlib + +class RedisWQ(object): + """Simple Finite Work Queue with Redis Backend + + This work queue is finite: as long as no more work is added + after workers start, the workers can detect when the queue + is completely empty. + + The items in the work queue are assumed to have unique values. + + This object is not intended to be used by multiple threads + concurrently. + """ + def __init__(self, name, **redis_kwargs): + """The default connection parameters are: host='localhost', port=6379, db=0 + + The work queue is identified by "name". The library may create other + keys with "name" as a prefix. + """ + self._db = redis.StrictRedis(**redis_kwargs) + # The session ID will uniquely identify this "worker". + self._session = str(uuid.uuid4()) + # Work queue is implemented as two queues: main, and processing. + # Work is initially in main, and moved to processing when a client picks it up. + self._main_q_key = name + self._processing_q_key = name + ":processing" + self._lease_key_prefix = name + ":leased_by_session:" + + def sessionID(self): + """Return the ID for this session.""" + return self._session + + def _main_qsize(self): + """Return the size of the main queue.""" + return self._db.llen(self._main_q_key) + + def _processing_qsize(self): + """Return the size of the main queue.""" + return self._db.llen(self._processing_q_key) + + def empty(self): + """Return True if the queue is empty, including work being done, False otherwise. + + False does not necessarily mean that there is work available to work on right now, + """ + return self._main_qsize() == 0 and self._processing_qsize() == 0 + +# TODO: implement this +# def check_expired_leases(self): +# """Return to the work queueReturn True if the queue is empty, False otherwise.""" +# # Processing list should not be _too_ long since it is approximately as long +# # as the number of active and recently active workers. +# processing = self._db.lrange(self._processing_q_key, 0, -1) +# for item in processing: +# # If the lease key is not present for an item (it expired or was +# # never created because the client crashed before creating it) +# # then move the item back to the main queue so others can work on it. +# if not self._lease_exists(item): +# TODO: transactionally move the key from processing queue to +# to main queue, while detecting if a new lease is created +# or if either queue is modified. + + def _itemkey(self, item): + """Returns a string that uniquely identifies an item (bytes).""" + return hashlib.sha224(item).hexdigest() + + def _lease_exists(self, item): + """True if a lease on 'item' exists.""" + return self._db.exists(self._lease_key_prefix + self._itemkey(item)) + + def lease(self, lease_secs=60, block=True, timeout=None): + """Begin working on an item the work queue. + + Lease the item for lease_secs. After that time, other + workers may consider this client to have crashed or stalled + and pick up the item instead. + + If optional args block is true and timeout is None (the default), block + if necessary until an item is available.""" + if block: + item = self._db.brpoplpush(self._main_q_key, self._processing_q_key, timeout=timeout) + else: + item = self._db.rpoplpush(self._main_q_key, self._processing_q_key) + if item: + # Record that we (this session id) are working on a key. Expire that + # note after the lease timeout. + # Note: if we crash at this line of the program, then GC will see no lease + # for this item a later return it to the main queue. + itemkey = self._itemkey(item) + self._db.setex(self._lease_key_prefix + itemkey, lease_secs, self._session) + return item + + def complete(self, value): + """Complete working on the item with 'value'. + + If the lease expired, the item may not have completed, and some + other worker may have picked it up. There is no indication + of what happened. + """ + self._db.lrem(self._processing_q_key, 0, value) + # If we crash here, then the GC code will try to move the value, but it will + # not be here, which is fine. So this does not need to be a transaction. + itemkey = self._itemkey(value) + self._db.delete(self._lease_key_prefix + itemkey, self._session) + +# TODO: add functions to clean up all keys associated with "name" when +# processing is complete. + +# TODO: add a function to add an item to the queue. Atomically +# check if the queue is empty and if so fail to add the item +# since other workers might think work is done and be in the process +# of exiting. + +# TODO(etune): move to my own github for hosting, e.g. github.com/erictune/rediswq-py and +# make it so it can be pip installed by anyone (see +# http://stackoverflow.com/questions/8247605/configuring-so-that-pip-install-can-work-from-github) + +# TODO(etune): finish code to GC expired leases, and call periodically +# e.g. each time lease times out. + diff --git a/content/zh/examples/application/job/worker.py b/content/zh/examples/application/job/worker.py new file mode 100644 index 0000000000..a20884515d --- /dev/null +++ b/content/zh/examples/application/job/worker.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +# Just prints standard out and sleeps for 10 seconds. +import sys +import time +print("Processing " + sys.stdin.lines()) +time.sleep(10) diff --git a/content/zh/examples/application/mysql/mysql-configmap.yaml b/content/zh/examples/application/mysql/mysql-configmap.yaml new file mode 100644 index 0000000000..46d34e422c --- /dev/null +++ b/content/zh/examples/application/mysql/mysql-configmap.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql + labels: + app: mysql +data: + master.cnf: | + # Apply this config only on the master. + [mysqld] + log-bin + slave.cnf: | + # Apply this config only on slaves. + [mysqld] + super-read-only + diff --git a/content/zh/examples/application/mysql/mysql-deployment.yaml b/content/zh/examples/application/mysql/mysql-deployment.yaml new file mode 100644 index 0000000000..518457777e --- /dev/null +++ b/content/zh/examples/application/mysql/mysql-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: Service +metadata: + name: mysql +spec: + ports: + - port: 3306 + selector: + app: mysql + clusterIP: None +--- +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: mysql +spec: + selector: + matchLabels: + app: mysql + strategy: + type: Recreate + template: + metadata: + labels: + app: mysql + spec: + containers: + - image: mysql:5.6 + name: mysql + env: + # Use secret in real usage + - name: MYSQL_ROOT_PASSWORD + value: password + ports: + - containerPort: 3306 + name: mysql + volumeMounts: + - name: mysql-persistent-storage + mountPath: /var/lib/mysql + volumes: + - name: mysql-persistent-storage + persistentVolumeClaim: + claimName: mysql-pv-claim diff --git a/content/zh/examples/application/mysql/mysql-pv.yaml b/content/zh/examples/application/mysql/mysql-pv.yaml new file mode 100644 index 0000000000..6f4e692f3b --- /dev/null +++ b/content/zh/examples/application/mysql/mysql-pv.yaml @@ -0,0 +1,26 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: mysql-pv-volume + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 20Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data" +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pv-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi diff --git a/content/zh/examples/application/mysql/mysql-services.yaml b/content/zh/examples/application/mysql/mysql-services.yaml new file mode 100644 index 0000000000..f538992566 --- /dev/null +++ b/content/zh/examples/application/mysql/mysql-services.yaml @@ -0,0 +1,30 @@ +# Headless service for stable DNS entries of StatefulSet members. +apiVersion: v1 +kind: Service +metadata: + name: mysql + labels: + app: mysql +spec: + ports: + - name: mysql + port: 3306 + clusterIP: None + selector: + app: mysql +--- +# Client service for connecting to any MySQL instance for reads. +# For writes, you must instead connect to the master: mysql-0.mysql. +apiVersion: v1 +kind: Service +metadata: + name: mysql-read + labels: + app: mysql +spec: + ports: + - name: mysql + port: 3306 + selector: + app: mysql + diff --git a/content/zh/examples/application/mysql/mysql-statefulset.yaml b/content/zh/examples/application/mysql/mysql-statefulset.yaml new file mode 100644 index 0000000000..e0c04007a8 --- /dev/null +++ b/content/zh/examples/application/mysql/mysql-statefulset.yaml @@ -0,0 +1,167 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mysql +spec: + selector: + matchLabels: + app: mysql + serviceName: mysql + replicas: 3 + template: + metadata: + labels: + app: mysql + spec: + initContainers: + - name: init-mysql + image: mysql:5.7 + command: + - bash + - "-c" + - | + set -ex + # Generate mysql server-id from pod ordinal index. + [[ `hostname` =~ -([0-9]+)$ ]] || exit 1 + ordinal=${BASH_REMATCH[1]} + echo [mysqld] > /mnt/conf.d/server-id.cnf + # Add an offset to avoid reserved server-id=0 value. + echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf + # Copy appropriate conf.d files from config-map to emptyDir. + if [[ $ordinal -eq 0 ]]; then + cp /mnt/config-map/master.cnf /mnt/conf.d/ + else + cp /mnt/config-map/slave.cnf /mnt/conf.d/ + fi + volumeMounts: + - name: conf + mountPath: /mnt/conf.d + - name: config-map + mountPath: /mnt/config-map + - name: clone-mysql + image: gcr.io/google-samples/xtrabackup:1.0 + command: + - bash + - "-c" + - | + set -ex + # Skip the clone if data already exists. + [[ -d /var/lib/mysql/mysql ]] && exit 0 + # Skip the clone on master (ordinal index 0). + [[ `hostname` =~ -([0-9]+)$ ]] || exit 1 + ordinal=${BASH_REMATCH[1]} + [[ $ordinal -eq 0 ]] && exit 0 + # Clone data from previous peer. + ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql + # Prepare the backup. + xtrabackup --prepare --target-dir=/var/lib/mysql + volumeMounts: + - name: data + mountPath: /var/lib/mysql + subPath: mysql + - name: conf + mountPath: /etc/mysql/conf.d + containers: + - name: mysql + image: mysql:5.7 + env: + - name: MYSQL_ALLOW_EMPTY_PASSWORD + value: "1" + ports: + - name: mysql + containerPort: 3306 + volumeMounts: + - name: data + mountPath: /var/lib/mysql + subPath: mysql + - name: conf + mountPath: /etc/mysql/conf.d + resources: + requests: + cpu: 500m + memory: 1Gi + livenessProbe: + exec: + command: ["mysqladmin", "ping"] + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + exec: + # Check we can execute queries over TCP (skip-networking is off). + command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"] + initialDelaySeconds: 5 + periodSeconds: 2 + timeoutSeconds: 1 + - name: xtrabackup + image: gcr.io/google-samples/xtrabackup:1.0 + ports: + - name: xtrabackup + containerPort: 3307 + command: + - bash + - "-c" + - | + set -ex + cd /var/lib/mysql + + # Determine binlog position of cloned data, if any. + if [[ -f xtrabackup_slave_info ]]; then + # XtraBackup already generated a partial "CHANGE MASTER TO" query + # because we're cloning from an existing slave. + mv xtrabackup_slave_info change_master_to.sql.in + # Ignore xtrabackup_binlog_info in this case (it's useless). + rm -f xtrabackup_binlog_info + elif [[ -f xtrabackup_binlog_info ]]; then + # We're cloning directly from master. Parse binlog position. + [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1 + rm xtrabackup_binlog_info + echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\ + MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in + fi + + # Check if we need to complete a clone by starting replication. + if [[ -f change_master_to.sql.in ]]; then + echo "Waiting for mysqld to be ready (accepting connections)" + until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done + + echo "Initializing replication from clone position" + # In case of container restart, attempt this at-most-once. + mv change_master_to.sql.in change_master_to.sql.orig + mysql -h 127.0.0.1 < + imagePullSecrets: + - name: regcred + diff --git a/content/zh/examples/pods/probe/exec-liveness.yaml b/content/zh/examples/pods/probe/exec-liveness.yaml new file mode 100644 index 0000000000..07bf75f85c --- /dev/null +++ b/content/zh/examples/pods/probe/exec-liveness.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + test: liveness + name: liveness-exec +spec: + containers: + - name: liveness + image: k8s.gcr.io/busybox + args: + - /bin/sh + - -c + - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 + livenessProbe: + exec: + command: + - cat + - /tmp/healthy + initialDelaySeconds: 5 + periodSeconds: 5 diff --git a/content/zh/examples/pods/probe/http-liveness.yaml b/content/zh/examples/pods/probe/http-liveness.yaml new file mode 100644 index 0000000000..23d37b480a --- /dev/null +++ b/content/zh/examples/pods/probe/http-liveness.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + labels: + test: liveness + name: liveness-http +spec: + containers: + - name: liveness + image: k8s.gcr.io/liveness + args: + - /server + livenessProbe: + httpGet: + path: /healthz + port: 8080 + httpHeaders: + - name: X-Custom-Header + value: Awesome + initialDelaySeconds: 3 + periodSeconds: 3 diff --git a/content/zh/examples/pods/probe/pod-with-http-healthcheck.yaml b/content/zh/examples/pods/probe/pod-with-http-healthcheck.yaml new file mode 100644 index 0000000000..3f40854e92 --- /dev/null +++ b/content/zh/examples/pods/probe/pod-with-http-healthcheck.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: pod-with-http-healthcheck +spec: + containers: + - name: nginx + image: nginx + # defines the health checking + livenessProbe: + # an http probe + httpGet: + path: /_status/healthz + port: 80 + # length of time to wait for a pod to initialize + # after pod startup, before applying health checking + initialDelaySeconds: 30 + timeoutSeconds: 1 + ports: + - containerPort: 80 diff --git a/content/zh/examples/pods/probe/pod-with-tcp-socket-healthcheck.yaml b/content/zh/examples/pods/probe/pod-with-tcp-socket-healthcheck.yaml new file mode 100644 index 0000000000..5f0bca283c --- /dev/null +++ b/content/zh/examples/pods/probe/pod-with-tcp-socket-healthcheck.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: pod-with-tcp-socket-healthcheck +spec: + containers: + - name: redis + image: redis + # defines the health checking + livenessProbe: + # a TCP socket probe + tcpSocket: + port: 6379 + # length of time to wait for a pod to initialize + # after pod startup, before applying health checking + initialDelaySeconds: 30 + timeoutSeconds: 1 + ports: + - containerPort: 6379 diff --git a/content/zh/examples/pods/probe/tcp-liveness-readiness.yaml b/content/zh/examples/pods/probe/tcp-liveness-readiness.yaml new file mode 100644 index 0000000000..08fb77ff0f --- /dev/null +++ b/content/zh/examples/pods/probe/tcp-liveness-readiness.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Pod +metadata: + name: goproxy + labels: + app: goproxy +spec: + containers: + - name: goproxy + image: k8s.gcr.io/goproxy:0.1 + ports: + - containerPort: 8080 + readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/content/zh/examples/pods/qos/qos-pod-2.yaml b/content/zh/examples/pods/qos/qos-pod-2.yaml new file mode 100644 index 0000000000..115d4de21e --- /dev/null +++ b/content/zh/examples/pods/qos/qos-pod-2.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo-2 + namespace: qos-example +spec: + containers: + - name: qos-demo-2-ctr + image: nginx + resources: + limits: + memory: "200Mi" + requests: + memory: "100Mi" diff --git a/content/zh/examples/pods/qos/qos-pod-3.yaml b/content/zh/examples/pods/qos/qos-pod-3.yaml new file mode 100644 index 0000000000..dac3629942 --- /dev/null +++ b/content/zh/examples/pods/qos/qos-pod-3.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo-3 + namespace: qos-example +spec: + containers: + - name: qos-demo-3-ctr + image: nginx diff --git a/content/zh/examples/pods/qos/qos-pod-4.yaml b/content/zh/examples/pods/qos/qos-pod-4.yaml new file mode 100644 index 0000000000..d4818b277e --- /dev/null +++ b/content/zh/examples/pods/qos/qos-pod-4.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo-4 + namespace: qos-example +spec: + containers: + + - name: qos-demo-4-ctr-1 + image: nginx + resources: + requests: + memory: "200Mi" + + - name: qos-demo-4-ctr-2 + image: redis diff --git a/content/zh/examples/pods/qos/qos-pod.yaml b/content/zh/examples/pods/qos/qos-pod.yaml new file mode 100644 index 0000000000..b4a6b1ea82 --- /dev/null +++ b/content/zh/examples/pods/qos/qos-pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo + namespace: qos-example +spec: + containers: + - name: qos-demo-ctr + image: nginx + resources: + limits: + memory: "200Mi" + cpu: "700m" + requests: + memory: "200Mi" + cpu: "700m" diff --git a/content/zh/examples/pods/resource/cpu-request-limit-2.yaml b/content/zh/examples/pods/resource/cpu-request-limit-2.yaml new file mode 100644 index 0000000000..f505c77fbb --- /dev/null +++ b/content/zh/examples/pods/resource/cpu-request-limit-2.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: cpu-demo-2 + namespace: cpu-example +spec: + containers: + - name: cpu-demo-ctr-2 + image: vish/stress + resources: + limits: + cpu: "100" + requests: + cpu: "100" + args: + - -cpus + - "2" diff --git a/content/zh/examples/pods/resource/cpu-request-limit.yaml b/content/zh/examples/pods/resource/cpu-request-limit.yaml new file mode 100644 index 0000000000..2cc0b2cf4f --- /dev/null +++ b/content/zh/examples/pods/resource/cpu-request-limit.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: cpu-demo + namespace: cpu-example +spec: + containers: + - name: cpu-demo-ctr + image: vish/stress + resources: + limits: + cpu: "1" + requests: + cpu: "0.5" + args: + - -cpus + - "2" diff --git a/content/zh/examples/pods/resource/extended-resource-pod-2.yaml b/content/zh/examples/pods/resource/extended-resource-pod-2.yaml new file mode 100644 index 0000000000..9c15d9ec86 --- /dev/null +++ b/content/zh/examples/pods/resource/extended-resource-pod-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: extended-resource-demo-2 +spec: + containers: + - name: extended-resource-demo-2-ctr + image: nginx + resources: + requests: + example.com/dongle: 2 + limits: + example.com/dongle: 2 diff --git a/content/zh/examples/pods/resource/extended-resource-pod.yaml b/content/zh/examples/pods/resource/extended-resource-pod.yaml new file mode 100644 index 0000000000..4fb3de740e --- /dev/null +++ b/content/zh/examples/pods/resource/extended-resource-pod.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: extended-resource-demo +spec: + containers: + - name: extended-resource-demo-ctr + image: nginx + resources: + requests: + example.com/dongle: 3 + limits: + example.com/dongle: 3 diff --git a/content/zh/examples/pods/resource/memory-request-limit-2.yaml b/content/zh/examples/pods/resource/memory-request-limit-2.yaml new file mode 100644 index 0000000000..99032c4fc2 --- /dev/null +++ b/content/zh/examples/pods/resource/memory-request-limit-2.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: memory-demo-2 + namespace: mem-example +spec: + containers: + - name: memory-demo-2-ctr + image: polinux/stress + resources: + requests: + memory: "50Mi" + limits: + memory: "100Mi" + command: ["stress"] + args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"] diff --git a/content/zh/examples/pods/resource/memory-request-limit-3.yaml b/content/zh/examples/pods/resource/memory-request-limit-3.yaml new file mode 100644 index 0000000000..9f089c4a7a --- /dev/null +++ b/content/zh/examples/pods/resource/memory-request-limit-3.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: memory-demo-3 + namespace: mem-example +spec: + containers: + - name: memory-demo-3-ctr + image: polinux/stress + resources: + limits: + memory: "1000Gi" + requests: + memory: "1000Gi" + command: ["stress"] + args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] diff --git a/content/zh/examples/pods/resource/memory-request-limit.yaml b/content/zh/examples/pods/resource/memory-request-limit.yaml new file mode 100644 index 0000000000..985b1308d9 --- /dev/null +++ b/content/zh/examples/pods/resource/memory-request-limit.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: memory-demo + namespace: mem-example +spec: + containers: + - name: memory-demo-ctr + image: polinux/stress + resources: + limits: + memory: "200Mi" + requests: + memory: "100Mi" + command: ["stress"] + args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"] diff --git a/content/zh/examples/pods/security/hello-apparmor.yaml b/content/zh/examples/pods/security/hello-apparmor.yaml new file mode 100644 index 0000000000..3e9b3b2a9c --- /dev/null +++ b/content/zh/examples/pods/security/hello-apparmor.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: hello-apparmor + annotations: + # Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write". + # Note that this is ignored if the Kubernetes node is not running version 1.4 or greater. + container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write +spec: + containers: + - name: hello + image: busybox + command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ] diff --git a/content/zh/examples/pods/security/security-context-2.yaml b/content/zh/examples/pods/security/security-context-2.yaml new file mode 100644 index 0000000000..0e3185341e --- /dev/null +++ b/content/zh/examples/pods/security/security-context-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo-2 +spec: + securityContext: + runAsUser: 1000 + containers: + - name: sec-ctx-demo-2 + image: gcr.io/google-samples/node-hello:1.0 + securityContext: + runAsUser: 2000 + allowPrivilegeEscalation: false diff --git a/content/zh/examples/pods/security/security-context-3.yaml b/content/zh/examples/pods/security/security-context-3.yaml new file mode 100644 index 0000000000..05295e1a03 --- /dev/null +++ b/content/zh/examples/pods/security/security-context-3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo-3 +spec: + containers: + - name: sec-ctx-3 + image: gcr.io/google-samples/node-hello:1.0 + + + diff --git a/content/zh/examples/pods/security/security-context-4.yaml b/content/zh/examples/pods/security/security-context-4.yaml new file mode 100644 index 0000000000..d725308fec --- /dev/null +++ b/content/zh/examples/pods/security/security-context-4.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo-4 +spec: + containers: + - name: sec-ctx-4 + image: gcr.io/google-samples/node-hello:1.0 + securityContext: + capabilities: + add: ["NET_ADMIN", "SYS_TIME"] diff --git a/content/zh/examples/pods/security/security-context.yaml b/content/zh/examples/pods/security/security-context.yaml new file mode 100644 index 0000000000..86ca51d39a --- /dev/null +++ b/content/zh/examples/pods/security/security-context.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: security-context-demo +spec: + securityContext: + runAsUser: 1000 + fsGroup: 2000 + volumes: + - name: sec-ctx-vol + emptyDir: {} + containers: + - name: sec-ctx-demo + image: gcr.io/google-samples/node-hello:1.0 + volumeMounts: + - name: sec-ctx-vol + mountPath: /data/demo + securityContext: + allowPrivilegeEscalation: false diff --git a/content/zh/examples/pods/share-process-namespace.yaml b/content/zh/examples/pods/share-process-namespace.yaml new file mode 100644 index 0000000000..af812732a2 --- /dev/null +++ b/content/zh/examples/pods/share-process-namespace.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + shareProcessNamespace: true + containers: + - name: nginx + image: nginx + - name: shell + image: busybox + securityContext: + capabilities: + add: + - SYS_PTRACE + stdin: true + tty: true diff --git a/content/zh/examples/pods/simple-pod.yaml b/content/zh/examples/pods/simple-pod.yaml new file mode 100644 index 0000000000..4208f4b365 --- /dev/null +++ b/content/zh/examples/pods/simple-pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 diff --git a/content/zh/examples/pods/storage/projected.yaml b/content/zh/examples/pods/storage/projected.yaml new file mode 100644 index 0000000000..172ca0dee5 --- /dev/null +++ b/content/zh/examples/pods/storage/projected.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-projected-volume +spec: + containers: + - name: test-projected-volume + image: busybox + args: + - sleep + - "86400" + volumeMounts: + - name: all-in-one + mountPath: "/projected-volume" + readOnly: true + volumes: + - name: all-in-one + projected: + sources: + - secret: + name: user + - secret: + name: pass diff --git a/content/zh/examples/pods/storage/pv-claim.yaml b/content/zh/examples/pods/storage/pv-claim.yaml new file mode 100644 index 0000000000..197db917c8 --- /dev/null +++ b/content/zh/examples/pods/storage/pv-claim.yaml @@ -0,0 +1,11 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: task-pv-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi diff --git a/content/zh/examples/pods/storage/pv-pod.yaml b/content/zh/examples/pods/storage/pv-pod.yaml new file mode 100644 index 0000000000..9bb4ca45ad --- /dev/null +++ b/content/zh/examples/pods/storage/pv-pod.yaml @@ -0,0 +1,20 @@ +kind: Pod +apiVersion: v1 +metadata: + name: task-pv-pod +spec: + volumes: + - name: task-pv-storage + persistentVolumeClaim: + claimName: task-pv-claim + containers: + - name: task-pv-container + image: nginx + ports: + - containerPort: 80 + name: "http-server" + volumeMounts: + - mountPath: "/usr/share/nginx/html" + name: task-pv-storage + + diff --git a/content/zh/examples/pods/storage/pv-volume.yaml b/content/zh/examples/pods/storage/pv-volume.yaml new file mode 100644 index 0000000000..33ca6843f4 --- /dev/null +++ b/content/zh/examples/pods/storage/pv-volume.yaml @@ -0,0 +1,14 @@ +kind: PersistentVolume +apiVersion: v1 +metadata: + name: task-pv-volume + labels: + type: local +spec: + storageClassName: manual + capacity: + storage: 10Gi + accessModes: + - ReadWriteOnce + hostPath: + path: "/mnt/data" diff --git a/content/zh/examples/pods/storage/redis.yaml b/content/zh/examples/pods/storage/redis.yaml new file mode 100644 index 0000000000..cb06456d4b --- /dev/null +++ b/content/zh/examples/pods/storage/redis.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis +spec: + containers: + - name: redis + image: redis + volumeMounts: + - name: redis-storage + mountPath: /data/redis + volumes: + - name: redis-storage + emptyDir: {} diff --git a/content/zh/examples/pods/two-container-pod.yaml b/content/zh/examples/pods/two-container-pod.yaml new file mode 100644 index 0000000000..031ada7112 --- /dev/null +++ b/content/zh/examples/pods/two-container-pod.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Pod +metadata: + name: two-containers +spec: + + restartPolicy: Never + + volumes: + - name: shared-data + emptyDir: {} + + containers: + + - name: nginx-container + image: nginx + volumeMounts: + - name: shared-data + mountPath: /usr/share/nginx/html + + - name: debian-container + image: debian + volumeMounts: + - name: shared-data + mountPath: /pod-data + command: ["/bin/sh"] + args: ["-c", "echo Hello from the debian container > /pod-data/index.html"] diff --git a/content/zh/examples/policy/example-psp.yaml b/content/zh/examples/policy/example-psp.yaml new file mode 100644 index 0000000000..7531949b65 --- /dev/null +++ b/content/zh/examples/policy/example-psp.yaml @@ -0,0 +1,17 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: example +spec: + privileged: false # Don't allow privileged pods! + # The rest fills in some required fields. + seLinux: + rule: RunAsAny + supplementalGroups: + rule: RunAsAny + runAsUser: + rule: RunAsAny + fsGroup: + rule: RunAsAny + volumes: + - '*' diff --git a/content/zh/examples/policy/privileged-psp.yaml b/content/zh/examples/policy/privileged-psp.yaml new file mode 100644 index 0000000000..915c8d37b5 --- /dev/null +++ b/content/zh/examples/policy/privileged-psp.yaml @@ -0,0 +1,27 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: privileged + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' +spec: + privileged: true + allowPrivilegeEscalation: true + allowedCapabilities: + - '*' + volumes: + - '*' + hostNetwork: true + hostPorts: + - min: 0 + max: 65535 + hostIPC: true + hostPID: true + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' diff --git a/content/zh/examples/policy/restricted-psp.yaml b/content/zh/examples/policy/restricted-psp.yaml new file mode 100644 index 0000000000..e677ba8e22 --- /dev/null +++ b/content/zh/examples/policy/restricted-psp.yaml @@ -0,0 +1,48 @@ +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: restricted + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default' + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + # This is redundant with non-root + disallow privilege escalation, + # but we can provide it for defense in depth. + requiredDropCapabilities: + - ALL + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + # Assume that persistentVolumes set up by the cluster admin are safe to use. + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + # Require the container to run without root privileges. + rule: 'MustRunAsNonRoot' + seLinux: + # This policy assumes the nodes are using AppArmor rather than SELinux. + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false diff --git a/content/zh/examples/service/access/frontend.yaml b/content/zh/examples/service/access/frontend.yaml new file mode 100644 index 0000000000..9f5b6b757f --- /dev/null +++ b/content/zh/examples/service/access/frontend.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Service +metadata: + name: frontend +spec: + selector: + app: hello + tier: frontend + ports: + - protocol: "TCP" + port: 80 + targetPort: 80 + type: LoadBalancer +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: frontend +spec: + selector: + matchLabels: + app: hello + tier: frontend + track: stable + replicas: 1 + template: + metadata: + labels: + app: hello + tier: frontend + track: stable + spec: + containers: + - name: nginx + image: "gcr.io/google-samples/hello-frontend:1.0" + lifecycle: + preStop: + exec: + command: ["/usr/sbin/nginx","-s","quit"] diff --git a/content/zh/examples/service/access/hello-service.yaml b/content/zh/examples/service/access/hello-service.yaml new file mode 100644 index 0000000000..1e4c7a6c32 --- /dev/null +++ b/content/zh/examples/service/access/hello-service.yaml @@ -0,0 +1,12 @@ +kind: Service +apiVersion: v1 +metadata: + name: hello +spec: + selector: + app: hello + tier: backend + ports: + - protocol: TCP + port: 80 + targetPort: http diff --git a/content/zh/examples/service/access/hello.yaml b/content/zh/examples/service/access/hello.yaml new file mode 100644 index 0000000000..85dff18ee1 --- /dev/null +++ b/content/zh/examples/service/access/hello.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hello +spec: + selector: + matchLabels: + app: hello + tier: backend + track: stable + replicas: 7 + template: + metadata: + labels: + app: hello + tier: backend + track: stable + spec: + containers: + - name: hello + image: "gcr.io/google-samples/hello-go-gke:1.0" + ports: + - name: http + containerPort: 80 diff --git a/content/zh/examples/service/networking/curlpod.yaml b/content/zh/examples/service/networking/curlpod.yaml new file mode 100644 index 0000000000..c15133641f --- /dev/null +++ b/content/zh/examples/service/networking/curlpod.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: curl-deployment +spec: + selector: + matchLabels: + app: curlpod + replicas: 1 + template: + metadata: + labels: + app: curlpod + spec: + volumes: + - name: secret-volume + secret: + secretName: nginxsecret + containers: + - name: curlpod + command: + - sh + - -c + - while true; do sleep 1; done + image: radial/busyboxplus:curl + volumeMounts: + - mountPath: /etc/nginx/ssl + name: secret-volume diff --git a/content/zh/examples/service/networking/custom-dns.yaml b/content/zh/examples/service/networking/custom-dns.yaml new file mode 100644 index 0000000000..3e5acd841a --- /dev/null +++ b/content/zh/examples/service/networking/custom-dns.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + namespace: default + name: dns-example +spec: + containers: + - name: test + image: nginx + dnsPolicy: "None" + dnsConfig: + nameservers: + - 1.2.3.4 + searches: + - ns1.svc.cluster.local + - my.dns.search.suffix + options: + - name: ndots + value: "2" + - name: edns0 diff --git a/content/zh/examples/service/networking/hostaliases-pod.yaml b/content/zh/examples/service/networking/hostaliases-pod.yaml new file mode 100644 index 0000000000..643813b34a --- /dev/null +++ b/content/zh/examples/service/networking/hostaliases-pod.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Pod +metadata: + name: hostaliases-pod +spec: + restartPolicy: Never + hostAliases: + - ip: "127.0.0.1" + hostnames: + - "foo.local" + - "bar.local" + - ip: "10.1.2.3" + hostnames: + - "foo.remote" + - "bar.remote" + containers: + - name: cat-hosts + image: busybox + command: + - cat + args: + - "/etc/hosts" diff --git a/content/zh/examples/service/networking/ingress.yaml b/content/zh/examples/service/networking/ingress.yaml new file mode 100644 index 0000000000..163c1d5b9d --- /dev/null +++ b/content/zh/examples/service/networking/ingress.yaml @@ -0,0 +1,9 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: test-ingress +spec: + backend: + serviceName: testsvc + servicePort: 80 + diff --git a/content/zh/examples/service/networking/nginx-secure-app.yaml b/content/zh/examples/service/networking/nginx-secure-app.yaml new file mode 100644 index 0000000000..ec180a18df --- /dev/null +++ b/content/zh/examples/service/networking/nginx-secure-app.yaml @@ -0,0 +1,46 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + type: NodePort + ports: + - port: 8080 + targetPort: 80 + protocol: TCP + name: http + - port: 443 + protocol: TCP + name: https + selector: + run: my-nginx +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 1 + template: + metadata: + labels: + run: my-nginx + spec: + volumes: + - name: secret-volume + secret: + secretName: nginxsecret + containers: + - name: nginxhttps + image: bprashanth/nginxhttps:1.0 + ports: + - containerPort: 443 + - containerPort: 80 + volumeMounts: + - mountPath: /etc/nginx/ssl + name: secret-volume diff --git a/content/zh/examples/service/networking/nginx-svc.yaml b/content/zh/examples/service/networking/nginx-svc.yaml new file mode 100644 index 0000000000..12fcd5d0bf --- /dev/null +++ b/content/zh/examples/service/networking/nginx-svc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx diff --git a/content/zh/examples/service/networking/run-my-nginx.yaml b/content/zh/examples/service/networking/run-my-nginx.yaml new file mode 100644 index 0000000000..76a879f5c4 --- /dev/null +++ b/content/zh/examples/service/networking/run-my-nginx.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 + diff --git a/content/zh/examples/service/nginx-service.yaml b/content/zh/examples/service/nginx-service.yaml new file mode 100644 index 0000000000..810f0ec7d8 --- /dev/null +++ b/content/zh/examples/service/nginx-service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx-service +spec: + ports: + - port: 8000 # the port that this service should serve on + # the container on each pod to connect to, can be a name + # (e.g. 'www') or a number (e.g. 80) + targetPort: 80 + protocol: TCP + # just like the selector in the deployment, + # but this time it identifies the set of pods to load balance + # traffic to. + selector: + app: nginx diff --git a/content/zh/examples/windows/configmap-pod.yaml b/content/zh/examples/windows/configmap-pod.yaml new file mode 100644 index 0000000000..e30939b367 --- /dev/null +++ b/content/zh/examples/windows/configmap-pod.yaml @@ -0,0 +1,31 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: example-config +data: + example.property.1: hello + example.property.2: world + +--- + +apiVersion: v1 +kind: Pod +metadata: + name: configmap-pod +spec: + containers: + - name: configmap-redis + image: redis:3.0-nanoserver + env: + - name: EXAMPLE_PROPERTY_1 + valueFrom: + configMapKeyRef: + name: example-config + key: example.property.1 + - name: EXAMPLE_PROPERTY_2 + valueFrom: + configMapKeyRef: + name: example-config + key: example.property.2 + nodeSelector: + beta.kubernetes.io/os: windows \ No newline at end of file diff --git a/content/zh/examples/windows/daemonset.yaml b/content/zh/examples/windows/daemonset.yaml new file mode 100644 index 0000000000..d3a7bb6636 --- /dev/null +++ b/content/zh/examples/windows/daemonset.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: my-daemonset + labels: + app: foo +spec: + selector: + matchLabels: + app: foo + template: + metadata: + labels: + app: foo + spec: + containers: + - name: foo + image: microsoft/windowsservercore:1709 + nodeSelector: + beta.kubernetes.io/os: windows + diff --git a/content/zh/examples/windows/deploy-hyperv.yaml b/content/zh/examples/windows/deploy-hyperv.yaml new file mode 100644 index 0000000000..c8b71ce8cb --- /dev/null +++ b/content/zh/examples/windows/deploy-hyperv.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: iis +spec: + selector: + matchLabels: + app: iis + replicas: 3 + template: + metadata: + labels: + app: iis + annotations: + experimental.windows.kubernetes.io/isolation-type: hyperv + spec: + containers: + - name: iis + image: microsoft/iis + ports: + - containerPort: 80 + diff --git a/content/zh/examples/windows/deploy-resource.yaml b/content/zh/examples/windows/deploy-resource.yaml new file mode 100644 index 0000000000..81207a3804 --- /dev/null +++ b/content/zh/examples/windows/deploy-resource.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: iis +spec: + replicas: 3 + selector: + matchLabels: + app: iis + template: + metadata: + labels: + app: iis + spec: + containers: + - name: iis + image: microsoft/iis + resources: + limits: + memory: "128Mi" + cpu: 2 + ports: + - containerPort: 80 + diff --git a/content/zh/examples/windows/emptydir-pod.yaml b/content/zh/examples/windows/emptydir-pod.yaml new file mode 100644 index 0000000000..3210576a59 --- /dev/null +++ b/content/zh/examples/windows/emptydir-pod.yaml @@ -0,0 +1,20 @@ + apiVersion: v1 + kind: Pod + metadata: + name: my-empty-dir-pod + spec: + containers: + - image: microsoft/windowsservercore:1709 + name: my-empty-dir-pod + volumeMounts: + - mountPath: /cache + name: cache-volume + - mountPath: C:/scratch + name: scratch-volume + volumes: + - name: cache-volume + emptyDir: {} + - name: scratch-volume + emptyDir: {} + nodeSelector: + beta.kubernetes.io/os: windows diff --git a/content/zh/examples/windows/hostpath-volume-pod.yaml b/content/zh/examples/windows/hostpath-volume-pod.yaml new file mode 100644 index 0000000000..843250c80c --- /dev/null +++ b/content/zh/examples/windows/hostpath-volume-pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: hostpath-volume-pod +spec: + containers: + - name: my-hostpath-volume-pod + image: microsoft/windowsservercore:1709 + volumeMounts: + - name: foo + mountPath: "C:\\etc\\foo" + readOnly: true + nodeSelector: + beta.kubernetes.io/os: windows + volumes: + - name: foo + hostPath: + path: "C:\\etc\\foo" diff --git a/content/zh/examples/windows/secret-pod.yaml b/content/zh/examples/windows/secret-pod.yaml new file mode 100644 index 0000000000..f4a8122c0a --- /dev/null +++ b/content/zh/examples/windows/secret-pod.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +data: + username: YWRtaW4= + password: MWYyZDFlMmU2N2Rm + +--- + +apiVersion: v1 +kind: Pod +metadata: + name: my-secret-pod +spec: + containers: + - name: my-secret-pod + image: microsoft/windowsservercore:1709 + env: + - name: USERNAME + valueFrom: + secretKeyRef: + name: mysecret + key: username + - name: PASSWORD + valueFrom: + secretKeyRef: + name: mysecret + key: password + nodeSelector: + beta.kubernetes.io/os: windows diff --git a/content/zh/examples/windows/simple-pod.yaml b/content/zh/examples/windows/simple-pod.yaml new file mode 100644 index 0000000000..f056f3cf0a --- /dev/null +++ b/content/zh/examples/windows/simple-pod.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: iis + labels: + name: iis +spec: + containers: + - name: iis + image: microsoft/iis:windowsservercore-1709 + ports: + - containerPort: 80 + nodeSelector: + "beta.kubernetes.io/os": windows