mirror of
https://github.com/hanzo-ml/kserve.git
synced 2026-10-30 20:53:49 +00:00
232 lines
9.8 KiB
Bash
Executable File
232 lines
9.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# Usage: kserve_migration.sh
|
|
|
|
set -o errexit
|
|
set -o errtrace
|
|
|
|
export KSERVE_VERSION=v0.7.0-rc0
|
|
export CONFIG_DIR="config"
|
|
export ISVC_CONFIG_DIR="${CONFIG_DIR}/isvc"
|
|
export KSVC_CONFIG_DIR="${CONFIG_DIR}/ksvc"
|
|
|
|
CLEAN_KFSERVING="true"
|
|
KFSERVING_NAMESPACE=${KFSERVING_NAMESPACE:-kfserving-system}
|
|
|
|
# custom logger
|
|
log() {
|
|
level=$1
|
|
msg=$2
|
|
ts=$(date -u +'%F %T')
|
|
echo "${ts} [${level}] $msg"
|
|
}
|
|
|
|
# Validates whether controller manager and models web app service running
|
|
# on this machine for the given namespace or not.
|
|
isControllerRunning() {
|
|
namespace=$1
|
|
prefix="kserve"
|
|
if [ "${namespace}" == "${KFSERVING_NAMESPACE}" ]; then
|
|
prefix="kfserving"
|
|
fi
|
|
svc_names=$(kubectl get svc -n $namespace -o jsonpath='{.items[*].metadata.name}')
|
|
for svc_name in "${prefix}-controller-manager-metrics-service" \
|
|
"${prefix}-controller-manager-service"; do
|
|
if [ ! -z "${svc_names##*$svc_name*}" ]; then
|
|
log ERROR "${prefix} controller services are not installed completely."
|
|
exit 1;
|
|
fi
|
|
done
|
|
po_names=$(kubectl get po -n $namespace -o jsonpath='{.items[*].metadata.name}')
|
|
po_name="${prefix}-controller-manager"
|
|
if [ ! -z "${po_names##*$po_name*}" ]; then
|
|
log ERROR "${prefix} controller services are not installed completely."
|
|
exit 1;
|
|
fi
|
|
}
|
|
|
|
# Checks user preference on cleaning kfserving controller
|
|
if [ "${REMOVE_KFSERVING}" == "false" ]; then
|
|
CLEAN_KFSERVING="false"
|
|
fi
|
|
|
|
# Checks whether the kfserving is running or not
|
|
log INFO "checking whether kfserving is running or not"
|
|
isControllerRunning "${KFSERVING_NAMESPACE}"
|
|
|
|
# Checks whether the kserve is running or not
|
|
log INFO "checking whether kserve is running or not"
|
|
isControllerRunning kserve
|
|
|
|
# # Deploy kserve
|
|
# log INFO "deploying kserve"
|
|
# cd ..
|
|
# KSERVE_CONFIG=kserve.yaml
|
|
# for i in 1 2 3 4 5 ; do kubectl apply -f install/${KSERVE_VERSION}/${KSERVE_CONFIG} && break || sleep 15; done
|
|
# kubectl wait --for=condition=ready --timeout=120s po --all -n kserve
|
|
# isControllerRunning kserve
|
|
# cd hack
|
|
# log INFO "kserve deployment completed"
|
|
|
|
# Get inference services config
|
|
log INFO "getting inference services config"
|
|
inference_services=$(kubectl get inferenceservice.serving.kubeflow.org -A -o jsonpath='{.items[*].metadata.namespace},{.items[*].metadata.name}')
|
|
declare -a isvc_names
|
|
declare -a isvc_ns
|
|
declare -A kfserving_isvc_status
|
|
if [ ! -z "$inference_services" ]; then
|
|
mkdir -p ${ISVC_CONFIG_DIR}
|
|
IFS=','; isvc_split=($inference_services); unset IFS;
|
|
isvc_ns=(${isvc_split[0]})
|
|
isvc_names=(${isvc_split[1]})
|
|
fi
|
|
isvc_count=${#isvc_names[@]}
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
kubectl get inferenceservice.serving.kubeflow.org ${isvc_names[$i]} -n ${isvc_ns[$i]} -o yaml > "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
kfserving_isvc_status[${isvc_names[$i]}]=$(kubectl get inferenceservice.serving.kubeflow.org ${isvc_names[$i]} -n ${isvc_ns[$i]} -o json | jq --raw-output '.status.conditions | map(select(.type == "Ready"))[0].status')
|
|
done
|
|
|
|
# Get knative services names
|
|
log INFO "getting knative services"
|
|
knative_services=$(kubectl get ksvc -A -o jsonpath='{.items[*].metadata.namespace},{.items[*].metadata.name}')
|
|
declare -a ksvc_names;
|
|
declare -a ksvc_ns;
|
|
if [ ! -z "$knative_services" ]; then
|
|
mkdir -p ${KSVC_CONFIG_DIR}
|
|
IFS=','; ksvc_split=(${knative_services}); unset IFS;
|
|
ksvc_ns=(${ksvc_split[0]})
|
|
ksvc_names=(${ksvc_split[1]})
|
|
fi
|
|
ksvc_count=${#ksvc_names[@]}
|
|
|
|
(
|
|
# Stop kfserving controller
|
|
log INFO "stopping kfserving controller"
|
|
kubectl scale --replicas=0 statefulset.apps kfserving-controller-manager -n "${KFSERVING_NAMESPACE}"
|
|
sleep 30
|
|
|
|
trap 'kubectl scale --replicas=1 statefulset.apps kfserving-controller-manager -n ${KFSERVING_NAMESPACE}' ERR
|
|
|
|
# Deploy inference services on kserve
|
|
log INFO "deploying inference services on kserve"
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
yq 'del(.metadata.annotations[kubectl.kubernetes.io/last-applied-configuration])' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.metadata.creationTimestamp)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.metadata.finalizers)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.metadata.generation)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.metadata.resourceVersion)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.metadata.uid)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.metadata.managedFields)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
yq 'del(.status)' -i "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
sed -i -- 's/kubeflow.org/kserve.io/g' ${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml
|
|
kubectl apply --server-side=true -f "${ISVC_CONFIG_DIR}/${isvc_names[$i]}.yaml"
|
|
done
|
|
)
|
|
sleep 300
|
|
|
|
# Remove owner references from knative services
|
|
log INFO "removing owner references from knative services"
|
|
declare -A ksvc_isvc_map
|
|
for (( i=0; i<${ksvc_count}; i++ ));
|
|
do
|
|
ksvc_api_version=$(kubectl get ksvc ${ksvc_names[$i]} -n ${ksvc_ns[$i]} -o json | jq --raw-output '.metadata.ownerReferences[0].apiVersion')
|
|
if [ "$ksvc_api_version" == "serving.kubeflow.org/v1beta1" ]; then
|
|
ksvc_isvc_map[${ksvc_names[$i]}]=$(kubectl get ksvc ${ksvc_names[$i]} -n ${ksvc_ns[$i]} -o json | jq --raw-output '.metadata.ownerReferences[0].name')
|
|
kubectl patch ksvc ${ksvc_names[$i]} -n ${ksvc_ns[$i]} --type json -p='[{"op": "remove", "path": "/metadata/ownerReferences"}]'
|
|
fi
|
|
done
|
|
|
|
# Remove owner references from virtual services
|
|
log INFO "removing owner references from virtual services"
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
vsvc_api_version=$(kubectl get virtualservices ${isvc_names[$i]} -n ${isvc_ns[$i]} -o json | jq --raw-output '.metadata.ownerReferences[0].apiVersion')
|
|
if [ "$vsvc_api_version" == "serving.kubeflow.org/v1beta1" ]; then
|
|
kubectl patch virtualservices ${isvc_names[$i]} -n ${isvc_ns[$i]} --type json -p='[{"op": "remove", "path": "/metadata/ownerReferences"}]'
|
|
fi
|
|
done
|
|
sleep 5
|
|
|
|
# Extract inference service uids
|
|
log INFO "extracting inference service uids"
|
|
declare -A infr_uid_map
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
infr_uid_map[${isvc_names[$i]}]=$(kubectl get inferenceservice.serving.kserve.io ${isvc_names[$i]} -n ${isvc_ns[$i]} -o json | jq --raw-output '.metadata.uid')
|
|
done
|
|
|
|
# Update knative services with new owner reference
|
|
log INFO "updating knative services with new owner reference"
|
|
for (( i=0; i<${ksvc_count}; i++ ));
|
|
do
|
|
owner_ref_count=$(kubectl get ksvc ${ksvc_names[$i]} -n ${ksvc_ns[$i]} -o json | jq --raw-output '.metadata.ownerReferences | length')
|
|
if [ $owner_ref_count -eq 0 ]; then
|
|
isvc_name=${ksvc_isvc_map[${ksvc_names[$i]}]}
|
|
isvc_uid=${infr_uid_map[${isvc_name}]}
|
|
kubectl patch ksvc ${ksvc_names[$i]} -n ${ksvc_ns[$i]} --type='json' -p='[{"op": "add", "path": "/metadata/ownerReferences", "value": [{"apiVersion": "serving.kserve.io/v1beta1","blockOwnerDeletion": true,"controller": true,"kind": "InferenceService","name": "'${isvc_name}'","uid": "'${isvc_uid}'"}] }]'
|
|
fi
|
|
done
|
|
|
|
# Update virtual services with new owner reference
|
|
log INFO "updating virtual services with new owner reference"
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
owner_ref_count=$(kubectl get virtualservices ${isvc_names[$i]} -n ${isvc_ns[$i]} -o json | jq --raw-output '.metadata.ownerReferences | length')
|
|
if [ $owner_ref_count -eq 0 ]; then
|
|
isvc_uid=${infr_uid_map[${isvc_names[$i]}]}
|
|
kubectl patch virtualservices ${isvc_names[$i]} -n ${isvc_ns[$i]} --type='json' -p='[{"op": "add", "path": "/metadata/ownerReferences", "value": [{"apiVersion": "serving.kserve.io/v1beta1","blockOwnerDeletion": true,"controller": true,"kind": "InferenceService","name": "'${isvc_names[$i]}'","uid": "'${isvc_uid}'"}] }]'
|
|
fi
|
|
done
|
|
sleep 5
|
|
|
|
# Verify that all inference services are migrated and ready
|
|
log INFO "verifying inference services are migrated and ready"
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
if [ "${kfserving_isvc_status[${isvc_names[$i]}]}" == "True" ]; then
|
|
(
|
|
trap 'log ERROR "inference service ${isvc_names[$i]} did not migrate properly. migration job exits with code 1."' ERR
|
|
kubectl wait --for=condition=ready --timeout=10s inferenceservice.serving.kserve.io/${isvc_names[$i]} -n ${isvc_ns[$i]}
|
|
)
|
|
fi
|
|
done
|
|
|
|
# Start kfserving controller for clean up
|
|
log INFO "starting kfserving controller for clean up"
|
|
kubectl scale --replicas=1 statefulset.apps kfserving-controller-manager -n "${KFSERVING_NAMESPACE}"
|
|
|
|
# Delete inference services running on kfserving
|
|
log INFO "deleting inference services on kfserving"
|
|
for (( i=0; i<${isvc_count}; i++ ));
|
|
do
|
|
kubectl delete inferenceservice.serving.kubeflow.org ${isvc_names[$i]} -n ${isvc_ns[$i]}
|
|
done
|
|
|
|
# Clean up kfserving
|
|
if [ "${CLEAN_KFSERVING}" == "true" ]; then
|
|
log INFO "deleting kfserving namespace"
|
|
|
|
if [ "${KFSERVING_NAMESPACE}" != "kubeflow" ]; then
|
|
kubectl delete ns "${KFSERVING_NAMESPACE}"
|
|
fi
|
|
|
|
log INFO "deleting kfserving cluster role and cluster role binding"
|
|
kubectl delete ClusterRoleBinding kfserving-manager-rolebinding
|
|
kubectl delete ClusterRoleBinding kfserving-models-web-app-binding
|
|
kubectl delete ClusterRoleBinding kfserving-proxy-rolebinding
|
|
|
|
log INFO "deleting kfserving webhook configuration and crd"
|
|
kubectl delete CustomResourceDefinition inferenceservices.serving.kubeflow.org
|
|
kubectl delete CustomResourceDefinition trainedmodels.serving.kubeflow.org
|
|
|
|
kubectl delete MutatingWebhookConfiguration inferenceservice.serving.kubeflow.org
|
|
kubectl delete ValidatingWebhookConfiguration inferenceservice.serving.kubeflow.org
|
|
kubectl delete ValidatingWebhookConfiguration trainedmodel.serving.kubeflow.org
|
|
fi
|
|
|
|
rm -rf ${CONFIG_DIR}
|
|
|
|
log INFO "kserve migration completed successfully"
|
|
exit 0;
|