# Installing Rancher Desktop in your laptop ## Index [Install Rancher Desktop](#install-rancher-desktop) [Install local path provisioner](#install-local-path-provisioner) [Deploy a local registry](#deploy-local-registry) [Notas sobre DNS](#notas-sobre-dns) ## Install Rancher Desktop Follow instructions in [Rancher Desktop Web](https://docs.rancherdesktop.io/getting-started/installation/) ## Install local path provisioner In order to be able to work with persitent storage, it is useful to deploy a local path provisioner so that all pvc created will assing their own persistent volume locally. You can find intrunctions [here](https://github.com/rancher/local-path-provisioner) Basically, write a ```local-path-storage.yaml``` file with this content: apiVersion: v1 kind: Namespace metadata: name: local-path-storage --- apiVersion: v1 kind: ServiceAccount metadata: name: local-path-provisioner-service-account namespace: local-path-storage --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: local-path-provisioner-role namespace: local-path-storage rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch", "create", "patch", "update", "delete"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: local-path-provisioner-role rules: - apiGroups: [""] resources: ["nodes", "persistentvolumeclaims", "configmaps", "pods", "pods/log"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "patch", "update", "delete"] - apiGroups: [""] resources: ["events"] verbs: ["create", "patch"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: local-path-provisioner-bind namespace: local-path-storage roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: local-path-provisioner-role subjects: - kind: ServiceAccount name: local-path-provisioner-service-account namespace: local-path-storage --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: local-path-provisioner-bind roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: local-path-provisioner-role subjects: - kind: ServiceAccount name: local-path-provisioner-service-account namespace: local-path-storage --- apiVersion: apps/v1 kind: Deployment metadata: name: local-path-provisioner namespace: local-path-storage spec: replicas: 1 selector: matchLabels: app: local-path-provisioner template: metadata: labels: app: local-path-provisioner spec: serviceAccountName: local-path-provisioner-service-account containers: - name: local-path-provisioner image: rancher/local-path-provisioner:v0.0.32 imagePullPolicy: IfNotPresent command: - local-path-provisioner - --debug - start - --config - /etc/config/config.json volumeMounts: - name: config-volume mountPath: /etc/config/ env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: CONFIG_MOUNT_PATH value: /etc/config/ volumes: - name: config-volume configMap: name: local-path-config --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-path provisioner: rancher.io/local-path volumeBindingMode: WaitForFirstConsumer reclaimPolicy: Delete --- kind: ConfigMap apiVersion: v1 metadata: name: local-path-config namespace: local-path-storage data: config.json: |- { "nodePathMap":[ { "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES", "paths":["/opt/local-path-provisioner"] } ] } setup: |- #!/bin/sh set -eu mkdir -m 0777 -p "$VOL_DIR" teardown: |- #!/bin/sh set -eu rm -rf "$VOL_DIR" helperPod.yaml: |- apiVersion: v1 kind: Pod metadata: name: helper-pod spec: priorityClassName: system-node-critical tolerations: - key: node.kubernetes.io/disk-pressure operator: Exists effect: NoSchedule containers: - name: helper-pod image: busybox imagePullPolicy: IfNotPresent and kubectl create -f local-path-storage.yaml This will create the provisioner as well as a storage class named ```local-path``` ## Set default storage class kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE hostpath (default) docker.io/hostpath Delete Immediate false 76m local-path rancher.io/local-path Delete WaitForFirstConsumer false 2m10s kubectl patch storageclass hostpath -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}' storageclass.storage.k8s.io/hostpath patched kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' storageclass.storage.k8s.io/local-path patched kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE hostpath docker.io/hostpath Delete Immediate false 76m local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 2m50s To make ```local-path``` StorageClass the default: kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' Your PVCs either specify to use this storage class or don't specify anything and the default will be used. Example specifying storageclass apiVersion: v1 kind: PersistentVolumeClaim metadata: name: local-path-pvc spec: accessModes: - ReadWriteOnce storageClassName: local-path resources: requests: storage: 128Mi to use the default storage class, just remove the ```storageClassName``` directive Bear in mind that the storage class is configured to ```WaitForFirstConsumer``` so the persistent volume will not be created until a pod request the PVC. ### local path provisioner post-installation For some reason, the ```local-path-provisioner``` pod keeps on crashing. Inspecting the logs it says: kubectl logs deployment.apps/local-path-provisioner -n local-path-storage time="2021-02-24T10:39:15Z" level=fatal msg="Error starting daemon: invalid empty flag helper-pod-file and it also does not exist at ConfigMap local-path-storage/local-path-config with err: configmaps \"local-path-config\" is forbidden: User \"system:serviceaccount:local-path-storage:local-path-provisioner-service- ccount\" cannot get resource \"configmaps\" in API group \"\" in the namespace \"local-path-storage\"" to solve it, we need to apply a change to RBAC by creating a file ```role-local-path.yaml```: --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: local-path-provisioner-workaround namespace: local-path-storage rules: - apiGroups: - '' resources: - configmaps verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: local-path-provisioner-workaround namespace: local-path-storage roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: local-path-provisioner-workaround subjects: - kind: ServiceAccount name: local-path-provisioner-service-account and applying (not creating) it with kubectl apply -f role-local-path.yaml -n local-path-storage then restarting the deployment: kubectl rollout restart deployment.apps/local-path-provisioner -n local-path-storage and finally checking that the pod doesn't crash: kubectl get pod -n local-path-storage which should result in: NAME READY STATUS RESTARTS AGE local-path-provisioner-5897596697-n2gcg 1/1 Running 0 6m40s ## Deploy local registry If you need to create your own images, you will need a registry. You can use a public one, such as [Dockehub](https://hub.docker.com) and deal with with thinks like credentials and the like which is good if you want to go to production with your app, or you can deploy your own local registry withing Rancher Desktop. This is only recommended for development. To deploy a local registry, first create a ```docker-registry.yaml``` file: --- apiVersion: v1 kind: Service metadata: name: docker-registry-service labels: app: docker-registry spec: selector: app: docker-registry ports: - protocol: TCP port: 5000 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: docker-registry-pvc labels: app: docker-registry spec: accessModes: - ReadWriteOnce storageClassName: local-path resources: requests: storage: 10Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: docker-registry labels: app: docker-registry spec: replicas: 1 selector: matchLabels: app: docker-registry template: metadata: labels: app: docker-registry spec: containers: - name: docker-registry image: registry ports: - containerPort: 5000 protocol: TCP volumeMounts: - name: storage mountPath: /var/lib/registry env: - name: REGISTRY_HTTP_ADDR value: :5000 - name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY value: /var/lib/registry volumes: - name: storage persistentVolumeClaim: claimName: docker-registry-pvc and an ```ingress.yaml```: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/proxy-body-size: '0' name: docker-registry-ingress spec: ingressClassName: nginx rules: - host: registry.rancher.lab http: paths: - path: / pathType: Prefix backend: service: name: docker-registry-service port: number: 5000 then, create a namespace, the registry and the ingress: kubectl create ns docker-registry kubectl create -f docker-registry.yaml -f ingress.yaml ## Notas sobre DNS He observado que los pods no pillan la configuración DNS del ordenador host. Buscando en internet, encontré que una solución era reiniciar el servicio ```coredns``` kubectl -n kube-system rollout restart deployment coredns