W tej części zajmiemy się skonfigurowaniem sieci na naszym klastrze oraz sterownika do tworzenia volumenów. Zostanie stworzony obiekt StorageClass, który automatycznie utworzy wolumeny, kiedy będą potrzebne.

Zaczynamy od utworzenia pływającego IP (floating-ip). To IP w przyszłości będzie używane jako publiczne IP naszego klastra.

hcloud floating-ip create --type ipv4 --home-location fsn1

Następnie musimy utworzyć „sekret” zawierający nasz token, który został przez nas utworzony w części 1. Posłuży on do utworzenia Cloud Controller Manager, który połączy nasz klaster przez Hetzner API. Network_id można uzyskać przez wykonanie polecenia:

NETWORK_ID=$(hcloud network list -o noheader -o columns=id)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: hcloud
  namespace: kube-system
stringData:
  token: $HCLOUD_TOKEN
  network: "$NETWORK_ID"
EOF

Potem musimy jeszcze doinstalować wspomnianego wcześniej Cloud Controller Manager. Robimy to za pomocą polecenia:

kubectl apply -f  https://raw.githubusercontent.com/hetznercloud/hcloud-cloud-controller-manager/master/deploy/ccm.yaml

Następnie wykorzystamy test od Cilium, który przetestuje komunikację w różny sposób pomiędzy podami. Jeżeli wszystko jest skonfigurowane poprawnie, każdy z testów powinien zadziałać. Wykonujemy polecenie i czekamy parę minut, obserwując, jak kolejne pody zaczynają działać.

kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/master/examples/kubernetes/connectivity-check/connectivity-check.yaml
$ kubectl get po -o wide
NAME                                                    READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES
echo-a-dc9bcfd8f-mhbk2                                  1/1     Running   0          64s   10.0.2.123       worker-1   <none>           <none>
echo-b-5884b7dc69-jwc6q                                 1/1     Running   0          64s   10.0.2.220       worker-1   <none>           <none>
echo-b-host-cfdd57978-cwdr7                             1/1     Running   0          64s   168.119.96.200   worker-1   <none>           <none>
host-to-b-multi-node-clusterip-c4ff7ff64-k2677          1/1     Running   0          63s   78.46.206.239    worker-2   <none>           <none>
host-to-b-multi-node-headless-84d8f6f4c4-zmq8h          1/1     Running   0          63s   78.46.206.239    worker-2   <none>           <none>
pod-to-a-5cdfd4754d-vkmsp                               1/1     Running   0          64s   10.0.1.161       worker-2   <none>           <none>
pod-to-a-allowed-cnp-7d7c8f9f9b-bd89g                   1/1     Running   0          63s   10.0.1.133       worker-2   <none>           <none>
pod-to-a-denied-cnp-75cb89dfd-nhtfp                     1/1     Running   0          63s   10.0.2.106       worker-1   <none>           <none>
pod-to-b-intra-node-nodeport-99b499f7d-jrkk9            1/1     Running   0          62s   10.0.2.9         worker-1   <none>           <none>
pod-to-b-multi-node-clusterip-cd4d764b6-cn7cz           1/1     Running   0          63s   10.0.1.225       worker-2   <none>           <none>
pod-to-b-multi-node-headless-6696c5f8cd-qrn54           1/1     Running   0          63s   10.0.1.117       worker-2   <none>           <none>
pod-to-b-multi-node-nodeport-7ff5595558-trhpp           1/1     Running   0          62s   10.0.1.72        worker-2   <none>           <none>
pod-to-external-1111-d5c7bb4c4-wzwdc                    1/1     Running   0          64s   10.0.1.57        worker-2   <none>           <none>
pod-to-external-fqdn-allow-google-cnp-f48574954-dhtsc   1/1     Running   0          63s   10.0.2.206       worker-1   <none>           <none>

Jak możemy zaobserwować, pody są utworzone i działają. Mają przypisane IP i są hostowane na jednym z 2 worker nodów. Nie było aż tak ciężko, prawda? Po zakończeniu testu możemy go usunąć poleceniem:

kubectl delete -f https://raw.githubusercontent.com/cilium/cilium/master/examples/kubernetes/connectivity-check/connectivity-check.yaml
$ kubectl create deploy nginx --image=nginx --replicas=10
deployment.apps/nginx created
$ kubectl get deploy,po
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES   SELECTOR
deployment.apps/nginx   10/10   10           10          3m34s   nginx        nginx    app=nginx

NAME                         READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
pod/nginx-6799fc88d8-7jcd7   1/1     Running   0          3m33s   10.244.1.4   worker-1   <none>           <none>
pod/nginx-6799fc88d8-brm6t   1/1     Running   0          3m34s   10.244.1.6   worker-1   <none>           <none>
pod/nginx-6799fc88d8-cxcwh   1/1     Running   0          3m34s   10.244.2.4   worker-2   <none>           <none>
pod/nginx-6799fc88d8-g7m9j   1/1     Running   0          3m34s   10.244.1.2   worker-1   <none>           <none>
pod/nginx-6799fc88d8-jxd6m   1/1     Running   0          3m34s   10.244.2.5   worker-2   <none>           <none>
pod/nginx-6799fc88d8-lmn7w   1/1     Running   0          3m34s   10.244.1.3   worker-1   <none>           <none>
pod/nginx-6799fc88d8-s4r5t   1/1     Running   0          3m33s   10.244.2.3   worker-2   <none>           <none>
pod/nginx-6799fc88d8-vbsmn   1/1     Running   0          3m34s   10.244.1.5   worker-1   <none>           <none>
pod/nginx-6799fc88d8-vdxtp   1/1     Running   0          3m33s   10.244.2.6   worker-2   <none>           <none>
pod/nginx-6799fc88d8-vm8j4   1/1     Running   0          3m34s   10.244.2.2   worker-2   <none>           <none>

Ostatnim punktem konfiguracji klastra jest zaimplementowanie CSI, czyli Container Storage Interface. Oczywiście firma Hetzner dostarcza własną implementację tego interfejsu. Pozwoli ona utworzyć wirtualne dyski w firmie Hetzner, widoczne w Kubernetes jako wolumeny. Ponownie zaczynamy od utworzenia sekretu zawierającego nasz token.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: hcloud-csi
  namespace: kube-system
stringData:
  token: $HCLOUD_TOKEN
EOF

A następnie instalujemy implementację CSI z firmy Hetzner.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/csi-api/release-1.14/pkg/crd/manifests/csidriver.yaml && \
kubectl apply -f https://raw.githubusercontent.com/kubernetes/csi-api/release-1.14/pkg/crd/manifests/csinodeinfo.yaml && \
kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/master/deploy/kubernetes/hcloud-csi.yml

Po chwili pody CSI działają. Mamy też skonfigurowany domyślny StorageClass, tworzący wolumeny, kiedy są potrzebne.

$ kubectl get po -n kube-system | grep csi
hcloud-csi-controller-0                           4/4     Running   0          31s
hcloud-csi-node-mgx59                             2/2     Running   0          31s
hcloud-csi-node-wmssb                             2/2     Running   0          31s
$ kubectl get sc
NAME                       PROVISIONER         RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
hcloud-volumes (default)   csi.hetzner.cloud   Delete          WaitForFirstConsumer   true                   3m5s

Aby sprawdzić, czy wszystko działa, tworzymy pod z podpiętym wolumenem.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: hcloud-volumes
---
kind: Pod
apiVersion: v1
metadata:
  name: my-csi-app
spec:
  containers:
    - name: my-frontend
      image: busybox
      volumeMounts:
      - mountPath: "/data"
        name: my-csi-volume
      command: [ "sleep", "1000000" ]
  volumes:
    - name: my-csi-volume
      persistentVolumeClaim:
        claimName: csi-pvc
EOF

Po chwili widzimy, że pod działa, a wolumen został utworzony automatycznie. Tę samą informację znajdziemy w konsoli Hetzner.

$ kubectl get po,pvc,pv
NAME             READY   STATUS    RESTARTS   AGE
pod/my-csi-app   1/1     Running   0          32s

NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE
persistentvolumeclaim/csi-pvc   Bound    pvc-9648fb6b-c22a-43bc-8d26-5720b428a9fe   10Gi       RWO            hcloud-volumes   32s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS     REASON   AGE
persistentvolume/pvc-9648fb6b-c22a-43bc-8d26-5720b428a9fe   10Gi       RWO            Delete           Bound    default/csi-pvc   hcloud-volumes            29s
$ hcloud volume list
ID        NAME                                       SIZE    SERVER     LOCATION
8178835   pvc-9648fb6b-c22a-43bc-8d26-5720b428a9fe   10 GB   worker-2   fsn1

Po usunięciu poda oraz persistentVolumeClaim nasz wolumen zostanie automatycznie usunięty (tak jest domyślnie skonfigurowany StorageClass).

Na dziś to już wszystko. W kolejnym wpisie skonfigurujemy prawdziwą aplikację, skonfigurujmy dla niej domenę oraz ustawimy automatycznie odnawialny certyfikat SSL z wykorzystaniem Let’s Encrypt. Daj znać w komentarzu czy i u Ciebie wszystko działa tak, jak powinno.


0 komentarzy

Dodaj komentarz

Avatar placeholder

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *