Installation et mise à jour d'un OpenShift en environnement déconnecté
Beaucoup de mes clients travaillent en environnement déconnecté. C’est à dire que les environnements de production ne sont pas connecté à internet de manière directe: les flux entrants passent par un reverse proxy et les flux sortant sont souvent complètement interdits pour éviter l’exfiltration de données. OpenShift peut être installé dans ces environnements déconnectés. C’est même documenté par Red Hat. La documentation pouvant être intimidante au premier abord, je propose ici un résumé “clé en main” de la marche à suivre.
Dans cet article, nous installerons un OpenShift 4.7 et le mettrons à jour en 4.8 (dernière version disponible lors de l’écriture de cet article).
Les étapes résumées ici s’appuient sur ces documentations :
- Mirroring images for a disconnected installation
- Using Operator Lifecycle Manager on restricted networks
- Updating a restricted network cluster
- Installing and configuring the OpenShift Update Service
Dans la suite de cet article, je pars du principe que la station de travail de l’administrateur (ou le serveur de rebond le cas échéant) est connecté à Internet. Toutes les commandes sont exécutées depuis ce poste.
Pour synchroniser les images, nous aurons besoin d’une registry docker privée, accessible depuis la station de travail de l’administrateur et depuis l’environnement de production. Dans mon cas, c’est une simple instance docker-distribution déployée en conteneur.
Pré-requis
Installer les outils ligne de commande d’OpenShift: oc et opm, ici en version 4.7.
curl -s https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/stable-4.7/openshift-client-linux.tar.gz |sudo tar -zxv -C /usr/local/bin/ oc kubectl
curl -s https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/latest-4.7/opm-linux.tar.gz |sudo tar -zxv -C /usr/local/bin/ opm
Installer les outils habituels pour travailler avec les conteneurs: skopeo, buildah et podman.
Installer grpcurl.
curl -sL https://github.com/fullstorydev/grpcurl/releases/download/v1.8.1/grpcurl_1.8.1_linux_x86_64.tar.gz | tar -zxv -C /usr/local/bin grpcurl
Télécharger votre pull secret Red Hat depuis cloud.redhat.com et enregistrez le dans un fichier rh-pull-secret.json.
Créer le pull secret permettant de s’authentifier sur votre registry docker privée. Ma registry est registry.itix.xyz et je m’y authentifie avec l’utilisateur admin et le mot de passe s3cr3t.
cat > my-pull-secret.json <<EOF
{
"auths": {
"registry.itix.xyz": {
"auth": "$(echo -n 'admin:s3cr3t' | base64 -w0)",
"email": "nmasse@redhat.com"
}
}
}
EOF
Fusionner les deux pull secrets à l’aide de jq.
jq -cs '.[0] * .[1]' rh-pull-secret.json my-pull-secret.json > pull-secret.json
Installation d’un OpenShift 4.7
Dans l’exemple ci-dessous, je vais installer un OpenShift 4.7.10. La liste de toutes les releases est disponible sur quay.io.
Lancer la recopie des images de conteneur.
OCP_RELEASE=4.7.10
ARCHITECTURE=x86_64
LOCAL_REGISTRY=registry.itix.xyz
LOCAL_REPOSITORY=openshift-mirror/ocp4
LOCAL_SECRET_JSON=pull-secret.json
oc adm release mirror -a ${LOCAL_SECRET_JSON} \
--from=quay.io/openshift-release-dev/ocp-release:${OCP_RELEASE}-${ARCHITECTURE} \
--to=${LOCAL_REGISTRY}/${LOCAL_REPOSITORY} \
--to-release-image=${LOCAL_REGISTRY}/${LOCAL_REPOSITORY}-release:${OCP_RELEASE}-${ARCHITECTURE}```
Cette commande ira copier les images de la 4.7.10 vers registry.itix.xyz/openshift-mirror/ocp4 (images des composants d’OpenShift) et vers registry.itix.xyz/openshift-mirror/ocp4-release (image “chapeau”).
Elle affichera à l’écran, une fois terminé, une section imageContentSources qu’il faudra ajouter au fichier install-config.yaml. Pensez à la copier/coller, nous en aurons besoin pour la suite.
Exemple de sortie:
Success
Update image: registry.itix.xyz/openshift-mirror/ocp4-release:4.7.10-x86_64
Mirror prefix: registry.itix.xyz/openshift-mirror/ocp4
Mirror prefix: registry.itix.xyz/openshift-mirror/ocp4-release:4.7.10-x86_64
To use the new mirrored repository to install, add the following section to the install-config.yaml:
imageContentSources:
- mirrors:
- registry.itix.xyz/openshift-mirror/ocp4
- registry.itix.xyz/openshift-mirror/ocp4-release
source: quay.io/openshift-release-dev/ocp-release
- mirrors:
- registry.itix.xyz/openshift-mirror/ocp4
- registry.itix.xyz/openshift-mirror/ocp4-release
source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
To use the new mirrored repository for upgrades, use the following to create an ImageContentSourcePolicy:
apiVersion: operator.openshift.io/v1alpha1
kind: ImageContentSourcePolicy
metadata:
name: example
spec:
repositoryDigestMirrors:
- mirrors:
- registry.itix.xyz/openshift-mirror/ocp4
- registry.itix.xyz/openshift-mirror/ocp4-release
source: quay.io/openshift-release-dev/ocp-release
- mirrors:
- registry.itix.xyz/openshift-mirror/ocp4
- registry.itix.xyz/openshift-mirror/ocp4-release
source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
Nous pouvons maintenant créer le binaire openshift-install, patché avec les bonnes références vers les images de la registry privée.
oc adm release extract -a ${LOCAL_SECRET_JSON} --command=openshift-install "${LOCAL_REGISTRY}/${LOCAL_REPOSITORY}:${OCP_RELEASE}-${ARCHITECTURE}"
Pensez à stocker le fichier openshift-install généré dans un répertoire dédié et correctement nommé, afin de ne pas utiliser par mégarde une vieille version plus tard. En effet, ce fichier openshift-install n’est valide que pour une install de cette release dans cet environnement.
Créer le fichier install-config.yaml comme pour une installation connectée, en fonction de vos choix d’architecture et de votre environnement. Ajouter la section imageContentSources comme indiqué ci-dessus.
apiVersion: v1
baseDomain: itix.xyz
compute:
- name: worker
hyperthreading: Enabled
replicas: 0
controlPlane:
name: master
hyperthreading: Enabled
replicas: 3
metadata:
name: secure
networking:
clusterNetworks:
- cidr: 10.128.0.0/14
hostPrefix: 23
serviceNetwork:
- 172.30.0.0/16
networkType: OpenShiftSDN
platform:
none: {}
pullSecret:
'{"auths":{"cloud.openshift.com":{"auth":"REDACTED","email":"nmasse@redhat.com"},"quay.io":{"auth":"REDACTED","email":"nmasse@redhat.com"},"registry.connect.redhat.com":{"auth":"REDACTED","email":"nmasse@redhat.com"},"registry.redhat.io":{"auth":"REDACTED","email":"nmasse@redhat.com"},"registry.itix.xyz":{"auth":"REDACTED","email":"nmasse@redhat.com"}}}'
sshKey: |
ssh-ed25519 REDACTED nmasse@redhat.com
imageContentSources:
- mirrors:
- registry.itix.xyz/openshift-mirror/ocp4
- registry.itix.xyz/openshift-mirror/ocp4-release
source: quay.io/openshift-release-dev/ocp-release
- mirrors:
- registry.itix.xyz/openshift-mirror/ocp4
- registry.itix.xyz/openshift-mirror/ocp4-release
source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
Puis lancer l’installation comme pour une installation connectée.
./openshift-install create manifests --dir=.
./openshift-install create ignition-configs --dir=.
./openshift-install wait-for bootstrap-complete --dir=.
./openshift-install wait-for install-complete --dir=.
Notez l’utilisation du “./” devant la commande openshift-install pour utiliser la version générée précédemment.
L’installation devrait normalement se terminer en 30 à 45 minutes.
Synchronisation des opérateurs en mode déconnecté
Dans un environnement déconnecté, les opérateurs nécessitent une procédure spécifique pour fonctionner. En effet, l’Operator Hub présent dans OpenShift récupère la liste des opérateurs disponibles depuis internet. Les opérateurs sont téléchargés depuis internet et font appel à des images de conteneurs également téléchargées depuis internet.
La procédure qui suit à pour objectif de sélectionner les opérateurs à rendre disponible dans l’environnement déconnecté et à répliquer localement toutes leurs images de conteneur ainsi que leurs dépendances.
La première étape est dresser une liste de tous les opérateurs disponibles en standard.
OCP_MAJOR_RELEASE=4.7
# Podman va s'authentifier avec le pull secret utilisé ci-dessus
mkdir -p ${XDG_RUNTIME_DIR}/containers
cp $LOCAL_SECRET_JSON ${XDG_RUNTIME_DIR}/containers/auth.json
# On lance une copie de l'operator index
podman run -p 50051:50051 -d --rm --name rhoi registry.redhat.io/redhat/redhat-operator-index:v${OCP_MAJOR_RELEASE}
# On sort la liste de tous les operateurs connus
grpcurl -plaintext localhost:50051 api.Registry/ListPackages | sed -E 's/.*"name": "([^"]+)".*/\1/; t; d'
# On peut arrêter l'operator index
podman stop -l
Vous pouvez ensuite choisir dans cette liste les opérateurs que vous souhaitez répliquer localement. Dans l’exemple ci-dessous, j’ai choisi d’en répliquer deux: l’opérateur OpenShift Pipelines et l’opérateur Cincinnati (je l’utilise dans la suite de l’article).
# On construit un index contenant uniquement les opérateurs désirés
opm index prune -f registry.redhat.io/redhat/redhat-operator-index:v${OCP_MAJOR_RELEASE} -p openshift-pipelines-operator-rh,cincinnati-operator -t ${LOCAL_REGISTRY}/openshift-mirror/redhat-operator-index:v${OCP_MAJOR_RELEASE}
# On le pousse dans notre registry locale
podman push ${LOCAL_REGISTRY}/openshift-mirror/redhat-operator-index:v${OCP_MAJOR_RELEASE}
# On lance l'extraction des digests
oc adm catalog mirror -a ${LOCAL_SECRET_JSON} --manifests-only --index-filter-by-os='.*' ${LOCAL_REGISTRY}/openshift-mirror/redhat-operator-index:v${OCP_MAJOR_RELEASE} ${LOCAL_REGISTRY}/openshift-mirror
# On lance la copie des images
oc image mirror --skip-multiple-scopes=true -a ${LOCAL_SECRET_JSON} --filter-by-os='.*' -f manifests-redhat-operator-index-*/mapping.txt
Une fois les images répliquées localement, il faut ensuite provisionner l’Operator Hub avec la liste des opérateurs disponibles localement.
# On désactive les sources par défaut
oc patch OperatorHub cluster --type json -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'
# Et on crée la content source policy
oc apply -f manifests-redhat-operator-index-*/imageContentSourcePolicy.yaml
# Et enfin la catalog source
oc apply -f - <<EOF
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: local-catalog
namespace: openshift-marketplace
spec:
sourceType: grpc
image: ${LOCAL_REGISTRY}/openshift-mirror/redhat-operator-index:v${OCP_MAJOR_RELEASE}
displayName: Local Catalog
publisher: ITIX
updateStrategy:
registryPoll:
interval: 30m
EOF
Installation de l’opérateur Cincinnati
L’opérateur Cincinnati, aussi appellé OpenShift Update Service permet à OpenShift de calculer un chemin de mise à jour supporté. Par défaut OpenShift s’appuie sur l’OpenShift Update Service qui est sur internet. Mais dans un environnement déconnecté, il est nécessaire de l’héberger localement pour bénéficier de cette fonctionnalité. Il n’est toutefois pas nécessaire d’en exécuter une instance sur chaque cluster : une instance centrale peut suffire.
Déployer l’opérateur Cincinnati.
oc apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: openshift-update-service
annotations:
openshift.io/node-selector: ""
labels:
openshift.io/cluster-monitoring: "true"
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: update-service-operator-group
namespace: openshift-update-service
spec:
targetNamespaces:
- openshift-update-service
---
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: update-service-subscription
namespace: openshift-update-service
spec:
channel: v1
installPlanApproval: "Automatic"
source: "local-catalog"
sourceNamespace: "openshift-marketplace"
name: "cincinnati-operator"
EOF
Créer un fichier Dockerfile avec le contenu suivant.
FROM registry.access.redhat.com/ubi8/ubi:8.1
RUN curl -L -o cincinnati-graph-data.tar.gz https://github.com/openshift/cincinnati-graph-data/archive/master.tar.gz
CMD exec /bin/bash -c "tar xvzf cincinnati-graph-data.tar.gz -C /var/lib/cincinnati/graph-data/ --strip-components=1"
Construire l’image correspondante et la pousser dans la registry privée.
podman build -f ./Dockerfile -t ${LOCAL_REGISTRY}/openshift-mirror/graph-data:latest
podman push ${LOCAL_REGISTRY}/openshift-mirror/graph-data:latest
Cette image contient le graphe des chemins de mise à jour de toutes les versions d’OpenShift.
Dans l’étape suivante, nous allons récupérer le certificat de l’Autorité de Certification de la registry privée et l’ajouter aux autorités de confiance. Dans mon cas, le certificat de ma registry privée est signé par Let’s Encrypt mais chez vous cela peut être différent.
curl -Lo ca.crt https://letsencrypt.org/certs/isrgrootx1.pem
oc create configmap additional-trusted-ca -n openshift-config --from-file=updateservice-registry=ca.crt
oc patch image.config.openshift.io/cluster --type=merge -p '{"spec":{"additionalTrustedCA":{"name":"additional-trusted-ca"}}}'
Note: il est important de respecter le nom de la clé (updateservice-registry) dans la Config Map car c’est cette clé que cherche l’opérateur Cincinnati à l’installation.
Déployer Cincinnati.
oc apply -f - <<EOF
apiVersion: updateservice.operator.openshift.io/v1
kind: UpdateService
metadata:
name: service
namespace: openshift-update-service
spec:
replicas: 1
releases: ${LOCAL_REGISTRY}/openshift-mirror/ocp4-release
graphDataImage: ${LOCAL_REGISTRY}/openshift-mirror/graph-data:latest
EOF
Une fois déployé, patcher la configuration du cluster pour utiliser cette instance locale.
POLICY_ENGINE_GRAPH_URI="$(oc -n openshift-update-service get -o jsonpath='{.status.policyEngineURI}/api/upgrades_info/v1/graph{"\n"}' updateservice service)"
oc patch clusterversion version -p "{\"spec\":{\"upstream\":\"${POLICY_ENGINE_GRAPH_URI}\"}}" --type merge
Mise à jour en 4.8
Pour préparer la mise à jour, j’utilise le Red Hat OpenShift Container Platform Update Graph.
Il m’a permis de découvrir que le channel fast-4.8 me permet de passer de la 4.7.10 à la 4.8.5 avec une seule étape intermédiaire: la 4.7.24.
L’outil génère aussi un graphe contenant toutes les versions disponibles et les chemins autorisés entre ces versions.
Nous effectuerons donc une mise à jour en deux étapes: d’abord une mise à jour vers la 4.7.24, puis vers la 4.8.5.
Première étape: passer sur le canal fast-4.8, qui est celui que j’ai choisi.
oc patch clusterversion version --type merge -p '{"spec": {"channel": "fast-4.8"}}'
Ensuite, il faut télécharger et appliquer la clé publique permettant de valider les signatures des images de conteneur de la nouvelle version.
OCP_RELEASE=4.7.24
DIGEST="$(skopeo inspect docker://quay.io/openshift-release-dev/ocp-release:${OCP_RELEASE}-x86_64 | jq -r .Digest)"
DIGEST_ALGO="${DIGEST%%:*}"
DIGEST_ENCODED="${DIGEST#*:}"
SIGNATURE_BASE64="$(curl -s "https://mirror.openshift.com/pub/openshift-v4/signatures/openshift/release/${DIGEST_ALGO}=${DIGEST_ENCODED}/signature-1" | base64 -w0 && echo)"
oc apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: release-image-${OCP_RELEASE}
namespace: openshift-config-managed
labels:
release.openshift.io/verification-signatures: ""
binaryData:
${DIGEST_ALGO}-${DIGEST_ENCODED}: ${SIGNATURE_BASE64}
EOF
Cette étape déclenche une reconfiguration des noeuds du cluster (noeud après noeud).
oc get nodes -w
Attendez que tous les noeuds aient été reconfigurés.
On peut ensuite lancer une recopie des images de conteneur de la nouvelle version (comme pour l’installation).
oc adm release mirror -a ${LOCAL_SECRET_JSON} \
--from=quay.io/openshift-release-dev/ocp-release:${OCP_RELEASE}-${ARCHITECTURE} \
--to=${LOCAL_REGISTRY}/${LOCAL_REPOSITORY} \
--to-release-image=${LOCAL_REGISTRY}/${LOCAL_REPOSITORY}-release:${OCP_RELEASE}-${ARCHITECTURE}
Et lancer la mise à jour en tant que telle.
oc adm upgrade --allow-explicit-upgrade --to-image ${LOCAL_REGISTRY}/${LOCAL_REPOSITORY}-release@${DIGEST_ALGO}:${DIGEST_ENCODED}
Une fois le cluster mis à jour en 4.7.24, vous pouvez refaire la procédure de mise à jour vers la version 4.8.5.
OCP_RELEASE=4.8.5
...
Conclusion
Dans cet article nous avons installé un OpenShift 4.7, avons synchronisé les opérateurs, déployé l’OpenShift Update Service et enfin mis à jour OpenShift vers la version 4.8. Tout ça dans un environnement déconnecté d’internet !