我正在开发一个项目,每次我的应用程序调用我的azure函数时,我都需要这个函数以某种方式重新启动kubernetes中的pod,我不确定如何做到这一点,我正在考虑使用函数运行脚本重新启动这个 Pod,但我不知道如何设置我的函数来执行此操作,或者这是否可能。
我是天蓝色的新手,所以每个帮助都会持续。谢谢你
我尝试在函数中使用 SDK,但无法连接到 Closter,我得到了
DefaultAzureCredential acquired a token from EnvironmentCredential
[2024-09-20T03:41:52.511Z] C:\Users\Andres_Sanchez1\AppData\Roaming\Python\Python311\site-packages\urllib3\connectionpool.py:1061: InsecureRequestWarning: Unverified HTTPS request is being made to host 'abccall-demo-lgq05iz2.hcp.eastus.azmk8s.io'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
[2024-09-20T03:41:52.514Z] warnings.warn(
[2024-09-20T03:42:04.837Z] Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000002835461E050>: Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it')': /api/v1/namespaces/eks_demo/pods
[2024-09-20T03:42:08.923Z] 401
[2024-09-20T03:42:08.923Z] Unexpected error: HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /api/v1/namespaces/eks_demo/pods (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000002835461E9D0>: Failed to establish a new connection: [WinError 10061] No connection could be made because the target machine actively refused it'))
[2024-09-20T03:42:08.928Z] {'kind': 'Status', 'apiVersion': 'v1', 'metadata': {}, 'status': 'Failure', 'message': 'Unauthorized', 'reason': 'Unauthorized', 'code': 401}
我能够从azure获取凭据,但我无法与集群通信,这是我的功能代码:
import logging
import os
import azure.functions as func
from kubernetes import client, config
from kubernetes.client.rest import ApiException
from azure.identity import DefaultAzureCredential
import requests
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
@app.route(route="http_trigger")
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Processing a request to restart a Kubernetes pod using managed identity.')
# Get pod name and namespace from query parameters
pod_name = req.params.get('pod_name')
namespace = req.params.get('namespace', 'default')
if not pod_name:
return func.HttpResponse(
"Please pass a pod_name in the query string.",
status_code=400
)
try:
# Use ManagedIdentityCredential for managed identity authentication
credential = DefaultAzureCredential()
# Get the AKS API server endpoint from environment variables
aks_api_server = 'https://abccall-demo-lgq05iz2.hcp.eastus.azmk8s.io' # Set this in your Function App settings
if not aks_api_server:
return func.HttpResponse("AKS_API_SERVER environment variable is not set.", status_code=500)
# Get the access token
token = credential.get_token("https://management.azure.com/.default").token
# Create a Kubernetes API client configuration
configuration = client.Configuration()
configuration.host = aks_api_server
configuration.verify_ssl = False # Consider enabling SSL verification in production
configuration.api_key = {"authorization": f"Bearer {token}"}
response = requests.get(f"{aks_api_server}/api/v1/namespaces/default/pods", verify=False) # Change verify=True in production
print(response.status_code)
print(response.json())
# Create the Kubernetes API client
k8s_client = client.CoreV1Api(client.ApiClient(configuration))
v1 = client.CoreV1Api()
pods = v1.list_namespaced_pod(namespace)
for pod in pods.items:
print(f"Pod Name: {pod.metadata.name}")
# Delete the pod to trigger a restart
logging.info(f"Attempting to restart pod {pod_name} in namespace {namespace}.")
k8s_client.delete_namespaced_pod(pod_name, namespace, body=client.V1DeleteOptions())
return func.HttpResponse(
f"Pod {pod_name} in namespace {namespace} has been restarted.",
status_code=200
)
except ApiException as e:
logging.error(f"Exception when calling CoreV1Api->delete_namespaced_pod: {e}")
return func.HttpResponse(
f"Error: {str(e)}",
status_code=e.status
)
except Exception as e:
logging.error(f"Unexpected error: {e}")
return func.HttpResponse(
f"Error: {str(e)}",
status_code=500
)
我希望能够连接到集群并重新启动我的 Pod
您需要将托管身份分配给AKS集群中具有足够权限的函数。由于您已经编写了一个 Python 函数来重新启动 pod,因此创建集群后,请为 Azure Function 创建系统分配的托管标识。
az storage account create --name arkofunctionstorage --resource-group arkorg --location eastus --sku Standard_LRS
az functionapp create \
--resource-group arkorg \
--consumption-plan-location eastus \
--runtime python \
--functions-version 4 \
--name MyK8sFunctionApp \
--storage-account arkofunctionstorage \
--os-type Linux \
--assign-identity
将必要的角色(Azure Kubernetes 服务 RBAC 集群管理员角色)分配给 Azure Function 的托管标识
az functionapp identity show --name MyK8sFunctionApp --resource-group arkorg --query principalId --output tsv
az role assignment create --assignee 1234-79f2-abcd-5678-54xyzc \
--scope /subscriptions/abcd-efg-hijk-lmnop-uvwxyz/resourcegroups/arkorg/providers/Microsoft.ContainerService/managedClusters/myAKSCluster \
--role "Azure Kubernetes Service RBAC Cluster Admin"
接下来,创建集群角色和角色绑定,以便托管身份具有与 Pod 交互所需的权限。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: function-app-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "delete"]
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: function-app-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: function-app-role
subjects:
- kind: User
name: 13f2b02a-79f2-47c5-9ad5-54f7a35e30fc
apiGroup: rbac.authorization.k8s.io
现在使用 Azure Function 代码重新启动 Kubernetes pod。您共享的代码中的问题是身份验证部分并确保 AKS API 服务器通信的 SSL 验证。下面是更新的
import logging
import azure.functions as func
from azure.identity import DefaultAzureCredential
from kubernetes import client, config
def main(req: func.HttpRequest) -> func.HttpResponse:
try:
# Get pod name and namespace from query parameters
pod_name = req.params.get('pod_name')
namespace = req.params.get('namespace', 'default')
if not pod_name:
return func.HttpResponse(
"Please pass a pod_name in the query string.",
status_code=400
)
aks_api_server = 'https://myakscluster-dns-ieevn5ni.hcp.eastus.azmk8s.io'
# Get token using managed identity
credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/.default").token
configuration = client.Configuration()
configuration.host = aks_api_server
configuration.verify_ssl = True
configuration.api_key = {"authorization": f"Bearer {token}"}
k8s_client = client.CoreV1Api(client.ApiClient(configuration))
logging.info(f"Attempting to restart pod {pod_name} in namespace {namespace}.")
# Restart pod by deleting it
k8s_client.delete_namespaced_pod(pod_name, namespace, body=client.V1DeleteOptions())
return func.HttpResponse(
f"Pod {pod_name} in namespace {namespace} has been restarted.",
status_code=200
)
except client.ApiException as e:
logging.error(f"Exception when calling CoreV1Api->delete_namespaced_pod: {e}")
return func.HttpResponse(
f"Error: {str(e)}",
status_code=e.status
)
except Exception as e:
logging.error(f"Unexpected error: {e}")
return func.HttpResponse(
f"Error: {str(e)}",
status_code=500
)
构建并运行它
该函数删除指定的pod,会触发k8s重新创建pod