不同命名空间中 k8s 的入口配置

Posted

技术标签:

【中文标题】不同命名空间中 k8s 的入口配置【英文标题】:Ingress configuration for k8s in different namespaces 【发布时间】:2020-05-07 17:19:40 【问题描述】:

我需要在 azure k8s 上配置 Ingress nginx,我的问题是是否可以在一个命名空间等中配置入口。 ingress-nginx 和其他命名空间中的一些服务,例如。资源? 我的文件如下所示:

# ingress-nginx.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ingress-nginx
  template:
    metadata:
      labels:
        app: ingress-nginx
      annotations:
        prometheus.io/port: '10254'
        prometheus.io/scrape: 'true' 
    spec:
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.12.0
          args:
            - /nginx-ingress-controller
            - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --annotations-prefix=nginx.ingress.kubernetes.io
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
          - name: http
            containerPort: 80
          - name: https
            containerPort: 443
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
# configmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
---
# default-backend.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: default-http-backend
  labels:
    app: default-http-backend
  namespace: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: default-http-backend
  template:
    metadata:
      labels:
        app: default-http-backend
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: default-http-backend
        # Any image is permissible as long as:
        # 1. It serves a 404 page at /
        # 2. It serves 200 on a /healthz endpoint
        image: gcr.io/google_containers/defaultbackend:1.4
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi
---
apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: ingress-nginx
  labels:
    app: default-http-backend
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: default-http-backend

kind: Service
apiVersion: v1
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app: ingress-nginx
spec:
  externalTrafficPolicy: Local
  type: LoadBalancer
  selector:
    app: ingress-nginx
  ports:
  - name: http
    port: 80
    targetPort: http
  - name: https
    port: 443
    targetPort: https
        # app-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: app-ingress
  namespace: ingress-nginx
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
    - hosts:
      - api-sand.fake.com
  rules:
  - host: api-sand.fake.com
    http:
      paths:
      - backend:
          serviceName: api-sand
          servicePort: 80
        path: /

然后我在 resources 命名空间中运行了一些应用程序,问题是我收到以下错误

error obtaining service endpoints: error getting service resources/api-sand from the cache: service resources/api-sand was not found

如果我将 api-sand 部署在 ingress 所在的同一命名空间中,则此服务可以正常工作。

【问题讨论】:

【参考方案1】:

与其在ingress-nginx 命名空间中创建入口app-ingress,不如在您拥有服务api-sand 和pod 的命名空间中创建它。

另外,还有一种方法可以通过externalName.Checkout Kubernetes Cross Namespace Ingress Network 在一个命名空间中实现入口并在另一个命名空间中实现服务

这是here引用的示例。

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  type: ExternalName
  externalName: test-service.namespacename.svc.cluster.local

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: my-service
          servicePort: 80

【讨论】:

你是如何让它工作的?我不断收到service "default/my-service" is type "ExternalName", expected "NodePort" or "LoadBalancer"; 我也无法让它工作。我想知道这是否是提供程序和/或版本问题?我在 EKS 1.14... () 在描述入口时,显示此错误。有什么线索可以解决吗?【参考方案2】:

其实是可以的,你可以在namespace A中定义一个Ingress和一个ExternalName类型的service,而ExternalName指向namespace B中service的DNS。更多细节请参考这个答案:https://***.com/a/51899301/2995449

【讨论】:

【参考方案3】:

对于那些对 Kubernetes 及其入口选项比较陌生的人,我想进一步简化答案。 要使 ingress 正常工作,需要提供 2 个不同的东西:

    入口控制器(本质上是一个单独的 Pod/Deployment 以及 可用于利用路由和代理的服务。基于 例如 nginx 容器); 入口规则(一个单独的 Kubernetes kind: Ingress 的资源。只有 Ingress 才会生效 控制器已经是deployed)

现在,Ingress Controller 可以部署在任何命名空间中,实际上,通常部署在与您的应用服务分开的命名空间中。它可以开箱即用地查看集群中所有命名空间中的 Ingress 规则并将它们拾取。但是,Ingress 规则必须驻留在它们配置的应用程序所在的命名空间中。

有一些解决方法,但这是最常见的方法。

【讨论】:

很好的答案:请问在创建 Ingress 规则时,是否都需要在单个 Ingress 规则中定义它们,或者每个命名空间内是否可以有多个 Ingress 规则,每个映射到一个服务在那个命名空间内?交易 嗯,它不像网络策略那么简单。并不是说 NP 很简单,而是有一种相对简单的方法可以合并它们。有了 Ingress,事情就不会这么简单了,因为标准化底层 Ingress Controller 实现更加困难,特别是因为它们是建立在完全独立的组件之上的,这些组件早在 Kubernetes 诞生之前就已经存在,比如 Nginx。话虽如此,你不是第一个,@Choco,谁有这个想法:github.com/kubernetes/ingress-nginx/issues/1539【参考方案4】:

每个入口资源都有一个way to configure 您的默认后端,尽管文档说它通常在入口控制器级别进行配置。

例如:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myingress
  namespace: myns
spec: 
  defaultBackend:
    service:
      name: default-http-backend
      port: 
        number: 80
...

这里 default-http-backend 必须定义在与入口资源相同的命名空间中。

【讨论】:

【参考方案5】:

外部流量来自ingress controller service,它负责根据定义的路由规则或我们在 k8s 世界中称为 ingress rules 的方式路由流量。

换句话说,ingress 资源只是路由规则(认为它类似于 DNS 记录),因此当您定义 ingress 资源时,您只需为 ingress controller 定义一个规则来处理和路由流量基于此类定义的规则。

解决方案:

    由于Ingress 只是路由规则,您可以在集群中的任何位置(在任何namespace)中定义此类规则,controller 应在监控此类资源的创建并做出相应反应时选择它们。

    这里是使用kubectl轻松创建入口的方法

    kubectl create ingress <name> -n namespaceName --rule="host/prefix=serviceName:portNumber"

    注意:添加--dry-run=client -oyaml生成yaml清单文件

    或者您可以在定义了ingress 的同一namespace 中创建ExternalName 类型的服务。此类外部服务可以指向任何 URL(位于 namespace 甚至 k8s 集群之外的服务)

    这是一个示例,展示了如何使用 kubectl 创建 ExternalName 服务:

    kubectl create service externalname ingress-ns -n namespaceName --external-name=serviceName.namespace.svc.cluster.local --tcp=80:80 --dry-run=client -oyaml

这应该会生成类似于以下内容的内容:

kind: Service
apiVersion: v1
metadata:
  name: nginx
  namespace: ingress-ns
spec:
  type: ExternalName
  externalName: serviceName.namespace.svc.cluster.local #or any external svc
  ports:
  - port: 80 #specify the port of service you want to expose 
    targetPort: 80 #port of external service 

如上所述,创建一个入口如下: kubectl create ingress <name> -n namespaceName --rule="host/prefix=serviceName:portNumber"

注意:添加--dry-run=client -oyaml生成yaml清单文件

【讨论】:

以上是关于不同命名空间中 k8s 的入口配置的主要内容,如果未能解决你的问题,请参考以下文章

k8s基础整理-标签/注解/命名空间

k8s命名空间Namespace介绍与使用,以及用kubens插件管理namespace

cicd怎么解决配置中心

在 Spring Boot 应用程序中获取 k8s 命名空间?

k8s 网络基础

如何在特定命名空间中创建 K8S 部署?