Skip to content

Commit

Permalink
Add ztunnel configdump and log to bugreport (istio#43878)
Browse files Browse the repository at this point in the history
* init

* add feature

* add log test

* fix lint

* revise after ztunnel change

* address comments

* add copyright

* fix log processing test

* fix lint

* fix log processing
  • Loading branch information
hanxiaop authored Apr 5, 2023
1 parent d954f1b commit f916acc
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 183 deletions.
17 changes: 7 additions & 10 deletions istioctl/cmd/proxyconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"

ambientutil "istio.io/istio/istioctl/pkg/util/ambient"
"istio.io/istio/istioctl/pkg/util/handlers"
"istio.io/istio/istioctl/pkg/writer"
"istio.io/istio/istioctl/pkg/writer/envoy/clusters"
Expand Down Expand Up @@ -496,7 +497,7 @@ func allConfigCmd() *cobra.Command {
return err
}

if isZtunnelPod(podName) {
if ambientutil.IsZtunnelPod(podName) {
dump, err = extractZtunnelConfigDump(podName, podNamespace)
} else {
dump, err = extractConfigDump(podName, podNamespace, false)
Expand Down Expand Up @@ -525,7 +526,7 @@ func allConfigCmd() *cobra.Command {
return err
}

if isZtunnelPod(podName) {
if ambientutil.IsZtunnelPod(podName) {
w, err := setupZtunnelConfigDumpWriter(podName, podNamespace, c.OutOrStdout())
if err != nil {
return err
Expand Down Expand Up @@ -635,7 +636,7 @@ func workloadConfigCmd() *cobra.Command {
if podName, podNamespace, err = getComponentPodName(args[0]); err != nil {
return err
}
if !isZtunnelPod(podName) {
if !ambientutil.IsZtunnelPod(podName) {
return fmt.Errorf("workloads command is only supported by ztunnel proxies: %v", podName)
}
configWriter, err = setupZtunnelConfigDumpWriter(podName, podNamespace, c.OutOrStdout())
Expand Down Expand Up @@ -877,7 +878,7 @@ func logCmd() *cobra.Command {
if err != nil {
return err
}
if isZtunnelPod(pod) {
if ambientutil.IsZtunnelPod(pod) {
loggerNames[name] = Ztunnel
} else {
loggerNames[name] = Envoy
Expand Down Expand Up @@ -931,7 +932,7 @@ func logCmd() *cobra.Command {
var resp string
var errs *multierror.Error
for _, podName := range podNames {
if isZtunnelPod(podName) {
if ambientutil.IsZtunnelPod(podName) {
q := "level=" + ztunnelLogLevel(loggerLevelString)
if reset {
q += "&reset"
Expand Down Expand Up @@ -992,10 +993,6 @@ func logCmd() *cobra.Command {
return logCmd
}

func isZtunnelPod(podName string) bool {
return strings.HasPrefix(podName, "ztunnel")
}

func routeConfigCmd() *cobra.Command {
var podName, podNamespace string

Expand Down Expand Up @@ -1314,7 +1311,7 @@ func secretConfigCmd() *cobra.Command {
if podName, podNamespace, err = getPodName(args[0]); err != nil {
return err
}
if isZtunnelPod(podName) {
if ambientutil.IsZtunnelPod(podName) {
newWriter, err = setupZtunnelConfigDumpWriter(podName, podNamespace, c.OutOrStdout())
} else {
newWriter, err = setupPodConfigdumpWriter(podName, podNamespace, false, c.OutOrStdout())
Expand Down
21 changes: 21 additions & 0 deletions istioctl/pkg/util/ambient/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ambient

import "strings"

func IsZtunnelPod(podName string) bool {
return strings.HasPrefix(podName, "ztunnel")
}
7 changes: 6 additions & 1 deletion tools/bug-report/pkg/bugreport/bugreport.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/spf13/cobra"

label2 "istio.io/api/label"
"istio.io/istio/istioctl/pkg/util/ambient"
"istio.io/istio/operator/pkg/util"
"istio.io/istio/pkg/kube"
"istio.io/istio/pkg/kube/inject"
Expand Down Expand Up @@ -305,12 +306,16 @@ func gatherInfo(runner *kubectlcmd.Runner, config *config.BugReportConfig, resou
cp := params.SetNamespace(namespace).SetPod(pod).SetContainer(container)
proxyDir := archive.ProxyOutputPath(tempDir, namespace, pod)
switch {
case common.IsProxyContainer(params.ClusterVersion, container):
case common.IsProxyContainer(params.ClusterVersion, container) && !ambient.IsZtunnelPod(pod):
getFromCluster(content.GetCoredumps, cp, filepath.Join(proxyDir, "cores"), &mandatoryWg)
getFromCluster(content.GetNetstat, cp, proxyDir, &mandatoryWg)
getFromCluster(content.GetProxyInfo, cp, archive.ProxyOutputPath(tempDir, namespace, pod), &optionalWg)
getProxyLogs(runner, config, resources, p, namespace, pod, container, &optionalWg)

case ambient.IsZtunnelPod(pod):
getFromCluster(content.GetNetstat, cp, proxyDir, &mandatoryWg)
getFromCluster(content.GetZtunnelInfo, cp, archive.ProxyOutputPath(tempDir, namespace, pod), &optionalWg)
getProxyLogs(runner, config, resources, p, namespace, pod, container, &optionalWg)
case resources.IsDiscoveryContainer(params.ClusterVersion, namespace, pod, container):
getFromCluster(content.GetIstiodInfo, cp, archive.IstiodPath(tempDir, namespace, pod), &mandatoryWg)
getIstiodLogs(runner, config, resources, namespace, pod, &mandatoryWg)
Expand Down
94 changes: 78 additions & 16 deletions tools/bug-report/pkg/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"

"istio.io/istio/operator/pkg/name"
analyzer_util "istio.io/istio/pkg/config/analysis/analyzers/util"
"istio.io/istio/pkg/config/resource"
"istio.io/istio/tools/bug-report/pkg/common"
Expand All @@ -44,18 +45,13 @@ func ParsePath(path string) (namespace string, deployment, pod string, container
}

// shouldSkip means that current pod should be skip or not based on given --include and --exclude
func shouldSkip(deployment string, config *config2.BugReportConfig, pod *corev1.Pod) bool {
func shouldSkipPod(pod *corev1.Pod, config *config2.BugReportConfig) bool {
for _, eld := range config.Exclude {
if len(eld.Namespaces) > 0 {
if isIncludeOrExcludeEntriesMatched(eld.Namespaces, pod.Namespace) {
return true
}
}
if len(eld.Deployments) > 0 {
if isIncludeOrExcludeEntriesMatched(eld.Deployments, deployment) {
return true
}
}
if len(eld.Pods) > 0 {
if isIncludeOrExcludeEntriesMatched(eld.Pods, pod.Name) {
return true
Expand Down Expand Up @@ -94,11 +90,6 @@ func shouldSkip(deployment string, config *config2.BugReportConfig, pod *corev1.
return true
}
}
if len(ild.Deployments) > 0 {
if !isIncludeOrExcludeEntriesMatched(ild.Deployments, deployment) {
return true
}
}
if len(ild.Pods) > 0 {
if !isIncludeOrExcludeEntriesMatched(ild.Pods, pod.Name) {
return true
Expand Down Expand Up @@ -151,6 +142,45 @@ func shouldSkip(deployment string, config *config2.BugReportConfig, pod *corev1.
return false
}

func shouldSkipDeployment(deployment string, config *config2.BugReportConfig) bool {
for _, eld := range config.Exclude {
if len(eld.Deployments) > 0 {
if isIncludeOrExcludeEntriesMatched(eld.Deployments, deployment) {
return true
}
}
}

for _, ild := range config.Include {
if len(ild.Deployments) > 0 {
if !isIncludeOrExcludeEntriesMatched(ild.Deployments, deployment) {
return true
}
}
}

return false
}

func shouldSkipDaemonSet(daemonSet string, config *config2.BugReportConfig) bool {
for _, eld := range config.Exclude {
if len(eld.Daemonsets) > 0 {
if isIncludeOrExcludeEntriesMatched(eld.Daemonsets, daemonSet) {
return true
}
}
}

for _, ild := range config.Include {
if len(ild.Daemonsets) > 0 {
if !isIncludeOrExcludeEntriesMatched(ild.Daemonsets, daemonSet) {
return true
}
}
}
return false
}

func isExactMatchedOrPatternMatched(pattern string, term string) bool {
result, _ := regexp.MatchString(entryPatternToRegexp(pattern), term)
return result
Expand Down Expand Up @@ -194,19 +224,38 @@ func GetClusterResources(ctx context.Context, clientset *kubernetes.Clientset, c
return nil, err
}

daemonsets, err := clientset.AppsV1().DaemonSets("").List(ctx, metav1.ListOptions{})
if err != nil {
return nil, err
}

for i, p := range pods.Items {
if analyzer_util.IsSystemNamespace(resource.Namespace(p.Namespace)) {
continue
}
if skip := shouldSkipPod(&p, config); skip {
continue
}

deployment := getOwnerDeployment(&p, replicasets.Items)
if skip := shouldSkip(deployment, config, &p); skip {
if skip := shouldSkipDeployment(deployment, config); skip {
continue
}
daemonset := getOwnerDaemonSet(&p, daemonsets.Items)
if skip := shouldSkipDaemonSet(daemonset, config); skip {
continue
}

for _, c := range p.Spec.Containers {
out.insertContainer(p.Namespace, deployment, p.Name, c.Name)
if deployment != "" {
for _, c := range p.Spec.Containers {
out.insertContainer(p.Namespace, deployment, p.Name, c.Name)
}
} else if daemonset != "" {
for _, c := range p.Spec.Containers {
out.insertContainer(p.Namespace, daemonset, p.Name, c.Name)
}
}

out.Labels[PodKey(p.Namespace, p.Name)] = p.Labels
out.Annotations[PodKey(p.Namespace, p.Name)] = p.Annotations
out.Pod[PodKey(p.Namespace, p.Name)] = &pods.Items[i]
Expand Down Expand Up @@ -305,11 +354,11 @@ func PodKey(namespace, pod string) string {

func getOwnerDeployment(pod *corev1.Pod, replicasets []appsv1.ReplicaSet) string {
for _, o := range pod.OwnerReferences {
if o.Kind == "ReplicaSet" {
if o.Kind == name.ReplicaSetStr {
for _, rs := range replicasets {
if rs.Name == o.Name {
for _, oo := range rs.OwnerReferences {
if oo.Kind == "Deployment" {
if oo.Kind == name.DeploymentStr {
return oo.Name
}
}
Expand All @@ -320,6 +369,19 @@ func getOwnerDeployment(pod *corev1.Pod, replicasets []appsv1.ReplicaSet) string
return ""
}

func getOwnerDaemonSet(pod *corev1.Pod, daemonsets []appsv1.DaemonSet) string {
for _, o := range pod.OwnerReferences {
if o.Kind == name.DaemonSetStr {
for _, ds := range daemonsets {
if ds.Name == o.Name {
return ds.Name
}
}
}
}
return ""
}

func imageToVersion(imageStr string) string {
vs := versionRegex.FindStringSubmatch(imageStr)
if len(vs) != 2 {
Expand Down
Loading

0 comments on commit f916acc

Please sign in to comment.