├── README.md ├── hosts.ini ├── kubernetes ├── install.sh ├── k8s_containrd_pkg.yml ├── k8s_master_init.yml └── k8s_workers.yml ├── main.tf ├── nginx ├── install.sh ├── nginx-deployment.yaml └── nginx-service.yaml ├── output.tf ├── provider.tf ├── variables.tf ├── variables.tfvars.sample └── wordpress ├── install.sh ├── mysql-deployment.yaml ├── services.yaml └── wordpress-deployment.yaml /README.md: -------------------------------------------------------------------------------- 1 | # Terraform dengan Kubernetes 2 | 3 | Proyek ini menggunakan Terraform untuk mengelola infrastruktur di platform Proxmox, di mana kami menginstal Kubernetes dan menyebarkan aplikasi WordPress di dalamnya. Proyek ini bertujuan untuk memberikan solusi yang mudah dan otomatis untuk mengatur lingkungan pengembangan dan produksi. 4 | 5 | ## Fitur 6 | 7 | - Mengelola infrastruktur menggunakan Terraform. 8 | - Menginstal dan mengonfigurasi Kubernetes secara otomatis. 9 | - Menyebarkan aplikasi WordPress di dalam kluster Kubernetes. 10 | - Menggunakan Proxmox sebagai platform virtualisasi. 11 | 12 | ## Version 13 | 14 | - **Proxmox VE**: Versi 8.2 15 | - **Kubernetes**: Versi terbaru (latest) 16 | - **WordPress**: Versi terbaru (latest) 17 | - **MySQL**: Versi 8.0 18 | - **Plugin Proxmox Telmate/Proxmox**: Versi 3.0.1-rc3 19 | - **Terraform**: Versi terbaru 20 | - **kubectl**: Versi terbaru (untuk mengelola kluster Kubernetes) 21 | 22 | ## Prasyarat 23 | 24 | Sebelum memulai, pastikan Anda telah memenuhi syarat berikut: 25 | 26 | - mempunyai username: user, dan akses root 27 | - sudah mempunyai template cloud init 28 | - membuat user api proxmox 29 | - mengganti hosts.ini dengan ip yang akan digunakan 30 | - sesuaikan wordpress/mysql-deployment.yaml, wordpress/wordpress-deployment.yaml 31 | - sesuaikan variables.tfvars setelah anda mengcopy dari sample 32 | 33 | ## Instalasi 34 | 1. git clone https://github.com/ForensicID/terraform-kubernetes.git 35 | 2. cd terraform-kubernetes 36 | 3. cp -R variables.tfvars.sample variables.tfvars 37 | 4. terraform init 38 | 5. terraform plan -var-file=variables.tfvars 39 | 6. terraform apply -var-file=variables.tfvars 40 | 41 | ### Jika ada pertanyaan silahkan 42 | -------------------------------------------------------------------------------- /hosts.ini: -------------------------------------------------------------------------------- 1 | [all] 2 | master ansible_host=192.168.1.x 3 | worker1 ansible_host=192.168.1.x 4 | worker2 ansible_host=192.168.1.x 5 | 6 | [masters] 7 | master 8 | 9 | [workers] 10 | worker1 11 | worker2 12 | 13 | [all:vars] 14 | ansible_ssh_common_args='-o StrictHostKeyChecking=no' 15 | -------------------------------------------------------------------------------- /kubernetes/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sleep 320s 4 | 5 | # Variabel 6 | HOST="hosts.ini" 7 | 8 | # File known_hosts 9 | KNOWN_HOSTS_FILE="/root/.ssh/known_hosts" 10 | 11 | # Ambil daftar host dari file inventori 12 | HOSTS=$(grep ansible_host "$INVENTORY_FILE" | awk -F'=' '{print $2}' | awk '{print $1}') 13 | 14 | # Tambahkan kunci SSH ke file known_hosts 15 | for HOST in $HOSTS; do 16 | echo "Adding $HOST to known_hosts" 17 | ssh-keyscan -H "$HOST" >> "$KNOWN_HOSTS_FILE" 18 | done 19 | 20 | # Execute Ansible playbook to install and configure containerd package on hosts 21 | ansible-playbook -i hosts.ini kubernetes/k8s_containrd_pkg.yml 22 | echo "Containerd package configuration applied." 23 | sleep 300s 24 | 25 | # Execute Ansible playbook to initialize the Kubernetes master node 26 | ansible-playbook -i hosts.ini kubernetes/k8s_master_init.yml 27 | echo "Kubernetes master node initialized." 28 | sleep 100s 29 | 30 | # Execute Ansible playbook to configure worker nodes 31 | ansible-playbook -i hosts.ini kubernetes/k8s_workers.yml 32 | echo "Kubernetes worker nodes configured." 33 | sleep 200s -------------------------------------------------------------------------------- /kubernetes/k8s_containrd_pkg.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | remote_user: user 3 | become: yes 4 | 5 | tasks: 6 | - name: Update and upgrade apt packages 7 | apt: 8 | update_cache: yes 9 | upgrade: dist 10 | 11 | - name: Make the Swap inactive 12 | command: swapoff -a 13 | 14 | - name: Remove Swap entry from /etc/fstab. 15 | lineinfile: 16 | dest: /etc/fstab 17 | regexp: swap 18 | state: absent 19 | 20 | - name: Create a empty file for containerd module. 21 | copy: 22 | content: "" 23 | dest: /etc/modules-load.d/containerd.conf 24 | force: no 25 | 26 | - name: Buat file konfigurasi untuk containerd 27 | ansible.builtin.copy: 28 | dest: /etc/modules-load.d/containerd.conf 29 | content: | 30 | overlay 31 | br_netfilters 32 | owner: root 33 | group: root 34 | mode: '0644' 35 | 36 | - name: Muat modul overlay 37 | ansible.builtin.command: 38 | cmd: modprobe overlay 39 | 40 | - name: Muat modul br_netfilter 41 | ansible.builtin.command: 42 | cmd: modprobe br_netfilter 43 | 44 | - name: Buat file konfigurasi sysctl untuk Kubernetes 45 | ansible.builtin.copy: 46 | dest: /etc/sysctl.d/kubernetes.conf 47 | content: | 48 | net.bridge.bridge-nf-call-iptables=1 49 | net.bridge.bridge-nf-call-ip6tables = 1 50 | net.bridge.bridge-nf-call-iptables = 1 51 | net.ipv4.ip_forward = 1 52 | owner: root 53 | group: root 54 | mode: '0644' 55 | 56 | - name: Terapkan perubahan sysctl 57 | ansible.builtin.command: 58 | cmd: sysctl --system 59 | 60 | - name: Apply sysctl changes 61 | command: sysctl -p 62 | 63 | - name: Installing Prerequisites for Kubernetes 64 | apt: 65 | name: 66 | - apt-transport-https 67 | - gnupg2 68 | - ca-certificates 69 | - curl 70 | - gnupg-agent 71 | - vim 72 | - software-properties-common 73 | state: present 74 | 75 | - name: Unduh GPG key Docker dan simpan ke /etc/apt/trusted.gpg.d/docker.gpg 76 | ansible.builtin.get_url: 77 | url: https://download.docker.com/linux/ubuntu/gpg 78 | dest: /tmp/docker.gpg 79 | mode: '0644' 80 | 81 | - name: Konversi GPG key Docker ke format yang benar 82 | ansible.builtin.command: 83 | cmd: gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg /tmp/docker.gpg 84 | 85 | - name: Add Docker Repository 86 | ansible.builtin.apt_repository: 87 | repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable" 88 | state: present 89 | filename: docker 90 | update_cache: yes 91 | 92 | - name: Install containerd. 93 | apt: 94 | name: 95 | - containerd.io 96 | state: present 97 | 98 | - name: Menghasilkan konfigurasi default containerd 99 | command: containerd config default 100 | register: containerd_config_default 101 | changed_when: false 102 | 103 | - name: Menulis konfigurasi default containerd ke file 104 | ansible.builtin.copy: 105 | content: "{{ containerd_config_default.stdout }}" 106 | dest: /etc/containerd/config.toml 107 | mode: '0644' 108 | 109 | - name: Backup config file 110 | copy: 111 | src: /etc/containerd/config.toml 112 | dest: /etc/containerd/config.toml.bak 113 | remote_src: yes 114 | 115 | - name: Replace SystemdCgroup setting with sed 116 | shell: sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml 117 | 118 | - name: Enable containerd service, and start it. 119 | systemd: 120 | name: containerd 121 | state: restarted 122 | enabled: yes 123 | daemon-reload: yes 124 | 125 | - name: Add Google official GPG key 126 | apt_key: 127 | url: https://packages.cloud.google.com/apt/doc/apt-key.gpg 128 | state: present 129 | 130 | - name: Tambahkan repository Kubernetes ke sumber apt 131 | ansible.builtin.copy: 132 | dest: /etc/apt/sources.list.d/kubernetes.list 133 | content: "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /\n" 134 | owner: root 135 | group: root 136 | mode: '0644' 137 | 138 | - name: Unduh kunci GPG Kubernetes 139 | ansible.builtin.get_url: 140 | url: https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key 141 | dest: /tmp/kubernetes-release.key 142 | 143 | - name: Konversi kunci GPG Kubernetes ke format yang benar 144 | ansible.builtin.command: 145 | cmd: gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg /tmp/kubernetes-release.key 146 | 147 | - name: Hapus kunci GPG sementara 148 | ansible.builtin.file: 149 | path: /tmp/kubernetes-release.key 150 | state: absent 151 | 152 | - name: Update APT package index 153 | ansible.builtin.apt: 154 | update_cache: yes 155 | 156 | - name: Installing Kubernetes Cluster Packages. 157 | apt: 158 | name: 159 | - kubeadm 160 | - kubectl 161 | - kubelet 162 | state: present 163 | 164 | - name: Enable service kubelet, and enable persistently 165 | service: 166 | name: kubelet 167 | enabled: yes 168 | 169 | - name: Reboot all the kubernetes nodes. 170 | reboot: 171 | post_reboot_delay: 60 172 | reboot_timeout: 80 173 | connect_timeout: 300 174 | test_command: uptime -------------------------------------------------------------------------------- /kubernetes/k8s_master_init.yml: -------------------------------------------------------------------------------- 1 | - hosts: masters 2 | remote_user: user 3 | become: yes 4 | 5 | tasks: 6 | 7 | - name: Intilizing Kubernetes Cluster 8 | shell: kubeadm init --ignore-preflight-errors=all 9 | 10 | - pause: seconds=30 11 | 12 | - name: Create directory for kube config. 13 | become: yes 14 | file: 15 | path: /root/.kube 16 | state: directory 17 | owner: root 18 | group: root 19 | mode: 0755 20 | 21 | - name: Copy /etc/kubernetes/admin.conf to user home directory /root/.kube/config 22 | become: yes 23 | copy: 24 | src: /etc/kubernetes/admin.conf 25 | dest: /root/.kube/config 26 | remote_src: yes 27 | owner: root 28 | group: root 29 | mode: '0644' 30 | 31 | - pause: seconds=30 32 | 33 | - name: Remove the cache directory. 34 | become: yes 35 | file: 36 | path: /root/.kube/cache 37 | state: absent 38 | 39 | - name: Create Pod Network & RBAC. 40 | become: yes 41 | command: "{{ item }}" 42 | with_items: 43 | - sudo kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml 44 | - sudo kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml 45 | 46 | - pause: seconds=30 47 | 48 | - name: Get the token for joining the nodes with Kuberentes master. 49 | shell: kubeadm token create --print-join-command 50 | register: kubernetes_join_command 51 | 52 | - debug: 53 | msg: "{{ kubernetes_join_command.stdout }}" 54 | 55 | - name: Copy join command to local file. 56 | become: false 57 | local_action: copy content="{{ kubernetes_join_command.stdout_lines[0] }}" dest="/tmp/kubernetes_join_command" mode=0777 -------------------------------------------------------------------------------- /kubernetes/k8s_workers.yml: -------------------------------------------------------------------------------- 1 | - hosts: masters 2 | remote_user: user 3 | become: yes 4 | become_method: sudo 5 | become_user: root 6 | 7 | tasks: 8 | - name: Get the token for joining the nodes with Kubernetes master 9 | shell: kubeadm token create --print-join-command 10 | register: kubernetes_join_command 11 | 12 | - name: Debug Kubernetes join command 13 | debug: 14 | msg: "{{ kubernetes_join_command.stdout }}" 15 | 16 | - name: Construct the join command with ignore preflight errors 17 | set_fact: 18 | join_command: "{{ kubernetes_join_command.stdout.strip() }} --ignore-preflight-errors=all" 19 | 20 | - name: Copy join command to local file 21 | ansible.builtin.copy: 22 | content: "{{ join_command }}" 23 | dest: "/tmp/kubernetes_join_command" 24 | mode: '0777' 25 | owner: "root" 26 | group: "root" 27 | 28 | - hosts: workers 29 | remote_user: user 30 | become: yes 31 | 32 | tasks: 33 | - name: Ensure file is removed 34 | ansible.builtin.file: 35 | path: "/tmp/kubernetes_join_command" 36 | state: absent 37 | 38 | - name: Copy join command to worker nodes 39 | ansible.builtin.copy: 40 | src: /tmp/kubernetes_join_command 41 | dest: /tmp/kubernetes_join_command 42 | mode: '0777' 43 | owner: "root" 44 | group: "root" 45 | 46 | - name: Menambahkan perintah ke /tmp/kubernetes_join_command 47 | shell: echo "--ignore-preflight-errors=all" >> /tmp/kubernetes_join_command 48 | 49 | - name: Debug join command file content 50 | ansible.builtin.command: 51 | cmd: cat /tmp/kubernetes_join_command 52 | register: join_command_content 53 | 54 | - name: Debug join command content 55 | debug: 56 | msg: "{{ join_command_content.stdout }}" 57 | 58 | - name: Join the worker nodes with the master 59 | shell: "sh /tmp/kubernetes_join_command" 60 | register: joined_or_not 61 | 62 | - name: Debug join command execution result 63 | debug: 64 | msg: "{{ joined_or_not.stdout }}" 65 | 66 | - hosts: masters 67 | remote_user: user 68 | become: yes 69 | 70 | tasks: 71 | - name: Configure kubectl command auto-completion 72 | lineinfile: 73 | dest: /root/.bashrc 74 | line: 'source <(kubectl completion bash)' -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_vm_qemu" "proxmox_vm_master" { 2 | count = var.num_k8s_masters_host 3 | name = "${var.num_k8s_masters_name}-${count.index}" 4 | target_node = var.pm_node_name 5 | clone = var.tamplate_vm_name 6 | os_type = "cloud-init" 7 | agent = 1 8 | memory = var.num_k8s_masters_mem 9 | sockets = "1" 10 | cores = var.num_k8s_workers_cpu 11 | full_clone = true 12 | scsihw = "virtio-scsi-pci" 13 | 14 | disks { 15 | ide { 16 | ide3 { 17 | cloudinit { 18 | storage = var.storage_name_location 19 | } 20 | } 21 | } 22 | scsi { 23 | scsi0 { 24 | disk { 25 | size = var.num_k8s_masters_disk 26 | storage = var.storage_name_location 27 | iothread = false 28 | discard = false 29 | } 30 | } 31 | } 32 | } 33 | 34 | network { 35 | model = "virtio" 36 | bridge = "vmbr0" 37 | } 38 | 39 | ipconfig0 = "ip=${var.master_ips[count.index]}/${var.networkrange},gw=${var.gateway}" 40 | 41 | lifecycle { 42 | ignore_changes = [ 43 | ciuser, 44 | sshkeys, 45 | disks, 46 | network 47 | ] 48 | } 49 | 50 | sshkeys = <