├── .gitignore ├── .envrc ├── .mk ├── ipvs.mk ├── helm.mk ├── kubectl.mk ├── flux.mk ├── help.mk ├── frr.mk ├── kind.mk ├── gobgp.mk ├── services.mk ├── cache.mk ├── ingress.mk └── plugins.mk ├── manifests ├── calico │ ├── bgpconfig.yaml │ ├── bgppeer.yaml │ └── calico-installation.yaml ├── metallb-l2 │ └── metallb.yml ├── egress-gw │ └── cilium.yaml ├── metallb-l3 │ └── metallb.yml ├── statefulset │ └── consul.yml ├── app │ └── tshoot.yml ├── gateway-api │ └── istio.yaml ├── cilium │ └── cilium.yml ├── ipvs │ └── ipvs.yaml ├── weave │ ├── kube-proxy.yml │ └── weavenet.yml └── flannel │ └── flannel.yml ├── frr ├── frr.conf └── daemons ├── flux ├── git-source.yaml ├── app.yaml └── lab-configs │ ├── ipvs.yaml │ ├── weave.yaml │ ├── calico.yaml │ ├── cilium.yaml │ ├── flannel.yaml │ ├── headless.yaml │ ├── gateway-api.yaml │ ├── egress.yaml │ ├── metallb.yaml │ ├── ingress-nginx.yaml │ └── istio.yaml ├── cni-installer └── Dockerfile ├── hacks ├── unhook-cilium.sh └── 10-kubeadm.conf ├── kind.yaml ├── gobgp ├── Dockerfile └── rr.conf ├── README.md ├── Makefile ├── license.md └── diagrams └── k8s-guide.drawio /.gitignore: -------------------------------------------------------------------------------- 1 | kubeconfig -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | export KUBECONFIG=kubeconfig 2 | -------------------------------------------------------------------------------- /.mk/ipvs.mk: -------------------------------------------------------------------------------- 1 | ipvs: flux-init-wait 2 | kubectl apply -f flux/lab-configs/ipvs.yaml 3 | 4 | kube-proxy-logs: 5 | kubectl logs -l k8s-app=kube-proxy -n kube-system 6 | 7 | 8 | -------------------------------------------------------------------------------- /manifests/calico/bgpconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: crd.projectcalico.org/v1 2 | kind: BGPConfiguration 3 | metadata: 4 | name: default 5 | spec: 6 | asNumber: 64496 7 | nodeToNodeMeshEnabled: false -------------------------------------------------------------------------------- /manifests/calico/bgppeer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: crd.projectcalico.org/v1 2 | kind: BGPPeer 3 | metadata: 4 | name: gobgp-peer 5 | spec: 6 | peerIP: gobgp 7 | asNumber: 64496 8 | nodeSelector: all() -------------------------------------------------------------------------------- /.mk/helm.mk: -------------------------------------------------------------------------------- 1 | helm-test: 2 | @which helm 1>/dev/null 2>&1 3 | 4 | helm-install: 5 | @echo 'helm is not found. Follow: https://helm.sh/docs/intro/install/' 6 | 7 | helm-ensure: 8 | @make -s helm-test || make -s helm-install 9 | 10 | -------------------------------------------------------------------------------- /frr/frr.conf: -------------------------------------------------------------------------------- 1 | ! 2 | service integrated-vtysh-config 3 | ! 4 | router bgp 64496 5 | bgp router-id 198.51.100.255 6 | no bgp ebgp-requires-policy 7 | neighbor k8s peer-group 8 | neighbor k8s remote-as external 9 | bgp listen range 0.0.0.0/0 peer-group k8s 10 | ! -------------------------------------------------------------------------------- /.mk/kubectl.mk: -------------------------------------------------------------------------------- 1 | kubectl-test: 2 | @which kubectl 1>/dev/null 2>&1 3 | 4 | kubectl-install: 5 | echo 'kubectl not found. Follow: https://kubernetes.io/docs/tasks/tools/install-kubectl/' 6 | 7 | kubectl-ensure: 8 | @make -s kubectl-test || make -s kubectl-install 9 | 10 | -------------------------------------------------------------------------------- /flux/git-source.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: source.toolkit.fluxcd.io/v1beta1 3 | kind: GitRepository 4 | metadata: 5 | name: labs 6 | namespace: flux 7 | spec: 8 | interval: 1m0s 9 | ref: 10 | branch: master 11 | url: https://github.com/networkop/k8s-guide-labs 12 | 13 | -------------------------------------------------------------------------------- /manifests/metallb-l2/metallb.yml: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: metallb 5 | namespace: kube-system 6 | data: 7 | config: | 8 | address-pools: 9 | - addresses: 10 | - 198.51.100.0/24 11 | name: default 12 | protocol: layer2 13 | -------------------------------------------------------------------------------- /flux/app.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: app 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/app 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /flux/lab-configs/ipvs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: svc 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/ipvs 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /flux/lab-configs/weave.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: cni 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/weave 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /flux/lab-configs/calico.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: cni 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/calico 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /flux/lab-configs/cilium.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: cni 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/cilium 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /flux/lab-configs/flannel.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: cni 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/flannel 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /cni-installer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | RUN mkdir /opt/bin 4 | 5 | WORKDIR /opt/bin 6 | 7 | ADD https://github.com/containernetworking/plugins/releases/download/v0.8.7/cni-plugins-linux-amd64-v0.8.7.tgz ./ 8 | 9 | RUN tar zxvf cni-plugins-linux-amd64-v0.8.7.tgz && rm cni-plugins-linux-amd64-v0.8.7.tgz 10 | 11 | 12 | -------------------------------------------------------------------------------- /flux/lab-configs/headless.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: svc 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/statefulset 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | 15 | -------------------------------------------------------------------------------- /flux/lab-configs/gateway-api.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: gateway-api 6 | namespace: flux 7 | spec: 8 | interval: 10m0s 9 | path: ./manifests/gateway-api 10 | prune: true 11 | sourceRef: 12 | kind: GitRepository 13 | name: labs 14 | -------------------------------------------------------------------------------- /manifests/egress-gw/cilium.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cilium.io/v2alpha1 2 | kind: CiliumEgressNATPolicy 3 | metadata: 4 | name: egress-all 5 | namespace: default 6 | spec: 7 | egress: 8 | - podSelector: 9 | matchLabels: 10 | io.kubernetes.pod.namespace: default 11 | destinationCIDRs: 12 | - ${destination_cidr} 13 | egressSourceIP: "${egress_ip}" -------------------------------------------------------------------------------- /manifests/metallb-l3/metallb.yml: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: metallb 5 | namespace: kube-system 6 | data: 7 | config: | 8 | address-pools: 9 | - addresses: 10 | - 198.51.100.0/24 11 | name: default 12 | protocol: bgp 13 | peers: 14 | - my-asn: 64500 15 | peer-address: ${peer_addr} 16 | peer-asn: 64496 17 | -------------------------------------------------------------------------------- /hacks/unhook-cilium.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | KUBECONFIG=kubeconfig 6 | 7 | attachments=$(kubectl -n cilium exec ds/cilium -- bpftool cgroup list /run/cilium/cgroupv2 | tail -n +2 | awk '{print $2 " id " $1 }') 8 | 9 | echo "${attachments}" | 10 | while IFS= read -r args; do 11 | kubectl -n cilium exec ds/cilium -- bpftool cgroup detach /run/cilium/cgroupv2 ${args} 12 | done -------------------------------------------------------------------------------- /.mk/flux.mk: -------------------------------------------------------------------------------- 1 | 2 | flux-install: 3 | @kubectl apply -f flux/install.yaml 4 | @kubectl apply -f flux/git-source.yaml 5 | @kubectl apply -f flux/app.yaml 6 | 7 | flux-init-wait: 8 | @echo 'Waiting for flux to initialize...' 9 | @kubectl wait --for=condition=available --timeout=60s -n flux deploy/kustomize-controller \ 10 | || echo "ERROR: Flux Failed to Initialse. Please 'make down' and reboot." 11 | 12 | 13 | -------------------------------------------------------------------------------- /kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | containerdConfigPatches: 4 | - |- 5 | [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] 6 | endpoint = ["http://docker-cache:5000"] 7 | - |- 8 | [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"] 9 | endpoint = ["http://quay-cache:5000"] 10 | nodes: 11 | - role: control-plane 12 | - role: worker 13 | - role: worker -------------------------------------------------------------------------------- /.mk/help.mk: -------------------------------------------------------------------------------- 1 | # From: https://gist.github.com/klmr/575726c7e05d8780505a 2 | help: 3 | @echo "$$(tput sgr0)";sed -ne"/^## /{h;s/.*//;:d" -e"H;n;s/^## //;td" -e"s/:.*//;G;s/\\n## /---/;s/\\n/ /g;p;}" ${MAKEFILE_LIST}|awk -F --- -v n=$$(tput cols) -v i=15 -v a="$$(tput setaf 6)" -v z="$$(tput sgr0)" '{printf"%s%*s%s ",a,-i,$$1,z;m=split($$2,w," ");l=n-i;for(j=1;j<=m;j++){l-=length(w[j])+1;if(l<= 0){l=n-i-length(w[j])-1;printf"\n%*s ",-i," ";}printf"%s ",w[j];}printf"\n";}' 4 | -------------------------------------------------------------------------------- /gobgp/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.16-alpine as builder 2 | 3 | ENV GO111MODULE=on 4 | ENV CGO_ENABLED=0 5 | 6 | RUN apk add --no-cache git 7 | RUN git clone https://github.com/osrg/gobgp /gobgp 8 | 9 | WORKDIR /gobgp 10 | RUN git checkout tags/v2.30.0 11 | RUN go install /gobgp/cmd/gobgp 12 | RUN go install /gobgp/cmd/gobgpd 13 | 14 | FROM alpine:3.12 15 | 16 | COPY --from=builder /go/bin/gobgpd /usr/local/bin/ 17 | COPY --from=builder /go/bin/gobgp /usr/local/bin/ 18 | 19 | ENTRYPOINT [ "gobgpd" ] -------------------------------------------------------------------------------- /manifests/calico/calico-installation.yaml: -------------------------------------------------------------------------------- 1 | # For more information, see: https://docs.projectcalico.org/v3.16/reference/installation/api#operator.tigera.io/v1.Installation 2 | apiVersion: operator.tigera.io/v1 3 | kind: Installation 4 | metadata: 5 | name: default 6 | spec: 7 | # Configures Calico networking. 8 | calicoNetwork: 9 | bgp: Enabled 10 | ipPools: 11 | - blockSize: 24 12 | cidr: 10.244.128.0/17 13 | encapsulation: None 14 | natOutgoing: Enabled 15 | nodeSelector: all() 16 | 17 | -------------------------------------------------------------------------------- /.mk/frr.mk: -------------------------------------------------------------------------------- 1 | FRR_IMG := frrouting/frr:v7.5.1 2 | FRR_IP ?= $(shell docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' frr) 3 | 4 | frr-start: frr-cleanup 5 | docker run -d --name frr \ 6 | --privileged \ 7 | --mount type=bind,source="$$(pwd)"/frr/daemons,target=/etc/frr/daemons \ 8 | --mount type=bind,source="$$(pwd)"/frr/frr.conf,target=/etc/frr/frr.conf \ 9 | --network kind \ 10 | $(FRR_IMG) 11 | 12 | frr-cleanup: 13 | -docker rm -f frr 14 | sudo chown -R $$USER:$$USER frr/* 15 | 16 | frr-ip: 17 | @echo ${FRR_IP} 18 | 19 | -------------------------------------------------------------------------------- /gobgp/rr.conf: -------------------------------------------------------------------------------- 1 | [global.config] 2 | as = 64496 3 | router-id = "192.0.2.1" 4 | 5 | [[dynamic-neighbors]] 6 | [dynamic-neighbors.config] 7 | prefix = "0.0.0.0/0" 8 | peer-group = "k8s-group" 9 | 10 | [[peer-groups]] 11 | [peer-groups.config] 12 | peer-group-name = "k8s-group" 13 | peer-as = 64496 14 | [peer-groups.transport.config] 15 | passive-mode = true 16 | [peer-groups.route-reflector.config] 17 | route-reflector-client = true 18 | route-reflector-cluster-id = "192.0.2.1" 19 | [[peer-groups.afi-safis]] 20 | [peer-groups.afi-safis.config] 21 | afi-safi-name = "ipv4-unicast" -------------------------------------------------------------------------------- /manifests/statefulset/consul.yml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta1 2 | kind: HelmRepository 3 | metadata: 4 | name: hashicorp 5 | namespace: default 6 | spec: 7 | url: https://helm.releases.hashicorp.com 8 | interval: 10m 9 | --- 10 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 11 | kind: HelmRelease 12 | metadata: 13 | name: consul 14 | namespace: default 15 | spec: 16 | interval: 5m 17 | chart: 18 | spec: 19 | chart: consul 20 | version: "0.20.1" 21 | sourceRef: 22 | kind: HelmRepository 23 | name: hashicorp 24 | namespace: default 25 | interval: 1m 26 | values: 27 | global: 28 | name: consul 29 | 30 | -------------------------------------------------------------------------------- /flux/lab-configs/egress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: egress-gw 5 | namespace: flux 6 | spec: 7 | interval: 10m0s 8 | path: ./manifests/egress-gw 9 | prune: true 10 | sourceRef: 11 | kind: GitRepository 12 | name: labs 13 | postBuild: 14 | substitute: 15 | destination_cidr: "172.18.0.0/16" 16 | egress_ip: "172.18.0.5" 17 | --- 18 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 19 | kind: Kustomization 20 | metadata: 21 | name: lb-controller 22 | namespace: flux 23 | spec: 24 | interval: 10m0s 25 | path: ./manifests/metallb-l2 26 | prune: true 27 | sourceRef: 28 | kind: GitRepository 29 | name: labs 30 | -------------------------------------------------------------------------------- /.mk/kind.mk: -------------------------------------------------------------------------------- 1 | # Targets to manage a kind cluster 2 | 3 | KIND_CLUSTER_NAME ?= k8s-guide 4 | KIND_NETWORK:=kind 5 | export KUBECONFIG=kubeconfig 6 | 7 | ifeq (,$(wildcard ./kind.yaml)) 8 | KIND_CONF:= 9 | else 10 | KIND_CONF:=--config ./kind.yaml 11 | endif 12 | 13 | kind-install: 14 | GO111MODULE="on" go get -u sigs.k8s.io/kind@v0.9.0 15 | 16 | 17 | kind-stop: 18 | @kind delete cluster --name $(KIND_CLUSTER_NAME) || \ 19 | echo "kind cluster is not running" 20 | 21 | kind-test: 22 | @which kind 1>/dev/null 2>&1 23 | 24 | kind-ensure: 25 | @make -s kind-test || make -s kind-install 26 | 27 | 28 | kind-start: 29 | @kind get clusters | grep $(KIND_CLUSTER_NAME) || \ 30 | kind create cluster --name $(KIND_CLUSTER_NAME) --kubeconfig kubeconfig $(KIND_CONF) 31 | 32 | 33 | kind-load: kind-ensure 34 | kind load docker-image --name $(KIND_CLUSTER_NAME) ${IMG} 35 | 36 | -------------------------------------------------------------------------------- /manifests/app/tshoot.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | labels: 5 | run: net-tshoot 6 | name: net-tshoot 7 | namespace: default 8 | spec: 9 | selector: 10 | matchLabels: 11 | name: net-tshoot 12 | template: 13 | metadata: 14 | labels: 15 | name: net-tshoot 16 | spec: 17 | containers: 18 | - command: ["tail", "-f", "/dev/null"] 19 | image: nicolaka/netshoot 20 | imagePullPolicy: Always 21 | name: net-tshoot 22 | securityContext: 23 | privileged: true 24 | volumeMounts: 25 | - mountPath: /lib/modules/ 26 | name: lib-modules 27 | #hostNetwork: true 28 | tolerations: 29 | - effect: NoSchedule 30 | operator: Exists 31 | volumes: 32 | - hostPath: 33 | path: /lib/modules 34 | type: "" 35 | name: lib-modules 36 | 37 | -------------------------------------------------------------------------------- /flux/lab-configs/metallb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta1 2 | kind: HelmRepository 3 | metadata: 4 | name: metallb 5 | namespace: flux 6 | spec: 7 | interval: 1m 8 | url: https://metallb.github.io/metallb 9 | --- 10 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 11 | kind: HelmRelease 12 | metadata: 13 | name: metallb 14 | namespace: kube-system 15 | spec: 16 | interval: 5m 17 | chart: 18 | spec: 19 | chart: metallb 20 | version: 'v0.10.2' 21 | sourceRef: 22 | kind: HelmRepository 23 | name: metallb 24 | namespace: flux 25 | interval: 1m 26 | --- 27 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 28 | kind: Kustomization 29 | metadata: 30 | name: metallb 31 | namespace: flux 32 | spec: 33 | interval: 10m0s 34 | path: ./manifests/metallb-l3 35 | prune: true 36 | sourceRef: 37 | kind: GitRepository 38 | name: labs 39 | postBuild: 40 | substitute: 41 | peer_addr: "10.10.10.10" 42 | -------------------------------------------------------------------------------- /manifests/gateway-api/istio.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.x-k8s.io/v1alpha1 2 | kind: GatewayClass 3 | metadata: 4 | name: istio 5 | spec: 6 | controller: istio.io/gateway-controller 7 | --- 8 | apiVersion: networking.x-k8s.io/v1alpha1 9 | kind: Gateway 10 | metadata: 11 | name: gateway 12 | namespace: istio-system 13 | spec: 14 | gatewayClassName: istio 15 | listeners: 16 | - hostname: "*" 17 | port: 80 18 | protocol: HTTP 19 | routes: 20 | namespaces: 21 | from: All 22 | selector: 23 | matchLabels: 24 | selected: "yes" 25 | kind: HTTPRoute 26 | --- 27 | apiVersion: networking.x-k8s.io/v1alpha1 28 | kind: HTTPRoute 29 | metadata: 30 | name: http 31 | namespace: default 32 | labels: 33 | selected: "yes" 34 | spec: 35 | gateways: 36 | allow: All 37 | hostnames: ["gateway.tkng.io"] 38 | rules: 39 | - matches: 40 | - path: 41 | type: Prefix 42 | value: / 43 | forwardTo: 44 | - serviceName: web 45 | port: 80 -------------------------------------------------------------------------------- /flux/lab-configs/ingress-nginx.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta1 2 | kind: HelmRepository 3 | metadata: 4 | name: ingress-nginx 5 | namespace: flux 6 | spec: 7 | interval: 1m 8 | url: https://kubernetes.github.io/ingress-nginx 9 | --- 10 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 11 | kind: HelmRelease 12 | metadata: 13 | name: ingress-controller 14 | namespace: kube-system 15 | spec: 16 | interval: 5m 17 | chart: 18 | spec: 19 | chart: ingress-nginx 20 | version: '4.0.1' 21 | sourceRef: 22 | kind: HelmRepository 23 | name: ingress-nginx 24 | namespace: flux 25 | interval: 1m 26 | values: 27 | admissionWebhooks: 28 | enabled: false 29 | --- 30 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 31 | kind: Kustomization 32 | metadata: 33 | name: lb-controller 34 | namespace: flux 35 | spec: 36 | interval: 10m0s 37 | path: ./manifests/metallb-l2 38 | prune: true 39 | sourceRef: 40 | kind: GitRepository 41 | name: labs 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | 1. Install main dependencies: 4 | 5 | * Go https://golang.org/doc/install 6 | * Docker https://docs.docker.com/engine/install/ 7 | * direnv https://direnv.net/ 8 | 9 | 2. Clone this repository 10 | 11 | ``` 12 | $ git clone https://github.com/networkop/k8s-guide-labs.git && \ 13 | cd k8s-guide-labs && \ 14 | direnv allow 15 | ``` 16 | 17 | 3. View available targets 18 | 19 | ``` 20 | $ make help 21 | 22 | check Check prerequisites 23 | setup Setup the lab environment 24 | up Bring up the cluster 25 | connect Connect to Weave Scope 26 | tshoot Connect to the troubleshooting pod 27 | reset Reset k8s cluster 28 | down Shutdown 29 | cleanup Destroy the lab environment 30 | ``` 31 | 32 | 4. Check prerequisites 33 | 34 | ``` 35 | $ make check 36 | all good 37 | ``` 38 | 39 | 5. Bring up the lab 40 | 41 | ``` 42 | $ make setup 43 | ``` 44 | 45 | 6. Configure the cluster 46 | 47 | ``` 48 | $ make up 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /.mk/gobgp.mk: -------------------------------------------------------------------------------- 1 | GOBGP_IMG := gobgp:k8s-labs 2 | GOBGP_IP ?= $(shell docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' gobgp) 3 | 4 | gobgp-build: 5 | docker build -t $(GOBGP_IMG) gobgp/ 6 | 7 | gobgp-rr: gobgp-cleanup gobgp-build 8 | docker run -d --name gobgp \ 9 | --mount type=bind,source="$$(pwd)"/gobgp,target=/tmp/gobgp \ 10 | --network kind \ 11 | $(GOBGP_IMG) \ 12 | -f /tmp/gobgp/rr.conf 13 | 14 | gobgp-cleanup: 15 | -docker rm -f gobgp 16 | 17 | gobgp-ip: 18 | @echo ${GOBGP_IP} 19 | 20 | # 1. extract existing bgppeer definition 21 | # 2. change the name to prevent flux from overwriting it 22 | # 3. change the peerIP to match the IP of the gobgp container 23 | gobgp-calico-patch: 24 | kubectl get bgppeers gobgp-peer -oyaml | \ 25 | kubectl patch -f - --type=merge -oyaml \ 26 | --dry-run=client --local \ 27 | -p '{"metadata":{"name": "gobgp-peer-updated"}}' | \ 28 | kubectl patch -f - --type=json -oyaml \ 29 | --dry-run=client --local \ 30 | -p='[{"op": "replace", "path": "/spec/peerIP", "value":"$(GOBGP_IP)"}]' | \ 31 | kubectl apply -f - 32 | -------------------------------------------------------------------------------- /manifests/cilium/cilium.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: cilium 5 | --- 6 | apiVersion: source.toolkit.fluxcd.io/v1beta1 7 | kind: HelmRepository 8 | metadata: 9 | name: cilium 10 | namespace: cilium 11 | spec: 12 | url: https://helm.cilium.io/ 13 | interval: 10m 14 | --- 15 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 16 | kind: HelmRelease 17 | metadata: 18 | name: cilium 19 | namespace: cilium 20 | spec: 21 | interval: 5m 22 | chart: 23 | spec: 24 | chart: cilium 25 | version: "1.10.3" 26 | sourceRef: 27 | kind: HelmRepository 28 | name: cilium 29 | namespace: cilium 30 | interval: 1m 31 | values: 32 | nodeinit: 33 | enabled: true 34 | kubeProxyReplacement: strict 35 | hostServices: 36 | enabled: true 37 | externalIPs: 38 | enabled: true 39 | nodePort: 40 | enabled: true 41 | egressGateway: 42 | enabled: true 43 | k8sServiceHost: k8s-guide-control-plane 44 | k8sServicePort: "6443" 45 | hostPort: 46 | enabled: true 47 | bpf: 48 | masquerade: true 49 | 50 | 51 | -------------------------------------------------------------------------------- /.mk/services.mk: -------------------------------------------------------------------------------- 1 | untaint: 2 | kubectl taint node k8s-guide-control-plane node-role.kubernetes.io/master- 3 | 4 | headless: untaint 5 | kubectl apply -f flux/lab-configs/headless.yaml 6 | 7 | headless-cleanup: 8 | kubectl delete -f flux/lab-configs/headless.yaml 9 | 10 | 11 | deployment: 12 | -kubectl create deployment web --image=nginx 13 | 14 | deployment-show: 15 | kubectl get pod -owide -l app=web 16 | 17 | scale-up: 18 | -kubectl scale --replicas=3 deployment/web 19 | 20 | scale-down: 21 | -kubectl scale --replicas=0 deployment/web 22 | 23 | cluster-ip: 24 | -kubectl expose deployment web --port=80 25 | 26 | nodeport: 27 | -kubectl expose deployment web --port=80 --type=NodePort 28 | 29 | node-ip-1: 30 | @docker inspect --format='control-plane:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' k8s-guide-control-plane 31 | 32 | node-ip-2: 33 | @docker inspect --format='worker:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' k8s-guide-worker 34 | 35 | node-ip-3: 36 | @docker inspect --format='worker2:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' k8s-guide-worker2 37 | 38 | loadbalancer: 39 | -kubectl expose deployment web --port=80 --type=LoadBalancer -------------------------------------------------------------------------------- /.mk/cache.mk: -------------------------------------------------------------------------------- 1 | # Targets to manage docker and quay.io pull-through registries 2 | # some pointers 3 | # https://www.talos.dev/docs/v0.6/guides/configuring-pull-through-cache/ 4 | # https://maelvls.dev/docker-proxy-registry-kind/ 5 | 6 | 7 | DOCKER_CACHE := docker-cache 8 | QUAYIO_CACHE := quay-cache 9 | 10 | cache-start: docker-cache quayio-cache 11 | 12 | docker-cache: 13 | @docker inspect -f '{{.State.Running}}' $(DOCKER_CACHE) 2>/dev/null || \ 14 | docker run -d --restart=always --network $(KIND_NETWORK) \ 15 | -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \ 16 | --name $(DOCKER_CACHE) registry:2 17 | 18 | quayio-cache: 19 | @docker inspect -f '{{.State.Running}}' $(QUAYIO_CACHE) 2>/dev/null || \ 20 | docker run -d --restart=always --network $(KIND_NETWORK) \ 21 | -e REGISTRY_PROXY_REMOTEURL=https://quay.io \ 22 | --name $(QUAYIO_CACHE) registry:2 23 | 24 | cache-stop: docker-cache-stop quayio-cache-stop 25 | 26 | quayio-cache-stop: 27 | @docker inspect -f '{{.State.Running}}' $(QUAYIO_CACHE) 2>/dev/null && \ 28 | docker rm -f $(QUAYIO_CACHE) 2>/dev/null || echo 'quay-cache is not running' 29 | 30 | docker-cache-stop: 31 | @docker inspect -f '{{.State.Running}}' $(DOCKER_CACHE) 2>/dev/null && \ 32 | docker rm -f $(DOCKER_CACHE) 2>/dev/null || echo 'docker-cache is not running' -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NODE?=k8s-guide-control-plane 2 | POD?=$(shell kubectl get -l name=net-tshoot pods -n default --field-selector spec.nodeName=$(NODE) -o jsonpath='{.items[0].metadata.name}') 3 | NODES?=$(shell kubectl get nodes -o jsonpath='{.items[*].metadata.name}') 4 | 5 | include .mk/kind.mk 6 | include .mk/help.mk 7 | include .mk/cache.mk 8 | include .mk/kubectl.mk 9 | include .mk/flux.mk 10 | include .mk/helm.mk 11 | include .mk/plugins.mk 12 | include .mk/gobgp.mk 13 | include .mk/services.mk 14 | include .mk/ipvs.mk 15 | include .mk/frr.mk 16 | include .mk/ingress.mk 17 | 18 | .DEFAULT_GOAL := help 19 | 20 | ## Check prerequisites 21 | check: kind-ensure kubectl-ensure helm-ensure 22 | @make -s kind-test && \ 23 | make -s kubectl-test && \ 24 | make -s helm-test && \ 25 | echo 'all good' || echo 'check failed. see logs above.' 26 | 27 | ## Setup the lab environment 28 | setup: kind-start cache-start 29 | 30 | ## Bring up the cluster 31 | up: kind-start 32 | @make -s flux-install 1>/dev/null 2>&1 33 | 34 | ## Connect to Weave Scope 35 | connect: 36 | echo 'Navigate to http://localhost:8080' && \ 37 | kubectl -n weave port-forward deployment/weave-scope-frontend-weave-scope 8080:4040 38 | 39 | ## Connect to the troubleshooting pod 40 | tshoot: 41 | @kubectl -n default exec -it $(POD) -- bash 42 | 43 | ## Reset k8s cluster 44 | reset: 45 | make -s down && make -s up 46 | 47 | ## Shutdown 48 | down: 49 | make -s kind-stop 50 | 51 | ## Destroy the lab environment 52 | cleanup: kind-stop cache-stop 53 | -------------------------------------------------------------------------------- /flux/lab-configs/istio.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: istio-system 5 | --- 6 | apiVersion: source.toolkit.fluxcd.io/v1beta1 7 | kind: GitRepository 8 | metadata: 9 | name: istio 10 | namespace: flux 11 | spec: 12 | interval: 1m0s 13 | ref: 14 | tag: 1.11.1 15 | url: https://github.com/istio/istio 16 | --- 17 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 18 | kind: HelmRelease 19 | metadata: 20 | name: istio-base 21 | namespace: istio-system 22 | spec: 23 | interval: 5m 24 | chart: 25 | spec: 26 | chart: manifests/charts/base 27 | sourceRef: 28 | kind: GitRepository 29 | name: istio 30 | namespace: flux 31 | interval: 1m 32 | --- 33 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 34 | kind: HelmRelease 35 | metadata: 36 | name: istio-discovery 37 | namespace: istio-system 38 | spec: 39 | interval: 5m 40 | chart: 41 | spec: 42 | chart: manifests/charts/istio-control/istio-discovery 43 | sourceRef: 44 | kind: GitRepository 45 | name: istio 46 | namespace: flux 47 | interval: 1m 48 | values: 49 | meshConfig: 50 | accessLogFile: /dev/stdout 51 | --- 52 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 53 | kind: HelmRelease 54 | metadata: 55 | name: istio-gateway 56 | namespace: istio-system 57 | spec: 58 | interval: 5m 59 | chart: 60 | spec: 61 | chart: manifests/charts/gateways/istio-ingress 62 | sourceRef: 63 | kind: GitRepository 64 | name: istio 65 | namespace: flux 66 | interval: 1m 67 | -------------------------------------------------------------------------------- /hacks/10-kubeadm.conf: -------------------------------------------------------------------------------- 1 | # https://github.com/kubernetes/kubernetes/blob/ba8fcafaf8c502a454acd86b728c857932555315/build/debs/10-kubeadm.conf 2 | # Note: This dropin only works with kubeadm and kubelet v1.11+ 3 | [Service] 4 | Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" 5 | Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" 6 | # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically 7 | EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env 8 | # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use 9 | # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. 10 | EnvironmentFile=-/etc/default/kubelet 11 | # On cgroup v1, the /kubelet cgroup is created in the entrypoint script before running systemd. 12 | # On cgroup v2, the /kubelet cgroup is created here. (See the comments in the entrypoint script for the reason.) 13 | ExecStartPre=/bin/sh -euc "if [ -f /sys/fs/cgroup/cgroup.controllers ]; then create-kubelet-cgroup-v2; fi" 14 | # WSL2 workaround 15 | ExecStartPre=/bin/sh -euc "if [ ! -f /sys/fs/cgroup/cgroup.controllers ] && [ ! -d /sys/fs/cgroup/systemd/kubelet ]; then mkdir -p /sys/fs/cgroup/systemd/kubelet; fi" 16 | ExecStart= 17 | ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS --cgroup-root=/kubelet -------------------------------------------------------------------------------- /manifests/ipvs/ipvs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | config.conf: |- 4 | apiVersion: kubeproxy.config.k8s.io/v1alpha1 5 | bindAddress: 0.0.0.0 6 | bindAddressHardFail: false 7 | clientConnection: 8 | acceptContentTypes: "" 9 | burst: 0 10 | contentType: "" 11 | kubeconfig: /var/lib/kube-proxy/kubeconfig.conf 12 | qps: 0 13 | clusterCIDR: 10.244.0.0/16 14 | configSyncPeriod: 0s 15 | conntrack: 16 | maxPerCore: null 17 | min: null 18 | tcpCloseWaitTimeout: null 19 | tcpEstablishedTimeout: null 20 | detectLocalMode: "" 21 | enableProfiling: false 22 | healthzBindAddress: "" 23 | hostnameOverride: "" 24 | iptables: 25 | masqueradeAll: false 26 | masqueradeBit: null 27 | minSyncPeriod: 1s 28 | syncPeriod: 0s 29 | ipvs: 30 | excludeCIDRs: null 31 | minSyncPeriod: 0s 32 | scheduler: "" 33 | strictARP: false 34 | syncPeriod: 0s 35 | tcpFinTimeout: 0s 36 | tcpTimeout: 0s 37 | udpTimeout: 0s 38 | kind: KubeProxyConfiguration 39 | metricsBindAddress: "" 40 | mode: ipvs 41 | nodePortAddresses: null 42 | oomScoreAdj: null 43 | portRange: "" 44 | showHiddenMetricsForVersion: "" 45 | udpIdleTimeout: 0s 46 | winkernel: 47 | enableDSR: false 48 | networkName: "" 49 | sourceVip: "" 50 | kubeconfig.conf: |- 51 | apiVersion: v1 52 | kind: Config 53 | clusters: 54 | - cluster: 55 | certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 56 | server: https://k8s-guide-control-plane:6443 57 | name: default 58 | contexts: 59 | - context: 60 | cluster: default 61 | namespace: default 62 | user: default 63 | name: default 64 | current-context: default 65 | users: 66 | - name: default 67 | user: 68 | tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 69 | kind: ConfigMap 70 | metadata: 71 | labels: 72 | app: kube-proxy 73 | name: kube-proxy 74 | namespace: kube-system 75 | -------------------------------------------------------------------------------- /manifests/weave/kube-proxy.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | config.conf: |- 4 | apiVersion: kubeproxy.config.k8s.io/v1alpha1 5 | bindAddress: 0.0.0.0 6 | bindAddressHardFail: false 7 | clientConnection: 8 | acceptContentTypes: "" 9 | burst: 0 10 | contentType: "" 11 | kubeconfig: /var/lib/kube-proxy/kubeconfig.conf 12 | qps: 0 13 | clusterCIDR: 10.32.0.0/12 14 | configSyncPeriod: 0s 15 | conntrack: 16 | maxPerCore: null 17 | min: null 18 | tcpCloseWaitTimeout: null 19 | tcpEstablishedTimeout: null 20 | detectLocalMode: "" 21 | enableProfiling: false 22 | healthzBindAddress: "" 23 | hostnameOverride: "" 24 | iptables: 25 | masqueradeAll: false 26 | masqueradeBit: null 27 | minSyncPeriod: 1s 28 | syncPeriod: 0s 29 | ipvs: 30 | excludeCIDRs: null 31 | minSyncPeriod: 0s 32 | scheduler: "" 33 | strictARP: false 34 | syncPeriod: 0s 35 | tcpFinTimeout: 0s 36 | tcpTimeout: 0s 37 | udpTimeout: 0s 38 | kind: KubeProxyConfiguration 39 | metricsBindAddress: "" 40 | mode: iptables 41 | nodePortAddresses: null 42 | oomScoreAdj: null 43 | portRange: "" 44 | showHiddenMetricsForVersion: "" 45 | udpIdleTimeout: 0s 46 | winkernel: 47 | enableDSR: false 48 | networkName: "" 49 | sourceVip: "" 50 | kubeconfig.conf: |- 51 | apiVersion: v1 52 | kind: Config 53 | clusters: 54 | - cluster: 55 | certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 56 | server: https://k8s-guide-control-plane:6443 57 | name: default 58 | contexts: 59 | - context: 60 | cluster: default 61 | namespace: default 62 | user: default 63 | name: default 64 | current-context: default 65 | users: 66 | - name: default 67 | user: 68 | tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 69 | kind: ConfigMap 70 | metadata: 71 | labels: 72 | app: kube-proxy 73 | name: kube-proxy 74 | namespace: kube-system 75 | -------------------------------------------------------------------------------- /frr/daemons: -------------------------------------------------------------------------------- 1 | # This file tells the frr package which daemons to start. 2 | # 3 | # Sample configurations for these daemons can be found in 4 | # /usr/share/doc/frr/examples/. 5 | # 6 | # ATTENTION: 7 | # 8 | # When activating a daemon for the first time, a config file, even if it is 9 | # empty, has to be present *and* be owned by the user and group "frr", else 10 | # the daemon will not be started by /etc/init.d/frr. The permissions should 11 | # be u=rw,g=r,o=. 12 | # When using "vtysh" such a config file is also needed. It should be owned by 13 | # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. 14 | # 15 | # The watchfrr, zebra and staticd daemons are always started. 16 | # 17 | bgpd=yes 18 | ospfd=no 19 | ospf6d=no 20 | ripd=no 21 | ripngd=no 22 | isisd=no 23 | pimd=no 24 | ldpd=no 25 | nhrpd=no 26 | eigrpd=no 27 | babeld=no 28 | sharpd=no 29 | pbrd=no 30 | bfdd=no 31 | fabricd=no 32 | vrrpd=no 33 | 34 | # 35 | # If this option is set the /etc/init.d/frr script automatically loads 36 | # the config via "vtysh -b" when the servers are started. 37 | # Check /etc/pam.d/frr if you intend to use "vtysh"! 38 | # 39 | vtysh_enable=yes 40 | zebra_options=" -A 127.0.0.1 -s 90000000" 41 | bgpd_options=" -A 127.0.0.1" 42 | ospfd_options=" -A 127.0.0.1" 43 | ospf6d_options=" -A ::1" 44 | ripd_options=" -A 127.0.0.1" 45 | ripngd_options=" -A ::1" 46 | isisd_options=" -A 127.0.0.1" 47 | pimd_options=" -A 127.0.0.1" 48 | ldpd_options=" -A 127.0.0.1" 49 | nhrpd_options=" -A 127.0.0.1" 50 | eigrpd_options=" -A 127.0.0.1" 51 | babeld_options=" -A 127.0.0.1" 52 | sharpd_options=" -A 127.0.0.1" 53 | pbrd_options=" -A 127.0.0.1" 54 | staticd_options="-A 127.0.0.1" 55 | bfdd_options=" -A 127.0.0.1" 56 | fabricd_options="-A 127.0.0.1" 57 | vrrpd_options=" -A 127.0.0.1" 58 | 59 | # configuration profile 60 | # 61 | #frr_profile="traditional" 62 | #frr_profile="datacenter" 63 | 64 | # 65 | # This is the maximum number of FD's that will be available. 66 | # Upon startup this is read by the control files and ulimit 67 | # is called. Uncomment and use a reasonable value for your 68 | # setup if you are expecting a large number of peers in 69 | # say BGP. 70 | #MAX_FDS=1024 71 | 72 | # The list of daemons to watch is automatically generated by the init script. 73 | #watchfrr_options="" 74 | 75 | # To make watchfrr create/join the specified netns, use the following option: 76 | #watchfrr_options="--netns" 77 | # This only has an effect in /etc/frr//daemons, and you need to 78 | # start FRR with "/usr/lib/frr/frrinit.sh start ". 79 | 80 | # for debugging purposes, you can specify a "wrap" command to start instead 81 | # of starting the daemon directly, e.g. to use valgrind on ospfd: 82 | # ospfd_wrap="/usr/bin/valgrind" 83 | # or you can use "all_wrap" for all daemons, e.g. to use perf record: 84 | # all_wrap="/usr/bin/perf record --call-graph -" 85 | # the normal daemon command is added to this at the end. -------------------------------------------------------------------------------- /.mk/ingress.mk: -------------------------------------------------------------------------------- 1 | CONTROL_PLANE_NODE_IP := $(shell docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' k8s-guide-control-plane) 2 | KIND_BRIDGE_SUBNET := $(shell docker network inspect kind --format='{{(index .IPAM.Config 0).Subnet}}') 3 | 4 | ingress-nginx-add: 5 | kubectl apply -f flux/lab-configs/ingress-nginx.yaml 6 | 7 | ingress-nginx-delete: 8 | kubectl delete -f flux/lab-configs/ingress-nginx.yaml 9 | 10 | ingress-prep-add: 11 | kubectl -n default create deployment prod --image=nginxdemos/nginx-hello:plain-text 12 | kubectl -n default create deployment dev --image=nginxdemos/nginx-hello:plain-text 13 | kubectl -n default expose deployment prod --port=8080 14 | kubectl -n default expose deployment dev --port=8080 15 | 16 | ingress-prep-delete: 17 | -kubectl -n default delete deployment prod 18 | -kubectl -n default delete deployment dev 19 | -kubectl -n default delete svc prod 20 | -kubectl -n default delete svc dev 21 | 22 | ingress-path-routing: 23 | kubectl -n default create ingress tkng-1 --class=nginx --rule="/prod*=prod:8080" --rule="/dev*=dev:8080" 24 | 25 | ingress-host-routing: 26 | kubectl -n default create ingress tkng-2 --class=nginx --rule="prod/*=prod:8080" --rule="dev/*=dev:8080" 27 | 28 | ingress-delete: 29 | -kubectl -n default delete ingress tkng-1 30 | -kubectl -n default delete ingress tkng-2 31 | 32 | ingress-wait: 33 | kubectl wait --for=condition=ready --timeout=60s -n kube-system pod -l app.kubernetes.io/instance=ingress-controller 34 | 35 | ingress-setup: 36 | make -s ingress-nginx-add 37 | 38 | ingress-prep: 39 | make -s ingress-prep-add 40 | make -s ingress-path-routing 41 | make -s ingress-host-routing 42 | 43 | ingress-cleanup: ingress-delete ingress-prep-delete 44 | -make -s ingress-nginx-delete 45 | 46 | egress-prep: 47 | -docker rm -f echo 48 | -docker run -d --rm --network kind --name echo mpolden/echoip -l ":80" 49 | 50 | egress-setup: egress-prep 51 | kubectl apply -f flux/lab-configs/egress.yaml 52 | kubectl patch kustomizations -n flux egress-gw --patch '{"spec": {"postBuild": {"substitute": {"destination_cidr": "$(KIND_BRIDGE_SUBNET)"}}}}' --type=merge 53 | kubectl patch kustomizations -n flux egress-gw --patch '{"spec": {"postBuild": {"substitute": {"egress_ip": "$(CONTROL_PLANE_NODE_IP)"}}}}' --type=merge 54 | 55 | egress-cleanup: 56 | -docker rm -f echo 57 | -kubectl delete -f flux/lab-configs/egress.yaml 58 | 59 | 60 | gateway-setup: metallb 61 | kubectl apply -k github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0 62 | kubectl apply -f flux/lab-configs/istio.yaml 63 | kubectl apply -f flux/lab-configs/gateway-api.yaml 64 | 65 | gateway-check: 66 | @kubectl wait --for=condition=ready --timeout=60s -n istio-system pod --all 67 | @kubectl wait --for=condition=ready --timeout=60s -n kube-system pod -l app.kubernetes.io/instance=metallb 68 | 69 | gateway-cleanup: 70 | kubectl delete -k github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0 71 | kubectl delete -f flux/lab-configs/istio.yaml 72 | kubectl delete -f flux/lab-configs/gateway-api.yaml -------------------------------------------------------------------------------- /.mk/plugins.mk: -------------------------------------------------------------------------------- 1 | delete-kindnet: 2 | -kubectl -n kube-system delete daemonset kindnet 3 | 4 | flannel: delete-kindnet preload-cni-image 5 | kubectl apply -f flux/lab-configs/flannel.yaml 6 | 7 | weave: delete-kindnet 8 | kubectl apply -f flux/lab-configs/weave.yaml 9 | 10 | weave-restart: 11 | kubectl -n kube-system delete pod -l name=weave-net 12 | 13 | calico: delete-kindnet 14 | kubectl apply -f flux/lab-configs/calico.yaml 15 | 16 | calico-restart: flush-routes 17 | kubectl -n calico-system delete pod -l k8s-app=calico-node 18 | 19 | metallb: frr-start 20 | kubectl apply -f flux/lab-configs/metallb.yaml 21 | kubectl patch kustomizations -n flux metallb --patch '{"spec": {"postBuild": {"substitute": {"peer_addr": "$(FRR_IP)"}}}}' --type=merge 22 | 23 | metallb-delete: frr-cleanup 24 | kubectl delete -f flux/lab-configs/metallb.yaml 25 | git checkout HEAD -- frr/frr.conf 26 | 27 | cilium: flux-init-wait delete-kindnet 28 | kubectl apply -f flux/lab-configs/cilium.yaml 29 | 30 | cilium-wait: 31 | kubectl wait --for=condition=ready --timeout=60s -n cilium pod -l k8s-app=cilium 32 | 33 | cilium-check: 34 | kubectl exec -n cilium daemonset/cilium -- cilium status 35 | 36 | cilium-restart: flush-routes 37 | kubectl -n cilium delete pod -l k8s-app=cilium 38 | 39 | cilium-unhook: 40 | -@hacks/unhook-cilium.sh 2>/dev/null 41 | 42 | nuke-all-pods: flush-cni-dir 43 | kubectl delete --all pods --all-namespaces 44 | 45 | preload-cni-image: 46 | docker build -t networkop.co.uk/cni-install cni-installer 47 | kind load docker-image networkop.co.uk/cni-install:latest --name k8s-guide 48 | 49 | flush-routes: 50 | docker exec -it k8s-guide-control-plane ip route flush root 10.244.0.0/16 51 | docker exec -it k8s-guide-worker ip route flush root 10.244.0.0/16 52 | docker exec -it k8s-guide-worker2 ip route flush root 10.244.0.0/16 53 | 54 | flush-nat: 55 | docker exec -it k8s-guide-control-plane iptables --table nat --flush KIND-MASQ-AGENT 56 | docker exec -it k8s-guide-control-plane iptables --table nat --flush KUBE-SERVICES 57 | docker exec -it k8s-guide-worker iptables --table nat --flush KIND-MASQ-AGENT 58 | docker exec -it k8s-guide-worker iptables --table nat --flush KUBE-SERVICES 59 | docker exec -it k8s-guide-worker2 iptables --table nat --flush KIND-MASQ-AGENT 60 | docker exec -it k8s-guide-worker2 iptables --table nat --flush KUBE-SERVICES 61 | kubectl -n kube-system delete pod -l k8s-app=kube-proxy 62 | #docker exec -e ID=$(shell docker exec k8s-guide-control-plane bash -c "crictl ps --name kube-proxy -q") k8s-guide-control-plane bash -c 'crictl rm --force $${ID}' 63 | #docker exec -e ID=$(shell docker exec k8s-guide-worker bash -c "crictl ps --name kube-proxy -q") k8s-guide-worker bash -c 'crictl rm --force $${ID}' 64 | #docker exec -e ID=$(shell docker exec k8s-guide-worker2 bash -c "crictl ps --name kube-proxy -q") k8s-guide-worker2 bash -c 'crictl rm --force $${ID}' 65 | 66 | flush-all: flush-routes flush-nat 67 | 68 | nuke-kube-proxy: 69 | -kubectl -n kube-system delete ds kube-proxy 70 | -kubectl -n kube-system delete cm kube-proxy 71 | docker exec -it k8s-guide-worker bash -c 'iptables-restore <(iptables-save | grep -v KUBE)' 72 | docker exec -it k8s-guide-worker2 bash -c 'iptables-restore <(iptables-save | grep -v KUBE)' 73 | docker exec -it k8s-guide-control-plane bash -c 'iptables-restore <(iptables-save | grep -v KUBE)' 74 | 75 | flush-cni-dir: 76 | -docker exec -t k8s-guide-control-plane rm /etc/cni/net.d/10-kindnet.conflist 77 | -docker exec -t k8s-guide-worker rm /etc/cni/net.d/10-kindnet.conflist 78 | -docker exec -t k8s-guide-worker2 rm /etc/cni/net.d/10-kindnet.conflist 79 | 80 | 81 | test: 82 | docker exec -it k8s-guide-control-plane crictl ps `crictl ps --name kube-proxy -q` -------------------------------------------------------------------------------- /manifests/flannel/flannel.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: policy/v1beta1 3 | kind: PodSecurityPolicy 4 | metadata: 5 | name: psp.flannel.unprivileged 6 | annotations: 7 | seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default 8 | seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default 9 | apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default 10 | apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default 11 | spec: 12 | privileged: false 13 | volumes: 14 | - configMap 15 | - secret 16 | - emptyDir 17 | - hostPath 18 | allowedHostPaths: 19 | - pathPrefix: "/etc/cni/net.d" 20 | - pathPrefix: "/etc/kube-flannel" 21 | - pathPrefix: "/run/flannel" 22 | readOnlyRootFilesystem: false 23 | # Users and groups 24 | runAsUser: 25 | rule: RunAsAny 26 | supplementalGroups: 27 | rule: RunAsAny 28 | fsGroup: 29 | rule: RunAsAny 30 | # Privilege Escalation 31 | allowPrivilegeEscalation: false 32 | defaultAllowPrivilegeEscalation: false 33 | # Capabilities 34 | allowedCapabilities: ['NET_ADMIN', 'NET_RAW'] 35 | defaultAddCapabilities: [] 36 | requiredDropCapabilities: [] 37 | # Host namespaces 38 | hostPID: false 39 | hostIPC: false 40 | hostNetwork: true 41 | hostPorts: 42 | - min: 0 43 | max: 65535 44 | # SELinux 45 | seLinux: 46 | # SELinux is unused in CaaSP 47 | rule: 'RunAsAny' 48 | --- 49 | kind: ClusterRole 50 | apiVersion: rbac.authorization.k8s.io/v1beta1 51 | metadata: 52 | name: flannel 53 | rules: 54 | - apiGroups: ['extensions'] 55 | resources: ['podsecuritypolicies'] 56 | verbs: ['use'] 57 | resourceNames: ['psp.flannel.unprivileged'] 58 | - apiGroups: 59 | - "" 60 | resources: 61 | - pods 62 | verbs: 63 | - get 64 | - apiGroups: 65 | - "" 66 | resources: 67 | - nodes 68 | verbs: 69 | - list 70 | - watch 71 | - apiGroups: 72 | - "" 73 | resources: 74 | - nodes/status 75 | verbs: 76 | - patch 77 | --- 78 | kind: ClusterRoleBinding 79 | apiVersion: rbac.authorization.k8s.io/v1beta1 80 | metadata: 81 | name: flannel 82 | roleRef: 83 | apiGroup: rbac.authorization.k8s.io 84 | kind: ClusterRole 85 | name: flannel 86 | subjects: 87 | - kind: ServiceAccount 88 | name: flannel 89 | namespace: kube-system 90 | --- 91 | apiVersion: v1 92 | kind: ServiceAccount 93 | metadata: 94 | name: flannel 95 | namespace: kube-system 96 | --- 97 | kind: ConfigMap 98 | apiVersion: v1 99 | metadata: 100 | name: kube-flannel-cfg 101 | namespace: kube-system 102 | labels: 103 | tier: node 104 | app: flannel 105 | data: 106 | cni-conf.json: | 107 | { 108 | "name": "cbr0", 109 | "cniVersion": "0.3.1", 110 | "plugins": [ 111 | { 112 | "type": "flannel", 113 | "delegate": { 114 | "hairpinMode": true, 115 | "isDefaultGateway": true 116 | } 117 | }, 118 | { 119 | "type": "portmap", 120 | "capabilities": { 121 | "portMappings": true 122 | } 123 | } 124 | ] 125 | } 126 | net-conf.json: | 127 | { 128 | "Network": "10.244.0.0/16", 129 | "Backend": { 130 | "Type": "vxlan" 131 | } 132 | } 133 | --- 134 | apiVersion: apps/v1 135 | kind: DaemonSet 136 | metadata: 137 | name: kube-flannel-ds 138 | namespace: kube-system 139 | labels: 140 | tier: node 141 | app: flannel 142 | spec: 143 | selector: 144 | matchLabels: 145 | app: flannel 146 | template: 147 | metadata: 148 | labels: 149 | tier: node 150 | app: flannel 151 | spec: 152 | affinity: 153 | nodeAffinity: 154 | requiredDuringSchedulingIgnoredDuringExecution: 155 | nodeSelectorTerms: 156 | - matchExpressions: 157 | - key: kubernetes.io/os 158 | operator: In 159 | values: 160 | - linux 161 | hostNetwork: true 162 | priorityClassName: system-node-critical 163 | tolerations: 164 | - operator: Exists 165 | effect: NoSchedule 166 | serviceAccountName: flannel 167 | initContainers: 168 | - name: install-cni 169 | image: quay.io/coreos/flannel:v0.13.0-rc2 170 | command: 171 | - cp 172 | args: 173 | - -f 174 | - /etc/kube-flannel/cni-conf.json 175 | - /etc/cni/net.d/01-flannel.conflist 176 | volumeMounts: 177 | - name: cni 178 | mountPath: /etc/cni/net.d 179 | - name: flannel-cfg 180 | mountPath: /etc/kube-flannel/ 181 | ##### This is added by me to populate all standard CNI plugins in the /opt/cni/bin 182 | - name: install-binary 183 | image: networkop.co.uk/cni-install 184 | imagePullPolicy: Never 185 | command: 186 | - cp 187 | args: 188 | - -au 189 | - /opt/bin 190 | - /opt/cni/ 191 | volumeMounts: 192 | - name: bin 193 | mountPath: /opt/cni/bin 194 | ##### By default kind only includes a small subset of them 195 | containers: 196 | - name: kube-flannel 197 | image: quay.io/coreos/flannel:v0.13.0-rc2 198 | command: 199 | - /opt/bin/flanneld 200 | args: 201 | - --ip-masq 202 | - --kube-subnet-mgr 203 | resources: 204 | requests: 205 | cpu: "100m" 206 | memory: "50Mi" 207 | limits: 208 | cpu: "100m" 209 | memory: "50Mi" 210 | securityContext: 211 | privileged: false 212 | capabilities: 213 | add: ["NET_ADMIN", "NET_RAW"] 214 | env: 215 | - name: POD_NAME 216 | valueFrom: 217 | fieldRef: 218 | fieldPath: metadata.name 219 | - name: POD_NAMESPACE 220 | valueFrom: 221 | fieldRef: 222 | fieldPath: metadata.namespace 223 | volumeMounts: 224 | - name: run 225 | mountPath: /run/flannel 226 | - name: flannel-cfg 227 | mountPath: /etc/kube-flannel/ 228 | volumes: 229 | - name: run 230 | hostPath: 231 | path: /run/flannel 232 | - name: cni 233 | hostPath: 234 | path: /etc/cni/net.d 235 | - name: bin 236 | hostPath: 237 | path: /opt/cni/bin 238 | - name: flannel-cfg 239 | configMap: 240 | name: kube-flannel-cfg 241 | -------------------------------------------------------------------------------- /manifests/weave/weavenet.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: List 3 | items: 4 | - apiVersion: v1 5 | kind: ServiceAccount 6 | metadata: 7 | name: weave-net 8 | annotations: 9 | cloud.weave.works/launcher-info: |- 10 | { 11 | "original-request": { 12 | "url": "/k8s/v1.16/net.yaml?k8s-version=v1.19.1", 13 | "date": "Thu Oct 01 2020 17:42:18 GMT+0000 (UTC)" 14 | }, 15 | "email-address": "support@weave.works" 16 | } 17 | labels: 18 | name: weave-net 19 | namespace: kube-system 20 | - apiVersion: rbac.authorization.k8s.io/v1 21 | kind: ClusterRole 22 | metadata: 23 | name: weave-net 24 | annotations: 25 | cloud.weave.works/launcher-info: |- 26 | { 27 | "original-request": { 28 | "url": "/k8s/v1.16/net.yaml?k8s-version=v1.19.1", 29 | "date": "Thu Oct 01 2020 17:42:18 GMT+0000 (UTC)" 30 | }, 31 | "email-address": "support@weave.works" 32 | } 33 | labels: 34 | name: weave-net 35 | rules: 36 | - apiGroups: 37 | - '' 38 | resources: 39 | - pods 40 | - namespaces 41 | - nodes 42 | verbs: 43 | - get 44 | - list 45 | - watch 46 | - apiGroups: 47 | - networking.k8s.io 48 | resources: 49 | - networkpolicies 50 | verbs: 51 | - get 52 | - list 53 | - watch 54 | - apiGroups: 55 | - '' 56 | resources: 57 | - nodes/status 58 | verbs: 59 | - patch 60 | - update 61 | - apiVersion: rbac.authorization.k8s.io/v1 62 | kind: ClusterRoleBinding 63 | metadata: 64 | name: weave-net 65 | annotations: 66 | cloud.weave.works/launcher-info: |- 67 | { 68 | "original-request": { 69 | "url": "/k8s/v1.16/net.yaml?k8s-version=v1.19.1", 70 | "date": "Thu Oct 01 2020 17:42:18 GMT+0000 (UTC)" 71 | }, 72 | "email-address": "support@weave.works" 73 | } 74 | labels: 75 | name: weave-net 76 | roleRef: 77 | kind: ClusterRole 78 | name: weave-net 79 | apiGroup: rbac.authorization.k8s.io 80 | subjects: 81 | - kind: ServiceAccount 82 | name: weave-net 83 | namespace: kube-system 84 | - apiVersion: rbac.authorization.k8s.io/v1 85 | kind: Role 86 | metadata: 87 | name: weave-net 88 | annotations: 89 | cloud.weave.works/launcher-info: |- 90 | { 91 | "original-request": { 92 | "url": "/k8s/v1.16/net.yaml?k8s-version=v1.19.1", 93 | "date": "Thu Oct 01 2020 17:42:18 GMT+0000 (UTC)" 94 | }, 95 | "email-address": "support@weave.works" 96 | } 97 | labels: 98 | name: weave-net 99 | namespace: kube-system 100 | rules: 101 | - apiGroups: 102 | - '' 103 | resourceNames: 104 | - weave-net 105 | resources: 106 | - configmaps 107 | verbs: 108 | - get 109 | - update 110 | - apiGroups: 111 | - '' 112 | resources: 113 | - configmaps 114 | verbs: 115 | - create 116 | - apiVersion: rbac.authorization.k8s.io/v1 117 | kind: RoleBinding 118 | metadata: 119 | name: weave-net 120 | annotations: 121 | cloud.weave.works/launcher-info: |- 122 | { 123 | "original-request": { 124 | "url": "/k8s/v1.16/net.yaml?k8s-version=v1.19.1", 125 | "date": "Thu Oct 01 2020 17:42:18 GMT+0000 (UTC)" 126 | }, 127 | "email-address": "support@weave.works" 128 | } 129 | labels: 130 | name: weave-net 131 | namespace: kube-system 132 | roleRef: 133 | kind: Role 134 | name: weave-net 135 | apiGroup: rbac.authorization.k8s.io 136 | subjects: 137 | - kind: ServiceAccount 138 | name: weave-net 139 | namespace: kube-system 140 | - apiVersion: apps/v1 141 | kind: DaemonSet 142 | metadata: 143 | name: weave-net 144 | annotations: 145 | cloud.weave.works/launcher-info: |- 146 | { 147 | "original-request": { 148 | "url": "/k8s/v1.16/net.yaml?k8s-version=v1.19.1", 149 | "date": "Thu Oct 01 2020 17:42:18 GMT+0000 (UTC)" 150 | }, 151 | "email-address": "support@weave.works" 152 | } 153 | labels: 154 | name: weave-net 155 | namespace: kube-system 156 | spec: 157 | minReadySeconds: 5 158 | selector: 159 | matchLabels: 160 | name: weave-net 161 | template: 162 | metadata: 163 | labels: 164 | name: weave-net 165 | spec: 166 | containers: 167 | - name: weave 168 | command: 169 | - /home/weave/launch.sh 170 | env: 171 | - name: HOSTNAME 172 | valueFrom: 173 | fieldRef: 174 | apiVersion: v1 175 | fieldPath: spec.nodeName 176 | image: 'docker.io/weaveworks/weave-kube:2.7.0' 177 | readinessProbe: 178 | httpGet: 179 | host: 127.0.0.1 180 | path: /status 181 | port: 6784 182 | resources: 183 | requests: 184 | cpu: 50m 185 | memory: 100Mi 186 | securityContext: 187 | privileged: true 188 | volumeMounts: 189 | - name: weavedb 190 | mountPath: /weavedb 191 | - name: cni-bin 192 | mountPath: /host/opt 193 | - name: cni-bin2 194 | mountPath: /host/home 195 | - name: cni-conf 196 | mountPath: /host/etc 197 | - name: dbus 198 | mountPath: /host/var/lib/dbus 199 | - name: lib-modules 200 | mountPath: /lib/modules 201 | - name: xtables-lock 202 | mountPath: /run/xtables.lock 203 | - name: weave-npc 204 | env: 205 | - name: HOSTNAME 206 | valueFrom: 207 | fieldRef: 208 | apiVersion: v1 209 | fieldPath: spec.nodeName 210 | image: 'docker.io/weaveworks/weave-npc:2.7.0' 211 | resources: 212 | requests: 213 | cpu: 50m 214 | memory: 100Mi 215 | securityContext: 216 | privileged: true 217 | volumeMounts: 218 | - name: xtables-lock 219 | mountPath: /run/xtables.lock 220 | dnsPolicy: ClusterFirstWithHostNet 221 | hostNetwork: true 222 | hostPID: true 223 | priorityClassName: system-node-critical 224 | restartPolicy: Always 225 | securityContext: 226 | seLinuxOptions: {} 227 | serviceAccountName: weave-net 228 | tolerations: 229 | - effect: NoSchedule 230 | operator: Exists 231 | - effect: NoExecute 232 | operator: Exists 233 | volumes: 234 | - name: weavedb 235 | hostPath: 236 | path: /var/lib/weave 237 | - name: cni-bin 238 | hostPath: 239 | path: /opt 240 | - name: cni-bin2 241 | hostPath: 242 | path: /home 243 | - name: cni-conf 244 | hostPath: 245 | path: /etc 246 | - name: dbus 247 | hostPath: 248 | path: /var/lib/dbus 249 | - name: lib-modules 250 | hostPath: 251 | path: /lib/modules 252 | - name: xtables-lock 253 | hostPath: 254 | path: /run/xtables.lock 255 | type: FileOrCreate 256 | updateStrategy: 257 | type: RollingUpdate 258 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /diagrams/k8s-guide.drawio: -------------------------------------------------------------------------------- 1 | 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 --------------------------------------------------------------------------------