Skip to content

Commit

Permalink
Add statefulsets to the dashboard and CLI (#2234)
Browse files Browse the repository at this point in the history
Fixes #1983

Signed-off-by: Ivan Sim <ivan@buoyant.io>
  • Loading branch information
ihcsim authored Feb 8, 2019
1 parent 030767d commit f6e75ec
Show file tree
Hide file tree
Showing 27 changed files with 2,539 additions and 25 deletions.
2 changes: 1 addition & 1 deletion chart/templates/base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ metadata:
{{- end}}
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers"{{if not .Values.SingleNamespace}}, "namespaces"{{end}}]
Expand Down
12 changes: 7 additions & 5 deletions cli/cmd/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ func newCmdStat() *cobra.Command {
Examples:
* deploy
* deploy/my-deploy
* deploy/ po/
* ds/my-daemonset
* rc/my-replication-controller
* ns/my-ns
* authority
* au/my-authority
* po/mypod1 rc/my-replication-controller
* po mypod1 mypod2
* deploy/ po/
* rc/my-replication-controller
* sts/my-statefulset
* authority
* au/my-authority
* all
Valid resource types include:
Expand All @@ -75,9 +76,10 @@ func newCmdStat() *cobra.Command {
* namespaces
* pods
* replicationcontrollers
* statefulsets
* authorities (not supported in --from)
* services (only supported if a --from is also specified, or as a --to)
* jobs (only supported as a --from or --to)
* services (only supported if a --from is also specified, or as a --to)
* all (all resource types, not supported in --from or --to)
This command will hide resources that have completed, such as pods that are in the Succeeded or Failed phases.
Expand Down
7 changes: 5 additions & 2 deletions cli/cmd/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,18 @@ func newCmdTap() *cobra.Command {
* deploy my-deploy
* ds/my-daemonset
* ns/my-ns
* sts
* sts/my-statefulset
Valid resource types include:
* daemonsets
* deployments
* namespaces
* pods
* replicationcontrollers
* services (only supported as a --to resource)
* jobs (only supported as a --to resource)`,
* statefulsets
* jobs (only supported as a --to resource)
* services (only supported as a --to resource)`,
Example: ` # tap the web deployment in the default namespace
linkerd tap deploy/web
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_default.golden
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ metadata:
name: linkerd-linkerd-controller
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_ha_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ metadata:
name: linkerd-linkerd-controller
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_ha_with_overrides_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ metadata:
name: linkerd-linkerd-controller
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_no_init_container.golden
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ metadata:
name: linkerd-linkerd-controller
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ metadata:
name: linkerd-linkerd-controller
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ metadata:
name: linkerd-Namespace-controller
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers", "namespaces"]
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/testdata/install_single_namespace_output.golden
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ metadata:
namespace: Namespace
rules:
- apiGroups: ["extensions", "apps"]
resources: ["daemonsets", "deployments", "replicasets"]
resources: ["daemonsets", "deployments", "replicasets", "statefulsets"]
verbs: ["list", "get", "watch"]
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "replicationcontrollers"]
Expand Down
7 changes: 5 additions & 2 deletions cli/cmd/top.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,18 @@ func newCmdTop() *cobra.Command {
* deploy my-deploy
* ds/my-daemonset
* ns/my-ns
* sts
* sts/my-statefulset
Valid resource types include:
* daemonsets
* deployments
* namespaces
* pods
* replicationcontrollers
* services (only supported as a --to resource)
* jobs (only supported as a --to resource)`,
* statefulsets
* jobs (only supported as a --to resource),
* services (only supported as a --to resource)`,
Example: ` # display traffic for the web deployment in the default namespace
linkerd top deploy/web
Expand Down
103 changes: 102 additions & 1 deletion controller/api/public/stat_summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ func testStatSummary(t *testing.T, expectations []statSumExpected) {
if !proto.Equal(exp.expectedResponse.GetOk(), statOkRsp) {
t.Fatalf("Expected: %+v\n Got: %+v", &exp.expectedResponse, rsp)
}

}
}

Expand Down Expand Up @@ -286,6 +285,101 @@ status:
testStatSummary(t, expectations)
})

t.Run("Successfully performs a query based on resource type StatefulSet", func(t *testing.T) {
expectations := []statSumExpected{
statSumExpected{
expectedStatRPC: expectedStatRPC{
err: nil,
k8sConfigs: []string{`
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: emojivoto
labels:
app: redis
linkerd.io/control-plane-ns: linkerd
spec:
replicas: 3
serviceName: redis
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- image: redis
volumeMounts:
- name: data
mountPath: /var/lib/redis
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
`, `
apiVersion: v1
kind: Pod
metadata:
name: redis-0
namespace: emojivoto
labels:
app: redis
linkerd.io/control-plane-ns: linkerd
status:
phase: Running
`, `
apiVersion: v1
kind: Pod
metadata:
name: redis-1
namespace: emojivoto
labels:
app: redis
linkerd.io/control-plane-ns: linkerd
status:
phase: Running
`, `
apiVersion: v1
kind: Pod
metadata:
name: redis-2
namespace: emojivoto
labels:
app: redis
linkerd.io/control-plane-ns: linkerd
status:
phase: Running
`,
},
mockPromResponse: prometheusMetric("redis", "statefulset", "emojivoto", "success", false),
},
req: pb.StatSummaryRequest{
Selector: &pb.ResourceSelection{
Resource: &pb.Resource{
Namespace: "emojivoto",
Type: pkgK8s.StatefulSet,
},
},
TimeWindow: "1m",
},
expectedResponse: GenStatSummaryResponse("redis", pkgK8s.StatefulSet, []string{"emojivoto"}, &PodCounts{
MeshedPods: 3,
RunningPods: 3,
FailedPods: 0,
}, true),
},
}

testStatSummary(t, expectations)
})

t.Run("Queries prometheus for a specific resource if name is specified", func(t *testing.T) {
expectations := []statSumExpected{
statSumExpected{
Expand Down Expand Up @@ -713,6 +807,13 @@ status:
},
},
},
&pb.StatTable{
Table: &pb.StatTable_PodGroup_{
PodGroup: &pb.StatTable_PodGroup{
Rows: []*pb.StatTable_PodGroup_Row{},
},
},
},
&pb.StatTable{
Table: &pb.StatTable_PodGroup_{
PodGroup: &pb.StatTable_PodGroup{
Expand Down
64 changes: 64 additions & 0 deletions controller/api/public/top_routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,36 @@ spec:
containers:
- image: buoyantio/booksapp:v0.0.2`

var booksStatefulsetConfig = `kind: StatefulSet
apiVersion: apps/v1
metadata:
name: books
namespace: default
spec:
selector:
matchLabels:
app: books
template:
serviceName: books
metadata:
labels:
app: books
spec:
containers:
- image: buoyantio/booksapp:v0.0.2
volumes:
- name: data
mountPath: /usr/src/app
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
`

var booksServiceConfig = []string{
// service/books
`apiVersion: v1
Expand Down Expand Up @@ -93,6 +123,7 @@ spec:

var booksConfig = append(booksServiceConfig, booksDeployConfig)
var booksDSConfig = append(booksServiceConfig, booksDaemonsetConfig)
var booksSSConfig = append(booksServiceConfig, booksStatefulsetConfig)

type topRoutesExpected struct {
expectedStatRPC
Expand Down Expand Up @@ -292,6 +323,39 @@ func TestTopRoutes(t *testing.T) {
testTopRoutes(t, expectations)
})

t.Run("Successfully performs a routes query for a statefulset", func(t *testing.T) {
routes := []string{"/a"}
counts := []uint64{123}
expectations := []topRoutesExpected{
topRoutesExpected{
expectedStatRPC: expectedStatRPC{
err: nil,
mockPromResponse: routesMetric([]string{"/a"}),
expectedPrometheusQueries: []string{
`histogram_quantile(0.5, sum(irate(route_response_latency_ms_bucket{direction="inbound", dst=~"(books.default.svc.cluster.local)(:\\d+)?", namespace="default", statefulset="books"}[1m])) by (le, dst, rt_route))`,
`histogram_quantile(0.95, sum(irate(route_response_latency_ms_bucket{direction="inbound", dst=~"(books.default.svc.cluster.local)(:\\d+)?", namespace="default", statefulset="books"}[1m])) by (le, dst, rt_route))`,
`histogram_quantile(0.99, sum(irate(route_response_latency_ms_bucket{direction="inbound", dst=~"(books.default.svc.cluster.local)(:\\d+)?", namespace="default", statefulset="books"}[1m])) by (le, dst, rt_route))`,
`sum(increase(route_response_total{direction="inbound", dst=~"(books.default.svc.cluster.local)(:\\d+)?", namespace="default", statefulset="books"}[1m])) by (rt_route, dst, classification)`,
},
k8sConfigs: booksSSConfig,
},
req: pb.TopRoutesRequest{
Selector: &pb.ResourceSelection{
Resource: &pb.Resource{
Namespace: "default",
Type: pkgK8s.StatefulSet,
Name: "books",
},
},
TimeWindow: "1m",
},
expectedResponse: GenTopRoutesResponse(routes, counts, false, "books"),
},
}

testTopRoutes(t, expectations)
})

t.Run("Successfully performs an outbound routes query", func(t *testing.T) {
routes := []string{"/a"}
counts := []uint64{123}
Expand Down
10 changes: 6 additions & 4 deletions controller/api/util/api_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var (
k8s.Namespace,
k8s.Pod,
k8s.ReplicationController,
k8s.StatefulSet,
}

// ValidTapDestinations specifies resource types allowed as a tap destination:
Expand All @@ -45,6 +46,7 @@ var (
k8s.Pod,
k8s.ReplicationController,
k8s.Service,
k8s.StatefulSet,
}
)

Expand Down Expand Up @@ -551,16 +553,16 @@ func K8sPodToPublicPod(pod v1.Pod, ownerKind string, ownerName string) pb.Pod {
switch ownerKind {
case k8s.Deployment:
item.Owner = &pb.Pod_Deployment{Deployment: namespacedOwnerName}
case k8s.DaemonSet:
item.Owner = &pb.Pod_DaemonSet{DaemonSet: namespacedOwnerName}
case k8s.Job:
item.Owner = &pb.Pod_Job{Job: namespacedOwnerName}
case k8s.ReplicaSet:
item.Owner = &pb.Pod_ReplicaSet{ReplicaSet: namespacedOwnerName}
case k8s.ReplicationController:
item.Owner = &pb.Pod_ReplicationController{ReplicationController: namespacedOwnerName}
case k8s.StatefulSet:
item.Owner = &pb.Pod_StatefulSet{StatefulSet: namespacedOwnerName}
case k8s.DaemonSet:
item.Owner = &pb.Pod_DaemonSet{DaemonSet: namespacedOwnerName}
case k8s.Job:
item.Owner = &pb.Pod_Job{Job: namespacedOwnerName}
}

return item
Expand Down
Loading

0 comments on commit f6e75ec

Please sign in to comment.