搜索

配置集群

download PDF
OpenShift Container Platform 3.11

OpenShift Container Platform 3.11 安装和配置

摘要

OpenShift 安装和配置主题涵盖环境中安装和配置 OpenShift 的基础知识。将这些主题用于启动和运行 OpenShift 所需的一次性任务。

第 1 章 概述

本指南涵盖了安装后 OpenShift Container Platform 集群的更多配置选项。

第 2 章 设置 Registry

2.1. 内部 Registry 概述

2.1.1. 关于 Registry

OpenShift Container Platform 可以从源代码构建 容器镜像,部署并管理它们的生命周期。为此,OpenShift Container Platform 提供了一个内部集成的容器镜像 registry,可在 OpenShift Container Platform 环境中部署以在本地管理镜像。

2.1.2. 集成的或独立 registry

在初始安装完整 OpenShift Container Platform 集群期间,可能会在安装过程中自动部署 registry。如果没有,或者您要进一步自定义 registry 的配置,请参阅在现有集群中部署 registry。

虽然它可以部署为作为完整 OpenShift Container Platform 集群集成的一部分运行,但 OpenShift Container Platform registry 可以作为独立容器镜像 registry 单独安装。

要安装独立 registry,请遵循安装独立 Registry。此安装路径部署运行 registry 和专用 Web 控制台的一体化集群。

2.2. 在现有集群中部署 registry

2.2.1. 概述

如果集成的 registry 之前在 OpenShift Container Platform 集群的初始安装过程中没有被自动部署,或者如果不再成功运行,您需要在现有集群中重新部署它,请参阅以下部分来了解部署新 registry 的选项。

注意

如果您安装了 独立 registry,则不需要这个主题。

2.2.2. 设置 Registry 主机名

您可以为内部和外部引用配置 registry 的主机名和端口。通过这样做,镜像流将为镜像提供基于主机名的推送和拉取规格,允许使用镜像与对 registry 服务 IP 的更改进行隔离,并有可能允许镜像流及其引用在集群中可移植。

要设置从集群内部引用 registry 的主机名,请在 master 配置文件的 imagePolicyConfig 部分中设置 internalRegistryHostname。外部主机名通过在同一位置设置 externalRegistryHostname 值来控制。

镜像策略配置

imagePolicyConfig:
  internalRegistryHostname: docker-registry.default.svc.cluster.local:5000
  externalRegistryHostname: docker-registry.mycompany.com

registry 本身必须使用相同的内部主机名值进行配置。这可以通过在 registry 署配置中设置 REGISTRY_OPENSHIFT_SERVER_ADDR 环境变量或设置 registry 配置的 OpenShift 部分中的值来完成。

注意

如果您已经为 registry 启用了 TLS,服务器证书必须包含您希望引用 registry 的主机名。有关添加主机名到服务器证书的说明,请参阅保护registry

2.2.3. 部署 Registry

要部署集成的容器镜像 registry,请以具有集群管理员特权的用户身份使用 oc adm registry 命令。例如:

$ oc adm registry --config=/etc/origin/master/admin.kubeconfig \1
    --service-account=registry \2
    --images='registry.redhat.io/openshift3/ose-${component}:${version}' 3
1
--config集群管理员 CLI 配置文件 的路径。
2
--service-account 是用于运行 registry pod 的服务帐户。
3
为 OpenShift Container Platform 拉取正确的镜像是必需的。${component}${version} 在安装过程中会被动态替换。

这将创建服务和部署配置,两者均称为 docker-registry。部署成功后,会使用类似于 docker-registry-1-cpty9 的名称创建 pod。

查看创建 registry 时可以指定的完整选项列表:

$ oc adm registry --help

--fs-group 的值需要是 registry 使用的 SCC 所允许的(通常为有限制的 SCC)。

2.2.4. 将 Registry 部署为 DaemonSet

使用 oc adm registry 命令将 registry 部署为带有 --daemonset 选项的 DaemonSet

DaemonSet 可确保在创建节点时,节点包含指定 pod 的副本。删除节点时,会收集 pod。

如需有关 DaemonSet 的更多信息,请参阅使用 Daemonsets

2.2.5. registry 计算资源

默认情况下,创建 registry 时没有设置计算资源请求或限值。对于生产环境,强烈建议更新 registry 的部署配置,以便为 registry 容器集设置资源请求和限值。否则,registry pod 将被视为 BestEffort pod

有关配置请求和限制的更多信息,请参阅计算资源

2.2.6. Registry 的存储

registry 存储容器镜像和元数据。如果您只是使用 registry 来部署 pod,它会使用一个在 pod 退出时销毁的临时卷。任何用户已构建或推送到 registry 的镜像都会消失。

本节列出了支持的 registry 存储驱动程序。如需更多信息,请参阅容器镜像 registry 文档

以下列表包括在 registry 配置文件中需要配置的存储驱动程序:

支持常规 registry 存储配置选项。如需更多信息,请参阅容器镜像 registry 文档

以下存储选项需要通过文件系统驱动程序配置:

注意

如需有关支持的持久性存储驱动程序的更多信息,请参阅配置持久性存储持久性存储示例

2.2.6.1. 产品使用

对于生产环境,请附加一个远程卷,或者 定义和使用您选择的持久性存储方法

例如,使用现有持久性卷声明:

$ oc set volume deploymentconfigs/docker-registry --add --name=registry-storage -t pvc \
     --claim-name=<pvc_name> --overwrite
重要

测试显示,使用 RHEL NFS 服务器作为容器镜像 registry 的存储后端会出现问题。这包括 OpenShift Container Registry 和 Quay。因此,不建议使用 RHEL NFS 服务器来备份核心服务使用的 PV。

市场上的其他 NFS 实现可能没有这些问题。如需了解更多与此问题相关的信息,请联络相关的 NFS 厂商。

2.2.6.1.1. 使用 Amazon S3 作为存储后端

还有一个选项,可以将 Amazon Simple Storage Service 存储与内部容器镜像 registry 搭配使用。它是一种安全云存储,可通过 AWS 管理控制台进行管理。要使用它,必须手动编辑注册表的配置文件并将其挂载到 registry Pod。但是,在开始配置之前,请查看上游的建议步骤

采用 默认 YAML 配置文件作为基础,并将 storage 部分中的 filesystem 条目替换为 s3 条目,如下方所示:生成的存储部分可能类似如下:

storage:
  cache:
    layerinfo: inmemory
  delete:
    enabled: true
  s3:
    accesskey: awsaccesskey 1
    secretkey: awssecretkey 2
    region: us-west-1
    regionendpoint: http://myobjects.local
    bucket: bucketname
    encrypt: true
    keyid: mykeyid
    secure: true
    v4auth: false
    chunksize: 5242880
    rootdirectory: /s3/object/name/prefix
1
使用您的 Amazon 访问密钥替换。
2
使用您的 Amazon secret 密钥替换。

所有 s3 配置选项都记录在上游 驱动程序参考文档中

覆盖 registry 配置将引导您完成将配置文件挂载到 pod 的其他步骤。

警告

当 registry 在 S3 存储后端上运行时,会报告问题

如果要使用您正在使用的集成 registry 不支持的 S3 区域,请参阅 S3 驱动程序配置

2.2.6.2. 非生产环境中的使用

对于非生产环境,您可以使用 --mount-host=<path> 选项为 registry 指定用于持久性存储的目录。然后,registry 卷在指定的 <path> 上创建为 host-mount。

重要

mount-host 选项可从 registry 容器所在的节点上挂载目录。如果扩展 docker-registry 部署配置,您的 registry Pod 和容器可能会在不同节点上运行,这可能会导致两个或多个 registry 容器,每个容器都有自己的本地存储。这会导致无法预测的行为,因为后续的拉取同一镜像的请求可能并不总是成功,具体取决于请求最终所针对的容器。

--mount-host 选项要求 registry 容器以特权模式运行。这在指定 --mount-host 时自动启用。但是,并非所有 pod 都默认允许运行特权容器。如果您仍然希望使用这个选项,请创建 registry 并指定它使用在安装过程中创建的 registry 服务帐户:

$ oc adm registry --service-account=registry \
    --config=/etc/origin/master/admin.kubeconfig \
    --images='registry.redhat.io/openshift3/ose-${component}:${version}' \ 1
    --mount-host=<path>
1
为 OpenShift Container Platform 拉取正确的镜像是必需的。${component}${version} 在安装过程中会被动态替换。
重要

容器镜像 registry 容器集以用户 1001 身份运行。此用户必须能够写入主机目录。使用以下命令,您可能需要将目录所有权改为用户 ID 1001

$ sudo chown 1001:root <path>

2.2.7. 启用 Registry 控制台

OpenShift Container Platform 为集成的 registry 提供了一个基于 Web 的界面。此 registry 控制台是浏览和管理镜像的可选组件。它部署为作为容器集运行的无状态服务。

注意

如果将 OpenShift Container Platform 作为独立 registry 安装,则 registry 控制台在安装过程中会自动部署和保护。

重要

如果 Cockpit 已在运行,您需要先将其关闭,然后才能继续,以避免与 registry 控制台造成端口冲突(默认为 9090)。

2.2.7.1. 部署 Registry 控制台
重要

您必须首先 公开 registry

  1. default 项目中创建一个 passthrough 路由。下一步中创建 registry 控制台应用时,您将需要此设置。

    $ oc create route passthrough --service registry-console \
        --port registry-console \
        -n default
  2. 部署 registry 控制台应用。将 <openshift_oauth_url> 替换为 OpenShift Container Platform OAuth 供应商的 URL,通常是 master。

    $ oc new-app -n default --template=registry-console \
        -p OPENSHIFT_OAUTH_PROVIDER_URL="https://<openshift_oauth_url>:8443" \
        -p REGISTRY_HOST=$(oc get route docker-registry -n default --template='{{ .spec.host }}') \
        -p COCKPIT_KUBE_URL=$(oc get route registry-console -n default --template='https://{{ .spec.host }}')
    注意

    如果您试图登录到 registry 控制台时重定向 URL 错误,请使用 oc get oauthclients 检查 OAuth 客户端。

  3. 最后,使用 Web 浏览器使用路由 URI 查看控制台。
2.2.7.2. 保护 Registry 控制台

默认情况下,如果按照部署 registry 控制台中的步骤手动部署,registry 控制台会生成自签名 TLS 证书 。如需更多信息,请参阅 对 Registry 控制台进行故障排除

使用以下步骤将组织的签名证书添加为 secret 卷。假设您的证书在 oc 客户端主机上可用。

  1. 创建一个包含证书和密钥的 .cert 文件。使用以下内容格式化文件:

    • 服务器证书和中间证书颁发机构的一个或多个 BEGIN CERTIFICATE
    • 包含该密钥的 BEGIN PRIVATE KEY 或类似密钥的块。密钥不能加密

      例如:

      -----BEGIN CERTIFICATE-----
      MIIDUzCCAjugAwIBAgIJAPXW+CuNYS6QMA0GCSqGSIb3DQEBCwUAMD8xKTAnBgNV
      BAoMIGI0OGE2NGNkNmMwNTQ1YThhZTgxOTEzZDE5YmJjMmRjMRIwEAYDVQQDDAls
      ...
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      MIIDUzCCAjugAwIBAgIJAPXW+CuNYS6QMA0GCSqGSIb3DQEBCwUAMD8xKTAnBgNV
      BAoMIGI0OGE2NGNkNmMwNTQ1YThhZTgxOTEzZDE5YmJjMmRjMRIwEAYDVQQDDAls
      ...
      -----END CERTIFICATE-----
      -----BEGIN PRIVATE KEY-----
      MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyOJ5garOYw0sm
      8TBCDSqQ/H1awGMzDYdB11xuHHsxYS2VepPMzMzryHR137I4dGFLhvdTvJUH8lUS
      ...
      -----END PRIVATE KEY-----
    • 安全 registry 应包含以下主题备用名称(SAN)列表:

      • 两个服务主机名:

        例如:

        docker-registry.default.svc.cluster.local
        docker-registry.default.svc
      • 服务 IP 地址.

        例如:

        172.30.124.220

        使用以下命令获取容器镜像 registry 服务 IP 地址:

        oc get service docker-registry --template='{{.spec.clusterIP}}'
      • 公共主机名.

        例如:

        docker-registry-default.apps.example.com

        使用以下命令获取容器镜像 registry 公共主机名:

        oc get route docker-registry --template '{{.spec.host}}'

        例如,服务器证书应包含类似如下的 SAN 详情:

        X509v3 Subject Alternative Name:
                       DNS:docker-registry-public.openshift.com, DNS:docker-registry.default.svc, DNS:docker-registry.default.svc.cluster.local, DNS:172.30.2.98, IP Address:172.30.2.98

        registry 控制台从 /etc/cockpit/ws-certs.d 目录中加载证书。它使用最后一个带有 .cert 扩展名的文件(按字母顺序排列)。因此,.cert 文件应至少包含以 OpenSSL 样式格式化的至少两个 PEM 块。

        如果没有找到证书,将使用 openssl 命令创建自签名证书,并存储在 0-self-signed.cert 文件中。

  2. 创建 secret:

    $ oc create secret generic console-secret \
        --from-file=/path/to/console.cert
  3. 将 secret 添加到 registry-console 部署配置中:

    $ oc set volume dc/registry-console --add --type=secret \
        --secret-name=console-secret -m /etc/cockpit/ws-certs.d

    这会触发 registry 控制台的新部署,使其包含您的签名证书。

2.2.7.3. 对 Registry 控制台进行故障排除
2.2.7.3.1. 调试模式

使用环境变量启用 registry 控制台调试模式。以下命令以 debug 模式重新部署 registry 控制台:

$ oc set env dc registry-console G_MESSAGES_DEBUG=cockpit-ws,cockpit-wrapper

启用调试模式允许在 registry 控制台的 pod 日志中显示更详细的日志。

2.2.7.3.2. 显示 SSL 证书路径

要检查 registry 控制台正在使用的证书,可以从控制台容器集内运行命令。

  1. 列出 default 项目中的 pod,并找到 registry 控制台的 pod 名称:

    $ oc get pods -n default
    NAME                       READY     STATUS    RESTARTS   AGE
    registry-console-1-rssrw   1/1       Running   0          1d
  2. 使用上一命令中的容器集名称,获取 cockpit-ws 进程使用的证书路径。本例演示了使用自动生成的证书的控制台:

    $ oc exec registry-console-1-rssrw remotectl certificate
    certificate: /etc/cockpit/ws-certs.d/0-self-signed.cert

2.3. 访问 Registry

2.3.1. 查看日志

要查看容器镜像 registry 的日志,请使用带有部署配置的 oc logs 命令:

$ oc logs dc/docker-registry
2015-05-01T19:48:36.300593110Z time="2015-05-01T19:48:36Z" level=info msg="version=v2.0.0+unknown"
2015-05-01T19:48:36.303294724Z time="2015-05-01T19:48:36Z" level=info msg="redis not configured" instance.id=9ed6c43d-23ee-453f-9a4b-031fea646002
2015-05-01T19:48:36.303422845Z time="2015-05-01T19:48:36Z" level=info msg="using inmemory layerinfo cache" instance.id=9ed6c43d-23ee-453f-9a4b-031fea646002
2015-05-01T19:48:36.303433991Z time="2015-05-01T19:48:36Z" level=info msg="Using OpenShift Auth handler"
2015-05-01T19:48:36.303439084Z time="2015-05-01T19:48:36Z" level=info msg="listening on :5000" instance.id=9ed6c43d-23ee-453f-9a4b-031fea646002

2.3.2. 文件存储

标签和镜像元数据存储在 OpenShift Container Platform 中,但 registry 将层和签名数据存储在挂载到位于 /registry 的 registry 容器中的卷中。因为 oc exec 不在特权容器上工作,若要查看 registry 的内容,您必须手动 SSH 到 registry pod 的容器所在的节点,然后在容器本身上运行 docker exec

  1. 列出当前的 pod 以查找容器镜像 registry 的 pod 名称:

    # oc get pods

    然后,使用 oc describe 来查找运行容器的节点的主机名:

    # oc describe pod <pod_name>
  2. 登录到所需的节点:

    # ssh node.example.com
  3. 从节点主机上的默认项目中列出正在运行的容器,并确定容器镜像 registry 的容器 ID:

    # docker ps --filter=name=registry_docker-registry.*_default_
  4. 使用 oc rsh 命令列出 registry 内容:

    # oc rsh dc/docker-registry find /registry
    /registry/docker
    /registry/docker/registry
    /registry/docker/registry/v2
    /registry/docker/registry/v2/blobs 1
    /registry/docker/registry/v2/blobs/sha256
    /registry/docker/registry/v2/blobs/sha256/ed
    /registry/docker/registry/v2/blobs/sha256/ed/ede17b139a271d6b1331ca3d83c648c24f92cece5f89d95ac6c34ce751111810
    /registry/docker/registry/v2/blobs/sha256/ed/ede17b139a271d6b1331ca3d83c648c24f92cece5f89d95ac6c34ce751111810/data 2
    /registry/docker/registry/v2/blobs/sha256/a3
    /registry/docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    /registry/docker/registry/v2/blobs/sha256/a3/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4/data
    /registry/docker/registry/v2/blobs/sha256/f7
    /registry/docker/registry/v2/blobs/sha256/f7/f72a00a23f01987b42cb26f259582bb33502bdb0fcf5011e03c60577c4284845
    /registry/docker/registry/v2/blobs/sha256/f7/f72a00a23f01987b42cb26f259582bb33502bdb0fcf5011e03c60577c4284845/data
    /registry/docker/registry/v2/repositories 3
    /registry/docker/registry/v2/repositories/p1
    /registry/docker/registry/v2/repositories/p1/pause 4
    /registry/docker/registry/v2/repositories/p1/pause/_manifests
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions/sha256
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions/sha256/e9a2ac6418981897b399d3709f1b4a6d2723cd38a4909215ce2752a5c068b1cf
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions/sha256/e9a2ac6418981897b399d3709f1b4a6d2723cd38a4909215ce2752a5c068b1cf/signatures 5
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions/sha256/e9a2ac6418981897b399d3709f1b4a6d2723cd38a4909215ce2752a5c068b1cf/signatures/sha256
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions/sha256/e9a2ac6418981897b399d3709f1b4a6d2723cd38a4909215ce2752a5c068b1cf/signatures/sha256/ede17b139a271d6b1331ca3d83c648c24f92cece5f89d95ac6c34ce751111810
    /registry/docker/registry/v2/repositories/p1/pause/_manifests/revisions/sha256/e9a2ac6418981897b399d3709f1b4a6d2723cd38a4909215ce2752a5c068b1cf/signatures/sha256/ede17b139a271d6b1331ca3d83c648c24f92cece5f89d95ac6c34ce751111810/link 6
    /registry/docker/registry/v2/repositories/p1/pause/_uploads 7
    /registry/docker/registry/v2/repositories/p1/pause/_layers 8
    /registry/docker/registry/v2/repositories/p1/pause/_layers/sha256
    /registry/docker/registry/v2/repositories/p1/pause/_layers/sha256/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    /registry/docker/registry/v2/repositories/p1/pause/_layers/sha256/a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4/link 9
    /registry/docker/registry/v2/repositories/p1/pause/_layers/sha256/f72a00a23f01987b42cb26f259582bb33502bdb0fcf5011e03c60577c4284845
    /registry/docker/registry/v2/repositories/p1/pause/_layers/sha256/f72a00a23f01987b42cb26f259582bb33502bdb0fcf5011e03c60577c4284845/link
    1
    此目录将所有层和签名存储为 blob。
    2
    此文件包含 blob 的内容。
    3
    此目录存储所有镜像存储库。
    4
    此目录适用于单个镜像存储库 p1/pause
    5
    此目录包含特定镜像清单修订版本的签名。
    6
    此文件包含返回到 blob(包含签名数据)的引用。
    7
    此目录包含目前为给定存储库上传和暂存的任何层。
    8
    此目录包含指向这个存储库引用的所有层的链接。
    9
    此文件包含对已通过镜像链接到该存储库的特定层的引用。

2.3.3. 直接访问 Registry

对于高级用途,您可以直接访问 registry 来调用 docker 命令。这可让您直接使用 docker pushdocker pull 等操作从集成的 registry 中推送镜像或从中提取镜像。为此,您必须使用 docker login 命令登录 registry。您可以执行的操作取决于您的用户权限,如以下各节所述。

2.3.3.1. 用户必备条件

要直接访问 registry,您使用的用户必须满足以下条件,具体取决于您的预期用途:

  • 对于任何直接访问,您必须有首选身份提供程序常规用户。普通用户可以生成登录到 registry 所需的访问令牌。系统用户(如 system:admin )无法获取访问令牌,因此无法直接访问 registry。

    例如,如果您使用 HTPASSWD 身份验证,您可以使用以下命令创建一个:

    # htpasswd /etc/origin/master/htpasswd <user_name>
  • 若要调取镜像,例如使用 docker pull 命令,用户必须具有 registry-viewer 角色。添加此角色:

    $ oc policy add-role-to-user registry-viewer <user_name>
  • 为了编写或推送镜像,例如使用 docker push 命令,用户必须具有 registry-editor 角色。添加此角色:

    $ oc policy add-role-to-user registry-editor <user_name>

如需有关用户权限的更多信息,请参阅管理角色绑定

2.3.3.2. 登录到 Registry
注意

确保您的用户满足直接访问 registry 的先决条件

直接登录到 registry:

  1. 确保您以 普通用户身份 登录到 OpenShift Container Platform:

    $ oc login
  2. 使用您的访问令牌登录到容器镜像registry:

    docker login -u openshift -p $(oc whoami -t) <registry_ip>:<port>
注意

您可以为用户名传递任何值,令牌包含所有必要的信息。传递包含冒号的用户名将导致登录失败。

2.3.3.3. 推送和拉取镜像

登录 registry 后,您可以对 registry 执行 docker pulldocker push 操作。

重要

您可以抓取任意镜像,但是如果已添加了system:registry角色,则只能将镜像推送到您自己的registry中。

在以下示例中,我们使用:

组件

<registry_ip>

172.30.124.220

<port>

5000

<project>

openshift

<image>

busybox

<tag>

忽略 (默认为 latest)

  1. 抓取任意镜像:

    $ docker pull docker.io/busybox
  2. 使用 <registry_ip>:<port>/<project>/<image> 格式标记(tag)新镜像。项目名称必须出现在这个 pull 规范中,以供OpenShift Container Platform 把这个镜像正确放置在 registry 中,并在以后正确访问 registry 中的这个镜像:

    $ docker tag docker.io/busybox 172.30.124.220:5000/openshift/busybox
    注意

    您的常规用户必须具有指定项目的 system:image-builder 角色,该角色允许用户写入或推送镜像。否则,下一步中的 docker push 将失败。若要进行测试,您可以创建一个新项目来推送 busybox 镜像。

  3. 将新标记的镜像推送到registry:

    $ docker push 172.30.124.220:5000/openshift/busybox
    ...
    cf2616975b4a: Image successfully pushed
    Digest: sha256:3662dd821983bc4326bee12caec61367e7fb6f6a3ee547cbaff98f77403cab55

2.3.4. 访问 Registry 指标

OpenShift Container Registry 为 Prometheus metrics 提供了一个端点。Prometheus是一个独立的开源系统监视和警报工具包。

metrics 可以通过registry端点的/extensions/v2/metrics路径获得。但是,必须先启用此路由;请参阅 Extended Registry Configuration 了解说明。

以下是指标查询的简单示例:

$ curl -s -u <user>:<secret> \ 1
    http://172.30.30.30:5000/extensions/v2/metrics | grep openshift | head -n 10

# HELP openshift_build_info A metric with a constant '1' value labeled by major, minor, git commit & git version from which OpenShift was built.
# TYPE openshift_build_info gauge
openshift_build_info{gitCommit="67275e1",gitVersion="v3.6.0-alpha.1+67275e1-803",major="3",minor="6+"} 1
# HELP openshift_registry_request_duration_seconds Request latency summary in microseconds for each operation
# TYPE openshift_registry_request_duration_seconds summary
openshift_registry_request_duration_seconds{name="test/origin-pod",operation="blobstore.create",quantile="0.5"} 0
openshift_registry_request_duration_seconds{name="test/origin-pod",operation="blobstore.create",quantile="0.9"} 0
openshift_registry_request_duration_seconds{name="test/origin-pod",operation="blobstore.create",quantile="0.99"} 0
openshift_registry_request_duration_seconds_sum{name="test/origin-pod",operation="blobstore.create"} 0
openshift_registry_request_duration_seconds_count{name="test/origin-pod",operation="blobstore.create"} 5
1
<user> 可以是任意的,但 <secret> 必须与 registry 配置中指定的值匹配。

访问指标的另一种方法是使用集群角色。您仍然需要启用端点,但不需要指定 <secret>。配置文件中与指标数据相关的部分应如下所示:

openshift:
  version: 1.0
  metrics:
    enabled: true
...

如果您还没有角色来访问指标,则必须创建一个集群角色:

$ cat <<EOF |
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus-scraper
rules:
- apiGroups:
  - image.openshift.io
  resources:
  - registry/metrics
  verbs:
  - get
EOF
oc create -f -

要将此角色添加到用户,请运行以下命令:

$ oc adm policy add-cluster-role-to-user prometheus-scraper <username>

有关更高级查询和推荐的可视化工具,请参阅 上游 Prometheus 文档

2.4. 保护并公开 Registry

2.4.1. 概述

默认情况下,OpenShift Container Platform registry 在集群安装过程中是安全的,以便通过 TLS 提供流量。默认情况下还会创建一个 passthrough 路由,以将服务公开到外部。

如果出于任何原因您的 registry 没有被保护或公开,请参阅以下部分来了解如何手动操作。

2.4.2. 手动保护 Registry

手动保护 registry 以通过 TLS 提供流量:

  1. 部署 registry
  2. 获取 registry 的服务 IP 和端口:

    $ oc get svc/docker-registry
    NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    docker-registry   ClusterIP   172.30.82.152   <none>        5000/TCP   1d
  3. 您可以使用现有服务器证书,或者创建对指定 CA 签名的指定 IP 和主机名有效的密钥和服务器证书。要为 registry 服务 IP 和 docker-registry.default.svc.cluster.local 主机名创建服务器证书,请在 Ansible 主机清单文件中列出的第一个 master 中运行以下命令,默认为 /etc/ansible/hosts

    $ oc adm ca create-server-cert \
        --signer-cert=/etc/origin/master/ca.crt \
        --signer-key=/etc/origin/master/ca.key \
        --signer-serial=/etc/origin/master/ca.serial.txt \
        --hostnames='docker-registry.default.svc.cluster.local,docker-registry.default.svc,172.30.124.220' \
        --cert=/etc/secrets/registry.crt \
        --key=/etc/secrets/registry.key

    如果路由器将在 外部公开,请在 --hostnames 标志中添加公共路由主机名:

    --hostnames='mydocker-registry.example.com,docker-registry.default.svc.cluster.local,172.30.124.220 \

    如需有关更新默认证书的更多详细信息,请参阅重新部署 Registry 和路由器 证书,以便可从外部访问该路由。

    注意

    oc adm ca create-server-cert 命令会生成一个有效期为两年的证书。这可以通过 --expire-days 选项进行修改,但出于安全原因,建议不要超过这个值。

  4. 为 registry 证书创建 secret:

    $ oc create secret generic registry-certificates \
        --from-file=/etc/secrets/registry.crt \
        --from-file=/etc/secrets/registry.key
  5. 将该机密添加到 registry 容器集的服务帐户(包括 默认 服务帐户):

    $ oc secrets link registry registry-certificates
    $ oc secrets link default  registry-certificates
    注意

    默认情况下,“将 secret 仅限于引用它们的服务帐户”的功能被禁用。这意味着,如果在主配置文件中将 serviceAccountConfig.limitSecretReferences 设置为 false(默认设置),则不需要将 secret 连接到一个特定的服务。

  6. 暂停 docker-registry 服务:

    $ oc rollout pause dc/docker-registry
  7. 将 secret 卷添加到 registry 部署配置中:

    $ oc set volume dc/docker-registry --add --type=secret \
        --secret-name=registry-certificates -m /etc/secrets
  8. 通过在 registry 部署配置中添加以下环境变量来启用 TLS:

    $ oc set env dc/docker-registry \
        REGISTRY_HTTP_TLS_CERTIFICATE=/etc/secrets/registry.crt \
        REGISTRY_HTTP_TLS_KEY=/etc/secrets/registry.key

    如需更多信息,请参阅 Docker 文档中的配置 registry 部分

  9. 将 registry 的存活度探测使用从 HTTP 更新到 HTTPS:

    $ oc patch dc/docker-registry -p '{"spec": {"template": {"spec": {"containers":[{
        "name":"registry",
        "livenessProbe":  {"httpGet": {"scheme":"HTTPS"}}
      }]}}}}'
  10. 如果您的 registry 最初部署在 OpenShift Container Platform 3.2 或更高版本上,请将用于 registry 的就绪度探测从 HTTP 更新到 HTTPS:

    $ oc patch dc/docker-registry -p '{"spec": {"template": {"spec": {"containers":[{
        "name":"registry",
        "readinessProbe":  {"httpGet": {"scheme":"HTTPS"}}
      }]}}}}'
  11. 恢复 docker-registry 服务:

    $ oc rollout resume dc/docker-registry
  12. 验证 registry 是否以 TLS 模式运行。等待最新的 docker-registry 部署完成,再验证 registry 容器的 Docker 日志。您应该找到 listening on :5000, tls 的条目。

    $ oc logs dc/docker-registry | grep tls
    time="2015-05-27T05:05:53Z" level=info msg="listening on :5000, tls" instance.id=deeba528-c478-41f5-b751-dc48e4935fc2
  13. 将 CA 证书复制到 Docker 证书目录。这必须在集群的所有节点上完成:

    $ dcertsdir=/etc/docker/certs.d
    $ destdir_addr=$dcertsdir/172.30.124.220:5000
    $ destdir_name=$dcertsdir/docker-registry.default.svc.cluster.local:5000
    
    $ sudo mkdir -p $destdir_addr $destdir_name
    $ sudo cp ca.crt $destdir_addr    1
    $ sudo cp ca.crt $destdir_name
    1
    ca.crt 文件是 master 上的 /etc/origin/master/ca.crt 的副本。
  14. 在使用身份验证时,一些 docker 版本还需要将集群配置为信任操作系统级别的证书。

    1. 复制证书:

      $ cp /etc/origin/master/ca.crt /etc/pki/ca-trust/source/anchors/myregistrydomain.com.crt
    2. 运行:

      $ update-ca-trust enable
  15. 只删除 /etc/sysconfig/docker 文件中的这个特定 registry 的 --insecure-registry 选项。然后,重新载入守护进程并重启 docker 服务来反映这个配置更改:

    $ sudo systemctl daemon-reload
    $ sudo systemctl restart docker
  16. 验证 docker 客户端连接。运行 docker push 到 registry 或 registry 中的 docker pull 应该会成功。确保您已登录到 registry

    $ docker tag|push <registry/image> <internal_registry/project/image>

    例如:

    $ docker pull busybox
    $ docker tag docker.io/busybox 172.30.124.220:5000/openshift/busybox
    $ docker push 172.30.124.220:5000/openshift/busybox
    ...
    cf2616975b4a: Image successfully pushed
    Digest: sha256:3662dd821983bc4326bee12caec61367e7fb6f6a3ee547cbaff98f77403cab55

2.4.3. 手动公开安全 Registry

您可以通过首先保护 registry,然后使用路由公开它,而不是从 OpenShift Container Platform 集群内部登录到 OpenShift Container Platform registry。您可以使用路由地址从集群以外登陆到 registry,并使用路由主机进行镜像的 tag 和 push 操作。

  1. 以下每个先决条件步骤都会在典型的集群安装过程中默认执行。如果没有,请手动执行它们:

  2. 在初始集群安装过程中,默认为 registry 创建 passthrough 路由:

    1. 验证路由是否存在:

      $ oc get route/docker-registry -o yaml
      apiVersion: v1
      kind: Route
      metadata:
        name: docker-registry
      spec:
        host: <host> 1
        to:
          kind: Service
          name: docker-registry 2
        tls:
          termination: passthrough 3
      1
      路由的主机。您必须能够通过 DNS 外部将此名称解析到路由器的 IP 地址。
      2
      registry 的服务名称。
      3
      将此路由指定为 passthrough 路由。
      注意

      也支持重新加密路由来公开安全 registry。

    2. 如果不存在,则通过 oc create route passthrough 命令创建路由,将 registry 指定为路由的服务。默认情况下,创建的路由的名称与服务名称相同:

      1. 获取 docker-registry 服务详情:

        $ oc get svc
        NAME              CLUSTER_IP       EXTERNAL_IP   PORT(S)                 SELECTOR                  AGE
        docker-registry   172.30.69.167    <none>        5000/TCP                docker-registry=default   4h
        kubernetes        172.30.0.1       <none>        443/TCP,53/UDP,53/TCP   <none>                    4h
        router            172.30.172.132   <none>        80/TCP                  router=router             4h
      2. 创建路由:

        $ oc create route passthrough    \
            --service=docker-registry    \1
            --hostname=<host>
        route "docker-registry" created     2
        1
        将 registry 指定为路由的服务。
        2
        路由名称与服务名称相同。
  3. 接下来,您必须信任主机系统上用于 registry 的证书,以允许主机推送和拉取镜像。引用的证书是在保护 registry 时创建的。

    $ sudo mkdir -p /etc/docker/certs.d/<host>
    $ sudo cp <ca_certificate_file> /etc/docker/certs.d/<host>
    $ sudo systemctl restart docker
  4. 使用保护 registry 的信息,登录到 registry。但是,这一次指向路由中使用的主机名,而不是您的服务 IP。登录到安全且公开的 registry 时,请确保在 docker login 命令中指定 registry:

    # docker login -e user@company.com \
        -u f83j5h6 \
        -p Ju1PeM47R0B92Lk3AZp-bWJSck2F7aGCiZ66aFGZrs2 \
        <host>
  5. 现在,您可以使用路由主机标记和推送镜像。例如,要在名为 test 的项目中标记和推送 busybox 镜像:

    $ oc get imagestreams -n test
    NAME      DOCKER REPO   TAGS      UPDATED
    
    $ docker pull busybox
    $ docker tag busybox <host>/test/busybox
    $ docker push <host>/test/busybox
    The push refers to a repository [<host>/test/busybox] (len: 1)
    8c2e06607696: Image already exists
    6ce2e90b0bc7: Image successfully pushed
    cf2616975b4a: Image successfully pushed
    Digest: sha256:6c7e676d76921031532d7d9c0394d0da7c2906f4cb4c049904c4031147d8ca31
    
    $ docker pull <host>/test/busybox
    latest: Pulling from <host>/test/busybox
    cf2616975b4a: Already exists
    6ce2e90b0bc7: Already exists
    8c2e06607696: Already exists
    Digest: sha256:6c7e676d76921031532d7d9c0394d0da7c2906f4cb4c049904c4031147d8ca31
    Status: Image is up to date for <host>/test/busybox:latest
    
    $ oc get imagestreams -n test
    NAME      DOCKER REPO                       TAGS      UPDATED
    busybox   172.30.11.215:5000/test/busybox   latest    2 seconds ago
    注意

    您的镜像流将具有 registry 服务的 IP 地址和端口,而不是路由名称和端口。详情请参阅 oc get imagestreams

2.4.4. 手动公开 Non-Secure Registry

对于非生产环境的 OpenShift Container Platform,可以公开一个非安全的 registry,而不必通过安全 registry 来公开 registry。这允许您使用一个外部路由到 registry,而无需使用 SSL 证书。

警告

为外部访问非安全的 registry 只适用于非生产环境。

公开一个非安全的 registry:

  1. 公开 registry:

    # oc expose service docker-registry --hostname=<hostname> -n default

    这会创建以下 JSON 文件:

    apiVersion: v1
    kind: Route
    metadata:
      creationTimestamp: null
      labels:
        docker-registry: default
      name: docker-registry
    spec:
      host: registry.example.com
      port:
        targetPort: "5000"
      to:
        kind: Service
        name: docker-registry
    status: {}
  2. 验证路由是否已创建成功:

    # oc get route
    NAME              HOST/PORT                    PATH      SERVICE           LABELS                    INSECURE POLICY   TLS TERMINATION
    docker-registry   registry.example.com            docker-registry   docker-registry=default
  3. 检查 registry 的健康状况:

    $ curl -v http://registry.example.com/healthz

    预期为 HTTP 200/OK 消息。

    公开 registry 后,通过将端口号添加到 OPTIONS 条目来更新您的 /etc/sysconfig/docker 文件。例如:

    OPTIONS='--selinux-enabled --insecure-registry=172.30.0.0/16 --insecure-registry registry.example.com:80'
    重要

    上面的选项应该添加到您要从其登录的客户端上。

    此外,确保 Docker 在客户端上运行。

登录到非安全且公开的 registry 时,请确保在 docker login 命令中指定 registry。例如:

# docker login -e user@company.com \
    -u f83j5h6 \
    -p Ju1PeM47R0B92Lk3AZp-bWJSck2F7aGCiZ66aFGZrs2 \
    <host>

2.5. 扩展 Registry 配置

2.5.1. 维护 Registry IP 地址

OpenShift Container Platform 使用其服务 IP 地址来引用集成的 registry,因此如果您决定删除并重新创建 docker-registry 服务,您可以通过安排在新服务中重复使用旧 IP 地址来确保完全透明转换。如果无法避免新的 IP 地址,您可以通过只重启 master 来最小化集群中断。

重新使用地址
要重新使用 IP 地址,您必须在删除旧 docker-registry 服务前保存其 IP 地址,并安排将新分配的 IP 地址替换为新 docker-registry 服务中保存的 IP 地址。
  1. 记录该服务的 clusterIP:

    $ oc get svc/docker-registry -o yaml | grep clusterIP:
  2. 删除服务:

    $ oc delete svc/docker-registry dc/docker-registry
  3. registry.yaml 中创建 registry 定义,将 <options> 替换为非生产环境使用部分中说明的第 3 步中使用的 :

    $ oc adm registry <options> -o yaml > registry.yaml
  4. 编辑 registry.yaml,找到 Service,并将其 clusterIP 更改为第 1 步中记录的地址。
  5. 使用修改后的 registry.yaml 创建 registry:

    $ oc create -f registry.yaml
重启 Master
如果您无法重新使用 IP 地址,则任何使用包含旧 IP 地址的 pull specification 的操作都将失败。要最小化集群中断,您必须重启 master:
# master-restart api
# master-restart controllers

这样可确保从缓存中清除包括旧 IP 地址的旧 registry URL。

注意

我们建议不要重启整个集群,因为这会对 pod 造成不必要的停机时间,实际上不会清除缓存。

2.5.2. 配置外部 registry 搜索列表

您可以使用 /etc/containers/registries.conf 文件创建 Docker Registry 列表来搜索容器镜像。

/etc/containers/registries.conf 文件是 OpenShift Container Platform 在用户使用镜像简短名称(如 myimage:latest )提取镜像时应对其搜索的 registry 服务器列表。您可以自定义搜索顺序,指定安全且不安全的 registry,并定义一个被阻断的 registry 列表。OpenShift Container Platform 不允许搜索或允许从被阻塞列表中的 registry 中拉取(pull)。

例如,如果用户想要拉取 myimage:latest 镜像,OpenShift Container Platform 会按照它们出现在列表中的顺序搜索 registry,直到找到 myimage:latest 镜像。

registry 搜索列表允许您策展一组可供 OpenShift Container Platform 用户下载的镜像和模板。您可以将这些镜像放在一个或多个 Docker registry 中,将 registry 添加到列表中,并将这些镜像拉取到集群中。

注意

使用 registry 搜索列表时,OpenShift Container Platform 不会从不在搜索列表中的 registry 中拉取镜像。

配置 registry 搜索列表:

  1. 编辑 /etc/containers/registries.conf 文件,根据需要添加或编辑以下参数:

    [registries.search] 1
    registries = ["reg1.example.com", "reg2.example.com"]
    
    [registries.insecure] 2
    registries = ["reg3.example.com"]
    
    [registries.block] 3
    registries = ['docker.io']
    1
    指定用户可以使用 SSL/TLS 从中下载镜像的安全 registry。
    2
    指定用户可以在不使用 TLS 的情况下下载镜像的不安全 registry。
    3
    指定用户无法从中下载镜像的 registry。

2.5.3. 设置 Registry 主机名

您可以为内部和外部引用配置 registry 的主机名和端口。通过这样做,镜像流将为镜像提供基于主机名的推送和拉取规格,允许使用镜像与对 registry 服务 IP 的更改进行隔离,并有可能允许镜像流及其引用在集群中可移植。

要设置从集群内部引用 registry 的主机名,请在 master 配置文件的 imagePolicyConfig 部分中设置 internalRegistryHostname。外部主机名通过在同一位置设置 externalRegistryHostname 值来控制。

镜像策略配置

imagePolicyConfig:
  internalRegistryHostname: docker-registry.default.svc.cluster.local:5000
  externalRegistryHostname: docker-registry.mycompany.com

registry 本身必须使用相同的内部主机名值进行配置。这可以通过在 registry 署配置中设置 REGISTRY_OPENSHIFT_SERVER_ADDR 环境变量或设置 registry 配置的 OpenShift 部分中的值来完成。

注意

如果您已经为 registry 启用了 TLS,服务器证书必须包含您希望引用 registry 的主机名。有关添加主机名到服务器证书的说明,请参阅保护registry

2.5.4. 覆盖 Registry 配置

您可以使用自己的自定义配置覆盖集成 registry 的默认配置,默认覆盖正在运行的 registry 容器中的 /config.yml 中的默认配置。

注意

此文件中的上游配置选项也可使用环境变量覆盖。middleware 部分是一个例外,因为只有几个选项可以使用环境变量覆盖。了解如何覆盖特定的配置选项

要启用对 registry 配置文件的管理,并使用 ConfigMap 部署更新的配置:

  1. 部署 registry
  2. 根据需要在本地编辑 registry 配置文件。registry 中部署的初始 YAML 文件如下所示:查看支持的选项

    registry 配置文件

    version: 0.1
    log:
      level: debug
    http:
      addr: :5000
    storage:
      cache:
        blobdescriptor: inmemory
      filesystem:
        rootdirectory: /registry
      delete:
        enabled: true
    auth:
      openshift:
        realm: openshift
    middleware:
      registry:
        - name: openshift
      repository:
        - name: openshift
          options:
            acceptschema2: true
            pullthrough: true
            enforcequota: false
            projectcachettl: 1m
            blobrepositorycachettl: 10m
      storage:
        - name: openshift
    openshift:
      version: 1.0
      metrics:
        enabled: false
        secret: <secret>

  3. 创建一个 ConfigMap,包含此目录中每个文件的内容:

    $ oc create configmap registry-config \
        --from-file=</path/to/custom/registry/config.yml>/
  4. registry-config ConfigMap 作为卷添加到 registry 的部署配置中,以在 /etc/docker/registry/ 中挂载自定义配置文件:

    $ oc set volume dc/docker-registry --add --type=configmap \
        --configmap-name=registry-config -m /etc/docker/registry/
  5. 通过在 registry 的部署配置中添加以下环境变量来更新 registry,以引用上一步中的配置路径:

    $ oc set env dc/docker-registry \
        REGISTRY_CONFIGURATION_PATH=/etc/docker/registry/config.yml

这可以作为迭代过程执行,从而实现所需的配置。例如,在故障排除期间,可临时更新配置以将其置于 debug 模式。

更新现有配置:

警告

此流程将覆盖当前部署的 registry 配置。

  1. 编辑本地 registry 配置文件 config.yml
  2. 删除 registry-config configmap:

    $ oc delete configmap registry-config
  3. 重新创建 configmap 以引用更新的配置文件:

    $ oc create configmap registry-config\
        --from-file=</path/to/custom/registry/config.yml>/
  4. 重新部署 registry 以读取更新的配置:

    $ oc rollout latest docker-registry
提示

在源代码控制存储库中维护配置文件。

2.5.5. registry 配置参考

上游 docker distribution 库中有许多配置选项。并非所有配置选项都受到支持或启用。覆盖 registry 配置时,请使用本节作为参考。

注意

此文件中的上游配置选项也可使用环境变量覆盖。但是,middleware 部分可能无法使用环境变量覆盖。了解如何覆盖特定的配置选项

2.5.5.1. Log

支持上游选项

例如:

log:
  level: debug
  formatter: text
  fields:
    service: registry
    environment: staging
2.5.5.2. Hook

不支持邮件 hook。

2.5.5.3. 存储

本节列出了支持的 registry 存储驱动程序。如需更多信息,请参阅容器镜像 registry 文档

以下列表包括在 registry 配置文件中需要配置的存储驱动程序:

支持常规 registry 存储配置选项。如需更多信息,请参阅容器镜像 registry 文档

以下存储选项需要通过文件系统驱动程序配置:

注意

如需有关支持的持久性存储驱动程序的更多信息,请参阅配置持久性存储持久性存储示例

常规存储配置选项

storage:
  delete:
    enabled: true 1
  redirect:
    disable: false
  cache:
    blobdescriptor: inmemory
  maintenance:
    uploadpurging:
      enabled: true
      age: 168h
      interval: 24h
      dryrun: false
    readonly:
      enabled: false

1
此条目对于镜像修剪正常工作是必需的
2.5.5.4. Auth

不应更改 Auth 选项。openshift 扩展是唯一支持的选项。

auth:
  openshift:
    realm: openshift
2.5.5.5. Middleware

存储库 中间件扩展允许配置负责与 OpenShift Container Platform 和镜像代理交互的 OpenShift Container Platform 中间件。

middleware:
  registry:
    - name: openshift 1
  repository:
    - name: openshift 2
      options:
        acceptschema2: true 3
        pullthrough: true 4
        mirrorpullthrough: true 5
        enforcequota: false 6
        projectcachettl: 1m 7
        blobrepositorycachettl: 10m 8
  storage:
    - name: openshift 9
1 2 9
这些条目是必需的。其存在可确保加载所需的组件。这些值不应更改。
3
允许您在推送到 registry 期间存储 清单模式 v2。详情请查看 下方
4
允许 registry 充当远程 Blob 的代理。详情请查看 下方
5
允许从远程 registry 提供 registry 缓存 Blob,以便稍后进行快速访问。镜像在第一次访问 Blob 时开始。如果禁用了 pullthrough,则选项无效。
6
防止 Blob 上传超过目标项目中定义的大小限制。
7
在 registry 中缓存的限制的过期超时。值越低,限制更改传播到 registry 所需的时间就会越短。但是,registry 会更频繁地从服务器查询限制,因此推送速度会较慢。
8
blob 和 repository 之间记住关联的过期超时。值越大,快速查找的几率更高,registry 操作效率越高。另一方面,内存使用会增加为用户提供服务的风险,因为用户不再获得访问该层的权限。
2.5.5.5.1. S3 驱动程序配置

如果要使用您正在使用的集成 registry 不支持的 S3 区域,您可以指定一个 regionendpoint 以避免 区域 验证错误。

有关使用 Amazon Simple Storage Service 存储的更多信息,请参阅 Amazon S3 作为存储后端

例如:

version: 0.1
log:
  level: debug
http:
  addr: :5000
storage:
  cache:
    blobdescriptor: inmemory
  delete:
    enabled: true
  s3:
    accesskey: BJKMSZBRESWJQXRWMAEQ
    secretkey: 5ah5I91SNXbeoUXXDasFtadRqOdy62JzlnOW1goS
    bucket: docker.myregistry.com
    region: eu-west-3
    regionendpoint: https://s3.eu-west-3.amazonaws.com
 auth:
  openshift:
    realm: openshift
middleware:
  registry:
    - name: openshift
  repository:
    - name: openshift
  storage:
    - name: openshift
注意

验证 regionregionendpoint 字段本身是否一致。否则,集成的 registry 将启动,但它无法读取或写入 S3 存储。

如果您使用与 Amazon S3 不同的 S3 存储,则 regionendpoint 也很有用。

2.5.5.5.2. CloudFront 中间件

可以添加 CloudFront 中间件扩展 以支持 AWS CloudFront CDN 存储供应商。CloudFront 中间件加快了镜像内容在国际间分发。Blob 分布到世界各地的几个边缘位置。客户端始终定向到延迟最低的边缘。

注意

CloudFront 中间件扩展 只能用于 S3 存储。它仅在 Blob 服务期间使用。因此,只有 Blob 下载可以加快,不能上传。

以下是带有 CloudFront 中间件的 S3 存储驱动程序的最小配置示例:

version: 0.1
log:
  level: debug
http:
  addr: :5000
storage:
  cache:
    blobdescriptor: inmemory
  delete:
    enabled: true
  s3: 1
    accesskey: BJKMSZBRESWJQXRWMAEQ
    secretkey: 5ah5I91SNXbeoUXXDasFtadRqOdy62JzlnOW1goS
    region: us-east-1
    bucket: docker.myregistry.com
auth:
  openshift:
    realm: openshift
middleware:
  registry:
    - name: openshift
  repository:
    - name: openshift
  storage:
    - name: cloudfront 2
      options:
        baseurl: https://jrpbyn0k5k88bi.cloudfront.net/ 3
        privatekey: /etc/docker/cloudfront-ABCEDFGHIJKLMNOPQRST.pem 4
        keypairid: ABCEDFGHIJKLMNOPQRST 5
    - name: openshift
1
无论 CloudFront 中间件如何,S3 存储都必须以相同的方式进行配置。
2
OpenShift 中间件需要先列出 CloudFront 存储中间件。
3
CloudFront 基本 URL。在 AWS 管理控制台中,这被列为 CloudFront 发行版本的 Domain Name
4
AWS 私钥在文件系统中的位置。这不能与 Amazon EC2 密钥对混淆。请参阅 AWS 文档 为您的可信签名者创建 CloudFront 密钥对。文件需要作为 机密 挂载到 registry 容器集。
5
云前端密钥对的 ID。
2.5.5.5.3. 覆盖中间件配置选项

middleware 部分无法使用环境变量覆盖。但也有一些例外:例如:

middleware:
  repository:
    - name: openshift
      options:
        acceptschema2: true 1
        pullthrough: true 2
        mirrorpullthrough: true 3
        enforcequota: false 4
        projectcachettl: 1m 5
        blobrepositorycachettl: 10m 6
1
此配置选项可以被布尔值环境变量 REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_ACCEPTSCHEMA2 覆盖,允许在清单放置请求时接受清单架构 v2。可识别的值为 truefalse (适用于以下所有其他布尔值变量)。
2
此配置选项可以被布尔值环境变量 REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_PULLTHROUGH 覆盖,启用远程存储库的代理模式。
3
此配置选项可以被布尔值环境变量 REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_MIRRORPULLTHROUGH 覆盖,它指示 registry 在提供远程 Blob 时在本地镜像 Blob。
4
此配置选项可以被布尔值环境变量 REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_ENFORCEQUOTA 覆盖,允许开启或关闭配额执行。默认情况下,配额强制是禁用的。
5
可被环境变量 REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_PROJECTCACHETTL 覆盖的配置选项,为项目配额对象指定驱除超时。它需要一个有效的持续时间字符串(如 2m)。如果为空,则获得默认超时。如果零(0m),则禁用缓存。
6
可被环境变量 REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_BLOBREPOSITORYCACHETTL 覆盖的配置选项,为 blob 和包含存储库之间的关联指定驱除超时。值的格式与 projectcachettl 示例中的格式相同。
2.5.5.5.4. 镜像 Pullthrough

如果启用,registry 将尝试从远程 registry 获取请求的 blob,除非 blob 在本地存在。远程候选从存储在 镜像流 状态的 DockerImage 条目(客户端从中拉取)计算。此类条目中的所有唯一远程 registry 引用将依次尝试,直到找到 Blob。

只有存在拉取镜像的镜像流标签时才会进行 pullthrough。例如,如果拉取的镜像为 docker-registry.default.svc:5000/yourproject/yourimage:prod,则 registry 将在项目 yourproject 中查找名为 yourimage:prod 的镜像流标签。如果找到镜像,它将尝试使用该镜像流标签关联的 dockerImageReference 来拉取镜像。

在执行 pullthrough 时,registry 将使用与所引用镜像流标签关联的项目中找到的拉取凭据。此功能还允许您拉取驻留在 registry 上的镜像,它们没有凭证可以访问,只要您有权访问引用该镜像的镜像流标签。

您必须确保 registry 具有适当的证书来信任您针对的任何外部 registry。证书需要放置在 pod 上的 /etc/pki/tls/certs 目录中。您可以使用 配置映射secret 挂载证书。请注意,必须替换整个 /etc/pki/tls/certs 目录。您必须包含新证书,并在您挂载的 secret 或配置映射中替换系统证书。

请注意,默认情况下,镜像流标签使用引用策略类型 Source,这意味着镜像流引用被解析为镜像拉取规格时,使用的规格将指向镜像的来源。对于托管在外部 registry 上的镜像,这将是外部 registry,因此该资源将引用外部 registry 并拉取镜像。例如,registry.redhat.io/openshift3/jenkins-2-rhel7 和 pullthrough 将不适用。为确保引用镜像流的资源使用指向内部 Registry 的拉取规格,镜像流标签应使用引用策略类型 Local。有关参考政策的更多信息,

这个功能默认是开启的。不过,它可以通过配置选项来禁用。

默认情况下,除非禁用 mirrorpullthrough,否则通过这种方式提供的所有远程 Blob 都存储在本地以进行后续的快速访问。此镜像功能的缺点是增加存储的使用。

注意

当客户端尝试至少获取一个 blob 字节时,镜像开始。要在实际需要前将特定镜像预先放入集成的 registry 中,您可以运行以下命令:

$ oc get imagestreamtag/${IS}:${TAG} -o jsonpath='{ .image.dockerImageLayers[*].name }' | \
  xargs -n1 -I {} curl -H "Range: bytes=0-1" -u user:${TOKEN} \
  http://${REGISTRY_IP}:${PORT}/v2/default/mysql/blobs/{}
注意

此 OpenShift Container Platform 镜像功能不应与上游 registry 通过缓存功能拉取(pull) 混淆,后者是类似但不同的功能。

2.5.5.5.5. 清单架构 v2 支持

每一镜像具有一个清单,用于描述其 Blob、运行它的说明以及其他元数据。清单是经过版本控制的,每个版本具有不同的结构和字段,随着时间推移而发展。同一镜像可由多个清单版本表示。每个版本都有不同的摘要。

registry 目前支持 清单 v2 模式 1 (schema1)清单 v2 模式 2架构2)。前者已被淘汰,但将会延长支持时间。

默认配置是存储 schema2

您应注意与各种 Docker 客户端的兼容性问题:

  • 1.9 或更早版本的 Docker 客户端仅支持 schema1。此客户端拉取或推送的任何清单都将是这种传统架构。
  • 版本 1.10 的 Docker 客户端支持 schema1schema2。默认情况下,如果支持较新的架构,它会将后者推送到 registry。

存储具有 schema1 的镜像的 registry 将始终不动地将其返回到客户端。Schema2 将仅原封不动传输到较新的 Docker 客户端。对于较旧版本,它将自行转换为 schema1

这具有显著的后果。例如,通过较新的 Docker 客户端推送到 registry 的镜像无法被旧 Docker 通过其摘要拉取。这是因为存储的镜像的清单是 schema2,其摘要只能用于拉取此版本的清单。

旦您确信所有 registry 客户端都支持 schema2,就可以在 registry 中启用其支持。有关特定选项,请参见上述中间件配置参考

2.5.5.6. OpenShift

本节回顾针对特定于 OpenShift Container Platform 的功能的全局设置配置。在以后的发行版本中,Middleware 部分中与 openshift相关的设置将被弃用。

目前,本节允许您配置 registry 指标集合:

openshift:
  version: 1.0 1
  server:
    addr: docker-registry.default.svc 2
  metrics:
    enabled: false 3
    secret: <secret> 4
  requests:
    read:
      maxrunning: 10 5
      maxinqueue: 10 6
      maxwaitinqueue 2m 7
    write:
      maxrunning: 10 8
      maxinqueue: 10 9
      maxwaitinqueue 2m 10
1
指定本节配置版本的必填条目。唯一支持的值是 1.0
2
registry 的主机名。应设置为 master 上配置的相同值。它可以被环境变量 REGISTRY_OPENSHIFT_SERVER_ADDR 覆盖。
3
可以设置为 true 来启用指标集合。它可以被布尔值环境变量 REGISTRY_OPENSHIFT_METRICS_ENABLED 覆盖。
4
用于授权客户端请求的机密。指标客户端必须在 Authorization 标头中将它用作 bearer 令牌。它可以被环境变量 REGISTRY_OPENSHIFT_METRICS_SECRET 覆盖。
5
同时拉取请求的最大数量。它可以被环境变量 REGISTRY_OPENSHIFT_REQUESTS_READ_MAXRUNNING 覆盖。零表示无限制。
6
已排队拉取请求的最大数量。它可以被环境变量 REGISTRY_OPENSHIFT_REQUESTS_READ_MAXINQUEUE 覆盖。零表示无限制。
7
拉取请求在被拒绝前可在队列中等待的最长时间。它可以被环境变量 REGISTRY_OPENSHIFT_REQUESTS_READ_MAXWAITINQUEUE 覆盖。零表示无限制。
8
同时推送请求的最大数量。它可以被环境变量 REGISTRY_OPENSHIFT_REQUESTS_WRITE_MAXRUNNING 覆盖。零表示无限制。
9
最多排队的推送请求数.它可以被环境变量 REGISTRY_OPENSHIFT_REQUESTS_WRITE_MAXINQUEUE 覆盖。零表示无限制。
10
推送请求在被拒绝前可在队列中等待的最长时间。它可以被环境变量 REGISTRY_OPENSHIFT_REQUESTS_WRITE_MAXWAITINQUEUE 覆盖。零表示无限制。

有关使用信息,请参阅访问 Registry Metrics

2.5.5.7. 报告

报告不受支持。

2.5.5.8. HTTP

支持上游选项了解如何通过环境变量更改这些设置。应当仅更改 tls 部分。例如:

http:
  addr: :5000
  tls:
    certificate: /etc/secrets/registry.crt
    key: /etc/secrets/registry.key
2.5.5.9. 通知

支持上游选项REST API 参考 提供了更加全面的集成选项。

例如:

notifications:
  endpoints:
    - name: registry
      disabled: false
      url: https://url:port/path
      headers:
        Accept:
          - text/plain
      timeout: 500
      threshold: 5
      backoff: 1000
2.5.5.10. Redis

不支持 Redis。

2.5.5.11. Health

支持上游选项。registry 部署配置在 /healthz 上提供了一个集成健康检查。

2.5.5.12. Proxy

不应启用代理配置。此功能由 OpenShift Container Platform 存储库中间件扩展 pullthrough: true 提供。

2.5.5.13. Cache

集成 registry 会主动缓存数据,以减少对减慢外部资源的调用数量。有两个缓存:

  1. 用于缓存 Blob 元数据的存储缓存。此缓存没有过期时间,数据会一直存在,直到显式删除为止。
  2. 应用缓存包含 blob 和存储库之间的关联。此缓存中的数据具有过期时间。

要完全关闭缓存,您需要更改配置:

version: 0.1
log:
  level: debug
http:
  addr: :5000
storage:
  cache:
    blobdescriptor: "" 1
openshift:
  version: 1.0
  cache:
    disabled: true 2
    blobrepositoryttl: 10m
1
禁用存储后端中访问的元数据的缓存。如果没有此缓存,registry 服务器将持续访问元数据后端。
2
禁用包含 blob 和存储库关联的缓存。如果没有这个缓存,registry 服务器将持续从主 API 重新查询数据并重新计算关联。

2.6. 已知问题

2.6.1. 概述

以下是部署或使用集成 registry 时已知的问题。

2.6.2. 使用 Registry Pull-through 的并发构建

本地 docker-registry 部署会增加负载。默认情况下,它现在缓存 registry.redhat.io 的内容。来自为 STI 构建的 registry.redhat.io 的镜像现在存储在本地 registry 中。尝试拉取它们的结果从本地 docker-registry 中拉取。因此,在有些情况下,并发构建可能会造成拉取超时,构建可能会失败。要缓解此问题,请将 docker-registry 部署扩展到多个副本。检查构建器容器集日志中的超时。

2.6.3. 使用共享 NFS 卷扩展 registry 的镜像推送错误

当将扩展的 registry 与共享 NFS 卷搭配使用时,您可能会在推送镜像的过程中看到以下错误之一:

  • digest invalid: provided digest did not match uploaded content
  • blob upload unknown
  • blob upload invalid

当 Docker 尝试推送镜像时,内部 registry 服务将返回这些错误。其原因源自于跨节点的文件属性同步。使用默认循环负载平衡配置推送镜像时可能会出现的错误,如 NFS 客户端缓存、网络延迟和层大小等因素。

您可以执行以下步骤来最大程度减少此类故障的可能性:

  1. 确保 docker-registry 服务的 sessionAffinity 设置为 ClientIP:

    $ oc get svc/docker-registry --template='{{.spec.sessionAffinity}}'

    这应该会返回 ClientIP,这是 OpenShift Container Platform 近期版本中的默认设置。如果没有,请修改它:

    $ oc patch svc/docker-registry -p '{"spec":{"sessionAffinity": "ClientIP"}}'
  2. 确保 NFS 服务器上的 registry 卷的 NFS 导出行列出 no_wdelay 选项。no_wdelay 选项可防止服务器延迟写入,这极大提高了读写一致性,这是 Registry 的一项要求。
重要

测试显示,使用 RHEL NFS 服务器作为容器镜像 registry 的存储后端会出现问题。这包括 OpenShift Container Registry 和 Quay。因此,不建议使用 RHEL NFS 服务器来备份核心服务使用的 PV。

市场上的其他 NFS 实现可能没有这些问题。如需了解更多与此问题相关的信息,请联络相关的 NFS 厂商。

2.6.4. 使用 "not found" 错误来拉取内部管理的镜像故障

当拉取镜像推送到不同于从中拉取的镜像流时,会发生此错误。这是因为将构建的镜像重新标记到任意镜像流中:

$ oc tag srcimagestream:latest anyproject/pullimagestream:latest

然后,使用如下镜像引用从中提取:

internal.registry.url:5000/anyproject/pullimagestream:latest

在手动 Docker 拉取过程中,这会导致类似的错误:

Error: image anyproject/pullimagestream:latest not found

为防止这种情况,请完全避免标记内部管理的镜像,或者 手动 将构建的镜像重新推送到所需的命名空间。

2.6.5. S3 Storage 上带有 "500 Internal Server Error"的镜像 Push Fails

当 registry 在 S3 存储后端上运行时,会报告问题。推送到容器镜像 registry 有时会失败,并显示以下错误:

Received unexpected HTTP status: 500 Internal Server Error

要进行调试,您需要 查看 registry 日志。在这里,查看推送失败时出现的类似的错误消息:

time="2016-03-30T15:01:21.22287816-04:00" level=error msg="unknown error completing upload: driver.Error{DriverName:\"s3\", Enclosed:(*url.Error)(0xc20901cea0)}" http.request.method=PUT
...
time="2016-03-30T15:01:21.493067808-04:00" level=error msg="response completed with error" err.code=UNKNOWN err.detail="s3: Put https://s3.amazonaws.com/oso-tsi-docker/registry/docker/registry/v2/blobs/sha256/ab/abe5af443833d60cf672e2ac57589410dddec060ed725d3e676f1865af63d2e2/data: EOF" err.message="unknown error" http.request.method=PUT
...
time="2016-04-02T07:01:46.056520049-04:00" level=error msg="error putting into main store: s3: The request signature we calculated does not match the signature you provided. Check your key and signing method." http.request.method=PUT
atest

如果您看到此类错误,请联系您的 Amazon S3 支持。您所在地区或您的特定存储桶可能有问题。

2.6.6. 镜像修剪失败

如果您在修剪镜像时遇到以下错误:

BLOB sha256:49638d540b2b62f3b01c388e9d8134c55493b1fa659ed84e97cb59b87a6b8e6c error deleting blob

您的 registry 日志 包含以下信息:

error deleting blob \"sha256:49638d540b2b62f3b01c388e9d8134c55493b1fa659ed84e97cb59b87a6b8e6c\": operation unsupported

这意味着您的 自定义配置文件 缺少 storage 部分中的强制条目,即 storage:delete:enabled 设置为 true。添加它们,重新部署 registry,再重复您的镜像修剪操作。

第 3 章 设置路由器

3.1. 路由器概述

3.1.1. 关于路由器

可以通过多种方式使 流量进入集群。最常见的方法是使用 OpenShift Container Platform router 作为 OpenShift Container Platform 安装中 services 的外部流量入口点。

OpenShift Container Platform 提供和支持以下路由器插件:

3.1.2. 路由器服务帐户

在部署 OpenShift Container Platform 集群前,您必须有一个路由器的服务帐户,该帐户会在集群安装过程中自动创建。此服务帐户具有 安全性上下文约束 (SCC)的权限,允许它指定主机端口。

3.1.2.1. 访问标签的权限

使用 命名空间标签 时,例如在创建 路由器分片 时,路由器的服务帐户必须具有 cluster-reader 权限。

$ oc adm policy add-cluster-role-to-user \
    cluster-reader \
    system:serviceaccount:default:router

服务帐户就位后,您可以继续安装默认的 HAProxy 路由器自定义 HAProxy 路由器

3.2. 使用默认 HAProxy 路由器

3.2.1. 概述

oc adm router 命令随管理员 CLI 一同提供,以简化在新安装中设置路由器的任务。oc adm router 命令创建服务和部署配置对象。使用 --service-account 选项指定路由器用于联系主控机的服务帐户。

路由器服务帐户 可以提前创建,或者通过 oc adm router --service-account 命令创建。

OpenShift Container Platform 组件之间的每种通信都受到 TLS 的保护,并使用各种证书和身份验证方法。可以提供 --default-certificate .pem 格式文件,或者由 oc adm router 命令创建文件。创建路由时,用户可以提供路由器在处理路由时使用的路由证书。

重要

删除路由器时,请确保也删除了部署配置、服务和机密。

路由器部署到特定的节点上。这使得集群管理员和外部网络管理器能够更轻松地协调哪个 IP 地址将运行路由器以及路由器将处理的流量。路由器通过使用 节点选择器 部署到特定的节点上。

重要

路由器默认使用主机网络,它们直接连接到主机上所有接口上的端口 80 和 443。将路由器限制为端口 80/443 可用且未被其他服务使用的主机,再使用 节点选择器调度程序配置 进行设置。例如,您可以通过专用基础架构节点来运行路由器等服务来达到此目的。

重要

建议将不同的 openshift-router 服务帐户与路由器分开。这可以通过 oc adm router 命令的 --service-account 标志来提供。

$ oc adm router --dry-run --service-account=router 1
1
--service-accountopenshift-router 服务帐户 的名称。
重要

使用 oc adm router 创建的路由器 pod 具有默认的资源请求,节点必须满足这些请求才能部署路由器 pod。为提高基础架构组件的可靠性,默认资源请求用于在不使用资源请求的情况下增加 pod 以上的路由器容器集的 QoS 层。默认值表示部署基本路由器所需的已观察到最少资源,可以在路由器部署配置中编辑,并且您可能希望根据路由器负载来增加这些资源。

3.2.2. 创建路由器

如果路由器不存在,请运行以下命令来创建路由器:

$ oc adm router <router_name> --replicas=<number> --service-account=router --extended-logging=true

除非创建 高可用性 配置,否则 --replicas 通常为 1

--extended-logging=true 配置路由器,将 HAProxy 生成的日志转发到 syslog 容器。

查找路由器的主机 IP 地址:

$ oc get po <router-pod>  --template={{.status.hostIP}}

您还可以使用路由器分片来确保路由器被过滤到特定的命名空间或路由,或者在路由器创建后设置任何环境变量。本例中为每个分片创建一个路由器。

3.2.3. 其他基本路由器命令

检查默认路由器
名为 router 的默认路由器服务帐户会在集群安装过程中自动创建。验证此帐户是否已存在:
$ oc adm router --dry-run --service-account=router
查看默认路由器
查看创建的默认路由器会是什么样子:
$ oc adm router --dry-run -o yaml --service-account=router
将路由器配置为转发 HAProxy 日志
您可以将路由器配置为将 HAProxy 生成的日志转发到 rsyslog sidecar 容器。--extended-logging=true 参数附加 syslog 容器将 HAProxy 日志转发到标准输出。
$ oc adm router --extended-logging=true

以下示例是使用 --extended-logging=true 的路由器的配置:

$ oc get pod router-1-xhdb9 -o yaml
apiVersion: v1
kind: Pod
spec:
  containers:
  - env:

    ....

    - name: ROUTER_SYSLOG_ADDRESS 1
      value: /var/lib/rsyslog/rsyslog.sock

    ....

 - command: 2
   - /sbin/rsyslogd
   - -n
   - -i
   - /tmp/rsyslog.pid
   - -f
   - /etc/rsyslog/rsyslog.conf
   image: registry.redhat.io/openshift3/ose-haproxy-router:v3.11.188
   imagePullPolicy: IfNotPresent
   name: syslog
1
--extended-logging=true 参数为日志创建一个套接字文件。
2
--extended-logging=true 参数向路由器添加一个容器。在容器中,rsyslog 进程作为 /sbin/rsyslogd -n -i /tmp/rsyslog.pid -f /etc/rsyslog/rsyslog.conf 运行。

使用以下命令查看 HAProxy 日志:

$ oc set env dc/test-router ROUTER_LOG_LEVEL=info 1
$ oc logs -f <pod-name> -c syslog 2
1
将日志级别设置为 infodebug。默认值为 warning
2
指定要查看日志的路由器 pod 的名称。

HAProxy 日志的格式如下:

2020-04-14T03:05:36.629527+00:00 test-311-node-1 haproxy[43]: 10.0.151.166:59594 [14/Apr/2020:03:05:36.627] fe_no_sni~ be_secure:openshift-console:console/pod:console-b475748cb-t6qkq:console:10.128.0.5:8443 0/0/1/1/2 200 393 - - --NI 2/1/0/1/0 0/0 "HEAD / HTTP/1.1"
2020-04-14T03:05:36.633024+00:00 test-311-node-1 haproxy[43]: 10.0.151.166:59594 [14/Apr/2020:03:05:36.528] public_ssl be_no_sni/fe_no_sni 95/1/104 2793 -- 1/1/0/0/0 0/0
将路由器部署到标记的节点
将路由器部署到与指定 节点标签 匹配的任何节点上:
$ oc adm router <router_name> --replicas=<number> --selector=<label> \
    --service-account=router

例如,如果要创建一个名为 router 的路由器,并将其放置到带有 node-role.kubernetes.io/infra=true 标签的节点上:

$ oc adm router router --replicas=1 --selector='node-role.kubernetes.io/infra=true' \
  --service-account=router

在集群安装过程中,openshift_router_selectoropenshift_registry_selector Ansible 设置默认设置为 node-role.kubernetes.io/infra=true。只有在存在与 node-role.kubernetes.io/infra=true 标签匹配的节点时,才会自动部署默认路由器和 registry。

有关更新标签的详情,请参阅更新节点上的标签

根据调度程序策略,在不同的主机上创建多个实例。

使用不同的路由器镜像
使用其他路由器镜像并查看要使用的路由器配置:
$ oc adm router <router_name> -o <format> --images=<image> \
    --service-account=router

例如:

$ oc adm router region-west -o yaml --images=myrepo/somerouter:mytag \
    --service-account=router

3.2.4. 过滤到特定路由器的路由

使用 ROUTE_LABELS 环境变量,您可以过滤路由,使其仅供特定路由器使用。

例如,如果您有多个路由器和 100 个路由,您可以将标签附加到路由,以便一部分标签由一个路由器处理,而其余则由另一个路由器处理。

  1. 创建路由器 后,使用 ROUTE_LABELS 环境变量标记路由器:

    $ oc set env dc/<router=name>  ROUTE_LABELS="key=value"
  2. 将标签添加到所需路由中:

    oc label route <route=name> key=value
  3. 要验证标签是否已附加到路由,请检查路由配置:

    $ oc describe route/<route_name>
设置最大并发连接数
默认情况下,路由器可以处理最多 20000 连接。您可以根据需要更改该限制。由于连接太少,健康检查无法正常工作,从而导致不必要的重启。您需要配置系统,以支持最大连接数。'sysctl fs.nr_open''sysctl fs.file-max' 中显示的限值必须足够大。否则,HAproxy 将不会启动。

创建路由器时,--max-connections= 选项会设置所需的限制:

$ oc adm router --max-connections=10000   ....

编辑路由器部署配置中的 ROUTER_MAX_CONNECTIONS 环境变量,以更改值。路由器容器集使用新值重启。如果 ROUTER_MAX_CONNECTIONS 不存在,则使用默认值 20000。

注意

连接包括 frontend 和 internal 后端。这表示两个连接。务必将 ROUTER_MAX_CONNECTIONS 设置为两倍,超过您要创建的连接数。

3.2.5. HAProxy Strict SNI

HAProxy strict-sni 可以通过路由器部署配置中的 ROUTER_STRICT_SNI 环境变量来控制。也可以使用 --strict-sni 命令行选项创建路由器时设置它。

$ oc adm router --strict-sni

3.2.6. TLS 密码套件

在创建路由器时使用 --ciphers 选项设置路由器密码套件

$ oc adm router --ciphers=modern   ....

值包括:modern, intermediate, 或 oldintermediate 为默认值。或者,可以提供一组":"分隔的密码。密码必须来自以下集合:

$ openssl ciphers

或者,将 ROUTER_CIPHERS 环境变量用于现有路由器。

3.2.7. 双向 TLS 身份验证

可以使用 mutual TLS 身份验证限制对路由器和后端服务的客户端访问。路由器将拒绝来自不在 通过身份验证 的集合中的客户端的请求。双向 TLS 身份验证是在客户端证书上实施的,可以根据签发证书的证书颁发机构(CA)控制,证书撤销列表和/或任何证书主题过滤器。在创建路由器时,使用 mutual tls 配置选项 --mutual-tls-auth, --mutual-tls-auth-ca, --mutual-tls-auth-crl--mutual-tls-auth-filter

$ oc adm router --mutual-tls-auth=required  \
                --mutual-tls-auth-ca=/local/path/to/cacerts.pem   ....

--mutual-tls-auth 的值是 required, optional, 或 nonenone 是默认值。--mutual-tls-auth-ca 值指定包含一个或多个 CA 证书的文件。路由器使用这些 CA 证书来验证客户端的证书。

可以使用 --mutual-tls-auth-crl 指定证书撤销列表,以处理证书(由有效认证机构签发)被撤销的情况。

$ oc adm router --mutual-tls-auth=required  \
     --mutual-tls-auth-ca=/local/path/to/cacerts.pem  \
     --mutual-tls-auth-filter='^/CN=my.org/ST=CA/C=US/O=Security/OU=OSE$'  \
     ....

--mutual-tls-auth-filter 值可用于根据证书主题进行精细的访问控制。该值是一个正则表达式,用于匹配证书的主题。

注意

上面的 mutual TLS 身份验证过滤器显示了一个限制性正则表达式(regex),包括在 ^$ 之间,这会完全准确匹配证书的主题。如果您决定使用限制较小的正则表达式,请注意这可能与您认为有效的任何 CA 颁发的证书匹配。建议您使用 --mutual-tls-auth-ca 选项,以便您更精细地控制发布的证书。

使用 --mutual-tls-auth=required 可确保您只允许经过身份验证的客户端访问后端资源。这意味着始终 需要 客户端来提供身份验证信息(提供一个客户端证书)。要使 mutual TLS 身份验证可选,请使用 --mutual-tls-auth=optional (或使用 none 禁用它,这是默认设置)。请注意,optional 意味着您 不需要 客户端提供任何身份验证信息,如果客户端提供任何身份验证信息,这会在 X-SSL* HTTP 标头中传递给后端。

$ oc adm router --mutual-tls-auth=optional  \
     --mutual-tls-auth-ca=/local/path/to/cacerts.pem  \
     ....

启用 mutual TLS 身份验证支持时(使用 --mutual-tls-auth 标志的 required 值或 optional 值),客户端身份验证信息将以 X-SSL* HTTP 标头的形式传递给后端。

X-SSL* HTTP 标头 X-SSL-Client-DN 示例:证书主题的完整可分辨名称(DN)。X-SSL-Client-NotBefore :客户端证书启动日期为 YYMMDDhhmmss[Z] 格式。X-SSL-Client-NotAfter :客户端证书结束日期,采用 YYMMDDhhmmss[Z] 格式。X-SSL-Client-SHA1 :客户端证书的 SHA-1 指纹。X-SSL-Client-DER :提供客户端证书的完整访问权限。包含以 base-64 格式编码的 DER 格式的客户端证书。

3.2.8. 高可用路由器

您可以使用 IP 故障切换在 OpenShift Container Platform 集群中设置高可用性路由器。此设置在不同节点上有多个副本,因此如果当前副本失败,故障切换软件可以切换到另一个副本。

3.2.9. 自定义路由器服务端口

您可以通过设置环境变量 ROUTER_SERVICE_HTTP_PORTROUTER_SERVICE_HTTPS_PORT 来自定义模板路由器绑定的服务端口。这可以通过创建模板路由器,然后编辑其部署配置来完成。

以下示例创建带有 0 个副本的路由器部署,并自定义路由器服务 HTTP 和 HTTPS 端口,然后相应地将其扩展(到 1 个副本)。

$ oc adm router --replicas=0 --ports='10080:10080,10443:10443' 1
$ oc set env dc/router ROUTER_SERVICE_HTTP_PORT=10080  \
                   ROUTER_SERVICE_HTTPS_PORT=10443
$ oc scale dc/router --replicas=1
1
确保为使用容器网络模式 --host-network=false 的路由器正确设置公开端口。
重要

如果您确实自定义模板路由器服务端口,您还需要确保运行路由器 Pod 的节点在防火墙中打开这些自定义端口(通过 Ansible 或 iptables,或通过 firewall-cmd使用的任何其他自定义方式)。

以下是使用 iptables 打开自定义路由器服务端口的示例:

$ iptables -A OS_FIREWALL_ALLOW -p tcp --dport 10080 -j ACCEPT
$ iptables -A OS_FIREWALL_ALLOW -p tcp --dport 10443 -j ACCEPT

3.2.10. 使用多个路由器

管理员可以创建具有相同定义的多个路由器,为同一组路由提供服务。每个路由器将位于不同的节点,并且具有不同的 IP 地址。网络管理员需要获取到每个节点所需的流量。

可以分组多个路由器来在集群中分发路由负载,并将租户单独的租户分发到不同的路由器或 分片。组中的每个路由器或分片都根据路由器中的选择器接受路由。管理员可以使用 ROUTE_LABELS 在整个集群中创建分片。用户可以使用 NAMESPACE_LABELS 在命名空间(项目)上创建分片。

3.2.11. 在部署配置中添加 Node Selector

将特定路由器部署到特定的节点上需要两个步骤:

  1. 为所需节点添加 标签

    $ oc label node 10.254.254.28 "router=first"
  2. 将节点选择器添加到路由器部署配置中:

    $ oc edit dc <deploymentConfigName>

    使用与标签对应的键和值添加 template.spec.nodeSelector 字段:

    ...
      template:
        metadata:
          creationTimestamp: null
          labels:
            router: router1
        spec:
          nodeSelector:      1
            router: "first"
    ...
    1
    键和值分别是 routerfirst,对应于 router=first 标签。

3.2.12. 使用路由器共享

路由器分片使用 NAMESPACE_LABELSROUTE_LABELS 来过滤路由器命名空间和路由。这可让您通过多个路由器部署分发路由的子集。通过使用非覆盖的子集,您可以有效地对一组路由进行分区。或者,您可以定义由重叠的路由子集组成的分片。

默认情况下,路由器从所有项目(命名空间)中选择所有路由。分片涉及将标签添加到路由或命名空间,以及向路由器添加标签选择器。每个路由器分片都由一组特定标签选择器或属于由特定标签选择器选择的命名空间来选择的路由组成。

注意

路由器服务帐户必须设置 [集群读取器] 权限,以允许访问其他命名空间中的标签。

路由器划分和 DNS

由于需要外部 DNS 服务器将请求路由到所需的分片,因此管理员负责为项目中的每个路由器创建单独的 DNS 条目。路由器不会将未知路由转发到另一个路由器。

考虑以下示例:

  • 路由器 A 驻留在主机 192.168.0.5 上,并且具有 *.foo.com 的路由。
  • 路由器 B 驻留在主机 192.168.1.9 上,并且具有 *.example.com 的路由。

单独的 DNS 条目必须将 *.foo.com 解析为托管 Router A 和 *.example.com 的节点:

  • *.foo.com A IN 192.168.0.5
  • *.example.com A IN 192.168.1.9

路由器分片示例

本节论述了使用命名空间和路由标签进行路由器分片。

图 3.1. 路由器划分基于命名空间标签

路由器划分基于命名空间标签
  1. 使用命名空间标签选择器配置路由器:

    $ oc set env dc/router NAMESPACE_LABELS="router=r1"
  2. 由于该路由器在命名空间上有一个选择器,因此路由器将仅处理匹配的命名空间的路由。要使此选择器与命名空间匹配,请相应地标记命名空间:

    $ oc label namespace default "router=r1"
  3. 现在,如果您在 default 命名空间中创建路由,该路由位于默认路由器中:

    $ oc create -f route1.yaml
  4. 创建新项目(命名空间)并创建路由 route2

    $ oc new-project p1
    $ oc create -f route2.yaml

    注意路由在路由器中不可用。

  5. 标签命名空间 p1 带有 router=r1

    $ oc label namespace p1 "router=r1"

添加此标签使路由在路由器中可用。

示例

一个路由器部署 finops-router 使用标签选择器 NAMESPACE_LABELS="name in (finance, ops)" 配置,一个路由器部署 dev-router 使用标签选择器 NAMESPACE_LABELS="name=dev" 配置。

如果所有路由都位于标有 name=financename=opsname=dev 的命名空间 中,则此配置会在两个路由器部署之间有效分发您的路由。

在上面的场景中,分片成为分区的一种特殊情况,没有重叠的子集。路由在路由器分片之间划分。

路由选择标准适用于路由的分布方式。有可能在路由器部署之间具有重叠的路由子集。

示例

除了上例中的 finops-routerdev-router 外,您还有 devops-router,它使用标签选择器 NAMESPACE_LABELS="name in (dev, ops)" 配置。

标签为 name=devname=ops 的命名空间中的路由现在由两个不同的路由器部署服务。在这种情况下,您定义了重叠的路由子集,如 基于命名空间标签的路由器交换过程中所示。

另外,这可让您创建更复杂的路由规则,允许将优先级更高的流量转移到专用的 finops-router,同时将较低优先级的流量发送到 devops-router

基于路由标签的路由器划分

NAMESPACE_LABELS 允许过滤项目来服务并从这些项目中选择所有路由,但您可能希望根据与路由本身相关的其他标准对路由进行分区。ROUTE_LABELS 选择器允许您对路由本身进行分片。

示例

使用标签选择器 ROUTE_LABELS="mydeployment=prod" 配置路由器部署 prod-router,路由器部署 devtest-router 则配置了标签选择器 ROUTE_LABELS="mydeployment in(dev, test)"

此配置根据路由的标签(无论命名空间如何)在两个路由器部署之间路由。

这个示例假设您有要服务的所有路由,并带有标签 "mydeployment=<tag>"

3.2.12.1. 创建路由器分片

本节描述了路由器分片的高级示例。假设有 26 个路由,名为 a 到 z,且具有不同的标签:

路由上可能的标签

sla=high       geo=east     hw=modest     dept=finance
sla=medium     geo=west     hw=strong     dept=dev
sla=low                                   dept=ops

这些标签表达了包括服务级别协议、地理位置、硬件要求和部门在内的概念。路由最多可在每列中有一个标签。有些路由可能具有其他标签,或者根本没有标签。

名称SLA地域HW部门其他标签

a

high

东部

中等

finance

type=static

b

 

西部

 

type=dynamic

cde

 

中等

 

type=static

g 到 k

 

dev

 

l 到 s

high

 

中等

ops

 

t — z

 

西部

  

type=dynamic

以下是一个便捷脚本 mkshard,它演示了如何一起使用 oc adm routeroc set envoc scale 来创建路由器分片。

#!/bin/bash
# Usage: mkshard ID SELECTION-EXPRESSION
id=$1
sel="$2"
router=router-shard-$id           1
oc adm router $router --replicas=0  2
dc=dc/router-shard-$id            3
oc set env   $dc ROUTE_LABELS="$sel"  4
oc scale $dc --replicas=3         5
1
创建的路由器具有名称 router-shard-<id>
2
暂时不要进行扩展。
3
路由器的部署配置。
4
使用 oc set env 设置选择表达式。选择表达式是 ROUTE_LABELS 环境变量的值。
5
向上扩展。

运行 mkshard 几次创建多个路由器:

路由器选择表达式Routes

router-shard-1

sla=high

a, l — s

router-shard-2

geo=west

b, t — z

router-shard-3

dept=dev

g 到 k

3.2.12.2. 修改路由器分片

由于路由器分片是基于标签的结构,因此您可以修改标签(通过 oc label)或选择表达式(通过 oc set env)。

本节扩展了创建路由器分片一节中启动的示例,演示了如何更改选择表达式。

以下是可修改现有路由器以使用新选择表达式的便捷脚本 modshard

#!/bin/bash
# Usage: modshard ID SELECTION-EXPRESSION...
id=$1
shift
router=router-shard-$id       1
dc=dc/$router                 2
oc scale $dc --replicas=0     3
oc set env   $dc "$@"             4
oc scale $dc --replicas=3     5
1
修改后的路由器具有名称 router-shard-<id>
2
进行修改的部署配置。
3
缩减规模。
4
使用 oc set env 设置新的选择表达式。与创建路由器分片部分中的 mkshard 不同,在 modshard 中指定为非ID 参数的选择表达式必须包含环境变量名称及其值。
5
纵向扩展。
注意

modshard 中,如果 router-shard-<id>部署策略Rolling,则不需要 oc scale 命令。

例如,将 router-shard-3 的部门扩展到包含 opsdev

$ modshard 3 ROUTE_LABELS='dept in (dev, ops)'

结果是,router-shard-3 现在选择路由 g — s (g — kl — s 的组合)。

本例考虑了本例中只有三个部门,并指定了一个部门离开分片,从而得到与上例相同的结果:

$ modshard 3 ROUTE_LABELS='dept != finance'

这个示例指定了三个用逗号分开的功能,并只选择路由 b

$ modshard 3 ROUTE_LABELS='hw=strong,type=dynamic,geo=west'

与涉及路由标签的 ROUTE_LABELS 类似,您可以使用 NAMESPACE_LABELS 环境变量根据路由命名空间的标签选择路由。本例修改 router-shard-3 以提供命名空间具有标签 frequency=weekly 的路由:

$ modshard 3 NAMESPACE_LABELS='frequency=weekly'

最后一个示例组合了 ROUTE_LABELSNAMESPACE_LABELS,以选择带有标签 sla=low 的路由,其命名空间具有标签 frequency=weekly

$ modshard 3 \
    NAMESPACE_LABELS='frequency=weekly' \
    ROUTE_LABELS='sla=low'

3.2.13. 查找路由器的主机名

在公开服务时,用户可以使用来自外部用户用于访问应用的 DNS 名称相同的路由。外部网络的网络管理员必须确保主机名解析为已接受该路由的路由器的名称。用户可以使用指向此主机名的 CNAME 设置 DNS。但是,用户可能不知道路由器的主机名。当不知道时,集群管理员可以提供它。

在创建路由器时,集群管理员可以使用 --router-canonical-hostname 选项和路由器的规范主机名。例如:

# oc adm router myrouter --router-canonical-hostname="rtr.example.com"

这会在包含路由器主机名的路由器部署配置中创建 ROUTER_CANONICAL_HOSTNAME 环境变量。

对于已存在的路由器,集群管理员可以编辑路由器的部署配置,并添加 ROUTER_CANONICAL_HOSTNAME 环境变量:

spec:
  template:
    spec:
      containers:
        - env:
          - name: ROUTER_CANONICAL_HOSTNAME
            value: rtr.example.com

ROUTER_CANONICAL_HOSTNAME 值显示在接受该路由的所有路由器的路由状态中。每次重新载入路由器时,路由状态都会刷新。

当用户创建路由时,所有活跃的路由器都会评估路由,如果满足条件,则接受路由。当定义 ROUTER_CANONICAL_HOSTNAME 环境变量的路由器接受该路由时,路由器会将该值放在路由状态的 routerCanonicalHostname 字段中。用户可以检查路由状态,以确定路由器是否允许该路由,从列表中选择路由器,再查找要传给网络管理员的路由器的主机名。

status:
  ingress:
    conditions:
      lastTransitionTime: 2016-12-07T15:20:57Z
      status: "True"
      type: Admitted
      host: hello.in.mycloud.com
      routerCanonicalHostname: rtr.example.com
      routerName: myrouter
      wildcardPolicy: None

在可用时 oc describe 会包括主机名:

$ oc describe route/hello-route3
...
Requested Host: hello.in.mycloud.com exposed on router myroute (host rtr.example.com) 12 minutes ago

利用上述信息,用户可以要求 DNS 管理员将路由的主机 hello.in.mycloud.com 中的 CNAME 设置为路由器的规范主机名 rtr.example.com。这将导致指向 hello.in.mycloud.com 的任何流量到达用户的应用。

3.2.14. 自定义默认路由子域

您可以通过修改 master 配置文件(默认为 /etc/origin/master/master-config.yaml 文件)来自定义用作环境默认路由子域的后缀。没有指定主机名的路由会有一个使用该默认路由子域生成的路由。

以下示例演示了如何将配置的后缀设置为 v3.openshift.test

routingConfig:
  subdomain: v3.openshift.test
注意

如果 master 正在运行,这个更改需要重启。

运行上述配置的 OpenShift Container Platform master 时,对于名为 no-route-hostname 的示例路由(没有主机名添加到命名空间 mynamespace生成的主机名将是:

no-route-hostname-mynamespace.v3.openshift.test

3.2.15. 将路由主机名强制到自定义路由子域

如果管理员希望限制到特定路由子域的所有路由,他们可以将 --force-subdomain 选项传递给 oc adm router 命令。这会强制路由器覆盖路由中指定的任何主机名,并根据提供给 --force-subdomain 选项的模板生成一个主机名。

以下示例运行路由器,它使用自定义子域模板 ${name}-${namespace}.apps.example.com 来覆盖路由主机名。

$ oc adm router --force-subdomain='${name}-${namespace}.apps.example.com'

3.2.16. 使用通配符证书

不包含证书的 TLS 路由改为使用路由器的默认证书。在大多数情况下,此证书应由可信证书颁发机构提供,但为了方便起见,您可以使用 OpenShift Container Platform CA 创建证书。例如:

$ CA=/etc/origin/master
$ oc adm ca create-server-cert --signer-cert=$CA/ca.crt \
      --signer-key=$CA/ca.key --signer-serial=$CA/ca.serial.txt \
      --hostnames='*.cloudapps.example.com' \
      --cert=cloudapps.crt --key=cloudapps.key
注意

oc adm ca create-server-cert 命令会生成一个有效期为两年的证书。这可以通过 --expire-days 选项进行修改,但出于安全原因,建议不要超过这个值。

仅从 Ansible 主机清单文件中列出的第一个 master 运行 oc adm 命令,默认为 /etc/ansible/hosts

路由器预期证书和密钥在单个文件中采用 PEM 格式:

$ cat cloudapps.crt cloudapps.key $CA/ca.crt > cloudapps.router.pem

在这里您可以使用 --default-cert 标志:

$ oc adm router --default-cert=cloudapps.router.pem --service-account=router
注意

浏览器只考虑一个级别深度的子域有效通配符。因此在此示例中,证书对 a.cloudapps.example.com 有效,但不适用于 a.b.cloudapps.example.com

3.2.17. 手动重新部署证书

手动重新部署路由器证书:

  1. 检查包含默认路由器证书的 secret 是否已添加到路由器中:

    $ oc set volume dc/router
    
    deploymentconfigs/router
      secret/router-certs as server-certificate
        mounted at /etc/pki/tls/private

    如果添加了证书,请跳过以下步骤并覆盖 secret。

  2. 确保为以下变量 DEFAULT_CERTIFICATE_DIR 设置了一个默认证书目录:

    $ oc set env dc/router --list
    
    DEFAULT_CERTIFICATE_DIR=/etc/pki/tls/private

    如果没有,请使用以下命令创建该目录:

    $ oc set env dc/router DEFAULT_CERTIFICATE_DIR=/etc/pki/tls/private
  3. 将证书导出到 PEM 格式:

    $ cat custom-router.key custom-router.crt custom-ca.crt > custom-router.crt
  4. 覆盖或创建路由器证书 secret:

    如果证书 secret 添加到路由器,请覆盖该 secret。如果没有,请创建一个新 secret。

    要覆盖 secret,请运行以下命令:

    $ oc create secret generic router-certs --from-file=tls.crt=custom-router.crt --from-file=tls.key=custom-router.key --type=kubernetes.io/tls -o json --dry-run | oc replace -f -

    要创建新 secret,请运行以下命令:

    $ oc create secret generic router-certs --from-file=tls.crt=custom-router.crt --from-file=tls.key=custom-router.key --type=kubernetes.io/tls
    
    $ oc set volume dc/router --add --mount-path=/etc/pki/tls/private --secret-name='router-certs' --name router-certs
  5. 部署路由器。

    $ oc rollout latest dc/router

3.2.18. 使用安全路由

目前,不支持密码保护的密钥文件。启动后,HAProxy 会提示输入密码,且无法自动执行此过程。要从密钥文件中删除密码短语,您可以运行以下命令:

# openssl rsa -in <passwordProtectedKey.key> -out <new.key>

以下是如何在流量代理到目的地之前使用发生在路由器上发生 TLS 终止的安全边缘终止路由的示例:安全边缘终止路由指定 TLS 证书和密钥信息。TLS 证书由路由器前端提供。

首先,启动一个路由器实例:

# oc adm router --replicas=1 --service-account=router

接下来,为我们边缘安全路由创建私钥、csr 和证书。有关如何执行此操作的说明将特定于您的证书颁发机构和提供商。有关名为 www.example.test 的域的简单自签名证书,请参考以下示例:

# sudo openssl genrsa -out example-test.key 2048
#
# sudo openssl req -new -key example-test.key -out example-test.csr  \
  -subj "/C=US/ST=CA/L=Mountain View/O=OS3/OU=Eng/CN=www.example.test"
#
# sudo openssl x509 -req -days 366 -in example-test.csr  \
      -signkey example-test.key -out example-test.crt

使用上述证书和密钥生成路由。

$ oc create route edge --service=my-service \
    --hostname=www.example.test \
    --key=example-test.key --cert=example-test.crt
route "my-service" created

看一下其定义。

$ oc get route/my-service -o yaml
apiVersion: v1
kind: Route
metadata:
  name:  my-service
spec:
  host: www.example.test
  to:
    kind: Service
    name: my-service
  tls:
    termination: edge
    key: |
      -----BEGIN PRIVATE KEY-----
      [...]
      -----END PRIVATE KEY-----
    certificate: |
      -----BEGIN CERTIFICATE-----
      [...]
      -----END CERTIFICATE-----

确保 www.example.test 的 DNS 条目指向您的路由器实例,并且到您的域的路由应可用。以下示例使用 curl 和本地解析器模拟 DNS 查找:

# routerip="4.1.1.1"  #  replace with IP address of one of your router instances.
# curl -k --resolve www.example.test:443:$routerip https://www.example.test/

3.2.19. 使用通配符路由(用于子域)

HAProxy 路由器支持通配符路由,这通过将 ROUTER_ALLOW_WILDCARD_ROUTES 环境变量设置为 true 来启用。具有 Subdomain 通配符策略且通过路由器准入检查的任何路由都将由 HAProxy 路由器提供服务。然后,HAProxy 路由器根据路由的通配符策略公开相关的服务(用于路由)。

重要

要更改路由的通配符策略,您必须删除路由并使用更新的通配符策略重新创建路由。仅编辑路由的 .yaml 文件中的路由通配符策略无法正常工作。

$ oc adm router --replicas=0 ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true
$ oc scale dc/router --replicas=1

了解如何为通配符路由配置 Web 控制台

使用安全通配符边缘终止路由

这个示例反映了在流量代理到目的地之前在路由器上发生的 TLS 终止。发送到子域 example.org(*.example.org )中的任何主机的流量将代理到公开的服务。

安全边缘终止路由指定 TLS 证书和密钥信息。TLS 证书由与子域(*.example.org)匹配的所有主机的路由器前端提供。

  1. 启动路由器实例:

    $ oc adm router --replicas=0 --service-account=router
    $ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true
    $ oc scale dc/router --replicas=1
  2. 为边缘安全路由创建私钥、证书签名请求(CSR)和证书。

    有关如何执行此操作的说明特定于您的证书颁发机构和供应商。有关名为 *.example.test 的域的简单自签名证书,请查看以下示例:

    # sudo openssl genrsa -out example-test.key 2048
    #
    # sudo openssl req -new -key example-test.key -out example-test.csr  \
      -subj "/C=US/ST=CA/L=Mountain View/O=OS3/OU=Eng/CN=*.example.test"
    #
    # sudo openssl x509 -req -days 366 -in example-test.csr  \
          -signkey example-test.key -out example-test.crt
  3. 使用上述证书和密钥生成通配符路由:

    $ cat > route.yaml  <<REOF
    apiVersion: v1
    kind: Route
    metadata:
      name:  my-service
    spec:
      host: www.example.test
      wildcardPolicy: Subdomain
      to:
        kind: Service
        name: my-service
      tls:
        termination: edge
        key: "$(perl -pe 's/\n/\\n/' example-test.key)"
        certificate: "$(perl -pe 's/\n/\\n/' example-test.cert)"
    REOF
    $ oc create -f route.yaml

    确保 *.example.test 的 DNS 条目指向您的路由器实例,并且到域的路由可用。

    这个示例使用带有本地解析器的 curl 来模拟 DNS 查找:

    # routerip="4.1.1.1"  #  replace with IP address of one of your router instances.
    # curl -k --resolve www.example.test:443:$routerip https://www.example.test/
    # curl -k --resolve abc.example.test:443:$routerip https://abc.example.test/
    # curl -k --resolve anyname.example.test:443:$routerip https://anyname.example.test/

对于允许通配符路由的路由器(ROUTER_ALLOW_WILDCARD_ROUTES 设置为 true),存在一些注意事项,即与通配符路由关联的子域的所有权。

在通配符路由之前,所有权基于针对任何其他声明赢得路由最旧的命名空间的主机名提出的声明。例如,如果路由 r1 比路由 r2 老,对于 主机名 one.example.test,命名空间 ns1 中的路由 r1(有一个 one.example.test 的声明)会优于命令空间 ns2 中具有相同声明的路由 r2

另外,其他命名空间中的路由也被允许声明非覆盖的主机名。例如,命名空间 ns1 中的路由 rone 可以声明 www.example.test,命名空间 d2 中的另一个路由 rtwo 可以声明 c3po.example.test

如果没有任何通配符路由声明同一子域(上例中的example.test ),则仍会出现这种情况。

但是,通配符路由需要声明子域中的所有主机名(以 \*.example.test格式的主机名)。通配符路由的声明会根据该子域的最旧路由(example.test)是否与通配符路由在同一命名空间中被允许或拒绝。最旧的路由可以是常规路由,也可以是通配符路由。

例如,如果已有一个路由 eldest 存在于 s1 命名空间中,声明一个名为 owner.example.test 的主机,如果稍后某个时间点上添加了一个新的通配符用来通配子域 (example.test) 中的路由,则通配路由的声明仅在与拥有的路由处于相同命名空间 (ns1)时才被允许。

以下示例演示了通配符路由的声明将成功或失败的各种情景。

在以下示例中,只要通配符路由未声明子域,允许通配符路由的路由器将允许对子域 example.test 中的主机进行非覆盖声明。

$ oc adm router ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true

$ oc project ns1
$ oc expose service myservice --hostname=owner.example.test
$ oc expose service myservice --hostname=aname.example.test
$ oc expose service myservice --hostname=bname.example.test

$ oc project ns2
$ oc expose service anotherservice --hostname=second.example.test
$ oc expose service anotherservice --hostname=cname.example.test

$ oc project otherns
$ oc expose service thirdservice --hostname=emmy.example.test
$ oc expose service thirdservice --hostname=webby.example.test

在以下示例中,允许通配符路由的路由器不允许 owner.example.testaname.example.test 的声明成功,因为拥有的命名空间是 ns1

$ oc adm router ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true

$ oc project ns1
$ oc expose service myservice --hostname=owner.example.test
$ oc expose service myservice --hostname=aname.example.test

$ oc project ns2
$ oc expose service secondservice --hostname=bname.example.test
$ oc expose service secondservice --hostname=cname.example.test

$ # Router will not allow this claim with a different path name `/p1` as
$ # namespace `ns1` has an older route claiming host `aname.example.test`.
$ oc expose service secondservice --hostname=aname.example.test --path="/p1"

$ # Router will not allow this claim as namespace `ns1` has an older route
$ # claiming host name `owner.example.test`.
$ oc expose service secondservice --hostname=owner.example.test

$ oc project otherns

$ # Router will not allow this claim as namespace `ns1` has an older route
$ # claiming host name `aname.example.test`.
$ oc expose service thirdservice --hostname=aname.example.test

在以下示例中,允许通配符路由的路由器将允许 '\*.example.test 声明成功,因为拥有的命名空间是 ns1,通配符路由属于同一命名空间。

$ oc adm router ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true

$ oc project ns1
$ oc expose service myservice --hostname=owner.example.test

$ # Reusing the route.yaml from the previous example.
$ # spec:
$ #   host: www.example.test
$ #   wildcardPolicy: Subdomain

$ oc create -f route.yaml   #  router will allow this claim.

在以下示例中,允许通配符路由的路由器不允许 '\*.example.test 声明成功,因为拥有的命名空间是 ns1,并且通配符路由属于另一个命名空间 cyclone

$ oc adm router ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true

$ oc project ns1
$ oc expose service myservice --hostname=owner.example.test

$ # Switch to a different namespace/project.
$ oc project cyclone

$ # Reusing the route.yaml from a prior example.
$ # spec:
$ #   host: www.example.test
$ #   wildcardPolicy: Subdomain

$ oc create -f route.yaml   #  router will deny (_NOT_ allow) this claim.

同样,当具有通配符路由的命名空间声明子域后,只有该命名空间中的路由才能声明同一子域中的任何主机。

在以下示例中,当命名空间 ns1 中带有通配符路由声明子域 example.test 的路由之后,只有命名空间 ns1 中的路由可以声明同一子域中的任何主机。

$ oc adm router ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true

$ oc project ns1
$ oc expose service myservice --hostname=owner.example.test

$ oc project otherns

$ # namespace `otherns` is allowed to claim for other.example.test
$ oc expose service otherservice --hostname=other.example.test

$ oc project ns1

$ # Reusing the route.yaml from the previous example.
$ # spec:
$ #   host: www.example.test
$ #   wildcardPolicy: Subdomain

$ oc create -f route.yaml   #  Router will allow this claim.

$ #  In addition, route in namespace otherns will lose its claim to host
$ #  `other.example.test` due to the wildcard route claiming the subdomain.

$ # namespace `ns1` is allowed to claim for deux.example.test
$ oc expose service mysecondservice --hostname=deux.example.test

$ # namespace `ns1` is allowed to claim for deux.example.test with path /p1
$ oc expose service mythirdservice --hostname=deux.example.test --path="/p1"

$ oc project otherns

$ # namespace `otherns` is not allowed to claim for deux.example.test
$ # with a different path '/otherpath'
$ oc expose service otherservice --hostname=deux.example.test --path="/otherpath"

$ # namespace `otherns` is not allowed to claim for owner.example.test
$ oc expose service yetanotherservice --hostname=owner.example.test

$ # namespace `otherns` is not allowed to claim for unclaimed.example.test
$ oc expose service yetanotherservice --hostname=unclaimed.example.test

在以下示例中,显示了不同的场景,其中删除所有者路由并在命名空间内和跨命名空间传递所有权。虽然命名空间 ns1 中存在声明主机 eldest.example.test 的路由,但该命名空间中的通配符路由可以声明子域 example.test。当删除主机 eldest.example.test 的路由时,下一个最旧的路由 senior.example.test 将成为最旧的路由,不会影响任何其他路由。删除主机 senior.example.test 的路由后,下一个最旧的路由 junior.example.test 将成为最旧路由并阻止通配符路由。

$ oc adm router ...
$ oc set env dc/router ROUTER_ALLOW_WILDCARD_ROUTES=true

$ oc project ns1
$ oc expose service myservice --hostname=eldest.example.test
$ oc expose service seniorservice --hostname=senior.example.test

$ oc project otherns

$ # namespace `otherns` is allowed to claim for other.example.test
$ oc expose service juniorservice --hostname=junior.example.test

$ oc project ns1

$ # Reusing the route.yaml from the previous example.
$ # spec:
$ #   host: www.example.test
$ #   wildcardPolicy: Subdomain

$ oc create -f route.yaml   #  Router will allow this claim.

$ #  In addition, route in namespace otherns will lose its claim to host
$ #  `junior.example.test` due to the wildcard route claiming the subdomain.

$ # namespace `ns1` is allowed to claim for dos.example.test
$ oc expose service mysecondservice --hostname=dos.example.test

$ # Delete route for host `eldest.example.test`, the next oldest route is
$ # the one claiming `senior.example.test`, so route claims are unaffacted.
$ oc delete route myservice

$ # Delete route for host `senior.example.test`, the next oldest route is
$ # the one claiming `junior.example.test` in another namespace, so claims
$ # for a wildcard route would be affected. The route for the host
$ # `dos.example.test` would be unaffected as there are no other wildcard
$ # claimants blocking it.
$ oc delete route seniorservice

3.2.20. 使用 Container Network Stack

OpenShift Container Platform 路由器在容器内运行,默认的行为是使用主机的网络堆栈(即,路由器容器运行的节点)。这个默认行为有利于性能,因为来自远程客户端的网络流量不需要通过用户空间获取多个跃点来访问目标服务和容器。

另外,这个默认行为可让路由器获取远程连接的实际源 IP 地址,而不是获取节点的 IP 地址。这可用于定义基于原始 IP、支持粘性会话和监控流量以及其他用途的入口规则。

此主机网络行为由 --host-network 路由器命令行选项控制,默认行为等同于使用 --host-network=true。如果要使用容器网络堆栈运行路由器,请在创建路由器时使用 --host-network=false 选项。例如:

$ oc adm router --service-account=router --host-network=false

在内部,这意味着路由器容器必须发布 80 和 443 端口,以便外部网络与路由器通信。

注意

使用容器网络堆栈运行意味着路由器将连接的源 IP 地址视为节点的 NATed IP 地址,而不是实际的远程 IP 地址。

注意

在使用多租户网络隔离的 OpenShift Container Platform 集群中,带有 --host-network=false 选项的非默认命名空间中的路由器将加载集群中的所有路由,但命名空间之间的路由会因为网络隔离而无法访问。使用 --host-network=true 选项时,路由会绕过容器网络,并且可以访问集群中的任何 pod。在这种情况下,如果需要隔离,则不要在命名空间间添加路由。

3.2.21. 使用动态配置管理器

您可以配置 HAProxy 路由器来支持动态配置管理器。

动态配置管理器带来某些类型的在线路由,无需 HAProxy 重新加载停机时间。它处理任何路由和端点生命周期事件,如路由和端点附加 |deletion|update

通过将 ROUTER_HAPROXY_CONFIG_MANAGER 环境变量设置为 true 来启用动态配置管理器:

$ oc set env dc/<router_name> ROUTER_HAPROXY_CONFIG_MANAGER='true'

如果动态配置管理器无法动态配置 HAProxy,它会重写配置并重新加载 HAProxy 进程。例如,如果新路由包含自定义注解,如自定义超时,或者路由需要自定义 TLS 配置。

动态配置内部使用 HAProxy 套接字和配置 API,以及预分配的路由和后端服务器池。预分配的路由池使用路由蓝图创建。默认蓝图集支持不安全的路由、边缘安全路由,无需任何自定义 TLS 配置和直通路由。

重要

重新加密 路由需要自定义 TLS 配置信息,因此需要额外的配置才能将其用于动态配置管理器。

通过设置 ROUTER_BLUEPRINT_ROUTE_NAMESPACE 以及可选的 ROUTER_BLUEPRINT_ROUTE_LABELS 环境变量来扩展动态配置管理器可以使用的蓝图。

蓝图路由命名空间中的所有路由或路由标签的路由作为与默认蓝图集类似的自定义蓝图处理。这包括使用自定义注解或路由的重新加密路由或自定义 TLS 配置的路由。

以下流程假定您已创建了三个路由对象:reencrypt-blueprint, annotated-edge-blueprint, 和 annotated-unsecured-blueprint。如需不同路由类型对象的示例,请参阅 Route Types

流程

  1. 创建一个新项目

    $ oc new-project namespace_name
  2. 创建新路由。此方法公开现有的服务:

    $ oc create route edge edge_route_name --key=/path/to/key.pem \
          --cert=/path/to/cert.pem --service=<service> --port=8443
  3. 标记路由:

    $ oc label route edge_route_name type=route_label_1
  4. 创建与路由对象定义不同的路由 :所有都具有标签 type=route_label_1:

    $ oc create -f reencrypt-blueprint.yaml
    $ oc create -f annotated-edge-blueprint.yaml
    $ oc create -f annotated-unsecured-blueprint.json

    您还可以从路由中删除标签,这会阻止它用作蓝图路由。例如,防止 annotated-unsecured-blueprint 用作蓝图路由:

    $ oc label route annotated-unsecured-blueprint type-
  5. 创建用于蓝图池的新路由器:

    $ oc adm router
  6. 为新路由器设置环境变量:

    $ oc set env dc/router ROUTER_HAPROXY_CONFIG_MANAGER=true      \
                           ROUTER_BLUEPRINT_ROUTE_NAMESPACE=namespace_name  \
                           ROUTER_BLUEPRINT_ROUTE_LABELS="type=route_label_1"

    处理命名空间或带有 type=route_label_1 标签的项目 namespace_name 中的所有路由,并用作自定义蓝图。

    请注意,您还可以通过管理该命名空间 namespace_name 中的路由来添加、更新或删除蓝图。动态配置管理器会监视命名空间 namespace_name 中路由的更改,类似于路由器监视路由服务的方式。

  7. 预分配的路由和后端服务器的池大小可以通过 ROUTER_BLUEPRINT_ROUTE_POOL_SIZE 控制,默认为 10, 而 ROUTER_MAX_DYNAMIC_SERVERS 默认为 5 环境变量。您还可以控制动态配置管理器所做的更改的频率,即当重新编写 HAProxy 配置并重新加载 HAProxy 进程时。默认值为 1 小时或 3600 秒,或者当动态配置管理器用尽池空间时。COMMIT_INTERVAL 环境变量控制此设置:

    $ oc set env dc/router -c router ROUTER_BLUEPRINT_ROUTE_POOL_SIZE=20  \
          ROUTER_MAX_DYNAMIC_SERVERS=3 COMMIT_INTERVAL=6h

    这个示例将每个蓝图路由的池大小增加到 20,将动态服务器的数量减少到 3,并将提交间隔增加到 6 小时。

3.2.22. 公开路由器指标

HAProxy 路由器指标 默认以 Prometheus 格式 公开或发布,供外部指标收集和聚合系统(如 Prometheus、statsd)使用。指标数据也可直接从 HAProxy 路由器 以自己的 HTML 格式获取,以便在浏览器或 CSV 下载中查看。这些指标包括 HAProxy 原生指标和一些控制器指标。

当您使用以下命令创建路由器时,OpenShift Container Platform 以 Prometheus 格式在 stats 端口(默认为 1936)上提供指标数据。

$ oc adm router --service-account=router
  • 要提取 Prometheus 格式的原始统计信息,请运行以下命令:

    curl <user>:<password>@<router_IP>:<STATS_PORT>

    例如:

    $ curl admin:sLzdR6SgDJ@10.254.254.35:1936/metrics

    您可以获取访问路由器服务注解中的指标所需的信息:

    $ oc edit service <router-name>
    
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        prometheus.io/port: "1936"
        prometheus.io/scrape: "true"
        prometheus.openshift.io/password: IImoDqON02
        prometheus.openshift.io/username: admin

    prometheus.io/port 是 stats 端口,默认为 1936。您可能需要配置防火墙以允许访问。使用前面的用户名和密码来访问指标。路径是 /metrics

    $ curl <user>:<password>@<router_IP>:<STATS_PORT>
    for example:
    $ curl admin:sLzdR6SgDJ@10.254.254.35:1936/metrics
    ...
    # HELP haproxy_backend_connections_total Total number of connections.
    # TYPE haproxy_backend_connections_total gauge
    haproxy_backend_connections_total{backend="http",namespace="default",route="hello-route"} 0
    haproxy_backend_connections_total{backend="http",namespace="default",route="hello-route-alt"} 0
    haproxy_backend_connections_total{backend="http",namespace="default",route="hello-route01"} 0
    ...
    # HELP haproxy_exporter_server_threshold Number of servers tracked and the current threshold value.
    # TYPE haproxy_exporter_server_threshold gauge
    haproxy_exporter_server_threshold{type="current"} 11
    haproxy_exporter_server_threshold{type="limit"} 500
    ...
    # HELP haproxy_frontend_bytes_in_total Current total of incoming bytes.
    # TYPE haproxy_frontend_bytes_in_total gauge
    haproxy_frontend_bytes_in_total{frontend="fe_no_sni"} 0
    haproxy_frontend_bytes_in_total{frontend="fe_sni"} 0
    haproxy_frontend_bytes_in_total{frontend="public"} 119070
    ...
    # HELP haproxy_server_bytes_in_total Current total of incoming bytes.
    # TYPE haproxy_server_bytes_in_total gauge
    haproxy_server_bytes_in_total{namespace="",pod="",route="",server="fe_no_sni",service=""} 0
    haproxy_server_bytes_in_total{namespace="",pod="",route="",server="fe_sni",service=""} 0
    haproxy_server_bytes_in_total{namespace="default",pod="docker-registry-5-nk5fz",route="docker-registry",server="10.130.0.89:5000",service="docker-registry"} 0
    haproxy_server_bytes_in_total{namespace="default",pod="hello-rc-vkjqx",route="hello-route",server="10.130.0.90:8080",service="hello-svc-1"} 0
    ...
  • 在浏览器中获取指标:

    1. 从路由器部署配置文件中删除以下 环境变量

      $ oc edit dc router
      
      - name: ROUTER_LISTEN_ADDR
        value: 0.0.0.0:1936
      - name: ROUTER_METRICS_TYPE
        value: haproxy
    2. 对路由器就绪度探测进行补丁,以使用与存活度探测相同的路径,它现在由 haproxy 路由器提供:

      $ oc patch dc router -p '"spec": {"template": {"spec": {"containers": [{"name": "router","readinessProbe": {"httpGet": {"path": "/healthz"}}}]}}}'
    3. 在浏览器中使用以下 URL 启动 stats 窗口,其中 STATS_PORT 值默认为 1936:

      http://admin:<Password>@<router_IP>:<STATS_PORT>

      您可以通过在 URL 中添加 ;csv 来获得 CSV 格式的统计信息:

      例如:

      http://admin:<Password>@<router_IP>:1936;csv

      获取路由器 IP、管理员名称和密码:

      oc describe pod <router_pod>
  • 禁止指标收集:

    $ oc adm router --service-account=router --stats-port=0

3.2.23. 大型集群的 ARP 缓存调优

在具有大量路由的 OpenShift Container Platform 集群中(超过 net.ipv4.neigh.default.gc_thresh3 的值 65536),您必须增加运行路由器 pod 的集群中每个节点上的 sysctl 变量默认值,以允许 ARP 缓存中更多条目。

当出现问题时,内核信息类似如下:

[ 1738.811139] net_ratelimit: 1045 callbacks suppressed
[ 1743.823136] net_ratelimit: 293 callbacks suppressed

当出现这个问题时,oc 命令可能会因为以下错误开始失败:

Unable to connect to the server: dial tcp: lookup <hostname> on <ip>:<port>: write udp <ip>:<port>-><ip>:<port>: write: invalid argument

要验证 IPv4 的 ARP 条目的实际数量,请运行以下内容:

# ip -4 neigh show nud all | wc -l

如果数字开始接近 net.ipv4.neigh.default.gc_thresh3 阈值,则增加值。运行以下命令来获取当前值:

# sysctl net.ipv4.neigh.default.gc_thresh1
net.ipv4.neigh.default.gc_thresh1 = 128
# sysctl net.ipv4.neigh.default.gc_thresh2
net.ipv4.neigh.default.gc_thresh2 = 512
# sysctl net.ipv4.neigh.default.gc_thresh3
net.ipv4.neigh.default.gc_thresh3 = 1024

以下 sysctl 将变量设置为 OpenShift Container Platform 当前默认值。

# sysctl net.ipv4.neigh.default.gc_thresh1=8192
# sysctl net.ipv4.neigh.default.gc_thresh2=32768
# sysctl net.ipv4.neigh.default.gc_thresh3=65536

要使这些设置永久生效,请查看本文档

3.2.24. 保护 DDoS Attacks

向默认 HAProxy 路由器镜像添加 超时 http-request,以防止部署遭受分布式拒绝服务(例如,slowloris)攻击:

# and the haproxy stats socket is available at /var/run/haproxy.stats
global
  stats socket ./haproxy.stats level admin

defaults
  option http-server-close
  mode http
  timeout http-request 5s
  timeout connect 5s 1
  timeout server 10s
  timeout client 30s
1
超时 http-request 设置为 5 秒。HAProxy 为客户端 5 秒提供 * 以发送其整个 HTTP 请求。否则,HAProxy 会关闭连接并显示 *an 错误。

另外,当设置环境变量 ROUTER_SLOWLORIS_TIMEOUT 时,它会限制客户端发送整个 HTTP 请求所需的时间。否则,HAProxy 将关闭连接。

通过设置 环境变量,可以将信息捕获为路由器部署配置的一部分,不需要手动修改模板,而手动添加 HAProxy 设置要求您重新构建路由器 Pod 和维护路由器模板文件。

使用注解在 HAProxy 模板路由器中实施基本的 DDoS 保护,包括限制以下功能:

  • 并发 TCP 连接数
  • 客户端可以请求 TCP 连接的速率
  • 可以发出 HTTP 请求的速率

这些是在每个路由上启用的,因为应用可能有完全不同的流量模式。

表 3.1. HAProxy 模板路由器设置
设置描述

haproxy.router.openshift.io/rate-limit-connections

启用设置(例如,设置为 true )。

haproxy.router.openshift.io/rate-limit-connections.concurrent-tcp

此路由上相同 IP 地址可执行的并发 TCP 连接数。

haproxy.router.openshift.io/rate-limit-connections.rate-tcp

客户端 IP 可以打开的 TCP 连接数。

haproxy.router.openshift.io/rate-limit-connections.rate-http

客户端 IP 在 3 秒期间内可以进行的 HTTP 请求数。

3.2.25. 启用 HAProxy 线程

使用 --threads 标志启用线程处理。此标志指定 HAProxy 路由器将使用的线程数量。

3.3. 部署自定义 HAProxy 路由器

3.3.1. 概述

默认 HAProxy 路由器旨在满足大多数用户的需求。但是,它不会公开 HAProxy 的所有功能。因此,用户可能需要根据自己的需求修改路由器。

您可能需要在应用后端内实施新功能,或修改当前的操作。router 插件提供了进行此自定义所需的所有功能。

路由器容器集使用模板文件来创建所需的 HAProxy 配置文件。模板文件是 golang 模板。在处理模板时,路由器可以访问 OpenShift Container Platform 信息,包括路由器的部署配置、接受路由集和一些帮助程序功能。

当路由器 pod 启动时,并且每次重新加载时,它会创建一个 HAProxy 配置文件,然后启动 HAProxy。HAProxy 配置手册 描述了 HAProxy 的所有功能以及如何构建有效的配置文件。

configMap 可用于添加新模板到路由器 pod。通过这种方法,修改路由器部署配置,将 configMap 挂载为路由器 Pod 中的卷。TEMPLATE_FILE 环境变量设置为路由器 Pod 中模板文件的完整路径名称。

重要

无法保证在升级 OpenShift Container Platform 后路由器模板自定义仍然可以正常工作。

此外,路由器模板自定义必须应用到运行的路由器的模板版本。

或者,您也可以构建自定义路由器镜像,并在部署部分或所有路由器时使用它。不需要所有路由器来运行同一镜像。为此,请修改 haproxy-template.config 文件,再重新构建 路由器 镜像。新镜像推送到集群的 Docker 存储库,路由器的部署配置 image: 字段则使用新名称更新。更新集群时,需要重新构建并推送镜像。

在这两种情况下,路由器容器集都以模板文件开头。

3.3.2. 获取路由器配置模板

HAProxy 模板文件非常大且复杂。对于某些更改,修改现有模板可能比编写完整的替换版本更简单。您可以通过在 master 上运行并引用路由器 pod,从正在运行的路由器获取 haproxy-config.template 文件:

# oc get po
NAME                       READY     STATUS    RESTARTS   AGE
router-2-40fc3             1/1       Running   0          11d
# oc exec router-2-40fc3 cat haproxy-config.template > haproxy-config.template
# oc exec router-2-40fc3 cat haproxy.config > haproxy.config

另外,您可以登录到运行路由器的节点:

# docker run --rm --interactive=true --tty --entrypoint=cat \
    registry.redhat.io/openshift3/ose-haproxy-router:v{product-version} haproxy-config.template

镜像名称来自容器镜像

将此内容保存到文件中,以用作自定义模板的基础。保存的 haproxy.config 显示实际运行的内容。

3.3.3. 修改路由器配置模板

3.3.3.1. 背景信息

模板基于 golang 模板。它可以引用路由器部署配置中的任何环境变量、下面描述的任何配置信息,以及路由器提供的帮助程序功能。

模板文件的结构镜像生成的 HAProxy 配置文件。在处理模板时,所有未被 {{" something "}} 包括的内容会直接复制到配置文件。被 {{" something "}} 包括的内容会被评估。生成的文本(如果有)复制到配置文件。

3.3.3.2. Go 模板操作

define 操作命名将包含已处理模板的文件。

{{define "/var/lib/haproxy/conf/haproxy.config"}}pipeline{{end}}
表 3.2. 模板路由器功能
功能含义

processEndpointsForAlias(alias ServiceAliasConfig, svc ServiceUnit, action string) []Endpoint

返回有效端点列表。当操作为"shuffle"时,端点的顺序是随机的。

env(variable, default …​string) string

尝试从容器集获取 named 环境变量。如果未定义或为空,它将返回可选的第二个参数。否则,它将返回空字符串。

matchPattern(pattern, s string) bool

第一个参数是包含正则表达式的字符串,第二个参数是要测试的变量。返回一个布尔值,指示作为第一个参数提供的正则表达式是否与作为第二个参数提供的字符串匹配。

isInteger(s string) bool

确定给定变量是否为整数。

firstMatch(s string, allowedValues …​string) bool

将给定字符串与允许字符串的列表进行比较。通过列表向右返回第一个匹配扫描.

matchValues(s string, allowedValues …​string) bool

将给定字符串与允许字符串的列表进行比较。如果字符串为允许的值,则返回 "true",否则返回 false。

generateRouteRegexp(hostname, path string, wildcard bool) string

生成与路由主机(和路径)匹配的正则表达式。第一个参数是主机名,第二个参数是路径,第三个参数是通配符布尔值。

genCertificateHostName(hostname string, wildcard bool) string

生成用于服务/匹配证书的主机名。第一个参数是主机名,第二个参数是通配符布尔值。

isTrue(s string) bool

确定给定变量是否包含"true"。

这些功能由 HAProxy 模板路由器插件提供。

3.3.3.3. 路由器提供的信息

本节回顾路由器在模板中提供的 OpenShift Container Platform 信息。路由器配置参数是 HAProxy 路由器插件提供的一组数据。这些字段可由 (dot).Fieldname 访问。

路由器配置参数下方的表格根据各种字段的定义展开。特别是 .State 拥有一组可接受的路由。

表 3.3. 路由器配置参数
字段类型描述

WorkingDir

字符串

文件要写入的目录,默认为 /var/lib/containers/router

State

map[string](ServiceAliasConfig)

路由。

ServiceUnits

map[string]ServiceUnit

服务查找。

DefaultCertificate

字符串

以 pem 格式到默认证书的完整路径名称。

PeerEndpoints

[]Endpoint

对等。

StatsUser

字符串

公开统计数据的用户名(如果模板支持)。

StatsPassword

字符串

公开统计数据的密码(如果模板支持)。

StatsPort

int

公开统计信息的端口(如果模板支持)。

BindPorts

bool

路由器是否应绑定默认端口。

表 3.4. 路由器 ServiceAliasConfig(A Route)
字段类型描述

Name

字符串

路由特定于用户的名称。

Namespace

字符串

路由的命名空间。

Host

字符串

主机名。例如: www.example.com

Path

字符串

可选路径。例如: www.example.com/myservice,其中 myservice 是路径。

TLSTermination

routeapi.TLSTerminationType

此后端的终止策略;驱动映射文件和路由器配置。

Certificates

map[string]Certificate

用于保护此后端的证书。按证书 ID 的键。

Status

ServiceAliasConfigStatus

指明需要永久保留的配置状态。

PreferPort

字符串

指明用户要公开的端口。如果为空,将为服务选择一个端口。

InsecureEdgeTerminationPolicy

routeapi.InsecureEdgeTerminationPolicyType

指明到边缘终端路由的不安全连接所需的行为: none (或 disable), allow, 或 redirect

RoutingKeyName

字符串

用于模糊 cookie ID 的路由 + 命名空间名称的哈希值。

IsWildcard

bool

表示此服务单元需要通配符支持。

Annotations

map[string]string

附加到此路由的注解。

ServiceUnitNames

map[string]int32

支持此路由的服务集合,按服务名称键,并根据映射中其他条目的权重加上相应的权重。

ActiveServiceUnits

int

权重为非零的 ServiceUnitName 的数量。

ServiceAliasConfig 是服务的路由。由主机 + 路径唯一标识指定。默认模板使用 {{range $cfgIdx、$cfg := .State }} 迭代路由。在这样的 {{range}} 块中,模板可以使用 $cfg.Field 引用当前 ServiceAliasConfig 的任何字段。

表 3.5. Router ServiceUnit
字段类型描述

Name

字符串

对应于服务名称 + namespace 的名称。由 ServiceUnit 唯一标识。

EndpointTable

[]Endpoint

支持该服务的端点。这转换为路由器的最终后端实施。

ServiceUnit 是一种服务封装、支持该服务的端点,以及指向服务的路由。这是驱动创建路由器配置文件的数据

表 3.6. 路由器端点
字段类型

ID

字符串

IP

字符串

Port

字符串

TargetName

字符串

PortName

字符串

IdHash

字符串

NoHealthCheck

bool

Endpoint 是 Kubernetes 端点的内部表示。

表 3.7. Router Certificate, ServiceAliasConfigStatus
字段类型描述

Certificate

字符串

代表一个公钥/私钥对。它通过 ID 来标识,该 ID 将成为文件名。CA 证书将不会设置 PrivateKey

ServiceAliasConfigStatus

字符串

表示此配置所需的文件已持久保存到磁盘。有效值:"saved", ""。

表 3.8. 路由器证书类型
字段类型描述

ID

字符串

 

内容

字符串

证书。

PrivateKey

字符串

私钥。

表 3.9. 路由器 TLSTerminationType
字段类型描述

TLSTerminationType

字符串

指定安全通信将停止的位置。

InsecureEdgeTerminationPolicyType

字符串

表示路由不安全连接所需的行为。虽然每个路由器可能会对要公开的端口做出自己的决定,但通常这是端口 80。

TLSTerminationTypeInsecureEdgeTerminationPolicyType 指定安全通信将停止的位置。

表 3.10. 路由器 TLSTerminationType 值
常数含义

TLSTerminationEdge

edge

终止边缘路由器上的加密。

TLSTerminationPassthrough

passthrough

目的地终止加密,目的地负责解密流量。

TLSTerminationReencrypt

reencrypt

在边缘路由器中终止加密,并使用目的地提供的新证书重新加密。

表 3.11. Router InsecureEdgeTerminationPolicyType Values
类型含义

Allow

流量发送到不安全端口(默认)上的服务器。

Disable

不安全的端口不允许流量。

Redirect

客户端重定向到安全端口。

None ("") 与 Disable 相同。

3.3.3.4. 注解

每个路由都可以附加注解。每个注释仅是一个名称和一个值。

apiVersion: v1
kind: Route
metadata:
  annotations:
    haproxy.router.openshift.io/timeout: 5500ms
[...]

名称可以是与现有 Annotations 没有冲突的任何内容。值是任意字符串。字符串可以具有多个令牌,用空格分开。例如,aa bb cc.该模板使用 {{index}} 来提取注释的值。例如:

{{$balanceAlgo := index $cfg.Annotations "haproxy.router.openshift.io/balance"}}

这是如何将其用于相互客户端授权的示例。

{{ with $cnList := index $cfg.Annotations "whiteListCertCommonName" }}
  {{   if ne $cnList "" }}
    acl test ssl_c_s_dn(CN) -m str {{ $cnList }}
    http-request deny if !test
  {{   end }}
{{ end }}

然后,您可以使用此命令处理列入白名单的 CN。

$ oc annotate route <route-name> --overwrite whiteListCertCommonName="CN1 CN2 CN3"

如需更多信息,请参阅特定于路由的注解

3.3.3.5. 环境变量

该模板可以使用路由器 pod 中存在的任何环境变量。环境变量可以在部署配置中设置。可以添加新的环境变量。

它们由 env 函数引用:

{{env "ROUTER_MAX_CONNECTIONS" "20000"}}

第一个字符串是 变量,第二个字符串是变量缺失或 nil 时的默认值。当 ROUTER_MAX_CONNECTIONS 未设置或为 nil 时,则使用 20000。环境变量是一个映射,其中键是环境变量名称,内容是 变量的值。

如需更多信息,请参阅特定于路由的环境变量

3.3.3.6. 用法示例

以下是基于 HAProxy 模板文件的简单模板:

从注释开始:

{{/*
  Here is a small example of how to work with templates
  taken from the HAProxy template file.
*/}}

模板可以创建任意数量的输出文件。使用定义结构来创建输出文件。文件名指定为要定义的参数,定义块内直到匹配端的所有内容都会被写入为该文件的内容。

{{ define "/var/lib/haproxy/conf/haproxy.config" }}
global
{{ end }}

上方会将 global 复制到 /var/lib/haproxy/conf/haproxy.config 文件,然后关闭该文件。

根据环境变量设置日志记录。

{{ with (env "ROUTER_SYSLOG_ADDRESS" "") }}
  log {{.}} {{env "ROUTER_LOG_FACILITY" "local1"}} {{env "ROUTER_LOG_LEVEL" "warning"}}
{{ end }}

env 函数提取环境变量的值。如果未定义环境变量或 nil,则返回第二个参数。

通过,使用 将 块中的 "."(dot)值设置为作为使用 的参数提供的任何值。with 操作测试点为 nil。如果没有 nil,则会处理到最后。在上面,假设 ROUTER_SYSLOG_ADDRESS 包含 /var/log/msgROUTER_LOG_FACILITY 未定义,并且 ROUTER_LOG_LEVEL 包含 info。以下命令将复制到输出文件中:

  log /var/log/msg local1 info

每个接受的路由最终都会在配置文件中生成行。使用 范围 来进入接受的路由:

{{ range $cfgIdx, $cfg := .State }}
  backend be_http_{{$cfgIdx}}
{{end}}

.StateServiceAliasConfig 的映射,其中键是路由名称. 范围 步骤通过映射,每个传递都使用 设置 $cfgIdx,并将 $cfg 设置为指向描述路由的 ServiceAliasConfig。如果有两个路由名为 myrouteheroute,则上述命令会将以下内容复制到输出文件中:

  backend be_http_myroute
  backend be_http_hisroute

Route Annotations、$cfg.Annotations 也是注解名称作为键的映射,内容字符串作为值。路由可以根据需要拥有更多注解,其使用由模板作者定义。用户将注解代码到路由中,模板作者则自定义 HAProxy 模板来处理注解。

常见用法是索引注解以获取值。

{{$balanceAlgo := index $cfg.Annotations "haproxy.router.openshift.io/balance"}}

索引提取给定注解的值(若有)。因此,$balanceAlgo 将包含与注解或 nil 关联的字符串。如上所示,您可以测试非空字符串,并使用 with 结构对其执行操作。

{{ with $balanceAlgo }}
  balance $balanceAlgo
{{ end }}

此处,如果 $balanceAlgo 不是 nil平衡 $balanceAlgo 将复制到输出文件中。

在第二个示例中,您想要根据注释中设置的超时值设置服务器超时。

$value := index $cfg.Annotations "haproxy.router.openshift.io/timeout"

现在 $value 会被评估,以确保它包含正确构建的字符串。matchPattern 函数接受正则表达式,如果参数满足表达式要求,则返回 true

matchPattern "[1-9][0-9]*(us\|ms\|s\|m\|h\|d)?" $value

这会接受 5000ms,但不接受 7y。结果可用于测试。

{{if (matchPattern "[1-9][0-9]*(us\|ms\|s\|m\|h\|d)?" $value) }}
  timeout server  {{$value}}
{{ end }}

它还可用于匹配令牌:

matchPattern "roundrobin|leastconn|source" $balanceAlgo

另外,也可以使用 matchValues 来匹配令牌:

matchValues $balanceAlgo "roundrobin" "leastconn" "source"

3.3.4. 使用 ConfigMap 替换路由器配置模板

您可以使用 ConfigMap 来自定义路由器实例,而无需重新构建路由器镜像。可以修改 haproxy-config.templatereload-haproxy 和其他脚本,以及创建和修改路由器环境变量。

  1. 复制您要修改的 haproxy-config.template如上所述根据需要进行修改。
  2. 创建 ConfigMap:

    $ oc create configmap customrouter --from-file=haproxy-config.template

    customrouter ConfigMap 现在包含修改后的 haproxy-config.template 文件的副本。

  3. 修改路由器部署配置,将 ConfigMap 挂载为文件,并将 TEMPLATE_FILE 环境变量指向该文件。这可以通过 oc set envoc set volume 命令完成,或者通过编辑路由器部署配置来完成。

    使用 oc 命令
    $ oc set volume dc/router --add --overwrite \
        --name=config-volume \
        --mount-path=/var/lib/haproxy/conf/custom \
        --source='{"configMap": { "name": "customrouter"}}'
    $ oc set env dc/router \
        TEMPLATE_FILE=/var/lib/haproxy/conf/custom/haproxy-config.template
    编辑路由器部署配置

    使用 oc edit dc router,使用文本编辑器编辑路由器部署配置。

    ...
            - name: STATS_USERNAME
              value: admin
            - name: TEMPLATE_FILE  1
              value: /var/lib/haproxy/conf/custom/haproxy-config.template
            image: openshift/origin-haproxy-routerp
    ...
            terminationMessagePath: /dev/termination-log
            volumeMounts: 2
            - mountPath: /var/lib/haproxy/conf/custom
              name: config-volume
          dnsPolicy: ClusterFirst
    ...
          terminationGracePeriodSeconds: 30
          volumes: 3
          - configMap:
              name: customrouter
            name: config-volume
    ...
    1
    spec.container.env 字段中,添加 TEMPLATE_FILE 环境变量以指向挂载的 haproxy-config.template 文件。
    2
    添加 spec.container.volumeMounts 字段以创建挂载点。
    3
    添加新的 spec.volumes 字段来引用 ConfigMap。

    保存更改并退出编辑器。这将重新启动路由器。

3.3.5. 使用粘滞表

以下示例自定义可在高可用性路由设置中使用,以使用在对等点间同步的粘滞表。

添加 Peer 部分

要在对等点间同步粘滞位,您必须在 HAProxy 配置中定义对等部分。本节决定了 HAProxy 如何识别并连接到同级服务器。插件在 .PeerEndpoints 变量下向模板提供数据,以便您可以轻松地识别路由器服务的成员。您可以通过添加以下内容,将 peer 部分添加到路由器镜像中的 haproxy-config.template 文件中:

{{ if (len .PeerEndpoints) gt 0 }}
peers openshift_peers
  {{ range $endpointID, $endpoint := .PeerEndpoints }}
    peer {{$endpoint.TargetName}} {{$endpoint.IP}}:1937
  {{ end }}
{{ end }}

更改重新加载脚本

使用粘滞位时,您可以选择告知 HAProxy 在 peer 部分中应考虑本地主机的名称。在创建端点时,插件会尝试将 TargetName 设置为端点的 TargetRef.Name 的值。如果没有设置 TargetRef,它会将 TargetName 设置为 IP 地址。TargetRef.Name 与 Kubernetes 主机名对应,因此您可以将 -L 选项添加到 reload-haproxy 脚本中,以标识 peer 部分中的本地主机。

peer_name=$HOSTNAME 1

if [ -n "$old_pid" ]; then
  /usr/sbin/haproxy -f $config_file -p $pid_file -L $peer_name -sf $old_pid
else
  /usr/sbin/haproxy -f $config_file -p $pid_file -L $peer_name
fi
1
必须与 peer 部分中使用的端点目标名称匹配。

修改后端

最后,若要在后端使用 stick-tables,您可以修改 HAProxy 配置以使用 stick-tables 和 peer 设置。以下是将 TCP 连接的现有后端更改为使用 stick-table 的示例:

            {{ if eq $cfg.TLSTermination "passthrough" }}
backend be_tcp_{{$cfgIdx}}
  balance leastconn
  timeout check 5000ms
  stick-table type ip size 1m expire 5m{{ if (len $.PeerEndpoints) gt 0 }} peers openshift_peers {{ end }}
  stick on src
                {{ range $endpointID, $endpoint := $serviceUnit.EndpointTable }}
  server {{$endpointID}} {{$endpoint.IP}}:{{$endpoint.Port}} check inter 5000ms
                {{ end }}
            {{ end }}

在修改后,您可以重建路由器

3.3.6. 重建路由器

若要重建路由器,您需要复制正在运行的路由器上存在的多个文件。创建一个工作目录并从路由器复制文件:

# mkdir - myrouter/conf
# cd myrouter
# oc get po
NAME                       READY     STATUS    RESTARTS   AGE
router-2-40fc3             1/1       Running   0          11d
# oc exec router-2-40fc3 cat haproxy-config.template > conf/haproxy-config.template
# oc exec router-2-40fc3 cat error-page-503.http > conf/error-page-503.http
# oc exec router-2-40fc3 cat default_pub_keys.pem > conf/default_pub_keys.pem
# oc exec router-2-40fc3 cat ../Dockerfile > Dockerfile
# oc exec router-2-40fc3 cat ../reload-haproxy > reload-haproxy

您可以编辑或替换其中任何一个文件。但是,conf/haproxy-config.templatereload-haproxy 最有可能被修改。

更新文件后:

# docker build -t openshift/origin-haproxy-router-myversion .
# docker tag openshift/origin-haproxy-router-myversion 172.30.243.98:5000/openshift/haproxy-router-myversion 1
# docker push 172.30.243.98:5000/openshift/origin-haproxy-router-pc:latest 2
1
使用存储库标记 version。在本例中,存储库是 172.30.243.98:5000
2
将标记的版本推送到存储库。可能需要先 docker login 存储库。

要使用新路由器,请通过更改 image: 字符串或将 --images=<repo>/<image>:<tag> 标志添加到 oc adm router 命令来编辑路由器部署配置。

调试更改时,设置 imagePullPolicy:Always 在部署配置中,强制在每次 pod 创建时拉取镜像。调试完成后,您可以将其改回到 imagePullPolicy:IfNotPresent 以避免每次 pod 启动时都拉取。

3.4. 将 HAProxy 路由器配置为使用 PROXY 协议

3.4.1. 概述

默认情况下,HAProxy 路由器要求进入到不安全、边缘和重新加密路由的连接才能使用 HTTP。但是,您可以使用 PROXY 协议 将路由器配置为预期传入请求。本节论述了如何将 HAProxy 路由器和外部负载均衡器配置为使用 PROXY 协议。

3.4.2. 为什么使用 PROXY 协议?

当代理服务器或负载平衡器等中间服务转发 HTTP 请求时,它会将连接的源地址附加到请求的"Forwarded"标头,从而将此信息提供给后续请求,以及最终将请求转发到的后端服务。但是,如果连接被加密,则无法修改"Forwarded"标头。在这种情况下,HTTP 标头无法在转发请求时准确传达原始源地址。

为了解决这个问题,一些负载均衡器使用 PROXY 协议封装 HTTP 请求,作为只转发 HTTP 的替代选择。封装使负载平衡器能够在不修改转发请求本身的情况下向请求添加信息。特别是,这意味着负载均衡器即使在转发加密的连接时也能通信源地址。

HAProxy 路由器可以配置为接受 PROXY 协议并解封 HTTP 请求。由于路由器终止对边缘和再加密路由的加密,因此路由器随后可以更新请求中的 "Forwarded" HTTP 标头(及相关的 HTTP 标头),附加使用 PROXY 协议通信的任何源地址。

警告

PROXY 协议和 HTTP 不兼容,不可混合。如果您在路由器前面使用负载均衡器,则必须使用 PROXY 协议或 HTTP。将一个协议配置为使用一个协议,另一个协议使用其他协议会导致路由失败。

3.4.3. 使用 PROXY 协议

默认情况下,HAProxy 路由器不使用 PROXY 协议。可以使用 ROUTER_USE_PROXY_PROTOCOL 环境变量配置路由器,以预期传入连接的 PROXY 协议:

启用 PROXY 协议

$ oc set env dc/router ROUTER_USE_PROXY_PROTOCOL=true

将变量设置为 trueTRUE 以外的任何值,以禁用 PROXY 协议:

禁用 PROXY 协议

$ oc set env dc/router ROUTER_USE_PROXY_PROTOCOL=false

如果您在路由器中启用 PROXY 协议,则必须将路由器前面的负载均衡器配置为使用 PROXY 协议。以下是配置 Amazon Elastic Load Balancer(ELB)服务以使用 PROXY 协议的示例。本例假定 ELB 将端口 80(HTTP)、443(HTTPS)和 5000(镜像注册表)转发到一个或多个 EC2 实例上运行的路由器。

将 Amazon ELB 配置为使用 PROXY 协议

  1. 要简化后续步骤,首先设置一些 shell 变量:

    $ lb='infra-lb' 1
    $ instances=( 'i-079b4096c654f563c' ) 2
    $ secgroups=( 'sg-e1760186' ) 3
    $ subnets=( 'subnet-cf57c596' ) 4
    1
    您的 ELB 的名称。
    2
    运行路由器的实例。
    3
    此 ELB 的安全组或组。
    4
    此 ELB 的子网。
  2. 接下来,使用适当的监听程序、安全组和子网创建 ELB。

    注意

    您必须将所有监听程序配置为使用 TCP 协议,而不是 HTTP 协议。

    $ aws elb create-load-balancer --load-balancer-name "$lb" \
       --listeners \
        'Protocol=TCP,LoadBalancerPort=80,InstanceProtocol=TCP,InstancePort=80' \
        'Protocol=TCP,LoadBalancerPort=443,InstanceProtocol=TCP,InstancePort=443' \
        'Protocol=TCP,LoadBalancerPort=5000,InstanceProtocol=TCP,InstancePort=5000' \
       --security-groups $secgroups \
       --subnets $subnets
    {
        "DNSName": "infra-lb-2006263232.us-east-1.elb.amazonaws.com"
    }
  3. 使用 ELB 注册路由器实例或实例:

    $ aws elb register-instances-with-load-balancer --load-balancer-name "$lb" \
       --instances $instances
    {
        "Instances": [
            {
                "InstanceId": "i-079b4096c654f563c"
            }
        ]
    }
  4. 配置 ELB 的健康检查:

    $ aws elb configure-health-check --load-balancer-name "$lb" \
       --health-check 'Target=HTTP:1936/healthz,Interval=30,UnhealthyThreshold=2,HealthyThreshold=2,Timeout=5'
    {
        "HealthCheck": {
            "HealthyThreshold": 2,
            "Interval": 30,
            "Target": "HTTP:1936/healthz",
            "Timeout": 5,
            "UnhealthyThreshold": 2
        }
    }
  5. 最后,创建一个启用了 ProxyProtocol 属性的负载均衡器策略,并在 ELB 的 TCP 端口 80 和 443 中配置它:

    $ aws elb create-load-balancer-policy --load-balancer-name "$lb" \
       --policy-name "${lb}-ProxyProtocol-policy" \
       --policy-type-name 'ProxyProtocolPolicyType' \
       --policy-attributes 'AttributeName=ProxyProtocol,AttributeValue=true'
    $ for port in 80 443
      do
        aws elb set-load-balancer-policies-for-backend-server \
         --load-balancer-name "$lb" \
         --instance-port "$port" \
         --policy-names "${lb}-ProxyProtocol-policy"
      done

验证配置

您可以按如下所示检查负载均衡器以验证配置是否正确:

$ aws elb describe-load-balancers --load-balancer-name "$lb" |
    jq '.LoadBalancerDescriptions| [.[]|.ListenerDescriptions]'
[
  [
    {
      "Listener": {
        "InstancePort": 80,
        "LoadBalancerPort": 80,
        "Protocol": "TCP",
        "InstanceProtocol": "TCP"
      },
      "PolicyNames": ["infra-lb-ProxyProtocol-policy"] 1
    },
    {
      "Listener": {
        "InstancePort": 443,
        "LoadBalancerPort": 443,
        "Protocol": "TCP",
        "InstanceProtocol": "TCP"
      },
      "PolicyNames": ["infra-lb-ProxyProtocol-policy"] 2
    },
    {
      "Listener": {
        "InstancePort": 5000,
        "LoadBalancerPort": 5000,
        "Protocol": "TCP",
        "InstanceProtocol": "TCP"
      },
      "PolicyNames": [] 3
    }
  ]
]
1
TCP 端口 80 的监听器应具有使用 PROXY 协议的策略。
2
TCP 端口 443 的监听程序应具有相同的策略。
3
TCP 端口 5000 的监听程序 不应 具有该策略。

或者,如果您已经配置了 ELB,但没有配置为使用 PROXY 协议,则需要更改 TCP 端口 80 的现有监听程序以使用 TCP 协议而不是 HTTP(TCP 端口 443 应已使用 TCP 协议):

$ aws elb delete-load-balancer-listeners --load-balancer-name "$lb" \
   --load-balancer-ports 80
$ aws elb create-load-balancer-listeners --load-balancer-name "$lb" \
   --listeners 'Protocol=TCP,LoadBalancerPort=80,InstanceProtocol=TCP,InstancePort=80'

验证协议更新

验证协议是否已更新,如下所示:

$ aws elb describe-load-balancers --load-balancer-name "$lb" |
   jq '[.LoadBalancerDescriptions[]|.ListenerDescriptions]'
[
  [
    {
      "Listener": {
        "InstancePort": 443,
        "LoadBalancerPort": 443,
        "Protocol": "TCP",
        "InstanceProtocol": "TCP"
      },
      "PolicyNames": []
    },
    {
      "Listener": {
        "InstancePort": 5000,
        "LoadBalancerPort": 5000,
        "Protocol": "TCP",
        "InstanceProtocol": "TCP"
      },
      "PolicyNames": []
    },
    {
      "Listener": {
        "InstancePort": 80,
        "LoadBalancerPort": 80,
        "Protocol": "TCP", 1
        "InstanceProtocol": "TCP"
      },
      "PolicyNames": []
    }
  ]
]
1
所有监听器(包括 TCP 端口 80 的监听器)都应使用 TCP 协议。

然后,创建一个负载均衡器策略,并将其添加到 ELB 中,如上一步第 5 步所述。

第 4 章 部署 Red Hat CloudForms

4.1. 在 OpenShift Container Platform 上部署 Red Hat CloudForms

4.1.1. 简介

OpenShift Container Platform 安装程序包括 Ansible 角色 openshift-management, 以及用于在 OpenShift Container Platform 上部署 Red Hat CloudForms 4.6(CloudForms Management Engine 5.9 或 CFME)的 playbook。

警告

当前实施与 Red Hat CloudForms 4.5 的技术预览部署过程不兼容,如 OpenShift Container Platform 3.6 文档 中所述。

在 OpenShift Container Platform 上部署 Red Hat CloudForms 时,需要做出两个主要决策:

  1. 您是否想要外部或容器化(也称为 podified)PostgreSQL 数据库?
  2. 哪个存储类将支持您的持久性卷(PV)?

对于第一个决定,您可以使用两种方式之一部署 Red Hat CloudForms,具体取决于 Red Hat CloudForms 使用的 PostgreSQL 数据库的位置:

Deployment Variant描述

完全容器化

所有应用程序服务和 PostgreSQL 数据库都作为 pod 在 OpenShift Container Platform 上运行。

外部数据库

应用程序使用外部托管的 PostgreSQL 数据库服务器,所有其他服务则作为 pod 在 OpenShift Container Platform 上运行。

对于第二个决定,openshift-management 角色提供了覆盖许多默认部署参数的自定义选项。这包括以下存储类选项来支持 PV:

Storage class描述

NFS(默认)

本地,在集群上

NFS 外部

NFS(如存储设备)

云供应商

使用云供应商(Google Cloud Engine、Amazon Web Services 或 Microsoft Azure)的自动存储置备。

预配置(高级)

假设您提前创建了所有内容

本指南的主题包括:在 OpenShift Container Platform 上运行 Red Hat CloudForms 的要求、可用配置变量的说明,以及在初始 OpenShift Container Platform 安装期间或置备集群之后运行安装程序的说明。

4.2. OpenShift Container Platform 上 Red Hat CloudForms 的要求

 
下表中列出了默认要求。可以通过 自定义模板参数 来覆盖它们。

重要

如果无法满足这些要求,应用性能将会受到影响,甚至可能无法部署。

表 4.1. 默认要求
要求描述自定义参数

应用程序内存

≥ 4.0 Gi

应用程序所需的最小内存

APPLICATION_MEM_REQ

应用程序存储

≥ 5.0 Gi

应用程序所需的最小 PV 大小

APPLICATION_VOLUME_CAPACITY

PostgreSQL 内存

≥ 6.0 Gi

数据库所需的最小内存

POSTGRESQL_MEM_REQ

PostgreSQL 存储

≥ 15.0 Gi

数据库所需的最小 PV 大小

DATABASE_VOLUME_CAPACITY

集群主机

≥ 3

集群中的主机数量

N/A

满足这些要求:

  • 您必须具有几个集群节点。
  • 您的集群节点必须具有大量可用内存。
  • 您必须有多个 GiB 的可用存储,无论是本地还是云供应商。
  • 可以通过为模板参数提供覆盖值来更改 PV 大小。

4.3. 配置角色变量

4.3.1. 概述

以下小节描述了 Ansible 清单文件中可能使用的角色变量,用于控制 运行安装程序 时红帽 CloudForms 安装的行为。

4.3.2. 常规变量

变量必填默认描述

openshift_management_install_management

false

布尔值,设置为 true 以安装应用程序。

openshift_management_app_template

cfme-template

要安装的红帽 CloudForms 的部署变体。为容器化数据库设置 cfme-template,或为外部数据库设置 cfme-template-ext-db

openshift_management_project

openshift-management

红帽 CloudForms 安装的命名空间(项目)

openshift_management_project_description

CloudForms Management Engine

命名空间(项目)描述。

openshift_management_username

admin

默认管理用户名。更改此值不会更改用户名;只有在您更改了名称并运行集成脚本(如 添加容器提供程序的脚本)时,才会更改此值。

openshift_management_password

smartvm

默认管理密码。更改此值不会更改密码;只有在您更改了密码并且正在运行集成脚本(如用于 添加容器提供程序的脚本)时,才会更改此值。

4.3.3. 自定义模板参数

您可以使用 openshift_management_template_parameters Ansible 角色变量来指定要在应用程序或 PV 模板中覆盖的任何模板参数。

例如,如果要降低 PostgreSQL pod 的内存要求,您可以设置以下内容:

openshift_management_template_parameters={'POSTGRESQL_MEM_REQ': '1Gi'}

处理红帽 CloudForms 模板后,1Gi 将用于 POSTGRESQL_MEM_REQ 模板参数的值。

并非所有模板参数都存在于 两种 模板变体中(容器化或外部数据库)。例如,虽然 podified 数据库模板具有 POSTGRESQL_MEM_REQ 参数,但外部 db 模板中没有这样的参数,因为不需要此信息,因为没有要求 pod 的数据库。

因此,如果您要覆盖模板参数,请非常小心。包含模板中未定义的参数将导致错误。如果在 Ensure the Management App is created 任务期间收到错误,请在再次运行安装程序前先运行 卸载脚本

4.3.4. 数据库变量

4.3.4.1. 容器化(pod)数据库

cfme-template.yaml 文件中任何 POSTGRES _* 或DATABASE_* 模板参数都可以通过清单文件中的 openshift_management_template_parameters 哈希进行自定义。

4.3.4.2. 外部数据库

cfme-template-ext-db.yaml 文件中的任何 POSTGRES _*DATABASE_* 模板参数都可以通过清单文件中的 openshift_management_template_parameters 哈希进行自定义。

外部 PostgreSQL 数据库要求您提供数据库连接参数。您必须在清单中的 openshift_management_template_parameters 参数中设置所需的连接密钥。以下键是必需的:

  • DATABASE_USER
  • DATABASE_PASSWORD
  • DATABASE_IP
  • DATABASE_PORT (大多数 PostgreSQL 服务器在端口 5432上运行)
  • DATABASE_NAME
注意

确保您的外部数据库正在运行 PostgreSQL 9.5,或者您可能无法成功部署 CloudForms 应用。

您的清单将包含类似如下的行:

[OSEv3:vars]
openshift_management_app_template=cfme-template-ext-db 1
openshift_management_template_parameters={'DATABASE_USER': 'root', 'DATABASE_PASSWORD': 'mypassword', 'DATABASE_IP': '10.10.10.10', 'DATABASE_PORT': '5432', 'DATABASE_NAME': 'cfme'}
1
openshift_management_app_template 参数设置为 cfme-template-ext-db

4.3.5. 存储类变量

变量必填默认描述

openshift_management_storage_class

nfs

要使用的存储类型。选项包括 nfsnfs_externalpreconfiguredcloudprovider

openshift_management_storage_nfs_external_hostname

false

如果您使用的是外部 NFS 服务器,如 NetApp 设备,则必须在此处设置主机名。如果没有使用外部 NFS,则该值保留为 false。另外,外部 NFS 要求您创建将支持应用程序 PV 的 NFS 导出以及数据库 PV(可选)。

openshift_management_storage_nfs_base_dir

/exports/

如果您使用外部 NFS,则可以在此处将基本路径设置为导出位置。对于本地 NFS,如果您要更改用于本地 NFS 导出的默认路径,您还可以更改此值。

openshift_management_storage_nfs_local_hostname

false

如果您的清单中没有 [nfs] 组,或者只想手动定义集群中的本地 NFS 主机,请将这个参数设置为首选 NFS 服务器的主机名。服务器必须是 OpenShift Container Platform 集群的一部分。

4.3.5.1. NFS(默认)

NFS 存储类最适合概念验证和测试部署。它也是部署的默认存储类。选择时不需要额外的配置。

此存储类将集群主机上的 NFS(默认为清单文件中的第一个 master)配置为支持所需的 PV。应用需要一个 PV,而数据库(可能外部托管)可能需要一秒钟。Red Hat CloudForms 应用所需的最小 PV 大小为 5GiB,PostgreSQL 数据库为 15GiB(如果专用于 NFS,则为卷或分区上的最小可用空间为 20GiB)。

自定义通过以下角色变量提供:

  • openshift_management_storage_nfs_base_dir
  • openshift_management_storage_nfs_local_hostname
4.3.5.2. NFS 外部

外部 NFS 依靠预先配置的 NFS 服务器为所需的 PV 提供导出。对于外部 NFS,您必须有一个 cfme-app 和可选的一个 cfme-db (容器化数据库)导出。

配置通过以下角色变量提供:

  • openshift_management_storage_nfs_external_hostname
  • openshift_management_storage_nfs_base_dir

openshift_management_storage_nfs_external_hostname 参数必须设置为外部 NFS 服务器的主机名或 IP。

如果 /exports 不是您的导出的父目录,则必须通过 openshift_management_storage_nfs_base_dir 参数设置基础目录。

例如,如果您的服务器导出为 /exports/hosted/prod/cfme-app,则必须设置 openshift_management_storage_nfs_base_dir=/exports/hosted/prod

4.3.5.3. 云供应商

如果您要将 OpenShift Container Platform 云供应商集成用于存储类,Red Hat CloudForms 也可以使用云供应商存储来支持其所需的 PV。要使此功能正常工作,您必须已配置了 openshift_cloudprovider_kind 变量(用于 AWS 或 GCE),以及特定于您所选云供应商的所有关联参数。

当使用此存储类创建应用程序时,需要使用配置的云供应商存储集成自动置备所需的 PV。

没有额外的变量可用于配置此存储类的行为。

4.3.5.4. 预配置(高级)

预配置 存储类意味着您准确知道您的操作,并且所有存储要求都已提前处理。通常,这意味着您已创建了正确大小的 PV。安装程序不会进行任何操作来修改任何存储设置。

没有额外的变量可用于配置此存储类的行为。

4.4. 运行安装程序

4.4.1. 在 OpenShift Container Platform 安装期间或之后部署 Red Hat CloudForms

您可以选择在初始 OpenShift Container Platform 安装过程中或置备集群后部署 Red Hat CloudForms:

  1. 确定在清单文件 [OSEv3:vars] 部分下的清单文件中将 openshift_management_install_management 设置为 true

    [OSEv3:vars]
    openshift_management_install_management=true
  2. 在清单文件中设置任何其他红帽 CloudForms 角色变量,如 配置角色变量 中所述。清单文件示例中提供了有助于执行此操作 的资源。
  3. 根据是否已置备 OpenShift Container Platform,选择要运行的 playbook:

    1. 如果要在安装 OpenShift Container Platform 集群的同时安装 Red Hat CloudForms,请调用标准 config.yml playbook,如 运行安装 Playbook 所述以开始 OpenShift Container Platform 集群和 Red Hat CloudForms 安装。
    2. 如果要在已置备的 OpenShift Container Platform 集群上安装 Red Hat CloudForms,请切换到 playbook 目录,并直接调用 Red Hat CloudForms playbook 开始安装:

      $ cd /usr/share/ansible/openshift-ansible
      $ ansible-playbook -v [-i /path/to/inventory] \
          playbooks/openshift-management/config.yml

4.4.2. 清单文件示例

以下小节演示了在 OpenShift Container Platform 中显示 Red Hat CloudForms 的各种配置的清单文件示例片段,可帮助您开始。

注意

如需完整的变量描述,请参阅配置角色变量

4.4.2.1. 所有默认值

本例最简单的方法是使用所有默认值和选项。这将实现完全容器化(指定)红帽 CloudForms 安装。所有应用程序组件以及 PostgreSQL 数据库都是在 OpenShift Container Platform 中创建的:

[OSEv3:vars]
openshift_management_app_template=cfme-template
4.4.2.2. 外部 NFS 存储

如前例所示,除了在集群中使用本地 NFS 服务外,它使用的是现有的外部 NFS 服务器(如存储设备)。请注意两个新参数:

[OSEv3:vars]
openshift_management_app_template=cfme-template
openshift_management_storage_class=nfs_external 1
openshift_management_storage_nfs_external_hostname=nfs.example.com 2
1
将设置为 nfs_external
2
设置为 NFS 服务器的主机名。

如果外部 NFS 主机在不同的父目录下导出目录,如 /exports/hosted/prod,请添加以下额外变量:

openshift_management_storage_nfs_base_dir=/exports/hosted/prod
4.4.2.3. 覆盖 PV 大小

这个示例覆盖持久性卷(PV)大小。PV 大小必须通过 openshift_management_template_parameters 设置,这样可确保应用程序和数据库能够在创建的 PV 上发出声明,而无需相互干扰:

[OSEv3:vars]
openshift_management_app_template=cfme-template
openshift_management_template_parameters={'APPLICATION_VOLUME_CAPACITY': '10Gi', 'DATABASE_VOLUME_CAPACITY': '25Gi'}
4.4.2.4. 覆盖内存要求

在测试或概念验证安装中,您可能需要降低应用程序和数据库内存要求,以符合您的容量。请注意,减少内存限值可能会导致性能降低或完全失败来初始化应用程序:

[OSEv3:vars]
openshift_management_app_template=cfme-template
openshift_management_template_parameters={'APPLICATION_MEM_REQ': '3000Mi', 'POSTGRESQL_MEM_REQ': '1Gi', 'ANSIBLE_MEM_REQ': '512Mi'}

本例指示安装程序处理应用程序模板,参数 APPLICATION_MEM_REQ 设置为 3000MiPOSTGRESQL_MEM_REQ 设置为 1GiANSIBLE_MEM_REQ 设置为 512Mi

这些参数可以和上一示例 覆盖 PV Sizes 中显示的参数结合使用。

4.4.2.5. 外部 PostgreSQL 数据库

要使用外部数据库,您必须将 openshift_management_app_template 参数值改为 cfme-template-ext-db

此外,必须使用 openshift_management_template_parameters 变量提供数据库连接信息。如需了解更多详细信息,请参阅配置角色变量

[OSEv3:vars]
openshift_management_app_template=cfme-template-ext-db
openshift_management_template_parameters={'DATABASE_USER': 'root', 'DATABASE_PASSWORD': 'mypassword', 'DATABASE_IP': '10.10.10.10', 'DATABASE_PORT': '5432', 'DATABASE_NAME': 'cfme'}
重要

确保您正在运行 PostgreSQL 9.5,或者您可能无法成功部署应用。

4.5. 启用容器提供程序集成

4.5.1. 添加单一容器提供程序

在 OpenShift Container Platform 上部署 Red Hat CloudForms 后,如 运行安装程序 所述,有两种方法可用于启用容器供应商集成。您可以将 OpenShift Container Platform 手动添加为容器供应商,也可以尝试使用此角色中包含的 playbook。

4.5.1.1. 手动添加

有关将 OpenShift Container Platform 集群手动添加为容器供应商的步骤,请参阅以下 Red Hat CloudForms 文档:

4.5.1.2. 自动添加

可以使用此角色中包含的 playbook 来完成自动化容器提供程序集成。

此 playbook:

  1. 收集所需的身份验证 secret。
  2. 查找指向红帽 CloudForms 应用程序和集群 API 的公共路由。
  3. 发出 REST 调用,以将 OpenShift Container Platform 集群添加为容器供应商。

进入 playbook 目录并运行容器供应商 playbook:

$ cd /usr/share/ansible/openshift-ansible
$ ansible-playbook -v [-i /path/to/inventory] \
    openshift-management/add_container_provider.yml

4.5.2. 多个容器供应商

除了提供 playbook 以将当前 OpenShift Container Platform 集群集成到 Red Hat CloudForms 部署中,此角色包含一个脚本,允许您在任何任意红帽 CloudForms 服务器中添加多个容器平台作为容器供应商。容器平台可以是 OpenShift Container Platform 或 OpenShift Origin。

在运行 playbook 时,使用多个提供程序脚本需要在 CLI 上手动配置和设置 EXTRA_VARS 参数。

4.5.2.1. 准备脚本

要准备多个供应商脚本,请完成以下手动配置:

  1. 复制 /usr/share/ansible/openshift-ansible/roles/openshift_management/files/examples/container_providers.yml 示例,如 /tmp/cp.yml。您将修改此文件。
  2. 如果您更改了红帽 CloudForms 名称或密码,请更新您复制的 container_providers.yml 文件中的 management_server 键中的 hostname、user password 参数。
  3. 填写您要添加为容器供应商的每个容器平台集群的 container_providers 键下的条目。

    1. 必须配置以下参数:

      • auth_key - 这是具有 cluster-admin 权限的服务帐户的令牌。
      • hostname - 这是指向集群 API 的主机名。每个容器提供程序必须具有唯一的主机名。
      • name - 这是要在红帽 CloudForms 服务器容器提供程序概览页面中显示的集群名称。这必须是唯一的。
      提示

      从集群中获取 auth_key bearer 令牌:

      $ oc serviceaccounts get-token -n management-infra management-admin
    2. 可选择性地配置以下参数:

      • port - 如果您的容器平台集群在 8443 之外的端口上运行 API,则更新此密钥。
      • endpoint - 您可以启用 SSL验证(verify_ssl),或将验证设置更改为 ssl-with-validation。目前不支持自定义可信 CA 证书。
4.5.2.1.1. 示例

例如,请考虑以下情况:

  • 您可以将 container_providers.yml 文件复制到 /tmp/cp.yml
  • 您需要添加两个 OpenShift Container Platform 集群。
  • 您的红帽 CloudForms 服务器在 mgmt.example.com上运行

在这种情况下,您将自定义 /tmp/cp.yml,如下所示:

container_providers:
  - connection_configurations:
      - authentication: {auth_key: "<token>", authtype: bearer, type: AuthToken} 1
        endpoint: {role: default, security_protocol: ssl-without-validation, verify_ssl: 0}
    hostname: "<provider_hostname1>"
    name: <display_name1>
    port: 8443
    type: "ManageIQ::Providers::Openshift::ContainerManager"
  - connection_configurations:
      - authentication: {auth_key: "<token>", authtype: bearer, type: AuthToken} 2
        endpoint: {role: default, security_protocol: ssl-without-validation, verify_ssl: 0}
    hostname: "<provider_hostname2>"
    name: <display_name2>
    port: 8443
    type: "ManageIQ::Providers::Openshift::ContainerManager"
management_server:
  hostname: "<hostname>"
  user: <user_name>
  password: <password>
1 2
<token> 替换为此集群的管理令牌。
4.5.2.2. 运行 Playbook

要运行 multi-providers 集成脚本,您必须提供容器提供程序配置文件的路径,作为 ansible-playbook 命令的 EXTRA_VARS 参数。使用 -e (或 --extra-vars)参数将 container_providers_config 设置为配置文件路径。进入 playbook 目录并运行 playbook:

$ cd /usr/share/ansible/openshift-ansible
$ ansible-playbook -v [-i /path/to/inventory] \
    -e container_providers_config=/tmp/cp.yml \
    playbooks/openshift-management/add_many_container_providers.yml

playbook 完成后,您应在红帽 CloudForms 服务中找到两个新的容器提供程序。导航到 Compute → Containers → Providers 页面,查看概述。

4.5.3. 刷新供应商

添加单个或多个容器提供程序后,必须在红帽 CloudForms 中刷新新的提供程序,以获取关于容器提供程序和所管理容器的所有最新数据。这涉及导航到红帽 CloudForms Web 控制台中的各个提供程序,然后单击每个控制台的刷新按钮。

有关步骤,请参阅以下 Red Hat CloudForms 文档:

4.6. 卸载 Red Hat CloudForms

4.6.1. 运行卸载 Playbook

要从 OpenShift Container Platform 卸载并删除部署的 Red Hat CloudForms 安装,请切换到 playbook 目录并运行 uninstall.yml playbook:

$ cd /usr/share/ansible/openshift-ansible
$ ansible-playbook -v [-i /path/to/inventory] \
    playbooks/openshift-management/uninstall.yml
重要

NFS 导出定义和数据不会自动删除。在尝试初始化新部署之前,您必须手动从旧应用或数据库部署中清除任何数据。

4.6.2. 故障排除

无法擦除旧的 PostgreSQL 数据可能会导致级联错误,从而导致 postgresql pod 进入 crashloopbackoff 状态。这会阻止 cfme pod 启动。crashloopbackoff 的原因是,之前部署期间创建的数据库 NFS 导出的文件权限不正确。

要继续,请从 PostgreSQL 导出中删除所有数据,并删除 pod(而不是部署器 Pod)。例如,如果您有以下 pod:

$ oc get pods
NAME                 READY     STATUS             RESTARTS   AGE
httpd-1-cx7fk        1/1       Running            1          21h
cfme-0               0/1       Running            1          21h
memcached-1-vkc7p    1/1       Running            1          21h
postgresql-1-deploy  1/1       Running            1          21h
postgresql-1-6w2t4   0/1       CrashLoopBackOff   1          21h

然后,您将:

  1. 从数据库 NFS 导出中删除数据。
  2. 运行:

    $ oc delete postgresql-1-6w2t4

PostgreSQL 部署器容器集将尝试扩展新的 postgresql 容器集,以取代您删除的容器集。在 postgresql 容器集运行后,cfme 容器集将停止阻止并开始应用初始化。

第 5 章 Prometheus Cluster Monitoring

5.1. 概述

OpenShift Container Platform 附带一个预先配置和自我更新的监控堆栈,它基于 Prometheus 开源项目及其更广泛的生态系统。它提供对集群组件的监控,并附带一组警报,以便立即通知集群管理员任何出现的问题,以及一组 Grafana 仪表板。

监控图表

上图中突出显示,监控堆栈的核心是 OpenShift Container Platform Cluster Monitoring Operator(CMO),它监视部署的监控组件和资源,并确保它们始终保持最新状态。

Prometheus Operator (PO) 可以创建、配置和管理 Prometheus 和 Alertmanager 实例。还能根据熟悉的 Kubernetes 标签查询来自动生成监控目标配置。

除了 Prometheus 和 Alertmanager 外,OpenShift Container Platform 监控还包括 node-exporterkube-state-metrics。node-exporter 是部署在每个节点上的代理,用于收集有关它的指标。kube-state-metrics 导出器代理将 Kubernetes 对象转换为 Prometheus 可使用的指标。

作为集群监控的一部分监控的目标有:

  • Prometheus 本身
  • Prometheus-Operator
  • cluster-monitoring-operator
  • Alertmanager 集群实例
  • Kubernetes apiserver
  • kubelet(kubelet 为每个容器指标嵌入 cAdvisor)
  • kube-controllers
  • kube-state-metrics
  • node-exporter
  • etcd(如果启用了 etcd 监控)

所有这些组件都会自动更新。

如需有关 OpenShift Container Platform Cluster Monitoring Operator 的更多信息,请参阅 Cluster Monitoring Operator GitHub 项目。

注意

为了能够提供具有保证兼容性的更新,OpenShift Container Platform 监控堆栈的可配置性仅限于明确可用的选项。

5.2. 配置 OpenShift Container Platform 集群监控

OpenShift Container Platform Ansible openshift_cluster_monitoring_operator 角色使用清单文件中的变量配置和部署 Cluster Monitoring Operator。

表 5.1. Ansible 变量
变量描述

openshift_cluster_monitoring_operator_install

如果为 true,部署 Cluster Monitoring Operator。否则,取消部署。默认将此变量设置为 true

openshift_cluster_monitoring_operator_prometheus_storage_capacity

每个 Prometheus 实例的持久性卷声明大小。只有在 openshift_cluster_monitoring_operator_prometheus_storage_enabled 被设置为 true 时才会应用这个变量。默认值为 50Gi

openshift_cluster_monitoring_operator_alertmanager_storage_capacity

每个 Alertmanager 实例的持久性卷声明大小。只有在 openshift_cluster_monitoring_operator_alertmanager_storage_enabled 被设置为 true 时才会应用这个变量。默认值为 2Gi

openshift_cluster_monitoring_operator_node_selector

设置为所需的现有 节点选择器,以确保 pod 放置到具有特定标签的节点上。默认为 node-role.kubernetes.io/infra=true

openshift_cluster_monitoring_operator_alertmanager_config

配置 Alertmanager。

openshift_cluster_monitoring_operator_prometheus_storage_enabled

启用 Prometheus 时间序列数据的持久性存储。默认将此变量设置为 false

openshift_cluster_monitoring_operator_alertmanager_storage_enabled

启用 Alertmanager 通知和静默的持久性存储。默认将此变量设置为 false

openshift_cluster_monitoring_operator_prometheus_storage_class_name

如果启用了 openshift_cluster_monitoring_operator_prometheus_storage_enabled 选项,请设置特定的 StorageClass 以确保 pod 被配置为使用该 storageclassPVC。默认值为 none,它应用默认存储类名称。

openshift_cluster_monitoring_operator_alertmanager_storage_class_name

如果启用了 openshift_cluster_monitoring_operator_alertmanager_storage_enabled 选项,请设置特定的 StorageClass 以确保 pod 被配置为使用该 storageclassPVC。默认值为 none,它应用默认存储类名称。

5.2.1. 监控先决条件

监控堆栈会带来额外的资源需求。详情请查看计算资源建议

5.2.2. 安装监控堆栈

监控堆栈默认安装有 OpenShift Container Platform。您可以防止安装它。为此,请在 Ansible 清单文件中将此变量设置为 false

openshift_cluster_monitoring_operator_install

您可以通过运行以下命令完成:

$ ansible-playbook [-i </path/to/inventory>] <OPENSHIFT_ANSIBLE_DIR>/playbooks/openshift-monitoring/config.yml \
   -e openshift_cluster_monitoring_operator_install=False

Ansible 目录的常用路径是 /usr/share/ansible/openshift-ansible/。在本例中,配置文件的路径为 /usr/share/ansible/openshift-ansible/playbooks/openshift-monitoring/config.yml

5.2.3. 持久性存储

使用持久性存储运行集群监控意味着您的指标存储在 持久性卷中,并可在 Pod 重新启动或重新创建后保留。如果您需要预防指标或警报数据丢失,这是理想方案。在生产环境中,强烈建议您使用块存储技术配置永久存储。

5.2.3.1. 启用持久性存储

默认情况下,对于 Prometheus 时间序列数据和 Alertmanager 通知和静默禁用持久性存储。您可以将集群配置为永久存储其中任何一个或两者。

  • 要启用 Prometheus 时间序列数据的持久性存储,请在 Ansible 清单文件中将此变量设置为 true

    openshift_cluster_monitoring_operator_prometheus_storage_enabled

  • 要启用 Alertmanager 通知和静默的持久性存储,请在 Ansible 清单文件中将此变量设置为 true

    openshift_cluster_monitoring_operator_alertmanager_storage_enabled

5.2.3.2. 确定需要多少存储

您需要的存储量取决于 Pod 的数目。管理员负责投入足够的存储来确保磁盘未满。如需有关持久性存储的系统要求的信息,请参阅 Cluster Monitoring Operator 的容量规划

5.2.3.3. 设置持久性存储大小

要为 Prometheus 和 Alertmanager 指定持久性卷声明的大小,请更改这些 Ansible 变量:

  • openshift_cluster_monitoring_operator_prometheus_storage_capacity (default:50Gi)
  • openshift_cluster_monitoring_operator_alertmanager_storage_capacity (default:2Gi)

只有将其对应的 storage_enabled 变量设置为 true 时,每个变量才会生效。

5.2.3.4. 分配充足的持久性卷

除非使用动态置备的存储,否则您需要确保 PVC 准备好声明持久性卷(PV),每个副本一个 PV。Prometheus 有两个副本,Alertmanager 有三个副本,它们相当于五个 PV。

5.2.3.5. 启用动态置备的存储

您可以使用动态置备的存储,而不是静态置备的存储。详情请参阅动态卷置备

要为 Prometheus 和 Alertmanager 启用动态存储,请在 Ansible 清单文件中将以下参数设置为 true

  • openshift_cluster_monitoring_operator_prometheus_storage_enabled (Default: false)
  • openshift_cluster_monitoring_operator_alertmanager_storage_enabled (Default: false)

启用动态存储后,您还可以在 Ansible 清单文件中为每个组件设置存储类

  • openshift_cluster_monitoring_operator_prometheus_storage_class_name (default: "")
  • openshift_cluster_monitoring_operator_alertmanager_storage_class_name (default: "")

只有将其对应的 storage_enabled 变量设置为 true 时,每个变量才会生效。

5.2.4. 支持的配置

配置 OpenShift Container Platform Monitoring 的支持方法是使用本指南中介绍的选项进行配置。除了这些明确的配置选项外,还可以将其他配置注入到堆栈中。但不受支持,因为配置范例可能会在 Prometheus 发行版本间有所变化,只有在控制了所有可能的配置时,才能安全地应对这样的情况。

明确不支持的情形包括:

  • openshift-monitoring 命名空间中创建额外的 ServiceMonitor 对象,从而扩展集群监控 Prometheus 实例提取的目标。这可能导致无法考量的冲突和负载差异,因此 Prometheus 设置可能会不稳定。
  • 创建额外的 ConfigMap 对象,导致集群监控 Prometheus 实例包含额外的警报和记录规则。请注意,如果应用此行为,这个行为会导致行为中断,因为 Prometheus 2.0 将附带新的规则文件语法。

5.3. 配置 Alertmanager

Alertmanager 管理传入的警报;这包括银级、禁止、聚合和通过电子邮件、PagerDuty 和 HipChat 等方法发送通知。

OpenShift Container Platform Monitoring Alertmanager 集群的默认配置是:

  global:
    resolve_timeout: 5m
  route:
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 12h
    receiver: default
    routes:
    - match:
        alertname: DeadMansSwitch
      repeat_interval: 5m
      receiver: deadmansswitch
  receivers:
  - name: default
  - name: deadmansswitch

可以使用 openshift_cluster_monitoring_operator 角色中的 Ansible 变量 openshift_cluster_monitoring_operator_alertmanager_config 覆盖此配置。

以下示例将 PagerDuty 配置为通知。如需了解如何检索 service_key,请参阅 Alertmanager 的 PagerDuty 文档。

openshift_cluster_monitoring_operator_alertmanager_config: |+
  global:
    resolve_timeout: 5m
  route:
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 12h
    receiver: default
    routes:
    - match:
        alertname: DeadMansSwitch
      repeat_interval: 5m
      receiver: deadmansswitch
    - match:
        service: example-app
      routes:
      - match:
          severity: critical
        receiver: team-frontend-page
  receivers:
  - name: default
  - name: deadmansswitch
  - name: team-frontend-page
    pagerduty_configs:
    - service_key: "<key>"

子路由仅匹配严重性为 critical 的警报,并使用名为 team-frontend-page 的接收器发送它们。如名称所示,对于关键警报,应传出某人。参阅 Alertmanager 配置来配置通过不同警报接收器发送警报。

5.3.1. 死人开关

OpenShift Container Platform Monitoring 附带了一个 死人开关,用于确保监控基础架构的可用性。

死人开关是始终触发的简单 Prometheus 警报规则。Alertmanager 持续向支持此功能的通知提供程序发送死人交换机的通知。这也可确保 Alertmanager 和通知提供程序之间的通信正常工作。

PagerDuty 支持这种机制,以在监控系统本身停机时发出警报。如需更多信息,请参阅下面的死人开关 PagerDuty

5.3.2. 分组警报

在警报针对 Alertmanager 触发后,必须将其配置为了解如何在逻辑上分组它们。

在本例中,添加了一个新的路由来反映 frontend 团队的警报路由。

流程

  1. 添加新路由。可以在原始路由下添加多个路由,通常用于定义通知的接收方。以下示例使用匹配器来确保只使用来自服务 example-app 的警报:

    global:
      resolve_timeout: 5m
    route:
      group_wait: 30s
      group_interval: 5m
      repeat_interval: 12h
      receiver: default
      routes:
      - match:
          alertname: DeadMansSwitch
        repeat_interval: 5m
        receiver: deadmansswitch
      - match:
          service: example-app
        routes:
        - match:
            severity: critical
          receiver: team-frontend-page
    receivers:
    - name: default
    - name: deadmansswitch

    子路由仅匹配严重性为 critical 的警报,并使用名为 team-frontend-page 的接收器发送它们。如名称所示,对于关键警报,应传出某人。

5.3.3. 死人开关 PagerDuty

PagerDuty 通过名为 死人开关 的集成来支持此机制。只需将 PagerDuty 配置添加到默认的 deadmanswitch 接收器。使用上述流程添加此配置。

如果死人开关警报静默 15 分钟,将死人开关配置为页面运算符。使用默认的 Alertmanager 配置时,死人开关警报每五分钟重复一次。如果死人开关在 15 分钟后触发,这表明通知失败至少两次。

了解如何 为 PagerDuty 配置死人开关

5.3.4. 警报规则

OpenShift Container Platform Cluster Monitoring 附带了以下默认配置的警报规则。目前无法添加自定义警报规则。

有些警报规则的名称相同。这是有意设计的。它们会警告同一事件,它们具有不同的阈值,或严重性不同。在禁止规则中,触发较高的严重性时会禁止较低严重性。

有关警报规则的详情,请查看配置文件

警报重要性描述

ClusterMonitoringOperatorErrors

critical

Cluster Monitoring Operator 会出现 X% 错误。

AlertmanagerDown

critical

Alertmanager 已从 Prometheus 目标发现中消失。

ClusterMonitoringOperatorDown

critical

ClusterMonitoringOperator 已从 Prometheus 目标发现中消失。

KubeAPIDown

critical

KubeAPI 已从 Prometheus 目标发现中消失。

KubeControllerManagerDown

critical

kubecontrollermanager 已从 Prometheus 目标发现中消失。

KubeSchedulerDown

critical

kubescheduler 已从 Prometheus 目标发现中消失。

KubeStateMetricsDown

critical

kubeStateMetrics 已从 Prometheus 目标发现中消失。

KubeletDown

critical

kubelet 已从 Prometheus 目标发现中消失。

NodeExporterDown

critical

NodeExporter 已从 Prometheus 目标发现中消失。

PrometheusDown

critical

Prometheus 已从 Prometheus 目标发现中消失。

PrometheusOperatorDown

critical

PrometheusOperator 已从 Prometheus 目标发现中消失。

KubePodCrashLooping

critical

Namespace/Pod (Container) 重启 times / second

KubePodNotReady

critical

Namespace/Pod 未就绪。

KubeDeploymentGenerationMismatch

critical

部署 Namespace/Deployment 生成不匹配

KubeDeploymentReplicasMismatch

critical

部署 Namespace/Deployment 副本不匹配

KubeStatefulSetReplicasMismatch

critical

StatefulSet Namespace/StatefulSet 副本不匹配

KubeStatefulSetGenerationMismatch

critical

StatefulSet Namespace/StatefulSet 生成不匹配

KubeDaemonSetRolloutStuck

critical

只有调度并准备好用于守护进程设置 Namespace/DaemonSet 的所需 pod 的 X%

KubeDaemonSetNotScheduled

warning

没有调度 daemonset Namespace/DaemonSet 的 pod。

KubeDaemonSetMisScheduled

warning

许多 daemonset Namespace/DaemonSet 的 pod 在不应该运行的位置运行。

KubeCronJobRunning

warning

CronJob Namespace/CronJob 需要 1h 以上才能完成。

KubeJobCompletion

warning

Job Namespaces/Job 需要超过 1h 的时间才能完成。

KubeJobFailed

warning

Job Namespaces/Job 无法完成。

KubeCPUOvercommit

warning

Pod 上过量使用的 CPU 资源请求无法容忍节点失败。

KubeMemOvercommit

warning

Pod 上过量使用的内存资源请求,无法容忍节点失败。

KubeCPUOvercommit

warning

命名空间上过量使用的 CPU 资源请求配额。

KubeMemOvercommit

warning

命名空间上过量使用的内存资源请求配额。

alerKubeQuotaExceeded

warning

命名空间 Namespace 中的 X% 的资源已使用。

KubePersistentVolumeUsageCritical

critical

命名空间 Namespace 中的 PersistentVolumeClaim 声明的持久性卷有 X% free。

KubePersistentVolumeFullInFourDays

critical

根据最近的抽样,命名空间 Namespace 中的 PersistentVolumeClaim 声明的持久性卷应该在四天内填满。X 字节当前可用。

KubeNodeNotReady

warning

节点 已就绪一小时以上

KubeVersionMismatch

warning

运行 X 种不同版本的 Kubernetes 组件。

KubeClientErrors

warning

Kubernetes API 服务器客户端的 'Job/Instance' 正在遇到 X% 错误。

KubeClientErrors

warning

Kubernetes API 服务器客户端的 'Job/Instance' 正在遇到 X 错误/ sec'。

KubeletTooManyPods

warning

kubelet 实例正在运行 X pod,接近 110。

KubeAPILatencyHigh

warning

API 服务器具有 99% 的 Verb 资源 延迟 X 秒。

KubeAPILatencyHigh

critical

API 服务器具有 99% 的 Verb 资源 延迟 X 秒。

KubeAPIErrorsHigh

critical

API 服务器针对 X% 的请求出错。

KubeAPIErrorsHigh

warning

API 服务器针对 X% 的请求出错。

KubeClientCertificateExpiration

warning

Kubernetes API 证书将在不到 7 天后过期。

KubeClientCertificateExpiration

critical

Kubernetes API 证书将在不到 1 天后过期。

AlertmanagerConfigInconsistent

critical

Summary:配置不同步.描述:Alertmanager 集群 服务 的实例配置不同步。

AlertmanagerFailedReload

warning

Summary:Alertmanager 的配置重新加载失败。描述:重新加载 Alertmanager 的配置对于 Namespace/Pod 失败。

TargetDown

warning

Summary:目标已停机。描述:X% 的作业 目标为 down。

DeadMansSwitch

none

Summary:通知 DeadMansSwitch.描述:这是一个 DeadMansSwitch,可确保整个 Alerting 管道正常工作。

NodeDiskRunningFull

warning

node-exporter Namespace/Pod 的设备设备在接下来 24 小时内完全运行。

NodeDiskRunningFull

critical

node-exporter Namespace/Pod 的设备设备在接下来 2 小时内完全运行。

PrometheusConfigReloadFailed

warning

Summary:重新载入 Prometheus 配置失败。描述:为 Namespace/Pod 重新载入 Prometheus 配置失败

PrometheusNotificationQueueRunningFull

warning

Summary:Prometheus 的警报通知队列已满运行。描述:Prometheus 的警报通知队列已完全针对 Namespace/Pod 运行

PrometheusErrorSendingAlerts

warning

Summary:从 Prometheus 发送警报时出错。描述:将警报从 Prometheus Namespace/Pod 发送到 Alertmanager 时出错

PrometheusErrorSendingAlerts

critical

Summary:从 Prometheus 发送警报时出错。描述:将警报从 Prometheus Namespace/Pod 发送到 Alertmanager 时出错

PrometheusNotConnectedToAlertmanagers

warning

Summary:Prometheus 没有连接到任何 Alertmanager。描述:Prometheus Namespace/Pod 没有连接到任何 Alertmanager

PrometheusTSDBReloadsFailing

warning

Summary:Prometheus 在从磁盘重新载入数据块时遇到问题。描述:在过去四个小时内,实例中的作业X 重新加载失败。

PrometheusTSDBCompactionsFailing

warning

Summary:Prometheus 在压缩示例块时遇到问题。描述:实例作业过去四小时内出现 X 紧凑故障。

PrometheusTSDBWALCorruptions

warning

Summary:Prometheus write-ahead 日志已被损坏。描述:Instance 中的 作业 具有损坏的 write-ahead 日志(WAL)。

PrometheusNotIngestingSamples

warning

Summary:Prometheus 不捕获示例。描述:Prometheus Namespace/Pod 不嵌套示例。

PrometheusTargetScrapesDuplicate

warning

Summary:Prometheus 有许多示例被拒绝。描述:Namespace/Pod 因为时间戳重复但不同的值而拒绝多个示例

EtcdInsufficientMembers

critical

Etcd 集群 "Job": insufficient members (X).

EtcdNoLeader

critical

Etcd 集群 "Job": member Instance 没有 leader。

EtcdHighNumberOfLeaderChanges

warning

Etcd 集群 "Job": 实例 Instance 在过去一小时内看到 X leader 改变。

EtcdHighNumberOfFailedGRPCRequests

warning

Etcd 集群 "Job":X% 的 GRPC_Method 请求在 etcd 实例 Instance 上失败。

EtcdHighNumberOfFailedGRPCRequests

critical

Etcd 集群 "Job":X% 的 GRPC_Method 请求在 etcd 实例 Instance 上失败。

EtcdGRPCRequestsSlow

critical

Etcd 集群 "Job": 到 GRPC_Method 的 gRPC 请求在 X_s on etcd instance _Instance

EtcdMemberCommunicationSlow

warning

Etcd 集群 "Job": 成员与 To 通信正在 X_s on etcd instance _Instance

EtcdHighNumberOfFailedProposals

warning

Etcd 集群 "Job":X 提议在 etcd 实例 Instance 的最后一小时内失败。

EtcdHighFsyncDurations

warning

Etcd 集群 "Job":99th percentile fync durations 是 X_s on etcd instance _Instance

EtcdHighCommitDurations

warning

Etcd 集群 "Job":99 percentile 的提交持续时间为 X_s on etcd instance _Instance

FdExhaustionClose

warning

Job instance Instance 很快会耗尽其文件描述符

FdExhaustionClose

critical

Job instance Instance 很快会耗尽其文件描述符

5.4. 配置 etcd 监控

如果 etcd 服务没有正确运行,则整个 OpenShift Container Platform 集群的成功操作将处于危险之中。因此,最好为 etcd 配置监控。

按照以下步骤配置 etcd 监控 :

流程

  1. 验证监控堆栈是否正在运行:

    $ oc -n openshift-monitoring get pods
    NAME                                           READY     STATUS              RESTARTS   AGE
    alertmanager-main-0                            3/3       Running             0          34m
    alertmanager-main-1                            3/3       Running             0          33m
    alertmanager-main-2                            3/3       Running             0          33m
    cluster-monitoring-operator-67b8797d79-sphxj   1/1       Running             0          36m
    grafana-c66997f-pxrf7                          2/2       Running             0          37s
    kube-state-metrics-7449d589bc-rt4mq            3/3       Running             0          33m
    node-exporter-5tt4f                            2/2       Running             0          33m
    node-exporter-b2mrp                            2/2       Running             0          33m
    node-exporter-fd52p                            2/2       Running             0          33m
    node-exporter-hfqgv                            2/2       Running             0          33m
    prometheus-k8s-0                               4/4       Running             1          35m
    prometheus-k8s-1                               0/4       ContainerCreating   0          21s
    prometheus-operator-6c9fddd47f-9jfgk           1/1       Running             0          36m
  2. 打开集群监控堆栈的配置文件:

    $ oc -n openshift-monitoring edit configmap cluster-monitoring-config
  3. config.yaml: |+ 下,添加 etcd 部分。

    1. 如果在 master 节点上运行静态 pod 的 etcd,您可以使用选择器指定 etcd 节点:

      ...
      data:
        config.yaml: |+
          ...
          etcd:
            targets:
              selector:
                openshift.io/component: etcd
                openshift.io/control-plane: "true"
    2. 如果在单独的主机上运行 etcd,则需要使用 IP 地址指定节点:

      ...
      data:
        config.yaml: |+
          ...
          etcd:
            targets:
             ips:
             - "127.0.0.1"
             - "127.0.0.2"
             - "127.0.0.3"

      如果 etcd 节点的 IP 地址有变化,您必须更新此列表。

  4. 验证 etcd 服务监控器现在是否正在运行:

    $ oc -n openshift-monitoring get servicemonitor
    NAME                  AGE
    alertmanager          35m
    etcd                  1m 1
    kube-apiserver        36m
    kube-controllers      36m
    kube-state-metrics    34m
    kubelet               36m
    node-exporter         34m
    prometheus            36m
    prometheus-operator   37m
    1
    etcd 服务监控器。

    etcd 服务监控器最多可能需要一分钟才能启动。

  5. 现在,您可以进入 Web 界面来查看有关 etcd 监控状态的更多信息。

    1. 要获取 URL,请运行:

      $ oc -n openshift-monitoring get routes
      NAME                HOST/PORT                                                                           PATH      SERVICES            PORT      TERMINATION   WILDCARD
      ...
      prometheus-k8s      prometheus-k8s-openshift-monitoring.apps.msvistun.origin-gce.dev.openshift.com                prometheus-k8s      web       reencrypt     None
    2. 使用 https,导航到为 prometheus-k8s 列出的 URL。登录。
  6. 确保该用户属于 cluster-monitoring-view 角色。此角色提供查看集群监控 UI 的访问权限。

    例如,要将用户 developer 添加到 cluster-monitoring-view 角色中,请运行:

    $ oc adm policy add-cluster-role-to-user cluster-monitoring-view developer
  7. 在 Web 界面中,以属于 cluster-monitoring-view 角色的用户身份登录。
  8. 单击 Status,然后单击 Targets。如果您看到 etcd 条目,则会监控 etcd

    etcd 无证书
  9. 虽然 etcd 被监控,但 Prometheus 还无法通过 etcd 进行身份验证,因此无法收集指标数据。

    针对 etcd 配置 Prometheus 身份验证:

    1. /etc/etcd/ca/ca.crt/etc/etcd/ca/ca.key 凭证文件从 master 节点复制到本地机器:

      $ ssh -i gcp-dev/ssh-privatekey cloud-user@35.237.54.213
    2. 创建包含以下内容的 openssl.cnf 文件:

      [ req ]
      req_extensions = v3_req
      distinguished_name = req_distinguished_name
      [ req_distinguished_name ]
      [ v3_req ]
      basicConstraints = CA:FALSE
      keyUsage = nonRepudiation, keyEncipherment, digitalSignature
      extendedKeyUsage=serverAuth, clientAuth
    3. 生成 etcd.key 私钥文件:

      $ openssl genrsa -out etcd.key 2048
    4. 生成 etcd.csr 证书签名请求文件:

      $ openssl req -new -key etcd.key -out etcd.csr -subj "/CN=etcd" -config openssl.cnf
    5. 生成 etcd.crt 证书文件:

      $ openssl x509 -req -in etcd.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out etcd.crt -days 365 -extensions v3_req -extfile openssl.cnf
    6. 将凭证置于 OpenShift Container Platform 使用的格式:

      $ cat <<-EOF > etcd-cert-secret.yaml
      apiVersion: v1
      data:
        etcd-client-ca.crt: "$(cat ca.crt | base64 --wrap=0)"
        etcd-client.crt: "$(cat etcd.crt | base64 --wrap=0)"
        etcd-client.key: "$(cat etcd.key | base64 --wrap=0)"
      kind: Secret
      metadata:
        name: kube-etcd-client-certs
        namespace: openshift-monitoring
      type: Opaque
      EOF

      这会创建 etcd-cert-secret.yaml 文件

    7. 将凭证文件应用到集群:

      $ oc apply -f etcd-cert-secret.yaml
  10. 现在您已配置了身份验证,请再次访问 Web 界面的 Targets 页面。验证 etcd 现在是否正确监控。可能需要几分钟后更改才会生效。

    etcd 监控工作
  11. 如果您希望在更新 OpenShift Container Platform 时自动更新 etcd 监控,请将 Ansible 清单文件中的这个变量设置为 true

    openshift_cluster_monitoring_operator_etcd_enabled=true

    如果您在单独的主机上运行 etcd,请按照 IP 地址使用此 Ansible 变量指定节点:

    openshift_cluster_monitoring_operator_etcd_hosts=[<address1>, <address2>, ...]

    如果 etcd 节点的 IP 地址改变,您必须更新此列表。

5.5. 访问 Prometheus、Alertmanager 和 Grafana。

OpenShift Container Platform Monitoring 附带了一个用于集群监控的 Prometheus 实例和一个中央 Alertmanager 集群。除了 Prometheus 和 Alertmanager 外,OpenShift Container Platform Monitoring 还包含一个 Grafana 实例,以及用于集群监控故障排除的预构建仪表板。由监控堆栈提供的 Grafana 实例及其仪表板是只读的。

获取用于访问 Prometheus、Alertmanager 和 Grafana Web UI 的地址:

流程

  1. 运行以下命令:

    $ oc -n openshift-monitoring get routes
    NAME                HOST/PORT
    alertmanager-main   alertmanager-main-openshift-monitoring.apps._url_.openshift.com
    grafana             grafana-openshift-monitoring.apps._url_.openshift.com
    prometheus-k8s      prometheus-k8s-openshift-monitoring.apps._url_.openshift.com

    确保将 https:// 添加到这些地址。您无法使用未加密的连接访问 Web UI。

  2. 根据 OpenShift Container Platform 身份进行身份验证,并使用与 OpenShift Container Platform 其他位置相同的凭证或验证方式。您必须使用具有所有命名空间的读取访问权限的角色,如 cluster-monitoring-view 集群角色。

第 6 章 访问并配置 Red Hat Registry

6.1. 启用身份验证的 Red Hat Registry

Red Hat Container Catalog (registry.access.redhat.com)是一个托管的镜像 registry,通过它可以获得所需的容器镜像。OpenShift Container Platform 3.11 Red Hat Container Catalog 从 registry.access.redhat.com 移到 registry.redhat.io

新的 registry(Registry.redhat.io)需要进行身份验证才能访问OpenShift Container Platform上的镜像及内容。当迁移到新registry后,现有的registry仍将在一段时间内可用。

注意

OpenShift Container Platform从Registry.redhat.io中提取(pull)镜像,因此需要配置集群以使用它。

新registry使用标准的OAuth机制进行身份验证:

  • 身份验证令牌。令牌(token)是服务帐户,由管理员生成。系统可以使用它们与容器镜像registry进行身份验证。服务帐户不受用户帐户更改的影响,因此使用令牌进行身份验证是一个可靠且具有弹性的方法。这是生产环境集群中唯一受支持的身份验证选项。
  • Web用户名和密码。这是用于登录到诸如access.redhat.com之类的资源的标准凭据集。虽然可以在OpenShift Container Platform上使用此身份验证方法,但在生产环境部署中不支持此方法。此身份验证方法应该只限于在OpenShift Container Platform之外的独立项目中使用。

您可以在 docker login 中使用您的凭证(用户名和密码,或身份验证令牌)来访问新 registry 中的内容。

所有镜像流均指向新的registry。由于新 registry 需要进行身份验证才能访问,因此 OpenShift 命名空间中有一个名为 imagestreamsecret 的新机密。

您需要将凭据放在两个位置:

  • OpenShift 命名空间 。您的凭据必须存在于 OpenShift 命名空间中,以便 OpenShift 命名空间中的镜像流可以导入。
  • 您的主机。您的凭据必须存在于主机上,因为在抓取(pull)镜像时,Kubernetes会使用主机中的凭据。

访问新 registry:

  • 验证镜像导入 secret( imagestreamsecret )是否位于 OpenShift 命名空间中。该 secret 具有允许您访问新 registry 的凭证。
  • 验证所有集群节点都有一个 /var/lib/origin/.docker/config.json,可以从 master 中复制,供您访问红帽 registry。

6.1.1. 创建用户帐户

如果您是有权使用红帽产品的红帽客户,则拥有具有适用用户凭证的帐户。这些是您用于登录到红帽客户门户的用户名和密码。

如果您没有帐户,可以通过注册以下选项之一获取免费帐户:

6.1.2. 为 Red Hat Registry 创建服务帐户和身份验证令牌

如果您的组织管理共享帐户,则必须创建令牌。管理员可以创建、查看和删除与组织关联的所有令牌。

先决条件

  • 用户凭证

流程

要创建令牌以完成 docker login,请执行以下操作 :

  1. 导航到 registry.redhat.io
  2. 使用您的红帽网络(RHN)用户名和密码登录。
  3. 出现提示时接受条款.

    • 如果未立即提示您接受条款,则在继续以下步骤时会提示您。
  4. Registry Service Accounts 页面中点 Create Service Account

    1. 为服务帐户提供名称。它将带有一个随机字符串。
    2. 输入描述。
    3. 单击 create。
  5. 切回到您的服务帐户。
  6. 点您创建的服务帐户。
  7. 复制用户名,包括前缀字符串。
  8. 复制令牌。

6.1.3. 管理用于安装和升级的 registry 凭证

您还可以在安装过程中使用 Ansible 安装程序管理 registry 凭据。

这将设置以下内容:

  • OpenShift 命名空间中的 imagestreamsecret
  • 所有节点上的凭据。

当您将 registry.redhat.io 的默认值用于 openshift_examples_registryurloreg_url 时,Ansible 安装程序将需要凭证。

先决条件

  • 用户凭证
  • 服务帐户
  • 服务帐户令牌

流程

要在安装过程中使用 Ansible 安装程序管理 registry 凭证:

  • 在安装或升级过程中,指定安装程序清单中的 oreg_auth_useroreg_auth_password 变量。
注意

如果您已创建了令牌,请将 oreg_auth_password 设置为令牌的值。

需要访问其他经过身份验证的 registry 的集群可以通过设置 openshift_additional_registry_credentials 来配置 registry 列表。每个 registry 都需要主机和密码值,您可以通过设置用户来指定用户名。默认情况下,通过尝试检查指定 registry 上的镜像 openshift3/ose-pod 来验证指定的凭证。

要指定备用镜像,请执行以下操作:

  • 设置 test_image
  • 通过将 test_login 设置为 False 来禁用凭据验证。

如果 registry 不安全,则将 tls_verify 设置为 False。

此列表中的所有凭据都将在 OpenShift 命名空间中创建 imagestreamsecret,并部署到所有节点的凭据。

例如:

openshift_additional_registry_credentials=[{'host':'registry.example.com','user':'name','password':'pass1','test_login':'False'},{'host':'registry2.example.com','password':'token12345','tls_verify':'False','test_image':'mongodb/mongodb'}]

6.1.4. 在 Red Hat Registry 中使用服务帐户

在为 Red Hat Registry 创建服务帐户和生成的令牌后,您可以执行其他任务。

注意

本节提供了手动步骤,可以通过提供 管理 registry Credentials for Installation 和 Upgrade 部分中概述的清单变量来自动执行这些步骤。

先决条件

  • 用户凭证
  • 服务帐户
  • 服务帐户令牌

流程

Registry Service Accounts 页面中点击您的帐户名称。在这里,您可以执行以下任务:

  • Token Information 选项卡中,您可以查看您的用户名(您提供的带有随机字符串的名称)和密码(令牌)。在此选项卡中,您可以重新生成令牌。
  • OpenShift Secret 选项卡中,您可以:

    1. 单击选项卡中的链接,以下载该机密。
    2. 将 secret 提交到集群:

      # oc create -f <account-name>-secret.yml --namespace=openshift
    3. 使用 imagePullSecrets 字段在 Kubernetes pod 配置中添加对 secret 的引用来更新 Kubernetes 配置,例如:

      apiVersion: v1
      kind: Pod
      metadata:
        name: somepod
        namespace: all
        spec:
          containers:
            - name: web
            image: registry.redhat.io/REPONAME
      
          imagePullSecrets:
            - name: <numerical-string-account-name>-pull-secret
  • Docker Login 选项卡中,您可以运行 docker login。例如:

    # docker login -u='<numerical-string|account-name>'
      -p=<token>

    成功登录后,将 ~/.docker/config.json 复制到 /var/lib/origin/.docker/config.json,然后重新启动节点。

    # cp -r ~/.docker /var/lib/origin/
      systemctl restart atomic-openshift-node
  • Docker Configuration 选项卡中,您可以:

    1. 单击选项卡中的链接,下载凭据配置。
    2. 通过将文件放入 Docker 配置目录中,将配置写入到磁盘。这将覆盖现有的凭据。例如:

      # mv <account-name>-auth.json ~/.docker/config.json

第 7 章 Master 和节点配置

7.1. 安装后自定义 master 和节点配置

openshift start 命令(用于 master 服务器)和 Hyperkube 命令(用于节点服务器)采用一组有限的参数,足以在开发或实验环境中启动服务器。但是,这些参数不足以描述和控制生产环境中所需的整套配置和安全选项。

您必须在 master 配置文件(/etc/origin/master/master-config.yaml) 和 节点配置映射中提供这些选项。这些文件定义了选项,包括覆盖默认插件、连接到 etcd、自动创建服务帐户、构建镜像名称、自定义项目请求、配置卷插件等。

本节介绍了自定义 OpenShift Container Platform master 和节点主机的可用选项,并演示了如何在安装后更改配置。

在不使用默认值的情况下,将完全指定这些文件。因此,一个空值表示您要使用该参数的空值启动。这样可以轻松地说明您配置的确切原因,但也难以记住要指定的所有选项。为此,可以使用 --write-config 选项创建配置文件,然后与 --config 选项一起使用。

7.2. 安装依赖项

生产环境应该使用标准 集群安装 过程进行安装。在生产环境中,最好将 多个 master 用于 高可用性 (HA)。建议使用三个 master 的集群架构,并且推荐使用 HAproxy

小心

如果在 master 主机上 安装 etcd,则必须将集群配置为使用至少三个 master,因为 etcd 无法决定哪个是权威的。成功运行两个 master 的唯一方法是在 master 以外的主机上安装 etcd。

7.3. 配置主控机和节点

配置 master 和节点配置文件的方法必须与用于安装 OpenShift Container Platform 集群的方法匹配。如果您遵循标准 集群安装 过程,请在 Ansible 清单文件中进行配置更改。

7.4. 使用 Ansible 进行配置更改

对于本节,假设您熟悉 Ansible。

只有一部分可用的主机配置选项会 公开给 Ansible。安装 OpenShift Container Platform 后,Ansible 会使用一些替换的值创建一个清单文件。修改此清单文件并重新运行 Ansible 安装程序 playbook 是为了自定义 OpenShift Container Platform 集群。

虽然 OpenShift Container Platform 支持使用 Ansible playbook 和清单文件进行集群安装,但您也可以使用其他管理工具,如 PuppetChefSalt

使用案例:将集群配置为使用 HTPasswd 身份验证

注意
  • 此用例假定您已为 playbook 中引用的所有节点设置了 SSH 密钥
  • htpasswd 工具程序位于 httpd-tools 软件包中:

    # yum install httpd-tools

修改 Ansible 清单并进行配置更改:

  1. 打开 ./hosts 清单文件。
  2. 在文件的 [OSEv3:vars] 部分添加以下新变量:

    # htpasswd auth
    openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider'}]
    # Defining htpasswd users
    #openshift_master_htpasswd_users={'<name>': '<hashed-password>', '<name>': '<hashed-password>'}
    # or
    #openshift_master_htpasswd_file=/etc/origin/master/htpasswd

    对于 HTPasswd 身份验证,openshift_master_identity_providers 变量启用身份验证类型。您可以使用 HTPasswd 配置三个不同的身份验证选项:

    • 如果主机上已配置了 /etc/origin/master/htpasswd,则仅指定 openshift_master _identity_providers
    • 指定 openshift_master_identity_providersopenshift_master_htpasswd_file 将本地 htpasswd 文件复制到主机。
    • 指定 openshift_master_identity_providersopenshift_master_htpasswd_users,以在主机上生成新的 htpasswd 文件。

    由于 OpenShift Container Platform 需要哈希密码来配置 HTPasswd 身份验证,因此您可以使用 htpasswd 命令(如以下小结所述)为用户生成哈希密码,或使用用户和相关哈希密码创建平面文件。

    以下示例将身份验证方法从默认 拒绝所有 设置到 htpasswd,并使用指定的文件为 jsmithblob 用户可以生成用户 ID 和密码

    # htpasswd auth
    openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true', 'challenge': 'true', 'kind': 'HTPasswdPasswordIdentityProvider'}]
    # Defining htpasswd users
    openshift_master_htpasswd_users={'jsmith': '$apr1$wIwXkFLI$bAygtKGmPOqaJftB', 'bloblaw': '7IRJ$2ODmeLoxf4I6sUEKfiA$2aDJqLJe'}
    # or
    #openshift_master_htpasswd_file=/etc/origin/master/htpasswd
  3. 重新运行 ansible playbook 以使这些修改生效:

    $ ansible-playbook -b -i ./hosts ~/src/openshift-ansible/playbooks/deploy_cluster.yml

    playbook 更新配置,并重启 OpenShift Container Platform master 服务以应用更改。

您现在已使用 Ansible 修改了 master 和节点配置文件,但这只是一个简单的用例。从此处您可以看到哪些 master节点配置选项 公开给 Ansible,并自定义您自己的 Ansible 清单。

7.4.1. 使用 htpasswd 命令

要将 OpenShift Container Platform 集群配置为使用 HTPasswd 身份验证,您至少需要一个带有哈希密码的用户才能包含在 清单文件中

您可以:

创建用户和散列密码:

  1. 运行以下命令来添加指定用户:

    $ htpasswd -n <user_name>
    注意

    您可以包含 -b 选项,用于在命令行中提供密码:

    $ htpasswd -nb <user_name> <password>
  2. 输入并确认用户的明文密码。

    例如:

    $ htpasswd -n myuser
    New password:
    Re-type new password:
    myuser:$apr1$vdW.cI3j$WSKIOzUPs6Q

    该命令将生成散列版本的密码。

然后您可以在配置 HTPasswd 身份验证时使用哈希密码。hashed 密码是字符串,位于 : 后面。在上例中,请输入:

openshift_master_htpasswd_users={'myuser': '$apr1$wIwXkFLI$bAygtISk2eKGmqaJftB'}

创建带有用户名和散列密码的平面文件:

  1. 执行以下命令:

    $ htpasswd -c /etc/origin/master/htpasswd <user_name>
    注意

    您可以包含 -b 选项,用于在命令行中提供密码:

    $ htpasswd -c -b <user_name> <password>
  2. 输入并确认用户的明文密码。

    例如:

    htpasswd -c /etc/origin/master/htpasswd user1
    New password:
    Re-type new password:
    Adding password for user user1

    命令会生成一个文件,其中包含用户名以及用户密码的散列版本。

然后,您可以在配置 HTPasswd 身份验证时使用密码文件。

注意

如需有关 htpasswd 命令的更多信息,请参阅 HTPasswd 身份提供程序

7.5. 进行手动配置更改

使用案例:配置集群以使用 HTPasswd 身份验证

手动修改配置文件:

  1. 打开您要修改的配置文件,本例中为 /etc/origin/master/master-config.yaml 文件:
  2. 将以下新变量添加到文件的 identityProviders 小节中:

    oauthConfig:
      ...
      identityProviders:
      - name: my_htpasswd_provider
        challenge: true
        login: true
        mappingMethod: claim
        provider:
          apiVersion: v1
          kind: HTPasswdPasswordIdentityProvider
          file: /etc/origin/master/htpasswd
  3. 保存您的更改并关闭该文件。
  4. 重启 master 以使更改生效:

    # master-restart api
    # master-restart controllers

您现在已手动修改 master 和节点配置文件,但这只是一个简单的用例。在这里,您可以通过进行进一步的修改来查看所有 master节点配置选项,并进一步自定义自己的集群。

注意

要修改集群中的节点,请根据需要更新节点配置映射。不要手动编辑 node-config.yaml 文件。

7.6. 主配置文件

本节介绍了 master-config.yaml 文件中提到的参数。

您可以 创建新的 master 配置文件 来查看已安装 OpenShift Container Platform 版本的有效选项。

重要

每当修改 master-config.yaml 文件时,您必须重启 master 才能使更改生效。请参阅重启 OpenShift Container Platform 服务

7.6.1. 准入控制配置

表 7.1. 准入控制配置参数
参数名称描述

AdmissionConfig

包含 准入插件 配置。OpenShift Container Platform 具有可在创建或修改 API 对象时触发的准入控制器插件的可配置列表。此选项允许您覆盖默认插件列表;例如,禁用一些插件、添加其他插件、更改顺序以及指定配置。插件及其配置列表都可从 Ansible 控制。

APIServerArguments

键值对将直接传递给与 API 服务器的命令行参数匹配的 Kube API 服务器。它们不会被迁移,但如果您引用了不存在服务器的值,则不会启动。这些值可能会覆盖 KubernetesMasterConfig 中的其他设置,这可能会导致无效的配置。使用带有 event-ttl 值的 APIServerArguments 将事件存储在 etcd 中。默认值为 2h,但可将其设置为 less 以防止内存增长:

apiServerArguments:
  event-ttl:
  - "15m"

控制器参数

键值对将直接传递给与控制器管理器的命令行参数匹配的 Kube 控制器管理器。它们不会被迁移,但如果您引用了不存在服务器的值,则不会启动。这些值可能会覆盖 KubernetesMasterConfig 中的其他设置,这可能会导致无效的配置。

DefaultAdmissionConfig

用于启用或禁用各种准入插件。当此类型作为 pluginConfig 下的 configuration 对象以及准入插件支持时,这会导致启用 默认的 准入插件。

PluginConfig

允许为每个准入插件指定配置文件。

PluginOrderOverride

master 上将安装的准入插件名称列表。订购非常显著。如果为空,则使用默认插件列表。

SchedulerArguments

键值对将直接传递给与调度程序的命令行参数匹配的 Kube 调度程序。它们不会被迁移,但如果您引用了不存在服务器的值,则不会启动。这些值可能会覆盖 KubernetesMasterConfig 中的其他设置,这可能会导致无效的配置。

7.6.2. 资产配置

表 7.2. 资产配置参数
参数名称描述

AssetConfig

如果存在,则资产服务器会根据定义的参数启动。例如:

assetConfig:
  logoutURL: ""
  masterPublicURL: https://master.ose32.example.com:8443
  publicURL: https://master.ose32.example.com:8443/console/
  servingInfo:
    bindAddress: 0.0.0.0:8443
    bindNetwork: tcp4
    certFile: master.server.crt
    clientCA: ""
    keyFile: master.server.key
    maxRequestsInFlight: 0
    requestTimeoutSeconds: 0

corsAllowedOrigins

要使用其他主机名从 web 应用访问 API 服务器,您必须通过将配置字段中的 corsAllowedOrigins 指定 corsAllowedOrigins 或在 openshift start 中指定 --cors-allowed-origins 选项来列入主机名。不会对值进行固定或转义。如需示例用法,请参阅 Web 控制台

DisabledFeatures

不应启动的功能列表。您可能想将其设置为 null。不太可能每个人都希望手动禁用功能,不建议这样做。

扩展

从子上下文下资产服务器文件系统提供服务的文件。

扩展开发

当设置为 true 时,告诉资产服务器为每个请求重新载入扩展脚本和样式表,而不是只在启动时使用。它使您可以开发扩展,无需每次更改重启服务器。

ExtensionProperties

key-(string)和 value-(字符串)对,这些对将注入到全局变量 OPENSHIFT_EXTENSION_PROPERTIES 下。

ExtensionScripts

Web 控制台加载时,资产服务器文件中的文件路径作为脚本加载。

ExtensionStylesheets

Web 控制台加载时,资产服务器上的文件路径以作为风格的表加载。

LoggingPublicURL

用于日志记录的公共端点(可选)。

LogoutURL

在登出 Web 控制台后将 Web 浏览器重定向到的一个可选的绝对 URL。如果未指定,则会显示内置注销页面。

MasterPublicURL

Web 控制台如何访问 OpenShift Container Platform 服务器。

MetricsPublicURL

指标的公共端点(可选)。

PublicURL

资产服务器的 URL。

7.6.3. 认证和授权配置

表 7.3. 认证和授权参数
参数名称描述

authConfig

包含身份验证和授权配置选项。

AuthenticationCacheSize

指明应缓存多少个验证结果。如果为 0,则使用默认的缓存大小。

AuthorizationCacheTTL

表示应缓存授权结果的时长。它接受有效的持续时间字符串(例如:"5m").如果为空,则获得默认超时。如果为 0 (例如"0m"), 禁用缓存。

7.6.4. Controller 配置

表 7.4. 控制器配置参数
参数名称描述

Controllers

应该启动的控制器列表。如果设置为 none,则不会自动启动任何控制器。默认值为 *,它将启动所有控制器。当使用 * 时,您可以通过在其名称前加上 - 来排除控制器。此时无法识别其他值。

ControllerLeaseTTL

启用控制器选择,指示 master 在控制器启动并在该值定义的秒数内尝试获取租期。将此值设置为非负值会强制 pauseControllers=true。这个值默认为 off(0 或 omitted),控制器选择可以使用 -1 来禁用控制器选择。

PauseControllers

指示 master 不会自动启动控制器,而是等待接收通知到服务器,然后再启动它们。

7.6.5. etcd 配置

表 7.5. etcd 配置参数
参数名称描述

Address

advertised host:port 用于客户端连接到 etcd。

etcdClientInfo

包含有关如何连接到 etcd 的信息。指定 etcd 是否作为嵌入式或非嵌入运行,以及主机。其余的配置由 Ansible 清单处理。例如:

etcdClientInfo:
  ca: ca.crt
  certFile: master.etcd-client.crt
  keyFile: master.etcd-client.key
  urls:
  - https://m1.aos.example.com:4001

etcdConfig

如果存在,etcd 会根据定义的参数启动。例如:

etcdConfig:
  address: master.ose32.example.com:4001
  peerAddress: master.ose32.example.com:7001
  peerServingInfo:
    bindAddress: 0.0.0.0:7001
    certFile: etcd.server.crt
    clientCA: ca.crt
    keyFile: etcd.server.key
  servingInfo:
    bindAddress: 0.0.0.0:4001
    certFile: etcd.server.crt
    clientCA: ca.crt
    keyFile: etcd.server.key
  storageDirectory: /var/lib/origin/openshift.local.etcd

etcdStorageConfig

包含 API 资源如何在 etcd 中存储的信息。这些值只有在 etcd 是集群的后备存储时才相关。

KubernetesStoragePrefix

etcd 中的路径,Kubernetes 资源将在其下作为根(root) 。如果更改,这个值将意味着 etcd 中的现有对象将不再存在。默认值为 kubernetes.io

KubernetesStorageVersion

etcd 中的 Kubernetes 资源应该被序列化为的 API 版本。当从 etcd 读取的集群的所有客户端都有相应的代码才能读取新版本时,这个值不应该为高级。

OpenShiftStoragePrefix

OpenShift Container Platform 资源根到的 etcd 中的路径。如果更改,这个值将意味着 etcd 中的现有对象将不再存在。默认值为 openshift.io

OpenShiftStorageVersion

etcd 中 OS 资源的 API 版本应序列化为。当从 etcd 读取的集群的所有客户端都有相应的代码才能读取新版本时,这个值不应该为高级。

PeerAddress

etcd 的对等点连接的广告 host:port。

PeerServingInfo

描述如何开始为 etcd peer 提供服务。

ServingInfo

描述如何开始服务。例如:

servingInfo:
  bindAddress: 0.0.0.0:8443
  bindNetwork: tcp4
  certFile: master.server.crt
  clientCA: ca.crt
  keyFile: master.server.key
  maxRequestsInFlight: 500
  requestTimeoutSeconds: 3600

StorageDir

etcd 存储目录的路径。

7.6.6. 授权配置

表 7.6. 授予配置参数
参数名称描述

GrantConfig

描述如何处理补贴。

GrantHandlerAuto

自动批准客户端授权请求。

GrantHandlerDeny

自动拒绝客户端授权请求。

GrantHandlerPrompt

提示用户批准新的客户端授权请求。

Method

决定在 OAuth 客户端请求授权时使用的默认策略。只有特定的 OAuth 客户端不提供自己策略,则使用这种方法。有效的授权处理方法有:

  • auto:始终批准授权请求,对受信任的客户端很有用
  • prompt: 提示用户输入授权请求的批准,对第三方客户端很有用
  • deny:始终拒绝授权请求,对黑名单的客户端很有用

7.6.7. 镜像配置

表 7.7. 镜像配置参数
参数名称描述

Format

为系统组件构建的名称格式。

Latest

决定是否将从 registry 中拉取 latest 标签。

7.6.8. 镜像策略配置

表 7.8. 镜像策略配置参数
参数名称描述

DisableScheduledImport

允许禁用镜像的调度后台导入。

MaxImagesBulkImportedPerRepository

控制用户执行 Docker 存储库批量导入时导入的镜像数量。此数字默认为 5,以防止用户意外导入大量镜像。设置 -1 代表没有限制。

MaxScheduledImageImportsPerMinute

每分钟将在后台导入的最大调度镜像流数。默认值为 60。

ScheduledImageImportMinimumIntervalSeconds

针对上游存储库检查调度后台导入的镜像流时可达最少的秒数。默认值为 15 分钟。

AllowedRegistriesForImport

限制普通用户可从中导入镜像的 Docker docker。将此列表设置为您信任包含有效 Docker 镜像且希望应用程序能够从中导入的 registry。有权通过 API 创建镜像或 ImageStreamMappings 的用户不受此策略的影响 - 通常只有管理员或系统集成将具有这些权限。

AdditionalTrustedCA

指定到 PEM 编码文件的文件路径,它列出了在镜像流导入期间应被信任的额外证书颁发机构。此文件需要可以被 API 服务器进程访问。根据集群安装的方式,这可能需要将文件挂载到 API 服务器 pod 中。

InternalRegistryHostname

设置默认内部镜像 registry 的主机名。该值必须采用 hostname[:port] 格式。为实现向后兼容,用户仍然可以使用 OPENSHIFT_DEFAULT_REGISTRY 环境变量,但此设置会覆盖环境变量。当设定此参数时,内部 registry 还需要设置其主机名。如需了解更多详细信息,请参阅设置 registry 主机名

ExternalRegistryHostname

ExternalRegistryHostname 设置默认外部镜像 registry 的主机名。只有在镜像 registry 对外公开时才应设置外部主机名。该值用于 ImageStreams 中的 publicDockerImageRepository 字段。该值必须采用 hostname[:port] 格式。

7.6.9. Kubernetes 的主配置

表 7.9. Kubernetes 主配置参数
参数名称描述

APILevels

应该在启动时启用的 API 级别的列表 v1 作为示例。

DisabledAPIGroupVersions

组映射到应禁用的版本(或 *)的映射。

KubeletClientInfo

包含有关如何连接到 kubelet 的信息。

KubernetesMasterConfig

包含如何连接到 kubelet 的 KubernetesMasterConfig 的信息。如果存在,则使用此流程启动 kubernetes master。

MasterCount

应正在运行的预期 master 数量。这个值默认为 1,可以被设置为正整数,或者设置为 -1,这表示这是集群的一部分。

MasterIP

Kubernetes 资源的公共 IP 地址。如果为空,来自 net.InterfaceAddrs 的第一个结果将被使用。

MasterKubeConfig

描述如何将此节点连接到 master 的 .kubeconfig 文件的文件名。

PodEvictionTimeout

控制删除失败节点上的 pod 的宽限期。它需要有效的持续时间字符串。如果为空,您会收到默认的 pod 驱除超时。默认值为 5m0s

ProxyClientInfo

指定代理到 pod 时使用的客户端证书/密钥。例如:

  proxyClientInfo:
    certFile: master.proxy-client.crt
    keyFile: master.proxy-client.key

ServicesNodePortRange

用于分配主机上服务公共端口的范围。默认 30000-32767。

ServicesSubnet

用于分配服务 IP 的子网。

StaticNodeNames

静态已知的节点列表。

7.6.10. 网络配置

仔细选择以下参数中的 CIDR,因为 IPv4 地址空间由节点的所有用户共享。OpenShift Container Platform 为自己的使用保留 IPv4 地址空间中的 CIDR,并为外部用户和集群间共享的地址保留来自 IPv4 地址空间的 CIDR。

表 7.10. 网络配置参数
参数名称描述

ClusterNetworkCIDR

指定全局覆盖网络的 L3 空间的 CIDR 字符串。这为集群网络的内部使用保留。

externalIPNetworkCIDRs

控制服务外部 IP 字段可接受哪些值。如果为空,则不能设置 externalIP。它可以包含检查访问的 CIDR 列表。如果 CIDR 的前缀为 !,则该 CIDR 中的 IP 将被拒绝。首先应用拒绝,然后针对其中一个允许的 CIDR 检查的 IP。为了安全起见,您必须确保此范围不会与节点、Pod 或服务 CIDR 重叠。

HostSubnetLength

分配给每一主机子网的位数。例如,8 表示主机上的 /24 网络。

ingressIPNetworkCIDR

控制为裸机上的类型为 LoadBalancer 的服务分配入口 IP 的范围。它可以包含从其中分配的一个 CIDR。默认情况下,配置了 172.46.0.0/16。为安全起见,您应该确保此范围与为外部 IP、节点、Pod 或服务保留的 CIDR 重叠。

HostSubnetLength

分配给每一主机子网的位数。例如,8 表示主机上的 /24 网络。

NetworkConfig

传递给 compiled-in-network 的插件。此处的许多选项可以在 Ansible 清单中控制。

  • NetworkPluginName (字符串)
  • ClusterNetworkCIDR (字符串)
  • hostSubnetLength (无符号整数)
  • ServiceNetworkCIDR (字符串)
  • externalIPNetworkCIDRs (字符串数组):控制服务外部 IP 字段可以接受哪些值。如果为空,则不能设置外部 IP。它可以包含检查访问的 CIDR 列表。如果 CIDR 的前缀为 !,则该 CIDR 中的 IP 会拒绝。首先应用拒绝,然后针对其中一个允许的 CIDR 检查 IP。为了安全起见,您应该确保此范围与节点、Pod 或服务 CIDR 不重叠。

例如:

networkConfig:
  clusterNetworks
  - cidr: 10.3.0.0/16
    hostSubnetLength: 8
  networkPluginName: example/openshift-ovs-subnet
# serviceNetworkCIDR must match kubernetesMasterConfig.servicesSubnet
  serviceNetworkCIDR: 179.29.0.0/16

NetworkPluginName

要使用的网络插件的名称。

ServiceNetwork

用于指定服务网络的 CIDR 字符串。

7.6.11. OAuth 身份验证配置

表 7.11. OAuth 配置参数
参数名称描述

AlwaysShowProviderSelection

强制供应商选择页面,即使只有一个提供程序,也要呈现。

AssetPublicURL

用于构建有效客户端重定向 URL 用于外部访问。

Error

一个包含 go 模板的文件路径,用于在身份验证期间呈现错误页面,或授权流(如果没有指定),则会使用默认错误页面。

IdentityProviders

订购用户以识别自身的方式列表。

Login

包含用来呈现登录页面的 go 模板的文件路径。如果未指定,则使用默认登录页面。

MasterCA

用于验证到 MasterURL 的 TLS 连接的 CA。

MasterPublicURL

用于构建有效客户端重定向 URL 用于外部访问。

MasterURL

用于让服务器对服务器调用来交换访问令牌的授权代码。

OAuthConfig

如果存在,/oauth 端点会根据定义的参数启动。例如:

oauthConfig:
  assetPublicURL: https://master.ose32.example.com:8443/console/
  grantConfig:
    method: auto
  identityProviders:
  - challenge: true
    login: true
    mappingMethod: claim
    name: htpasswd_all
    provider:
      apiVersion: v1
      kind: HTPasswdPasswordIdentityProvider
      file: /etc/origin/openshift-passwd
  masterCA: ca.crt
  masterPublicURL: https://master.ose32.example.com:8443
  masterURL: https://master.ose32.example.com:8443
  sessionConfig:
    sessionMaxAgeSeconds: 3600
    sessionName: ssn
    sessionSecretsFile: /etc/origin/master/session-secrets.yaml
  tokenConfig:
    accessTokenMaxAgeSeconds: 86400
    authorizeTokenMaxAgeSeconds: 500

OAuthTemplates

允许自定义登录页面等页面。

ProviderSelection

包含用来呈现提供程序选择页面的 go 模板的文件路径。如果未指定,则使用默认供应商选择页面。

SessionConfig

包含有关配置会话的信息。

Templates

允许您自定义登录页面等页面。

TokenConfig

包含授权和访问令牌的选项。

7.6.12. 项目配置

表 7.12. 项目配置参数
参数名称描述

DefaultNodeSelector

包含默认项目节点选择器。

ProjectConfig

包含有关项目创建和默认值的信息:

  • defaultNodeSelector (字符串):包含默认项目节点选择器。
  • projectRequestMessage (字符串):当用户无法通过 projectrequest API 端点请求一个项目时,向用户显示的字符串。
  • ProjectRequestTemplate (字符串):响应 projectrequest 以创建项目时使用的模板。采用 <namespace>/<template> 格式。它是可选的;如果没有指定,则使用默认模板。
  • SecurityAllocator:控制为项目自动分配 UID 和 MCS 标签。如果为 nil,则禁用分配:

    • mcsAllocatorRange (字符串):定义将分配给命名空间的 MCS 类别范围。格式为 <prefix>/<numberOfLabels>[,<maxCategory>]。默认值为 s0/2,并从 c0 → c1023 分配,这表示总计有 535k 标签。如果此值在启动后改变,新项目可能会接收已经分配给其他项目的标签。前缀可以是任何有效的 SELinux 术语集合(包括 user、role 和 type)。但是,使用默认前缀可让服务器自动设置它们。例如,s0:/2 分配 s0:c0,c0 到 s0:c511,c511 的标签,而 s0:/2,512 会将标签从 s0:c0,c0,c0 分配给 s0:c511,c511,511。
    • mcsLabelsPerProject (整数):定义每个项目要保留的标签数。默认值是 5,用于匹配默认 UID 和 MCS 范围。
    • uidAllocatorRange (字符串):定义自动分配给项目的 Unix 用户 ID(UID),以及每个命名空间获取的块的大小。例如,1000-1999/10 将为每个命名空间分配十个 UID,并能够在用尽空间前分配最多 100 个块。默认值为在 10k 块中分配 10 亿到 20 亿的块,这是用户命名空间启动时为容器镜像的预期范围范围。

ProjectRequestMessage

当用户无法通过项目请求 API 端点来请求项目时向用户显示的字符串。

ProjectRequestTemplate

响应 projectrequest 以创建项目时使用的模板。它采用 namespace/template 格式,它是可选的。如果没有指定,则使用默认模板。

7.6.13. 调度程序配置

表 7.13. 调度程序配置参数
参数名称描述

SchedulerConfigFile

指向描述如何设置调度程序的文件。如果为空,您可以获得默认的调度规则

7.6.14. 安全分配器配置

表 7.14. 安全分配器参数
参数名称描述

MCSAllocatorRange

定义将分配给命名空间的 MCS 类别范围。格式为 <prefix>/<numberOfLabels>[,<maxCategory>]。默认值为 s0/2,并从 c0 到 c1023 分配,这表示有总计 535k 个标签(1024 选择 2 ~ 535k)。如果此值在启动后改变,新项目可能会接收已经分配给其他项目的标签。前缀可以是任何有效的 SELinux 术语集合(包括 user、role 和 type),虽然它们保留为默认值,但允许服务器自动设置它们。

SecurityAllocator

控制为项目自动分配 UID 和 MCS 标签。如果为 nil,则禁用分配。

UIDAllocatorRange

定义会自动分配给项目的 Unix 用户 ID(UID),以及每个命名空间获取的块的大小。例如,1000-1999/10 将根据每个命名空间分配十个 UID,并在用尽空间前分配最多 100 个块。默认值为在 10k 块中分配 10 亿到 20 亿的块(这是在用户命名空间启动后使用范围容器镜像的预期大小)。

7.6.15. 服务帐户配置

表 7.15. 服务帐户配置参数
参数名称描述

LimitSecretReferences

控制是否允许服务帐户在没有显式引用命名空间中引用任何 secret。

ManagedNames

在每个命名空间中创建的服务帐户名称列表。如果没有指定名称,则不会启动 ServiceAccountsController

MasterCA

用于验证 TLS 连接到主主机的 CA。服务帐户控制器会自动将此文件的内容注入到 pod 中,以便它们能够验证与主控机的连接。

PrivateKeyFile

包含 PEM 编码私有 RSA 密钥的文件,用于签署服务帐户令牌。如果没有指定私钥,则不会启动服务帐户 TokensController

PublicKeyFiles

文件列表,各自包含 PEM 编码的公共 RSA 密钥。如果有任何文件包含私钥,则使用密钥的公钥部分。公钥列表用于验证所提供的服务帐户令牌。每个密钥按顺序尝试,直到列表耗尽或验证成功为止。如果没有指定密钥,则不会使用服务帐户身份验证。

ServiceAccountConfig

包含与服务帐户相关的选项:

  • LimitSecretReferences (boolean):控制是否允许服务帐户在没有显式引用命名空间中引用任何 secret。
  • ManagedNames (字符串):在每个命名空间中创建的服务帐户名称列表。如果没有指定名称,则不会启动 ServiceAccountsController
  • MasterCA (字符串):用于验证 TLS 连接到主设备的证书颁发机构。服务帐户控制器会自动将此文件的内容注入到 pod 中,以便它们能够验证与主控机的连接。
  • privateKeyFile (字符串):包含 PEM 编码的私有 RSA 密钥,用于签署服务帐户令牌。如果没有指定私钥,则不会启动服务帐户 TokensController
  • publicKeyFiles (字符串):文件列表,各自包含 PEM 编码的公共 RSA 密钥。如果有任何文件包含私钥,OpenShift Container Platform 将使用密钥的公钥部分。公钥列表用于验证服务帐户令牌 ; 每个密钥按顺序尝试,直到列表耗尽或验证成功为止。如果没有指定密钥,则无法使用服务帐户身份验证。

7.6.16. 服务信息配置

表 7.16. 服务信息配置参数
参数名称描述

AllowRecursiveQueries

允许主服务器上的 DNS 服务器以递归方式应答查询。请注意,打开解析器可用于 DNS 模糊攻击,并且主 DNS 不应该被公共网络访问。

BindAddress

要服务的 ip:port

BindNetwork

控制导入镜像的限值和行为。

CertFile

包含 PEM 编码证书的文件。

CertInfo

用于提供安全流量的 TLS 证书信息。

ClientCA

您识别传入客户端证书的所有签名人的证书捆绑包。

dnsConfig

如果存在,则根据定义的参数启动 DNS 服务器。例如:

dnsConfig:
  bindAddress: 0.0.0.0:8053
  bindNetwork: tcp4

DNSDomain

包含域后缀。

DNSIP

包含 IP。

KeyFile

包含由 CertFile 指定的证书的 PEM 编码私钥的文件。

MasterClientConnectionOverrides

为用于连接 master 的客户端连接提供覆盖。这个参数不被支持。要设置 QPS 和 burst 值,请参阅设置节点 QPS 和 Burst 值

MaxRequestsInFlight

允许到服务器的并发请求数。如果零,则不限制。

NamedCertificates

用于保护到特定主机名请求的证书列表。

RequestTimeoutSecond

请求超时前的秒数。默认值为 60 分钟。如果 -1,请求没有限制。

ServingInfo

资产的 HTTP 服务信息。

7.6.17. 卷配置

表 7.17. 卷配置参数
参数名称描述

DynamicProvisioningEnabled

启用或禁用动态置备的布尔值。默认为 true

FSGroup

为每个 FSGroup 在每个节点上启用 本地存储配额。目前,这仅适用于 emptyDir 卷,如果底层 volumeDirectory 位于 XFS 文件系统中。

MasterVolumeConfig

包含用于在 master 节点上配置卷插件的选项。

NodeVolumeConfig

包含用于在节点上配置卷的选项。

VolumeConfig

包含用于在节点中配置卷插件的选项:

  • DynamicProvisioningEnabled (布尔值):默认值为 true,并在 false 时关闭动态置备。

VolumeDirectory

卷所在的目录。使用 openshift_node_group_data_dir 参数更改此值。

7.6.18. 基本审计

审计提供一组安全相关的按时间排序的记录,记录各个用户、管理员或其他系统组件影响系统的一系列活动。

审计在 API 服务器级别运作,记录所有传入到服务器的请求。每个审计日志包含两个条目:

  1. 请求行中包含:

    1. 用于匹配响应行的唯一 ID(参见 #2)
    2. 请求的源 IP
    3. 被调用的 HTTP 方法
    4. 调用该操作的原始用户
    5. 操作的模拟用户(self 表示自己)
    6. 操作的模拟组(lookup 表示用户的组)
    7. 请求的命名空间或 <none>
    8. 请求的 URI
  2. 响应行中包括:

    1. #1 中的唯一 ID
    2. 响应代码

用户 admin 询问 pod 列表的输出示例:

AUDIT: id="5c3b8227-4af9-4322-8a71-542231c3887b" ip="127.0.0.1" method="GET" user="admin" as="<self>" asgroups="<lookup>" namespace="default" uri="/api/v1/namespaces/default/pods"
AUDIT: id="5c3b8227-4af9-4322-8a71-542231c3887b" response="200"
7.6.18.1. 启用基本审计

以下流程在安装后启用基本审计。

注意

高级审计必须在安装过程中启用。

  1. 编辑所有 master 节点上的 /etc/origin/master/master-config.yaml 文件,如下例所示:

    auditConfig:
      auditFilePath: "/var/log/origin/audit-ocp.log"
      enabled: true
      maximumFileRetentionDays: 14
      maximumFileSizeMegabytes: 500
      maximumRetainedFiles: 15
  2. 重启集群中的 API pod。

    # /usr/local/bin/master-restart api

要在安装过程中启用基本审计,请在清单文件中添加以下变量声明。根据情况调整值。

openshift_master_audit_config={"enabled": true, "auditFilePath": "/var/lib/origin/openpaas-oscp-audit.log", "maximumFileRetentionDays": 14, "maximumFileSizeMegabytes": 500, "maximumRetainedFiles": 5}

审计配置采用以下参数:

表 7.18. Audit 配置参数
参数名称描述

enabled

启用或禁用审计日志的布尔值。默认为 false

auditFilePath

请求应记录到的文件路径。如果没有设置,日志会被输出到 master 日志中。

maximumFileRetentionDays

根据文件名中编码的时间戳,指定用于保留旧审计日志文件的最大天数。

maximumRetainedFiles

指定要保留的旧审计日志文件的最大数量。

maximumFileSizeMegabytes

在轮转日志文件前,指定日志文件的最大大小(以 MB 为单位)。默认值为 100MB。

Audit 配置示例

auditConfig:
  auditFilePath: "/var/log/origin/audit-ocp.log"
  enabled: true
  maximumFileRetentionDays: 14
  maximumFileSizeMegabytes: 500
  maximumRetainedFiles: 15

当您定义 auditFilePath 参数时,如果该目录不存在,则会创建该目录。

7.6.19. 高级审计

高级审计功能对 基本审计功能 进行了一些改进,包括精细的事件过滤和多个输出后端。

要启用高级审计功能,您可以创建一个审计策略文件,并在 openshift_master_audit_configopenshift_master_audit_policyfile 参数中指定以下值:

openshift_master_audit_config={"enabled": true, "auditFilePath": "/var/log/origin/audit-ocp.log", "maximumFileRetentionDays": 14, "maximumFileSizeMegabytes": 500, "maximumRetainedFiles": 5, "policyFile": "/etc/origin/master/adv-audit.yaml", "logFormat":"json"}
openshift_master_audit_policyfile="/<path>/adv-audit.yaml"
重要

您必须在安装集群前创建 adv-audit.yaml 文件,并指定其在集群清单文件中的位置。

下表包含您可以使用的附加选项。

表 7.19. 高级审计配置参数
参数名称描述

policyFile

定义审计策略配置的文件的路径。

policyConfiguration

嵌入式审计策略配置。

logFormat

指定保存的审计日志的格式。允许的值是 legacy (基本审计中使用的格式)和