☸️ Как перехватывать http-трафик, передаваемый от пода к поду, с помощью контейнера sidecar |

☸️ Как перехватывать http-трафик, передаваемый от пода к поду, с помощью контейнера sidecar

Мануал

В этой статье мы попробуем рассмотреть, как перехватить взаимодействие между подами с помощью функции sidecar-контейнера, предоставляемой кластером kubernetes.

Тестовая среда

Кластер Kubernetes – v1.28.5

Контейнеры Sidecar

Контейнеры Sidecar – это вторичные контейнеры, которые запускаются вместе с основным контейнером приложения в рамках одного пода.

Эти контейнеры используются для улучшения или расширения функциональности основного контейнера приложения путем предоставления дополнительных сервисов или функций, таких как логирование, мониторинг, безопасность или синхронизация данных, без непосредственного изменения кода основного приложения.

☸️ Что такое Kubernetes Service Mesh и Istio

Kubernetes реализует контейнеры sidecar как особый случай контейнеров init; контейнеры sidecar остаются запущенными после запуска пода.

Шаг 1: Убедитесь, что кластер Kubernetes запущен

В качестве первого шага убедитесь, что у вас настроен рабочий кластер kubernetes.

kubectl get nodes
NAME                 STATUS   ROLES           AGE    VERSION
k8master.stack.com   Ready    control-plane   215d   v1.28.5
k8node.stack.com     Ready    <none>          215d   v1.28.5

Шаг 2: Включите функцию sidecar feature gate для компонентов

Начиная с Kubernetes 1.28, функция под названием SidecarContainers позволяют указать политику перезапуска для контейнеров, перечисленных в поле initContainers пода.

Но эта функция не включена по умолчанию, как указано в документации «Feature Gates».

Нам нужно включить ее с помощью feature gate на всех необходимых компонентах, как показано ниже.

Обновите файлы манифеста API-сервера, контроллера и планировщика, чтобы включить функцию «SidecarContainers».

root@k8master:/etc/kubernetes/manifests# cat kube-apiserver.yaml | grep -i feature
    - --feature-gates=SidecarContainers=true

root@k8master:/etc/kubernetes/manifests# cat kube-controller-manager.yaml | grep -i feature
    - --feature-gates=SidecarContainers=true

root@k8master:/etc/kubernetes/manifests# cat kube-scheduler.yaml | grep -i feature
    - --feature-gates=SidecarContainers=true

Также обновите конфигурационный файл kubelet, чтобы включить эту функцию на главном и рабочих узлах, и перезапустите службу kubelet.

cat /var/lib/kubelet/config.yaml
...
kind: KubeletConfiguration
logging:
flushFrequency: 0
options:
json:
infoBufferSize: "0"
verbosity: 0
memorySwap: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
resolvConf: /run/systemd/resolve/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 0s
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s
featureGates:
SidecarContainers: true
cat /var/lib/kubelet/config.yaml
...
kind: KubeletConfiguration
logging:
flushFrequency: 0
options:
json:
infoBufferSize: "0"
verbosity: 0
memorySwap: {}
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
resolvConf: /run/systemd/resolve/resolv.conf
rotateCertificates: true
runtimeRequestTimeout: 0s
shutdownGracePeriod: 0s
shutdownGracePeriodCriticalPods: 0s
staticPodPath: /etc/kubernetes/manifests
streamingConnectionIdleTimeout: 0s
syncFrequency: 0s
volumeStatsAggPeriod: 0s
featureGates:
SidecarContainers: true

Шаг 3: Создание деплоймента с sidecar контейнером

На этом шаге мы будем использовать образ nginx для запуска в нашем основном контейнере, который будет выступать в качестве контейнера приложения.

В нашем контейнере sidecar мы будем использовать «sadeghrz/kubernetes-pod2pod-log» для перехвата http-трафика от пода к поду.

Вот configmap, который мы будем использовать для передачи конфигурации нашему образу.

Согласно документации, я использую «SEND_LOGS_TO» с «stdout» для захвата HTTP-трафика и отправки его в вывод терминала.

У нас есть и другие варианты отправки логов в систему, которые вы можете изучить подробнее.

☸️ Обновление ConfigMap и secrets без перезапуска пода в K8s

cat sidecarloggingconfigmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: k8s-pod2pod-log-configmap
data:
SEND_LOGS_TO: stdout

Вот определение развертывания с контейнером sidecar для захвата HTTP-трафика как входящего, так и исходящего.

Обратите внимание, что мы запускаем initcontainer в привилегированном режиме, так как он требует захвата трафика интерфейса пода, что является операцией, недопустимой в непривилегированных контейнерах.

cat sidecarloggingnginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
initContainers:
- name: k8s-pod2pod-log
image: sadeghrz/kubernetes-pod2pod-log
restartPolicy: Always
envFrom:
- configMapRef:
name: k8s-pod2pod-log-configmap
securityContext:
privileged: true

Шаг 4: Развертывание приложения

Теперь давайте применим наши файлы определения yaml к нашему кластеру kubernetes.

kubectl apply -f sidecarloggingconfigmap.yaml
kubeclt apply -f sidecarloggingnginx.yaml

Шаг 5: Привязка порта к приложению

Здесь мы опубликуем наш деплоймент в качестве службы на nodeport, как показано ниже.

☸️ Определение пода Kubernetes в качестве службы NodePort

kubectl get svc
NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes         ClusterIP   10.96.0.1      <none>        443/TCP        215d
nginx-deployment   NodePort    10.96.242.95   <none>        80:31568/TCP   4s

Шаг 6: Генерируем входящий и исходящий трафик

Здесь мы попробуем сгенерировать входящий и исходящий трафик с узла и внутри стручка соответственно, как показано ниже.

Трафик с ноды на под

curl http://k8master.stack.com:31568

Трафик из пода в Интернет

root@nginx-deployment-6db4f9dbdb-h2tdb:/# curl www.google.com

Шаг 7: Проверка логов

Если режим привилегий не включен в initcontainer и вы пытаетесь проверить логи initcontainer, вы увидите следующую ошибку.

kubectl logs -c k8s-pod2pod-log nginx-deployment-598cdb85ff-cg4v6
log to stdout
/usr/src/app/src/cap.js:46
const linkType = cap.open(IFACENAME, _CAPFILTER, bufSize, buffer);
^
Error: socket: Operation not permitted
at Object.<anonymous> (/usr/src/app/src/cap.js:46:22)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

Если режим привилегий включен, вы сможете увидеть входящий и исходящий http-трафик, регистрируемый в формате json в stdout, как показано ниже.

kubectl logs -f -c k8s-pod2pod-log nginx-deployment-6db4f9dbdb-h2tdb
log to stdout
start capture http traffic on iface: eth0 with serverAddr: 10.0.1.94
check timeouted requests every 2000ms. timeout request after 10000ms
{ resTime: 0.508,
type: 'outgo',
srcIP: '10.0.0.x',
srcPort: 46986,
dstIP: '142.250.70.68',
dstPort: 80,
host: 'www.google.com',
url: '/',
method: 'GET',
resCode: '200',
HOSTNAME: 'nginx-deployment-6db4f9dbdb-h2tdb' }
{ resTime: 0.014,
type: 'outgo',
srcIP: '10.0.0.x',
srcPort: 57846,
dstIP: '23.62.41.85',
dstPort: 80,
host: 'www.ndtv.com',
url: '/',
method: 'GET',
resCode: '301',
HOSTNAME: 'nginx-deployment-6db4f9dbdb-h2tdb' }
{ resTime: 0.001,
type: 'income',
srcIP: '10.0.0.x',
srcPort: 58522,
dstIP: '10.0.0.x',
dstPort: 80,
host: 'k8master.stack.com:31568',
url: '/',
method: 'GET',
resCode: '200',
HOSTNAME: 'nginx-deployment-6db4f9dbdb-h2tdb' }

см. также:

 

Пожалуйста, не спамьте и никого не оскорбляйте. Это поле для комментариев, а не спамбокс. Рекламные ссылки не индексируются!
Добавить комментарий