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

Support for NetworkPolicy ingress/egress #534

Closed
manics opened this issue Feb 23, 2018 · 12 comments
Closed

Support for NetworkPolicy ingress/egress #534

manics opened this issue Feb 23, 2018 · 12 comments

Comments

@manics
Copy link
Member

manics commented Feb 23, 2018

I'm interested in using a singleuser pod NetworkPolicy to limit egress. The use-case I have in mind is providing a public but very locked-down jupyterhub deployment to give people a taster with minimal barriers, and to provide full access behind a second authenticated deployment.

I found a related discussion on jupyterhub/mybinder.org-deploy#146 and can see pros and cons to including it in this chart:

  • Configuring everything in zero-to-jupyterhub-k8s is very convenient
  • A NetworkPolicy is very specific to a deployment, and can be applied outside the chart since the pod labels are known

If you think it's worthwhile here's a proposal:

singleuser:
  networkPolicy:
    ingress:
      - List of ingress rules from https://kubernetes.io/docs/concepts/services-networking/network-policies/
    egress:
      - List of egress rules from https://kubernetes.io/docs/concepts/services-networking/network-policies/

applied to

  podSelector:
    matchLabels:
      app: jupyterhub
      component: singleuser-server
@minrk
Copy link
Member

minrk commented Feb 23, 2018

I 100% think we should apply network policies here.

The one thing I was bitten by in jupyterhub/mybinder.org-deploy#146 is that kubernetes doesn't check at all for using unsupported features, so you can happily load an egress network policy that is completely ignored without any warnings or errors. I haven't checked in a bit, but I assume gke-1.9 will have sufficiently recent calico (>= 2.6.1) to enable egress policies.

We should start by sketching out a network policy of who needs to talk to whom, and what the default should be. To get started:

ingress:

  • single-user servers need only accept ingress directly from the hub and proxy (everybody else should communicate with them via proxy)
  • hub needs only accept ingress from proxy, services, and single-user server
  • proxy should accept ingress from the world, or maybe only ingress-controller if enabled?

egress:

  • proxy only needs egress to hub, services, single-user servers
  • hub needs egress to proxy-api, services, single-user servers, and whatever may be needed by the Authenticator (maybe world for OAuthenticators?) and Spawner (kube itself for kubespawner)
  • single-user servers need egress to the hub and the outside world, but no other in-cluster addresses

Figuring out the right labeling scheme / default policies for that would be great!

@manics
Copy link
Member Author

manics commented Feb 23, 2018

Thanks, I'll try and come up with something. A barrier I've already run into is that the DNS server is in the kube-system namespace so the obvious thing is to allow egress to port 53 in kube-system, however namespaceSelector only works on labels, and at least on my cluster namespaces are unlabelled. Best I've come up with is to allow UDP/53 egress to anywhere.

@manics
Copy link
Member Author

manics commented Feb 26, 2018

This is what I've come up with so far based on @minrk's outline: https://gist.github.com/manics/ccc96169e4ce22f4cf434c7c7f9b9630

I've been testing on openstack (deployed with kubespray, canal network plugin)

proxy

  • Ingress from world 80,443, hub 8000,8001,8080
  • Egress to hub 8081, singleuser-servers 8888, world 80,443 (for lets-encrypt, not sure about this)

hub

  • Ingress from proxy 8081, singleuser-servers 8081
  • Egress to proxy 8001, singleuser-servers 8888, k8s-api (I can't find a way to specifically whitelist this), optionally world for auth

singleuser-servers

  • Ingress from hub 8888, proxy 8888
  • Egress to hub 8081, proxy 8000,8001 (do users need access to all these APIs?), optionally world

@yuvipanda
Copy link
Collaborator

This is great, since I need something like this for a course starting in a month :D

I agree this belongs in z2jh. I think the only knob we should turn to begin with is 'who can single-user server talk to?', since you might have plenty of other in-cluster services that you might wanna expose to the singleuser server.

What you have sounds like a good start, @manics!

@minrk
Copy link
Member

minrk commented Feb 27, 2018

@manics awesome! Feel free to make a PR with what you have, and we can iron it out.

My only question based on your gist is about best practices in terms of how to organize the information: when giving pods access to the proxy, should we be putting those pods in the proxy's network policy explicitly, or should we be using a single label like 'proxy-api-access' in the network policy and applying that label to all of the pods that need access?

i.e. when granting a new pod access to the proxy, do I modify the pod's labels, or the proxy's network policy? It seems like the former makes the most sense for ingress. I'm not sure if egress is best treated the same or not.

@yuvipanda
Copy link
Collaborator

I think ingress is fairly easy policy:

  1. Proxy allows ingress from everywhere
  2. Hub allows ingress from proxy and singleuser servers only
  3. singleuser servers allow ingress from proxy and hub only.

Egress is definitely going to be more complicated, so I suggest we tackle ingress first and then go from there?

@manics
Copy link
Member Author

manics commented Feb 28, 2018

Thanks for the feedback, I'll open a PR today/tomorrow.

@manics
Copy link
Member Author

manics commented Mar 19, 2018

Implemented in #546

@manics manics closed this as completed Mar 19, 2018
@consideRatio
Copy link
Member

@manics @minrk @yuvipanda awesome!!! I learned a lot by reading this thread!

@manics I think the pod will talk to the k8s-api through kube-proxy pods (one per node), so if we manage to target that we are good I think. Also I think they communicate with HTTP by default.

Name:         kube-proxy-gke-jupyter-se-cpu1-core-pool-08ec0c9f-ps6x
Namespace:    kube-system
Node:         gke-jupyter-se-cpu1-core-pool-08ec0c9f-ps6x/10.156.0.2
Start Time:   Tue, 03 Apr 2018 03:55:00 +0200
Labels:       component=kube-proxy
              tier=node
Annotations:  kubernetes.io/config.hash=52dadc5e78a1031dc12599fa181e4548
              kubernetes.io/config.mirror=52dadc5e78a1031dc12599fa181e4548
              kubernetes.io/config.seen=2018-04-03T01:54:55.691951702Z
              kubernetes.io/config.source=file
              scheduler.alpha.kubernetes.io/critical-pod=
Status:       Running
IP:           10.156.0.2
Containers:
  kube-proxy:
    Container ID:  docker://f8c76cadebfa4c5a4bf588a4ea875624c80cce6b04dbab2fabd6a74f8e095e3c
    Image:         gcr.io/google_containers/kube-proxy:v1.9.4-gke.1
    Image ID:      docker://sha256:6c8f7ef27e17f23e30691157b7b713d4032acc6bc04a8657082a26979559995b
    Port:          <none>
    Command:
      /bin/sh
      -c
      exec kube-proxy --master=https://35.198.66.16 --kubeconfig=/var/lib/kube-proxy/kubeconfig --cluster-cidr=10.16.0.0/14 --resource-container="" --oom-score-adj=-998 --v=2 --feature-gates=ExperimentalCriticalPodAnnotation=true --iptables-sync-period=1m --iptables-min-sync-period=10s --ipvs-sync-period=1m --ipvs-min-sync-period=10s 1>>/var/log/kube-proxy.log 2>&1

@menendes
Copy link

menendes commented Dec 2, 2021

I 100% think we should apply network policies here.

The one thing I was bitten by in jupyterhub/mybinder.org-deploy#146 is that kubernetes doesn't check at all for using unsupported features, so you can happily load an egress network policy that is completely ignored without any warnings or errors. I haven't checked in a bit, but I assume gke-1.9 will have sufficiently recent calico (>= 2.6.1) to enable egress policies.

We should start by sketching out a network policy of who needs to talk to whom, and what the default should be. To get started:

ingress:

  • single-user servers need only accept ingress directly from the hub and proxy (everybody else should communicate with them via proxy)
  • hub needs only accept ingress from proxy, services, and single-user server
  • proxy should accept ingress from the world, or maybe only ingress-controller if enabled?

egress:

  • proxy only needs egress to hub, services, single-user servers
  • hub needs egress to proxy-api, services, single-user servers, and whatever may be needed by the Authenticator (maybe world for OAuthenticators?) and Spawner (kube itself for kubespawner)
  • single-user servers need egress to the hub and the outside world, but no other in-cluster addresses

Figuring out the right labeling scheme / default policies for that would be great!

Do you know that how we define eggress for the singleuser to access outside the world ?

@bfotzo
Copy link

bfotzo commented Nov 8, 2022

I 100% think we should apply network policies here.
The one thing I was bitten by in jupyterhub/mybinder.org-deploy#146 is that kubernetes doesn't check at all for using unsupported features, so you can happily load an egress network policy that is completely ignored without any warnings or errors. I haven't checked in a bit, but I assume gke-1.9 will have sufficiently recent calico (>= 2.6.1) to enable egress policies.
We should start by sketching out a network policy of who needs to talk to whom, and what the default should be. To get started:
ingress:

  • single-user servers need only accept ingress directly from the hub and proxy (everybody else should communicate with them via proxy)
  • hub needs only accept ingress from proxy, services, and single-user server
  • proxy should accept ingress from the world, or maybe only ingress-controller if enabled?

egress:

  • proxy only needs egress to hub, services, single-user servers
  • hub needs egress to proxy-api, services, single-user servers, and whatever may be needed by the Authenticator (maybe world for OAuthenticators?) and Spawner (kube itself for kubespawner)
  • single-user servers need egress to the hub and the outside world, but no other in-cluster addresses

Figuring out the right labeling scheme / default policies for that would be great!

Do you know that how we define eggress for the singleuser to access outside the world ?

Hello @menendes !
Did you find how to do that please? I'm facing this issue right now.

To be clear: I'm trying to deploy a jupyter hub on a kubernetes cluster. I then used the official helm chart (version 2.0.0) of jupyter hub. I can access my notebook but when working with it, I can't communicate with the world (can't pip install, can't make requests, etc...).
I can only make requests to services deployed in my kubernetes cluster.

Did someone faced this kind of issue please?

@consideRatio
Copy link
Member

Please ask it at discourse.jupyter.org, but my best guess is that you dont have networking setup in a way that make any pod able to send traffic to the internet - because for example not having public IPs on nodes, and then a need for some public IP, that could ve provided via a service like google's Cloud NAT.

Please refrain from following up here though, open a discourse.jupyter.org question about it instead please.

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

No branches or pull requests

7 participants