ื”ื’ื™ืจื” ืž-Nginx ืœ-Envoy Proxy

ืฉืœื•ื, ื”ื‘ืจ! ืื ื™ ืžื‘ื™ื ืœื™ื“ื™ืขืชืš ืชืจื’ื•ื ืฉืœ ื”ืคื•ืกื˜: ื”ื’ื™ืจื” ืž-Nginx ืœ-Envoy Proxy.

Envoy ื”ื•ื ืฉืจืช ืคืจื•ืงืกื™ ืžื‘ื•ื–ืจ ื‘ืขืœ ื‘ื™ืฆื•ืขื™ื ื’ื‘ื•ื”ื™ื (ื›ืชื•ื‘ ื‘-C++) ื”ืžื™ื•ืขื“ ืœืฉื™ืจื•ืชื™ื ื•ื™ื™ืฉื•ืžื™ื ื‘ื•ื“ื“ื™ื, ื”ื•ื ื’ื ืืคื™ืง ืชืงืฉื•ืจืช ื•"ืžื™ืฉื•ืจ ื ืชื•ื ื™ื ืื•ื ื™ื‘ืจืกืœื™" ื”ืžื™ื•ืขื“ ืœืืจื›ื™ื˜ืงื˜ื•ืจื•ืช "ืจืฉืช ืฉื™ืจื•ืช" ื’ื“ื•ืœื•ืช ืฉืœ ืžื™ืงืจื•-ืฉื™ืจื•ืชื™ื. ื‘ืขืช ื™ืฆื™ืจืชื• ื ืœืงื—ื• ื‘ื—ืฉื‘ื•ืŸ ืคืชืจื•ื ื•ืช ืœื‘ืขื™ื•ืช ืฉืขืœื• ื‘ืžื”ืœืš ืคื™ืชื•ื— ืฉืจืชื™ื ื›ื’ื•ืŸ NGINX, HAProxy, ื—ื•ืžืจื” ืžืื–ื ื™ ืขื•ืžืกื™ื ื•ืžืื–ื ื™ ืขื•ืžืก ื‘ืขื ืŸ. Envoy ืคื•ืขืœืช ืœืฆื“ ื›ืœ ืืคืœื™ืงืฆื™ื” ื•ืžืคืฉื˜ืช ืืช ื”ืจืฉืช ื›ื“ื™ ืœืกืคืง ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ืžืฉื•ืชืคืช ืœืœื ืงืฉืจ ืœืคืœื˜ืคื•ืจืžื”. ื›ืืฉืจ ื›ืœ ืชืขื‘ื•ืจืช ื”ืฉื™ืจื•ืช ื‘ืชืฉืชื™ืช ื–ื•ืจืžืช ื“ืจืš ืจืฉืช Envoy, ืงืœ ืœื“ืžื™ื™ืŸ ืื–ื•ืจื™ื ื‘ืขื™ื™ืชื™ื™ื ืขื ืฆืคื™ื™ื” ืขืงื‘ื™ืช, ืœื›ื•ื•ืŸ ืืช ื”ื‘ื™ืฆื•ืขื™ื ื”ื›ื•ืœืœื™ื ื•ืœื”ื•ืกื™ืฃ ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ืœื™ื‘ื” ื‘ืžื™ืงื•ื ืกืคืฆื™ืคื™.

ื™ื›ื•ืœื•ืช

  • ืืจื›ื™ื˜ืงื˜ื•ืจื” ืžื—ื•ืฅ ืœืชื”ืœื™ืš: envoy ื”ื•ื ืฉืจืช ืขืฆืžืื™, ื‘ืขืœ ื‘ื™ืฆื•ืขื™ื ื’ื‘ื•ื”ื™ื, ืืฉืจ ืชื•ืคืก ื›ืžื•ืช ืงื˜ื ื” ืฉืœ ื–ื™ื›ืจื•ืŸ RAM. ื–ื” ืขื•ื‘ื“ ื‘ืฉื™ืœื•ื‘ ืขื ื›ืœ ืฉืคืช ื™ื™ืฉื•ื ืื• ืžืกื’ืจืช.
  • ืชืžื™ื›ื” ื‘-http/2 ื•-grpc: ืœ-envoy ื™ืฉ ืชืžื™ื›ื” ื‘-http/2 ื•-grpc ืžื”ืฉื•ืจื” ื”ืจืืฉื•ื ื” ืขื‘ื•ืจ ื—ื™ื‘ื•ืจื™ื ื ื›ื ืกื™ื ื•ื™ื•ืฆืื™ื. ื–ื”ื• ืคืจื•ืงืกื™ ืฉืงื•ืฃ ืž-http/1.1 ืœ-http/2.
  • ืื™ื–ื•ืŸ ืขื•ืžืกื™ื ืžืชืงื“ื: ื”ืฉืœื™ื— ืชื•ืžืš ื‘ืชื›ื•ื ื•ืช ืžืชืงื“ืžื•ืช ืฉืœ ืื™ื–ื•ืŸ ืขื•ืžืกื™ื ื›ื•ืœืœ ื ื™ืกื™ื•ื ื•ืช ื—ื•ื–ืจื™ื ืื•ื˜ื•ืžื˜ื™ื™ื, ืฉื‘ื™ืจืช ืฉืจืฉืจืช, ื”ื’ื‘ืœืช ืชืขืจื™ืคื™ื ื’ืœื•ื‘ืœื™ืช, ื”ืฆืœืœืช ื‘ืงืฉื•ืช, ืื™ื–ื•ืŸ ืขื•ืžืก ืื–ื•ืจื™ ืžืงื•ืžื™ ื•ื›ื•'.
  • API ืœื ื™ื”ื•ืœ ืชืฆื•ืจื”: envoy ืžืกืคืง API ื—ื–ืง ืœื ื™ื”ื•ืœ ื“ื™ื ืžื™ ืฉืœ ื”ืชืฆื•ืจื” ืฉืœืš.
  • ืฆืคื™ื™ื”: ืฆืคื™ื•ืช ืขืžื•ืงื” ืฉืœ ืชืขื‘ื•ืจืช L7, ืชืžื™ื›ื” ืžืงื•ืจื™ืช ืœืžืขืงื‘ ื•ืฆืคื™ื™ื” ืžื‘ื•ื–ืจ ืฉืœ mongodb, dynamodb ื•ื™ื™ืฉื•ืžื™ื ืจื‘ื™ื ืื—ืจื™ื.

ืฉืœื‘ 1 - ื“ื•ื’ืžื” ืœืชืฆื•ืจืช NGINX

ืกืงืจื™ืคื˜ ื–ื” ืžืฉืชืžืฉ ื‘ืงื•ื‘ืฅ ื‘ืขืœ ืžื‘ื ื” ืžื™ื•ื—ื“ nginx.conf, ื‘ื”ืชื‘ืกืก ืขืœ ื”ื“ื•ื’ืžื” ื”ืžืœืื” ืž NGINX Wiki. ืืชื” ื™ื›ื•ืœ ืœื”ืฆื™ื’ ืืช ื”ืชืฆื•ืจื” ื‘ืขื•ืจืš ืขืœ ื™ื“ื™ ืคืชื™ื—ื” nginx.conf

ืชืฆื•ืจืช ื”ืžืงื•ืจ ืฉืœ nginx

user  www www;
pid /var/run/nginx.pid;
worker_processes  2;

events {
  worker_connections   2000;
}

http {
  gzip on;
  gzip_min_length  1100;
  gzip_buffers     4 8k;
  gzip_types       text/plain;

  log_format main      '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$gzip_ratio"';

  log_format download  '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$http_range" "$sent_http_content_range"';

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

  server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

    access_log   /var/log/nginx.access_log  main;
    error_log  /var/log/nginx.error_log  info;

    location / {
      proxy_pass         http://targetCluster/;
      proxy_redirect     off;

      proxy_set_header   Host             $host;
      proxy_set_header   X-Real-IP        $remote_addr;
    }
  }
}

ืœืชืฆื•ืจื•ืช NGINX ื™ืฉ ื‘ื“ืจืš ื›ืœืœ ืฉืœื•ืฉื” ืžืจื›ื™ื‘ื™ ืžืคืชื—:

  1. ื”ื’ื“ืจืช ืฉืจืช NGINX, ืžื‘ื ื” ื™ื•ืžืŸ ื•ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช Gzip. ื–ื” ืžื•ื’ื“ืจ ื‘ืื•ืคืŸ ื’ืœื•ื‘ืœื™ ื‘ื›ืœ ื”ืžืงืจื™ื.
  2. ื”ื’ื“ืจืช NGINX ืœืงื‘ืœืช ื‘ืงืฉื•ืช ืœืžืืจื— one.example.com ื‘ื™ืฆื™ืื” 8080.
  3. ื”ื’ื“ืจืช ืžื™ืงื•ื ื”ื™ืขื“, ื›ื™ืฆื“ ืœื˜ืคืœ ื‘ืชื ื•ืขื” ืขื‘ื•ืจ ื—ืœืงื™ื ืฉื•ื ื™ื ืฉืœ ื›ืชื•ื‘ืช ื”ืืชืจ.

ืœื ื›ืœ ื”ืชืฆื•ืจื” ืชื—ื•ืœ ืขืœ Envoy Proxy, ื•ืืชื” ืœื ืฆืจื™ืš ืœื”ื’ื“ื™ืจ ื”ื’ื“ืจื•ืช ืžืกื•ื™ืžื•ืช. ืฉืœื™ื— ืคืจื•ืงืกื™ ื™ืฉ ืืจื‘ืขื” ืกื•ื’ื™ ืžืคืชื—, ื”ืชื•ืžื›ื™ื ื‘ืชืฉืชื™ืช ื”ืœื™ื‘ื” ืฉืžืฆื™ืขื” NGINX. ื”ืœื™ื‘ื” ื”ื™ื:

  • ืžืื–ื™ื ื™ื: ื”ื ืงื•ื‘ืขื™ื ื›ื™ืฆื“ ื”-Envoy Proxy ืžืงื‘ืœ ื‘ืงืฉื•ืช ื ื›ื ืกื•ืช. Envoy Proxy ืชื•ืžืš ื›ืจื’ืข ืจืง ื‘ืžืื–ื™ื ื™ื ืžื‘ื•ืกืกื™ TCP. ืœืื—ืจ ื™ืฆื™ืจืช ื—ื™ื‘ื•ืจ, ื”ื•ื ืžื•ืขื‘ืจ ืœืžืขืจื›ืช ืฉืœ ืžืกื ื ื™ื ืœืขื™ื‘ื•ื“.
  • ืžืกื ื ื™ื: ื”ื ื—ืœืง ืžืืจื›ื™ื˜ืงื˜ื•ืจืช ืฆื™ื ื•ืจ ืฉื™ื›ื•ืœื” ืœืขื‘ื“ ื ืชื•ื ื™ื ื ื›ื ืกื™ื ื•ื™ื•ืฆืื™ื. ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ื–ื• ื›ื•ืœืœืช ืžืกื ื ื™ื ื›ื’ื•ืŸ Gzip, ืืฉืจ ื“ื•ื—ืก ืืช ื”ื ืชื•ื ื™ื ืœืคื ื™ ืฉืœื™ื—ืชื ืœืœืงื•ื—.
  • ื ืชื‘ื™ื: ื”ื ืžืขื‘ื™ืจื™ื ืชื ื•ืขื” ืœื™ืขื“ ื”ื ื“ืจืฉ, ื”ืžื•ื’ื“ืจ ื›ืืฉื›ื•ืœ.
  • ืืฉื›ื•ืœื•ืช: ื”ื ืžื’ื“ื™ืจื™ื ืืช ื ืงื•ื“ืช ื”ืงืฆื” ืขื‘ื•ืจ ืคืจืžื˜ืจื™ ืชืขื‘ื•ืจื” ื•ืชืฆื•ืจื”.

ืื ื• ื ืฉืชืžืฉ ื‘ืืจื‘ืขืช ื”ืจื›ื™ื‘ื™ื ื”ืœืœื• ื›ื“ื™ ืœื™ืฆื•ืจ ืชืฆื•ืจืช Proxy ืฉืœ Envoy ืฉืชืชืื™ื ืœืชืฆื•ืจืช NGINX ืกืคืฆื™ืคื™ืช. ื”ืžื˜ืจื” ืฉืœ Envoy ื”ื™ื ืœืขื‘ื•ื“ ืขื ืžืžืฉืงื™ API ื•ืชืฆื•ืจื” ื“ื™ื ืžื™ืช. ื‘ืžืงืจื” ื–ื”, ืชืฆื•ืจืช ื”ื‘ืกื™ืก ืชืฉืชืžืฉ ื‘ื”ื’ื“ืจื•ืช ืกื˜ื˜ื™ื•ืช ืขื ืงื™ื“ื•ื“ ืงืฉื™ื— ืž-NGINX.

ืฉืœื‘ 2 - ืชืฆื•ืจืช NGINX

ื”ื—ืœืง ื”ืจืืฉื•ืŸ nginx.conf ืžื’ื“ื™ืจ ื›ืžื” ืจื›ื™ื‘ื™ื ืคื ื™ืžื™ื™ื ืฉืœ NGINX ืฉื™ืฉ ืœื”ื’ื“ื™ืจ.

ืงืฉืจื™ ืขื•ื‘ื“ื™ื

ื”ืชืฆื•ืจื” ืฉืœื”ืœืŸ ืงื•ื‘ืขืช ืืช ืžืกืคืจ ืชื”ืœื™ื›ื™ ื”ืขื‘ื•ื“ื” ื•ื”ื—ื™ื‘ื•ืจื™ื. ื–ื” ืžืฆื™ื™ืŸ ื›ื™ืฆื“ NGINX ื™ืชืื™ื ืœื‘ื™ืงื•ืฉ.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy ืžื ื”ืœ ื–ืจื™ืžื•ืช ืขื‘ื•ื“ื” ื•ื—ื™ื‘ื•ืจื™ื ื‘ื“ืจื›ื™ื ืฉื•ื ื•ืช.

Envoy ื™ื•ืฆืจ ืฉืจืฉื•ืจ ืขื•ื‘ื“ ืขื‘ื•ืจ ื›ืœ ืฉืจืฉื•ืจ ื—ื•ืžืจื” ื‘ืžืขืจื›ืช. ื›ืœ ืฉืจืฉื•ืจ ืขื•ื‘ื“ ืžื‘ืฆืข ืœื•ืœืืช ืื™ืจื•ืข ืœื ื—ื•ืกืžืช ืฉืื—ืจืื™ ืขืœื™ื”

  1. ืžืงืฉื™ื‘ ืœื›ืœ ืžืื–ื™ืŸ
  2. ืงื‘ืœืช ืงืฉืจื™ื ื—ื“ืฉื™ื
  3. ื™ืฆื™ืจืช ืงื‘ื•ืฆืช ืžืกื ื ื™ื ืœื—ื™ื‘ื•ืจ
  4. ืขื‘ื“ ืืช ื›ืœ ืคืขื•ืœื•ืช ื”-I/O ื‘ืžื”ืœืš ื—ื™ื™ ื”ื—ื™ื‘ื•ืจ.

ื›ืœ ืขื™ื‘ื•ื“ ื”ื—ื™ื‘ื•ืจื™ื ื”ื ื•ืกืฃ ืžื˜ื•ืคืœ ื‘ืžืœื•ืื• ื‘ืฉืจืฉื•ืจ ื”ืขื•ื‘ื“, ื›ื•ืœืœ ื›ืœ ื”ืชื ื”ื’ื•ืช ื”ืขื‘ืจื”.

ืœื›ืœ ื—ื•ื˜ ืขื•ื‘ื“ื™ื ื‘-Envoy ื™ืฉ ืžืื’ืจ ื—ื™ื‘ื•ืจื™ื. ืื– ืžืื’ืจื™ ื—ื™ื‘ื•ืจ HTTP/2 ืžืงื™ืžื™ื ืจืง ื—ื™ื‘ื•ืจ ืื—ื“ ืœื›ืœ ืžืืจื— ื—ื™ืฆื•ื ื™ ื‘ื›ืœ ืคืขื, ืื ื™ืฉ ืืจื‘ืขื” ืฉืจืฉื•ืจื™ ืขื•ื‘ื“ื™ื ื™ื”ื™ื• ืืจื‘ืขื” ื—ื™ื‘ื•ืจื™ HTTP/2 ืœื›ืœ ืžืืจื— ื—ื™ืฆื•ื ื™ ื‘ืžืฆื‘ ื™ืฆื™ื‘. ืขืœ ื™ื“ื™ ืฉืžื™ืจื” ืขืœ ื”ื›ืœ ื‘ืฉืจืฉื•ืจ ืขื•ื‘ื“ ืื—ื“, ื›ืžืขื˜ ื›ืœ ื”ืงื•ื“ ื™ื›ื•ืœ ืœื”ื™ื›ืชื‘ ืœืœื ื—ืกื™ืžื”, ื›ืื™ืœื• ื”ื™ื” ืฉืจืฉื•ืจ ื‘ื•ื“ื“. ืื ืžื•ืงืฆื™ื ื™ื•ืชืจ ืฉืจืฉื•ืจื™ ืขื•ื‘ื“ื™ื ืžื”ื ื“ืจืฉ, ื”ื“ื‘ืจ ืขืœื•ืœ ืœื”ื•ื‘ื™ืœ ืœื‘ื–ื‘ื•ื– ื–ื™ื›ืจื•ืŸ, ื™ืฆื™ืจืช ืžืกืคืจ ืจื‘ ืฉืœ ื—ื™ื‘ื•ืจื™ื ืกืจืง, ื•ื”ืคื—ืชืช ืžืกืคืจ ื”ืคืขืžื™ื ืฉื—ื™ื‘ื•ืจื™ื ืžื•ื—ื–ืจื™ื ื‘ื—ื–ืจื” ืœื‘ืจื™ื›ื”.

ืœืžื™ื“ืข ื ื•ืกืฃ ื‘ืงืจื• ื‘ืืชืจ ื”ื‘ืœื•ื’ ืฉืœ ืฉืœื™ื— ืคืจื•ืงืกื™.

ืชืฆื•ืจืช HTTP

ื‘ืœื•ืง ื”ืชืฆื•ืจื” ื”ื‘ื ืฉืœ NGINX ืžื’ื“ื™ืจ ื”ื’ื“ืจื•ืช HTTP ื›ื’ื•ืŸ:

  • ืื™ืœื• ืกื•ื’ื™ ืคื ื˜ื•ืžื™ืžืื™ ื ืชืžื›ื™ื
  • ื‘ืจื™ืจืช ื”ืžื—ื“ืœ ืฉืœ ืคืกืง ื–ืžืŸ
  • ืชืฆื•ืจืช Gzip

ืืชื” ื™ื›ื•ืœ ืœื”ืชืื™ื ืื™ืฉื™ืช ืืช ื”ื”ื™ื‘ื˜ื™ื ื”ืืœื” ื‘ืืžืฆืขื•ืช ืžืกื ื ื™ื ื‘-Envoy Proxy, ืฉื‘ื• ื ื“ื•ืŸ ื‘ื”ืžืฉืš.

ืฉืœื‘ 3 - ืชืฆื•ืจืช ืฉืจืช

ื‘ื‘ืœื•ืง ืชืฆื•ืจืช HTTP, ืชืฆื•ืจืช NGINX ืžืฆื™ื™ื ืช ืœื”ืื–ื™ืŸ ื‘ื™ืฆื™ืื” 8080 ื•ืœื”ื’ื™ื‘ ืœื‘ืงืฉื•ืช ื ื›ื ืกื•ืช ืœื“ื•ืžื™ื™ื ื™ื one.example.com ะธ www.one.example.com.

 server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

ื‘ืชื•ืš Envoy, ื”ื•ื ื ืฉืœื˜ ืขืœ ื™ื“ื™ ืžืื–ื™ื ื™ื.

ืžืื–ื™ื ื™ื ืฉืœื™ื—

ื”ื”ื™ื‘ื˜ ื”ื—ืฉื•ื‘ ื‘ื™ื•ืชืจ ื‘ื”ืชื—ืœื” ืขื Envoy Proxy ื”ื•ื ื”ื’ื“ืจืช ื”ืžืื–ื™ื ื™ื ืฉืœืš. ืขืœื™ืš ืœื™ืฆื•ืจ ืงื•ื‘ืฅ ืชืฆื•ืจื” ืฉืžืชืืจ ื›ื™ืฆื“ ื‘ืจืฆื•ื ืš ืœื”ืคืขื™ืœ ืืช ื”ืžื•ืคืข ืฉืœ Envoy.

ื”ืงื˜ืข ืฉืœืžื˜ื” ื™ื™ืฆื•ืจ ืžืื–ื™ืŸ ื—ื“ืฉ ื•ื™ืงืฉืจ ืื•ืชื• ืœื™ืฆื™ืื” 8080. ื”ืชืฆื•ืจื” ืื•ืžืจืช ืœ-Envoy Proxy ืœืื™ืœื• ื™ืฆื™ืื•ืช ื”ื•ื ืฆืจื™ืš ืœืื’ื“ ืขื‘ื•ืจ ื‘ืงืฉื•ืช ื ื›ื ืกื•ืช.

Envoy Proxy ืžืฉืชืžืฉ ื‘ืกื™ืžื•ืŸ YAML ืขื‘ื•ืจ ื”ืชืฆื•ืจื” ืฉืœื•. ืœืžื‘ื•ื ืœืกื™ืžื•ืŸ ื–ื”, ืขื™ื™ืŸ ื›ืืŸ ืงืฉืจ.

Copy to Editorstatic_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }

ืื™ืŸ ืฆื•ืจืš ืœื”ื’ื“ื™ืจ ืฉื ืฉืจืช, ืฉื›ืŸ ืžืกื ื ื™ Proxy ืฉืœ Envoy ื™ื˜ืคืœื• ื‘ื–ื”.

ืฉืœื‘ 4 - ืชืฆื•ืจืช ืžื™ืงื•ื

ื›ืฉืžื’ื™ืขื” ื‘ืงืฉื” ืœ-NGINX, ื‘ืœื•ืง ื”ืžื™ืงื•ื ืงื•ื‘ืข ื›ื™ืฆื“ ืœืขื‘ื“ ื•ืœืืŸ ืœื ืชื‘ ืืช ื”ืชืขื‘ื•ืจื”. ื‘ืคืจื’ืžื ื˜ ื”ื‘ื, ื›ืœ ื”ืชืขื‘ื•ืจื” ืœืืชืจ ืžื•ืขื‘ืจืช ืœืืฉื›ื•ืœ ื‘ืžืขืœื” (ื”ืขืจืช ื”ืžืชืจื’ื: ื‘ืžืขืœื” ื”ื–ืจื ื”ื•ื ื‘ื“ืจืš ื›ืœืœ ืฉืจืช ื™ื™ืฉื•ืžื™ื) ื‘ืฉื targetCluster. ื”ืืฉื›ื•ืœ ื‘ืžืขืœื” ื”ื–ืจื ืžื’ื“ื™ืจ ืืช ื”ืฆืžืชื™ื ืฉืฆืจื™ื›ื™ื ืœืขื‘ื“ ืืช ื”ื‘ืงืฉื”. ื ื“ื•ืŸ ื‘ื›ืš ื‘ืฉืœื‘ ื”ื‘ื.

location / {
    proxy_pass         http://targetCluster/;
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
}

ื‘-Envoy, ืคื™ืœื˜ืจื™ื ืขื•ืฉื™ื ื–ืืช.

ืžืกื ื ื™ ืฉืœื™ื—ื™ื

ืขื‘ื•ืจ ืชืฆื•ืจื” ืกื˜ื˜ื™ืช, ืžืกื ื ื™ื ืงื•ื‘ืขื™ื ื›ื™ืฆื“ ืœืขื‘ื“ ื‘ืงืฉื•ืช ื ื›ื ืกื•ืช. ื‘ืžืงืจื” ื–ื” ืื ื• ืžื’ื“ื™ืจื™ื ืžืกื ื ื™ื ืฉืžืชืื™ืžื™ื server_names ื‘ืฉืœื‘ ื”ืงื•ื“ื. ื›ืืฉืจ ืžื’ื™ืขื•ืช ื‘ืงืฉื•ืช ื ื›ื ืกื•ืช ื”ืชื•ืืžื•ืช ืชื—ื•ืžื™ื ื•ืžืกืœื•ืœื™ื ืžืกื•ื™ืžื™ื, ื”ืชืขื‘ื•ืจื” ืžื ื•ืชื‘ืช ืœืืฉื›ื•ืœ. ื–ื•ื”ื™ ื”ืžืงื‘ื™ืœื” ืœืชืฆื•ืจืช NGINX ืžืœืžื˜ื” ืœืžืขืœื”.

Copy to Editor    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router

ืฉื envoy.http_connection_manager ื”ื•ื ืžืกื ืŸ ืžื•ื‘ื ื” ื‘-Envoy Proxy. ืžืกื ื ื™ื ืื—ืจื™ื ื›ื•ืœืœื™ื Redis, Mongo, TCP. ืชื•ื›ืœ ืœืžืฆื•ื ืืช ื”ืจืฉื™ืžื” ื”ืžืœืื” ื‘ื›ืชื•ื‘ืช ืชื™ืขื•ื“.

ืœืžื™ื“ืข ื ื•ืกืฃ ืขืœ ืžื“ื™ื ื™ื•ืช ืื—ืจืช ืฉืœ ืื™ื–ื•ืŸ ืขื•ืžืกื™ื, ื‘ืงืจ ืชื™ืขื•ื“ ืฉืœื™ื—.

ืฉืœื‘ 5 - ืชืฆื•ืจืช Proxy ื•-Upstream

ื‘-NGINX, ื”ืชืฆื•ืจื” ื‘ืžืขืœื” ื”ื–ืจื ืžื’ื“ื™ืจื” ืงื‘ื•ืฆื” ืฉืœ ืฉืจืชื™ ื™ืขื“ ืฉื™ืขื‘ื“ื• ืชืขื‘ื•ืจื”. ื‘ืžืงืจื” ื–ื”, ื”ื•ืงืฆื• ืฉื ื™ ืืฉื›ื•ืœื•ืช.

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

ื‘-Envoy, ื–ื” ืžื ื•ื”ืœ ืขืœ ื™ื“ื™ ืืฉื›ื•ืœื•ืช.

ืืฉื›ื•ืœื•ืช ืฉืœื™ื—ื™ื

ื”ืžืงื‘ื™ืœื” ื‘ืžืขืœื” ื”ื–ืจื ืžื•ื’ื“ืจืช ื›ืืฉื›ื•ืœื•ืช. ื‘ืžืงืจื” ื–ื”, ื”ืžืืจื—ื™ื ืฉื™ืฉืจืชื• ืืช ื”ืชืขื‘ื•ืจื” ื–ื•ื”ื•. ืื•ืคืŸ ื”ื’ื™ืฉื” ืœืžืืจื—ื™ื, ื›ื’ื•ืŸ ืคืกืงื™ ื–ืžืŸ, ืžื•ื’ื“ืจ ื›ืชืฆื•ืจืช ืืฉื›ื•ืœ. ื–ื” ืžืืคืฉืจ ืฉืœื™ื˜ื” ืžืคื•ืจื˜ืช ื™ื•ืชืจ ืขืœ ื”ื™ื‘ื˜ื™ื ื›ืžื• ื—ื‘ื™ื•ืŸ ื•ืื™ื–ื•ืŸ ืขื•ืžืกื™ื.

Copy to Editor  clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

ื‘ืขืช ืฉื™ืžื•ืฉ ื‘ื’ื™ืœื•ื™ ืฉื™ืจื•ืช STRICT_DNS Envoy ื™ืคืชื•ืจ ื‘ืื•ืคืŸ ืจืฆื™ืฃ ื•ื-ืกื™ื ื›ืจื•ื ื™ ืืช ื™ืขื“ื™ ื”-DNS ืฉืฆื•ื™ื ื•. ื›ืœ ื›ืชื•ื‘ืช IP ืฉื”ื•ื—ื–ืจื” ืžืชื•ืฆืืช ื”-DNS ืชื™ื—ืฉื‘ ื›ืžืืจื— ืžืคื•ืจืฉ ื‘ืืฉื›ื•ืœ ื‘ืžืขืœื” ื”ื–ืจื. ื”ืžืฉืžืขื•ืช ื”ื™ื ืฉืื ื‘ืงืฉื” ืชื—ื–ื™ืจ ืฉืชื™ ื›ืชื•ื‘ื•ืช IP, Envoy ื™ื ื™ื— ืฉื™ืฉ ืฉื ื™ ืžืืจื—ื™ื ื‘ืืฉื›ื•ืœ, ื•ืฉื ื™ื”ื ื—ื™ื™ื‘ื™ื ืœื”ื™ื•ืช ืžืื•ื–ื ื™ื ื‘ืขื•ืžืก. ืื ืžืืจื— ื™ื•ืกืจ ืžื”ืชื•ืฆืื”, Envoy ื™ื ื™ื— ืฉื”ื•ื ืื™ื ื• ืงื™ื™ื ื™ื•ืชืจ ื•ืชืžืฉื•ืš ืชื ื•ืขื” ืžื›ืœ ืžืื’ืจ ื—ื™ื‘ื•ืจื™ื ืงื™ื™ืžื™ื.

ืœืžื™ื“ืข ื ื•ืกืฃ ืจืื” ืชื™ืขื•ื“ ืคืจื•ืงืกื™ ืฉืœ ื”ืฉืœื™ื—.

ืฉืœื‘ 6 - ื’ื™ืฉืช ื™ื•ืžืŸ ื•ืฉื’ื™ืื•ืช

ื”ืชืฆื•ืจื” ื”ืกื•ืคื™ืช ื”ื™ื ืจื™ืฉื•ื. ื‘ืžืงื•ื ืœื“ื—ื•ืฃ ื™ื•ืžื ื™ ืฉื’ื™ืื” ืœื“ื™ืกืง, Envoy Proxy ื ื•ืงื˜ ื‘ื’ื™ืฉื” ืžื‘ื•ืกืกืช ืขื ืŸ. ื›ืœ ื™ื•ืžื ื™ ื”ื™ื™ืฉื•ืžื™ื ืžื•ืคืœื˜ื™ื ืืœ stdout ะธ ืกื˜ื“ืจืจ.

ื›ืืฉืจ ืžืฉืชืžืฉื™ื ืžื’ื™ืฉื™ื ื‘ืงืฉื”, ื™ื•ืžื ื™ ื’ื™ืฉื” ื”ื ืื•ืคืฆื™ื•ื ืœื™ื™ื ื•ืžื•ืฉื‘ืชื™ื ื›ื‘ืจื™ืจืช ืžื—ื“ืœ. ื›ื“ื™ ืœื”ืคืขื™ืœ ื™ื•ืžื ื™ ื’ื™ืฉื” ืขื‘ื•ืจ ื‘ืงืฉื•ืช HTTP, ื”ืคืขืœ ืืช ื”ืชืฆื•ืจื” ื’ื™ืฉื”_ื‘ืœื•ื’ ืขื‘ื•ืจ ืžื ื”ืœ ื—ื™ื‘ื•ืจื™ HTTP. ื”ื ืชื™ื‘ ื™ื›ื•ืœ ืœื”ื™ื•ืช ืžื›ืฉื™ืจ ื›ื’ื•ืŸ stdout, ืื• ืงื•ื‘ืฅ ื‘ื“ื™ืกืง, ื‘ื”ืชืื ืœื“ืจื™ืฉื•ืช ืฉืœืš.

ื”ืชืฆื•ืจื” ื”ื‘ืื” ืชืคื ื” ืืช ื›ืœ ื™ื•ืžื ื™ ื”ื’ื™ืฉื” ืืœ stdout (ื”ืขืจืช ื”ืžืชืจื’ื - stdout ื ื“ืจืฉ ื›ื“ื™ ืœื”ืฉืชืžืฉ ื‘-envoy ื‘ืชื•ืš docker. ืื ืžืฉืชืžืฉื™ื ื‘ื• ืœืœื docker, ืื– ื”ื—ืœื™ืคื• ืืช /dev/stdout ื‘ื ืชื™ื‘ ืœืงื•ื‘ืฅ ื™ื•ืžืŸ ืจื’ื™ืœ). ื”ืขืชืง ืืช ืงื˜ืข ื”ืงื•ื“ ืœืžื“ื•ืจ ื”ืชืฆื•ืจื” ืฉืœ ืžื ื”ืœ ื”ื—ื™ื‘ื•ืจื™ื:

Copy to Clipboardaccess_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"

ื”ืชื•ืฆืื•ืช ืืžื•ืจื•ืช ืœื”ื™ืจืื•ืช ื›ืš:

      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          access_log:
          - name: envoy.file_access_log
            config:
              path: "/dev/stdout"
          route_config:

ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ืœ-Envoy ื™ืฉ ืžื—ืจื•ื–ืช ืคื•ืจืžื˜ ื”ื›ื•ืœืœืช ืืช ื”ืคืจื˜ื™ื ืฉืœ ื‘ืงืฉืช ื”-HTTP:

[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n

ื”ืชื•ืฆืื” ืฉืœ ืžื—ืจื•ื–ืช ืคื•ืจืžื˜ ื–ื• ื”ื™ื:

[2018-11-23T04:51:00.281Z] "GET / HTTP/1.1" 200 - 0 58 4 1 "-" "curl/7.47.0" "f21ebd42-6770-4aa5-88d4-e56118165a7d" "one.example.com" "172.18.0.4:80"

ื ื™ืชืŸ ืœื”ืชืื™ื ืื™ืฉื™ืช ืืช ืชื•ื›ืŸ ื”ืคืœื˜ ืขืœ ื™ื“ื™ ื”ื’ื“ืจืช ืฉื“ื” ื”ืคื•ืจืžื˜. ืœื“ื•ื’ืžื”:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    format: "[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n"

ื ื™ืชืŸ ืœื”ืคื™ืง ืืช ืฉื•ืจืช ื”ื™ื•ืžืŸ ื’ื ื‘ืคื•ืจืžื˜ JSON ืขืœ ื™ื“ื™ ื”ื’ื“ืจืช ื”ืฉื“ื” json_format. ืœื“ื•ื’ืžื:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}

ืœืžื™ื“ืข ื ื•ืกืฃ ืขืœ ืžืชื•ื“ื•ืœื•ื’ื™ื™ืช ืจื™ืฉื•ื ื”ืฉืœื™ื—, ื‘ืงืจ

https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries

ืจื™ืฉื•ื ื”ื•ื ืœื ื”ื“ืจืš ื”ื™ื—ื™ื“ื” ืœืงื‘ืœ ืชื•ื‘ื ื•ืช ืœื’ื‘ื™ ื”ืขื‘ื•ื“ื” ืขื Envoy Proxy. ื™ืฉ ืœื• ื™ื›ื•ืœื•ืช ืžืขืงื‘ ื•ืžื“ื“ื™ื ืžืชืงื“ืžื•ืช ื”ืžื•ื‘ื ื•ืช ื‘ืชื•ื›ื•. ืืชื” ื™ื›ื•ืœ ืœื‘ืจืจ ืขื•ื“ ื‘ ืชื™ืขื•ื“ ืžืขืงื‘ ืื• ื“ืจืš ืกืงืจื™ืคื˜ ืžืขืงื‘ ืื™ื ื˜ืจืืงื˜ื™ื‘ื™.

ืฉืœื‘ 7 - ื”ืฉืงื”

ื›ืขืช ื”ืขื‘ืจืช ืืช ื”ืชืฆื•ืจื” ืฉืœืš ืž-NGINX ืœ-Envoy Proxy. ื”ืฉืœื‘ ื”ืื—ืจื•ืŸ ื”ื•ื ืœื”ืคืขื™ืœ ืžื•ืคืข ืฉืœ Envoy Proxy ื›ื“ื™ ืœื‘ื“ื•ืง ืื•ืชื•.

ื”ืคืขืœ ื›ืžืฉืชืžืฉ

ื‘ืจืืฉ ืฉื•ืจืช ื”ืชืฆื•ืจื” ืฉืœ NGINX ืžืฉืชืžืฉ www www; ืžืฆื™ื™ืŸ ืœื”ืคืขื™ืœ ืืช NGINX ื›ืžืฉืชืžืฉ ื‘ืขืœ ื”ืจืฉืื•ืช ื ืžื•ื›ื•ืช ื›ื“ื™ ืœืฉืคืจ ืืช ื”ืื‘ื˜ื—ื”.

Envoy Proxy ื ื•ืงื˜ ื‘ื’ื™ืฉื” ืžื‘ื•ืกืกืช ืขื ืŸ ืœื ื™ื”ื•ืœ ืžื™ ื”ื‘ืขืœื™ื ืฉืœ ืชื”ืœื™ืš. ื›ืืฉืจ ืื ื• ืžืคืขื™ืœื™ื ืืช Envoy Proxy ื“ืจืš ืงื•ื ื˜ื™ื™ื ืจ, ืื ื• ื™ื›ื•ืœื™ื ืœืฆื™ื™ืŸ ืžืฉืชืžืฉ ื‘ืขืœ ื”ืจืฉืื•ืช ื ืžื•ื›ื”.

ื”ืคืขืœืช Proxy ืฉืœ Envoy

ื”ืคืงื•ื“ื” ืœืžื˜ื” ืชืคืขื™ืœ ืืช Envoy Proxy ื“ืจืš ืงื•ื ื˜ื™ื™ื ืจ Docker ื‘ืžืืจื—. ืคืงื•ื“ื” ื–ื• ืžืขื ื™ืงื” ืœ-Envoy ืืช ื”ื™ื›ื•ืœืช ืœื”ืื–ื™ืŸ ืœื‘ืงืฉื•ืช ื ื›ื ืกื•ืช ื‘ื™ืฆื™ืื” 80. ืขื ื–ืืช, ื›ืคื™ ืฉืฆื•ื™ืŸ ื‘ืชืฆื•ืจืช ื”ืžืื–ื™ืŸ, Envoy Proxy ืžืื–ื™ืŸ ืœืชืขื‘ื•ืจื” ื ื›ื ืกืช ื‘ื™ืฆื™ืื” 8080. ื–ื” ืžืืคืฉืจ ืœืชื”ืœื™ืš ืœืคืขื•ืœ ื›ืžืฉืชืžืฉ ื‘ืขืœ ื”ืจืฉืื•ืช ื ืžื•ื›ื•ืช.

docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy

ื‘ื“ื™ืงื”

ื›ืืฉืจ ืคืจื•ืงืกื™ ืคื•ืขืœ, ื›ืขืช ื ื™ืชืŸ ืœื‘ืฆืข ื•ืœืขื‘ื“ ื‘ื“ื™ืงื•ืช. ืคืงื•ื“ืช cURL ื”ื‘ืื” ืžื ืคื™ืงื” ื‘ืงืฉื” ืขื ื›ื•ืชืจืช ื”ืžืืจื— ื”ืžื•ื’ื“ืจืช ื‘ืชืฆื•ืจืช ื”-proxy.

curl -H "Host: one.example.com" localhost -i

ื‘ืงืฉืช ื”-HTTP ืชื’ืจื•ื ืœืฉื’ื™ืื” 503. ื”ืกื™ื‘ื” ืœื›ืš ื”ื™ื ืฉื—ื™ื‘ื•ืจื™ื ื‘ืžืขืœื” ื”ื–ืจื ืื™ื ื ืคื•ืขืœื™ื ื•ืื™ื ื ื–ืžื™ื ื™ื. ืœื›ืŸ, ืœ-Envoy Proxy ืื™ืŸ ื™ืขื“ื™ื ื–ืžื™ื ื™ื ืœื‘ืงืฉื”. ื”ืคืงื•ื“ื” ื”ื‘ืื” ืชืชื—ื™ืœ ืกื“ืจื” ืฉืœ ืฉื™ืจื•ืชื™ HTTP ื”ืชื•ืืžื™ื ืœืชืฆื•ืจื” ืฉื”ื•ื’ื“ืจื” ืขื‘ื•ืจ Envoy.

docker run -d katacoda/docker-http-server; docker run -d katacoda/docker-http-server;

ืขื ื”ืฉื™ืจื•ืชื™ื ื”ื–ืžื™ื ื™ื, Envoy ื™ื›ื•ืœื” ื‘ื”ืฆืœื—ื” ืืช ื”ืชืขื‘ื•ืจื” ืœื™ืขื“ ืฉืœื”.

curl -H "Host: one.example.com" localhost -i

ืืชื” ืืžื•ืจ ืœืจืื•ืช ืชื’ื•ื‘ื” ื”ืžืฆื™ื™ื ืช ืื™ื–ื” ืžื™ื›ืœ Docker ืขื™ื‘ื“ ืืช ื”ื‘ืงืฉื”. ื‘ื™ื•ืžื ื™ ื”-Proxy ืฉืœ Envoy ืืชื” ืืžื•ืจ ืœืจืื•ืช ื’ื ืคืœื˜ ืฉืœ ืžื—ืจื•ื–ืช ื’ื™ืฉื”.

ื›ื•ืชืจื•ืช ืชื’ื•ื‘ืช HTTP ื ื•ืกืคื•ืช

ืชืจืื” ื›ื•ืชืจื•ืช HTTP ื ื•ืกืคื•ืช ื‘ื›ื•ืชืจื•ืช ื”ืชื’ื•ื‘ื” ืฉืœ ื”ื‘ืงืฉื” ื‘ืคื•ืขืœ. ื”ื›ื•ืชืจืช ืžืฆื™ื’ื” ืืช ื”ื–ืžืŸ ืฉื”ืžืืจื— ื‘ืžืขืœื” ื”ื–ืจื ื‘ื™ืœื” ื‘ืขื™ื‘ื•ื“ ื”ื‘ืงืฉื”. ืžืชื‘ื˜ื ื‘ืืœืคื™ื•ืช ืฉื ื™ื•ืช. ื–ื” ืฉื™ืžื•ืฉื™ ืื ื”ืœืงื•ื— ืจื•ืฆื” ืœืงื‘ื•ืข ืืช ื–ืžืŸ ื”ืฉื™ืจื•ืช ื‘ื”ืฉื•ื•ืื” ืœืื—ื–ื•ืจ ื”ืจืฉืช.

x-envoy-upstream-service-time: 0
server: envoy

ืชืฆื•ืจื” ืกื•ืคื™ืช

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router
          clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9090 }

ืžื™ื“ืข ื ื•ืกืฃ ืžื”ืžืชืจื’ื

ื”ื•ืจืื•ืช ืœื”ืชืงื ืช Envoy Proxy ื ื™ืชืŸ ืœืžืฆื•ื ื‘ืืชืจ https://www.getenvoy.io/

ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ืœ-rpm ืื™ืŸ ืชืฆื•ืจืช ืฉื™ืจื•ืช systemd.

ื”ื•ืกืฃ ืชืฆื•ืจืช ืฉื™ืจื•ืช systemd /etc/systemd/system/envoy.service:

[Unit]
Description=Envoy Proxy
Documentation=https://www.envoyproxy.io/
After=network-online.target
Requires=envoy-auth-server.service
Wants=nginx.service

[Service]
User=root
Restart=on-failure
ExecStart=/usr/bin/envoy --config-path /etc/envoy/config.yaml
[Install]
WantedBy=multi-user.target

ืืชื” ืฆืจื™ืš ืœื™ืฆื•ืจ ืกืคืจื™ื™ื” /etc/envoy/ ื•ืœืฉื™ื ืฉื ืืช config.yaml config.

ื™ืฉ ืฆ'ืื˜ ื˜ืœื’ืจื ื‘ืืžืฆืขื•ืช ืคืจื•ืงืกื™ ืฉืœื™ื—: https://t.me/envoyproxy_ru

Envoy Proxy ืื™ื ื• ืชื•ืžืš ื‘ื”ืฆื’ืช ืชื•ื›ืŸ ืกื˜ื˜ื™. ืœื›ืŸ, ืžื™ ื™ื›ื•ืœ ืœื”ืฆื‘ื™ืข ืœืชื›ื•ื ื”: https://github.com/envoyproxy/envoy/issues/378

ืจืง ืžืฉืชืžืฉื™ื ืจืฉื•ืžื™ื ื™ื›ื•ืœื™ื ืœื”ืฉืชืชืฃ ื‘ืกืงืจ. ืœื”ืชื—ื‘ืจื‘ื‘ืงืฉื”.

ื”ืื ื”ืคื•ืกื˜ ื”ื–ื” ืขื•ื“ื“ ืื•ืชืš ืœื”ืชืงื™ืŸ ื•ืœื‘ื“ื•ืง ืืช proxy ืฉืœ ืฉืœื™ื—ื•ืช?

  • ื›ืŸ

  • ืœื

75 ืžืฉืชืžืฉื™ื ื”ืฆื‘ื™ืขื•. 18 ืžืฉืชืžืฉื™ื ื ืžื ืขื•.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”