【问题标题】:Ingress configuration for k8s in different namespaces不同命名空间中 k8s 的入口配置
【发布时间】: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 所在的同一命名空间中,则此服务可以正常工作。

【问题讨论】:

    标签: kubernetes kubernetes-ingress nginx-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://stackoverflow.com/a/51899301/2995449

    【讨论】:

      【解决方案3】:

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

      1. 入口控制器(本质上是一个单独的 Pod/Deployment 以及 可用于利用路由和代理的服务。基于 例如 nginx 容器);
      2. 入口规则(一个单独的 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 定义一个规则来处理和路由流量基于此类定义的规则。

        解决方案:

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

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

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

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

        2. 或者您可以在定义了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清单文件

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-04
          • 2022-01-26
          • 1970-01-01
          • 2020-12-07
          • 1970-01-01
          • 2019-12-26
          相关资源
          最近更新 更多