Services & Networking (13%)
Routing Traffic to Pods from Inside and Outside of a Cluster
- Create a deployment named
myapp
that creates 2 replicas for Pods with the imagenginx
. Expose the container port 80. - Expose the Pods so that requests can be made against the service from inside of the cluster.
- Create a temporary Pods using the image
busybox
and run awget
command against the IP of the service. - Change the service type so that the Pods can be reached from outside of the cluster.
- Run a
wget
command against the service from outside of the cluster. - (Optional) Can you expose the Pods as a service without a deployment?
Solution:
Create a deployment with 2 replicas first. You should end up with one deployment and two Pods.
$ kubectl run myapp --image=nginx --restart=Always --replicas=2 --port=80 deployment.apps/myapp created $ kubectl get deployments,pods NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.extensions/myapp 2 2 2 2 59s NAME READY STATUS RESTARTS AGE pod/myapp-7bc568bfdd-972wg 1/1 Running 0 59s pod/myapp-7bc568bfdd-l5nmz 1/1 Running 0 59s
Expose the service with the type ClusterIP
and the target port 80.
$ kubectl expose deploy myapp --target-port=80 service/myapp exposed $ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE myapp ClusterIP 10.108.88.208 <none> 80/TCP 15s
Determine the cluster IP and use it for the wget
command.
$ kubectl run tmp --image=busybox --restart=Never -it --rm -- wget -O- 10.108.88.208:80 Connecting to 10.108.88.208:80 (10.108.88.208:80) <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> - 100% |********************************| 612 0:00:00 ETA pod "tmp" deleted
Turn the type of the service into NodePort
to expose it outside of the cluster. Now, the service should expose a port in the 30000 range.
$ kubectl edit service myapp ... spec: type: NodePort ... kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE myapp NodePort 10.108.88.208 <none> 80:30441/TCP 3m
Run a wget
or curl
command against the service using port 30441
. On Docker for Windows/Mac you may have to use localhost or 127.0.0.1
$ wget -O- localhost:30441 --2019-05-10 16:32:35-- http://localhost:30441/ Resolving localhost (localhost)... ::1, 127.0.0.1 Connecting to localhost (localhost)|::1|:30441... connected. HTTP request sent, awaiting response... 200 OK Length: 612 [text/html] Saving to: ‘STDOUT’ - 0%[ ] 0 --.-KB/s <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> - 100%[==================================================================================>] 612 --.-KB/s in 0s 2019-05-10 16:32:35 (24.3 MB/s) - written to stdout [612/612]
Restricting Access to and from a Pod
Let's assume we are working on an application stack that defines three different layers: a frontend, a backend and a database. Each of the layers runs in a Pod. You can find the definition in the YAML file app-stack.yaml
. The application needs to run in the namespace app-stack
.
kind: Pod apiVersion: v1 metadata: name: frontend namespace: app-stack labels: app: todo tier: frontend spec: containers: - name: frontend image: nginx --- kind: Pod apiVersion: v1 metadata: name: backend namespace: app-stack labels: app: todo tier: backend spec: containers: - name: backend image: nginx --- kind: Pod apiVersion: v1 metadata: name: database namespace: app-stack labels: app: todo tier: database spec: containers: - name: database image: mysql env: - name: MYSQL_ROOT_PASSWORD value: example
- Create the required namespace.
- Copy the Pod definition to the file
app-stack.yaml
and create all three Pods. Notice that the namespace has already been defined in the YAML definition. - Create a network policy in the YAML file
app-stack-network-policy.yaml
. - The network policy should allow incoming traffic from the backend to the database but disallow incoming traffic from the frontend.
- Incoming traffic to the database should only be allowed on TCP port 3306 and no other port.
Solution:
Create the namespace
kubectl create namespace app-stack namespace/app-stack created $ vim app-stack.yaml $ kubectl create -f app-stack.yaml pod/frontend created pod/backend created pod/database created $ kubectl get pods --namespace app-stack NAME READY STATUS RESTARTS AGE backend 1/1 Running 0 22s database 1/1 Running 0 22s frontend 1/1 Running 0 22s
The following definition ensure that all rules are fulfilled.
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: app-stack-network-policy namespace: app-stack spec: podSelector: matchLabels: app: todo tier: database policyTypes: - Ingress - Egress ingress: - from: - podSelector: matchLabels: app: todo tier: backend ports: - protocol: TCP port: 3306
Create the network policy.
$ vim app-stack-network-policy.yaml $ kubectl create -f app-stack-network-policy.yaml $ kubectl get networkpolicy --namespace app-stack NAME POD-SELECTOR AGE app-stack-network-policy app=todo,tier=database 5s