# 🇫🇷 Kit de survie K8S pour les dévs avec K3S - Partie 4: Utiliser une registry privée (unsecure)
Avant de passer à la partie Microservices, je me suis dit que j'aimerais utiliser une Docker Registry privée pour mes développements. Ainsi je peux "embarquer" des images à l'avance, puis utiliser ma registry au lieu de passer par le Docker hub (ce qui m'évitera beaucoup d'A/R sur internet). Je n'imaginais pas que je bataillerais autant. Du coup j'ai pris du retard dans mon programme, mais j'ai appris pas mal de choses (et j'ai eu beaucoup d'échanges sur le sujet avec Louis Tournayre (opens new window))
Donc voici étape par étape ce que j'ai fait.
# Création de la Docker registry
J'ai utilisé une docker registry "unsecure": donc pas de https, ni de certificats, ni d'authentification
J'ai à nouveau utilisé Multipass pour créer une VM qui va contenir ma registry. J4ai donc créé un script create.docker.registry.sh
pour cela:
#!/bin/sh
eval $(cat registry.config)
multipass launch --name ${registry_name} --cpus 1 --mem 1G
IP=$(multipass info ${registry_name} | grep IPv4 | awk '{print $2}')
echo "👋 Initialize 🐳 ${registry_name}..."
multipass --verbose exec ${registry_name} -- sudo -- sh -c "
apt-get update
apt-get install -y docker.io
docker run -d -p 5000:5000 --restart=always --name registry registry:2
"
# run this after every start of the registry
multipass --verbose exec ${registry_name} -- sudo -- sh -c "
usermod -a -G docker ubuntu
chmod 666 /var/run/docker.sock
docker start registry
"
Mon fichier de configuration registry.config
est le suivant:
registry_name="registry";
registry_domain="registry.dev.test";
Et je lis les variables comme cela: eval $(cat registry.config)
vous n'êtes pas obligés de faire comme moi
Et maintenant lancez ./create.docker.registry.sh
et patientez un peu
# Stop/Start
Pour stopper votre VM:
eval $(cat registry.config)
multipass stop ${registry_name}
"
Pour relancer votre VM:
eval $(cat registry.config)
multipass --verbose exec ${registry_name} -- sudo -- sh -c "
usermod -a -G docker ubuntu
chmod 666 /var/run/docker.sock
docker start registry
"
# Une fois la registry créée et lancée
Tout d'abord, ajoutez 192.168.64.20 registry.dev.test
au fichier hosts
de votre ordinateur hôte (192.168.64.20
est l'IP attribuée à ma VM, donc changez cette valeur en fonction de l'IP qui a été attribuée à votre VM). Vous pouvez obtenir l'IP comme ceci:
IP=$(multipass info ${registry_name} | grep IPv4 | awk '{print $2}')
Ensuite, pour pouvoir utiliser une "registry unsecure" avec votre client Docker, vous devez aller modifier les paramètres de celui-ci. Allez dans Preferences / Docker Engine
et modifiez la configurations pour déclarer/ajouter votre registry:
{
"insecure-registries": [
"registry.dev.test:5000"
]
}
Appliquez les changements, le client Docker va re-démarrer.
# Tester votre registry
Maintenant vous pouvez "récupérer" une image docker du Docker Hub, la taguer et la pousser vers votre propre registry:
docker pull node:12.0-slim
docker tag node:12.0-slim registry.dev.test:5000/node:12.0-slim
docker push registry.dev.test:5000/node:12.0-slim
Si vous faites:
curl http://registry.dev.test:5000/v2/_catalog
Vous obtiendrez:
{"repositories":["node"]}
Et avec:
curl registry.dev.test:5000/v2/node/tags/list
Vous aurez:
{"name":"node","tags":["12.0-slim"]}
# Rendre votre registry visible à l'intérieur de K3S
Et c'est à partir de là que c'est devenu plus dur... Et si vous avez plus simple, je vous écouterais avec intérêt.
# registries.yaml
D'après la documentation de K3S, sur chaque noeud du cluster il va falloir modifier ou créer ce fichier /etc/rancher/k3s/registries.yaml
avec le contenu suivant:
mirrors:
"registry.dev.test:5000":
endpoint:
- "http://registry.dev.test:5000"
- pour accéder au shell d'une VM:
multipass shell name_of_the_node
- 📘 Ref: https://rancher.com/docs/k3s/latest/en/installation/private-registry/ (opens new window)
# /etc/hosts
Ensuite sur chaque VM contenant un noeud du cluster, il va fallor modifier le fichier hosts
pour ajouter l'entrée correspondant à la VM de la registry (par exemple: 192.168.64.20 registry.dev.test
).
Mais attention avec Multipass, le système est configuré pour gérer automatiquement le fichier hosts
et le générer automatiquement à partir d'un template à chaque re-démarrage. Dinc si vous faites une modification, vous la perdrez.
A la place il faut aller modifier (sur chaque noeud du cluster) le fichier /etc/cloud/templates/hosts.debian.tmpl
pour y ajouter 192.168.64.20 registry.dev.test
(avec l'IP de votre VM).
# Ensuite: CoreDNS et ConfigMap
Ce n'est pas fini, normalement il faudrait modifier la ConfigMap de CoreDNS pour ajouter l'entrée ci-dessous qui permettra de contacter la registry à partir des autres pods:
hosts registry.dev.test.hosts {
hosts {
192.168.64.20 registry.dev.test
fallthrough
}
}
- Une ConfigMap est une sorte de fichier de configuration pour pod.
- 📘 Ref: https://matthewpalmer.net/kubernetes-app-developer/articles/ultimate-configmap-guide-kubernetes.html (opens new window)
Normalement il faudrait récupérer la ConfigMap comme cela:
kubectl get configmap coredns -n kube-system -o yaml > coredns.yaml
cette commande va générer un fichier
coredns.yaml
décrivant le configmap de coredns
Modifier l'entrée data.Corefile
, faire un kubectl apply -f coredns.yaml
et enfin supprimer le pod qui va être recréé automatiquement et prendre en compte les modifications (comme ceci kubectl delete pod --selector=k8s-app=kube-dns -n kube-system
)
✋🐛 Mais il y a un bug, ça ne fonctionne pas (ou je ne l'ai pas fait comme il faut)
A la place, il ne faut pas ajouter une rubrique hosts
mais modifier l'existante:
Corefile: |-
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
hosts /etc/coredns/NodeHosts {
192.168.64.20 registry.dev.test # 👋👋👋 ajouter l'entrée ici
reload 1s
fallthrough
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
puis faire kubectl apply -f coredns.yaml
et enfin kubectl delete pod --selector=k8s-app=kube-dns -n kube-system
✋🐛 Mais il y a un autre bug, au redémarrage du cluster la ConfigMap redevient comme avant 😡
# La solution (la grosse rustine pour le moment)
- J'ai installé
yq
qui permet de manipuler du yaml via le shell https://mikefarah.gitbook.io/yq/ (opens new window) - J'ai créé un fichier
coredns.patch.yaml
avec le contenu suivant:
data:
Corefile: |-
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
hosts /etc/coredns/NodeHosts {
192.168.64.20 registry.dev.test
reload 1s
fallthrough
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
✋✋✋ Vous remarquez l'entrée correspondant à ma registry
Et j'ai ensuite créé le script suivant update-coredns.sh
:
#!/bin/bash
export KUBECONFIG=$PWD/k3s.yaml
rm coredns.yaml
kubectl get configmap coredns -n kube-system -o yaml > coredns.yaml
corefilepatch=$(yq read coredns.patch.yaml 'data.Corefile')
yq delete -i coredns.yaml 'data.Corefile'
yq write -i coredns.yaml 'data.Corefile' "${corefilepatch}"
kubectl apply -f coredns.yaml
kubectl delete pod --selector=k8s-app=kube-dns -n kube-system
Donc après le re-démarrage de mon cluster, je lance ./update-coredns.sh
qui va mettre à jour la ConfigMap avec les bonnes informations et appliquer les modifications.
Je sais, c'est lourd, mais ça fonctionne 😉 (suivre ceci https://github.com/rancher/k3s/pull/743 (opens new window) qui pourrait nous simplifier la vie).
# Tout ça pourquoi?
Nous avons donc notre registry privée, et maintenant nous allons l'utiliser pour le déploiement de notre application.
Modifiez votre fichier Dockerfile
:
#FROM node:12.0-slim
FROM registry.dev.test:5000/node:12.0-slim
COPY . .
RUN npm install
CMD [ "node", "index.js" ]
Et maintenant pour déployer l'application:
git add .; git commit -m "update"
export KUBECONFIG=../create-cluster/k3s.yaml
export NAMESPACE="training"
export DOCKER_USER="registry.dev.test:5000" # ✋ en fait c'est notre seul changement
export CLUSTER_IP="192.168.64.17"
export CONTAINER_PORT=${CONTAINER_PORT:-8080}
export EXPOSED_PORT=${EXPOSED_PORT:-80}
export APPLICATION_NAME=$(basename $(git rev-parse --show-toplevel))
export DOCKER_USER="${DOCKER_USER}"
export NAMESPACE="${NAMESPACE}"
export IMAGE_NAME="${APPLICATION_NAME}-img"
export TAG=$(git rev-parse --short HEAD)
export IMAGE="${DOCKER_USER}/${IMAGE_NAME}:${TAG}"
export CLUSTER_IP="${CLUSTER_IP}"
export BRANCH=$(git symbolic-ref --short HEAD)
export HOST="${APPLICATION_NAME}.${BRANCH}.${CLUSTER_IP}.nip.io"
docker build -t ${IMAGE_NAME} .
docker tag ${IMAGE_NAME} ${IMAGE}
docker push ${IMAGE}
envsubst < ./kube/deploy.template.yaml > ./kube/deploy.${TAG}.yaml
kubectl apply -f ./kube/deploy.${TAG}.yaml -n ${NAMESPACE}
echo "🌍 http://${HOST}"
Remarque: par rapport aux articles précédents, ce qui change c'est la valeur de
DOCKER_USER
Si vous utilisez notre plugin kubectl easy
, il suffira de faire ceci:
git add .; git commit -m "update"
export KUBECONFIG=../create-cluster/k3s.yaml
NAMESPACE="training" \
DOCKER_USER="registry.dev.test:5000" \
CLUSTER_IP="192.168.64.17" \
kubectl easy deploy
Et une fois déployée, vous pouvez vérifier qu'il y a l'image du container de votre application qui est présente dans votre registry (faites un curl http://registry.dev.test:5000/v2/_catalog
).
- le code source mis à jour de la webapp: https://gitlab.com/learn-k3s/amazing-web-app/-/tree/fourth-steps (opens new window)
- le code source du scrip d'update de CoreDNS: https://gitlab.com/learn-k3s/create-cluster/-/blob/master/update-coredns.sh (opens new window)
- le code pour modifier la ConfigMap: https://gitlab.com/learn-k3s/create-cluster/-/blob/master/coredns.patch.yaml (opens new window) ✋ pensez à modifier l'adresse IP
- le repository de la registry: https://gitlab.com/learn-k3s/registry (opens new window)
Voilà, c'était un peu "lourd" à faire mais plutôt pratique. Si ce n'est pas clair (j'ai un peu eu de mal à écrire cet article), n'hésitez pas à commenter, où à me contacter.
A bientôt pour la suite.
Last Articles
- 🇫🇷 Type Result en Kotlin | 2020-10-31 | Kotlin
- 🇫🇷 Type Result en Kotlin | 2020-10-31 | Kotlin
- 🇬🇧 Every GitLab Page deserves a real CI/CD | 2020-07-23 | GitLab CI
- 🇫🇷 Lit-Element, commencer doucement | 2020-07-20 | WebComponent
- 🇬🇧 Build quickly and host easily your Docker images with GitLab and GitLab CI | 2020-06-02 | GitLab CI
- 🇬🇧 Deploy quickly on Clever Cloud with GitLab CI | 2020-05-31 | GitLab CI
- 🇫🇷 Borg Collective, mes jouets pour apprendre Knative | 2020-05-30 | Knative
- 🇬🇧 Borg Collective, Toys to learn Knative | 2020-05-30 | Knative
- 🇫🇷 M5Stack, une petit device IOT bien sympathique, programmable en Python | 2020-05-09 | IOT
- 🇫🇷 Knative, l'outil qui rend Kubernetes sympathique | 2020-05-02 | kubernetes