diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85e7c1d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.idea/ diff --git a/Initial_Setup/README.md b/Initial_Setup/README.md new file mode 100644 index 0000000..54b3af2 --- /dev/null +++ b/Initial_Setup/README.md @@ -0,0 +1,8 @@ + +# Pi4 + +For debian [Pi4 images](https://raspi.debian.net/tested-images/): + +- Use a keyboard and a screen to log in into `root` (password is empty) and set whatever. +- install `python3, python3-apt`. +- `ln -s /usr/bin/python3 /usr/bin/python` diff --git a/armbian_initial_setup.yaml b/Initial_Setup/armbian_initial_setup.yaml similarity index 60% rename from armbian_initial_setup.yaml rename to Initial_Setup/armbian_initial_setup.yaml index 86e12c9..ffcad36 100644 --- a/armbian_initial_setup.yaml +++ b/Initial_Setup/armbian_initial_setup.yaml @@ -4,6 +4,7 @@ - name: Pre Setup hosts: all gather_facts: false + become: true vars: # Connect @@ -13,8 +14,8 @@ # New values ## Users - new_user_name: "orangepi" - new_user_pass: "orangepi" + new_user_name: "kuser" + new_user_pass: "kuser1234" new_root_pass: "1234" ## Locales @@ -24,9 +25,29 @@ # SSH with ROOT tasks: + # Install sudo and locale thingies + - name: apt update + ansible.builtin.apt: + update_cache: yes + + - name: apt upgrade + ansible.builtin.apt: + name: "*" + state: latest + + - name: Install sudo + ansible.builtin.apt: + pkg: + - sudo + - locales + - locales-all + + - name: update facts + setup: # Set locale # https://serverfault.com/a/981742 + # https://andreas.scherbaum.la/blog/archives/941-Configuring-locales-in-Debian-and-Ubuntu,-using-Ansible-Reloaded.html - name: Ensure localisation files for '{{ new_locale }}' are available locale_gen: name: "{{ new_locale }}" @@ -42,19 +63,18 @@ register: locale_status changed_when: false - - name: Parse 'LANG' from current locale and language configuration - set_fact: - locale_lang: "{{ locale_status.stdout | regex_search('LANG=([^\n]+)', '\\1') | first }}" +# - name: Parse 'LANG' from current locale and language configuration +# set_fact: +# locale_lang: "{{ locale_status.stdout | regex_search('LANG=([^\n]+)', '\\1') | first }}" - - name: Parse 'LANGUAGE' from current locale and language configuration - set_fact: - locale_language: "{{ locale_status.stdout | regex_search('LANGUAGE=([^\n]+)', '\\1') | default([locale_lang], true) | first }}" +# - name: Parse 'LANGUAGE' from current locale and language configuration +# set_fact: +# locale_language: "{{ locale_status.stdout | regex_search('LANGUAGE=([^\n]+)', '\\1') | default([locale_lang], true) | first }}" - name: Configure locale to '{{ new_locale }}' and language to '{{ new_language }}' command: localectl set-locale LANG={{ new_locale }} LANGUAGE={{ new_language }} - changed_when: locale_lang != new_locale or locale_language != new_language - become: yes # no idea if it's needed nor I care about - +# changed_when: locale_lang != new_locale or locale_language != new_language +# become: yes # no idea if it's needed nor I care about # Wheel group with sudo access # https://stackoverflow.com/a/33362805 @@ -62,7 +82,7 @@ group: name: wheel state: present - become: true +# become: true - name: Allow 'wheel' group to have passwordless sudo ansible.builtin.lineinfile: @@ -71,24 +91,24 @@ regexp: '^%wheel' line: '%wheel ALL=(ALL) PASSWD: ALL' validate: visudo -cf %s - become: true +# become: true -# Create orangepi user (will bother about it later) move to -> kuser (kluster user) +# Create `orangepi` (or whatever user u want to create) user (will bother about it later) # maybe move to -> kuser (kluster user)? - name: Add user new_user_name ansible.builtin.user: name: "{{ new_user_name }}" password: "{{ new_user_pass | password_hash }}" shell: /bin/bash - become: true +# become: true - name: adding user '{{ new_user_name }}' to group wheel - user: + ansible.builtin.user: name: '{{ new_user_name }}' groups: sudo append: yes - become: true +# become: true # Set root password to whatever shit @@ -97,7 +117,7 @@ ansible.builtin.user: name: root password: "{{ new_root_pass | password_hash }}" - become: yes +# become: yes # Disable SSH with ROOT @@ -107,10 +127,11 @@ regexp: '^PermitRootLogin' line: PermitRootLogin = no backrefs: yes - become: yes +# become: yes # REBOOT - name: reboot - ansible.builtin.shell: 'sleep 1 && dhclient -r && dhclient && reboot' + ansible.builtin.reboot: +# ansible.builtin.shell: 'sleep 1 && dhclient -r && dhclient && reboot' ignore_unreachable: true - become: yes +# become: yes diff --git a/inventory.yaml b/inventory.yaml index 8f6b8f1..f5981d1 100644 --- a/inventory.yaml +++ b/inventory.yaml @@ -1,10 +1,11 @@ masters: hosts: - masterk.filter.home: + pi4.filter.home: +# masterk.filter.home: vars: is_master: yes -slaves: - hosts: - slave[01:01].filter.home: - vars: - is_master: no +#slaves: +# hosts: +# slave[01:01].filter.home: +# vars: +# is_master: no diff --git a/ksetup/K/testD/Deployment.yaml b/ksetup/K/testD/Deployment.yaml new file mode 100755 index 0000000..233fd2c --- /dev/null +++ b/ksetup/K/testD/Deployment.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: helloworld-nginx + labels: + app: helloworld +spec: + replicas: 1 + selector: + matchLabels: + app: helloworld + template: + metadata: + labels: + app: helloworld + spec: + containers: + - name: helloworld + image: nginx + resources: + requests: + cpu: "100m" + imagePullPolicy: IfNotPresent #Always + ports: + - containerPort: 80 diff --git a/ksetup/K/testD/Gateway.yaml b/ksetup/K/testD/Gateway.yaml new file mode 100644 index 0000000..8e13616 --- /dev/null +++ b/ksetup/K/testD/Gateway.yaml @@ -0,0 +1,14 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: Gateway +metadata: + name: helloworld-gateway +spec: + selector: + istio: public-ingress + servers: + - port: + number: 80 + name: http + protocol: HTTP + hosts: + - "*" diff --git a/ksetup/K/testD/README.md b/ksetup/K/testD/README.md new file mode 100755 index 0000000..0641ada --- /dev/null +++ b/ksetup/K/testD/README.md @@ -0,0 +1,236 @@ +--- +gitea: none +include_toc: true +--- + + +# Description + +This is the most basic example, most of the examples spread through this [repository](../../) will be using variants of this. + +This example configures: + + Generic Kubernetes resources: + - 1 Service + - 1 Deployment + + Istio resources: + - 1 Gateway + - 1 Virtual Service + +> **Note:**\ +> I don't intend to explain thing related to Kubernetes unless necessary. + +# Configuration + +## Service + +Creates a service named `helloworld`. + +This service listens for the port `80` expecting `HTTP` traffic and will forward the incoming traffic towards the port `80` from the destination pod. + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: helloworld + labels: + app: helloworld + service: helloworld +spec: + ports: + - port: 80 + name: http + selector: + app: helloworld +``` + +## Deployment + +Deploys a Nginx server that listens for the port `80`. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: helloworld-nginx + labels: + app: helloworld +spec: + replicas: 1 + selector: + matchLabels: + app: helloworld + template: + metadata: + labels: + app: helloworld + spec: + containers: + - name: helloworld + image: nginx + resources: + requests: + cpu: "100m" + imagePullPolicy: IfNotPresent #Always + ports: + - containerPort: 80 +``` + +## Gateway + +Deploys an Istio gateway that's listening to the port `80` for `HTTP` traffic. + +It doesn't filter for any specific host. + +The `selector` field is used to "choose" which Istio Load Balancers will have this gateway assigned to. + +The Istio `default` profile creates a Load Balancer in the namespace `istio-system` that has the label `istio: ingressgateway` set, allowing us to target that specific Load Balancer and assign this gateway resource to it. + +```yaml +apiVersion: networking.istio.io/v1alpha3 +kind: Gateway +metadata: + name: helloworld-gateway +spec: + selector: + istio: ingressgateway + servers: + - port: + number: 80 + name: http + protocol: HTTP + hosts: + - "*" +``` + +## VirtualService + +The Virtual Service resources are used to route and filter the received traffic from the gateway resources, and route it towards the desired destination. + +On this example we select the gateway `helloworld-gateway`, which is the [gateway that 's described in the `Gateway` section](#gateway). + +On this resource, we are also not limiting the incoming traffic to any specific host, allowing for all the incoming traffic to go through the rules set. + +Here we created a rule that will be applied on `HTTP` related traffic (including `HTTPS` and `HTTP2`) when the destination path is exactly `/helloworld`. + +This traffic will be forwarded to the port `80` of the destination service `helloworld` (the full path URL equivalent would be `helloworld.$NAMESPACE.svc.cluster.local`). + +Additionally, there will be an internal URL rewrite set, as if the URL is not modified, it would attempt to reach to the `/helloworld` path from the Nginx deployment, which currently has no content and would result in an error code `404` (Not found). + +```yaml +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: helloworld-vs +spec: + hosts: + - "*" + gateways: + - helloworld-gateway + http: + - match: + - uri: + exact: /helloworld + route: + - destination: + host: helloworld + port: + number: 80 + rewrite: + uri: "/" +``` + +# Walkthrough + +## Deploy resources + +Deploy the resources. + +```shell +kubectl apply -f ./ +``` +```text +deployment.apps/helloworld-nginx created +gateway.networking.istio.io/helloworld-gateway created +service/helloworld created +virtualservice.networking.istio.io/helloworld-vs created +``` + +## Wait for the deployment to be ready + +Wait for the Nginx deployment to be up and ready. + +```shell +kubectl get deployment helloworld-nginx -w +``` +```text +NAME READY UP-TO-DATE AVAILABLE AGE +helloworld-nginx 1/1 1 1 44s +``` + +## Test the service + +### Get LB IP + +To perform the desired tests, we will need to obtain the IP Istio Load Balancer that we selected in the [Gateway section](#gateway). + +On my environment, the IP is the `192.168.1.50`. + +```shell +kubectl get svc -l istio=ingressgateway -A +``` +```text +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +istio-ingressgateway LoadBalancer 10.97.47.216 192.168.1.50 15021:31316/TCP,80:32012/TCP,443:32486/TCP 39h +``` + +### Curl /helloworld + +Due to accessing the path `/helloworld`, we are triggering the rule set on the [VirtualService configuration](#virtualservice), sending a request to the Nginx backend and returning us its contents. + +```shell +curl 192.168.1.50/helloworld -s | grep ".*" +``` +```text +Welcome to nginx! +``` + +### Curl /other + +What happens if we access a path or URL that doesn't trigger any rule? + + +```shell +curl 192.168.1.50/other -s -I +``` +```text +HTTP/1.1 404 Not Found +date: Sun, 30 Apr 2023 22:16:30 GMT +server: istio-envoy +transfer-encoding: chunked +``` + +We receive a status code `404`. + +I would like to put emphasis on the following line returned: + +```text +server: istio-envoy +``` + +This means that the contents returned was performed by the Istio service, therefore, the request was able to reach Istio and received a response from it. + +## Cleanup + +Finally, a cleanup from the resources deployed. + +```shell +kubectl delete -f ./ +``` +```text +deployment.apps "helloworld-nginx" deleted +gateway.networking.istio.io "helloworld-gateway" deleted +service "helloworld" deleted +virtualservice.networking.istio.io "helloworld-vs" deleted +``` \ No newline at end of file diff --git a/ksetup/K/testD/Service.yaml b/ksetup/K/testD/Service.yaml new file mode 100644 index 0000000..271ce25 --- /dev/null +++ b/ksetup/K/testD/Service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: helloworld + labels: + app: helloworld + service: helloworld +spec: + ports: + - port: 80 + name: http + selector: + app: helloworld \ No newline at end of file diff --git a/ksetup/K/testD/VirtualService.yaml b/ksetup/K/testD/VirtualService.yaml new file mode 100755 index 0000000..205231b --- /dev/null +++ b/ksetup/K/testD/VirtualService.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: helloworld-vs +spec: + hosts: + - "*" + gateways: + - helloworld-gateway + http: + - match: + - uri: + exact: /helloworld + route: + - destination: + host: helloworld + port: + number: 80 + rewrite: + uri: "/" \ No newline at end of file diff --git a/ksetup/Terraform/main.tf b/ksetup/Terraform/main.tf new file mode 100644 index 0000000..2627c37 --- /dev/null +++ b/ksetup/Terraform/main.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = ">= 2.0.3" + } + kubectl = { + source = "gavinbunney/kubectl" + version = ">= 1.14.0" + } + } +} +# +#module "deployment" { +# source = "terraform-iaac/deployment/kubernetes" +# version = "1.4.3" +# # insert the 2 required variables here +#} + +provider "kubernetes" { + config_path = "../Exported/kubeconfig.conf" +} + +#provider "kubectl" { +# config_path = "../Exported/kubeconfig.conf" +#} + +data "http" "manifestfile" { + url = "https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml" + + method = "GET" +} +# https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/annotations +# https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest +#resource "kubectl_manifest" "mymanifest" { +# yaml_body = data.http.manifestfile.response_body +#} + +#resource "kubernetes_manifest" "calico" { +# manifest = yamldecode(data.http.manifestfile.response_body) +#} + +#output "VMCount" { +# value = yamldecode(file("namespace.yaml")) +## value = file("namespace.yaml") +## value = yamldecode(data.http.manifestfile.response_body) +## value = data.http.manifestfile.response_body +#} + +resource "kubectl_manifest" "my_service" { + yaml_body = file("namespace.yaml") +# yaml_body = data.http.manifestfile.response_body +} + +# +#resource "kubernetes_deployment" "nginx" { +# source = "https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml" +#} +# + +#resource "kubernetes_namespace" "example" { +# metadata { +# name = "testing" +# } +#} \ No newline at end of file diff --git a/ksetup/playbook.yaml b/ksetup/playbook.yaml index 321b9fb..e020960 100755 --- a/ksetup/playbook.yaml +++ b/ksetup/playbook.yaml @@ -10,9 +10,9 @@ vars: # Testing purposes - ansible_user: "orangepi" # Testing purposes - ansible_password: "orangepi" # Testing purposes - ansible_become_password: "orangepi" # Testing purposes + ansible_user: "kuser" # Testing purposes + ansible_password: "kuser1234" # Testing purposes + ansible_become_password: "{{ ansible_password }}" # Testing purposes # Actual vars set_hostname: "{{ ansible_host }}" @@ -24,25 +24,25 @@ tasks: -# - check vars - - debug: var=set_hostname - - debug: var=is_master - -# Init / Basic setup - - name: set up node - import_tasks: tasks_prepare_node.yaml - become: true +## - check vars +# - debug: var=set_hostname +# - debug: var=is_master +# +## Init / Basic setup +# - name: set up node +# import_tasks: tasks_prepare_node.yaml +# become: true # If is_master: init - name: init cluster import_tasks: tasks_master.yaml when: is_master - -# else: join - - name: join cluster - import_tasks: tasks_slave.yaml - when: not is_master - -# Do other stuff - - name: post setup - import_tasks: tasks_end.yaml +# +## else: join +# - name: join cluster +# import_tasks: tasks_slave.yaml +# when: not is_master +# +## Do other stuff +# - name: post setup +# import_tasks: tasks_end.yaml diff --git a/ksetup/tasks_master.yaml b/ksetup/tasks_master.yaml index 4845ed2..044f5c2 100755 --- a/ksetup/tasks_master.yaml +++ b/ksetup/tasks_master.yaml @@ -1,54 +1,84 @@ -# Init -- name: Init cluster - ansible.builtin.command: "kubeadm init" - become: true +## Init +#- name: Init cluster +# ansible.builtin.command: "kubeadm init" +# become: true -# Set kubectl tool -- user: - name: "{{ ansible_user_id }}" - state: present - register: user_info_registered +### get kubectl file -- name: create .kube directory - become: yes - become_user: "{{ ansible_user_id }}" - file: - path: "{{ user_info_registered.home }}/.kube" - state: directory - mode: 0755 - -- debug: var=user_info_registered.home - -- name: copy admin.conf to user's kube config - copy: +- name: Export remote kubeconfig file + ansible.builtin.fetch: src: /etc/kubernetes/admin.conf - remote_src: yes - dest: "{{ user_info_registered.home }}/.kube/config" - owner: "{{ ansible_user_id }}" + dest: ./Exported/kubeconfig.conf + flat: true become: true -# Network Plugin + +## CNI + +### Calico - name: Calico - ansible.builtin.command: "kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml" + ansible.builtin.command: "kubectl create --kubeconfig /etc/kubernetes/admin.conf -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml" + become: true -# Remove taints -- name: Remove Taint (allows deployment in control plane) - ansible.builtin.shell: "kubectl taint nodes --all node-role.kubernetes.io/control-plane-" +## Extras +### MetalLB +- name: MetalLB + ansible.builtin.command: "kubectl create --kubeconfig /etc/kubernetes/admin.conf -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml" + become: true -# Join token / command -- name: Generate join token - shell: kubeadm token create --print-join-command - register: kubeadm_join_cmd +#- name: Calico custom +# ansible.builtin.command: "kubectl create --kubeconfig /etc/kubernetes/admin.conf -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml" +# become: true -- set_fact: - kubeadm_join_command: "{{ kubeadm_join_cmd.stdout }}" -- debug: var=kubeadm_join_command -- name: Store join command in "{{ kubeadm_join_path }}" - copy: - dest: "{{ kubeadm_join_path }}" - content: | - {{ kubeadm_join_command }} - delegate_to: localhost +## Set kubectl tool +#- user: +# name: "{{ ansible_user_id }}" +# state: present +# register: user_info_registered + +#- name: create .kube directory +# become: yes +# become_user: "{{ ansible_user_id }}" +# file: +# path: "{{ user_info_registered.home }}/.kube" +# state: directory +# mode: 0755 + +#- debug: var=user_info_registered.home + +#- name: copy admin.conf to user's kube config +# copy: +# src: /etc/kubernetes/admin.conf +# remote_src: yes +# dest: "{{ user_info_registered.home }}/.kube/config" +# owner: "{{ ansible_user_id }}" +# become: true + + +## Network Plugin +#- name: Calico +# ansible.builtin.command: "kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml" +# +## Remove taints +#- name: Remove Taint (allows deployment in control plane) +# ansible.builtin.shell: "kubectl taint nodes --all node-role.kubernetes.io/control-plane-" +# +## Join token / command +#- name: Generate join token +# shell: kubeadm token create --print-join-command +# register: kubeadm_join_cmd +# +#- set_fact: +# kubeadm_join_command: "{{ kubeadm_join_cmd.stdout }}" +# +#- debug: var=kubeadm_join_command +# +#- name: Store join command in "{{ kubeadm_join_path }}" +# copy: +# dest: "{{ kubeadm_join_path }}" +# content: | +# {{ kubeadm_join_command }} +# delegate_to: localhost diff --git a/ksetup/tasks_prepare_node.yaml b/ksetup/tasks_prepare_node.yaml index 9432460..3bd3540 100755 --- a/ksetup/tasks_prepare_node.yaml +++ b/ksetup/tasks_prepare_node.yaml @@ -51,6 +51,11 @@ name: "*" state: latest +- name: apt install gnupg + ansible.builtin.apt: + pkg: + - gnupg + ## Keyrings directory - name: Creating a new directory file: @@ -72,16 +77,16 @@ state: present ## Kubeshit repo -- name: Download Kubernetes GPG key - ansible.builtin.get_url: - url: "https://packages.cloud.google.com/apt/doc/apt-key.gpg" - dest: "/etc/apt/keyrings/kubernetes-archive-keyring.gpg" - timeout: 10 -- name: Add Kubernetes keyring - copy: - dest: "/etc/apt/sources.list.d/kubernetes.list" - content: "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" +- name: Add Kubernetes GPG key + apt_key: + url: https://packages.cloud.google.com/apt/doc/apt-key.gpg + state: present + +- name: Add Kubernetes APT repository + apt_repository: + repo: deb https://apt.kubernetes.io/ kubernetes-xenial main + state: present ## Install packages @@ -95,7 +100,7 @@ - kubelet - kubeadm - kubectl - - git # fuck it, you will need it + - git # fuck it, you will need it, maybe - vim # fuck it, I need it. - name: Hold kubeadm diff --git a/run.sh b/run.sh index 55c9d04..3a6a22f 100755 --- a/run.sh +++ b/run.sh @@ -2,9 +2,10 @@ export ANSIBLE_HOST_KEY_CHECKING=False # Replace for an inventory -IP="192.168.1.50,192.168.1.51," +IP="192.168.1.2" +#IP="192.168.1.50,192.168.1.51" -ansible-playbook -i $IP, armbian_initial_setup.yaml && sleep 25 # Wait for reboot +#ansible-playbook -i $IP, Initial_Setup/armbian_initial_setup.yaml && sleep 25 # Wait for reboot ansible-playbook -i inventory.yaml ksetup/playbook.yaml