githubixx.kubernetes_controller
ansible-role-kubernetes-controller
此角色在 使用 Ansible 轻松部署 Kubernetes 控制平面 中使用。它安装 Kubernetes API 服务器、调度器和控制器管理器。有关此角色的更多信息,请查看 使用 Ansible 轻松部署 Kubernetes 控制平面。
版本
我为每个版本打标签,并努力遵循 语义化版本控制。如果您想使用此角色,我建议您查看最新标签。master 分支主要用于开发,而标签标记为稳定发布。不过,我会尽量保持 master 版本的良好状态。标签 23.0.0+1.28.5
意味着这是该角色的版本 23.0.0
,并且旨在与 Kubernetes 版本 1.28.5
一起使用(当然,它也应与任何 K8s 1.27.x 版本正常工作)。如果角色本身发生变化,则 X.Y.Z
在 +
之前将增加。如果 Kubernetes 版本发生变化,则 X.Y.Z
在 +
之后也将增加。这允许在为特定 Kubernetes 版本开发时标记修复和新的主要版本。这对于存在破坏性更改的 Kubernetes 主要版本尤为有用。
需求
此角色要求您已经为 Kubernetes API 服务器创建了一些证书(请参见 使用 Ansible 创建 Kubernetes 证书颁发机构 (CA))。该角色将证书从 k8s_ctl_ca_conf_directory
(默认与 githubixx.kubernetes_ca
角色使用的 k8s_ca_conf_directory
相同)复制到目标主机。您还应设置一个完全网状的 VPN,例如使用 WireGuard(请参见 使用 Ansible 创建 WireGuard)和当然还需要一个 etcd 集群(请参见 使用 Ansible 创建 etcd 集群)。虽然 WireGuard VPN 网状结构并不是必须的,但它会增加安全性,因为所有 K8s 主机之间的流量默认都是加密的。只要所有相关主机都有可以相互通信的接口,使用其他方式也是可以的。
支持的操作系统
- Ubuntu 20.04 (Focal Fossa)
- Ubuntu 22.04 (Jammy Jellyfish)
更新日志
更改历史:
查看完整的 CHANGELOG.md
重要:如果您从版本 < 22.0.0+1.27.8
升级,请仔细阅读 CHANGELOG.md!版本 22.0.0+1.27.8
有许多破坏性更改!
最近更改:
24.0.0+1.29.4
- 更新
- 更新
k8s_release
到1.29.4
- 更新
24.0.0+1.29.3
- 更新
- 更新
k8s_release
到1.29.3
- Molecule:使用
alvistack
代替generic
Vagrant 镜像
- 更新
23.1.2+1.28.8
- 更新
- 更新
k8s_release
到1.28.8
- 更新
23.1.1+1.28.5
- 修复
- ClusterRoleBinding
system:kube-apiserver
需要使用k8s_apiserver_csr_cn
的值作为用户名 - 因为之前的更改,将
files/kube-apiserver-to-kubelet_cluster_role.yaml -> templates/rbac/kube-apiserver-to-kubelet_cluster_role.yaml.j2
和files/kube-apiserver-to-kubelet_cluster_role_binding.yaml -> templates/rbac/kube-apiserver-to-kubelet_cluster_role_binding.yaml.j2
移动,因为这两个文件都成为了 Jinja2 模板。
- ClusterRoleBinding
23.1.0+1.28.5
Molecule
- 更改测试资产 VM 为 Ubuntu 22.04
- 调整证书的通用名称 / 更改算法为 ecdsa 以及算法大小
其他更改
- 修复临时目录的权限
- 由于 Ansible Galaxy 的更改,调整 Github 操作
23.0.0+1.28.5
更新
- 更新
k8s_release
到1.28.5
- 更新
破坏性
- 在
k8s_apiserver_settings
中扩展enable-admission-plugins
:包括PodSecurity,Priority,StorageObjectInUseProtection,RuntimeClass,CertificateApproval,CertificateSigning,ClusterTrustBundleAttest,CertificateSubjectRestriction,DefaultIngressClass
。如果没有指定此标志,默认情况下将启用这些插件(有关更多信息,请参见 Admission Controllers Reference)。
- 在
Molecule
- 更改 IP 地址
安装
直接从 Github 下载(在克隆之前切换到 Ansible 角色目录。您可以使用
ansible-config dump | grep DEFAULT_ROLES_PATH
命令找到角色路径):git clone https://github.com/githubixx/ansible-role-kubernetes-controller.git githubixx.kubernetes_controller
通过
ansible-galaxy
命令直接从 Ansible Galaxy 下载:ansible-galaxy install role githubixx.kubernetes_controller
创建一个
requirements.yml
文件,内容如下(这将从 Github 下载角色),并使用以下命令安装:ansible-galaxy role install -r requirements.yml
(如有需要请更改version
):
---
roles:
- name: githubixx.kubernetes_controller
src: https://github.com/githubixx/ansible-role-kubernetes-controller.git
version: 24.0.1+1.29.4
默认角色变量
# Kubernetes 配置和证书文件的基础目录,控制平面相关的所有内容。剧本执行完毕后,此目录将包含各种子文件夹。
k8s_ctl_conf_dir: "/etc/kubernetes/controller"
# 所有证书文件(与私钥基础设施相关)将在此处存储,具体文件在 "k8s_ctl_certificates" 和 "k8s_ctl_etcd_certificates" 中指定(请参见 "vars/main.yml")。该新目录的所有者将为 "root",组将是 "k8s_run_as_group" 中指定的组。该目录中的文件将由 "root" 拥有,组权限与 "k8s_run_as_group" 中指定的组一致。文件权限为 "0640"。
k8s_ctl_pki_dir: "{{ k8s_ctl_conf_dir }}/pki"
# 存储 Kubernetes 二进制文件的目录(请参见 "vars/main.yml" 中的 "k8s_ctl_binaries" 变量)。该新目录的所有者和组都将是 "root"。此目录的权限将是 "0755"。
#
# 注意:默认目录 "/usr/local/bin" 在每个 Linux 安装中通常已经存在,具有上述提到的所有者、组和权限。如果您当前的设置不同,请考虑使用其他目录。但请确保新目录包含在您的 "$PATH" 变量值中。
k8s_ctl_bin_dir: "/usr/local/bin"
# Kubernetes 版本。
k8s_ctl_release: "1.29.4"
# Kubernetes 服务应监听的接口。由于所有集群通信都应使用 VPN 接口,接口名称通常为 "wg0"(WireGuard)、"peervpn0"(PeerVPN)或 "tap0"。
#
# Kubernetes 控制平面服务应监听的网络接口。
k8s_interface: "eth0"
# 以此用户身份运行 Kubernetes 控制平面服务(kube-apiserver, kube-scheduler, kube-controller-manager)。
#
# 如果您想为 "kube-apiserver" 使用低于 1024 的 "secure-port",则可能需要以 "root" 用户身份运行 "kube-apiserver"(不推荐)。
#
# 如果在 "k8s_run_as_user" 中指定的用户不存在,则角色将创建它。只有在用户已存在的情况下,角色才不会创建它,而是会根据以下设置调整 UID/GID 和 shell。因此,确保 UID、GID 和 shell 与现有用户匹配,如果您不希望该用户被更改的话。
#
# 此外,如果 "k8s_run_as_user" 为 "root",则此角色不会更改用户。
k8s_run_as_user: "k8s"
# "k8s_run_as_user" 中指定用户的 UID。如果未指定,则从 "/etc/login.defs" 中获取下一个可用的 UID(请参阅该文件中的 "SYS_UID_MAX" 设置)。
# k8s_run_as_user_uid: "999"
# "k8s_run_as_user" 中指定用户的 shell。为了提高安全性,请保持默认值。
k8s_run_as_user_shell: "/bin/false"
# 指定 "k8s_run_as_user" 是否为系统用户(默认值),如果为 "true",则将忽略 "k8s_run_as_user_home" 设置。通常保留默认值是有意义的,因为没有必要使用运行 kube-apiserver、kube-scheduler 或 kube-controller-manager 的用户登录。
k8s_run_as_user_system: true
# "k8s_run_as_user" 中指定用户的主目录。如果将 "k8s_run_as_user_system" 设置为 "true",则将被忽略。在此情况下,不会创建主目录。通常不需要。
# k8s_run_as_user_home: "/home/k8s"
# 以此组身份运行 Kubernetes 守护进程(kube-apiserver, kube-scheduler, kube-controller-manager)。
#
# 注意:如果 "k8s_run_as_group" 中指定的组不存在,则角色将创建它。只有在组已经存在的情况下,角色不会创建它,但会根据 "k8s_run_as_group_gid" 中的设置调整 GID。
k8s_run_as_group: "k8s"
# "k8s_run_as_group" 中指定组的 GID。如果未指定,则从 "/etc/login.defs" 中获取下一个可用的 GID(请参阅该文件中的 "SYS_GID_MAX" 设置)。
# k8s_run_as_group_gid: "999"
# 指定 "k8s_run_as_group" 中指定的组是否为系统组(默认值)。
k8s_run_as_group_system: true
# 默认情况下,所有需要与 Kubernetes 集群通信的任务都在本地主机(127.0.0.1)上执行。但是,如果该主机与 K8s 集群没有直接连接或应在其他地方执行,则此变量可以相应更改。
k8s_ctl_delegate_to: "127.0.0.1"
# Kubernetes API 端点的 IP 地址或主机名。该变量由 "kube-scheduler" 和 "kube-controller-manager" 用于连接 "kube-apiserver"(Kubernetes API 服务器)。
#
# 默认情况下,这里指定 Ansible 组 "k8s_controller" 中的第一个主机。注意:此设置不是容错的!这意味着如果 Ansible 组 "k8s_controller" 中的第一个主机出现故障,工作节点及其工作负载将继续工作,但工作节点不会接收到来自 Kubernetes API 服务器的任何更新。
#
# 如果您有一个负载均衡器在所有 Kubernetes API 服务器之间分发流量,则应在此处指定该负载均衡器的 IP 地址或 DNS 名称。但您需要确保要在此使用的 IP 地址或 DNS 名称包含在 Kubernetes API 服务器 TLS 证书中(请参见 https://github.com/githubixx/ansible-role-kubernetes-ca 角色的 "k8s_apiserver_cert_hosts" 变量)。如果未指定,您将在上述服务的日志中收到证书错误。
k8s_ctl_api_endpoint_host: "{% set controller_host = groups['k8s_controller'][0] %}{{ hostvars[controller_host]['ansible_' + hostvars[controller_host]['k8s_interface']].ipv4.address }}"
# 与上述相同,只是指定端口。它指定 Kubernetes API 服务器监听的端口。同样,如果有负载均衡器在分发请求到 Kubernetes API 服务器,则在此处填写负载均衡器的端口。
k8s_ctl_api_endpoint_port: "6443"
# 默认情况下,"kube-apiserver"、"kube-controller-manager" 和 "kube-scheduler" 日志记录到 "journald"。但有些例外,比如审计日志。对于这种日志文件,此目录将用作基础路径。此目录的所有者和组将是 "k8s_run_as_user" 和 "k8s_run_as_group" 中指定的内容,因为这些服务以该用户身份运行,需要权限在此目录中创建日志文件。
k8s_ctl_log_base_dir: "/var/log/kubernetes"
# "k8s_ctl_log_base_dir" 中指定目录的权限
k8s_ctl_log_base_dir_mode: "0770"
# 控制平面组件应连接到 etcd 集群的端口
k8s_ctl_etcd_client_port: "2379"
# etcd 集群监听的接口
k8s_ctl_etcd_interface: "eth0"
# 存储 Kubernetes 证书的目录位置。如果您没有使用其他方法生成这些证书,这些证书由 "kubernetes_ca" Ansible 角色生成。因此该目录位于 Ansible 控制主机上。这通常是执行 "ansible-playbook" 的主机。 "k8s_ca_conf_directory" 由 "kubernetes_ca" Ansible 角色用于存储证书。因此假设此变量已经设置。
k8s_ctl_ca_conf_directory: "{{ k8s_ca_conf_directory }}"
# 存储 "admin" 用户的 "admin.kubeconfig"(凭证文件)目录。默认情况下,该目录(及其 "kubeconfig" 文件)将存储在 "k8s_ctl_delegate_to" 中指定的主机上。默认情况下,这是 "127.0.0.1"。因此,如果您在本地运行 "ansible-playbook",例如,目录和文件将在那里创建。
#
# 默认情况下,该变量的值将扩展为用户的本地 $HOME 加上 "/k8s/certs"。这意味着如果用户的 $HOME 目录是 "/home/da_user",则 "k8s_admin_conf_dir" 的值将为 "/home/da_user/k8s/certs"。
k8s_admin_conf_dir: "{{ '~/k8s/configs' | expanduser }}"
# "k8s_admin_conf_dir" 中指定目录的权限
k8s_admin_conf_dir_perm: "0700"
# 在 "k8s_admin_conf_dir" 中指定目录的所有者和 "admin.kubeconfig"。
k8s_admin_conf_owner: "root"
# 在 "k8s_admin_conf_dir" 中指定目录的组和 "admin.kubeconfig"。
k8s_admin_conf_group: "root"
# "admin" 用户用于管理 K8s 集群的主机。此设置写入 "admin.kubeconfig"。这允许使用不同的主机/负载均衡器与 K8s 服务进行连接,可能使用内部负载均衡器,而 "admin" 用户连接到连接到 "kube-apiserver" 的不同主机/负载均衡器。
#
# 除此之外,基本上与 "k8s_ctl_api_endpoint_host" 变量的注释相同。
k8s_admin_api_endpoint_host: "{% set controller_host = groups['k8s_controller'][0] %}{{ hostvars[controller_host]['ansible_' + hostvars[controller_host]['k8s_interface']].ipv4.address }}"
# 与上述相同,只是为端口。
k8s_admin_api_endpoint_port: "6443"
# 存储 "kube-apiserver" 审计日志的目录(如果启用)。该目录的所有者和组将是 "k8s_run_as_user" 和 "k8s_run_as_group" 中指定的内容。
k8s_apiserver_audit_log_dir: "{{ k8s_ctl_log_base_dir }}/kube-apiserver"
# 存储 "kube-apiserver" 配置的目录。
k8s_apiserver_conf_dir: "{{ k8s_ctl_conf_dir }}/kube-apiserver"
# "kube-apiserver" 守护进程设置(可以通过定义 "k8s_apiserver_settings_user" 进行覆盖或添加其他设置)
k8s_apiserver_settings:
"advertise-address": "{{ hostvars[inventory_hostname]['ansible_' + k8s_interface].ipv4.address }}"
"bind-address": "{{ hostvars[inventory_hostname]['ansible_' + k8s_interface].ipv4.address }}"
"secure-port": "6443"
"enable-admission-plugins": "NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount,TaintNodesByCondition,Priority,DefaultTolerationSeconds,DefaultStorageClass,PersistentVolumeClaimResize,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodSecurity,Priority,StorageObjectInUseProtection,RuntimeClass,CertificateApproval,CertificateSigning,ClusterTrustBundleAttest,CertificateSubjectRestriction,DefaultIngressClass"
"allow-privileged": "true"
"authorization-mode": "Node,RBAC"
"audit-log-maxage": "30"
"audit-log-maxbackup": "3"
"audit-log-maxsize": "100"
"audit-log-path": "{{ k8s_apiserver_audit_log_dir }}/audit.log"
"event-ttl": "1h"
"kubelet-preferred-address-types": "InternalIP,Hostname,ExternalIP" # "--kubelet-preferred-address-types" 默认值:
# "Hostname,InternalDNS,InternalIP,ExternalDNS,ExternalIP"
# 需要更改以使 "kubectl logs" 和 "kubectl exec" 生效。
"runtime-config": "api/all=true"
"service-cluster-ip-range": "10.32.0.0/16"
"service-node-port-range": "30000-32767"
"client-ca-file": "{{ k8s_ctl_pki_dir }}/ca-k8s-apiserver.pem"
"etcd-cafile": "{{ k8s_ctl_pki_dir }}/ca-etcd.pem"
"etcd-certfile": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver-etcd.pem"
"etcd-keyfile": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver-etcd-key.pem"
"encryption-provider-config": "{{ k8s_apiserver_conf_dir }}/encryption-config.yaml"
"encryption-provider-config-automatic-reload": "true"
"kubelet-certificate-authority": "{{ k8s_ctl_pki_dir }}/ca-k8s-apiserver.pem"
"kubelet-client-certificate": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver.pem"
"kubelet-client-key": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver-key.pem"
"service-account-key-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-controller-manager-sa.pem"
"service-account-signing-key-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-controller-manager-sa-key.pem"
"service-account-issuer": "https://{{ groups.k8s_controller | first }}:6443"
"tls-cert-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver.pem"
"tls-private-key-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver-key.pem"
# 这是 "encryption-config.yaml" 的内容。由 "kube-apiserver" 使用(请参见 "k8s_apiserver_settings" 中的 "encryption-provider-config" 选项)。
# "kube-apiserver" 将使用此配置在将数据存储到 etcd 之前对其进行加密(对静态数据进行加密)。
#
# 下面的配置是一个可用的示例,但可能不符合您的需求。因此请仔细审查!例如,您可能希望将 "aescbc" 提供程序替换为其他提供程序,如 "secretbox"。如您所见,这个配置仅用于对 "secrets" 进行静态数据加密。但也可以对其他 K8s 资源进行加密。注意:"identity" 提供程序不会加密任何内容!这意味着明文。在下面的配置中,它被用作后备。
#
# 如果您保留下面定义的默认值,请确保将变量 "k8s_encryption_config_key" 在某个地方(例如 "group_vars/all.yml" 或更好的是使用 "ansible-vault" 存储这些机密)。
# 这需要是一个 base64 编码的值。要在 Linux 上创建这样的值,请运行以下命令:
#
# head -c 32 /dev/urandom | base64
#
# 有关详细描述,请访问:
# https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
#
# 如何轮换加密密钥或在现有 K8s 集群中实现静态数据加密,请访问:
# https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/#rotating-a-decryption-key
k8s_apiserver_encryption_provider_config: |
---
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: {{ k8s_encryption_config_key }}
- identity: {}
# 存储控制器经理配置的目录。
k8s_controller_manager_conf_dir: "{{ k8s_ctl_conf_dir }}/kube-controller-manager"
# K8s 控制器管理器设置(可以通过定义 "k8s_controller_manager_settings_user" 进行覆盖或添加其他设置)
k8s_controller_manager_settings:
"bind-address": "{{ hostvars[inventory_hostname]['ansible_' + k8s_interface].ipv4.address }}"
"secure-port": "10257"
"cluster-cidr": "10.200.0.0/16"
"allocate-node-cidrs": "true"
"cluster-name": "kubernetes"
"authentication-kubeconfig": "{{ k8s_controller_manager_conf_dir }}/kubeconfig"
"authorization-kubeconfig": "{{ k8s_controller_manager_conf_dir }}/kubeconfig"
"kubeconfig": "{{ k8s_controller_manager_conf_dir }}/kubeconfig"
"leader-elect": "true"
"service-cluster-ip-range": "10.32.0.0/16"
"cluster-signing-cert-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver.pem"
"cluster-signing-key-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-apiserver-key.pem"
"root-ca-file": "{{ k8s_ctl_pki_dir }}/ca-k8s-apiserver.pem"
"requestheader-client-ca-file": "{{ k8s_ctl_pki_dir }}/ca-k8s-apiserver.pem"
"service-account-private-key-file": "{{ k8s_ctl_pki_dir }}/cert-k8s-controller-manager-sa-key.pem"
"use-service-account-credentials": "true"
# 存储调度程序配置的目录。
k8s_scheduler_conf_dir: "{{ k8s_ctl_conf_dir }}/kube-scheduler"
# kube-scheduler 设置
k8s_scheduler_settings:
"bind-address": "{{ hostvars[inventory_hostname]['ansible_' + k8s_interface].ipv4.address }}"
"config": "{{ k8s_scheduler_conf_dir }}/kube-scheduler.yaml"
"authentication-kubeconfig": "{{ k8s_scheduler_conf_dir }}/kubeconfig"
"authorization-kubeconfig": "{{ k8s_scheduler_conf_dir }}/kubeconfig"
"requestheader-client-ca-file": "{{ k8s_ctl_pki_dir }}/ca-k8s-apiserver.pem"
# 这些沙箱安全/沙箱相关设置将用于 "kube-apiserver"、"kube-scheduler" 和 "kube-controller-manager" 的 systemd 单元。这些选项将放置在 "[Service]" 部分。
# 默认设置应该适合增强提到的服务的安全性。因此,如果可能的话,保留它们是有意义的。
#
# 有关更多信息,请参见:
# https://www.freedesktop.org/software/systemd/man/systemd.service.html#Options
#
# 下面的选项 "RestartSec=5" 主要是与安全/沙箱相关的设置,并限制系统向单元进程的暴露。根据需要,您可以添加或删除选项。有关更多信息,请参见:
# https://www.freedesktop.org/software/systemd/man/systemd.exec.html
k8s_ctl_service_options:
- User={{ k8s_run_as_user }}
- Group={{ k8s_run_as_group }}
- Restart=on-failure
- RestartSec=5
- NoNewPrivileges=true
- ProtectHome=true
- PrivateTmp=true
- PrivateUsers=true
- ProtectSystem=full
- ProtectClock=true
- ProtectKernelModules=true
- ProtectKernelTunables=true
- ProtectKernelLogs=true
- ProtectControlGroups=true
- ProtectHostname=true
- ProtectControlGroups=true
- RestrictNamespaces=true
- RestrictRealtime=true
- RestrictSUIDSGID=true
- CapabilityBoundingSet=~CAP_SYS_PTRACE
- CapabilityBoundingSet=~CAP_KILL
- CapabilityBoundingSet=~CAP_MKNOD
- CapabilityBoundingSet=~CAP_SYS_CHROOT
- CapabilityBoundingSet=~CAP_SYS_ADMIN
- CapabilityBoundingSet=~CAP_SETUID
- CapabilityBoundingSet=~CAP_SETGID
- CapabilityBoundingSet=~CAP_SETPCAP
- CapabilityBoundingSet=~CAP_CHOWN
- SystemCallFilter=@system-service
- ReadWritePaths=-/usr/libexec/kubernetes
在 k8s_apiserver_settings
中定义的 kube-apiserver 设置可以通过定义名为 k8s_apiserver_settings_user
的变量来覆盖。您还可以通过使用此变量添加其他设置。例如,要覆盖 audit-log-maxage
和 audit-log-maxbackup
默认值并添加 watch-cache
,请将以下设置添加到 group_vars/k8s.yml
:
k8s_apiserver_settings_user:
"audit-log-maxage": "40"
"audit-log-maxbackup": "4"
"watch-cache": "false"
对于 kube-controller-manager
,通过将条目添加到 k8s_controller_manager_settings_user
变量来执行相同操作。对于 kube-scheduler
,通过将条目添加到 k8s_scheduler_settings_user
变量来覆盖或添加 k8s_scheduler_settings
字典中的设置。
示例剧本
- hosts: k8s_controller
roles:
- githubixx.kubernetes_controller
测试
此角色有一个小测试设置,使用 Molecule、libvirt (vagrant-libvirt) 和 QEMU/KVM 创建。请查看我的博客文章 使用 Molecule、libvirt (vagrant-libvirt) 和 QEMU/KVM 测试 Ansible 角色 以了解如何设置。测试配置在 这里。
之后可以执行 Molecule:
molecule converge
这将设置一些支持的 Ubuntu OS 的虚拟机 (VM) 并安装一个 Kubernetes 集群,但没有工作节点(因此没有已安装 kube-proxy
和 kubelet
的节点)。还包括一个小的验证步骤:
molecule verify
要进行清理,请运行
molecule destroy
许可证
GNU 通用公共许可证 第 3 版
作者信息
Installs the Kubernetes API server, scheduler and controller manager.
ansible-galaxy install githubixx.kubernetes_controller