-
Notifications
You must be signed in to change notification settings - Fork 712
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
Conversation
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? |
base = addKubernetesLabelAndRank(base, n) | ||
return base | ||
} | ||
|
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
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.
This comment was marked as abuse.
Sorry, something went wrong.
probe/kubernetes/reporter.go
Outdated
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.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
for _, n := range inputNodes { | ||
pvcName := c.toPV(n) | ||
pvNodes[pvcName] = n.ID | ||
} |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
|
||
return MapStorageEndpoints( | ||
func(m report.Node) string { | ||
pvcName, ok := m.Latest.Lookup(kubernetes.Name) |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
} | ||
|
||
// Map2PVCName returns PVC name for the given Pod. | ||
func Map2PVCName(m report.Node) string { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
|
||
// 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.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
} | ||
|
||
// Map2SC returns pvc node ID | ||
func Map2SC(n report.Node) string { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
MapEndpoints( | ||
Map2SC, | ||
report.PersistentVolumeClaim, | ||
))) |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/render.go
Outdated
} | ||
return Nodes{Nodes: ret.nodes} | ||
} | ||
|
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
test/fixture/report_fixture.go
Outdated
@@ -354,12 +358,48 @@ var ( | |||
}, | |||
Window: 2 * time.Second, | |||
} | |||
PVReport = report.Report{ |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
Couldn't the edges from PVCs to PVs be added by the probes, thus obviating the need for any special rendering code? |
Pods has 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.
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
Yes! PVCs can have
Yes! Searching works properly. However, we're not able to apply |
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. |
Fixing this and other suggested changes. Will push all soon.
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 Thanks! |
@satyamz any chance of implementing the suggested changes anytime soon? |
@2opremio I am sending changes today. |
Hi @rade , @bboreham , @2opremio , Storage Filter On: Storage Filter Off:
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 Thanks |
@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 I left in that branch a previous commit where the information goes via the 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. |
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 👍 |
Hi @bboreham, If we want to add adjacency for pod -> pvc with the method proposed by you then we'll have to consider Thanks |
We had a more detailed conversation in Slack. |
Awesome! Looking forward to the changes and getting this merged! |
Hi @bboreham please review this approach mayadata-io/scope@add-pv-pvc-support...satyamz:refactor-render |
There was a problem hiding this 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.
probe/kubernetes/persistentvolume.go
Outdated
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.
This comment was marked as abuse.
Sorry, something went wrong.
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.
This comment was marked as abuse.
Sorry, something went wrong.
probe/kubernetes/persistentvolume.go
Outdated
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.
This comment was marked as abuse.
Sorry, something went wrong.
probe/kubernetes/storageclass.go
Outdated
// 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.
This comment was marked as abuse.
Sorry, something went wrong.
probe/kubernetes/persistentvolume.go
Outdated
// 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.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
} | ||
|
||
//PodToVolumeRenderer renders Pod and PVC resources | ||
func PodToVolumeRenderer() Renderer { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/persistentvolume.go
Outdated
} | ||
|
||
// PVCToStorageClassRenderer renders PVC and Storage class objects. | ||
func PVCToStorageClassRenderer() Renderer { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
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.
This comment was marked as abuse.
Sorry, something went wrong.
|
||
// 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.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
render/render.go
Outdated
} | ||
|
||
// storageResult returns Nodes for after adding adjacencies | ||
func (ret *joinResults) storageResult(input Nodes) Nodes { |
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
There was a problem hiding this 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 👌
client/app/scripts/charts/edge.js
Outdated
@@ -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.
This comment was marked as abuse.
Sorry, something went wrong.
client/app/scripts/charts/edge.js
Outdated
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.
This comment was marked as abuse.
Sorry, something went wrong.
@foot Please review the changes. Thanks |
I will squash commits in this PR once it's approved by all stakeholders. |
There was a problem hiding this 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.
client/app/scripts/charts/edge.js
Outdated
@@ -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.
This comment was marked as abuse.
Sorry, something went wrong.
client/app/scripts/charts/edge.js
Outdated
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.
This comment was marked as abuse.
Sorry, something went wrong.
} | ||
|
||
// 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.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
I just built this branch and tried it out. Working, but I think one part of @rade's comment got misunderstood:
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
Controller view can come later. |
Correction to my last comment: the code has "only storage, plus pods that have a volumeClaim" Think I need to do more experiments. |
@bboreham If I remove the constraint on the only storage view then I get something like this: Do we want it to be like this? I am bit confused here because this will make pods view visually more complicated. |
@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. |
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.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
@satyamz we recently switched to sentenced cased text, would you mind changing all the strings (e.g., from "Show Storage" to "Show storage"). Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@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. |
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>
8c08737
to
c4dcaa3
Compare
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>
c4dcaa3
to
d9bd17a
Compare
There was a problem hiding this 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.
probe/kubernetes/persistentvolume.go
Outdated
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.
Sorry, something went wrong.
This comment was marked as abuse.
This comment was marked as abuse.
Sorry, something went wrong.
Note that at this time PVs and PVCs won't show up out of the box (if one follows the default install instructions) because - apiGroups:
- ''
resources:
- pods/log
- services
- nodes
- namespaces
- persistentvolumes
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- storage.k8s.io
resources:
- storageclasses
verbs:
- get
- list
- watch |
Hi @tallaxes , I am sending PR for the same. Thanks for pointing this out. 👍 |
As a part of this, a new sub-topology called
Persistent Volumes
which contain the graph ofPersistent Volume
andPersistent Volume Claim
.Edges are drawn on the basis of Volume Claim Name in PV and PVC.
Fixes: #3130