Monitorowanie klastra Nexus Kubernetes

Każdy klaster Kubernetes Nexus składa się z wielu warstw:

  • Virtual Machines
  • Warstwa kubernetes
  • Zasobniki aplikacji

Screenshot of Sample Nexus Kubernetes cluster.

Rysunek: Przykładowy klaster Kubernetes Nexus

W wystąpieniu klastry Nexus Kubernetes są dostarczane z opcjonalnymrozwiązaniem kontenera Szczegółowe informacje obserwacji. Kontener Szczegółowe informacje przechwytuje dzienniki i metryki z klastrów i obciążeń Nexus Kubernetes. To wyłącznie twoja swoboda, czy włączyć to narzędzie, czy wdrożyć własny stos telemetrii.

Klaster Nexus Kubernetes z narzędziem do monitorowania platformy Azure wygląda następująco:

Screenshot of Nexus Kubernetes cluster with Monitoring Tools.

Rysunek: klaster Nexus Kubernetes z narzędziami do monitorowania

Dołączanie rozszerzenia za pomocą interfejsu wiersza polecenia przy użyciu uwierzytelniania tożsamości zarządzanej

Dokumentacja dotycząca rozpoczynania pracy z interfejsem wiersza polecenia platformy Azure, sposobu instalowania jej w wielu systemach operacyjnych oraz instalowania rozszerzeń interfejsu wiersza polecenia.

Zainstaluj najnowszą wersję niezbędnych rozszerzeń interfejsu wiersza polecenia.

Monitorowanie klastra Nexus Kubernetes — warstwa maszyny wirtualnej

Ten przewodnik z instrukcjami zawiera instrukcje i skrypty narzędziowe służące do łączenia maszyn wirtualnych klastra Nexus Kubernetes z platformą Azure i włączania agentów monitorowania na potrzeby zbierania dzienników systemu z tych maszyn wirtualnych przy użyciu agenta monitorowania platformy Azure. Dalsze instrukcje zawierają szczegółowe informacje na temat konfigurowania zbierania danych dzienników w obszarze roboczym usługi Log Analytics.

Następujące zasoby zapewniają pomoc techniczną:

  • arc-connect.env: użyj tego pliku szablonu, aby utworzyć zmienne środowiskowe wymagane przez dołączone skrypty

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: użyj tego skryptu, aby utworzyć regułę zbierania danych (DCR) w celu skonfigurowania zbierania dzienników syslog

#!/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: użyj skryptu, aby utworzyć zasady, aby skojarzyć kontroler domeny ze wszystkimi serwerami z obsługą usługi Arc w grupie zasobów

#!/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: Zainstaluj agenta monitorowania platformy Azure na każdej maszynie wirtualnej, aby zbierać dane monitorowania z usługi Azure Virtual Machines.
#!/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

Wymagania wstępne — maszyna wirtualna

  • Dostęp administratora klastra do klastra Nexus Kubernetes.

  • Aby użyć serwerów z obsługą usługi Azure Arc, zarejestruj następujących dostawców zasobów platformy Azure w ramach subskrypcji:

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

Zarejestruj tych dostawców zasobów, jeśli nie zostało to zrobione wcześniej:

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'
  • W razie potrzeby przypisz jednostkę usługi platformy Azure do następujących wbudowanych ról platformy Azure. Przypisz jednostkę usługi do grupy zasobów platformy Azure, która ma maszyny do połączenia:
Rola Wymagane do
Połączenie ed Machine Resource Administracja istrator lub Współautor Połączenie serwer maszyny wirtualnej klastra Kubernetes z obsługą usługi Arc w usłudze Arc w grupie zasobów i zainstaluj agenta monitorowania platformy Azure (AMA)
Współautor lub współautor monitorowania Utwórz regułę zbierania danych (DCR) w grupie zasobów i skojarz z nią serwery z obsługą usługi Arc
Administracja istrator dostępu użytkowników i współautorzasad zasobów Wymagane, jeśli chcesz używać przypisań zasad platformy Azure, aby upewnić się, że kontroler domeny jest skojarzony z maszynami z obsługą usługi Arc
Współautor rozszerzenia Kubernetes Wymagane do wdrożenia rozszerzenia K8s dla usługi Container Szczegółowe informacje

Konfigurowanie środowiska

Skopiuj i uruchom dołączone skrypty. Można je uruchomić z poziomu usługi Azure Cloud Shell w witrynie Azure Portal. Możesz też uruchomić je z poziomu wiersza polecenia systemu Linux, w którym zainstalowano narzędzie wiersza polecenia Kubernetes (kubectl) i interfejs wiersza polecenia platformy Azure.

Przed uruchomieniem dołączonych skryptów zdefiniuj następujące zmienne środowiskowe:

Zmienna środowiskowa opis
SUBSCRIPTION_ID Identyfikator subskrypcji platformy Azure, która zawiera grupę zasobów
RESOURCE_GROUP Nazwa grupy zasobów, w której jest tworzony serwer z obsługą usługi Arc i skojarzone zasoby
LOKALIZACJA Region świadczenia usługi Azure, w którym są tworzone serwery z obsługą usługi Arc i skojarzone zasoby
SERVICE_PRINCIPAL_ID Identyfikator appId jednostki usługi platformy Azure z odpowiednimi przypisaniami ról
SERVICE_PRINCIPAL_SECRET Hasło uwierzytelniania dla jednostki usługi platformy Azure
TENANT_ID Identyfikator katalogu dzierżawy, w którym istnieje jednostka usługi
PROXY_URL Adres URL serwera proxy używany do nawiązywania połączenia z usługami platformy Azure
OBSZARU NAZW Przestrzeń nazw, w której są tworzone artefakty kubernetes

Dla wygody możesz zmodyfikować plik szablonu, arc-connect.env, aby ustawić wartości zmiennych środowiskowych.

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

Dodawanie reguły zbierania danych (DCR)

Skojarz serwery z obsługą usługi Arc z kontrolerem domeny, aby umożliwić zbieranie danych dziennika w obszarze roboczym usługi Log Analytics. Kontroler domeny można utworzyć za pośrednictwem witryny Azure Portal lub interfejsu wiersza polecenia. Informacje na temat tworzenia kontrolera domeny w celu zbierania danych z maszyn wirtualnych są dostępne tutaj.

Dołączony dcr.sh skrypt tworzy kontroler domeny w określonej grupie zasobów, który skonfiguruje zbieranie dzienników.

  1. Upewnij się, że odpowiednie wymagania wstępne dotyczące konfiguracji środowiska i roli dla jednostki usługi. Kontroler domeny jest tworzony w określonej grupie zasobów.

  2. Utwórz lub zidentyfikuj obszar roboczy usługi Log Analytics na potrzeby pozyskiwania danych dzienników zgodnie z dcR. Ustaw zmienną środowiskową, LAW_RESOURCE_ID na jej identyfikator zasobu. Pobierz identyfikator zasobu dla znanej nazwy obszaru roboczego usługi Log Analytics:

export LAW_RESOURCE_ID=$(az monitor log-analytics workspace show -g "${RESOURCE_GROUP}" -n <law name> --query id -o tsv)
  1. Uruchom skrypt dcr.sh. Tworzy kontroler domeny w określonej grupie zasobów o nazwie ${RESOURCE_GROUP}-syslog-dcr
./dcr.sh

Wyświetlanie dcR i zarządzanie nim z poziomu witryny Azure Portal lub interfejsu wiersza polecenia. Domyślnie poziom dziennika syslog systemu Linux ma wartość "INFO". W razie potrzeby można zmienić poziom dziennika.

Uwaga

Ręcznie lub za pomocą zasad skojarz serwery utworzone przed utworzeniem kontrolera domeny. Zobacz zadanie korygowania.

Kojarzenie zasobów serwera z obsługą usługi Arc do usługi DCR

Skojarz zasoby serwera z obsługą usługi Arc do utworzonego kontrolera domeny, aby dzienniki przepływły do obszaru roboczego usługi Log Analytics. Istnieją opcje kojarzenia serwerów z kontrolerami domeny.

Używanie witryny Azure Portal lub interfejsu wiersza polecenia do kojarzenia wybranych serwerów z obsługą usługi Arc do usługi DCR

W witrynie Azure Portal dodaj zasób serwera z obsługą usługi Arc do usługi DCR przy użyciu sekcji Zasoby.

Użyj tego linku , aby uzyskać informacje na temat kojarzenia zasobów za pośrednictwem interfejsu wiersza polecenia platformy Azure.

Zarządzanie skojarzeniami DCR przy użyciu zasad platformy Azure

Przypisz zasady do grupy zasobów, aby wymusić skojarzenie. Istnieje wbudowana definicja zasad do skojarzenia maszyn z systemem Linux Arc z kontrolerem domeny. Przypisz zasady do grupy zasobów z kontrolerem domeny jako parametrem. Zapewnia skojarzenie wszystkich serwerów z obsługą usługi Arc w grupie zasobów z tym samym kontrolerem domeny.

W witrynie Azure Portal wybierz Assign przycisk na stronie definicji zasad.

Dla wygody podany assign.sh skrypt przypisuje wbudowane zasady do określonej grupy zasobów i kontroler domeny utworzony za pomocą skryptu dcr.sh .

  1. Upewnij się, że odpowiednie wymagania wstępne dotyczące konfiguracji środowiska i roli dla jednostki usługi umożliwiają wykonywanie przypisań zasad i ról.
  2. Utwórz kontroler domeny w grupie zasobów przy użyciu skryptu zgodnie z dcr.sh opisem w sekcji Dodawanie reguły zbierania danych.
  3. Uruchom skrypt assign.sh. Tworzy przypisanie zasad i niezbędne przypisania ról.
./assign.sh

Instalowanie agenta monitorowania platformy Azure

Użyj dołączonego install.sh elementu, który tworzy demon KubernetesSet w klastrze Nexus Kubernetes. Wdraża zasobnik w każdym węźle klastra i instaluje agenta monitorowania platformy Azure (AMA). Zawiera daemonSet również sondę aktualności, która monitoruje połączenia serwera i procesy AMA.

Uwaga

Aby zainstalować agenta monitorowania platformy Azure, musisz najpierw połączyć maszyny wirtualne klastra Nexus Kubernetes z usługą Arc. Ten proces jest zautomatyzowany, jeśli używasz najnowszej wersji pakietu. Jeśli jednak używany pakiet wersji nie obsługuje rejestracji maszyny wirtualnej klastra w usłudze Arc domyślnie, należy uaktualnić klaster do najnowszej wersji pakietu. Aby uzyskać więcej informacji na temat pakietu wersji, zobacz Nexus Kubernetes cluster supported versions (Obsługiwane wersje klastra Nexus Kubernetes)

  1. Ustaw środowisko zgodnie z ustawieniami środowiska. Ustaw bieżący kubeconfig kontekst dla maszyn wirtualnych klastra Nexus Kubernetes.
  2. Zezwól na Kubectl dostęp do klastra Nexus Kubernetes.

    Uwaga

    Podczas tworzenia klastra Nexus Kubernetes nexus automatycznie tworzy zarządzaną grupę zasobów przeznaczoną do przechowywania zasobów klastra w ramach tej grupy zostanie ustanowiony zasób klastra połączonego z usługą Arc.

    Aby uzyskać dostęp do klastra, należy skonfigurować klaster connect kubeconfig. Po zalogowaniu się do interfejsu wiersza polecenia platformy Azure przy użyciu odpowiedniej jednostki Firmy Microsoft Entra możesz uzyskać kubeconfig niezbędne do komunikowania się z klastrem z dowolnego miejsca, nawet poza zaporą, która go otacza.
    1. Ustaw CLUSTER_NAMEzmienne i SUBSCRIPTION_IDRESOURCE_GROUP .

      CLUSTER_NAME="myNexusK8sCluster"
      RESOURCE_GROUP="myResourceGroup"
      SUBSCRIPTION_ID=<set the correct subscription_id>
      
    2. Wykonywanie zapytań względem zarządzanej grupy zasobów za pomocą az polecenia i przechowywania w usłudze 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. Następujące polecenie uruchamia serwer proxy connectedk8s, który umożliwia nawiązanie połączenia z serwerem interfejsu API Kubernetes dla określonego klastra Nexus Kubernetes.

      az connectedk8s proxy -n $CLUSTER_NAME  -g $MANAGED_RESOURCE_GROUP &
      
    4. Użyj kubectl polecenia , aby wysyłać żądania do klastra:

      kubectl get pods -A
      

      Powinna zostać wyświetlona odpowiedź z klastra zawierającego listę wszystkich węzłów.

    Uwaga

    Jeśli zostanie wyświetlony komunikat o błędzie "Nie można opublikować tokenu dostępu do serwera proxy klientaFailed w celu nawiązania połączenia z tożsamością usługi zarządzanej", może być konieczne wykonanie polecenia az login w celu ponownego uwierzytelnienia na platformie Azure.

  3. install.sh Uruchom skrypt z poziomu wiersza polecenia z dostępem kubectl do klastra Nexus Kubernetes.

Skrypt wdraża daemonSet element w klastrze. Monitoruj postęp w następujący sposób:

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

Po zakończeniu system rejestruje komunikat "Pomyślnie skonfigurowano monitorowanie serwera".

Uwaga

Skojarz te połączone serwery z kontrolerem domeny. Po skonfigurowaniu zasad może wystąpić pewne opóźnienie w obserwowaniu dzienników w obszarze roboczym usługi Azure Log Analytics

Monitorowanie klastra Kubernetes Nexus — warstwa K8s

Wymagania wstępne — Kubernetes

Operator powinien mieć pewne wymagania wstępne, aby skonfigurować narzędzia do monitorowania w klastrach Kubernetes Nexus.

Kontener Szczegółowe informacje przechowuje swoje dane w obszarze roboczym usługi Log Analytics. Dane dzienników przepływają do obszaru roboczego, którego identyfikator zasobu podany podczas początkowych skryptów omówionych w sekcji "Dodawanie reguły zbierania danych (DCR)". W przeciwnym razie lejki danych do domyślnego obszaru roboczego w grupie Zasobów skojarzonej z subskrypcją (na podstawie lokalizacji platformy Azure).

Przykład dla wschodnich stanów USA może wyglądać następująco:

  • Nazwa obszaru roboczego usługi Log Analytics: DefaultWorkspace-GUID-EUS<>
  • Nazwa grupy zasobów: DefaultResourceGroup-EUS

Uruchom następujące polecenie, aby uzyskać wcześniej istniejący identyfikator zasobu obszaru roboczego usługi Log Analytics:

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

Aby wdrożyć kontener Szczegółowe informacje i wyświetlić dane w odpowiednim obszarze roboczym usługi Log Analytics, wymagane są pewne przypisania ról na twoim koncie. Na przykład przypisanie roli "Współautor". Zapoznaj się z instrukcjami dotyczącymi przypisywania wymaganych ról:

  • Rola współautora usługi Log Analytics: niezbędne uprawnienia do włączania monitorowania kontenerów w klastrze CNF (aprowizowany).
  • Rola czytelnika usługi Log Analytics: członkowie roli Współautor usługi Log Analytics otrzymują uprawnienia do wyświetlania danych w obszarze roboczym usługi Log Analytics po włączeniu monitorowania kontenerów.

Instalowanie rozszerzenia klastra

Zaloguj się do usługi Azure Cloud Shell, aby uzyskać dostęp do klastra:

az login

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

Teraz wdróż rozszerzenie Container Szczegółowe informacje w aprowizowanej klastrze Nexus Kubernetes przy użyciu jednego z dwóch następnych poleceń:

W przypadku wstępnie utworzonego obszaru roboczego usługi Log Analytics przez klienta

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

Korzystanie z domyślnego obszaru roboczego usługi Log Analytics

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

Weryfikowanie rozszerzenia klastra

Zweryfikuj pomyślne wdrożenie włączania agentów monitorowania w klastrach Kubernetes Nexus przy użyciu następującego polecenia:

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

Poszukaj stanu aprowizacji "Powodzenie" dla rozszerzenia. Polecenie "k8s-extension create" mogło również zwrócić stan.

Dostosowywanie kolekcji dzienników i metryk

Usługa Container Szczegółowe informacje udostępnia użytkownikom końcowym funkcje umożliwiające dostosowanie kolekcji dzienników i metryk z klastrów Nexus Kubernetes — konfigurowanie zbierania danych agenta usługi Container Insights.

Dodatkowe zasoby

  • Przejrzyj dokumentację skoroszytów, a następnie możesz użyć przykładowych skoroszytów operatorów Nexus operatora Nexus.
  • Przejrzyj alerty usługi Azure Monitor, jak utworzyć reguły alertów usługi Azure Monitor i użyć przykładowych szablonów alertów operatora Nexus.