Skip to content

Commit

Permalink
Add statefulsets to the dashboard and CLI (#1983)
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Sim <ivan@buoyant.io>
  • Loading branch information
Ivan Sim committed Feb 8, 2019
1 parent 19120d3 commit c3f131f
Show file tree
Hide file tree
Showing 27 changed files with 2,524 additions and 10 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
2 changes: 2 additions & 0 deletions cli/cmd/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func newCmdStat() *cobra.Command {
* deploy
* deploy/my-deploy
* ds/my-daemonset
* statefulset/my-statefulset
* rc/my-replication-controller
* ns/my-ns
* authority
Expand All @@ -71,6 +72,7 @@ func newCmdStat() *cobra.Command {
Valid resource types include:
* daemonsets
* statefulsets
* deployments
* namespaces
* pods
Expand Down
3 changes: 3 additions & 0 deletions cli/cmd/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ func newCmdTap() *cobra.Command {
* deploy/my-deploy
* deploy my-deploy
* ds/my-daemonset
* statefulset
* statefulset/my-statefulset
* ns/my-ns
Valid resource types include:
* daemonsets
* statefulsets
* deployments
* namespaces
* pods
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
3 changes: 3 additions & 0 deletions cli/cmd/top.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,13 @@ func newCmdTop() *cobra.Command {
* deploy/my-deploy
* deploy my-deploy
* ds/my-daemonset
* statefulset
* statefulset/my-statefulset
* ns/my-ns
Valid resource types include:
* daemonsets
* statefulsets
* deployments
* namespaces
* pods
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
2 changes: 2 additions & 0 deletions controller/api/util/api_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ var (
ValidTargets = []string{
k8s.Authority,
k8s.DaemonSet,
k8s.StatefulSet,
k8s.Deployment,
k8s.Namespace,
k8s.Pod,
Expand All @@ -39,6 +40,7 @@ var (
// destination resource on an outbound 'to' query
ValidTapDestinations = []string{
k8s.DaemonSet,
k8s.StatefulSet,
k8s.Deployment,
k8s.Job,
k8s.Namespace,
Expand Down
2 changes: 1 addition & 1 deletion controller/cmd/public-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func main() {

var spClient *spclient.Clientset
restrictToNamespace := ""
resources := []k8s.APIResource{k8s.DS, k8s.Deploy, k8s.Pod, k8s.RC, k8s.RS, k8s.Svc}
resources := []k8s.APIResource{k8s.DS, k8s.Deploy, k8s.Pod, k8s.RC, k8s.RS, k8s.Svc, k8s.SS}

if *singleNamespace {
restrictToNamespace = *controllerNamespace
Expand Down
1 change: 1 addition & 0 deletions controller/cmd/tap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func main() {
nil,
restrictToNamespace,
k8s.DS,
k8s.SS,
k8s.Deploy,
k8s.Pod,
k8s.RC,
Expand Down
Loading

0 comments on commit c3f131f

Please sign in to comment.