Kubernetes 入门之网络详解

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: Service 是 k8s 网络部分的核心概念,在 k8s 中,Service 主要担任了四层负载均衡的职责。本文从负载均衡、外网访问、DNS 服务的搭建及 Ingress 七层路由机制等方面,讲解 k8s 的网络相关原理。

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

1.Service 详解

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

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

Service 的创建

命令行快速创建

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



  
  
  1. kubectl expose rc hdls

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

通过 YAML 创建



  
  
  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: hdls

  5. spec:

  6. ports:

  7. - port: 8080 # Service 的虚拟端口

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

  9. selector: # Label 选择器

  10. 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 列表返回给调用的客户端。



  
  
  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: hdls

  5. spec:

  6. ports:

  7. - port: 8080

  8. targetPort: 8000

  9. clusterIP: None

  10. selector:

  11. app: hdls

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

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

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



  
  
  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: hdls

  5. spec:

  6. ports:

  7. - port: 8080

  8. targetPort: 8000

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



  
  
  1. apiVersion: v1

  2. kind: Endpoints

  3. metadata:

  4. name: hdls # 与 Service 同名

  5. subsets:

  6. - addresss:

  7. - IP: 1.2.3.4 # 用户指定的 IP

  8. ports:

  9. - port: 8000

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

3.多端口的 Service

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



  
  
  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: hdls

  5. spec:

  6. ports:

  7. - name: dns

  8. port: 8080

  9. protocol: TCP

  10. - name: dns-tcp

  11. port: 8080

  12. protocol: UDP

  13. selector:

  14. app: hdls

2.外网访问

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

外网访问 Pod

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

设置容器级别的 hostPort

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



  
  
  1. apiVersion: v1

  2. kind: Pod

  3. metadata:

  4. name: hdls-pod

  5. spec:

  6. containers:

  7. - name: hdls-container

  8. image: ***

  9. ports:

  10. - containerPort: 8000

  11. hostPort: 8000

设置 Pod 级别的 hostNetwork=true

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



  
  
  1. apiVersion: v1

  2. kind: Pod

  3. metadata:

  4. name: hdls-pod

  5. spec:

  6. hostNetwork: true

  7. containers:

  8. - name: hdls-container

  9. image: ***

  10. ports:

  11. - containerPort: 8000

外网访问 Service

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

1.设置 nodePort 映射到物理机

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



  
  
  1. apiVersion: v1

  2. kind: Service

  3. metadata:

  4. name: hdls

  5. spec:

  6. type: NodePort # 指定类型为 NodePort

  7. ports:

  8. - port: 8080

  9. targetPort: 8000

  10. nodePort: 8000 # 指定 nodePort

  11. selector:

  12. 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= ,dns cluster_ip 为 DNS 服务的 ClusterIP ;

  • --clusterdomain= , dns domain 为 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:



  
  
  1. apiVersion: extensions/v1beta1

  2. kind: Ingress

  3. metadata:

  4. name: hdls-ingress

  5. spec:

  6. rules:

  7. - host: hdls.me

  8. http:

  9. paths:

  10. - path: /web

  11. backend:

  12. serviceName: hdls

  13. servicePort: 8000

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

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

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
Kubernetes Cloud Native 云计算
云原生入门:从Docker到Kubernetes的旅程
【10月更文挑战第2天】本文将带你走进云原生的世界,从基础的Docker容器技术开始,逐步深入到Kubernetes集群管理。我们将通过实际代码示例,探索如何利用这些工具构建、部署和管理现代云应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的知识和技能,让你在云原生领域迈出坚实的一步。
82 5
|
4天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
11天前
|
Kubernetes 关系型数据库 MySQL
Kubernetes入门:搭建高可用微服务架构
【10月更文挑战第25天】在快速发展的云计算时代,微服务架构因其灵活性和可扩展性备受青睐。本文通过一个案例分析,展示了如何使用Kubernetes将传统Java Web应用迁移到Kubernetes平台并改造成微服务架构。通过定义Kubernetes服务、创建MySQL的Deployment/RC、改造Web应用以及部署Web应用,最终实现了高可用的微服务架构。Kubernetes不仅提供了服务发现和负载均衡的能力,还通过各种资源管理工具,提升了系统的可扩展性和容错性。
35 3
|
14天前
|
Kubernetes Cloud Native 开发者
云原生技术入门:Kubernetes和Docker的协作之旅
【10月更文挑战第22天】在数字化转型的浪潮中,云原生技术成为推动企业创新的重要力量。本文旨在通过浅显易懂的语言,引领读者步入云原生的世界,着重介绍Kubernetes和Docker如何携手打造弹性、可扩展的云环境。我们将从基础概念入手,逐步深入到它们在实际场景中的应用,以及如何简化部署和管理过程。文章不仅为初学者提供入门指南,还为有一定基础的开发者提供实践参考,共同探索云原生技术的无限可能。
24 3
|
13天前
|
运维 Kubernetes Cloud Native
云原生入门:Kubernetes和容器化的未来
【10月更文挑战第23天】本文将带你走进云原生的世界,探索Kubernetes如何成为现代软件部署的心脏。我们将一起揭开容器化技术的神秘面纱,了解它如何改变软件开发和运维的方式。通过实际的代码示例,你将看到理论与实践的结合,感受到云原生技术带来的革命性影响。无论你是初学者还是有经验的开发者,这篇文章都将为你开启一段新的旅程。让我们一起踏上这段探索之旅,解锁云原生技术的力量吧!
|
1月前
|
弹性计算 人工智能 运维
Terraform从入门到实践:快速构建你的第一张业务网络(上)
本次分享主题为《Terraform从入门到实践:快速构建你的第一张业务网络》。首先介绍如何入门和实践Terraform,随后演示如何使用Terraform快速构建业务网络。内容涵盖云上运维挑战及IaC解决方案,并重磅发布Terraform Explorer产品,旨在降低使用门槛并提升用户体验。此外,还将分享Terraform在实际生产中的最佳实践,帮助解决云上运维难题。
118 1
Terraform从入门到实践:快速构建你的第一张业务网络(上)
|
16天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
15 1
|
1天前
|
Kubernetes Cloud Native 前端开发
Kubernetes入门指南:从基础到实践
Kubernetes入门指南:从基础到实践
5 0
|
1月前
|
Kubernetes 网络协议 网络安全
k8s中网络连接问题
【10月更文挑战第3天】
103 7
|
1月前
|
Kubernetes Cloud Native Docker
云原生入门:Kubernetes和Docker的协同之旅
【10月更文挑战第4天】在这篇文章中,我们将通过一次虚拟的旅行来探索云原生技术的核心——Kubernetes和Docker。就像乘坐一艘由Docker驱动的小船启航,随着波浪(代码示例)起伏,最终抵达由Kubernetes指挥的宏伟舰队。这不仅是一段技术上的旅程,也是理解现代云架构如何支撑数字世界的冒险。让我们扬帆起航,一探究竟!
下一篇
无影云桌面