Run vScope in Kubernetes with Restricted Privileges
The Kubernetes manifests in Installation and Discovery Proxies run vScope as root inside the container, which is the recommended setup. Use this guide if your cluster policies require restricted privileges.
Choose one of the options below. They are listed in order of preference. To understand what each option changes for discovery, see Container privileges.
- Use a user namespace: vScope keeps root inside the container, mapped to an unprivileged user on the node.
- Run as non-root: vScope runs as a regular user. Use this when your policies require non-root containers, for example the Pod Security
restrictedprofile.
Both options change only the Deployment. Make the changes in the manifest you saved during installation, then apply it again with kubectl apply. You can keep the existing PVC.
Use a user namespace
Section titled “Use a user namespace”Prerequisites
Section titled “Prerequisites”- Kubernetes 1.33 or later. Kubernetes 1.30–1.32 needs the
UserNamespacesSupportfeature gate. - Linux kernel 6.3 or later on the nodes.
- containerd 2.0 or later, or CRI-O 1.25 or later.
- The persistent volume mounted at
/datamust use a filesystem that supports idmapped mounts, such as ext4 or xfs. Some network filesystems, such as NFS, may not support it.
See System Requirements.
-
In the server Deployment, add
hostUsers: falseunderspec.template.spec:spec:template:spec:hostUsers: falseterminationGracePeriodSeconds: 330containers:- name: vscope-server# ...unchanged -
Apply the manifest and wait for the rollout:
Terminal window kubectl apply -f vscope-server.yamlkubectl -n default rollout status deployment/vscope-server --timeout=600s -
Check that the pod runs in a user namespace:
Terminal window kubectl -n default exec deployment/vscope-server -- cat /proc/self/uid_mapThe output should map user
0to a high ID, for example0 1882324992 65536. If the output is0 0 4294967295, the pod is not in a user namespace and still runs as root on the node. Clusters that do not support user namespaces ignorehostUserswithout reporting an error. -
For each proxy, add
hostUsers: falsein the same place invscope-proxy.yaml, apply the manifest, and run the same check againstdeployment/vscope-proxy.
Run as non-root
Section titled “Run as non-root”Prerequisites
Section titled “Prerequisites”- The cluster must allow the sysctls
net.ipv4.ip_unprivileged_port_startandnet.ipv4.ping_group_range. Both are safe sysctls and are allowed by default in Kubernetes 1.22 or later.
The examples run vScope with user and group ID 1000. You can use another non-zero ID; use the same group ID in ping_group_range.
-
In the server Deployment, add a pod-level
securityContextunderspec.template.spec, add a container-levelsecurityContext, and add-Duser.home=/datatoJAVA_OPTS:spec:template:spec:securityContext:runAsNonRoot: truerunAsUser: 1000runAsGroup: 1000fsGroup: 1000fsGroupChangePolicy: OnRootMismatchseccompProfile:type: RuntimeDefaultsysctls:- name: net.ipv4.ip_unprivileged_port_startvalue: "80"- name: net.ipv4.ping_group_rangevalue: "1000 1000"terminationGracePeriodSeconds: 330containers:- name: vscope-serverenv:- name: JAVA_OPTSvalue: "-Xmx16g -Duser.home=/data"securityContext:allowPrivilegeEscalation: falsecapabilities:drop:- ALL# ...image, ports, resources and volumeMounts unchangedsysctlsis only valid in the pod-levelsecurityContext. Kubernetes rejects it in the container-level one.ip_unprivileged_port_startlets vScope listen on port 80 without root.ping_group_rangelets the group send ping requests.fsGroupmakes/datawritable for the group, including data written by an earlier root installation. If your storage does not applyfsGroup, for example some NFS volumes, change the ownership of the volume to the user and group ID.
-
Apply the manifest and wait for the rollout:
Terminal window kubectl apply -f vscope-server.yamlkubectl -n default rollout status deployment/vscope-server --timeout=600s -
Check that vScope runs as the configured user and can ping:
Terminal window kubectl -n default exec deployment/vscope-server -- idkubectl -n default exec deployment/vscope-server -- ping -c 1 <target-ip>Expect
uid=1000 gid=1000and a ping reply.idmay also report that it cannot find a name for the group ID, which is expected. -
Open the vScope web address and sign in.
-
For each proxy, make the same changes in
vscope-proxy.yaml, but leave out theip_unprivileged_port_startsysctl because the proxy does not listen on port 80. Add-Duser.home=/datato the existingJAVA_OPTS:spec:template:spec:securityContext:runAsNonRoot: truerunAsUser: 1000runAsGroup: 1000fsGroup: 1000fsGroupChangePolicy: OnRootMismatchseccompProfile:type: RuntimeDefaultsysctls:- name: net.ipv4.ping_group_rangevalue: "1000 1000"terminationGracePeriodSeconds: 330containers:- name: vscope-proxyenv:- name: JAVA_OPTSvalue: >--Xmx4g-Dproxy.master.host=YOUR-VSCOPE-MASTER-Dproxy.master.port=4445-Duser.home=/datasecurityContext:allowPrivilegeEscalation: falsecapabilities:drop:- ALL# ...image, resources and volumeMounts unchangedApply the manifest and run the same checks against
deployment/vscope-proxy.
Discovery log messages
Section titled “Discovery log messages”When running as non-root, discovery may report Could not initialize raw ping socket for scanned ranges. This is expected: vScope cannot use raw sockets and continues with the ping tool instead.
If /data/log/debug.log also shows System ping not available, run ping -c 1 127.0.0.1 in the pod. If it fails with ping: socket: Operation not permitted, ping_group_range does not include the pod’s group ID. Until this is fixed, vScope falls back to a TCP-based reachability check, which finds fewer hosts.