actualized for kubespray version 2.28.0
This commit is contained in:
@@ -14,8 +14,6 @@ etcd_cert_alt_ips: []
|
||||
etcd_heartbeat_interval: "250"
|
||||
etcd_election_timeout: "5000"
|
||||
|
||||
# etcd_snapshot_count: "10000"
|
||||
|
||||
etcd_metrics: "basic"
|
||||
|
||||
## A dictionary of extra environment variables to add to etcd.env, formatted like:
|
||||
|
||||
@@ -4,7 +4,7 @@ kube_kubeadm_scheduler_extra_args: {}
|
||||
|
||||
# Associated interface must be reachable by the rest of the cluster, and by
|
||||
# CLI/web clients.
|
||||
kube_scheduler_bind_address: 0.0.0.0
|
||||
kube_scheduler_bind_address: "::"
|
||||
|
||||
# ClientConnection options (e.g. Burst, QPS) except from kubeconfig.
|
||||
kube_scheduler_client_conn_extra_opts: {}
|
||||
|
||||
@@ -5,8 +5,8 @@ upgrade_cluster_setup: false
|
||||
# By default the external API listens on all interfaces, this can be changed to
|
||||
# listen on a specific address/interface.
|
||||
# NOTE: If you specific address/interface and use loadbalancer_apiserver_localhost
|
||||
# loadbalancer_apiserver_localhost (nginx/haproxy) will deploy on masters on 127.0.0.1:{{ loadbalancer_apiserver_port | default(kube_apiserver_port) }} too.
|
||||
kube_apiserver_bind_address: 0.0.0.0
|
||||
# loadbalancer_apiserver_localhost (nginx/haproxy) will deploy on control plane nodes on 127.0.0.1:{{ loadbalancer_apiserver_port | default(kube_apiserver_port) }} too.
|
||||
kube_apiserver_bind_address: "::"
|
||||
|
||||
# A port range to reserve for services with NodePort visibility.
|
||||
# Inclusive at both ends of the range.
|
||||
@@ -29,7 +29,7 @@ kube_etcd_key_file: node-{{ inventory_hostname }}-key.pem
|
||||
|
||||
# Associated interfaces must be reachable by the rest of the cluster, and by
|
||||
# CLI/web clients.
|
||||
kube_controller_manager_bind_address: 0.0.0.0
|
||||
kube_controller_manager_bind_address: "::"
|
||||
|
||||
# Leader election lease durations and timeouts for controller-manager
|
||||
kube_controller_manager_leader_elect_lease_duration: 15s
|
||||
@@ -38,7 +38,7 @@ kube_controller_manager_leader_elect_renew_deadline: 10s
|
||||
# discovery_timeout modifies the discovery timeout
|
||||
discovery_timeout: 5m0s
|
||||
|
||||
# Instruct first master to refresh kubeadm token
|
||||
# Instruct first control plane node to refresh kubeadm token
|
||||
kubeadm_refresh_token: true
|
||||
|
||||
# Scale down coredns replicas to 0 if not using coredns dns_mode
|
||||
@@ -107,18 +107,29 @@ kube_apiserver_admission_control_config_file: false
|
||||
# cache_size: <cache_size_value>
|
||||
kube_apiserver_admission_event_rate_limits: {}
|
||||
|
||||
## PodSecurityAdmission plugin configuration
|
||||
kube_pod_security_use_default: false
|
||||
kube_pod_security_default_enforce: baseline
|
||||
kube_pod_security_default_enforce_version: "{{ kube_major_version }}"
|
||||
kube_pod_security_default_enforce_version: "v{{ kube_major_version }}"
|
||||
kube_pod_security_default_audit: restricted
|
||||
kube_pod_security_default_audit_version: "{{ kube_major_version }}"
|
||||
kube_pod_security_default_audit_version: "v{{ kube_major_version }}"
|
||||
kube_pod_security_default_warn: restricted
|
||||
kube_pod_security_default_warn_version: "{{ kube_major_version }}"
|
||||
kube_pod_security_default_warn_version: "v{{ kube_major_version }}"
|
||||
kube_pod_security_exemptions_usernames: []
|
||||
kube_pod_security_exemptions_runtime_class_names: []
|
||||
kube_pod_security_exemptions_namespaces:
|
||||
- kube-system
|
||||
|
||||
## ResourceQuota plugin configuration
|
||||
## Resources that ResourceQuota should limit by default if no quota exists
|
||||
## Example below enforces quota on all storage classes
|
||||
# kube_resource_quota_limited_resources:
|
||||
# - apiGroup: ""
|
||||
# resource: persistentvolumeclaims
|
||||
# matchContains:
|
||||
# - .storageclass.storage.k8s.io/requests.storage
|
||||
kube_resource_quota_limited_resources: []
|
||||
|
||||
# 1.10+ list of disabled admission plugins
|
||||
kube_apiserver_disable_admission_plugins: []
|
||||
|
||||
@@ -184,13 +195,6 @@ kube_encryption_algorithm: "secretbox"
|
||||
# Which kubernetes resources to encrypt
|
||||
kube_encryption_resources: [secrets]
|
||||
|
||||
# If non-empty, will use this string as identification instead of the actual hostname
|
||||
kube_override_hostname: >-
|
||||
{%- if cloud_provider is defined and cloud_provider in ['aws'] -%}
|
||||
{%- else -%}
|
||||
{{ inventory_hostname }}
|
||||
{%- endif -%}
|
||||
|
||||
secrets_encryption_query: "resources[*].providers[0].{{ kube_encryption_algorithm }}.keys[0].secret"
|
||||
|
||||
## Support tls min version, Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13.
|
||||
@@ -238,8 +242,16 @@ kubeadm_upgrade_auto_cert_renewal: true
|
||||
|
||||
## Enable distributed tracing for kube-apiserver
|
||||
kube_apiserver_tracing: false
|
||||
kube_apiserver_tracing_endpoint: 0.0.0.0:4317
|
||||
kube_apiserver_tracing_endpoint: "[::]:4317"
|
||||
kube_apiserver_tracing_sampling_rate_per_million: 100
|
||||
|
||||
# Enable kubeadm file discovery if anonymous access has been removed
|
||||
kubeadm_use_file_discovery: "{{ remove_anonymous_access }}"
|
||||
|
||||
# imagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. Default: true
|
||||
kubeadm_image_pull_serial: true
|
||||
|
||||
# Supported asymmetric encryption algorithm types for the cluster's keys and certificates.
|
||||
# can be one of RSA-2048(default), RSA-3072, RSA-4096, ECDSA-P256
|
||||
# ref: https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta4/#kubeadm-k8s-io-v1beta4-ClusterConfiguration
|
||||
kube_asymmetric_encryption_algorithm: "RSA-2048"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
- name: Master | reload systemd
|
||||
- name: Control plane | reload systemd
|
||||
systemd_service:
|
||||
daemon_reload: true
|
||||
listen: Master | restart kubelet
|
||||
listen: Control plane | restart kubelet
|
||||
|
||||
- name: Master | reload kubelet
|
||||
- name: Control plane | reload kubelet
|
||||
service:
|
||||
name: kubelet
|
||||
state: restarted
|
||||
listen: Master | restart kubelet
|
||||
listen: Control plane | restart kubelet
|
||||
|
||||
- name: Master | Remove apiserver container docker
|
||||
- name: Control plane | Remove apiserver container docker
|
||||
shell: "set -o pipefail && docker ps -af name=k8s_kube-apiserver* -q | xargs --no-run-if-empty docker rm -f"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
@@ -19,10 +19,10 @@
|
||||
until: remove_apiserver_container.rc == 0
|
||||
delay: 1
|
||||
when: container_manager == "docker"
|
||||
listen: Master | Restart apiserver
|
||||
listen: Control plane | Restart apiserver
|
||||
|
||||
- name: Master | Remove apiserver container containerd/crio
|
||||
shell: "set -o pipefail && {{ bin_dir }}/crictl pods --name kube-apiserver* -q | xargs -I% --no-run-if-empty bash -c '{{ bin_dir }}/crictl stopp % && {{ bin_dir }}/crictl rmp %'"
|
||||
- name: Control plane | Remove apiserver container containerd/crio
|
||||
shell: "set -o pipefail && {{ bin_dir }}/crictl pods --name 'kube-apiserver*' -q | xargs -I% --no-run-if-empty bash -c '{{ bin_dir }}/crictl stopp % && {{ bin_dir }}/crictl rmp %'"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: remove_apiserver_container
|
||||
@@ -30,9 +30,9 @@
|
||||
until: remove_apiserver_container.rc == 0
|
||||
delay: 1
|
||||
when: container_manager in ['containerd', 'crio']
|
||||
listen: Master | Restart apiserver
|
||||
listen: Control plane | Restart apiserver
|
||||
|
||||
- name: Master | Remove scheduler container docker
|
||||
- name: Control plane | Remove scheduler container docker
|
||||
shell: "set -o pipefail && {{ docker_bin_dir }}/docker ps -af name=k8s_kube-scheduler* -q | xargs --no-run-if-empty {{ docker_bin_dir }}/docker rm -f"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
@@ -41,10 +41,10 @@
|
||||
until: remove_scheduler_container.rc == 0
|
||||
delay: 1
|
||||
when: container_manager == "docker"
|
||||
listen: Master | Restart kube-scheduler
|
||||
listen: Control plane | Restart kube-scheduler
|
||||
|
||||
- name: Master | Remove scheduler container containerd/crio
|
||||
shell: "set -o pipefail && {{ bin_dir }}/crictl pods --name kube-scheduler* -q | xargs -I% --no-run-if-empty bash -c '{{ bin_dir }}/crictl stopp % && {{ bin_dir }}/crictl rmp %'"
|
||||
- name: Control plane | Remove scheduler container containerd/crio
|
||||
shell: "set -o pipefail && {{ bin_dir }}/crictl pods --name 'kube-scheduler*' -q | xargs -I% --no-run-if-empty bash -c '{{ bin_dir }}/crictl stopp % && {{ bin_dir }}/crictl rmp %'"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: remove_scheduler_container
|
||||
@@ -52,9 +52,9 @@
|
||||
until: remove_scheduler_container.rc == 0
|
||||
delay: 1
|
||||
when: container_manager in ['containerd', 'crio']
|
||||
listen: Master | Restart kube-scheduler
|
||||
listen: Control plane | Restart kube-scheduler
|
||||
|
||||
- name: Master | Remove controller manager container docker
|
||||
- name: Control plane | Remove controller manager container docker
|
||||
shell: "set -o pipefail && {{ docker_bin_dir }}/docker ps -af name=k8s_kube-controller-manager* -q | xargs --no-run-if-empty {{ docker_bin_dir }}/docker rm -f"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
@@ -63,10 +63,10 @@
|
||||
until: remove_cm_container.rc == 0
|
||||
delay: 1
|
||||
when: container_manager == "docker"
|
||||
listen: Master | Restart kube-controller-manager
|
||||
listen: Control plane | Restart kube-controller-manager
|
||||
|
||||
- name: Master | Remove controller manager container containerd/crio
|
||||
shell: "set -o pipefail && {{ bin_dir }}/crictl pods --name kube-controller-manager* -q | xargs -I% --no-run-if-empty bash -c '{{ bin_dir }}/crictl stopp % && {{ bin_dir }}/crictl rmp %'"
|
||||
- name: Control plane | Remove controller manager container containerd/crio
|
||||
shell: "set -o pipefail && {{ bin_dir }}/crictl pods --name 'kube-controller-manager*' -q | xargs -I% --no-run-if-empty bash -c '{{ bin_dir }}/crictl stopp % && {{ bin_dir }}/crictl rmp %'"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
register: remove_cm_container
|
||||
@@ -74,11 +74,11 @@
|
||||
until: remove_cm_container.rc == 0
|
||||
delay: 1
|
||||
when: container_manager in ['containerd', 'crio']
|
||||
listen: Master | Restart kube-controller-manager
|
||||
listen: Control plane | Restart kube-controller-manager
|
||||
|
||||
- name: Master | wait for kube-scheduler
|
||||
- name: Control plane | wait for kube-scheduler
|
||||
vars:
|
||||
endpoint: "{{ kube_scheduler_bind_address if kube_scheduler_bind_address != '0.0.0.0' else 'localhost' }}"
|
||||
endpoint: "{{ kube_scheduler_bind_address if kube_scheduler_bind_address != '::' else 'localhost' }}"
|
||||
uri:
|
||||
url: https://{{ endpoint }}:10259/healthz
|
||||
validate_certs: false
|
||||
@@ -87,12 +87,12 @@
|
||||
retries: 60
|
||||
delay: 1
|
||||
listen:
|
||||
- Master | restart kubelet
|
||||
- Master | Restart kube-scheduler
|
||||
- Control plane | restart kubelet
|
||||
- Control plane | Restart kube-scheduler
|
||||
|
||||
- name: Master | wait for kube-controller-manager
|
||||
- name: Control plane | wait for kube-controller-manager
|
||||
vars:
|
||||
endpoint: "{{ kube_controller_manager_bind_address if kube_controller_manager_bind_address != '0.0.0.0' else 'localhost' }}"
|
||||
endpoint: "{{ kube_controller_manager_bind_address if kube_controller_manager_bind_address != '::' else 'localhost' }}"
|
||||
uri:
|
||||
url: https://{{ endpoint }}:10257/healthz
|
||||
validate_certs: false
|
||||
@@ -101,10 +101,10 @@
|
||||
retries: 60
|
||||
delay: 1
|
||||
listen:
|
||||
- Master | restart kubelet
|
||||
- Master | Restart kube-controller-manager
|
||||
- Control plane | restart kubelet
|
||||
- Control plane | Restart kube-controller-manager
|
||||
|
||||
- name: Master | wait for the apiserver to be running
|
||||
- name: Control plane | wait for the apiserver to be running
|
||||
uri:
|
||||
url: "{{ kube_apiserver_endpoint }}/healthz"
|
||||
validate_certs: false
|
||||
@@ -113,5 +113,5 @@
|
||||
retries: 60
|
||||
delay: 1
|
||||
listen:
|
||||
- Master | restart kubelet
|
||||
- Master | Restart apiserver
|
||||
- Control plane | restart kubelet
|
||||
- Control plane | Restart apiserver
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
---
|
||||
dependencies:
|
||||
- role: kubernetes/tokens
|
||||
when: kube_token_auth
|
||||
tags:
|
||||
- k8s-secrets
|
||||
- role: kubernetes/kubeadm_common
|
||||
- role: adduser
|
||||
user: "{{ addusers.etcd }}"
|
||||
when:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Kubeadm | Check api is up
|
||||
uri:
|
||||
url: "https://{{ ip | default(fallback_ip) }}:{{ kube_apiserver_port }}/healthz"
|
||||
validate_certs: false
|
||||
when: ('kube_control_plane' in group_names)
|
||||
register: _result
|
||||
retries: 60
|
||||
delay: 5
|
||||
until: _result.status == 200
|
||||
@@ -23,7 +23,7 @@
|
||||
kube_encrypt_token_extracted: "{{ secret_file_decoded | json_query(secrets_encryption_query) | first | b64decode }}"
|
||||
when: secrets_encryption_file.stat.exists
|
||||
|
||||
- name: Set kube_encrypt_token across master nodes
|
||||
- name: Set kube_encrypt_token across control plane nodes
|
||||
set_fact:
|
||||
kube_encrypt_token: "{{ kube_encrypt_token_extracted }}"
|
||||
delegate_to: "{{ item }}"
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
- kubelet.conf
|
||||
- scheduler.conf
|
||||
notify:
|
||||
- "Master | Restart kube-controller-manager"
|
||||
- "Master | Restart kube-scheduler"
|
||||
- "Master | reload kubelet"
|
||||
- "Control plane | Restart kube-controller-manager"
|
||||
- "Control plane | Restart kube-scheduler"
|
||||
- "Control plane | reload kubelet"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# noqa: jinja[spacing]
|
||||
kubeadm_discovery_address: >-
|
||||
{%- if "127.0.0.1" in kube_apiserver_endpoint or "localhost" in kube_apiserver_endpoint -%}
|
||||
{{ first_kube_control_plane_address }}:{{ kube_apiserver_port }}
|
||||
{{ first_kube_control_plane_address | ansible.utils.ipwrap }}:{{ kube_apiserver_port }}
|
||||
{%- else -%}
|
||||
{{ kube_apiserver_endpoint | regex_replace('https://', '') }}
|
||||
{%- endif %}
|
||||
@@ -24,26 +24,27 @@
|
||||
|
||||
- name: Parse certificate key if not set
|
||||
set_fact:
|
||||
kubeadm_certificate_key: "{{ hostvars[groups['kube_control_plane'][0]]['kubeadm_upload_cert'].stdout_lines[-1] | trim }}"
|
||||
kubeadm_certificate_key: "{{ hostvars[first_kube_control_plane]['kubeadm_upload_cert'].stdout_lines[-1] | trim }}"
|
||||
run_once: true
|
||||
when:
|
||||
- hostvars[groups['kube_control_plane'][0]]['kubeadm_upload_cert'] is defined
|
||||
- hostvars[groups['kube_control_plane'][0]]['kubeadm_upload_cert'] is not skipped
|
||||
- hostvars[first_kube_control_plane]['kubeadm_upload_cert'] is defined
|
||||
- hostvars[first_kube_control_plane]['kubeadm_upload_cert'] is not skipped
|
||||
|
||||
- name: Create kubeadm ControlPlane config
|
||||
template:
|
||||
src: "kubeadm-controlplane.{{ kubeadmConfig_api_version }}.yaml.j2"
|
||||
src: "kubeadm-controlplane.yaml.j2"
|
||||
dest: "{{ kube_config_dir }}/kubeadm-controlplane.yaml"
|
||||
mode: "0640"
|
||||
backup: true
|
||||
validate: "{{ kubeadm_config_validate_enabled | ternary(bin_dir + '/kubeadm config validate --config %s', omit) }}"
|
||||
when:
|
||||
- inventory_hostname != first_kube_control_plane
|
||||
- not kubeadm_already_run.stat.exists
|
||||
|
||||
- name: Wait for k8s apiserver
|
||||
wait_for:
|
||||
host: "{{ kubeadm_discovery_address.split(':')[0] }}"
|
||||
port: "{{ kubeadm_discovery_address.split(':')[1] }}"
|
||||
host: "{{ kubeadm_discovery_address | regex_replace('\\]?:\\d+$', '') | regex_replace('^\\[', '') }}"
|
||||
port: "{{ kubeadm_discovery_address.split(':')[-1] }}"
|
||||
timeout: 180
|
||||
|
||||
|
||||
@@ -87,7 +88,7 @@
|
||||
command: >-
|
||||
{{ bin_dir }}/kubeadm join
|
||||
--config {{ kube_config_dir }}/kubeadm-controlplane.yaml
|
||||
--ignore-preflight-errors=all
|
||||
--ignore-preflight-errors={{ kubeadm_ignore_preflight_errors | join(',') }}
|
||||
--skip-phases={{ kubeadm_join_phases_skip | join(',') }}
|
||||
environment:
|
||||
PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
|
||||
|
||||
@@ -35,12 +35,13 @@
|
||||
- "{{ kube_apiserver_ip }}"
|
||||
- "localhost"
|
||||
- "127.0.0.1"
|
||||
- "::1"
|
||||
sans_lb: "{{ [apiserver_loadbalancer_domain_name] if apiserver_loadbalancer_domain_name is defined else [] }}"
|
||||
sans_lb_ip: "{{ [loadbalancer_apiserver.address] if loadbalancer_apiserver is defined and loadbalancer_apiserver.address is defined else [] }}"
|
||||
sans_supp: "{{ supplementary_addresses_in_ssl_keys if supplementary_addresses_in_ssl_keys is defined else [] }}"
|
||||
sans_access_ip: "{{ groups['kube_control_plane'] | map('extract', hostvars, 'access_ip') | list | select('defined') | list }}"
|
||||
sans_ip: "{{ groups['kube_control_plane'] | map('extract', hostvars, 'ip') | list | select('defined') | list }}"
|
||||
sans_address: "{{ groups['kube_control_plane'] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) | list | select('defined') | list }}"
|
||||
sans_access_ip: "{{ groups['kube_control_plane'] | map('extract', hostvars, 'main_access_ip') | list | select('defined') | list }}"
|
||||
sans_ip: "{{ groups['kube_control_plane'] | map('extract', hostvars, 'main_ip') | list | select('defined') | list }}"
|
||||
sans_address: "{{ groups['kube_control_plane'] | map('extract', hostvars, ['ansible_default_ipv6', 'ansible_default_ipv4', 'address']) | list | select('defined') | list }}"
|
||||
sans_override: "{{ [kube_override_hostname] if kube_override_hostname else [] }}"
|
||||
sans_hostname: "{{ groups['kube_control_plane'] | map('extract', hostvars, ['ansible_hostname']) | list | select('defined') | list }}"
|
||||
sans_fqdn: "{{ groups['kube_control_plane'] | map('extract', hostvars, ['ansible_fqdn']) | list | select('defined') | list }}"
|
||||
@@ -52,21 +53,23 @@
|
||||
path: "{{ audit_policy_file | dirname }}"
|
||||
state: directory
|
||||
mode: "0640"
|
||||
when: kubernetes_audit | default(false) or kubernetes_audit_webhook | default(false)
|
||||
when: kubernetes_audit or kubernetes_audit_webhook
|
||||
|
||||
- name: Write api audit policy yaml
|
||||
template:
|
||||
src: apiserver-audit-policy.yaml.j2
|
||||
dest: "{{ audit_policy_file }}"
|
||||
mode: "0640"
|
||||
when: kubernetes_audit | default(false) or kubernetes_audit_webhook | default(false)
|
||||
when: kubernetes_audit or kubernetes_audit_webhook
|
||||
notify: Control plane | Restart apiserver
|
||||
|
||||
- name: Write api audit webhook config yaml
|
||||
template:
|
||||
src: apiserver-audit-webhook-config.yaml.j2
|
||||
dest: "{{ audit_webhook_config_file }}"
|
||||
mode: "0640"
|
||||
when: kubernetes_audit_webhook | default(false)
|
||||
when: kubernetes_audit_webhook
|
||||
notify: Control plane | Restart apiserver
|
||||
|
||||
- name: Create apiserver tracing config directory
|
||||
file:
|
||||
@@ -81,6 +84,7 @@
|
||||
dest: "{{ kube_config_dir }}/tracing/apiserver-tracing.yaml"
|
||||
mode: "0640"
|
||||
when: kube_apiserver_tracing
|
||||
notify: Control plane | Restart apiserver
|
||||
|
||||
# Nginx LB(default), If kubeadm_config_api_fqdn is defined, use other LB by kubeadm controlPlaneEndpoint.
|
||||
- name: Set kubeadm_config_api_fqdn define
|
||||
@@ -88,15 +92,12 @@
|
||||
kubeadm_config_api_fqdn: "{{ apiserver_loadbalancer_domain_name | default('lb-apiserver.kubernetes.local') }}"
|
||||
when: loadbalancer_apiserver is defined
|
||||
|
||||
- name: Set kubeadm api version to v1beta3
|
||||
set_fact:
|
||||
kubeadmConfig_api_version: v1beta3
|
||||
|
||||
- name: Kubeadm | Create kubeadm config
|
||||
template:
|
||||
src: "kubeadm-config.{{ kubeadmConfig_api_version }}.yaml.j2"
|
||||
src: "kubeadm-config.{{ kubeadm_config_api_version }}.yaml.j2"
|
||||
dest: "{{ kube_config_dir }}/kubeadm-config.yaml"
|
||||
mode: "0640"
|
||||
validate: "{{ kubeadm_config_validate_enabled | ternary(bin_dir + '/kubeadm config validate --config %s', omit) }}"
|
||||
|
||||
- name: Kubeadm | Create directory to store admission control configurations
|
||||
file:
|
||||
@@ -111,6 +112,7 @@
|
||||
dest: "{{ kube_config_dir }}/admission-controls/admission-controls.yaml"
|
||||
mode: "0640"
|
||||
when: kube_apiserver_admission_control_config_file
|
||||
notify: Control plane | Restart apiserver
|
||||
|
||||
- name: Kubeadm | Push admission control config files
|
||||
template:
|
||||
@@ -121,15 +123,7 @@
|
||||
- kube_apiserver_admission_control_config_file
|
||||
- item in kube_apiserver_admission_plugins_needs_configuration
|
||||
loop: "{{ kube_apiserver_enable_admission_plugins }}"
|
||||
|
||||
- name: Kubeadm | Configure default cluster podnodeslector
|
||||
template:
|
||||
src: "podnodeselector.yaml.j2"
|
||||
dest: "{{ kube_config_dir }}/admission-controls/podnodeselector.yaml"
|
||||
mode: "0640"
|
||||
when:
|
||||
- kube_apiserver_admission_plugins_podnodeselector_default_node_selector is defined
|
||||
- kube_apiserver_admission_plugins_podnodeselector_default_node_selector | length > 0
|
||||
notify: Control plane | Restart apiserver
|
||||
|
||||
- name: Kubeadm | Check apiserver.crt SANs
|
||||
vars:
|
||||
@@ -145,12 +139,14 @@
|
||||
loop: "{{ apiserver_ips }}"
|
||||
register: apiserver_sans_ip_check
|
||||
changed_when: apiserver_sans_ip_check.stdout is not search('does match certificate')
|
||||
failed_when: apiserver_sans_ip_check.rc != 0 and apiserver_sans_ip_check.stdout is not search('does NOT match certificate')
|
||||
- name: Kubeadm | Check apiserver.crt SAN hosts
|
||||
command:
|
||||
cmd: "openssl x509 -noout -in {{ kube_cert_dir }}/apiserver.crt -checkhost {{ item }}"
|
||||
loop: "{{ apiserver_hosts }}"
|
||||
register: apiserver_sans_host_check
|
||||
changed_when: apiserver_sans_host_check.stdout is not search('does match certificate')
|
||||
failed_when: apiserver_sans_host_check.rc != 0 and apiserver_sans_host_check.stdout is not search('does NOT match certificate')
|
||||
|
||||
- name: Kubeadm | regenerate apiserver cert 1/2
|
||||
file:
|
||||
@@ -174,38 +170,33 @@
|
||||
- apiserver_sans_ip_check.changed or apiserver_sans_host_check.changed
|
||||
- not kube_external_ca_mode
|
||||
|
||||
- name: Kubeadm | Create directory to store kubeadm patches
|
||||
file:
|
||||
path: "{{ kubeadm_patches.dest_dir }}"
|
||||
state: directory
|
||||
mode: "0640"
|
||||
when: kubeadm_patches is defined and kubeadm_patches.enabled
|
||||
|
||||
- name: Kubeadm | Copy kubeadm patches from inventory files
|
||||
copy:
|
||||
src: "{{ kubeadm_patches.source_dir }}/"
|
||||
dest: "{{ kubeadm_patches.dest_dir }}"
|
||||
owner: "root"
|
||||
mode: "0644"
|
||||
when: kubeadm_patches is defined and kubeadm_patches.enabled
|
||||
|
||||
- name: Kubeadm | Initialize first master
|
||||
command: >-
|
||||
timeout -k {{ kubeadm_init_timeout }} {{ kubeadm_init_timeout }}
|
||||
{{ bin_dir }}/kubeadm init
|
||||
--config={{ kube_config_dir }}/kubeadm-config.yaml
|
||||
--ignore-preflight-errors=all
|
||||
--skip-phases={{ kubeadm_init_phases_skip | join(',') }}
|
||||
{{ kube_external_ca_mode | ternary('', '--upload-certs') }}
|
||||
register: kubeadm_init
|
||||
# Retry is because upload config sometimes fails
|
||||
retries: 3
|
||||
until: kubeadm_init is succeeded or "field is immutable" in kubeadm_init.stderr
|
||||
- name: Kubeadm | Initialize first control plane node
|
||||
when: inventory_hostname == first_kube_control_plane and not kubeadm_already_run.stat.exists
|
||||
failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
|
||||
vars:
|
||||
kubeadm_init_first_control_plane_cmd: >-
|
||||
timeout -k {{ kubeadm_init_timeout }} {{ kubeadm_init_timeout }}
|
||||
{{ bin_dir }}/kubeadm init
|
||||
--config={{ kube_config_dir }}/kubeadm-config.yaml
|
||||
--ignore-preflight-errors={{ kubeadm_ignore_preflight_errors | join(',') }}
|
||||
--skip-phases={{ kubeadm_init_phases_skip | join(',') }}
|
||||
{{ kube_external_ca_mode | ternary('', '--upload-certs') }}
|
||||
environment:
|
||||
PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
|
||||
notify: Master | restart kubelet
|
||||
notify: Control plane | restart kubelet
|
||||
block:
|
||||
- name: Kubeadm | Initialize first control plane node (1st try)
|
||||
command: "{{ kubeadm_init_first_control_plane_cmd }}"
|
||||
register: kubeadm_init
|
||||
failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
|
||||
rescue:
|
||||
# Retry is because upload config sometimes fails
|
||||
# This retry task is separated from 1st task to show log of failure of 1st task.
|
||||
- name: Kubeadm | Initialize first control plane node (retry)
|
||||
command: "{{ kubeadm_init_first_control_plane_cmd }}"
|
||||
register: kubeadm_init
|
||||
retries: 2
|
||||
until: kubeadm_init is succeeded or "field is immutable" in kubeadm_init.stderr
|
||||
failed_when: kubeadm_init.rc != 0 and "field is immutable" not in kubeadm_init.stderr
|
||||
|
||||
- name: Set kubeadm certificate key
|
||||
set_fact:
|
||||
@@ -250,20 +241,20 @@
|
||||
tags:
|
||||
- kubeadm_token
|
||||
|
||||
- name: Kubeadm | Join other masters
|
||||
- name: Kubeadm | Join other control plane nodes
|
||||
include_tasks: kubeadm-secondary.yml
|
||||
|
||||
- name: Kubeadm | upgrade kubernetes cluster
|
||||
- name: Kubeadm | upgrade kubernetes cluster to {{ kube_version }}
|
||||
include_tasks: kubeadm-upgrade.yml
|
||||
when:
|
||||
- upgrade_cluster_setup
|
||||
- kubeadm_already_run.stat.exists
|
||||
|
||||
# FIXME(mattymo): from docs: If you don't want to taint your control-plane node, set this field to an empty slice, i.e. `taints: {}` in the YAML file.
|
||||
- name: Kubeadm | Remove taint for master with node role
|
||||
- name: Kubeadm | Remove taint for control plane node with node role
|
||||
command: "{{ kubectl }} taint node {{ inventory_hostname }} {{ item }}"
|
||||
delegate_to: "{{ first_kube_control_plane }}"
|
||||
with_items:
|
||||
- "node-role.kubernetes.io/control-plane:NoSchedule-"
|
||||
when: inventory_hostname in groups['kube_node']
|
||||
when: ('kube_node' in group_names)
|
||||
failed_when: false
|
||||
|
||||
@@ -1,55 +1,80 @@
|
||||
---
|
||||
- name: Kubeadm | Check api is up
|
||||
uri:
|
||||
url: "https://{{ ip | default(fallback_ips[inventory_hostname]) }}:{{ kube_apiserver_port }}/healthz"
|
||||
validate_certs: false
|
||||
when: inventory_hostname in groups['kube_control_plane']
|
||||
register: _result
|
||||
retries: 60
|
||||
delay: 5
|
||||
until: _result.status == 200
|
||||
- name: Ensure kube-apiserver is up before upgrade
|
||||
import_tasks: check-api.yml
|
||||
|
||||
- name: Kubeadm | Upgrade first master
|
||||
# kubeadm-config.v1beta4 with UpgradeConfiguration requires some values that were previously allowed as args to be specified in the config file
|
||||
- name: Kubeadm | Upgrade first control plane node
|
||||
command: >-
|
||||
timeout -k 600s 600s
|
||||
{{ bin_dir }}/kubeadm
|
||||
upgrade apply -y {{ kube_version }}
|
||||
{{ bin_dir }}/kubeadm upgrade apply -y v{{ kube_version }}
|
||||
{%- if kubeadm_config_api_version == 'v1beta3' %}
|
||||
--certificate-renewal={{ kubeadm_upgrade_auto_cert_renewal }}
|
||||
--ignore-preflight-errors=all
|
||||
--ignore-preflight-errors={{ kubeadm_ignore_preflight_errors | join(',') }}
|
||||
--allow-experimental-upgrades
|
||||
--etcd-upgrade={{ (etcd_deployment_type == "kubeadm") | bool | lower }}
|
||||
{% if kubeadm_patches is defined and kubeadm_patches.enabled %}--patches={{ kubeadm_patches.dest_dir }}{% endif %}
|
||||
--etcd-upgrade={{ (etcd_deployment_type == "kubeadm") | lower }}
|
||||
{% if kubeadm_patches | length > 0 %}--patches={{ kubeadm_patches_dir }}{% endif %}
|
||||
--force
|
||||
{%- else %}
|
||||
--config={{ kube_config_dir }}/kubeadm-config.yaml
|
||||
{%- endif -%}
|
||||
register: kubeadm_upgrade
|
||||
# Retry is because upload config sometimes fails
|
||||
retries: 3
|
||||
until: kubeadm_upgrade.rc == 0
|
||||
when: inventory_hostname == first_kube_control_plane
|
||||
failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
|
||||
environment:
|
||||
PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
|
||||
notify: Master | restart kubelet
|
||||
|
||||
- name: Kubeadm | Upgrade other masters
|
||||
- name: Kubeadm | Upgrade other control plane nodes
|
||||
command: >-
|
||||
timeout -k 600s 600s
|
||||
{{ bin_dir }}/kubeadm
|
||||
upgrade apply -y {{ kube_version }}
|
||||
{{ bin_dir }}/kubeadm upgrade node
|
||||
{%- if kubeadm_config_api_version == 'v1beta3' %}
|
||||
--certificate-renewal={{ kubeadm_upgrade_auto_cert_renewal }}
|
||||
--ignore-preflight-errors=all
|
||||
--allow-experimental-upgrades
|
||||
--etcd-upgrade={{ (etcd_deployment_type == "kubeadm") | bool | lower }}
|
||||
{% if kubeadm_patches is defined and kubeadm_patches.enabled %}--patches={{ kubeadm_patches.dest_dir }}{% endif %}
|
||||
--force
|
||||
--ignore-preflight-errors={{ kubeadm_ignore_preflight_errors | join(',') }}
|
||||
--etcd-upgrade={{ (etcd_deployment_type == "kubeadm") | lower }}
|
||||
{% if kubeadm_patches | length > 0 %}--patches={{ kubeadm_patches_dir }}{% endif %}
|
||||
{%- else %}
|
||||
--config={{ kube_config_dir }}/kubeadm-config.yaml
|
||||
{%- endif -%}
|
||||
register: kubeadm_upgrade
|
||||
# Retry is because upload config sometimes fails
|
||||
retries: 3
|
||||
until: kubeadm_upgrade.rc == 0
|
||||
when: inventory_hostname != first_kube_control_plane
|
||||
failed_when: kubeadm_upgrade.rc != 0 and "field is immutable" not in kubeadm_upgrade.stderr
|
||||
environment:
|
||||
PATH: "{{ bin_dir }}:{{ ansible_env.PATH }}"
|
||||
notify: Master | restart kubelet
|
||||
|
||||
# kubeadm upgrade no longer reconciles ClusterConfiguration and KubeProxyConfiguration changes, this must be done separately after upgrade to ensure the latest config is applied
|
||||
- name: Update kubeadm and kubelet configmaps after upgrade
|
||||
command: "{{ bin_dir }}/kubeadm init phase upload-config all --config {{ kube_config_dir }}/kubeadm-config.yaml"
|
||||
register: kubeadm_upload_config
|
||||
# Retry is because upload config sometimes fails
|
||||
retries: 3
|
||||
until: kubeadm_upload_config.rc == 0
|
||||
when:
|
||||
- inventory_hostname == first_kube_control_plane
|
||||
|
||||
- name: Update kube-proxy configmap after upgrade
|
||||
command: "{{ bin_dir }}/kubeadm init phase addon kube-proxy --config {{ kube_config_dir }}/kubeadm-config.yaml"
|
||||
register: kube_proxy_upload_config
|
||||
# Retry is because upload config sometimes fails
|
||||
retries: 3
|
||||
until: kube_proxy_upload_config.rc == 0
|
||||
when:
|
||||
- inventory_hostname == first_kube_control_plane
|
||||
- ('addon/kube-proxy' not in kubeadm_init_phases_skip)
|
||||
|
||||
- name: Rewrite kubeadm managed etcd static pod manifests with updated configmap
|
||||
command: "{{ bin_dir }}/kubeadm init phase etcd local --config {{ kube_config_dir }}/kubeadm-config.yaml"
|
||||
when:
|
||||
- etcd_deployment_type == "kubeadm"
|
||||
notify: Control plane | restart kubelet
|
||||
|
||||
- name: Rewrite kubernetes control plane static pod manifests with updated configmap
|
||||
command: "{{ bin_dir }}/kubeadm init phase control-plane all --config {{ kube_config_dir }}/kubeadm-config.yaml"
|
||||
notify: Control plane | restart kubelet
|
||||
|
||||
- name: Flush kubelet handlers
|
||||
meta: flush_handlers
|
||||
|
||||
- name: Ensure kube-apiserver is up after upgrade and control plane configuration updates
|
||||
import_tasks: check-api.yml
|
||||
|
||||
- name: Kubeadm | Remove binding to anonymous user
|
||||
command: "{{ kubectl }} -n kube-public delete rolebinding kubeadm:bootstrap-signer-clusterinfo --ignore-not-found"
|
||||
@@ -60,8 +85,8 @@
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- /root/.kube/cache
|
||||
- /root/.kube/http-cache
|
||||
- /root/.kube/cache
|
||||
- /root/.kube/http-cache
|
||||
|
||||
# FIXME: https://github.com/kubernetes/kubeadm/issues/1318
|
||||
- name: Kubeadm | scale down coredns replicas to 0 if not using coredns dns_mode
|
||||
@@ -75,6 +100,6 @@
|
||||
until: scale_down_coredns is succeeded
|
||||
run_once: true
|
||||
when:
|
||||
- kubeadm_scale_down_coredns_enabled
|
||||
- dns_mode not in ['coredns', 'coredns_dual']
|
||||
- kubeadm_scale_down_coredns_enabled
|
||||
- dns_mode not in ['coredns', 'coredns_dual']
|
||||
changed_when: false
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
line: ' client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem'
|
||||
backup: true
|
||||
notify:
|
||||
- "Master | reload kubelet"
|
||||
- "Control plane | reload kubelet"
|
||||
|
||||
- name: Fixup kubelet client cert rotation 2/2
|
||||
lineinfile:
|
||||
@@ -15,4 +15,4 @@
|
||||
line: ' client-key: /var/lib/kubelet/pki/kubelet-client-current.pem'
|
||||
backup: true
|
||||
notify:
|
||||
- "Master | reload kubelet"
|
||||
- "Control plane | reload kubelet"
|
||||
|
||||
@@ -18,6 +18,18 @@
|
||||
mode: "0640"
|
||||
when: kube_webhook_authorization | default(false)
|
||||
|
||||
- name: Create structured AuthorizationConfiguration file
|
||||
copy:
|
||||
content: "{{ authz_config | to_nice_yaml(indent=2, sort_keys=false) }}"
|
||||
dest: "{{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml"
|
||||
mode: "0640"
|
||||
vars:
|
||||
authz_config:
|
||||
apiVersion: apiserver.config.k8s.io/{{ kube_apiserver_authorization_config_api_version }}
|
||||
kind: AuthorizationConfiguration
|
||||
authorizers: "{{ kube_apiserver_authorization_config_authorizers }}"
|
||||
when: kube_apiserver_use_authorization_config_file
|
||||
|
||||
- name: Create kube-scheduler config
|
||||
template:
|
||||
src: kubescheduler-config.yaml.j2
|
||||
@@ -43,7 +55,7 @@
|
||||
|
||||
- name: Install kubectl bash completion
|
||||
shell: "{{ bin_dir }}/kubectl completion bash >/etc/bash_completion.d/kubectl.sh"
|
||||
when: ansible_os_family in ["Debian","RedHat"]
|
||||
when: ansible_os_family in ["Debian","RedHat", "Suse"]
|
||||
tags:
|
||||
- kubectl
|
||||
ignore_errors: true # noqa ignore-errors
|
||||
@@ -54,7 +66,7 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
when: ansible_os_family in ["Debian","RedHat"]
|
||||
when: ansible_os_family in ["Debian","RedHat", "Suse"]
|
||||
tags:
|
||||
- kubectl
|
||||
- upgrade
|
||||
@@ -73,7 +85,7 @@
|
||||
state: present
|
||||
marker: "# Ansible entries {mark}"
|
||||
when:
|
||||
- ansible_os_family in ["Debian","RedHat"]
|
||||
- ansible_os_family in ["Debian","RedHat", "Suse"]
|
||||
- kubectl_alias is defined and kubectl_alias != ""
|
||||
tags:
|
||||
- kubectl
|
||||
@@ -93,6 +105,13 @@
|
||||
- name: Include kubeadm secondary server apiserver fixes
|
||||
include_tasks: kubeadm-fix-apiserver.yml
|
||||
|
||||
- name: Cleanup unused AuthorizationConfiguration file versions
|
||||
file:
|
||||
path: "{{ kube_config_dir }}/apiserver-authorization-config-{{ item }}.yaml"
|
||||
state: absent
|
||||
loop: "{{ ['v1alpha1', 'v1beta1', 'v1'] | reject('equalto', kube_apiserver_authorization_config_api_version) | list }}"
|
||||
when: kube_apiserver_use_authorization_config_file
|
||||
|
||||
- name: Include kubelet client cert rotation fixes
|
||||
include_tasks: kubelet-fix-client-cert-rotation.yml
|
||||
when: kubelet_rotate_certificates
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: "Pre-upgrade | Delete master manifests if etcd secrets changed"
|
||||
- name: "Pre-upgrade | Delete control plane manifests if etcd secrets changed"
|
||||
file:
|
||||
path: "/etc/kubernetes/manifests/{{ item }}.manifest"
|
||||
state: absent
|
||||
@@ -8,14 +8,14 @@
|
||||
register: kube_apiserver_manifest_replaced
|
||||
when: etcd_secret_changed | default(false)
|
||||
|
||||
- name: "Pre-upgrade | Delete master containers forcefully" # noqa no-handler
|
||||
- name: "Pre-upgrade | Delete control plane containers forcefully" # noqa no-handler
|
||||
shell: "set -o pipefail && docker ps -af name=k8s_{{ item }}* -q | xargs --no-run-if-empty docker rm -f"
|
||||
args:
|
||||
executable: /bin/bash
|
||||
with_items:
|
||||
- ["kube-apiserver", "kube-controller-manager", "kube-scheduler"]
|
||||
when: kube_apiserver_manifest_replaced.changed
|
||||
register: remove_master_container
|
||||
register: remove_control_plane_container
|
||||
retries: 10
|
||||
until: remove_master_container.rc == 0
|
||||
until: remove_control_plane_container.rc == 0
|
||||
delay: 1
|
||||
|
||||
@@ -7,7 +7,7 @@ bootstrapTokens:
|
||||
ttl: "24h"
|
||||
{% endif %}
|
||||
localAPIEndpoint:
|
||||
advertiseAddress: {{ kube_apiserver_address }}
|
||||
advertiseAddress: "{{ kube_apiserver_address }}"
|
||||
bindPort: {{ kube_apiserver_port }}
|
||||
{% if kubeadm_certificate_key is defined %}
|
||||
certificateKey: {{ kubeadm_certificate_key }}
|
||||
@@ -16,7 +16,7 @@ nodeRegistration:
|
||||
{% if kube_override_hostname | default('') %}
|
||||
name: "{{ kube_override_hostname }}"
|
||||
{% endif %}
|
||||
{% if inventory_hostname in groups['kube_control_plane'] and inventory_hostname not in groups['kube_node'] %}
|
||||
{% if 'kube_control_plane' in group_names and 'kube_node' not in group_names %}
|
||||
taints:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/control-plane
|
||||
@@ -24,13 +24,13 @@ nodeRegistration:
|
||||
taints: []
|
||||
{% endif %}
|
||||
criSocket: {{ cri_socket }}
|
||||
{% if cloud_provider is defined and cloud_provider in ["external"] %}
|
||||
{% if cloud_provider == "external" %}
|
||||
kubeletExtraArgs:
|
||||
cloud-provider: external
|
||||
{% endif %}
|
||||
{% if kubeadm_patches is defined and kubeadm_patches.enabled %}
|
||||
{% if kubeadm_patches | length > 0 %}
|
||||
patches:
|
||||
directory: {{ kubeadm_patches.dest_dir }}
|
||||
directory: {{ kubeadm_patches_dir }}
|
||||
{% endif %}
|
||||
---
|
||||
apiVersion: kubeadm.k8s.io/v1beta3
|
||||
@@ -41,7 +41,7 @@ etcd:
|
||||
external:
|
||||
endpoints:
|
||||
{% for endpoint in etcd_access_addresses.split(',') %}
|
||||
- {{ endpoint }}
|
||||
- "{{ endpoint }}"
|
||||
{% endfor %}
|
||||
caFile: {{ etcd_cert_dir }}/{{ kube_etcd_cacert_file }}
|
||||
certFile: {{ etcd_cert_dir }}/{{ kube_etcd_cert_file }}
|
||||
@@ -94,9 +94,9 @@ dns:
|
||||
imageTag: {{ coredns_image_tag }}
|
||||
networking:
|
||||
dnsDomain: {{ dns_domain }}
|
||||
serviceSubnet: "{{ kube_service_addresses }}{{ ',' + kube_service_addresses_ipv6 if enable_dual_stack_networks else '' }}"
|
||||
serviceSubnet: "{{ kube_service_subnets }}"
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["kube-ovn"] %}
|
||||
podSubnet: "{{ kube_pods_subnet }}{{ ',' + kube_pods_subnet_ipv6 if enable_dual_stack_networks else '' }}"
|
||||
podSubnet: "{{ kube_pods_subnets }}"
|
||||
{% endif %}
|
||||
{% if kubeadm_feature_gates %}
|
||||
featureGates:
|
||||
@@ -104,11 +104,11 @@ featureGates:
|
||||
{{ feature | replace("=", ": ") }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
kubernetesVersion: {{ kube_version }}
|
||||
kubernetesVersion: v{{ kube_version }}
|
||||
{% if kubeadm_config_api_fqdn is defined %}
|
||||
controlPlaneEndpoint: {{ kubeadm_config_api_fqdn }}:{{ loadbalancer_apiserver.port | default(kube_apiserver_port) }}
|
||||
controlPlaneEndpoint: "{{ kubeadm_config_api_fqdn }}:{{ loadbalancer_apiserver.port | default(kube_apiserver_port) }}"
|
||||
{% else %}
|
||||
controlPlaneEndpoint: {{ ip | default(fallback_ips[inventory_hostname]) }}:{{ kube_apiserver_port }}
|
||||
controlPlaneEndpoint: "{{ main_ip | ansible.utils.ipwrap }}:{{ kube_apiserver_port }}"
|
||||
{% endif %}
|
||||
certificatesDir: {{ kube_cert_dir }}
|
||||
imageRepository: {{ kube_image_repo }}
|
||||
@@ -126,8 +126,12 @@ apiServer:
|
||||
{% if kube_api_anonymous_auth is defined %}
|
||||
anonymous-auth: "{{ kube_api_anonymous_auth }}"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_use_authorization_config_file %}
|
||||
authorization-config: "{{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml"
|
||||
{% else %}
|
||||
authorization-mode: {{ authorization_modes | join(',') }}
|
||||
bind-address: {{ kube_apiserver_bind_address }}
|
||||
{% endif %}
|
||||
bind-address: "{{ kube_apiserver_bind_address }}"
|
||||
{% if kube_apiserver_enable_admission_plugins | length > 0 %}
|
||||
enable-admission-plugins: {{ kube_apiserver_enable_admission_plugins | join(',') }}
|
||||
{% endif %}
|
||||
@@ -143,12 +147,12 @@ apiServer:
|
||||
etcd-servers-overrides: "/events#{{ etcd_events_access_addresses_semicolon }}"
|
||||
{% endif %}
|
||||
service-node-port-range: {{ kube_apiserver_node_port_range }}
|
||||
service-cluster-ip-range: "{{ kube_service_addresses }}{{ ',' + kube_service_addresses_ipv6 if enable_dual_stack_networks else '' }}"
|
||||
service-cluster-ip-range: "{{ kube_service_subnets }}"
|
||||
kubelet-preferred-address-types: "{{ kubelet_preferred_address_types }}"
|
||||
profiling: "{{ kube_profiling }}"
|
||||
request-timeout: "{{ kube_apiserver_request_timeout }}"
|
||||
enable-aggregator-routing: "{{ kube_api_aggregator_routing }}"
|
||||
{% if kube_token_auth | default(true) %}
|
||||
{% if kube_token_auth %}
|
||||
token-auth-file: {{ kube_token_dir }}/known_tokens.csv
|
||||
{% endif %}
|
||||
{% if kube_apiserver_service_account_lookup %}
|
||||
@@ -176,7 +180,7 @@ apiServer:
|
||||
{% if kube_webhook_token_auth | default(false) %}
|
||||
authentication-token-webhook-config-file: {{ kube_config_dir }}/webhook-token-auth-config.yaml
|
||||
{% endif %}
|
||||
{% if kube_webhook_authorization | default(false) %}
|
||||
{% if kube_webhook_authorization and not kube_apiserver_use_authorization_config_file %}
|
||||
authorization-webhook-config-file: {{ kube_config_dir }}/webhook-authorization-config.yaml
|
||||
{% endif %}
|
||||
{% if kube_encrypt_secret_data %}
|
||||
@@ -210,10 +214,6 @@ apiServer:
|
||||
{% if kube_apiserver_feature_gates or kube_feature_gates %}
|
||||
feature-gates: "{{ kube_apiserver_feature_gates | default(kube_feature_gates, true) | join(',') }}"
|
||||
{% endif %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] %}
|
||||
cloud-provider: {{ cloud_provider }}
|
||||
cloud-config: {{ kube_config_dir }}/cloud_config
|
||||
{% endif %}
|
||||
{% if tls_min_version is defined %}
|
||||
tls-min-version: {{ tls_min_version }}
|
||||
{% endif %}
|
||||
@@ -230,14 +230,9 @@ apiServer:
|
||||
{% if kube_apiserver_tracing %}
|
||||
tracing-config-file: {{ kube_config_dir }}/tracing/apiserver-tracing.yaml
|
||||
{% endif %}
|
||||
{% if kubernetes_audit or kube_token_auth | default(true) or kube_webhook_token_auth | default(false) or ( cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] ) or apiserver_extra_volumes or ssl_ca_dirs | length %}
|
||||
{% if kubernetes_audit or kube_token_auth or kube_webhook_token_auth or apiserver_extra_volumes or ssl_ca_dirs | length %}
|
||||
extraVolumes:
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] %}
|
||||
- name: cloud-config
|
||||
hostPath: {{ kube_config_dir }}/cloud_config
|
||||
mountPath: {{ kube_config_dir }}/cloud_config
|
||||
{% endif %}
|
||||
{% if kube_token_auth | default(true) %}
|
||||
{% if kube_token_auth %}
|
||||
- name: token-auth-config
|
||||
hostPath: {{ kube_token_dir }}
|
||||
mountPath: {{ kube_token_dir }}
|
||||
@@ -252,6 +247,11 @@ apiServer:
|
||||
hostPath: {{ kube_config_dir }}/webhook-authorization-config.yaml
|
||||
mountPath: {{ kube_config_dir }}/webhook-authorization-config.yaml
|
||||
{% endif %}
|
||||
{% if kube_apiserver_use_authorization_config_file %}
|
||||
- name: authorization-config
|
||||
hostPath: {{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml
|
||||
mountPath: {{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml
|
||||
{% endif %}
|
||||
{% if kubernetes_audit or kubernetes_audit_webhook %}
|
||||
- name: {{ audit_policy_name }}
|
||||
hostPath: {{ audit_policy_hostpath }}
|
||||
@@ -294,7 +294,7 @@ apiServer:
|
||||
{% endif %}
|
||||
certSANs:
|
||||
{% for san in apiserver_sans %}
|
||||
- "{{ san }}"
|
||||
- {{ san }}
|
||||
{% endfor %}
|
||||
timeoutForControlPlane: 5m0s
|
||||
controllerManager:
|
||||
@@ -302,22 +302,22 @@ controllerManager:
|
||||
node-monitor-grace-period: {{ kube_controller_node_monitor_grace_period }}
|
||||
node-monitor-period: {{ kube_controller_node_monitor_period }}
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["kube-ovn"] %}
|
||||
cluster-cidr: "{{ kube_pods_subnet }}{{ ',' + kube_pods_subnet_ipv6 if enable_dual_stack_networks else '' }}"
|
||||
cluster-cidr: "{{ kube_pods_subnets }}"
|
||||
{% endif %}
|
||||
service-cluster-ip-range: "{{ kube_service_addresses }}{{ ',' + kube_service_addresses_ipv6 if enable_dual_stack_networks else '' }}"
|
||||
service-cluster-ip-range: "{{ kube_service_subnets }}"
|
||||
{% if kube_network_plugin is defined and kube_network_plugin == "calico" and not calico_ipam_host_local %}
|
||||
allocate-node-cidrs: "false"
|
||||
{% else %}
|
||||
{% if enable_dual_stack_networks %}
|
||||
{% if ipv4_stack %}
|
||||
node-cidr-mask-size-ipv4: "{{ kube_network_node_prefix }}"
|
||||
{% endif %}
|
||||
{% if ipv6_stack %}
|
||||
node-cidr-mask-size-ipv6: "{{ kube_network_node_prefix_ipv6 }}"
|
||||
{% else %}
|
||||
node-cidr-mask-size: "{{ kube_network_node_prefix }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
profiling: "{{ kube_profiling }}"
|
||||
terminated-pod-gc-threshold: "{{ kube_controller_terminated_pod_gc_threshold }}"
|
||||
bind-address: {{ kube_controller_manager_bind_address }}
|
||||
bind-address: "{{ kube_controller_manager_bind_address }}"
|
||||
leader-elect-lease-duration: {{ kube_controller_manager_leader_elect_lease_duration }}
|
||||
leader-elect-renew-deadline: {{ kube_controller_manager_leader_elect_renew_deadline }}
|
||||
{% if kube_controller_feature_gates or kube_feature_gates %}
|
||||
@@ -326,10 +326,6 @@ controllerManager:
|
||||
{% for key in kube_kubeadm_controller_extra_args %}
|
||||
{{ key }}: "{{ kube_kubeadm_controller_extra_args[key] }}"
|
||||
{% endfor %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] %}
|
||||
cloud-provider: {{ cloud_provider }}
|
||||
cloud-config: {{ kube_config_dir }}/cloud_config
|
||||
{% endif %}
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["cloud"] %}
|
||||
configure-cloud-routes: "false"
|
||||
{% endif %}
|
||||
@@ -343,18 +339,8 @@ controllerManager:
|
||||
tls-cipher-suites: {% for tls in tls_cipher_suites %}{{ tls }}{{ "," if not loop.last else "" }}{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] or controller_manager_extra_volumes %}
|
||||
{% if controller_manager_extra_volumes %}
|
||||
extraVolumes:
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack"] and openstack_cacert is defined %}
|
||||
- name: openstackcacert
|
||||
hostPath: "{{ kube_config_dir }}/openstack-cacert.pem"
|
||||
mountPath: "{{ kube_config_dir }}/openstack-cacert.pem"
|
||||
{% endif %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] %}
|
||||
- name: cloud-config
|
||||
hostPath: {{ kube_config_dir }}/cloud_config
|
||||
mountPath: {{ kube_config_dir }}/cloud_config
|
||||
{% endif %}
|
||||
{% for volume in controller_manager_extra_volumes %}
|
||||
- name: {{ volume.name }}
|
||||
hostPath: {{ volume.hostPath }}
|
||||
@@ -364,7 +350,7 @@ controllerManager:
|
||||
{% endif %}
|
||||
scheduler:
|
||||
extraArgs:
|
||||
bind-address: {{ kube_scheduler_bind_address }}
|
||||
bind-address: "{{ kube_scheduler_bind_address }}"
|
||||
config: {{ kube_config_dir }}/kubescheduler-config.yaml
|
||||
{% if kube_scheduler_feature_gates or kube_feature_gates %}
|
||||
feature-gates: "{{ kube_scheduler_feature_gates | default(kube_feature_gates, true) | join(',') }}"
|
||||
@@ -398,7 +384,7 @@ scheduler:
|
||||
---
|
||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
kind: KubeProxyConfiguration
|
||||
bindAddress: {{ kube_proxy_bind_address }}
|
||||
bindAddress: "{{ kube_proxy_bind_address }}"
|
||||
clientConnection:
|
||||
acceptContentTypes: {{ kube_proxy_client_accept_content_types }}
|
||||
burst: {{ kube_proxy_client_burst }}
|
||||
@@ -406,7 +392,7 @@ clientConnection:
|
||||
kubeconfig: {{ kube_proxy_client_kubeconfig }}
|
||||
qps: {{ kube_proxy_client_qps }}
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["kube-ovn"] %}
|
||||
clusterCIDR: "{{ kube_pods_subnet }}{{ ',' + kube_pods_subnet_ipv6 if enable_dual_stack_networks else '' }}"
|
||||
clusterCIDR: "{{ kube_pods_subnets }}"
|
||||
{% endif %}
|
||||
configSyncPeriod: {{ kube_proxy_config_sync_period }}
|
||||
conntrack:
|
||||
@@ -415,7 +401,7 @@ conntrack:
|
||||
tcpCloseWaitTimeout: {{ kube_proxy_conntrack_tcp_close_wait_timeout }}
|
||||
tcpEstablishedTimeout: {{ kube_proxy_conntrack_tcp_established_timeout }}
|
||||
enableProfiling: {{ kube_proxy_enable_profiling }}
|
||||
healthzBindAddress: {{ kube_proxy_healthz_bind_address }}
|
||||
healthzBindAddress: "{{ kube_proxy_healthz_bind_address }}"
|
||||
hostnameOverride: "{{ kube_override_hostname }}"
|
||||
iptables:
|
||||
masqueradeAll: {{ kube_proxy_masquerade_all }}
|
||||
@@ -431,7 +417,7 @@ ipvs:
|
||||
tcpTimeout: {{ kube_proxy_tcp_timeout }}
|
||||
tcpFinTimeout: {{ kube_proxy_tcp_fin_timeout }}
|
||||
udpTimeout: {{ kube_proxy_udp_timeout }}
|
||||
metricsBindAddress: {{ kube_proxy_metrics_bind_address }}
|
||||
metricsBindAddress: "{{ kube_proxy_metrics_bind_address }}"
|
||||
mode: {{ kube_proxy_mode }}
|
||||
nodePortAddresses: {{ kube_proxy_nodeport_addresses }}
|
||||
oomScoreAdj: {{ kube_proxy_oom_score_adj }}
|
||||
|
||||
@@ -0,0 +1,593 @@
|
||||
apiVersion: kubeadm.k8s.io/v1beta4
|
||||
kind: InitConfiguration
|
||||
{% if kubeadm_token is defined %}
|
||||
bootstrapTokens:
|
||||
- token: "{{ kubeadm_token }}"
|
||||
description: "kubespray kubeadm bootstrap token"
|
||||
ttl: "24h"
|
||||
{% endif %}
|
||||
localAPIEndpoint:
|
||||
advertiseAddress: "{{ kube_apiserver_address }}"
|
||||
bindPort: {{ kube_apiserver_port }}
|
||||
{% if kubeadm_certificate_key is defined %}
|
||||
certificateKey: {{ kubeadm_certificate_key }}
|
||||
{% endif %}
|
||||
nodeRegistration:
|
||||
{% if kube_override_hostname | default('') %}
|
||||
name: "{{ kube_override_hostname }}"
|
||||
{% endif %}
|
||||
{% if 'kube_control_plane' in group_names and 'kube_node' not in group_names %}
|
||||
taints:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/control-plane
|
||||
{% else %}
|
||||
taints: []
|
||||
{% endif %}
|
||||
criSocket: {{ cri_socket }}
|
||||
{% if cloud_provider == "external" %}
|
||||
kubeletExtraArgs:
|
||||
- name: cloud-provider
|
||||
value: external
|
||||
{% endif %}
|
||||
imagePullPolicy: {{ k8s_image_pull_policy }}
|
||||
imagePullSerial: {{ kubeadm_image_pull_serial | lower }}
|
||||
{% if kubeadm_patches | length > 0 %}
|
||||
patches:
|
||||
directory: {{ kubeadm_patches_dir }}
|
||||
{% endif %}
|
||||
---
|
||||
apiVersion: kubeadm.k8s.io/v1beta4
|
||||
kind: ClusterConfiguration
|
||||
clusterName: {{ cluster_name }}
|
||||
encryptionAlgorithm: {{ kube_asymmetric_encryption_algorithm }}
|
||||
etcd:
|
||||
{% if etcd_deployment_type != "kubeadm" %}
|
||||
external:
|
||||
endpoints:
|
||||
{% for endpoint in etcd_access_addresses.split(',') %}
|
||||
- "{{ endpoint }}"
|
||||
{% endfor %}
|
||||
caFile: {{ etcd_cert_dir }}/{{ kube_etcd_cacert_file }}
|
||||
certFile: {{ etcd_cert_dir }}/{{ kube_etcd_cert_file }}
|
||||
keyFile: {{ etcd_cert_dir }}/{{ kube_etcd_key_file }}
|
||||
{% elif etcd_deployment_type == "kubeadm" %}
|
||||
local:
|
||||
imageRepository: "{{ etcd_image_repo | regex_replace("/etcd$","") }}"
|
||||
imageTag: "{{ etcd_image_tag }}"
|
||||
dataDir: "{{ etcd_data_dir }}"
|
||||
extraArgs:
|
||||
- name: metrics
|
||||
value: {{ etcd_metrics }}
|
||||
- name: election-timeout
|
||||
value: "{{ etcd_election_timeout }}"
|
||||
- name: heartbeat-interval
|
||||
value: "{{ etcd_heartbeat_interval }}"
|
||||
- name: auto-compaction-retention
|
||||
value: "{{ etcd_compaction_retention }}"
|
||||
{% if etcd_listen_metrics_urls is defined %}
|
||||
- name: listen-metrics-urls
|
||||
value: "{{ etcd_listen_metrics_urls }}"
|
||||
{% endif %}
|
||||
{% if etcd_snapshot_count is defined %}
|
||||
- name: snapshot-count
|
||||
value: "{{ etcd_snapshot_count }}"
|
||||
{% endif %}
|
||||
{% if etcd_quota_backend_bytes is defined %}
|
||||
- name: quota-backend-bytes
|
||||
value: "{{ etcd_quota_backend_bytes }}"
|
||||
{% endif %}
|
||||
{% if etcd_max_request_bytes is defined %}
|
||||
- name: max-request-bytes
|
||||
value: "{{ etcd_max_request_bytes }}"
|
||||
{% endif %}
|
||||
{% if etcd_log_level is defined %}
|
||||
- name: log-level
|
||||
value: "{{ etcd_log_level }}"
|
||||
{% endif %}
|
||||
{% for key, value in etcd_extra_vars.items() %}
|
||||
- name: {{ key }}
|
||||
value: "{{ value }}"
|
||||
{% endfor %}
|
||||
serverCertSANs:
|
||||
{% for san in etcd_cert_alt_names %}
|
||||
- "{{ san }}"
|
||||
{% endfor %}
|
||||
{% for san in etcd_cert_alt_ips %}
|
||||
- "{{ san }}"
|
||||
{% endfor %}
|
||||
peerCertSANs:
|
||||
{% for san in etcd_cert_alt_names %}
|
||||
- "{{ san }}"
|
||||
{% endfor %}
|
||||
{% for san in etcd_cert_alt_ips %}
|
||||
- "{{ san }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
dns:
|
||||
{% if 'addon/coredns' in kubeadm_init_phases_skip %}
|
||||
disabled: true
|
||||
{% endif %}
|
||||
imageRepository: {{ coredns_image_repo | regex_replace('/coredns(?!/coredns).*$', '') }}
|
||||
imageTag: {{ coredns_image_tag }}
|
||||
networking:
|
||||
dnsDomain: {{ dns_domain }}
|
||||
serviceSubnet: "{{ kube_service_subnets }}"
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["kube-ovn"] %}
|
||||
podSubnet: "{{ kube_pods_subnets }}"
|
||||
{% endif %}
|
||||
{% if kubeadm_feature_gates %}
|
||||
featureGates:
|
||||
{% for feature in kubeadm_feature_gates %}
|
||||
{{ feature | replace("=", ": ") }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
kubernetesVersion: v{{ kube_version }}
|
||||
{% if kubeadm_config_api_fqdn is defined %}
|
||||
controlPlaneEndpoint: "{{ kubeadm_config_api_fqdn }}:{{ loadbalancer_apiserver.port | default(kube_apiserver_port) }}"
|
||||
{% else %}
|
||||
controlPlaneEndpoint: "{{ main_ip | ansible.utils.ipwrap }}:{{ kube_apiserver_port }}"
|
||||
{% endif %}
|
||||
certificatesDir: {{ kube_cert_dir }}
|
||||
imageRepository: {{ kube_image_repo }}
|
||||
apiServer:
|
||||
extraArgs:
|
||||
{% if kube_apiserver_etcd_compaction_interval is defined %}
|
||||
- name: etcd-compaction-interval
|
||||
value: "{{ kube_apiserver_etcd_compaction_interval }}"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_pod_eviction_not_ready_timeout_seconds is defined %}
|
||||
- name: default-not-ready-toleration-seconds
|
||||
value: "{{ kube_apiserver_pod_eviction_not_ready_timeout_seconds }}"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_pod_eviction_unreachable_timeout_seconds is defined %}
|
||||
- name: default-unreachable-toleration-seconds
|
||||
value: "{{ kube_apiserver_pod_eviction_unreachable_timeout_seconds }}"
|
||||
{% endif %}
|
||||
{% if kube_api_anonymous_auth is defined %}
|
||||
- name: anonymous-auth
|
||||
value: "{{ kube_api_anonymous_auth }}"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_use_authorization_config_file %}
|
||||
- name: authorization-config
|
||||
value: "{{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml"
|
||||
{% else %}
|
||||
- name: authorization-mode
|
||||
value: "{{ authorization_modes | join(',') }}"
|
||||
{% endif %}
|
||||
- name: bind-address
|
||||
value: "{{ kube_apiserver_bind_address }}"
|
||||
{% if kube_apiserver_enable_admission_plugins | length > 0 %}
|
||||
- name: enable-admission-plugins
|
||||
value: "{{ kube_apiserver_enable_admission_plugins | join(',') }}"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_admission_control_config_file %}
|
||||
- name: admission-control-config-file
|
||||
value: "{{ kube_config_dir }}/admission-controls.yaml"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_disable_admission_plugins | length > 0 %}
|
||||
- name: disable-admission-plugins
|
||||
value: "{{ kube_apiserver_disable_admission_plugins | join(',') }}"
|
||||
{% endif %}
|
||||
- name: apiserver-count
|
||||
value: "{{ kube_apiserver_count }}"
|
||||
- name: endpoint-reconciler-type
|
||||
value: lease
|
||||
{% if etcd_events_cluster_enabled %}
|
||||
- name: etcd-servers-overrides
|
||||
value: "/events#{{ etcd_events_access_addresses_semicolon }}"
|
||||
{% endif %}
|
||||
- name: service-node-port-range
|
||||
value: "{{ kube_apiserver_node_port_range }}"
|
||||
- name: service-cluster-ip-range
|
||||
value: "{{ kube_service_subnets }}"
|
||||
- name: kubelet-preferred-address-types
|
||||
value: "{{ kubelet_preferred_address_types }}"
|
||||
- name: profiling
|
||||
value: "{{ kube_profiling }}"
|
||||
- name: request-timeout
|
||||
value: "{{ kube_apiserver_request_timeout }}"
|
||||
- name: enable-aggregator-routing
|
||||
value: "{{ kube_api_aggregator_routing }}"
|
||||
{% if kube_apiserver_service_account_lookup %}
|
||||
- name: service-account-lookup
|
||||
value: "{{ kube_apiserver_service_account_lookup }}"
|
||||
{% endif %}
|
||||
{% if kube_oidc_auth | default(false) and kube_oidc_url is defined and kube_oidc_client_id is defined %}
|
||||
- name: oidc-issuer-url
|
||||
value: "{{ kube_oidc_url }}"
|
||||
- name: oidc-client-id
|
||||
value: "{{ kube_oidc_client_id }}"
|
||||
{% if kube_oidc_ca_file is defined %}
|
||||
- name: oidc-ca-file
|
||||
value: "{{ kube_oidc_ca_file }}"
|
||||
{% endif %}
|
||||
{% if kube_oidc_username_claim is defined %}
|
||||
- name: oidc-username-claim
|
||||
value: "{{ kube_oidc_username_claim }}"
|
||||
{% endif %}
|
||||
{% if kube_oidc_groups_claim is defined %}
|
||||
- name: oidc-groups-claim
|
||||
value: "{{ kube_oidc_groups_claim }}"
|
||||
{% endif %}
|
||||
{% if kube_oidc_username_prefix is defined %}
|
||||
- name: oidc-username-prefix
|
||||
value: "{{ kube_oidc_username_prefix }}"
|
||||
{% endif %}
|
||||
{% if kube_oidc_groups_prefix is defined %}
|
||||
- name: oidc-groups-prefix
|
||||
value: "{{ kube_oidc_groups_prefix }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if kube_webhook_token_auth | default(false) %}
|
||||
- name: authentication-token-webhook-config-file
|
||||
value: "{{ kube_config_dir }}/webhook-token-auth-config.yaml"
|
||||
{% endif %}
|
||||
{% if kube_webhook_authorization and not kube_apiserver_use_authorization_config_file %}
|
||||
- name: authorization-webhook-config-file
|
||||
value: "{{ kube_config_dir }}/webhook-authorization-config.yaml"
|
||||
{% endif %}
|
||||
{% if kube_encrypt_secret_data %}
|
||||
- name: encryption-provider-config
|
||||
value: "{{ kube_cert_dir }}/secrets_encryption.yaml"
|
||||
{% endif %}
|
||||
- name: storage-backend
|
||||
value: "{{ kube_apiserver_storage_backend }}"
|
||||
{% if kube_api_runtime_config | length > 0 %}
|
||||
- name: runtime-config
|
||||
value: "{{ kube_api_runtime_config | join(',') }}"
|
||||
{% endif %}
|
||||
- name: allow-privileged
|
||||
value: "true"
|
||||
{% if kubernetes_audit or kubernetes_audit_webhook %}
|
||||
- name: audit-policy-file
|
||||
value: "{{ audit_policy_file }}"
|
||||
{% endif %}
|
||||
{% if kubernetes_audit %}
|
||||
- name: audit-log-path
|
||||
value: "{{ audit_log_path }}"
|
||||
- name: audit-log-maxage
|
||||
value: "{{ audit_log_maxage }}"
|
||||
- name: audit-log-maxbackup
|
||||
value: "{{ audit_log_maxbackups }}"
|
||||
- name: audit-log-maxsize
|
||||
value: "{{ audit_log_maxsize }}"
|
||||
{% endif %}
|
||||
{% if kubernetes_audit_webhook %}
|
||||
- name: audit-webhook-config-file
|
||||
value: "{{ audit_webhook_config_file }}"
|
||||
- name: audit-webhook-mode
|
||||
value: "{{ audit_webhook_mode }}"
|
||||
{% if audit_webhook_mode == "batch" %}
|
||||
- name: audit-webhook-batch-max-size
|
||||
value: "{{ audit_webhook_batch_max_size }}"
|
||||
- name: audit-webhook-batch-max-wait
|
||||
value: "{{ audit_webhook_batch_max_wait }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% for key in kube_kubeadm_apiserver_extra_args %}
|
||||
- name: "{{ key }}"
|
||||
value: "{{ kube_kubeadm_apiserver_extra_args[key] }}"
|
||||
{% endfor %}
|
||||
{% if kube_apiserver_feature_gates or kube_feature_gates %}
|
||||
- name: feature-gates
|
||||
value: "{{ kube_apiserver_feature_gates | default(kube_feature_gates, true) | join(',') }}"
|
||||
{% endif %}
|
||||
{% if tls_min_version is defined %}
|
||||
- name: tls-min-version
|
||||
value: "{{ tls_min_version }}"
|
||||
{% endif %}
|
||||
{% if tls_cipher_suites is defined %}
|
||||
- name: tls-cipher-suites
|
||||
value: "{% for tls in tls_cipher_suites %}{{ tls }}{{ ',' if not loop.last else '' }}{% endfor %}"
|
||||
{% endif %}
|
||||
{% if event_ttl_duration is defined %}
|
||||
- name: event-ttl
|
||||
value: "{{ event_ttl_duration }}"
|
||||
{% endif %}
|
||||
{% if kubelet_rotate_server_certificates %}
|
||||
- name: kubelet-certificate-authority
|
||||
value: "{{ kube_cert_dir }}/ca.crt"
|
||||
{% endif %}
|
||||
{% if kube_apiserver_tracing %}
|
||||
- name: tracing-config-file
|
||||
value: "{{ kube_config_dir }}/tracing/apiserver-tracing.yaml"
|
||||
{% endif %}
|
||||
{% if kubernetes_audit or kube_token_auth or kube_webhook_token_auth or apiserver_extra_volumes or ssl_ca_dirs | length %}
|
||||
extraVolumes:
|
||||
{% if kube_token_auth %}
|
||||
- name: token-auth-config
|
||||
hostPath: {{ kube_token_dir }}
|
||||
mountPath: {{ kube_token_dir }}
|
||||
{% endif %}
|
||||
{% if kube_webhook_token_auth | default(false) %}
|
||||
- name: webhook-token-auth-config
|
||||
hostPath: {{ kube_config_dir }}/webhook-token-auth-config.yaml
|
||||
mountPath: {{ kube_config_dir }}/webhook-token-auth-config.yaml
|
||||
{% endif %}
|
||||
{% if kube_webhook_authorization | default(false) %}
|
||||
- name: webhook-authorization-config
|
||||
hostPath: {{ kube_config_dir }}/webhook-authorization-config.yaml
|
||||
mountPath: {{ kube_config_dir }}/webhook-authorization-config.yaml
|
||||
{% endif %}
|
||||
{% if kube_apiserver_use_authorization_config_file %}
|
||||
- name: authorization-config
|
||||
hostPath: {{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml
|
||||
mountPath: {{ kube_config_dir }}/apiserver-authorization-config-{{ kube_apiserver_authorization_config_api_version }}.yaml
|
||||
{% endif %}
|
||||
{% if kubernetes_audit or kubernetes_audit_webhook %}
|
||||
- name: {{ audit_policy_name }}
|
||||
hostPath: {{ audit_policy_hostpath }}
|
||||
mountPath: {{ audit_policy_mountpath }}
|
||||
{% if audit_log_path != "-" %}
|
||||
- name: {{ audit_log_name }}
|
||||
hostPath: {{ audit_log_hostpath }}
|
||||
mountPath: {{ audit_log_mountpath }}
|
||||
readOnly: false
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if kube_apiserver_admission_control_config_file %}
|
||||
- name: admission-control-configs
|
||||
hostPath: {{ kube_config_dir }}/admission-controls
|
||||
mountPath: {{ kube_config_dir }}
|
||||
readOnly: false
|
||||
pathType: DirectoryOrCreate
|
||||
{% endif %}
|
||||
{% if kube_apiserver_tracing %}
|
||||
- name: tracing
|
||||
hostPath: {{ kube_config_dir }}/tracing
|
||||
mountPath: {{ kube_config_dir }}/tracing
|
||||
readOnly: true
|
||||
pathType: DirectoryOrCreate
|
||||
{% endif %}
|
||||
{% for volume in apiserver_extra_volumes %}
|
||||
- name: {{ volume.name }}
|
||||
hostPath: {{ volume.hostPath }}
|
||||
mountPath: {{ volume.mountPath }}
|
||||
readOnly: {{ volume.readOnly | d(not (volume.writable | d(false))) }}
|
||||
{% endfor %}
|
||||
{% if ssl_ca_dirs | length %}
|
||||
{% for dir in ssl_ca_dirs %}
|
||||
- name: {{ dir | regex_replace('^/(.*)$', '\\1' ) | regex_replace('/', '-') }}
|
||||
hostPath: {{ dir }}
|
||||
mountPath: {{ dir }}
|
||||
readOnly: true
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
certSANs:
|
||||
{% for san in apiserver_sans %}
|
||||
- {{ san }}
|
||||
{% endfor %}
|
||||
controllerManager:
|
||||
extraArgs:
|
||||
- name: node-monitor-grace-period
|
||||
value: "{{ kube_controller_node_monitor_grace_period }}"
|
||||
- name: node-monitor-period
|
||||
value: "{{ kube_controller_node_monitor_period }}"
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["kube-ovn"] %}
|
||||
- name: cluster-cidr
|
||||
value: "{{ kube_pods_subnets }}"
|
||||
{% endif %}
|
||||
- name: service-cluster-ip-range
|
||||
value: "{{ kube_service_subnets }}"
|
||||
{% if kube_network_plugin is defined and kube_network_plugin == "calico" and not calico_ipam_host_local %}
|
||||
- name: allocate-node-cidrs
|
||||
value: "false"
|
||||
{% else %}
|
||||
{% if ipv4_stack %}
|
||||
- name: node-cidr-mask-size-ipv4
|
||||
value: "{{ kube_network_node_prefix }}"
|
||||
{% endif %}
|
||||
{% if ipv6_stack %}
|
||||
- name: node-cidr-mask-size-ipv6
|
||||
value: "{{ kube_network_node_prefix_ipv6 }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
- name: profiling
|
||||
value: "{{ kube_profiling }}"
|
||||
- name: terminated-pod-gc-threshold
|
||||
value: "{{ kube_controller_terminated_pod_gc_threshold }}"
|
||||
- name: bind-address
|
||||
value: "{{ kube_controller_manager_bind_address }}"
|
||||
- name: leader-elect-lease-duration
|
||||
value: "{{ kube_controller_manager_leader_elect_lease_duration }}"
|
||||
- name: leader-elect-renew-deadline
|
||||
value: "{{ kube_controller_manager_leader_elect_renew_deadline }}"
|
||||
{% if kube_controller_feature_gates or kube_feature_gates %}
|
||||
- name: feature-gates
|
||||
value: "{{ kube_controller_feature_gates | default(kube_feature_gates, true) | join(',') }}"
|
||||
{% endif %}
|
||||
{% for key in kube_kubeadm_controller_extra_args %}
|
||||
- name: "{{ key }}"
|
||||
value: "{{ kube_kubeadm_controller_extra_args[key] }}"
|
||||
{% endfor %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] %}
|
||||
- name: cloud-provider
|
||||
value: "{{ cloud_provider }}"
|
||||
- name: cloud-config
|
||||
value: "{{ kube_config_dir }}/cloud_config"
|
||||
{% endif %}
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["cloud"] %}
|
||||
- name: configure-cloud-routes
|
||||
value: "false"
|
||||
{% endif %}
|
||||
{% if kubelet_flexvolumes_plugins_dir is defined %}
|
||||
- name: flex-volume-plugin-dir
|
||||
value: "{{ kubelet_flexvolumes_plugins_dir }}"
|
||||
{% endif %}
|
||||
{% if tls_min_version is defined %}
|
||||
- name: tls-min-version
|
||||
value: "{{ tls_min_version }}"
|
||||
{% endif %}
|
||||
{% if tls_cipher_suites is defined %}
|
||||
- name: tls-cipher-suites
|
||||
value: "{% for tls in tls_cipher_suites %}{{ tls }}{{ ',' if not loop.last else '' }}{% endfor %}"
|
||||
{% endif %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] or controller_manager_extra_volumes %}
|
||||
extraVolumes:
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack"] and openstack_cacert is defined %}
|
||||
- name: openstackcacert
|
||||
hostPath: "{{ kube_config_dir }}/openstack-cacert.pem"
|
||||
mountPath: "{{ kube_config_dir }}/openstack-cacert.pem"
|
||||
{% endif %}
|
||||
{% if cloud_provider is defined and cloud_provider in ["openstack", "azure", "vsphere", "aws", "gce"] %}
|
||||
- name: cloud-config
|
||||
hostPath: {{ kube_config_dir }}/cloud_config
|
||||
mountPath: {{ kube_config_dir }}/cloud_config
|
||||
{% endif %}
|
||||
{% for volume in controller_manager_extra_volumes %}
|
||||
- name: {{ volume.name }}
|
||||
hostPath: {{ volume.hostPath }}
|
||||
mountPath: {{ volume.mountPath }}
|
||||
readOnly: {{ volume.readOnly | d(not (volume.writable | d(false))) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
scheduler:
|
||||
extraArgs:
|
||||
- name: bind-address
|
||||
value: "{{ kube_scheduler_bind_address }}"
|
||||
- name: config
|
||||
value: "{{ kube_config_dir }}/kubescheduler-config.yaml"
|
||||
{% if kube_scheduler_feature_gates or kube_feature_gates %}
|
||||
- name: feature-gates
|
||||
value: "{{ kube_scheduler_feature_gates | default(kube_feature_gates, true) | join(',') }}"
|
||||
{% endif %}
|
||||
- name: profiling
|
||||
value: "{{ kube_profiling }}"
|
||||
{% if kube_kubeadm_scheduler_extra_args | length > 0 %}
|
||||
{% for key in kube_kubeadm_scheduler_extra_args %}
|
||||
- name: "{{ key }}"
|
||||
value: "{{ kube_kubeadm_scheduler_extra_args[key] }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if tls_min_version is defined %}
|
||||
- name: tls-min-version
|
||||
value: "{{ tls_min_version }}"
|
||||
{% endif %}
|
||||
{% if tls_cipher_suites is defined %}
|
||||
- name: tls-cipher-suites
|
||||
value: "{% for tls in tls_cipher_suites %}{{ tls }}{{ ',' if not loop.last else '' }}{% endfor %}"
|
||||
{% endif %}
|
||||
extraVolumes:
|
||||
- name: kubescheduler-config
|
||||
hostPath: {{ kube_config_dir }}/kubescheduler-config.yaml
|
||||
mountPath: {{ kube_config_dir }}/kubescheduler-config.yaml
|
||||
readOnly: true
|
||||
{% if scheduler_extra_volumes %}
|
||||
{% for volume in scheduler_extra_volumes %}
|
||||
- name: {{ volume.name }}
|
||||
hostPath: {{ volume.hostPath }}
|
||||
mountPath: {{ volume.mountPath }}
|
||||
readOnly: {{ volume.readOnly | d(not (volume.writable | d(false))) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
---
|
||||
apiVersion: kubeadm.k8s.io/v1beta4
|
||||
kind: UpgradeConfiguration
|
||||
apply:
|
||||
kubernetesVersion: v{{ kube_version }}
|
||||
allowExperimentalUpgrades: true
|
||||
certificateRenewal: {{ kubeadm_upgrade_auto_cert_renewal | lower }}
|
||||
etcdUpgrade: {{ (etcd_deployment_type == "kubeadm") | lower }}
|
||||
forceUpgrade: true
|
||||
{% if kubeadm_ignore_preflight_errors | length > 0 %}
|
||||
ignorePreflightErrors:
|
||||
{% for ignore_error in kubeadm_ignore_preflight_errors %}
|
||||
- "{{ ignore_error }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if kubeadm_patches | length > 0 %}
|
||||
patches:
|
||||
directory: {{ kubeadm_patches_dir }}
|
||||
{% endif %}
|
||||
imagePullPolicy: {{ k8s_image_pull_policy }}
|
||||
imagePullSerial: {{ kubeadm_image_pull_serial | lower }}
|
||||
node:
|
||||
certificateRenewal: {{ kubeadm_upgrade_auto_cert_renewal | lower }}
|
||||
etcdUpgrade: {{ (etcd_deployment_type == "kubeadm") | lower }}
|
||||
{% if kubeadm_ignore_preflight_errors | length > 0 %}
|
||||
ignorePreflightErrors:
|
||||
{% for ignore_error in kubeadm_ignore_preflight_errors %}
|
||||
- "{{ ignore_error }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if kubeadm_patches | length > 0 %}
|
||||
patches:
|
||||
directory: {{ kubeadm_patches_dir }}
|
||||
{% endif %}
|
||||
imagePullPolicy: {{ k8s_image_pull_policy }}
|
||||
imagePullSerial: {{ kubeadm_image_pull_serial | lower }}
|
||||
---
|
||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
kind: KubeProxyConfiguration
|
||||
bindAddress: "{{ kube_proxy_bind_address }}"
|
||||
clientConnection:
|
||||
acceptContentTypes: {{ kube_proxy_client_accept_content_types }}
|
||||
burst: {{ kube_proxy_client_burst }}
|
||||
contentType: {{ kube_proxy_client_content_type }}
|
||||
kubeconfig: {{ kube_proxy_client_kubeconfig }}
|
||||
qps: {{ kube_proxy_client_qps }}
|
||||
{% if kube_network_plugin is defined and kube_network_plugin not in ["kube-ovn"] %}
|
||||
clusterCIDR: "{{ kube_pods_subnets }}"
|
||||
{% endif %}
|
||||
configSyncPeriod: {{ kube_proxy_config_sync_period }}
|
||||
conntrack:
|
||||
maxPerCore: {{ kube_proxy_conntrack_max_per_core }}
|
||||
min: {{ kube_proxy_conntrack_min }}
|
||||
tcpCloseWaitTimeout: {{ kube_proxy_conntrack_tcp_close_wait_timeout }}
|
||||
tcpEstablishedTimeout: {{ kube_proxy_conntrack_tcp_established_timeout }}
|
||||
enableProfiling: {{ kube_proxy_enable_profiling }}
|
||||
healthzBindAddress: "{{ kube_proxy_healthz_bind_address }}"
|
||||
hostnameOverride: "{{ kube_override_hostname }}"
|
||||
iptables:
|
||||
masqueradeAll: {{ kube_proxy_masquerade_all }}
|
||||
masqueradeBit: {{ kube_proxy_masquerade_bit }}
|
||||
minSyncPeriod: {{ kube_proxy_min_sync_period }}
|
||||
syncPeriod: {{ kube_proxy_sync_period }}
|
||||
ipvs:
|
||||
excludeCIDRs: {{ kube_proxy_exclude_cidrs }}
|
||||
minSyncPeriod: {{ kube_proxy_min_sync_period }}
|
||||
scheduler: {{ kube_proxy_scheduler }}
|
||||
syncPeriod: {{ kube_proxy_sync_period }}
|
||||
strictARP: {{ kube_proxy_strict_arp }}
|
||||
tcpTimeout: {{ kube_proxy_tcp_timeout }}
|
||||
tcpFinTimeout: {{ kube_proxy_tcp_fin_timeout }}
|
||||
udpTimeout: {{ kube_proxy_udp_timeout }}
|
||||
metricsBindAddress: "{{ kube_proxy_metrics_bind_address }}"
|
||||
mode: {{ kube_proxy_mode }}
|
||||
nodePortAddresses: {{ kube_proxy_nodeport_addresses }}
|
||||
oomScoreAdj: {{ kube_proxy_oom_score_adj }}
|
||||
portRange: {{ kube_proxy_port_range }}
|
||||
{% if kube_proxy_feature_gates or kube_feature_gates %}
|
||||
{% set feature_gates = ( kube_proxy_feature_gates | default(kube_feature_gates, true) ) %}
|
||||
featureGates:
|
||||
{% for feature in feature_gates %}
|
||||
{{ feature | replace("=", ": ") }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{# DNS settings for kubelet #}
|
||||
{% if enable_nodelocaldns %}
|
||||
{% set kubelet_cluster_dns = [nodelocaldns_ip] %}
|
||||
{% elif dns_mode in ['coredns'] %}
|
||||
{% set kubelet_cluster_dns = [skydns_server] %}
|
||||
{% elif dns_mode == 'coredns_dual' %}
|
||||
{% set kubelet_cluster_dns = [skydns_server,skydns_server_secondary] %}
|
||||
{% elif dns_mode == 'manual' %}
|
||||
{% set kubelet_cluster_dns = [manual_dns_server] %}
|
||||
{% else %}
|
||||
{% set kubelet_cluster_dns = [] %}
|
||||
{% endif %}
|
||||
---
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
kind: KubeletConfiguration
|
||||
clusterDNS:
|
||||
{% for dns_address in kubelet_cluster_dns %}
|
||||
- {{ dns_address }}
|
||||
{% endfor %}
|
||||
{% if kubelet_feature_gates or kube_feature_gates %}
|
||||
{% set feature_gates = ( kubelet_feature_gates | default(kube_feature_gates, true) ) %}
|
||||
featureGates:
|
||||
{% for feature in feature_gates %}
|
||||
{{ feature | replace("=", ": ") }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -1,4 +1,4 @@
|
||||
apiVersion: kubeadm.k8s.io/v1beta3
|
||||
apiVersion: kubeadm.k8s.io/{{ kubeadm_config_api_version }}
|
||||
kind: JoinConfiguration
|
||||
discovery:
|
||||
{% if kubeadm_use_file_discovery %}
|
||||
@@ -9,29 +9,35 @@ discovery:
|
||||
{% if kubeadm_config_api_fqdn is defined %}
|
||||
apiServerEndpoint: {{ kubeadm_config_api_fqdn }}:{{ loadbalancer_apiserver.port | default(kube_apiserver_port) }}
|
||||
{% else %}
|
||||
apiServerEndpoint: {{ kubeadm_discovery_address }}
|
||||
apiServerEndpoint: "{{ kubeadm_discovery_address }}"
|
||||
{% endif %}
|
||||
token: {{ kubeadm_token }}
|
||||
unsafeSkipCAVerification: true
|
||||
{% endif %}
|
||||
timeout: {{ discovery_timeout }}
|
||||
tlsBootstrapToken: {{ kubeadm_token }}
|
||||
{# TODO: drop the if when we drop support for k8s<1.31 #}
|
||||
{% if kubeadm_config_api_version == 'v1beta3' %}
|
||||
timeout: {{ discovery_timeout }}
|
||||
{% else %}
|
||||
timeouts:
|
||||
discovery: {{ discovery_timeout }}
|
||||
{% endif %}
|
||||
controlPlane:
|
||||
localAPIEndpoint:
|
||||
advertiseAddress: {{ kube_apiserver_address }}
|
||||
advertiseAddress: "{{ kube_apiserver_address }}"
|
||||
bindPort: {{ kube_apiserver_port }}
|
||||
certificateKey: {{ kubeadm_certificate_key }}
|
||||
nodeRegistration:
|
||||
name: {{ kube_override_hostname | default(inventory_hostname) }}
|
||||
criSocket: {{ cri_socket }}
|
||||
{% if inventory_hostname in groups['kube_control_plane'] and inventory_hostname not in groups['kube_node'] %}
|
||||
{% if 'kube_control_plane' in group_names and 'kube_node' not in group_names %}
|
||||
taints:
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/control-plane
|
||||
{% else %}
|
||||
taints: []
|
||||
{% endif %}
|
||||
{% if kubeadm_patches is defined and kubeadm_patches.enabled %}
|
||||
{% if kubeadm_patches | length > 0 %}
|
||||
patches:
|
||||
directory: {{ kubeadm_patches.dest_dir }}
|
||||
directory: {{ kubeadm_patches_dir }}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,8 @@
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: ResourceQuotaConfiguration
|
||||
{% if kube_resource_quota_limited_resources | d(false) -%}
|
||||
limitedResources:
|
||||
{{ kube_resource_quota_limited_resources | to_nice_yaml(indent=2, sort_keys=false) }}
|
||||
{% else %}
|
||||
# No limitedResources configured. If limitedResources are required, please set kube_resource_quota_limited_resources.
|
||||
{%- endif %}
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
# list of admission plugins that needs to be configured
|
||||
kube_apiserver_admission_plugins_needs_configuration: [EventRateLimit, PodSecurity]
|
||||
# https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/
|
||||
kube_apiserver_admission_plugins_needs_configuration:
|
||||
- EventRateLimit
|
||||
- ImagePolicyWebhook
|
||||
- PodSecurity
|
||||
- PodNodeSelector
|
||||
- ResourceQuota
|
||||
|
||||
Reference in New Issue
Block a user