########## Kubernetes ########## ======= Critics ======= * `A skeptic's first contact with Kubernetes `_ - `HN discussion `__ - `tg discussion `__ + No enums in yaml: responsible for validation are either a controller or a validation admission webhook. + Kube-proxy and iptables: many CNI have their own kube-proxy implementations, working with eBPF. Kube-proxy is not a necessary component anymore. * `Why the fuck are we templating yaml? `_ - Recommends Jsonnet in place of Helm. - `HN `__ + Other suckers: Github Actions (+ don't support anchors), Ansible. + Other options: - json5, toml (gets ugly when nested) - nix, dhall ("JSON + functions + types + imports", but lacks type inference. slow) - Jsonnet, Ksonnet, Nu, or CUELang - Starlark/ytt - Nickel (Like cuelang, but with functions; `RATIONALE.md `__) - HCL, Pulumi - https://github.com/grafana/tanka - https://github.com/cdk8s-team/cdk8s + https://github.com/shipmight/helm-playground + ``YAML is the Bradford Pear of serialization formats. It looks good at first, but as your project ages, and the YAML grows it collapses under the weight of its own branches.`` + Use ``envsubst`` instead of ``sed -e s/$FOO/foo/g`` + IMHO: ``string interpolation should not be used to generate machine-readable code, and template languages (string template languages) are just fancy string interpolation`` * `The good, the bad and the ugly of templating YAML in Kubernetes `_ - Logical/Arithmetical operations without operators: + Go templates: no infix operators, functions instead. - No: ``{{ if a and b }}``. Yes: ``{{ if and a b }}`` - No: ``{{ if a and(b or c) }}``. Yes: ``{{ if and a (or b c) }}`` + Deeply nested variables: ``.Values.prometheus.ingress.enabled`` + Accessing items: - No: ``{{ $myList[0] }}``. Yes: ``{{ index $myList 0 }}`` - Example: ``{{ index $myMap (index $myList 0) }}`` - Whitespaces:: {{- with .Values.startupapicheck.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} # <--- no real reason to avoid leaving a blank line here for readability {{- with .Values.startupapicheck.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} - People try to make a good-looking YAML, but that's too complicated. - The only reason for readability is that you cannot pass ``helm template ... | yq`` if templating fails. - Go template contexts: + Current context = ``.``, e.g. ``{{ with .Values.something }}{{ .MemberOfSomething }}{{ end }}`` + Initial/global context = ``$``, e.g. ``{{ $.Some.Member }}`` + "Contexts" feel odd, normal template languages have nested "scopes" instead. === k0s === * YT: `K0S Kubernetes Demo `_ * YT: `Hands-on Introduction to K0s `_ Install ======= Download ``k0s`` binary to ``/usr/local/bin/k0s``: .. code-block:: sh curl -sSLf https://get.k0s.sh | sudo sh # or curl -sSLf https://get.k0s.sh | sudo K0S_VERSION=v1.21.2+k0s.0 DEBUG=true sh Install k0s as a systemd service. Can install a worker, a controller, or a single node (controller+worker). This will create a ``/etc/systemd/system/k0scontroller.service`` running a ``/usr/local/bin/k0s controller --single=true`` command: .. code-block:: sh sudo k0s install controller --single # or, with explicitly specified (custom) config file k0s default-config > k0s.yaml sudo k0s install controller -c ${PWD}/k0s.yaml # Show service file created systemctl list-unit-files |grep k0s systemctl cat k0scontroller.service Start a service: .. code-block:: sh sudo k0s start # or systemctl start k0scontroller.service # Check status (takes a 1-2 minutes) sudo k0s status # Can now use kubectl sudo k0s kubectl get nodes Install via k0sctl ================== .. code-block:: sh wget -O ~/bin/k0sctl https://github.com/k0sproject/k0sctl/releases/download/v0.12.5/k0sctl-linux-x64 chmod +x ~/bin/k0sctl # or nix-env -i k0sctl ======== Minikube ======== .. code-block:: sh curl -Lo ~/bin/minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 chmod +x ~/bin/minikube === k3s === * `A visual guide on troubleshooting kubernetes deployments `_ Install ======= * `k3s: High Availability with Embedded DB `_ * `k3s: Architecture `_ - A server node is defined as a machine (bare-metal or virtual) running the ``k3s server`` command. A worker node is defined as a machine running the ``k3s agent`` command. .. code-block:: sh curl -sfL https://get.k3s.io | K3S_TOKEN=SECRET sh -s - server --cluster-init curl -sfL https://get.k3s.io | K3S_TOKEN=SECRET sh -s - server --server https://:6443 curl -sfL https://get.k3s.io | K3S_TOKEN=SECRET sh -s - server --server https://:6443 Using kubectl on Desktop ======================== * `k3s: Cluster Access `_ .. code-block:: sh scp root@:/etc/rancher/k3s/k3s.yaml ~/.kube/config vim ~/.kube/config # change server: to Contexts, Switching Clusters and Namespaces =========================================== * `stepik k8s: 1.3 Устанавливаем Kubernetes локально `_ * `SO: What is the difference between namespaces and contexts in Kubernetes? `_ Context - client connection parameters (cluster+user). .. code-block:: sh kubectl config get-contexts # показать список контекстов kubectl config current-context # показать текущий контекст (current-context) kubectl config use-context my-cluster-name # установить my-cluster-name как контекст по умолчанию kubectl --context default --namespace lesson14 get pods # or kubectl --context default get pods -n lesson14 kubectl apply -f namespace.yaml # or kubectl create ns lesson14 kubectl delete -f namespace.yaml .. code-block:: yaml :caption: namespace.yaml apiVersion: v1 kind: Namespace metadata: name: lesson14 Get information about k8s ========================= .. code-block:: sh # also returns server version, so can be used to check connectivity kubectl version kubectl cluster-info # kubectl get - list resources # kubectl describe - show detailed information about a resource # kubectl logs - print the logs from a container in a pod # kubectl exec - execute a command on a container in a pod kubectl get pods kubectl get rs # or: replicaset kubectl get deployments kubectl get nodes kubectl get pods -o wide kubectl get nodes -o wide kubectl get pod/redis configmap/example-redis-config kubectl get pods -l app=kubernetes-bootcamp kubectl get services kubectl get services -l app=kubernetes-bootcamp # Get pod's manifest kubectl -n lesson14 get pod/static-web -o yaml kubectl get --watch pods kubectl get events # "event" lists errors kubectl describe pods |grep Image kubectl describe pods kubectl describe services/kubernetes-bootcamp kubectl describe deployments kubectl describe deployments/kubernetes-bootcamp kubectl describe configmap/example-redis-config export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}') kubectl logs $POD_NAME # Show pods CPU and memory usage # k3s: provided by API by deployment/metrics-server in kube-system namespace # (enabled by default) kubectl top pods Labels and Annotations ====================== * `Kubernetes Annotations and Labels: What’s the Difference? `_ - Labels are for Kubernetes, while annotations are for humans. * `Best Practices Guide for Kubernetes Labels and Annotations `_ .. code-block:: sh kubectl get node srv1 -o json | jq .metadata.labels kubectl get node srv1 -o json | jq .metadata.annotations kubectl get node --selector kubernetes.io/hostname=srv1 # or -l Annotations and labels syntax: * key-value pairs * Keys consists of two parts: an optional (but highly suggested) prefix and name - Prefix: DNS subdomain (<= 253 chars), ends with ``/``. E.g.: ``k8s.komodor.com/`` - Name: required (<= 63 chars) * if prefix is ommited, then label/annotation is private to the cluster+user .. code-block:: yaml apiVersion: v1 kind: Pod metadata: name: demo labels: environment: production app: nginx annotations: komodor.com/owner: alice komodor.com/owner-phone: 911 spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 Configs and Secrets =================== * `k8s: ConfigMaps `_ .. code-block:: sh kubectl create configmap sys-app-name --from-literal name=my-system # --from-file # --from-env-file kubectl create secret generic sys-app-credentials --from-literal username=bob --from-literal password=bobpwd kubectl create cm test-config -n lesson16 --from-file=root-ca.pem Types of secrets: * arbitrary data * service account tokens * docker configs * basic auth * ssh auth * tls data * bootstrap tokens ENV variables don't support hot reloading, use volume mount for that. Secrets are stored at ETCD. If you want to store them encrypted: provide a key to kube-apiserver. External secret providers: * hashicorp's vault - create ``kind: SecretProviderClass`` with ``spec.provider: vault`` - then in target pod's spec: ``serviceAccountName: my-sa`` - then can reference provided secrets in ``secretKeyRef`` - mount secrets in ``volumeMounts`` to ``/mnt/secrets`` - in ``volumes`` add ``csi: ...`` * cyberark * can use CSI to retrieve secrets from the storage Typical set: using a sidecar to inject secrets into the pod. .. code-block:: yaml apiVersion: v1 kind: ConfigMap metadata: name: first-cm namespace: lesson16 data: config.yaml: | colorgood: purple colorbad: yellow --- # ... # in spec.containers.[] env: - name: COLORGOOD valueFrom: configMapKeyRef: name: env-cm key: colorgood - name: COLORBAD valueFrom: configMapKeyRef: name: env-cm key: colorbad --- # or # in spec.containers.[] volumeMounts: - name: cm-volume mountPath: "/etc/ssl/certs/" readOnly: true # in spec volumes: - name: cm-volume configMap: name: test-config Certificate management ====================== Certificate Authorities: * digicert * cloudflare * aws * google cloud * Let's Encrypt * Vault (own certificate authority) .. code-block:: yaml kind: certificate metadata: name: example-com spec: secretName: example-com-tls duration: 2160h # 90 days renewBefore: 360h # 15 days dnsNames: - mail.example.com - login.example.net ipAddresses: - 192.168.50.19 For automation: cert-manager. Can be integrated with Ingress Controller. CRDs: * Certificate Requests * Certificates * Issuers, Cluster Issuers * Orders * Challenges ``kubectl get certs`` Operators ========= * Custom **Controller** (from "control loop" in robotics, e.g. cruise control) * and **Resources** e.g. Prometheus Operator Volumes ======= ``emptyDir``: remains while the pod lives. Is a bit like ``/tmp``. Also, it can be used for two container in one pod to share files. .. code-block:: yaml spec: containers: - name: web image: ksxack/lesson1:v0.2 ports: - containerPort: 8080 volumeMounts: - name: cache-volume mountPath: /cache volumes: - name: cache-volume emptyDir: {} Deployments and Scaling ======================= .. code-block:: sh kubectl scale deployments/kubernetes-bootcamp --replicas=4 kubectl scale deployments/kubernetes-bootcamp --replicas=2 Exec into the pod ================= .. code-block:: sh kubectl exec $POD_NAME -- env kubectl exec -ti $POD_NAME -- bash # cat server.js # curl localhost:8080 kubectl exec -ti $POD_NAME -- curl localhost:8080 kubectl exec -it redis -- redis-cli # CONFIG GET maxmemory --> 0 # CONFIG GET maxmemory-policy --> noeviction # Run new pod kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm Copy files from/to Pod ====================== .. code-block:: sh kubectl cp {{namespace}}/{{podname}}:path/to/directory /local/path # copy from pod kubectl cp /local/path namespace/podname:path/to/directory # copy to pod Port Forwarding =============== .. code-block:: sh kubectl port-forward pods/mongo-75f59d57f4-4nd6q 28015:27017 # Проброс порта Пода kubectl port-forward mongo-75f59d57f4-4nd6q 28015:27017 # Проброс порта Сервиса kubectl port-forward -n lesson14 static-web 8080:80 curl 127.0.0.1:8080 Services ======== * ` Kubernetes Service Types Explained `_ * `K3s Load Balancing with Klipper `_ * `k3s docs: networking: How the Service LB Works `_ Types of services: * ClusterIP - makes pod available only from inside the cluster * LoadBalancer - binds to the external IP - k3s servicelb + listens on every host, so only one service per port is possible + creates a pod (in ``kube-system`` namespace) on each node, which redirects (via iptables) traffic from this pod to service's IP and port * NodePort - every node redirects the request to given port - only 30000–32767 ports available Also: * ExternalName - local "alias" for an outside enpodint - not port-forward'able, port-forward directs it's traffic to a single specific pod * Ingress - tls termination, dns/url-based routing rules - you gotta configure *Ingress Controller* - nginx/traefik etc: what is configured by ``kind: Ingress``. Also cloud provider can provide one. - Istio uses ``kind: Gateway`` for ingress .. code-block:: yaml # ClusterIP spec: ports: - protocol: TCP port: 80 # service port targetPort: 8080 # port in pod # LoadBalancer spec: type: LoadBalancer ports: - port: 80 name: webport targetPort: 8080 loadBalancerIP: 10.10.130.145 # NodePort spec: type: NodePort ports: - name: http port: 80 # targetPort: 8080 nodePort: 30050 protocol: TCP Also can set ``externalIPs`` for ``type: ClusterIP`` service. Deploy ====== * `How to use kubectl dry run `_ * `matchLabels, labels, and selectors explained in detail, for beginners `_ - ``Why doesn’t the deployment automatically match the pod it’s deploying? I have no idea.`` Deployment is a kubernetes controller over ReplicaSet controller. Other controllers are: DaemonSet and Job, CronJob: * DaemonSet: creates one pod per node (like docker swarm's ``deploy.mode: global``) - use cases: promtail/fluentd, k8s-pinger/goldpinger * Job: one-shot job. Starts pod, waits for it to finish, dies * CronJob: run a job, scheduled .. code-block:: sh kubectl apply -f redis-config.yaml --dry-run=server # Update image kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2 curl 95.216.150.107:$NODE_PORT kubectl rollout status deployments/kubernetes-bootcamp kubectl rollout history deployment/goapp-deployment # Проверить историю деплоймента kubectl rollout undo deployment/goapp-deployment # Откатиться к предыдущей версии деплоймента kubectl rollout restart deployment/goapp-deployment # Плавающий рестарт Подов в деплойменте .. code-block:: yaml apiVersion: apps/v1 kind: Deployment metadata: name: declarative-deployment labels: app: go-web spec: replicas: 1 selector: matchLabels: app: goapp # <-- to which pods this deployment is applied to template: # <-- more like `podTemplate` starting here metadata: labels: app: goapp # <-- pod's labels (usually same as matchLabels from above) spec: containers: - name: goapp image: ksxack/lesson1:v0.2 ports: - containerPort: 8080 Log into private Registry ========================= * `k8s: `_ .. code-block:: sh # Based on existing credentials docker login ghcr.io # --username --password kubectl create secret generic regcred --from-file=.dockerconfigjson=${PWD}/.docker/config.json --type=kubernetes.io/dockerconfigjson # Create anew kubectl create secret docker-registry regcred --docker-server= --docker-username= --docker-password= --docker-email= kubectl get secret regcred --output=yaml kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" |base64 --decode # Then apply the pod below: kubectl apply -f private-reg-pod.yaml .. code-block:: yaml :caption: private-reg-pod.yaml apiVersion: v1 kind: Pod metadata: name: private-reg spec: containers: - name: private-reg-container image: imagePullSecrets: - name: regcred Helm ==== * `Grafana Helm Chart `_ * `What Is Helm? A Quickstart Tutorial For Kubernetes Beginners `_ Chart structure:: test-chart ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── secret.yaml │ └── service.yaml └── values.yaml .. code-block:: yaml :caption: Chart.yaml apiVersion: v2 name: test-chart description: A Helm chart for Kubernetes type: application version: 0.1.0 appVersion: "1.16.0" .. code-block:: yaml :caption: templates/secret.yaml apiVersion: v1 kind: Secret metadata: name: {{ .Values.secret.name }} stringData: password: {{ .Values.secret.password }} .. code-block:: yaml :caption: values.yaml image: nginx:latest replicas: 3 secret: name: load-secret password: loadqwerty .. code-block:: sh helm create test-chart # helm lint test-chart helm install my-helm-release test-chart -n tst-namespace -f test-chart/values.yaml --create-namespace helm uninstall -n tst-namespace my-helm-release helm install --debug --dry-run nginx nginx helm install my-release bitnami/nginx -f values.yaml helm repo add grafana https://grafana.github.io/helm-charts # helm search repo grafana # helm repo update helm install grafana grafana/grafana kubectl get pods -w kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=grafana" -o jsonpath="{.items[0].metadata.name}") kubectl --namespace default port-forward $POD_NAME 3000 helm install gabibbo97/gangway \ --set config.apiServerURL='https://api.example.com:6443' \ --set config.authorizeURL='https://auth.example.com/auth' \ --set config.tokenURL='https://auth.example.com/token' \ --set config.clientSecret='superSecret' \ --set config.sessionSecurityKey='superSecure' Requests, Limits ================ .. code-block:: yaml containers: - name: app image: ksxack/lesson1:v0.2 resources: requests: # how much pod wants to have (affects placement) memory: "100Mi" cpu: "200m" # миллиядер CPU limits: # how much pod can use, at max memory: "150Mi" cpu: "300m" Quality of Service (QoS): * Best Effort - такой класс присваивается, когда Вы вообще не указываете реквесты и лимиты; * Burstable - данный класс будет присвоен, если лимиты и реквесты отличаются; * Guaranted - когда лимиты и реквесты равны друг-другу. По приоритету идут так Guaranted > Burstable > Best Effort. Healthchecks (Probes) ============================ * `Configure Liveness, Readiness and Startup Probes `_ :: startupProbe --> readinessProbe --> livenessProbe .. code-block:: yaml :caption: livenessProbe apiVersion: v1 kind: Pod metadata: labels: test: my-pod name: my-pod-http spec: containers: - name: containername image: k8s.gcr.io/liveness args: - /server livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: Awesome initialDelaySeconds: 3 # default: 0 periodSeconds: 2 # default: 10 # failureThreshold: 3 # default: 3 # timeoutSeconds: 1 # successThreshold: 1 .. code-block:: yaml :caption: readinessProbe readinessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5 .. code-block:: yaml :caption: startupProbe startupProbe: httpGet: path: /healthz port: liveness-port failureThreshold: 30 periodSeconds: 10 Horizontal Pod Autoscaler ========================= .. code-block:: yaml apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: php-apache spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 80 В данном примере, Делпойменту php-apache присуждается минимальное количество реплик - 1, максимальное - 5, и в случае, если CPU у одного из Подов дойдет до 80% от реквеста, то HPA добавит еще одну реплику. Volumes ======= * `SO: Kubernetes Persistent Volume Claim Indefinitely in Pending State `_ .. code-block:: sh docker run -d --net=host \ --privileged --name nfs-server \ katacoda/contained-nfs-server:centos7 \ /exports/data-0001 /exports/data-0002 .. code-block:: yaml apiVersion: v1 kind: PersistentVolume metadata: name: nfs-0002 spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce - ReadWriteMany persistentVolumeReclaimPolicy: Recycle nfs: server: 172.17.0.1 path: /exports/data-0002 .. code-block:: yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: claim-http spec: storageClassName: "" # <-- added to match the storage class of PV accessModes: - ReadWriteOnce resources: requests: storage: 1Gi There's ``Ephemeral Storage`` (what's within the container), ``HostPath`` (path on the current node: wouldn't survive a restart on the other node), and ``PV``. Use ``StorageClass`` to allow users to define storage requirements similar to CPU/RAM. Other things ============ .. code-block:: sh GITHUB_URL=https://github.com/kubernetes/dashboard/releases VERSION_KUBE_DASHBOARD=$(curl -w '%{url_effective}' -I -L -s -S ${GITHUB_URL}/latest -o /dev/null | sed -e 's|.*/||') k3s kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/${VERSION_KUBE_DASHBOARD}/aio/deploy/recommended.yaml kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 kubectl create deployment first-deployment --image=ksxack/lesson1:v0.2 kubectl edit ... # just don't kubectl proxy & curl http://localhost:8001/version # fg # Ctrl+C curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080 curl 95.216.150.107:$NODE_PORT kubectl label pods $POD_NAME version=v1 kubectl get pods -l version=v1 kubectl delete service -l app=kubernetes-bootcamp curl 95.216.150.107:$NODE_PORT # kubectl create deployment node-hello --image=gcr.io/google-samples/node-hello:1.0 --port=8080 # kubectl proxy --port=8080 # curl http://localhost:8080/api/ # curl http://localhost:8080/api/v1/namespaces/default/pods curl 95.216.150.107:$NODE_PORT curl 95.216.150.107:$NODE_PORT kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2 curl 95.216.150.107:$NODE_PORT kubectl rollout status deployments/kubernetes-bootcamp kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10 kubectl rollout undo deployments/kubernetes-bootcamp cd sample-kubernetes-config/start/ mvn package -pl system mvn package -pl inventory # https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/ kubectl apply -f kubernetes.yaml kubectl wait --for=condition=ready pod -l app=inventory kubectl wait --for=condition=ready pod -l app=system curl -u bob:bobpwd http://$( minikube ip ):31000/system/properties curl http://$( minikube ip ):32000/inventory/systems/system-service curl -# -I -u bob:bobpwd -D - http://$( minikube ip ):31000/system/properties | grep -i ^X-App-Name: mvn package -pl system mvn package -pl inventory kubectl replace --force -f kubernetes.yaml curl -# -I -u bob:bobpwd -D - http://$( minikube ip ):31000/system/properties | grep -i ^X-App-Name: curl http://$( minikube ip ):32000/inventory/systems/system-service kubectl apply -f example-redis-config.yaml kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/config/redis-pod.yaml kubectl apply -f example-redis-config.yaml kubectl delete pod redis kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/config/redis-pod.yaml kubectl exec -it redis -- redis-cli kubectl delete pod/redis configmap/example-redis-config Issues with official k8s tutorial: * Some curl in the playground required -L (not mentioned in tutorial), while not requiring it for k3s installation * Curling service behind proxy required a port number (8080) explicitly written (gist: https://gist.github.com/ipedrazas/403df2ed30ea8682e2b709ddc1c24bcf) - ``docker image pull gcr.io/google-samples/kubernetes-bootcamp:v1`` - ``docker image inspect gcr.io/google-samples/kubernetes-bootcamp:v1`` * In module 4 ``kubectl label pods $POD_NAME version=v1`` in playground yields error message about label being already defined K3s Hetzner Integration ======================= * `How to set up K3S, GlusterFS and Hetzner's cloud load balancer `_ * `How to integrate k3s with a cloud controller `_ Contaners ========= * https://kube.academy/courses/containers-101/ .. code-block:: sh docker run -d --rm --hostname c1 --name test nicolaka/netshoot:latest sleep 50000 docker exec -ti test bash $ ip a docker container inspect test |grep -i pid sudo nsenter --target 640805 --uts $ ip a # host's networking stack $ hostname # c1 sudo nsenter --target 640805 --net --mount $ ip a # in container $ hostname # desktop hostname $ ls /home # no desktop users cat /proc/640805/cgroup cat /sys/fs/cgroup/system.slice/docker-9dd4def410e43aa629115927c2116e67342afdd58bf7579542acd030ba5257aa.scope/memory.peak docker rm -f test docker run -d --rm --memory 6m --hostname c1 --name test nicolaka/netshoot:latest sleep 50000 find /sys/fs/cgroup/ -name '*memory*' |grep eaebb88 |grep peak cat /sys/fs/cgroup/system.slice/docker-eaebb888a6c9fbf81d878ce3c5e4cbc05f8dc00ad2e02a6086fef36fa6d79c83.scope/memory.peak # 4022272 == 3.8 * 1024^2 wget https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.20.0-x86_64.tar.gz cat <<'EOF' >Dockerfile # syntax=docker/dockerfile:1.3 FROM scratch ADD alpine-minirootfs-3.20.0-x86_64.tar.gz / CMD ["/bin/sh"] EOF ============================ Kubernetes Platform Security ============================ Network Policies and CNI ======================== * Network Policy - requires a CNI * Policies for pods are label-based * Policies are additive, order doesn't matter * Policy rules can be applied in ingress and egress directions Example: .. code-block:: yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: demo-network-policy namespace: default spec: podSelector: matchLabels: role: demo-app policyTypes: - Ingress - Egress ingress: - from: - ipBlock: cidr: 172.17.0.0/16 except: - 172.17.1.0/24 - namespaceSelector: matchLabels: project: myproject - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 6379 CNI: * An interface between container runtime and network implementation * A contract between container runtime and network * Responsible for net connectivity and removal of allocated resources once container is deleted