Kubernetes 部署一个外网可访问的服务

2 阅读3分钟

本文通过部署 ingress-nginx 来暴露一个外网可访问的 HTTP 服务

主要步骤有:

    1. 部署后端服务,这里以 nginx 作为后端处理请求的服务,可以替换成自己的服务
    1. 部署后端服务的Service。
    1. 部署 Ingress Controller ,用于处理静态规则请求
    1. 部署 Ingress ,用于将 ingress-nginx 的请求转发到后端服务上

部署Nginx作为后端服务

通过 kubectl apply -f 下面的文件,部署出有三个 Pod 的Nginx服务

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: ingress-nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.14.2
          ports:
            - containerPort: 80

部署Nginx Service

通过Service给Pod增加集群内访问的入口

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: ingress-nginx
spec:
  selector:
    app: nginx
  ports:
    - name: http
      port: 80
      targetPort: 80 # nginx pod 对应的端口

为什么要引入Ingress

kube-proxy 实现了四层负载,但是在四层负载中看不到主机名、请求头和证书等七层负载的内容,并且Service集群内的服务,如果要灵活可配置各种转发,Service就会有较大的限制,所以引入了Ingress来完成七层负载的内容来弥补这些缺点,Nodeport 和ingress 暴露服务的区别也在这里。

Ingress 、IngressClass 和 IngressController 是什么关系?

Ingress 跟 Service 一样属于是转发的静态规则,实现真正转发逻辑的并不是Ingress的静态规则,而是Ingress Controller 根据规则来处理相应的转发,类似于kube-proxy 通过Service的规则来处理请求。

但是如果只有Ingress Controller 和 Ingress的话,那集群只能有一个控制器的Deployment ,当业务日渐复杂,Ingress规则逐渐增加,管理起来的复杂度会相对较高,所以引入了Ingress Class 来解耦 Ingress 和 Ingress Controller 的关系,从而实现多个Ingress Controller 处理多种不同业务需求。

image.png

image.png

部署 Ingress Controller 和 Ingress Class

通过 Nginx Ingress部署文档 部署 ingress-controller 。但是直接通过它提供的文件部署有以下问题

  1. unknown field "ipFamilyPolicy" in io.k8s.api.core.v1.ServiceSpec字段不支持,所以直接将对应字段去掉不进行设置
  2. 镜像在国内没有科学上网无法正常拉取,所以替换了阿里云的镜像
  3. 部署后获取Ingress 的service信息发现外部地址无法获取, Service 一直处于 Pending 的状态
$ kubectl get service -n <namespace>

NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer    10.101.255.31   Pending       80:38888/TCP,443:45486/TCP   65m

通过stackoverflow.com/questions/4… 该问题知道,是在自己的服务器通过 kubeadm 搭建的集群,所以没有集成LoadBalancer,暴露端口可以通过 NodePort 方式来暴露端口给外部

minikube 的话可以使用 这个方式解决

修改成NodePort后重新查看Service的状态

kubectl get service -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.101.255.31   <none>        80:38888/TCP,443:45486/TCP   65m

经过上述修改后的完整文件:github.com/caijiatao/g…

增加Ingress 规则

有了Ingress之后需要转发到后端的规则,来转发到后端服务

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  namespace: ingress-nginx
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - backend:
              service:
                name: nginx-service
                port:
                  number: 80 # 跟service的port一致
            path: /
            pathType: Prefix

最后我们用一张图来总结部署起来的内容:

image.png