• Русский
  • Уведомление о совместимости с ядром Linux

    Для узлов с версиями ядра Linux ранее 4.11 (например, CentOS 7) требуется дополнительная настройка перед установкой шлюза. Существуют два сценария в зависимости от того, нужно ли слушать порты ниже 1024:

    • Сценарий 1: только версии ядра ранее 4.11 — шлюз слушает порты 1024 и выше. Необходимо установить sysctls: [], чтобы убрать стандартный sysctl net.ipv4.ip_unprivileged_port_start, который отсутствует в ядрах ранее 4.11.
    • Сценарий 2: версии ядра ранее 4.11 + привилегированные порты — шлюз должен слушать порты ниже 1024. Помимо изменения sysctls: [] из Сценария 1, нужно добавить capability NET_BIND_SERVICE для разрешения привязки к привилегированным портам.
    INFO

    Пропустите этот раздел, если версия вашего ядра 4.11 или новее.

    Istio Gateway

    Предварительные требования

    • Установите jq локально для обработки JSON на следующих шагах.

    Процедура

    Сценарий 1: только версии ядра ранее 4.11 (порты ≥ 1024)

    1. Создайте YAML-файл с именем gateway-injection-template.txt, содержащий шаблон инъекции по умолчанию для шлюзов.

      Нажмите, чтобы развернуть
      gateway-injection-template.txt
      {{- $containers := list }}
      {{- range $index, $container := .Spec.Containers }}{{ if not (eq $container.Name "istio-proxy") }}{{ $containers = append $containers $container.Name }}{{end}}{{- end}}
      metadata:
        labels:
          service.istio.io/canonical-name: {{ index .ObjectMeta.Labels `service.istio.io/canonical-name` | default (index .ObjectMeta.Labels `app.kubernetes.io/name`) | default (index .ObjectMeta.Labels `app`) | default .DeploymentMeta.Name  | quote }}
          service.istio.io/canonical-revision: {{ index .ObjectMeta.Labels `service.istio.io/canonical-revision` | default (index .ObjectMeta.Labels `app.kubernetes.io/version`) | default (index .ObjectMeta.Labels `version`) | default "latest"  | quote }}
        annotations:
          istio.io/rev: {{ .Revision | default "default" | quote }}
          {{- if ge (len $containers) 1 }}
          {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-logs-container`) }}
          kubectl.kubernetes.io/default-logs-container: "{{ index $containers 0 }}"
          {{- end }}
          {{- if not (isset .ObjectMeta.Annotations `kubectl.kubernetes.io/default-container`) }}
          kubectl.kubernetes.io/default-container: "{{ index $containers 0 }}"
          {{- end }}
          {{- end }}
      spec:
        securityContext:
        {{- if .Values.gateways.securityContext }}
          {{- toYaml .Values.gateways.securityContext | nindent 4 }}
        {{- else }}
          sysctls: []  
        {{- end }}
        containers:
        - name: istio-proxy
        {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }}
          image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}"
        {{- else }}
          image: "{{ .ProxyImage }}"
        {{- end }}
          ports:
          - containerPort: 15090
            protocol: TCP
            name: http-envoy-prom
          args:
          - proxy
          - router
          - --domain
          - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }}
          - --proxyLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/logLevel` .Values.global.proxy.logLevel }}
          - --proxyComponentLogLevel={{ annotation .ObjectMeta `sidecar.istio.io/componentLogLevel` .Values.global.proxy.componentLogLevel }}
          - --log_output_level={{ annotation .ObjectMeta `sidecar.istio.io/agentLogLevel` .Values.global.logging.level }}
        {{- if .Values.global.sts.servicePort }}
          - --stsPort={{ .Values.global.sts.servicePort }}
        {{- end }}
        {{- if .Values.global.logAsJson }}
          - --log_as_json
        {{- end }}
        {{- if .Values.global.proxy.lifecycle }}
          lifecycle:
            {{ toYaml .Values.global.proxy.lifecycle | indent 6 }}
        {{- end }}
          securityContext:
            runAsUser: {{ .ProxyUID | default "1337" }}
            runAsGroup: {{ .ProxyGID | default "1337" }}
          env:
          - name: PILOT_CERT_PROVIDER
            value: {{ .Values.global.pilotCertProvider }}
          - name: CA_ADDR
          {{- if .Values.global.caAddress }}
            value: {{ .Values.global.caAddress }}
          {{- else }}
            value: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Values.global.istioNamespace }}.svc:15012
          {{- end }}
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: INSTANCE_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
          - name: SERVICE_ACCOUNT
            valueFrom:
              fieldRef:
                fieldPath: spec.serviceAccountName
          - name: HOST_IP
            valueFrom:
              fieldRef:
                fieldPath: status.hostIP
          - name: ISTIO_CPU_LIMIT
            valueFrom:
              resourceFieldRef:
                resource: limits.cpu
          - name: PROXY_CONFIG
            value: |
                  {{ protoToJSON .ProxyConfig }}
          - name: ISTIO_META_POD_PORTS
            value: |-
              [
              {{- $first := true }}
              {{- range $index1, $c := .Spec.Containers }}
                {{- range $index2, $p := $c.Ports }}
                  {{- if (structToJSON $p) }}
                  {{if not $first}},{{end}}{{ structToJSON $p }}
                  {{- $first = false }}
                  {{- end }}
                {{- end}}
              {{- end}}
              ]
          - name: GOMEMLIMIT
            valueFrom:
              resourceFieldRef:
                resource: limits.memory
          - name: GOMAXPROCS
            valueFrom:
              resourceFieldRef:
                resource: limits.cpu
          {{- if .CompliancePolicy }}
          - name: COMPLIANCE_POLICY
            value: "{{ .CompliancePolicy }}"
          {{- end }}
          - name: ISTIO_META_APP_CONTAINERS
            value: "{{ $containers | join "," }}"
          - name: ISTIO_META_CLUSTER_ID
            value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}"
          - name: ISTIO_META_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: ISTIO_META_INTERCEPTION_MODE
            value: "{{ .ProxyConfig.InterceptionMode.String }}"
          {{- if .Values.global.network }}
          - name: ISTIO_META_NETWORK
            value: "{{ .Values.global.network }}"
          {{- end }}
          {{- if .DeploymentMeta.Name }}
          - name: ISTIO_META_WORKLOAD_NAME
            value: "{{ .DeploymentMeta.Name }}"
          {{ end }}
          {{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }}
          - name: ISTIO_META_OWNER
            value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }}
          {{- end}}
          {{- if .Values.global.meshID }}
          - name: ISTIO_META_MESH_ID
            value: "{{ .Values.global.meshID }}"
          {{- else if (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}
          - name: ISTIO_META_MESH_ID
            value: "{{ (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain) }}"
          {{- end }}
          {{- with (valueOrDefault .MeshConfig.TrustDomain .Values.global.trustDomain)  }}
          - name: TRUST_DOMAIN
            value: "{{ . }}"
          {{- end }}
          {{- range $key, $value := .ProxyConfig.ProxyMetadata }}
          - name: {{ $key }}
            value: "{{ $value }}"
          {{- end }}
          {{with .Values.global.imagePullPolicy }}imagePullPolicy: "{{.}}"{{end}}
          readinessProbe:
            httpGet:
              path: /healthz/ready
              port: 15021
            initialDelaySeconds: {{.Values.global.proxy.readinessInitialDelaySeconds }}
            periodSeconds: {{ .Values.global.proxy.readinessPeriodSeconds }}
            timeoutSeconds: 3
            failureThreshold: {{ .Values.global.proxy.readinessFailureThreshold }}
          volumeMounts:
          - name: workload-socket
            mountPath: /var/run/secrets/workload-spiffe-uds
          - name: credential-socket
            mountPath: /var/run/secrets/credential-uds
          {{- if eq .Values.global.caName "GkeWorkloadCertificate" }}
          - name: gke-workload-certificate
            mountPath: /var/run/secrets/workload-spiffe-credentials
            readOnly: true
          {{- else }}
          - name: workload-certs
            mountPath: /var/run/secrets/workload-spiffe-credentials
          {{- end }}
          {{- if eq .Values.global.pilotCertProvider "istiod" }}
          - mountPath: /var/run/secrets/istio
            name: istiod-ca-cert
          {{- end }}
          - mountPath: /var/lib/istio/data
            name: istio-data
          # SDS channel between istioagent and Envoy
          - mountPath: /etc/istio/proxy
            name: istio-envoy
          - mountPath: /var/run/secrets/tokens
            name: istio-token
          {{- if .Values.global.mountMtlsCerts }}
          # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications.
          - mountPath: /etc/certs/
            name: istio-certs
            readOnly: true
          {{- end }}
          - name: istio-podinfo
            mountPath: /etc/istio/pod
        volumes:
        - emptyDir: {}
          name: workload-socket
        - emptyDir: {}
          name: credential-socket
        {{- if eq .Values.global.caName "GkeWorkloadCertificate" }}
        - name: gke-workload-certificate
          csi:
            driver: workloadcertificates.security.cloud.google.com
        {{- else}}
        - emptyDir: {}
          name: workload-certs
        {{- end }}
        # SDS channel between istioagent and Envoy
        - emptyDir:
            medium: Memory
          name: istio-envoy
        - name: istio-data
          emptyDir: {}
        - name: istio-podinfo
          downwardAPI:
            items:
              - path: "labels"
                fieldRef:
                  fieldPath: metadata.labels
              - path: "annotations"
                fieldRef:
                  fieldPath: metadata.annotations
        - name: istio-token
          projected:
            sources:
            - serviceAccountToken:
                path: istio-token
                expirationSeconds: 43200
                audience: {{ .Values.global.sds.token.aud }}
        {{- if eq .Values.global.pilotCertProvider "istiod" }}
        - name: istiod-ca-cert
        {{- if eq (.Values.pilot.env).ENABLE_CLUSTER_TRUST_BUNDLE_API true }}
          projected:
            sources:
            - clusterTrustBundle:
              name: istio.io:istiod-ca:root-cert
              path: root-cert.pem
        {{- else }}
          configMap:
            name: istio-ca-root-cert
        {{- end }}
        {{- end }}
        {{- if .Values.global.mountMtlsCerts }}
        # Use the key and cert mounted to /etc/certs/ for the in-cluster mTLS communications.
        - name: istio-certs
          secret:
            optional: true
            {{ if eq .Spec.ServiceAccountName "" }}
            secretName: istio.default
            {{ else -}}
            secretName: {{  printf "istio.%s" .Spec.ServiceAccountName }}
            {{  end -}}
        {{- end }}
        {{- if .Values.global.imagePullSecrets }}
        imagePullSecrets:
          {{- range .Values.global.imagePullSecrets }}
          - name: {{ . }}
          {{- end }}
        {{- end }}
      1. Удалите sysctls, так как net.ipv4.ip_unprivileged_port_start отсутствует в ядрах Linux ранее 4.11.

    Сценарий 2: версии ядра ранее 4.11 + привилегированные порты (порты < 1024)

    Если вашему шлюзу нужно слушать порты ниже 1024, необходимо добавить capability NET_BIND_SERVICE помимо изменения sysctls: []. Измените секцию securityContext контейнера istio-proxy в gateway-injection-template.txt:

        securityContext:
          capabilities:
            add:
            - NET_BIND_SERVICE
          runAsUser: {{ .ProxyUID | default "1337" }}
          runAsGroup: {{ .ProxyGID | default "1337" }}
          # Раскомментируйте следующие поля, чтобы при необходимости запускать шлюз от root.
          # runAsUser: 0
          # runAsGroup: 0
          # runAsNonRoot: false
    WARNING

    Если после добавления capability NET_BIND_SERVICE шлюз всё ещё не может слушать порты ниже 1024, рассмотрите следующие альтернативы:

    1. Используйте порты 1024 и выше (рекомендуется) — перенастройте слушатели шлюза на порты ≥ 1024, чтобы полностью избежать проблем с привилегиями.
    2. Запустите шлюз от root — установите runAsUser: 0, runAsGroup: 0 и runAsNonRoot: false в securityContext контейнера. Это предоставит процессу шлюза полные привилегии. Тщательно оцените последствия для безопасности перед использованием этого подхода.

    Применение шаблона инъекции

    1. Примените патч к шаблону инъекции gateway ресурса Istio:

      TEMPLATE_CONTENT=$(cat gateway-injection-template.txt)
      PATCH_DATA=$(jq -n \
        --arg template "${TEMPLATE_CONTENT}" \
        '{
          "spec": {
            "values": {
              "sidecarInjectorWebhook": {
                "templates": {
                  "gateway": $template
                }
              }
            }
          }
        }')
      # Наконец примените патч к ресурсу Istio с именем `default`:
      kubectl patch istio default --type=merge -p "${PATCH_DATA}"
    2. Дождитесь, пока контрольная плоскость вернёт состояние Ready, выполнив команду:

      kubectl wait --for condition=Ready istio/default --timeout=3m

    Kubernetes Gateway API

    Предварительные требования

    • Alauda Container Platform версии 4.2.0 или новее, либо обновите CRD Gateway API до последней версии.

    Процедура

    Сценарий 1: только версии ядра ранее 4.11 (порты ≥ 1024)

    1. Создайте ConfigMap с именем asm-kube-gateway-options в том же namespace, где планируете развернуть Gateway:

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: asm-kube-gateway-options
        # Замените `<your-gateway-namespace>` на фактический namespace, где будет развернут ваш Gateway.
        namespace: <your-gateway-namespace>
      data:
        deployment: |
          spec:
            template:
              spec:
                securityContext:
                  sysctls: []
      1. Удалите sysctls, так как net.ipv4.ip_unprivileged_port_start отсутствует в ядрах Linux ранее 4.11.

    Сценарий 2: версии ядра ранее 4.11 + привилегированные порты (порты < 1024)

    Если вашему шлюзу нужно слушать порты ниже 1024, добавьте capability NET_BIND_SERVICE в ConfigMap. Измените поле data.deployment, чтобы включить securityContext на уровне контейнера:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: asm-kube-gateway-options
      namespace: <your-gateway-namespace>
    data:
      deployment: |
        spec:
          template:
            spec:
              securityContext:
                sysctls: []
              # Добавьте следующий securityContext на уровне контейнера для предоставления capability NET_BIND_SERVICE.
              containers:
              - name: istio-proxy
                securityContext:
                  capabilities:
                    add:
                    - NET_BIND_SERVICE
                  # Раскомментируйте следующие поля, чтобы при необходимости запускать шлюз от root.
                  # runAsUser: 0
                  # runAsGroup: 0
                  # runAsNonRoot: false
    WARNING

    Если после добавления capability NET_BIND_SERVICE шлюз всё ещё не может слушать порты ниже 1024, рассмотрите следующие альтернативы:

    1. Используйте порты 1024 и выше (рекомендуется) — перенастройте слушатели шлюза на порты ≥ 1024, чтобы полностью избежать проблем с привилегиями.
    2. Запустите шлюз от root — установите runAsUser: 0, runAsGroup: 0 и runAsNonRoot: false в securityContext контейнера. Это предоставит процессу шлюза полные привилегии. Тщательно оцените последствия для безопасности перед использованием этого подхода.

    Применение ConfigMap

    1. Сошлитесь на ConfigMap в вашем ресурсе Gateway, добавив поле infrastructure.parametersRef:

      apiVersion: gateway.networking.k8s.io/v1
      kind: Gateway
      metadata:
        name: <your-gateway-name>
        namespace: <your-gateway-namespace>
      spec:
        # Добавьте следующую инфраструктурную конфигурацию в ваш CR Gateway
        infrastructure:
          parametersRef:
            group: ""
            kind: ConfigMap
            name: asm-kube-gateway-options
        # ... остальная конфигурация вашего Gateway

      Эта конфигурация гарантирует, что развертывание шлюза использует пользовательские настройки securityContext, определённые в ConfigMap.