Kubernetes的网络结构

K8s的网络相对比较复杂, 包含了如下几类IP地址:

Host Network

运行K8s集群的宿主服务器的内网IP, 其网段在配置宿主机时设置. 这些服务器可能是物理机, 也可能是ESXi或KVM虚机. 可以根据这个IP在K8s初始化时设置--apiserver-advertise-address, 配置外网访问时, 前端的负载均衡要通过这些IP访问服务.

Docker Bridge Network

运行Docker服务时启动的虚拟网卡docker0的IP, 通常为 172.17.0.1/16, 对应docker内部默认的bridge网段. 这个网络在K8s中不会用到.

Pod Network

K8s中Pod单元的IP, 其网段在K8s初始化时使用--pod-network-cidr设置, 此处使用172.16.0.0/16, 在每个宿主(node节点)上, 都会有一个对应的二级网段, 例如 172.16.1.0/24, 如果使用的是flannel, 那么在宿主机上会对应成对出现的两个虚拟网卡 cni0 和 flannel.1 (如果宿主机上还没部署pod, cni0可能不会出现)

Pod网络在集群内可以跨节点相互ping通, 在master和node主机上也可以直接访问Pod的IP

Service Network

K8s中Service单元的IP, 其网段在K8s初始化时使用--service-cidr设置, 在master和node主机上不能直接访问. 这里使用10.1.0.0/16.

Ingress的机制

要解决的问题

因为K8s中Pod是易变的, Pod IP在更新中会自动修改, 使用Service能使访问入口相对固定, 但是Service IP在集群外不能访问, 要对外提供访问, 只能把Service以NodePort, LoadBalancer这些方式Expose出去, 但是NodePort会与每一个Node主机绑定, 而LoadBalancer需要云服务商提供相应的服务(或自己安装).

原理

Ingress 启动一个独立的Pod来运行七层代理, 可以是 Nginx, Traefik 或者是 Envoy. Ingress Pod会直接代理后端提供服务的Pod, 为了能监听后端Pod的变化, 需要一个 Headless Service 通过Selector选择指定的Pod, 并收集到Pod对应的IP. 一旦后端Pod产生变化, Headless Service 会自动根据变化更改配置文件并重载.

如果使用的是 Nginx 类型的 Ingress Pod, 则每次变化后通过reload修改过的配置文件实现规则更新.

Ingress Controller

在kubernetes集群内节点上运行web七层代理所对应的Pod, 由此Pod代理集群内部的Service, Service再把流量转发给集群内部对应的Pod, 这就叫做 Ingress Controller, Ingress Controller 基于 DaemonSet 控制器实现, DaemonSet用于保证集群内部每个节点上都运行一个指定的Pod.

部署Ingress Nginx

软件版本

这里使用的环境是 K8s 1.17, Docker 18.06.3, Ingress Nginx 0.26.2

Ingress Nginx项目地址: https://github.com/kubernetes/ingress-nginx/

Ingress Nginx的安装文档: https://kubernetes.github.io/ingress-nginx/deploy/ 使用 https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/

安装前提

已经配置好K8s集群

部署公共部分

现在最新的标签是0.26.2, 使用部署模板

https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.26.2/deploy/static/mandatory.yaml

下载后在master主机上执行

kubectl apply -f mandatory.yaml

可以使用下面的命令查看部署的结果

kubectl get pods --all-namespaces -l app.kubernetes.io/name=ingress-nginx --watch
kubectl get services

部署Nodeport部分

因为不使用云服务商的服务, 所以要使用Nodeport的方式, 对应的部署模板在

https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.26.2/deploy/static/provider/baremetal/service-nodeport.yaml

这一步实际上是创建一个Nodeport将ingress-nginx服务发布到Node节点的Host Network上, 原模板中未指定端口, 创建后会随机设置端口, 可以修改一下, 只能使用端口范围 3000 ~ 32767. 修改后的service-nodeport.yaml, 将80端口映射到了30080, 443映射到了30443

apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
nodePort: 30080
- name: https
port: 443
targetPort: 443
protocol: TCP
nodePort: 30443
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx

可以使用下面的命令查看发布的结果, 以及映射出去的实际端口

kubectl get services -n ingress-nginx

创建服务并测试

以下都是使用defalut的namespace. 都使用kubectl apply -f 模板名 命令进行发布

Deployment, 创建两个nginx的pod

# nginx-deployment.yml
apiVersion: apps/v1
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: registry.cn-shanghai.aliyuncs.com/jovi/nginx:alpine
ports:
- containerPort: 80

Service, 将上面创建的两个Pod发布为Servce, 将Pod的80端口映射到Service的8080端口

# nginx-service.yml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 8080
targetPort: 80

查看service详情

$ kubectl describe service my-service
Name: my-service
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"my-service","namespace":"default"},"spec":{"ports":[{"port":8080,...
Selector: app=nginx
Type: ClusterIP
IP: 10.1.116.99
Port: <unset> 8080/TCP
TargetPort: 80/TCP
Endpoints: 172.16.1.6:80,172.16.1.7:80
Session Affinity: None
Events: <none>

  

Ingress, 将上面的Service的8080端口映射到Ingress的http

# ingress-test.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-ingress
annotations:
# use the shared ingress-nginx
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- http:
paths:
- backend:
serviceName: my-service
servicePort: 8080

查看Ingress详情

$ kubectl get services -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx NodePort 10.1.60.152 <none> 80:30080/TCP,443:30443/TCP 69m
milton@k8s00:~/backup$ kubectl describe ingress test-ingress
Name: test-ingress
Namespace: default
Address: 10.1.60.152
Default backend: default-http-backend:80 (<none>)
Rules:
Host Path Backends
---- ---- --------
*
my-service:8080 (172.16.1.6:80,172.16.1.7:80)
Annotations:
kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"name":"test-ingress","namespace":"default"},"spec":{"rules":[{"http":{"paths":[{"backend":{"serviceName":"my-service","servicePort":8080}}]}}]}} kubernetes.io/ingress.class: nginx
Events: <none>

这时候, 就可以通过 http://宿主机IP:30080 访问到这两个Pod的Nginx默认页.

Kubernetes上使用Ingress Nginx将服务发布到外部IP的更多相关文章

  1. 为苹果ATS和微信小程序搭建 Nginx + HTTPS 服务

    昨天测试开发微信小程序,才发现微信也要求用HTTPS加密数据,想来是由于之前苹果的ATS审核政策的缘故吧,微信想在苹果上开放小程序必然也只能要求开发者必须使用HTTPS了,于是在服务器上测试安装Ngi ...

  2. 微服务开发有道之把项目迁移到Kubernetes上的5个小技巧

    我们将在本文中提供5个诀窍帮你将项目迁移到Kubernetes上,这些诀窍来源于过去12个月中OpenFaas社区的经验.下文的内容与Kubernetes 1.8兼容,并且已经应用于OpenFaaS ...

  3. Kubernetes 系列(三):Kubernetes使用Traefik Ingress暴露服务

    一.Kubernetes 服务暴露介绍 从 kubernetes 1.2 版本开始,kubernetes提供了 Ingress 对象来实现对外暴露服务:到目前为止 kubernetes 总共有三种暴露 ...

  4. 在k8s(kubernetes)上安装 ingress V1.1.3

    介绍 Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由.流量路由由 Ingress 资源上定义的规则控制. 下面是一个将所有流量都发送到同一 Service 的简单 In ...

  5. 在k8s(kubernetes) 上安装 ingress V1.1.0

    Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由.流量路由由 Ingress 资源上定义的规则控制. 下面是一个将所有流量都发送到同一 Service 的简单 Ingre ...

  6. 基于Nginx dyups模块的站点动态上下线并实现简单服务治理

    简介 今天主要讨论一下,对于分布式服务,站点如何平滑的上下线问题. 分布式服务 在分布式服务下,我们会用nginx做负载均衡, 业务站点访问某服务站点的时候, 统一走nginx, 然后nginx根据一 ...

  7. 使用Netsil监控Kubernetes上的微服务

    ubernetes是容器编排和调度领域的王者,它击败了竞争对手Docker Swarm和Apache Mesos,开启了闪耀的未来,微服务可以自修复,可以自动扩展,可以跨zone,region甚至跨云 ...

  8. 在Docker和Kubernetes上运行MongoDB微服务

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟.容器是完全使用沙箱机制,相互之间不会有任何接 ...

  9. Linux实战教学笔记37:企业级Nginx Web服务优化实战(上)

    一,Nginx基本安全优化 1.1 调整参数隐藏Nginx软件版本号信息 一般来说,软件的漏洞都和版本有关,这个很像汽车的缺陷,同一批次的要有问题就都有问题,别的批次可能就都是好的.因此,我们应尽量隐 ...

  10. 利用 istio 来对运行在 Kubernetes 上的微服务进行管理

    尝试在一个准生产环境下,利用 istio 来对运行在 Kubernetes 上的微服务进行管理. 这一篇是第一篇,将一些主要的坑和环境准备工作. 内容较多,因此无法写成手把手教程,希望读者有一定 Ku ...

随机推荐

  1. Laravel组件化开发学习笔记

    组件化开发就是基于组件来进行迭代开发,而不是从零开始开发 1.语法基础 组件开发的基础语法是命名空间. 可以使用魔法常量__NAMESPACE__可以直接获取当前命名空间的名称的字符串. 例如: &l ...

  2. ECharts——快速入门

    ECharts快速入门 引入 ECharts <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...

  3. [转帖]ESXi主机RAID卡_HBA卡_网卡 型号_固件_驱动查询

    https://www.cnblogs.com/vincenshen/p/12332142.html 一.RAID卡/HBA卡 型号_固件_驱动查询 1. 查询所有SCSI设备列表 # esxcfg- ...

  4. [转帖]Kafka中Topic级别配置

    https://www.cnblogs.com/moonandstar08/p/6139502.html 一.Kafka中topic级别配置 1.Topic级别配置 配置topic级别参数时,相同(参 ...

  5. ebpf的简单学习

    ebpf的简单学习-万事开头难 前言 bpf 值得是巴克利包过滤器 他的核心思想是在内核态增加一个可编程的虚拟机. 可以在用户态定义很多规则, 然后直接在内核态进行过滤和使用. 他的效率极高. 因为避 ...

  6. ESXi6.5 登录后出现错误 必须 退出的解决办法

  7. ClickHouse(09)ClickHouse合并树MergeTree家族表引擎之MergeTree详细解析

    目录 建表 数据存储 主键和索引在查询中的表现 主键的选择 选择与排序键不同的主键 索引和分区在查询中的应用 部分单调主键的使用 跳数索引 可用的索引类型 并发数据访问 列和表的 TTL 列TTL 表 ...

  8. TortoiseGit 常见问题汇总

    1.test分支修改后合并到master分支 1)切换本地分支到master分支 2)TortoiseGit --->  merge,选择远程分支test 提交到远程分支master 2.将远程 ...

  9. 无法下载安装文件,请检查internet连接

    win10 vs2019下提示visual studio installer无法下载安装文件,请检查internet连接     1.打开"网络和Internet设置",更改适配器 ...

  10. 消息队列RabbitMQ教程

    RabbitMQ教程 翻译自RabbitMQ Tutorials. 0. 准备 前期准备 1. Hello World 最简入门教程 2. 工作队列 竞争消费者模式 3. 发布/订阅 同时发送消息给多 ...