Kubernetes 入门之网络详解

简介: Service 是 k8s 网络部分的核心概念,在 k8s 中,Service 主要担任了四层负载均衡的职责。本文从负载均衡、外网访问、DNS 服务的搭建及 Ingress 七层路由机制等方面,讲解 k8s 的网络相关原理。

Service 是 k8s 网络部分的核心概念,在 k8s 中,Service 主要担任了四层负载均衡的职责。本文从负载均衡、外网访问、DNS 服务的搭建及 Ingress 七层路由机制等方面,讲解 k8s 的网络相关原理。

1.Service 详解

Service 是主要用来实现应用程序对外提供 服务的机制。

1

如上图所示,Service 是对 Pod 的一层抽象,主要通过 TCP/IP 机制及监听 IP 和端口号来对外提供服务。与 Pod 不同的是,Service 一旦创建,系统会为其分发一个 ClusterIP (也可以自己指定),且在其生命周期内不会发生变化。

Service 的创建

命令行快速创建

在创建好 RC 后,可以通过命令行 kubectl expose 来快速创建一个对应的 Service 。比如现已有一个名为 hdls 的 rc:


kubectl expose rc hdls

这种方式创建出来的 Service,其 ClusterIP 是系统自动为其分配的,而 Service 的端口号是从 Pod 中的 containerPort 复制而来。

通过 YAML 创建


apiVersion: v1

kind: Service

metadata:

name: hdls

spec:

ports:

- port: 8080 # Service 的虚拟端口

targetPort: 8000 # 指定后端 Pod 的端口号

selector: # Label 选择器

app: hdls

定义好 YAML 文件后,通过命令 kubectl create-f<service.yml> 即可创建。Service 的定义需要指定以下几个关键字段:

ports

  • port:Service 的虚拟端口

  • targetPort:后端 Pod 的端口号,若不填则默认与 Service 的端口一致

selector:Label 选择器,指定后端 Pod 所拥有的 Label

负载分发策略

k8s 提供了两种负载分发策略:

  • RoundRobin:轮询方式。即轮询将请求转发到后端的各个 Pod 上。

  • SessionAffinity:基于客户端 IP 地址进行会话保持模式。即相同 IP 的客户端发起的请求被转发到相同的 Pod 上。

在默认情况下,k8s 采用轮询模式进行路由选择,但我们也可以通过将 service.spec.SessionAffinity 设置为 “ClusterIP” 来启用 SessionAffinity 模式。

Notes:一些特殊情况

1.开发人员需要自己控制负载均衡策略的情况

在这种情况下,k8s 通过 Headless Service 的概念来实现,即不给 Service 设置 ClusterIP (无入口 IP),仅通过 Label Selector 将后端的 Pod 列表返回给调用的客户端。


apiVersion: v1

kind: Service

metadata:

name: hdls

spec:

ports:

- port: 8080

targetPort: 8000

clusterIP: None

selector:

app: hdls

该 Service 没有虚拟的 ClusterIP ,对其访问可以获得所有具有 app=hdls 的 Pod 列表,客户端需要实现自己的负责均衡策略,再确定具体访问哪一个 Pod。

2.需要将某些服务作为后端服务

一般来说,应用系统需要将外部数据库作为后端服务进行连接,或另一个集群或 namespace 中的服务作为后端服务。这些情况,可以通过建立一个无 Label Selector 的 Service 来实现:


apiVersion: v1

kind: Service

metadata:

name: hdls

spec:

ports:

- port: 8080

targetPort: 8000

该 Service 没有标签选择器,即无法选择后端 Pod。这时系统不会自动创建 Endpoint,需要手动创建一个与该 Service 同名的 Endpoint,用于指向实际的后端访问地址。


apiVersion: v1

kind: Endpoints

metadata:

name: hdls # 与 Service 同名

subsets:

- addresss:

- IP: 1.2.3.4 # 用户指定的 IP

ports:

- port: 8000

此时,如上面的 YAML 创建出来 Endpoint,访问无 Label Selector 的 Service ,即可将请求路由到用户指定的 Endpoint 上。

3.多端口的 Service

在 service.spec.ports 中定义多个 port 即可,包括指定 port 的名字和协议。


apiVersion: v1

kind: Service

metadata:

name: hdls

spec:

ports:

- name: dns

port: 8080

protocol: TCP

- name: dns-tcp

port: 8080

protocol: UDP

selector:

app: hdls

2.外网访问

Pod 和 Service 都是 k8s 集群内部的虚拟概念,所以集群外的客户无法访问。但在某些特殊条件下,我们需要外网可以访问 Pod 或 Service,这时我们需要将 Pod 或 Service 的端口号映射到宿主机,这样客户就可以通过物理机访问容器应用。

外网访问 Pod

将容器应用的端口号映射到物理机上。有两种方式,如下。

设置容器级别的 hostPort

这种是将容器应用的端口号映射到物理机。设置如下:


apiVersion: v1

kind: Pod

metadata:

name: hdls-pod

spec:

containers:

- name: hdls-container

image: ***

ports:

- containerPort: 8000

hostPort: 8000

设置 Pod 级别的 hostNetwork=true

这种是将该 Pod 中所有容器端口号都直接映射到物理机上。此时需要注意的是,在容器的 ports 定义部分,若不指定 hostPort,默认 hostPort=containerPort,若设置了 hostPort,则 hostPort 必须等于 containerPort。设置如下:


apiVersion: v1

kind: Pod

metadata:

name: hdls-pod

spec:

hostNetwork: true

containers:

- name: hdls-container

image: ***

ports:

- containerPort: 8000

外网访问 Service

对于外网访问 Service 也有两种方式。

1.设置 nodePort 映射到物理机

首先需要设置 nodePort 映射到物理机,同时需要设置 Service 的类型为 NodePort:


apiVersion: v1

kind: Service

metadata:

name: hdls

spec:

type: NodePort # 指定类型为 NodePort

ports:

- port: 8080

targetPort: 8000

nodePort: 8000 # 指定 nodePort

selector:

app: hdls

2.设置 LoadBalancer 映射到云服务商提供的 LoadBalancer 地址

这种用法仅用于在公有云服务提供商的云平台上设置 Service 的场景。需要将 service.status.loadBalancer.ingress.ip 设置为云服务商提供的负载均衡器的 IP。则对该 Service 的访问请求将会通过 LoadBalancer 转发到后端 Pod,且负载均衡的实现方式依赖于云服务商提供的 LoadBalancer 的实现机制。

3.DNS 搭建

为了能够实现通过服务名在集群内部进行服务的相互访问,需要创建一个虚拟的 DNS 服务来完成服务名到 ClusterIP 的解析。

k8s 提供的 DNS

k8s 提供的 DNS 服务名为 skydns,由下面四个组件组成:

  • etcd:DNS 存储;

  • kube2sky:将 k8s Master 中的 Service 注册到 etcd ;

  • skyDNS:DNS 域名解析服务;

  • healthz:对 skyDNS 的健康检查。

skyDNS 服务由一个 RC 和一个 Service 组成。在 RC 的配置文件中,需要定义 etcd / kube2sky / skydns / healthz 四个容器,以保证 DNS 服务正常工作。需要注意的是:

1. kube2sky 容器需要访问 k8s Master,所以需要在配置文件中为其配置 Master 所在物理主机的 IP 地址和端口;

2. 需要将 kube2sky 和 skydns 容器的启动参数 --domain 设置为 k8s 集群中 Service 所属域名。容器启动后 kube2sky 会通过 API Server 监控集群中所有 service 的定义,生成相应的记录并保存到 etcd ;

3. skydns 的启动参数 -addr=<IP:Port> 表示本机 TCP 和 UDP 的 Port 端口提供服务。

在 DNS Service 的配置文件中,skyDNS 的 ClusterIP 需要我们指定,每个 Node 的 kubelet 都会使用这个 IP 地址,不会通过系统自动分配;另外,这个 IP 需要在 kube-apiserver 启动参数 --service-cluster-ip-range 内。

在 skydns 容器创建之前,需要先修改每个 Node 上 kubelet 的启动参数:

  • --clusterdns= ,dnscluster_ip 为 DNS 服务的 ClusterIP ;

  • --clusterdomain= , dnsdomain 为 DNS 服务中设置的域名。

DNS 工作原理

1. 首先 kube2sky 容器应用通过调用 k8s Master 的 API 获得集群中所有 Service 信息,并持续监控新 Service 的生成,写入 etcd;

2. 根据 kubelet 的启动参数的设置,kubelet 会在每个新创建的 Pod 中设置 DNS 域名解析配置文件 /etc/resolv.conf 中增加一条 nameserver 配置和 search 配置,通过 nameserver 访问的实际上就是 skydns 在对应端口上提供的 DNS 解析服务;

3. 最后,应用程序就可以像访问网站域名一样,仅通过服务的名字就能访问服务了。

4.Ingress

Service 工作在 TCP/IP 层,而 Ingress 将不同的 URL 访问请求转发到后端不同的 Service ,实现 HTTP 层的业务路由机制。而在 k8s 中,需要结合 Ingress 和 Ingress Controller ,才能形成完整的 HTTP 负载均衡。

Ingress Controller

Ingress Controller 用来实现为所有后端 Service 提供一个统一的入口,需要实现基于不同 HTTP URL 向后转发的负载分发规则。Ingress Controller 以 Pod 的形式运行,需要实现的逻辑:

  • 监听 APIServer,获取所有 Ingress 定义;

  • 基于 Ingress 的定义,生成 Nginx 所需的配置文件 /etc/nginx/nginx.conf

  • 执行 nginx-s reload ,重新加载 nginx.conf 配置文件的内容。

定义 Ingress

k8s 中有一种单独的名为 Ingress 的资源,在其配置文件中可以设置到后端 Service 的转发规则。比如,为 hdls.me 定义一个 ingress.yml:


apiVersion: extensions/v1beta1

kind: Ingress

metadata:

name: hdls-ingress

spec:

rules:

- host: hdls.me

http:

paths:

- path: /web

backend:

serviceName: hdls

servicePort: 8000

最后采用 kubectl create-f ingress.yml 创建 Ingress。可以登录 nginx-ingress Pod 查看其自动生成的 nginx.conf 配置文件内容。

本文转自掘金-Kubernetes 入门之网络详解

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
1月前
|
监控 网络协议 Java
Linux 网络编程从入门到进阶 学习指南
在上一篇文章中,我们探讨了 Linux 系统编程的诸多基础构件,包括文件操作、进程管理和线程同步等,接下来,我们将视野扩展到网络世界。在这个新篇章里,我们要让应用跳出单机限制,学会在网络上跨机器交流信息。
Linux 网络编程从入门到进阶 学习指南
|
16天前
|
运维 Kubernetes Cloud Native
探索Kubernetes的大二层网络:原理、优势与挑战🚀
在云原生领域,Kubernetes (K8s) 已经成为容器编排的事实标准☁️📦。为了支撑其灵活的服务发现和负载均衡🔍🔄,K8s采用了大二层网络的设计理念🕸️。本文将深入探讨大二层网络的工作原理、带来的好处✨,以及面临的挑战和解决方案❗🛠️。
探索Kubernetes的大二层网络:原理、优势与挑战🚀
|
11天前
|
JSON Kubernetes 网络架构
Kubernetes CNI 网络模型及常见开源组件
【4月更文挑战第13天】目前主流的容器网络模型是CoreOS 公司推出的 Container Network Interface(CNI)模型
|
25天前
|
Kubernetes Shell Docker
K8S核心插件-Flannel网络插件
K8S核心插件-Flannel网络插件
44 0
|
26天前
|
Kubernetes 开发工具 Docker
K8S 极速入门
K8S 极速入门
50 0
|
1月前
|
Kubernetes 应用服务中间件 nginx
Kubernetes服务网络Ingress网络模型分析、安装和高级用法
Kubernetes服务网络Ingress网络模型分析、安装和高级用法
35 5
|
1月前
|
安全 网络安全 数据安全/隐私保护
网络拓扑结构入门快速介绍
网络拓扑结构入门快速介绍
|
1月前
|
数据采集 Web App开发 数据处理
Ruby网络爬虫教程:从入门到精通下载图片
Ruby网络爬虫教程:从入门到精通下载图片
|
1月前
|
人工智能 监控 安全
网络安全知识入门:Web应用防火墙是什么?
网络安全知识入门:Web应用防火墙是什么?
22 1
|
2月前
|
Java
[Java]Socket套接字(网络编程入门)
[Java]Socket套接字(网络编程入门)
38 0