В k8s я хочу, чтобы мой сервер прослушивал podIP, а не 127.0.0.1 или 0.0.0.0. Но podIP выделяется динамически, поэтому я хочу сделать что-то вроде:
ip := getIPFromNic("eth0")
net.Listen(ip)
Но я не знаю, как обеспечить, чтобы nic в pod назывался eth0, а не en0 или другими. Должен ли я что-то делать в Dockerfile или что-то делать в deployment.yaml?
Я попытался выполнить поиск в Google, но не нашел никаких связанных ресурсов о ник в докере. Большинство блогов говорят о veth и docker bridge.
Для сетевой политики k8s требуется специальный плагин CNI.
Да, но именно так это и делается. Если вы заботитесь о видимости, вы используете тот, который может это сделать. Если вам все равно, вам все равно. При этом я не уверен, что привязка к очень конкретному IP-адресу вообще дает какие-либо преимущества. Не похоже, что это распространится на другие интерфейсы, кроме петлевого.
У вас, вероятно, будет ровно два интерфейса, поэтому выбор того, который не является петлевым интерфейсом, даст вам нужный адрес. Как предполагает @tadman, перебор интерфейсов и привязка ко всем по отдельности будут очень похожи на просто привязку к 0.0.0.0. Ваш фрагмент выглядит как Go; Как получить локальный IP-адрес в Go? найти нужный адрес?
/proc/1/task/1/net/fib_trie
файлмоя такая:
cat /proc/1/task/1/net/fib_trie
Main:
+-- 0.0.0.0/1 2 0 2
+-- 0.0.0.0/4 2 0 2
|-- 0.0.0.0
/0 universe UNICAST
+-- 10.0.0.0/24 2 0 2
|-- 10.0.0.45
/32 host LOCAL
|-- 10.0.0.184
/32 link UNICAST
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/32 link BROADCAST
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
а 10.0.0.45 — это IP-адрес моего модуля.
curl -s -H "Authorization: Bearer $YOUR_TOKEN" https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods/$(hostname)/ | grep "podIP" | awk '{print $2}' | tr -d '",'
к сожалению, привилегий по умолчанию cat /var/run/secrets/kubernetes.io/serviceaccount/token
недостаточно для этого запроса.
Вы можете получить IP-адрес модуля от Kubernetes, а не пытаться искать его в интерфейсе (или файлах в /proc
).
Вы можете предоставлять информацию о поде в виде переменных среды; документация включает этот пример; посмотрите, в частности, как устанавливается MY_POD_IP
:
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-fieldref
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
sleep 10;
done;
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MY_POD_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
restartPolicy: Never
Вы можете использовать пример этого в манифестах node_exporter из проекта kube-prometheus.
Изучив эту проблему, я обнаружил, что имя сетевого интерфейса контролируется kubelet, это конфигурация всего кластера, которую пользователи не могут изменить. По умолчанию имя nic — eth0, и если вы не уверены, вы можете проверить любой модуль в кластере, чтобы подтвердить это.
На практике рекомендуется использовать нисходящий API для передачи PodIP в виде env var в pod, таким образом, вы можете легко получить PodIP. Но мой случай немного особенный, файлу конфигурации приложения (смонтированному как configmap) нужен адрес прослушивания, который должен быть либо IP-адресом, либо именем nic. Вот почему мне нужно фиксированное значение.
Почему привязка к этому конкретному IP имеет значение? Вы можете контролировать видимость через сеть контейнеров.