NICによるTCP/UDPの通信制御

この章では、実際にデプロイしたNGINX Ingress Controllerを使い、TCP/UDPのアプリケーションに対する通信制御方法を確認します 設定例は NGINX Inc GitHubの examples/custom-resources/ に管理されております

TCP / UDP の分散設定

TCP / UDP を分散するためアプリケーションをデプロイします

https://github.com/nginxinc/kubernetes-ingress/tree/v3.1.1/examples/custom-resources/basic-tcp-udp

Deployment、NodePortの内容を修正しデプロイ

TCP / UDP を分散するため、NGINX Ingress Controller のDeployment、NodePortの内容を修正しデプロイします。 Deploymentのargsで指定するパラメータの詳細は Command-line Arguments を参照してください

cd ~/kubernetes-ingress/deployments
cp deployment/nginx-plus-ingress.yaml deployment/nginx-plus-ingress-tcpudp.yaml
vi deployment/nginx-plus-ingress-tcpudp.yaml

コメントを付与した行を参考に適切な内容に修正してください

deployment/nginx-plus-ingress-tcpudp.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
** 省略 **
spec:
   serviceAccountName: nginx-ingress
   containers:
   - image: registry.example.com/root/nic/nginxplus-ingress-nap-dos:2.1.0
   imagePullPolicy: IfNotPresent
   name: nginx-plus-ingress
   ports:
   - name: dns-tcp         # DNS TCP を有効にします
     containerPort: 5353
   - name: dns-udp         # DNS UDP を有効にします
     containerPort: 53
     protocol: UDP
   #- name: http
   #  containerPort: 80
   #- name: https
   #  containerPort: 443
** 省略 **
    args:
      - -nginx-plus
      - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
      - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
     #- -enable-app-protect
     #- -enable-app-protect-dos
     #- -v=3 # Enables extensive logging. Useful for troubleshooting.
     #- -report-ingress-status
     #- -external-service=nginx-ingress
     #- -enable-prometheus-metrics
      - -global-configuration=$(POD_NAMESPACE)/nginx-configuration # Global Configuration を有効にします

単一のNodePortでTCP/UDP双方を設定できないため、2つのファイルに分けて設定します。

## cd ~/kubernetes-ingress/deployments
cp service/nodeport.yaml  service/nodeport-tcp.yaml
vi service/nodeport-tcp.yaml

以下の内容を参考に修正してください。

service/nodeport-tcp.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  type: NodePort
  ports:
  - port: 5353        # DNS TCP を有効にします (ファイルからDNS UDPを削除します)
    targetPort: 5353
    protocol: TCP
    name: dns-tcp
  selector:
    app: nginx-ingress
## cd ~/kubernetes-ingress/deployments
cp service/nodeport.yaml  service/nodeport-udp.yaml
vi service/nodeport-udp.yaml

以下の内容を参考に修正してください。

service/nodeport-udp.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-udp
  namespace: nginx-ingress
spec:
  type: NodePort
  ports:
  - port: 53        # DNS UDP のポート番号を変更します (ファイルからDNS TCPを削除します)
    targetPort: 53
    protocol: UDP
    name: dns-udp
  selector:
    app: nginx-ingress

TCP/UDPではGlobal Configurationにより外部から通信を待ち受ける設定を行います

cd ~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp/
cp global-configuration.yaml  global-configuration.yaml-bak
vi global-configuration.yaml

以下の内容を参考に修正してください。

global-configuration.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
apiVersion: k8s.nginx.org/v1alpha1
kind: GlobalConfiguration
metadata:
  name: nginx-configuration
  namespace: nginx-ingress
spec:
  listeners:
  - name: dns-udp
    port: 53       # DNS UDP のポート番号を 5353 -> 53 に変更
    protocol: UDP
  - name: dns-tcp
    port: 5353
    protocol: TCP

その他、NGINX Ingress ControlleでTCP/UDPを転送するための設定、サンプルアプリケーションを確認します。

TCPの設定です。Kindで TransportServer を指定します。

transport-server-tcp.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: k8s.nginx.org/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

UDPの設定です。TCPとほぼ同様です

transport-server-udp.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: k8s.nginx.org/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

サンプルアプリケーションです。TCP/UDP共に5353で通信を待ち受けます。またDNSを 8.8.8.8:53 へと転送する動作となります。

修正した内容、各種リソースをデプロイします。 デプロイする内容に応じてディレクトリが変更となりますので注意ください

~/kubernetes-ingress/deployments 配下の内容を設定してください。(NICのDeployment, NodePort)

cd ~/kubernetes-ingress/deployments
kubectl apply -f service/nodeport-tcp.yaml
kubectl apply -f service/nodeport-udp.yaml
kubectl apply -f deployment/nginx-plus-ingress-tcpudp.yaml

~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp 配下の内容を設定してください。(サンプルアプリケーション、分散設定等)

cd ~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp
kubectl apply -f global-configuration.yaml
kubectl apply -f dns.yaml
kubectl apply -f transport-server-tcp.yaml
kubectl apply -f transport-server-udp.yaml

デプロイしたNodePortの内容を確認し、TCP/UDPの待ち受けているポートに対してリクエストを転送するようNGINXの設定を変更します。

kubectl get svc -n nginx-ingress
実行結果サンプル
1
2
3
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
nginx-ingress            NodePort    10.108.250.160   <none>        5353:30292/TCP   6d14h
nginx-ingress-udp        NodePort    10.99.147.245    <none>        53:31482/UDP     16m

確認したNode Portで割り当てられたポート番号宛に通信を転送するように、NGINXを設定します。 転送するポート番号は、環境に合わせて適切に変更してください。

cd ~/
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf-
cat << EOF > nginx.conf
user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
   worker_connections  1024;
}


# TCP/UDP load balancing
#
stream {
   upstream tcp5353_backend {
      server node1:30292;    # DNS TCP(TCP/5353)に割り当てられたポート番号
   }
   upstream udp53_backend {
      server node1:31482;     # DNS UDP(UDP/53)に割り当てられたポート番号
   }

   server {
      listen 5353;            # DNS TCPを(TCP/5353)で待ち受けます
      proxy_pass tcp5353_backend;
   }
   server {
      listen 53 udp;          # DNS UDPを(UDP/53)で待ち受けます
      proxy_pass udp53_backend;
   }
}
EOF
sudo cp nginx.conf /etc/nginx/nginx.conf
sudo nginx -s reload

デプロイした結果の確認

kubectl get pod -n nginx-ingress | grep nginx-ingress
実行結果サンプル
1
nginx-ingress-68949d7f46-qh9kp        1/1     Running   0             4s

NGINX Ingress ControllerのPodの詳細を確認します

## pod名は、kuebctl get pod -n nginx-ingress の出力結果を参照してください
kubectl describe pod nginx-ingress-68949d7f46-qh9kp -n nginx-ingress
実行結果サンプル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
** 省略 **

Containers:
  nginx-plus-ingress:
    Container ID:  docker://f1aa9d4434ebda4817f9ff957987120c85808bcdcb9d64978e76814c20e422fe
    Image:         registry.example.com/root/nic/nginxplus-ingress-nap-dos:2.1.0
    Image ID:      docker-pullable://registry.example.com/root/nic/nginxplus-ingress-nap-dos@sha256:8c9a8ce1cdda45c2a289cb20ce37a60e25b4d4669c2c9c9d4d0831c353c6c668
    Ports:         5353/TCP, 53/UDP, 8081/TCP, 9113/TCP
    Host Ports:    0/TCP, 0/UDP, 0/TCP, 0/TCP
    Args:
      -nginx-plus
      -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
      -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
      -global-configuration=$(POD_NAMESPACE)/nginx-configuration
    State:          Running

** 省略 **

TCPは 5353/TCP 、UDP 53/UDP となっていることが確認できます。また global-configuration のargsが正しく記載されています

kubectl get globalconfiguration -n nginx-ingress
実行結果サンプル
1
2
NAME                  AGE
nginx-configuration   8m3s
kubectl get svc coredns
実行結果サンプル
1
2
NAME      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
coredns   ClusterIP   10.101.115.180   <none>        5353/UDP,5353/TCP   2m41s
kubectl get pod | grep coredns
実行結果サンプル
1
2
coredns-75466b69b7-8b7r5   1/1     Running   0              3m29s
coredns-75466b69b7-8tgrc   1/1     Running   0              3m29s

先程確認したとおり、TCP/UDPそれぞれのNodePortの内容が確認できます

kubectl get svc -n nginx-ingress
実行結果サンプル
1
2
3
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
nginx-ingress            NodePort    10.108.250.160   <none>        5353:30292/TCP   6d14h
nginx-ingress-udp        NodePort    10.99.147.245    <none>        53:31482/UDP     16m

動作確認

TCP/UDPのそれぞれで kubernetes.io の名前解決を行います。NGINX Ingress ControllerへQueryを送信します。

TCPでDNS Queryを送信します。Portは 5353 です。

dig node1 -p 5353  kubernetes.io +tcp
実行結果サンプル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
; <<>> DiG 9.16.1-Ubuntu <<>> node1 -p 5353 kubernetes.io +tcp
;; global options: +cmd
;; connection timed out; no servers could be reached

;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28171
;; 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.          2474    IN      A       147.75.40.148

;; Query time: 23 msec
;; SERVER: 127.0.0.53#5353(127.0.0.53)
;; WHEN: Fri Jan 21 06:46:38 UTC 2022
;; MSG SIZE  rcvd: 71

.. code-block:: cmdin

UDPでDNS Queryを送信します。Portは 53 です。

dig node1 -p 53  kubernetes.io
実行結果サンプル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
; <<>> DiG 9.16.1-Ubuntu <<>> node1 -p 53 kubernetes.io
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2308
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;node1.                         IN      A

;; ANSWER SECTION:
node1.                  0       IN      A       10.1.1.9

;; Query time: 3 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Fri Jan 21 06:46:48 UTC 2022
;; MSG SIZE  rcvd: 50

;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22877
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

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

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

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Fri Jan 21 06:46:48 UTC 2022
;; MSG SIZE  rcvd: 58

リソースの削除

サンプルアプリケーション、及び分散設定を削除します

cd ~/kubernetes-ingress/examples/custom-resources/basic-tcp-udp
kubectl delete -f global-configuration.yaml
kubectl delete -f dns.yaml
kubectl delete -f transport-server-tcp.yaml
kubectl delete -f transport-server-udp.yaml

HTTP/HTTPSを待ち受ける設定に戻す場合、以下の操作を参考に実施してください。

NGINXの設定については、再度デプロイの後、待受のポート番号を確認して適切にnginx.confを変更してください。
手順は以下を参照してください。
cd ~/kubernetes-ingress/deployments
kubectl delete -f service/nodeport-tcp.yaml
kubectl delete -f service/nodeport-udp.yaml
kubectl delete -f deployment/nginx-plus-ingress-tcpudp.yaml

kubectl apply -f service/nodeport.yaml
kubectl apply -f deployment/nginx-plus-ingress.yaml
## 手順を参考にnginx.confを変更してください