一些服务需要由负载均衡器对象(比如 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 好运。