czwartek, 5 sierpnia 2021

Wspaniały DevOps

Docker:

Kubernetes:
Helm:
Terraform:
Ansible:
  • Ansible Tower.
CI CD:
AWS:
Wirtualizacja:
  • Vagrant.
Testowanie:
Inne:

środa, 4 sierpnia 2021

Konfiguracja i bezpieczeństwo SSH

 Generujemy klucz ECDSA, którego później będziemy używać do uwierzytelniania:

ssh-keygen -t ecdsa -b 521 -C "seprob"

Edytujemy plik "/etc/ssh/sshd_config":

# Nasłuchuj na danym porcie.

Port 5022

# Użytkownik "root" nie może się zalogowac.

PermitRootLogin no

# Zadwaj uzytkownikowi dowolna liczbe wielowatkowych pytan.

ChallengeResponseAuthentication no

# Wlacz interfejs Pluggable Authentication Module (wtedy nawet zablokowany uzytkownik moze sie zalogowac).

UsePAM no

X11Forwarding yes

# Wyswietlaj Message Of The Day.

PrintMotd yes

AcceptEnv LANG LC_*

Subsystem sftp /usr/lib/openssh/sftp-server

# Nie wysyłaj pakietu aby sprawdzić czy serwer żyje.

TCPKeepAlive no

# Wysyłaj zaszyfrowaną wiadomość co 30 sekund.

ClientAliveInterval 30

# Rozłącz niaktywnego użytkownika po 120 minutach (30 sekund * 240).

ClientAliveCountMax 240

# Dozwolone uwierzytelnianie za pomocą hasła.

PasswordAuthentication yes

# Nie zezwalaj na zalogowanie się na konta posiadające puste hasła.

PermitEmptyPasswords no 

Walidacja konfiguracji demona SSH może być wykonana za pomocą komendy "sshd -t" (lub "sshd -T" jako wersja rozszerzona). 

wtorek, 3 sierpnia 2021

Kubernetes RBAC

Dane wejściowe:

  • system: Debian 9,
  • użytkownik: root,
  • Kubernetes 1.21.3.
Na samym początku stwórzmy dedykowaną dla użytkownika przestrzeń nazw:

kind: Namespace
apiVersion: v1
metadata:
  name: seprob
  labels:
    name: seprob

Przejdźmy do "/etc/kubernetes/pki" gdzie zlokalizowane jest CA Kubernetesa.

Teraz musimy wygenerować klucz i certyfikat:
openssl genrsa -out seprob.key 2048

openssl req -new -key seprob.key -out seprob.csr -subj "/CN=seprob/O=yolandi"

openssl x509 -req -in seprob.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out seprob.crt -days 500

Certyfikat i klucz dostarczamy użytkownikowi aby skonfigurował sobie odpowiednio kubectl. Może to zrobić np. w poniższy sposób:

kubectl config set-credentials seprob --client-certificate=~/Documents/seprob_yolandi_kubernetes.crt --client-key=~/Documents/seprob_yolandi_kubernetes.crt

kubectl config set-context seprob-yolandi --cluster=yolandi --namespace=seprob --user=seprob

Dodatkowo musi ustawić w konfiguracji adres oraz CA klastra. Aktualnie jeżeli będziemy się próbowali połączyć to dostaniemy błąd.

Najpierw stwórzmy obiekt Role:

kind: Role

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  namespace: seprob

  name: seprob-role

rules:

- apiGroups: ["", "extensions", "apps"]

  resources: ["deployments", "replicasets", "pods"]

  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

Teraz obiekt RoleBinding:

kind: RoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: seprob-rolebinding

  namespace: seprob

subjects:

- kind: User

  name: seprob

  apiGroup: ""

roleRef:

  kind: Role

  name: seprob-role

  apiGroup: ""

W tym momencie już powinniśmy mieć możliwość sprawdzić np. czy mamy jakieś Pody w przestrzeni nazw. 

poniedziałek, 2 sierpnia 2021

Instalacja Kubernetes

Dane wejściowe:

  • system operacyjny: Debian 9,
  • użytkownik: root.

Do instalacji klastra Kubernetes użyjemy oprogramowania kubeadm. Nim je zainstalujemy upewnijmy się, że system obsługuje w odpowiedni sposób ruch sieciowy.

Ładowanie modułu br_netfilter podczas ładowania systemu:

cat <<EOF | tee /etc/modules-load.d/k8s.conf

br_netfilter

EOF

Ustaw opcję "net.bridge.bridge-nf-call-iptables" na 1:

cat <<EOF | tee /etc/sysctl.d/k8s.conf

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

EOF

sysctl --system

Partycja wymiana musi być wyłączona. Najpierw sprawdźmy czy jest dostępna:

swapon --show

Jeżeli nic się nie pojawi to nie mamy partycji wymiany. W innym wypadku musimy ją wyłączyć:

swapoff -a 

Nasz serwer musi zezwalać na ruch wchodzący dla następujących portów po protokole TCP:

  • 6443, serwer API Kubernetesa,
  • 2379-2380, API klienta do serwera etcd,
  • 10250, kubelet API,
  • 10251, kube-scheduler,
  • 10252, kube-controller-manager.
Zainstaluj środowisko uruchomieniowe dla kontenerów spośród:
  • Docker,
  • containerd,
  • CRI-O.
Mu użyjemy containerd, które już mam zainstalowane na serwerze (przychodzi wraz z instalacją Dockera) więc teraz pora na konfigurację.

Potrzebne moduły:
cat <<EOF | tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

modprobe overlay

modprobe br_netfilter

Parametry sysctl:

cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf

net.bridge.bridge-nf-call-iptables  = 1

net.ipv4.ip_forward                 = 1

net.bridge.bridge-nf-call-ip6tables = 1

EOF

sysctl --system 

I na koniec dla containerd:

mkdir -p /etc/containerd

containerd config default | tee /etc/containerd/config.toml

systemctl restart containerd

Dodatkowo musimy użyć sterownika systemd dla cgroup. W tym celu edytujemy plik "/etc/containerd/config.toml" i szukamy sekcji

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]

i dodajemy pod nią

SystemdCgroup = true

Na koniec restartujemy demona:

systemctl restart containerd

I wreszcie przyszła pora na instalację kubeadm (inicjalizacja klastra), kubelet (uruchamianie Podów, znajduje się na wszystkich maszynach klastra) oraz kubectl (komunikacja z K8s):

apt-get update

apt-get install -y apt-transport-https ca-certificates curl

curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list

apt-get update

apt-get install -y kubelet kubeadm kubectl

apt-mark hold kubelet kubeadm kubectl

Ostatnia komenda sprawi, że apt nie będzie aktualizował podanych pakietów.

Wykonajmy zatem wreszcie inicjalizację klastra:

kubeadm init --apiserver-advertise-address=92.222.79.22 --pod-network-cidr=10.244.0.0/16

Jako argumenty podajemy odpowiednio adres IP, do którego mają się podłączać nasze węzły w klastrze oraz CIDR sieci Kubernetes.

Uzyskajmy dostęp poprzez kubectl:

mkdir -p $HOME/.kube

cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

chown $(id -u):$(id -g) $HOME/.kube/config

Poleceniem "kubectl get nodes" możemy sprawdzić czy mamy połączenie z klastrem.

Przyszła pora na zainstalowanie wtyczki sieciowej. My wybierzemy Flannel:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Z powodów bezpieczeństwa nie można uruchamiać Podów na głównym węźle więc zmieńmy to:

kubectl taint nodes --all node-role.kubernetes.io/master-

Sprawdźmy czy działa ścieżką szczęścia:

kubectl run bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1 --port=8080

iptables

Zezwól na wszystkie przychodzące połączenia SSH (zmień na inny port jeżeli nie używasz domyślnego):

iptables -A INPUT -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

Wiele portów jednocześnie:

iptables -A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW,ESTABLISHED -j ACCEPT

Zezwól na dostęp połączeń DNS:

iptables -A INPUT -p udp --sport 53 -j ACCEPT

Domyślnie nie wpuszczaj żadnego pakietu:

iptables -P INPUT DROP

Zezwól na pobieranie pakietów za pośrednictwem apt:

iptables -A INPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

iptables -A INPUT -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT

Zachowywanie zmian na stałe

Zacznijmy od zainstalowania pakietu iptables-persistent (możemy zaakceptować zachowanie akturalnych reguł do "/etc/iptables/rules.v4" i "/etc/iptables/rules.v6"):

apt-get install -y iptables-persistent

Jeżeli chcemy zachować aktualne reguły to:

iptables-save > /etc/iptables/rules.v4

ip6tables-save > /etc/iptables/rules.v6