Я играю с coreos и digitalocean и хочу разрешить внутреннюю связь между моими контейнерами.
Я настроил частную сеть для всех хостов, и теперь я хотел бы убедиться, что некоторые контейнеры открывают порты только для локального хоста и внутреннего интерфейса.
Я изучил множество вариантов для этого, но ни один из них не кажется удовлетворительным:
- Using the '-p', I can ensure docker binds to the local interface, but this has two downsides:
- I can't easily test services by SSHing in, because that traffic originates from localhost
- Мне нужно написать несколько хакерских сценариев оболочки, чтобы запустить мои службы, чтобы ввести адрес машины, на которой работает контейнер.
- Я пытался использовать фланель, но это не делает трафик приватным (или я не правильно настроил)
- Я рассматривал возможность использования iptables в контейнерах для предотвращения внешнего доступа, но это не кажется безопасным.
- I tried using iptables on the coreos hosts, but ... it's tricky, and I couldn't get it working.
- When I tried to configured iptables on the host, I used the method here: https://docs.docker.com/articles/networking/#communication-between-containers-and-the-wider-world, by adding a DROP rule to the docker chain, but it didn't work, and packets still got through
Итак, каков наилучший подход, и я потрачу время на то, чтобы заставить его работать.
В целом, я думаю, мне нужно найти что-то, что я могу:
- Надежное развертывание на всех хостах
- Что-то достаточно гибкое в будущем
- Что-то, что позволяет использовать «пограничные машины», доступные из более широкого Интернета.
Решение
Я расскажу, как я решил это. Спасибо larsks за помощь. В конце концов, их подход был правильным. Это сложно на coreos, потому что не существует действительно стабильных адресов, как предполагает larsks. Весь смысл coreos в том, чтобы можно было забыть об IP-адресах.
Я решил эту проблему, найдя неплохой способ ввести IP-адрес в команду в служебном файле. Сложность в том, что он не поддерживает многие функции оболочки, которые я ожидал. Что я хотел сделать, так это присвоить IP-адрес машины переменной, а затем внедрить ее в команду:
ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');
/usr/bin/docker run -p $ip:7000:7000 ...
Но, как уже упоминалось, это не работает. Так что делать? Получите оболочку!
ExecStart=/usr/bin/sh -c "\
export ip=$(ifconfig eth1 | grep -o 'inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*');\
echo $ip;\
/usr/bin/docker run -p $ip:7000:7000"
По пути я столкнулся с несколькими проблемами.
- Я почти уверен, что в этой команде нет новых строк, поэтому мне пришлось добавить ';' персонажи
- когда вы тестируете приведенную выше команду bash -c в оболочке, она будет иметь совсем другие эффекты, чем когда это делает systemd. В оболочке вам нужно экранировать символы '$', а в конфигурационных файлах systemd этого делать не нужно.
- Я включил эхо, чтобы увидеть, что команда думает об ip.
- Когда я все это делал, я фактически вставил небольшой веб-сервер в образ докера, чтобы я мог просто протестировать его с помощью curl.
Недостатком этого подхода является то, что он привязан к тому, как работает ifconfig, и ipv4. На самом деле этот подход не работает на моем ноутбуке с Linux Mint, где ifconfig выдает вывод в другом формате. Важным уроком здесь является вывод данных в yaml или json, чтобы инструменты оболочки json могли получить к ним более легкий доступ.