From 998d1dcb70cb97cee3636877cc68cb296cdc32b6 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Fri, 16 Aug 2024 11:12:54 +0100 Subject: [PATCH] Add initial example with Kubernetes (#21) * Add initial example with Kubernetes This commit adds an example for container migration in Kubernetes cluster. This example consists of several components: - `http-server`: an HTTP server that responds with the hostname and IP address of the container it is currently running into. - `local-registry`: a set of scripts for setting up a local container registry that can be used to distribute container checkpoints across cluster nodes. - `build-image`: a script building an OCI container image from checkpoint tar archive - `kubectl-plugin`: a plugin introducing a `checkpoint` command to kubectl - `manifests`: yaml files for deploying the HTTP server example and kube-router - `cni`: a cni configuration for kube-router Signed-off-by: Radostin Stoyanov * local-registry: add predefined folders The shell scripts for generating certificates, password and running a local registry assume that "auth/", "certs/", and "data/" directories exist. Signed-off-by: Radostin Stoyanov * local-registry: enable support for ubuntu/fedora Installing root CA certificate requires different commands on different Linux distributions. This patch updates the script to support Ubuntu in addition to Fedora/RHEL. Signed-off-by: Radostin Stoyanov * Use fully-qualified container image references It is highly recommended to always use fully-qualified image references as short-name aliases can create ambiguity. Signed-off-by: Radostin Stoyanov * readme: use sudo when running commands as root Signed-off-by: Radostin Stoyanov --------- Signed-off-by: Radostin Stoyanov Co-authored-by: Stanislav Kosorin --- .../README.md | 102 +++++++++++++ .../build-image/ANNOTATIONS_FILE.template | 1 + .../build-image/build-image.sh | 78 ++++++++++ .../cni/10-kuberouter.conf | 10 ++ .../http-server/Dockerfile | 8 ++ .../http-server/README.md | 27 ++++ .../http-server/main.py | 118 +++++++++++++++ .../http-server/send_request.sh | 6 + .../kubectl-plugin/kubectl-checkpoint | 21 +++ .../local-registry/.gitignore | 3 + .../local-registry/auth/.keep | 0 .../local-registry/certs/.keep | 0 .../local-registry/data/.keep | 0 .../local-registry/generate-certificates.sh | 53 +++++++ .../local-registry/generate-password.sh | 25 ++++ .../local-registry/run.sh | 20 +++ .../local-registry/trust-certificates.sh | 29 ++++ .../manifests/http-server-deployment.yaml | 22 +++ .../manifests/http-server-service.yaml | 13 ++ .../manifests/kube-router-daemonset.yaml | 136 ++++++++++++++++++ 20 files changed, 672 insertions(+) create mode 100644 examples/container_migration_in_kubernetes/README.md create mode 100644 examples/container_migration_in_kubernetes/build-image/ANNOTATIONS_FILE.template create mode 100755 examples/container_migration_in_kubernetes/build-image/build-image.sh create mode 100644 examples/container_migration_in_kubernetes/cni/10-kuberouter.conf create mode 100644 examples/container_migration_in_kubernetes/http-server/Dockerfile create mode 100644 examples/container_migration_in_kubernetes/http-server/README.md create mode 100755 examples/container_migration_in_kubernetes/http-server/main.py create mode 100755 examples/container_migration_in_kubernetes/http-server/send_request.sh create mode 100755 examples/container_migration_in_kubernetes/kubectl-plugin/kubectl-checkpoint create mode 100644 examples/container_migration_in_kubernetes/local-registry/.gitignore create mode 100644 examples/container_migration_in_kubernetes/local-registry/auth/.keep create mode 100644 examples/container_migration_in_kubernetes/local-registry/certs/.keep create mode 100644 examples/container_migration_in_kubernetes/local-registry/data/.keep create mode 100755 examples/container_migration_in_kubernetes/local-registry/generate-certificates.sh create mode 100755 examples/container_migration_in_kubernetes/local-registry/generate-password.sh create mode 100755 examples/container_migration_in_kubernetes/local-registry/run.sh create mode 100755 examples/container_migration_in_kubernetes/local-registry/trust-certificates.sh create mode 100644 examples/container_migration_in_kubernetes/manifests/http-server-deployment.yaml create mode 100644 examples/container_migration_in_kubernetes/manifests/http-server-service.yaml create mode 100644 examples/container_migration_in_kubernetes/manifests/kube-router-daemonset.yaml diff --git a/examples/container_migration_in_kubernetes/README.md b/examples/container_migration_in_kubernetes/README.md new file mode 100644 index 0000000..e2ba72c --- /dev/null +++ b/examples/container_migration_in_kubernetes/README.md @@ -0,0 +1,102 @@ +# Container migration in Kubernetes + +In this example, we have HTTP server running in a Kubernetes Pod where a BMv2 +switch is used for traffic load balancing to dynamically reroutes packets to +the correct IP address after container migration. + +This example assumes that the Kubernenes cluster has been configured with +recent version of CRI-O that supports container checkpointing, and Kubelet +Checkpoint API has been enabled. To learn more about the container +checkpointing feature in Kubernetes, please refer to the following pages: + + - https://kubernetes.io/blog/2022/12/05/forensic-container-checkpointing-alpha/ + - https://kubernetes.io/docs/reference/node/kubelet-checkpoint-api/ + +## Running the example + +1. Install CNI Plugins on each node + +The CNI configuration file is expected to be present as `/etc/cni/net.d/10-kuberouter.conf` +``` +sudo mkdir -p /etc/cni/net.d/ +sudo cp cni/10-kuberouter.conf /etc/cni/net.d/ +``` + +Install `bridge` CNI plugin and `host-local` IP address management plugin: + +``` +git clone https://github.com/containernetworking/plugins +cd plugins +git checkout v1.1.1 + +./build_linux.sh + +sudo mkdir -p /opt/cni/bin +sudo cp bin/* /opt/cni/bin/ +``` + +2. Deploy daemonset +``` +kubectl apply -f manifests/kube-router-daemonset.yaml +``` + +3. Setup a local container registry + +``` +cd local-registry/ +./generate-password.sh +./generate-certificates.sh +./trust-certificates.sh +./run.sh + +buildah login :5000 +``` + +3. Deploy an HTTP server + +``` +kubectl apply -f manifests/http-server-deployment.yaml +kubectl apply -f manifests/http-server-service.yaml + +# Check the status of the deployment +kubectl get deployments + +# Check the assigned IP address +kubectl get service http-server +``` + +4. Install kubectl checkpoint plugin + +``` +sudo cp kubectl-plugin/kubectl-checkpoint /usr/local/bin/ +``` + +5. Enable checkpoint/restore with established TCP connections +``` +sudo mkdir -p /etc/criu/ +echo "tcp-established" | sudo tee -a /etc/criu/runc.conf +``` + +6. Create container checkpoint + +``` +kubectl checkpoint +``` + +7. Build a checkpoint OCI image and push to registry + +``` +build-image/build-image.sh -a -c -i :5000/: + +buildah push :5000/: +``` + +7. Restore container from checkpoint image + +Replace the container `image` filed in `http-server-deployment.yaml` with the +checkpoint OCI image `:5000/:` and apply the new deployment. + +``` +kubectl apply -f manifests/http-server-deployment.yaml +``` + diff --git a/examples/container_migration_in_kubernetes/build-image/ANNOTATIONS_FILE.template b/examples/container_migration_in_kubernetes/build-image/ANNOTATIONS_FILE.template new file mode 100644 index 0000000..09fb1a1 --- /dev/null +++ b/examples/container_migration_in_kubernetes/build-image/ANNOTATIONS_FILE.template @@ -0,0 +1 @@ +io.kubernetes.cri-o.annotations.checkpoint.name= diff --git a/examples/container_migration_in_kubernetes/build-image/build-image.sh b/examples/container_migration_in_kubernetes/build-image/build-image.sh new file mode 100755 index 0000000..35080a2 --- /dev/null +++ b/examples/container_migration_in_kubernetes/build-image/build-image.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +set -euo pipefail + +usage() { + cat </dev/null; then + echo "buildah is not installed. Please install buildah before running 'checkpointctl build' command." + exit 1 +fi + +if [[ ! -f $annotationsFilePath ]]; then + echo "Annotations file not found: $annotationsFilePath" + exit 1 +fi + +if [[ ! -f $checkpointPath ]]; then + echo "Checkpoint file not found: $checkpointPath" + exit 1 +fi + +newcontainer=$(buildah from scratch) + +buildah add "$newcontainer" "$checkpointPath" + +while IFS= read -r line; do + key=$(echo "$line" | cut -d '=' -f 1) + value=$(echo "$line" | cut -d '=' -f 2-) + buildah config --annotation "$key=$value" "$newcontainer" +done <"$annotationsFilePath" + +buildah commit "$newcontainer" "$imageName" + +buildah rm "$newcontainer" + +echo "Checkpoint image created successfully: $imageName" diff --git a/examples/container_migration_in_kubernetes/cni/10-kuberouter.conf b/examples/container_migration_in_kubernetes/cni/10-kuberouter.conf new file mode 100644 index 0000000..09f6e22 --- /dev/null +++ b/examples/container_migration_in_kubernetes/cni/10-kuberouter.conf @@ -0,0 +1,10 @@ +{ + "cniVersion": "0.3.0", + "name":"mynet", + "type":"bridge", + "bridge":"kube-bridge", + "isDefaultGateway":true, + "ipam": { + "type":"host-local" + } +} diff --git a/examples/container_migration_in_kubernetes/http-server/Dockerfile b/examples/container_migration_in_kubernetes/http-server/Dockerfile new file mode 100644 index 0000000..11ce7ed --- /dev/null +++ b/examples/container_migration_in_kubernetes/http-server/Dockerfile @@ -0,0 +1,8 @@ +FROM docker.io/library/python:3.11-slim + +WORKDIR /app +COPY main.py /app/ +EXPOSE 12345 + +CMD ["python3", "main.py"] + diff --git a/examples/container_migration_in_kubernetes/http-server/README.md b/examples/container_migration_in_kubernetes/http-server/README.md new file mode 100644 index 0000000..ce5b987 --- /dev/null +++ b/examples/container_migration_in_kubernetes/http-server/README.md @@ -0,0 +1,27 @@ +# Simple HTTP Server with Request Counter + +This Python program implements a simple HTTP server that keeps track of the +number of GET requests it has received. Each client receives an initial +response that includes the request count, server hostname, and IP address. +After the initial response, the server sends a dot (`.`) every second for 10 +seconds. + +## Usage + +1. Run server + +By default, the server listens on port 12345. To specify a different port, use +the `-p` option: + +``` +python3 main.py -p +``` + +2. Send an HTTP request + +You can use any HTTP client to make a GET request to the server. The following +script uses `curl` with the default port number: + +``` +./send_request.sh +``` diff --git a/examples/container_migration_in_kubernetes/http-server/main.py b/examples/container_migration_in_kubernetes/http-server/main.py new file mode 100755 index 0000000..3d758f6 --- /dev/null +++ b/examples/container_migration_in_kubernetes/http-server/main.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import argparse +import logging +import socket +import time +from http.server import BaseHTTPRequestHandler, HTTPServer + +# Initialize counter +counter = 0 + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s' +) + + +class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): + def do_GET(self): + global counter + # Increment the counter + counter += 1 + # Log the current count + logging.info(f"Request count: {counter}") + + # Determine the hostname and IP address + hostname = socket.gethostname() + ip_address = socket.gethostbyname(hostname) + + # Respond with the initial headers + self.send_response(200) + self.send_header("Content-type", "text/plain") + # Indicate that the connection should be kept alive + self.send_header("Connection", "keep-alive") + # Use chunked transfer encoding + self.send_header("Transfer-Encoding", "chunked") + self.end_headers() + + # Send the initial message with the counter, hostname, and IP address + message_str = ( + f"Request [{counter}]: " + f"Hostname: {hostname}, " + f"IP Address: {ip_address}\n" + ) + initial_message = message_str.encode('utf-8') + + self.send_chunk(initial_message) + + # Send a dot every second for 10 seconds + self.send_dots_for_duration(10) + + def send_chunk(self, data): + """Send a chunk of data.""" + try: + self.wfile.write(f"{len(data):X}\r\n".encode('utf-8')) + self.wfile.write(data) + # End of the chunk + self.wfile.write(b"\r\n") + # Ensure the data is sent immediately + self.wfile.flush() + except ConnectionResetError as e: + logging.warning("Connection reset by peer: %s", e) + raise + except BrokenPipeError as e: + logging.warning("Error while sending data: %s", e) + raise + except Exception as e: + logging.error("Unexpected error: %s", e) + raise + + def send_dots_for_duration(self, duration): + """Send a dot every second for the given duration.""" + end_time = time.time() + duration + while time.time() < end_time: + # Send a dot as a separate chunk + dot = b"." + try: + self.send_chunk(dot) + except (ConnectionResetError, BrokenPipeError) as e: + logging.warning("Connection error: %s", e) + break + except Exception as e: + logging.error("Unexpected error: %s", e) + break + # Wait for 1 second before sending another chunk + time.sleep(1) + else: + # Send an empty chunk to indicate the end of the response + try: + self.send_chunk(b"") + except (ConnectionResetError, BrokenPipeError) as e: + logging.warning("Error while sending end of response: %s", e) + except Exception as e: + logging.error("Unexpected error: %s", e) + + +def run( + server_class=HTTPServer, + handler_class=SimpleHTTPRequestHandler, + port=12345 +): + server_address = ('', port) + httpd = server_class(server_address, handler_class) + logging.info(f'Starting HTTP server on port {port}...') + httpd.serve_forever() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="A simple HTTP server with a request counter" + ) + parser.add_argument( + '-p', '--port', type=int, default=12345, + help='Port number to run the server on (default: 12345)' + ) + args = parser.parse_args() + run(port=args.port) diff --git a/examples/container_migration_in_kubernetes/http-server/send_request.sh b/examples/container_migration_in_kubernetes/http-server/send_request.sh new file mode 100755 index 0000000..abac31f --- /dev/null +++ b/examples/container_migration_in_kubernetes/http-server/send_request.sh @@ -0,0 +1,6 @@ +#!/usr/bin/sh + +# The -N option ensures that curl does not buffer the output and +# you should see the data as it is received from the server in real-time. +curl -N http://localhost:12345 + diff --git a/examples/container_migration_in_kubernetes/kubectl-plugin/kubectl-checkpoint b/examples/container_migration_in_kubernetes/kubectl-plugin/kubectl-checkpoint new file mode 100755 index 0000000..568bbaa --- /dev/null +++ b/examples/container_migration_in_kubernetes/kubectl-plugin/kubectl-checkpoint @@ -0,0 +1,21 @@ +#!/bin/bash + +HOST="$1" +POD="$2" +CTR="$3" + +if [ "$#" -eq 2 ]; then + HOST=localhost + POD="$1" + CTR="$2" +elif [ "$#" -ne 3 ]; then + echo "Usage: $(basename $0) " + exit 1 +fi + +curl --insecure \ + --cert /var/lib/kubelet/pki/kubelet-client-current.pem \ + --key /var/lib/kubelet/pki/kubelet-client-current.pem \ + -X POST \ + "https://${HOST}:10250/checkpoint/default/${POD}/${CTR}" + diff --git a/examples/container_migration_in_kubernetes/local-registry/.gitignore b/examples/container_migration_in_kubernetes/local-registry/.gitignore new file mode 100644 index 0000000..0f12f3b --- /dev/null +++ b/examples/container_migration_in_kubernetes/local-registry/.gitignore @@ -0,0 +1,3 @@ +auth/* +certs/* +data/* diff --git a/examples/container_migration_in_kubernetes/local-registry/auth/.keep b/examples/container_migration_in_kubernetes/local-registry/auth/.keep new file mode 100644 index 0000000..e69de29 diff --git a/examples/container_migration_in_kubernetes/local-registry/certs/.keep b/examples/container_migration_in_kubernetes/local-registry/certs/.keep new file mode 100644 index 0000000..e69de29 diff --git a/examples/container_migration_in_kubernetes/local-registry/data/.keep b/examples/container_migration_in_kubernetes/local-registry/data/.keep new file mode 100644 index 0000000..e69de29 diff --git a/examples/container_migration_in_kubernetes/local-registry/generate-certificates.sh b/examples/container_migration_in_kubernetes/local-registry/generate-certificates.sh new file mode 100755 index 0000000..95e5d92 --- /dev/null +++ b/examples/container_migration_in_kubernetes/local-registry/generate-certificates.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 0 +fi + +# Generate a private key for the CAPermalink +openssl ecparam \ + -out certs/container-registry-root.key \ + -name prime256v1 \ + -genkey + +# Generate a certificate signing request for the CA +openssl req -new \ + -sha256 \ + -subj "/CN=$1" \ + -addext "subjectAltName = DNS:$1" \ + -key certs/container-registry-root.key \ + -out certs/container-registry-root.csr + +# Generate a root certificate +openssl x509 -req \ + -sha256 \ + -days 3650 \ + -in certs/container-registry-root.csr \ + -signkey certs/container-registry-root.key \ + -out certs/container-registry-root-CA.crt + +# Create a private key for the certificate +openssl ecparam \ + -out certs/container-registry-local.key \ + -name prime256v1 \ + -genkey + +# Create a certificate signing request for the server SSL +openssl req -new \ + -sha256 \ + -subj "/CN=$1" \ + -addext "subjectAltName = DNS:$1" \ + -key certs/container-registry-local.key \ + -out certs/container-registry-local.csr + +# Create a certificate and sign it with the CA private key +openssl x509 -req \ + -in certs/container-registry-local.csr \ + -CA certs/container-registry-root-CA.crt \ + -CAkey certs/container-registry-root.key \ + -out certs/container-registry-local.crt \ + -CAcreateserial \ + -days 3650 \ + -sha256 + diff --git a/examples/container_migration_in_kubernetes/local-registry/generate-password.sh b/examples/container_migration_in_kubernetes/local-registry/generate-password.sh new file mode 100755 index 0000000..e009b66 --- /dev/null +++ b/examples/container_migration_in_kubernetes/local-registry/generate-password.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Function to escape special characters +escape_string() { + printf '%q' "$1" +} + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +user=$1 + +# Read password securely +read -e -s -p "Enter password: " password +echo + +# Escape password to handle special characters +escaped_password=$(escape_string "$password") + +# Generate the password file using podman and htpasswd +podman pull docker.io/library/httpd:2 +podman run --entrypoint htpasswd httpd:2 -Bbn "$user" "$escaped_password" > auth/htpasswd + diff --git a/examples/container_migration_in_kubernetes/local-registry/run.sh b/examples/container_migration_in_kubernetes/local-registry/run.sh new file mode 100755 index 0000000..8795fb3 --- /dev/null +++ b/examples/container_migration_in_kubernetes/local-registry/run.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# See more examples at: +# - https://distribution.github.io/distribution/about/deploying/ +# - https://www.redhat.com/sysadmin/simple-container-registry + +sudo podman run -d \ + -p 5000:5000 \ + --restart=always \ + --name registry \ + -v "$(pwd)"/auth:/auth:z \ + -v "$(pwd)"/certs:/certs:z \ + -v "$(pwd)"/data:/var/lib/registry:z \ + -e "REGISTRY_AUTH=htpasswd" \ + -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ + -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ + -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/container-registry-local.crt \ + -e REGISTRY_HTTP_TLS_KEY=/certs/container-registry-local.key \ + -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \ + registry:2 diff --git a/examples/container_migration_in_kubernetes/local-registry/trust-certificates.sh b/examples/container_migration_in_kubernetes/local-registry/trust-certificates.sh new file mode 100755 index 0000000..9e7c212 --- /dev/null +++ b/examples/container_migration_in_kubernetes/local-registry/trust-certificates.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +if [ -f /etc/os-release ]; then + . /etc/os-release +else + echo "Cannot find /etc/os-release" + exit 1 +fi + +case "$ID" in + fedora|rhel) + sudo mkdir -p /etc/pki/ca-trust/source/anchors/ + sudo cp ./certs/container-registry-local.crt /etc/pki/ca-trust/source/anchors/ + sudo update-ca-trust + ;; + + ubuntu) + sudo mkdir -p /usr/local/share/ca-certificates + sudo cp ./certs/container-registry-local.crt /usr/local/share/ca-certificates/ + sudo update-ca-certificates + ;; + + *) + echo "Unsupported or unrecognized distribution: $ID" + exit 1 + ;; +esac + +exit 0 diff --git a/examples/container_migration_in_kubernetes/manifests/http-server-deployment.yaml b/examples/container_migration_in_kubernetes/manifests/http-server-deployment.yaml new file mode 100644 index 0000000..776eb10 --- /dev/null +++ b/examples/container_migration_in_kubernetes/manifests/http-server-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: http-server + labels: + app: http-server +spec: + replicas: 2 + selector: + matchLabels: + app: http-server + template: + metadata: + labels: + app: http-server + spec: + containers: + - name: http-server + image: quay.io/radostin/http-server:latest + ports: + - containerPort: 12345 + diff --git a/examples/container_migration_in_kubernetes/manifests/http-server-service.yaml b/examples/container_migration_in_kubernetes/manifests/http-server-service.yaml new file mode 100644 index 0000000..2ea1ef1 --- /dev/null +++ b/examples/container_migration_in_kubernetes/manifests/http-server-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: http-server +spec: + selector: + app: http-server + ports: + - protocol: TCP + port: 12345 + targetPort: 12345 + type: ClusterIP + diff --git a/examples/container_migration_in_kubernetes/manifests/kube-router-daemonset.yaml b/examples/container_migration_in_kubernetes/manifests/kube-router-daemonset.yaml new file mode 100644 index 0000000..563f7ad --- /dev/null +++ b/examples/container_migration_in_kubernetes/manifests/kube-router-daemonset.yaml @@ -0,0 +1,136 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: kube-router-cfg + namespace: kube-system + labels: + tier: node + k8s-app: kube-router +data: + cni-conf.json: | + { + "cniVersion":"0.3.0", + "name":"mynet", + "plugins":[ + { + "name":"kubernetes", + "type":"bridge", + "bridge":"kube-bridge", + "isDefaultGateway":true, + "ipam":{ + "type":"host-local" + } + } + ] + } +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kube-router + namespace: kube-system + labels: + k8s-app: kube-router +spec: + selector: + matchLabels: + k8s-app: kube-router + template: + metadata: + labels: + k8s-app: kube-router + spec: + priorityClassName: system-node-critical + containers: + - name: kube-router + image: docker.io/cloudnativelabs/kube-router + args: + - "--run-router=true" + - "--run-firewall=true" + - "--run-loadbalancer=true" + - "--run-service-proxy=true" + - "--bgp-graceful-restart=true" + - "--kubeconfig=/var/lib/kube-router/kubeconfig" + securityContext: + privileged: true + imagePullPolicy: Always + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: KUBE_ROUTER_CNI_CONF_FILE + value: /etc/cni/net.d/10-kuberouter.conflist + livenessProbe: + httpGet: + path: /healthz + port: 20244 + initialDelaySeconds: 10 + periodSeconds: 3 + volumeMounts: + - name: lib-modules + mountPath: /lib/modules + readOnly: true + - name: cni-conf-dir + mountPath: /etc/cni/net.d + - name: kubeconfig + mountPath: /var/lib/kube-router/kubeconfig + readOnly: true + - name: xtables-lock + mountPath: /run/xtables.lock + readOnly: false + initContainers: + - name: install-cni + image: docker.io/cloudnativelabs/kube-router + imagePullPolicy: Always + command: + - /bin/sh + - -c + - set -e -x; + if [ ! -f /etc/cni/net.d/10-kuberouter.conflist ]; then + if [ -f /etc/cni/net.d/*.conf ]; then + rm -f /etc/cni/net.d/*.conf; + fi; + TMP=/etc/cni/net.d/.tmp-kuberouter-cfg; + cp /etc/kube-router/cni-conf.json ${TMP}; + mv ${TMP} /etc/cni/net.d/10-kuberouter.conflist; + fi; + if [ -x /usr/local/bin/cni-install ]; then + /usr/local/bin/cni-install; + fi; + volumeMounts: + - name: cni-conf-dir + mountPath: /etc/cni/net.d + - name: kube-router-cfg + mountPath: /etc/kube-router + - name: host-opt + mountPath: /opt + hostNetwork: true + hostPID: true + tolerations: + - effect: NoSchedule + operator: Exists + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + volumes: + - name: lib-modules + hostPath: + path: /lib/modules + - name: cni-conf-dir + hostPath: + path: /etc/cni/net.d + - name: kube-router-cfg + configMap: + name: kube-router-cfg + - name: kubeconfig + hostPath: + path: /var/lib/kube-router/kubeconfig + - name: xtables-lock + hostPath: + path: /run/xtables.lock + type: FileOrCreate + - name: host-opt + hostPath: + path: /opt