Kubernetes Service 详解

schema

Author:rab



前言

Kubernetes (K8s) 提供不同类型的服务,用于不同的应用场景。

  1. ClusterIP

    • 类型:ClusterIP(默认类型)。
    • 应用:用于内部服务。
    • 描述:这种类型将服务公开在群集内部的 IP 地址上,只能从群集内部访问。当我们需要提供内部服务,但不希望从集群外部访问时,可以使用 ClusterIP。例如,您的应用程序需要与数据库服务通信。
  2. NodePort

    • 类型:NodePort。
    • 应用:用于开发和测试。
    • 描述:这种类型将服务公开在每个节点的 IP 地址上的固定端口上,允许从外部访问服务。NodePort 服务通常在开发和测试环境中使用,以便快速从集群外部访问服务。通常不在生产环境中使用,除非有特定的需求。
  3. LoadBalancer

    • 类型:LoadBalancer。
    • 应用:需要从外部访问的生产服务。
    • 描述:这种类型会创建一个外部负载均衡器,通常由云基础设施提供,然后将流量路由到服务。它适用于需要从互联网访问的生产应用程序。例如,提供面向公众的 Web 应用程序。
  4. ExternalName

    • 类型:ExternalName。
    • 应用:映射外部服务。
    • 描述:ExternalName 服务将服务映射到外部 DNS 名称。它用于执行对外部服务的 DNS 查询,这在你想要通过名称访问外部服务而不通过 Kubernetes 服务公开它时很有用。例如,您可以使用它来映射外部数据库服务器。
  5. Headless

    • 类型:无头服务(即没有 ClusterIP 且没有选择器)。
    • 应用:StatefulSet 和直接 Pod 通信。
    • 描述:Headless 服务是一种没有群集内部 IP 或选择器的服务。它不提供负载均衡,而是返回一组 Pod IP,用于直接通信。Headless 服务主要用于 StatefulSet,以确保为各个 Pod 提供稳定的网络标识。它还适用于需要进行直接 Pod 到 Pod 通信的应用。
  6. Ingress

    这是 Ingress 控制器,不是服务类型,但值得一提。

    • 类型:HTTP 和 HTTPS 服务的路由。
    • 描述:Ingress 控制器管理对服务的外部访问,主要用于 HTTP 和 HTTPS 流量。它提供基于主机的路由、基于路径的路由、SSL 终止等功能。Ingress 控制器通常与 LoadBalancer 或 NodePort 服务结合使用,将流量路由到集群内特定的服务。

接下来,将逐一对以上 Service 类型进行案例分析。

一、ClusterIP

1.1 简介

在 Kubernetes(K8s)中,ClusterIP 是一种 Service 类型,用于将内部服务映射到集群内的一组Pod。ClusterIP 服务是Kubernetes中最常见的服务类型之一,用于在集群内部提供负载均衡和服务发现。

1.2 案例

1、Deployment 资源

apiVersion: v1
kind: Namespace
metadata:
  name: myweb
  labels:
    name: ops
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: myweb
  labels:
    app: webdemo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80

2、Service 资源

apiVersion: v1           # service版本
kind: Service            # 对象类型(如service、deployment、pod等)
metadata:                # 元数据信息(名称、名称空间等)
  name: nginx-srv        # 指定service的名称(自定义)
  namespace: myweb       # 指定service的名称空间(与deployment资源的名称空间必须保持一致)
spec:                    # service的规格
  selector:              # service选择器(逻辑上代表一组Pod)
    app: demo            # 选择标签为app:demo的一组后端Pod(这里的标签必须与上面deployment资源中选择器selector一致)
  ports:                 # service端口
    - protocol: TCP      # 通信协议(支持TCP/UDP/SCTP,默认是TCP)
      port: 80           # service的端口(注意不是nginx的端口,这里可自定义)
      targetPort: 80     # 后端Pod的端口(即是我们上面Deployment的Pod端口 => containerPort)
  type: ClusterIP        # 指定service的类型(不指定默认为ClusterIP)

此时只能从群集内部访问,可通过集群 Service IP、Pod IP 来访问资源。注意的是,当我们没指定 type 时,默认就是 ClusterIP 类型。

二、NodePort

2.1 简介

Kubernetes中的NodePort是一种Service类型,用于将外部流量引导到Kubernetes集群内的一组Pod。NodePort服务允许您通过一个静态端口(在每个节点上都开放)将外部流量引导到内部服务,并且通常用于需要从外部网络访问应用程序的情况。

2.2 案例

1、Deployment 资源

apiVersion: v1
kind: Namespace
metadata:
  name: myweb
  labels:
    name: ops
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: myweb
  labels:
    app: webdemo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80

2、Service 资源

apiVersion: v1
kind: Service
metadata:
  name: nginx-srv
  namespace: myweb
spec:
  selector:
    app: demo
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30333     # service端口映射到主机节点的端口(即将service的80端口映射到主机节点的30333端口)
  type: NodePort          # 此时需指定service类型为NodePort

与 NodePort 类似,不同的就是指定 type 为 NodePort,此时集群外部就可以通过访问我们 Host 节点 IP 来访问我们集群资源了(可通过集群 节点 IP、Service IP、Pod IP 来访问资源)。你会注意到,service 资源中多了 nodePort 字段,该字段用于主机节点端口映射,也就是说我们会将 service 的 80 端口映射到集群节点的 30333 端口,便于集群外部可通过集群节点的 30333 端口来访问我们的集群资源。

三、LoadBalancer

3.1 简介

Kubernetes 中的 LoadBalancer 服务是一种 Service 类型,用于将外部流量负载均衡到Kubernetes集群内的多个Pod。LoadBalancer服务允许您在不了解集群内部结构的情况下暴露应用程序,并且由云提供商(如 AWS、GCP、Azure)或 MetalLB 等工具来处理负载均衡的配置和管理。

ClustrerIP、NodePort 这两种无论在内网还是公网环境下使用都很常见,只有 LoadBalancer 大部分情况下只适用于支持外部负载均衡器的云提供商(AWS、阿里云、华为云等)使用。

如果我们使用 AWS、阿里云、华为云等公有云,那么一般来说我们给 Service 的 Type 写成 LoadBalancer,云服务厂商就会分配一个 External IP 给我们的 Service,我们只需要访问这个 External IP,其内部就能自动均衡我们的流量到各个实例上。

那我们自建的 Metallb 要如何配置呢?首先它是一款开源的 K8s 负载均衡控制器,只要部署该控制器,我们的 Service 就可以拿到 IP 了(从我们配置的 Metallb 的地址池中获取),实际上就是这个 IP 就是我们 K8s 集群中主机节点上 iptables 里的一条记录。

3.1.1 MetalLB 简介

一旦 MetalLB 为服务分配了IP地址,它需要对外宣告此 IP 地址,并让外部主机可以路由到此 IP,外部声明有两种模式。

1、Layer 2 模式

Layer 2 模式下,每个 Service 会有集群中的一个 Node 来负责。服务的入口流量全部经由单个节点,然后该节点的 Kube-Proxy 会把流量再转发给服务的 Pods。也就是说,该模式下 MetalLB 并没有真正提供负载均衡器。尽管如此,MetalLB 提供了故障转移功能,如果持有 IP 的节点出现故障,则默认 10 秒后即发生故障转移,IP 会被分配给其它健康的节点。它可以在任何以太网网络上运行,不需要特殊的硬件。

nw-metallb-layer2

从上图也不难看出,Layer 2 模式下存在单节点性能瓶颈,服务所有流量都经过一个 Node 节点,这意味着服务的入口带宽被限制为单个节点的带宽。因此,严格意义上来讲,Layer 2 模式的 Service 不是一个真正的 LoadBalancer。

2、BGP 模式

BGP 模式下,集群中所有 Node 都会跟上联路由器建立 BGP 连接,并且会告知路由器应该如何转发 Service 的流量,如下图。

209_OpenShift_BGP_0122

BGP 模式下才是一个真正的 LoadBalancer,通过 BGP 协议正确分布流量,不再需要一个 Leader 节点。

但该模式下要注意:需要上层路由器支持 BGP。而且因为 BGP 单 Session 的限制,如果 Calico 也是使用的 BGP 模式,就会有冲突从而导致 Metallb 无法正常工作。

3.1.2 MetalLB 部署

官网:https://metallb.universe.tf/installation/

参考1:https://access.redhat.com/documentation/

参考2:https://www.cnblogs.com/gaoyukun/articles/17156408.html

参考3:https://www.infvie.com/ops-notes/kubernetes-load-balancer-metallb.html

参考4:https://blog.csdn.net/zuoyang1990/article/details/128898396

1、K8s 启用 ARP 模式

如果环境是 Kubernetes v1.14.2+ 使用 IPVS模式,必须启用 ARP 模式。

kubectl edit configmap -n kube-system kube-proxy

image-20231027121158233

2、部署 MetalLB

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.12/config/manifests/metallb-native.yaml

# 如果在线无法部署,可将yml文件下载到本地后再上传服务器执行(如下图)
kubectl apply -f metallb-native.yaml

image-20231027113533936

大概看看,服务是部署在 metallb-system 的名称空间中,如下图。

image-20231027113837151

看看是否正常运行:

kubectl  get svc,pod -n metallb-system

image-20231027121356068

说明:controller 负责 IP 地址的分配,以及 service 和 endpoint 的监听,speaker 负责保证 service 地址可达,例如 Layer 2 模式下,speaker 会负责ARP请求应答。部署完成后,还需配置 IP 地址池。

3.1.3 MetalLB 配置
3.1.3.1 Layer 2 模式

1、给 Metallb 创建 IP 地址池

vim iptool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: default
  namespace: metallb-system
spec:
  addresses:
  - 192.168.56.20-192.168.56.110
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: default
  namespace: metallb-system
spec:
  ipAddressPools:
  - default

上面例子,IP 地址池为 192.168.56.20 - 192.168.56.110。

注意:IP段根据自己实际情况来设置(我的虚拟机测试环境网段是 192.168.56.0/24)

2、应用配置文件

kubectl apply -f iptool.yaml

3、查看状态

kubectl get IPAddressPool,L2Advertisement -n metallb-system

image-20231029163442040

3.1.3.2 BGP 模式

这部分要结合你本地的路由来具体配置(且本地路由必须支持 BGP 模式),这里我就不演示了。具体步骤可参考这部分内容 => 配置 MetalLB BGP peer

3.2 案例

3.2.1 部署

1、创建 yml 测试文件

注:这些资源的 namespace 不必与 metallb 的 namespace 保持一致(默认或指定为你自定义的 namespace 即可)。

vim demo.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: webdemo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-srv
spec:
  selector:
    app: demo
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30333
  type: LoadBalancer

2、应用配置

kubectl apply -f demo.yml

3、验证是否获取地址池 IP

kubectl get service

# 如下图,正好分配到了我们指定IP地址池内的IP

image-20231029161016783

3.2.2 验证

本地浏览器访问!注意,访问地址格式为 http://<EXTERNAL-IP>:<ServicePort>,其中 EXTERNAL-IP 就是分配给我们的 IP 地址,ServicePort 是 80,而不是 30333。因此你可以两种方式访问:

  • 通过分配的 IP 地址:http://192.168.56.20/
  • 通过K8s集群节点IP地址:http://192.168.56.160:30333/、http://192.168.56.161:30333/、http://192.168.56.162:30333/

image-20231029145149923

四、ExternalName

4.1 简介

Kubernetes 中的 ExternalName 服务是一种特殊类型的服务,它允许将一个 Kubernetes 服务映射到一个外部域名(或外部服务)。这对于将内部Kubernetes集群内的服务与外部服务(例如外部数据库、第三方API等)关联起来非常有用。

ExternalName服务通常用于以下情况:

  • 访问外部数据库。
  • 访问外部第三方 API。
  • 切换外部服务提供商的域名。
  • 隐藏外部服务的实际域名,以提供更友好的服务名。

总之,ExternalName 服务是 Kubernetes 中一种非常有用的服务类型,它允许将内部服务名映射到外部域名,提供了灵活性和透明性,以便访问外部服务。这对于将内部应用程序与外部服务集成起到了重要作用。

4.2 案例

4.2.1 反代 IP

1、创建 yml 测试文件

vim ep.yml
---
apiVersion: v1
kind: Endpoints
metadata:
  name: baidu-ep          # 与svc资源的metadata.name保持一致
subsets:
- addresses:
  - ip: 220.181.38.148
  ports:
  - name: baidu           # 与svc资源的spec.ports.name保持一致
    port: 80
    protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: baidu-svc        # 与ep资源的metadata.name保持一致
spec:
  ports:
  - name: baidu          # 与ep资源的subsets.ports.name保持一致
    port: 8080
    protocol: TCP
    targetPort: 80       # 这里的targetPort是ep资源中的port
kubectl apply -f ep.yml

2、验证

kubectl get svc,ep

image-20231029211515551

此时你就可以通过集群 Service IP 来访问了后端服务了。

curl 10.101.86.52:8080 
# 或
curl -I 10.101.86.52:8080

image-20231029211717028

以上的 Service 类型是 ClusterIP,如果你想通过 K8s 集群外部来访问,修改 Service 类型为 NodePort 即可,这里不再演示。

4.2.2 反代域名

1、创建 yml 测试文件

vim externalName.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: externalname-test
  name: externalname-test
spec:
  ports:
  - name: http
    port: 80
    protocol: tcp
    targetPort: 80
  sessionAffinity: None
  type: ExternalName
  externalName: www.baidu.com
kubectl apply -f externalName.yaml

2、验证

创建一个测试 Pod:

vim test-pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: nginx
kubectl apply -f test-pod.yml

启动后可先进入测试 Pod 中查看一下 /etc/resolve.conf

在看看 Service 的 DNS:

kubectl get svc externalname-test -n default -o jsonpath='{.metadata.name}.{.metadata.namespace}.svc.cluster.local'

image-20231030110811698

此时其他 Pod 就可以通过我们查询的 Service 的 DNS 进行访问测试:

dig @10.96.0.10 externalname-test.default.svc.cluster.local

image-20231030111035548

结果表明:当我们在其他 Pod 访问 ExternalName 类型的 Service 时,实现了反代的效果。

五、Headless

5.1 简介

Kubernetes 中的 Headless Service 是一种特殊类型的 Service,与标准的 ClusterIP Service 不同,它不会分配 ClusterIP,而是用于实现服务的 DNS 负载均衡。Headless Service 通常用于需要直接与 Pod 的 IP 地址交互或实现服务发现的情况,特别适用于需要直接访问 Pod IP 地址或实现服务发现的情况。它提供了更高级别的控制,同时还允许使用 Kubernetes 的内置 DNS 解析来管理服务和 Pod 之间的通信。

5.2 案例

1、创建一个 Headless Service 的 YAML 文件

vim headless-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-headless-service
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
  - protocol: TCP
    port: 80

在上述 YAML 文件中,我们定义了一个名为 my-headless-service 的 Headless Service,clusterIP 设置为 None,这将创建一个 Headless Service。Service 选择了带有标签 app: my-app 的 Pod。

2、创建一个 StatefulSet 用于部署有状态的Pod

vim statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset
spec:
  serviceName: my-headless-service
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx

在上述 YAML 文件中,我们创建了一个 StatefulSet,它使用 my-headless-service 作为服务名称,创建了 3 个具有 app: my-app 标签的 Pod,这些 Pod 将具有唯一的标识。

3、使用kubectl部署 Headless Service 和 StatefulSet

kubectl apply -f headless-service.yaml
kubectl apply -f statefulset.yaml

这将创建 Headless Service 以及 StatefulSet 中的 Pod。

image-20231030113152021

4、验证

查看每个 Pod 的 DNS 记录,以验证 Headless Service 的 DNS 负载均衡。通过以下方式进入一个Pod:

kubectl exec -it my-statefulset-0 -- /bin/bash

image-20231030113659751

接着我们就可以查看每个 Pod 的 DNS 记录,以验证 Headless Service 的 DNS 负载均衡,如下图,您会看到与 StatefulSet 中每个 Pod 相关的 DNS 记录,其中包括唯一的Pod IP地址。

dig @10.96.0.10 my-headless-service.default.svc.cluster.local

image-20231030113612872

六、Ingress

6.1 简介

Kubernetes Ingress 是一种资源对象,用于管理外部 HTTP 和 HTTPS 访问到 Kubernetes 集群内部的服务。它充当 HTTP 和 HTTPS 流量的入口点,允许我们定义请求路由、负载均衡、SSL 终止等功能。

通俗来讲,Ingress 和 Service、Deployment 类似,也是一个 k8s 的资源类型,Ingress 用于实现用域名的方式访问 k8s 内部应用管理对集群中的服务(通常是 HTTP 或 HTTPS)的外部访问的 API 对象。

官方文档:https://kubernetes.github.io/ingress-nginx/deploy/

6.2 案例

6.2.1 安装 Helm

具体安装看《K8s 之 Helm 部署 MySQL 5.7》

6.2.2 安装 Ingress

可通过两种方式安装:Yaml、Helm(本质上就是 Yaml 文件)

1、通过 Helm 方式部署

# 添加helm仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

# 下载 Ingress 的 Helm 包至本地
mkdir /opt/helm_images && cd /opt/helm_images
helm pull ingress-nginx/ingress-nginx

2、通过 Yaml 文件部署

本次我们通过该方式部署。

参考:https://zhuanlan.zhihu.com/p/590474850

vim ingressdeploy.yaml
apiVersion: v1
kind: Namespace
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  name: ingress-nginx
---
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx
  namespace: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx
  namespace: ingress-nginx
rules:
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - configmaps
  - pods
  - secrets
  - endpoints
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses/status
  verbs:
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingressclasses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resourceNames:
  - ingress-controller-leader
  resources:
  - configmaps
  verbs:
  - get
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  verbs:
  - create
- apiGroups:
  - coordination.k8s.io
  resourceNames:
  - ingress-controller-leader
  resources:
  - leases
  verbs:
  - get
  - update
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission
  namespace: ingress-nginx
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - nodes
  - pods
  - secrets
  - namespaces
  verbs:
  - list
  - watch
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses/status
  verbs:
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingressclasses
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission
rules:
- apiGroups:
  - admissionregistration.k8s.io
  resources:
  - validatingwebhookconfigurations
  verbs:
  - get
  - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx
  namespace: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ingress-nginx
subjects:
- kind: ServiceAccount
  name: ingress-nginx
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission
  namespace: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
  name: ingress-nginx-admission
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ingress-nginx
subjects:
- kind: ServiceAccount
  name: ingress-nginx
  namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
  name: ingress-nginx-admission
  namespace: ingress-nginx
---
apiVersion: v1
data:
  allow-snippet-annotations: "true"
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Local
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-controller-admission
  namespace: ingress-nginx
spec:
  ports:
  - appProtocol: https
    name: https-webhook
    port: 443
    targetPort: webhook
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  minReadySeconds: 0
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/component: controller
      app.kubernetes.io/instance: ingress-nginx
      app.kubernetes.io/name: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/component: controller
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
    spec:
      containers:
      - args:
        - /nginx-ingress-controller
        - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
        - --election-id=ingress-controller-leader
        - --controller-class=k8s.io/ingress-nginx
        - --ingress-class=nginx
        - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
        - --validating-webhook=:8443
        - --validating-webhook-certificate=/usr/local/certificates/cert
        - --validating-webhook-key=/usr/local/certificates/key
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: LD_PRELOAD
          value: /usr/local/lib/libmimalloc.so
        image: dyrnq/ingress-nginx-controller:v1.3.0
        imagePullPolicy: IfNotPresent
        lifecycle:
          preStop:
            exec:
              command:
              - /wait-shutdown
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: controller
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        - containerPort: 443
          name: https
          protocol: TCP
        - containerPort: 8443
          name: webhook
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          requests:
            cpu: 100m
            memory: 90Mi
        securityContext:
          allowPrivilegeEscalation: true
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - ALL
          runAsUser: 101
        volumeMounts:
        - mountPath: /usr/local/certificates/
          name: webhook-cert
          readOnly: true
      dnsPolicy: ClusterFirst
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: ingress-nginx
      terminationGracePeriodSeconds: 300
      volumes:
      - name: webhook-cert
        secret:
          secretName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission-create
  namespace: ingress-nginx
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/component: admission-webhook
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
        app.kubernetes.io/version: 1.3.0
      name: ingress-nginx-admission-create
    spec:
      containers:
      - args:
        - create
        - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
        - --namespace=$(POD_NAMESPACE)
        - --secret-name=ingress-nginx-admission
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: dyrnq/kube-webhook-certgen:v1.1.1
        imagePullPolicy: IfNotPresent
        name: create
        securityContext:
          allowPrivilegeEscalation: false
      nodeSelector:
        kubernetes.io/os: linux
      restartPolicy: OnFailure
      securityContext:
        fsGroup: 2000
        runAsNonRoot: true
        runAsUser: 2000
      serviceAccountName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission-patch
  namespace: ingress-nginx
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/component: admission-webhook
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
        app.kubernetes.io/version: 1.3.0
      name: ingress-nginx-admission-patch
    spec:
      containers:
      - args:
        - patch
        - --webhook-name=ingress-nginx-admission
        - --namespace=$(POD_NAMESPACE)
        - --patch-mutating=false
        - --secret-name=ingress-nginx-admission
        - --patch-failure-policy=Fail
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: dyrnq/kube-webhook-certgen:v1.1.1
        imagePullPolicy: IfNotPresent
        name: patch
        securityContext:
          allowPrivilegeEscalation: false
      nodeSelector:
        kubernetes.io/os: linux
      restartPolicy: OnFailure
      securityContext:
        fsGroup: 2000
        runAsNonRoot: true
        runAsUser: 2000
      serviceAccountName: ingress-nginx-admission
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: nginx
spec:
  controller: k8s.io/ingress-nginx
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
  name: ingress-nginx-admission
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: ingress-nginx-controller-admission
      namespace: ingress-nginx
      path: /networking/v1/ingresses
  failurePolicy: Fail
  matchPolicy: Equivalent
  name: validate.nginx.ingress.kubernetes.io  
  rules:
  - apiGroups:
    - networking.k8s.io
    apiVersions:
    - v1
    operations:
    - CREATE
    - UPDATE
    resources:
    - ingresses
  sideEffects: None

3、执行部署

kubectl apply -f ingressdeploy.yaml

image-20231030190526324

4、查看资源部署情况

kubectl get all -n ingress-nginx

# 如下图ingress-nginx-controller的EXTERNAL-IP是从我们上面的LoadBalancer地址池获取的

image-20231030190944688

5、验证

创建一个 Ingress

vim ingress-1.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-mytest
  namespace: default #必须与service的名称空间一致
  annotations:
    kubernetes.io/ingress.class: "nginx"  
spec:
  rules:
  - host: "mytest.zrsops.com"
    http:
      paths:
      - path: "/"
        pathType: Exact
        backend:
          service: 
            name: mytest #service名称 
            port: 
              number: 80 #service端口

创建一个 Nginx 资源

vim ingress-ng.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mytest
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mytest
      release: v1
      env: test
  template:
    metadata:
      labels:
        app: mytest
        release: v1
        env: test
    spec:
      containers:
      - name: mytest
        image: nginx 
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: mytest
  namespace: default
spec:
  type: ClusterIP   #默认类型
  selector:
    app: mytest
    release: v1
    env: test
  ports:
  - name: http
    port: 80
    targetPort: 80

执行创建

kubectl apply -f ingress-1.yml
kubectl apply -f ingress-ng.yml

在浏览器本地验证

先在 Windows Hosts 文件添加如下内容。

路径:C:\Windows\System32\drivers\etc\hosts

192.168.56.20 mytest.zrsops.com

image-20231030201557413

注意:192.168.56.20 这个 IP 是 ingress-nginx-controller 资源的 EXTERNAL-IP,这也印证了,Ingress 通常会和 LoadBalancer 配合使用。大致示意图如下:

ingress

总结

  • ClusterIP:在集群内部使用,也是默认值;
  • NodePort:在所有安装了kube-proxy的节点上打开一个端口,此端口可以代理至后端Pod,然后集群外部可以使用节
    点的IP地址和NodePort的端口号访问到集群Pod的服务。NodePort端口范围默认是30000-32767。
  • LoadBalancer:使用云提供商的负载均衡器公开服务;
  • ExternalName:通过返回定义的CNAME别名;
  • Headless:是一种没有群集内部 IP 或选择器的服务。它不提供负载均衡,而是返回一组 Pod IP,用于直接通信。
  • Ingress:Ingress 控制器管理对服务的外部访问,主要用于 HTTP 和 HTTPS 流量。

—END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云计算-Security

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值