Share via


Überwachen eines Nexus Kubernetes-Clusters

Jeder Nexus Kubernetes-Cluster besteht aus mehreren Layern:

  • Virtuelle Computer (Virtual Machines, VMs)
  • Kubernetes-Layer
  • Anwendungspods

Screenshot of Sample Nexus Kubernetes cluster.

Abbildung: Beispiel eines Nexus Kubernetes-Clusters

Auf einer Instanz werden Nexus Kubernetes-Cluster mit einer optionalen Container Insights Observability-Lösung geliefert. Container Insights erfasst die Protokolle und Metriken von Nexus Kubernetes-Clustern und Workloads. Es liegt allein in Ihrem Ermessen, ob Sie dieses Tool aktivieren oder Ihren eigenen Telemetrie-Stack bereitstellen.

So sieht der Nexus Kubernetes-Cluster mit dem Azure-Überwachungstool aus:

Screenshot of Nexus Kubernetes cluster with Monitoring Tools.

Abbildung: Nexus Kubernetes-Cluster mit Überwachungstools

Onboarding von Erweiterungen mit CLI unter Verwendung von Managed Identity Auth

Dokumentation für den Einstieg in die Azure CLI, wie man sie über mehrere Betriebssysteme hinweg installiert und wie man CLI-Erweiterungen installiert.

Installieren Sie die aktuelle Version der erforderlichen CLI-Erweiterungen.

Überwachen eines Nexus Kubernetes-Clusters – VM-Layer

Diese Anleitung enthält Schritte und Hilfsskripte, um die VMs des Nexus Kubernetes-Clusters über Arc mit Azure zu verbinden und Überwachungsagenten für die Sammlung von Systemprotokollen dieser VMs mit Azure Monitoring Agent zu aktivieren. In der Anleitung finden Sie weitere Einzelheiten zur Einrichtung der Protokolldatenerfassung in einem Log Analytics-Arbeitsbereich.

Die folgenden Ressourcen bieten Ihnen Unterstützung:

  • arc-connect.env: Verwenden Sie diese Vorlagendatei, um Umgebungsvariablen zu erstellen, die von den enthaltenen Skripten benötigt werden.

export SUBSCRIPTION_ID=""
export SERVICE_PRINCIPAL_ID=""
export SERVICE_PRINCIPAL_SECRET=""
export RESOURCE_GROUP=""
export TENANT_ID=""
export LOCATION=""
export INSTALL_AZURE_MONITOR_AGENT="true"
export PROXY_URL=""
export NAMESPACE=""
export AZURE_MONITOR_AGENT_VERSION="1.24.2"
export CONNECTEDMACHINE_AZCLI_VERSION="0.6.0"
  • dcr.sh: Verwenden Sie dieses Skript, um eine Datensammlungsregel (DCR, Data Collection Rule) zur Konfiguration der Syslog-Sammlung zu erstellen.

#!/bin/bash
set -e

SUBSCRIPTION_ID="${SUBSCRIPTION_ID:?SUBSCRIPTION_ID must be set}"
SERVICE_PRINCIPAL_ID="${SERVICE_PRINCIPAL_ID:?SERVICE_PRINCIPAL_ID must be set}"
SERVICE_PRINCIPAL_SECRET="${SERVICE_PRINCIPAL_SECRET:?SERVICE_PRINCIPAL_SECRET must be set}"
RESOURCE_GROUP="${RESOURCE_GROUP:?RESOURCE_GROUP must be set}"
TENANT_ID="${TENANT_ID:?TENANT_ID must be set}"
LOCATION="${LOCATION:?LOCATION must be set}"
LAW_RESOURCE_ID="${LAW_RESOURCE_ID:?LAW_RESOURCE_ID must be set}"
DCR_NAME=${DCR_NAME:-${RESOURCE_GROUP}-syslog-dcr}

az login --service-principal -u "${SERVICE_PRINCIPAL_ID}" -p "${SERVICE_PRINCIPAL_SECRET}" -t "${TENANT_ID}"

az account set -s "${SUBSCRIPTION_ID}"

az extension add --name monitor-control-service

RULEFILE=$(mktemp)
tee "${RULEFILE}" <<EOF
{
  "location": "${LOCATION}",
  "properties": {
    "dataSources": {
      "syslog": [
        {
          "name": "syslog",
          "streams": [
            "Microsoft-Syslog"
          ],
          "facilityNames": [
            "auth",
            "authpriv",
            "cron",
            "daemon",
            "mark",
            "kern",
            "local0",
            "local1",
            "local2",
            "local3",
            "local4",
            "local5",
            "local6",
            "local7",
            "lpr",
            "mail",
            "news",
            "syslog",
            "user",
            "uucp"
          ],
          "logLevels": [
            "Info",
            "Notice",
            "Warning",
            "Error",
            "Critical",
            "Alert",
            "Emergency"
          ]
        }
      ]
    },
    "destinations": {
      "logAnalytics": [
        {
          "workspaceResourceId": "${LAW_RESOURCE_ID}",
          "name": "centralWorkspace"
        }
      ]
    },
    "dataFlows": [
      {
        "streams": [
          "Microsoft-Syslog"
        ],
        "destinations": [
          "centralWorkspace"
        ]
      }
    ]
  }
}

EOF

az monitor data-collection rule create --name "${DCR_NAME}" --resource-group "${RESOURCE_GROUP}" --location "${LOCATION}" --rule-file "${RULEFILE}" -o tsv --query id

rm -rf "${RULEFILE}"
  • assign.sh: Verwenden Sie das Skript, um eine Richtlinie zu erstellen, die die DCR mit allen Arc-fähigen Servern in einer Ressourcengruppe verknüpft.

#!/bin/bash
set -e

SUBSCRIPTION_ID="${SUBSCRIPTION_ID:?SUBSCRIPTION_ID must be set}"
SERVICE_PRINCIPAL_ID="${SERVICE_PRINCIPAL_ID:?SERVICE_PRINCIPAL_ID must be set}"
SERVICE_PRINCIPAL_SECRET="${SERVICE_PRINCIPAL_SECRET:?SERVICE_PRINCIPAL_SECRET must be set}"
RESOURCE_GROUP="${RESOURCE_GROUP:?RESOURCE_GROUP must be set}"
TENANT_ID="${TENANT_ID:?TENANT_ID must be set}"
LOCATION="${LOCATION:?LOCATION must be set}"
DCR_NAME=${DCR_NAME:-${RESOURCE_GROUP}-syslog-dcr}
POLICY_NAME=${POLICY_NAME:-${DCR_NAME}-policy}

az login --service-principal -u "${SERVICE_PRINCIPAL_ID}" -p "${SERVICE_PRINCIPAL_SECRET}" -t "${TENANT_ID}"

az account set -s "${SUBSCRIPTION_ID}"

DCR=$(az monitor data-collection rule show --name "${DCR_NAME}" --resource-group "${RESOURCE_GROUP}" -o tsv --query id)

PRINCIPAL=$(az policy assignment create \
  --name "${POLICY_NAME}" \
  --display-name "${POLICY_NAME}" \
  --resource-group "${RESOURCE_GROUP}" \
  --location "${LOCATION}" \
  --policy "d5c37ce1-5f52-4523-b949-f19bf945b73a" \
  --assign-identity \
  -p "{\"dcrResourceId\":{\"value\":\"${DCR}\"}}" \
  -o tsv --query identity.principalId)

required_roles=$(az policy definition show -n "d5c37ce1-5f52-4523-b949-f19bf945b73a" --query policyRule.then.details.roleDefinitionIds -o tsv)
for roleId in $(echo "$required_roles"); do
  az role assignment create \
    --role "${roleId##*/}" \
    --assignee-object-id "${PRINCIPAL}" \
    --assignee-principal-type "ServicePrincipal" \
    --scope /subscriptions/"$SUBSCRIPTION_ID"/resourceGroups/"$RESOURCE_GROUP"
done
  • install.sh: Installieren Sie den Azure Monitoring Agent auf jeder VM, um Überwachungsdaten von Azure-VMs zu sammeln.
#!/bin/bash
set -e

function create_secret() {
  kubectl apply -f - -n "${NAMESPACE}" <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: naks-vm-telemetry
type: Opaque
stringData:
  SUBSCRIPTION_ID: "${SUBSCRIPTION_ID}"
  SERVICE_PRINCIPAL_ID: "${SERVICE_PRINCIPAL_ID}"
  SERVICE_PRINCIPAL_SECRET: "${SERVICE_PRINCIPAL_SECRET}"
  RESOURCE_GROUP: "${RESOURCE_GROUP}"
  TENANT_ID: "${TENANT_ID}"
  LOCATION: "${LOCATION}"
  PROXY_URL: "${PROXY_URL}"
  INSTALL_AZURE_MONITOR_AGENT: "${INSTALL_AZURE_MONITOR_AGENT}"
  VERSION: "${AZURE_MONITOR_AGENT_VERSION}"
  CONNECTEDMACHINE_AZCLI_VERSION: "${CONNECTEDMACHINE_AZCLI_VERSION}"
EOF
}

function create_daemonset() {
  kubectl apply -f - -n "${NAMESPACE}" <<EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: naks-vm-telemetry
  labels:
    k8s-app: naks-vm-telemetry
spec:
  selector:
    matchLabels:
      name: naks-vm-telemetry
  template:
    metadata:
      labels:
        name: naks-vm-telemetry
    spec:
      hostNetwork: true
      hostPID: true
      containers:
        - name: naks-vm-telemetry
          image: mcr.microsoft.com/oss/mirror/docker.io/library/ubuntu:20.04
          env:
            - name: SUBSCRIPTION_ID
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: SUBSCRIPTION_ID
            - name: SERVICE_PRINCIPAL_ID
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: SERVICE_PRINCIPAL_ID
            - name: SERVICE_PRINCIPAL_SECRET
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: SERVICE_PRINCIPAL_SECRET
            - name: RESOURCE_GROUP
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: RESOURCE_GROUP
            - name: TENANT_ID
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: TENANT_ID
            - name: LOCATION
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: LOCATION
            - name: PROXY_URL
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: PROXY_URL
            - name: INSTALL_AZURE_MONITOR_AGENT
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: INSTALL_AZURE_MONITOR_AGENT
            - name: VERSION
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: VERSION
            - name: CONNECTEDMACHINE_AZCLI_VERSION
              valueFrom:
                secretKeyRef:
                  name: naks-vm-telemetry
                  key: CONNECTEDMACHINE_AZCLI_VERSION
          securityContext:
            privileged: true
          command:
            - /bin/bash
            - -c
            - |
              set -e
              WORKDIR=\$(nsenter -t1 -m -u -n -i mktemp -d)
              trap 'nsenter -t1 -m -u -n -i rm -rf "\${WORKDIR}"; echo "Azure Monitor Configuration Failed"' ERR
              nsenter -t1 -m -u -n -i mkdir -p "\${WORKDIR}"/telemetry

              nsenter -t1 -m -u -n -i tee "\${WORKDIR}"/telemetry/telemetry_common.py > /dev/null <<EOF
              #!/usr/bin/python3
              import json
              import logging
              import os
              import socket
              import subprocess
              import sys

              arc_config_file = "\${WORKDIR}/telemetry/arc-connect.json"


              class AgentryResult:
                  CONNECTED = "Connected"
                  CREATING = "Creating"
                  DISCONNECTED = "Disconnected"
                  FAILED = "Failed"
                  SUCCEEDED = "Succeeded"


              class OnboardingMessage:
                  COMPLETED = "Onboarding completed"
                  STILL_CREATING = "Azure still creating"
                  STILL_TRYING = "Service still trying"


              def get_logger(logger_name):
                  logger = logging.getLogger(logger_name)
                  logger.setLevel(logging.DEBUG)
                  handler = logging.StreamHandler(stream=sys.stdout)
                  format = logging.Formatter(fmt="%(name)s - %(levelname)s - %(message)s")
                  handler.setFormatter(format)
                  logger.addHandler(handler)
                  return logger


              def az_cli_cm_ext_install(logger, config):
                  logger.info("Install az CLI connectedmachine extension")
                  proxy_url = config.get("PROXY_URL")
                  if proxy_url is not None:
                      os.environ["HTTP_PROXY"] = proxy_url
                      os.environ["HTTPS_PROXY"] = proxy_url
                  cm_azcli_version = config.get("CONNECTEDMACHINE_AZCLI_VERSION")
                  logger.info("Install az CLI connectedmachine extension: {cm_azcli_version}")
                  ext_cmd = f'/usr/bin/az extension add --name connectedmachine --version "{cm_azcli_version}" --yes'
                  run_cmd(logger, ext_cmd)


              def get_cm_properties(logger, config):
                  hostname = socket.gethostname()
                  resource_group = config.get("RESOURCE_GROUP")

                  logger.info(f"Getting arc enrollment properties for {hostname}...")

                  az_login(logger, config)

                  property_cmd = f'/usr/bin/az connectedmachine show --machine-name "{hostname}" --resource-group "{resource_group}"'

                  try:
                      raw_property = run_cmd(logger, property_cmd)
                      cm_json = json.loads(raw_property.stdout)
                      provisioning_state = cm_json["provisioningState"]
                      status = cm_json["status"]
                  except:
                      logger.warning("Connectedmachine not yet present")
                      provisioning_state = "NOT_PROVISIONED"
                      status = "NOT_CONNECTED"
                  finally:
                      az_logout(logger)

                  logger.info(
                      f'Connected machine "{hostname}" provisioningState is "{provisioning_state}" and status is "{status}"'
                  )

                  return provisioning_state, status


              def get_cm_extension_state(logger, config, extension_name):
                  resource_group = config.get("RESOURCE_GROUP")
                  hostname = socket.gethostname()

                  logger.info(f"Getting {extension_name} state for {hostname}...")

                  az_login(logger, config)

                  state_cmd = f'/usr/bin/az connectedmachine extension show --name "{extension_name}" --machine-name "{hostname}" --resource-group "{resource_group}"'

                  try:
                      raw_state = run_cmd(logger, state_cmd)
                      cme_json = json.loads(raw_state.stdout)
                      provisioning_state = cme_json["provisioningState"]
                  except:
                      logger.warning("Connectedmachine extension not yet present")
                      provisioning_state = "NOT_PROVISIONED"
                  finally:
                      az_logout(logger)

                  logger.info(
                      f'Connected machine "{hostname}" extenstion "{extension_name}" provisioningState is "{provisioning_state}"'
                  )

                  return provisioning_state


              def run_cmd(logger, cmd, check_result=True, echo_output=True):
                  res = subprocess.run(
                      cmd,
                      shell=True,
                      stdout=subprocess.PIPE,
                      stderr=subprocess.PIPE,
                      universal_newlines=True,
                  )

                  if res.stdout:
                      if echo_output:
                          logger.info(f"[OUT] {res.stdout}")

                  if res.stderr:
                      if echo_output:
                          logger.info(f"[ERR] {res.stderr}")

                  if check_result:
                      res.check_returncode()

                  return res  # can parse out res.stdout and res.returncode


              def az_login(logger, config):
                  logger.info("Login to Azure account...")
                  proxy_url = config.get("PROXY_URL")
                  if proxy_url is not None:
                      os.environ["HTTP_PROXY"] = proxy_url
                      os.environ["HTTPS_PROXY"] = proxy_url

                  service_principal_id = config.get("SERVICE_PRINCIPAL_ID")
                  service_principal_secret = config.get("SERVICE_PRINCIPAL_SECRET")
                  tenant_id = config.get("TENANT_ID")
                  subscription_id = config.get("SUBSCRIPTION_ID")
                  cmd = f'/usr/bin/az login --service-principal --username "{service_principal_id}" --password "{service_principal_secret}" --tenant "{tenant_id}"'
                  run_cmd(logger, cmd)
                  logger.info(f"Set Subscription...{subscription_id}")
                  set_sub = f'/usr/bin/az account set --subscription "{subscription_id}"'
                  run_cmd(logger, set_sub)


              def az_logout(logger):
                  logger.info("Logout of Azure account...")
                  run_cmd(logger, "/usr/bin/az logout --verbose", check_result=False)

              EOF

              nsenter -t1 -m -u -n -i tee "\${WORKDIR}"/telemetry/setup_azure_monitor_agent.py > /dev/null <<EOF
              #!/usr/bin/python3
              import json
              import os
              import socket
              import time

              import telemetry_common


              def run_install(logger, ama_config):
                  logger.info("Install Azure Monitor agent...")
                  resource_group = ama_config.get("RESOURCE_GROUP")
                  location = ama_config.get("LOCATION")
                  proxy_url = ama_config.get("PROXY_URL")
                  hostname = socket.gethostname()
                  if proxy_url is not None:
                      os.environ["HTTP_PROXY"] = proxy_url
                      os.environ["HTTPS_PROXY"] = proxy_url
                      settings = (
                          '{"proxy":{"mode":"application","address":"'
                          + proxy_url
                          + '","auth": "false"}}'
                      )
                      cmd = f'/usr/bin/az connectedmachine extension create --no-wait --name "AzureMonitorLinuxAgent" --publisher "Microsoft.Azure.Monitor" --type "AzureMonitorLinuxAgent" --machine-name "{hostname}" --resource-group "{resource_group}" --location "{location}" --verbose --settings \'{settings}\''
                  else:
                      cmd = f'/usr/bin/az connectedmachine extension create --no-wait --name "AzureMonitorLinuxAgent" --publisher "Microsoft.Azure.Monitor" --type "AzureMonitorLinuxAgent" --machine-name "{hostname}" --resource-group "{resource_group}" --location "{location}" --verbose'

                  version = ama_config.get("VERSION")
                  if version is not None:
                      cmd += f' --type-handler-version "{version}"'

                  logger.info("Installing Azure Monitor agent...")
                  telemetry_common.az_login(logger, ama_config)

                  try:
                      telemetry_common.run_cmd(logger, cmd)
                  except:
                      logger.info("Trying to install Azure Monitor agent...")
                  finally:
                      telemetry_common.az_logout(logger)


              def run_uninstall(logger, ama_config):
                  logger.info("Uninstall Azure Monitor agent...")
                  resource_group = ama_config.get("RESOURCE_GROUP")
                  hostname = socket.gethostname()
                  cmd = f'/usr/bin/az connectedmachine extension delete --name "AzureMonitorLinuxAgent" --machine-name "{hostname}" --resource-group "{resource_group}" --yes --verbose'

                  telemetry_common.az_login(logger, ama_config)
                  logger.info("Uninstalling Azure Monitor agent...")

                  try:
                      telemetry_common.run_cmd(logger, cmd)
                  except:
                      print("Trying to uninstall Azure Monitor agent...")
                  finally:
                      telemetry_common.az_logout(logger)


              def ama_installation(logger, ama_config):
                  logger.info("Executing AMA extenstion installation...")
                  telemetry_common.az_cli_cm_ext_install(logger, ama_config)

                  # Get connected machine properties
                  cm_provisioning_state, cm_status = telemetry_common.get_cm_properties(
                    logger, ama_config
                  )

                  if (
                    cm_provisioning_state == telemetry_common.AgentryResult.SUCCEEDED
                    and cm_status == telemetry_common.AgentryResult.CONNECTED
                  ):
                    # Get AzureMonitorLinuxAgent extension status
                    ext_provisioning_state = telemetry_common.get_cm_extension_state(
                      logger, ama_config, "AzureMonitorLinuxAgent"
                    )
  
                    if ext_provisioning_state == telemetry_common.AgentryResult.SUCCEEDED:
                      logger.info(telemetry_common.OnboardingMessage.COMPLETED)
                      return True
                    elif ext_provisioning_state == telemetry_common.AgentryResult.FAILED:
                      run_uninstall(logger, ama_config)
                      logger.warning(telemetry_common.OnboardingMessage.STILL_TRYING)
                      return False
                    elif ext_provisioning_state == telemetry_common.AgentryResult.CREATING:
                      logger.warning(telemetry_common.OnboardingMessage.STILL_CREATING)
                      return False
                    else:
                      run_install(logger, ama_config)
                      logger.warning(telemetry_common.OnboardingMessage.STILL_TRYING)
                      return False
                  else:
                    logger.error("Server not arc enrolled, enroll the server and retry")
                    return False


              def main():
                  timeout = 60  # TODO: increase when executed via systemd unit
                  start_time = time.time()
                  end_time = start_time + timeout

                  config_file = telemetry_common.arc_config_file

                  logger = telemetry_common.get_logger(__name__)

                  logger.info("Running setup_azure_monitor_agent.py...")

                  if config_file is None:
                      raise Exception("config file is expected")

                  ama_config = {}

                  with open(config_file, "r") as file:
                      ama_config = json.load(file)

                  ama_installed = False

                  while time.time() < end_time:
                      logger.info("Installing AMA extension...")
                      try:
                          ama_installed = ama_installation(logger, ama_config)
                      except Exception as e:
                          logger.error(f"Could not install AMA extension: {e}")
                      if ama_installed:
                          break
                      logger.info("Sleeping 30s...")  # retry for Azure info
                      time.sleep(30)


              if __name__ == "__main__":
                  main()

              EOF


              nsenter -t1 -m -u -n -i tee "\${WORKDIR}"/arc-connect.sh > /dev/null <<EOF
              #!/bin/bash
              set -e

              echo "{\"VERSION\": \"\${VERSION}\", \"SUBSCRIPTION_ID\": \"\${SUBSCRIPTION_ID}\", \"SERVICE_PRINCIPAL_ID\": \"\${SERVICE_PRINCIPAL_ID}\", \"SERVICE_PRINCIPAL_SECRET\": \"\${SERVICE_PRINCIPAL_SECRET}\", \"RESOURCE_GROUP\": \"\${RESOURCE_GROUP}\", \"TENANT_ID\": \"\${TENANT_ID}\", \"LOCATION\": \"\${LOCATION}\", \"PROXY_URL\": \"\${PROXY_URL}\", \"CONNECTEDMACHINE_AZCLI_VERSION\": \"\${CONNECTEDMACHINE_AZCLI_VERSION}\"}" > "\${WORKDIR}"/telemetry/arc-connect.json

              if [ "\${INSTALL_AZURE_MONITOR_AGENT}" = "true" ]; then
                echo "Installing Azure Monitor agent..."
                /usr/bin/python3 "\${WORKDIR}"/telemetry/setup_azure_monitor_agent.py > "\${WORKDIR}"/setup_azure_monitor_agent.out
                cat "\${WORKDIR}"/setup_azure_monitor_agent.out
                if grep "Could not install AMA extension" "\${WORKDIR}"/setup_azure_monitor_agent.out > /dev/null; then
                  exit 1
                fi
              fi
              EOF

              nsenter -t1 -m -u -n -i sh "\${WORKDIR}"/arc-connect.sh
              nsenter -t1 -m -u -n -i rm -rf "\${WORKDIR}"
              echo "Server monitoring configured successfully"
              tail -f /dev/null
          livenessProbe:
            initialDelaySeconds: 600
            periodSeconds: 60
            timeoutSeconds: 30
            exec:
              command:
                - /bin/bash
                - -c
                - |
                  set -e
                  WORKDIR=\$(nsenter -t1 -m -u -n -i mktemp -d)
                  trap 'nsenter -t1 -m -u -n -i rm -rf "\${WORKDIR}"' ERR EXIT
                  nsenter -t1 -m -u -n -i tee "\${WORKDIR}"/liveness.sh > /dev/null <<EOF
                  #!/bin/bash
                  set -e

                  # Check AMA processes
                  ps -ef | grep "\\\s/opt/microsoft/azuremonitoragent/bin/agentlauncher\\\s"
                  ps -ef | grep "\\\s/opt/microsoft/azuremonitoragent/bin/mdsd\\\s"
                  ps -ef | grep "\\\s/opt/microsoft/azuremonitoragent/bin/amacoreagent\\\s"

                  # Check Arc server agent is Connected
                  AGENTSTATUS="\\\$(azcmagent show -j)"
                  if [[ \\\$(echo "\\\${AGENTSTATUS}" | jq -r .status) != "Connected" ]]; then
                    echo "azcmagent is not connected"
                    echo "\\\${AGENTSTATUS}"
                    exit 1
                  fi

                  # Verify dependent services are running
                  while IFS= read -r status; do
                    if [[ "\\\${status}" != "active" ]]; then
                      echo "one or more azcmagent services not active"
                      echo "\\\${AGENTSTATUS}"
                      exit 1
                    fi
                  done < <(jq -r '.services[] | (.status)' <<<\\\${AGENTSTATUS})

                  # Run connectivity tests
                  RESULT="\\\$(azcmagent check -j)"
                  while IFS= read -r reachable; do
                    if [[ ! \\\${reachable} ]]; then
                      echo "one or more connectivity tests failed"
                      echo "\\\${RESULT}"
                      exit 1
                    fi
                  done < <(jq -r '.[] | (.reachable)' <<<\\\${RESULT})

                  EOF

                  nsenter -t1 -m -u -n -i sh "\${WORKDIR}"/liveness.sh
                  nsenter -t1 -m -u -n -i rm -rf "\${WORKDIR}"
                  echo "Liveness check succeeded"

      tolerations:
        - operator: "Exists"
          effect: "NoSchedule"

EOF
}

SUBSCRIPTION_ID="${SUBSCRIPTION_ID:?SUBSCRIPTION_ID must be set}"
SERVICE_PRINCIPAL_ID="${SERVICE_PRINCIPAL_ID:?SERVICE_PRINCIPAL_ID must be set}"
SERVICE_PRINCIPAL_SECRET="${SERVICE_PRINCIPAL_SECRET:?SERVICE_PRINCIPAL_SECRET must be set}"
RESOURCE_GROUP="${RESOURCE_GROUP:?RESOURCE_GROUP must be set}"
TENANT_ID="${TENANT_ID:?TENANT_ID must be set}"
LOCATION="${LOCATION:?LOCATION must be set}"
PROXY_URL="${PROXY_URL:?PROXY_URL must be set}"
INSTALL_AZURE_MONITOR_AGENT="${INSTALL_AZURE_MONITOR_AGENT:?INSTALL_AZURE_MONITOR_AGENT must be true/false}"
NAMESPACE="${NAMESPACE:?NAMESPACE must be set}"
AZURE_MONITOR_AGENT_VERSION="${AZURE_MONITOR_AGENT_VERSION:-"1.24.2"}"
CONNECTEDMACHINE_AZCLI_VERSION="${CONNECTEDMACHINE_AZCLI_VERSION:-"0.6.0"}"

create_secret
create_daemonset

Voraussetzungen – VM

  • Cluster-Administrator-Zugriff auf den Nexus Kubernetes-Cluster.

  • Um Azure Arc-fähige Server zu verwenden, registrieren Sie die folgenden Azure-Ressourcenanbieter in Ihrem Abonnement:

    • Microsoft.HybridCompute
    • Microsoft.GuestConfiguration
    • Microsoft.HybridConnectivity

Registrieren Sie diese Ressourcenanbieter, falls dies noch nicht geschehen ist:

az account set --subscription "{the Subscription Name}"
az provider register --namespace 'Microsoft.HybridCompute'
az provider register --namespace 'Microsoft.GuestConfiguration'
az provider register --namespace 'Microsoft.HybridConnectivity'
  • Weisen Sie ein Azure Dienstprinzipal je nach Bedarf den folgenden integrierten Azure-Rollen zu. Weisen Sie das Dienstprinzipal der Azure-Ressourcengruppe zu, zu der die zu verbindenden Computer gehören:
Role Erforderlich für
Ressourcenadmin für Azure Connected Machine oder Mitwirkende Verbinden Sie den Arc-fähigen Nexus Kubernetes-Cluster-VM-Server mit der Ressourcengruppe und installieren Sie den Azure Monitoring Agent (AMA)
Überwachende Mitwirkende oder Mitwirkende Erstellen Sie eine Datensammlungsregel (DCR) in der Ressourcengruppe und ordnen Sie ihr Arc-aktivierte Server zu.
Benutzerzugriffsadmin und Ressourcenrichtlinien-Mitwirkende oder Mitwirkende Erforderlich, wenn Sie Azure-Richtlinienzuweisung(en) verwenden möchten, um sicherzustellen, dass eine DCR mit Arc-fähigen Computern verbunden ist
Mitwirkender für Kubernetes-Erweiterungen Erforderlich für die Bereitstellung der K8s-Erweiterung für Container Insights

Einrichten der Umgebung

Kopieren sie die enthaltenen Skripte, und führen Sie sie aus. Sie können sie über Azure Cloud Shell im Azure-Portal ausführen. Oder Sie können sie über eine Linux-Kommandozeile ausführen, auf der das Kubernetes-Kommandozeilentool (kubectl) und Azure CLI installiert sind.

Definieren Sie vor dem Ausführen der enthaltenen Skripte die folgenden Umgebungsvariablen:

Umgebungsvariable Beschreibung
SUBSCRIPTION_ID Die ID des Azure-Abonnements, das die Ressourcengruppe enthält
RESOURCE_GROUP Der Name der Ressourcengruppe, in der Arc-fähige Server und zugehörige Ressourcen erstellt werden
LOCATION Die Azure-Region, in der die Arc-fähigen Server und die zugehörigen Ressourcen erstellt werden
SERVICE_PRINCIPAL_ID Die appId des Azure-Dienstprinzipals mit entsprechender(n) Rollenzuweisung(en)
SERVICE_PRINCIPAL_SECRET Das Kennwort zur Authentifizierung für den Dienstprinzipal von Azure
TENANT_ID Die ID des Mandantenverzeichnisses, in dem der Dienstprinzipal existiert
PROXY_URL Die Proxy-URL, die für die Verbindung zu Azure-Diensten verwendet wird
NAMESPACE Der Namespace, in dem die Kubernetes-Artefakte erstellt werden

Der Einfachheit halber können Sie die Vorlagendatei arc-connect.env, ändern, um die Werte der Umgebungsvariablen festzulegen.

# Apply the modified values to the environment
 ./arc-connect.env

Hinzufügen einer Datensammlungsregel (DCR)

Verbinden Sie die Arc-fähigen Server mit einem DCR, um die Sammlung von Protokolldaten in einem Log Analytics-Arbeitsbereich zu ermöglichen. Sie können die DCR über das Azure-Portal oder die CLI erstellen. Informationen zur Erstellung eines DCR, um Daten von den VMs zu sammeln, finden Sie hier.

Das enthaltene dcr.sh-Skript erstellt eine DCR in der angegebenen Ressourcengruppe, die die Protokollsammlung konfiguriert.

  1. Stellen Sie sicher, dass die Umgebung und die Rollenvoraussetzungen für den Dienstprinzipal richtig eingerichtet sind. Die DCR wird in der angegebenen Ressourcengruppe erstellt.

  2. Erstellen oder identifizieren Sie einen Log Analytics-Arbeitsbereich für die Aufnahme von Protokolldaten gemäß der DCR. Legen Sie die Umgebungsvariable LAW_RESOURCE_ID auf ihre Ressourcen-ID fest. Rufen Sie die Ressourcen-ID für einen bekannten Log Analytics-Arbeitsbereichsnamen ab:

export LAW_RESOURCE_ID=$(az monitor log-analytics workspace show -g "${RESOURCE_GROUP}" -n <law name> --query id -o tsv)
  1. Führen Sie das dcr.sh-Skript aus. Er erstellt eine DCR in der angegebenen Ressourcengruppe mit dem Namen ${RESOURCE_GROUP}-syslog-dcr
./dcr.sh

Betrachten/verwalten Sie die DCR über das Azure-Portal oder die CLI. Die Linux Syslog-Protokollebene ist standardmäßig auf „INFO“ eingestellt. Sie können die Protokollstufe nach Bedarf ändern.

Hinweis

Verknüpfen Sie manuell oder über eine Richtlinie Server, die vor der Erstellung des DCRs erstellt wurden. Weitere Informationen finden Sie unter Wartungstask.

Zuordnen von Arc-fähigen Serverressourcen mit der DCR

Verknüpfen Sie die Arc-aktivierten Server-Ressourcen mit der erstellten DCR, damit die Protokolle in den Log Analytics-Arbeitsbereich fließen können. Es gibt Optionen für die Verknüpfung von Servern mit DCRs.

Verwenden Sie das Azure-Portal oder die CLI, um ausgewählte Arc-aktivierte Server mit DCR zu verknüpfen.

Fügen Sie im Azure-Portal über den Abschnitt Ressourcen eine Arc-fähige Serverressource zur DCR hinzu.

Unter diesem Link finden Sie Informationen über die Verknüpfung der Ressourcen über die Azure CLI.

Verwenden Sie Azure-Richtlinien zur Verwaltung von DCR-Zuordnungen

Weisen Sie der Ressourcengruppe eine Richtlinie zu, um die Zuordnung zu erzwingen. Es gibt eine integrierte Richtliniendefinition, um Linux Arc Machines mit einer DCR zu verknüpfen. Weisen Sie die Richtlinie der Ressourcengruppe mit der DCR als Parameter zu. Dadurch wird sichergestellt, dass alle Arc-fähigen Server innerhalb der Ressourcengruppe derselben DCR zugeordnet werden.

Wählen Sie im Azure-Portal die Schaltfläche Assign auf der Seite für die Richtliniendefinition aus.

Der Einfachheit halber weist das bereitgestellte assign.sh-Skript die integrierte Richtlinie der angegebenen Ressourcengruppe und der mit dem dcr.sh-Skript erstellten DCR zu.

  1. Sorgen Sie für eine ordnungsgemäße Einrichtung der Umgebung und der Rollenvoraussetzungen für den Dienstprinzipal, um Richtlinien- und Rollenzuweisungen vorzunehmen.
  2. Erstellen Sie die DCR in der Ressourcengruppe mithilfe des dcr.sh-Skripts, wie im Abschnitt Hinzufügen einer Datensammlungsregel beschrieben.
  3. Führen Sie das Skript assign.sh aus. Sie erstellt die Richtlinienzuweisung und die erforderlichen Rollenzuweisungen.
./assign.sh

Installieren des Azure Monitor-Agents

Verwenden Sie das mitgelieferte install.sh, das ein Kubernetes-DaemonSet auf dem Nexus Kubernetes-Cluster erstellt. Er stellt auf jedem Clusterknoten einen Pod bereit und installiert den Azure Monitoring Agent (AMA). daemonSet enthält auch einen Livetest, der die Serververbindung und die AMA-Prozesse überwacht.

Hinweis

Um den Azure Monitoring Agent zu installieren, müssen Sie zunächst die Nexus Kubernetes-Cluster-VMs mit Arc verbinden. Dieser Vorgang ist automatisiert, wenn Sie das neueste Versionspaket verwenden. Wenn das von Ihnen verwendete Versionspaket die Cluster-VM-Arc-Registrierung jedoch nicht standardmäßig unterstützt, müssen Sie Ihr Cluster auf das neueste Versionspaket aktualisieren. Weitere Informationen über das Versionspaket finden Sie unter Unterstützte Versionen für Nexus Kubernetes Cluster.

  1. Legen Sie die Umgebung wie in Umgebungseinrichtung angegeben fest. Legen Sie den aktuellen kubeconfig-Kontext für die Cluster-VMs von Nexus Kubernetes fest.
  2. Erlauben Sie Kubectl Zugriff auf den Nexus Kubernetes-Cluster.

    Hinweis

    Wenn Sie einen Nexus Kubernetes-Cluster erstellen, erstellt Nexus automatisch eine verwaltete Ressourcengruppe, die zum Speichern der Clusterressourcen bestimmt ist. Innerhalb dieser Gruppe wird die mit Arc verbundene Clusterressource eingerichtet.

    Um auf Ihren Cluster zuzugreifen, müssen Sie die Clusterverbindung kubeconfig festlegen. Nachdem Sie sich mit der entsprechenden Microsoft Entra-Entität bei Azure CLI angemeldet haben, können Sie die kubeconfig abrufen, die notwendig ist, um von überall aus mit dem Cluster zu kommunizieren, sogar außerhalb der Firewall, die ihn umgibt.
    1. Legen Sie die Variablen CLUSTER_NAME, RESOURCE_GROUP und SUBSCRIPTION_ID fest.

      CLUSTER_NAME="myNexusK8sCluster"
      RESOURCE_GROUP="myResourceGroup"
      SUBSCRIPTION_ID=<set the correct subscription_id>
      
    2. Abfragen einer verwalteten Ressourcengruppe mit az und Speichern in MANAGED_RESOURCE_GROUP

       az account set -s $SUBSCRIPTION_ID
       MANAGED_RESOURCE_GROUP=$(az networkcloud kubernetescluster show -n $CLUSTER_NAME -g $RESOURCE_GROUP --output tsv --query managedResourceGroupConfiguration.name)
      
    3. Der folgende Befehl startet einen connectedk8s-Proxy, mit dem Sie mit dem Kubernetes-API-Server für den angegebenen Nexus Kubernetes-Cluster eine Verbindung herstellen können.

      az connectedk8s proxy -n $CLUSTER_NAME  -g $MANAGED_RESOURCE_GROUP &
      
    4. Verwenden Sie kubectl, um Anforderungen an den Cluster zu senden:

      kubectl get pods -A
      

      Sie sollten jetzt eine Antwort des Clusters sehen, die die Liste aller Knoten enthält.

    Hinweis

    Wenn Sie die Fehlermeldung „Zugriffstoken konnte nicht für den Client proxyFailed veröffentlicht werden, um eine Verbindung mit MSI herzustellen“ sehen, müssen Sie möglicherweise ein az login durchführen, um sich erneut bei Azure zu authentifizieren.

  3. Führen Sie das install.sh-Skript über die Eingabeaufforderung mit Kubectl-Zugriff auf den Nexus Kubernetes-Cluster aus.

Das Skript stellt die daemonSet für den Cluster bereit. Überwachen Sie den Fortschritts wie folgt:

# Run the install script and observe results
./install.sh
kubectl get pod --selector='name=naks-vm-telemetry'
kubectl logs <podname>

Nach Abschluss protokolliert das System die Meldung „Serverüberwachung wurde erfolgreich konfiguriert“.

Hinweis

Ordnen Sie diese verbundenen Server der DCR zu. Nachdem Sie eine Richtlinie konfiguriert haben, kann es zu einer gewissen Verzögerung kommen, bis Sie die Protokolle im Azure Log Analytics-Arbeitsbereich sehen

Überwachen eines Nexus Kubernetes-Clusters – K8s-Layer

Anforderungen an Kubernetes

Es gibt bestimmte Voraussetzungen, die der Operator sicherstellen sollte, um die Überwachungstools auf Nexus Kubernetes Clustern zu konfigurieren.

Container Insights speichert Daten in einem Log Analytics-Arbeitsbereich. Die Protokolldaten fließen in den Arbeitsbereich, dessen Ressourcen-ID Sie während der ersten Skripte im Abschnitt „Hinzufügen einer Datensammlungsregel (DCR)“ angegeben haben. Andernfalls fließen die Daten in einen Standard-Arbeitsbereich in der Ressourcengruppe, die mit Ihrem Abonnement verbunden ist (je nach Azure-Standort).

Ein Beispiel für USA, Osten kann wie folgt aussehen:

  • Name des Log Analytics-Arbeitsbereichs: DefaultWorkspace-<GUID>-EUS
  • Name der Ressourcengruppe: DefaultResourceGroup-EUS

Verwenden Sie den folgenden Befehl, um die bereits existierende Ressourcen-ID Ihres Log Analytics-Arbeitsbereichs zu ermitteln:

az login

az account set --subscription "<Subscription Name or ID the Log Analytics workspace is in>"

az monitor log-analytics workspace show --workspace-name "<Log Analytics workspace Name>" \
  --resource-group "<Log Analytics workspace Resource Group>" \
  -o tsv --query id

Für die Bereitstellung von Container Insights und die Anzeige von Daten im entsprechenden Log Analytics-Arbeitsbereich sind bestimmte Rollenzuweisungen in Ihrem Konto erforderlich. Zum Beispiel die Rollenzuweisung „Mitwirkende“. Lesen Sie die Anweisungen zum Zuweisen der erforderlichen Rollen:

  • Log Analytics-Mitwirkende-Rolle: erforderliche Berechtigungen zum Aktivieren der Containerüberwachung auf einem CNF-Cluster (bereitgestellt).
  • Log Analytics-Lesen Rolle: Nichtmitglieder der Rolle „Log Analytics-Mitwirkende“, erhalten Berechtigungen zum Anzeigen von Daten im Log Analytics-Arbeitsbereich, sobald Sie die Containerüberwachung aktiviert haben.

Installieren der Clustererweiterung

Melden Sie sich bei der Azure Cloud Shell an, um auf den Cluster zuzugreifen:

az login

az account set --subscription "<Subscription Name or ID the Provisioned Cluster is in>"

Stellen Sie nun die Container Insights-Erweiterung auf einem bereitgestellten Nexus Kubernetes-Cluster mit einem der beiden folgenden Befehle bereit:

Mit einem kundenseitig erstellten Log Analytics-Arbeitsbereich

az k8s-extension create --name azuremonitor-containers \
  --cluster-name "<Nexus Kubernetes cluster Name>" \
  --resource-group "<Nexus Kubernetes cluster Resource Group>" \
  --cluster-type connectedClusters \
  --extension-type Microsoft.AzureMonitor.Containers \
  --release-train preview \
  --configuration-settings logAnalyticsWorkspaceResourceID="<Log Analytics workspace Resource ID>" \
  amalogsagent.useAADAuth=true

Verwenden eines Log Analytics-Standardarbeitsbereichs

az k8s-extension create --name azuremonitor-containers \
  --cluster-name "<Nexus Kubernetes cluster Name>" \
  --resource-group "<Nexus Kubernetes cluster Resource Group>" \
  --cluster-type connectedClusters \
  --extension-type Microsoft.AzureMonitor.Containers \
  --release-train preview \
  --configuration-settings amalogsagent.useAADAuth=true

Überprüfen von Clustererweiterungen

Überprüfen Sie die erfolgreiche Bereitstellung der Aktivierung von Überwachungsagenten auf Nexus Kubernetes Clustern mit dem folgenden Befehl:

az k8s-extension show --name azuremonitor-containers \
  --cluster-name "<Nexus Kubernetes cluster Name>" \
  --resource-group "<Nexus Kubernetes cluster Resource Group>" \
  --cluster-type connectedClusters

Suchen Sie nach dem Bereitstellungsstatus „Erfolgreich“ für die Erweiterung. Der Befehl „k8s-extension create“ hat möglicherweise den Status auch zurückgegeben.

Anpassen von Protokoll- und Metriksammlung

Container Insights bietet Funktionen zur Feinabstimmung der Sammlung von Protokollen und Metriken von Nexus Kubernetes Clustern--Konfigurieren der Datensammlung des Container Insights Agents.

Weitere Ressourcen