diff --git a/SUMMARY.md b/SUMMARY.md index 2217e575a..0cfcb72d4 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -37,10 +37,10 @@ * [设计理念](concepts/concepts.md) * [Etcd 解析](concepts/etcd.md) * [开放接口](concepts/open-interfaces.md) - * [CRI - Container Runtime Interface(容器运行时接口)](concepts/cri.md) - * [CNI - Container Network Interface(容器网络接口)](concepts/cni.md) - * [CSI - Container Storage Interface(容器存储接口)](concepts/csi.md) - * [资源对象与基本概念解析](concepts/objects.md) + * [容器运行时接口(CRI)](concepts/cri.md) + * [容器网络接口(CNI)](concepts/cni.md) + * [容器存储接口(CSI)](concepts/csi.md) + * [Kubernetes 中的资源对象](concepts/objects.md) * [Pod 状态与生命周期管理](concepts/pod-state-and-lifecycle.md) * [Pod 概览](concepts/pod-overview.md) * [Pod 解析](concepts/pod.md) @@ -73,16 +73,15 @@ * [拓扑感知路由](concepts/topology-aware-routing.md) * [Ingress](concepts/ingress.md) * [Traefik Ingress Controller](concepts/traefik-ingress-controller.md) - * [Kubernetes Service API](concepts/kubernetes-service-api.md) - * [Service API 简介](concepts/service-api-overview.md) + * [Gateway](concepts/gateway.md) * [身份与权限控制](concepts/authentication-and-permission.md) * [ServiceAccount](concepts/serviceaccount.md) * [基于角色的访问控制(RBAC)](concepts/rbac.md) * [NetworkPolicy](concepts/network-policy.md) * [网络](concepts/networking.md) - * [Kubernetes 中的网络解析 —— 以 flannel 为例](concepts/flannel.md) - * [Kubernetes 中的网络解析 —— 以 calico 为例](concepts/calico.md) - * [具备 API 感知的网络和安全性管理开源软件 Cilium](concepts/cilium.md) + * [扁平网络 Flannel](concepts/flannel.md) + * [非 Overlay 扁平网络 Calico](concepts/calico.md) + * [基于 eBPF 的网络 Cilium](concepts/cilium.md) * [Cilium 架构设计与概念解析](concepts/cilium-concepts.md) * [存储](concepts/storage.md) * [Secret](concepts/secret.md) diff --git a/concepts/calico.md b/concepts/calico.md index 4ab7e8100..3ab70ccc2 100644 --- a/concepts/calico.md +++ b/concepts/calico.md @@ -1,4 +1,4 @@ -# Kubernetes中的网络解析——以calico为例 +# 非 Overlay 扁平网络 Calico [Calico](https://www.projectcalico.org/) 原意为”有斑点的“,如果说一只猫为 calico cat 的话,就是说这是只花猫,也叫三色猫,所以 calico 的 logo 是只三色猫。 @@ -6,54 +6,147 @@ ## 概念 -Calico创建和管理一个扁平的三层网络(不需要overlay),每个容器会分配一个可路由的IP。由于通信时不需要解包和封包,网络性能损耗小,易于排查,且易于水平扩展。 +Calico 创建和管理一个扁平的三层网络(不需要 overlay),每个容器会分配一个可路由的 IP。由于通信时不需要解包和封包,网络性能损耗小,易于排查,且易于水平扩展。 -小规模部署时可以通过BGP client直接互联,大规模下可通过指定的BGP Route Reflector来完成,这样保证所有的数据流量都是通过IP路由的方式完成互联的。 +小规模部署时可以通过 BGP client 直接互联,大规模下可通过指定的 BGP Route Reflector 来完成,这样保证所有的数据流量都是通过 IP 路由的方式完成互联的。 -Calico基于iptables还提供了丰富而灵活的网络Policy,保证通过各个节点上的ACL来提供Workload的多租户隔离、安全组以及其他可达性限制等功能。 +Calico 基于 iptables 还提供了丰富而灵活的网络 Policy,保证通过各个节点上的 ACL 来提供 Workload 的多租户隔离、安全组以及其他可达性限制等功能。 -## Calico架构 +## Calico 架构 -![CRI架构-图片来自https://www.jianshu.com/p/f0177b84de66](../images/calico.png) +Calico 由以下组件组成,在部署 Calico 的时候部分组件是可选的。 -Calico主要由Felix、etcd、BGP client、BGP Route Reflector组成。 +- [Calico API server](https://projectcalico.docs.tigera.io/reference/architecture/overview#calico-api-server) +- [Felix](https://projectcalico.docs.tigera.io/reference/architecture/overview#felix) +- [BIRD](https://projectcalico.docs.tigera.io/reference/architecture/overview#bird) +- [confd](https://projectcalico.docs.tigera.io/reference/architecture/overview#confd) +- [Dikastes](https://projectcalico.docs.tigera.io/reference/architecture/overview#dikastes) +- [CNI 插件](https://projectcalico.docs.tigera.io/reference/architecture/overview#cni-plugin) +- [数据存储插件](https://projectcalico.docs.tigera.io/reference/architecture/overview#datastore-plugin) +- [IPAM 插件](https://projectcalico.docs.tigera.io/reference/architecture/overview#ipam-plugin) +- [kube-controllers](https://projectcalico.docs.tigera.io/reference/architecture/overview#kube-controllers) +- [Typha](https://projectcalico.docs.tigera.io/reference/architecture/overview#typha) +- [calicoctl](https://projectcalico.docs.tigera.io/reference/architecture/overview#calicoctl) +- [云编排器插件](https://projectcalico.docs.tigera.io/reference/architecture/overview#plugins-for-cloud-orchestrators) -- [Etcd](https://docs.projectcalico.org/v3.0/reference/architecture/):负责存储网络信息 -- [BGP client](https://docs.projectcalico.org/v3.0/reference/architecture/):负责将Felix配置的路由信息分发到其他节点 -- [Felix](https://docs.projectcalico.org/v3.0/reference/architecture/):Calico Agent,每个节点都需要运行,主要负责配置路由、配置ACLs、报告状态 -- [BGP Route Reflector](https://docs.projectcalico.org/v3.0/reference/architecture/):大规模部署时需要用到,作为BGP client的中心连接点,可以避免每个节点互联 +Calico 的架构图如下所示: -## 部署 +![Calico 架构图](../images/calico-architecture.png) -运行下面的命令可以部署 calico 网络。 +注:图片来自 [Calico 官网](https://projectcalico.docs.tigera.io/reference/architecture/overview)。 -```bash -mkdir /etc/cni/net.d/ +### Calico API Server -kubectl apply -f https://docs.projectcalico.org/v3.0/getting-started/kubernetes/installation/rbac.yaml +可以使用 kubectl 直接管理 Calico。 -wget https://docs.projectcalico.org/v3.0/getting-started/kubernetes/installation/hosted/calico.yaml +### Felix -# 修改etcd_endpoints的值和默认的192.168.0.0/16(不能和已有网段冲突) +Felix 以 agent 代理的形式在每台机器端点上运行。对路由和 ACL 以及主机编程,为该主机上的端点提供所需的连接。 -kubectl apply -f calico.yaml +根据具体的编排器环境,Felix负责: -wget https://github.com/projectcalico/calicoctl/releases/download/v2.0.0/calicoctl +**接口管理** -mv calicoctl /usr/loca/bin && chmod +x /usr/local/bin/calicoctl +将有关接口的信息编入内核,以便内核能够正确处理来自该端点的流量。特别是,确保主机响应来自每个工作负载的ARP请求,提供主机的MAC,并为它所管理的接口启用IP转发。它还监控接口,以确保编程在适当的时候应用。 -export CALICO_DATASTORE_TYPE=kubernetes +**路由编程** -export CALICO_KUBECONFIG=~/.kube/config +将其主机上的端点的路由编程到Linux内核的FIB(转发信息库)。这可以确保到达主机上的以这些端点为目的地的数据包被相应地转发。 -calicoctl get ippool +**ACL编程** -calicoctl get node -``` +在Linux内核中编程ACL,以确保只有有效的流量可以在端点之间发送,并且端点不能规避Calico的安全措施。 -如果安装时启用应用层策略的话还需要安装 [istio](https://istio.io),详见 [Enabling application layer policy](https://docs.projectcalico.org/v3.4/getting-started/kubernetes/installation/app-layer-policy#about-enabling-application-layer-policy)。 +**状态报告** + +提供网络健康数据。特别是在配置其主机时报告错误和问题。这些数据被写入数据存储,以便对网络的其他组件和运营商可见。 + +### BIRD + +BGP Internet Routing Daemon,简称 BIRD。从Felix获取路由,并分发到网络上的BGP peer,用于主机间的路由。在每个Felix代理的节点上运行。 + +BGP客户端负责: + +**路由分配** + +当Felix将路由插入Linux内核的FIB时,BGP客户端将它们分配给部署中的其他节点。这确保了部署中的有效流量路由。 + +**BGP路由反射器的配置** + +BGP路由反射器通常是为大型部署而配置的,而不是一个标准的BGP客户端。BGP路由反射器作为连接BGP客户端的一个中心点。(标准BGP要求每个BGP客户端在网状拓扑结构中与其他每个BGP客户端连接,这很难维护)。 + +为了实现冗余,你可以无缝部署多个BGP路由反射器。BGP路由反射器只参与网络的控制:没有终端数据通过它们。当Calico BGP客户端将其FIB中的路由通告给路由反射器时,路由反射器将这些路由通告给部署中的其他节点。 + +### confd + +开源的、轻量级的配置管理工具。监控Calico数据存储对BGP配置和全局默认的日志变更,如AS号、日志级别和IPAM信息。 + +Confd根据存储中的数据更新,动态生成BIRD配置文件。当配置文件发生变化时,confd会触发BIRD加载新的文件。 + +### Dikastes + +执行Istio服务网格的网络策略。作为Istio Envoy的一个Sidecar代理,在集群上运行。 + +Dikastes 是可选的。Calico在Linux内核(使用iptables,在三、四层)和三到七层使用Envoy的Sidecar代理Dikastes为工作负载执行网络策略,对请求进行加密认证。使用多个执行点可以根据多个标准确定远程端点的身份。即使工作负载Pod破坏,Envoy代理被绕过,主机Linux内核的执行也能保护你的工作负载。 + +### CNI 插件 + +为Kubernetes集群提供Calico网络。 + +向Kubernetes展示该API的Calico二进制文件被称为CNI插件,必须安装在Kubernetes集群的每个节点上。Calico CNI插件允许你为任何使用[CNI](../concepts/cni.md)网络规范的编排调度器使用Calico网络。 + +### 数据存储插件 + +通过减少每个节点对数据存储的影响来增加规模。它是Calico CNI的插件之一。 + +**Kubernetes API datastore(kdd)** + +在Calico中使用Kubernetes API数据存储(kdd)的优点是: + +- 管理更简单,因为不需要额外的数据存储 +- 使用Kubernetes RBAC来控制对Calico资源的访问 +- 使用Kubernetes审计日志来生成对Calico资源变化的审计日志 + +**etcd** + +[etcd](../concepts/etcd.md)是一个一致的、高可用的分布式键值存储,为Calico网络提供数据存储,并用于组件之间的通信。etcd仅支持保护非集群主机(从Calico v3.1开始)。etcd的优点是: + +- 让你在非Kubernetes平台上运行Calico +- 分离Kubernetes和Calico资源之间的关注点,例如允许你独立地扩展数据存储。 +- 让你运行的Calico集群不仅仅包含一个Kubernetes集群,例如,让带有Calico主机保护的裸机服务器与Kubernetes集群互通;或者多个Kubernetes集群。 + +### IPAM 插件 + +使用Calico的IP池资源来控制如何将IP地址分配给集群中的pod。它是大多数Calico安装所使用的默认插件。它是Calico CNI插件之一。 + +### kube-controller + +监控Kubernetes的API,并根据集群状态执行行动。 + +`tigera/kube-controllers` 容器包括以下控制器: + +- Policy 控制器 +- Namespace 控制器 +- ServiceAccount 控制器 +- WorkloadEndpoint 控制器 +- Node 控制器 + +### Typha + +通过减少每个节点对数据存储的影响来增加规模。作为数据存储和Felix实例之间的一个守护程序运行。默认安装,但没有配置。 + +Typha代表Felix和confd等所有客户端维护一个单一的数据存储连接。它缓存数据存储的状态,并复制事件,以便它们可以被推广到更多监听器。因为一个Typha实例可以支持数百个Felix实例,可以将数据存储的负载降低很多。由于Typha可以过滤掉与Felix无关的更新,它也减少了Felix的CPU使用。在一个大规模(100多个节点)的Kubernetes集群中,这是至关重要的,因为API服务器产生的更新数量随着节点数量的增加而增加。 + +### calicoctl + +Calicoctl命令行作为二进制或容器需要单独安装,可以在任何可以通过网络访问Calico数据存储的主机上使用。 + +## 云编排器插件 + +将管理网络的编排器API翻译成Calico的数据模型和数据存储。 + +对于云供应商,Calico为每个主要的云编排平台提供了一个单独的插件。这使得Calico能够与编排器紧密结合,因此用户可以使用他们的编排器工具来管理Calico网络。当需要时,编排器插件会将Calico网络的反馈信息提供给编排器。例如,提供关于Felix liveness的信息,并在网络设置失败时将特定端点标记为失败。 ## 参考 -- [calicoctl命令参考 - docs.projectcalico.org](https://docs.projectcalico.org/v3.4/reference/calicoctl/commands/) -- [Calico架构 - docs.projectcalico.org](https://docs.projectcalico.org/v3.4/reference/architecture/) +- [Calico 组件架构 - docs.projectcalico.org](https://projectcalico.docs.tigera.io/reference/architecture/overview) \ No newline at end of file diff --git a/concepts/cilium.md b/concepts/cilium.md index 1931d5a96..63daf27c2 100644 --- a/concepts/cilium.md +++ b/concepts/cilium.md @@ -1,4 +1,4 @@ -# 具备 API 感知的网络和安全性管理的开源软件 Cilium +# 基于 eBPF 的网络 Cilium Cilium 是一款开源软件,也是 CNCF 的孵化项目,目前[已有公司](https://isovalent.com/)提供商业化支持,还有基于 Cilium 实现的服务网格解决方案。最初它仅是作为一个 Kubernetes 网络组件。Cilium 在 1.7 版本后[推出并开源了 Hubble](https://cilium.io/blog/2019/11/19/announcing-hubble),它是专门为网络可视化设计,能够利用 Cilium 提供的 eBPF 数据路径,获得对 Kubernetes 应用和服务的网络流量的深度可见性。这些网络流量信息可以对接 Hubble CLI、UI 工具,可以通过交互式的方式快速进行问题诊断。除了 Hubble 自身的监控工具,还可以对接主流的云原生监控体系——Prometheus 和 Grafana,实现可扩展的监控策略。 diff --git a/concepts/cni.md b/concepts/cni.md index 34ca9e26c..893b8360a 100644 --- a/concepts/cni.md +++ b/concepts/cni.md @@ -1,8 +1,8 @@ -# CNI - Container Network Interface(容器网络接口) +# 容器网络接口(CNI) -CNI(Container Network Interface)是 CNCF 旗下的一个项目,由一组用于配置 Linux 容器的网络接口的规范和库组成,同时还包含了一些插件。CNI 仅关心容器创建时的网络分配,和当容器被删除时释放网络资源。通过此链接浏览该项目:。 +容器网络接口(Container Network Interface),简称 CNI,是 CNCF 旗下的一个项目,由一组用于配置 Linux 容器的网络接口的规范和库组成,同时还包含了一些插件。CNI 仅关心容器创建时的网络分配,和当容器被删除时释放网络资源。有关详情请查看 [GitHub](https://github.com/containernetworking/cni)。 -Kubernetes 源码的 `vendor/github.com/containernetworking/cni/libcni` 目录中已经包含了 CNI 的代码,也就是说 kubernetes 中已经内置了 CNI。 +Kubernetes 源码的 `vendor/github.com/containernetworking/cni/libcni` 目录中已经包含了 CNI 的代码,也就是说 Kubernetes 中已经内置了 CNI。 ## 接口定义 @@ -75,7 +75,7 @@ CNI 插件必须支持以下操作: - 所有参数应与传递给相应的添加操作的参数相同。 - 删除操作应释放配置的网络中提供的 containerid 拥有的所有资源。 -报告版本 +报告版本: - 参数:无。 - 结果:插件支持的 CNI 规范版本信息。 @@ -122,7 +122,7 @@ CNI 插件的详细说明请参考:[CNI SPEC](https://github.com/containernetw ## 参考 -- https://github.com/containernetworking/cni -- https://github.com/containernetworking/plugins -- [Container Networking Interface Specification](https://github.com/containernetworking/cni/blob/master/SPEC.md#container-networking-interface-specification) -- [CNI Extension conventions](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) +- [containernetworking/cni - github.com](https://github.com/containernetworking/cni) +- [containernetworking/plugins - github.com](https://github.com/containernetworking/plugins) +- [Container Networking Interface Specification - github.com](https://github.com/containernetworking/cni/blob/master/SPEC.md#container-networking-interface-specification) +- [CNI Extension conventions - github.com](https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md) diff --git a/concepts/cri.md b/concepts/cri.md index 4c5b32d18..52819e318 100644 --- a/concepts/cri.md +++ b/concepts/cri.md @@ -1,147 +1,145 @@ -# CRI - Container Runtime Interface(容器运行时接口) +# 容器运行时接口(CRI) -CRI中定义了**容器**和**镜像**的服务的接口,因为容器运行时与镜像的生命周期是彼此隔离的,因此需要定义两个服务。该接口使用[Protocol Buffer](https://developers.google.com/protocol-buffers/),基于[gRPC](https://grpc.io/),在Kubernetes v1.10+版本中是在`pkg/kubelet/apis/cri/runtime/v1alpha2`的`api.proto`中定义的。 +容器运行时接口(Container Runtime Interface),简称 CRI。CRI 中定义了 **容器** 和 **镜像** 的服务的接口,因为容器运行时与镜像的生命周期是彼此隔离的,因此需要定义两个服务。该接口使用 [Protocol Buffer](https://developers.google.com/protocol-buffers/),基于 [gRPC](https://grpc.io/),在 Kubernetes v1.10 + 版本中是在 `pkg/kubelet/apis/cri/runtime/v1alpha2` 的 `api.proto` 中定义的。 -## CRI架构 +## CRI 架构 -Container Runtime实现了CRI gRPC Server,包括`RuntimeService`和`ImageService`。该gRPC Server需要监听本地的Unix socket,而kubelet则作为gRPC Client运行。 +Container Runtime 实现了 CRI gRPC Server,包括 `RuntimeService` 和 `ImageService`。该 gRPC Server 需要监听本地的 Unix socket,而 kubelet 则作为 gRPC Client 运行。 -![CRI架构-图片来自kubernetes blog](../images/cri-architecture.png) +![CRI 架构 - 图片来自 kubernetes blog](../images/cri-architecture.png) -## 启用CRI +## 启用 CRI -除非集成了rktnetes,否则CRI都是被默认启用了,从Kubernetes1.7版本开始,旧的预集成的docker CRI已经被移除。 +除非集成了 rktnetes,否则 CRI 都是被默认启用了,从 Kubernetes 1.7 版本开始,旧的预集成的 docker CRI 已经被移除。 -要想启用CRI只需要在kubelet的启动参数重传入此参数:`--container-runtime-endpoint`远程运行时服务的端点。当前Linux上支持unix socket,windows上支持tcp。例如:`unix:///var/run/dockershim.sock`、 `tcp://localhost:373`,默认是`unix:///var/run/dockershim.sock`,即默认使用本地的docker作为容器运行时。 +要想启用 CRI 只需要在 kubelet 的启动参数重传入此参数:`--container-runtime-endpoint` 远程运行时服务的端点。当前 Linux 上支持 unix socket,windows 上支持 tcp。例如:`unix:///var/run/dockershim.sock`、 `tcp://localhost:373`,默认是 `unix:///var/run/dockershim.sock`,即默认使用本地的 docker 作为容器运行时。 -## CRI接口 +## CRI 接口 -Kubernetes 1.9中的CRI接口在`api.proto`中的定义如下: +Kubernetes 1.9 中的 CRI 接口在 `api.proto` 中的定义如下: ```protobuf // Runtime service defines the public APIs for remote container runtimes service RuntimeService { // Version returns the runtime name, runtime version, and runtime API version. - rpc Version(VersionRequest) returns (VersionResponse) {} + rpc Version (VersionRequest) returns (VersionResponse) {} // RunPodSandbox creates and starts a pod-level sandbox. Runtimes must ensure - // the sandbox is in the ready state on success. - rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {} + //the sandbox is in the ready state on success. + rpc RunPodSandbox (RunPodSandboxRequest) returns (RunPodSandboxResponse) {} // StopPodSandbox stops any running process that is part of the sandbox and - // reclaims network resources (e.g., IP addresses) allocated to the sandbox. + //reclaims network resources (e.g., IP addresses) allocated to the sandbox. // If there are any running containers in the sandbox, they must be forcibly - // terminated. + //terminated. // This call is idempotent, and must not return an error if all relevant - // resources have already been reclaimed. kubelet will call StopPodSandbox - // at least once before calling RemovePodSandbox. It will also attempt to - // reclaim resources eagerly, as soon as a sandbox is not needed. Hence, - // multiple StopPodSandbox calls are expected. - rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {} + //resources have already been reclaimed. kubelet will call StopPodSandbox + //at least once before calling RemovePodSandbox. It will also attempt to + //reclaim resources eagerly, as soon as a sandbox is not needed. Hence, + //multiple StopPodSandbox calls are expected. + rpc StopPodSandbox (StopPodSandboxRequest) returns (StopPodSandboxResponse) {} // RemovePodSandbox removes the sandbox. If there are any running containers - // in the sandbox, they must be forcibly terminated and removed. + //in the sandbox, they must be forcibly terminated and removed. // This call is idempotent, and must not return an error if the sandbox has - // already been removed. - rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {} + //already been removed. + rpc RemovePodSandbox (RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {} // PodSandboxStatus returns the status of the PodSandbox. If the PodSandbox is not - // present, returns an error. - rpc PodSandboxStatus(PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {} + //present, returns an error. + rpc PodSandboxStatus (PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {} // ListPodSandbox returns a list of PodSandboxes. - rpc ListPodSandbox(ListPodSandboxRequest) returns (ListPodSandboxResponse) {} + rpc ListPodSandbox (ListPodSandboxRequest) returns (ListPodSandboxResponse) {} // CreateContainer creates a new container in specified PodSandbox - rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {} + rpc CreateContainer (CreateContainerRequest) returns (CreateContainerResponse) {} // StartContainer starts the container. - rpc StartContainer(StartContainerRequest) returns (StartContainerResponse) {} + rpc StartContainer (StartContainerRequest) returns (StartContainerResponse) {} // StopContainer stops a running container with a grace period (i.e., timeout). // This call is idempotent, and must not return an error if the container has - // already been stopped. + //already been stopped. // TODO: what must the runtime do after the grace period is reached? - rpc StopContainer(StopContainerRequest) returns (StopContainerResponse) {} + rpc StopContainer (StopContainerRequest) returns (StopContainerResponse) {} // RemoveContainer removes the container. If the container is running, the - // container must be forcibly removed. + //container must be forcibly removed. // This call is idempotent, and must not return an error if the container has - // already been removed. - rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse) {} + //already been removed. + rpc RemoveContainer (RemoveContainerRequest) returns (RemoveContainerResponse) {} // ListContainers lists all containers by filters. - rpc ListContainers(ListContainersRequest) returns (ListContainersResponse) {} + rpc ListContainers (ListContainersRequest) returns (ListContainersResponse) {} // ContainerStatus returns status of the container. If the container is not - // present, returns an error. - rpc ContainerStatus(ContainerStatusRequest) returns (ContainerStatusResponse) {} + //present, returns an error. + rpc ContainerStatus (ContainerStatusRequest) returns (ContainerStatusResponse) {} // UpdateContainerResources updates ContainerConfig of the container. - rpc UpdateContainerResources(UpdateContainerResourcesRequest) returns (UpdateContainerResourcesResponse) {} + rpc UpdateContainerResources (UpdateContainerResourcesRequest) returns (UpdateContainerResourcesResponse) {} // ExecSync runs a command in a container synchronously. - rpc ExecSync(ExecSyncRequest) returns (ExecSyncResponse) {} + rpc ExecSync (ExecSyncRequest) returns (ExecSyncResponse) {} // Exec prepares a streaming endpoint to execute a command in the container. - rpc Exec(ExecRequest) returns (ExecResponse) {} + rpc Exec (ExecRequest) returns (ExecResponse) {} // Attach prepares a streaming endpoint to attach to a running container. - rpc Attach(AttachRequest) returns (AttachResponse) {} + rpc Attach (AttachRequest) returns (AttachResponse) {} // PortForward prepares a streaming endpoint to forward ports from a PodSandbox. - rpc PortForward(PortForwardRequest) returns (PortForwardResponse) {} + rpc PortForward (PortForwardRequest) returns (PortForwardResponse) {} // ContainerStats returns stats of the container. If the container does not - // exist, the call returns an error. - rpc ContainerStats(ContainerStatsRequest) returns (ContainerStatsResponse) {} + //exist, the call returns an error. + rpc ContainerStats (ContainerStatsRequest) returns (ContainerStatsResponse) {} // ListContainerStats returns stats of all running containers. - rpc ListContainerStats(ListContainerStatsRequest) returns (ListContainerStatsResponse) {} + rpc ListContainerStats (ListContainerStatsRequest) returns (ListContainerStatsResponse) {} // UpdateRuntimeConfig updates the runtime configuration based on the given request. - rpc UpdateRuntimeConfig(UpdateRuntimeConfigRequest) returns (UpdateRuntimeConfigResponse) {} + rpc UpdateRuntimeConfig (UpdateRuntimeConfigRequest) returns (UpdateRuntimeConfigResponse) {} // Status returns the status of the runtime. - rpc Status(StatusRequest) returns (StatusResponse) {} -} + rpc Status (StatusRequest) returns (StatusResponse) {}} // ImageService defines the public APIs for managing images. service ImageService { // ListImages lists existing images. - rpc ListImages(ListImagesRequest) returns (ListImagesResponse) {} + rpc ListImages (ListImagesRequest) returns (ListImagesResponse) {} // ImageStatus returns the status of the image. If the image is not - // present, returns a response with ImageStatusResponse.Image set to - // nil. - rpc ImageStatus(ImageStatusRequest) returns (ImageStatusResponse) {} + //present, returns a response with ImageStatusResponse.Image set to + //nil. + rpc ImageStatus (ImageStatusRequest) returns (ImageStatusResponse) {} // PullImage pulls an image with authentication config. - rpc PullImage(PullImageRequest) returns (PullImageResponse) {} + rpc PullImage (PullImageRequest) returns (PullImageResponse) {} // RemoveImage removes the image. // This call is idempotent, and must not return an error if the image has - // already been removed. - rpc RemoveImage(RemoveImageRequest) returns (RemoveImageResponse) {} + //already been removed. + rpc RemoveImage (RemoveImageRequest) returns (RemoveImageResponse) {} // ImageFSInfo returns information of the filesystem that is used to store images. - rpc ImageFsInfo(ImageFsInfoRequest) returns (ImageFsInfoResponse) {} -} + rpc ImageFsInfo (ImageFsInfoRequest) returns (ImageFsInfoResponse) {}} ``` -这其中包含了两个gRPC服务: +这其中包含了两个 gRPC 服务: -- **RuntimeService**:容器和Sandbox运行时管理。 -- **ImageService**:提供了从镜像仓库拉取、查看、和移除镜像的RPC。 +- **RuntimeService**:容器和 Sandbox 运行时管理。 +- **ImageService**:提供了从镜像仓库拉取、查看、和移除镜像的 RPC。 -## 当前支持的CRI后端 +## 当前支持的 CRI 后端 -我们最初在使用Kubernetes时通常会默认使用Docker作为容器运行时,其实从Kubernetes 1.5开始已经开始支持CRI,目前是处于Alpha版本,通过CRI接口可以指定使用其它容器运行时作为Pod的后端,目前支持 CRI 的后端有: +我们最初在使用 Kubernetes 时通常会默认使用 Docker 作为容器运行时,其实从 Kubernetes 1.5 开始已经支持 CRI,通过 CRI 接口可以指定使用其它容器运行时作为 Pod 的后端,目前支持 CRI 的后端有: -- [cri-o](https://github.com/kubernetes-incubator/cri-o):cri-o是Kubernetes的CRI标准的实现,并且允许Kubernetes间接使用OCI兼容的容器运行时,可以把cri-o看成Kubernetes使用OCI兼容的容器运行时的中间层。 -- [cri-containerd](https://github.com/containerd/cri-containerd):基于[Containerd](https://github.com/containerd/containerd)的Kubernetes CRI 实现 -- [rkt](https://coreos.com/rkt/):由CoreOS主推的用来跟docker抗衡的容器运行时 -- [frakti](https://github.com/kubernetes/frakti):基于hypervisor的CRI -- [docker](https://www.docker.com):kuberentes最初就开始支持的容器运行时,目前还没完全从kubelet中解耦,docker公司同时推广了[OCI](https://www.opencontainers.org/)标准 +- [cri-o](https://github.com/kubernetes-incubator/cri-o):cri-o 是 Kubernetes 的 CRI 标准的实现,并且允许 Kubernetes 间接使用 OCI 兼容的容器运行时,可以把 cri-o 看成 Kubernetes 使用 OCI 兼容的容器运行时的中间层。 +- [cri-containerd](https://github.com/containerd/cri-containerd):基于 [Containerd](https://github.com/containerd/containerd) 的 Kubernetes CRI 实现 +- [rkt](https://coreos.com/rkt/):由 CoreOS 主推的用来跟 docker 抗衡的容器运行时 +- [frakti](https://github.com/kubernetes/frakti):基于 hypervisor 的 CRI +- [docker](https://www.docker.com):Kuberentes 最初就开始支持的容器运行时,目前还没完全从 kubelet 中解耦,Docker 公司同时推广了 [OCI](https://www.opencontainers.org/) 标准 -CRI是由[SIG-Node](https://kubernetes.slack.com/archives/sig-node)来维护的。 +CRI 是由 [SIG-Node](https://kubernetes.slack.com/archives/sig-node) 来维护的。 -## 当前通过CRI-O间接支持CRI的后端 +## 当前通过 CRI-O 间接支持 CRI 的后端 -当前同样存在一些只实现了[OCI](https://www.opencontainers.org/)标准的容器,但是它们可以通过CRI-O来作为Kubernetes的容器运行时。CRI-O是Kubernetes的CRI标准的实现,并且允许Kubernetes间接使用OCI兼容的容器运行时。 +当前同样存在一些只实现了 [OCI](https://www.opencontainers.org/) 标准的容器,但是它们可以通过 CRI-O 来作为 Kubernetes 的容器运行时。CRI-O 是 Kubernetes 的 CRI 标准的实现,并且允许 Kubernetes 间接使用 OCI 兼容的容器运行时。 -- [Clear Containers](https://github.com/clearcontainers):由Intel推出的兼容OCI容器运行时,可以通过CRI-O来兼容CRI。 -- [Kata Containers](https://katacontainers.io/):符合OCI规范,可以通过CRI-O或[Containerd CRI Plugin](https://github.com/containerd/cri)来兼容CRI。。 -- [gVisor](https://github.com/google/gvisor):由谷歌推出的容器运行时沙箱(Experimental),可以通过CRI-O来兼容CRI。 +- [Clear Containers](https://github.com/clearcontainers):由 Intel 推出的兼容 OCI 容器运行时,可以通过 CRI-O 来兼容 CRI。 +- [Kata Containers](https://katacontainers.io/):符合 OCI 规范,可以通过 CRI-O 或 [Containerd CRI Plugin](https://github.com/containerd/cri) 来兼容 CRI。 +- [gVisor](https://github.com/google/gvisor):由谷歌推出的容器运行时沙箱 (Experimental),可以通过 CRI-O 来兼容 CRI。 ## 参考 -- [Kubernetes CRI and Minikube](https://sreeninet.wordpress.com/2017/02/11/kubernetes-cri-and-minikube/) -- [CRI-O and Alternative Runtimes in Kubernetes](https://www.projectatomic.io/blog/2017/02/crio-runtimes/) +- [Kubernetes CRI and Minikube - sreeninet.wordpress.com](https://sreeninet.wordpress.com/2017/02/11/kubernetes-cri-and-minikube/) +- [CRI-O and Alternative Runtimes in Kubernetes - projectatomic.io](https://projectatomic.io/blog/2017/02/crio-runtimes/) - [Docker、Containerd、RunC...:你应该知道的所有](https://www.infoq.cn/article/2017/02/Docker-Containerd-RunC/) -- [Introducing Container Runtime Interface (CRI) in Kubernetes](http://blog.kubernetes.io/2016/12/container-runtime-interface-cri-in-kubernetes.html) -- [cri-o](https://cri-o.io/) -- [Kata Containers Architecture](https://github.com/kata-containers/documentation/blob/master/design/architecture.md#kubernetes-support) +- [Introducing Container Runtime Interface (CRI) in Kubernetes - blog.kubernetes.io](https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/) +- [cri-o 官网 - cri-o.io](https://cri-o.io/) +- [Kata Containers Architecture - github.com](https://github.com/kata-containers/documentation/blob/master/design/architecture.md#kubernetes-support) diff --git a/concepts/csi.md b/concepts/csi.md index ae1adba2c..bb542c7c4 100644 --- a/concepts/csi.md +++ b/concepts/csi.md @@ -1,6 +1,6 @@ -# CSI - Container Storage Interface(容器存储接口) +# 容器存储接口(CSI) -CSI 代表[容器存储接口](https://github.com/container-storage-interface/spec/blob/master/spec.md),CSI 试图建立一个行业标准接口的规范,借助 CSI 容器编排系统(CO)可以将任意存储系统暴露给自己的容器工作负载。有关详细信息,请查看[设计方案](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md)。 +容器存储接口(Container Storage Interface),简称 CSI,CSI 试图建立一个行业标准接口的规范,借助 CSI 容器编排系统(CO)可以将任意存储系统暴露给自己的容器工作负载。有关详细信息,请查看[设计方案](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md)。 `csi` 卷类型是一种 out-tree(即跟其它存储插件在同一个代码路径下,随 Kubernetes 的代码同时编译的) 的 CSI 卷插件,用于 Pod 与在同一节点上运行的外部 CSI 卷驱动程序交互。部署 CSI 兼容卷驱动后,用户可以使用 `csi` 作为卷类型来挂载驱动提供的存储。 @@ -134,4 +134,4 @@ Kubernetes 尽可能少地指定 CSI Volume 驱动程序的打包和部署规范 ## 参考 -- [Container Storage Interface (CSI)](https://github.com/container-storage-interface/spec/blob/master/spec.md) +- [Container Storage Interface (CSI) - github.com](https://github.com/container-storage-interface/spec/blob/master/spec.md) diff --git a/concepts/etcd.md b/concepts/etcd.md index d9306b083..9163d3b2e 100644 --- a/concepts/etcd.md +++ b/concepts/etcd.md @@ -1,23 +1,23 @@ -# Etcd解析 +# Etcd 解析 -Etcd是Kubernetes集群中的一个十分重要的组件,用于保存集群所有的网络配置和对象的状态信息。在后面具体的安装环境中,我们安装的etcd的版本是v3.1.5,整个kubernetes系统中一共有两个服务需要用到etcd用来协同和存储配置,分别是: +Etcd 是 Kubernetes 集群中的一个十分重要的组件,用于保存集群所有的网络配置和对象的状态信息。在后面具体的安装环境中,我们安装的 etcd 的版本是 v3.1.5,整个 Kubernetes 系统中一共有两个服务需要用到 etcd 用来协同和存储配置,分别是: -- 网络插件flannel、对于其它网络插件也需要用到etcd存储网络的配置信息 -- kubernetes本身,包括各种对象的状态和元信息配置 +- 网络插件 flannel、对于其它网络插件也需要用到 etcd 存储网络的配置信息 +- Kubernetes 本身,包括各种对象的状态和元信息配置 -**注意**:flannel操作etcd使用的是v2的API,而kubernetes操作etcd使用的v3的API,所以在下面我们执行`etcdctl`的时候需要设置`ETCDCTL_API`环境变量,该变量默认值为2。 +**注意**:flannel 操作 etcd 使用的是 v2 的 API,而 Kubernetes 操作 etcd 使用的 v3 的 API,所以在下面我们执行 `etcdctl` 的时候需要设置 `ETCDCTL_API` 环境变量,该变量默认值为 2。 ## 原理 -Etcd使用的是raft一致性算法来实现的,是一款分布式的一致性KV存储,主要用于共享配置和服务发现。关于raft一致性算法请参考[该动画演示](http://thesecretlivesofdata.com/raft/)。 +Etcd 使用的是 raft 一致性算法来实现的,是一款分布式的一致性 KV 存储,主要用于共享配置和服务发现。关于 raft 一致性算法请参考 [该动画演示](http://thesecretlivesofdata.com/raft/)。 -关于Etcd的原理解析请参考[Etcd 架构与实现解析](http://jolestar.com/etcd-architecture/)。 +关于 Etcd 的原理解析请参考 [Etcd 架构与实现解析](http://jolestar.com/etcd-architecture/)。 -## 使用Etcd存储Flannel网络信息 +## 使用 Etcd 存储 Flannel 网络信息 -我们在安装Flannel的时候配置了`FLANNEL_ETCD_PREFIX="/kube-centos/network"`参数,这是Flannel查询etcd的目录地址。 +我们在安装 Flannel 的时候配置了 `FLANNEL_ETCD_PREFIX="/kube-centos/network"` 参数,这是 Flannel 查询 etcd 的目录地址。 -查看Etcd中存储的flannel网络信息: +查看 Etcd 中存储的 flannel 网络信息: ```ini $ etcdctl --ca-file=/etc/kubernetes/ssl/ca.pem --cert-file=/etc/kubernetes/ssl/kubernetes.pem --key-file=/etc/kubernetes/ssl/kubernetes-key.pem ls /kube-centos/network -r @@ -27,19 +27,15 @@ $ etcdctl --ca-file=/etc/kubernetes/ssl/ca.pem --cert-file=/etc/kubernetes/ssl/k /kube-centos/network/subnets/172.30.31.0-24 /kube-centos/network/subnets/172.30.20.0-24 /kube-centos/network/subnets/172.30.23.0-24 -``` - -查看flannel的配置: - -```bash +```查看 flannel 的配置:```bash $ etcdctl --ca-file=/etc/kubernetes/ssl/ca.pem --cert-file=/etc/kubernetes/ssl/kubernetes.pem --key-file=/etc/kubernetes/ssl/kubernetes-key.pem get /kube-centos/network/config 2018-01-19 18:38:22.768145 I | warning: ignoring ServerName for user-provided CA for backwards compatibility is deprecated -{ "Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "host-gw" } } +{"Network": "172.30.0.0/16", "SubnetLen": 24, "Backend": { "Type": "host-gw"} } ``` -## 使用Etcd存储Kubernetes对象信息 +## 使用 Etcd 存储 Kubernetes 对象信息 -Kubernetes使用etcd v3的API操作etcd中的数据。所有的资源对象都保存在`/registry`路径下,如下: +Kubernetes 使用 etcd v3 的 API 操作 etcd 中的数据。所有的资源对象都保存在 `/registry` 路径下,如下: ```ini ThirdPartyResourceData @@ -77,28 +73,28 @@ storageclasses thirdpartyresources ``` -如果你还创建了CRD(自定义资源定义),则在此会出现CRD的API。 +如果你还创建了 CRD(自定义资源定义),则在此会出现 CRD 的 API。 -### 查看集群中所有的Pod信息 +### 查看集群中所有的 Pod 信息 -例如我们直接从etcd中查看kubernetes集群中所有的pod的信息,可以使用下面的命令: +例如我们直接从 etcd 中查看 kubernetes 集群中所有的 pod 的信息,可以使用下面的命令: ```bash ETCDCTL_API=3 etcdctl get /registry/pods --prefix -w json|python -m json.tool ``` -此时将看到json格式输出的结果,其中的`key`使用了`base64`编码,关于etcdctl命令的详细用法请参考[使用etcdctl访问kubernetes数据](../guide/using-etcdctl-to-access-kubernetes-data.md)。 +此时将看到 json 格式输出的结果,其中的`key`使用了`base64` 编码,关于 etcdctl 命令的详细用法请参考 [使用 etcdctl 访问 kubernetes 数据](../guide/using-etcdctl-to-access-kubernetes-data.md)。 -## Etcd V2与V3版本API的区别 +## Etcd V2 与 V3 版本 API 的区别 -Etcd V2和V3之间的数据结构完全不同,互不兼容,也就是说使用V2版本的API创建的数据只能使用V2的API访问,V3的版本的API创建的数据只能使用V3的API访问。这就造成我们访问etcd中保存的flannel的数据需要使用`etcdctl`的V2版本的客户端,而访问kubernetes的数据需要设置`ETCDCTL_API=3`环境变量来指定V3版本的API。 +Etcd V2 和 V3 之间的数据结构完全不同,互不兼容,也就是说使用 V2 版本的 API 创建的数据只能使用 V2 的 API 访问,V3 的版本的 API 创建的数据只能使用 V3 的 API 访问。这就造成我们访问 etcd 中保存的 flannel 的数据需要使用 `etcdctl` 的 V2 版本的客户端,而访问 kubernetes 的数据需要设置 `ETCDCTL_API=3` 环境变量来指定 V3 版本的 API。 -## Etcd数据备份 +## Etcd 数据备份 -我们安装的时候指定的Etcd数据的存储路径是`/var/lib/etcd`,一定要对该目录做好备份。 +我们安装的时候指定的 Etcd 数据的存储路径是 `/var/lib/etcd`,一定要对该目录做好备份。 ## 参考 -- [etcd官方文档](https://coreos.com/etcd/docs/latest) -- [etcd v3命令和API](http://blog.csdn.net/u010278923/article/details/71727682) -- [Etcd 架构与实现解析](http://jolestar.com/etcd-architecture/) +- [etcd 官方文档 - etcd.io](https://etcd.io/) +- [etcd v3 命令和 API - blog.csdn.net](http://blog.csdn.net/u010278923/article/details/71727682) +- [Etcd 架构与实现解析 - jolestar.com](http://jolestar.com/etcd-architecture/) diff --git a/concepts/flannel.md b/concepts/flannel.md index e66be9843..61c9e2204 100644 --- a/concepts/flannel.md +++ b/concepts/flannel.md @@ -1,6 +1,6 @@ -# Kubernetes中的网络解析——以flannel为例 +# 扁平网络 Flannel -我们当初使用[kubernetes-vagrant-centos-cluster](https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster)安装了拥有三个节点的kubernetes集群,节点的状态如下所述。 +如果你使用 [kubernetes-vagrant-centos-cluster](https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster) 安装了拥有三个节点的 Kubernetes 集群,节点的状态如下所述。 ```bash [root@node1 ~]# kubectl get nodes -o wide @@ -10,7 +10,7 @@ node2 Ready 2d v1.9.1 CentOS Linux 7 ( node3 Ready 2d v1.9.1 CentOS Linux 7 (Core) 3.10.0-693.11.6.el7.x86_64 docker://1.12.6 ``` -当前Kubernetes集群中运行的所有Pod信息: +当前 Kubernetes 集群中运行的所有 Pod 信息: ```bash [root@node1 ~]# kubectl get pods --all-namespaces -o wide @@ -22,7 +22,7 @@ kube-system kubernetes-dashboard-6b66b8b96c-mnm2c 1/1 Runnin kube-system monitoring-influxdb-grafana-v4-54b7854697-tw9cd 2/2 Running 2 1h 172.33.96.2 node3 ``` -当前etcd中的注册的宿主机的pod地址网段信息: +当前 etcd 中的注册的宿主机的 pod 地址网段信息: ```bash [root@node1 ~]# etcdctl ls /kube-centos/network/subnets @@ -31,35 +31,35 @@ kube-system monitoring-influxdb-grafana-v4-54b7854697-tw9cd 2/2 Runnin /kube-centos/network/subnets/172.33.96.0-24 ``` -而每个node上的Pod子网是根据我们在安装flannel时配置来划分的,在etcd中查看该配置: +而每个 node 上的 Pod 子网是根据我们在安装 flannel 时配置来划分的,在 etcd 中查看该配置: ```bash [root@node1 ~]# etcdctl get /kube-centos/network/config {"Network":"172.33.0.0/16","SubnetLen":24,"Backend":{"Type":"host-gw"}} ``` -我们知道Kubernetes集群内部存在三类IP,分别是: +我们知道 Kubernetes 集群内部存在三类 IP,分别是: -- Node IP:宿主机的IP地址 -- Pod IP:使用网络插件创建的IP(如flannel),使跨主机的Pod可以互通 -- Cluster IP:虚拟IP,通过iptables规则访问服务 +- Node IP:宿主机的 IP 地址 +- Pod IP:使用网络插件创建的 IP(如 flannel),使跨主机的 Pod 可以互通 +- Cluster IP:虚拟 IP,通过 iptables 规则访问服务 -在安装node节点的时候,节点上的进程是按照flannel -> docker -> kubelet -> kube-proxy的顺序启动的,我们下面也会按照该顺序来讲解,flannel的网络划分和如何与docker交互,如何通过iptables访问service。 +在安装 node 节点的时候,节点上的进程是按照 flannel -> docker -> kubelet -> kube-proxy 的顺序启动的,我们下面也会按照该顺序来讲解,flannel 的网络划分和如何与 docker 交互,如何通过 iptables 访问 service。 ### Flannel -Flannel是作为一个二进制文件的方式部署在每个node上,主要实现两个功能: +Flannel 是作为一个二进制文件的方式部署在每个 node 上,主要实现两个功能: -- 为每个node分配subnet,容器将自动从该子网中获取IP地址 -- 当有node加入到网络中时,为每个node增加路由配置 +- 为每个 node 分配 subnet,容器将自动从该子网中获取 IP 地址 +- 当有 node 加入到网络中时,为每个 node 增加路由配置 -下面是使用`host-gw` backend的flannel网络架构图: +下面是使用 `host-gw` backend 的 flannel 网络架构图: -![flannel网络架构(图片来自openshift)](../images/flannel-networking.png) +![flannel 网络架构(图片来自 openshift)](../images/flannel-networking.png) -**注意**:以上IP非本示例中的IP,但是不影响读者理解。 +**注意**:以上 IP 非本示例中的 IP,但是不影响读者理解。 -Node1上的flannel配置如下: +Node1 上的 flannel 配置如下: ```bash [root@node1 ~]# cat /usr/lib/systemd/system/flanneld.service @@ -94,7 +94,7 @@ FLANNEL_ETCD_PREFIX="/kube-centos/network" FLANNEL_OPTIONS="-iface=eth2" ``` -上面的配置文件仅供flanneld使用。 +上面的配置文件仅供 flanneld 使用。 ```bash [root@node1 ~]# cat /etc/sysconfig/docker-network @@ -102,24 +102,24 @@ FLANNEL_OPTIONS="-iface=eth2" DOCKER_NETWORK_OPTIONS= ``` -还有一个`ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker`,其中的`/usr/libexec/flannel/mk-docker-opts.sh`脚本是在flanneld启动后运行,将会生成两个环境变量配置文件: +还有一个`ExecStartPost=/usr/libexec/flannel/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker`,其中的`/usr/libexec/flannel/mk-docker-opts.sh` 脚本是在 flanneld 启动后运行,将会生成两个环境变量配置文件: - /run/flannel/docker - /run/flannel/subnet.env -我们再来看下`/run/flannel/docker`的配置。 +我们再来看下 `/run/flannel/docker` 的配置。 ```bash [root@node1 ~]# cat /run/flannel/docker DOCKER_OPT_BIP="--bip=172.33.68.1/24" DOCKER_OPT_IPMASQ="--ip-masq=true" DOCKER_OPT_MTU="--mtu=1500" -DOCKER_NETWORK_OPTIONS=" --bip=172.33.68.1/24 --ip-masq=true --mtu=1500" +DOCKER_NETWORK_OPTIONS="--bip=172.33.68.1/24 --ip-masq=true --mtu=1500" ``` -如果你使用`systemctl`命令先启动flannel后启动docker的话,docker将会读取以上环境变量。 +如果你使用`systemctl` 命令先启动 flannel 后启动 docker 的话,docker 将会读取以上环境变量。 -我们再来看下`/run/flannel/subnet.env`的配置。 +我们再来看下 `/run/flannel/subnet.env` 的配置。 ```bash [root@node1 ~]# cat /run/flannel/subnet.env @@ -129,11 +129,11 @@ FLANNEL_MTU=1500 FLANNEL_IPMASQ=false ``` -以上环境变量是flannel向etcd中注册的。 +以上环境变量是 flannel 向 etcd 中注册的。 ### Docker -Node1的docker配置如下: +Node1 的 docker 配置如下: ```bash [root@node1 ~]# cat /usr/lib/systemd/system/docker.service @@ -179,7 +179,7 @@ KillMode=process WantedBy=multi-user.target ``` -查看Node1上的docker启动参数: +查看 Node1 上的 docker 启动参数: ```bash [root@node1 ~]# systemctl status -l docker @@ -194,9 +194,9 @@ WantedBy=multi-user.target ‣ 4334 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --selinux-enabled --log-driver=journald --signature-verification=false --bip=172.33.68.1/24 --ip-masq=true --mtu=1500 ``` -我们可以看到在docker在启动时有如下参数:`--bip=172.33.68.1/24 --ip-masq=true --mtu=1500`。上述参数flannel启动时运行的脚本生成的,通过环境变量传递过来的。 +我们可以看到在 docker 在启动时有如下参数:`--bip=172.33.68.1/24 --ip-masq=true --mtu=1500`。上述参数 flannel 启动时运行的脚本生成的,通过环境变量传递过来的。 -我们查看下node1宿主机上的网络接口: +我们查看下 node1 宿主机上的网络接口: ```bash [root@node1 ~]# ip addr @@ -237,13 +237,13 @@ WantedBy=multi-user.target 我们分类来解释下该虚拟机中的网络接口。 - lo:回环网络,127.0.0.1 -- eth0:NAT网络,虚拟机创建时自动分配,仅可以在几台虚拟机之间访问 -- eth1:bridge网络,使用vagrant分配给虚拟机的地址,虚拟机之间和本地电脑都可以访问 -- eth2:bridge网络,使用DHCP分配,用于访问互联网的网卡 -- docker0:bridge网络,docker默认使用的网卡,作为该节点上所有容器的虚拟交换机 -- veth295bef2@if6:veth pair,连接docker0和Pod中的容器。veth pair可以理解为使用网线连接好的两个接口,把两个端口放到两个namespace中,那么这两个namespace就能打通。参考[linux 网络虚拟化: network namespace 简介](http://cizixs.com/2017/02/10/network-virtualization-network-namespace)。 +- eth0:NAT 网络,虚拟机创建时自动分配,仅可以在几台虚拟机之间访问 +- eth1:bridge 网络,使用 vagrant 分配给虚拟机的地址,虚拟机之间和本地电脑都可以访问 +- eth2:bridge 网络,使用 DHCP 分配,用于访问互联网的网卡 +- docker0:bridge 网络,docker 默认使用的网卡,作为该节点上所有容器的虚拟交换机 +- veth295bef2@if6:veth pair,连接 docker0 和 Pod 中的容器。veth pair 可以理解为使用网线连接好的两个接口,把两个端口放到两个 namespace 中,那么这两个 namespace 就能打通。参考 [linux 网络虚拟化: network namespace 简介](http://cizixs.com/2017/02/10/network-virtualization-network-namespace)。 -我们再看下该节点的docker上有哪些网络。 +我们再看下该节点的 docker 上有哪些网络。 ```bash [root@node1 ~]# docker network ls @@ -253,7 +253,7 @@ d94c046e105d host host local 2db7597fd546 none null local ``` -再检查下bridge网络`940bb75e653b`的信息。 +再检查下 bridge 网络`940bb75e653b`的信息。 ```bash [root@node1 ~]# docker network inspect 940bb75e653b @@ -292,14 +292,13 @@ d94c046e105d host host local "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, - "Labels": {} - } + "Labels": {}} ] ``` -我们可以看到该网络中的`Config`与docker的启动配置相符。 +我们可以看到该网络中的`Config` 与 docker 的启动配置相符。 -Node1上运行的容器: +Node1 上运行的容器: ```bash [root@node1 ~]# docker ps @@ -308,9 +307,9 @@ a37407a234dd docker.io/coredns/coredns@sha256:adf2e5b4504ef9ffa43f16010bd 944d4aa660e3 docker.io/openshift/origin-pod "/usr/bin/pod" About an hour ago Up About an hour k8s_POD_coredns-5984fb8cbb-sjqv9_kube-system_c5a2e959-082a-11e8-b4cd-525400005732_0 ``` -我们可以看到当前已经有2个容器在运行。 +我们可以看到当前已经有 2 个容器在运行。 -Node1上的路由信息: +Node1 上的路由信息: ```bash [root@node1 ~]# route -n @@ -325,9 +324,9 @@ Destination Gateway Genmask Flags Metric Ref Use Iface 172.33.96.0 172.30.118.65 255.255.255.0 UG 0 0 0 eth2 ``` -以上路由信息是由flannel添加的,当有新的节点加入到Kubernetes集群中后,每个节点上的路由表都将增加。 +以上路由信息是由 flannel 添加的,当有新的节点加入到 Kubernetes 集群中后,每个节点上的路由表都将增加。 -我们在node上来`traceroute`下node3上的`coredns-5984fb8cbb-tkfrc`容器,其IP地址是`172.33.96.3`,看看其路由信息。 +我们在 node 上来 `traceroute` 下 node3 上的 `coredns-5984fb8cbb-tkfrc` 容器,其 IP 地址是 `172.33.96.3`,看看其路由信息。 ```bash [root@node1 ~]# traceroute 172.33.96.3 @@ -336,9 +335,9 @@ traceroute to 172.33.96.3 (172.33.96.3), 30 hops max, 60 byte packets 2 172.33.96.3 (172.33.96.3) 0.451 ms 0.352 ms 0.223 ms ``` -我们看到路由直接经过node3的公网IP后就到达了node3节点上的Pod。 +我们看到路由直接经过 node3 的公网 IP 后就到达了 node3 节点上的 Pod。 -Node1的iptables信息: +Node1 的 iptables 信息: ```bash [root@node1 ~]# iptables -L @@ -370,24 +369,24 @@ RETURN all -- anywhere anywhere Chain KUBE-FIREWALL (2 references) target prot opt source destination -DROP all -- anywhere anywhere /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000 +DROP all -- anywhere anywhere /* kubernetes firewall for dropping marked packets */mark match 0x8000/0x8000 Chain KUBE-FORWARD (1 references) target prot opt source destination -ACCEPT all -- anywhere anywhere /* kubernetes forwarding rules */ mark match 0x4000/0x4000 -ACCEPT all -- 10.254.0.0/16 anywhere /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED -ACCEPT all -- anywhere 10.254.0.0/16 /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED +ACCEPT all -- anywhere anywhere /* kubernetes forwarding rules */mark match 0x4000/0x4000 +ACCEPT all -- 10.254.0.0/16 anywhere /* kubernetes forwarding conntrack pod source rule */ctstate RELATED,ESTABLISHED +ACCEPT all -- anywhere 10.254.0.0/16 /* kubernetes forwarding conntrack pod destination rule */ctstate RELATED,ESTABLISHED Chain KUBE-SERVICES (2 references) target prot opt source destination ``` -从上面的iptables中可以看到注入了很多Kuberentes service的规则。 +从上面的 iptables 中可以看到注入了很多 Kuberentes service 的规则。 ## 参考 - [coreos/flannel - github.com](https://github.com/coreos/flannel) -- [linux 网络虚拟化: network namespace 简介](http://cizixs.com/2017/02/10/network-virtualization-network-namespace) -- [Linux虚拟网络设备之veth](https://segmentfault.com/a/1190000009251098) -- [flannel host-gw network](http://hustcat.github.io/flannel-host-gw-network/) +- [Linux 网络虚拟化:network namespace 简介 - cizixs.com](http://cizixs.com/2017/02/10/network-virtualization-network-namespace) +- [Linux 虚拟网络设备之 veth - segmentfault.com](https://segmentfault.com/a/1190000009251098) +- [flannel host-gw network - hustcat.github.io](http://hustcat.github.io/flannel-host-gw-network/) - [flannel - openshift.com](https://docs.openshift.com/container-platform/3.4/architecture/additional_concepts/flannel.html) diff --git a/concepts/gateway.md b/concepts/gateway.md new file mode 100644 index 000000000..4516abdae --- /dev/null +++ b/concepts/gateway.md @@ -0,0 +1,210 @@ +# Gateway + +除了直接使用 Service 和 Ingress 之外,Kubernetes 社区还发起了 [Gateway API 项目](https://github.com/kubernetes-sigs/gateway-api),这是一个 CRD,可以帮助我们将 Kubernetes 中的服务暴露到集群外。 + +Gateway API 是一个由 [SIG-NETWORK](https://github.com/kubernetes/community/tree/master/sig-network) 管理的开源项目。该项目的目标是在 Kubernetes 生态系统中发展服务网络 API。Gateway API 提供了暴露 Kubernetes 应用的接口 ——Service、Ingress 等。 + +该 API 在 Istio 中也被应用,用于将 Kubernetes 中的服务暴露到服务网格之外。 + +## 目标 + +Gateway API 旨在通过提供表现性的、可扩展的、面向角色的接口来改善服务网络,这些接口由许多厂商实现,并得到了业界的广泛支持。 + +Gateway API 是一个 API 资源的集合 —— Service、GatewayClass、Gateway、HTTPRoute、TCPRoute 等。使用这些资源共同为各种网络用例建模。 + +下图中展示的是 Kubernetes 集群中四层和七层的网络配置。从图中可以看到通过将这些资源对象分离,可以实现配置上的解耦,由不同角色的人员来管理。 + +![Kubernetes Gateway API 简介](../images/kubernetes-gateway-api-intro.jpg) + +## Gateway 相较于 Ingress 做了哪些改进? + +**更具表现力** + +Gateway 表达了更多的核心功能,比如基于头的匹配、流量加权和其他功能,而这些功能在 Ingress 中只能通过自定义方式实现。 + +**更具扩展性** + +Gateway API 允许在 API 的各个层次上链接自定义资源。这就允许在 API 结构的适当位置进行更精细的定制。 + +**面向角色** + +它们被分离成不同的 API 资源,这些资源映射到 Kubernetes 上运行应用程序的常见角色。 + +**通用性** + +这不是一种改进,而是应该保持不变。正如 Ingress 是一个具有众多实现的通用规范一样,Gateway API 被设计成一个由许多实现支持的可移植规范。 + +**共享网关** + +它们允许独立的路由资源绑定到同一个网关,从而实现负载均衡器和 VIP 的共享。这允许团队安全地共享基础设施,而不需要直接协调。 + +**类型化后端引用** + +通过类型化后端引用,Routes 可以引用 Kubernetes 服务,也可以引用任何一种被设计为 Gateway 后端的 Kubernetes 资源。 + +**跨命名空间引用** + +跨越不同 Namespaces 的路由可以绑定到网关。这样,尽管对工作负载进行了命名空间划分,但仍可共享网络基础设施。 + +**类** + +`GatewayClasses` 将负载均衡实现的类型形式化。这些类使用户可以很容易和明确地了解资源模型本身有什么样的能力。 + +在了解了 Gateway API 的目的后,接下来我们再看下它的资源模型、请求流程、TLS 配置及扩展点等。 + +## 角色 + +Gateway API 开发者为其使用场景定义四类角色: + +- 基础设施提供方:如 AWS、GKE 等 +- 集群运维:管理整个集群的计算、存储、网络、安全等 +- 应用程序开发者:为自己开发的应用负责,管理应用的健壮性 +- 应用管理员:不是所有的公司都有,通常在一些复杂系统中会有专门的应用管理员 + +## 资源模型 + +注意:资源最初将作为 CRD 存在于 `networking.x-k8s.io` API 组中。未限定的资源名称将隐含在该 API 组中。 + +Gateway API 的资源模型中,主要有三种类型的对象: + +- `GatewayClass`:定义了一组具有共同配置和行为的网关。 +- `Gateway`:请求一个点,在这个点上,流量可以被翻译到集群内的服务。 +- `Route`:描述了通过 Gateway 而来的流量如何映射到服务。 + +### GatewayClass + +`GatewayClass` 定义了一组共享共同配置和行为的 Gateway,每个 `GatewayClass` 由一个控制器处理,但控制器可以处理多个 `GatewayClass`。 + +`GatewayClass` 是一个集群范围的资源。必须至少定义一个 `GatewayClass`,`Gateway` 才能够生效。实现 Gateway API 的控制器通过关联的 `GatewayClass` 资源来实现,用户可以在自己的 `Gateway` 中引用该资源。 + +这类似于 `Ingress` 的 [`IngressClass`](https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/20190125-ingress-api-group.md#ingress-class) 和 `PersistentVolumes` 的 [`StorageClass`](https://kubernetes.io/docs/concepts/storage/storage-classes/)。在 `Ingress` v1beta1 中,最接近 `GatewayClass` 的是 `ingress-class` 注解,而在 IngressV1 中,最接近的类似物是 `IngressClass` 对象。 + +### Gateway + +`Gateway` 描述了如何将流量翻译到集群内的服务。也就是说,它定义了一个方法,将流量从不了解 Kubernetes 的地方翻译到了解 Kubernetes 的地方。例如,由云负载均衡器、集群内代理或外部硬件负载均衡器发送到 Kubernetes 服务的流量。虽然许多用例的客户端流量源自集群的 "外部",但这并不强求。 + +`Gateway` 定义了对实现 `GatewayClass` 配置和行为合同的特定负载均衡器配置的请求。该资源可以由运维人员直接创建,也可以由处理 `GatewayClass` 的控制器创建。 + +由于 `Gateway` 规范捕获了用户意图,它可能不包含规范中所有属性的完整规范。例如,用户可以省略地址、端口、TLS 设置等字段。这使得管理 `GatewayClass` 的控制器可以为用户提供这些设置,从而使规范更加可移植。这种行为将通过 `GatewayClass` 状态对象来明确。 + +一个 `Gateway` 可以包含一个或多个 `Route` 引用,这些 `Route` 引用的作用是将一个子集的流量引导到一个特定的服务上。 + +### {HTTP,TCP,Foo} Route + +`Route` 对象定义了特定协议的规则,用于将请求从 `Gateway` 映射到 Kubernetes 服务。 + +`HTTPRoute` 和 `TCPRoute` 是目前唯一已定义的 `Route` 对象。未来可能会添加其他特定协议的 `Route` 对象。 + +### BackendPolicy + +`BackendPolicy` 提供了一种配置 `Gateway` 和后端之间连接的方法。在这个 API 中,后端是指路由可以转发流量的任何资源。后端的一个常见例子是 `Service`。这个级别的配置目前仅限于 TLS,但将来会扩展到支持更高级的策略,如健康检查。 + +一些后端配置可能会根据针对后端的 `Route` 而有所不同。在这些情况下,配置字段将放在 `Route` 上,而不是 `BackendPolicy` 上。有关该资源未来可能配置的更多信息,请参考相关的 [GitHub issue](https://github.com/kubernetes-sigs/gateway-apis/issues/196)。 + +### 路由绑定 + +当 `Route` 绑定到 `Gateway` 时,代表应用在 `Gateway` 上的配置,配置了底层的负载均衡器或代理。哪些 `Route` 如何绑定到 `Gateway` 是由资源本身控制的。`Route` 和 `Gateway` 资源具有内置的控制,以允许或限制它们之间如何相互选择。这对于强制执行组织政策以确定 `Route` 如何暴露以及在哪些 `Gateway` 上暴露非常有用。看下下面的例子。 + +一个 Kubernetes 集群管理员在 `Infra` 命名空间中部署了一个名为 `shared-gw` 的 `Gateway`,供不同的应用团队使用,以便将其应用暴露在集群之外。团队 A 和团队 B(分别在命名空间 "A" 和 "B" 中)将他们的 `Route` 绑定到这个 `Gateway`。它们互不相识,只要它们的 `Route` 规则互不冲突,就可以继续隔离运行。团队 C 有特殊的网络需求(可能是性能、安全或关键性),他们需要一个专门的 `Gateway` 来代理他们的应用到集群外。团队 C 在 "C" 命名空间中部署了自己的 `Gateway` `specialive-gw`,该 Gateway 只能由 "C" 命名空间中的应用使用。 + +不同命名空间及 `Gateway` 与 `Route` 的绑定关系如下图所示。 + +![路由绑定示意图](../images/gateway-api-route-binding.jpg) + +在如何将路由与网关绑定以实现不同的组织政策和责任范围方面,有很大的灵活性。下面是网关和路由之间可能的对应关系: + +- 一对一:网关和路由可以由一个所有者部署和使用,并具有一对一的关系。团队 C 就是一个例子。 +- 一对多:一个网关可以有许多路由与之绑定,这些路由由来自不同命名空间的不同团队所拥有。团队 A 和 B 就是这样的一个例子。 +- 多对一:路由也可以绑定到多个网关,允许一个路由同时控制不同 IP、负载均衡器或网络上的应用暴露。 + +总之,网关选择路由,路由控制它们的暴露。当网关选择一个允许自己暴露的路由时,那么该路由将与网关绑定。当路由与网关绑定时,意味着它们的集体路由规则被配置在了由该网关管理的底层负载均衡器或代理服务器上。因此,网关是一个网络数据平面的逻辑表示,可以通过路由进行配置。 + +#### 路由选择 + +`Gateway` 根据 `Route` 元数据,特别是 `Route` 资源的种类、命名空间和标签来选择 `Route`。`Route` 实际上被绑定到 `Gateway` 中的特定监听器上,因此每个监听器都有一个 `listener.routes` 字段,它通过以下一个或多个标准来选择 `Route`。 + +- **Label**:`Gateway` 可以通过资源上存在的标签来选择 `Route`(类似于 Service 通过 Pod 标签选择 Pod 的方式)。 +- **Kind**:网关监听器只能选择单一类型的路由资源。可以是 `HTTPRoute`、`TCPRoute` 或自定义 `Route` 类型。 +- **Namespace**:`Gateway` 还可以通过 `namespaces.from` 字段控制可以从哪些 `Namespace`、 `Route` 中选择。它支持三种可能的值。 + - `SameNamespace` 是默认选项。只有与该网关相同的命名空间中的路由才会被选择。 + - `All` 将选择来自所有命名空间的 `Route`。 + - `Selector` 意味着该网关将选择由 Namespace 标签选择器选择的 Namespace 子集的 Route。当使用 Selector 时,那么 `listeners.route.namespaces.selector` 字段可用于指定标签选择器。`All` 或 `SameNamespace` 不支持该字段。 + +下面的 `Gateway` 将在集群中的所有 `Namespace` 中选择 `expose: prod-web-gw` 的所有 `HTTPRoute` 资源。 + +```yaml +kind: Gateway +... +spec: + listeners: + - routes: + kind: HTTPRoute + selector: + matchLabels: + expose: prod-web-gw + namespaces: + from: All +``` + +#### 路由暴露 + +路由可以决定它们如何通过网关暴露。`gateways.allow` 字段支持三个值。 + +- `All`:如果没有指定,则是默认值。这使得所有的 `Route` 标签和 `Namespace` 选择器都绑定在网关上。 +- `SameNamespace` 只允许该路由与来自同一 `Namespace` 的网关绑定。 +- `FromList` 允许指定一个明确的网关列表,以便路由与之绑定。 + +下面的 `my-route` Route 只选择 `foo-namespace` 中的 `foo-gateway`,而不能与其他 `Gateway` 绑定。注意,`foo-gateway` 与 `my-route` 在不同的 Namespace 中。如果 `foo-gateway` 允许跨 `Namespace` 绑定,并且也选择了这个 `Route`,那么 `my-route` 就会与之绑定。 + +```yaml +kind: HTTPRoute +metadata: + name: my-route + namespace: bar-namespace +spec: + gateways: + allow: FromList + gatewayRefs: + - name: foo-gateway + namespace: foo-namespace +``` + +请注意,网关和路由的绑定是双向的。这意味着两个资源必须相互选择才能绑定。如果一个`Gateway`的`Route`标签选择器不匹配任何现有的`Route`,那么即使`Route`的`spec.gateways.allow = All`,也不会有任何东西与之绑定。同样,如果一个`Route`引用了一个特定的`Gateway`,但该`Gateway`没有选择`Route`的`Namespace`,那么它们也不会绑定。只有当两个资源相互选择时,才会发生绑定。 + +从资源规范中可能并不总是能明显看出哪些网关和路由是绑定的,但可以通过资源状态来确定绑定。路由状态将列出路由所绑定的所有网关以及绑定的任何相关条件。 + +### 组合类型 + +`GatewayClass`、Gateway、`xRoute` 和 `Service` 的组合将定义一个可实现的负载均衡器。下图说明了不同资源之间的关系。 + +![Gateway API 流程图](../images/gateway-api-request-flow.png) + +## 请求流程 + +使用反向代理实现的网关的一个典型的客户端 / 网关 API 请求流程是: + +- 客户端向 `http://foo.example.com` 发出请求。 +- DNS 将该名称解析为网关地址。 +- 反向代理在 `Listener` 上接收请求,并使用 [`Host` 头](https://tools.ietf.org/html/rfc7230#section-5.4) 来匹配 `HTTPRoute`。 +- 可选地,反向代理可以根据 `HTTPRoute` 的匹配规则执行请求头和 / 或路径匹配。 +- 可选地,反向代理可以根据 `HTTPRoute` 的过滤规则修改请求,即添加 / 删除头。 +- 最后,反向代理可以根据 `HTTPRoute` 的 `forwardTo` 规则,将请求转发到集群中的一个或多个对象,即 `Service`。 + +## TLS 配置 + +TLS 配置在 `Gateway` 监听器上。此外,对于某些自助服务用例,TLS 证书可以配置在路由对象上。 + +## 扩展点 + +API 中提供了一些扩展点,以灵活处理大量通用 API 无法处理的用例。 + +以下是 API 中扩展点的摘要。 + +- `XRouteMatch.ExtensionRef`:这个扩展点应该用来扩展特定核心 `Route` 的匹配语义。这是一个实验性的扩展点,未来会根据反馈进行迭代。 +- `XForwardTo.BackendRef`:这个扩展点应该用于将流量转发到核心 Kubernetes 服务资源以外的网络端点。例如 S3 bucket、Lambda 函数、文件服务器等。 +- `HTTPRouteFilter`:`HTTPRoute` 为这一 API 类型提供了一种方法,可以钩入 HTTP 请求的请求 / 响应生命周期。 +- 自定义路由:如果上述扩展点都不能满足用例的需求,实现者可以选择为目前 API 中不支持的协议创建自定义路由资源。 + +## 参考 + +- [kuberentes-sigs/gateway-api - github.com](https://github.com/kubernetes-sigs/gateway-api) diff --git a/concepts/kubernetes-service-api.md b/concepts/kubernetes-service-api.md deleted file mode 100644 index 143ce8ba7..000000000 --- a/concepts/kubernetes-service-api.md +++ /dev/null @@ -1,56 +0,0 @@ -# Kubernetes Service API - -除了直接使用 Service 和 Ingress 之外,Kubernetes 社区还发起了 Service API 项目,这是一个 CRD,可以帮助我们将 Kubernetes 中的服务暴露到集群外。 - -Service API 是一个由 [SIG-NETWORK](https://github.com/kubernetes/community/tree/master/sig-network) 管理的开源项目。该项目的目标是在 Kubernetes 生态系统中发展服务网络 API。Service API 提供了暴露 Kubernetes 应用的接口 ——Service、Ingress 等。你可以在 [Service API 的官网](https://kubernetes-sigs.github.io/service-apis/) 了解更多。 - -该 API 在 [Istio](https://kubernetes-sigs.github.io/service-apis/) 中也被应用,用于将 Kubernetes 中的服务暴露到服务网格之外。 - -## 目标 - -Service API 旨在通过提供表现性的、可扩展的、面向角色的接口来改善服务网络,这些接口由许多厂商实现,并得到了业界的广泛支持。 - -Service API 是一个 API 资源的集合 —— 服务、GatewayClass、Gateway、HTTPRoute、TCPRoute 等。使用这些资源共同为各种网络用例建模。 - -下图中展示的是 Kubernetes 集群中四层和七层的网络配置。从图中可以看到通过将这些资源对象分离,可以实现配置上的解耦,由不同角色的人员来管理。 - -![Kubernetes Service API 简介](../images/kubernetes-service-api-intro.jpg) - -## Service API 相较于 Ingress 做了哪些改进? - -**更具表现力** - -Service API 表达了更多的核心功能,比如基于头的匹配、流量加权和其他功能,而这些功能在 Ingress 中只能通过自定义方式实现。 - -**更具扩展性** - -Service API 允许在 API 的各个层次上链接自定义资源。这就允许在 API 结构的适当位置进行更精细的定制。 - -**面向角色** - -它们被分离成不同的 API 资源,这些资源映射到 Kubernetes 上运行应用程序的常见角色。 - -**通用性** - -这不是一种改进,而是应该保持不变。正如 Ingress 是一个具有众多实现的通用规范一样,Service API 被设计成一个由许多实现支持的可移植规范。 - -**共享网关** - -它们允许独立的路由资源绑定到同一个网关,从而实现负载均衡器和 VIP 的共享。这允许团队安全地共享基础设施,而不需要直接协调。 - -**类型化后端引用** - -通过类型化后端引用,Routes 可以引用 Kubernetes 服务,也可以引用任何一种被设计为 Gateway 后端的 Kubernetes 资源。 - -**跨命名空间引用** - -跨越不同 Namespaces 的路由可以绑定到网关。这样,尽管对工作负载进行了命名空间划分,但仍可共享网络基础设施。 - -**类** - -`GatewayClasses` 将负载均衡实现的类型形式化。这些类使用户可以很容易和明确地了解资源模型本身有什么样的能力。 - -## 参考 - -- [Kubernetes Service APIs - kubernetes-sigs.github.io](https://kubernetes-sigs.github.io/service-apis/) - diff --git a/concepts/networking.md b/concepts/networking.md index 798130b13..6b718a9cb 100644 --- a/concepts/networking.md +++ b/concepts/networking.md @@ -1,33 +1,33 @@ # 网络 -Kubernetes中的网络可以说对初次接触Kubernetes或者没有网络方面经验的人来说可能是其中最难的部分。Kubernetes本身并不提供网络功能,只是把网络接口开放出来,通过插件的形式实现。 +Kubernetes 中的网络可以说对初次接触 Kubernetes 或者没有网络方面经验的人来说可能是其中最难的部分。Kubernetes 本身并不提供网络功能,只是把网络接口开放出来,通过插件的形式实现。 ## 网络要解决的问题 -既然Kubernetes中将容器的联网通过插件的方式来实现,那么该如何解决容器的联网问题呢? +既然 Kubernetes 中将容器的联网通过插件的方式来实现,那么该如何解决容器的联网问题呢? -如果您在本地单台机器上运行docker容器的话会注意到所有容器都会处在`docker0`网桥自动分配的一个网络IP段内(172.17.0.1/16)。该值可以通过docker启动参数`--bip`来设置。这样所有本地的所有的容器都拥有了一个IP地址,而且还是在一个网段内彼此就可以互相通信了。 +如果您在本地单台机器上运行 docker 容器的话会注意到所有容器都会处在 `docker0` 网桥自动分配的一个网络 IP 段内(172.17.0.1/16)。该值可以通过 docker 启动参数 `--bip` 来设置。这样所有本地的所有的容器都拥有了一个 IP 地址,而且还是在一个网段内彼此就可以互相通信了。 -但是Kubernetes管理的是集群,Kubernetes中的网络要解决的核心问题就是每台主机的IP地址网段划分,以及单个容器的IP地址分配。概括为: +但是 Kubernetes 管理的是集群,Kubernetes 中的网络要解决的核心问题就是每台主机的 IP 地址网段划分,以及单个容器的 IP 地址分配。概括为: -- 保证每个Pod拥有一个集群内唯一的IP地址 -- 保证不同节点的IP地址划分不会重复 -- 保证跨节点的Pod可以互相通信 -- 保证不同节点的Pod可以与跨节点的主机互相通信 +- 保证每个 Pod 拥有一个集群内唯一的 IP 地址 +- 保证不同节点的 IP 地址划分不会重复 +- 保证跨节点的 Pod 可以互相通信 +- 保证不同节点的 Pod 可以与跨节点的主机互相通信 -为了解决该问题,出现了一系列开源的Kubernetes中的网络插件与方案,如: +为了解决该问题,出现了一系列开源的 Kubernetes 中的网络插件与方案,如: - flannel - calico - contiv -- weave net +- weave - kube-router - cilium - canal -还有很多就不一一列举了,只要实现Kubernetes官方的设计的[CNI - Container Network Interface(容器网络接口)](cni.md)就可以自己写一个网络插件。 +还有很多就不一一列举了(请见 [Awesome Cloud Native](https://jimmysong.io/awesome-cloud-native/#network)),只要实现 Kubernetes 官方的设计的 [CNI - Container Network Interface(容器网络接口)](cni.md) 就可以自己写一个网络插件。 -下面仅以当前最常用的flannel和calico插件为例解析。 +下面仅以当前最常用的 flannel 和 calico 插件为例解析。 -- [Kubernetes中的网络解析——以flannel为例](flannel.md) -- [Kubernetes中的网络解析——以calico为例](calico.md) +- [Kubernetes 中的网络:flannel](flannel.md) +- [Kubernetes 中的网络:calico](calico.md) \ No newline at end of file diff --git a/concepts/objects.md b/concepts/objects.md index b37abfa4f..7a0aa7a15 100644 --- a/concepts/objects.md +++ b/concepts/objects.md @@ -1,6 +1,6 @@ -# Objects +# Kubernetes 中的资源对象 -以下列举的内容都是 kubernetes 中的 Object,这些对象都可以在 yaml 文件中作为一种 API 类型来配置。 +以下列举的内容都是 Kubernetes 中的对象(Object),这些对象都可以在 YAML 文件中作为一种 API 类型来配置。 - Pod - Node @@ -37,7 +37,7 @@ | 策略对象 | SecurityContext、ResourceQuota、LimitRange | | 身份对象 | ServiceAccount、Role、ClusterRole | -## 理解 kubernetes 中的对象 +## 理解 Kubernetes 中的对象 在 Kubernetes 系统中,*Kubernetes 对象* 是持久化的条目。Kubernetes 使用这些条目去表示整个集群的状态。特别地,它们描述了如下信息: diff --git a/concepts/open-interfaces.md b/concepts/open-interfaces.md index 6d47b7202..0f8413775 100644 --- a/concepts/open-interfaces.md +++ b/concepts/open-interfaces.md @@ -1,11 +1,9 @@ # 开放接口 -Kubernetes作为云原生应用的基础调度平台,相当于云原生的操作系统,为了便于系统的扩展,Kubernetes中开放的以下接口,可以分别对接不同的后端,来实现自己的业务逻辑: +Kubernetes 作为云原生应用的基础调度平台,相当于云原生的操作系统,为了便于系统的扩展,Kubernetes 中开放的以下接口,可以分别对接不同的后端,来实现自己的业务逻辑: -- **CRI(Container Runtime Interface)**:容器运行时接口,提供计算资源 -- **CNI(Container Network Interface)**:容器网络接口,提供网络资源 -- **CSI(Container Storage Interface**):容器存储接口,提供存储资源 +- [容器运行时接口(CRI)](cri.md):提供计算资源 +- [容器网络接口(CNI)](cni.md):提供网络资源 +- [容器存储接口(CSI)](csi.md),提供存储资源 -以上三种资源相当于一个分布式操作系统的最基础的几种资源类型,而Kuberentes是将他们粘合在一起的纽带。 - -![开放接口](../images/open-interfaces.jpg) +以上三种资源相当于一个分布式操作系统的最基础的几种资源类型,而 Kuberentes 是将他们粘合在一起的纽带。 diff --git a/concepts/service-api-overview.md b/concepts/service-api-overview.md index 14f2033c0..e69de29bb 100644 --- a/concepts/service-api-overview.md +++ b/concepts/service-api-overview.md @@ -1,157 +0,0 @@ -# Service API 简介 - -在了解了 Service API 的 [目的](kubernetes-service-api.md) 后,接下来我们再看下它的资源模型、请求流程、TLS 配置及扩展点等。 - -## 角色 - -Service API 开发者为其使用场景定义四类角色: - -- 基础设施提供方:如 AWS、GKE 等 -- 集群运维:管理整个集群的计算、存储、网络、安全等 -- 应用程序开发者:为自己开发的应用负责,管理应用的健壮性 -- 应用管理员:不是所有的公司都有,通常在一些复杂系统中会有专门的应用管理员 - -## 资源模型 - -注意:资源最初将作为 CRD 存在于 `networking.x-k8s.io` API 组中。未限定的资源名称将隐含在该 API 组中。 - -Service API 的资源模型中,主要有三种类型的对象: - -- `GatewayClass`:定义了一组具有共同配置和行为的网关。 -- `Gateway`:请求一个点,在这个点上,流量可以被翻译到集群内的服务。 -- `Route`:描述了通过 Gateway 而来的流量如何映射到服务。 - -### GatewayClass - -`GatewayClass` 定义了一组共享共同配置和行为的 Gateway,每个 `GatewayClass` 由一个控制器处理,但控制器可以处理多个 `GatewayClass`。 - -`GatewayClass` 是一个集群范围的资源。必须至少定义一个 `GatewayClass`,`Gateway` 才能够生效。实现 Gateway API 的控制器通过关联的 `GatewayClass` 资源来实现,用户可以在自己的 `Gateway` 中引用该资源。 - -这类似于 `Ingress` 的 [`IngressClass`](https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/20190125-ingress-api-group.md#ingress-class) 和 `PersistentVolumes` 的 [`StorageClass`](https://kubernetes.io/docs/concepts/storage/storage-classes/)。在 `Ingress` v1beta1 中,最接近 `GatewayClass` 的是 `ingress-class` 注解,而在 IngressV1 中,最接近的类似物是 `IngressClass` 对象。 - -### Gateway - -`Gateway` 描述了如何将流量翻译到集群内的服务。也就是说,它定义了一个方法,将流量从不了解 Kubernetes 的地方翻译到了解 Kubernetes 的地方。例如,由云负载均衡器、集群内代理或外部硬件负载均衡器发送到 Kubernetes 服务的流量。虽然许多用例的客户端流量源自集群的 "外部",但这并不强求。 - -`Gateway` 定义了对实现 `GatewayClass` 配置和行为合同的特定负载均衡器配置的请求。该资源可以由运维人员直接创建,也可以由处理 `GatewayClass` 的控制器创建。 - -由于 `Gateway` 规范捕获了用户意图,它可能不包含规范中所有属性的完整规范。例如,用户可以省略地址、端口、TLS 设置等字段。这使得管理 `GatewayClass` 的控制器可以为用户提供这些设置,从而使规范更加可移植。这种行为将通过 `GatewayClass` 状态对象来明确。 - -一个 `Gateway` 可以包含一个或多个 `Route` 引用,这些 `Route` 引用的作用是将一个子集的流量引导到一个特定的服务上。 - -### {HTTP,TCP,Foo} Route - -`Route` 对象定义了特定协议的规则,用于将请求从 `Gateway` 映射到 Kubernetes 服务。 - -`HTTPRoute` 和 `TCPRoute` 是目前唯一已定义的 `Route` 对象。未来可能会添加其他特定协议的 `Route` 对象。 - -### BackendPolicy - -`BackendPolicy` 提供了一种配置 `Gateway` 和后端之间连接的方法。在这个 API 中,后端是指路由可以转发流量的任何资源。后端的一个常见例子是 `Service`。这个级别的配置目前仅限于 TLS,但将来会扩展到支持更高级的策略,如健康检查。 - -一些后端配置可能会根据针对后端的 `Route` 而有所不同。在这些情况下,配置字段将放在 `Route` 上,而不是 `BackendPolicy` 上。有关该资源未来可能配置的更多信息,请参考相关的 [GitHub issue](https://github.com/kubernetes-sigs/service-apis/issues/196)。 - -### 路由绑定 - -当 `Route` 绑定到 `Gateway` 时,代表应用在 `Gateway` 上的配置,配置了底层的负载均衡器或代理。哪些 `Route` 如何绑定到 `Gateway` 是由资源本身控制的。`Route` 和 `Gateway` 资源具有内置的控制,以允许或限制它们之间如何相互选择。这对于强制执行组织政策以确定 `Route` 如何暴露以及在哪些 `Gateway` 上暴露非常有用。看下下面的例子。 - -一个 Kubernetes 集群管理员在 `Infra` 命名空间中部署了一个名为 `shared-gw` 的 `Gateway`,供不同的应用团队使用,以便将其应用暴露在集群之外。团队 A 和团队 B(分别在命名空间 "A" 和 "B" 中)将他们的 `Route` 绑定到这个 `Gateway`。它们互不相识,只要它们的 `Route` 规则互不冲突,就可以继续隔离运行。团队 C 有特殊的网络需求(可能是性能、安全或关键性),他们需要一个专门的 `Gateway` 来代理他们的应用到集群外。团队 C 在 "C" 命名空间中部署了自己的 `Gateway` `specialive-gw`,该 Gateway 只能由 "C" 命名空间中的应用使用。 - -不同命名空间及 `Gateway` 与 `Route` 的绑定关系如下图所示。 - -![路由绑定示意图](../images/service-api-route-binding.jpg) - -在如何将路由与网关绑定以实现不同的组织政策和责任范围方面,有很大的灵活性。下面是网关和路由之间可能的对应关系: - -- 一对一:网关和路由可以由一个所有者部署和使用,并具有一对一的关系。团队 C 就是一个例子。 -- 一对多:一个网关可以有许多路由与之绑定,这些路由由来自不同命名空间的不同团队所拥有。团队 A 和 B 就是这样的一个例子。 -- 多对一:路由也可以绑定到多个网关,允许一个路由同时控制不同 IP、负载均衡器或网络上的应用暴露。 - -总之,网关选择路由,路由控制它们的暴露。当网关选择一个允许自己暴露的路由时,那么该路由将与网关绑定。当路由与网关绑定时,意味着它们的集体路由规则被配置在了由该网关管理的底层负载均衡器或代理服务器上。因此,网关是一个网络数据平面的逻辑表示,可以通过路由进行配置。 - -#### 路由选择 - -`Gateway` 根据 `Route` 元数据,特别是 `Route` 资源的种类、命名空间和标签来选择 `Route`。`Route` 实际上被绑定到 `Gateway` 中的特定监听器上,因此每个监听器都有一个 `listener.routes` 字段,它通过以下一个或多个标准来选择 `Route`。 - -- **Label**:`Gateway` 可以通过资源上存在的标签来选择 `Route`(类似于 Service 通过 Pod 标签选择 Pod 的方式)。 -- **Kind**:网关监听器只能选择单一类型的路由资源。可以是 `HTTPRoute`、`TCPRoute` 或自定义 `Route` 类型。 -- **Namespace**:`Gateway` 还可以通过 `namespaces.from` 字段控制可以从哪些 `Namespace`、 `Route` 中选择。它支持三种可能的值。 - - `SameNamespace` 是默认选项。只有与该网关相同的命名空间中的路由才会被选择。 - - `All` 将选择来自所有命名空间的 `Route`。 - - `Selector` 意味着该网关将选择由 Namespace 标签选择器选择的 Namespace 子集的 Route。当使用 Selector 时,那么 `listeners.route.namespaces.selector` 字段可用于指定标签选择器。`All` 或 `SameNamespace` 不支持该字段。 - -下面的 `Gateway` 将在集群中的所有 `Namespace` 中选择 `expose: prod-web-gw` 的所有 `HTTPRoute` 资源。 - -```yaml -kind: Gateway -... -spec: - listeners: - - routes: - kind: HTTPRoute - selector: - matchLabels: - expose: prod-web-gw - namespaces: - from: All -``` - -#### 路由暴露 - -路由可以决定它们如何通过网关暴露。`gateways.allow` 字段支持三个值。 - -- `All`:如果没有指定,则是默认值。这使得所有的 `Route` 标签和 `Namespace` 选择器都绑定在网关上。 -- `SameNamespace` 只允许该路由与来自同一 `Namespace` 的网关绑定。 -- `FromList` 允许指定一个明确的网关列表,以便路由与之绑定。 - -下面的 `my-route` Route 只选择 `foo-namespace` 中的 `foo-gateway`,而不能与其他 `Gateway` 绑定。注意,`foo-gateway` 与 `my-route` 在不同的 Namespace 中。如果 `foo-gateway` 允许跨 `Namespace` 绑定,并且也选择了这个 `Route`,那么 `my-route` 就会与之绑定。 - -```yaml -kind: HTTPRoute -metadata: - name: my-route - namespace: bar-namespace -spec: - gateways: - allow: FromList - gatewayRefs: - - name: foo-gateway - namespace: foo-namespace -``` - -请注意,网关和路由的绑定是双向的。这意味着两个资源必须相互选择才能绑定。如果一个`Gateway`的`Route`标签选择器不匹配任何现有的`Route`,那么即使`Route`的`spec.gateways.allow = All`,也不会有任何东西与之绑定。同样,如果一个`Route`引用了一个特定的`Gateway`,但该`Gateway`没有选择`Route`的`Namespace`,那么它们也不会绑定。只有当两个资源相互选择时,才会发生绑定。 - -从资源规范中可能并不总是能明显看出哪些网关和路由是绑定的,但可以通过资源状态来确定绑定。路由状态将列出路由所绑定的所有网关以及绑定的任何相关条件。 - -### 组合类型 - -`GatewayClass`、Gateway、`xRoute` 和 `Service` 的组合将定义一个可实现的负载均衡器。下图说明了不同资源之间的关系。 - -![Service API 流程图](../images/service-api-request-flow.png) - -## 请求流程 - -使用反向代理实现的网关的一个典型的客户端 / 网关 API 请求流程是: - -- 客户端向 `http://foo.example.com` 发出请求。 -- DNS 将该名称解析为网关地址。 -- 反向代理在 `Listener` 上接收请求,并使用 [`Host` 头](https://tools.ietf.org/html/rfc7230#section-5.4) 来匹配 `HTTPRoute`。 -- 可选地,反向代理可以根据 `HTTPRoute` 的匹配规则执行请求头和 / 或路径匹配。 -- 可选地,反向代理可以根据 `HTTPRoute` 的过滤规则修改请求,即添加 / 删除头。 -- 最后,反向代理可以根据 `HTTPRoute` 的 `forwardTo` 规则,将请求转发到集群中的一个或多个对象,即 `Service`。 - -## TLS 配置 - -TLS 配置在 `Gateway` 监听器上。此外,对于某些自助服务用例,TLS 证书可以配置在路由对象上。 - -## 扩展点 - -API 中提供了一些扩展点,以灵活处理大量通用 API 无法处理的用例。 - -以下是 API 中扩展点的摘要。 - -- `XRouteMatch.ExtensionRef`:这个扩展点应该用来扩展特定核心 `Route` 的匹配语义。这是一个实验性的扩展点,未来会根据反馈进行迭代。 -- `XForwardTo.BackendRef`:这个扩展点应该用于将流量转发到核心 Kubernetes 服务资源以外的网络端点。例如 S3 bucket、Lambda 函数、文件服务器等。 -- `HTTPRouteFilter`:`HTTPRoute` 为这一 API 类型提供了一种方法,可以钩入 HTTP 请求的请求 / 响应生命周期。 -- 自定义路由:如果上述扩展点都不能满足用例的需求,实现者可以选择为目前 API 中不支持的协议创建自定义路由资源。 - diff --git a/concepts/storage.md b/concepts/storage.md index eee7f4a7f..f0d936015 100644 --- a/concepts/storage.md +++ b/concepts/storage.md @@ -1,3 +1,9 @@ # 存储 -为了管理存储,Kubernetes提供了Secret用于管理敏感信息,ConfigMap存储配置,Volume、PV、PVC、StorageClass等用来管理存储卷。 +为了管理存储,Kubernetes 提供了以下资源对象: + +- Secret:用于管理敏感信息 +- ConfigMap:存储配置 +- Volume、PV、PVC、StorageClass 等:用来管理存储卷 + +本节将为你讲解 Kubernetes 中的存储对象。 diff --git a/images/calico-architecture.png b/images/calico-architecture.png new file mode 100644 index 000000000..98ae8359c Binary files /dev/null and b/images/calico-architecture.png differ diff --git a/images/calico.png b/images/calico.png deleted file mode 100644 index 36f8aab76..000000000 Binary files a/images/calico.png and /dev/null differ diff --git a/images/service-api-request-flow.png b/images/gateway-api-request-flow.png similarity index 100% rename from images/service-api-request-flow.png rename to images/gateway-api-request-flow.png diff --git a/images/service-api-route-binding.jpg b/images/gateway-api-route-binding.jpg similarity index 100% rename from images/service-api-route-binding.jpg rename to images/gateway-api-route-binding.jpg diff --git a/images/kubernetes-service-api-intro.jpg b/images/kubernetes-gateway-api-intro.jpg similarity index 100% rename from images/kubernetes-service-api-intro.jpg rename to images/kubernetes-gateway-api-intro.jpg diff --git a/images/open-interfaces.jpg b/images/open-interfaces.jpg deleted file mode 100644 index 703291865..000000000 Binary files a/images/open-interfaces.jpg and /dev/null differ diff --git a/practice/openkruise.md b/practice/openkruise.md index e8a039ac1..9d9c66827 100644 --- a/practice/openkruise.md +++ b/practice/openkruise.md @@ -1,12 +1,12 @@ # OpenKruise -[OpenKruise](https://openkruise.io/) 是阿里云开源的大规模应用自动化管理引擎,在 Kubernetes 原生 Deployment/StatefulSet 等控制器基础上,提供了更多的增强功能如: +[OpenKruise](https://openkruise.io/) 是阿里云开源的大规模应用自动化管理引擎,于 2021 年 12 月[发布 1.0](https://openkruise.io/zh/blog/openkruise-1.0) 。在 Kubernetes 原生 Deployment/StatefulSet 等控制器基础上,提供了更多的增强功能如: -- 优雅原地升级 -- 发布优先级/打散策略 -- 多可用区 workload 抽象管理 -- 统一 sidecar 容器注入管理等 -- 应用安全防护 +- **应用工作负载**:面向无状态、有状态、daemon 等多种类型应用的高级部署发布策略,例如原地升级、灰度流式发布等。 +- **Sidecar 容器管理**:支持独立定义 sidecar 容器,完成动态注入、独立原地升级、热升级等功能。 +- **增强运维能力**:包括容器原地重启、镜像预拉取、容器启动顺序保障等。 +- **应用分区管理**:管理应用在多个分区(可用区、不同机型等)上的部署比例、顺序、优先级等。 +- **应用安全防护**:帮助应用在 Kubernetes 之上获得更高的安全性保障与可用性防护。 这些控制器可以帮助开发者应对更加多样化的部署环境和需求、为集群维护者和应用开发者带来更加灵活的部署发布组合策略。