如何从 Kubernetes 集群中正在运行的 Pod 内部获取外部 IP 地址?

如何从 Kubernetes 集群中正在运行的 Pod 内部获取外部 IP 地址?

一些服务需要由负载均衡器对象(比如 Metallb)在运行时提供的外部 IP 地址(例如 LHOST 或 pasv_address)。

假设你已经基于 Alpine:latest 构建了一个镜像。附加到 pod 后,似乎没有办法内部的正在运行的 Pod 知道负载均衡器为其分配了哪个 IP 地址,

那么如何从 Kubernetes 集群中正在运行的 Pod 内部获取外部 IP 地址?

答案1

在这里我可以为你节省数小时的研究时间:

诀窍是使用集群中的控制节点提供的 API(如果您正在试验,它可能是 minikube virtualbox vm 或 docker 容器)。您可以按如下方式访问它:

首先创建一个服务帐户,您可以通过该帐户访问 Kubernetes 控制平面 API(顺便说一下,pod-service-access 这个名称完全是任意的):

 kubectl create serviceaccount pod-service-access

或者,您还可以通过应用以下 yaml 来创建 serviceaccount:

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

然后应用以下 ClusterRole 和 Rolebinding yaml,它将为服务帐户分配权限并将其绑定到 clusterrole。如您所见,服务帐户 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

现在,您必须将服务帐户分配给部署,这样当部署生成 pod 时,这些正在运行的 pod 将使用用户帐户的权限访问控制节点 api。这是一个示例部署,请特别注意“serviceAccount: pod-service-access”行,并且在构建 dockerimage 时不要忘记安装包“jq”和“curl”:

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: {}

现在,当您的部署生成新的 pod 时,您将能够访问 kubernetes 控制节点 api。这是一个脚本,它将从 api 中提取服务“vsftpd”的信息(重要:这里我假设您的服务名称与您的部署名称相同,如 SERVICE= 行中所示),并通过一些 jq(json 处理器)魔法提取外部 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 $?

祝 Codam (ja toch) 的 ft_services 好运。

相关内容