<a id="basic-tcp-udp"></a>

# Базовая балансировка TCP- и UDP-трафика

Ниже приведен пример развертывания DNS-сервера в кластере и настройки балансировки TCP- и UDP-трафика для него с использованием ресурса `TransportServer`. ANIC будет передавать все соединения или датаграммы, поступающие на порт 5353, в поды DNS-сервера.

## Предварительные действия

1. Установите ANIC:
   - Убедитесь, что ресурс `GlobalConfiguration` развернут и ANIC использует его.
   - Откройте порт 5353 как для TCP-, так и для UDP-трафика.
2. Сохраните публичный IP-адрес ANIC в переменной оболочки:
   ```console
   $ IC_IP=<ваш_IP-адрес>
   ```
3. Сохраните порт 5353, используемый ANIC, в переменной оболочки:
   ```console
   $ IC_5353_PORT=<номер порта>
   ```

   #### NOTE
   Если вы хотите настроить ANIC с помощью сервиса `LoadBalancer`, то в нем нельзя использовать
   протоколы TCP и UDP одновременно.
   В этом случае создайте два отдельных сервиса: для TCP и для UDP.
   Соответственно, у вас будет два разных публичных IP-адреса (см. примеры на последнем шаге).
4. Убедитесь, что у вас установлена утилита `dig` (используется для тестирования).

   #### NOTE
   В процессе установки ANIC ресурс `GlobalConfiguration` должен
   быть развернут в пространстве имен `angie-ingress` с именем `angie-configuration`.
   Если это не так, обновите файл `global-configuration.yaml`, правильно указав пространство имен и имя.

## Балансировка TCP/UDP-трафика

1. Разверните DNS-сервер:
   - Разверните две реплики `CoreDNS`, настроенные на пересылку DNS-запросов на `8.8.8.8`.
   - Создайте сервис `coredns`, который откроет порт 5353 как для TCP, так и для UDP.

   ```yaml
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: coredns
   data:
     Corefile: |
       .:5353 {
         forward . 8.8.8.8:53
         log
       }
   ---
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: coredns
   spec:
     replicas: 2
     selector:
       matchLabels:
         app: coredns
     template:
       metadata:
         labels:
           app: coredns
       spec:
         containers:
         - name: coredns
           image: coredns/coredns:1.10.0
           args: [ "-conf", "/etc/coredns/Corefile" ]
           volumeMounts:
           - name: config-volume
             mountPath: /etc/coredns
             readOnly: true
           ports:
           - containerPort: 5353
             name: dns
             protocol: UDP
           - containerPort: 5353
             name: dns-tcp
             protocol: TCP
           securityContext:
             readOnlyRootFilesystem: true
         volumes:
           - name: config-volume
             configMap:
               name: coredns
               items:
               - key: Corefile
                 path: Corefile
   ---
   apiVersion: v1
   kind: Service
   metadata:
     name: coredns
   spec:
     selector:
      app: coredns
     ports:
     - name: dns
       port: 5353
       protocol: UDP
     - name: dns-tcp
       port: 5353
       protocol: TCP
   ```

   Примените настройки:
   ```console
   $ kubectl apply -f dns.yaml
   ```
2. Настройте слушатели.

   Обновите ресурс `GlobalConfiguration`, добавив два слушателя: один для TCP-порта 5353 и один для UDP-порта 5353:
   ```yaml
   apiVersion: k8s.angie.software/v1alpha1
   kind: GlobalConfiguration
   metadata:
     name: angie-configuration
     namespace: angie-ingress
   spec:
     listeners:
     - name: dns-udp
       port: 5353
       protocol: UDP
     - name: dns-tcp
       port: 5353
       protocol: TCP
   ```

   Примените настройки:
   ```console
   $ kubectl apply -f global-configuration.yaml
   ```
3. Проверьте, что конфигурация успешно применена, просмотрев события `GlobalConfiguration`:
   ```console
   $ kubectl describe gc angie-configuration -n angie-ingress
   ```

   Пример вывода:
   ```console
   Events:
     Type    Reason   Age               From  Message
     ----    ------   ----              ----  -------
     Normal  Updated  0s (x2 over 10s)  anic  GlobalConfiguration anic/angie-configuration was updated
   ```
4. Настройте балансировку нагрузки.

   Создайте ресурс `TransportServer`, чтобы настроить балансировку TCP:
   ```yaml
   apiVersion: k8s.angie.software/v1alpha1
   kind: TransportServer
   metadata:
     name: dns-tcp
   spec:
     listener:
       name: dns-tcp
       protocol: TCP
     upstreams:
     - name: dns-app
       service: coredns
       port: 5353
     action:
       pass: dns-app
   ```

   Примените настройки:
   ```console
   $ kubectl apply -f transport-server-tcp.yaml
   ```
5. Проверьте, что конфигурация успешно применена:
   ```console
   $ kubectl describe ts dns-tcp
   ```

   Пример вывода:
   ```console
   Events:
     Type    Reason          Age   From  Message
     ----    ------          ----  ----  -------
     Normal  AddedOrUpdated  3s    anic  Configuration for default/dns-tcp was added or updated
   ```
6. Создайте ресурс `TransportServer`, чтобы настроить балансировку UDP:
   ```yaml
   apiVersion: k8s.angie.software/v1alpha1
   kind: TransportServer
   metadata:
     name: dns-udp
   spec:
     listener:
       name: dns-udp
       protocol: UDP
     upstreams:
     - name: dns-app
       service: coredns
       port: 5353
     upstreamParameters:
       udpRequests: 1
       udpResponses: 1
     action:
       pass: dns-app
   ```

   Примените настройки:
   ```console
   $ kubectl apply -f transport-server-udp.yaml
   ```
7. Проверьте, что конфигурация успешно применена:
   ```console
   $ kubectl describe ts dns-udp
   ```

   Пример вывода:
   ```console
   Events:
     Type    Reason          Age   From  Message
     ----    ------          ----  ----  -------
     Normal  AddedOrUpdated  0s    anic  Configuration for default/dns-udp was added or updated
   ```
8. Протестируйте конфигурацию.

   Чтобы проверить, что настроенный балансировщик нагрузки TCP/UDP работает, разрешите DNS-имя `kubernetes.io` с помощью DNS-сервера.

   Разрешение `kubernetes.io` через TCP:
   ```shell
   $ dig @$IC_IP -p $IC_5353_PORT kubernetes.io +tcp

   ; <<>> DiG 9.10.3-P4-Debian <<>> @<REDACTED> -p 5353 kubernetes.io +tcp
   ; (1 server found)
   ;; global options: +cmd
   ;; Got answer:
   ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44784
   ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

   ;; OPT PSEUDOSECTION:
   ; EDNS: version: 0, flags:; udp: 4096
   ;; QUESTION SECTION:
   ;kubernetes.io.                 IN      A

   ;; ANSWER SECTION:
   kubernetes.io.          3596    IN      A       147.75.40.148

   ;; Query time: 134 msec
   ;; SERVER: <REDACTED>#5353(<REDACTED>)
   ;; WHEN: Thu Mar 12 22:01:55 UTC 2020
   ;; MSG SIZE  rcvd: 71
   ```

   Разрешение `kubernetes.io` через UDP:
   ```shell
   $ dig @$IC_IP -p $IC_5353_PORT kubernetes.io

   ; <<>> DiG 9.10.3-P4-Debian <<>> @<REDACTED> -p 5353 kubernetes.io
   ; (1 server found)
   ;; global options: +cmd
   ;; Got answer:
   ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39087
   ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

   ;; OPT PSEUDOSECTION:
   ; EDNS: version: 0, flags:; udp: 4096
   ;; QUESTION SECTION:
   ;kubernetes.io.                 IN      A

   ;; ANSWER SECTION:
   kubernetes.io.          2157    IN      A       147.75.40.148

   ;; Query time: 134 msec
   ;; SERVER: <REDACTED>#5353(<REDACTED>)
   ;; WHEN: Thu Mar 12 22:02:12 UTC 2020
   ;; MSG SIZE  rcvd: 71
   ```
