LINUX.ORG.RU

Сообщения olegd

 

Затык в туториале kubernetes — не виден прокси

Помогите!

Пытаюсь повторить действия из интерактивного туториала https://kubernetes.io/docs/tutorials/kubernetes-basics/deploy-app/deploy-inte... на своей ВМ. На подключении к запущеному контейнеру получаю отлуп.

Minikube и kubectl уже установлены.

$ minikube status
host: Stopped
kubelet:
apiserver:
kubectl:
$ minikube start
* minikube v1.2.0 on linux (amd64)
* Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...
* Configuring environment for Kubernetes v1.15.0 on Docker 18.09.6
* Pulling images ...
* Launching Kubernetes ...
* Verifying: apiserver proxy etcd scheduler controller dns
* Done! kubectl is now configured to use "minikube"
$ kubectl get pods -o wide
No resources found.
$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/kubernetes-bootcamp created
$ kubectl get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-7b75749df7-55qd7   1/1     Running   0          27s   172.17.0.6   minikube   <none>           <none>
$ kubectl get deployments -o wide
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS            IMAGES                                         SELECTOR
kubernetes-bootcamp   1/1     1            1           41s   kubernetes-bootcamp   gcr.io/google-samples/kubernetes-bootcamp:v1   run=kubernetes-bootcamp
$ export POD_NAME=`kubectl get pods -o go-template --template '{{range.items}}{{.metadata.name}}{{"\n"}}{{end}}'`
$ echo $POD_NAME
kubernetes-bootcamp-7b75749df7-55qd7

В другом шелле запускаю прокси:

$ kubectl proxy
Starting to serve on 127.0.0.1:8001
В первом шелле пытаюсь подключиться:
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
Error: 'dial tcp 172.17.0.6:80: connect: connection refused'
Trying to reach: 'http://172.17.0.6/'

Что ещё нужно сделать?

Дистрибутив Debian 10 (amd64).

P.S. Не связано ли это с тем, что контейнер пытается работать через 443 порт, а не 80-й?

P.P.S. Хотя

kubectl exec $POD_NAME curl localhost:8080
отрабатывает правильно.

P.P.P.S. На всякий случай: через expose deployment приложение доступно:

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port=8080
service/kubernetes-bootcamp exposed
$ export NODE_PORT=`kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}'`
$ echo $NODE_PORT
30156
$ curl `minikube ip`:$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-7b75749df7-55qd7 | v=1
Но вопрос причины отказа через прокси по-прежнему стоит.

 

olegd
()

Увидеть ВМ внутри ВМ

На хостовой машине стоит ОС Windows. В ней запущен VMware Player с Debian 9. Под Дебианом установлен Kubernetes. Он создаёт виртуальную машину VirtualBox, и открывает её как 192.168.99.100:32123.

Что нужно сделать, чтобы эту 192.168.99.100:32123 было видно в браузере, запущеном в хостовой Windows? iptables и netstat в Дебиане не установлены.

Сгодятся ссылки на документацию и правильное словосочетание для гугления.

 , , ,

olegd
()

Haproxy не запускается при загрузке сервера

Тестовая система из пяти виртуальных машин. На 192.168.56.147 Debian x86_64 GNU/Linux, на котором Haproxy слушает порт 7100.

После загрузки у службы haproxy статус failed. Но если запустить её командой «sudo systemctl start haproxy service», всё работает. Journalctl после загрузки пишет:

$ sudo journalctl | grep -i haproxy
Jun 26 16:00:43 debian systemd[1]: Starting HAProxy Load Balancer...
Jun 26 16:00:43 debian systemd[1]: Started HAProxy Load Balancer.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[293]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 26 16:00:43 debian haproxy-systemd-wrapper[293]: Note: setting global.maxconn to 2000.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[293]: [ALERT] 176/160043 (296) : Starting frontend localnodes: cannot bind socket [192.168.56.147:7100]
Jun 26 16:00:43 debian haproxy-systemd-wrapper[293]: haproxy-systemd-wrapper: exit, haproxy RC=1
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Unit entered failed state.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Failed with result 'exit-code'.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Service hold-off time over, scheduling restart.
Jun 26 16:00:43 debian systemd[1]: Stopped HAProxy Load Balancer.
Jun 26 16:00:43 debian systemd[1]: Starting HAProxy Load Balancer...
Jun 26 16:00:43 debian systemd[1]: Started HAProxy Load Balancer.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[319]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 26 16:00:43 debian haproxy-systemd-wrapper[319]: Note: setting global.maxconn to 2000.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[319]: [ALERT] 176/160043 (322) : Starting frontend localnodes: cannot bind socket [192.168.56.147:7100]
Jun 26 16:00:43 debian haproxy-systemd-wrapper[319]: haproxy-systemd-wrapper: exit, haproxy RC=1
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Unit entered failed state.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Failed with result 'exit-code'.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Service hold-off time over, scheduling restart.
Jun 26 16:00:43 debian systemd[1]: Stopped HAProxy Load Balancer.
Jun 26 16:00:43 debian systemd[1]: Starting HAProxy Load Balancer...
Jun 26 16:00:43 debian systemd[1]: Started HAProxy Load Balancer.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[352]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 26 16:00:43 debian haproxy-systemd-wrapper[352]: Note: setting global.maxconn to 2000.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[352]: [ALERT] 176/160043 (355) : Starting frontend localnodes: cannot bind socket [192.168.56.147:7100]
Jun 26 16:00:43 debian haproxy-systemd-wrapper[352]: haproxy-systemd-wrapper: exit, haproxy RC=1
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Unit entered failed state.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Failed with result 'exit-code'.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Service hold-off time over, scheduling restart.
Jun 26 16:00:43 debian systemd[1]: Stopped HAProxy Load Balancer.
Jun 26 16:00:43 debian systemd[1]: Starting HAProxy Load Balancer...
Jun 26 16:00:43 debian systemd[1]: Started HAProxy Load Balancer.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[388]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 26 16:00:43 debian haproxy-systemd-wrapper[388]: Note: setting global.maxconn to 2000.
Jun 26 16:00:43 debian haproxy-systemd-wrapper[388]: [ALERT] 176/160043 (391) : Starting frontend localnodes: cannot bind socket [192.168.56.147:7100]
Jun 26 16:00:43 debian haproxy-systemd-wrapper[388]: haproxy-systemd-wrapper: exit, haproxy RC=1
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Unit entered failed state.
Jun 26 16:00:43 debian systemd[1]: haproxy.service: Failed with result 'exit-code'.
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Service hold-off time over, scheduling restart.
Jun 26 16:00:44 debian systemd[1]: Stopped HAProxy Load Balancer.
Jun 26 16:00:44 debian systemd[1]: Starting HAProxy Load Balancer...
Jun 26 16:00:44 debian systemd[1]: Started HAProxy Load Balancer.
Jun 26 16:00:44 debian haproxy-systemd-wrapper[434]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 26 16:00:44 debian haproxy-systemd-wrapper[434]: Note: setting global.maxconn to 2000.
Jun 26 16:00:44 debian haproxy-systemd-wrapper[434]: [ALERT] 176/160044 (435) : Starting frontend localnodes: cannot bind socket [192.168.56.147:7100]
Jun 26 16:00:44 debian haproxy-systemd-wrapper[434]: haproxy-systemd-wrapper: exit, haproxy RC=1
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Main process exited, code=exited, status=1/FAILURE
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Unit entered failed state.
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Failed with result 'exit-code'.
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Service hold-off time over, scheduling restart.
Jun 26 16:00:44 debian systemd[1]: Stopped HAProxy Load Balancer.
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Start request repeated too quickly.
Jun 26 16:00:44 debian systemd[1]: Failed to start HAProxy Load Balancer.
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Unit entered failed state.
Jun 26 16:00:44 debian systemd[1]: haproxy.service: Failed with result 'exit-code'.

Конфиг:

$ cat /etc/haproxy/haproxy.cfg
global
        debug

frontend localnodes
        bind 192.168.56.147:7100
        mode tcp
        default_backend nodes
        timeout client          1m
        acl block_1 src 192.168.56.1
        acl block_2 src 192.168.56.149

        use_backend ls1 if block_1
        use_backend ls2 if block_2

backend ls1
        mode tcp
        balance roundrobin
        server mytestweb1 192.168.56.150:7189
        timeout connect        10s
        timeout server          1m

backend ls2
        mode tcp
        balance roundrobin
        server mytestweb2 192.168.56.151:7189
        timeout connect        10s
        timeout server          1m

backend nodes
        mode tcp
        balance roundrobin
        server web01 192.168.56.150:7189
        server web02 192.168.56.151:7189
        timeout connect        10s
        timeout server          1m

После запуска вручную journalctl показывает:

Jun 26 16:11:04 debian systemd[1]: Starting HAProxy Load Balancer...
Jun 26 16:11:04 debian systemd[1]: Started HAProxy Load Balancer.
Jun 26 16:11:04 debian haproxy-systemd-wrapper[677]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
Jun 26 16:11:04 debian haproxy-systemd-wrapper[677]: Note: setting global.maxconn to 2000.

В чём проблема? Почему ошибка «cannot bind socket [192.168.56.147:7100]» возникает при автозагрузке и не возникает при ручном запуске?

Ответ: Haproxy запускается до того, как машина получает адрес по DHCP. Помогло сменить адрес на 0.0.0.0:

frontend localnodes
        bind 0.0.0.0:7100

Либо можно в /etc/systemd/system/multi-user.target.wants/haproxy.service в строку After добавить network-online.target

 , ,

olegd
()

Как быстро освоить Kubernetes?

Человеку требуется срочно освоить Kubernetes. Мой вариант «сразу приступить к работе, а на каждый затык гуглить Stackoverflow» его не устраивает. Есть что-либо быстрее, чем прочитать все доки и выполнить все упражнения с https://kubernetes.io/docs/home/ ?

 

olegd
()

Zork открыли

На Гитхаб выложили исходники текстовых игр Инфокома. Язык — их собственный Лисп, с <> вместо круглых скобок. С лицензией мутно, несвободные.

https://github.com/historicalsource/moonmist

https://www.opennet.ru/opennews/art.shtml?num=50525#49

Кому не лень — можете сделать новость.

Интересно, что там в комментариях пошла дискуссия о Лиспе, вспомнили лисп в <200 строк на Си: https://carld.github.io/2017/06/20/lisp-in-less-than-200-lines-of-c.html И дошло до дилеммы: если делать транслятор лиспа просто, в нём течёт память за счёт фрагментации, но если делать правильно, тратится на порядки больше памяти, чем в принципе может утечь.

 , ,

olegd
()

linux-talks@conference.jabber.ru

Что с ней? Вход по паролю, в публичных логах знакомых ников не видно, содержимое — унылые репосты с «Медузы». Угнали?

 

olegd
()

Jabber vs Slack (vs Skype vs GoToMeeting) для чайников

Шёл разговор: хотелось бы систему для переписки наподобие Slack, но на своём сервере. Возник вопрос: умеет ли Джаббер делать то же? Чаты — есть. Поднять свой сервер — можно. А как сейчас с другими фичами?

Есть ли работоспособные веб-клиенты для Джаббера?

Как в нём с голосовой связью?

С передачей видео?

Самое главное: как долго хранятся логи чатов и есть ли поиск по ним?

И дополнительно: что такое Cisco Jabber, и связан ли он с тем Джаббером, который на XMPP?

 ,

olegd
()

Чем опасен http.server?

Если срочно нужен веб-сервер, можно запустить

python3 -m http.server 80
и он будет раздавать файлы из текущей директории. Но во всех мануалах предупреждают, что его ни в коем случае нельзя использовать в продакшене.

Вопрос: а чем он так плох? Что может при желании сделать злоумышленник с системой, на которой запущен этот сервер?

 , ,

olegd
()

Конфиг Traefik в качестве балансировщика

Помогите, пожалуйста, разобраться с конфигом Traefik. Требуется настроить его для балансировки нескольких веб-серверов. На 2.0.0 я стабильно получаю ошибку 404.

Дополнение: Переписал конфиг с учётом изменений в версии 2 (https://docs.traefik.io/v2.0/) Новый конфиг под TCP:

[global]
sendanonymoususage = false

[entrypoints]
  [entrypoints.sdb]
    address = ":7100"
# [entrypoints.sdb.proxyProtocol]
#   trustedIPs = ["127.0.0.1/32", "192.168.56.1/24"]

[tcp]
  [tcp.routers]
    [tcp.routers.toDBplain]
      entrypoints = ["sdb"]
      rule = "HostSNI(`*`)"
      service = "toDBplain"
      [tcp.routers.toDBplain.tls]

  [tcp.services]
    [tcp.services.toDBplain.LoadBalancer]
      [[tcp.services.toDBplain.LoadBalancer.servers]]
        address = "192.168.56.1:7201"
      [[tcp.services.toDBplain.LoadBalancer.servers]]
        address = "192.168.56.1:7202"

[accessLog]
  format = "json"
  logLevel = "debug"
[log]
  format = "json"
  logLevel = "debug"

Лог с новым конфигом:

{«level»:«info»,«msg»:«Using TOML configuration file /home/powtest/traefik/new.toml»,«time»:«2019-03-23T11:47:47+03:00»}
{«level»:«info»,«msg»:«Traefik version 2.0.0-alpha1 built on 2019-03-18T14:26:35Z»,«time»:«2019-03-23T11:47:47+03:00»}
{«level»:«debug»,«msg»:«Static configuration loaded {\„Global\“:{\„Debug\“:false,\„CheckNewVersion\“:false,\„SendAnonymousUsage\“:false},\„ServersTransport\“:{\„InsecureSkipVerify\“:false,\„RootCAs\“:null,\„MaxIdleConnsPerHost\“:200,\„ForwardingTimeouts\“:null},\„EntryPoints\“:{\„sdb\“:{\„Address\“:\»:7100\",\«Transport\»:{\«LifeCycle\»:{\«RequestAcceptGraceTimeout\»:0,\«GraceTimeOut\»:10000000000},\«RespondingTimeouts\»:{\«ReadTimeout\»:0,\«WriteTimeout\»:0,\«IdleTimeout\»:180000000000}},\«ProxyProtocol\»:null,\«ForwardedHeaders\»:{\«Insecure\»:false,\«TrustedIPs\»:null}}},\«Providers\»:{\«ProvidersThrottleDuration\»:2000000000,\«Docker\»:null,\«File\»:null,\«Marathon\»:null,\«Kubernetes\»:null,\«KubernetesCRD\»:null,\«Rest\»:null},\«API\»:null,\«Metrics\»:null,\«Ping\»:null,\«Log\»:{\«LogLevel\»:\«debug\»,\«format\»:\«json\»},\«AccessLog\»:{\«format\»:\«json\»},\«Tracing\»:null,\«HostResolver\»:null,\«ACME\»:null}",«time»:«2019-03-23T11:47:47+03:00»}
{«level»:«info»,«msg»:«\nStats collection is disabled.\nHelp us improve Traefik by turning this feature on :)\nMore details on: https://docs.traefik.io/basics/#collected-data\n»,«time»:«2019-03-23T11:47:47+03:00»}
{«level»:«debug»,«msg»:«No default certificate, generate one»,«time»:«2019-03-23T11:47:47+03:00»}
{«level»:«info»,«msg»:«Starting provider aggregator.ProviderAggregator {}»,«time»:«2019-03-23T11:47:47+03:00»}
{«entryPointName»:«sdb»,«level»:«debug»,«msg»:«Start TCP Server»,«time»:«2019-03-23T11:47:47+03:00»}
{«ClientAddr»:«192.168.56.147:46164»,«ClientHost»:«192.168.56.147»,«ClientPort»:«46164»,«ClientUsername»:"-",«DownstreamContentSize»:19,«DownstreamStatus»:404,«Duration»:13552163,«Overhead»:13552163,«RequestAddr»:«192.168.56.147:7100»,«RequestContentSize»:0,«RequestCount»:1,«RequestHost»:«192.168.56.147»,«RequestMethod»:«GET»,«RequestPath»:«/api»,«RequestPort»:«7100»,«RequestProtocol»:«HTTP/1.1»,«RetryAttempts»:0,«StartLocal»:«2019-03-23T11:47:52.614208064+03:00»,«StartUTC»:«2019-03-23T08:47:52.614208064Z»,«downstream_Content-Type»:«text/plain; charset=utf-8»,«downstream_X-Content-Type-Options»:«nosniff»,«level»:«info»,«msg»:"",«request_Accept»:«*/*»,«request_User-Agent»:«curl/7.52.1»,«time»:«2019-03-23T11:47:52+03:00»}
^C{«level»:«info»,«msg»:«I have to go...»,«time»:«2019-03-23T11:47:56+03:00»}
{«level»:«info»,«msg»:«Stopping server gracefully»,«time»:«2019-03-23T11:47:56+03:00»}
{«entryPointName»:«sdb»,«level»:«debug»,«msg»:«Waiting 10s seconds before killing connections.»,«time»:«2019-03-23T11:47:56+03:00»}
{«level»:«error»,«msg»:«accept tcp [::]:7100: use of closed network connection»,«time»:«2019-03-23T11:47:56+03:00»}
{«entryPointName»:«sdb»,«level»:«debug»,«msg»:«Entry point sdb closed»,«time»:«2019-03-23T11:47:56+03:00»}
{«level»:«info»,«msg»:«Server stopped»,«time»:«2019-03-23T11:47:56+03:00»}
{«level»:«info»,«msg»:«Shutting down»,«time»:«2019-03-23T11:47:56+03:00»}

Конфиг для HTTP:

[global]
sendanonymoususage = false
[entrypoints]
  [entrypoints.sdb]
    address = ":7100"
[http]
  [http.routers]
    [http.routers.toDBr1]
      entrypoints = ["sdb"]
      rule = "Host(`*`)"
      service = "toDBs1"
  [http.services]
    [http.services.toDBs1.LoadBalancer]
      [[http.services.toDBs1.LoadBalancer.servers]]
        url = "http://192.168.56.1:7201"
      [[http.services.toDBs1.LoadBalancer.servers]]
        url = "http://192.168.56.1:7202"
[accessLog]
  format = "json"
  logLevel = "debug"
[log]
  format = "json"
  logLevel = "debug"
Результат тот же:
{«ClientAddr»:«192.168.56.147:46166»,«ClientHost»:«192.168.56.147»,«ClientPort»:«46166»,«ClientUsername»:"-",«DownstreamContentSize»:19,«DownstreamStatus»:404,«Duration»:57476,«Overhead»:57476,«RequestAddr»:«192.168.56.147:7100»,«RequestContentSize»:0,«RequestCount»:1,«RequestHost»:«192.168.56.147»,«RequestMethod»:«GET»,«RequestPath»:«/api»,«RequestPort»:«7100»,«RequestProtocol»:«HTTP/1.1»,«RetryAttempts»:0,«StartLocal»:«2019-03-23T12:44:06.053655548+03:00»,«StartUTC»:«2019-03-23T09:44:06.053655548Z»,«downstream_Content-Type»:«text/plain; charset=utf-8»,«downstream_X-Content-Type-Options»:«nosniff»,«level»:«info»,«msg»:"",«request_Accept»:«*/*»,«request_User-Agent»:«curl/7.52.1»,«time»:«2019-03-23T12:44:06+03:00»}

Как заставить его работать?

И спасибо тому, кто добавил тэг «traefik»!

Рабочие конфиги (всё на локалхосте):

Старая версия 1.7:

[file]

[entryPoints]
  [entryPoints.http]
  address = ":7100"

[backends]
  [backends.backend1]
    [backends.backend1.servers]
      [backends.backend1.servers.server0]
        url = "http://localhost:8001"
        weight = 1
      [backends.backend1.servers.server1]
        url = "http://localhost:8002"
        weight = 1

[frontends]
  [frontends.frontend1]
  backend = "backend1"
    [frontends.frontend1.routes.test_1]
    rule = "HostRegexp: {domain:.+}"
Альфа 2.0 для HTTP:
[global]
sendanonymoususage = false

[providers.file]

[entrypoints]
  [entrypoints.http]
    address = ":7100"

[http]
  [http.routers]
    [http.routers.toDBr1]
      entrypoints = ["http"]
      rule = "PathPrefix(`/`)"
      service = "toDBs1"
  [http.services]
    [http.services.toDBs1.LoadBalancer]
      method = "wrr"
      [[http.services.toDBs1.LoadBalancer.servers]]
        url = "http://localhost:8001"
        weight = 1
      [[http.services.toDBs1.LoadBalancer.servers]]
        url = "http://localhost:8002"
        weight = 1

[accessLog]
[log]
Альфа 2.0 для TCP:
[global]
sendanonymoususage = false

[providers.file]

[entrypoints]
  [entrypoints.tcp]
    address = ":7100"

[tcp]
  [tcp.routers]
    [tcp.routers.toDBr1]
      entrypoints = ["tcp"]
      rule = "HostSNI(`*`)"
      service = "toDBs1"
  [tcp.services]
    [tcp.services.toDBs1.LoadBalancer]
      method = "wrr"
      [[tcp.services.toDBs1.LoadBalancer.servers]]
        address = "127.0.0.1:8001"
        weight = 1
      [[tcp.services.toDBs1.LoadBalancer.servers]]
        address = "127.0.0.1:8002"
        weight = 1
[docker]
exposedByDefault = false

[accessLog]
[log]

Мои ошибки: TCP требует «address» вместо «url», weight нужно указывать явно, т.к. по умолчанию 0. Не понял, должны ли точки входа иметь имена «tcp» и «http», но без этого не работало.

P.S. Но так как обслуживаемый клиент не умеет пользоваться куками, а Traefik не умеет без них организовывать «липкие» сессии, а балансировка сводится к dynamic/weighted round robin, всё это оказалось бесполезно. Для аутентификации нужно послать 6 запросов на один и тот же сервер. А они всегда идут на разные.

 , ,

olegd
()

HTTPS в Gunicorn + Meinheld

Пытаюсь настроить работу WSGI-скрипта в Докере с Gunicorn и Meinheld на основе образа https://github.com/tiangolo/meinheld-gunicorn-docker/tree/master/python3.7-al...

По HTTP заработало сразу, когда заменил entrypoint.sh на:

gunicorn -k "egg:meinheld#gunicorn_worker" \
  -c "$GUNICORN_CONF" "$MODULE_NAME:$VARIABLE_NAME" \
  --chdir "$GUNICORN_WORKDIR" \
  --limit-request-line 0 \
  --access-logfile - \
  --log-level debug \
  --capture-output
Для HTTPS добавил сертификаты и ключ, и явно прописал bind для обоих портов:
gunicorn -k "egg:meinheld#gunicorn_worker" \
  -c "$GUNICORN_CONF" "$MODULE_NAME:$VARIABLE_NAME" \
  --chdir "$GUNICORN_WORKDIR" \
  --limit-request-line 0 \
  --access-logfile - \
  --log-level debug \
  --capture-output \
  --certfile $S_HTTP_TLS_CERTIFICATE \
  --keyfile $S_HTTP_TLS_KEY \
  --bind 0.0.0.0:80 --bind 0.0.0.0:443
но оба порта отдают HTTP.

Лог при включении: https://pastebin.com/E88vib2C

Что сделать, чтобы на 443 порту отдавал HTTPS?

P.S. Если выбросить

-k "egg:meinheld#gunicorn_worker"
, оба порта начинают отдавать HTTPS. То есть в дефолтной конфигурации Meinheld превращает HTTPS в HTTP. Как его сконфигурировать?

P.P.S. Сайт Meinheld заработал. Оказывается, поддержка SSL отсутствует: https://github.com/mopemope/meinheld/issues/64

Что значит «please PR»? «Пожалуйста, сделай пулл-реквест, добавляющий поддержку»?

 , ,

olegd
()

Сортировать и синхронизировать массивы

Имеются 2 массива данных I(e,t) в виде 2 троек 1-мерных массивов одинаковой длины: t1, e1, I1 и t2, e2, I2. (Точнее, это — группы в открытых HDF-файлах f1['data/t'], f1['data/e'], f1['data/i'] и f2['data/t'], f2['data/e'], f2['data/i']). Данные отсортированны по возрастанию e, затем по возрастанию t. e и t образуют регулярную сетку с шагами ~0.001 и 1. I задана не во всех узлах. Повторяющихся узлов нет.

Требуется проверить, совпадают ли массивы I1 и I2. Оба файла содержат одинаковый набор пар e-t. Но из-за ошибок округления часть изначально совпадавших e немного отличается. Поэтому данные в I2 перетасованы относительно I1 — одинаковые индексы необязательно соответствуют одинаковым значениям e и t.

Имеется питоновская библиотека для чтения этих файлов, h5py. Есть ли какой-то штатный способ быстро отсортировать I2, вначале сравнивая t как целые числа, а затем e — как дробные с заданной погрешностью (скажем, абсолютная погрешность 1e-3)? Реализовать это сам я могу, но вдруг есть готовое?

Можно ли получить искомое, применив numpy.sort к list( zip( t1, e2, I2 ) ) ? Как там задать погрешность? Или есть что-то получше?

Пока сделал так:

#!/usr/bin/python3
from sys import argv
import h5py
import numpy as np

f1, f2 = h5py.File( argv[1],'r' ), h5py.File( argv[2],'r' ) 
I1, I2 = np.array(f1['data/i']), np.array(f2['data/i'])
t1, t2 = np.array(f1['data/t']), np.array(f2['data/t'])
e1, e2 = np.ma.round(np.array(f1['data/e']), 7), np.ma.round(np.array(f2['data/e']), 7)

j1, j2 = np.lexsort( (e1, t1) ), np.lexsort( (e2, t2) )

a1 = np.stack( ( t1[j1], e1[j1], I1[j1] ), axis=-1 )
a2 = np.stack( ( t2[j2], e2[j2], I2[j2] ), axis=-1 )

print( ( a1 == a2 ).all() )

Или так:

#!/usr/bin/python3
from sys import argv
import h5py
import numpy as np

f1, f2 = h5py.File( argv[1],'r' ), h5py.File( argv[2],'r' ) 
I1, I2 = np.array(f1['data/i']), np.array(f2['data/i'])
t1, t2 = np.array(f1['data/t']), np.array(f2['data/t'])
e1, e2 = np.array(f1['data/e']), np.array(f2['data/e'])

j1, j2 = np.lexsort( (e1, t1) ), np.lexsort( (e2, t2) )

print( ( t1[j1] == t2[j2] ).all() and
       ( abs(e1[j1] - e2[j2]) < 0.0000001 ).all() and
       ( abs(I1[j1] - I2[j2]) < 1 ).all() )

 , ,

olegd
()

Wine и Windows по-разному округляют

Cтолкнулся тут... Программа наподобие Proteo Wizard. Закрытой библиотекой импортируются данные. Интерполируются под регулярную сетку. Значения сетки — от 10 до 100. Если запускать программу в Виндоуз или если в Вайне, в полученных массивах часть узлов сетки отличаются на 1e-14, то есть на последний значащий бит. Похоже, проблема возникает при преобразовани 10-байтных extended в 8-байтные double.

Обидно.

 ,

olegd
()

xvfb и x11vnc

На линуксовой машине (Debian Stretch) в Докере на 99-м экране запускается Xvfb, под которым открывается окно, которое ожидает нажатия OK:

xvfb-run -n 99 bash winetricks vcrun2005
Требуется нажать кнопку с машины под управлением Windows.

Вхожу в тот же контейнер вторым bash-ем и запускаю x11vnc. Получаю ошибку:

# x11vnc -auth /home/root/.Xauthority -display :99 -rfbauth
26/02/2019 16:30:16 passing arg to libvncserver: -rfbauth
26/02/2019 16:30:16 x11vnc version: 0.9.13 lastmod: 2011-08-10  pid: 8655
No protocol specified
26/02/2019 16:30:16 XOpenDisplay(":99") failed.
26/02/2019 16:30:16 Trying again with XAUTHLOCALHOSTNAME=localhost ...
No protocol specified

26/02/2019 16:30:16 ***************************************
26/02/2019 16:30:16 *** XOpenDisplay failed (:99)

*** x11vnc was unable to open the X DISPLAY: ":99", it cannot continue.
*** There may be "Xlib:" error messages above with details about the failure.

В чём проблема? Куда копать?

P.S. На x11vnc -find -rfbauth ругается «unrecognized option(s)»

Ответ нашел сам: надо явно указать файл authority для xvfb; кроме того, -rfbauth иногда нужно явно указывать имя дефолтного файла /root/.vnc/passwd

Остался без ответа второй вопрос: когда VNC-сервер запустится, как подключиться к нему с виндовой машины при помощи TightVNC? Указал IP хоста, дефолтный порт, но до ввода пароля (который в /root/.vnc/passwd контейнера) не доходит, пишет «No connection could be made because the target machine actively refused it.» Какие нужны дополнительные действия?

Пока нашёл следующее:

Запуская докер добавить к «docker run» что-то вроде "-p 5900:5900". Если контейнер уже запущен, выяснить его адрес на хосте командой

docker inspect keen_beaver | grep IPAddress
и настроить фаервол (подставить нужный IP):
sudo /sbin/iptables -t nat -A DOCKER -p tcp --dport 5900 -j DNAT --to-destination 172.17.0.3:5900

После этого VNC-сервер будет виден на порту 5900.

И да, на этом порту что-то видно — curl servername:5900 отваливается не через 2 секунды, а через 22, и с ошибкой не «Connection refused», а «Timed out». Telnet тоже на этом порту что-то видит, но не получает ответа.

Но подключиться не получается. TightVNC пишет «A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.» noVNC выдаёт «Failed to connect to server» в браузере и коды 404 и 111 «Connection refused» в консоли.

В чём может быть дело?

Ответ 2: начало нормально отвечать после перезагрузки хоста.

Ещё выяснилось, что необходимо запускать x11vnc с ключами "-visual TrueColor" и "-forever" Первый нужен клиентам, не понимающим 8-битный цвет, второй — чтобы сервер не отключался при закрытии соединения с клиентом.

 , ,

olegd
()

Пара вопросов про WINE

1. В Windows у утилиты reg есть команды save и restore. Как я понял, для сохранения информации из реестра в формат HIV и восстановления из HIV в реестр. В WINE reg таких команд не знает. Как перенести информацию из HIV в реестр Вайна без использования машины с оффтопиком?

2. Шелл-скрипт перед запуском команды выводит её в консоль echo-м. Но команда вызывает программу под Wine и переменная содержит путь с бэкслэшами. Поэтому «c:\external\catalogue.txt» превращается во что-то вроде «c:ternaltalogue.txt». Как лучше экранировать бэкслэши? Помимо прогона через sed 's/\\/\\\\/g'

Пояснение по пункту 2: Бэкслэши — в параметре командной строки, передаваемом виндовой программе. Если бы эта программа умела работать с обоими слэшами, проблемы бы не возникло.

P.S. Debian Stretch, Ubuntu 16.04.

Ответ 2: Использовать bash. Сейчас пойдёт, но в дальнейшем понадобится пускать его и в BusyBox.

 

olegd
()

Wine на машине без дисплея и рантаймы от МС

Есть консольное приложение под Windows. Нужно запустить его под WINE на линуксовом сервере без дисплея. Приложение использует сторонние библиотеки, которым требуются ратнаймы VC++ и .Net. Требуется поставить их под вайн. Как это лучше сделать?

Debian 9 и Wine-stable 4.0 с winehq.org.

Большинство рантаймов в виде экзешников, например vcredist-2008sp1-x86.exe. При их запуске выдаёт ошибку наподобие:

0028:err:winediag:nodrv_CreateWindow Application tried to create a window, but no driver could be loaded.
0028:err:winediag:nodrv_CreateWindow Make sure that your X server is running and that $DISPLAY is set correctly.

winetricks пытается скачивать и устанавливать те же экзешники и выдаёт те же ошибки.

Запуск с /nogui ничего не меняет.

Нашёл упоминания ключа /display, но не понял, как его применять.

Поставил xserver-xorg-video-dummy, настроил как описано здесь https://gist.github.com/mangoliou/27c6c5867a95932f21ae59ad7152aa33 и https://gist.githubusercontent.com/mangoliou/ba126832f2fb8f86cc5b956355346038... Запускается без ошибок, но как его использовать? В $DISPLAY пусто.

Как поставить рантаймы?

 , , ,

olegd
()

wineboot -u криво работает при сборке Докера

Если запустить wineboot -u в хостовой системе или в контейнере, он нормально отработает, в частности присвоит системные переменные, включая %ProgramFiles%.

Если запустить wineboot -u при сборке образа (RUN wineboot -u), он вроде бы отработает так же, но %ProgramFiles% останется пустой.

А без %ProgramFiles% не работает winetricks и не ставятся рантаймы VC. Можно это как-то обойти?

P.S. А если wine ставится в /opt, и пакет добавляет путь в PATH, путь в PATH не добавляется.

Debian:stable-slim, wine 1.8.7 (последний дебиановский) или 4.0 (последний стабильный на WineHQ).

Воркэраунд: wineboot -u && winetricks vcrun2005

Но после него опять не видит эти переменные.

Ответ 1: Каждая строка RUN выполняется в отдельном шелле, который завершается при выходе из последней команды в строке. Если какие-то из команд породили процессы, например, wineserver, эти процессы убиваются, и не успевают сохранить результаты. Добавление в конце строки wineboot -s не помогает, так как она тоже завершается до завершения wineserver. Необходимо дождаться завершения самого wineserver, например

RUN wineboot -i && wineserver -w

Но пока не решил, что делать с PATH.

Ответ 2: Похоже, сам пакет wine-stable не прописывает /opt/wine-stable/bin в PATH, и это следует делать вручную. Добавил соответствующую команду ENV.

Итого получился 3-гигабайтный образ вместо 14-гигабайтного с Windows. Возможно, стоит поставить какой-нибудь сервер X, чтобы избавиться от ошибок OLE.

 ,

olegd
()

Как получаются эти величины?

На сайте http://www.usdebtclock.org/ в реальном времени показываются разные экономические показатели, включая госдолг США и объём их импорта нефти. Величины увеличиваются несколько раз в секунду. Кто-нибудь может сказать, как они получаются? Насколько часто они берутся с сервера, а сколько получается экстраполяцией джаваскриптом? И откуда они берутся?

Перемещено jollheef из talks

 ,

olegd
()

Абсолютный «dotted path»

Наткнулся на термин «dotted path». Из контекста понял, что это обозначает путь к файлу, в котором / заменены точками. То есть из «scripts/server.py» получается «scripts.server». Термин встретил в документации к Gunicorn, но поиском в Гугле нашёл его применительно к Питону вообще. (Но в основном, Гугл находит Фотошоп.)

Вопрос: как записать таким образом абсолютный путь? А заодно путь с "..".

Про ключ --pythonpath знаю.

 

olegd
()

Время отдельных тестов в pytest

Есть машина, на которой pytest прогоняет тесты. Иногда её сильно грузят другими задачами. Как мне сказали, pytest показывает только общее астрономическое время от начала до конца теста (возможно, за вычетом «setup» и «teardown») — как «real» в утилите time. Требуется узнать время потраченное только на выполнение каждого из тестов, без учёта ожиданий, пока процессор освободится. pytest умеет его вычленять? Если нет, то как лучше его определить?

 ,

olegd
()

Нужен ли nginx?

uwsgi и gunicorn сами могут отдавать страницы по HTTP/HTTPS. Отдаваемые данные генерируются динамически. Если вероятность дважды сгенерировать одинаковую страницу исчезающе мала, кешировать нечего, и по основному назначению nginx не используется. Так? Или от него есть польза где-то ещё?

Ситуация следующая. Веб-сервер получает REST-запросы и отдаёт простыни JSON, от нескольких килобайт до сотен мегабайт. Время генерации ответа — миллисекунды. Никаких статических объектов нет. Дважды получить одинаковый запрос маловероятно. Будет ли выигрыш в скорости, потребляемой памяти или нагрузке на процессор при отказе от nginx? Если это имеет значение, сервера виртуальные, в Докере.

(Мерять будем на следующей неделе.)

 , , ,

olegd
()

RSS подписка на новые темы