/kind bug
We are getting lots of reports about problems caused because the KFServing admission hook is unavailable preventing pods from being created. The error message looks like the following
4m58s Warning FailedCreate replicaset/activator-5484756f7b Error creating: Internal error occurred: failed calling webhook "inferenceservice.kfserving-webhook-server.pod-mutator": Post https://kfserving-webhook-server-service.kubeflow.svc:443/mutate-pods?timeout=30s: service "kfserving-webhook-server-service" not found
Here's my understanding
For a variety of reasons we are reaching into a deadlock state where
How is the inference service currently scoped?
Here's the config for the spec
kubectl -n kubeflow get MutatingWebHookConfiguration inferenceservice.serving.kubeflow.org -o yaml
I notice the following
failurePolicy: Fail
name: inferenceservice.kfserving-webhook-server.pod-mutator
namespaceSelector:
matchExpressions:
- key: control-plane
operator: DoesNotExist
rules:
It doesn't look like the kubeflow namespace has the label "control-plane"
kubectl get namespace kubeflow -o yaml
apiVersion: v1
kind: Namespace
metadata:
creationTimestamp: "2019-11-04T13:51:37Z"
labels:
katib-metricscollector-injection: enabled
name: kubeflow
resourceVersion: "1176"
selfLink: /api/v1/namespaces/kubeflow
uid: 38b15187-ff0a-11e9-ad03-42010a8e011f
spec:
finalizers:
- kubernetes
status:
phase: Active
We probably shouldn't be applying the hook in the kubeflow namespace; that would probably prevent us from the deadlock state where we can't deploy the pods for the admission hook because the hook isn't running but the mutating hook is defined.
@animeshsingh @ellis-bigelow @ryandawsonuk
What are the various options for a quick fix that can limit the blast radius of problems with the web hook?
Short term fix could be to Ignore errors: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy though that would mean kfserving deployments might be broken.
Longer term would be to match labels which is available from 1.15? https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector
Possible fixes
Add the label control-plane to the kubeflow namespace
kubectl label namespace kubeflow control-plane=true
1. Change the namespaceSelector to be opt in; match namespaces with specific labels
* This won't work because the changes will be overwritten when the controller restarts because the controller creates the webhook
Ref: https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector
control-plane to the kubeflow namespaceA possible recipe
Get the inference spec
kubectl -n kubeflow get MutatingWebHookConfiguration inferenceservice.serving.kubeflow.org -o yaml > /tmp/inferceservice.yaml
Change the matchSelector
namespaceSelector:
matchLabels:
serving.kubeflow.org: "true"
Apply it
kubectl apply -f /tmp/inferenceservice.yaml
Label any namespaces in which you want to use KFServing as
kubectl label namespace ${NAMESPACE} serving.kubeflow.org=true
So this is related to https://github.com/kubeflow/kfserving/issues/480. As long as the kfserving controller is available then things work, even though it is looking at every Pod. The way that all Pod submissions can fail is if the controller itself isn't available. When kubernetes tries to bring it back then the hook fires but the controller isn't there to implement the hook so you get a catch-22.
I would definitely lean to simply add a control-plane label to the kubeflow namespace.
This is one of the newer features from kubebuilder that was probably missed when the original kf controllers were set up.
Opt in is a pretty poor UX for KFServing. If we want to avoid adding the control-plane label, I'd much rather users not install KFServing by default or have the webhook fail open.
From a Kubeflow perspective a cluster can have 3 types of namespaces
kubeflow - This is the system namespace where controllers and other shared components should run
*kubeflow user namespaces * - These are the namespaces in which users consume KF services
non-KF namespaces - These are all other namespaces
I think we want to require that KF not impact non-kf namespaces. KFServing's current configuration is not meeting this requirement because its selector forces non-KF namespaces to opt out by adding a label "control-plane". This is not a scalable approach. An admin/owner for non-KF namespaces shouldn't have to think about KF. More generally an admin/owner shouldn't have to worry about protecting themselves against the applications they aren't running.
The profile controller is responsible for setting up a namespace to be suitable for consumption of KF. So we can just make profile controller add any labels necessary to allow KFServing to be consumed by default so that no explicit action by the user is needed.
This is what we did before kubernetes 1.15, we have similar profile controller running in our cluster which adds a label to indicate which ones are user namespaces, so we have a namespace selector in mutating webhook configuration that only allow pods from user namespaces go through the kfserving pod mutator. Since we are on kubernetes 1.15 now we switched to use the object selector then only kfserving managed pods go through the webhook.
@yuzisun the profile controller can also add labels to each namespace. This is currently a hard coded list
https://github.com/kubeflow/kubeflow/blob/183919dccbe1e5c77aece17fd5064992383dddb6/components/profile-controller/controllers/profile_controller.go#L118
So we should add an appropriate label for kfserving.
I think we want application specific labels because someone might want to enable/disable the KFServing webhook but not other hooks.
To summarize some discussion in slack
The webhook is currently defined & created by the controller and not using a kustomize manifest
https://github.com/kubeflow/kfserving/blob/master/pkg/webhook/webhook.go#L118
The code currently doesn't explicitly set that namespace criterion but relies on the default behavior of the controller runtime
https://github.com/kubernetes-sigs/controller-runtime/blob/v0.1.9/pkg/webhook/bootstrap.go#L300
@jlewi three PRs have gone in, one each in kfserving, manifests and kubeflow profile controller to tackle this.
Thanks @animeshsingh!
Can you link to the relevant PRs so we can ensure they land in 0.7.1.
It looks like #571 is the change to kfserving.
It looks like #631 updated manifests to kfserving 0.2.2. I assume 0.2.2 includes #571?
Can we just cherry-pick #631 on to the v0.7-branch of manifests to create a 0.7.1 KFDef manifest which is shipping KFServing 0.2.2
Before we do that we need to take care of kubeflow/manifests#643
It looks like kubeflow/kubeflow#4533 is the change to the profile controller to add the appropriate label to the Kubeflow namespaces to apply the KFServing mutating webhook.
So it looks like we need to do the following
@lluunn you are the buildcop this week can you help with the above steps and coordinating the 0.7.1 release.
@lluunn am hoping you can cover this. Letme know if you will need any info. From our persepctive, two important PRs which need to land in 0.7.1 are:
https://github.com/kubeflow/manifests/pull/631
and
https://github.com/kubeflow/kfserving/pull/571
cc @hougangliu
@animeshsingh
To confirm, kubeflow/manifests#631 is to move kfserving to 0.2.2, and 0.2.2 has #571, so after cherrypick kubeflow/manifests#631 to 0.7, I don't need to do other things with #571, right?
@lluunn yes.
#571 and https://github.com/kubeflow/kubeflow/pull/4533 is what you need
When I tried to cherrypick kubeflow/manifests#631 to 0.7, I got merge conflict on some kfserving files.
Can someone from kfserving help cherrypick and resolve conflict?
@lluunn I think a suitable solution is just to overwrite the files on the v0.7-branch for kubeflow/kfserving with the files on master at the commit for #587
I think you can do this just by doing the following
Check out the files from master onto that branch; something like
git checkout master kfserving/
@jlewi I synced up with @lluunn last Friday - we are hopefully past that
Thanks @animeshsingh so IIUC
This PR went into Profile controller and was cherry picked in release
https://github.com/kubeflow/kubeflow/pull/4533
Thanks looks like profile controller manifests on master were updated in
kubeflow/manifests#646
Do we still need to cherry-pick this to the v0.7-branch of manifests?
step 1~5 of https://github.com/kubeflow/kfserving/issues/568#issuecomment-561974987 is done.
We actually didn't have any release in kubeflow/kfctl repo before.
Should we release new 0.7.1 kfctl from kubeflow/kfctl?
I tried the 0.7 kfctl (same as before) with the new 0.7.1 kfdef: https://raw.githubusercontent.com/kubeflow/manifests/v0.7-branch/kfdef/kfctl_gcp_iap.0.7.1.yaml.
Deployment succeeded, endpoint is accessible, and I can create and connect to a notebook.
Should we close this one?
@lluunn Thanks! To verify that things are working as expected in the 0.7.1 release can you
Paste into this issue the output of
kubectl get namespace ${KF-USER-NAMESPACE}
The output of
kubectl -n kubeflow get MutatingWebHookConfiguration inferenceservice.serving.kubeflow.org -o yaml
$ kg namespace kubeflow-lunkai -o yaml
apiVersion: v1
kind: Namespace
metadata:
annotations:
owner: [email protected]
creationTimestamp: "2019-12-11T23:04:28Z"
labels:
istio-injection: enabled
katib-metricscollector-injection: enabled
serving.kubeflow.org/inferenceservice: enabled . --> this one right?
name: kubeflow-lunkai
...
Seems there are two versions:
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: "2019-12-11T23:03:15Z"
generation: 1
name: inferenceservice.serving.kubeflow.org
resourceVersion: "3644"
selfLink: /apis/admissionregistration.k8s.io/v1beta1/mutatingwebhookconfigurations/inferenceservice.serving.kubeflow.org
uid: 699442b0-1c6a-11ea-b902-42010a80003a
webhooks:
- admissionReviewVersions:
- v1beta1
service:
name: kfserving-webhook-server-service
namespace: kubeflow
path: /mutate-inferenceservices
failurePolicy: Fail
name: inferenceservice.kfserving-webhook-server.defaulter
namespaceSelector:
matchExpressions:
- key: control-plane
operator: DoesNotExist
rules:
- apiGroups:
- serving.kubeflow.org
apiVersions:
- v1alpha2
operations:
- CREATE
- UPDATE
resources:
- inferenceservices
scope: '*'
sideEffects: Unknown
timeoutSeconds: 30
- admissionReviewVersions:
- v1beta1
service:
name: kfserving-webhook-server-service
namespace: kubeflow
path: /mutate-pods
failurePolicy: Fail
name: inferenceservice.kfserving-webhook-server.pod-mutator
namespaceSelector:
matchLabels:
serving.kubeflow.org/inferenceservice: enabled
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- pods
scope: '*'
sideEffects: Unknown
timeoutSeconds: 30
The inferenceservice.kfserving-webhook-server.pod-mutator indeed has serving.kubeflow.org/inferenceservice: enabled
@animeshsingh should we modify the first service as well?
no, the first one is not global mutator, it is only for inference service crd.
I lost all the kubeflow pods all of a sudden. @jlewi's workaround here works, got the pods back thanks https://github.com/kubeflow/kfserving/issues/568#issuecomment-557619909
@animeshsingh we can close this one now right ?
yes we are out of the woods on this one
cc @jlewi @ellis-bigelow
/close
@animeshsingh: Closing this issue.
In response to this:
/close
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.
Issue Label Bot is not confident enough to auto-label this issue.
See dashboard for more details.
@animeshsingh @jlewi We encountered this issue when I testing KFP multi-user support, I actually just re-verified this with the latest changes on the manifests repo. The problem first comes when control-plane is enabled on the kubeflow namespace, this prevents the istio sidecar injection from working on that namespace, so in order to have mutli-user support for KFP we removed the label. I didn't investigate any further why this happens, but I'd love to get some documentation on what KFServing is doing on those webooks.
The second issue is this deadlock outlined above, this happened when I deleted the kubeflow resources, then attempted to reinstall kubeflow (with istio already installed) this caused the widespread issue that prevented any pods from being created.
To avoid the deadlock and to have the sidecar injection on the kubeflow namespace, I had to re-apply the profile with istioctl (we are using 1.6), create the kubeflow namespace without the control-plane enabled and then proceed to install kubeflow, kfserving, knative etc...
It's quite strange but I suspect you guys or other will run into this issues so I wanted to post this information here.
Thanks @maganaluis would you mind opening a new issue?
thanks @maganaluis - the details of why the label control plane is needed are listed here
https://github.com/kubeflow/kfserving#standalone-kfserving-installation
cc @yuzisun @adrian555 @shawnzhu for awareness - multi-cloud KFP has brought a requirement to enable sidecar injection in kubeflow namespace, looks like resurfacing this old kfserving issue.
@maganaluis We need to use object selector on the mutating webhook configuration so that only kfserving labelled pods go through the KFServing pod mutator, the problem is that object selector is only supported kubernetes 1.15+ while kubeflow's minimal requirement is still kubernetes 1.14. If you are on kubernetes 1.15+ you can use following command to solve the issue.
kubectl patch mutatingwebhookconfiguration inferenceservice.serving.kubeflow.org --patch '{"webhooks":[{"name": "inferenceservice.kfserving-webhook-server.pod-mutator","objectSelector":{"matchExpressions":[{"key":"serving.kubeflow.org/inferenceservice", "operator": "Exists"}]}}]}'
@yuzisun Thank you that fixes the issue
I faced the same issue when I upgraded my GKE cluster from minor version 14 to 17.
@yuzisun's patch worked for me.
@yuzisun this solution worked. However, this issue should be re-opened as the default behavior should match this solution. Otherwise, non-kf namespaces could have pods evicted en masse.
Most helpful comment
@maganaluis We need to use object selector on the mutating webhook configuration so that only kfserving labelled pods go through the KFServing pod mutator, the problem is that object selector is only supported kubernetes 1.15+ while kubeflow's minimal requirement is still kubernetes 1.14. If you are on kubernetes 1.15+ you can use following command to solve the issue.