mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
(kubectl debug): Support debugging via files
Currently `kubectl debug` only supports passing names in command line. However, users might want to pass resources in files by passing `-f` flag like in all other kubectl commands. This PR adds this ability.
This commit is contained in:
parent
d2f40481d1
commit
e0fedec69d
@ -77,6 +77,10 @@ var (
|
|||||||
# Create an interactive debugging session in pod mypod and immediately attach to it.
|
# Create an interactive debugging session in pod mypod and immediately attach to it.
|
||||||
kubectl debug mypod -it --image=busybox
|
kubectl debug mypod -it --image=busybox
|
||||||
|
|
||||||
|
# Create an interactive debugging session for the pod in the file pod.yaml and immediately attach to it.
|
||||||
|
# (requires the EphemeralContainers feature to be enabled in the cluster)
|
||||||
|
kubectl debug -f pod.yaml -it --image=busybox
|
||||||
|
|
||||||
# Create a debug container named debugger using a custom automated debugging image.
|
# Create a debug container named debugger using a custom automated debugging image.
|
||||||
kubectl debug --image=myproj/debug-tools -c debugger mypod
|
kubectl debug --image=myproj/debug-tools -c debugger mypod
|
||||||
|
|
||||||
@ -123,6 +127,7 @@ type DebugOptions struct {
|
|||||||
Profile string
|
Profile string
|
||||||
Applier ProfileApplier
|
Applier ProfileApplier
|
||||||
|
|
||||||
|
explicitNamespace bool
|
||||||
attachChanged bool
|
attachChanged bool
|
||||||
shareProcessedChanged bool
|
shareProcessedChanged bool
|
||||||
|
|
||||||
@ -130,6 +135,8 @@ type DebugOptions struct {
|
|||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
WarningPrinter *printers.WarningPrinter
|
WarningPrinter *printers.WarningPrinter
|
||||||
|
|
||||||
|
resource.FilenameOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDebugOptions returns a DebugOptions initialized with default values.
|
// NewDebugOptions returns a DebugOptions initialized with default values.
|
||||||
@ -160,6 +167,7 @@ func NewCmdDebug(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.
|
|||||||
}
|
}
|
||||||
|
|
||||||
addDebugFlags(cmd, o)
|
addDebugFlags(cmd, o)
|
||||||
|
cmdutil.AddJsonFilenameFlag(cmd.Flags(), &o.FilenameOptions.Filenames, "identifying the resource to debug")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +220,7 @@ func (o *DebugOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Namespace
|
// Namespace
|
||||||
o.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
|
o.Namespace, o.explicitNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -272,8 +280,8 @@ func (o *DebugOptions) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
if len(o.TargetNames) == 0 {
|
if len(o.TargetNames) == 0 && len(o.FilenameOptions.Filenames) == 0 {
|
||||||
return fmt.Errorf("NAME is required for debug")
|
return fmt.Errorf("NAME or filename is required for debug")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pull Policy
|
// Pull Policy
|
||||||
@ -327,6 +335,7 @@ func (o *DebugOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
|
|
||||||
r := f.NewBuilder().
|
r := f.NewBuilder().
|
||||||
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
||||||
|
FilenameParam(o.explicitNamespace, &o.FilenameOptions).
|
||||||
NamespaceParam(o.Namespace).DefaultNamespace().ResourceNames("pods", o.TargetNames...).
|
NamespaceParam(o.Namespace).DefaultNamespace().ResourceNames("pods", o.TargetNames...).
|
||||||
Do()
|
Do()
|
||||||
if err := r.Err(); err != nil {
|
if err := r.Err(); err != nil {
|
||||||
@ -691,18 +700,15 @@ func (o *DebugOptions) computeDebugContainerName(pod *corev1.Pod) string {
|
|||||||
if len(o.Container) > 0 {
|
if len(o.Container) > 0 {
|
||||||
return o.Container
|
return o.Container
|
||||||
}
|
}
|
||||||
name := o.Container
|
|
||||||
if len(name) == 0 {
|
cn, containerByName := "", containerNameToRef(pod)
|
||||||
cn, containerByName := "", containerNameToRef(pod)
|
for len(cn) == 0 || (containerByName[cn] != nil) {
|
||||||
for len(cn) == 0 || (containerByName[cn] != nil) {
|
cn = fmt.Sprintf("debugger-%s", nameSuffixFunc(5))
|
||||||
cn = fmt.Sprintf("debugger-%s", nameSuffixFunc(5))
|
|
||||||
}
|
|
||||||
if !o.Quiet {
|
|
||||||
fmt.Fprintf(o.Out, "Defaulting debug container name to %s.\n", cn)
|
|
||||||
}
|
|
||||||
name = cn
|
|
||||||
}
|
}
|
||||||
return name
|
if !o.Quiet {
|
||||||
|
fmt.Fprintf(o.Out, "Defaulting debug container name to %s.\n", cn)
|
||||||
|
}
|
||||||
|
return cn
|
||||||
}
|
}
|
||||||
|
|
||||||
func containerNameToRef(pod *corev1.Pod) map[string]*corev1.Container {
|
func containerNameToRef(pod *corev1.Pod) map[string]*corev1.Container {
|
||||||
|
@ -25,6 +25,18 @@ run_kubectl_debug_pod_tests() {
|
|||||||
create_and_use_new_namespace
|
create_and_use_new_namespace
|
||||||
kube::log::status "Testing kubectl debug (pod tests)"
|
kube::log::status "Testing kubectl debug (pod tests)"
|
||||||
|
|
||||||
|
### Pod Troubleshooting by ephemeral containers
|
||||||
|
|
||||||
|
# Pre-Condition: Pod "nginx" is created
|
||||||
|
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
|
# Command: create a copy of target with a new debug container
|
||||||
|
kubectl debug target -it --image=busybox --attach=false -c debug-container "${kube_flags[@]:?}"
|
||||||
|
# Post-Conditions
|
||||||
|
kube::test::get_object_assert pod/target '{{range.spec.ephemeralContainers}}{{.name}}:{{end}}' 'debug-container:'
|
||||||
|
# Clean up
|
||||||
|
kubectl delete pod target "${kube_flags[@]:?}"
|
||||||
|
|
||||||
### Pod Troubleshooting by Copy
|
### Pod Troubleshooting by Copy
|
||||||
|
|
||||||
# Pre-Condition: Pod "nginx" is created
|
# Pre-Condition: Pod "nginx" is created
|
||||||
@ -63,6 +75,19 @@ run_kubectl_debug_pod_tests() {
|
|||||||
# Clean up
|
# Clean up
|
||||||
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
||||||
|
|
||||||
|
# Pre-Condition: Pod "nginx" is created
|
||||||
|
kubectl run target "--image=${IMAGE_NGINX:?}" "${kube_flags[@]:?}"
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:'
|
||||||
|
kube::test::get_object_assert pod/target '{{(index .spec.containers 0).name}}' 'target'
|
||||||
|
# Command: copy the pod and replace the image of an existing container
|
||||||
|
kubectl get pod/target -o yaml > "${KUBE_TEMP}"/test-pod-debug.yaml
|
||||||
|
kubectl debug -f "${KUBE_TEMP}"/test-pod-debug.yaml --image=busybox --container=target --copy-to=target-copy "${kube_flags[@]:?}" -- sleep 1m
|
||||||
|
# Post-Conditions
|
||||||
|
kube::test::get_object_assert pod "{{range.items}}{{${id_field:?}}}:{{end}}" 'target:target-copy:'
|
||||||
|
kube::test::get_object_assert pod/target-copy "{{(len .spec.containers)}}:{{${image_field:?}}}" '1:busybox'
|
||||||
|
# Clean up
|
||||||
|
kubectl delete pod target target-copy "${kube_flags[@]:?}"
|
||||||
|
|
||||||
set +o nounset
|
set +o nounset
|
||||||
set +o errexit
|
set +o errexit
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user