五、服务发布
  BMwtnym6fXTR 2023年11月02日 41 0

五、服务发布

1. Pod生命周期带来的问题

Pod 的生命是有限的,死亡过后不会复活了。每个 Pod 都有自己的 IP 地址,但是如果 Pod 重建了的话那么他的 IP 很有可能也就变化了。

这就会带来一个问题:比如我们有一些后端的 Pod 集合为集群中的其他应用提供 API 服务,如果我们在前端应用中把所有的这些后端的 Pod 的地址都写死,然后以某种方式去访问其中一个 Pod 的服务,这样看上去是可以工作的,对吧?但是如果这个 Pod 挂掉了,然后重新启动起来了,是不是 IP 地址非常有可能就变了,这个时候前端就极大可能访问不到后端的服务了。


2. k8s为什么要发布服务

当我们通过Replication Controller(简称 RC)、ReplicaSet 、Deployment、StatefulSet 、DaemonSet创建完Pod后,每个Pod都会被分配到一个IP地址,而Pod的IP地址总是不稳定和难依赖的。假设后端的一组Pod为前端的Pod提供服务,此时如果后端的这组Pod异常重建,Pod的IP地址也随之改变,导致它们之间服务无法正常通信。

为了解决上面问题,k8s引入Service这样的概念。这样我们只需访问Service即可,不用关注Pod是否异常重建导致服务无法通信的问题。

3. 什么是Service

在没有使用 Kubernetes 之前,比如我们在部署一个WEB 服务的时候,前端一般部署一个 Nginx 作为服务的入口,然后 Nginx 后面肯定就是挂载的这个服务的大量后端服务,很早以前我们可能是去手动更改Nginx 配置中的 upstream 选项,来动态改变提供服务的数量,到后面出现了一些服务发现的工具,比如 Consul、ZooKeeper 还有我们熟悉的 etcd 等工具,有了这些工具过后我们就可以只需要把我们的服务注册到这些服务发现中心去就可以,然后让这些工具动态的去更新 Nginx 的配置就可以了,我们完全不用去手工的操作了,是不是非常方便。


同样的,要解决我们上面遇到的问题是不是实现一个服务发现的工具也可以解决?没错的,当我们 Pod 被销毁或者新建过后,我们可以把这个 Pod 的地址注册到这个服务发现中心去就可以,但是这样的话我们的前端应用就不能直接去连接后台的 Pod 集合了,应该连接到一个能够做服务发现的中间件上面,对吧?


为解决这个问题 Kubernetes 就为我们提供了这样的一个对象 Service,Service 是一种抽象的对象,它定义了一组 Pod 的逻辑集合和一个用于访问它们的策略,其实这个概念和微服务非常类似**。一个 Serivce 下面包含的 Pod 集合是由 Label Selector 来决定的。**

Service主要用于Pod之间的通信,对于Pod的IP地址而言,Service是提前定义好并且是不变的资源类型,在生产环境中最佳的实践方式就是每个应用互相调用时使用Service的名字进行连接,而非IP地址。


4. Service的类型

Kubernetes Service Type(服务类型)主要包括以下几种:

  • ClusterIP:在集群内部使用,默认值,只能从集群中访问。
  • NodePort:在所有安装了 Kube-Proxy 的节点上打开一个端口,此端口可以代理至后端Pod,可以通过 NodePort 从集群外部访问集群内的服务,格式为 NodeIP:NodePort。
  • LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
  • ExternalName:通过返回定义的 CNAME 别名,没有设置任何类型的代理,需要 1.7 或更高版本 kube-dns 支持。


5. 使用Service

5.1 定义Service

和创建其他类型的资源一样,定义一个YAML文件,即可通过kubectl客户端创建一个Service。假定有一组 Pod 服务,它们对外暴露了 80 端口,同时都被打上了 app=yinjay 这样的标签,那么我们就可以像下面这样来定义一个 Service 对象:

[root@k8s-master01 service]# cat /yaml/service/yinjay-80.yaml
apiVersion: v1
kind: Service
metadata:
  name: yinjay-80
spec:
  selector:
    app: yinjay
  ports:
  - protocol: TCP
    port: 32000
    targetPort: 80
    name: http

Tips:targetPort如果为空,targetPort将被设置为与Port字段相同的值。


5.2 创建Service

根据上述yaml文件配置创建一个名为yinjay-80的Service对象,它会将请求代理到TCP端口为80并且具有标签app=yinjay的Pod上。这个Service会被分配一个IP地址,通常称为ClusterIP,它会被服务的代理使用。在集群内部可以通过该ClusterIP(不建议使用ClusterIP进行访问)或Service名加上port(port名称)进行访问,该示例yinjay-80:32000(port名称)即可访问具有app=yinjay标签的Pod的80端口。

五、服务发布_Kubernetes

Tips:该 Service 还会持续的监听 selector 下面的 Pod,会把这些 Pod 信息更新到一个名为 yinjay-80 的Endpoints 对象上去。


创建Deployment

根据下面的yaml文件进行创建Deployment

[root@k8s-master01 service]# cat /yaml/service/nginx-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: app-nginx
spec:
  replicas: 3
  selector:    #selector:定义Deployment如何找到要管理的Pod,与template的label (标签)对应
    matchLabels:
      app: yinjay
  template:
    metadata:
      labels:
        app: yinjay  #使用label(标签)标记Pod
    spec:
      containers:
      - name: app-nginx
        image: nginx:1.14.2 #运行此Pod使用的镜像
        ports:
        - containerPort: 80  #容器用于发送和接收流量的端口

五、服务发布_Kubernetes_02


重新查看Service,该 Service 持续的监听定义的 selector,也就yinjay标签下面的 Pod,会把这些 Pod 信息更新到Endpoints 上去。

五、服务发布_Kubernetes_03


5.3 集群内IP访问方式

例如是多deployment(在同一命名空间下)之间需要互相的访问,此时创建一个测试的deployment

kubectl create deploy cluster-test --image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools -- sleep 3600


进入该测试deployment下的Pod,进行访问 yinjay-80 这个Service(此时Service Endpoints中的Pod,index.html已修改,方便看实验效果)。此时能看到访问Service IP + 端口号能够正常负载访问!

五、服务发布_Kubernetes_04

Tips:Cluster IP方式通过kube-proxy组件实现负载均衡和服务代理的功能。


5.4 集群内域名访问方式

采用域名 + 端口访问

五、服务发布_Kubernetes_05


也可以通过这种DNS方式进行访问,但是解析的还是Cluster IP。

五、服务发布_Kubernetes_06


5.5 Headless Service

如果是Headless Service,我们访问“yinjay-80.default.svc.cluster.local”这条 DNS 记录,就可以访问到 default 这个命名空间下面名为 yinjay-80 的 Service 所代理的某一个 Pod。(通常末尾svc.cluster.local没修改就不变)


下面更改普通Service为Headless Service,删除原来的,重新创建下面这个。

[root@k8s-master01 service]# cat /yaml/service/yinjay-80.yaml
apiVersion: v1
kind: Service
metadata:
  name: yinjay-80
spec:
  selector:
    app: yinjay
  clusterIP: None
  ports:
  - protocol: TCP
    port: 32000
    targetPort: 80
    name: http

五、服务发布_Kubernetes_07


进入该测试deployment下的Pod,测试访问Headless Service,没有Cluster IP,直接访问yinjay-80.default.svc.cluster.local就能访问 Service 所代理的某一个 Pod。(DNS轮询方式实现流量分发)

五、服务发布_Kubernetes_08


访问Service名称也可以。

五、服务发布_Kubernetes_09


5.6 多端口Service

对于某些服务,需要公开多个端口。 Kubernetes 允许在 Service 对象上配置多个端口定义。 为服务使用多个端口时,必须提供所有端口名称,以使它们无歧义。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - name: port1
      protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30001
    - name: port2
      protocol: TCP
      port: 8081
      targetPort: 8081
      nodePort: 30002
  type: NodePort


6. 使用NodePort对外发布服务

通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 NodeIp:NodePort,可以从集群的外部访问一个 NodePort 服务。

Kubernetes master 将从给定的配置范围内(默认:30000-32767)分配端口,每个 Node 将从该端口(每个 Node 上的同一端口)代理到 Service。

Tips:Service 的 spec.ports.nodePort 字段如果不指定的话会自动生成一个端口。


修改Service的yaml文件如下:

[root@k8s-master01 service]# cat yinjay-80.yaml
apiVersion: v1
kind: Service
metadata:
  name: yinjay-80
spec:
  selector:
    app: yinjay
  type: NodePort
  ports:
  - protocol: TCP
    port: 32000
    targetPort: 80
    name: http
    nodePort: 30076


创建Service,Service的端口是6666,暴露在Node节点上的端口是30076。

五、服务发布_Kubernetes_10


宿主机进行访问,访问方式NodeIP:NodePort,只要是各节点上的IP都可以。

五、服务发布_Kubernetes_11

五、服务发布_Kubernetes_12

五、服务发布_Kubernetes_13


7. 使用Service代理k8s外部服务

我们有时需要通过Service代理集群外部服务时,可以创建一个没有Selector字段的Service,之后再手动创建Endpoint添加外部服务即可,以下情况均可使用无选择器的Service,例如:

  • 希望在生产环境中使用某个固定的名称而非IP地址访问外部的中间件服务。
  • 希望Service指向另一个Namespace或其他集群中的服务。
  • 正在将工作负载转移到Kubernetes集群,但是一部分服务仍运行在Kubernetes集群之外的backend。


定义一个无Selector的yaml文件,下面的Service没有Selector字段,那就不会去筛选带标签的Pod,自然Endpoints也是None。(如果创建带有Selector字段和标签的,会自动创建一个和Service name同名的Endpoints)

[root@k8s-master01 service]# cat /yaml/service/nginx-svc-external.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  sessionAffinity: None
  type: ClusterIP

五、服务发布_Kubernetes_14


如果刚从的配置后面加上这个Endpoints的yaml内容,创建出来则会是带上subsets字段定义的IP。(此时删除刚才的Service,重新执行下面yaml内容的文件)

[root@k8s-master01 service]# cat /yaml/service/nginx-svc-external.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
spec:
  ports:
  - name: http
    port: 80      #暴露给集群内的端口,可改
    protocol: TCP
    targetPort: 80  #要与Endpoints的port一致,包括协议。
  sessionAffinity: None
  type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
  labels:
    app: nginx-svc-external
  name: nginx-svc-external
subsets:
- addresses:
  - ip: 121.14.77.221
  ports:
  - name: http
    port: 80
    protocol: TCP

五、服务发布_Kubernetes_15

Tips:同名的Service和Endpoints会自动建立连接!


进入一个Pod,来测试是否能访问到该Service所代理的外部服务,没问题!

五、服务发布_Kubernetes_16


8. ExternalName方式

ExternalName是 Service 的特例,它没有 selector,也没有定义任何的端口和 Endpoint。对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。


定义一个ExternalName的yaml文件

[root@k8s-master01 service]# cat /yaml/service/externalname-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  type: ExternalName
  externalName: www.baidu.com

当查找主机 external-service.default.svc.cluster.local 时,集群 DNS 服务返回 CNAME 记录, 其值为 www.baidu.com。 访问 external-service 的方式与其他服务的方式相同,但主要区别在于重定向发生在 DNS 级别,而不是通过代理或转发。


进入一个Pod当中,使用wget访问external-service服务。

五、服务发布_Kubernetes_17


9. Ingress对外暴露集群服务

9.1 传统架构和K8s架构访问

五、服务发布_Kubernetes_18

在没有使用Kubernetes的传统架构中,部署一个应用并使用域名进行发布的流程如下:

  1. 部署应用至宿主机,启动应用并暴露一个端口号。
  2. 通过Nginx或其他代理工具配置域名,并代理至后端应用。
  3. 在域名厂商进行域名解析,设置DNS记录至Nginx或其他代理工具(Nginx的前面可能还有其他代理服务器,在此不进行说明)的服务器上,之后就能通过域名访问我们的应用。


在使用Kubernetes时,部署一个应用并使用域名进行发布的流程如下:

  1. 部署应用至Kubernetes集群,容器内定义了程序启动的方式。
  2. 配置ClusterIP类型的Service,通过Selector链接到容器内的应用。
  3. 配置Ingress链接到该应用的Service,之后将域名解析到Ingress(Ingress前面可能还有其他代理服务器)对应的宿主机上即可。


9.2 为什么使用Ingress

可以使用 NodePort 和 LoadBlancer类型的 Service 可以把应用暴露给外部用户使用,除此之外,Kubernetes 还为我们提供了一个非常重要的资源对象可以用来暴露服务给外部用户,那就是Ingress。对于小规模的应用我们使用 NodePort 或许能够满足我们的需求,但是当你的应用越来越多的时候,你就会发现对于 NodePort 的管理就非常麻烦了,这个时候使用 Ingress 就非常方便了,可以避免管理大量的端口。


9.3 了解Ingress

Ingress就是实现用域名的方式访问应用。Ingress实现的方式有很多,比如Nginx、HAProxy、Treafik等,就Nginx而言,和上述提到的传统服务架构用Nginx类似。Ingress控制器在每个符合条件的宿主机上部署一个Pod,这个Pod里面运行的就是Nginx进程,里面的实现逻辑和宿主机部署Nginx的方式并无太大区别。

Ingress 其实就是从 Kuberenets 集群外部访问集群的一个入口,将外部的请求转发到集群内不同的 Service 上,其实就相当于 nginx、haproxy 等负载均衡代理服务器,可能你会觉得我们直接使用 nginx 就实现了,但是只使用 nginx 这种方式有很大缺陷。

每次有新服务加入的时候怎么改 Nginx 配置?不可能让我们去手动更改或者滚动更新前端的 Nginx Pod 吧?那我们再加上一个服务发现的工具比如 consul 如何?貌似是可以,对吧?Ingress 实际上就是这样实现的,只是服务发现的功能自己实现了,不需要使用第三方的服务了,然后再加上一个域名规则定义,路由信息的刷新依靠 Ingress Controller 来提供。

Ingress Controller 可以理解为一个监听器,通过不断地监听 kube-apiserver,实时的感知后端 Service、Pod 的变化,当得到这些信息变化后,Ingress Controller 再结合 Ingress 的配置,更新反向代理负载均衡器,达到服务发现的作用。


9.4 Ingress Controller安装

官方安装文档:https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters ,如果使用官网的yaml,记得自己先同步gcr镜像,然后再替换镜像地址。


下面进行安装Ingress Controller,先定义一个yaml。

[root@k8s-master01 Ingress]# cat /yaml/Ingress/deploy-ingress.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.7.1
  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.7.1
  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.7.1
  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:
  - coordination.k8s.io
  resourceNames:
  - ingress-nginx-leader
  resources:
  - leases
  verbs:
  - get
  - update
- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
  - watch
  - get
---
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.7.1
  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.7.1
  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
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - list
  - watch
  - get
---
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.7.1
  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.7.1
  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.7.1
  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.7.1
  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.7.1
  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.7.1
  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.7.1
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  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: NodePort
---
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.7.1
  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.7.1
  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
        app.kubernetes.io/part-of: ingress-nginx
        app.kubernetes.io/version: 1.7.1
    spec:
      containers:
      - args:
        - /nginx-ingress-controller
        - --election-id=ingress-nginx-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: registry.cn-beijing.aliyuncs.com/dotbalo/ingress-nginx-controller:v1.7.1
        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.7.1
  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.7.1
      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: registry.cn-beijing.aliyuncs.com/dotbalo/kube-webhook-certgen:v20230312
        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.7.1
  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.7.1
      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: registry.cn-beijing.aliyuncs.com/dotbalo/kube-webhook-certgen:v20230312
        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.7.1
  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.7.1
  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


安装ingress服务并查询Pod状态,出现以下情况即可。

kubectl create -f deploy-ingress.yaml

五、服务发布_Kubernetes_19

安装后会将 NGINX Ingress Controller 安装在一个统一的 ingress-nginx 的 namespace 下面!


9.5 使用域名发布K8s内部服务

在完成Ingress Controller安装后,进行创建一个测试nginx的Pod。

kubectl create deploy nginx --image=nginx:1.14.2


暴露Service的80端口

#命令格式:kubectl expose deploy deployment名称 --port 要暴露的端口
kubectl expose deploy nginx --port 80

五、服务发布_Kubernetes_20


定义一个Ingress的yaml文件

[root@k8s-master01 Ingress]# cat web-ingress.yaml
apiVersion: networking.k8s.io/v1  #版本大于1.22,必须选择v1,小于1.22是v1beta1
kind: Ingress
metadata:
  name: nginx-ingress
spec:
  ingressClassName: nginx #ingressClassName:指定ingress controller的名字,一个集群中可以有多个controller,如果是ingress-nginx,controller名字为nginx。(可通过这个命令查看kubectl get ingressclass)
  rules:  #一个Ingress可以配置多个rule。
  - host: nginx.yinjay.com #一般都会配置对应的域名。
    http:
     paths: #域名的location配置,同一个host可以配置多个path。比如有一个路径格式为xxx.com/abc,可以配置path为/abc,每个路径都有一个对应的backend,对应到应用的Service和Port。
      - backend: #描述Service和Port的组合,对Ingress匹配主机和路径的HTTP与HTTPS请求将被发送到对应的后端。
          service:
            name: nginx   #代理的Service名字
            port:
              number: 80  #代理的Service端口配置
              #name:web  #名字型的端口号配置,比如web,表示Port的名字。
        path: /
        pathType: ImplementationSpecific #pathType:路径的匹配方式,目前有ImplementationSpecific、Exact和Prefix方式。

关于pathType

ImplementationSpecific:这种类型的路由匹配根据Ingress Controller来实现,可以当作一个单独的类型。

Exact:精确匹配,比如配置的path为/bar,那么/bar/将不能被路由。

Prefix:前缀匹配,基于以“/”分隔的URL路径。比如path为/abc,可以匹配到/abc/bbb等,比较常用的配置。


创建并查看Ingress

五、服务发布_Kubernetes_21


查看Ingress暴露的端口

五、服务发布_Kubernetes_22


浏览器访问域名,宿主机需要做host解析(节点上的Node IP,或者VIP)。

五、服务发布_Kubernetes_23


本篇文章内容参考杜宽的《云原生Kubernetes全栈架构师》,视频、资料文档等,大家可以多多支持!还有k8s训练营“我为什么这么菜”知乎博主等资料文档,感谢无私奉献!

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

上一篇: 六、配置管理 下一篇: 四、自动扩缩容HPA
  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  O704k6GYsxMM   2023年11月13日   19   0   0 rkeDockerkubernetes
BMwtnym6fXTR