带安全功能的自定义 Marathon

ENTERPRISE

使用高级非本地 Marathon 实例

本专题描述了如何部署具有独立角色、保留、配额和安全功能的非本地 Marathon 实例 (Marathon on Marathon) 。高级非本地 Marathon 程序只能在您需要 密钥 或细粒度 ACL 时使用。否则,请使用 基本程序.

对于本程序,我们假设您已从支持团队成员获得了 Marathon 的企业版。如果您仍然需要企业工件,则需要首先通过 [Mesosphere 支持门户] 提交故障单。(https://support.mesosphere.com/s/). 企业工件作为 Docker 镜像文件提供,并包含 Marathon 以及 Marathon 插件,可启用 DC/OS Enterprise 功能 - 例如密钥和细分访问权限控制。

前提条件:

此示例中的变量

整个页面将指示您调用命令或执行使用特定于群集的值的操作。我们使用 ${VARIABLE} 表示法引用这些特定于群集的值;请将以下变量替换为您的群集的合适值。

该表包含本页所用的所有变量:

变量 描述
${MESOS_ROLE} 新 Marathon 实例将使用的 Mesos 角色的名称。该名称应该全部小写,并且是有效的 Mesos 角色名称,例如 "marathon_ee".
${SERVICE_ACCOUNT} Marathon 用来和 DC/OS 中的其他服务进行通信的 服务帐户 的名称。名称应仅包含字母、数字、@.\_-. 例如 "marathon_user_ee"
${MARATHON_INSTANCE_NAME} 新 Marathon 实例的服务名称,由根 Marathon 实例启动。这应该是有效的 Marathon 服务名称,例如 "mom_ee".
${SERVICE_ACCOUNT_SECRET} 密钥存储库中的密钥路径,用于保存 Marathon 将使用的私钥以及要在 DC/OS 上进行身份认证的 ${SERVICE_ACCOUNT} 帐户。此名称 不得包含一个领导的 /. 有效示例: "marathon_user_ee_secret"
${DOCKER_REGISTRY_SECRET} 密钥的名称,用于保存从专用注册表中获取 Marathon Docker 镜像的凭据。此名称 不得包含一个领导的 /. 有效示例: "registry_secret".
${PRIVATE_KEY} PEM 格式化私钥文件的路径(在本地文件系统中,不确定是否存在),最好以 .pem 为后缀
${PUBLIC_KEY} PEM 格式化公钥文件的路径(在本地文件系统中,不确定是否存在),最好以 .pem 为后缀
${MARATHON_IMAGE} 专用存储库中的 Marathon 镜像的名称**,例如,private-repo/marathon-dcos-ee
${MARATHON_TAG} 要部署的 Marathon 版本的 Docker 镜像标记。例如,v1.5.11_1.10.2 (0.11.0 或更高版本)。

如果您使用的是 Mac OS 或 Linux 计算机,则可以在终端会话中预先定义上述大多数变量,只需将片段复制并粘贴到终端中即可:

set -a
MESOS_ROLE="..."
SERVICE_ACCOUNT="..."
BEGIN_PORT="..."
END_PORT="..."
MARATHON_INSTANCE_NAME="..."
SERVICE_ACCOUNT_SECRET="..."
DOCKER_REGISTRY_SECRET="..."
PRIVATE_KEY="..."
PUBLIC_KEY="..."
MARATHON_IMAGE="..."
MARATHON_TAG="..."

步骤 1:准备

在以下步骤中,我们假设您已经:

  1. 将 Marathon 企业镜像推送到您的专用注册表(说明),名称为 ${MARATHON_IMAGE}:${MARATHON_TAG}.

  2. 将您的专用 Docker 凭据存储在密钥存储库 (说明)中,名称为 ${DOCKER_REGISTRY_SECRET}.

    警告:密钥的名称应该位于根路径(例如 /some-secret-name)中,或者以应用程序的名称为前缀(例如 /${MARATHON_INSTANCE_NAME}/some-secret-name). 如果不这样做,将使根 Marathon 无法读取密钥值,并且无法启动自定义 Marathon-on-Marathon 实例。

步骤 2:创建 Marathon 服务帐户

本步骤创建了 Marathon 服务账户 Marathon 将使用此帐户对其余 DC/OS 组件进行身份认证。稍后授予此帐户的权限将定义允许 Marathon 执行的操作。

Marathon 服务账户可能是可选或必填项,具体取决于您的 安全模式

安全模式 Marathon 服务帐户
宽容 可选
严格 必填
  1. 创建 2048 位 RSA 公私密钥对 (${PRIVATE_KEY}${PUBLIC_KEY}) 并将值分别保存到当前目录中的单独文件中。

    使用以下命令,我们创建一个公私密钥对。公钥将用于创建 Marathon 服务帐户。我们将私钥存储在 密钥存储库 然后将其传递至 Marathon,供其进行自我授权。

    dcos security org service-accounts keypair ${PRIVATE_KEY} ${PUBLIC_KEY}
    
  2. 使用我们生成的公钥(${SERVICE_ACCOUNT})创建一个名为 ${PUBLIC_KEY}). 的新服务帐户。

    dcos security org service-accounts create -p ${PUBLIC_KEY} -d "Marathon-on-Marathon User" ${SERVICE_ACCOUNT}
    

步骤 3:创建服务帐户密钥

在此步骤中,为 Marathon 服务帐户创建密钥,并存储在密钥存储库中。

创建的密钥 (${SERVICE_ACCOUNT_SECRET}) 将包含私钥 (${PRIVATE_KEY}) 和服务帐户名称 (${SERVICE_ACCOUNT}). Marathon 将使用此信息对 DC/OS 进行身份认证。

宽容

dcos security secrets create-sa-secret ${PRIVATE_KEY} ${SERVICE_ACCOUNT} ${SERVICE_ACCOUNT_SECRET}

严格

dcos security secrets create-sa-secret --strict ${PRIVATE_KEY} ${SERVICE_ACCOUNT} ${SERVICE_ACCOUNT_SECRET}

建议

  • 使用以下命令确保您的密钥已就绪:

    dcos security secrets list /
    
  • 查看您的密钥,确保其包含正确的服务帐户 ID、私钥和 login_endpoint URL。如果是 strict 模式,应为 HTTPS,如果是 permissive 模式,则应为 HTTP。如果 URL 不正确,尝试 升级 DC/OS Enterprise CLI,删除密钥,并重新创建。

    您可以使用此命令查看内容(需要安装 jq 1.5 或更高版本

    dcos security secrets get ${SERVICE_ACCOUNT_SECRET} --json | jq -r .value | jq
    
  • 从文件系统中删除私钥文件,防止不法之徒利用私钥通过 DC/OS 身份认证。

步骤 4:分配权限(仅限严格模式)

在此步骤中,权限被分配至 Marathon-on-Marathon 实例。在严格模式下需要权限,而在其他安全模式将其忽略即可。

安全模式 权限
宽容 不可用
严格 必填

所有 CLI 命令也可通过 [IAM API]执行。(/mesosphere/dcos/cn/1.13/security/ent/iam-api/).

授予服务帐户 ${SERVICE_ACCOUNT} 权限,以启动将作为 Linux 用户 nobody. 执行的 Mesos 任务。

要以不同 Linux 用户的身份执行任务,请将 nobody 替换为该用户的 Linux 用户名。例如,如需以 Linux 用户 bob 身份启动任务,请替换 nobody 为以下的 bob

请注意,nobodyroot 用户是默认出现在所有代理上的;如果指定自定义用户(例如,bob),则用户 bob 需要在可以执行这些任务的每个代理上手动创建(例如,使用 Linux adduser 或类似实用程序)。

dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:task:user:nobody create --description "Tasks can execute as Linux user nobody"
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:framework:role:${MESOS_ROLE} create --description "Controls the ability of ${MESOS_ROLE} to register as a framework with the Mesos master"
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:reservation:role:${MESOS_ROLE} create --description "Controls the ability of ${MESOS_ROLE} to reserve resources"
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:volume:role:${MESOS_ROLE} create --description "Controls the ability of ${MESOS_ROLE} to access volumes"
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:reservation:principal:${SERVICE_ACCOUNT} delete --description "Controls the ability of ${SERVICE_ACCOUNT} to reserve resources"
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:task:app_id:/ create --description "Controls the ability to launch tasks"
dcos security org users grant ${SERVICE_ACCOUNT} dcos:mesos:master:volume:principal:${SERVICE_ACCOUNT} delete --description "Controls the ability of ${SERVICE_ACCOUNT} to access volumes"

步骤 5:安装具有分配角色 的非本地 Marathon 实例

在此步骤中,非本地 Marathon 实例安装在 DC/OS上,并分配了 Mesos 角色。

  1. 创建一个自定义 JSON 配置,用于安装自定义非本机 Marathon 实例。JSON 文件内容因您的 [安全模式]而有所不同。(/mesosphere/dcos/cn/1.13/security/ent/#security-modes).

    确保使用正确的值替换 JSON 文件中的所有 ${VARIABLES}

    或者,如果已在终端会话中导出变量(如 变量部分 中所述),则可以使用以下命令自动将所有替代变量替换为其导出值。所得文件将保存为 marathon-filled.json:

    perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"<missing-variable-$1>")/eg' < marathon.json > marathon-filled.json
    

    宽容

    如果在 permissive 安全模式下运行群集,请使用以下 JSON 模板。不要忘记替换符合 ${VARIABLES} 格式的所有环境变量:

    {
      "id":"/${MARATHON_INSTANCE_NAME}",
      "cmd":"cd $MESOS_SANDBOX && LIBPROCESS_PORT=$PORT1 && /marathon/bin/start --default_accepted_resource_roles \"*,${MESOS_ROLE}\" --enable_features \"vips,task_killing,external_volumes,secrets,gpu_resources\" --framework_name ${MARATHON_INSTANCE_NAME} --hostname $LIBPROCESS_IP --http_port $PORT0 --master zk://master.mesos:2181/mesos --max_instances_per_offer 1 --mesos_leader_ui_url /mesos --mesos_role ${MESOS_ROLE}  --zk zk://master.mesos:2181/universe/${MARATHON_INSTANCE_NAME} --mesos_user nobody --mesos_authentication --mesos_authentication_principal ${SERVICE_ACCOUNT}",
      "user":"nobody",
      "cpus":2,
      "mem":4096,
      "disk":0,
      "instances":1,
      "constraints":[
         [
            "hostname",
            "UNIQUE"
         ]
      ],
      "container":{
         "type": "MESOS",
         "docker":{
            "image":"${MARATHON_IMAGE}:${MARATHON_TAG}",
            "pullConfig": {
                "secret": "docker-registry-credential"
            }
         }
      },
      "env":{
         "JVM_OPTS":"-Xms256m -Xmx2g",
         "DCOS_STRICT_SECURITY_ENABLED":"false",
         "DCOS_SERVICE_ACCOUNT_CREDENTIAL":{
            "secret":"service-credential"
         },
         "MESOS_AUTHENTICATEE":"com_mesosphere_dcos_ClassicRPCAuthenticatee",
         "MESOS_MODULES":"{\"libraries\":[{\"file\":\"/opt/libmesos-bundle/lib/libdcos_security.so\",\"modules\":[{\"name\":\"com_mesosphere_dcos_ClassicRPCAuthenticatee\"}]}]}",
         "MESOS_VERBOSE":"true",
         "GLOG_v":"2",
         "PLUGIN_ACS_URL":"http://master.mesos",
         "PLUGIN_AUTHN_MODE":"dcos/jwt+anonymous",
         "PLUGIN_FRAMEWORK_TYPE":"marathon"
      },
      "healthChecks":[
         {
            "path":"/ping",
            "protocol":"HTTP",
            "portIndex":0,
            "gracePeriodSeconds":1800,
            "intervalSeconds":10,
            "timeoutSeconds":5,
            "maxConsecutiveFailures":3,
            "ignoreHttp1xx":false
         }
      ],
      "secrets":{
         "service-credential":{
            "source":"${SERVICE_ACCOUNT_SECRET}"
         },
         "docker-registry-credential": {
            "source":"${DOCKER_REGISTRY_SECRET}"
         }
      },
      "labels":{
         "DCOS_SERVICE_NAME":"${MARATHON_INSTANCE_NAME}",
         "DCOS_SERVICE_PORT_INDEX":"0",
         "DCOS_SERVICE_SCHEME":"http"
      },
      "portDefinitions":[
         {
            "port":0,
            "name":"http"
         },
         {
            "port":0,
            "name":"libprocess"
         }
      ]
    }
    

    严格

    如果在 strict 安全模式下运行群集,请使用以下 JSON 模板。不要忘记替换符合 ${VARIABLES} 格式的所有环境变量:

    {
      "id":"/${MARATHON_INSTANCE_NAME}",
      "cmd":"cd $MESOS_SANDBOX && LIBPROCESS_PORT=$PORT1 && /marathon/bin/start --default_accepted_resource_roles \"*,${MESOS_ROLE}\" --enable_features \"vips,task_killing,external_volumes,secrets,gpu_resources\" --framework_name ${MARATHON_INSTANCE_NAME} --hostname $LIBPROCESS_IP --http_port $PORT0 --master zk://master.mesos:2181/mesos --max_instances_per_offer 1 --mesos_leader_ui_url /mesos --mesos_role ${MESOS_ROLE}  --zk zk://master.mesos:2181/universe/${MARATHON_INSTANCE_NAME} --mesos_user nobody --mesos_authentication --mesos_authentication_principal ${SERVICE_ACCOUNT}",
      "user":"nobody",
      "cpus":2,
      "mem":4096,
      "disk":0,
      "instances":1,
      "constraints":[
         [
            "hostname",
            "UNIQUE"
         ]
      ],
      "container":{
         "type": "MESOS",
         "docker":{
            "image":"${MARATHON_IMAGE}:${MARATHON_TAG}",
            "pullConfig": {
                "secret": "docker-registry-credential"
            }
         }
      },
      "env":{
         "JVM_OPTS":"-Xms256m -Xmx2g",
         "DCOS_STRICT_SECURITY_ENABLED":"true",
         "DCOS_SERVICE_ACCOUNT_CREDENTIAL":{
            "secret":"service-credential"
         },
         "MESOS_AUTHENTICATEE":"com_mesosphere_dcos_ClassicRPCAuthenticatee",
         "MESOS_MODULES":"{\"libraries\":[{\"file\":\"/opt/libmesos-bundle/lib/libdcos_security.so\",\"modules\":[{\"name\":\"com_mesosphere_dcos_ClassicRPCAuthenticatee\"}]}]}",
         "MESOS_VERBOSE":"true",
         "GLOG_v":"2",
         "PLUGIN_ACS_URL":"https://master.mesos",
         "PLUGIN_AUTHN_MODE":"dcos/jwt",
         "PLUGIN_FRAMEWORK_TYPE":"marathon"
      },
      "healthChecks":[
         {
            "path":"/",
            "protocol":"HTTP",
            "portIndex":0,
            "gracePeriodSeconds":1800,
            "intervalSeconds":10,
            "timeoutSeconds":5,
            "maxConsecutiveFailures":3,
            "ignoreHttp1xx":false
         }
      ],
      "secrets":{
         "service-credential":{
            "source":"${SERVICE_ACCOUNT_SECRET}"
         },
         "docker-registry-credential": {
            "source":"${DOCKER_REGISTRY_SECRET}"
         }
      },
      "labels":{
         "DCOS_SERVICE_NAME":"${MARATHON_INSTANCE_NAME}",
         "DCOS_SERVICE_PORT_INDEX":"0",
         "DCOS_SERVICE_SCHEME":"http"
      },
      "portDefinitions":[
         {
            "port":0,
            "name":"http"
         },
         {
            "port":0,
            "name":"libprocess"
         }
      ]
    }
    
  2. 部署 Marathon 实例,传递您在上一步中创建的 JSON 文件。

    dcos marathon app add marathon-filled.json
    

步骤 6:授予用户对非本地 Marathon 的访问权限

到目前为止,您的新 Marathon 实例只能由 DC/OS 超级用户访问。为了提供对常规用户的访问权限,您需要根据群集安全模式明确授予他们访问权限:

宽容

对于您要授予访问权限的每个 ${USER_ACCOUNT},是否在 permissive 安全模式下运行群集,取决于您要提供的权限类型:

  • 为在新创建的 Marathon 上运行的任何服务(或组)提供完全权限:

    # Access to the new Marathon service under `/service/<name>` URL
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:${MARATHON_INSTANCE_NAME} full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:${MARATHON_INSTANCE_NAME}:services:/ full
    
    # Access to the Mesos tasks and their sandbox
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:mesos full
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:slave full
    
    # (Optionally) Access to the Marathon instance that runs on the root
    # Marathon and can be controlled via the DC/OS UI
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:marathon full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:marathon:services:/${MARATHON_INSTANCE_NAME} full
    
  • 向在新创建的 Marathon 上运行且名为 的个体服务(或组)提供权限:${CHILD_SERVICE_NAME}:

    # Access to the new Marathon service under `/service/<name>` URL
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:${MARATHON_INSTANCE_NAME} full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:${MARATHON_INSTANCE_NAME}:services:/${CHILD_SERVICE_NAME} full
    
    # Access to the Mesos tasks and their sandbox
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:mesos full
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:slave full
    
    # (Optionally) Access to the Marathon instance that runs on the root
    # Marathon and can be controlled via the DC/OS UI
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:marathon full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:marathon:services:/${MARATHON_INSTANCE_NAME} full
    

严格

对于您要授予访问权限的每个 ${USER_ACCOUNT},是否在 strict 安全模式下运行群集,取决于您要提供的权限类型:

  • 为在新创建的 Marathon 上运行的任何服务(或组)提供完全权限:

    # Access to the new Marathon service under `/service/<name>` URL
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:${MARATHON_INSTANCE_NAME} full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:${MARATHON_INSTANCE_NAME}:services:/ full
    
    # Access to the Mesos tasks and their sandbox
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:mesos full
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:slave full
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:executor:app_id:/ read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:framework:role:${MESOS_ROLE} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:sandbox:app_id:/ read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:task:app_id:/ read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:master:executor:app_id:/ read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:master:framework:role:${MESOS_ROLE} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:master:task:app_id:/ read
    
    # (Optionally) Access to the Marathon instance that runs on the root
    # Marathon and can be controlled via the DC/OS UI
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:marathon full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:marathon:services:/${MARATHON_INSTANCE_NAME} full
    
  • 向在新创建的 Marathon 上运行且名为 的个体服务(或组)提供权限:${CHILD_SERVICE_NAME}:

    # Access to the new Marathon service under `/service/<name>` URL
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:${MARATHON_INSTANCE_NAME} full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:${MARATHON_INSTANCE_NAME}:services:/${CHILD_SERVICE_NAME} full
    
    # Access to the Mesos tasks and their sandbox
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:mesos full
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:ops:slave full
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:executor:app_id:/${CHILD_SERVICE_NAME} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:framework:role:${MESOS_ROLE} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:sandbox:app_id:/${CHILD_SERVICE_NAME} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:agent:task:app_id:/${CHILD_SERVICE_NAME} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:master:executor:app_id:/${CHILD_SERVICE_NAME} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:master:framework:role:${MESOS_ROLE} read
    dcos security org users grant ${USER_ACCOUNT} dcos:mesos:master:task:app_id:/${CHILD_SERVICE_NAME} read
    
    # (Optionally) Access to the Marathon instance that runs on the root
    # Marathon and can be controlled via the DC/OS UI
    dcos security org users grant ${USER_ACCOUNT} dcos:adminrouter:service:marathon full
    dcos security org users grant ${USER_ACCOUNT} dcos:service:marathon:marathon:services:/${MARATHON_INSTANCE_NAME} full
    

步骤 7:访问非本地 Marathon 实例

在此步骤中,您以授权用户身份登录非本地 Marathon DC/OS 服务。

  1. 启动非本地 Marathon 接口,位于:http://<master-public-ip>/service/${SERVICE_ACCOUNT}/.

  2. 输入您的用户名和密码,然后单击 登录

    Log in DC/OS

    图 4. 成功了!

    Marathon on Marathon

后续步骤

  • 您可以使用以下命令将 DC/OS CLI 配置为与非本机 Marathon 实例进行交互:

    dcos config set marathon.url \
      $(dcos config show core.dcos_url)/service/${MARATHON_INSTANCE_NAME}
    

    现在,任何未来 dcos marathon ... 命令将瞄准您的新 Marathon 实例。

    要撤消此更改,请使用以下命令:

    dcos config unset marathon.url
    

已知问题

  • 启动 Docker 容器时,用户 nobody 可能没有足够的权限来成功运行。例如,无法作为用户 nginx 启动 nobody Docker 容器,因为 nobody 没有 /var/log 所需的 nginx 的写入权限。

  • 用户 nobody 在不同系统中有不同的 UID(通常默认为 65534)。根据代理的分布情况,您可能需要修改容器镜像以使 UID 匹配!使用用户 时也是如此。bob.

  • 使用自定义用户(例如,bob)时,用户必须存在于代理中,若是使用容器,则必须存在于容器内。

  • 使用新用户(例如,bob)时,请记住授予 Marathon 服务帐户以此用户身份运行任务的权限。