├── .gitignore ├── handlers └── main.yml ├── molecule └── default │ ├── templates │ ├── serviceaccount.yml.j2 │ ├── encryption-config.yml.j2 │ ├── clusterrole.yml.j2 │ ├── clusterrolebinding.yml.j2 │ ├── service.yml.j2 │ ├── configmap.yml.j2 │ ├── values.yml.j2 │ └── deployment.yml.j2 │ ├── host_vars │ ├── test-etcd1.yml │ ├── test-etcd2.yml │ ├── test-etcd3.yml │ ├── test-worker2.yml │ ├── test-assets.yml │ ├── test-worker1.yml │ ├── test-controller1.yml │ ├── test-controller2.yml │ └── test-controller3.yml │ ├── group_vars │ ├── k8s.yml │ ├── k8s_etcd.yml │ └── all.yml │ ├── tasks │ ├── cilium_status.yml │ ├── coredns_status.yml │ ├── taint_controller_nodes.yml │ └── coredns.yml │ ├── converge.yml │ ├── verify.yml │ ├── molecule.yml │ └── prepare.yml ├── templates ├── cilium_values_default_pre_flight_check.yml.j2 ├── etcd-secrets.yml.j2 └── cilium_values_default.yml.j2 ├── .yamllint ├── files └── etc │ └── systemd │ └── system │ └── sys-fs-bpf.mount ├── meta └── main.yml ├── tasks ├── main.yml ├── helm_repository.yml ├── delete.yml ├── pre_flight_check.yml ├── template.yml ├── install.yml └── upgrade.yml ├── .github └── workflows │ └── release.yml ├── defaults └── main.yml ├── CHANGELOG.md ├── README.md └── LICENSES └── GPL-3.0-or-later.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2025 Robert Wimmer 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | 4 | molecule/kvm/.vagrant 5 | .vscode 6 | .ansible 7 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Reload systemd 6 | ansible.builtin.systemd: 7 | daemon_reload: true 8 | -------------------------------------------------------------------------------- /molecule/default/templates/serviceaccount.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: v1 6 | kind: ServiceAccount 7 | metadata: 8 | name: coredns 9 | namespace: kube-system 10 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-etcd1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.100/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.100" 9 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-etcd2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.110/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.110" 9 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-etcd3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.120/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.120" 9 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-worker2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.210/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.210" 9 | -------------------------------------------------------------------------------- /templates/cilium_values_default_pre_flight_check.yml.j2: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2025 Robert Wimmer 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | 4 | agent: false 5 | preflight: 6 | enabled: true 7 | tolerations: 8 | - operator: Exists 9 | operator: 10 | enabled: false 11 | -------------------------------------------------------------------------------- /molecule/default/group_vars/k8s.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | # Allow all traffic from the following networks. 6 | harden_linux_ufw_allow_networks: 7 | - "10.32.0.0/16" # Server Cluster IP range 8 | - "10.200.0.0/16" # Pod IP range 9 | - "10.10.10.0/24" # Wireguard IP range 10 | - "172.16.10.0/24" # VM IP range 11 | -------------------------------------------------------------------------------- /molecule/default/templates/encryption-config.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | kind: EncryptionConfiguration 6 | apiVersion: apiserver.config.k8s.io/v1 7 | resources: 8 | - resources: 9 | - secrets 10 | providers: 11 | - aescbc: 12 | keys: 13 | - name: key1 14 | secret: {{ k8s_encryption_config_key }} 15 | - identity: {} 16 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | extends: default 6 | 7 | rules: 8 | line-length: 9 | max: 150 10 | level: warning 11 | 12 | comments-indentation: disable 13 | comments: 14 | min-spaces-from-content: 1 15 | braces: 16 | min-spaces-inside: 0 17 | max-spaces-inside: 1 18 | octal-values: 19 | forbid-implicit-octal: true 20 | forbid-explicit-octal: true 21 | -------------------------------------------------------------------------------- /files/etc/systemd/system/sys-fs-bpf.mount: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2025 Robert Wimmer 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | 4 | [Unit] 5 | Description=Cilium BPF mounts 6 | Documentation=http://docs.cilium.io/ 7 | DefaultDependencies=no 8 | Before=local-fs.target umount.target 9 | After=swap.target 10 | 11 | [Mount] 12 | What=bpffs 13 | Where=/sys/fs/bpf 14 | Type=bpf 15 | Options=rw,nosuid,nodev,noexec,relatime,mode=700 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /molecule/default/group_vars/k8s_etcd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | # Open a few ports for ssh, Wireguard and etcd 6 | harden_linux_ufw_rules: 7 | - rule: "allow" 8 | to_port: "22" 9 | protocol: "tcp" 10 | - rule: "allow" 11 | to_port: "51820" 12 | protocol: "udp" 13 | - rule: "allow" 14 | to_port: "2379" 15 | protocol: "tcp" 16 | - rule: "allow" 17 | to_port: "2380" 18 | protocol: "tcp" 19 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-assets.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.5/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.5" 9 | 10 | k8s_admin_api_endpoint_host: "{{ hostvars[groups['k8s_controller'] | first]['ansible_' + hostvars[groups['k8s_controller'] | first]['k8s_interface']].ipv4.address }}" 11 | k8s_admin_api_endpoint_port: "16443" 12 | -------------------------------------------------------------------------------- /molecule/default/templates/clusterrole.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: rbac.authorization.k8s.io/v1 6 | kind: ClusterRole 7 | metadata: 8 | labels: 9 | kubernetes.io/bootstrapping: rbac-defaults 10 | name: system:coredns 11 | rules: 12 | - apiGroups: 13 | - "" 14 | - discovery.k8s.io 15 | resources: 16 | - endpointslices 17 | - endpoints 18 | - services 19 | - pods 20 | - namespaces 21 | verbs: 22 | - list 23 | - watch 24 | -------------------------------------------------------------------------------- /molecule/default/tasks/cilium_status.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Waiting for Cilium Helm chart to be applied 6 | ansible.builtin.wait_for: 7 | timeout: 10 8 | run_once: true 9 | 10 | - name: Fetch Cilium DaemonSet information 11 | kubernetes.core.k8s_info: 12 | api_version: v1 13 | kind: DaemonSet 14 | name: cilium 15 | namespace: cilium 16 | wait: true 17 | wait_sleep: 10 18 | wait_timeout: 600 19 | register: cilium__daemonset_info 20 | -------------------------------------------------------------------------------- /molecule/default/tasks/coredns_status.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Waiting for CoreDNS manifest being applied 6 | ansible.builtin.wait_for: 7 | timeout: 10 8 | run_once: true 9 | 10 | - name: Waiting for CoreDNS deployment 11 | kubernetes.core.k8s_info: 12 | api_version: v1 13 | kind: Deployment 14 | name: coredns 15 | namespace: kube-system 16 | wait: true 17 | wait_sleep: 10 18 | wait_timeout: 600 19 | register: coredns__deployment_info 20 | -------------------------------------------------------------------------------- /molecule/default/tasks/taint_controller_nodes.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Taint Kubernetes control plane nodes 6 | kubernetes.core.k8s_taint: 7 | state: present 8 | name: "{{ k8s_controller_node }}" 9 | taints: 10 | - effect: NoExecute 11 | key: "node-role.kubernetes.io/control-plane" 12 | - effect: NoSchedule 13 | key: "node-role.kubernetes.io/control-plane" 14 | loop: "{{ groups['k8s_controller'] }}" 15 | loop_control: 16 | loop_var: k8s_controller_node 17 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-worker1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.200/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.200" 9 | 10 | ha_proxy_frontend_bind_address: "127.0.0.1" 11 | ha_proxy_frontend_port: "16443" 12 | 13 | k8s_ctl_api_endpoint_host: "127.0.0.1" 14 | k8s_ctl_api_endpoint_port: "16443" 15 | 16 | k8s_worker_api_endpoint_host: "{{ k8s_ctl_api_endpoint_host }}" 17 | k8s_worker_api_endpoint_port: "{{ k8s_ctl_api_endpoint_port }}" 18 | -------------------------------------------------------------------------------- /molecule/default/templates/clusterrolebinding.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: rbac.authorization.k8s.io/v1 6 | kind: ClusterRoleBinding 7 | metadata: 8 | annotations: 9 | rbac.authorization.kubernetes.io/autoupdate: "true" 10 | labels: 11 | kubernetes.io/bootstrapping: rbac-defaults 12 | name: system:coredns 13 | roleRef: 14 | apiGroup: rbac.authorization.k8s.io 15 | kind: ClusterRole 16 | name: system:coredns 17 | subjects: 18 | - kind: ServiceAccount 19 | name: coredns 20 | namespace: kube-system 21 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | galaxy_info: 6 | author: Robert Wimmer 7 | description: Installs Cilium network on a Kubernetes cluster. 8 | license: GPLv3 9 | min_ansible_version: "2.12" 10 | role_name: cilium_kubernetes 11 | namespace: githubixx 12 | platforms: 13 | - name: ArchLinux 14 | - name: Ubuntu 15 | versions: 16 | - "jammy" 17 | - "noble" 18 | galaxy_tags: 19 | - kubernetes 20 | - worker 21 | - k8s 22 | - network 23 | - networking 24 | - cilium 25 | - pod 26 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-controller1.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.10/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.10" 9 | 10 | haproxy_frontend_bind_address: "10.10.10.10" 11 | haproxy_frontend_port: "16443" 12 | haproxy_k8s_api_endpoint_port: "6443" 13 | 14 | k8s_ctl_api_endpoint_host: "10.10.10.10" 15 | k8s_ctl_api_endpoint_port: "16443" 16 | 17 | k8s_worker_api_endpoint_host: "{{ haproxy_frontend_bind_address }}" 18 | k8s_worker_api_endpoint_port: "{{ haproxy_frontend_port }}" 19 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-controller2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.20/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.20" 9 | 10 | haproxy_frontend_bind_address: "10.10.10.20" 11 | haproxy_frontend_port: "16443" 12 | haproxy_k8s_api_endpoint_port: "6443" 13 | 14 | k8s_ctl_api_endpoint_host: "10.10.10.20" 15 | k8s_ctl_api_endpoint_port: "16443" 16 | 17 | k8s_worker_api_endpoint_host: "{{ haproxy_frontend_bind_address }}" 18 | k8s_worker_api_endpoint_port: "{{ haproxy_frontend_port }}" 19 | -------------------------------------------------------------------------------- /molecule/default/host_vars/test-controller3.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | wireguard_address: "10.10.10.30/24" 6 | wireguard_port: 51820 7 | wireguard_persistent_keepalive: "30" 8 | wireguard_endpoint: "172.16.10.30" 9 | 10 | haproxy_frontend_bind_address: "10.10.10.30" 11 | haproxy_frontend_port: "16443" 12 | haproxy_k8s_api_endpoint_port: "6443" 13 | 14 | k8s_ctl_api_endpoint_host: "10.10.10.30" 15 | k8s_ctl_api_endpoint_port: "16443" 16 | 17 | k8s_worker_api_endpoint_host: "{{ haproxy_frontend_bind_address }}" 18 | k8s_worker_api_endpoint_port: "{{ haproxy_frontend_port }}" 19 | -------------------------------------------------------------------------------- /templates/etcd-secrets.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: v1 6 | kind: Secret 7 | metadata: 8 | name: {{ cilium_etcd_secrets_name }} 9 | namespace: {{ cilium_namespace }} 10 | type: Opaque 11 | data: 12 | etcd-client-ca.crt: {{ lookup('file', cilium_etcd_cert_directory + '/' + cilium_etcd_cafile, rstrip=False) | b64encode }} 13 | etcd-client.key: {{ lookup('file', cilium_etcd_cert_directory + '/' + cilium_etcd_keyfile, rstrip=False) | b64encode }} 14 | etcd-client.crt: {{ lookup('file', cilium_etcd_cert_directory + '/' + cilium_etcd_certfile, rstrip=False) | b64encode }} 15 | -------------------------------------------------------------------------------- /molecule/default/templates/service.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: v1 6 | kind: Service 7 | metadata: 8 | name: kube-dns 9 | namespace: kube-system 10 | annotations: 11 | prometheus.io/port: "9153" 12 | prometheus.io/scrape: "true" 13 | labels: 14 | k8s-app: kube-dns 15 | kubernetes.io/cluster-service: "true" 16 | kubernetes.io/name: "CoreDNS" 17 | spec: 18 | selector: 19 | k8s-app: kube-dns 20 | clusterIP: 10.32.0.254 21 | ports: 22 | - name: dnsudp 23 | port: 53 24 | protocol: UDP 25 | - name: dnstcp 26 | port: 53 27 | protocol: TCP 28 | -------------------------------------------------------------------------------- /molecule/default/templates/configmap.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: v1 6 | kind: ConfigMap 7 | metadata: 8 | name: coredns 9 | namespace: kube-system 10 | data: 11 | Corefile: | 12 | .:53 { 13 | errors 14 | health { 15 | lameduck 5s 16 | } 17 | kubernetes cluster.local in-addr.arpa ip6.arpa { 18 | pods insecure 19 | fallthrough in-addr.arpa ip6.arpa 20 | } 21 | prometheus :9153 22 | forward . 1.1.1.1 9.9.9.9 23 | cache 30 24 | loop 25 | reload 26 | loadbalance 27 | ready 28 | } 29 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Check if Helm command is installed 6 | ansible.builtin.shell: hash helm 7 | delegate_to: "{{ cilium_delegate_to }}" 8 | run_once: true 9 | changed_when: false 10 | args: 11 | executable: "/bin/bash" 12 | 13 | - name: Set action according to cilium_action variable 14 | when: 15 | - cilium_action is not defined 16 | ansible.builtin.set_fact: 17 | cilium_action: "template" 18 | delegate_to: "{{ cilium_delegate_to }}" 19 | run_once: true 20 | 21 | - name: Include tasks to execute requested action 22 | ansible.builtin.include_tasks: 23 | file: "tasks/{{ cilium_action | lower }}.yml" 24 | -------------------------------------------------------------------------------- /tasks/helm_repository.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Add Helm repository 6 | when: 7 | - cilium__helm_repo_installed.status is not defined 8 | kubernetes.core.helm_repository: 9 | name: "{{ cilium_repo_name }}" 10 | repo_url: "{{ cilium_chart_url }}" 11 | delegate_to: "{{ cilium_delegate_to }}" 12 | run_once: true 13 | register: cilium__helm_add_repo 14 | 15 | - name: Add Helm repository (helm command executed) 16 | when: 17 | - cilium__helm_add_repo is defined 18 | - cilium__helm_add_repo.command is defined 19 | - cilium_helm_show_commands 20 | ansible.builtin.debug: 21 | var: cilium__helm_add_repo.command 22 | delegate_to: "{{ cilium_delegate_to }}" 23 | run_once: true 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This workflow requires a GALAXY_API_KEY secret present in the GitHub 3 | # repository or organization. 4 | # 5 | # See: https://github.com/marketplace/actions/publish-ansible-role-to-galaxy 6 | # See: https://github.com/ansible/galaxy/issues/46 7 | 8 | name: Release 9 | on: 10 | push: 11 | tags: 12 | - '*' 13 | 14 | defaults: 15 | run: 16 | working-directory: 'githubixx.cilium_kubernetes' 17 | 18 | jobs: 19 | release: 20 | name: Release 21 | runs-on: ubuntu-latest 22 | steps: 23 | - name: Check out the codebase. 24 | uses: actions/checkout@v2 25 | with: 26 | path: 'githubixx.cilium_kubernetes' 27 | 28 | - name: Set up Python 3. 29 | uses: actions/setup-python@v2 30 | with: 31 | python-version: '3.x' 32 | 33 | - name: Install Ansible. 34 | run: pip3 install ansible-core 35 | 36 | - name: Trigger a new import on Galaxy. 37 | run: >- 38 | ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} 39 | $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) 40 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Gather facts 6 | hosts: all 7 | become: true 8 | gather_facts: true 9 | tasks: 10 | - name: Populate Ansible hostVars 11 | ansible.builtin.setup: 12 | 13 | - name: Setup Cilium 14 | hosts: k8s_worker 15 | become: true 16 | environment: 17 | K8S_AUTH_KUBECONFIG: "{{ k8s_admin_conf_dir }}/admin.kubeconfig" 18 | tasks: 19 | - name: Include Cilium role 20 | ansible.builtin.include_role: 21 | name: githubixx.cilium_kubernetes 22 | vars: 23 | cilium_action: "install" 24 | 25 | - name: Setup tooling to make worker nodes usable 26 | hosts: test-assets 27 | become: true 28 | environment: 29 | K8S_AUTH_KUBECONFIG: "{{ k8s_admin_conf_dir }}/admin.kubeconfig" 30 | tasks: 31 | - name: Setup tooling 32 | when: 33 | - cilium_setup_networking is defined 34 | - cilium_setup_networking == "install" 35 | block: 36 | - name: Waiting for Cilium to become ready 37 | ansible.builtin.include_tasks: 38 | file: tasks/cilium_status.yml 39 | 40 | - name: Control plane nodes should only run Cilium pods 41 | ansible.builtin.include_tasks: 42 | file: tasks/taint_controller_nodes.yml 43 | 44 | - name: Install CoreDNS 45 | ansible.builtin.include_tasks: 46 | file: tasks/coredns.yml 47 | 48 | - name: Waiting for CoreDNS to become ready 49 | ansible.builtin.include_tasks: 50 | file: tasks/coredns_status.yml 51 | -------------------------------------------------------------------------------- /molecule/default/tasks/coredns.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Create CoreDNS service account 6 | kubernetes.core.k8s: 7 | state: present 8 | definition: "{{ lookup('template', 'templates/serviceaccount.yml.j2') | from_yaml }}" 9 | delegate_to: "{{ coredns_delegate_to }}" 10 | run_once: true 11 | 12 | - name: Create CoreDNS ClusterRole 13 | kubernetes.core.k8s: 14 | state: present 15 | definition: "{{ lookup('template', 'templates/clusterrole.yml.j2') | from_yaml }}" 16 | delegate_to: "{{ coredns_delegate_to }}" 17 | run_once: true 18 | 19 | - name: Create CoreDNS ClusterRoleBinding 20 | kubernetes.core.k8s: 21 | state: present 22 | definition: "{{ lookup('template', 'templates/clusterrolebinding.yml.j2') | from_yaml }}" 23 | delegate_to: "{{ coredns_delegate_to }}" 24 | run_once: true 25 | 26 | - name: Create CoreDNS ConfigMap 27 | kubernetes.core.k8s: 28 | state: present 29 | definition: "{{ lookup('template', 'templates/configmap.yml.j2') | from_yaml }}" 30 | delegate_to: "{{ coredns_delegate_to }}" 31 | run_once: true 32 | 33 | - name: Create CoreDNS Deployment 34 | kubernetes.core.k8s: 35 | state: present 36 | definition: "{{ lookup('template', 'templates/deployment.yml.j2') | from_yaml }}" 37 | delegate_to: "{{ coredns_delegate_to }}" 38 | run_once: true 39 | 40 | - name: Create CoreDNS Service 41 | kubernetes.core.k8s: 42 | state: present 43 | definition: "{{ lookup('template', 'templates/service.yml.j2') | from_yaml }}" 44 | delegate_to: "{{ coredns_delegate_to }}" 45 | run_once: true 46 | -------------------------------------------------------------------------------- /molecule/default/templates/values.yml.j2: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2025 Robert Wimmer 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # 4 | # See https://github.com/cilium/cilium/blob/master/install/kubernetes/cilium/values.yaml 5 | # for all possible values. 6 | # 7 | # All possible Jinja2 features/filters can be used but keep in mind that the 8 | # result needs to be a valid YAML file. 9 | 10 | # The Helm option keepDeprecatedProbes=true will keep the exec probe in 11 | # the new DaemonSet. 12 | keepDeprecatedProbes: true 13 | 14 | # The eBPF-based masquerading implementation is the most efficient implementation. 15 | # It requires Linux kernel >= 4.19. 16 | # See: https://docs.cilium.io/en/stable/concepts/networking/masquerading/ 17 | bpf: 18 | masquerade: true 19 | 20 | # Keep "kube-proxy" functionality 21 | kubeProxyReplacement: "false" 22 | 23 | # Enable nodePort 24 | nodePort: 25 | enabled: true 26 | enableHealthCheck: false 27 | 28 | # Enable socketLB 29 | socketLB: 30 | enabled: true 31 | 32 | # Use Cilium's IPAM. Every K8s node will get a "/24" for Pod IPs out of the 33 | # range specifed in "clusterPoolIPv4PodCIDRList". 34 | ipam: 35 | mode: "cluster-pool" 36 | ciliumNodeUpdateRate: "15s" 37 | operator: 38 | clusterPoolIPv4PodCIDRList: ["10.100.0.0/16"] 39 | clusterPoolIPv4MaskSize: 24 40 | 41 | cni: 42 | chainingMode: portmap 43 | {% if cilium_etcd_enabled is defined and cilium_etcd_enabled == "true" -%} 44 | etcd: 45 | enabled: true 46 | endpoints: 47 | {% for host in groups[cilium_etcd_nodes_group] -%} 48 | - {% if cilium_etcd_secrets_name is defined %}https{% else %}http{% endif -%}://{{ hostvars[host]['ansible_' + cilium_etcd_interface].ipv4.address }}:{{ cilium_etcd_client_port }} 49 | {% endfor -%} 50 | ssl: {% if cilium_etcd_secrets_name is defined %}true{% else %}false{% endif -%} 51 | {% endif %} 52 | -------------------------------------------------------------------------------- /tasks/delete.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Uninstall release via Helm 6 | kubernetes.core.helm: 7 | name: "{{ cilium_release_name }}" 8 | release_namespace: "{{ cilium_namespace }}" 9 | state: absent 10 | run_once: true 11 | delegate_to: "{{ cilium_delegate_to }}" 12 | register: cilium__helm_show_uninstall_release 13 | 14 | - name: Uninstall release via Helm (helm command executed) 15 | when: 16 | - cilium__helm_show_uninstall_release is defined 17 | - cilium__helm_show_uninstall_release.command is defined 18 | - cilium_helm_show_commands 19 | ansible.builtin.debug: 20 | var: cilium__helm_show_uninstall_release.command 21 | delegate_to: "{{ cilium_delegate_to }}" 22 | run_once: true 23 | 24 | - name: Delete Cilium etcd secrets in k8s 25 | kubernetes.core.k8s: 26 | state: absent 27 | name: "{{ cilium_etcd_secrets_name }}" 28 | namespace: "{{ cilium_namespace }}" 29 | api_version: v1 30 | kind: Secret 31 | delegate_to: "{{ cilium_delegate_to }}" 32 | run_once: true 33 | 34 | - name: BPFFS handling for Ubuntu 18.04 35 | when: 36 | - ansible_lsb.release is defined 37 | - ansible_lsb.release is version('20.04', '<') 38 | block: 39 | - name: Disable and umount BPFFS 40 | ansible.builtin.service: 41 | name: sys-fs-bpf.mount 42 | enabled: false 43 | state: stopped 44 | 45 | - name: Remove systemd unit file for mounting BPFFS 46 | ansible.builtin.file: 47 | path: "/etc/systemd/system/sys-fs-bpf.mount" 48 | state: absent 49 | notify: 50 | - Reload systemd 51 | 52 | - name: Delete namespace used by Cilium 53 | kubernetes.core.k8s: 54 | name: "{{ cilium_namespace }}" 55 | api_version: v1 56 | kind: Namespace 57 | state: absent 58 | delegate_to: "{{ cilium_delegate_to }}" 59 | run_once: true 60 | -------------------------------------------------------------------------------- /templates/cilium_values_default.yml.j2: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020-2025 Robert Wimmer 2 | # SPDX-License-Identifier: GPL-3.0-or-later 3 | # 4 | # See https://github.com/cilium/cilium/blob/master/install/kubernetes/cilium/values.yaml 5 | # for all possible values. 6 | # 7 | # All possible Jinja2 features/filters can be used but keep in mind that the 8 | # result needs to be a valid YAML file. 9 | 10 | # The Helm option keepDeprecatedProbes=true will keep the exec probe in 11 | # the new DaemonSet. 12 | keepDeprecatedProbes: true 13 | 14 | # To minimize datapath disruption during the upgrade, the upgradeCompatibility 15 | # option should be set to the INITIAL Cilium version which was installed in this 16 | # cluster. 17 | # 18 | # This is flag is not required for new installations! 19 | # 20 | # Valid options are: 21 | # 1.7 -> if the initial install was Cilium 1.7.x or earlier. 22 | # 1.8 -> if the initial install was Cilium 1.8.x. 23 | # 1.9 -> if the initial install was Cilium 1.9.x. 24 | # 1.10 -> if the initial install was Cilium 1.10.x. 25 | upgradeCompatibility: "1.7" 26 | 27 | # The eBPF-based masquerading implementation is the most efficient implementation. 28 | # It requires Linux kernel >= 4.19. 29 | # See: https://docs.cilium.io/en/stable/concepts/networking/masquerading/ 30 | bpf: 31 | masquerade: true 32 | 33 | # Keep "kube-proxy" functionality 34 | kubeProxyReplacement: "false" 35 | 36 | # Enable nodePort 37 | nodePort: 38 | enabled: true 39 | enableHealthCheck: false 40 | 41 | # Enable socketLB 42 | socketLB: 43 | enabled: true 44 | 45 | cni: 46 | chainingMode: portmap 47 | {% if cilium_etcd_enabled is defined and cilium_etcd_enabled == "true" -%} 48 | etcd: 49 | enabled: true 50 | endpoints: 51 | {% for host in groups[cilium_etcd_nodes_group] -%} 52 | - {% if cilium_etcd_secrets_name is defined %}https{% else %}http{% endif -%}://{{ hostvars[host]['ansible_' + cilium_etcd_interface].ipv4.address }}:{{ cilium_etcd_client_port }} 53 | {% endfor -%} 54 | ssl: {% if cilium_etcd_secrets_name is defined %}true{% else %}false{% endif -%} 55 | {% endif %} 56 | -------------------------------------------------------------------------------- /tasks/pre_flight_check.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Pre flight pod check 6 | block: 7 | - name: Set the retry count 8 | ansible.builtin.set_fact: 9 | retry_count: "{{ 0 if retry_count is undefined else retry_count | int + 1 }}" 10 | run_once: true 11 | delegate_to: "{{ cilium_delegate_to }}" 12 | 13 | - name: Waiting for pre flight deployment 14 | ansible.builtin.wait_for: 15 | timeout: 10 16 | run_once: true 17 | 18 | - name: Fetch current Cilium pre flight DaemonSet state 19 | kubernetes.core.k8s_info: 20 | api_version: v1 21 | kind: DaemonSet 22 | name: cilium-pre-flight-check 23 | namespace: "{{ cilium_namespace }}" 24 | register: cilium_pre_flight_check_daemonset 25 | run_once: true 26 | delegate_to: "{{ cilium_delegate_to }}" 27 | 28 | - name: Register current Cilium pre flight pods running 29 | ansible.builtin.set_fact: 30 | cilium_pre_flight_pods_running: "{{ cilium_pre_flight_check_daemonset | to_json | from_json | community.general.json_query(json_query) }}" 31 | vars: 32 | json_query: "resources[0].status.numberReady" 33 | run_once: true 34 | delegate_to: "{{ cilium_delegate_to }}" 35 | 36 | - name: Checking if Cilium pre flight pod count == Cilium pod count 37 | ansible.builtin.fail: 38 | msg: "Pre flight count: {{ cilium_pre_flight_pods_running }} / Cilium count: {{ cilium_pods_running }}" 39 | when: cilium_pre_flight_pods_running | int != cilium_pods_running | int 40 | run_once: true 41 | delegate_to: "{{ cilium_delegate_to }}" 42 | rescue: 43 | - name: Fail if retry count is reached 44 | ansible.builtin.fail: 45 | msg: Ended after 60 retries 46 | when: retry_count | int == 60 47 | run_once: true 48 | delegate_to: "{{ cilium_delegate_to }}" 49 | 50 | - name: Preflight waiting loop 51 | ansible.builtin.debug: 52 | msg: "Waiting for Cilium pre flight pods starting up..." 53 | run_once: true 54 | delegate_to: "{{ cilium_delegate_to }}" 55 | 56 | - name: Sleeping 57 | ansible.builtin.wait_for: 58 | timeout: 10 59 | run_once: true 60 | delegate_to: "{{ cilium_delegate_to }}" 61 | 62 | - name: Include pre flight checks 63 | ansible.builtin.include_tasks: 64 | file: pre_flight_check.yml 65 | -------------------------------------------------------------------------------- /molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Verify setup 6 | hosts: test-assets 7 | environment: 8 | K8S_AUTH_KUBECONFIG: "{{ k8s_admin_conf_dir }}/admin.kubeconfig" 9 | tasks: 10 | - name: Fetch Cilium DaemonSet information 11 | kubernetes.core.k8s_info: 12 | api_version: v1 13 | kind: DaemonSet 14 | name: cilium 15 | namespace: cilium 16 | register: cilium__daemonset_info 17 | 18 | - name: Print DaemonSet JSON blob 19 | ansible.builtin.debug: 20 | var: cilium__daemonset_info 21 | when: ansible_verbosity > 1 22 | 23 | - name: There should be a DaemonSet called cilium 24 | ansible.builtin.assert: 25 | that: 26 | - cilium__daemonset_info.resources[0].metadata.name == "cilium" 27 | 28 | - name: There should be at least one Cilium pod running 29 | ansible.builtin.assert: 30 | that: 31 | - (cilium__daemonset_info.resources[0].status.numberReady | default(0) | int ) >= 1 32 | 33 | - name: Fetch Cilium status 34 | become: true 35 | become_user: vagrant 36 | ansible.builtin.command: 37 | cmd: cilium -n cilium status --output json 38 | register: cilium__json_status 39 | changed_when: false 40 | 41 | - name: Register cilium pods unavailable 42 | ansible.builtin.set_fact: 43 | cilium__cilium_pods_running: "{{ cilium__json_status | to_json | from_json | community.general.json_query(json_query) }}" 44 | vars: 45 | json_query: "pod_state.cilium.Unavailable" 46 | 47 | - name: Check if cilium pods unavailable is 0 48 | ansible.builtin.fail: 49 | msg: "Ja: {{ cilium__cilium_pods_running }}" 50 | when: cilium__cilium_pods_running | int != 0 51 | 52 | - name: Register cilium-operator pods unavailable 53 | ansible.builtin.set_fact: 54 | cilium__cilium_operator_pods_running: "{{ cilium__json_status | to_json | from_json | community.general.json_query(json_query) }}" 55 | vars: 56 | json_query: 'pod_state."cilium-operator".Unavailable' 57 | 58 | - name: Check if cilium-operator pods unavailable is 0 59 | ansible.builtin.fail: 60 | msg: "Ja: {{ cilium__cilium_operator_pods_running }}" 61 | when: cilium__cilium_operator_pods_running | int != 0 62 | 63 | - name: Print Cilium status output 64 | ansible.builtin.debug: 65 | var: cilium__json_status.stdout 66 | when: ansible_verbosity > 1 67 | -------------------------------------------------------------------------------- /molecule/default/templates/deployment.yml.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | apiVersion: apps/v1 6 | kind: Deployment 7 | metadata: 8 | name: coredns 9 | namespace: kube-system 10 | labels: 11 | k8s-app: kube-dns 12 | kubernetes.io/name: "CoreDNS" 13 | spec: 14 | replicas: 2 15 | strategy: 16 | type: RollingUpdate 17 | rollingUpdate: 18 | maxUnavailable: 1 19 | selector: 20 | matchLabels: 21 | k8s-app: kube-dns 22 | template: 23 | metadata: 24 | labels: 25 | k8s-app: kube-dns 26 | spec: 27 | serviceAccountName: coredns 28 | tolerations: 29 | - key: node-role.kubernetes.io/control-plane 30 | effect: NoSchedule 31 | - key: "CriticalAddonsOnly" 32 | operator: "Exists" 33 | containers: 34 | - name: coredns 35 | image: coredns/coredns:1.13.1 36 | imagePullPolicy: IfNotPresent 37 | resources: 38 | limits: 39 | memory: 170Mi 40 | requests: 41 | cpu: 100m 42 | memory: 70Mi 43 | args: [ "-conf", "/etc/coredns/Corefile" ] 44 | volumeMounts: 45 | - name: config-volume 46 | mountPath: /etc/coredns 47 | readOnly: true 48 | ports: 49 | - containerPort: 53 50 | name: dns 51 | protocol: UDP 52 | - containerPort: 53 53 | name: dns-tcp 54 | protocol: TCP 55 | - containerPort: 9153 56 | name: metrics 57 | protocol: TCP 58 | securityContext: 59 | allowPrivilegeEscalation: false 60 | capabilities: 61 | add: 62 | - NET_BIND_SERVICE 63 | drop: 64 | - all 65 | readOnlyRootFilesystem: true 66 | livenessProbe: 67 | httpGet: 68 | path: /health 69 | port: 8080 70 | scheme: HTTP 71 | initialDelaySeconds: 60 72 | timeoutSeconds: 5 73 | successThreshold: 1 74 | failureThreshold: 5 75 | dnsPolicy: Default 76 | volumes: 77 | - name: config-volume 78 | configMap: 79 | name: coredns 80 | items: 81 | - key: Corefile 82 | path: Corefile 83 | affinity: 84 | podAntiAffinity: 85 | preferredDuringSchedulingIgnoredDuringExecution: 86 | - weight: 100 87 | podAffinityTerm: 88 | labelSelector: 89 | matchExpressions: 90 | - key: "k8s-app" 91 | operator: In 92 | values: 93 | - kube-dns 94 | topologyKey: "kubernetes.io/hostname" 95 | -------------------------------------------------------------------------------- /tasks/template.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Include Helm repository tasks 6 | ansible.builtin.include_tasks: 7 | file: helm_repository.yml 8 | 9 | - name: Render values 10 | block: 11 | - name: Create temporary file for Helm values 12 | ansible.builtin.tempfile: 13 | state: file 14 | suffix: cilium_values 15 | delegate_to: "{{ cilium_delegate_to }}" 16 | run_once: true 17 | register: cilium__values_tmp_file 18 | 19 | - name: Select values file for Helm template 20 | ansible.builtin.template: 21 | src: "{{ lookup('first_found', params) }}" 22 | dest: "{{ cilium__values_tmp_file.path }}" 23 | mode: "0600" 24 | delegate_to: "{{ cilium_delegate_to }}" 25 | run_once: true 26 | vars: 27 | params: 28 | files: 29 | - values.yml.j2 30 | - values.yaml.j2 31 | - cilium_values_user.yml.j2 32 | - cilium_values_default.yml.j2 33 | paths: 34 | - "{{ cilium_chart_values_directory }}" 35 | - templates 36 | 37 | - name: Render template 38 | kubernetes.core.helm_template: 39 | chart_ref: "{{ cilium_chart_name }}" 40 | chart_version: "{{ cilium_chart_version }}" 41 | release_namespace: "{{ cilium_namespace }}" 42 | update_repo_cache: true 43 | values_files: 44 | - "{{ cilium__values_tmp_file.path }}" 45 | run_once: true 46 | delegate_to: "{{ cilium_delegate_to }}" 47 | register: cilium__template 48 | 49 | - name: Render template (helm command executed) 50 | when: 51 | - cilium__template is defined 52 | - cilium__template.command is defined 53 | - cilium_helm_show_commands 54 | ansible.builtin.debug: 55 | var: cilium__template.command 56 | delegate_to: "{{ cilium_delegate_to }}" 57 | run_once: true 58 | 59 | - name: Create directory to store template.yml 60 | ansible.builtin.file: 61 | dest: "{{ cilium_template_output_directory }}" 62 | state: directory 63 | mode: "0755" 64 | run_once: true 65 | delegate_to: "{{ cilium_delegate_to }}" 66 | 67 | - name: Write templates to file 68 | ansible.builtin.copy: 69 | dest: "{{ cilium_template_output_directory }}/template.yml" 70 | content: "{{ cilium__template.stdout }}" 71 | mode: "0644" 72 | run_once: true 73 | delegate_to: "{{ cilium_delegate_to }}" 74 | 75 | - name: Delete temporary file for Helm values 76 | when: cilium__values_tmp_file.path is defined 77 | ansible.builtin.file: 78 | path: "{{ cilium__values_tmp_file.path }}" 79 | state: absent 80 | run_once: true 81 | delegate_to: "{{ cilium_delegate_to }}" 82 | 83 | rescue: 84 | - name: Delete temporary file for Helm values 85 | when: cilium__values_tmp_file.path is defined 86 | ansible.builtin.file: 87 | path: "{{ cilium__values_tmp_file.path }}" 88 | state: absent 89 | run_once: true 90 | delegate_to: "{{ cilium_delegate_to }}" 91 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | dependency: 6 | name: galaxy 7 | 8 | driver: 9 | name: vagrant 10 | provider: 11 | name: libvirt 12 | type: libvirt 13 | 14 | platforms: 15 | - name: test-assets 16 | box: alvistack/ubuntu-24.04 17 | memory: 2048 18 | cpus: 2 19 | groups: 20 | - vpn 21 | - k8s_assets 22 | - k8s 23 | interfaces: 24 | - auto_config: true 25 | network_name: private_network 26 | type: static 27 | ip: 172.16.10.5 28 | - name: test-controller1 29 | box: alvistack/ubuntu-24.04 30 | memory: 2048 31 | cpus: 2 32 | groups: 33 | - vpn 34 | - haproxy 35 | - k8s_controller 36 | - k8s_worker 37 | - k8s 38 | interfaces: 39 | - auto_config: true 40 | network_name: private_network 41 | type: static 42 | ip: 172.16.10.10 43 | - name: test-controller2 44 | box: alvistack/ubuntu-24.04 45 | memory: 2048 46 | cpus: 2 47 | groups: 48 | - vpn 49 | - haproxy 50 | - k8s_controller 51 | - k8s_worker 52 | - k8s 53 | interfaces: 54 | - auto_config: true 55 | network_name: private_network 56 | type: static 57 | ip: 172.16.10.20 58 | - name: test-controller3 59 | box: alvistack/ubuntu-24.04 60 | memory: 2048 61 | cpus: 2 62 | groups: 63 | - vpn 64 | - haproxy 65 | - k8s_controller 66 | - k8s_worker 67 | - k8s 68 | interfaces: 69 | - auto_config: true 70 | network_name: private_network 71 | type: static 72 | ip: 172.16.10.30 73 | - name: test-etcd1 74 | box: alvistack/ubuntu-24.04 75 | memory: 2048 76 | cpus: 2 77 | groups: 78 | - vpn 79 | - k8s_etcd 80 | interfaces: 81 | - auto_config: true 82 | network_name: private_network 83 | type: static 84 | ip: 172.16.10.100 85 | - name: test-etcd2 86 | box: alvistack/ubuntu-24.04 87 | memory: 2048 88 | cpus: 2 89 | groups: 90 | - vpn 91 | - k8s_etcd 92 | interfaces: 93 | - auto_config: true 94 | network_name: private_network 95 | type: static 96 | ip: 172.16.10.110 97 | - name: test-etcd3 98 | box: alvistack/ubuntu-24.04 99 | memory: 2048 100 | cpus: 2 101 | groups: 102 | - vpn 103 | - k8s_etcd 104 | interfaces: 105 | - auto_config: true 106 | network_name: private_network 107 | type: static 108 | ip: 172.16.10.120 109 | - name: test-worker1 110 | box: alvistack/ubuntu-24.04 111 | memory: 2048 112 | cpus: 2 113 | groups: 114 | - vpn 115 | - haproxy 116 | - k8s_worker 117 | - k8s 118 | interfaces: 119 | - auto_config: true 120 | network_name: private_network 121 | type: static 122 | ip: 172.16.10.200 123 | - name: test-worker2 124 | box: alvistack/ubuntu-24.04 125 | memory: 2048 126 | cpus: 2 127 | groups: 128 | - vpn 129 | - k8s_worker 130 | - k8s 131 | interfaces: 132 | - auto_config: true 133 | network_name: private_network 134 | type: static 135 | ip: 172.16.10.210 136 | 137 | provisioner: 138 | name: ansible 139 | connection_options: 140 | ansible_ssh_user: vagrant 141 | ansible_become: true 142 | log: true 143 | lint: yamllint . && flake8 && ansible-lint 144 | 145 | scenario: 146 | name: default 147 | test_sequence: 148 | - prepare 149 | - converge 150 | 151 | verifier: 152 | name: ansible 153 | enabled: true 154 | -------------------------------------------------------------------------------- /tasks/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Create namespace 6 | kubernetes.core.k8s: 7 | name: "{{ cilium_namespace }}" 8 | api_version: v1 9 | kind: Namespace 10 | state: present 11 | delegate_to: "{{ cilium_delegate_to }}" 12 | run_once: true 13 | 14 | - name: Include Helm repository tasks 15 | ansible.builtin.include_tasks: 16 | file: helm_repository.yml 17 | 18 | - name: BPFFS handling for Ubuntu 18.04 19 | when: 20 | - ansible_lsb.release is defined 21 | - ansible_lsb.release is version('20.04', '<') 22 | block: 23 | - name: Install systemd unit file for mounting BPFFS 24 | ansible.builtin.copy: 25 | src: "files/etc/systemd/system/sys-fs-bpf.mount" 26 | dest: "/etc/systemd/system/sys-fs-bpf.mount" 27 | mode: "0644" 28 | owner: root 29 | group: root 30 | notify: 31 | - Reload systemd 32 | 33 | - name: Enable and mount BPFFSS 34 | ansible.builtin.service: 35 | name: sys-fs-bpf.mount 36 | enabled: true 37 | state: started 38 | 39 | - name: Install Cilium etcd secrets in k8s 40 | when: 41 | - cilium_etcd_enabled is defined 42 | - cilium_etcd_enabled == "true" 43 | - cilium_etcd_secrets_name is defined 44 | kubernetes.core.k8s: 45 | state: present 46 | definition: "{{ lookup('template', 'etcd-secrets.yml.j2') }}" 47 | namespace: "{{ cilium_namespace }}" 48 | delegate_to: "{{ cilium_delegate_to }}" 49 | run_once: true 50 | 51 | - name: Install Cilium via Helm 52 | block: 53 | - name: Create temporary file for Helm values 54 | ansible.builtin.tempfile: 55 | state: file 56 | suffix: cilium_values 57 | delegate_to: "{{ cilium_delegate_to }}" 58 | run_once: true 59 | register: cilium__values_tmp_file 60 | 61 | - name: Select values file for Helm template 62 | ansible.builtin.template: 63 | src: "{{ lookup('first_found', params) }}" 64 | dest: "{{ cilium__values_tmp_file.path }}" 65 | mode: "0600" 66 | delegate_to: "{{ cilium_delegate_to }}" 67 | run_once: true 68 | vars: 69 | params: 70 | files: 71 | - values.yml.j2 72 | - values.yaml.j2 73 | - cilium_values_user.yml.j2 74 | - cilium_values_default.yml.j2 75 | paths: 76 | - "{{ cilium_chart_values_directory }}" 77 | - templates 78 | 79 | - name: Install chart 80 | kubernetes.core.helm: 81 | name: "{{ cilium_release_name }}" 82 | chart_ref: "{{ cilium_chart_name }}" 83 | chart_version: "{{ cilium_chart_version }}" 84 | release_namespace: "{{ cilium_namespace }}" 85 | create_namespace: false 86 | update_repo_cache: true 87 | values_files: 88 | - "{{ cilium__values_tmp_file.path }}" 89 | run_once: true 90 | delegate_to: "{{ cilium_delegate_to }}" 91 | register: cilium__helm_install_chart 92 | 93 | - name: Install chart (helm command executed) 94 | when: 95 | - cilium__helm_install_chart is defined 96 | - cilium__helm_install_chart.command is defined 97 | - cilium_helm_show_commands 98 | ansible.builtin.debug: 99 | var: cilium__helm_install_chart.command 100 | delegate_to: "{{ cilium_delegate_to }}" 101 | run_once: true 102 | 103 | - name: Delete temporary file for Helm values 104 | when: cilium__values_tmp_file.path is defined 105 | ansible.builtin.file: 106 | path: "{{ cilium__values_tmp_file.path }}" 107 | state: absent 108 | run_once: true 109 | delegate_to: "{{ cilium_delegate_to }}" 110 | 111 | rescue: 112 | - name: Delete temporary file for Helm values 113 | when: cilium__values_tmp_file.path is defined 114 | ansible.builtin.file: 115 | path: "{{ cilium__values_tmp_file.path }}" 116 | state: absent 117 | run_once: true 118 | delegate_to: "{{ cilium_delegate_to }}" 119 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | # Helm chart version (uses Cilium v1.17.8) 6 | cilium_chart_version: "1.17.8" 7 | 8 | # Helm release name 9 | cilium_release_name: "cilium" 10 | 11 | # Helm repository name 12 | cilium_repo_name: "cilium" 13 | 14 | # Helm chart name 15 | cilium_chart_name: "{{ cilium_repo_name }}/{{ cilium_release_name }}" 16 | 17 | # Helm chart URL 18 | cilium_chart_url: "https://helm.cilium.io/" 19 | 20 | # Kubernetes namespace where Cilium resources should be installed 21 | cilium_namespace: "cilium" 22 | 23 | # Directory that contains Helm chart values file. Ansible will try to locate 24 | # a file called "values.yml.j2" or "values.yaml.j2" in the specified directory 25 | # (".j2" because you can use the usual Jinja2 template stuff there). 26 | # If not found the default "templates/cilium_values_default.yml.j2" will be 27 | # used (which can be used as a template BTW). The content of this file 28 | # will be provided to "helm install/template" command as values file. 29 | cilium_chart_values_directory: "/tmp/cilium/helm" 30 | 31 | # etcd settings. If "cilium_etcd_enabled" variable is defined and set to "true", 32 | # Cilium etcd settings are generated and deployed. Otherwise all the following 33 | # "cilium_etcd_*" settings are ignored. 34 | # 35 | cilium_etcd_enabled: "true" 36 | 37 | # Interface where etcd daemons are listening. If etcd daemons are bound to 38 | # a WireGuard interface this setting should be "wg0" (by default) e.g. 39 | # You can also use a variable like "{{ etcd_interface }}" if you used 40 | # my etcd role (https://github.com/githubixx/ansible-role-etcd) 41 | cilium_etcd_interface: "eth0" 42 | 43 | # Port where etcd daemons are listening 44 | cilium_etcd_client_port: 2379 45 | 46 | # Ansible etcd host group in Ansible's "hosts" file. This value is used in 47 | # "templates/cilium_values_default.yml.j2" template to determine the IP 48 | # addresses of the hosts where etcd daemons are listening. 49 | cilium_etcd_nodes_group: "k8s_etcd" 50 | 51 | # If this variable is defined a Kubernetes secret will be installed which 52 | # contains the certificate files defined in "cilium_etcd_cafile", 53 | # "cilium_etcd_certfile" and "cilium_etcd_keyfile" 54 | # 55 | # This causes that a secure connection (https) will be established to etcd. 56 | # This of course requires that etcd is configured to use SSL/TLS. 57 | # 58 | # If this value is not defined (e.g. commented) the rest of the "cilium_etcd_*" 59 | # settings below are ignored and connection to etcd will be established 60 | # unsecured via "http". 61 | cilium_etcd_secrets_name: "cilium-etcd-secrets" 62 | 63 | # Where to find the certificate files defined below. If you used my 64 | # Kubernetes Certificate role (https://github.com/githubixx/ansible-role-kubernetes-ca) 65 | # you may already have "k8s_ca_conf_directory" variable defined which you 66 | # can re-use here. This role also generates the certificate files that can 67 | # be used for the variables below. 68 | # By default this will be "$HOME/k8s/certs" of the current user that runs 69 | # "ansible-playbook" command. 70 | cilium_etcd_cert_directory: "{{ '~/k8s/certs' | expanduser }}" 71 | 72 | # etcd certificate authority file (file will be fetched in "cilium_etcd_cert_directory") 73 | cilium_etcd_cafile: "ca-etcd.pem" 74 | 75 | # etcd certificate file (file will be fetched in "cilium_etcd_cert_directory") 76 | # Make sure that the certificate contains the IP addresses in the "Subject 77 | # Alternative Name" (SAN) of the interfaces where etcd daemons listens on 78 | # (that's the IP addresses of the interfaces defined in "cilium_etcd_interface"). 79 | # This is already handled by my Kubernetes Certificate Authority role 80 | # (https://github.com/githubixx/ansible-role-kubernetes-ca) if you used that one. 81 | cilium_etcd_certfile: "cert-cilium.pem" 82 | 83 | # etcd certificate key file (file will be fetched in "cilium_etcd_cert_directory") 84 | cilium_etcd_keyfile: "cert-cilium-key.pem" 85 | 86 | # By default all tasks that needs to communicate with the Kubernetes 87 | # cluster are executed on your local host (127.0.0.1). But if that one 88 | # doesn't have direct connection to this cluster or should be executed 89 | # elsewhere this variable can be changed accordingly. 90 | cilium_delegate_to: 127.0.0.1 91 | 92 | # Shows the "helm" command that was executed if a task uses Helm to 93 | # install, update/upgrade or deletes such a resource. 94 | cilium_helm_show_commands: false 95 | 96 | # Without "action" variable defined this role will only render a file 97 | # with all the resources that will be installed or upgraded. The rendered 98 | # file with the resources will be called "template.yml" and will be 99 | # placed in the directory specified below. 100 | cilium_template_output_directory: "{{ '~/cilium/template' | expanduser }}" 101 | -------------------------------------------------------------------------------- /molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Update cache 6 | hosts: k8s 7 | remote_user: vagrant 8 | become: true 9 | gather_facts: true 10 | tasks: 11 | - name: Update APT package cache 12 | ansible.builtin.apt: 13 | update_cache: true 14 | cache_valid_time: 3600 15 | - name: Reboot for kernel updates 16 | ansible.builtin.reboot: 17 | 18 | - name: Harden hosts 19 | hosts: all 20 | remote_user: vagrant 21 | become: true 22 | gather_facts: true 23 | tasks: 24 | - name: Setup harden_linux role 25 | ansible.builtin.include_role: 26 | name: githubixx.harden_linux 27 | 28 | - name: Setup Wireguard VPN 29 | hosts: vpn 30 | remote_user: vagrant 31 | become: true 32 | gather_facts: true 33 | tasks: 34 | - name: Setup wireguard role 35 | ansible.builtin.include_role: 36 | name: githubixx.ansible_role_wireguard 37 | 38 | - name: Setup cfssl 39 | hosts: k8s_assets 40 | become: true 41 | gather_facts: false 42 | tasks: 43 | - name: Install cfssl 44 | ansible.builtin.include_role: 45 | name: githubixx.cfssl 46 | 47 | - name: Setup Kubernetes certificates 48 | hosts: k8s_assets 49 | gather_facts: false 50 | tasks: 51 | - name: Generate etcd and K8s TLS certificates 52 | ansible.builtin.include_role: 53 | name: githubixx.kubernetes_ca 54 | 55 | - name: Copy certificate files from assets to local host 56 | ansible.posix.synchronize: 57 | mode: pull 58 | src: "{{ k8s_ca_conf_directory }}" 59 | dest: "/tmp" 60 | 61 | - name: Setup etcd 62 | hosts: k8s_etcd 63 | remote_user: vagrant 64 | become: true 65 | gather_facts: true 66 | tasks: 67 | - name: Include etcd role 68 | ansible.builtin.include_role: 69 | name: githubixx.etcd 70 | 71 | - name: Setup Kubernetes client tooling 72 | hosts: k8s_assets 73 | become: true 74 | gather_facts: true 75 | tasks: 76 | - name: Install kubectl 77 | ansible.builtin.include_role: 78 | name: githubixx.kubectl 79 | 80 | - name: Install support packages 81 | ansible.builtin.package: 82 | name: "{{ packages }}" 83 | state: present 84 | vars: 85 | packages: 86 | - conntrack 87 | - python3-pip 88 | 89 | - name: Install kubernetes Python package 90 | ansible.builtin.package: 91 | name: python3-kubernetes 92 | state: present 93 | 94 | - name: Install Helm role 95 | ansible.builtin.include_role: 96 | name: gantsign.helm 97 | 98 | - name: Setup HAProxy 99 | hosts: haproxy 100 | remote_user: vagrant 101 | become: true 102 | gather_facts: true 103 | tasks: 104 | - name: Setup haproxy role 105 | ansible.builtin.include_role: 106 | name: githubixx.haproxy 107 | 108 | - name: Setup containerd 109 | hosts: k8s_worker 110 | become: true 111 | gather_facts: true 112 | tasks: 113 | - name: Include runc role 114 | ansible.builtin.include_role: 115 | name: githubixx.runc 116 | 117 | - name: Include CNI role 118 | ansible.builtin.include_role: 119 | name: githubixx.cni 120 | 121 | - name: Include containerd role 122 | ansible.builtin.include_role: 123 | name: githubixx.containerd 124 | 125 | - name: Setup Kubernetes controller 126 | hosts: k8s_controller 127 | become: true 128 | gather_facts: true 129 | tasks: 130 | - name: Include kubernetes_controller role 131 | ansible.builtin.include_role: 132 | name: githubixx.kubernetes_controller 133 | 134 | - name: Prepare kubeconfig for vagrant user 135 | hosts: k8s_assets 136 | become: true 137 | gather_facts: false 138 | vars: 139 | k8s_controller__vagrant_kube_directory: "/home/vagrant/.kube" 140 | tasks: 141 | - name: Ensure .kube directory in vagrant home 142 | ansible.builtin.file: 143 | path: "{{ k8s_controller__vagrant_kube_directory }}" 144 | state: directory 145 | mode: "0700" 146 | owner: "vagrant" 147 | group: "vagrant" 148 | 149 | - name: Copy admin.kubeconfig to vagrant home directory 150 | ansible.builtin.copy: 151 | src: "{{ k8s_admin_conf_dir }}/admin.kubeconfig" 152 | dest: "{{ k8s_controller__vagrant_kube_directory }}/config" 153 | mode: "0400" 154 | remote_src: true 155 | owner: "vagrant" 156 | group: "vagrant" 157 | 158 | - name: Setup Kubernetes worker 159 | hosts: k8s_worker 160 | become: true 161 | gather_facts: true 162 | tasks: 163 | - name: Include kubernetes_worker role 164 | ansible.builtin.include_role: 165 | name: githubixx.kubernetes_worker 166 | 167 | - name: Setup Cilium CLI 168 | hosts: test-assets 169 | become: true 170 | tasks: 171 | - name: Include cilium_cli role 172 | ansible.builtin.include_role: 173 | name: githubixx.cilium_cli 174 | -------------------------------------------------------------------------------- /molecule/default/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | # Use "systemd-timesyncd" for time services. It's available by default. 6 | harden_linux_ntp: "systemd-timesyncd" 7 | 8 | # Password for user "root" and "vagrant" is "vagrant" in both cases. As 9 | # "vagrant" user is available in every Vagrant Ubuntu Box just use it. 10 | harden_linux_root_password: "$6$ec6PmcEygP6do8Ls$847Pqqo1fXJFeMvPkmP3ipLQ9vhny1PYtwnnIptpZ1Sc8KXUuPGu29aUTOdNdgIfxR3Bix5SUkNfSMMCetej41" 11 | harden_linux_deploy_user: "vagrant" 12 | harden_linux_deploy_user_password: "$6$ec6PmcEygP6do8Ls$847Pqqo1fXJFeMvPkmP3ipLQ9vhny1PYtwnnIptpZ1Sc8KXUuPGu29aUTOdNdgIfxR3Bix5SUkNfSMMCetej41" 13 | harden_linux_deploy_user_home: "/home/vagrant" 14 | harden_linux_deploy_user_uid: "1000" 15 | harden_linux_deploy_user_shell: "/bin/bash" 16 | 17 | # Enable IP forwarding for IPv4 and IPv6 18 | harden_linux_sysctl_settings_user: 19 | "net.ipv4.ip_forward": 1 20 | "net.ipv6.conf.default.forwarding": 1 21 | "net.ipv6.conf.all.forwarding": 1 22 | 23 | # Let SSHd listen on port 22, allow password authentication and allow "root" 24 | # login. The last two settings are not recommended for production use but for 25 | # this test deployment it's okay as it makes debugging easier and faster. 26 | harden_linux_sshd_settings_user: 27 | "^Port ": "Port 22" 28 | "^PasswordAuthentication": "PasswordAuthentication yes" 29 | "^PermitRootLogin": "PermitRootLogin yes" 30 | 31 | # Enable logging for UFW. 32 | harden_linux_ufw_logging: 'on' 33 | 34 | # Set the default forward policy to "ACCEPT". 35 | harden_linux_ufw_defaults_user: 36 | "^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="ACCEPT"' 37 | 38 | # Don't block SSH logins from the following networks even login attempts fail 39 | # for a few times. 40 | harden_linux_sshguard_whitelist: 41 | - "127.0.0.0/8" 42 | - "::1/128" 43 | - "10.0.0.0/8" 44 | - "172.16.0.0/12" 45 | - "192.168.0.0/16" 46 | 47 | # DNS 48 | harden_linux_systemd_resolved_settings: 49 | - DNS= 50 | - DNS=8.8.8.8 1.1.1.1 2606:4700:4700::1111 2620:fe::fe 51 | - FallbackDNS= 52 | - FallbackDNS=149.112.112.112 1.0.0.1 2620:fe::9 2606:4700:4700::1001 53 | - DNSOverTLS= 54 | - DNSOverTLS=opportunistic 55 | 56 | # Directory where the etcd certificates are stored on the Ansible controller 57 | # host. Certificate files for etcd will be copied from this directory to 58 | # the etcd nodes. 59 | etcd_ca_conf_directory: "{{ k8s_ca_conf_directory }}" 60 | # Directory where the etcd certificates are stored on the etcd hosts. 61 | etcd_conf_dir: "/etc/etcd" 62 | # Interface where the etcd service is listening on. 63 | etcd_interface: "{{ k8s_interface }}" 64 | # A few additional settings for etcd. 65 | etcd_settings_user: 66 | "heartbeat-interval": "250" 67 | "election-timeout": "2500" 68 | # Host names and IP addresses in the etcd certificates. 69 | etcd_cert_hosts: 70 | - localhost 71 | - 127.0.0.1 72 | # This list should contain all etcd clients that wants to connect to the etcd 73 | # cluster. The most important client is "kube-apiserver" of course. Also 74 | # "cilium" should connect. So we add this here too to generate the needed 75 | # certificates. 76 | etcd_additional_clients: 77 | - cilium 78 | - k8s-apiserver-etcd 79 | 80 | # Directory where the Kubernetes certificates are stored on the Ansible 81 | # controller host. 82 | k8s_ca_conf_directory: "/tmp/k8s-ca" 83 | # Permissions for the Kubernetes CA directory. 84 | k8s_ca_conf_directory_perm: "0700" 85 | # Permissions for the Kubernetes CA files. 86 | k8s_ca_file_perm: "0600" 87 | # Owner of the Kubernetes CA files. 88 | k8s_ca_certificate_owner: "vagrant" 89 | # Group of the Kubernetes CA files. 90 | k8s_ca_certificate_group: "vagrant" 91 | 92 | # Interface where the Kubernetes control plane services are listening on. 93 | k8s_interface: "wg0" 94 | # Interface where the etcd daemons listening on. 95 | k8s_ctl_etcd_interface: "{{ etcd_interface }}" 96 | 97 | # Delegate tasks like creating the Kubernetes CA certificates to the following 98 | # host. This host also communicates with the "kube-apiserver" if required 99 | # for certain tasks. 100 | k8s_ctl_delegate_to: "test-assets" 101 | 102 | # Directory where the Kubernetes certificates are stored on the Ansible 103 | # controller host and where the Ansible can find them to be copied to the 104 | # Kubernetes control plane nodes. 105 | k8s_ctl_ca_conf_directory: "{{ k8s_ca_conf_directory }}" 106 | 107 | # The name of the Kubernetes cluster. 108 | k8s_config_cluster_name: "k8s" 109 | 110 | # Directory where "admin.kubeconfig" (the credentials file) for the "admin" 111 | # user is stored 112 | k8s_admin_conf_dir: "/home/vagrant/.kube" 113 | # Permissions for the directory specified in "k8s_admin_conf_dir" 114 | k8s_admin_conf_dir_perm: "0700" 115 | # Owner of the directory specified in "k8s_admin_conf_dir" and for 116 | # "admin.kubeconfig" stored in this directory. 117 | k8s_admin_conf_owner: "vagrant" 118 | # Group of the directory specified in "k8s_admin_conf_dir" and for 119 | # "admin.kubeconfig" stored in this directory. 120 | k8s_admin_conf_group: "vagrant" 121 | 122 | # Run Kubernetes control plane services as the following user. 123 | k8s_run_as_user: "k8s" 124 | # Run Kubernetes control plane services as the following group. 125 | k8s_run_as_group: "k8s" 126 | 127 | # Key used for encrypting secrets (encryption at-rest) by the 128 | # "kube-apiserver". 129 | k8s_encryption_config_key: "Y29uZmlndXJhdGlvbjIyCg==" 130 | 131 | # Additional settings for the "kube-apiserver". 132 | k8s_apiserver_settings_user: 133 | "enable-aggregator-routing": "true" 134 | 135 | k8s_worker_kubelet_settings: 136 | "config": "{{ k8s_worker_kubelet_conf_dir }}/kubelet-config.yaml" 137 | "node-ip": "{{ hostvars[inventory_hostname]['ansible_' + k8s_interface].ipv4.address }}" 138 | "kubeconfig": "{{ k8s_worker_kubelet_conf_dir }}/kubeconfig" 139 | "seccomp-default": "" 140 | 141 | # Directory for the "runc" binaries 142 | runc_bin_directory: "/usr/local/sbin" 143 | 144 | # Directory to store the "containerd" archive after download 145 | containerd_tmp_directory: "/tmp" 146 | 147 | # Use "etcd" for Cilium 148 | cilium_etcd_enabled: "true" 149 | # Delegate Cilium tasks that needs to communicate with the Kubernetes API 150 | # server to the following host. 151 | cilium_delegate_to: "test-assets" 152 | # Template directory for custom "values.yml.j2" 153 | cilium_chart_values_directory: "templates" 154 | # Show debug output for Cilium Helm commands. 155 | cilium_helm_show_commands: true 156 | cilium_etcd_interface: "{{ k8s_interface }}" 157 | cilium_etcd_client_port: 2379 158 | cilium_etcd_nodes_group: "k8s_etcd" 159 | 160 | cilium_etcd_secrets_name: "cilium-etcd-secrets" 161 | cilium_etcd_cert_directory: "{{ k8s_ca_conf_directory }}" 162 | cilium_etcd_cafile: "ca-etcd.pem" 163 | cilium_etcd_certfile: "cert-cilium.pem" 164 | cilium_etcd_keyfile: "cert-cilium-key.pem" 165 | 166 | # Delegate tasks to create CoreDNS K8s resources to this host. 167 | coredns_delegate_to: "test-assets" 168 | 169 | # Common name for "etcd" certificate authority certificates. 170 | ca_etcd_csr_cn: "etcd" 171 | ca_etcd_csr_key_algo: "ecdsa" 172 | ca_etcd_csr_key_size: "384" 173 | 174 | # Common name for "kube-apiserver" certificate authority certificate. 175 | ca_k8s_apiserver_csr_cn: "kubernetes" 176 | ca_k8s_apiserver_csr_key_algo: "ecdsa" 177 | ca_k8s_apiserver_csr_key_size: "384" 178 | 179 | # Common names for "etcd" server, peer and client certificates. 180 | etcd_server_csr_cn: "etcd-server" 181 | etcd_server_csr_key_algo: "ecdsa" 182 | etcd_server_csr_key_size: "384" 183 | 184 | etcd_peer_csr_cn: "etcd-peer" 185 | etcd_peer_csr_key_algo: "ecdsa" 186 | etcd_peer_csr_key_size: "384" 187 | 188 | etcd_client_csr_cn_prefix: "etcd-client" 189 | etcd_client_csr_key_algo: "ecdsa" 190 | etcd_client_csr_key_size: "384" 191 | 192 | # Common names for kube-apiserver, admin and kube-controller-manager certificates. 193 | k8s_apiserver_csr_cn: "k8s-apiserver" 194 | k8s_apiserver_csr_key_algo: "ecdsa" 195 | k8s_apiserver_csr_key_size: "384" 196 | 197 | k8s_admin_csr_cn: "k8s-admin" 198 | k8s_admin_csr_key_algo: "ecdsa" 199 | k8s_admin_csr_key_size: "384" 200 | 201 | k8s_worker_csr_key_algo: "ecdsa" 202 | k8s_worker_csr_key_size: "384" 203 | 204 | k8s_controller_manager_csr_key_algo: "ecdsa" 205 | k8s_controller_manager_csr_key_size: "384" 206 | 207 | k8s_scheduler_csr_key_algo: "ecdsa" 208 | k8s_scheduler_csr_key_size: "384" 209 | 210 | k8s_controller_manager_sa_csr_cn: "k8s-service-accounts" 211 | k8s_controller_manager_sa_csr_key_algo: "ecdsa" 212 | k8s_controller_manager_sa_csr_key_size: "384" 213 | 214 | k8s_kube_proxy_csr_key_algo: "ecdsa" 215 | k8s_kube_proxy_csr_key_size: "384" 216 | -------------------------------------------------------------------------------- /tasks/upgrade.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Copyright (C) 2020-2025 Robert Wimmer 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | 5 | - name: Ensure Cilium etcd secrets in k8s 6 | when: 7 | - cilium_etcd_enabled is defined 8 | - cilium_etcd_enabled == "true" 9 | - cilium_etcd_secrets_name is defined 10 | kubernetes.core.k8s: 11 | state: present 12 | definition: "{{ lookup('template', 'etcd-secrets.yml.j2') }}" 13 | namespace: "{{ cilium_namespace }}" 14 | run_once: true 15 | delegate_to: "{{ cilium_delegate_to }}" 16 | 17 | - name: Fetch current Cilium DaemonSet information 18 | kubernetes.core.k8s_info: 19 | api_version: v1 20 | kind: DaemonSet 21 | name: "{{ cilium_release_name }}" 22 | namespace: "{{ cilium_namespace }}" 23 | register: cilium__daemonset 24 | run_once: true 25 | delegate_to: "{{ cilium_delegate_to }}" 26 | 27 | - name: Register current Cilium pods running 28 | ansible.builtin.set_fact: 29 | cilium_pods_running: "{{ cilium__daemonset | to_json | from_json | community.general.json_query(json_query) }}" 30 | vars: 31 | json_query: "resources[0].status.numberReady" 32 | run_once: true 33 | delegate_to: "{{ cilium_delegate_to }}" 34 | 35 | - name: Fetch information if there is a Cilium pre-flight check deployment leftover 36 | kubernetes.core.k8s_info: 37 | api_version: v1 38 | kind: Deployment 39 | name: cilium-pre-flight-check 40 | namespace: "{{ cilium_namespace }}" 41 | register: cilium__pre_flight_check_deployment 42 | run_once: true 43 | delegate_to: "{{ cilium_delegate_to }}" 44 | 45 | - name: Register if there is a Cilium pre-flight check deployment leftover 46 | ansible.builtin.set_fact: 47 | cilium_pre_flight_check_leftover: "{{ cilium__pre_flight_check_deployment | to_json | from_json | community.general.json_query(json_query) }}" 48 | vars: 49 | json_query: "resources[0].metadata.name" 50 | run_once: true 51 | delegate_to: "{{ cilium_delegate_to }}" 52 | 53 | - name: Delete Cilium pre-flight check leftover 54 | when: 55 | - cilium_pre_flight_check_leftover.find("cilium-pre-flight-check") != -1 56 | kubernetes.core.helm: 57 | name: "cilium-preflight" 58 | release_namespace: "{{ cilium_namespace }}" 59 | state: absent 60 | changed_when: false 61 | run_once: true 62 | delegate_to: "{{ cilium_delegate_to }}" 63 | 64 | - name: Give Kubernetes 30 secs to delete Cilium pre-flight check 65 | when: 66 | - cilium_pre_flight_check_leftover.find("cilium-pre-flight-check") != -1 67 | ansible.builtin.wait_for: 68 | timeout: 30 69 | run_once: true 70 | delegate_to: "{{ cilium_delegate_to }}" 71 | 72 | - name: Install Cilium pre-flight check 73 | kubernetes.core.helm: 74 | name: "cilium-preflight" 75 | chart_ref: "{{ cilium_chart_name }}" 76 | chart_version: "{{ cilium_chart_version }}" 77 | release_namespace: "{{ cilium_namespace }}" 78 | create_namespace: false 79 | update_repo_cache: true 80 | values: "{{ lookup('template', lookup('first_found', params)) | from_yaml }}" 81 | vars: 82 | params: 83 | files: 84 | - cilium_values_user_pre_flight_check.yml.j2 85 | - cilium_values_default_pre_flight_check.yml.j2 86 | paths: 87 | - templates 88 | changed_when: false 89 | run_once: true 90 | delegate_to: "{{ cilium_delegate_to }}" 91 | register: cilium__helm_pre_flight 92 | 93 | - name: Install Cilium pre-flight check (helm command executed) 94 | when: 95 | - cilium__helm_pre_flight is defined 96 | - cilium__helm_pre_flight.command is defined 97 | - cilium_helm_show_commands 98 | ansible.builtin.debug: 99 | var: cilium__helm_pre_flight.command 100 | run_once: true 101 | delegate_to: "{{ cilium_delegate_to }}" 102 | 103 | - name: Waiting for pre flight check to be deployed 104 | ansible.builtin.include_tasks: 105 | file: pre_flight_check.yml 106 | 107 | - name: Fetch Cilium pre flight deployment information 108 | kubernetes.core.k8s_info: 109 | api_version: v1 110 | kind: Deployment 111 | name: cilium-pre-flight-check 112 | namespace: "{{ cilium_namespace }}" 113 | register: cilium__pre_flight_deployment 114 | run_once: true 115 | delegate_to: "{{ cilium_delegate_to }}" 116 | 117 | - name: Register Cilium pre flight ready replicas 118 | ansible.builtin.set_fact: 119 | cilium_pre_flight_ready_replicas: "{{ cilium__pre_flight_deployment | to_json | from_json | community.general.json_query(json_query) }}" 120 | vars: 121 | json_query: "resources[0].status.readyReplicas" 122 | run_once: true 123 | delegate_to: "{{ cilium_delegate_to }}" 124 | 125 | - name: Register Cilium pre flight replicas 126 | ansible.builtin.set_fact: 127 | cilium_pre_flight_replicas: "{{ cilium__pre_flight_deployment | to_json | from_json | community.general.json_query(json_query) }}" 128 | vars: 129 | json_query: "resources[0].status.replicas" 130 | run_once: true 131 | delegate_to: "{{ cilium_delegate_to }}" 132 | 133 | - name: Check replica count == ready replicas 134 | when: 135 | - cilium_pre_flight_replicas | int != cilium_pre_flight_ready_replicas | int 136 | ansible.builtin.fail: 137 | msg: "Replica count ({{ cilium_pre_flight_replicas }}) != ready replicas count ({{ cilium_pre_flight_ready_replicas }})" 138 | run_once: true 139 | delegate_to: "{{ cilium_delegate_to }}" 140 | 141 | - name: Delete Cilium pre flight via Helm 142 | kubernetes.core.helm: 143 | name: "cilium-preflight" 144 | release_namespace: "{{ cilium_namespace }}" 145 | state: absent 146 | changed_when: false 147 | run_once: true 148 | delegate_to: "{{ cilium_delegate_to }}" 149 | register: cilium__helm_pre_flight_chart 150 | 151 | - name: Delete Cilium pre flight via Helm (helm command executed) 152 | when: 153 | - cilium__helm_pre_flight_chart is defined 154 | - cilium__helm_pre_flight_chart.command is defined 155 | - cilium_helm_show_commands 156 | ansible.builtin.debug: 157 | var: cilium__helm_pre_flight_chart.command 158 | delegate_to: "{{ cilium_delegate_to }}" 159 | run_once: true 160 | 161 | - name: Upgrade Cilium via Helm 162 | block: 163 | - name: Create temporary file for Helm values 164 | ansible.builtin.tempfile: 165 | state: file 166 | suffix: cilium_values 167 | run_once: true 168 | delegate_to: "{{ cilium_delegate_to }}" 169 | register: cilium__values_tmp_file 170 | 171 | - name: Select values file for Helm template 172 | ansible.builtin.template: 173 | src: "{{ lookup('first_found', params) }}" 174 | dest: "{{ cilium__values_tmp_file.path }}" 175 | mode: "0600" 176 | run_once: true 177 | delegate_to: "{{ cilium_delegate_to }}" 178 | vars: 179 | params: 180 | files: 181 | - values.yml.j2 182 | - values.yaml.j2 183 | - cilium_values_user.yml.j2 184 | - cilium_values_default.yml.j2 185 | paths: 186 | - "{{ cilium_chart_values_directory }}" 187 | - templates 188 | 189 | - name: Upgrade Helm chart 190 | kubernetes.core.helm: 191 | name: "{{ cilium_release_name }}" 192 | chart_ref: "{{ cilium_chart_name }}" 193 | chart_version: "{{ cilium_chart_version }}" 194 | release_namespace: "{{ cilium_namespace }}" 195 | force: true 196 | create_namespace: false 197 | update_repo_cache: true 198 | values_files: 199 | - "{{ cilium__values_tmp_file.path }}" 200 | run_once: true 201 | delegate_to: "{{ cilium_delegate_to }}" 202 | register: cilium__helm_upgrade_chart 203 | 204 | - name: Upgrade Helm chart (helm command executed) 205 | when: 206 | - cilium__helm_upgrade_chart is defined 207 | - cilium__helm_upgrade_chart.command is defined 208 | - cilium_helm_show_commands 209 | ansible.builtin.debug: 210 | var: cilium__helm_upgrade_chart.command 211 | changed_when: false 212 | run_once: true 213 | delegate_to: "{{ cilium_delegate_to }}" 214 | 215 | - name: Delete temporary file for Helm values 216 | when: 217 | - cilium__values_tmp_file.path is defined 218 | ansible.builtin.file: 219 | path: "{{ cilium__values_tmp_file.path }}" 220 | state: absent 221 | changed_when: false 222 | run_once: true 223 | delegate_to: "{{ cilium_delegate_to }}" 224 | 225 | rescue: 226 | - name: Delete temporary file for Helm values 227 | when: 228 | - cilium__values_tmp_file.path is defined 229 | ansible.builtin.file: 230 | path: "{{ cilium__values_tmp_file.path }}" 231 | state: absent 232 | run_once: true 233 | delegate_to: "{{ cilium_delegate_to }}" 234 | changed_when: false 235 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Changelog 7 | 8 | ## 16.0.0+1.17.8 9 | 10 | **NOTE:** Upgrading from Cilium `1.16.x` to `1.17.x` is a major release upgrade! Please read the [1.17 Upgrade Notes](https://docs.cilium.io/en/v1.17/operations/upgrade/#current-release-required-changes) carefully and adjust your settings accordingly! 11 | 12 | In general it makes sense to update to the latest Cilium `1.16.x` version first before upgrading to `1.17.x`. If you've used the default (or slightly adjusted) settings that this Ansible role provides then the upgrade should be pretty straight forward. 13 | 14 | Further reading: 15 | 16 | [Cilium 1.17.0 CHANGELOG](https://github.com/cilium/cilium/blob/v1.17.0/CHANGELOG.md) 17 | [Cilium 1.17.0 release](https://github.com/cilium/cilium/releases/tag/v1.17.0) 18 | 19 | - **Update** 20 | - upgrade to Cilium `v1.17.8` 21 | 22 | - **Molecule** 23 | - Molecule: update CoreDNS to `v1.13.1` 24 | 25 | ## 15.0.0+1.16.15 26 | 27 | - **Breaking** 28 | - `meta/main.yml`: Change `min_ansible_version` to 2.12. Ansible 2.9 is end-of-life (EOL). The `kubernetes.core.helm_repository` module used in `tasks/helm_repository.yml` requires kubernetes.core 2.3.0+, which needs Ansible 2.12+. 29 | - removed support for `Ubuntu 18.04` (reached end of life) 30 | - removed support for `Ubuntu 20.04` (reached end of life) 31 | - added support for `Ubuntu 22.04` 32 | - added support for `Ubuntu 24.04` 33 | 34 | - **Update** 35 | - upgrade to Cilium `v1.16.15` 36 | - update `.github/workflows/release.yml` 37 | 38 | - **Other** 39 | - add SPDX license identifiers (`SPDX-License-Identifier: GPL-3.0-or-later`) and copyright notices to all source files following [REUSE specification](https://reuse.software/) best practices 40 | - move full GPL-3.0-or-later license text to `LICENSES/GPL-3.0-or-later.txt` 41 | - fix `ansible-lint` issues 42 | - remove `collections.yml` + `requirements.yml` 43 | - add `.ansible` to `.gitignore` 44 | 45 | - **Molecule** 46 | - `prepare.yml`: use `ansible.builtin.pip` instead of `ansible.builtin.package` to install kubernetes collection 47 | - various changes to Molecule `default` scenario 48 | 49 | ## 14.0.1+1.16.5 50 | 51 | - **Update** 52 | - upgrade to Cilium `v1.16.5` 53 | 54 | ## 14.0.0+1.16.2 55 | 56 | **NOTE:** Upgrading from Cilium `1.15.x` to `1.16.x` is a major release upgrade! Please read the [1.16 Upgrade Notes](https://docs.cilium.io/en/v1.16/operations/upgrade/#current-release-required-changes) carefully and adjust your settings accordingly! 57 | 58 | All new features are explained in the Cilium `1.16` announcement blog: [Cilium 1.16 – High-Performance Networking With Netkit, Gateway API Gamma Support, BGPV2 and More!](https://isovalent.com/blog/post/cilium-1-16/). 59 | 60 | In general it makes sense to update to the latest Cilium `1.15.x` version first before upgrading to `1.16.x`. If you've used the default (or slightly adjusted) settings that this Ansible role provides then the upgrade should be pretty straight forward. 61 | 62 | - **Update** 63 | - upgrade to Cilium `v1.16.2` 64 | 65 | - **Other** 66 | - update `.yamllint` 67 | 68 | - **Molecule** 69 | - add a few more checks in `verify.yml` 70 | 71 | ## 13.1.0+1.15.8 72 | 73 | - **Update** 74 | - upgrade to Cilium `v1.15.8` 75 | 76 | - **Molecule** 77 | - replace Vagrant `alvistack/ubuntu-22.04` boxes with `alvistack/ubuntu-24.04` 78 | 79 | ## 13.0.0+1.15.3 80 | 81 | - **Breaking** 82 | - changes in `templates/cilium_values_default.yml.j2`: added `kubeProxyReplacement`, `nodePort` and `socketLB` (this is needed because BPF masquerade requires NodePort) 83 | 84 | - **Update** 85 | - upgrade to Cilium `v1.15.3` 86 | 87 | - **Molecule** 88 | - replace Vagrant `generic/ubuntu2204` boxes with `alvistack/ubuntu-22.04` 89 | 90 | ## 12.0.0+1.15.0 91 | 92 | - upgrade to Cilium `v1.15.0` 93 | - refactor Molecule setup 94 | - introduce `cilium_chart_values_directory` variable 95 | 96 | ## 11.0.6+1.14.5 97 | 98 | - fix Github action 99 | 100 | ## 11.0.5+1.14.5 101 | 102 | - upgrade to Cilium `v1.14.5` 103 | 104 | ## 11.0.4+1.14.4 105 | 106 | - upgrade to Cilium `v1.14.4` 107 | 108 | ## 11.0.3+1.14.3 109 | 110 | - upgrade to Cilium `v1.14.3` 111 | 112 | ## 11.0.2+1.14.1 113 | 114 | - rename `githubixx.harden-linux` to `githubixx.harden_linux` 115 | 116 | ## 11.0.1+1.14.1 117 | 118 | - rename `githubixx.kubernetes-ca` to `githubixx.kubernetes_ca` 119 | 120 | ## 11.0.0+1.14.1 121 | 122 | - upgrade to Cilium `v1.14.1` 123 | - refactor Molecule tests 124 | 125 | ## 10.0.2+1.13.4 126 | 127 | - upgrade to Cilium `v1.13.4` 128 | 129 | ## 10.0.1+1.13.2 130 | 131 | - upgrade to Cilium `v1.13.2` 132 | 133 | ## 10.0.0+1.13.0 134 | 135 | - upgrade to Cilium `v1.13.0`. Please check [](https://docs.cilium.io/en/v1.13/operations/upgrade/#current-release-required-changes) for possible incompatible changes and deprecations. 136 | - added `force:true` in case of Helm chart upgrade to make sure the upgrade happens no matter what 137 | - `tasks/pre_flight_check.yml` + `upgrade.yml`: fix ansible-lint issues 138 | 139 | ## 9.0.0+1.12.5 140 | 141 | - **BREAKING**: The `action` variable was renamed to `cilium_action` variable. This avoids variable collisions with other roles. 142 | - **BREAKING**: Allow to set Helm values for pre-flight-check in `cilium_values_user_pre_flight_check.yml.j2` or `cilium_values_default_pre_flight_check.yml.j2` templates. In previous versions these values were hard-coded in `tasks/upgrade.yml`. This change comes together with the next one: 143 | - **BREAKING**: In previous versions the Helm values for pre-flight-check were: 144 | 145 | ```yaml 146 | agent: false 147 | preflight: 148 | enabled: true 149 | operator: 150 | enabled: false 151 | ``` 152 | 153 | This was changed to: 154 | 155 | ```yaml 156 | agent: false 157 | preflight: 158 | enabled: true 159 | tolerations: 160 | - operator: Exists 161 | operator: 162 | enabled: false 163 | ``` 164 | 165 | By default Cilium gets installed on all nodes including the control plane nodes. That's because the `toleration` is set to `operator: Exists` which ignores all taints set on all Kubernetes nodes. Since the "pre-flight-check" expects that the number of current Cilium pods equals the number of "pre-flight-check" pods, the "pre-flight-check" pods needs to run on all nodes where the current Cilium pods are running. The default Helm chart values disallow running "pre-flight-check" pods running on the control-plane nodes. If you've different taints you might need to adjust the "pre-flight-check" tolerations. 166 | 167 | - upgrade to Cilium `v1.12.5` 168 | - added `.gitignore` 169 | - added `.yamlint` 170 | 171 | ## 8.0.0+1.12.3 172 | 173 | - upgrade to Cilium `v1.12.3` 174 | - introduce `cilium_delegate_to` variable. Previously this was hard coded to `127.0.0.1` and it's also the default of this variable. 175 | - introduce `cilium_helm_show_commands` variable (see README for more information) 176 | - introduce `cilium_template_output_directory` variable (see README for more information) 177 | - introduce `Molecule` tests 178 | - don't use `shell` module anymore to execute `helm` command. Now `kubernetes.core.helm*` modules are used. 179 | - use two underscores for internal variables 180 | - ansible-lint: fix various issues like using FQDN Ansible module names now 181 | - add `requirements.yml` 182 | - add `collections.yml` 183 | 184 | ## 7.1.1+1.12.1 185 | 186 | - fix YAML syntax in `tasks/main.yml` 187 | - use FQN Ansible module names for `include_tasks` 188 | 189 | ## 7.1.0+1.12.1 190 | 191 | - fix various ansible-lint issues 192 | 193 | ## 7.0.0+1.12.1 194 | 195 | - upgrade to Cilium `v1.12.1` 196 | - add Github release action to push new release to Ansible Galaxy 197 | 198 | ## 6.0.4+1.11.6 199 | 200 | - upgrade to Cilium `v1.11.6` 201 | 202 | ## 6.0.3+1.11.5 203 | 204 | - upgrade to Cilium `v1.11.5` 205 | 206 | ## 6.0.2+1.11.4 207 | 208 | - upgrade to Cilium `v1.11.4` 209 | 210 | ## 6.0.1+1.11.1 211 | 212 | - upgrade to Cilium `v1.11.1` 213 | - make sure Cilium Helm chart is installed before rendering (contribution by @tiagoblackcode) 214 | 215 | ## 6.0.0+1.11.0 216 | 217 | - upgrade to Cilium `v1.11.0` 218 | - remove unneeded directories 219 | - fix some linting issues 220 | 221 | ## 5.1.0+1.10.4 222 | 223 | - upgrade to Cilium v1.10.4 224 | - add `bpf.masquerade: true` option to enable native IP masquerade support in eBPF. The eBPF-based masquerading implementation is the most efficient implementation. It requires Linux kernel >= 4.19. See: [Cilium Masquerading](https://docs.cilium.io/en/stable/concepts/networking/masquerading/) 225 | 226 | ## 5.0.0+1.10.1 227 | 228 | - upgrade to Cilium v1.10.1 229 | 230 | ## 4.0.1+1.9.7 231 | 232 | - upgrade to Cilium v1.9.7 233 | 234 | ## 4.0.0+1.9.1 235 | 236 | - introduce variables `cilium_release_name` and `cilium_repo_name` 237 | - `cilium_chart_name` had the wrong value. The `cilium_chart_name` was actually the `cilium_release_name`. If you used the default `cilium_chart_name: "cilium"` nothing will change for you. Otherwise you may need `cilium_release_name`, `cilium_repo_name` and `cilium_chart_name` accordingly. 238 | 239 | ## 3.0.0+1.9.1 240 | 241 | - upgrade to Cilium v1.9.1 242 | - refactor `cilium_values_default.yml.j2` because re-scoped in Cilium v1.9 (see [1.9 Upgrade Notes](https://docs.cilium.io/en/v1.9/operations/upgrade/#upgrade-notes) and [values.yaml](https://github.com/cilium/cilium/blob/master/install/kubernetes/cilium/values.yaml)). Esp. value names like `agent.*`, `config.*` and `global.*` have changed. 243 | - small changes in Helm values for pre-flight check 244 | - rename extra vars `cilium_(install|upgrade|delete)=true` to `action=(install|upgrade|delete)` 245 | 246 | ## 2.0.0+1.8.4 247 | 248 | - upgrade to Cilium v1.8.4 249 | 250 | ## 2.0.0+1.8.1 251 | 252 | - upgrade to Cilium v1.8.1 253 | - handle Cilium pre-flight check leftover 254 | - add new options to `cilium_values_default.yml.j2` as recommended in upgrade guide 255 | - `upgradeCompatibility` variable value needs to be string 256 | - increase retries for pre-flight-check from 30 to 60 257 | 258 | ## 1.0.1+1.7.4 259 | 260 | - formatting / make ansible-lint happy 261 | 262 | ## 1.0.0+1.7.4 263 | 264 | - initial commit 265 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # cilium-kubernetes 7 | 8 | This Ansible role installs [Cilium](https://docs.cilium.io) network on a Kubernetes cluster. Behind the doors it uses the official [Helm chart](https://helm.cilium.io/). Currently procedures like installing, upgrading and deleting the Cilium deployment are supported. 9 | 10 | ## Versions 11 | 12 | I tag every release and try to stay with [semantic versioning](http://semver.org). If you want to use the role I recommend to checkout the latest tag. The master branch is basically development while the tags mark stable releases. But in general I try to keep master in good shape too. A tag `16.0.0+1.17.8` means this is release `16.0.0` of this role and it contains Cilium chart version `1.17.8`. If the role itself changes `X.Y.Z` before `+` will increase. If the Cilium chart version changes `X.Y.Z` after `+` will increase too. This allows to tag bugfixes and new major versions of the role while it's still developed for a specific Cilium release. 13 | 14 | ## Requirements 15 | 16 | You need to have [Helm 3](https://helm.sh/) binary installed on that host where `ansible-playbook` is executed or on that host where you delegated the playbooks to (e.g. by using `cilium_delegate_to` variable). You can either 17 | 18 | - use your favorite package manager if your distribution includes `helm` in its repository (for Archlinux use `sudo pacman -S helm` e.g.) 19 | - or use one of the Ansible `Helm` roles (e.g. [helm](https://galaxy.ansible.com/gantsign/helm) - which gets also installed if you use `ansible-galaxy role install -vr requirements.yml` 20 | - or directly download the binary from [Helm releases](https://github.com/helm/helm/releases) and put it into `/usr/local/bin/` directory e.g. 21 | 22 | A properly configured `KUBECONFIG` is also needed (which is located at `${HOME}/.kube/config` by default). Normally if `kubectl` works with your cluster then everything should be already fine in this regards. 23 | 24 | Additionally the Ansible `kubernetes.core` collection needs to be installed. This can be done by using the `collections.yml` file included in this role: `ansible-galaxy install -r collections.yml`. 25 | 26 | And of course you need a Kubernetes Cluster ;-) 27 | 28 | ## Installation 29 | 30 | - Directly download from Github (Change into Ansible roles directory before cloning. You can figure out the role path by using `ansible-config dump | grep DEFAULT_ROLES_PATH` command): 31 | `git clone https://github.com/githubixx/ansible-role-cilium-kubernetes.git githubixx.cilium_kubernetes` 32 | 33 | - Via `ansible-galaxy` command and download directly from Ansible Galaxy: 34 | `ansible-galaxy install role githubixx.cilium_kubernetes` 35 | 36 | - Create a `requirements.yml` file with the following content (this will download the role from Github) and install with `ansible-galaxy role install -r requirements.yml` (change `version` if needed): 37 | 38 | ```yaml 39 | --- 40 | roles: 41 | - name: githubixx.cilium_kubernetes 42 | src: https://github.com/githubixx/ansible-role-cilium-kubernetes.git 43 | version: 16.0.0+1.17.8 44 | ``` 45 | 46 | ## Changelog 47 | 48 | **Change history:** 49 | 50 | See full [CHANGELOG.md](https://github.com/githubixx/ansible-role-kubernetes-worker/blob/master/CHANGELOG.md) 51 | 52 | **Recent changes:** 53 | 54 | ## 16.0.0+1.17.8 55 | 56 | **NOTE:** Upgrading from Cilium `1.16.x` to `1.17.x` is a major release upgrade! Please read the [1.17 Upgrade Notes](https://docs.cilium.io/en/v1.17/operations/upgrade/#current-release-required-changes) carefully and adjust your settings accordingly! 57 | 58 | In general it makes sense to update to the latest Cilium `1.16.x` version first before upgrading to `1.17.x`. If you've used the default (or slightly adjusted) settings that this Ansible role provides then the upgrade should be pretty straight forward. 59 | 60 | Further reading: 61 | 62 | [Cilium 1.17.0 CHANGELOG](https://github.com/cilium/cilium/blob/v1.17.0/CHANGELOG.md) 63 | [Cilium 1.17.0 release](https://github.com/cilium/cilium/releases/tag/v1.17.0) 64 | 65 | - **Update** 66 | - upgrade to Cilium `v1.17.8` 67 | 68 | - **Molecule** 69 | - Molecule: update CoreDNS to `v1.13.1` 70 | 71 | ## 15.0.0+1.16.15 72 | 73 | - **Breaking** 74 | - `meta/main.yml`: Change `min_ansible_version` to 2.12. Ansible 2.9 is end-of-life (EOL). The `kubernetes.core.helm_repository` module used in `tasks/helm_repository.yml` requires kubernetes.core 2.3.0+, which needs Ansible 2.12+. 75 | - removed support for `Ubuntu 18.04` (reached end of life) 76 | - removed support for `Ubuntu 20.04` (reached end of life) 77 | - added support for `Ubuntu 22.04` 78 | - added support for `Ubuntu 24.04` 79 | 80 | - **Update** 81 | - upgrade to Cilium `v1.16.15` 82 | - update `.github/workflows/release.yml` 83 | 84 | - **Other** 85 | - add SPDX license identifiers (`SPDX-License-Identifier: GPL-3.0-or-later`) and copyright notices to all source files following [REUSE specification](https://reuse.software/) best practices 86 | - move full GPL-3.0-or-later license text to `LICENSES/GPL-3.0-or-later.txt` 87 | - fix `ansible-lint` issues 88 | - remove `collections.yml` + `requirements.yml` 89 | - add `.ansible` to `.gitignore` 90 | 91 | - **Molecule** 92 | - `prepare.yml`: use `ansible.builtin.pip` instead of `ansible.builtin.package` to install kubernetes collection 93 | - various changes to Molecule `default` scenario 94 | 95 | ## Role Variables 96 | 97 | ```yaml 98 | # Helm chart version 99 | cilium_chart_version: "1.17.8" 100 | 101 | # Helm chart name 102 | cilium_chart_name: "cilium" 103 | 104 | # Helm chart URL 105 | cilium_chart_url: "https://helm.cilium.io/" 106 | 107 | # Kubernetes namespace where Cilium resources should be installed 108 | cilium_namespace: "cilium" 109 | 110 | # Directory that contains Helm chart values file. Ansible will try to locate 111 | # a file called "values.yml.j2" or "values.yaml.j2" in the specified directory 112 | # (".j2" because you can use the usual Jinja2 template stuff there). 113 | # If not found the default "templates/cilium_values_default.yml.j2" will be 114 | # used (which can be used as a template BTW). The content of this file 115 | # will be provided to "helm install/template" command as values file. 116 | cilium_chart_values_directory: "/tmp/cilium/helm" 117 | 118 | # etcd settings. If "cilium_etcd_enabled" variable is defined and set to "true", 119 | # Cilium etcd settings are generated and deployed. Otherwise all the following 120 | # "cilium_etcd_*" settings are ignored. 121 | # 122 | cilium_etcd_enabled: "true" 123 | 124 | # Interface where etcd daemons are listening. If etcd daemons are bound to 125 | # a WireGuard interface this setting should be "wg0" (by default) e.g. 126 | # You can also use a variable like "{{ etcd_interface }}" if you used 127 | # my etcd role (https://github.com/githubixx/ansible-role-etcd) 128 | cilium_etcd_interface: "eth0" 129 | 130 | # Port where etcd daemons are listening 131 | cilium_etcd_client_port: 2379 132 | 133 | # Ansible etcd host group in Ansible's "hosts" file. This value is used in 134 | # "templates/cilium_values_default.yml.j2" template to determine the IP 135 | # addresses of the hosts where etcd daemons are listening. 136 | cilium_etcd_nodes_group: "k8s_etcd" 137 | 138 | # If this variable is defined a Kubernetes secret will be installed which 139 | # contains the certificate files defined in "cilium_etcd_cafile", 140 | # "cilium_etcd_certfile" and "cilium_etcd_keyfile" 141 | # 142 | # This causes that a secure connection (https) will be established to etcd. 143 | # This of course requires that etcd is configured to use SSL/TLS. 144 | # 145 | # If this value is not defined (e.g. commented) the rest of the "cilium_etcd_*" 146 | # settings below are ignored and connection to etcd will be established 147 | # unsecured via "http". 148 | cilium_etcd_secrets_name: "cilium-etcd-secrets" 149 | 150 | # Where to find the certificate files defined below. If you used my 151 | # Kubernetes Certificate Authority role (https://github.com/githubixx/ansible-role-kubernetes-ca) 152 | # you may already have "k8s_ca_conf_directory" variable defined which you 153 | # can re-use here. This role also generates the certificate files that can 154 | # be used for the variables below. 155 | # By default this will be "$HOME/k8s/certs" of the current user that runs 156 | # "ansible-playbook" command. 157 | cilium_etcd_cert_directory: "{{ '~/k8s/certs' | expanduser }}" 158 | 159 | # etcd certificate authority file (file will be fetched in "cilium_etcd_cert_directory") 160 | cilium_etcd_cafile: "ca-etcd.pem" 161 | 162 | # etcd certificate file (file will be fetched in "cilium_etcd_cert_directory") 163 | # Make sure that the certificate contains the IP addresses in the "Subject 164 | # Alternative Name" (SAN) of the interfaces where etcd daemons listens on 165 | # (that's the IP addresses of the interfaces defined in "cilium_etcd_interface"). 166 | # This is already handled by my Kubernetes Certificate Authority role 167 | # (https://github.com/githubixx/ansible-role-kubernetes-ca) if you used that one. 168 | cilium_etcd_certfile: "cert-cilium.pem" 169 | 170 | # etcd certificate key file (file will be fetched in "cilium_etcd_cert_directory") 171 | cilium_etcd_keyfile: "cert-cilium-key.pem" 172 | 173 | # By default all tasks that needs to communicate with the Kubernetes 174 | # cluster are executed on your local host (127.0.0.1). But if that one 175 | # doesn't have direct connection to this cluster or should be executed 176 | # elsewhere this variable can be changed accordingly. 177 | cilium_delegate_to: 127.0.0.1 178 | 179 | # Shows the "helm" command that was executed if a task uses Helm to 180 | # install, update/upgrade or deletes such a resource. 181 | cilium_helm_show_commands: false 182 | 183 | # Without "cilium_action" variable defined this role will only render a file 184 | # with all the resources that will be installed or upgraded. The rendered 185 | # file with the resources will be called "template.yml" and will be 186 | # placed in the directory specified below. 187 | cilium_template_output_directory: "{{ '~/cilium/template' | expanduser }}" 188 | ``` 189 | 190 | ## Usage 191 | 192 | The first thing to do is to check `templates/cilium_values_default.yml.j2`. This file contains the values/settings for the Cilium Helm chart that are different to the default ones which are located at [cilium/values.yaml](https://github.com/cilium/cilium/blob/master/install/kubernetes/cilium/values.yaml). The default values of this Ansible role are using a TLS enabled `etcd` cluster. If you have a self hosted/bare metal Kubernetes cluster chances are high that there is already running an `etcd` cluster for the Kubernetes API server which is the case for me. I'm using my Ansible [etcd role](https://github.com/githubixx/ansible-role-etcd) to install such an `etcd` cluster and my [Kubernetes Certificate Authority role](https://github.com/githubixx/ansible-role-kubernetes-ca) to generate the certificates. So if you used my roles you can use this Cilium role basically as is. 193 | 194 | The `templates/cilium_values_default.yml.j2` template also contains some `if` clauses to use an `etcd` cluster that is not TLS enabled. See `defaults/main.yml` to check which values can be changed. You can also introduce your own variables. To use your own values just create a file called `values.yml.j2` or `values.yaml.j2` and put it into the directory specified in `cilium_chart_values_directory`. Then this role will use that file to render the Helm values. 195 | 196 | After the values file is in place and the `defaults/main.yml` values are checked the role can be installed. Most of the role's tasks are executed locally by default so to say as quite a few tasks need to communicate with the Kubernetes API server or executing [Helm](https://helm.sh/) commands. But you can delegate this kind of tasks to a different host by using `cilium_delegate_to` variable (see above). Just make sure that the host you delegate these kind of tasks has connection to the Kubernetes API server and the user a valid `KUBECONFIG` file. 197 | 198 | The default action is to just render the Kubernetes resources YAML file after replacing all Jinja2 variables and stuff like that. In the `Example Playbook` section below there is an `Example 2 (assign tag to role)`. The role `githubixx.cilium_kubernetes` has a tag `role-cilium-kubernetes` assigned. Assuming that the values for the Helm chart should be rendered (nothing will be installed in this case) and the playbook is called `k8s.yml` execute the following command: 199 | 200 | ```bash 201 | ansible-playbook --tags=role-cilium-kubernetes k8s.yml 202 | ``` 203 | 204 | To render the template into a different directory use `cilium_template_output_directory` variable e.g.: 205 | 206 | ```bash 207 | ansible-playbook --tags=role-cilium-kubernetes --extra-vars cilium_template_output_directory="/tmp/cilium" k8s.yml 208 | ``` 209 | 210 | If you want to see the `helm` commands and the parameters which were executed in the logs you can also specify `--extra-vars cilium_helm_show_commands=true`. 211 | 212 | One of the final tasks is called `TASK [githubixx.cilium_kubernetes : Write templates to file]`. This renders the template with the resources that will be created into the directory specified in `cilium_template_output_directory`. The file will be called `template.yml`. The directory/file will be placed on your local machine to be able to inspect it. 213 | 214 | If the rendered output contains everything you need the role can be installed which finally deploys Cilium: 215 | 216 | ```bash 217 | ansible-playbook --tags=role-cilium-kubernetes --extra-vars cilium_action=install k8s.yml 218 | ``` 219 | 220 | To check if everything was deployed use the usual `kubectl` commands like `kubectl -n get pods -o wide`. 221 | 222 | As [Cilium](https://docs.cilium.io) issues updates/upgrades every few weeks/months the role also can do upgrades. The role basically executes what is described in [Cilium upgrade guide](https://docs.cilium.io/en/v1.16/operations/upgrade/). That means the Cilium pre-flight check will be installed and some checks are executed before the update actually takes place. Have a look at `tasks/upgrade.yml` to see what's happening before, during and after the update. Of course you should consult [Cilium upgrade guide](https://docs.cilium.io/en/v1.16/operations/upgrade/) in general to check for major changes and stuff like that before upgrading. Also make sure to check the [Upgrade Notes](https://docs.cilium.io/en/stable/operations/upgrade/#current-release-required-changes)! 223 | 224 | If a upgrade wasn't successful a [Roll back](https://docs.cilium.io/en/v1.16/operations/upgrade/#step-3-rolling-back) to a previous version can be basically initiated by just changing `cilium_chart_version` variable. But you should definitely read the Cilium [roll back guide](https://docs.cilium.io/en/v1.16/operations/upgrade/#step-3-rolling-back). Switching between minor releases is normally not an issue but switching from one major release to a previous one might be not so easy. 225 | 226 | Also check `templates/cilium_values_default_pre_flight_check.yml.j2`. If you need to adjust values for the `pre-flight` check you can either change that file or create a file `templates/cilium_values_user_pre_flight_check.yml.j2` with your own values. 227 | 228 | Before doing the upgrade you basically only need to change `cilium_chart_version` variable e.g. from `1.15.8` to `1.16.2` to upgrade from `1.15.8` to `1.16.2`. So to do the update run 229 | 230 | ```bash 231 | ansible-playbook --tags=role-cilium-kubernetes --extra-vars cilium_action=upgrade k8s.yml 232 | ``` 233 | 234 | As already mentioned the role already includes some checks to make sure the upgrade runs smooth but you should again check with `kubectl` if all works as expected after the upgrade. 235 | 236 | And finally if you want to get rid of Cilium you can delete all resources again: 237 | 238 | ```bash 239 | ansible-playbook --tags=role-cilium-kubernetes --extra-vars cilium_action=delete k8s.yml 240 | ``` 241 | 242 | If you don't have any CNI plugins configured this will cause `kubelet` process on the Kubernetes worker nodes to issue CNI errors every now and then because there is no CNI related stuff anymore and of course connectivity between pods on different hosts will be gone together with any network policies and stuff like that. 243 | 244 | ## Example Playbook 245 | 246 | Example 1 (without role tag): 247 | 248 | ```yaml 249 | - hosts: k8s_worker 250 | roles: 251 | - githubixx.cilium_kubernetes 252 | ``` 253 | 254 | Example 2 (assign tag to role): 255 | 256 | ```yaml 257 | - 258 | hosts: k8s_worker 259 | roles: 260 | - 261 | role: githubixx.cilium_kubernetes 262 | tags: role-cilium-kubernetes 263 | ``` 264 | 265 | ## Testing 266 | 267 | This role has a small test setup that is created using [Molecule](https://github.com/ansible-community/molecule), libvirt (vagrant-libvirt) and QEMU/KVM. Please see my blog post [Testing Ansible roles with Molecule, libvirt (vagrant-libvirt) and QEMU/KVM](https://www.tauceti.blog/posts/testing-ansible-roles-with-molecule-libvirt-vagrant-qemu-kvm/) how to setup. The test configuration is [molecule/default](https://github.com/githubixx/ansible-role-cilium-kubernetes/tree/master/molecule/default). 268 | 269 | Afterwards molecule can be executed. The following command will do a basic setup and create a template of the resources (default action see above) that will be created: 270 | 271 | ```bash 272 | molecule converge 273 | ``` 274 | 275 | Installing `Cilium` and the required resources. This will setup a few virtual machines (VM) and installs a Kubernetes cluster. That setup will be used to install `Cilium` by using this role. 276 | 277 | ```bash 278 | molecule converge -- --extra-vars cilium_action=install 279 | ``` 280 | 281 | The following command can be used to install [CoreDNS](https://github.com/githubixx/ansible-kubernetes-playbooks/tree/master/coredns) for Kubernetes DNS stuff and taints controller nodes to only run Cilium pods: 282 | 283 | ```bash 284 | molecule converge -- --extra-vars cilium_setup_networking=install 285 | ``` 286 | 287 | Upgrading `Cilium` or changing parameters: 288 | 289 | ```bash 290 | molecule converge -- --extra-vars cilium_action=upgrade 291 | ``` 292 | 293 | Deleting `Cilium` and its resources: 294 | 295 | ```bash 296 | molecule converge -- --extra-vars cilium_action=delete 297 | ``` 298 | 299 | To run a few tests use (optionally add `-v` for more output): 300 | 301 | ```bash 302 | molecule verify 303 | ``` 304 | 305 | To clean up run 306 | 307 | ```bash 308 | molecule destroy 309 | ``` 310 | 311 | ## License 312 | 313 | GNU GENERAL PUBLIC LICENSE Version 3 314 | 315 | ## Author Information 316 | 317 | [http://www.tauceti.blog](http://www.tauceti.blog) 318 | -------------------------------------------------------------------------------- /LICENSES/GPL-3.0-or-later.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | 3 | Version 3, 29 June 2007 4 | 5 | Copyright © 2007 Free Software Foundation, Inc. 6 | 7 | Everyone is permitted to copy and distribute verbatim copies of this license 8 | document, but changing it is not allowed. 9 | 10 | Preamble 11 | 12 | The GNU General Public License is a free, copyleft license for software and 13 | other kinds of works. 14 | 15 | The licenses for most software and other practical works are designed to take 16 | away your freedom to share and change the works. By contrast, the GNU General 17 | Public License is intended to guarantee your freedom to share and change all 18 | versions of a program--to make sure it remains free software for all its users. 19 | We, the Free Software Foundation, use the GNU General Public License for most 20 | of our software; it applies also to any other work released this way by its 21 | authors. You can apply it to your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not price. Our 24 | General Public Licenses are designed to make sure that you have the freedom 25 | to distribute copies of free software (and charge for them if you wish), that 26 | you receive source code or can get it if you want it, that you can change 27 | the software or use pieces of it in new free programs, and that you know you 28 | can do these things. 29 | 30 | To protect your rights, we need to prevent others from denying you these rights 31 | or asking you to surrender the rights. Therefore, you have certain responsibilities 32 | if you distribute copies of the software, or if you modify it: responsibilities 33 | to respect the freedom of others. 34 | 35 | For example, if you distribute copies of such a program, whether gratis or 36 | for a fee, you must pass on to the recipients the same freedoms that you received. 37 | You must make sure that they, too, receive or can get the source code. And 38 | you must show them these terms so they know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: (1) assert 41 | copyright on the software, and (2) offer you this License giving you legal 42 | permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains that 45 | there is no warranty for this free software. For both users' and authors' 46 | sake, the GPL requires that modified versions be marked as changed, so that 47 | their problems will not be attributed erroneously to authors of previous versions. 48 | 49 | Some devices are designed to deny users access to install or run modified 50 | versions of the software inside them, although the manufacturer can do so. 51 | This is fundamentally incompatible with the aim of protecting users' freedom 52 | to change the software. The systematic pattern of such abuse occurs in the 53 | area of products for individuals to use, which is precisely where it is most 54 | unacceptable. Therefore, we have designed this version of the GPL to prohibit 55 | the practice for those products. If such problems arise substantially in other 56 | domains, we stand ready to extend this provision to those domains in future 57 | versions of the GPL, as needed to protect the freedom of users. 58 | 59 | Finally, every program is threatened constantly by software patents. States 60 | should not allow patents to restrict development and use of software on general-purpose 61 | computers, but in those that do, we wish to avoid the special danger that 62 | patents applied to a free program could make it effectively proprietary. To 63 | prevent this, the GPL assures that patents cannot be used to render the program 64 | non-free. 65 | 66 | The precise terms and conditions for copying, distribution and modification 67 | follow. 68 | 69 | TERMS AND CONDITIONS 70 | 71 | 0. Definitions. 72 | 73 | "This License" refers to version 3 of the GNU General Public License. 74 | 75 | "Copyright" also means copyright-like laws that apply to other kinds of works, 76 | such as semiconductor masks. 77 | 78 | "The Program" refers to any copyrightable work licensed under this License. 79 | Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals 80 | or organizations. 81 | 82 | To "modify" a work means to copy from or adapt all or part of the work in 83 | a fashion requiring copyright permission, other than the making of an exact 84 | copy. The resulting work is called a "modified version" of the earlier work 85 | or a work "based on" the earlier work. 86 | 87 | A "covered work" means either the unmodified Program or a work based on the 88 | Program. 89 | 90 | To "propagate" a work means to do anything with it that, without permission, 91 | would make you directly or secondarily liable for infringement under applicable 92 | copyright law, except executing it on a computer or modifying a private copy. 93 | Propagation includes copying, distribution (with or without modification), 94 | making available to the public, and in some countries other activities as 95 | well. 96 | 97 | To "convey" a work means any kind of propagation that enables other parties 98 | to make or receive copies. Mere interaction with a user through a computer 99 | network, with no transfer of a copy, is not conveying. 100 | 101 | An interactive user interface displays "Appropriate Legal Notices" to the 102 | extent that it includes a convenient and prominently visible feature that 103 | (1) displays an appropriate copyright notice, and (2) tells the user that 104 | there is no warranty for the work (except to the extent that warranties are 105 | provided), that licensees may convey the work under this License, and how 106 | to view a copy of this License. If the interface presents a list of user commands 107 | or options, such as a menu, a prominent item in the list meets this criterion. 108 | 109 | 1. Source Code. 110 | 111 | The "source code" for a work means the preferred form of the work for making 112 | modifications to it. "Object code" means any non-source form of a work. 113 | 114 | A "Standard Interface" means an interface that either is an official standard 115 | defined by a recognized standards body, or, in the case of interfaces specified 116 | for a particular programming language, one that is widely used among developers 117 | working in that language. 118 | 119 | The "System Libraries" of an executable work include anything, other than 120 | the work as a whole, that (a) is included in the normal form of packaging 121 | a Major Component, but which is not part of that Major Component, and (b) 122 | serves only to enable use of the work with that Major Component, or to implement 123 | a Standard Interface for which an implementation is available to the public 124 | in source code form. A "Major Component", in this context, means a major essential 125 | component (kernel, window system, and so on) of the specific operating system 126 | (if any) on which the executable work runs, or a compiler used to produce 127 | the work, or an object code interpreter used to run it. 128 | 129 | The "Corresponding Source" for a work in object code form means all the source 130 | code needed to generate, install, and (for an executable work) run the object 131 | code and to modify the work, including scripts to control those activities. 132 | However, it does not include the work's System Libraries, or general-purpose 133 | tools or generally available free programs which are used unmodified in performing 134 | those activities but which are not part of the work. For example, Corresponding 135 | Source includes interface definition files associated with source files for 136 | the work, and the source code for shared libraries and dynamically linked 137 | subprograms that the work is specifically designed to require, such as by 138 | intimate data communication or control flow between those subprograms and 139 | other parts of the work. 140 | 141 | The Corresponding Source need not include anything that users can regenerate 142 | automatically from other parts of the Corresponding Source. 143 | 144 | The Corresponding Source for a work in source code form is that same work. 145 | 146 | 2. Basic Permissions. 147 | 148 | All rights granted under this License are granted for the term of copyright 149 | on the Program, and are irrevocable provided the stated conditions are met. 150 | This License explicitly affirms your unlimited permission to run the unmodified 151 | Program. The output from running a covered work is covered by this License 152 | only if the output, given its content, constitutes a covered work. This License 153 | acknowledges your rights of fair use or other equivalent, as provided by copyright 154 | law. 155 | 156 | You may make, run and propagate covered works that you do not convey, without 157 | conditions so long as your license otherwise remains in force. You may convey 158 | covered works to others for the sole purpose of having them make modifications 159 | exclusively for you, or provide you with facilities for running those works, 160 | provided that you comply with the terms of this License in conveying all material 161 | for which you do not control copyright. Those thus making or running the covered 162 | works for you must do so exclusively on your behalf, under your direction 163 | and control, on terms that prohibit them from making any copies of your copyrighted 164 | material outside their relationship with you. 165 | 166 | Conveying under any other circumstances is permitted solely under the conditions 167 | stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 168 | 169 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 170 | 171 | No covered work shall be deemed part of an effective technological measure 172 | under any applicable law fulfilling obligations under article 11 of the WIPO 173 | copyright treaty adopted on 20 December 1996, or similar laws prohibiting 174 | or restricting circumvention of such measures. 175 | 176 | When you convey a covered work, you waive any legal power to forbid circumvention 177 | of technological measures to the extent such circumvention is effected by 178 | exercising rights under this License with respect to the covered work, and 179 | you disclaim any intention to limit operation or modification of the work 180 | as a means of enforcing, against the work's users, your or third parties' 181 | legal rights to forbid circumvention of technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you receive 186 | it, in any medium, provided that you conspicuously and appropriately publish 187 | on each copy an appropriate copyright notice; keep intact all notices stating 188 | that this License and any non-permissive terms added in accord with section 189 | 7 apply to the code; keep intact all notices of the absence of any warranty; 190 | and give all recipients a copy of this License along with the Program. 191 | 192 | You may charge any price or no price for each copy that you convey, and you 193 | may offer support or warranty protection for a fee. 194 | 195 | 5. Conveying Modified Source Versions. 196 | 197 | You may convey a work based on the Program, or the modifications to produce 198 | it from the Program, in the form of source code under the terms of section 199 | 4, provided that you also meet all of these conditions: 200 | 201 | a) The work must carry prominent notices stating that you modified it, and 202 | giving a relevant date. 203 | 204 | b) The work must carry prominent notices stating that it is released under 205 | this License and any conditions added under section 7. This requirement modifies 206 | the requirement in section 4 to "keep intact all notices". 207 | 208 | c) You must license the entire work, as a whole, under this License to anyone 209 | who comes into possession of a copy. This License will therefore apply, along 210 | with any applicable section 7 additional terms, to the whole of the work, 211 | and all its parts, regardless of how they are packaged. This License gives 212 | no permission to license the work in any other way, but it does not invalidate 213 | such permission if you have separately received it. 214 | 215 | d) If the work has interactive user interfaces, each must display Appropriate 216 | Legal Notices; however, if the Program has interactive interfaces that do 217 | not display Appropriate Legal Notices, your work need not make them do so. 218 | 219 | A compilation of a covered work with other separate and independent works, 220 | which are not by their nature extensions of the covered work, and which are 221 | not combined with it such as to form a larger program, in or on a volume of 222 | a storage or distribution medium, is called an "aggregate" if the compilation 223 | and its resulting copyright are not used to limit the access or legal rights 224 | of the compilation's users beyond what the individual works permit. Inclusion 225 | of a covered work in an aggregate does not cause this License to apply to 226 | the other parts of the aggregate. 227 | 228 | 6. Conveying Non-Source Forms. 229 | 230 | You may convey a covered work in object code form under the terms of sections 231 | 4 and 5, provided that you also convey the machine-readable Corresponding 232 | Source under the terms of this License, in one of these ways: 233 | 234 | a) Convey the object code in, or embodied in, a physical product (including 235 | a physical distribution medium), accompanied by the Corresponding Source fixed 236 | on a durable physical medium customarily used for software interchange. 237 | 238 | b) Convey the object code in, or embodied in, a physical product (including 239 | a physical distribution medium), accompanied by a written offer, valid for 240 | at least three years and valid for as long as you offer spare parts or customer 241 | support for that product model, to give anyone who possesses the object code 242 | either (1) a copy of the Corresponding Source for all the software in the 243 | product that is covered by this License, on a durable physical medium customarily 244 | used for software interchange, for a price no more than your reasonable cost 245 | of physically performing this conveying of source, or (2) access to copy the 246 | Corresponding Source from a network server at no charge. 247 | 248 | c) Convey individual copies of the object code with a copy of the written 249 | offer to provide the Corresponding Source. This alternative is allowed only 250 | occasionally and noncommercially, and only if you received the object code 251 | with such an offer, in accord with subsection 6b. 252 | 253 | d) Convey the object code by offering access from a designated place (gratis 254 | or for a charge), and offer equivalent access to the Corresponding Source 255 | in the same way through the same place at no further charge. You need not 256 | require recipients to copy the Corresponding Source along with the object 257 | code. If the place to copy the object code is a network server, the Corresponding 258 | Source may be on a different server (operated by you or a third party) that 259 | supports equivalent copying facilities, provided you maintain clear directions 260 | next to the object code saying where to find the Corresponding Source. Regardless 261 | of what server hosts the Corresponding Source, you remain obligated to ensure 262 | that it is available for as long as needed to satisfy these requirements. 263 | 264 | e) Convey the object code using peer-to-peer transmission, provided you inform 265 | other peers where the object code and Corresponding Source of the work are 266 | being offered to the general public at no charge under subsection 6d. 267 | 268 | A separable portion of the object code, whose source code is excluded from 269 | the Corresponding Source as a System Library, need not be included in conveying 270 | the object code work. 271 | 272 | A "User Product" is either (1) a "consumer product", which means any tangible 273 | personal property which is normally used for personal, family, or household 274 | purposes, or (2) anything designed or sold for incorporation into a dwelling. 275 | In determining whether a product is a consumer product, doubtful cases shall 276 | be resolved in favor of coverage. For a particular product received by a particular 277 | user, "normally used" refers to a typical or common use of that class of product, 278 | regardless of the status of the particular user or of the way in which the 279 | particular user actually uses, or expects or is expected to use, the product. 280 | A product is a consumer product regardless of whether the product has substantial 281 | commercial, industrial or non-consumer uses, unless such uses represent the 282 | only significant mode of use of the product. 283 | 284 | "Installation Information" for a User Product means any methods, procedures, 285 | authorization keys, or other information required to install and execute modified 286 | versions of a covered work in that User Product from a modified version of 287 | its Corresponding Source. The information must suffice to ensure that the 288 | continued functioning of the modified object code is in no case prevented 289 | or interfered with solely because modification has been made. 290 | 291 | If you convey an object code work under this section in, or with, or specifically 292 | for use in, a User Product, and the conveying occurs as part of a transaction 293 | in which the right of possession and use of the User Product is transferred 294 | to the recipient in perpetuity or for a fixed term (regardless of how the 295 | transaction is characterized), the Corresponding Source conveyed under this 296 | section must be accompanied by the Installation Information. But this requirement 297 | does not apply if neither you nor any third party retains the ability to install 298 | modified object code on the User Product (for example, the work has been installed 299 | in ROM). 300 | 301 | The requirement to provide Installation Information does not include a requirement 302 | to continue to provide support service, warranty, or updates for a work that 303 | has been modified or installed by the recipient, or for the User Product in 304 | which it has been modified or installed. Access to a network may be denied 305 | when the modification itself materially and adversely affects the operation 306 | of the network or violates the rules and protocols for communication across 307 | the network. 308 | 309 | Corresponding Source conveyed, and Installation Information provided, in accord 310 | with this section must be in a format that is publicly documented (and with 311 | an implementation available to the public in source code form), and must require 312 | no special password or key for unpacking, reading or copying. 313 | 314 | 7. Additional Terms. 315 | 316 | "Additional permissions" are terms that supplement the terms of this License 317 | by making exceptions from one or more of its conditions. Additional permissions 318 | that are applicable to the entire Program shall be treated as though they 319 | were included in this License, to the extent that they are valid under applicable 320 | law. If additional permissions apply only to part of the Program, that part 321 | may be used separately under those permissions, but the entire Program remains 322 | governed by this License without regard to the additional permissions. 323 | 324 | When you convey a copy of a covered work, you may at your option remove any 325 | additional permissions from that copy, or from any part of it. (Additional 326 | permissions may be written to require their own removal in certain cases when 327 | you modify the work.) You may place additional permissions on material, added 328 | by you to a covered work, for which you have or can give appropriate copyright 329 | permission. 330 | 331 | Notwithstanding any other provision of this License, for material you add 332 | to a covered work, you may (if authorized by the copyright holders of that 333 | material) supplement the terms of this License with terms: 334 | 335 | a) Disclaiming warranty or limiting liability differently from the terms of 336 | sections 15 and 16 of this License; or 337 | 338 | b) Requiring preservation of specified reasonable legal notices or author 339 | attributions in that material or in the Appropriate Legal Notices displayed 340 | by works containing it; or 341 | 342 | c) Prohibiting misrepresentation of the origin of that material, or requiring 343 | that modified versions of such material be marked in reasonable ways as different 344 | from the original version; or 345 | 346 | d) Limiting the use for publicity purposes of names of licensors or authors 347 | of the material; or 348 | 349 | e) Declining to grant rights under trademark law for use of some trade names, 350 | trademarks, or service marks; or 351 | 352 | f) Requiring indemnification of licensors and authors of that material by 353 | anyone who conveys the material (or modified versions of it) with contractual 354 | assumptions of liability to the recipient, for any liability that these contractual 355 | assumptions directly impose on those licensors and authors. 356 | 357 | All other non-permissive additional terms are considered "further restrictions" 358 | within the meaning of section 10. If the Program as you received it, or any 359 | part of it, contains a notice stating that it is governed by this License 360 | along with a term that is a further restriction, you may remove that term. 361 | If a license document contains a further restriction but permits relicensing 362 | or conveying under this License, you may add to a covered work material governed 363 | by the terms of that license document, provided that the further restriction 364 | does not survive such relicensing or conveying. 365 | 366 | If you add terms to a covered work in accord with this section, you must place, 367 | in the relevant source files, a statement of the additional terms that apply 368 | to those files, or a notice indicating where to find the applicable terms. 369 | 370 | Additional terms, permissive or non-permissive, may be stated in the form 371 | of a separately written license, or stated as exceptions; the above requirements 372 | apply either way. 373 | 374 | 8. Termination. 375 | 376 | You may not propagate or modify a covered work except as expressly provided 377 | under this License. Any attempt otherwise to propagate or modify it is void, 378 | and will automatically terminate your rights under this License (including 379 | any patent licenses granted under the third paragraph of section 11). 380 | 381 | However, if you cease all violation of this License, then your license from 382 | a particular copyright holder is reinstated (a) provisionally, unless and 383 | until the copyright holder explicitly and finally terminates your license, 384 | and (b) permanently, if the copyright holder fails to notify you of the violation 385 | by some reasonable means prior to 60 days after the cessation. 386 | 387 | Moreover, your license from a particular copyright holder is reinstated permanently 388 | if the copyright holder notifies you of the violation by some reasonable means, 389 | this is the first time you have received notice of violation of this License 390 | (for any work) from that copyright holder, and you cure the violation prior 391 | to 30 days after your receipt of the notice. 392 | 393 | Termination of your rights under this section does not terminate the licenses 394 | of parties who have received copies or rights from you under this License. 395 | If your rights have been terminated and not permanently reinstated, you do 396 | not qualify to receive new licenses for the same material under section 10. 397 | 398 | 9. Acceptance Not Required for Having Copies. 399 | 400 | You are not required to accept this License in order to receive or run a copy 401 | of the Program. Ancillary propagation of a covered work occurring solely as 402 | a consequence of using peer-to-peer transmission to receive a copy likewise 403 | does not require acceptance. However, nothing other than this License grants 404 | you permission to propagate or modify any covered work. These actions infringe 405 | copyright if you do not accept this License. Therefore, by modifying or propagating 406 | a covered work, you indicate your acceptance of this License to do so. 407 | 408 | 10. Automatic Licensing of Downstream Recipients. 409 | 410 | Each time you convey a covered work, the recipient automatically receives 411 | a license from the original licensors, to run, modify and propagate that work, 412 | subject to this License. You are not responsible for enforcing compliance 413 | by third parties with this License. 414 | 415 | An "entity transaction" is a transaction transferring control of an organization, 416 | or substantially all assets of one, or subdividing an organization, or merging 417 | organizations. If propagation of a covered work results from an entity transaction, 418 | each party to that transaction who receives a copy of the work also receives 419 | whatever licenses to the work the party's predecessor in interest had or could 420 | give under the previous paragraph, plus a right to possession of the Corresponding 421 | Source of the work from the predecessor in interest, if the predecessor has 422 | it or can get it with reasonable efforts. 423 | 424 | You may not impose any further restrictions on the exercise of the rights 425 | granted or affirmed under this License. For example, you may not impose a 426 | license fee, royalty, or other charge for exercise of rights granted under 427 | this License, and you may not initiate litigation (including a cross-claim 428 | or counterclaim in a lawsuit) alleging that any patent claim is infringed 429 | by making, using, selling, offering for sale, or importing the Program or 430 | any portion of it. 431 | 432 | 11. Patents. 433 | 434 | A "contributor" is a copyright holder who authorizes use under this License 435 | of the Program or a work on which the Program is based. The work thus licensed 436 | is called the contributor's "contributor version". 437 | 438 | A contributor's "essential patent claims" are all patent claims owned or controlled 439 | by the contributor, whether already acquired or hereafter acquired, that would 440 | be infringed by some manner, permitted by this License, of making, using, 441 | or selling its contributor version, but do not include claims that would be 442 | infringed only as a consequence of further modification of the contributor 443 | version. For purposes of this definition, "control" includes the right to 444 | grant patent sublicenses in a manner consistent with the requirements of this 445 | License. 446 | 447 | Each contributor grants you a non-exclusive, worldwide, royalty-free patent 448 | license under the contributor's essential patent claims, to make, use, sell, 449 | offer for sale, import and otherwise run, modify and propagate the contents 450 | of its contributor version. 451 | 452 | In the following three paragraphs, a "patent license" is any express agreement 453 | or commitment, however denominated, not to enforce a patent (such as an express 454 | permission to practice a patent or covenant not to sue for patent infringement). 455 | To "grant" such a patent license to a party means to make such an agreement 456 | or commitment not to enforce a patent against the party. 457 | 458 | If you convey a covered work, knowingly relying on a patent license, and the 459 | Corresponding Source of the work is not available for anyone to copy, free 460 | of charge and under the terms of this License, through a publicly available 461 | network server or other readily accessible means, then you must either (1) 462 | cause the Corresponding Source to be so available, or (2) arrange to deprive 463 | yourself of the benefit of the patent license for this particular work, or 464 | (3) arrange, in a manner consistent with the requirements of this License, 465 | to extend the patent license to downstream recipients. "Knowingly relying" 466 | means you have actual knowledge that, but for the patent license, your conveying 467 | the covered work in a country, or your recipient's use of the covered work 468 | in a country, would infringe one or more identifiable patents in that country 469 | that you have reason to believe are valid. 470 | 471 | If, pursuant to or in connection with a single transaction or arrangement, 472 | you convey, or propagate by procuring conveyance of, a covered work, and grant 473 | a patent license to some of the parties receiving the covered work authorizing 474 | them to use, propagate, modify or convey a specific copy of the covered work, 475 | then the patent license you grant is automatically extended to all recipients 476 | of the covered work and works based on it. 477 | 478 | A patent license is "discriminatory" if it does not include within the scope 479 | of its coverage, prohibits the exercise of, or is conditioned on the non-exercise 480 | of one or more of the rights that are specifically granted under this License. 481 | You may not convey a covered work if you are a party to an arrangement with 482 | a third party that is in the business of distributing software, under which 483 | you make payment to the third party based on the extent of your activity of 484 | conveying the work, and under which the third party grants, to any of the 485 | parties who would receive the covered work from you, a discriminatory patent 486 | license (a) in connection with copies of the covered work conveyed by you 487 | (or copies made from those copies), or (b) primarily for and in connection 488 | with specific products or compilations that contain the covered work, unless 489 | you entered into that arrangement, or that patent license was granted, prior 490 | to 28 March 2007. 491 | 492 | Nothing in this License shall be construed as excluding or limiting any implied 493 | license or other defenses to infringement that may otherwise be available 494 | to you under applicable patent law. 495 | 496 | 12. No Surrender of Others' Freedom. 497 | 498 | If conditions are imposed on you (whether by court order, agreement or otherwise) 499 | that contradict the conditions of this License, they do not excuse you from 500 | the conditions of this License. If you cannot convey a covered work so as 501 | to satisfy simultaneously your obligations under this License and any other 502 | pertinent obligations, then as a consequence you may not convey it at all. 503 | For example, if you agree to terms that obligate you to collect a royalty 504 | for further conveying from those to whom you convey the Program, the only 505 | way you could satisfy both those terms and this License would be to refrain 506 | entirely from conveying the Program. 507 | 508 | 13. Use with the GNU Affero General Public License. 509 | 510 | Notwithstanding any other provision of this License, you have permission to 511 | link or combine any covered work with a work licensed under version 3 of the 512 | GNU Affero General Public License into a single combined work, and to convey 513 | the resulting work. The terms of this License will continue to apply to the 514 | part which is the covered work, but the special requirements of the GNU Affero 515 | General Public License, section 13, concerning interaction through a network 516 | will apply to the combination as such. 517 | 518 | 14. Revised Versions of this License. 519 | 520 | The Free Software Foundation may publish revised and/or new versions of the 521 | GNU General Public License from time to time. Such new versions will be similar 522 | in spirit to the present version, but may differ in detail to address new 523 | problems or concerns. 524 | 525 | Each version is given a distinguishing version number. If the Program specifies 526 | that a certain numbered version of the GNU General Public License "or any 527 | later version" applies to it, you have the option of following the terms and 528 | conditions either of that numbered version or of any later version published 529 | by the Free Software Foundation. If the Program does not specify a version 530 | number of the GNU General Public License, you may choose any version ever 531 | published by the Free Software Foundation. 532 | 533 | If the Program specifies that a proxy can decide which future versions of 534 | the GNU General Public License can be used, that proxy's public statement 535 | of acceptance of a version permanently authorizes you to choose that version 536 | for the Program. 537 | 538 | Later license versions may give you additional or different permissions. However, 539 | no additional obligations are imposed on any author or copyright holder as 540 | a result of your choosing to follow a later version. 541 | 542 | 15. Disclaimer of Warranty. 543 | 544 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE 545 | LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 546 | OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 547 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 548 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 549 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM 550 | PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 551 | CORRECTION. 552 | 553 | 16. Limitation of Liability. 554 | 555 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL 556 | ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM 557 | AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, 558 | INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO 559 | USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 560 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE 561 | PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER 562 | PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 563 | 564 | 17. Interpretation of Sections 15 and 16. 565 | 566 | If the disclaimer of warranty and limitation of liability provided above cannot 567 | be given local legal effect according to their terms, reviewing courts shall 568 | apply local law that most closely approximates an absolute waiver of all civil 569 | liability in connection with the Program, unless a warranty or assumption 570 | of liability accompanies a copy of the Program in return for a fee. END OF 571 | TERMS AND CONDITIONS 572 | 573 | How to Apply These Terms to Your New Programs 574 | 575 | If you develop a new program, and you want it to be of the greatest possible 576 | use to the public, the best way to achieve this is to make it free software 577 | which everyone can redistribute and change under these terms. 578 | 579 | To do so, attach the following notices to the program. It is safest to attach 580 | them to the start of each source file to most effectively state the exclusion 581 | of warranty; and each file should have at least the "copyright" line and a 582 | pointer to where the full notice is found. 583 | 584 | 585 | 586 | Copyright (C) 587 | 588 | This program is free software: you can redistribute it and/or modify it under 589 | the terms of the GNU General Public License as published by the Free Software 590 | Foundation, either version 3 of the License, or (at your option) any later 591 | version. 592 | 593 | This program is distributed in the hope that it will be useful, but WITHOUT 594 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 595 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 596 | 597 | You should have received a copy of the GNU General Public License along with 598 | this program. If not, see . 599 | 600 | Also add information on how to contact you by electronic and paper mail. 601 | 602 | If the program does terminal interaction, make it output a short notice like 603 | this when it starts in an interactive mode: 604 | 605 | Copyright (C) 606 | 607 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 608 | 609 | This is free software, and you are welcome to redistribute it under certain 610 | conditions; type `show c' for details. 611 | 612 | The hypothetical commands `show w' and `show c' should show the appropriate 613 | parts of the General Public License. Of course, your program's commands might 614 | be different; for a GUI interface, you would use an "about box". 615 | 616 | You should also get your employer (if you work as a programmer) or school, 617 | if any, to sign a "copyright disclaimer" for the program, if necessary. For 618 | more information on this, and how to apply and follow the GNU GPL, see . 619 | 620 | The GNU General Public License does not permit incorporating your program 621 | into proprietary programs. If your program is a subroutine library, you may 622 | consider it more useful to permit linking proprietary applications with the 623 | library. If this is what you want to do, use the GNU Lesser General Public 624 | License instead of this License. But first, please read . 626 | --------------------------------------------------------------------------------