О внедрении gateway

Внедрение gateway использует тот же механизм, что и внедрение sidecar, для развертывания прокси Envoy в pod'ах gateway. Чтобы развернуть gateway:

  1. Создайте Kubernetes Deployment и соответствующий Service в namespace, видимом для контрольной плоскости Istio.
  2. Добавьте аннотации и метки к deployment, чтобы контрольная плоскость Istio внедрила прокси Envoy, настроенный как gateway.
  3. Примените ресурсы Istio Gateway и VirtualService для управления входящим или исходящим трафиком.

Содержание

Уведомление о совместимости с ядром Linux

Для узлов с версиями ядра Linux ниже 4.11 (например, CentOS 7) требуется дополнительная настройка перед установкой gateway.

INFO

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

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

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

Процедура

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

    Нажмите, чтобы развернуть
    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: []  
        capabilities:
          add: [CAP_NET_BIND_SERVICE]  
      {{- 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 канал между istioagent и Envoy
        - mountPath: /etc/istio/proxy
          name: istio-envoy
        - mountPath: /var/run/secrets/tokens
          name: istio-token
        {{- if .Values.global.mountMtlsCerts }}
        # Используйте ключ и сертификат, смонтированные в /etc/certs/ для внутрикластерных mTLS коммуникаций.
        - 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 канал между istioagent и 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 }}
      # Используйте ключ и сертификат, смонтированные в /etc/certs/ для внутрикластерных mTLS коммуникаций.
      - 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.
    2. Добавьте CAP_NET_BIND_SERVICE в список capabilities, чтобы разрешить gateway слушать порты ниже 1024.
  2. Примените патч к шаблону внедрения 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}"
  3. Дождитесь, пока контрольная плоскость не вернет состояние Ready, выполнив следующую команду:

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