Initial commit
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.tofu]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
@@ -0,0 +1,7 @@
|
||||
# General rules
|
||||
.*
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
|
||||
!.gitignore
|
||||
!.editorconfig
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env just
|
||||
|
||||
opentofu_dir := "infra/"
|
||||
|
||||
up:
|
||||
just gen-ssh-pair
|
||||
tofu -chdir=infra init
|
||||
tofu -chdir=infra apply -auto-approve
|
||||
|
||||
just playbook
|
||||
just get-admin-conf
|
||||
|
||||
tofu-init:
|
||||
tofu -chdir={{ opentofu_dir }} init -upgrade
|
||||
|
||||
tofu-apply: tofu-init gen-ssh-pair
|
||||
tofu -chdir={{ opentofu_dir }} apply -auto-approve
|
||||
|
||||
tofu-destroy: tofu-init
|
||||
tofu -chdir={{ opentofu_dir }} apply -auto-approve -destroy
|
||||
|
||||
build-inventory:
|
||||
#!/usr/bin/env bash
|
||||
master_ips=$(tofu -chdir=infra output -json master_addresses)
|
||||
worker_ips=$(tofu -chdir=infra output -json worker_addresses)
|
||||
|
||||
# Build the inventory file cleanly using bash loops over the JSON arrays
|
||||
{
|
||||
echo "[masters]"
|
||||
for i in $(seq 0 $(jq 'length - 1' <<< "${master_ips}")); do
|
||||
ip=$(jq -r ".[$i]" <<< "${master_ips}")
|
||||
echo "master-${i} ansible_host=${ip} ansible_user=root ansible_ssh_private_key_file=ansible/.ssh/key ansible_python_interpreter=auto_silent"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "[workers]"
|
||||
for i in $(seq 0 $(jq 'length - 1' <<< "${worker_ips}")); do
|
||||
ip=$(jq -r ".[$i]" <<< "${worker_ips}")
|
||||
echo "worker-${i} ansible_host=${ip} ansible_user=root ansible_ssh_private_key_file=ansible/.ssh/key ansible_python_interpreter=auto_silent"
|
||||
done
|
||||
} > ansible/hosts.ini
|
||||
|
||||
playbook: build-inventory
|
||||
ansible-playbook --inventory ansible/hosts.ini ansible/playbook.yaml --ssh-extra-args "-o StrictHostKeyChecking=no"
|
||||
# ansible-playbook --inventory ansible/hosts.ini ansible/setup-playbook.yaml --ssh-extra-args "-o StrictHostKeyChecking=no"
|
||||
# ansible-playbook --inventory ansible/hosts.ini ansible/master-playbook.yaml --ssh-extra-args "-o StrictHostKeyChecking=no"
|
||||
# ansible-playbook --inventory ansible/hosts.ini ansible/worker-playbook.yaml --ssh-extra-args "-o StrictHostKeyChecking=no"
|
||||
|
||||
down: tofu-destroy
|
||||
rm ansible/hosts.ini || true
|
||||
rm -r ansible/.ssh/ || true
|
||||
rm admin.conf || true
|
||||
|
||||
gen-ssh-pair:
|
||||
#!/usr/bin/env bash
|
||||
mkdir -p ansible/.ssh
|
||||
[ ! -f ansible/.ssh/key ] && ssh-keygen -f ansible/.ssh/key -P '' || true
|
||||
|
||||
get-admin-conf:
|
||||
incus exec master-0 -- cat /etc/kubernetes/admin.conf > k8s-admin.conf
|
||||
@@ -0,0 +1,5 @@
|
||||
[masters]
|
||||
master-0 ansible_host=10.150.0.2 ansible_user=root ansible_ssh_private_key_file=ansible/.ssh/key ansible_python_interpreter=auto_silent
|
||||
master-1 ansible_host=10.150.0.4 ansible_user=root ansible_ssh_private_key_file=ansible/.ssh/key ansible_python_interpreter=auto_silent
|
||||
|
||||
[workers]
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
- name: Initialise empty disk with BTRFS
|
||||
hosts: all
|
||||
vars:
|
||||
target_disk: /dev/disk/by-id/ata-QEMU_HARDDISK_incus_ext
|
||||
tasks:
|
||||
- name: Ensure btrfs-progs, parted and blkid is installed
|
||||
ansible.builtin.package:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- btrfs-progs
|
||||
- parted
|
||||
- blkid
|
||||
- name: Ensure external disk has single partition on GPT
|
||||
community.general.parted:
|
||||
device: "{{ target_disk }}"
|
||||
name: ext
|
||||
number: 1
|
||||
label: gpt
|
||||
state: present
|
||||
- name: Ensure BTRFS is formatted on external disk
|
||||
community.general.filesystem:
|
||||
dev: "{{ target_disk }}-part1"
|
||||
fstype: btrfs
|
||||
- name: Mount external disk to /mnt
|
||||
ansible.posix.mount:
|
||||
src: "{{ target_disk }}-part1"
|
||||
path: /mnt
|
||||
fstype: btrfs
|
||||
state: mounted
|
||||
|
||||
# - name: Create BTRFS filesystem on external disk
|
||||
# community.general.filesystem:
|
||||
# fstype: btrfs
|
||||
# dev: "{{ target_disk }}"
|
||||
@@ -0,0 +1,154 @@
|
||||
- name: Primary Master Initialisation
|
||||
hosts: masters[0]
|
||||
tasks:
|
||||
- name: Initialise high-availability Kubernetes cluster
|
||||
ansible.builtin.command: >-
|
||||
kubeadm init
|
||||
--pod-network-cidr="172.16.0.0/16"
|
||||
--control-plane-endpoint="{{ ansible_default_ipv4.address }}:6443"
|
||||
--upload-certs
|
||||
args:
|
||||
creates: /etc/kubernetes/admin.conf
|
||||
- name: Copy Kubernetes Admin Config
|
||||
ansible.builtin.command: "{{ item }}"
|
||||
loop:
|
||||
- mkdir -p $HOME/.kube
|
||||
- cp /etc/kubernetes/admin.conf $HOME/.kube/config
|
||||
- chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
args:
|
||||
creates: $HOME/.kube/config
|
||||
|
||||
- name: Install Pod Network (Calico)
|
||||
ansible.builtin.shell: kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.32.0/manifests/calico.yaml > pod_network_setup.txt
|
||||
args:
|
||||
chdir: $HOME
|
||||
creates: pod_network_setup.txt
|
||||
|
||||
- name: Add Helm repositories
|
||||
kubernetes.core.helm_repository:
|
||||
name: "{{ item.name }}"
|
||||
repo_url: "{{ item.url }}"
|
||||
loop:
|
||||
- name: metrics-server
|
||||
url: https://kubernetes-sigs.github.io/metrics-server/
|
||||
- name: prometheus-community
|
||||
url: https://prometheus-community.github.io/helm-charts
|
||||
- name: longhorn
|
||||
url: https://charts.longhorn.io
|
||||
- name: traefik
|
||||
url: https://traefik.github.io/charts
|
||||
- name: minecraft-server-charts
|
||||
url: https://itzg.github.io/minecraft-server-charts/
|
||||
|
||||
- name: Install Metrics Server
|
||||
kubernetes.core.helm:
|
||||
release_name: metrics-server
|
||||
release_namespace: kube-system
|
||||
chart_ref: metrics-server/metrics-server
|
||||
chart_version: 3.13.0
|
||||
values:
|
||||
args:
|
||||
- --kubelet-insecure-tls
|
||||
|
||||
- name: Install Longhorn
|
||||
kubernetes.core.helm:
|
||||
release_name: longhorn
|
||||
release_namespace: longhorn-system
|
||||
create_namespace: true
|
||||
chart_ref: longhorn/longhorn
|
||||
chart_version: 1.12.0
|
||||
|
||||
- name: Install Prometheus
|
||||
kubernetes.core.helm:
|
||||
release_name: prometheus
|
||||
release_namespace: monitoring
|
||||
create_namespace: true
|
||||
chart_ref: prometheus-community/prometheus
|
||||
chart_version: 29.10.0
|
||||
state: absent
|
||||
|
||||
- name: Install Traefik
|
||||
kubernetes.core.helm:
|
||||
release_name: traefik
|
||||
release_namespace: default
|
||||
create_namespace: true
|
||||
chart_ref: traefik/traefik
|
||||
chart_version: 40.2.0
|
||||
values:
|
||||
deployment:
|
||||
kind: DaemonSet
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop: [ALL]
|
||||
add: [NET_BIND_SERVICE]
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
ports:
|
||||
web:
|
||||
port: 80
|
||||
containerPort: 80
|
||||
hostPort: 80
|
||||
websecure:
|
||||
port: 443
|
||||
containerPort: 443
|
||||
hostPort: 443
|
||||
|
||||
- name: Install Minecraft
|
||||
kubernetes.core.helm:
|
||||
release_name: minecraft
|
||||
release_namespace: default
|
||||
chart_ref: minecraft-server-charts/minecraft
|
||||
chart_version: 5.1.3
|
||||
values:
|
||||
minecraftServer:
|
||||
eula: true
|
||||
persistence:
|
||||
dataDir:
|
||||
enabled: true
|
||||
|
||||
- name: Extract Control Plane Decryption Key & Join Token
|
||||
block:
|
||||
- name: Generate Fresh Join Command
|
||||
ansible.builtin.command: kubeadm token create --print-join-command
|
||||
register: join_command_raw
|
||||
|
||||
- name: Upload Certs and Capture Certificate Key
|
||||
shell: kubeadm init phase upload-certs --upload-certs | tail -n 1
|
||||
register: cert_key_raw
|
||||
|
||||
- name: Set facts across playbooks
|
||||
ansible.builtin.set_fact:
|
||||
k8s_join_base: "{{ join_command_raw.stdout }}"
|
||||
k8s_cert_key: "{{ cert_key_raw.stdout }}"
|
||||
delegate_to: localhost
|
||||
delegate_facts: true
|
||||
|
||||
|
||||
- name: Join Secondary Control Planes
|
||||
hosts: masters:!masters[0] # <--- Targets masters 1 and 2
|
||||
tasks:
|
||||
- name: Join Cluster as Control Plane Node
|
||||
ansible.builtin.shell: "{{ hostvars['localhost']['k8s_join_base'] }} --control-plane --certificate-key {{ hostvars['localhost']['k8s_cert_key'] }}"
|
||||
args:
|
||||
creates: /etc/kubernetes/admin.conf
|
||||
|
||||
- name: Copy Kubernetes Admin Config
|
||||
ansible.builtin.shell: "{{ item }}"
|
||||
loop:
|
||||
- mkdir -p $HOME/.kube
|
||||
- cp /etc/kubernetes/admin.conf $HOME/.kube/config
|
||||
- chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
args:
|
||||
creates: $HOME/.kube/config
|
||||
|
||||
- name: Remove control plane taint
|
||||
hosts: masters[0]
|
||||
tasks:
|
||||
- name: Remove control plane NoSchedule taint from all nodes
|
||||
kubernetes.core.k8s_taint:
|
||||
state: absent
|
||||
name: "{{ item }}"
|
||||
taints:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
effect: NoSchedule
|
||||
loop: "{{ groups['masters'] }}"
|
||||
@@ -0,0 +1,87 @@
|
||||
- name: Initialise Master and Worker Nodes
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: Enable IPv4 forwarding
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: 1
|
||||
sysctl_set: true
|
||||
|
||||
- name: Enable Kernel Modules
|
||||
community.general.modprobe:
|
||||
name: "{{ item }}"
|
||||
persistent: present
|
||||
loop:
|
||||
- br_netfilter
|
||||
- dm-crypt
|
||||
|
||||
- name: Ensure /sys mount is set to shared for container runtimes
|
||||
block:
|
||||
- name: Remount /sys as shared immediately
|
||||
ansible.builtin.command: mount --make-rshared {{ item }}
|
||||
loop:
|
||||
- /
|
||||
- /sys
|
||||
- /run
|
||||
changed_when: false
|
||||
|
||||
- name: Create Alpine local.d script for permanent shared mount
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/local.d/mount-shared.start
|
||||
content: |
|
||||
#!/bin/sh
|
||||
mount --make-rshared /
|
||||
mount --make-rshared /sys
|
||||
mount --make-rshared /run
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Alpine local service is enabled on boot
|
||||
ansible.builtin.service:
|
||||
name: local
|
||||
enabled: true
|
||||
runlevel: default
|
||||
|
||||
- name: Install tools
|
||||
ansible.builtin.package:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- htop
|
||||
|
||||
- name: Install kubectl, kubelet, kubeadm and containerd
|
||||
ansible.builtin.package:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
loop:
|
||||
- kubectl
|
||||
- kubeadm
|
||||
- kubelet
|
||||
- containerd
|
||||
- cni-plugins
|
||||
- helm
|
||||
- open-iscsi
|
||||
|
||||
- name: Start kubelet and containerd
|
||||
ansible.builtin.service:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- kubelet
|
||||
- containerd
|
||||
- iscsid
|
||||
|
||||
- name: Add /opt/cni/bin to containerd CNI binary directories
|
||||
ansible.builtin.replace:
|
||||
path: /etc/containerd/config.toml
|
||||
regexp: "bin_dirs = \\['/usr/libexec/cni'\\]"
|
||||
replace: "bin_dirs = ['/opt/cni/bin', '/usr/libexec/cni']"
|
||||
notify: Restart containerd
|
||||
|
||||
handlers:
|
||||
- name: Restart containerd
|
||||
ansible.builtin.service:
|
||||
name: containerd
|
||||
state: restarted
|
||||
@@ -0,0 +1,24 @@
|
||||
- name: Extract Worker Join Token from Primary Master
|
||||
hosts: masters[0] # <--- Targets only the first master safely
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Generate worker join command
|
||||
ansible.builtin.command: kubeadm token create --print-join-command
|
||||
register: join_command_raw
|
||||
changed_when: false # Reading/generating a token text string changes no host state
|
||||
|
||||
- name: Save join command globally
|
||||
ansible.builtin.set_fact:
|
||||
k8s_worker_join: "{{ join_command_raw.stdout }}"
|
||||
delegate_to: localhost
|
||||
delegate_facts: true
|
||||
|
||||
- name: Join Worker Nodes to Cluster
|
||||
hosts: workers
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Join cluster
|
||||
ansible.builtin.shell: "{{ hostvars['localhost']['k8s_worker_join'] }} >> node_joined.txt"
|
||||
args:
|
||||
chdir: $HOME
|
||||
creates: node_joined.txt
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env sh
|
||||
set -e
|
||||
|
||||
err() { echo "$@" >&2; exit 1; }
|
||||
log() { echo "$@" >&2; }
|
||||
|
||||
[ "$(id -u)" -ne 0 ] && err "You must run this script as root"
|
||||
|
||||
# Install minimal packages for provisioning
|
||||
PACKAGES="dropbear openssh-sftp-server python3 py3-yaml py3-kubernetes cloud-utils-growpart e2fsprogs-extra lsblk"
|
||||
apk update && apk upgrade
|
||||
apk add ${PACKAGES}
|
||||
|
||||
# Enable and start services
|
||||
enable_and_start() {
|
||||
service="$1"
|
||||
rc-update add "${service}" default
|
||||
service "${service}" start
|
||||
}
|
||||
|
||||
enable_and_start dropbear
|
||||
|
||||
# increase root partition size
|
||||
root_dev=$(readlink -f /dev/root)
|
||||
disk=$(lsblk -no pkname "$root_dev")
|
||||
part_num=$(echo "$root_dev" | sed 's|.*[^0-9]||')
|
||||
|
||||
echo "Growing /dev/${disk}${part_num}..."
|
||||
|
||||
# Grow partition and resize
|
||||
growpart "/dev/$disk" "$part_num" || err "Partition growth failed"
|
||||
resize2fs "$root_dev" || err "Filesystem resize failed"
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
# ------
|
||||
# Locals
|
||||
# ------
|
||||
|
||||
locals {
|
||||
root_disk_size = "16GiB"
|
||||
ext_disk_size = "16GiB"
|
||||
network_cidr = "10.150.0.1/24"
|
||||
|
||||
master_count = 2
|
||||
worker_count = 0
|
||||
}
|
||||
|
||||
# ---------
|
||||
# Resources
|
||||
# ---------
|
||||
|
||||
resource "incus_project" "this" {
|
||||
name = "deskpi-cluster"
|
||||
description = "The emulated DeskPi Super6C stack."
|
||||
}
|
||||
|
||||
resource "incus_image" "alpine" {
|
||||
project = incus_project.this.name
|
||||
|
||||
source_image = {
|
||||
remote = "images"
|
||||
name = "alpine/edge"
|
||||
type = "virtual-machine"
|
||||
}
|
||||
}
|
||||
|
||||
resource "incus_profile" "this" {
|
||||
name = "Default"
|
||||
description = "The default profile applied to both masters and workers."
|
||||
project = incus_project.this.name
|
||||
|
||||
depends_on = [incus_network.this]
|
||||
|
||||
config = {
|
||||
"limits.cpu" = var.cpus
|
||||
"limits.memory" = var.memory
|
||||
"boot.autostart" = false
|
||||
"security.secureboot" = false
|
||||
}
|
||||
|
||||
device {
|
||||
name = "root"
|
||||
type = "disk"
|
||||
|
||||
properties = {
|
||||
"pool" = "default"
|
||||
"path" = "/"
|
||||
"size" = local.root_disk_size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "incus_network" "this" {
|
||||
name = "deskpi-cluster"
|
||||
description = "An emulated network for the DeskPi Super6C cluster project."
|
||||
project = incus_project.this.name
|
||||
type = "bridge"
|
||||
|
||||
config = {
|
||||
"ipv4.address" = local.network_cidr
|
||||
"ipv4.nat" = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "incus_instance" "master" {
|
||||
count = local.master_count
|
||||
|
||||
name = "master-${count.index}"
|
||||
description = "Kubernetes Master ${count.index}"
|
||||
project = incus_project.this.name
|
||||
|
||||
type = "virtual-machine"
|
||||
image = incus_image.alpine.fingerprint
|
||||
profiles = [incus_profile.this.name]
|
||||
|
||||
wait_for {
|
||||
type = "agent"
|
||||
}
|
||||
|
||||
file {
|
||||
source_path = "bootstrap.sh"
|
||||
target_path = "/bootstrap.sh"
|
||||
}
|
||||
|
||||
file {
|
||||
source_path = "../ansible/.ssh/key.pub"
|
||||
target_path = "/root/.ssh/authorized_keys"
|
||||
create_directories = true
|
||||
}
|
||||
|
||||
device {
|
||||
name = "eth0"
|
||||
type = "nic"
|
||||
|
||||
properties = {
|
||||
"network" = incus_network.this.name
|
||||
"ipv4.address" = cidrhost(local.network_cidr, 2 + (2 * count.index))
|
||||
}
|
||||
}
|
||||
|
||||
device {
|
||||
name = "ext"
|
||||
type = "disk"
|
||||
|
||||
properties = {
|
||||
"pool" = "default"
|
||||
"source" = incus_storage_volume.master[count.index].name
|
||||
}
|
||||
}
|
||||
|
||||
exec = { "00-init" = { command = ["/bootstrap.sh"] } }
|
||||
}
|
||||
|
||||
resource "incus_storage_volume" "master" {
|
||||
count = local.master_count
|
||||
|
||||
name = "master-ext-${count.index}"
|
||||
description = "External drive for master ${count.index}"
|
||||
pool = "default"
|
||||
project = incus_project.this.name
|
||||
|
||||
content_type = "block"
|
||||
|
||||
config = {
|
||||
"size" = local.ext_disk_size
|
||||
}
|
||||
}
|
||||
|
||||
resource "incus_instance" "worker" {
|
||||
count = local.worker_count
|
||||
|
||||
name = "worker-${count.index}"
|
||||
description = "Kubernetes Worker ${count.index}"
|
||||
project = incus_project.this.name
|
||||
|
||||
type = "virtual-machine"
|
||||
image = incus_image.alpine.fingerprint
|
||||
profiles = [incus_profile.this.name]
|
||||
|
||||
wait_for {
|
||||
type = "agent"
|
||||
}
|
||||
|
||||
file {
|
||||
source_path = "bootstrap.sh"
|
||||
target_path = "/bootstrap.sh"
|
||||
}
|
||||
|
||||
file {
|
||||
source_path = "../ansible/.ssh/key.pub"
|
||||
target_path = "/root/.ssh/authorized_keys"
|
||||
create_directories = true
|
||||
}
|
||||
|
||||
device {
|
||||
name = "eth0"
|
||||
type = "nic"
|
||||
|
||||
properties = {
|
||||
"network" = incus_network.this.name
|
||||
"ipv4.address" = cidrhost(local.network_cidr, 3 + (2 * count.index))
|
||||
}
|
||||
}
|
||||
|
||||
exec = { "00-init" = { command = ["/bootstrap.sh"] } }
|
||||
}
|
||||
|
||||
# -------
|
||||
# Outputs
|
||||
# -------
|
||||
|
||||
output "master_addresses" {
|
||||
value = incus_instance.master[*].ipv4_address
|
||||
}
|
||||
|
||||
output "worker_addresses" {
|
||||
value = incus_instance.worker[*].ipv4_address
|
||||
}
|
||||
|
||||
# ---------
|
||||
# Terraform
|
||||
# ---------
|
||||
|
||||
terraform {
|
||||
required_version = "~> 1"
|
||||
|
||||
required_providers {
|
||||
incus = {
|
||||
source = "lxc/incus"
|
||||
version = "~> 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "incus" {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
variable "cpus" {
|
||||
description = "The number of CPU cores allocated to each virtual machine."
|
||||
type = number
|
||||
default = 2
|
||||
nullable = false
|
||||
|
||||
validation {
|
||||
condition = var.cpus >= 1
|
||||
error_message = "Allocated CPUs must be equal to or greater than 1."
|
||||
}
|
||||
}
|
||||
|
||||
variable "memory" {
|
||||
description = "The amount of memory allocated to each virtual machine."
|
||||
type = string
|
||||
default = "4GiB"
|
||||
nullable = false
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJZitGUlpSMUIydk13RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TmpBMk1EY3hNelF3TVROYUZ3MHpOakEyTURReE16UTFNVE5hTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURoMDNtOC8zWG5mNHptUGl5M1AzWHR3K2FzRWFOd3owbGZjdmloTzNDSGVmSjRkSHRNMlRyNmtrdnUKOW10R0l5L2UzRkd6Q3dybUIwZnRNZmY1WTlTMndSVFQrV25FOXFCWXZJeERJeWZYSFQ0Z3QyL2txR01Ib3ArTQoyeTZ5QTZ6a0RsVHFTQlZvU0hNNjBtT3IrU3MxUFp6VitvdVY1OFdOT1Y1bEpOYnNTcDlUNmtmYUtId0k2RnlYCmtvRGZFSERDdlZqMHU0S1ZCUzdxNHJUWGlQenA1WUFjRG1jUWJ1T1plb0VFd1RheTJuOXA5K3VZZ2wzd0RSalkKbnpMZGZQOU9LTVN6YVhDaUJjZDBkMllEdGR0UitHQ3ZlbktEZ3JISmI0YUQ4VmwzbE1XeUh0b0RJQ1NuQ290agpuSjZxVlpKNUJGeVd4NHhSKzViR3hRa3poUUdqQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJTYTI5VjBzdlhuUnlYN3YvNUR0UDdSWHdXczhEQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQXhYNkRLOWQ4Nwp3MEJBS3diQzRXblduTHlXMTRPc3Iwd3oxK2xCSnFrSkozZHlHRlpSRkFQVVpoNzV3dU5NTUNrNEZzcjhKbjA4CndtK1ZydHVvekpmeDJ6TUs0U1QzcElYOFR5QWptLzZYRjZ2dDNKUVV2WnJvMkRzcFZDOHdBVi93Y3Iwc2ZYVkgKSVB6TjVSZ3d5WENaUW41WFJxS2JpSG5TUXdTSVp5aXRkejQ3UHF4VFo5MTJiYnVuVCtjZHJ0bS9WMnBRajlpLwpmbHhoU292MG9henpoVVNWVHZqMUJqNm1tOXlOdzBlQTVTRW1YMm9La05lVW5aZDg5MWdBZnh6d1Fxd3hYUjZqCjU0aTJyclA2R3Iyc3U3bU9sTXI5UmxuZkROQkJ3Z0VoOUVHdFU4RXpNUzF4aW82ZXJvMlN5MzY1M3E2ZzZ5S3cKWjNBbllEbGk0Rjk4Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
||||
server: https://10.150.0.2:6443
|
||||
name: kubernetes
|
||||
contexts:
|
||||
- context:
|
||||
cluster: kubernetes
|
||||
user: kubernetes-admin
|
||||
name: kubernetes-admin@kubernetes
|
||||
current-context: kubernetes-admin@kubernetes
|
||||
kind: Config
|
||||
users:
|
||||
- name: kubernetes-admin
|
||||
user:
|
||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJY1RKVmdhbFhLRWt3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TmpBMk1EY3hNelF3TVROYUZ3MHlOekEyTURjeE16UTFNVE5hTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEVGVCRjkKelBKalZYajdMdFB0V1BBRklybnEyaE5vc2FtY2tjMmlUWU4xYU54bWI4a2kwMWRPOEVOT3ZPLzladzl6TStJZAphekRIMGlOR1BSRGdtYkhlZ2NDZ2VuZFlBNjN6T0xLdDM4clVoVDR0Q0hTRXdjRTVWeElwUXJOS0NjQXR5REQrCmxrL0Rza2o0cVRmWnBQcWpaVWFMVUZVLzNtM2V1Y3JrV2VrZlRaTlR4SERqdzgwVWVZRHJocjJxdmZsbjJZajMKLzB0UWdPSEdlcll2a2k5MEZLaDNFV1RnTGoyTnROeUtIY2FFSzBMRVRGREVtT251YS9XbXlFUTBELzlDVFFDYgpFQnhkVTZra2FRVlpGcGpDZWphWEF2QnN2KzZGZGlJQjkxT3F3ZnhLM1dzZlRzL1IrYklKb3RaQ1lvdkVTcVRhCjRDTDVTMEZ4UzZhZHIrdzVBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkpyYjFYU3k5ZWRISmZ1Lwova08wL3RGZkJhendNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJFMGFBYWIvMTVuZWxZdWVHOEtNV21wMnc2ClZxM2pleFE0U1o3bjQwQlJYZE5YRzhTblRnVXN6SHByNlRGcjUwajdobnlzaDIxZ3laSFliTm1QOG5STTdvRDkKMWJheWNZWGhUUXBseDA0aDRiVmt0VWlrOHBxSWZ1RGMyRHUwTmNNQVhsT09ram05TzNPL0l3dW1RUHhJdkh0ZwpRM3ROWGRpdmNWZFZhMHZNWWVXS2xqNXp1dzUzcGRQNEpSaTVOaWIzZmRKSTJCcDNBKzd0ZzFYckptSGpnM0RaCk81dEg5WFI3Y3NWUkJUbVdOL1U4UFdNTURMdHpmVStTMWFqUTFwWmVUd1l4emYxL3ZoL3B1czhkaGRpZ3plTDkKN2Z1VXl3MXhFQitkaTNQbk5UZ083c05qb3ptY0x6WU1POE9HTit5dE9QTG9GVm9tWDhtc3J0YlgrYWloCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
|
||||
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMDNnUmZjenlZMVY0K3k3VDdWandCU0s1NnRvVGFMR3BuSkhOb2syRGRXamNabS9KCkl0TlhUdkJEVHJ6di9XY1BjelBpSFdzd3g5SWpSajBRNEpteDNvSEFvSHAzV0FPdDh6aXlyZC9LMUlVK0xRaDAKaE1IQk9WY1NLVUt6U2duQUxjZ3cvcFpQdzdKSStLazMyYVQ2bzJWR2kxQlZQOTV0M3JuSzVGbnBIMDJUVThSdwo0OFBORkhtQTY0YTlxcjM1WjltSTkvOUxVSURoeG5xMkw1SXZkQlNvZHhGazRDNDlqYlRjaWgzR2hDdEN4RXhRCnhKanA3bXYxcHNoRU5BLy9RazBBbXhBY1hWT3BKR2tGV1JhWXdubzJsd0x3YkwvdWhYWWlBZmRUcXNIOFN0MXIKSDA3UDBmbXlDYUxXUW1LTHhFcWsydUFpK1V0QmNVdW1uYS9zT1FJREFRQUJBb0lCQUFMVWxhM25xcFFtbDlFdQorQWtPeGlUZnJPZ3NiMDl1VEJyeHEzdHlOeTQ5VklYNnBDTHNmQW4rN2NvazRWUzROcWJFZHNZVVkrTk1JUUExCjRRRGFsamxJUXl5QjBIUjZEajMzMVdkb2d6UnBzREtYdnc4cmNRR1lwa1BYNjFSVVdPTC9pazFXdERyTlhQYlAKb0FOQ09xb3d5cGU0RWR4Q09MWWJsSmRjeEl4czNmaDd0WVRsZFRDVUJxd3dsdmJnYUZ1UXdzRjByemVoTXpTMAp0SzJBUkNScmxnZzByVDA2OW1pcXRFVDdUTlhsd1U1bXNxR0FvaEk0aWRmbXZ3Y2JyRGdWb2NOOTdMYTNEKzNvCkswNE1EeEwrZ0lHYzJRVzRhNnJKMlU0K2lNNEtLcWdrak5xS3hiTWp2ZWxhcW1DNEl1a2wySzdUV0I2SVdKVWEKWWZMRnhYRUNnWUVBM2xEbEt3R08wUUExa3dqaVJiQlFBZjJITFFtTGVQNEExT0xUSHFLSlY1MzdBaWZyc2x2YgprekhNSGwySkFmVzBiSGpBMStsL2tKOU95dnVaK0FZRHd4RGVKK2dzY1d3amRId2hCWHo5Q3VnbDJpWVBiTWs3CkxkUUZ4NHhrV0Yxd0RRM3FjK2djb1BkNWlaVXdnUXpLMjZTNElzeHA1RzlpUkcyRWNIODJyREVDZ1lFQTg0SngKM1Bpc2JlQXVYNER6djUrbm5VU0VoUElBR242VG1tN0o2L1NDZU0rYjR3aHdsV1Zsd0xkY2R5dGJZV3Y2MldsQQpQV3RXd3JRT1V4NXF1K3JwN01zTkpiZTE2ZktpeWhVYk4zSVdMOU83a295RUwxWXlUNm9ETURkTjB4ZE9Cc1ZjCnZuY3NxaWk0UUFpbkRuZDU3Q2IwbXRxRWs3UTNwYlVaa3M2bXBva0NnWUE0ODdaUmx4dVVGUjZrWlRFNk14bTcKK012cFVMbW5MRUxnUnA5WkNNQndicXMvK1NRYlZBYmpKVzJxRmNJa2UySldLM1VUbXVDd0Z1K2pkbU1TTTlCQQo1NUJSM3R1THp1MGlTUzVZYnBXUWRycERzVjVnT3dqckM1YlRjUGEvNEdmMUlDeUF0dVNtbzk5QnpMTlpUQUtuCjFBSE1BRnZjUm1DQk1TRXRoSmxuOFFLQmdFdUp5WnlNbjZDdURIU2Y0ZjB0bjZkUG0vUkp4Zkp5RllPd25uN04KcUxPbFkydzRNQVNJSWRwNGh2eUl2SjRxQ3ZUcWkzMENFVFh3K1FpYnhPeHFZUXFOcXBScXVzbko5T25QUmxRYQoxZnNjS1hHNm1UNjk5SGwxK2VzNUhMRkE1M2wrTzlqeHl5ODExb0kyck92MThDSnJxekZtVy80ZHg2MWwwbnNTCkUreFJBb0dCQUpTRS9QZEcwWm4wVzlBeWZtQ2xKVHhFSnBIMk1jd3l3T0J2UEY4UnhPUCtEZDhBaTVLWEhtSGEKQjQwUW4wd0s4YVJBRm5nUGpTUC81ck9tWW5NRUI4cUEwTGNvenJON3ZhK2tveFdreVk4NmRjbHN3L3k3RVZvQQp4azh1MExka3puQmp4Mit3MmVqMnIzblBBT3RUSFk4U2NLWS83MGpiR1BDQkJPVjh1WXZrCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
|
||||
Reference in New Issue
Block a user