Skip to content

Commit 6ffed29

Browse files
committed
Add kubernetes network chapter
1 parent 9bbe854 commit 6ffed29

18 files changed

+274
-5
lines changed

images/7-1.png

195 KB
Loading

images/7-2.png

234 KB
Loading

images/7-3.png

186 KB
Loading

images/7-4.png

120 KB
Loading

images/7-5.png

182 KB
Loading

kubernetes/Kubernetes.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,15 @@
11
# 7.1 Kubernetes简介
22

3+
  Kubernetes是一款开源的容器编排系统。它源自谷歌内部的容器编排系统Borg所积累的十多年的经验。截至2018年初,Kubernetes被认为是容器编排领域事实上的行业标准,云原生领域的“Linux系统”。
4+
5+
  *我认为有关Kubernetes的诞生至少有两个重要时刻。第一次是在2014年6月7日,Joe Beda在GitHub上的最初[commit](https://github.com/kubernetes/kubernetes/commit/2c4b3a562ce34cddc3f8218a2c4d11c7310e6d56),它标志着项目开源的开始。第二个阶段是在一年后的2015年7月20日,当时谷歌推出了Kubernetes 1.0,并宣布组建一个专门的组织[云原生计算基金会(CNCF)](https://www.cncf.io)来主持和管理Kubernetes。我有幸参加了发布会,我可以告诉你,这无疑是庆祝项目诞生的一种方式。*
6+
7+
  Kubernetes的体系结构(图7-1)为许多工作负载提供支持,使您可以运行无状态以及有状态的容器化应用程序。您也可以启动伺服性服务,例如低延迟应用程序以及批处理作业。
8+
9+
![图7-1 Kubernetes架构](../images/7-1.png)
10+
11+
  Kubernetes的调度单位是一个pod。本质上,这是一组紧密耦合的一个或多个容器,它们总是并置在一起(即作为一个单元安排在一个节点上)。可以通过replicas控制器声明式地声明和执行以pod副本为模板的多个实例。所有资源(如pods,deployments,或者services)的逻辑组织都是通过标签选择器进行的。
12+
13+
  使用Kubernetes,您几乎总是可以选择使用某种开源或封闭源替代方法替换默认的实现,无论是DNS还是监控。Kubernetes具有高度的[可扩展性](https://kubernetes.io/docs/concepts/overview/extending/),从定义新的工作负载和资源类型到定制面向用户的部分都是可以的。
14+
15+
  本章假定您对Kubernetes及其术语有所了解。如果您需要了解关于Kubernetes如何运作的知识,我建议您查阅官方文档中的[Concepts部分](https://kubernetes.io/docs/concepts/)或Brendan Burns,Kelsey Hightower和Joe Beda撰写的[Kubernetes Up and Running(O'Reilly)](http://shop.oreilly.com/product/0636920043874.do)

kubernetes/advanced-networking.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
11
# 7.7 Kubernetes 中网络的高级主题
22

3+
  下面我将介绍两个与Kubernetes网络相关的高级主题:网络策略和服务网格。
4+
5+
## Network Policies
6+
7+
  Kubernetes中的[网络策略](https://kubernetes.io/docs/concepts/services-networking/network-policies/)允许您指定如何允许pod间彼此进行通信。Kubernetes 1.7及以上版本的网络策略被认为是稳定的,因此您可以在生产中使用它们。
8+
9+
  我们来看看具体的一个例子。例如,假设您想禁止所有通往superprivate namespace中所有pod的流量。您可以为该namespace创建默认的Egress策略,如下例所示:
10+
11+
```yaml
12+
apiVersion: networking.k8s.io/v1
13+
kind: NetworkPolicy
14+
metadata:
15+
name: bydefaultnoegress
16+
namespace: superprivate
17+
spec:
18+
podSelector: {}
19+
policyTypes:
20+
- Egress
21+
```
22+
23+
  请注意,不同的Kubernetes发行版在不同程度上支持网络策略:例如,在OpenShift中,它们作为一等公民受到支持,并且可以通过[redhat-cop/openshitoolkit](https://github.com/redhat-cop/openshift-toolkit/tree/master/networkpolicy) 找到一系列的示例。
24+
25+
  如果您想了解更多关于如何使用网络策略的信息,请查看Ahmet Alp Balkan的实用且详尽的博客“[Securing Kubernetes Cluster Networking](https://ahmet.im/blog/kubernetes-network-policy/)”.
26+
27+
## Service Meshes
28+
29+
  展望未来,您可以使用服务网格,例如下面所要讨论的两款服务网格方案。服务网格的想法是,开发人员不必把网络通信和控制的负担放到自己身上,而是将这些工作外包给服务网格。因此,您可以从流量控制,可观察性,安全性等方面受益,而无需对源代码进行任何的更改。是不是特别棒?
30+
31+
### Istio
32+
33+
  [Istio](https://istio.io)是目前最流行的服务网格,可用于Kubernetes,但不完全如此。它使用Envoy作为默认数据平面,它自己主要侧重于控制平面方面。仅举几例功能,它支持监视(Prometheus),跟踪(Zipkin/Jaeger),断路器,路由,负载平衡,故障注入,重试,超时,镜像,访问控制和速率限制等。Istio需要将Envoy代理作为sidecar容器部署在您的pod中。你可以通过Christian Posta的文章了解更多关于Istio的信息:[Deep Dive Envoy and Istio Workshop](http://blog.christianposta.com/microservices/deep-dive-envoy-and-istio-workshop/)。
34+
35+
### Conduit
36+
37+
  [Conduit](https://conduit.io)由作为数据平面(由Rust编写)的sidecar容器和管理这些代理的控制平面(用Go编写)组成,类似于Istio。在CNCF项目[Linkerd]之后,这是Buoyant关于服务网格思想的第二次迭代; 他们是这个领域的先锋,且在2016年建立了服务网格概念。通过Abhishek Tiwari的博客文章“[Getting started with Con‐ duit - lightweight service mesh for Kubernetes](https://abhishek-tiwari.com/getting-started-with-conduit-lightweight-service-mesh-for-kubernetes/)”了解更多信息。
38+
39+
  在我们结束本章和本书之前还有一点需要注意:服务网格还是很新的,所以你将其用于生产环境之前三思而行。

kubernetes/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# 7. Kubernetes网络
22

3+
  本章首先会简要Kubernetes,然后向您介绍Kubernetes中hight-level的网络概念。接下来我们将深入探讨Kubernetes如何实现容器网络,存在哪些流量类型以及如何在群集内彼此访问服务,以及如何让流量进入您的Kubernetes群集或访问特定的服务。

kubernetes/ingress-egress.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,71 @@
11
# 7.6 Ingress与Egress
22

3+
  下面我们将看看流量如何进出Kubernetes集群,也称为南北向流量。
4+
5+
## Ingress
6+
7+
  到目前为止,我们已经讨论了如何从群集内访问一个pod或service。从群集外部访问pod更具挑战性。Kubernetes旨在为服务提供高可用性,高性能负载平衡。
8+
9+
  最初,在Kubernetes中,南北向流量的唯一可用的方案是NodePort,现在LoadBalancer和ExternalName这些[方案](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types)也可供您使用。对于第7层流量(即HTTP),Ingress提供了更便携的方案,作为beta功能被引入Kubernetes 1.2,您可以使用Ingress将流量从外部世界路由到集群中的服务。
10+
11+
  Kubernetes中的[Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)的工作原理如图7-5所示:在概念上,它被分成两个主要部分,Ingress资源对象和一个Ingress控制器。Ingress资源对象定义了如何路由到后端service,Ingress控制器监听apiserver的/ingresses端点,了解正在创建或删除的service。一旦service的状态发送变化,Ingress控制器配置路由,以便外部流量落在集群内部的特定service。
12+
13+
![图7-5 Ingress](../images/7-5.png)
14+
15+
  以下示例展示了一个Ingress资源的具体示例,用于将myservice.example.com/somepath的请求路由到端口9876上名为service1的Kubernetes服务。
16+
17+
```yaml
18+
apiVersion: extensions/v1beta1
19+
kind: Ingress
20+
metadata:
21+
name: example-ingress
22+
spec:
23+
rules:
24+
- host: myservice.example.com
25+
http:
26+
paths:
27+
- path: /somepath
28+
backend:
29+
serviceName: service1
30+
servicePort: 9876
31+
```
32+
33+
  现在,Ingress资源定义好了,但是没有Ingress控制器,是没有任何反应的 所以让我们部署一个Ingress控制器,这里我们使用Minikube。
34+
35+
```bash
36+
$ minikube addons enable ingress
37+
```
38+
39+
  一旦您在Minikube上启用了Ingress,您应该会看到它在Minikube的附加组件列表中显示为已启用。一分钟左右后,两个新的pod将创建在kube-system namespace下。你现在可以使用ingress了,我们使用下面的yaml文件,它配置了一个NGINX web服务的路径。
40+
41+
```yaml
42+
$ cat nginx-ingress.yaml
43+
kind: Ingress
44+
apiVersion: extensions/v1beta1
45+
metadata:
46+
name: nginx-public
47+
annotations:
48+
ingress.kubernetes.io/rewrite-target: /
49+
spec:
50+
rules:
51+
- host:
52+
http:
53+
paths:
54+
- path: /web
55+
backend:
56+
serviceName: nginx
57+
servicePort: 80
58+
$ kubectl create -f nginx-ingress.yaml
59+
```
60+
61+
  现在NGINX通过IP地址192.168.99.100(这是我的Minikube IP)可用,yaml定义了它应该通过/web路径显示。
62+
63+
  请注意,Ingress控制器在技术上可以是任何能够进行反向代理的工具,但NGINX是最常用的。此外,Ingress还可以通过云厂商的负载均衡器(如亚马逊的[ALB](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html))实施。
64+
65+
  有关Ingress的更多详细信息,请阅读Mark Betz的文章“[Understanding Kubernetes Networking:Ingress](https://medium.com/google-cloud/understanding-kubernetes-networking-ingress-1bc341c84078)”,也可以查看[Kubernetes SIG Network针对此主题进行的调查结果](https://github.com/bowei/k8s-ingress-survey-2018)
66+
67+
## Egress
68+
69+
  在Ingress的情况下,我们将流量从集群外部路由到集群内的服务,在Egress的情况下,我们处理相反情况:pod中的应用如何调用集群外部API?
70+
71+
  人们可能想要控制允许哪个pod与外部服务之间可以通信,并且最重要的是实施网络策略。请注意,默认情况下,pod中的所有容器都可以执行egress流量。这些网络策略可以使用Kubernetes中的networkpolicy进行实施,也可以通过部署服务网格(service mesh)来实施。

kubernetes/inter-pod-networking.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,57 @@
11
# 7.4 Pod间网络
22

3+
  在Kubernetes中,每个pod具有可路由的IP,允许pod跨集群节点进行通信而无需NAT,也无需管理端口分配。由于每个pod都获得真实的IP地址,因此pod间可以在不使用代理或转换(例如NAT)的情况下进行通信。pod可以使用端口通信,也可以不使用更高级的服务发现机制进行通信。
4+
5+
  我们将pod间(也称为东西向流量)的通信分为两类:
6+
7+
- pod可以直接与其他pod进行通信; 在这种情况下,请求通信的pod需要知道被请求pod的IP地址,并且有可能会重复此操作,因为”牲畜模式“。
8+
9+
- 普遍地,pod通过service与其他pod进行通信。在这种情况下,该service提供了一个可以通过DNS发现的稳定的,虚拟IP地址。
10+
11+
  当一个容器试图获取网络接口的地址时,它看到的IP是与pod中任何其他容器看到的是同一个IP; 每个pod都有一个其他pod可以找到和使用的IP地址。通过使IP地址和端口在Pod内外相同,Kubernetes在整个集群中创建了一个编排的地址空间。有关此主题的更多详细信息,另请参阅Mark Betz撰写的文章“[Understanding Kubernetes Networking: Pods](https://medium.com/google-cloud/understanding-kubernetes-networking-pods-7117dd28727)”。
12+
13+
  现在我们来看看[service](https://kubernetes.io/docs/concepts/services-networking/service/),如图7-3所示。
14+
15+
![图7-3 Kubernetes中的service](../images/7-3.png)
16+
17+
  service为一组pod提供稳定的虚拟IP(VIP)地址。虽然Pod是经常变化的(扩容,缩容等),但service允许客户端通过使用VIP可靠地发现并连接到在Pod中正在运行的容器。VIP中的“虚拟”意味着它不是连接到网络接口的实际IP地址; 它的目的纯粹是充当稳定的”前端“,将流量转发到一个或多个Pod,因为service后端的pod的IP地址可能会不断变化。
18+
19+
  必须认识到VIP在网络堆栈中不存在的。例如,你不能ping它们。他们只是Kubernetes内部管理的实体。还要注意它的格式是IP:PORT,所以IP地址和端口一起构成了VIP。可以把VIP视为一种映射到实际IP地址的数据结构的索引。
20+
21+
  如图7-3所示,使用VIP 10.104.58.143的服务将流量路由到其中一个容器172.17.0.3或172.17.0.4。这里需要注意的是service和pod的属于不同的子网,现在,你可能想知道这实际上是如何工作的?
22+
23+
  您可以通过标签选择器指定service后端的一组pod,例如,spec.selector.app = someapp Kubernetes将创建一个service,该service的目标是带有标签app = someapp的所有pod。请注意,如果存在这样的选择器,那么对于每个目标Pod将创建一个Endpoint类型的子资源,并且如果不存在标签选择器,则不会创建Endpoint。例如,请参阅以下代码示例kubectl describe命令的输出。这种Endpoint也不是在所谓的[Headless的service](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services)的情况下创建的,它允许您对IP管理和服务发现的发生进行很好的控制。
24+
25+
  保持最新的VIP和pod之间的映射是kube-proxy的工作(另请参阅[kube-proxy文档](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/)),这是一个在kubernetes集群中的每个node节点上运行的进程。
26+
27+
  kube-proxy进程查询apiserver以了解群集中新的service,并相应地更新节点的iptables规则,以提供必要的路由信息。要了解更多service如何工作,请查看[Kubernetes Services By Example](https://blog.openshift.com/kubernetes-services-by-example/)
28+
29+
  让我们动手看看service是如何工作的:假设有一个名为webserver的deployment(例如,执行kubectl run webserver --image nginx),您可以自动创建一个服务,如下所示:
30+
31+
```bash
32+
$ kubectl expose deployment/webserver --port 80
33+
service "webserver" exposed
34+
$ kubectl describe service/webserver
35+
Name: webserver
36+
Namespace: default
37+
Labels: run=webserver
38+
Annotations: <none>
39+
Selector: run=webserver
40+
Type: ClusterIP
41+
IP: 10.104.58.143
42+
Port: <unset> 80/TCP
43+
TargetPort: 80/TCP
44+
Endpoints: 172.17.0.3:8080,172.17.0.4:8080
45+
Session Affinity: None
46+
Events: <none>
47+
48+
$ kubectl get service -l run=webserver
49+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
50+
webserver ClusterIP 10.104.58.143 <none> 80/TCP 1m
51+
```
52+
53+
&emsp;&emsp;我们可以看到service已经拥有了一个集群内部的IP(10.104.58.143),EXTERNAL-IP列告诉你这个服务只能在集群内部使用,也就是说,没有来自群集外部的流量可以访问此service。
54+
55+
&emsp;&emsp;在图7-4中,您可以在Kubernetes仪表板中看到该service。
56+
57+
![图7-4 Dashbord中的service](../images/7-4.png)

0 commit comments

Comments
 (0)