Назад | Перейти на главную страницу

Как получить внешний IP-адрес внутри работающего пода в кластере Kubernetes?

Некоторым службам требуется внешний IP-адрес, предоставляемый объектом балансировки нагрузки, таким как Metallb, во время выполнения (например, LHOST или pasv_address).

Допустим, вы создали образ на основе Alpine: latest. Прикрепленный к капсуле, похоже, нет возможности внутренний запущенного модуля, чтобы узнать, какой ip-адрес был назначен ему балансировщиком нагрузки,

так как же получить внешний IP-адрес внутри работающего пода в кластере Kubernetes?

А здесь я сэкономлю вам часы исследования:

Уловка состоит в том, чтобы использовать API, предоставляемый управляющим узлом в кластере (который, если вы экспериментируете, вероятно, это виртуальная машина minikube virtualbox или контейнер докеров). Вы можете получить к нему доступ следующим образом:

Сначала создайте сервисный аккаунт, с помощью которого вы получите доступ к API плоскости управления kubernetes (имя pod-service-access, кстати, совершенно произвольно):

 kubectl create serviceaccount pod-service-access

Альтернативно, вы также можете создать сервисный аккаунт, применив следующий код yaml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-service-access
  namespace: default

Затем примените следующий yaml ClusterRole и Rolebinding, который назначит разрешения для serviceaccount и привяжет его к кластерной роли. Как видите, serviceaccount pod-service-access имеет доступ только для чтения ко всем службам в пространстве имен «по умолчанию». Что желательно (полагаю).

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: read-services
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "watch", "list"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-services
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: read-services
subjects:
- kind: ServiceAccount
  name: pod-service-access
  namespace: default

Теперь вам нужно будет назначить serviceaccount для развертывания, поэтому, когда развертывание будет порождать модули, эти запущенные модули будут получать доступ к API узла управления с разрешениями учетной записи пользователя. Это пример развертывания, обратите особое внимание на строку «serviceAccount: pod-service-access» и не забудьте установить пакеты «jq» и «curl» при сборке dockerimage:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vsftpd
  labels:
    app: vsftpd
spec:
  selector:
    matchLabels:
      app: vsftpd
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: vsftpd
    spec:
      serviceAccount: pod-service-access
      containers:
      - image: vsftpd-alpine:v1
        imagePullPolicy: Never
        name: vsftpd
        ports:
        - containerPort: 21
          hostPort: 21
        - containerPort: 21000
          hostPort: 21000
        volumeMounts:
        - name: vsftpd-persistent-storage
          mountPath: /data
        - name: cluster-authentication
          mountPath: /auth
        - name: varlog
          mountPath: /var/log
        - name: certificate
          mountPath: /cert
      volumes:
      - name: vsftpd-persistent-storage
        persistentVolumeClaim:
          claimName: vsftpd-pv-claim
      - name: cluster-authentication
        secret:
          secretName: cluster-authentication
      - name: certificate
        secret:
          secretName: vsftpd-cert
      - name: varlog
        emptyDir: {}

Теперь, когда у вас есть развертывание, порождающее новые модули, вы сможете получить доступ к api узла управления kubernetes. Вот сценарий, который будет извлекать информацию для службы vsftpd из api (важно: здесь я предполагаю, что имя вашей службы совпадает с именем вашего развертывания, как можно увидеть в строке SERVICE =), и некоторыми jq ( json processor) magic извлекает внешний ip:

#!/bin/sh
# Point to the internal API server hostname
APISERVER=https://kubernetes.default.svc

# Path to ServiceAccount token
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount

# Read this Pod's namespace
NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)

# Read the ServiceAccount bearer token
TOKEN=$(cat ${SERVICEACCOUNT}/token)

# Reference the internal certificate authority (CA)
CACERT=${SERVICEACCOUNT}/ca.crt

SERVICE=$(echo $HOSTNAME | cut -d- -f1)

# Explore the API with TOKEN
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/$NAMESPACE/services/$SERVICE/ 2>/dev/null| jq -r '.status | .loadBalancer | .ingress | .[] | .ip'

exit $?

Удачи с ft_services от Codam (ja toch).