다음을 통해 공유


AKS(Azure Kubernetes Service)에 대한 고급 네트워크 가시성 설정(미리 보기)

이 문서에서는 AKS(Azure Kubernetes Service)에 대한 고급 네트워크 가시성을 설정하고 BYO(Bring Your Own) Prometheus 및 Grafana를 사용하여 메트릭을 시각화하는 방법을 보여 줍니다.

고급 네트워크 가시성을 사용하여 AKS 클러스터의 네트워크 트래픽 데이터에 대한 데이터를 수집할 수 있습니다. 네트워크 가시성을 사용하면 중앙 집중식 플랫폼에서 애플리케이션 및 네트워크 상태를 모니터링할 수 있습니다. 현재 메트릭은 Prometheus에 저장되고 Grafana를 사용하여 시각화할 수 있습니다. 고급 네트워크 가시성은 Hubble을 사용하도록 설정하는 기능도 제공합니다. 이러한 기능은 Cilium 및 비 Cilium 클러스터 모두에서 지원됩니다.

고급 네트워크 가시성은 고급 컨테이너 네트워킹 서비스의 기능 중 하나입니다. AKS(Azure Kubernetes Service)용 고급 컨테이너 네트워킹 서비스에 대한 자세한 내용은 AKS(Azure Kubernetes Service)용 고급 컨테이너 네트워킹 서비스란?을 참조하세요.

Important

고급 네트워크 가시성은 현재 미리 보기로 제공됩니다. 베타, 미리 보기로 제공되거나 아직 일반 공급으로 릴리스되지 않은 Azure 기능에 적용되는 약관은 Microsoft Azure 미리 보기에 대한 추가 사용 약관을 참조하세요.

필수 조건

  • 이 문서의 단계에 필요한 Azure CLI의 최소 버전은 2.56.0입니다. az --version을 실행하여 버전을 찾습니다. 설치 또는 업그레이드해야 하는 경우 Azure CLI 설치를 참조하세요.

aks-preview Azure CLI 확장 설치

az extension add 또는 az extension update 명령을 사용하여 Azure CLI 미리 보기 확장을 설치하거나 업데이트합니다.

# Install the aks-preview extension
az extension add --name aks-preview

# Update the extension to make sure you have the latest version installed
az extension update --name aks-preview

AdvancedNetworkingPreview 기능 플래그 등록

az feature register 명령을 사용하여 az feature register --namespace "Microsoft.ContainerService" --name "AdvancedNetworkingPreview" 기능 플래그를 등록합니다.

az feature register --namespace "Microsoft.ContainerService" --name "AdvancedNetworkingPreview"

az feature show 명령을 사용하여 등록에 성공했는지 확인합니다. 등록을 완료하려면 몇 분 정도 걸립니다.

az feature show --namespace "Microsoft.ContainerService" --name "AdvancedNetworkingPreview"

기능에 Registered가 표시되면 az provider register 명령을 사용하여 Microsoft.ContainerService 리소스 공급자를 등록을 새로 고칩니다.

리소스 그룹 만들기

리소스 그룹은 Azure 리소스가 배포 및 관리되는 논리적 컨테이너입니다. az group create 명령을 사용하여 리소스 그룹을 만듭니다.

# Set environment variables for the resource group name and location. Make sure to replace the placeholders with your own values.
export RESOURCE_GROUP="<resource-group-name>"
export LOCATION="<azure-region>"

# Create a resource group
az group create --name $RESOURCE_GROUP --location $LOCATION

고급 네트워크 가시성을 사용하여 AKS 클러스터 만들기

az aks create 명령과 --enable-advanced-networking-observability 플래그를 사용하여 Cilium이 아닌 데이터 평면을 사용하여 고급 네트워크 가시성을 사용하여 AKS 클러스터를 만듭니다.

# Set an environment variable for the AKS cluster name. Make sure to replace the placeholder with your own value.
export CLUSTER_NAME="<aks-cluster-name>"

# Create an AKS cluster
az aks create \
    --name $CLUSTER_NAME \
    --resource-group $RESOURCE_GROUP \
    --generate-ssh-keys \
    --network-plugin azure \
    --network-plugin-mode overlay \
    --pod-cidr 192.168.0.0/16 \
    --enable-advanced-network-observability

기존 클러스터에서 고급 네트워크 가시성 사용

az aks update 명령을 사용하여 기존 클러스터에서 고급 네트워크 가시성을 사용하도록 설정합니다.

참고 항목

Cilium 데이터 평면을 사용하는 클러스터는 Kubernetes 버전 1.29부터 고급 가시성을 지원합니다.

az aks update \
    --resource-group $RESOURCE_GROUP \
    --name $CLUSTER_NAME \
    --enable-advanced-network-observability

클러스터 자격 증명 가져오기

az aks get-credentials 명령을 사용하여 클러스터 자격 증명을 가져옵니다.

az aks get-credentials --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP

Grafana를 사용한 시각화

  1. 기존 Prometheus 구성에 다음 스크랩 작업을 추가하고 Prometheus 서버를 다시 시작합니다.

    - job_name: networkobservability-hubble
      kubernetes_sd_configs:
        - role: pod
      relabel_configs:
        - target_label: cluster
          replacement: myAKSCluster
          action: replace
        - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_pod_label_k8s_app]
          regex: kube-system;(retina|cilium)
          action: keep
        - source_labels: [__address__]
          action: replace
          regex: ([^:]+)(?::\d+)?
          replacement: $1:9965
          target_label: __address__
        - source_labels: [__meta_kubernetes_pod_node_name]
          target_label: instance
          action: replace
      metric_relabel_configs:
        - source_labels: [__name__]
          regex: '|hubble_dns_queries_total|hubble_dns_responses_total|hubble_drop_total|hubble_tcp_flags_total' # if desired, add |hubble_flows_processed_total
          action: keep
    
  2. Prometheus의 대상에서 network-obs-pods가 있는지 확인합니다.

  3. Grafana에 로그인하고 다음 ID를 사용하여 다음 예제 대시보드를 가져옵니다.

    • 클러스터: 클러스터에 대한 노드 수준 메트릭을 보여 줍니다. (ID: 18814)
    • DNS(클러스터): 클러스터 또는 노드 선택 영역에 DNS 메트릭을 표시합니다.(ID: 20925)
    • DNS(워크로드): 지정된 워크로드에 대한 DNS 메트릭을 표시합니다(예: DaemonSet의 Pod 또는 CoreDNS와 같은 배포). (ID: [20926] https://grafana.com/grafana/dashboards/20926-kubernetes-networking-dns-workload/)
    • 삭제(워크로드): 지정된 워크로드(예: 배포 또는 DaemonSet의 Pod)에 대한 삭제를 표시합니다.( ID: 20927).
    • Pod 흐름(네임스페이스): 지정된 네임스페이스(즉, 네임스페이스의 Pod)를 오가는 L4/L7 패킷 흐름을 보여 줍니다. (ID: 20928)
    • Pod 흐름(워크로드): 지정된 워크로드(예: 배포 또는 DaemonSet의 Pod)를 오가는 L4/L7 패킷 흐름을 보여 줍니다.( ID: 20929)

    참고 항목

    • Prometheus/Grafana 인스턴스의 설정에 따라 일부 대시보드 패널에서 모든 데이터를 표시하기 위해 조정이 필요할 수 있습니다.
    • Cilium은 현재 DNS 메트릭/대시보드를 지원하지 않습니다.
  4. 다음 명령을 사용하여 수집한 데이터에 액세스하려면 Hubble CLI를 설치합니다.

    # Set environment variables
    export HUBBLE_VERSION=v0.11.0
    export HUBBLE_ARCH=amd64
    
    # Install Hubble CLI
    if [ "$(uname -m)" = "aarch64" ]; then HUBBLE_ARCH=arm64; fi
    curl -L --fail --remote-name-all https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-${HUBBLE_ARCH}.tar.gz{,.sha256sum}
    sha256sum --check hubble-linux-${HUBBLE_ARCH}.tar.gz.sha256sum
    sudo tar xzvfC hubble-linux-${HUBBLE_ARCH}.tar.gz /usr/local/bin
    rm hubble-linux-${HUBBLE_ARCH}.tar.gz{,.sha256sum}
    

Hubble 흐름 시각화

  1. Hubble Pod가 kubectl get pods 명령을 사용하여 실행 중인지 확인합니다.

    kubectl get pods -o wide -n kube-system -l k8s-app=hubble-relay
    

    출력은 다음 예제 출력과 비슷하게 됩니다.

    hubble-relay-7ddd887cdb-h6khj     1/1  Running     0       23h 
    
  2. kubectl port-forward 명령을 사용하여 Hubble Relay로 포트 전달을 설정합니다.

    kubectl port-forward -n kube-system svc/hubble-relay --address 127.0.0.1 4245:443
    
  3. mTLS(상호 TLS)는 Hubble Relay 서버의 보안을 보장합니다. Hubble 클라이언트가 흐름을 검색할 수 있도록 하려면 적절한 인증서를 가져와서 클라이언트를 구성해야 합니다. 다음 명령을 사용하여 인증서를 적용합니다.

    #!/usr/bin/env bash
    
    set -euo pipefail
    set -x
    
    # Directory where certificates will be stored
    CERT_DIR="$(pwd)/.certs"
    mkdir -p "$CERT_DIR"
    
    declare -A CERT_FILES=(
      ["tls.crt"]="tls-client-cert-file"
      ["tls.key"]="tls-client-key-file"
      ["ca.crt"]="tls-ca-cert-files"
    )
    
    for FILE in "${!CERT_FILES[@]}"; do
      KEY="${CERT_FILES[$FILE]}"
      JSONPATH="{.data['${FILE//./\\.}']}"
    
      # Retrieve the secret and decode it
      kubectl get secret hubble-relay-client-certs -n kube-system \
        -o jsonpath="${JSONPATH}" | \
        base64 -d > "$CERT_DIR/$FILE"
    
      # Set the appropriate hubble CLI config
      hubble config set "$KEY" "$CERT_DIR/$FILE"
    done
    
    hubble config set tls true
    hubble config set tls-server-name instance.hubble-relay.cilium.io
    
  4. kubectl get secrets 명령을 사용하여 비밀이 생성되었는지 확인합니다.

    kubectl get secrets -n kube-system | grep hubble-
    

    출력은 다음 예제 출력과 비슷하게 됩니다.

    kube-system     hubble-relay-client-certs     kubernetes.io/tls     3     9d
    
    kube-system     hubble-relay-server-certs     kubernetes.io/tls     3     9d
    
    kube-system     hubble-server-certs           kubernetes.io/tls     3     9d    
    
  5. Hubble Relay Pod가 hubble relay service 명령을 사용하여 실행 중인지 확인합니다.

    hubble relay service 
    

Hubble UI를 사용하여 시각화

  1. Hubble UI를 사용하려면 다음을 hubble-ui.yaml에 저장합니다.

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: hubble-ui
      namespace: kube-system
    ---
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: hubble-ui
      labels:
        app.kubernetes.io/part-of: retina
    rules:
      - apiGroups:
          - networking.k8s.io
        resources:
          - networkpolicies
        verbs:
          - get
          - list
          - watch
      - apiGroups:
          - ""
        resources:
          - componentstatuses
          - endpoints
          - namespaces
          - nodes
          - pods
          - services
        verbs:
          - get
          - list
          - watch
      - apiGroups:
          - apiextensions.k8s.io
        resources:
          - customresourcedefinitions
        verbs:
          - get
          - list
          - watch
      - apiGroups:
          - cilium.io
        resources:
          - "*"
        verbs:
          - get
          - list
          - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: hubble-ui
      labels:
        app.kubernetes.io/part-of: retina
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: hubble-ui
    subjects:
      - kind: ServiceAccount
        name: hubble-ui
        namespace: kube-system
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: hubble-ui-nginx
      namespace: kube-system
    data:
      nginx.conf: |
        server {
            listen       8081;
            server_name  localhost;
            root /app;
            index index.html;
            client_max_body_size 1G;
            location / {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                # CORS
                add_header Access-Control-Allow-Methods "GET, POST, PUT, HEAD, DELETE, OPTIONS";
                add_header Access-Control-Allow-Origin *;
                add_header Access-Control-Max-Age 1728000;
                add_header Access-Control-Expose-Headers content-length,grpc-status,grpc-message;
                add_header Access-Control-Allow-Headers range,keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout;
                if ($request_method = OPTIONS) {
                    return 204;
                }
                # /CORS
                location /api {
                    proxy_http_version 1.1;
                    proxy_pass_request_headers on;
                    proxy_hide_header Access-Control-Allow-Origin;
                    proxy_pass http://127.0.0.1:8090;
                }
                location / {
                    try_files $uri $uri/ /index.html /index.html;
                }
                # Liveness probe
                location /healthz {
                    access_log off;
                    add_header Content-Type text/plain;
                    return 200 'ok';
                }
            }
        }
    ---
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: hubble-ui
      namespace: kube-system
      labels:
        k8s-app: hubble-ui
        app.kubernetes.io/name: hubble-ui
        app.kubernetes.io/part-of: retina
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: hubble-ui
      template:
        metadata:
          labels:
            k8s-app: hubble-ui
            app.kubernetes.io/name: hubble-ui
            app.kubernetes.io/part-of: retina
        spec:
          serviceAccount: hibble-ui
          serviceAccountName: hubble-ui
          automountServiceAccountToken: true
          containers:
          - name: frontend
            image: mcr.microsoft.com/oss/cilium/hubble-ui:v0.12.2   
            imagePullPolicy: Always
            ports:
            - name: http
              containerPort: 8081
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8081
            readinessProbe:
              httpGet:
                path: /
                port: 8081
            resources: {}
            volumeMounts:
            - name: hubble-ui-nginx-conf
              mountPath: /etc/nginx/conf.d/default.conf
              subPath: nginx.conf
            - name: tmp-dir
              mountPath: /tmp
            terminationMessagePolicy: FallbackToLogsOnError
            securityContext: {}
          - name: backend
            image: mcr.microsoft.com/oss/cilium/hubble-ui-backend:v0.12.2
            imagePullPolicy: Always
            env:
            - name: EVENTS_SERVER_PORT
              value: "8090"
            - name: FLOWS_API_ADDR
              value: "hubble-relay:443"
            - name: TLS_TO_RELAY_ENABLED
              value: "true"
            - name: TLS_RELAY_SERVER_NAME
              value: ui.hubble-relay.cilium.io
            - name: TLS_RELAY_CA_CERT_FILES
              value: /var/lib/hubble-ui/certs/hubble-relay-ca.crt
            - name: TLS_RELAY_CLIENT_CERT_FILE
              value: /var/lib/hubble-ui/certs/client.crt
            - name: TLS_RELAY_CLIENT_KEY_FILE
              value: /var/lib/hubble-ui/certs/client.key
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8090
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8090
            ports:
            - name: grpc
              containerPort: 8090
            resources: {}
            volumeMounts:
            - name: hubble-ui-client-certs
              mountPath: /var/lib/hubble-ui/certs
              readOnly: true
            terminationMessagePolicy: FallbackToLogsOnError
            securityContext: {}
          nodeSelector:
            kubernetes.io/os: linux 
          volumes:
          - configMap:
              defaultMode: 420
              name: hubble-ui-nginx
            name: hubble-ui-nginx-conf
          - emptyDir: {}
            name: tmp-dir
          - name: hubble-ui-client-certs
            projected:
              defaultMode: 0400
              sources:
              - secret:
                  name: hubble-relay-client-certs
                  items:
                    - key: tls.crt
                      path: client.crt
                    - key: tls.key
                      path: client.key
                    - key: ca.crt
                      path: hubble-relay-ca.crt
    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: hubble-ui
      namespace: kube-system
      labels:
        k8s-app: hubble-ui
        app.kubernetes.io/name: hubble-ui
        app.kubernetes.io/part-of: retina
    spec:
      type: ClusterIP
      selector:
        k8s-app: hubble-ui
      ports:
        - name: http
          port: 80
          targetPort: 8081
    
  2. 다음 명령을 사용하여 클러스터에 hubble-ui.yaml 매니페스트 적용

    kubectl apply -f hubble-ui.yaml
    
  3. kubectl port-forward 명령을 사용하여 포트 전달을 설정하여 서비스를 노출합니다.

    kubectl port-forward svc/hubble-ui 12000:80
    
  4. 웹 브라우저에 http://localhost:12000/를 입력하여 Hubble UI에 액세스합니다.


리소스 정리

이 애플리케이션을 사용할 플랜이 없는 경우 az group delete 명령을 사용하여 이 문서에서 만든 다른 리소스를 삭제합니다.

  az group delete --name $RESOURCE_GROUP

다음 단계

이 방법 문서에서는 AKS 클러스터에 고급 AKS 네트워크 가시성을 설치하고 사용하도록 설정하는 방법을 알아보았습니다.