---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: cilium
  namespace: kube-system
  labels:
    k8s-app: cilium
spec:
  selector:
    matchLabels:
      k8s-app: cilium
  updateStrategy:
    rollingUpdate:
      # Specifies the maximum number of Pods that can be unavailable during the update process.
      maxUnavailable: 2
    type: RollingUpdate
  template:
    metadata:
      annotations:
{% if cilium_enable_prometheus %}
        prometheus.io/port: "{{ cilium_agent_scrape_port }}"
        prometheus.io/scrape: "true"
{% endif %}
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]'
      labels:
        k8s-app: cilium
    spec:
      containers:
      - name: cilium-agent
        image: "{{ cilium_image_repo }}:{{ cilium_image_tag }}"
        imagePullPolicy: {{ k8s_image_pull_policy }}
        command:
        - cilium-agent
        args:
        - --config-dir=/tmp/cilium/config-map
{% if cilium_mtu != "" %}
        - --mtu={{ cilium_mtu }}
{% endif %}
{% if cilium_agent_custom_args is string %}
        - {{ cilium_agent_custom_args }}
{% else %}
{% for flag in cilium_agent_custom_args %}
        - {{ flag }}
{% endfor %}
{% endif %}
        startupProbe:
          httpGet:
            host: '127.0.0.1'
            path: /healthz
            port: {{ cilium_agent_health_port }}
            scheme: HTTP
            httpHeaders:
            - name: "brief"
              value: "true"
          failureThreshold: 105
          periodSeconds: 2
          successThreshold: 1
        livenessProbe:
          httpGet:
            host: '127.0.0.1'
            path: /healthz
            port: {{ cilium_agent_health_port }}
            scheme: HTTP
            httpHeaders:
            - name: "brief"
              value: "true"
          failureThreshold: 10
          periodSeconds: 30
          successThreshold: 1
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: {{ cilium_agent_health_port }}
            scheme: HTTP
            httpHeaders:
            - name: "brief"
              value: "true"
          initialDelaySeconds: 5
          periodSeconds: 30
          successThreshold: 1
          failureThreshold: 3
          timeoutSeconds: 5
        env:
        - name: K8S_NODE_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: spec.nodeName
        - name: CILIUM_K8S_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        - name: CILIUM_CLUSTERMESH_CONFIG
          value: /var/lib/cilium/clustermesh/
{% if cilium_kube_proxy_replacement == 'strict' %}
        - name: KUBERNETES_SERVICE_HOST
          value: "{{ kube_apiserver_global_endpoint | urlsplit('hostname') }}"
        - name: KUBERNETES_SERVICE_PORT
          value: "{{ kube_apiserver_global_endpoint | urlsplit('port') }}"
{% endif %}
{% for env_var in cilium_agent_extra_env_vars %}
        - {{ env_var | to_nice_yaml(indent=2) | indent(10) }}
{% endfor %}
        lifecycle:
{% if cilium_version | regex_replace('v') is version('1.14', '<') %}
          postStart:
            exec:
              command:
              - "/cni-install.sh"
              - "--cni-exclusive={{ cilium_cni_exclusive | string | lower }}"
{% if cilium_version | regex_replace('v') is version('1.12', '>=') %}
              - "--enable-debug={{ cilium_debug | string | lower }}"
              - "--log-file={{ cilium_cni_log_file }}"
{% endif %}
{% endif %}
          preStop:
            exec:
              command:
              - /cni-uninstall.sh
        resources:
          limits:
            cpu: {{ cilium_cpu_limit }}
            memory: {{ cilium_memory_limit }}
          requests:
            cpu: {{ cilium_cpu_requests }}
            memory: {{ cilium_memory_requests }}
{% if cilium_enable_prometheus or cilium_enable_hubble_metrics %}
        ports:
{% endif %}
{% if cilium_enable_prometheus %}
        - name: prometheus
          containerPort: {{ cilium_agent_scrape_port }}
          hostPort: {{ cilium_agent_scrape_port }}
          protocol: TCP
{% endif %}
{% if cilium_enable_hubble_metrics %}
        - name: hubble-metrics
          containerPort: {{ cilium_hubble_scrape_port }}
          hostPort: {{ cilium_hubble_scrape_port }}
          protocol: TCP
{% endif %}
        securityContext:
          privileged: true
        volumeMounts:
        - name: bpf-maps
          mountPath: /sys/fs/bpf
          mountPropagation: Bidirectional
        - name: cilium-run
          mountPath: /var/run/cilium
{% if cilium_version | regex_replace('v') is version('1.13.1', '<') %}
        - name: cni-path
          mountPath: /host/opt/cni/bin
{% endif %}
        - name: etc-cni-netd
          mountPath: /host/etc/cni/net.d
{% if cilium_identity_allocation_mode == "kvstore" %}
        - name: etcd-config-path
          mountPath: /var/lib/etcd-config
          readOnly: true
        - name: etcd-secrets
          mountPath: "{{ cilium_cert_dir }}"
          readOnly: true
{% endif %}
        - name: clustermesh-secrets
          mountPath: /var/lib/cilium/clustermesh
          readOnly: true
        - name: cilium-config-path
          mountPath: /tmp/cilium/config-map
          readOnly: true
{% if cilium_ip_masq_agent_enable %}
        - name: ip-masq-agent
          mountPath: /etc/config
          readOnly: true
{% endif %}
          # Needed to be able to load kernel modules
        - name: lib-modules
          mountPath: /lib/modules
          readOnly: true
        - name: xtables-lock
          mountPath: /run/xtables.lock
{% if cilium_encryption_enabled and cilium_encryption_type == "ipsec" %}
        - name: cilium-ipsec-secrets
          mountPath: /etc/ipsec
          readOnly: true
{% endif %}
{% if cilium_hubble_install %}
        - name: hubble-tls
          mountPath: /var/lib/cilium/tls/hubble
          readOnly: true
{% endif %}
{% for volume_mount in cilium_agent_extra_volume_mounts %}
        - {{ volume_mount | to_nice_yaml(indent=2) | indent(10) }}
{% endfor %}
# In managed etcd mode, Cilium must be able to resolve the DNS name of the etcd service
{% if cilium_identity_allocation_mode == "kvstore" %}
      dnsPolicy: ClusterFirstWithHostNet
{% endif %}
      hostNetwork: true
      initContainers:
{% if cilium_version | regex_replace('v') is version('1.11', '>=') and cilium_cgroup_auto_mount %}
      - name: mount-cgroup
        image: "{{ cilium_image_repo }}:{{ cilium_image_tag }}"
        imagePullPolicy: {{ k8s_image_pull_policy }}
        env:
        - name: CGROUP_ROOT
          value: {{ cilium_cgroup_host_root }}
        - name: BIN_PATH
          value: /opt/cni/bin
        command:
        - sh
        - -ec
        # The statically linked Go program binary is invoked to avoid any
        # dependency on utilities like sh and mount that can be missing on certain
        # distros installed on the underlying host. Copy the binary to the
        # same directory where we install cilium cni plugin so that exec permissions
        # are available.
        - |
          cp /usr/bin/cilium-mount /hostbin/cilium-mount;
          nsenter --cgroup=/hostproc/1/ns/cgroup --mount=/hostproc/1/ns/mnt "${BIN_PATH}/cilium-mount" $CGROUP_ROOT;
          rm /hostbin/cilium-mount
        volumeMounts:
        - name: hostproc
          mountPath: /hostproc
        - name: cni-path
          mountPath: /hostbin
        securityContext:
          privileged: true
{% endif %}
{% if cilium_version | regex_replace('v') is version('1.11.7', '>=') %}
      - name: apply-sysctl-overwrites
        image: "{{ cilium_image_repo }}:{{ cilium_image_tag }}"
        imagePullPolicy: {{ k8s_image_pull_policy }}
        env:
        - name: BIN_PATH
          value: /opt/cni/bin
        command:
        - sh
        - -ec
        # The statically linked Go program binary is invoked to avoid any
        # dependency on utilities like sh that can be missing on certain
        # distros installed on the underlying host. Copy the binary to the
        # same directory where we install cilium cni plugin so that exec permissions
        # are available.
        - |
          cp /usr/bin/cilium-sysctlfix /hostbin/cilium-sysctlfix;
          nsenter --mount=/hostproc/1/ns/mnt "${BIN_PATH}/cilium-sysctlfix";
          rm /hostbin/cilium-sysctlfix
        volumeMounts:
        - name: hostproc
          mountPath: /hostproc
        - name: cni-path
          mountPath: /hostbin
        securityContext:
          privileged: true
{% endif %}
      - name: clean-cilium-state
        image: "{{ cilium_image_repo }}:{{ cilium_image_tag }}"
        imagePullPolicy: {{ k8s_image_pull_policy }}
        command:
        - /init-container.sh
        env:
        - name: CILIUM_ALL_STATE
          valueFrom:
            configMapKeyRef:
              name: cilium-config
              key: clean-cilium-state
              optional: true
        - name: CILIUM_BPF_STATE
          valueFrom:
            configMapKeyRef:
              name: cilium-config
              key: clean-cilium-bpf-state
              optional: true
# Removed in 1.11 and up.
# https://github.com/cilium/cilium/commit/f7a3f59fd74983c600bfce9cac364b76d20849d9
{% if cilium_version | regex_replace('v') is version('1.11', '<') %}
        - name: CILIUM_WAIT_BPF_MOUNT
          valueFrom:
            configMapKeyRef:
              key: wait-bpf-mount
              name: cilium-config
              optional: true
{% endif %}
{% if cilium_kube_proxy_replacement == 'strict' %}
        - name: KUBERNETES_SERVICE_HOST
          value: "{{ kube_apiserver_global_endpoint | urlsplit('hostname') }}"
        - name: KUBERNETES_SERVICE_PORT
          value: "{{ kube_apiserver_global_endpoint | urlsplit('port') }}"
{% endif %}
        securityContext:
          privileged: true
        volumeMounts:
        - name: bpf-maps
          mountPath: /sys/fs/bpf
{% if cilium_version | regex_replace('v') is version('1.11', '>=') %}
          # Required to mount cgroup filesystem from the host to cilium agent pod
        - name: cilium-cgroup
          mountPath: {{ cilium_cgroup_host_root }}
          mountPropagation: HostToContainer
{% endif %}
        - name: cilium-run
          mountPath: /var/run/cilium
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
{% if cilium_version | regex_replace('v') is version('1.13.1', '>=') %}
      # Install the CNI binaries in an InitContainer so we don't have a writable host mount in the agent
      - name: install-cni-binaries
        image: "{{ cilium_image_repo }}:{{ cilium_image_tag }}"
        imagePullPolicy: {{ k8s_image_pull_policy }}
        command:
          - "/install-plugin.sh"
        resources:
          requests:
            cpu: 100m
            memory: 10Mi
        securityContext:
          privileged: true
        terminationMessagePolicy: FallbackToLogsOnError
        volumeMounts:
          - name: cni-path
            mountPath: /host/opt/cni/bin
{% endif %}
      restartPolicy: Always
      priorityClassName: system-node-critical
      serviceAccount: cilium
      serviceAccountName: cilium
      terminationGracePeriodSeconds: 1
      hostNetwork: true
# In managed etcd mode, Cilium must be able to resolve the DNS name of the etcd service
{% if cilium_identity_allocation_mode == "kvstore" %}
      dnsPolicy: ClusterFirstWithHostNet
{% endif %}
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: kubernetes.io/hostname
            labelSelector:
              matchLabels:
                k8s-app: cilium
      tolerations:
      - operator: Exists
      volumes:
        # To keep state between restarts / upgrades
      - name: cilium-run
        hostPath:
          path: /var/run/cilium
          type: DirectoryOrCreate
        # To keep state between restarts / upgrades for bpf maps
      - name: bpf-maps
        hostPath:
          path: /sys/fs/bpf
          type: DirectoryOrCreate
{% if cilium_version | regex_replace('v') is version('1.11', '>=') %}
      # To mount cgroup2 filesystem on the host
      - name: hostproc
        hostPath:
          path: /proc
          type: Directory
      # To keep state between restarts / upgrades for cgroup2 filesystem
      - name: cilium-cgroup
        hostPath:
          path: {{ cilium_cgroup_host_root }}
          type: DirectoryOrCreate
{% endif %}
        # To install cilium cni plugin in the host
      - name: cni-path
        hostPath:
          path: /opt/cni/bin
          type: DirectoryOrCreate
        # To install cilium cni configuration in the host
      - name: etc-cni-netd
        hostPath:
          path: /etc/cni/net.d
          type: DirectoryOrCreate
        # To be able to load kernel modules
      - name: lib-modules
        hostPath:
          path: /lib/modules
        # To access iptables concurrently with other processes (e.g. kube-proxy)
      - name: xtables-lock
        hostPath:
          path: /run/xtables.lock
          type: FileOrCreate
{% if cilium_identity_allocation_mode == "kvstore" %}
        # To read the etcd config stored in config maps
      - name: etcd-config-path
        configMap:
          name: cilium-config
          # note: the leading zero means this number is in octal representation: do not remove it
          defaultMode: 0400
          items:
          - key: etcd-config
            path: etcd.config
        # To read the k8s etcd secrets in case the user might want to use TLS
      - name: etcd-secrets
        hostPath:
          path: "{{ cilium_cert_dir }}"
{% endif %}
        # To read the clustermesh configuration
      - name: clustermesh-secrets
        secret:
          secretName: cilium-clustermesh
          # note: the leading zero means this number is in octal representation: do not remove it
          defaultMode: 0400
          optional: true
        # To read the configuration from the config map
      - name: cilium-config-path
        configMap:
          name: cilium-config
{% if cilium_ip_masq_agent_enable %}
      - name: ip-masq-agent
        configMap:
          name: ip-masq-agent
          optional: true
          items:
          - key: config
            path: ip-masq-agent
{% endif %}
{% if cilium_encryption_enabled and cilium_encryption_type == "ipsec" %}
      - name: cilium-ipsec-secrets
        secret:
          secretName: cilium-ipsec-keys
{% endif %}
{% if cilium_hubble_install %}
      - name: hubble-tls
        projected:
          # note: the leading zero means this number is in octal representation: do not remove it
          defaultMode: 0400
          sources:
          - secret:
              name: hubble-server-certs
              optional: true
              items:
                - key: ca.crt
                  path: client-ca.crt
                - key: tls.crt
                  path: server.crt
                - key: tls.key
                  path: server.key
{% endif %}
