使用 Ingress 私有化发布应用

通过创建由 Ingress 控制器管理的 Ingress 资源,在您的 Red Hat® OpenShift® on IBM Cloud® 集群中私有地对外暴露多个应用。

先决条件

开始使用 Ingress 之前,请查看以下先决条件。

  • 设置 Ingress 需要以下 IBM Cloud IAM 角色
    • IBM Cloud Kubernetes Service中集群的 管理员 平台访问角色。
    • 所有 IBM Cloud Kubernetes Service 名称空间 (Red Hat OpenShift 项目) 中的 管理者 服务访问角色。
  • 如果某个区域发生故障,那么您可能会在对该区域中的 Ingress 控制器所公开的应用程序的请求中看到间歇性故障。
  • 为确保高可用性,建议每个专区至少有两个工作程序节点。

使用公共云服务端点私下公开应用程序

经典集群 虚拟私有云

如果集群是在经典基础架构上创建的,或者如果集群是在 VPC 基础架构上创建的,并且您在集群创建期间启用了公共云服务端点,那么缺省情况下将仅使用公共 Ingress 控制器来创建集群。 要私下公开应用程序,必须首先创建专用 Ingress 控制器。 然后,您必须将 Ingress 控制器注册到一个子域名下,并可选择导入您自己的 TLS 证书。

步骤 1:部署应用程序并创建应用程序服务

首先部署应用程序,并创建 Kubernetes 服务来公开这些应用程序。

  1. 将应用程序部署到集群。 确保在配置文件的 metadata 部分中向部署添加标签,例如 app: code。 需要此标签来标识应用程序运行的所有 Pod,以便将这些 Pod 纳入 Ingress 负载均衡范围。

  2. 对于要公开的每个应用程序部署,创建 Kubernetes ClusterIP 服务。 您的应用必须通过 Kubernetes 服务对外暴露,才能被纳入Ingress负载均衡。

oc expose deploy <app_deployment_name> --name my-app-svc --port <app_port> -n <namespace>

步骤 2:使用 TLS 证书和 Kubernetes 密钥配置 TLS 终止服务

您的 TLS 证书必须作为 Kubernetes 密钥存储在应用所在的每个命名空间中。

TLS 自定义域名的秘诀

若要为您自行创建的域名(例如通过外部提供商注册的域名)配置 TLS 密钥,请参阅 《为自定义子域名配置 TLS 密钥》。 以下步骤同时适用于经典集群和 VPC 集群。

TLS IBM 托管域名的密钥

  1. 列出集群中的现有子域。 在输出的 子域 列中,复制具有最高 000<n> 值的子域。
    ibmcloud oc nlb-dns ls --cluster CLUSTER_NAME_OR_ID
    
    在此示例输出中, mycluster-a1b2cdef345678g9hi012j3kl4567890-0002.us-south.containers.appdomain.cloud 子域具有最高 000<n>0002
    Subdomain                                                                               Load Balancer Hostname                        Health Monitor   SSL Cert Status           SSL Cert Secret Name
    mycluster-a1b2cdef345678g9hi012j3kl4567890-0000.us-south.containers.appdomain.cloud     ["1234abcd-us-south.lb.appdomain.cloud"]      None             created                   mycluster-a1b2cdef345678g9hi012j3kl4567890-0000
    mycluster-a1b2cdef345678g9hi012j3kl4567890-0001.us-south.containers.appdomain.cloud     ["5678efgh-us-south.lb.appdomain.cloud"]      None             created                   mycluster-a1b2cdef345678g9hi012j3kl4567890-0001
    mycluster-a1b2cdef345678g9hi012j3kl4567890-0002.us-south.containers.appdomain.cloud     ["9012ijkl-us-south.lb.appdomain.cloud"]      None             created                   mycluster-a1b2cdef345678g9hi012j3kl4567890-0002
    
  2. 在复制的子域中,将子域中的 000<n> 值更改为 000<n+1>。 例如,mycluster-a1b2cdef345678g9hi012j3kl4567890-0002.us-south.containers.appdomain.cloud 子域将更改为 mycluster-a1b2cdef345678g9hi012j3kl4567890-0003.us-south.containers.appdomain.cloudn+1 值指示您在此集群中创建的下一个连续子域。 您可以在后续步骤中注册此子域。 注册域名时,系统会自动为该域名生成一个 TLS 密钥。 私钥名称遵循子域的截断格式,例如 mycluster-a1b2cdef345678g9hi012j3kl4567890-0003

步骤 3: 创建并配置专用 Ingress 控制器

准备好域名和 TLS 证书后,您必须创建一个私有 Ingress 控制器,并使用您的域名对该控制器进行配置。

  1. 为专用 Ingress 控制器创建配置文件。
    apiVersion: operator.openshift.io/v1
    kind: IngressController
    metadata:
      name: private-ingress-controller
      namespace: openshift-ingress-operator
    spec:
      #defaultCertificate: If you are using a custom domain, specify the domain certificate
        #name: custom-certs-default
      replicas: 2
      domain: <domain>
      endpointPublishingStrategy:
        loadBalancer:
          scope: Internal
        type: LoadBalancerService
    
  2. 在集群的 openshift-ingress-operator 项目中创建 IngressController 资源。 创建 IngressController, 将根据您在上一步中设置的 IngressController 设置,在 openshift-ingress 项目中自动创建和部署私有 Ingress 控制器。 此外,将创建 Ingress 控制器服务以使用 IP 地址 (经典集群) 或 VPC 主机名 (VPC 集群) 公开 Ingress 控制器。
    oc create -f private-ingress-controller.yaml -n openshift-ingress-operator
    
  3. 运行 oc get 命令,并在 router-private-ingress-controller 服务的 EXTERNAL IP 字段中找到 IP 地址或 VPC 主机名。
    oc get svc router-private-ingress-controller -n openshift-ingress
    
    经典集群的输出示例。
    NAME                                  TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                      AGE
    router-private-ingress-controller     LoadBalancer   172.21.57.132    10.XX.XX.XX    80/TCP,443/TCP,1940/TCP      3m
    
    VPC 集群的输出示例:
    NAME                                  TYPE           CLUSTER-IP       EXTERNAL-IP                             PORT(S)                      AGE
    router-private-ingress-controller     LoadBalancer   172.21.57.132    1234abcd-us-south.lb.appdomain.cloud    80/TCP,443/TCP,1940/TCP      3m
    
  4. 向先前选择的域注册服务的外部 IP 地址或 VPC 主机名。
    • 定制域: 使用 DNS 提供者将 router-private-ingress-controller 服务的外部 IP 地址作为 A 记录 (经典集群) 或 VPC 主机名作为映射到定制域的 CNAME (VPC 集群) 进行添加。
    • IBM提供的域: 为 router-private-ingress-controller 服务的 VPC 主机名创建 DNS 条目。 运行以下命令时,将自动生成在 private-ingress-controller.yaml 文件中指定的子域,并向 router-private-ingress-controller 服务注册该子域。 在您指定应用程序运行位置的项目中,系统会自动为该域名生成一个 TLS 密钥。 私钥名称遵循子域的截断格式,例如 mycluster-a1b2cdef345678g9hi012j3kl4567890-0003
        ibmcloud oc nlb-dns create vpc-gen2 --cluster <cluster_name_or_ID> --lb-host <VPC_hostname> --secret-namespace <project>
        ```
    
    
    

步骤 4:创建 Ingress 资源

Ingress 资源定义了 Ingress 控制器用于将流量路由到您的应用服务的路由规则。

  1. 定义一个 Ingress 资源配置文件,该文件使用 IBM 提供的域名或您的自定义域名,将传入的网络流量路由到您之前创建的服务。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: myingressresource
    spec:
      tls:
      - hosts:
        - <subdomain>
        secretName: <custom_secret_name>
      rules:
      - host: <subdomain>
        http:
          paths:
          - path: /<app1_path>
            backend:
                service:
                    name: <app1_service>
                    port:
                        number: 80
          - path: /<app2_path>
            backend:
                serivce:
                  name: <app2_service>
                  port:
                    number: 80
    
    tls
    如果您想使用 TLS,请在您的资源中包含此 TLS 部分。 将 <domain> 替换为子域。 请勿将 * 用作主机,也不要将 host 属性留空,以免在创建 Ingress 时出现错误。
    请将 <tls_secret_name> 替换为您之前创建的、包含自定义域名 TLS 证书和密钥的密钥,或者替换为针对 IBM 提供的子域名自动生成的 TLS 密钥。
    host
    <domain> 替换为子域。
    如果您的集群中有多个项目,且这些项目中都暴露了应用程序,则每个项目都需要一个 Ingress 资源。 可以在每个资源中使用相同的子域,也可以在每个资源中使用不同的子域。 例如,如果使用通配符域,那么可以将通配符子域追加到域的开头,例如 subdomain1.custom_domain.net
    请勿将 * 用作主机,也不要将 host 属性留空,以免在创建 Ingress 时出现错误。
    path
    <app_path> 替换为应用程序正在侦听的路径。 该路径将附加到 IBM 提供的域或定制域,以创建应用程序的唯一路径。 在 Web 浏览器中输入此路径时,网络流量会路由到 Ingress 控制器。 Ingress 控制器会查找相关联的服务,并将网络流量转发至该服务。 随后,该服务将流量转发至运行该应用的 Pod。 许多应用程序不会监听特定路径,而是使用根路径和特定端口。 在这种情况下,请将根路径定义为 /,且不要为您的应用指定单独的路径。
    例如,要使用 http://domain/,请输入 / 作为路径。 对于 http://domain/app1_path,请将路径设置为 /app1_path
    serviceName
    请将 <app1_service><app2_service> 等替换为您为发布应用而创建的服务名称。 如果您的应用由集群中不同项目中的服务所提供,请仅包含位于同一项目中的应用服务。 对于每个包含您希望对外公开的应用程序的项目,您都必须创建一个 Ingress 资源。
    servicePort
    服务侦听的端口。 使用针对应用程序创建 Kubernetes 服务时定义的端口。
  2. 为集群创建 Ingress 资源。 请确保该资源部署到与您在资源中指定的应用服务位于同一项目中。

    oc apply -f myingressresource.yaml -n <project>
    
  3. 验证 Ingress 资源是否已成功创建。 如果事件中的消息指出您的资源配置存在错误,请修正资源文件中的值,然后重新应用该资源文件。

    oc describe ingress myingressresource
    

将在应用程序服务所在的项目中创建 Ingress 资源,并向 Ingress 控制器注册应用程序。

步骤 5:通过专用网络访问应用程序

  1. 经典集群:在访问您的应用程序之前,请确保能够访问 DNS 服务。 要使用缺省外部 DNS 提供程序,必须 配置具有公共访问权的边缘节点配置 Virtual Router Appliance

  2. 在专用网络中,在 Web 浏览器中输入应用程序服务的 URL。

    https://<domain>/<app1_path>
    

    如果公开了多个应用程序,请通过更改附加到该 URL 的路径来访问这些应用程序。

    https://<domain>/<app2_path>
    

    如果使用通配符域,请使用这些应用程序自己的子域来访问这些应用程序。

    http://<subdomain1>.<domain>/<app1_path>
    
    http://<subdomain2>.<domain>/<app1_path>
    

无法通过 Ingress 连接到应用程序? 请尝试 对 Ingress 进行故障诊断

仅使用私有云服务端点在 VPC 集群中私下公开应用程序

如果在 VPC 基础结构上创建集群,并且在创建集群时仅启用了私有云服务端点,那么可以使用缺省专用 Ingress 控制器向来自专用网络的请求公开集群中的应用程序。

步骤 1:部署应用程序并创建应用程序服务

首先部署应用程序,并创建 Kubernetes 服务来公开这些应用程序。

  1. 将应用程序部署到集群。 确保在配置文件的 metadata 部分中向部署添加标签,例如 app: code。 需要此标签来标识应用程序运行的所有 Pod,以便将这些 Pod 纳入 Ingress 负载均衡范围。

  2. 对于要公开的每个应用程序部署,创建 Kubernetes ClusterIP 服务。 您的应用必须通过 Kubernetes 服务对外暴露,才能被纳入Ingress负载均衡。

oc expose deploy <app_deployment_name> --name my-app-svc --port <app_port> -n <namespace>

步骤 2:使用 TLS 证书和 Kubernetes 密钥配置 TLS 终止服务

您的 TLS 证书必须作为 Kubernetes 密钥存储在应用所在的每个命名空间中。

步骤 3:创建 Ingress 资源

Ingress 资源定义了 Ingress 控制器用于将流量路由到您的应用服务的路由规则。

  1. 定义一个 Ingress 资源配置文件,该文件使用 IBM 提供的域名或您的自定义域名,将传入的网络流量路由到您之前创建的服务。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: myingressresource
    spec:
      tls:
      - hosts:
        - <custom_domain>
        secretName: <custom_secret_name>
      rules:
      - host: <domain>
        http:
          paths:
          - path: /<app1_path>
            backend:
                service:
                  name: <app1_service>
                  port:
                    number: 80
          - path: /<app2_path>
            backend:
                service:
                  name: <app2_service>
                  port:
                    number: 80
    
    tls
    如果您想使用 TLS,请在您的资源中包含此 TLS 部分。
    <domain> 替换为子域。 请勿在主机中使用 *,也不要将主机属性留空,以免在创建 Ingress 时出现错误。
    请将 <tls_secret_name> 替换为您之前创建的、用于存储自定义域名 TLS 证书和密钥的密钥,或者替换为针对 IBM 提供的子域名自动生成的 TLS 密钥。
    host
    <domain> 替换为 IBM 提供的 Ingress 子域名或您的自定义域名。
    如果您的集群中有多个项目,且这些项目中都暴露了应用程序,则每个项目都需要一个 Ingress 资源。 可以在每个资源中使用相同的子域,也可以在每个资源中使用不同的子域。 例如,如果使用通配符域,那么可以将通配符子域附加到域的开头,例如 subdomain1.custom_domain.netsubdomain1.mycluster-<hash>-0000.us-south.containers.appdomain.cloud。 请勿将 ``* 用作主机,也不要将 host 属性留空,以免在创建 Ingress 时出现错误。
    path
    <app_path> 替换为应用程序正在侦听的路径。 该路径将附加到 IBM 提供的域或定制域,以创建应用程序的唯一路径。 在 Web 浏览器中输入此路径时,网络流量会路由到 Ingress 控制器。 Ingress 控制器会查找相关联的服务,并将网络流量转发至该服务。 随后,该服务将流量转发至运行该应用的 Pod。 许多应用程序不会监听特定路径,而是使用根路径和特定端口。 在这种情况下,请将根路径定义为 /,且不要为您的应用指定单独的路径。
    例如,要使用 http://domain/,请输入 / 作为路径。 对于 http://domain/app1_path,请将路径设置为 /app1_path
    name
    请将 <app1_service><app2_service> 等替换为您为发布应用而创建的服务名称。 如果您的应用由集群中不同项目中的服务所提供,请仅包含位于同一项目中的应用服务。 对于每个包含需要对外公开的应用程序的项目,您都必须创建一个 Ingress 资源。
    port
    服务侦听的端口。 使用针对应用程序创建 Kubernetes 服务时定义的端口。
  2. 为集群创建 Ingress 资源。 请确保该资源部署到与您在资源中指定的应用服务位于同一项目中。

    oc apply -f myingressresource.yaml -n <project>
    
  3. 验证 Ingress 资源是否已成功创建。 如果事件中的消息指出您的资源配置存在错误,请修正资源文件中的值,然后重新应用该资源文件。

    oc describe ingress myingressresource
    

将在应用程序服务所在的项目中创建 Ingress 资源,并向 Ingress 控制器注册应用程序。

第 4 步:访问您的应用

在 Web 浏览器中,输入要访问的应用程序服务的 URL。

https://<domain>/<app1_path>

如果公开了多个应用程序,请通过更改附加到该 URL 的路径来访问这些应用程序。

https://<domain>/<app2_path>

如果使用通配符域,请使用这些应用程序自己的子域来访问这些应用程序。

http://<subdomain1>.<domain>/<app1_path>
http://<subdomain2>.<domain>/<app1_path>

无法通过 Ingress 连接到应用程序? 请尝试 对 Ingress 进行故障诊断