mmul.kubelab

Kubelab Ansible 角色

这个角色可以用来部署一个 Kubernetes 集群,具备完全自动化和幂等性实现的多个组件。

Lint the project Ansible Galaxy

特性

这个角色可以配置以启用以下所有特性:

  • 单控制平面或多控制平面集群实现,使用 HAProxy 和 Keepalived 提供高可用性。

  • 多网络插件 Flannel 和 Calico。

  • Kubernetes 仪表板

  • 用户管理,包括证书生成和 kubeconfig 文件更新。

  • Ceph-CSI 存储类用于块设备。

  • MetalLB 负载均衡器用于裸金属环境。

  • Ingress NGINX 用于服务暴露。

  • Cert Manager 用于自动化证书管理。

使用 Ansible Playbook 安装集群

准备环境的最佳方式是使用 Python 虚拟环境,通过 pip3 安装 ansible:

user@lab ~ # python3 -m venv ansible
user@lab ~ # source ansible/bin/activate
(ansible) user@lab ~ # pip3 install ansible
正在收集 ansible
  使用缓存的 ansible-7.5.0-py3-none-any.whl (43.6 MB)
...
成功安装 MarkupSafe-2.1.2 PyYAML-6.0 ansible-7.5.0 ansible-core-2.14.5 cffi-1.15.1 cryptography-40.0.2 jinja2-3.1.2 packaging-23.1 pycparser-2.21 resolvelib-0.8.1

然后,你需要这个角色,在这种情况下,使用 ansible-galaxy 是一个好的选择,可以使其自动化:

(ansible) user@lab ~ # ansible-galaxy install mmul.kubelab -p ansible/roles/
开始安装角色过程
- 正在下载角色 'kubelab',拥有者为 mmul
- 从 https://github.com/mmul-it/kubelab/archive/main.tar.gz 下载角色
- 正在提取 mmul.kubelab 到 /home/rasca/ansible/roles/mmul.kubelab
- mmul.kubelab (main) 安装成功

角色到位后,你可以再次使用 pip3 完成需求:

(ansible) user@lab ~ # pip3 install -r ansible/roles/mmul.kubelab/requirements.txt
...
成功安装 ansible-vault-2.1.0 cachetools-5.3.0 certifi-2023.5.7 charset-normalizer-3.1.0 google-auth-2.18.0 idna-3.4 kubernetes-26.1.0 oauthlib-3.2.2 pyasn1-0.5.0 pyasn1-modules-0.3.0 python-dateutil-2.8.2 requests-2.30.0 requests-oauthlib-1.3.1 rsa-4.9 six-1.16.0 urllib3-1.26.15 websocket-client-1.5.1

一旦安装完成后,通常会通过启动 tests/kubelab.yml playbook 来使用这个角色,如下所示:

(ansible) user@lab ~ # ansible-playbook -i tests/inventory/kubelab tests/kubelab.yml

注意: 相关系统的日期和时间非常重要!执行 Ansible playbook 的机器和目标机器之间的时钟差异可能会导致证书验证失败。

注意: 你可以随时通过将 k8s_reset 设置为 true 来重置所有内容。这将重置整个集群,因此请谨慎使用:

(ansible) user@lab ~ # ansible-playbook -i tests/inventory/kubelab tests/kubelab.yml -e k8s_reset=true

安装后与集群交互

一旦 playbook 执行完成,与集群交互的最佳方式是使用 kubectl 命令,可以通过以下方式安装:

user@lab ~ # curl -s -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

user@lab ~ # chmod +x kubectl

user@lab ~ # sudo mv kubectl /usr/local/bin

Kubernetes 角色会生成一个本地目录,里面包含主要的 kubeconfig 文件,名为 admin.conf。使用它的最简单方法是导出 KUBECONFIG 变量,如下所示:

user@lab ~ # export KUBECONFIG=~/kubernetes/admin.conf

从现在开始直到会话结束,每次执行 kubectl 时都会依赖于该文件中的凭证:

user@lab ~ # kubectl cluster-info
Kubernetes 控制平面正在运行,地址为 https://192.168.122.199:8443
CoreDNS 正在运行,地址为 https://192.168.122.199:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

若要进一步调试和诊断集群问题,请使用 'kubectl cluster-info dump'。

user@lab ~ # kubectl get nodes
NAME           STATUS   ROLES           AGE   VERSION
kubernetes-1   Ready    control-plane   26h   v1.25.3
kubernetes-2   Ready    control-plane   26h   v1.25.3
kubernetes-3   Ready    control-plane   26h   v1.25.3
kubernetes-4   Ready    <none>          26h   v1.25.3

也可以使用不同的用户登录到集群,请查看 用户 部分获取详细信息。

配置

清单

典型的清单取决于你想要部署的内容,查看示例 kubelab,你可以在主机文件中声明所有节点(请参阅 tests/inventory/kubelab/hosts):

# Kubernetes 主机
[kubelab]
kubernetes-1 k8s_role=control-plane run_non_infra_pods=true
kubernetes-2 k8s_role=control-plane run_non_infra_pods=true
kubernetes-3 k8s_role=control-plane run_non_infra_pods=true
kubernetes-4 k8s_role=worker

你将设置哪些节点充当控制平面,同时确定这些节点是否会运行非基础设施的 Pod(以使控制平面也成为工作节点)。

然后你可以在组文件(即 inventory/kubelab/group_vars/kubelab.yml)内定义所有附加配置,具体取决于你想要实现的内容。

Kubernetes 主机的主机组名称默认是 kubelab,但可以通过声明 k8s_host_group 变量来重写。

Kubernetes 集群

如果你想要实现一个多控制平面的高可用集群,你需要指定这些变量:

k8s_cluster_name: kubelab

k8s_control_plane_node: kubernetes-1
k8s_control_plane_port: 6443
k8s_control_plane_cert_key: "91bded725a628a081d74888df8745172ed842fe30c7a3898b3c63ca98c7226fd"

k8s_multi_control_plane: true
k8s_balancer_VIP: 192.168.122.199
k8s_balancer_interface: eth0
k8s_balancer_port: 8443
k8s_balancer_password: "d6e284576158b1"

k8s_wait_timeout: 1200

k8s_control_plane_ports:
  - 2379-2380/tcp
  - 6443/tcp
  - 8443/tcp
  - 10250/tcp
  - 10257/tcp
  - 10259/tcp

这将从节点 kubernetes-1 启动集群,通过 k8s_multi_control_plane 启用多控制平面,并设置 VIP 地址和接口。

注意: 你会想要更改 k8s_control_plane_cert_keyk8s_balancer_password 以提高安全性。

注意: 目前只支持 rbd 供应。

网络插件

Kubernetes 角色支持 Flannel 和 Calico 网络插件。配置取决于你想要实现的插件。

对于 Flannel,你将需要类似以下内容:

# Flannel 插件
k8s_network_addon: flannel
k8s_network_addon_ports:
  - 8285/udp
  - 8472/udp

要查看如何实现 Calico,请查看 默认文件

仪表板

Kubernetes 仪表板可以通过在配置中添加以下内容来实现:

k8s_dashboard_enable: true

安装完成后,通过使用 kubectl proxy 访问仪表板的最简单方法是访问相关的 URL http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

将会提示输入登录信息,你可以通过传递一个令牌来登录。默认情况下,Kubernetes 角色会创建一个名为 dashboard-user 的用户(你可以覆盖它)。

要获取令牌,你需要使用 kubectl,如下所示:

user@lab ~ # kubectl -n kubernetes-dashboard create token dashboard-user
<你的令牌>

复制并粘贴上述命令的输出到提示符中,你将完成登录。

用户

你可以通过声明类似以下内容来向集群添加用户:

k8s_users:
  - name: pod-viewer
    namespace: default
    role_name: pod-viewer-role
    role_rules_apigroups: '""'
    role_rules_resources: '"pods","pods/exec","pods/log"'
    role_rules_verbs: '"*"'
    rolebinding_name: pod-viewer-rolebinding
    cert_expire_days: 3650
    update_kube_config: true

这将创建一个本地目录,包含以下文件:

user@lab ~ # ls -1 kubernetes/users/
pod-viewer.crt
pod-viewer.csr
pod-viewer.key
users.conf
users-rolebindings.yaml
users-roles.yaml

然后可以使用 users.conf 文件访问集群,如下所示:

user@lab ~ # export KUBECONFIG=~/kubernetes/users/users.conf

rasca@catastrofe [~]> kubectl config get-contexts
CURRENT   NAME                       CLUSTER   AUTHINFO           NAMESPACE
*         kubernetes-admin@kubelab   kubelab   kubernetes-admin
          pod-viewer@kubelab         kubelab   pod-viewer         default

user@lab ~ # kubectl config use-context pod-viewer@kubelab
切换到上下文 "pod-viewer@kubelab"。

user@lab ~ # kubectl config get-contexts
CURRENT   NAME                       CLUSTER   AUTHINFO           NAMESPACE
          kubernetes-admin@kubelab   kubelab   kubernetes-admin
*         pod-viewer@kubelab         kubelab   pod-viewer         default

user@lab ~ # kubectl get pods
在默认命名空间中未找到资源。

Ceph CSI

Kubernetes 角色实际上支持实现 Ceph CSI 存储类。可以如下定义:

k8s_ceph_csi_enable: true
k8s_ceph_csi_id: lab-ceph
k8s_ceph_csi_secret_userid: kubernetes
k8s_ceph_csi_secret_userkey: AQAWvU5jjBHSGhAAuAXtHFt0h05B5J/VHERGOA==
k8s_ceph_csi_clusterid: d046bbb0-4ee4-11ed-8f6f-525400f292ff
k8s_ceph_csi_pool: kubepool
k8s_ceph_csi_monitors:
  - 192.168.122.11:6789
  - 192.168.122.12:6789
  - 192.168.122.13:6789

然后可以声明新的 PVC:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rbd-pvc
  namespace: rasca
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: csi-rbd-sc

以及相关 Pod:

---
apiVersion: v1
kind: Pod
metadata:
  name: csi-rbd-demo-pod
  namespace: rasca
spec:
  containers:
    - name: web-server
      image: nginx
      volumeMounts:
        - name: mypvc
          mountPath: /var/lib/www/html
  volumes:
    - name: mypvc
      persistentVolumeClaim:
        claimName: rbd-pvc
        readOnly: false

注意: 目前只支持 rbd 供应。

MetalLB

要启用 MetalLB,一种适用于裸金属 Kubernetes 集群的负载均衡器实现,只需声明:

k8s_metallb_enable: true
k8s_metallb_pools:
  - name: 'first-pool'
    addresses: '192.168.122.100-192.168.122.130'

这样就可以使用这个负载均衡器在声明的地址范围内创建 IP(查看下一个 ingress-nginx 示例以便理解)。

Ingress NGINX

要启用 Ingress NGINX,一个在 Kubernetes 中使用 NGINX 作为反向代理和负载均衡器的 Ingress 控制器,只需声明:

k8s_ingress_nginx_enable: true

这将安装 Ingress NGINX 控制器,可用于不同目的。

控制平面上的 Ingress NGINX

例如,可以通过在 HAProxy 管理的平衡 IP 上暴露 80443 端口来使用 Ingress NGINX,如下所示:

k8s_ingress_nginx_enable: true
k8s_ingress_nginx_haproxy_conf: true
k8s_ingress_nginx_services:
  - name: ingress-nginx-externalip
    spec:
      externalIPs:
      - 192.168.122.199
      ports:
      - name: port-1
        port: 80
        protocol: TCP
      - name: port-2
        port: 443
        protocol: TCP
      selector:
        app.kubernetes.io/component: controller
        app.kubernetes.io/instance: ingress-nginx
        app.kubernetes.io/name: ingress-nginx

这将使两个端口在平衡 IP(在这个例子中为 192.168.122.199)上暴露,并使服务能够响应。

测试这个只需尝试以下操作:

$ kubectl create deployment demo --image=httpd --port=80
deployment.apps/demo 创建成功

$ kubectl expose deployment demo
service/demo 创建成功

$ kubectl create ingress demo --class=nginx \
    --rule="demo.192.168.122.199.nip.io/*=demo:80" \
    --annotation="nginx.ingress.kubernetes.io/service-upstream=true"
ingress.networking.k8s.io/demo 创建成功

$ curl http://demo.192.168.122.199.nip.io
<html><body><h1>它工作了!</h1></body></html>

或者测试 TLS:

$ kubectl create deployment demo --image=httpd --port=80
deployment.apps/demo 创建成功

$ kubectl expose deployment demo
service/demo 创建成功

$ openssl genrsa -out cert.key 2048
(没有输出)

$ openssl req -new -key cert.key -out cert.csr -subj "/CN=demo.192.168.122.199.nip.io"
(没有输出)

$ openssl x509 -req -days 366 -in cert.csr -signkey cert.key -out cert.crt
证书请求自签名成功
subject=CN = demo.192.168.122.199.nip.io

$ kubectl create secret tls tls-secret --cert=./cert.crt --key=./cert.key
secret/tls-secret 创建成功

$ kubectl create ingress demo --class=nginx \
    --rule="demo.192.168.122.199.nip.io/*=demo:80,tls=tls-secret" \
    --annotation="nginx.ingress.kubernetes.io/service-upstream=true"
ingress.networking.k8s.io/demo 创建成功

$ curl -k https://demo.192.168.122.199.nip.io
<html><body><h1>它工作了!</h1></body></html>

需要使用 --annotation="nginx.ingress.kubernetes.io/service-upstream=true" 的原因在于这个 ingress-nginx 问题

与 MetalLB 结合使用的 Ingress NGINX

另一种方式是结合使用 MetalLB,通过声明一个 LoadBalancer 服务,如下所示:

k8s_ingress_nginx_enable: true
k8s_ingress_nginx_services:
  - name: ingress-nginx-lb
    spec:
      type: LoadBalancer
      loadBalancerIP: 192.168.122.100
      ports:
      - name: port-1
        port: 80
        protocol: TCP
      - name: port-2
        port: 443
        protocol: TCP

这将安装与控制器相关的所有内容,并分配 MetalLB 提供的地址范围内的 loadBalancerIP,并暴露这两个端口 80443

Cert Manager

要启用 Cert Manager,一个自动化管理 Kubernetes 中证书的控制器,只需声明:

k8s_cert_manager_enable: true
k8s_cert_manager_issuers:
  - name: letsencrypt
    cluster: true
    acme:
      server: https://acme-v02.api.letsencrypt.org/directory
      email: [email protected]
      privateKeySecretRef:
        name: letsencrypt
      solvers:
      - http01:
          ingress:
            class: nginx

这将安装与控制器相关的所有内容,并创建一个将使用 letsencrypt 进行 HTTP01 挑战解析的集群发行者。

一旦安装完成并且你想要暴露一个应用程序,你可以使用类似以下 YAML 进行测试:

apiVersion: v1
kind: Namespace
metadata:
  name: rasca
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: index-html
  namespace: rasca
data:
  index.html: |
    这是我美妙的 Web 服务器!
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: rasca
  labels:
    app: nginx
spec:
  containers:
    - name: web-server
      image: nginx
      volumeMounts:
      - name: docroot
        mountPath: /usr/share/nginx/html
  volumes:
    - name: docroot
      configMap:
        name: index-html
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: rasca
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
  name: nginx-ingress
  namespace: rasca
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.apps.kubelab.mmul.it
    http:
      paths:
      - backend:
          service:
            name: nginx-service
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - nginx.apps.kubelab.mmul.it
    secretName: nginx.apps.kubelab.mmul.it

如果你仔细查看最后一个资源,名为 nginx-ingressIngress 将会看到两个重要部分:

  • metadata -> annotations 下的注释 cert-manager.io/cluster-issuer: letsencrypt

  • spec: -> tls 下的主机声明。

有了这些设置,在一些时间后,你将能够提供为暴露的服务的证书。

许可

MIT

作者信息

Raoul Scarazzini (rascasoft)

关于项目

This role automates the creation of a Kubernetes cluster complete of additional dashboard, users and operators.

安装
ansible-galaxy install mmul.kubelab
许可证
mit
下载
139
拥有者