Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pv and pvc support in weave scope #3132

Merged
merged 5 commits into from
Jun 8, 2018

Conversation

satyamz
Copy link
Contributor

@satyamz satyamz commented Apr 5, 2018

As a part of this, a new sub-topology called Persistent Volumes which contain the graph of Persistent Volume and Persistent Volume Claim.
Edges are drawn on the basis of Volume Claim Name in PV and PVC.

Fixes: #3130

pv-pvc-support

@rade
Copy link
Member

rade commented Apr 10, 2018

This is great! Good effort!

Is there anything showing which pods use which claims? Would that be useful? Which makes me wonder whether persistent volumes and claims should be shown in the existing k8s views rather than getting their own view. Or, as a stepping stone, showing lists of volumes on the pod/controller detail panels, and linking to the PV node details and vice versa.

Why do the PVCs in your example have such cryptic names?

Could you post a screen shot of the table mode, please?

Does the namespace selector apply to PVCs?

Does searching/filtering provide reasonable results?

rade
rade previously requested changes Apr 10, 2018
base = addKubernetesLabelAndRank(base, n)
return base
}

This comment was marked as abuse.

This comment was marked as abuse.

return p.MetaNode(report.MakePersistentVolumeClaimNodeID(p.UID())).WithLatests(map[string]string{
report.ControlProbeID: probeID,
NodeType: "Persistent Volume Claim",
Namespace: p.GetNamespace(),

This comment was marked as abuse.

Status: {ID: Status, Label: "Status", From: report.FromLatest, Priority: 3},
VolumeName: {ID: VolumeName, Label: "Volume", From: report.FromLatest, Priority: 4},
AccessModes: {ID: AccessModes, Label: "Access Modes", From: report.FromLatest, Priority: 5},
}

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

for _, n := range inputNodes {
pvcName := c.toPV(n)
pvNodes[pvcName] = n.ID
}

This comment was marked as abuse.


return MapStorageEndpoints(
func(m report.Node) string {
pvcName, ok := m.Latest.Lookup(kubernetes.Name)

This comment was marked as abuse.

}

// Map2PVCName returns PVC name for the given Pod.
func Map2PVCName(m report.Node) string {

This comment was marked as abuse.


// Map2PVCName returns PVC name for the given Pod.
func Map2PVCName(m report.Node) string {
pvcName, ok := m.Latest.Lookup(kubernetes.VolumeClaim)

This comment was marked as abuse.

}

// Map2SC returns pvc node ID
func Map2SC(n report.Node) string {

This comment was marked as abuse.

MapEndpoints(
Map2SC,
report.PersistentVolumeClaim,
)))

This comment was marked as abuse.

render/render.go Outdated
}
return Nodes{Nodes: ret.nodes}
}

This comment was marked as abuse.

@@ -354,12 +358,48 @@ var (
},
Window: 2 * time.Second,
}
PVReport = report.Report{

This comment was marked as abuse.

@rade
Copy link
Member

rade commented Apr 10, 2018

Couldn't the edges from PVCs to PVs be added by the probes, thus obviating the need for any special rendering code?

@satyamz
Copy link
Contributor Author

satyamz commented Apr 11, 2018

Is there anything showing which pods use which claims? Would that be useful? Which makes me wonder whether persistent volumes and claims should be shown in the existing k8s views rather than getting their own view. Or, as a stepping stone, showing lists of volumes on the pod/controller detail panels, and linking to the PV node details and vice versa.

Pods has VolumeClaim in the Spec. We are using the same to retrieve PVC for the given Pod. However, this change is not included in this PR. We're sending another PR for that as soon as this PR is merged (just to reduce the size of PR we've split it in two).

Regarding keeping PV, PVC along with pods, We want to show complete kubernetes storage support eventually. Another reason for this can be, for storage relations we do not need any networking based linking. Hence, We have our own storage specific and simple renderer for PV, PVC objects.
This is how final view looks:

Cylinder : PV
DottedCylinder: PVC
Sheet : Storage Class (SC)

storage-all

Why do the PVCs in your example have such cryptic names?

These are not PVCs. These are PVs. Names for the PV is generated by K8s storage controller. You can check the same https://github.com/kubernetes-incubator/external-storage/blob/e3789b84521b5e75f161a6885010d2b7b2f50033/lib/controller/controller.go#L1160:34

Could you post a screen shot of the table mode, please?

table-view

Does the namespace selector apply to PVCs?

Yes! PVCs can have Namespace but PVs, Storage Classes don't have Namespace. We're still not clear whether to use Namespace filter for PV sub-topology. Also, We're not able to remove the Namespace filter for PV sub-topology as Namespace filter is invoked on the basis of topology and not sub-topology. I would like to know your opinion on this.

Does searching/filtering provide reasonable results?

Yes! Searching works properly. However, we're not able to apply Namespace filters.
status-searching

@rade
Copy link
Member

rade commented Apr 11, 2018

Ah, I thought the dotted cylinders were PVs, and the solid ones PVCs, since the latter have "pvc-..." names in your screenshots.

IMO the pvc-pv edge has the wrong polarity. The PVC references the PV, so the arrow should go from the former to the latter. Then, by extension, we get pod -> pvc -> pv.

Regarding having a separate view... views with pods get crowded very quickly since that is the granularity at which things get scaled in k8s. Surely a user would want to see what PVs their workloads (i.e. groups of pods managed by a controller) are accessing. So IMO PVs and PVCs should go in the Pod and Controller views, possible with a selector that lets users decide whether they want to see them.

@satyamz
Copy link
Contributor Author

satyamz commented Apr 11, 2018

IMO the pvc-pv edge has the wrong polarity. The PVC references the PV, so the arrow should go from the former to the latter. Then, by extension, we get pod -> pvc -> pv.

Fixing this and other suggested changes. Will push all soon.

Regarding having a separate view... views with pods get crowded very quickly since that is the granularity at which things get scaled in k8s. Surely a user would want to see what PVs their workloads (i.e. groups of pods managed by a controller) are accessing. So IMO PVs and PVCs should go in the Pod and Controller views, possible with a selector that lets users decide whether they want to see them.
Merge state

Yes, I agree with you on the part where user would want to have separate storage view. Also, we already have PVC controllers and replicas in the PODS & CONTROLLERS section. As you are suggesting, we can add storage filter option there which will give mapping of stateful pods and PVC controller replicas only (no other pods). Indeed this is good suggestion, I will raise issue for this and will start work on this.

Having different storage view can help better storage management for K8s stateful workloads. Can we have new sub-topology under Hosts as Storage (below weave net) to show all the K8s storage components? As you know, we're finding storage relationship as pod->pvc->pv. In this phase, PV is the last components but in the Storage section we're extending this view to show which Disks are providing PV along with storage pool with opetations (in our scope term controls) such as snapshots, clone, backup etc. Hence, We're adding Persistent Volumes as a new sub-topology. We want to move this Persistent Volumes to Storage under Hosts once we've disks support. In that case, we can show disk and host relationship too. Storage topology will be big plus for weave scope wrt storage management. We are in the middle of development of Node Disk Manager (NDM) which we'll push to the Kubernetes. NDM will help us getting all the disk related info and operations handy.
If you're fine with this, we can move Persistent Volumes to the Storage section in this PR itself.

Thanks!

@satyamz
Copy link
Contributor Author

satyamz commented Apr 13, 2018

Here's screenshot for PVC to PV mapping:
pvc-to-pv-mapping

@2opremio
Copy link
Contributor

2opremio commented May 10, 2018

@satyamz any chance of implementing the suggested changes anytime soon?

@satyamz
Copy link
Contributor Author

satyamz commented May 10, 2018

@2opremio I am sending changes today.

@satyamz
Copy link
Contributor Author

satyamz commented May 10, 2018

Hi @rade , @bboreham , @2opremio ,
Latest changes will remove Persistent Volumes sub topology from PODS topology and add K8s storage components in the storage filter in PODS topology as per suggestion from @rade

Storage Filter On:

weave-scope-k8s-storage

Storage Filter Off:

weave-scope-k8s-pods

Why isn't the existing result() method sufficient?

Currently, if we want to connect pod1 with pod2 based on network connection then we've network endpoints to do that. endpoints are working as a reference node & they have all the adjacencies. Further, we're passing endpoints nodes with adjacencies to result(). In storage we don't have any common reference node such as endpoint. Storage components are connected together directly through one to one mapping. Hence, we're introducing storageResult() to handle resource(PVC) to resource (PV) mapping.

Thanks

@bboreham
Copy link
Collaborator

@satyamz apologies I have been away from this for some time. I finally got my own version to work - see master...k8s-volumes

It uses lots of code from this PR, but the key thing I wanted to show is that it has virtually no changes on the rendering side. No new methods on joinResult and none of the code you used to feed things into it. I simply create the adjacency I want in the probe. I don't include probeID in the storage node; can't see any need for it.

I left in that branch a previous commit where the information goes via the parent field; this seemed plausible but in the end unnecessary.

What I suggest is you look at my branch, then simplify this PR based on those ideas. I left out all your tests, also the most recent changes, because all I wanted to do was understand the rendering/adjacency side.

@satyamz
Copy link
Contributor Author

satyamz commented May 21, 2018

Hi @bboreham Thanks for the all the work and reply. I must say, you opened up my mind with these changes. I will reflect these changes in this PR and will push commits here soon.

Thanks a lot 👍

@satyamz
Copy link
Contributor Author

satyamz commented May 23, 2018

Hi @bboreham,
I tried the solution given you. It works fine for PV to PVC adjacency. However, this method will not work for adding adjacency from pod to pvc. If we send PVC as a adjacency for pod from probe then that'll be deleted by the call connectionJoin() here and here.

If we want to add adjacency for pod -> pvc with the method proposed by you then we'll have to consider ClaimName in the pod spec to create PVC nodeID because in pod spec UID for PVC is not available, ClaimName is unique. Similarly for PVC to StorageClass adjacency, PVC to PV adjacency (Your solution is for PV to PVC).

Thanks

@bboreham
Copy link
Collaborator

We had a more detailed conversation in Slack.
I suggested writing a self-contained Render() function that shows Pods related to Storage, then you can add that into the existing Pod screen by appending to the MakeReduce list.

@2opremio
Copy link
Contributor

2opremio commented May 29, 2018

Awesome! Looking forward to the changes and getting this merged!

@satyamz
Copy link
Contributor Author

satyamz commented May 29, 2018

Hi @bboreham please review this approach mayadata-io/scope@add-pv-pvc-support...satyamz:refactor-render

@satyamz
Copy link
Contributor Author

satyamz commented Jun 1, 2018

Hi @bboreham @2opremio
I updated this PR as per suggestions given by Bryan.
Thanks

Copy link
Collaborator

@bboreham bboreham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're getting there!
Few more clean-up and nit-picking requests.

VolumeClaim: p.Spec.ClaimRef.Name,
StorageClassName: p.Spec.StorageClassName,
Status: string(p.Status.Phase),
AccessModes: string(p.Spec.AccessModes[0]),

This comment was marked as abuse.

NodeType: "Persistent Volume Claim",
Status: string(p.Status.Phase),
VolumeName: p.Spec.VolumeName,
AccessModes: string(p.Spec.AccessModes[0]),

This comment was marked as abuse.

return p.MetaNode(report.MakePersistentVolumeNodeID(p.UID())).WithLatests(map[string]string{
report.ControlProbeID: probeID,
NodeType: "Persistent Volume",
VolumeClaim: p.Spec.ClaimRef.Name,

This comment was marked as abuse.

// GetNode returns StorageClass as Node
func (p *storageClass) GetNode(probeID string) report.Node {
return p.MetaNode(report.MakeStorageClassNodeID(p.UID())).WithLatests(map[string]string{
report.ControlProbeID: probeID,

This comment was marked as abuse.

// GetNode returns Persistent Volume as Node
func (p *persistentVolume) GetNode(probeID string) report.Node {
return p.MetaNode(report.MakePersistentVolumeNodeID(p.UID())).WithLatests(map[string]string{
report.ControlProbeID: probeID,

This comment was marked as abuse.

}

//PodToVolumeRenderer renders Pod and PVC resources
func PodToVolumeRenderer() Renderer {

This comment was marked as abuse.

}

// PVCToStorageClassRenderer renders PVC and Storage class objects.
func PVCToStorageClassRenderer() Renderer {

This comment was marked as abuse.

render/render.go Outdated
@@ -251,6 +251,29 @@ func (ret *joinResults) rewriteAdjacency(outID string, adjacency report.IDList)
ret.nodes[outID] = out
}

// storageAdjacency sets adjacency for the given node ID
func (ret *joinResults) storageAdjacency(outID string, adjacency string) {

This comment was marked as abuse.


// Storage Class represent all kubernetes Storage Classes on hosts running probes.
// Metadata is limited for now, more to come later.
StorageClass Topology

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

render/render.go Outdated
}

// storageResult returns Nodes for after adding adjacencies
func (ret *joinResults) storageResult(input Nodes) Nodes {

This comment was marked as abuse.

Copy link
Contributor

@foot foot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick tidy up of the JS would be great, but otherwise lgtm 👌

@@ -5,6 +5,20 @@ import classNames from 'classnames';
import { enterEdge, leaveEdge } from '../actions/app-actions';
import { encodeIdAttribute, decodeIdAttribute } from '../utils/dom-utils';


function getAdjacencyClass(id) {

This comment was marked as abuse.

if (from[1] !== undefined && to[1] !== undefined) {
from[1] = from[1].slice(1, -1);
to[1] = to[1].slice(1, -1);
if ((from[1] === 'persistent_volume' || from[1] === 'storage_class' || from[1] === 'persistent_volume_claim') || (to[1] === 'persistent_volume' || to[1] === 'storage_class' || to[1] === 'persistent_volume_claim')) {

This comment was marked as abuse.

@satyamz
Copy link
Contributor Author

satyamz commented Jun 5, 2018

@foot Please review the changes. Thanks

@satyamz
Copy link
Contributor Author

satyamz commented Jun 5, 2018

I will squash commits in this PR once it's approved by all stakeholders.

Copy link
Contributor

@foot foot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick response! Just a couple of small changes.

@@ -5,6 +5,30 @@ import classNames from 'classnames';
import { enterEdge, leaveEdge } from '../actions/app-actions';
import { encodeIdAttribute, decodeIdAttribute } from '../utils/dom-utils';

function IsStorageComponent(id) {

This comment was marked as abuse.

const to = topologyId[1].split(';');
if (from[1] !== undefined && to[1] !== undefined) {
from[1] = from[1].slice(1, -1);
to[1] = to[1].slice(1, -1);

This comment was marked as abuse.

}

// getAdjacencyClass takes id which contains information about edge as a topology
// of parent and child node.

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

@bboreham
Copy link
Collaborator

bboreham commented Jun 6, 2018

I just built this branch and tried it out. Working, but I think one part of @rade's comment got misunderstood:

Regarding having a separate view... views with pods get crowded very quickly since that is the granularity at which things get scaled in k8s. Surely a user would want to see what PVs their workloads (i.e. groups of pods managed by a controller) are accessing. So IMO PVs and PVCs should go in the Pod and Controller views, possible with a selector that lets users decide whether they want to see them.

It's in the Pod view, but with a switch that gives "only pods" or "only storage", which is basically a separate view. If I make the following patch to app/api_topologies.go I get storage interspersed with pods, which is what I expect:

-                       {Value: "show", Label: "Show Storage", filter: render.IsVolumesComponent, filterPseudo: false},
+                       {Value: "show", Label: "Show Storage", filter: nil, filterPseudo: false},

Controller view can come later.

@bboreham
Copy link
Collaborator

bboreham commented Jun 6, 2018

Correction to my last comment: the code has "only storage, plus pods that have a volumeClaim"

Think I need to do more experiments.

@satyamz
Copy link
Contributor Author

satyamz commented Jun 6, 2018

@bboreham If I remove the constraint on the only storage view then I get something like this:

image

And
image

Do we want it to be like this? I am bit confused here because this will make pods view visually more complicated.

@umamukkara
Copy link

@satyamz , my understanding also is that "show storage" will show every pod + graph nodes related to storage. It could become bit cluttered, but with the search filter, the resulting nodes could be thinned down.

@umamukkara
Copy link

May be as we add more storage related features to scope, we might need a special filter called "Show ONLY storage", but that is for future discussion I suppose

const topologyId = id.split('---');
const fromNode = topologyId[0].split(';');
const toNode = topologyId[1].split(';');
if (fromNode[1] !== undefined && toNode[1] !== undefined) {

This comment was marked as abuse.

This comment was marked as abuse.

@rndstr
Copy link
Contributor

rndstr commented Jun 6, 2018

@satyamz we recently switched to sentenced cased text, would you mind changing all the strings (e.g., from "Show Storage" to "Show storage"). Thanks!

Copy link
Contributor

@foot foot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@satyamz
Copy link
Contributor Author

satyamz commented Jun 7, 2018

@rndstr I made changes suggested by you on sentence cased.

@bboreham , @umamukkara I also made the change suggested by you on storage view. Now storage view have all the storage components along with pods.

Satyam Zode added 2 commits June 7, 2018 17:01
This will

- Add Kubernetes volume resources such as PV, PVC.
- Add shapes for Kubernetes PV and PVC
- Add `Cylinder` shape for PV and `Dotted Cylinder` shape for PVC.

Signed-off-by: Satyam Zode <satyam.zode@openebs.io>
- Kubernetes storage components such as PV and PVC are connected based on two
parameters Persistent volume claim name and Persistent Volume name.
- PVC contains the volume name which is, PV name itself. Hence, we can
show edge for PVC and PV.
- This will bring higher level visibility for kubernetes storage components.

Signed-off-by: Satyam Zode <satyam.zode@openebs.io>
@satyamz satyamz force-pushed the add-pv-pvc-support branch from 8c08737 to c4dcaa3 Compare June 7, 2018 11:35
Satyam Zode added 3 commits June 8, 2018 16:36
This will:

- Add StorageClass resource. Storage classes are mentioned
in the PVC spec. We're using storage class name from PVC spec to
add adjacency to the PVC node.
- Add square sheet shape for StorageClass.
- Add storage filter in the PODS topology.
Storage Filter will allow user to see distinct view of
stateful applications.
- Add visually distinct edge to show storage adjacency.

Signed-off-by: Satyam Zode <satyam.zode@openebs.io>
- Remove the complex volume rendering code.
- Remove volume specific code from Transform.
- Rename filtering methods
- Remove extra params from PV, PVC nodes to make table view look good.

Signed-off-by: Satyam Zode <satyam.zode@openebs.io>
- Refactor dotted edge logic.
- Change Storage view to show storage components as well as all
  the pods.
- Sentence case storage related variables.

Signed-off-by: Satyam Zode <satyam.zode@openebs.io>
@satyamz satyamz force-pushed the add-pv-pvc-support branch from c4dcaa3 to d9bd17a Compare June 8, 2018 11:17
Copy link
Collaborator

@bboreham bboreham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; we can fix anything else with further PRs.

ReclaimPolicy: string(p.Spec.PersistentVolumeReclaimPolicy),
Message: p.Status.Message,
NodeType: "Persistent Volume",
VolumeClaim: p.GetVolume(),

This comment was marked as abuse.

This comment was marked as abuse.

@bboreham bboreham dismissed rade’s stale review June 8, 2018 11:40

All points have been addressed

@bboreham bboreham merged commit 8c18a78 into weaveworks:master Jun 8, 2018
@tallaxes
Copy link

tallaxes commented Jul 24, 2018

Note that at this time PVs and PVCs won't show up out of the box (if one follows the default install instructions) because ClusterRole/weave-scope does not grant access to these. persistentvolumes, persistentvolumeclaims and storageclasses need to be added:

      - apiGroups:
          - ''
        resources:
          - pods/log
          - services
          - nodes
          - namespaces
          - persistentvolumes
          - persistentvolumeclaims
        verbs:
          - get
          - list
          - watch
      - apiGroups:
          - storage.k8s.io
        resources:
          - storageclasses
        verbs:
          - get
          - list
          - watch

@satyamz
Copy link
Contributor Author

satyamz commented Jul 25, 2018

Hi @tallaxes , I am sending PR for the same. Thanks for pointing this out. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants